3 V5.14 8 Sept 2011 (c) 2000-2011 John Lim (jlim#natsoft.com). All rights reserved.
4 Released under both BSD license and Lesser GPL library license.
5 Whenever there is any discrepancy between the two licenses,
6 the BSD license will take precedence.
8 Latest version is available at http://adodb.sourceforge.net
10 SQLite info: http://www.hwaci.com/sw/sqlite/
14 1. Place this in adodb/drivers
15 2. Rename the file, remove the .txt prefix.
18 // security - hide paths
19 if (!defined('ADODB_DIR')) die();
21 // class ADODB_sqlite extends ADOConnection { **change
22 class ADODB_sqlite3
extends ADOConnection
{
23 //var $databaseType = "sqlite"; **change
24 var $databaseType = "sqlite3";
25 var $replaceQuote = "''"; // string to use to replace quotes
26 var $concat_operator='||';
29 var $hasInsertID = true; /// supports autoincrement ID?
30 var $hasAffectedRows = true; /// supports affected rows for update/delete?
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'";
36 //function ADODB_sqlite3() **change
37 function ADODB_sqlite3()
45 case 'sysDate': return "'".date($this->fmtDate)."'";
46 case 'sysTimeStamp' : return "'".date($this->sysTimeStamp)."'";
52 $arr['version'] = sqlite_libversion(); //**tochange
53 $arr['description'] = 'SQLite '; //**tochange
54 $arr['encoding'] = sqlite_libencoding();//**tochange
60 if ($this->transOff
) return true;
61 $ret = $this->Execute("BEGIN TRANSACTION");
66 function CommitTrans($ok=true)
68 if ($this->transOff
) return true;
69 if (!$ok) return $this->RollbackTrans();
70 $ret = $this->Execute("COMMIT");
71 if ($this->transCnt
>0)$this->transCnt
-= 1;
75 function RollbackTrans()
77 if ($this->transOff
) return true;
78 $ret = $this->Execute("ROLLBACK");
79 if ($this->transCnt
>0)$this->transCnt
-= 1;
84 function MetaColumns($table, $normalize=true)
86 global $ADODB_FETCH_MODE;
88 $save = $ADODB_FETCH_MODE;
89 $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC
;
90 if ($this->fetchMode
!== false) $savem = $this->SetFetchMode(false);
91 $rs = $this->Execute("PRAGMA table_info('$table')");
92 if (isset($savem)) $this->SetFetchMode($savem);
94 $ADODB_FETCH_MODE = $save;
98 while ($r = $rs->FetchRow()) {
100 $type = explode('(',$r['type']);
102 if (sizeof($type)==2)
103 $size = trim($type[1],')');
104 $fn = strtoupper($r['name']);
105 $fld = new ADOFieldObject
;
106 $fld->name
= $r['name'];
107 $fld->type
= $type[0];
108 $fld->max_length
= $size;
109 $fld->not_null
= $r['notnull'];
110 $fld->default_value
= $r['dflt_value'];
112 if (isset($r['pk']) && $r['pk']) $fld->primary_key
=1;
113 if ($save == ADODB_FETCH_NUM
) $arr[] = $fld;
114 else $arr[strtoupper($fld->name
)] = $fld;
117 $ADODB_FETCH_MODE = $save;
121 function _init($parentDriver)
124 $parentDriver->hasTransactions
= false;
125 $parentDriver->hasInsertID
= true;
130 //return sqlite_last_insert_rowid($this->_connectionID)->; //**change
131 $temp = $this->_connectionID
;
132 return $temp->lastInsertRowID();
135 function _affectedrows()
137 return sqlite3_changes($this->_connectionID
); //**tochange
142 if ($this->_logsql
) return $this->_errorMsg
;
144 return ($this->_errorNo
) ?
sqlite_error_string($this->_errorNo
) : ''; //**tochange?
149 return $this->_errorNo
; //**tochange??
152 function SQLDate($fmt, $col=false)
154 $fmt = $this->qstr($fmt);
155 return ($col) ?
"adodb_date2($fmt,$col)" : "adodb_date($fmt)";
159 function _createFunctions()
161 //@sqlite3_create_function($this->_connectionID, 'adodb_date', 'adodb_date', 1); *change
162 $this->_connectionID
->createFunction('adodb_date', 'adodb_date', 1);
164 //@sqlite3_create_function($this->_connectionID, 'adodb_date2', 'adodb_date2', 2);**change
165 $this->_connectionID
->createFunction('adodb_date2', 'adodb_date2', 2);
169 // returns true or false
170 function _connect($argHostname, $argUsername, $argPassword, $argDatabasename) //**tochange: all the function need to be changed, just hacks for the moment
172 $this->_connectionID
= new SQLite3('/path/mydb'); // hack
173 if (empty($argHostname) && $argDatabasename) $argHostname = $argDatabasename; // hack
174 $this->_createFunctions();
178 if (!function_exists('sqlite_open')) return null;
179 if (empty($argHostname) && $argDatabasename) $argHostname = $argDatabasename;
181 $this->_connectionID
= sqlite_open($argHostname);
182 if ($this->_connectionID
=== false) return false;
183 $this->_createFunctions();
187 // returns true or false
188 function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) //**tochange
190 if (!function_exists('sqlite_open')) return null;
191 if (empty($argHostname) && $argDatabasename) $argHostname = $argDatabasename;
193 $this->_connectionID
= sqlite_popen($argHostname);
194 if ($this->_connectionID
=== false) return false;
195 $this->_createFunctions();
199 // returns query ID if successful, otherwise false
200 function _query($sql,$inputarr=false)
202 //$rez = sqlite_query($sql,$this->_connectionID);//**change
203 $rez = $this->_connectionID
->query($sql);
205 //$this->_errorNo = sqlite3_last_error($this->_connectionID);**change
206 $this->_connectionID
->lastErrorCode();
212 function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
214 $offsetStr = ($offset >= 0) ?
" OFFSET $offset" : '';
215 $limitStr = ($nrows >= 0) ?
" LIMIT $nrows" : ($offset >= 0 ?
' LIMIT 999999999' : '');
217 $rs = $this->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr);
219 $rs = $this->Execute($sql."$limitStr$offsetStr",$inputarr);
225 This algorithm is not very efficient, but works even if table locking
228 Will return false if unable to generate an ID after $MAXLOOPS attempts.
230 var $_genSeqSQL = "create table %s (id integer)";
232 function GenID($seq='adodbseq',$start=1)
234 // if you have to modify the parameter below, your database is overloaded,
235 // or you need to implement generation of id's yourself!
238 while (--$MAXLOOPS>=0) {
239 @($num = $this->GetOne("select id from $seq"));
240 if ($num === false) {
241 $this->Execute(sprintf($this->_genSeqSQL
,$seq));
244 $ok = $this->Execute("insert into $seq values($start)");
245 if (!$ok) return false;
247 $this->Execute("update $seq set id=id+1 where id=$num");
249 if ($this->affected_rows() > 0) {
255 if ($fn = $this->raiseErrorFn
) {
256 $fn($this->databaseType
,'GENID',-32000,"Unable to generate unique id after $MAXLOOPS attempts",$seq,$num);
261 function CreateSequence($seqname='adodbseq',$start=1)
263 if (empty($this->_genSeqSQL
)) return false;
264 $ok = $this->Execute(sprintf($this->_genSeqSQL
,$seqname));
265 if (!$ok) return false;
267 return $this->Execute("insert into $seqname values($start)");
270 var $_dropSeqSQL = 'drop table %s';
271 function DropSequence($seqname)
273 if (empty($this->_dropSeqSQL
)) return false;
274 return $this->Execute(sprintf($this->_dropSeqSQL
,$seqname));
277 // returns true or false
280 //return @sqlite3_close($this->_connectionID);**change
281 return $this->_connectionID
->close();
284 function MetaIndexes($table, $primary = FALSE, $owner=false, $owner = false)
287 // save old fetch mode
288 global $ADODB_FETCH_MODE;
289 $save = $ADODB_FETCH_MODE;
290 $ADODB_FETCH_MODE = ADODB_FETCH_NUM
;
291 if ($this->fetchMode
!== FALSE) {
292 $savem = $this->SetFetchMode(FALSE);
294 $SQL=sprintf("SELECT name,sql FROM sqlite_master WHERE type='index' AND tbl_name='%s'", strtolower($table));
295 $rs = $this->Execute($SQL);
296 if (!is_object($rs)) {
298 $this->SetFetchMode($savem);
299 $ADODB_FETCH_MODE = $save;
304 while ($row = $rs->FetchRow()) {
305 if ($primary && preg_match("/primary/i",$row[1]) == 0) continue;
306 if (!isset($indexes[$row[0]])) {
308 $indexes[$row[0]] = array(
309 'unique' => preg_match("/unique/i",$row[1]),
310 'columns' => array());
313 * There must be a more elegant way of doing this,
314 * the index elements appear in the SQL statement
315 * in cols[1] between parentheses
316 * e.g CREATE UNIQUE INDEX ware_0 ON warehouse (org,warehouse)
318 $cols = explode("(",$row[1]);
319 $cols = explode(")",$cols[1]);
321 $indexes[$row[0]]['columns'] = $cols;
324 $this->SetFetchMode($savem);
325 $ADODB_FETCH_MODE = $save;
332 /*--------------------------------------------------------------------------------------
333 Class Name: Recordset
334 --------------------------------------------------------------------------------------*/
336 //class ADORecordset_sqlite extends ADORecordSet {**change
337 class ADORecordset_sqlite3
extends ADORecordSet
{
339 //var $databaseType = "sqlite";**change
340 var $databaseType = "sqlite3";
343 //function ADORecordset_sqlite($queryID,$mode=false)**change
344 function ADORecordset_sqlite3($queryID,$mode=false)
347 if ($mode === false) {
348 global $ADODB_FETCH_MODE;
349 $mode = $ADODB_FETCH_MODE;
352 //case ADODB_FETCH_NUM: $this->fetchMode = SQLITE_NUM; break;**change
353 case ADODB_FETCH_NUM
: $this->fetchMode
= SQLITE3_NUM
; break;
354 //case ADODB_FETCH_ASSOC: $this->fetchMode = SQLITE_ASSOC; break;**change
355 case ADODB_FETCH_ASSOC
: $this->fetchMode
= SQLITE3_ASSOC
; break;
356 //default: $this->fetchMode = SQLITE_BOTH; break;**change
357 default: $this->fetchMode
= SQLITE3_BOTH
; break;
359 $this->adodbFetchMode
= $mode;
361 $this->_queryID
= $queryID;
363 $this->_inited
= true;
364 $this->fields
= array();
366 $this->_currentRow
= 0;
367 $this->EOF
= !$this->_fetch();
370 $this->_numOfRows
= 0;
371 $this->_numOfFields
= 0;
375 return $this->_queryID
;
379 function FetchField($fieldOffset = -1)
381 $fld = new ADOFieldObject
;
382 //$fld->name = sqlite3_field_name($this->_queryID, $fieldOffset);**change
383 $fld->name
->columnName($this->_queryID
, $fieldOffset);
384 $fld->type
= 'VARCHAR';
385 $fld->max_length
= -1;
391 //$this->_numOfRows = @sqlite_num_rows($this->_queryID); **tochange but sqlite3 doesn't implement this!
392 $this->_numOfRows
= 1;
393 //$this->_numOfFields = @sqlite3_num_fields($this->_queryID);**change
394 $this->_numOfFields
= $this->_queryID
->numColumns();
398 function Fields($colname)
400 //if ($this->fetchMode != SQLITE_NUM) return $this->fields[$colname];**change
401 if ($this->fetchMode
!= SQLITE3_NUM
) return $this->fields
[$colname];
403 $this->bind
= array();
404 for ($i=0; $i < $this->_numOfFields
; $i++
) {
405 $o = $this->FetchField($i);
406 $this->bind
[strtoupper($o->name
)] = $i;
410 return $this->fields
[$this->bind
[strtoupper($colname)]];
415 return sqlite3_seek($this->_queryID
, $row);//**tochange but sqlite3 seems not to implement seek!
418 function _fetch($ignore_fields=false)
420 //$this->fields = @sqlite3_fetch_array($this->_queryID,$this->fetchMode);**change
421 $this->fields
= $this->_queryID
->fetchArray($this->fetchMode
);
422 return !empty($this->fields
);