See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 401 and 402] [Versions 401 and 403]
1 <?php 2 /** 3 * Portable version of Oracle oci8 driver 4 * 5 * This file is part of ADOdb, a Database Abstraction Layer library for PHP. 6 * 7 * Portable version of oci8 driver, to make it more similar to other database 8 * drivers. The main differences are 9 * 1. that the OCI_ASSOC names are in lowercase instead of uppercase. 10 * 2. bind variables are mapped using ? instead of :<bindvar> 11 * 12 * @package ADOdb 13 * @link https://adodb.org Project's web site and documentation 14 * @link https://github.com/ADOdb/ADOdb Source code and issue tracker 15 * 16 * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause 17 * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, 18 * any later version. This means you can use it in proprietary products. 19 * See the LICENSE.md file distributed with this source code for details. 20 * @license BSD-3-Clause 21 * @license LGPL-2.1-or-later 22 * 23 * @copyright 2000-2013 John Lim 24 * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community 25 */ 26 27 // security - hide paths 28 if (!defined('ADODB_DIR')) die(); 29 30 include_once(ADODB_DIR.'/drivers/adodb-oci8.inc.php'); 31 32 class ADODB_oci8po extends ADODB_oci8 { 33 var $databaseType = 'oci8po'; 34 var $dataProvider = 'oci8'; 35 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 36 var $metaTablesSQL = "select lower(table_name),table_type from cat where table_type in ('TABLE','VIEW')"; 37 38 function Param($name,$type='C') 39 { 40 return '?'; 41 } 42 43 function Prepare($sql,$cursor=false) 44 { 45 $sqlarr = explode('?',$sql); 46 $sql = $sqlarr[0]; 47 for ($i = 1, $max = sizeof($sqlarr); $i < $max; $i++) { 48 $sql .= ':'.($i-1) . $sqlarr[$i]; 49 } 50 return ADODB_oci8::Prepare($sql,$cursor); 51 } 52 53 function Execute($sql,$inputarr=false) 54 { 55 return ADOConnection::Execute($sql,$inputarr); 56 } 57 58 /** 59 * The optimizations performed by ADODB_oci8::SelectLimit() are not 60 * compatible with the oci8po driver, so we rely on the slower method 61 * from the base class. 62 * We can't properly handle prepared statements either due to preprocessing 63 * of query parameters, so we treat them as regular SQL statements. 64 */ 65 function SelectLimit($sql, $nrows=-1, $offset=-1, $inputarr=false, $secs2cache=0) 66 { 67 if(is_array($sql)) { 68 // $sql = $sql[0]; 69 } 70 return ADOConnection::SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache); 71 } 72 73 // emulate handling of parameters ? ?, replacing with :bind0 :bind1 74 function _query($sql,$inputarr=false) 75 { 76 if (is_array($inputarr)) { 77 $i = 0; 78 if (is_array($sql)) { 79 foreach($inputarr as $v) { 80 $arr['bind'.$i++] = $v; 81 } 82 } else { 83 $sql = $this->extractBinds($sql,$inputarr); 84 } 85 } 86 return ADODB_oci8::_query($sql,$inputarr); 87 } 88 89 /** 90 * Replaces compatibility bind markers with oracle ones and returns a 91 * valid sql statement 92 * 93 * This replaces a regexp based section of code that has been subject 94 * to numerous tweaks, as more extreme test cases have appeared. This 95 * is now done this like this to help maintainability and avoid the 96 * need to rely on regexp experienced maintainers 97 * 98 * @param string $sql The sql statement 99 * @param string[] $inputarr The bind array 100 * 101 * @return string The modified statement 102 */ 103 private function extractBinds($sql,$inputarr) 104 { 105 $inString = false; 106 $escaped = 0; 107 $sqlLength = strlen($sql) - 1; 108 $newSql = ''; 109 $bindCount = 0; 110 111 /* 112 * inputarr is the passed in bind list, which is associative, but 113 * we only want the keys here 114 */ 115 $inputKeys = array_keys($inputarr); 116 117 118 for ($i=0;$i<=$sqlLength;$i++) 119 { 120 /* 121 * find the next character of the string 122 */ 123 $c = $sql[$i]; 124 125 if ($c == "'" && !$inString && $escaped==0) 126 /* 127 * Found the start of a string inside the statement 128 */ 129 $inString = true; 130 elseif ($c == "\\" && $escaped==0) 131 /* 132 * The next character will be escaped 133 */ 134 $escaped = 1; 135 elseif ($c == "'" && $inString && $escaped==0) 136 /* 137 * We found the end of the string 138 */ 139 $inString = false; 140 141 if ($escaped == 2) 142 $escaped = 0; 143 144 if ($escaped==0 && !$inString && $c == '?') 145 /* 146 * We found a bind symbol, replace it with the oracle equivalent 147 */ 148 $newSql .= ':' . $inputKeys[$bindCount++]; 149 else 150 /* 151 * Add the current character the pile 152 */ 153 $newSql .= $c; 154 155 if ($escaped == 1) 156 /* 157 * We have just found an escape character, make sure we ignore the 158 * next one that comes along, it might be a ' character 159 */ 160 $escaped = 2; 161 } 162 163 return $newSql; 164 165 } 166 } 167 168 /*-------------------------------------------------------------------------------------- 169 Class Name: Recordset 170 --------------------------------------------------------------------------------------*/ 171 172 class ADORecordset_oci8po extends ADORecordset_oci8 { 173 174 var $databaseType = 'oci8po'; 175 176 function Fields($colname) 177 { 178 if ($this->fetchMode & OCI_ASSOC) return $this->fields[$colname]; 179 180 if (!$this->bind) { 181 $this->bind = array(); 182 for ($i=0; $i < $this->_numOfFields; $i++) { 183 $o = $this->FetchField($i); 184 $this->bind[strtoupper($o->name)] = $i; 185 } 186 } 187 return $this->fields[$this->bind[strtoupper($colname)]]; 188 } 189 190 // lowercase field names... 191 function _FetchField($fieldOffset = -1) 192 { 193 $fld = new ADOFieldObject; 194 $fieldOffset += 1; 195 $fld->name = OCIcolumnname($this->_queryID, $fieldOffset); 196 if (ADODB_ASSOC_CASE == ADODB_ASSOC_CASE_LOWER) { 197 $fld->name = strtolower($fld->name); 198 } 199 $fld->type = OCIcolumntype($this->_queryID, $fieldOffset); 200 $fld->max_length = OCIcolumnsize($this->_queryID, $fieldOffset); 201 if ($fld->type == 'NUMBER') { 202 $sc = OCIColumnScale($this->_queryID, $fieldOffset); 203 if ($sc == 0) { 204 $fld->type = 'INT'; 205 } 206 } 207 return $fld; 208 } 209 210 // 10% speedup to move MoveNext to child class 211 function MoveNext() 212 { 213 $ret = @oci_fetch_array($this->_queryID,$this->fetchMode); 214 if($ret !== false) { 215 global $ADODB_ANSI_PADDING_OFF; 216 $this->fields = $ret; 217 $this->_currentRow++; 218 $this->_updatefields(); 219 220 if (!empty($ADODB_ANSI_PADDING_OFF)) { 221 foreach($this->fields as $k => $v) { 222 if (is_string($v)) $this->fields[$k] = rtrim($v); 223 } 224 } 225 return true; 226 } 227 if (!$this->EOF) { 228 $this->EOF = true; 229 $this->_currentRow++; 230 } 231 return false; 232 } 233 234 /* Optimize SelectLimit() by using OCIFetch() instead of OCIFetchInto() */ 235 function GetArrayLimit($nrows,$offset=-1) 236 { 237 if ($offset <= 0) { 238 $arr = $this->GetArray($nrows); 239 return $arr; 240 } 241 for ($i=1; $i < $offset; $i++) 242 if (!@OCIFetch($this->_queryID)) { 243 $arr = array(); 244 return $arr; 245 } 246 $ret = @oci_fetch_array($this->_queryID,$this->fetchMode); 247 if ($ret === false) { 248 $arr = array(); 249 return $arr; 250 } 251 $this->fields = $ret; 252 $this->_updatefields(); 253 $results = array(); 254 $cnt = 0; 255 while (!$this->EOF && $nrows != $cnt) { 256 $results[$cnt++] = $this->fields; 257 $this->MoveNext(); 258 } 259 260 return $results; 261 } 262 263 function _fetch() 264 { 265 global $ADODB_ANSI_PADDING_OFF; 266 267 $ret = @oci_fetch_array($this->_queryID,$this->fetchMode); 268 if ($ret) { 269 $this->fields = $ret; 270 $this->_updatefields(); 271 272 if (!empty($ADODB_ANSI_PADDING_OFF)) { 273 foreach($this->fields as $k => $v) { 274 if (is_string($v)) $this->fields[$k] = rtrim($v); 275 } 276 } 277 } 278 return $ret !== false; 279 } 280 281 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body