See Release Notes
Long Term Support Release
Differences Between: [Versions 311 and 401] [Versions 401 and 402] [Versions 401 and 403]
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 function _init($parentDriver) 36 { 37 $this->pdoDriver = $parentDriver; 38 //$parentDriver->_bindInputArray = true; 39 //$parentDriver->hasTransactions = false; // // should be set to false because of PDO SQLite driver not supporting changing autocommit mode 40 //$parentDriver->hasInsertID = true; 41 } 42 43 /** 44 * Gets the version iformation from the server 45 * 46 * @return string[] 47 */ 48 public function serverInfo() 49 { 50 $arr['dialect'] = $this->dialect; 51 switch ($arr['dialect']) { 52 case '': 53 case '1': 54 $s = 'Firebird Dialect 1'; 55 break; 56 case '2': 57 $s = 'Firebird Dialect 2'; 58 break; 59 default: 60 case '3': 61 $s = 'Firebird Dialect 3'; 62 break; 63 } 64 $arr['version'] = ADOConnection::_findvers($s); 65 $arr['description'] = $s; 66 return $arr; 67 } 68 69 /** 70 * Returns the tables in the database. 71 * 72 * @param mixed $ttype 73 * @param bool $showSchema 74 * @param mixed $mask 75 * 76 * @return string[] 77 */ 78 public function metaTables($ttype = false, $showSchema = false, $mask = false) 79 { 80 $ret = ADOConnection::MetaTables($ttype, $showSchema); 81 82 return $ret; 83 } 84 85 public function metaColumns($table, $normalize = true) 86 { 87 global $ADODB_FETCH_MODE; 88 89 $save = $ADODB_FETCH_MODE; 90 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 91 92 $rs = $this->Execute(sprintf($this->metaColumnsSQL, strtoupper($table))); 93 94 $ADODB_FETCH_MODE = $save; 95 96 if ($rs === false) { 97 return false; 98 } 99 100 $retarr = array(); 101 $dialect3 = $this->dialect == 3; 102 while (!$rs->EOF) { //print_r($rs->fields); 103 $fld = new ADOFieldObject(); 104 $fld->name = trim($rs->fields[0]); 105 $this->_ConvertFieldType($fld, $rs->fields[7], $rs->fields[3], $rs->fields[4], $rs->fields[5], 106 $rs->fields[6], $dialect3); 107 if (isset($rs->fields[1]) && $rs->fields[1]) { 108 $fld->not_null = true; 109 } 110 if (isset($rs->fields[2])) { 111 112 $fld->has_default = true; 113 $d = substr($rs->fields[2], strlen('default ')); 114 switch ($fld->type) { 115 case 'smallint': 116 case 'integer': 117 $fld->default_value = (int)$d; 118 break; 119 case 'char': 120 case 'blob': 121 case 'text': 122 case 'varchar': 123 $fld->default_value = (string)substr($d, 1, strlen($d) - 2); 124 break; 125 case 'double': 126 case 'float': 127 $fld->default_value = (float)$d; 128 break; 129 default: 130 $fld->default_value = $d; 131 break; 132 } 133 } 134 if ((isset($rs->fields[5])) && ($fld->type == 'blob')) { 135 $fld->sub_type = $rs->fields[5]; 136 } else { 137 $fld->sub_type = null; 138 } 139 if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) { 140 $retarr[] = $fld; 141 } else { 142 $retarr[strtoupper($fld->name)] = $fld; 143 } 144 145 $rs->MoveNext(); 146 } 147 $rs->Close(); 148 if (empty($retarr)) { 149 return false; 150 } else { 151 return $retarr; 152 } 153 } 154 155 public function metaIndexes($table, $primary = false, $owner = false) 156 { 157 // save old fetch mode 158 global $ADODB_FETCH_MODE; 159 $save = $ADODB_FETCH_MODE; 160 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 161 if ($this->fetchMode !== false) { 162 $savem = $this->SetFetchMode(false); 163 } 164 $table = strtoupper($table); 165 $sql = "SELECT * FROM RDB\$INDICES WHERE RDB\$RELATION_NAME = '" . $table . "'"; 166 if (!$primary) { 167 $sql .= " AND RDB\$INDEX_NAME NOT LIKE 'RDB\$%'"; 168 } else { 169 $sql .= " AND RDB\$INDEX_NAME NOT LIKE 'RDB\$FOREIGN%'"; 170 } 171 172 // get index details 173 $rs = $this->Execute($sql); 174 if (!is_object($rs)) { 175 // restore fetchmode 176 if (isset($savem)) { 177 $this->SetFetchMode($savem); 178 } 179 $ADODB_FETCH_MODE = $save; 180 return false; 181 } 182 183 $indexes = array(); 184 while ($row = $rs->FetchRow()) { 185 $index = $row[0]; 186 if (!isset($indexes[$index])) { 187 if (is_null($row[3])) { 188 $row[3] = 0; 189 } 190 $indexes[$index] = array( 191 'unique' => ($row[3] == 1), 192 'columns' => array() 193 ); 194 } 195 $sql = "SELECT * FROM RDB\$INDEX_SEGMENTS WHERE RDB\$INDEX_NAME = '" . $index . "' ORDER BY RDB\$FIELD_POSITION ASC"; 196 $rs1 = $this->Execute($sql); 197 while ($row1 = $rs1->FetchRow()) { 198 $indexes[$index]['columns'][$row1[2]] = $row1[1]; 199 } 200 } 201 // restore fetchmode 202 if (isset($savem)) { 203 $this->SetFetchMode($savem); 204 } 205 $ADODB_FETCH_MODE = $save; 206 207 return $indexes; 208 } 209 210 public function metaPrimaryKeys($table, $owner_notused = false, $internalKey = false) 211 { 212 if ($internalKey) { 213 return array('RDB$DB_KEY'); 214 } 215 216 $table = strtoupper($table); 217 218 $sql = 'SELECT S.RDB$FIELD_NAME AFIELDNAME 219 FROM RDB$INDICES I JOIN RDB$INDEX_SEGMENTS S ON I.RDB$INDEX_NAME=S.RDB$INDEX_NAME 220 WHERE I.RDB$RELATION_NAME=\'' . $table . '\' and I.RDB$INDEX_NAME like \'RDB$PRIMARY%\' 221 ORDER BY I.RDB$INDEX_NAME,S.RDB$FIELD_POSITION'; 222 223 $a = $this->GetCol($sql, false, true); 224 if ($a && sizeof($a) > 0) { 225 return $a; 226 } 227 return false; 228 } 229 230 public function createSequence($seqname = 'adodbseq', $startID = 1) 231 { 232 $ok = $this->execute("CREATE SEQUENCE $seqname"); 233 if (!$ok) { 234 return false; 235 } 236 237 return $this->execute("ALTER SEQUENCE $seqname RESTART WITH " . ($startID - 1)); 238 } 239 240 public function dropSequence($seqname = 'adodbseq') 241 { 242 $seqname = strtoupper($seqname); 243 return $this->Execute("DROP SEQUENCE $seqname"); 244 } 245 246 247 public function _affectedrows() 248 { 249 return fbird_affected_rows($this->_transactionID ? $this->_transactionID : $this->_connectionID); 250 } 251 252 public function genId($seqname = 'adodbseq', $startID = 1) 253 { 254 $getnext = ("SELECT Gen_ID($seqname,1) FROM RDB\$DATABASE"); 255 $rs = @$this->execute($getnext); 256 if (!$rs) { 257 $this->execute(("CREATE SEQUENCE $seqname")); 258 $this->execute("ALTER SEQUENCE $seqname RESTART WITH " . ($startID - 1) . ';'); 259 $rs = $this->execute($getnext); 260 } 261 if ($rs && !$rs->EOF) { 262 $this->genID = (integer)reset($rs->fields); 263 } else { 264 $this->genID = 0; // false 265 } 266 267 if ($rs) { 268 $rs->Close(); 269 } 270 271 return $this->genID; 272 } 273 274 public function selectLimit($sql, $nrows = -1, $offset = -1, $inputarr = false, $secs = 0) 275 { 276 $nrows = (integer)$nrows; 277 $offset = (integer)$offset; 278 $str = 'SELECT '; 279 if ($nrows >= 0) { 280 $str .= "FIRST $nrows "; 281 } 282 $str .= ($offset >= 0) ? "SKIP $offset " : ''; 283 284 $sql = preg_replace('/^[ \t]*select/i', $str, $sql); 285 if ($secs) { 286 $rs = $this->cacheExecute($secs, $sql, $inputarr); 287 } else { 288 $rs = $this->execute($sql, $inputarr); 289 } 290 291 return $rs; 292 } 293 294 /** 295 * Sets the appropriate type into the $fld variable 296 * 297 * @param ADOFieldObject $fld By reference 298 * @param int $ftype 299 * @param int $flen 300 * @param int $fscale 301 * @param int $fsubtype 302 * @param int $fprecision 303 * @param bool $dialect3 304 */ 305 private function _convertFieldType(&$fld, $ftype, $flen, $fscale, $fsubtype, $fprecision, $dialect3) 306 { 307 $fscale = abs($fscale); 308 $fld->max_length = $flen; 309 $fld->scale = null; 310 switch ($ftype) { 311 case 7: 312 case 8: 313 if ($dialect3) { 314 switch ($fsubtype) { 315 case 0: 316 $fld->type = ($ftype == 7 ? 'smallint' : 'integer'); 317 break; 318 case 1: 319 $fld->type = 'numeric'; 320 $fld->max_length = $fprecision; 321 $fld->scale = $fscale; 322 break; 323 case 2: 324 $fld->type = 'decimal'; 325 $fld->max_length = $fprecision; 326 $fld->scale = $fscale; 327 break; 328 } // switch 329 } else { 330 if ($fscale != 0) { 331 $fld->type = 'decimal'; 332 $fld->scale = $fscale; 333 $fld->max_length = ($ftype == 7 ? 4 : 9); 334 } else { 335 $fld->type = ($ftype == 7 ? 'smallint' : 'integer'); 336 } 337 } 338 break; 339 case 16: 340 if ($dialect3) { 341 switch ($fsubtype) { 342 case 0: 343 $fld->type = 'decimal'; 344 $fld->max_length = 18; 345 $fld->scale = 0; 346 break; 347 case 1: 348 $fld->type = 'numeric'; 349 $fld->max_length = $fprecision; 350 $fld->scale = $fscale; 351 break; 352 case 2: 353 $fld->type = 'decimal'; 354 $fld->max_length = $fprecision; 355 $fld->scale = $fscale; 356 break; 357 } // switch 358 } 359 break; 360 case 10: 361 $fld->type = 'float'; 362 break; 363 case 14: 364 $fld->type = 'char'; 365 break; 366 case 27: 367 if ($fscale != 0) { 368 $fld->type = 'decimal'; 369 $fld->max_length = 15; 370 $fld->scale = 5; 371 } else { 372 $fld->type = 'double'; 373 } 374 break; 375 case 35: 376 if ($dialect3) { 377 $fld->type = 'timestamp'; 378 } else { 379 $fld->type = 'date'; 380 } 381 break; 382 case 12: 383 $fld->type = 'date'; 384 break; 385 case 13: 386 $fld->type = 'time'; 387 break; 388 case 37: 389 $fld->type = 'varchar'; 390 break; 391 case 40: 392 $fld->type = 'cstring'; 393 break; 394 case 261: 395 $fld->type = 'blob'; 396 $fld->max_length = -1; 397 break; 398 } // switch 399 } 400 } 401 402 /** 403 * Class ADORecordSet_pdo_firebird 404 */ 405 class ADORecordSet_pdo_firebird extends ADORecordSet_pdo 406 { 407 408 public $databaseType = "pdo_firebird"; 409 410 /** 411 * returns the field object 412 * 413 * @param int $fieldOffset Optional field offset 414 * 415 * @return object The ADOFieldObject describing the field 416 */ 417 public function fetchField($fieldOffset = 0) 418 { 419 } 420 } 421 422 /** 423 * Class ADORecordSet_array_pdo_firebird 424 */ 425 class ADORecordSet_array_pdo_firebird extends ADORecordSet_array_pdo 426 { 427 public $databaseType = "pdo_firebird"; 428 public $canSeek = true; 429 430 /** 431 * returns the field object 432 * 433 * @param int $fieldOffset Optional field offset 434 * 435 * @return object The ADOFieldObject describing the field 436 */ 437 public function fetchField($fieldOffset = 0) 438 { 439 440 $fld = new ADOFieldObject; 441 $fld->name = $fieldOffset; 442 $fld->type = 'C'; 443 $fld->max_length = 0; 444 445 // This needs to be populated from the metadata 446 $fld->not_null = false; 447 $fld->has_default = false; 448 $fld->default_value = 'null'; 449 450 return $fld; 451 } 452 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body