Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
/**
3
 * PDO Firebird driver
4
 *
5
 * This version has only been tested on Firebird 3.0 and PHP 7
6
 *
7
 * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
8
 *
9
 * @package ADOdb
10
 * @link https://adodb.org Project's web site and documentation
11
 * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
12
 *
13
 * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
14
 * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
15
 * any later version. This means you can use it in proprietary products.
16
 * See the LICENSE.md file distributed with this source code for details.
17
 * @license BSD-3-Clause
18
 * @license LGPL-2.1-or-later
19
 *
20
 * @copyright 2000-2013 John Lim
21
 * @copyright 2019 Damien Regad, Mark Newnham and the ADOdb community
22
 */
23
 
24
/**
25
 * Class ADODB_pdo_firebird
26
 */
27
class ADODB_pdo_firebird extends ADODB_pdo
28
{
29
	public $dialect = 3;
30
	public $metaTablesSQL = "select lower(rdb\$relation_name) from rdb\$relations where rdb\$relation_name not like 'RDB\$%'";
31
	public $metaColumnsSQL = "select lower(a.rdb\$field_name), a.rdb\$null_flag, a.rdb\$default_source, b.rdb\$field_length, b.rdb\$field_scale, b.rdb\$field_sub_type, b.rdb\$field_precision, b.rdb\$field_type from rdb\$relation_fields a, rdb\$fields b where a.rdb\$field_source = b.rdb\$field_name and a.rdb\$relation_name = '%s' order by a.rdb\$field_position asc";
32
 
33
	var $arrayClass = 'ADORecordSet_array_pdo_firebird';
34
 
35
	/**
36
	 * Gets the version iformation from the server
37
	 *
38
	 * @return string[]
39
	 */
40
	public function serverInfo()
41
	{
42
		$arr['dialect'] = $this->dialect;
43
		switch ($arr['dialect']) {
44
			case '':
45
			case '1':
46
				$s = 'Firebird Dialect 1';
47
				break;
48
			case '2':
49
				$s = 'Firebird Dialect 2';
50
				break;
51
			default:
52
			case '3':
53
				$s = 'Firebird Dialect 3';
54
				break;
55
		}
56
		$arr['version'] = ADOConnection::_findvers($s);
57
		$arr['description'] = $s;
58
		return $arr;
59
	}
60
 
61
	/**
62
	 * Returns the tables in the database.
63
	 *
64
	 * @param mixed $ttype
65
	 * @param bool  $showSchema
66
	 * @param mixed $mask
67
	 *
68
	 * @return    string[]
69
	 */
70
	public function metaTables($ttype = false, $showSchema = false, $mask = false)
71
	{
72
		$ret = ADOConnection::MetaTables($ttype, $showSchema);
73
 
74
		return $ret;
75
	}
76
 
77
	public function metaColumns($table, $normalize = true)
78
	{
79
		global $ADODB_FETCH_MODE;
80
 
81
		$save = $ADODB_FETCH_MODE;
82
		$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
83
 
84
		$rs = $this->Execute(sprintf($this->metaColumnsSQL, strtoupper($table)));
85
 
86
		$ADODB_FETCH_MODE = $save;
87
 
88
		if ($rs === false) {
89
			return false;
90
		}
91
 
92
		$retarr = array();
93
		$dialect3 = $this->dialect == 3;
94
		while (!$rs->EOF) { //print_r($rs->fields);
95
			$fld = new ADOFieldObject();
96
			$fld->name = trim($rs->fields[0]);
97
			$this->_ConvertFieldType($fld, $rs->fields[7], $rs->fields[3], $rs->fields[4], $rs->fields[5],
98
				$rs->fields[6], $dialect3);
99
			if (isset($rs->fields[1]) && $rs->fields[1]) {
100
				$fld->not_null = true;
101
			}
102
			if (isset($rs->fields[2])) {
103
 
104
				$fld->has_default = true;
105
				$d = substr($rs->fields[2], strlen('default '));
106
				switch ($fld->type) {
107
					case 'smallint':
108
					case 'integer':
109
						$fld->default_value = (int)$d;
110
						break;
111
					case 'char':
112
					case 'blob':
113
					case 'text':
114
					case 'varchar':
115
						$fld->default_value = (string)substr($d, 1, strlen($d) - 2);
116
						break;
117
					case 'double':
118
					case 'float':
119
						$fld->default_value = (float)$d;
120
						break;
121
					default:
122
						$fld->default_value = $d;
123
						break;
124
				}
125
			}
126
			if ((isset($rs->fields[5])) && ($fld->type == 'blob')) {
127
				$fld->sub_type = $rs->fields[5];
128
			} else {
129
				$fld->sub_type = null;
130
			}
131
			if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) {
132
				$retarr[] = $fld;
133
			} else {
134
				$retarr[strtoupper($fld->name)] = $fld;
135
			}
136
 
137
			$rs->MoveNext();
138
		}
139
		$rs->Close();
140
		if (empty($retarr)) {
141
			return false;
142
		} else {
143
			return $retarr;
144
		}
145
	}
146
 
147
	public function metaIndexes($table, $primary = false, $owner = false)
148
	{
149
		// save old fetch mode
150
		global $ADODB_FETCH_MODE;
151
		$save = $ADODB_FETCH_MODE;
152
		$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
153
		if ($this->fetchMode !== false) {
154
			$savem = $this->SetFetchMode(false);
155
		}
156
		$table = strtoupper($table);
157
		$sql = "SELECT * FROM RDB\$INDICES WHERE RDB\$RELATION_NAME = '" . $table . "'";
158
		if (!$primary) {
159
			$sql .= " AND RDB\$INDEX_NAME NOT LIKE 'RDB\$%'";
160
		} else {
161
			$sql .= " AND RDB\$INDEX_NAME NOT LIKE 'RDB\$FOREIGN%'";
162
		}
163
 
164
		// get index details
165
		$rs = $this->Execute($sql);
166
		if (!is_object($rs)) {
167
			// restore fetchmode
168
			if (isset($savem)) {
169
				$this->SetFetchMode($savem);
170
			}
171
			$ADODB_FETCH_MODE = $save;
172
			return false;
173
		}
174
 
175
		$indexes = array();
176
		while ($row = $rs->FetchRow()) {
177
			$index = $row[0];
178
			if (!isset($indexes[$index])) {
179
				if (is_null($row[3])) {
180
					$row[3] = 0;
181
				}
182
				$indexes[$index] = array(
183
					'unique' => ($row[3] == 1),
184
					'columns' => array()
185
				);
186
			}
187
			$sql = "SELECT * FROM RDB\$INDEX_SEGMENTS WHERE RDB\$INDEX_NAME = '" . $index . "' ORDER BY RDB\$FIELD_POSITION ASC";
188
			$rs1 = $this->Execute($sql);
189
			while ($row1 = $rs1->FetchRow()) {
190
				$indexes[$index]['columns'][$row1[2]] = $row1[1];
191
			}
192
		}
193
		// restore fetchmode
194
		if (isset($savem)) {
195
			$this->SetFetchMode($savem);
196
		}
197
		$ADODB_FETCH_MODE = $save;
198
 
199
		return $indexes;
200
	}
201
 
202
	public function metaPrimaryKeys($table, $owner_notused = false, $internalKey = false)
203
	{
204
		if ($internalKey) {
205
			return array('RDB$DB_KEY');
206
		}
207
 
208
		$table = strtoupper($table);
209
 
210
		$sql = 'SELECT S.RDB$FIELD_NAME AFIELDNAME
211
	FROM RDB$INDICES I JOIN RDB$INDEX_SEGMENTS S ON I.RDB$INDEX_NAME=S.RDB$INDEX_NAME
212
	WHERE I.RDB$RELATION_NAME=\'' . $table . '\' and I.RDB$INDEX_NAME like \'RDB$PRIMARY%\'
213
	ORDER BY I.RDB$INDEX_NAME,S.RDB$FIELD_POSITION';
214
 
215
		$a = $this->GetCol($sql, false, true);
216
		if ($a && sizeof($a) > 0) {
217
			return $a;
218
		}
219
		return false;
220
	}
221
 
222
	public function createSequence($seqname = 'adodbseq', $startID = 1)
223
	{
224
		$ok = $this->execute("CREATE SEQUENCE $seqname");
225
		if (!$ok) {
226
			return false;
227
		}
228
 
229
		return $this->execute("ALTER SEQUENCE $seqname RESTART WITH " . ($startID - 1));
230
	}
231
 
232
	public function dropSequence($seqname = 'adodbseq')
233
	{
234
		$seqname = strtoupper($seqname);
235
		return $this->Execute("DROP SEQUENCE $seqname");
236
	}
237
 
238
	public function genId($seqname = 'adodbseq', $startID = 1)
239
	{
240
		$getnext = ("SELECT Gen_ID($seqname,1) FROM RDB\$DATABASE");
241
		$rs = @$this->execute($getnext);
242
		if (!$rs) {
243
			$this->execute(("CREATE SEQUENCE $seqname"));
244
			$this->execute("ALTER SEQUENCE $seqname RESTART WITH " . ($startID - 1) . ';');
245
			$rs = $this->execute($getnext);
246
		}
247
		if ($rs && !$rs->EOF) {
248
			$this->genID = (integer)reset($rs->fields);
249
		} else {
250
			$this->genID = 0; // false
251
		}
252
 
253
		if ($rs) {
254
			$rs->Close();
255
		}
256
 
257
		return $this->genID;
258
	}
259
 
260
	public function selectLimit($sql, $nrows = -1, $offset = -1, $inputarr = false, $secs = 0)
261
	{
262
		$nrows = (integer)$nrows;
263
		$offset = (integer)$offset;
264
		$str = 'SELECT ';
265
		if ($nrows >= 0) {
266
			$str .= "FIRST $nrows ";
267
		}
268
		$str .= ($offset >= 0) ? "SKIP $offset " : '';
269
 
270
		$sql = preg_replace('/^[ \t]*select/i', $str, $sql);
271
		if ($secs) {
272
			$rs = $this->cacheExecute($secs, $sql, $inputarr);
273
		} else {
274
			$rs = $this->execute($sql, $inputarr);
275
		}
276
 
277
		return $rs;
278
	}
279
 
280
	/**
281
	 * Sets the appropriate type into the $fld variable
282
	 *
283
	 * @param ADOFieldObject $fld By reference
284
	 * @param int            $ftype
285
	 * @param int            $flen
286
	 * @param int            $fscale
287
	 * @param int            $fsubtype
288
	 * @param int            $fprecision
289
	 * @param bool           $dialect3
290
	 */
291
	private function _convertFieldType(&$fld, $ftype, $flen, $fscale, $fsubtype, $fprecision, $dialect3)
292
	{
293
		$fscale = abs($fscale);
294
		$fld->max_length = $flen;
295
		$fld->scale = null;
296
		switch ($ftype) {
297
			case 7:
298
			case 8:
299
				if ($dialect3) {
300
					switch ($fsubtype) {
301
						case 0:
302
							$fld->type = ($ftype == 7 ? 'smallint' : 'integer');
303
							break;
304
						case 1:
305
							$fld->type = 'numeric';
306
							$fld->max_length = $fprecision;
307
							$fld->scale = $fscale;
308
							break;
309
						case 2:
310
							$fld->type = 'decimal';
311
							$fld->max_length = $fprecision;
312
							$fld->scale = $fscale;
313
							break;
314
					} // switch
315
				} else {
316
					if ($fscale != 0) {
317
						$fld->type = 'decimal';
318
						$fld->scale = $fscale;
319
						$fld->max_length = ($ftype == 7 ? 4 : 9);
320
					} else {
321
						$fld->type = ($ftype == 7 ? 'smallint' : 'integer');
322
					}
323
				}
324
				break;
325
			case 16:
326
				if ($dialect3) {
327
					switch ($fsubtype) {
328
						case 0:
329
							$fld->type = 'decimal';
330
							$fld->max_length = 18;
331
							$fld->scale = 0;
332
							break;
333
						case 1:
334
							$fld->type = 'numeric';
335
							$fld->max_length = $fprecision;
336
							$fld->scale = $fscale;
337
							break;
338
						case 2:
339
							$fld->type = 'decimal';
340
							$fld->max_length = $fprecision;
341
							$fld->scale = $fscale;
342
							break;
343
					} // switch
344
				}
345
				break;
346
			case 10:
347
				$fld->type = 'float';
348
				break;
349
			case 14:
350
				$fld->type = 'char';
351
				break;
352
			case 27:
353
				if ($fscale != 0) {
354
					$fld->type = 'decimal';
355
					$fld->max_length = 15;
356
					$fld->scale = 5;
357
				} else {
358
					$fld->type = 'double';
359
				}
360
				break;
361
			case 35:
362
				if ($dialect3) {
363
					$fld->type = 'timestamp';
364
				} else {
365
					$fld->type = 'date';
366
				}
367
				break;
368
			case 12:
369
				$fld->type = 'date';
370
				break;
371
			case 13:
372
				$fld->type = 'time';
373
				break;
374
			case 37:
375
				$fld->type = 'varchar';
376
				break;
377
			case 40:
378
				$fld->type = 'cstring';
379
				break;
380
			case 261:
381
				$fld->type = 'blob';
382
				$fld->max_length = -1;
383
				break;
384
		} // switch
385
	}
386
}
387
 
388
/**
389
 * Class ADORecordSet_pdo_firebird
390
 */
391
class ADORecordSet_pdo_firebird extends ADORecordSet_pdo
392
{
393
 
394
	public $databaseType = "pdo_firebird";
395
 
396
	/**
397
	 * returns the field object
398
	 *
399
	 * @param int $fieldOffset Optional field offset
400
	 *
401
	 * @return object The ADOFieldObject describing the field
402
	 */
403
	public function fetchField($fieldOffset = 0)
404
	{
405
	}
406
}
407
 
408
/**
409
 * Class ADORecordSet_array_pdo_firebird
410
 */
411
class ADORecordSet_array_pdo_firebird extends ADORecordSet_array_pdo
412
{
413
	public $databaseType = "pdo_firebird";
414
	public $canSeek = true;
415
 
416
	/**
417
	 * returns the field object
418
	 *
419
	 * @param int $fieldOffset Optional field offset
420
	 *
421
	 * @return object The ADOFieldObject describing the field
422
	 */
423
	public function fetchField($fieldOffset = 0)
424
	{
425
 
426
		$fld = new ADOFieldObject;
427
		$fld->name = $fieldOffset;
428
		$fld->type = 'C';
429
		$fld->max_length = 0;
430
 
431
		// This needs to be populated from the metadata
432
		$fld->not_null = false;
433
		$fld->has_default = false;
434
		$fld->default_value = 'null';
435
 
436
		return $fld;
437
	}
438
}