Automatically generated installer lang files
[moodle.git] / lib / adodb / drivers / adodb-sqlite.inc.php
blob0711f1dde1c161abe124a6cd4aa78d33ea983208
1 <?php
2 /**
3 * SQLite driver
5 * @link https://www.sqlite.org/
7 * @deprecated Use SQLite3 driver instead
9 * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
11 * @package ADOdb
12 * @link https://adodb.org Project's web site and documentation
13 * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
15 * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
16 * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
17 * any later version. This means you can use it in proprietary products.
18 * See the LICENSE.md file distributed with this source code for details.
19 * @license BSD-3-Clause
20 * @license LGPL-2.1-or-later
22 * @copyright 2000-2013 John Lim
23 * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
26 // security - hide paths
27 if (!defined('ADODB_DIR')) die();
29 class ADODB_sqlite extends ADOConnection {
30 var $databaseType = "sqlite";
31 var $dataProvider = "sqlite";
32 var $replaceQuote = "''"; // string to use to replace quotes
33 var $concat_operator='||';
34 var $_errorNo = 0;
35 var $hasLimit = true;
36 var $hasInsertID = true; /// supports autoincrement ID?
37 var $hasAffectedRows = true; /// supports affected rows for update/delete?
38 var $metaTablesSQL = "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name";
39 var $sysDate = "adodb_date('Y-m-d')";
40 var $sysTimeStamp = "adodb_date('Y-m-d H:i:s')";
41 var $fmtTimeStamp = "'Y-m-d H:i:s'";
43 function ServerInfo()
45 $arr['version'] = sqlite_libversion();
46 $arr['description'] = 'SQLite ';
47 $arr['encoding'] = sqlite_libencoding();
48 return $arr;
51 function BeginTrans()
53 if ($this->transOff) {
54 return true;
56 $ret = $this->Execute("BEGIN TRANSACTION");
57 $this->transCnt += 1;
58 return true;
61 function CommitTrans($ok=true)
63 if ($this->transOff) {
64 return true;
66 if (!$ok) {
67 return $this->RollbackTrans();
69 $ret = $this->Execute("COMMIT");
70 if ($this->transCnt > 0) {
71 $this->transCnt -= 1;
73 return !empty($ret);
76 function RollbackTrans()
78 if ($this->transOff) {
79 return true;
81 $ret = $this->Execute("ROLLBACK");
82 if ($this->transCnt > 0) {
83 $this->transCnt -= 1;
85 return !empty($ret);
88 // mark newnham
89 function MetaColumns($table, $normalize=true)
91 global $ADODB_FETCH_MODE;
92 $false = false;
93 $save = $ADODB_FETCH_MODE;
94 $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
95 if ($this->fetchMode !== false) {
96 $savem = $this->SetFetchMode(false);
98 $rs = $this->Execute("PRAGMA table_info('$table')");
99 if (isset($savem)) {
100 $this->SetFetchMode($savem);
102 if (!$rs) {
103 $ADODB_FETCH_MODE = $save;
104 return $false;
106 $arr = array();
107 while ($r = $rs->FetchRow()) {
108 $type = explode('(',$r['type']);
109 $size = '';
110 if (sizeof($type)==2) {
111 $size = trim($type[1],')');
113 $fn = strtoupper($r['name']);
114 $fld = new ADOFieldObject;
115 $fld->name = $r['name'];
116 $fld->type = $type[0];
117 $fld->max_length = $size;
118 $fld->not_null = $r['notnull'];
119 $fld->default_value = $r['dflt_value'];
120 $fld->scale = 0;
121 if (isset($r['pk']) && $r['pk']) {
122 $fld->primary_key=1;
124 if ($save == ADODB_FETCH_NUM) {
125 $arr[] = $fld;
126 } else {
127 $arr[strtoupper($fld->name)] = $fld;
130 $rs->Close();
131 $ADODB_FETCH_MODE = $save;
132 return $arr;
135 function _init($parentDriver)
137 $parentDriver->hasTransactions = false;
138 $parentDriver->hasInsertID = true;
141 protected function _insertID($table = '', $column = '')
143 return sqlite_last_insert_rowid($this->_connectionID);
146 function _affectedrows()
148 return sqlite_changes($this->_connectionID);
151 function ErrorMsg()
153 if ($this->_logsql) {
154 return $this->_errorMsg;
156 return ($this->_errorNo) ? sqlite_error_string($this->_errorNo) : '';
159 function ErrorNo()
161 return $this->_errorNo;
164 function SQLDate($fmt, $col=false)
166 $fmt = $this->qstr($fmt);
167 return ($col) ? "adodb_date2($fmt,$col)" : "adodb_date($fmt)";
171 function _createFunctions()
173 @sqlite_create_function($this->_connectionID, 'adodb_date', 'adodb_date', 1);
174 @sqlite_create_function($this->_connectionID, 'adodb_date2', 'adodb_date2', 2);
178 // returns true or false
179 function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
181 if (!function_exists('sqlite_open')) {
182 return null;
184 if (empty($argHostname) && $argDatabasename) {
185 $argHostname = $argDatabasename;
188 $this->_connectionID = sqlite_open($argHostname);
189 if ($this->_connectionID === false) {
190 return false;
192 $this->_createFunctions();
193 return true;
196 // returns true or false
197 function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
199 if (!function_exists('sqlite_open')) {
200 return null;
202 if (empty($argHostname) && $argDatabasename) {
203 $argHostname = $argDatabasename;
206 $this->_connectionID = sqlite_popen($argHostname);
207 if ($this->_connectionID === false) {
208 return false;
210 $this->_createFunctions();
211 return true;
214 // returns query ID if successful, otherwise false
215 function _query($sql,$inputarr=false)
217 $rez = sqlite_query($sql,$this->_connectionID);
218 if (!$rez) {
219 $this->_errorNo = sqlite_last_error($this->_connectionID);
221 // If no data was returned, we don't need to create a real recordset
222 // Note: this code is untested, as I don't have a sqlite2 setup available
223 elseif (sqlite_num_fields($rez) == 0) {
224 $rez = true;
227 return $rez;
230 function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
232 $nrows = (int) $nrows;
233 $offset = (int) $offset;
234 $offsetStr = ($offset >= 0) ? " OFFSET $offset" : '';
235 $limitStr = ($nrows >= 0) ? " LIMIT $nrows" : ($offset >= 0 ? ' LIMIT 999999999' : '');
236 if ($secs2cache) {
237 $rs = $this->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr);
238 } else {
239 $rs = $this->Execute($sql."$limitStr$offsetStr",$inputarr);
242 return $rs;
246 This algorithm is not very efficient, but works even if table locking
247 is not available.
249 Will return false if unable to generate an ID after $MAXLOOPS attempts.
251 var $_genSeqSQL = "create table %s (id integer)";
253 function GenID($seq='adodbseq',$start=1)
255 // if you have to modify the parameter below, your database is overloaded,
256 // or you need to implement generation of id's yourself!
257 $MAXLOOPS = 100;
258 //$this->debug=1;
259 while (--$MAXLOOPS>=0) {
260 @($num = $this->GetOne("select id from $seq"));
261 if ($num === false) {
262 $this->Execute(sprintf($this->_genSeqSQL ,$seq));
263 $start -= 1;
264 $num = '0';
265 $ok = $this->Execute("insert into $seq values($start)");
266 if (!$ok) {
267 return false;
270 $this->Execute("update $seq set id=id+1 where id=$num");
272 if ($this->affected_rows() > 0) {
273 $num += 1;
274 $this->genID = $num;
275 return $num;
278 if ($fn = $this->raiseErrorFn) {
279 $fn($this->databaseType,'GENID',-32000,"Unable to generate unique id after $MAXLOOPS attempts",$seq,$num);
281 return false;
284 function CreateSequence($seqname='adodbseq',$start=1)
286 if (empty($this->_genSeqSQL)) {
287 return false;
289 $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
290 if (!$ok) {
291 return false;
293 $start -= 1;
294 return $this->Execute("insert into $seqname values($start)");
297 var $_dropSeqSQL = 'drop table %s';
298 function DropSequence($seqname = 'adodbseq')
300 if (empty($this->_dropSeqSQL)) {
301 return false;
303 return $this->Execute(sprintf($this->_dropSeqSQL,$seqname));
306 // returns true or false
307 function _close()
309 return @sqlite_close($this->_connectionID);
312 function MetaIndexes($table, $primary = FALSE, $owner = false)
314 $false = false;
315 // save old fetch mode
316 global $ADODB_FETCH_MODE;
317 $save = $ADODB_FETCH_MODE;
318 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
319 if ($this->fetchMode !== FALSE) {
320 $savem = $this->SetFetchMode(FALSE);
322 $SQL=sprintf("SELECT name,sql FROM sqlite_master WHERE type='index' AND tbl_name='%s'", strtolower($table));
323 $rs = $this->Execute($SQL);
324 if (!is_object($rs)) {
325 if (isset($savem)) {
326 $this->SetFetchMode($savem);
328 $ADODB_FETCH_MODE = $save;
329 return $false;
332 $indexes = array ();
333 while ($row = $rs->FetchRow()) {
334 if ($primary && preg_match("/primary/i",$row[1]) == 0) {
335 continue;
337 if (!isset($indexes[$row[0]])) {
338 $indexes[$row[0]] = array(
339 'unique' => preg_match("/unique/i",$row[1]),
340 'columns' => array()
344 * There must be a more elegant way of doing this,
345 * the index elements appear in the SQL statement
346 * in cols[1] between parentheses
347 * e.g CREATE UNIQUE INDEX ware_0 ON warehouse (org,warehouse)
349 $cols = explode("(",$row[1]);
350 $cols = explode(")",$cols[1]);
351 array_pop($cols);
352 $indexes[$row[0]]['columns'] = $cols;
354 if (isset($savem)) {
355 $this->SetFetchMode($savem);
356 $ADODB_FETCH_MODE = $save;
358 return $indexes;
362 * Returns the maximum size of a MetaType C field. Because of the
363 * database design, sqlite places no limits on the size of data inserted
365 * @return int
367 function charMax()
369 return ADODB_STRINGMAX_NOLIMIT;
373 * Returns the maximum size of a MetaType X field. Because of the
374 * database design, sqlite places no limits on the size of data inserted
376 * @return int
378 function textMax()
380 return ADODB_STRINGMAX_NOLIMIT;
384 * Converts a date to a month only field and pads it to 2 characters
386 * @param str $fld The name of the field to process
387 * @return str The SQL Statement
389 function month($fld)
391 $x = "strftime('%m',$fld)";
393 return $x;
397 * Converts a date to a day only field and pads it to 2 characters
399 * @param str $fld The name of the field to process
400 * @return str The SQL Statement
402 function day($fld) {
403 $x = "strftime('%d',$fld)";
404 return $x;
408 * Converts a date to a year only field
410 * @param str $fld The name of the field to process
411 * @return str The SQL Statement
413 function year($fld) {
414 $x = "strftime('%Y',$fld)";
416 return $x;
420 /*--------------------------------------------------------------------------------------
421 Class Name: Recordset
422 --------------------------------------------------------------------------------------*/
424 class ADORecordset_sqlite extends ADORecordSet {
426 var $databaseType = "sqlite";
427 var $bind = false;
429 function __construct($queryID,$mode=false)
432 if ($mode === false) {
433 global $ADODB_FETCH_MODE;
434 $mode = $ADODB_FETCH_MODE;
436 switch($mode) {
437 case ADODB_FETCH_NUM:
438 $this->fetchMode = SQLITE_NUM;
439 break;
440 case ADODB_FETCH_ASSOC:
441 $this->fetchMode = SQLITE_ASSOC;
442 break;
443 default:
444 $this->fetchMode = SQLITE_BOTH;
445 break;
447 $this->adodbFetchMode = $mode;
449 $this->_queryID = $queryID;
451 $this->_inited = true;
452 $this->fields = array();
453 if ($queryID) {
454 $this->_currentRow = 0;
455 $this->EOF = !$this->_fetch();
456 @$this->_initrs();
457 } else {
458 $this->_numOfRows = 0;
459 $this->_numOfFields = 0;
460 $this->EOF = true;
463 return $this->_queryID;
467 function FetchField($fieldOffset = -1)
469 $fld = new ADOFieldObject;
470 $fld->name = sqlite_field_name($this->_queryID, $fieldOffset);
471 $fld->type = 'VARCHAR';
472 $fld->max_length = -1;
473 return $fld;
476 function _initrs()
478 $this->_numOfRows = @sqlite_num_rows($this->_queryID);
479 $this->_numOfFields = @sqlite_num_fields($this->_queryID);
482 function Fields($colname)
484 if ($this->fetchMode != SQLITE_NUM) {
485 return $this->fields[$colname];
487 if (!$this->bind) {
488 $this->bind = array();
489 for ($i=0; $i < $this->_numOfFields; $i++) {
490 $o = $this->FetchField($i);
491 $this->bind[strtoupper($o->name)] = $i;
495 return $this->fields[$this->bind[strtoupper($colname)]];
498 function _seek($row)
500 return sqlite_seek($this->_queryID, $row);
503 function _fetch($ignore_fields=false)
505 $this->fields = @sqlite_fetch_array($this->_queryID,$this->fetchMode);
506 return !empty($this->fields);
509 function _close()