Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

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