Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
/**
3
 * SQLite driver
4
 *
5
 * @link https://www.sqlite.org/
6
 *
7
 * @deprecated Use SQLite3 driver instead
8
 *
9
 * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
10
 *
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
14
 *
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
21
 *
22
 * @copyright 2000-2013 John Lim
23
 * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
24
 */
25
 
26
// security - hide paths
27
if (!defined('ADODB_DIR')) die();
28
 
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'";
42
 
43
	function ServerInfo()
44
	{
45
		$arr['version'] = sqlite_libversion();
46
		$arr['description'] = 'SQLite ';
47
		$arr['encoding'] = sqlite_libencoding();
48
		return $arr;
49
	}
50
 
51
	function BeginTrans()
52
	{
53
		if ($this->transOff) {
54
			return true;
55
		}
56
		$ret = $this->Execute("BEGIN TRANSACTION");
57
		$this->transCnt += 1;
58
		return true;
59
	}
60
 
61
	function CommitTrans($ok=true)
62
	{
63
		if ($this->transOff) {
64
			return true;
65
		}
66
		if (!$ok) {
67
			return $this->RollbackTrans();
68
		}
69
		$ret = $this->Execute("COMMIT");
70
		if ($this->transCnt > 0) {
71
			$this->transCnt -= 1;
72
		}
73
		return !empty($ret);
74
	}
75
 
76
	function RollbackTrans()
77
	{
78
		if ($this->transOff) {
79
			return true;
80
		}
81
		$ret = $this->Execute("ROLLBACK");
82
		if ($this->transCnt > 0) {
83
			$this->transCnt -= 1;
84
		}
85
		return !empty($ret);
86
	}
87
 
88
	// mark newnham
89
	function MetaColumns($table, $normalize=true)
90
	{
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);
97
		}
98
		$rs = $this->Execute("PRAGMA table_info('$table')");
99
		if (isset($savem)) {
100
			$this->SetFetchMode($savem);
101
		}
102
		if (!$rs) {
103
			$ADODB_FETCH_MODE = $save;
104
			return $false;
105
		}
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],')');
112
			}
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;
123
			}
124
			if ($save == ADODB_FETCH_NUM) {
125
				$arr[] = $fld;
126
			} else {
127
				$arr[strtoupper($fld->name)] = $fld;
128
			}
129
		}
130
		$rs->Close();
131
		$ADODB_FETCH_MODE = $save;
132
		return $arr;
133
	}
134
 
135
	function _init($parentDriver)
136
	{
137
		$parentDriver->hasTransactions = false;
138
		$parentDriver->hasInsertID = true;
139
	}
140
 
141
	protected function _insertID($table = '', $column = '')
142
	{
143
		return sqlite_last_insert_rowid($this->_connectionID);
144
	}
145
 
146
	function _affectedrows()
147
	{
148
		return sqlite_changes($this->_connectionID);
149
	}
150
 
151
	function ErrorMsg()
152
 	{
153
		if ($this->_logsql) {
154
			return $this->_errorMsg;
155
		}
156
		return ($this->_errorNo) ? sqlite_error_string($this->_errorNo) : '';
157
	}
158
 
159
	function ErrorNo()
160
	{
161
		return $this->_errorNo;
162
	}
163
 
164
	function SQLDate($fmt, $col=false)
165
	{
166
		$fmt = $this->qstr($fmt);
167
		return ($col) ? "adodb_date2($fmt,$col)" : "adodb_date($fmt)";
168
	}
169
 
170
 
171
	function _createFunctions()
172
	{
173
		@sqlite_create_function($this->_connectionID, 'adodb_date', 'adodb_date', 1);
174
		@sqlite_create_function($this->_connectionID, 'adodb_date2', 'adodb_date2', 2);
175
	}
176
 
177
 
178
	// returns true or false
179
	function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
180
	{
181
		if (!function_exists('sqlite_open')) {
182
			return null;
183
		}
184
		if (empty($argHostname) && $argDatabasename) {
185
			$argHostname = $argDatabasename;
186
		}
187
 
188
		$this->_connectionID = sqlite_open($argHostname);
189
		if ($this->_connectionID === false) {
190
			return false;
191
		}
192
		$this->_createFunctions();
193
		return true;
194
	}
195
 
196
	// returns true or false
197
	function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
198
	{
199
		if (!function_exists('sqlite_open')) {
200
			return null;
201
		}
202
		if (empty($argHostname) && $argDatabasename) {
203
			$argHostname = $argDatabasename;
204
		}
205
 
206
		$this->_connectionID = sqlite_popen($argHostname);
207
		if ($this->_connectionID === false) {
208
			return false;
209
		}
210
		$this->_createFunctions();
211
		return true;
212
	}
213
 
214
	function _query($sql,$inputarr=false)
215
	{
216
		$rez = sqlite_query($sql,$this->_connectionID);
217
		if (!$rez) {
218
			$this->_errorNo = sqlite_last_error($this->_connectionID);
219
		}
220
		// If no data was returned, we don't need to create a real recordset
221
		// Note: this code is untested, as I don't have a sqlite2 setup available
222
		elseif (sqlite_num_fields($rez) == 0) {
223
			$rez = true;
224
		}
225
 
226
		return $rez;
227
	}
228
 
229
	function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
230
	{
231
		$nrows = (int) $nrows;
232
		$offset = (int) $offset;
233
		$offsetStr = ($offset >= 0) ? " OFFSET $offset" : '';
234
		$limitStr  = ($nrows >= 0)  ? " LIMIT $nrows" : ($offset >= 0 ? ' LIMIT 999999999' : '');
235
		if ($secs2cache) {
236
			$rs = $this->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr);
237
		} else {
238
			$rs = $this->Execute($sql."$limitStr$offsetStr",$inputarr);
239
		}
240
 
241
		return $rs;
242
	}
243
 
244
	/*
245
		This algorithm is not very efficient, but works even if table locking
246
		is not available.
247
 
248
		Will return false if unable to generate an ID after $MAXLOOPS attempts.
249
	*/
250
	var $_genSeqSQL = "create table %s (id integer)";
251
 
252
	function GenID($seq='adodbseq',$start=1)
253
	{
254
		// if you have to modify the parameter below, your database is overloaded,
255
		// or you need to implement generation of id's yourself!
256
		$MAXLOOPS = 100;
257
		//$this->debug=1;
258
		while (--$MAXLOOPS>=0) {
259
			@($num = $this->GetOne("select id from $seq"));
260
			if ($num === false) {
261
				$this->Execute(sprintf($this->_genSeqSQL ,$seq));
262
				$start -= 1;
263
				$num = '0';
264
				$ok = $this->Execute("insert into $seq values($start)");
265
				if (!$ok) {
266
					return false;
267
				}
268
			}
269
			$this->Execute("update $seq set id=id+1 where id=$num");
270
 
271
			if ($this->affected_rows() > 0) {
272
				$num += 1;
273
				$this->genID = $num;
274
				return $num;
275
			}
276
		}
277
		if ($fn = $this->raiseErrorFn) {
278
			$fn($this->databaseType,'GENID',-32000,"Unable to generate unique id after $MAXLOOPS attempts",$seq,$num);
279
		}
280
		return false;
281
	}
282
 
283
	function CreateSequence($seqname='adodbseq',$start=1)
284
	{
285
		if (empty($this->_genSeqSQL)) {
286
			return false;
287
		}
288
		$ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
289
		if (!$ok) {
290
			return false;
291
		}
292
		$start -= 1;
293
		return $this->Execute("insert into $seqname values($start)");
294
	}
295
 
296
	var $_dropSeqSQL = 'drop table %s';
297
	function DropSequence($seqname = 'adodbseq')
298
	{
299
		if (empty($this->_dropSeqSQL)) {
300
			return false;
301
		}
302
		return $this->Execute(sprintf($this->_dropSeqSQL,$seqname));
303
	}
304
 
305
	// returns true or false
306
	function _close()
307
	{
308
		return @sqlite_close($this->_connectionID);
309
	}
310
 
311
	function MetaIndexes($table, $primary = FALSE, $owner = false)
312
	{
313
		$false = false;
314
		// save old fetch mode
315
		global $ADODB_FETCH_MODE;
316
		$save = $ADODB_FETCH_MODE;
317
		$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
318
		if ($this->fetchMode !== FALSE) {
319
			$savem = $this->SetFetchMode(FALSE);
320
		}
321
		$SQL=sprintf("SELECT name,sql FROM sqlite_master WHERE type='index' AND tbl_name='%s'", strtolower($table));
322
		$rs = $this->Execute($SQL);
323
		if (!is_object($rs)) {
324
			if (isset($savem)) {
325
				$this->SetFetchMode($savem);
326
			}
327
			$ADODB_FETCH_MODE = $save;
328
			return $false;
329
		}
330
 
331
		$indexes = array ();
332
		while ($row = $rs->FetchRow()) {
333
			if ($primary && preg_match("/primary/i",$row[1]) == 0) {
334
				continue;
335
			}
336
			if (!isset($indexes[$row[0]])) {
337
				$indexes[$row[0]] = array(
338
					'unique' => preg_match("/unique/i",$row[1]),
339
					'columns' => array()
340
				);
341
			}
342
			/**
343
			 * There must be a more elegant way of doing this,
344
			 * the index elements appear in the SQL statement
345
			 * in cols[1] between parentheses
346
			 * e.g CREATE UNIQUE INDEX ware_0 ON warehouse (org,warehouse)
347
			 */
348
			$cols = explode("(",$row[1]);
349
			$cols = explode(")",$cols[1]);
350
			array_pop($cols);
351
			$indexes[$row[0]]['columns'] = $cols;
352
		}
353
		if (isset($savem)) {
354
			$this->SetFetchMode($savem);
355
			$ADODB_FETCH_MODE = $save;
356
		}
357
		return $indexes;
358
	}
359
 
360
	/**
361
	* Returns the maximum size of a MetaType C field. Because of the
362
	* database design, sqlite places no limits on the size of data inserted
363
	*
364
	* @return int
365
	*/
366
	function charMax()
367
	{
368
		return ADODB_STRINGMAX_NOLIMIT;
369
	}
370
 
371
	/**
372
	* Returns the maximum size of a MetaType X field. Because of the
373
	* database design, sqlite places no limits on the size of data inserted
374
	*
375
	* @return int
376
	*/
377
	function textMax()
378
	{
379
		return ADODB_STRINGMAX_NOLIMIT;
380
	}
381
 
382
	/*
383
	 * Converts a date to a month only field and pads it to 2 characters
384
	 *
385
	 * @param 	str		$fld	The name of the field to process
386
	 * @return	str				The SQL Statement
387
	 */
388
	function month($fld)
389
	{
390
		$x = "strftime('%m',$fld)";
391
 
392
		return $x;
393
	}
394
 
395
	/*
396
	 * Converts a date to a day only field and pads it to 2 characters
397
	 *
398
	 * @param 	str		$fld	The name of the field to process
399
	 * @return	str				The SQL Statement
400
	 */
401
	function day($fld) {
402
		$x = "strftime('%d',$fld)";
403
		return $x;
404
	}
405
 
406
	/*
407
	 * Converts a date to a year only field
408
	 *
409
	 * @param 	str		$fld	The name of the field to process
410
	 * @return	str				The SQL Statement
411
	 */
412
	function year($fld) {
413
		$x = "strftime('%Y',$fld)";
414
 
415
		return $x;
416
	}
417
}
418
 
419
/*--------------------------------------------------------------------------------------
420
		Class Name: Recordset
421
--------------------------------------------------------------------------------------*/
422
 
423
class ADORecordset_sqlite extends ADORecordSet {
424
 
425
	var $databaseType = "sqlite";
426
	var $bind = false;
427
 
428
	function __construct($queryID,$mode=false)
429
	{
430
 
431
		if ($mode === false) {
432
			global $ADODB_FETCH_MODE;
433
			$mode = $ADODB_FETCH_MODE;
434
		}
435
		switch($mode) {
436
			case ADODB_FETCH_NUM:
437
				$this->fetchMode = SQLITE_NUM;
438
				break;
439
			case ADODB_FETCH_ASSOC:
440
				$this->fetchMode = SQLITE_ASSOC;
441
				break;
442
			default:
443
				$this->fetchMode = SQLITE_BOTH;
444
				break;
445
		}
446
		$this->adodbFetchMode = $mode;
447
 
448
		$this->_queryID = $queryID;
449
 
450
		$this->_inited = true;
451
		$this->fields = array();
452
		if ($queryID) {
453
			$this->_currentRow = 0;
454
			$this->EOF = !$this->_fetch();
455
			@$this->_initrs();
456
		} else {
457
			$this->_numOfRows = 0;
458
			$this->_numOfFields = 0;
459
			$this->EOF = true;
460
		}
461
 
462
		return $this->_queryID;
463
	}
464
 
465
 
466
	function FetchField($fieldOffset = -1)
467
	{
468
		$fld = new ADOFieldObject;
469
		$fld->name = sqlite_field_name($this->_queryID, $fieldOffset);
470
		$fld->type = 'VARCHAR';
471
		$fld->max_length = -1;
472
		return $fld;
473
	}
474
 
475
	function _initrs()
476
	{
477
		$this->_numOfRows = @sqlite_num_rows($this->_queryID);
478
		$this->_numOfFields = @sqlite_num_fields($this->_queryID);
479
	}
480
 
481
	function Fields($colname)
482
	{
483
		if ($this->fetchMode != SQLITE_NUM) {
484
			return $this->fields[$colname];
485
		}
486
		if (!$this->bind) {
487
			$this->bind = array();
488
			for ($i=0; $i < $this->_numOfFields; $i++) {
489
				$o = $this->FetchField($i);
490
				$this->bind[strtoupper($o->name)] = $i;
491
			}
492
		}
493
 
494
		return $this->fields[$this->bind[strtoupper($colname)]];
495
	}
496
 
497
	function _seek($row)
498
	{
499
		return sqlite_seek($this->_queryID, $row);
500
	}
501
 
502
	function _fetch($ignore_fields=false)
503
	{
504
		$this->fields = @sqlite_fetch_array($this->_queryID,$this->fetchMode);
505
		return !empty($this->fields);
506
	}
507
 
508
	function _close()
509
	{
510
	}
511
 
512
}