Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.0.x will end 8 May 2023 (12 months).
  • Bug fixes for security issues in 4.0.x will end 13 November 2023 (18 months).
  • PHP version: minimum PHP 7.3.0 Note: the minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is also supported.
<?php
/**
 * Portable version of Oracle oci8 driver
 *
 * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
 *
 * Portable version of oci8 driver, to make it more similar to other database
 * drivers. The main differences are
 * 1. that the OCI_ASSOC names are in lowercase instead of uppercase.
 * 2. bind variables are mapped using ? instead of :<bindvar>
 *
 * @package ADOdb
 * @link https://adodb.org Project's web site and documentation
 * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
 *
 * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
 * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
 * any later version. This means you can use it in proprietary products.
 * See the LICENSE.md file distributed with this source code for details.
 * @license BSD-3-Clause
 * @license LGPL-2.1-or-later
 *
 * @copyright 2000-2013 John Lim
 * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
 */

// security - hide paths
if (!defined('ADODB_DIR')) die();

include_once(ADODB_DIR.'/drivers/adodb-oci8.inc.php');

class ADODB_oci8po extends ADODB_oci8 {
	var $databaseType = 'oci8po';
	var $dataProvider = 'oci8';
	var $metaColumnsSQL = "select lower(cname),coltype,width, SCALE, PRECISION, NULLS, DEFAULTVAL from col where tname='%s' order by colno"; //changed by smondino@users.sourceforge. net
	var $metaTablesSQL = "select lower(table_name),table_type from cat where table_type in ('TABLE','VIEW')";

	function Param($name,$type='C')
	{
		return '?';
	}

	function Prepare($sql,$cursor=false)
	{
		$sqlarr = explode('?',$sql);
		$sql = $sqlarr[0];
		for ($i = 1, $max = sizeof($sqlarr); $i < $max; $i++) {
			$sql .=  ':'.($i-1) . $sqlarr[$i];
		}
		return ADODB_oci8::Prepare($sql,$cursor);
	}

	function Execute($sql,$inputarr=false)
	{
		return ADOConnection::Execute($sql,$inputarr);
	}

	/**
	 * The optimizations performed by ADODB_oci8::SelectLimit() are not
	 * compatible with the oci8po driver, so we rely on the slower method
	 * from the base class.
	 * We can't properly handle prepared statements either due to preprocessing
	 * of query parameters, so we treat them as regular SQL statements.
	 */
	function SelectLimit($sql, $nrows=-1, $offset=-1, $inputarr=false, $secs2cache=0)
	{
		if(is_array($sql)) {
//			$sql = $sql[0];
		}
		return ADOConnection::SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
	}

	// emulate handling of parameters ? ?, replacing with :bind0 :bind1
	function _query($sql,$inputarr=false)
	{
		if (is_array($inputarr)) {
			$i = 0;
			if (is_array($sql)) {
				foreach($inputarr as $v) {
					$arr['bind'.$i++] = $v;
				}
			} else {
				$sql = $this->extractBinds($sql,$inputarr);
			}
		}
		return ADODB_oci8::_query($sql,$inputarr);
	}
	
	/**
	* Replaces compatibility bind markers with oracle ones and returns a
	* valid sql statement
	*
	* This replaces a regexp based section of code that has been subject
	* to numerous tweaks, as more extreme test cases have appeared. This
	* is now done this like this to help maintainability and avoid the 
	* need to rely on regexp experienced maintainers
	*
	* @param	string		$sql		The sql statement
	* @param	string[]	$inputarr	The bind array
	*
	* @return	string	The modified statement
	*/	
	private function extractBinds($sql,$inputarr)
	{
		$inString  = false;
		$escaped   = 0;
		$sqlLength = strlen($sql) - 1;
		$newSql    = '';
		$bindCount = 0;
		
		/*
		* inputarr is the passed in bind list, which is associative, but
		* we only want the keys here
		*/
		$inputKeys = array_keys($inputarr);
		
<
for ($i=0;$i<=$sqlLength;$i++) { /* * find the next character of the string */ $c = $sql[$i]; if ($c == "'" && !$inString && $escaped==0) /* * Found the start of a string inside the statement */ $inString = true; elseif ($c == "\\" && $escaped==0) /* * The next character will be escaped */ $escaped = 1; elseif ($c == "'" && $inString && $escaped==0) /* * We found the end of the string */ $inString = false; if ($escaped == 2) $escaped = 0; if ($escaped==0 && !$inString && $c == '?') /* * We found a bind symbol, replace it with the oracle equivalent */ $newSql .= ':' . $inputKeys[$bindCount++]; else /* * Add the current character the pile */ $newSql .= $c; if ($escaped == 1) /* * We have just found an escape character, make sure we ignore the * next one that comes along, it might be a ' character */ $escaped = 2; } return $newSql; } } /*-------------------------------------------------------------------------------------- Class Name: Recordset --------------------------------------------------------------------------------------*/ class ADORecordset_oci8po extends ADORecordset_oci8 { var $databaseType = 'oci8po'; function Fields($colname) { if ($this->fetchMode & OCI_ASSOC) return $this->fields[$colname]; if (!$this->bind) { $this->bind = array(); for ($i=0; $i < $this->_numOfFields; $i++) { $o = $this->FetchField($i); $this->bind[strtoupper($o->name)] = $i; } } return $this->fields[$this->bind[strtoupper($colname)]]; } // lowercase field names... function _FetchField($fieldOffset = -1) { $fld = new ADOFieldObject; $fieldOffset += 1;
< $fld->name = OCIcolumnname($this->_queryID, $fieldOffset);
> $fld->name = oci_field_name($this->_queryID, $fieldOffset);
if (ADODB_ASSOC_CASE == ADODB_ASSOC_CASE_LOWER) { $fld->name = strtolower($fld->name); }
< $fld->type = OCIcolumntype($this->_queryID, $fieldOffset); < $fld->max_length = OCIcolumnsize($this->_queryID, $fieldOffset);
> $fld->type = oci_field_type($this->_queryID, $fieldOffset); > $fld->max_length = oci_field_size($this->_queryID, $fieldOffset);
if ($fld->type == 'NUMBER') {
< $sc = OCIColumnScale($this->_queryID, $fieldOffset);
> $sc = oci_field_scale($this->_queryID, $fieldOffset);
if ($sc == 0) { $fld->type = 'INT'; } } return $fld; } // 10% speedup to move MoveNext to child class function MoveNext() { $ret = @oci_fetch_array($this->_queryID,$this->fetchMode); if($ret !== false) { global $ADODB_ANSI_PADDING_OFF; $this->fields = $ret; $this->_currentRow++; $this->_updatefields(); if (!empty($ADODB_ANSI_PADDING_OFF)) { foreach($this->fields as $k => $v) { if (is_string($v)) $this->fields[$k] = rtrim($v); } } return true; } if (!$this->EOF) { $this->EOF = true; $this->_currentRow++; } return false; }
< /* Optimize SelectLimit() by using OCIFetch() instead of OCIFetchInto() */
function GetArrayLimit($nrows,$offset=-1) { if ($offset <= 0) { $arr = $this->GetArray($nrows); return $arr; } for ($i=1; $i < $offset; $i++)
< if (!@OCIFetch($this->_queryID)) {
> if (!@oci_fetch($this->_queryID)) {
$arr = array(); return $arr; } $ret = @oci_fetch_array($this->_queryID,$this->fetchMode); if ($ret === false) { $arr = array(); return $arr; } $this->fields = $ret; $this->_updatefields(); $results = array(); $cnt = 0; while (!$this->EOF && $nrows != $cnt) { $results[$cnt++] = $this->fields; $this->MoveNext(); } return $results; } function _fetch() { global $ADODB_ANSI_PADDING_OFF; $ret = @oci_fetch_array($this->_queryID,$this->fetchMode); if ($ret) { $this->fields = $ret; $this->_updatefields(); if (!empty($ADODB_ANSI_PADDING_OFF)) { foreach($this->fields as $k => $v) { if (is_string($v)) $this->fields[$k] = rtrim($v); } } } return $ret !== false; } }