Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

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

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