Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]

   1  <?php
   2  /*
   3  @version   v5.21.0  2021-02-27
   4  @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
   5  @copyright (c) 2014      Damien Regad, Mark Newnham and the ADOdb community
   6    Released under both BSD license and Lesser GPL library license.
   7    Whenever there is any discrepancy between the two licenses,
   8    the BSD license will take precedence.
   9  
  10    Latest version is available at https://adodb.org/
  11  
  12    Oracle data driver. Requires Oracle client. Works on Windows and Unix and Oracle 7.
  13  
  14    If you are using Oracle 8 or later, use the oci8 driver which is much better and more reliable.
  15  */
  16  
  17  // security - hide paths
  18  if (!defined('ADODB_DIR')) die();
  19  
  20  class ADODB_oracle extends ADOConnection {
  21  	 var $databaseType = "oracle";
  22  	 var $replaceQuote = "''"; // string to use to replace quotes
  23  	 var $concat_operator='||';
  24  	 var $_curs;
  25  	 var $_initdate = true; // init date to YYYY-MM-DD
  26  	 var $metaTablesSQL = 'select table_name from cat';
  27  	 var $metaColumnsSQL = "select cname,coltype,width from col where tname='%s' order by colno";
  28  	 var $sysDate = "TO_DATE(TO_CHAR(SYSDATE,'YYYY-MM-DD'),'YYYY-MM-DD')";
  29  	 var $sysTimeStamp = 'SYSDATE';
  30  	 var $connectSID = true;
  31  
  32  	 // format and return date string in database date format
  33  	function DBDate($d, $isfld = false)
  34  	 {
  35  	 	 if (is_string($d)) $d = ADORecordSet::UnixDate($d);
  36  	 	 if (is_object($d)) $ds = $d->format($this->fmtDate);
  37  	 	 else $ds = adodb_date($this->fmtDate,$d);
  38  	 	 return 'TO_DATE('.$ds.",'YYYY-MM-DD')";
  39  	 }
  40  
  41  	 // format and return date string in database timestamp format
  42  	function DBTimeStamp($ts, $isfld = false)
  43  	 {
  44  
  45  	 	 if (is_string($ts)) $ts = ADORecordSet::UnixTimeStamp($ts);
  46  	 	 if (is_object($ts)) $ds = $ts->format($this->fmtDate);
  47  	 	 else $ds = adodb_date($this->fmtTimeStamp,$ts);
  48  	 	 return 'TO_DATE('.$ds.",'RRRR-MM-DD, HH:MI:SS AM')";
  49  	 }
  50  
  51  
  52  	function BindDate($d)
  53  	 {
  54  	 	 $d = ADOConnection::DBDate($d);
  55  	 	 if (strncmp($d,"'",1)) return $d;
  56  
  57  	 	 return substr($d,1,strlen($d)-2);
  58  	 }
  59  
  60  	function BindTimeStamp($d)
  61  	 {
  62  	 	 $d = ADOConnection::DBTimeStamp($d);
  63  	 	 if (strncmp($d,"'",1)) return $d;
  64  
  65  	 	 return substr($d,1,strlen($d)-2);
  66  	 }
  67  
  68  
  69  
  70  	function BeginTrans()
  71  	 {
  72  	 	  $this->autoCommit = false;
  73  	 	  ora_commitoff($this->_connectionID);
  74  	 	  return true;
  75  	 }
  76  
  77  
  78  	function CommitTrans($ok=true)
  79  	 {
  80  	 	    if (!$ok) return $this->RollbackTrans();
  81  	 	    $ret = ora_commit($this->_connectionID);
  82  	 	    ora_commiton($this->_connectionID);
  83  	 	    return $ret;
  84  	 }
  85  
  86  
  87  	function RollbackTrans()
  88  	 {
  89  	 	 $ret = ora_rollback($this->_connectionID);
  90  	 	 ora_commiton($this->_connectionID);
  91  	 	 return $ret;
  92  	 }
  93  
  94  
  95  	 /* there seems to be a bug in the oracle extension -- always returns ORA-00000 - no error */
  96  	function ErrorMsg()
  97   	 {
  98          if ($this->_errorMsg !== false) return $this->_errorMsg;
  99  
 100          if (is_resource($this->_curs)) $this->_errorMsg = @ora_error($this->_curs);
 101   	 	 if (empty($this->_errorMsg)) $this->_errorMsg = @ora_error($this->_connectionID);
 102  	 	 return $this->_errorMsg;
 103  	 }
 104  
 105  
 106  	function ErrorNo()
 107  	 {
 108  	 	 if ($this->_errorCode !== false) return $this->_errorCode;
 109  
 110  	 	 if (is_resource($this->_curs)) $this->_errorCode = @ora_errorcode($this->_curs);
 111  	 	 if (empty($this->_errorCode)) $this->_errorCode = @ora_errorcode($this->_connectionID);
 112          return $this->_errorCode;
 113  	 }
 114  
 115  
 116  
 117  	 	 // returns true or false
 118  		function _connect($argHostname, $argUsername, $argPassword, $argDatabasename, $mode=0)
 119  	 	 {
 120  	 	 	 if (!function_exists('ora_plogon')) return null;
 121  
 122              // <G. Giunta 2003/03/03/> Reset error messages before connecting
 123              $this->_errorMsg = false;
 124  	 	     $this->_errorCode = false;
 125  
 126              // G. Giunta 2003/08/13 - This looks danegrously suspicious: why should we want to set
 127              // the oracle home to the host name of remote DB?
 128  //	 	 	 if ($argHostname) putenv("ORACLE_HOME=$argHostname");
 129  
 130  	 	 	 if($argHostname) { // code copied from version submitted for oci8 by Jorma Tuomainen <jorma.tuomainen@ppoy.fi>
 131  	 	 	 	 if (empty($argDatabasename)) $argDatabasename = $argHostname;
 132  	 	 	 	 else {
 133  	 	 	 	 	 if(strpos($argHostname,":")) {
 134  	 	 	 	 	 	 $argHostinfo=explode(":",$argHostname);
 135  	 	 	 	 	 	 $argHostname=$argHostinfo[0];
 136  	 	 	 	 	 	 $argHostport=$argHostinfo[1];
 137  	 	 	 	 	 } else {
 138  	 	 	 	 	 	 $argHostport="1521";
 139  	 	 	 	 	 }
 140  
 141  
 142  	 	 	 	 	 if ($this->connectSID) {
 143  	 	 	 	 	 	 $argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname
 144  	 	 	 	 	 	 .")(PORT=$argHostport))(CONNECT_DATA=(SID=$argDatabasename)))";
 145  	 	 	 	 	 } else
 146  	 	 	 	 	 	 $argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname
 147  	 	 	 	 	 	 .")(PORT=$argHostport))(CONNECT_DATA=(SERVICE_NAME=$argDatabasename)))";
 148  	 	 	 	 }
 149  
 150  	 	 	 }
 151  
 152  	 	 	 if ($argDatabasename) $argUsername .= "@$argDatabasename";
 153  
 154  	 	 //if ($argHostname) print "<p>Connect: 1st argument should be left blank for $this->databaseType</p>";
 155  	 	 	 if ($mode == 1)
 156  	 	 	 	 $this->_connectionID = ora_plogon($argUsername,$argPassword);
 157  	 	 	 else
 158  	 	 	 	 $this->_connectionID = ora_logon($argUsername,$argPassword);
 159  	 	 	 if ($this->_connectionID === false) return false;
 160  	 	 	 if ($this->autoCommit) ora_commiton($this->_connectionID);
 161  	 	 	 if ($this->_initdate) {
 162  	 	 	 	 $rs = $this->_query("ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD'");
 163  	 	 	 	 if ($rs) ora_close($rs);
 164  	 	 	 }
 165  
 166  	 	 	 return true;
 167  	 	 }
 168  
 169  
 170  	 	 // returns true or false
 171  		function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
 172  	 	 {
 173  	 	 	 return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename, 1);
 174  	 	 }
 175  
 176  
 177  	 	 // returns query ID if successful, otherwise false
 178  		function _query($sql,$inputarr=false)
 179  	 	 {
 180              // <G. Giunta 2003/03/03/> Reset error messages before executing
 181              $this->_errorMsg = false;
 182  	 	     $this->_errorCode = false;
 183  
 184  	 	 	 $curs = ora_open($this->_connectionID);
 185  
 186  	 	  	 if ($curs === false) return false;
 187  	 	 	 $this->_curs = $curs;
 188  	 	 	 if (!ora_parse($curs,$sql)) return false;
 189  	 	 	 if (ora_exec($curs)) return $curs;
 190              // <G. Giunta 2004/03/03> before we close the cursor, we have to store the error message
 191              // that we can obtain ONLY from the cursor (and not from the connection)
 192              $this->_errorCode = @ora_errorcode($curs);
 193              $this->_errorMsg = @ora_error($curs);
 194              // </G. Giunta 2004/03/03>
 195  	 	  	 @ora_close($curs);
 196  	 	 	 return false;
 197  	 	 }
 198  
 199  
 200  	 	 // returns true or false
 201  		function _close()
 202  	 	 {
 203  	 	 	 return @ora_logoff($this->_connectionID);
 204  	 	 }
 205  
 206  
 207  
 208  }
 209  
 210  
 211  /*--------------------------------------------------------------------------------------
 212  	 	  Class Name: Recordset
 213  --------------------------------------------------------------------------------------*/
 214  
 215  class ADORecordset_oracle extends ADORecordSet {
 216  
 217  	 var $databaseType = "oracle";
 218  	 var $bind = false;
 219  
 220  	function __construct($queryID,$mode=false)
 221  	 {
 222  
 223  	 	 if ($mode === false) {
 224  	 	 	 global $ADODB_FETCH_MODE;
 225  	 	 	 $mode = $ADODB_FETCH_MODE;
 226  	 	 }
 227  	 	 $this->fetchMode = $mode;
 228  
 229  	 	 $this->_queryID = $queryID;
 230  
 231  	 	 $this->_inited = true;
 232  	 	 $this->fields = array();
 233  	 	 if ($queryID) {
 234  	 	 	 $this->_currentRow = 0;
 235  	 	 	 $this->EOF = !$this->_fetch();
 236  	 	 	 @$this->_initrs();
 237  	 	 } else {
 238  	 	 	 $this->_numOfRows = 0;
 239  	 	 	 $this->_numOfFields = 0;
 240  	 	 	 $this->EOF = true;
 241  	 	 }
 242  
 243  	 	 return $this->_queryID;
 244  	 }
 245  
 246  
 247  
 248  	    /*	 	 Returns: an object containing field information.
 249  	 	 	    Get column information in the Recordset object. fetchField() can be used in order to obtain information about
 250  	 	 	    fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
 251  	 	 	    fetchField() is retrieved.	 	 */
 252  
 253  	   function FetchField($fieldOffset = -1)
 254  	    {
 255  	 	 	 $fld = new ADOFieldObject;
 256  	 	 	 $fld->name = ora_columnname($this->_queryID, $fieldOffset);
 257  	 	 	 $fld->type = ora_columntype($this->_queryID, $fieldOffset);
 258  	 	 	 $fld->max_length = ora_columnsize($this->_queryID, $fieldOffset);
 259  	 	 	 return $fld;
 260  	    }
 261  
 262  	 /* Use associative array to get fields array */
 263  	function Fields($colname)
 264  	 {
 265  	 	 if (!$this->bind) {
 266  	 	 	 $this->bind = array();
 267  	 	 	 for ($i=0; $i < $this->_numOfFields; $i++) {
 268  	 	 	 	 $o = $this->FetchField($i);
 269  	 	 	 	 $this->bind[strtoupper($o->name)] = $i;
 270  	 	 	 }
 271  	 	 }
 272  
 273  	 	  return $this->fields[$this->bind[strtoupper($colname)]];
 274  	 }
 275  
 276     function _initrs()
 277     {
 278  	 	    $this->_numOfRows = -1;
 279  	 	    $this->_numOfFields = @ora_numcols($this->_queryID);
 280     }
 281  
 282  
 283     function _seek($row)
 284     {
 285  	 	    return false;
 286     }
 287  
 288     function _fetch($ignore_fields=false) {
 289  // should remove call by reference, but ora_fetch_into requires it in 4.0.3pl1
 290  	 	 if ($this->fetchMode & ADODB_FETCH_ASSOC)
 291  	 	 	 return @ora_fetch_into($this->_queryID,$this->fields,ORA_FETCHINTO_NULLS|ORA_FETCHINTO_ASSOC);
 292     	 	 else
 293  	 	 	 return @ora_fetch_into($this->_queryID,$this->fields,ORA_FETCHINTO_NULLS);
 294     }
 295  
 296     /*	 	 close() only needs to be called if you are worried about using too much memory while your script
 297  	 	    is running. All associated result memory for the specified result identifier will automatically be freed.	 	 */
 298  
 299     function _close()
 300  {
 301  	 	    return @ora_close($this->_queryID);
 302     }
 303  
 304  	function MetaType($t, $len = -1, $fieldobj = false)
 305  	 {
 306  	 	 if (is_object($t)) {
 307  	 	 	 $fieldobj = $t;
 308  	 	 	 $t = $fieldobj->type;
 309  	 	 	 $len = $fieldobj->max_length;
 310  	 	 }
 311  
 312  	 	 switch (strtoupper($t)) {
 313  	 	 case 'VARCHAR':
 314  	 	 case 'VARCHAR2':
 315  	 	 case 'CHAR':
 316  	 	 case 'VARBINARY':
 317  	 	 case 'BINARY':
 318  	 	 	 	 if ($len <= $this->blobSize) return 'C';
 319  	 	 case 'LONG':
 320  	 	 case 'LONG VARCHAR':
 321  	 	 case 'CLOB':
 322  	 	 return 'X';
 323  	 	 case 'LONG RAW':
 324  	 	 case 'LONG VARBINARY':
 325  	 	 case 'BLOB':
 326  	 	 	 	 return 'B';
 327  
 328  	 	 case 'DATE': return 'D';
 329  
 330  	 	 //case 'T': return 'T';
 331  
 332  	 	 case 'BIT': return 'L';
 333  	 	 case 'INT':
 334  	 	 case 'SMALLINT':
 335  	 	 case 'INTEGER': return 'I';
 336  	 	 default: return 'N';
 337  	 	 }
 338  	 }
 339  }