See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]
1 <?php 2 /** 3 * Informix driver. 4 * 5 * @deprecated 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 2014 Damien Regad, Mark Newnham and the ADOdb community 22 * @author Mitchell T. Young <mitch@youngfamily.org> 23 * @author Samuel Carriere <samuel_carriere@hotmail.com> 24 */ 25 26 // security - hide paths 27 if (!defined('ADODB_DIR')) die(); 28 29 if (!defined('IFX_SCROLL')) define('IFX_SCROLL',1); 30 31 class ADODB_informix72 extends ADOConnection { 32 var $databaseType = "informix72"; 33 var $dataProvider = "informix"; 34 var $replaceQuote = "''"; // string to use to replace quotes 35 var $fmtDate = "'Y-m-d'"; 36 var $fmtTimeStamp = "'Y-m-d H:i:s'"; 37 var $hasInsertID = true; 38 var $hasAffectedRows = true; 39 var $substr = 'substr'; 40 var $metaTablesSQL="select tabname,tabtype from systables where tabtype in ('T','V') and owner!='informix'"; //Don't get informix tables and pseudo-tables 41 42 43 var $metaColumnsSQL = 44 "select c.colname, c.coltype, c.collength, d.default,c.colno 45 from syscolumns c, systables t,outer sysdefaults d 46 where c.tabid=t.tabid and d.tabid=t.tabid and d.colno=c.colno 47 and tabname='%s' order by c.colno"; 48 49 var $metaPrimaryKeySQL = 50 "select part1,part2,part3,part4,part5,part6,part7,part8 from 51 systables t,sysconstraints s,sysindexes i where t.tabname='%s' 52 and s.tabid=t.tabid and s.constrtype='P' 53 and i.idxname=s.idxname"; 54 55 var $concat_operator = '||'; 56 57 var $lastQuery = false; 58 var $has_insertid = true; 59 60 var $_autocommit = true; 61 var $_bindInputArray = true; // set to true if ADOConnection.Execute() permits binding of array parameters. 62 var $sysDate = 'TODAY'; 63 var $sysTimeStamp = 'CURRENT'; 64 var $cursorType = IFX_SCROLL; // IFX_SCROLL or IFX_HOLD or 0 65 66 function __construct() 67 { 68 // alternatively, use older method: 69 //putenv("DBDATE=Y4MD-"); 70 71 // force ISO date format 72 putenv('GL_DATE=%Y-%m-%d'); 73 74 if (function_exists('ifx_byteasvarchar')) { 75 ifx_byteasvarchar(1); // Mode "0" will return a blob id, and mode "1" will return a varchar with text content. 76 ifx_textasvarchar(1); // Mode "0" will return a blob id, and mode "1" will return a varchar with text content. 77 ifx_blobinfile_mode(0); // Mode "0" means save Byte-Blobs in memory, and mode "1" means save Byte-Blobs in a file. 78 } 79 } 80 81 function ServerInfo() 82 { 83 if (isset($this->version)) return $this->version; 84 85 $arr['description'] = $this->GetOne("select DBINFO('version','full') from systables where tabid = 1"); 86 $arr['version'] = $this->GetOne("select DBINFO('version','major') || DBINFO('version','minor') from systables where tabid = 1"); 87 $this->version = $arr; 88 return $arr; 89 } 90 91 92 93 protected function _insertID($table = '', $column = '') 94 { 95 $sqlca =ifx_getsqlca($this->lastQuery); 96 return @$sqlca["sqlerrd1"]; 97 } 98 99 function _affectedrows() 100 { 101 if ($this->lastQuery) { 102 return @ifx_affected_rows ($this->lastQuery); 103 } 104 return 0; 105 } 106 107 function BeginTrans() 108 { 109 if ($this->transOff) return true; 110 $this->transCnt += 1; 111 $this->Execute('BEGIN'); 112 $this->_autocommit = false; 113 return true; 114 } 115 116 function CommitTrans($ok=true) 117 { 118 if (!$ok) return $this->RollbackTrans(); 119 if ($this->transOff) return true; 120 if ($this->transCnt) $this->transCnt -= 1; 121 $this->Execute('COMMIT'); 122 $this->_autocommit = true; 123 return true; 124 } 125 126 function RollbackTrans() 127 { 128 if ($this->transOff) return true; 129 if ($this->transCnt) $this->transCnt -= 1; 130 $this->Execute('ROLLBACK'); 131 $this->_autocommit = true; 132 return true; 133 } 134 135 function RowLock($tables,$where,$col='1 as adodbignore') 136 { 137 if ($this->_autocommit) $this->BeginTrans(); 138 return $this->GetOne("select $col from $tables where $where for update"); 139 } 140 141 /* Returns: the last error message from previous database operation 142 Note: This function is NOT available for Microsoft SQL Server. */ 143 144 function ErrorMsg() 145 { 146 if (!empty($this->_logsql)) return $this->_errorMsg; 147 $this->_errorMsg = ifx_errormsg(); 148 return $this->_errorMsg; 149 } 150 151 function ErrorNo() 152 { 153 preg_match("/.*SQLCODE=([^\]]*)/",ifx_error(),$parse); 154 if (is_array($parse) && isset($parse[1])) return (int)$parse[1]; 155 return 0; 156 } 157 158 159 function MetaProcedures($NamePattern = false, $catalog = null, $schemaPattern = null) 160 { 161 // save old fetch mode 162 global $ADODB_FETCH_MODE; 163 164 $false = false; 165 $save = $ADODB_FETCH_MODE; 166 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 167 if ($this->fetchMode !== FALSE) { 168 $savem = $this->SetFetchMode(FALSE); 169 170 } 171 $procedures = array (); 172 173 // get index details 174 175 $likepattern = ''; 176 if ($NamePattern) { 177 $likepattern = " WHERE procname LIKE '".$NamePattern."'"; 178 } 179 180 $rs = $this->Execute('SELECT procname, isproc FROM sysprocedures'.$likepattern); 181 182 if (is_object($rs)) { 183 // parse index data into array 184 185 while ($row = $rs->FetchRow()) { 186 $procedures[$row[0]] = array( 187 'type' => ($row[1] == 'f' ? 'FUNCTION' : 'PROCEDURE'), 188 'catalog' => '', 189 'schema' => '', 190 'remarks' => '' 191 ); 192 } 193 } 194 195 // restore fetchmode 196 if (isset($savem)) { 197 $this->SetFetchMode($savem); 198 } 199 $ADODB_FETCH_MODE = $save; 200 201 return $procedures; 202 } 203 204 function MetaColumns($table, $normalize=true) 205 { 206 global $ADODB_FETCH_MODE; 207 208 $false = false; 209 if (!empty($this->metaColumnsSQL)) { 210 $save = $ADODB_FETCH_MODE; 211 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 212 if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false); 213 $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table)); 214 if (isset($savem)) $this->SetFetchMode($savem); 215 $ADODB_FETCH_MODE = $save; 216 if ($rs === false) return $false; 217 $rspkey = $this->Execute(sprintf($this->metaPrimaryKeySQL,$table)); //Added to get primary key colno items 218 219 $retarr = array(); 220 while (!$rs->EOF) { //print_r($rs->fields); 221 $fld = new ADOFieldObject(); 222 $fld->name = $rs->fields[0]; 223 /* //!eos. 224 $rs->fields[1] is not the correct adodb type 225 $rs->fields[2] is not correct max_length, because can include not-null bit 226 227 $fld->type = $rs->fields[1]; 228 $fld->primary_key=$rspkey->fields && array_search($rs->fields[4],$rspkey->fields); //Added to set primary key flag 229 $fld->max_length = $rs->fields[2];*/ 230 $pr=ifx_props($rs->fields[1],$rs->fields[2]); //!eos 231 $fld->type = $pr[0] ;//!eos 232 $fld->primary_key=$rspkey->fields && array_search($rs->fields[4],$rspkey->fields); 233 $fld->max_length = $pr[1]; //!eos 234 $fld->precision = $pr[2] ;//!eos 235 $fld->not_null = $pr[3]=="N"; //!eos 236 237 if (trim($rs->fields[3]) != "AAAAAA 0") { 238 $fld->has_default = 1; 239 $fld->default_value = $rs->fields[3]; 240 } else { 241 $fld->has_default = 0; 242 } 243 244 $retarr[strtolower($fld->name)] = $fld; 245 $rs->MoveNext(); 246 } 247 248 $rs->Close(); 249 $rspkey->Close(); //!eos 250 return $retarr; 251 } 252 253 return $false; 254 } 255 256 function xMetaColumns($table) 257 { 258 return ADOConnection::MetaColumns($table,false); 259 } 260 261 public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false) 262 { 263 $sql = " 264 select tr.tabname,updrule,delrule, 265 i.part1 o1,i2.part1 d1,i.part2 o2,i2.part2 d2,i.part3 o3,i2.part3 d3,i.part4 o4,i2.part4 d4, 266 i.part5 o5,i2.part5 d5,i.part6 o6,i2.part6 d6,i.part7 o7,i2.part7 d7,i.part8 o8,i2.part8 d8 267 from systables t,sysconstraints s,sysindexes i, 268 sysreferences r,systables tr,sysconstraints s2,sysindexes i2 269 where t.tabname='$table' 270 and s.tabid=t.tabid and s.constrtype='R' and r.constrid=s.constrid 271 and i.idxname=s.idxname and tr.tabid=r.ptabid 272 and s2.constrid=r.primary and i2.idxname=s2.idxname"; 273 274 $rs = $this->Execute($sql); 275 if (!$rs || $rs->EOF) return false; 276 $arr = $rs->GetArray(); 277 $a = array(); 278 foreach($arr as $v) { 279 $coldest=$this->metaColumnNames($v["tabname"]); 280 $colorig=$this->metaColumnNames($table); 281 $colnames=array(); 282 for($i=1;$i<=8 && $v["o$i"] ;$i++) { 283 $colnames[]=$coldest[$v["d$i"]-1]."=".$colorig[$v["o$i"]-1]; 284 } 285 if($upper) 286 $a[strtoupper($v["tabname"])] = $colnames; 287 else 288 $a[$v["tabname"]] = $colnames; 289 } 290 return $a; 291 } 292 293 function UpdateBlob($table, $column, $val, $where, $blobtype = 'BLOB') 294 { 295 $type = ($blobtype == 'TEXT') ? 1 : 0; 296 $blobid = ifx_create_blob($type,0,$val); 297 return $this->Execute("UPDATE $table SET $column=(?) WHERE $where",array($blobid)); 298 } 299 300 function BlobDecode($blobid) 301 { 302 return function_exists('ifx_byteasvarchar') ? $blobid : @ifx_get_blob($blobid); 303 } 304 305 // returns true or false 306 function _connect($argHostname, $argUsername, $argPassword, $argDatabasename) 307 { 308 if (!function_exists('ifx_connect')) return null; 309 310 $dbs = $argDatabasename . "@" . $argHostname; 311 if ($argHostname) putenv("INFORMIXSERVER=$argHostname"); 312 putenv("INFORMIXSERVER=".trim($argHostname)); 313 $this->_connectionID = ifx_connect($dbs,$argUsername,$argPassword); 314 if ($this->_connectionID === false) return false; 315 #if ($argDatabasename) return $this->SelectDB($argDatabasename); 316 return true; 317 } 318 319 // returns true or false 320 function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) 321 { 322 if (!function_exists('ifx_connect')) return null; 323 324 $dbs = $argDatabasename . "@" . $argHostname; 325 putenv("INFORMIXSERVER=".trim($argHostname)); 326 $this->_connectionID = ifx_pconnect($dbs,$argUsername,$argPassword); 327 if ($this->_connectionID === false) return false; 328 #if ($argDatabasename) return $this->SelectDB($argDatabasename); 329 return true; 330 } 331 /* 332 // ifx_do does not accept bind parameters - weird ??? 333 function Prepare($sql) 334 { 335 $stmt = ifx_prepare($sql); 336 if (!$stmt) return $sql; 337 else return array($sql,$stmt); 338 } 339 */ 340 // returns query ID if successful, otherwise false 341 function _query($sql,$inputarr=false) 342 { 343 global $ADODB_COUNTRECS; 344 345 // String parameters have to be converted using ifx_create_char 346 if ($inputarr) { 347 foreach($inputarr as $v) { 348 if (gettype($v) == 'string') { 349 $tab[] = ifx_create_char($v); 350 } 351 else { 352 $tab[] = $v; 353 } 354 } 355 } 356 357 // In case of select statement, we use a scroll cursor in order 358 // to be able to call "move", or "movefirst" statements 359 if (!$ADODB_COUNTRECS && preg_match("/^\s*select/is", $sql)) { 360 if ($inputarr) { 361 $this->lastQuery = ifx_query($sql,$this->_connectionID, $this->cursorType, $tab); 362 } 363 else { 364 $this->lastQuery = ifx_query($sql,$this->_connectionID, $this->cursorType); 365 } 366 } 367 else { 368 if ($inputarr) { 369 $this->lastQuery = ifx_query($sql,$this->_connectionID, $tab); 370 } 371 else { 372 $this->lastQuery = ifx_query($sql,$this->_connectionID); 373 } 374 } 375 376 // Following line have been commented because autocommit mode is 377 // not supported by informix SE 7.2 378 379 //if ($this->_autocommit) ifx_query('COMMIT',$this->_connectionID); 380 381 return $this->lastQuery; 382 } 383 384 // returns true or false 385 function _close() 386 { 387 $this->lastQuery = false; 388 if($this->_connectionID) { 389 return ifx_close($this->_connectionID); 390 } 391 return true; 392 } 393 } 394 395 396 /*-------------------------------------------------------------------------------------- 397 Class Name: Recordset 398 --------------------------------------------------------------------------------------*/ 399 400 class ADORecordset_informix72 extends ADORecordSet { 401 402 var $databaseType = "informix72"; 403 var $canSeek = true; 404 var $_fieldprops = false; 405 406 function __construct($id,$mode=false) 407 { 408 if ($mode === false) { 409 global $ADODB_FETCH_MODE; 410 $mode = $ADODB_FETCH_MODE; 411 } 412 $this->fetchMode = $mode; 413 parent::__construct($id); 414 } 415 416 417 418 /* Returns: an object containing field information. 419 Get column information in the Recordset object. fetchField() can be used in order to obtain information about 420 fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by 421 fetchField() is retrieved. */ 422 function FetchField($fieldOffset = -1) 423 { 424 if (empty($this->_fieldprops)) { 425 $fp = ifx_fieldproperties($this->_queryID); 426 foreach($fp as $k => $v) { 427 $o = new ADOFieldObject; 428 $o->name = $k; 429 $arr = explode(';',$v); //"SQLTYPE;length;precision;scale;ISNULLABLE" 430 $o->type = $arr[0]; 431 $o->max_length = $arr[1]; 432 $this->_fieldprops[] = $o; 433 $o->not_null = $arr[4]=="N"; 434 } 435 } 436 $ret = $this->_fieldprops[$fieldOffset]; 437 return $ret; 438 } 439 440 function _initrs() 441 { 442 $this->_numOfRows = -1; // ifx_affected_rows not reliable, only returns estimate -- ($ADODB_COUNTRECS)? ifx_affected_rows($this->_queryID):-1; 443 $this->_numOfFields = ifx_num_fields($this->_queryID); 444 } 445 446 function _seek($row) 447 { 448 return @ifx_fetch_row($this->_queryID, (int) $row); 449 } 450 451 function MoveLast() 452 { 453 $this->fields = @ifx_fetch_row($this->_queryID, "LAST"); 454 if ($this->fields) $this->EOF = false; 455 $this->_currentRow = -1; 456 457 if ($this->fetchMode == ADODB_FETCH_NUM) { 458 foreach($this->fields as $v) { 459 $arr[] = $v; 460 } 461 $this->fields = $arr; 462 } 463 464 return true; 465 } 466 467 function MoveFirst() 468 { 469 $this->fields = @ifx_fetch_row($this->_queryID, "FIRST"); 470 if ($this->fields) $this->EOF = false; 471 $this->_currentRow = 0; 472 473 if ($this->fetchMode == ADODB_FETCH_NUM) { 474 foreach($this->fields as $v) { 475 $arr[] = $v; 476 } 477 $this->fields = $arr; 478 } 479 480 return true; 481 } 482 483 function _fetch($ignore_fields=false) 484 { 485 486 $this->fields = @ifx_fetch_row($this->_queryID); 487 488 if (!is_array($this->fields)) return false; 489 490 if ($this->fetchMode == ADODB_FETCH_NUM) { 491 foreach($this->fields as $v) { 492 $arr[] = $v; 493 } 494 $this->fields = $arr; 495 } 496 return true; 497 } 498 499 /* close() only needs to be called if you are worried about using too much memory while your script 500 is running. All associated result memory for the specified result identifier will automatically be freed. */ 501 function _close() 502 { 503 if($this->_queryID) { 504 return ifx_free_result($this->_queryID); 505 } 506 return true; 507 } 508 509 } 510 /** !Eos 511 * Auxiliary function to Parse coltype,collength. Used by Metacolumns 512 * return: array ($mtype,$length,$precision,$nullable) (similar to ifx_fieldpropierties) 513 */ 514 function ifx_props($coltype,$collength){ 515 $itype=fmod($coltype+1,256); 516 $nullable=floor(($coltype+1) /256) ?"N":"Y"; 517 $mtype=substr(" CIIFFNNDN TBXCC ",$itype,1); 518 switch ($itype){ 519 case 2: 520 $length=4; 521 case 6: 522 case 9: 523 case 14: 524 $length=floor($collength/256); 525 $precision=fmod($collength,256); 526 break; 527 default: 528 $precision=0; 529 $length=$collength; 530 } 531 return array($mtype,$length,$precision,$nullable); 532 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body