Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

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  }