TYPO3 CMS  TYPO3_7-6
adodb-sqlite3.inc.php
Go to the documentation of this file.
1 <?php
2 /*
3 @version v5.20.3 01-Jan-2016
4 @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
5 @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
6  Released under both BSD license and Lesser GPL library license.
7  Whenever there is any discrepancy between the two licenses,
8  the BSD license will take precedence.
9 
10  Latest version is available at http://adodb.sourceforge.net
11 
12  SQLite info: http://www.hwaci.com/sw/sqlite/
13 
14  Install Instructions:
15  ====================
16  1. Place this in adodb/drivers
17  2. Rename the file, remove the .txt prefix.
18 */
19 
20 // security - hide paths
21 if (!defined('ADODB_DIR')) die();
22 
23 class ADODB_sqlite3 extends ADOConnection {
24  var $databaseType = "sqlite3";
25  var $replaceQuote = "''"; // string to use to replace quotes
26  var $concat_operator='||';
27  var $_errorNo = 0;
28  var $hasLimit = true;
29  var $hasInsertID = true;
30  var $hasAffectedRows = true;
31  var $metaTablesSQL = "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name";
32  var $sysDate = "adodb_date('Y-m-d')";
33  var $sysTimeStamp = "adodb_date('Y-m-d H:i:s')";
34  var $fmtTimeStamp = "'Y-m-d H:i:s'";
35 
36  function __construct()
37  {
38  }
39 
40  function ServerInfo()
41  {
42  $version = SQLite3::version();
43  $arr['version'] = $version['versionString'];
44  $arr['description'] = 'SQLite 3';
45  return $arr;
46  }
47 
48  function BeginTrans()
49  {
50  if ($this->transOff) {
51  return true;
52  }
53  $ret = $this->Execute("BEGIN TRANSACTION");
54  $this->transCnt += 1;
55  return true;
56  }
57 
58  function CommitTrans($ok=true)
59  {
60  if ($this->transOff) {
61  return true;
62  }
63  if (!$ok) {
64  return $this->RollbackTrans();
65  }
66  $ret = $this->Execute("COMMIT");
67  if ($this->transCnt > 0) {
68  $this->transCnt -= 1;
69  }
70  return !empty($ret);
71  }
72 
73  function RollbackTrans()
74  {
75  if ($this->transOff) {
76  return true;
77  }
78  $ret = $this->Execute("ROLLBACK");
79  if ($this->transCnt > 0) {
80  $this->transCnt -= 1;
81  }
82  return !empty($ret);
83  }
84 
85  // mark newnham
86  function MetaColumns($table, $normalize=true)
87  {
88  global $ADODB_FETCH_MODE;
89  $false = false;
90  $save = $ADODB_FETCH_MODE;
91  $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
92  if ($this->fetchMode !== false) {
93  $savem = $this->SetFetchMode(false);
94  }
95  $rs = $this->Execute("PRAGMA table_info('$table')");
96  if (isset($savem)) {
97  $this->SetFetchMode($savem);
98  }
99  if (!$rs) {
100  $ADODB_FETCH_MODE = $save;
101  return $false;
102  }
103  $arr = array();
104  while ($r = $rs->FetchRow()) {
105  $type = explode('(',$r['type']);
106  $size = '';
107  if (sizeof($type)==2) {
108  $size = trim($type[1],')');
109  }
110  $fn = strtoupper($r['name']);
111  $fld = new ADOFieldObject;
112  $fld->name = $r['name'];
113  $fld->type = $type[0];
114  $fld->max_length = $size;
115  $fld->not_null = $r['notnull'];
116  $fld->default_value = $r['dflt_value'];
117  $fld->scale = 0;
118  if (isset($r['pk']) && $r['pk']) {
119  $fld->primary_key=1;
120  }
121  if ($save == ADODB_FETCH_NUM) {
122  $arr[] = $fld;
123  } else {
124  $arr[strtoupper($fld->name)] = $fld;
125  }
126  }
127  $rs->Close();
128  $ADODB_FETCH_MODE = $save;
129  return $arr;
130  }
131 
132  function _init($parentDriver)
133  {
134  $parentDriver->hasTransactions = false;
135  $parentDriver->hasInsertID = true;
136  }
137 
138  function _insertid()
139  {
140  return $this->_connectionID->lastInsertRowID();
141  }
142 
143  function _affectedrows()
144  {
145  return $this->_connectionID->changes();
146  }
147 
148  function ErrorMsg()
149  {
150  if ($this->_logsql) {
151  return $this->_errorMsg;
152  }
153  return ($this->_errorNo) ? $this->ErrorNo() : ''; //**tochange?
154  }
155 
156  function ErrorNo()
157  {
158  return $this->_connectionID->lastErrorCode(); //**tochange??
159  }
160 
161  function SQLDate($fmt, $col=false)
162  {
163  $fmt = $this->qstr($fmt);
164  return ($col) ? "adodb_date2($fmt,$col)" : "adodb_date($fmt)";
165  }
166 
167 
168  function _createFunctions()
169  {
170  $this->_connectionID->createFunction('adodb_date', 'adodb_date', 1);
171  $this->_connectionID->createFunction('adodb_date2', 'adodb_date2', 2);
172  }
173 
174 
175  // returns true or false
176  function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
177  {
178  if (empty($argHostname) && $argDatabasename) {
179  $argHostname = $argDatabasename;
180  }
181  $this->_connectionID = new SQLite3($argHostname);
182  $this->_createFunctions();
183 
184  return true;
185  }
186 
187  // returns true or false
188  function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
189  {
190  // There's no permanent connect in SQLite3
191  return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);
192  }
193 
194  // returns query ID if successful, otherwise false
195  function _query($sql,$inputarr=false)
196  {
197  $rez = $this->_connectionID->query($sql);
198  if ($rez === false) {
199  $this->_errorNo = $this->_connectionID->lastErrorCode();
200  }
201  // If no data was returned, we don't need to create a real recordset
202  elseif ($rez->numColumns() == 0) {
203  $rez->finalize();
204  $rez = true;
205  }
206 
207  return $rez;
208  }
209 
210  function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
211  {
212  $offsetStr = ($offset >= 0) ? " OFFSET $offset" : '';
213  $limitStr = ($nrows >= 0) ? " LIMIT $nrows" : ($offset >= 0 ? ' LIMIT 999999999' : '');
214  if ($secs2cache) {
215  $rs = $this->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr);
216  } else {
217  $rs = $this->Execute($sql."$limitStr$offsetStr",$inputarr);
218  }
219 
220  return $rs;
221  }
222 
223  /*
224  This algorithm is not very efficient, but works even if table locking
225  is not available.
226 
227  Will return false if unable to generate an ID after $MAXLOOPS attempts.
228  */
229  var $_genSeqSQL = "create table %s (id integer)";
230 
231  function GenID($seq='adodbseq',$start=1)
232  {
233  // if you have to modify the parameter below, your database is overloaded,
234  // or you need to implement generation of id's yourself!
235  $MAXLOOPS = 100;
236  //$this->debug=1;
237  while (--$MAXLOOPS>=0) {
238  @($num = $this->GetOne("select id from $seq"));
239  if ($num === false) {
240  $this->Execute(sprintf($this->_genSeqSQL ,$seq));
241  $start -= 1;
242  $num = '0';
243  $ok = $this->Execute("insert into $seq values($start)");
244  if (!$ok) {
245  return false;
246  }
247  }
248  $this->Execute("update $seq set id=id+1 where id=$num");
249 
250  if ($this->affected_rows() > 0) {
251  $num += 1;
252  $this->genID = $num;
253  return $num;
254  }
255  }
256  if ($fn = $this->raiseErrorFn) {
257  $fn($this->databaseType,'GENID',-32000,"Unable to generate unique id after $MAXLOOPS attempts",$seq,$num);
258  }
259  return false;
260  }
261 
262  function CreateSequence($seqname='adodbseq',$start=1)
263  {
264  if (empty($this->_genSeqSQL)) {
265  return false;
266  }
267  $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
268  if (!$ok) {
269  return false;
270  }
271  $start -= 1;
272  return $this->Execute("insert into $seqname values($start)");
273  }
274 
275  var $_dropSeqSQL = 'drop table %s';
276  function DropSequence($seqname = 'adodbseq')
277  {
278  if (empty($this->_dropSeqSQL)) {
279  return false;
280  }
281  return $this->Execute(sprintf($this->_dropSeqSQL,$seqname));
282  }
283 
284  // returns true or false
285  function _close()
286  {
287  return $this->_connectionID->close();
288  }
289 
290  function MetaIndexes($table, $primary = FALSE, $owner = false)
291  {
292  $false = false;
293  // save old fetch mode
294  global $ADODB_FETCH_MODE;
295  $save = $ADODB_FETCH_MODE;
296  $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
297  if ($this->fetchMode !== FALSE) {
298  $savem = $this->SetFetchMode(FALSE);
299  }
300  $SQL=sprintf("SELECT name,sql FROM sqlite_master WHERE type='index' AND tbl_name='%s'", strtolower($table));
301  $rs = $this->Execute($SQL);
302  if (!is_object($rs)) {
303  if (isset($savem)) {
304  $this->SetFetchMode($savem);
305  }
306  $ADODB_FETCH_MODE = $save;
307  return $false;
308  }
309 
310  $indexes = array ();
311  while ($row = $rs->FetchRow()) {
312  if ($primary && preg_match("/primary/i",$row[1]) == 0) {
313  continue;
314  }
315  if (!isset($indexes[$row[0]])) {
316  $indexes[$row[0]] = array(
317  'unique' => preg_match("/unique/i",$row[1]),
318  'columns' => array()
319  );
320  }
327  $cols = explode("(",$row[1]);
328  $cols = explode(")",$cols[1]);
329  array_pop($cols);
330  $indexes[$row[0]]['columns'] = $cols;
331  }
332  if (isset($savem)) {
333  $this->SetFetchMode($savem);
334  $ADODB_FETCH_MODE = $save;
335  }
336  return $indexes;
337  }
338 
339 }
340 
341 /*--------------------------------------------------------------------------------------
342  Class Name: Recordset
343 --------------------------------------------------------------------------------------*/
344 
345 class ADORecordset_sqlite3 extends ADORecordSet {
346 
347  var $databaseType = "sqlite3";
348  var $bind = false;
349 
350  function __construct($queryID,$mode=false)
351  {
352 
353  if ($mode === false) {
354  global $ADODB_FETCH_MODE;
355  $mode = $ADODB_FETCH_MODE;
356  }
357  switch($mode) {
358  case ADODB_FETCH_NUM:
359  $this->fetchMode = SQLITE3_NUM;
360  break;
361  case ADODB_FETCH_ASSOC:
362  $this->fetchMode = SQLITE3_ASSOC;
363  break;
364  default:
365  $this->fetchMode = SQLITE3_BOTH;
366  break;
367  }
368  $this->adodbFetchMode = $mode;
369 
370  $this->_queryID = $queryID;
371 
372  $this->_inited = true;
373  $this->fields = array();
374  if ($queryID) {
375  $this->_currentRow = 0;
376  $this->EOF = !$this->_fetch();
377  @$this->_initrs();
378  } else {
379  $this->_numOfRows = 0;
380  $this->_numOfFields = 0;
381  $this->EOF = true;
382  }
383 
384  return $this->_queryID;
385  }
386 
387 
388  function FetchField($fieldOffset = -1)
389  {
390  $fld = new ADOFieldObject;
391  $fld->name = $this->_queryID->columnName($fieldOffset);
392  $fld->type = 'VARCHAR';
393  $fld->max_length = -1;
394  return $fld;
395  }
396 
397  function _initrs()
398  {
399  $this->_numOfFields = $this->_queryID->numColumns();
400 
401  }
402 
403  function Fields($colname)
404  {
405  if ($this->fetchMode != SQLITE3_NUM) {
406  return $this->fields[$colname];
407  }
408  if (!$this->bind) {
409  $this->bind = array();
410  for ($i=0; $i < $this->_numOfFields; $i++) {
411  $o = $this->FetchField($i);
412  $this->bind[strtoupper($o->name)] = $i;
413  }
414  }
415 
416  return $this->fields[$this->bind[strtoupper($colname)]];
417  }
418 
419  function _seek($row)
420  {
421  // sqlite3 does not implement seek
422  if ($this->debug) {
423  ADOConnection::outp("SQLite3 does not implement seek");
424  }
425  return false;
426  }
427 
428  function _fetch($ignore_fields=false)
429  {
430  $this->fields = $this->_queryID->fetchArray($this->fetchMode);
431  return !empty($this->fields);
432  }
433 
434  function _close()
435  {
436  }
437 
438 }
FetchField($fieldOffset=-1)
_fetch($ignore_fields=false)
__construct($queryID, $mode=false)
$hasAffectedRows
supports autoincrement ID?
if(isset($_REQUEST['nrows'])) else $rs
Definition: server.php:94
DropSequence($seqname='adodbseq')
debug($variable='', $name=' *variable *', $line=' *line *', $file=' *file *', $recursiveDepth=3, $debugLevel='E_DEBUG')
$metaTablesSQL
supports affected rows for update/delete?
_init($parentDriver)
_query($sql, $inputarr=false)
MetaIndexes($table, $primary=FALSE, $owner=false)
_connect($argHostname, $argUsername, $argPassword, $argDatabasename)
SelectLimit($sql, $nrows=-1, $offset=-1, $inputarr=false, $secs2cache=0)
GenID($seq='adodbseq', $start=1)
SQLDate($fmt, $col=false)
_pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
MetaColumns($table, $normalize=true)
$sql
Definition: server.php:84
CreateSequence($seqname='adodbseq', $start=1)
CommitTrans($ok=true)