From: Petr Skoda Date: Wed, 18 Nov 2009 21:18:25 +0000 (+0000) Subject: MDL-20899 import latest adodb 5.10 X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=2d7f16e204a866d7a506544f5fd7bbf5bc1511cd;p=moodle.git MDL-20899 import latest adodb 5.10 --- diff --git a/lib/adodb/adodb-active-record.inc.php b/lib/adodb/adodb-active-record.inc.php index 796713b06e..55a89bbb7c 100644 --- a/lib/adodb/adodb-active-record.inc.php +++ b/lib/adodb/adodb-active-record.inc.php @@ -1,7 +1,7 @@ DB(); if (!$db) return false; + return $db->nameQuote.$n.$db->nameQuote; + } + //------------------------------------------------------------ Public functions below function Load($where=null,$bindarr=false) @@ -708,6 +718,7 @@ class ADODB_Active_Record { return $ok; } + // false on error function Insert() { @@ -723,7 +734,7 @@ class ADODB_Active_Record { $val = $this->$name; if(!is_array($val) || !is_null($val) || !array_key_exists($name, $table->keys)) { $valarr[] = $val; - $names[] = $name; + $names[] = $this->_QName($name,$db); $valstr[] = $db->Param($cnt); $cnt += 1; } @@ -883,7 +894,7 @@ class ADODB_Active_Record { continue; } $valarr[] = $val; - $pairs[] = $name.'='.$db->Param($cnt); + $pairs[] = $this->_QName($name,$db).'='.$db->Param($cnt); $cnt += 1; } @@ -922,9 +933,9 @@ global $_ADODB_ACTIVE_DBS; { $rows = false; if(isset($extra['offset'])) { - $rs = $db->SelectLimit($qry, $extra['limit'], $extra['offset']); + $rs = $db->SelectLimit($qry, $extra['limit'], $extra['offset'],$bindarr); } else { - $rs = $db->SelectLimit($qry, $extra['limit']); + $rs = $db->SelectLimit($qry, $extra['limit'],-1,$bindarr); } if ($rs) { while (!$rs->EOF) { diff --git a/lib/adodb/adodb-csvlib.inc.php b/lib/adodb/adodb-csvlib.inc.php index 9c5385a747..7b1c9e1197 100644 --- a/lib/adodb/adodb-csvlib.inc.php +++ b/lib/adodb/adodb-csvlib.inc.php @@ -8,7 +8,7 @@ $ADODB_INCLUDED_CSV = 1; /* - V5.08 6 Apr 2009 (c) 2000-2009 John Lim (jlim#natsoft.com). All rights reserved. + V5.10 10 Nov 2009 (c) 2000-2009 John Lim (jlim#natsoft.com). All rights reserved. Released under both BSD license and Lesser GPL library license. Whenever there is any discrepancy between the two licenses, the BSD license will take precedence. See License.txt. @@ -71,6 +71,7 @@ $ADODB_INCLUDED_CSV = 1; $savefetch = isset($rs->adodbFetchMode) ? $rs->adodbFetchMode : $rs->fetchMode; $class = $rs->connection->arrayClass; $rs2 = new $class(); + $rs2->timeCreated = $rs->timeCreated; # memcache fix $rs2->sql = $rs->sql; $rs2->oldProvider = $rs->dataProvider; $rs2->InitArrayFields($rows,$flds); diff --git a/lib/adodb/adodb-datadict.inc.php b/lib/adodb/adodb-datadict.inc.php index c9ef4e7b64..19500ca908 100644 --- a/lib/adodb/adodb-datadict.inc.php +++ b/lib/adodb/adodb-datadict.inc.php @@ -1,7 +1,7 @@ renameColumn,$tabname,$this->NameQuote($oldcolumn),$this->NameQuote($newcolumn),$column_def)); } diff --git a/lib/adodb/adodb-errorhandler.inc.php b/lib/adodb/adodb-errorhandler.inc.php index cc735f8ec9..3cf68a414c 100644 --- a/lib/adodb/adodb-errorhandler.inc.php +++ b/lib/adodb/adodb-errorhandler.inc.php @@ -1,6 +1,6 @@ DBTimeStamp($arrFields[$fname]); break; - case "F": //Floating point number // Moodle added case "N": $val = $arrFields[$fname]; if (!is_numeric($val)) $val = str_replace(',', '.', (float)$val); break; - case "L": //Integer field suitable for storing booleans (0 or 1) // Moodle added case "I": case "R": $val = $arrFields[$fname]; @@ -1055,13 +1053,13 @@ function _adodb_debug_execute(&$zthis, $sql, $inputarr) $ss = ''.htmlspecialchars($ss).''; } if ($zthis->debug === -1) - ADOConnection::outp( "
\n($dbt): ".htmlspecialchars($sqlTxt)."   $ss\n
\n",false); /// Moodle XHTML + ADOConnection::outp( "
\n($dbt): ".htmlspecialchars($sqlTxt)."   $ss\n
\n",false); else if ($zthis->debug !== -99) - ADOConnection::outp( "
\n($dbt): ".htmlspecialchars($sqlTxt)."   $ss\n
\n",false); /// Moodle XHTML + ADOConnection::outp( "
\n($dbt): ".htmlspecialchars($sqlTxt)."   $ss\n
\n",false); } else { $ss = "\n ".$ss; if ($zthis->debug !== -99) - ADOConnection::outp("-----
\n($dbt): ".$sqlTxt." $ss\n-----
\n",false); /// Moodle XHTML + ADOConnection::outp("-----
\n($dbt): ".$sqlTxt." $ss\n-----
\n",false); } $qID = $zthis->_query($sql,$inputarr); @@ -1076,7 +1074,7 @@ function _adodb_debug_execute(&$zthis, $sql, $inputarr) if($emsg = $zthis->ErrorMsg()) { if ($err = $zthis->ErrorNo()) { if ($zthis->debug === -99) - ADOConnection::outp( "
\n($dbt): ".htmlspecialchars($sqlTxt)."   $ss\n
\n",false); /// Moodle XHTML + ADOConnection::outp( "
\n($dbt): ".htmlspecialchars($sqlTxt)."   $ss\n
\n",false); ADOConnection::outp($err.': '.$emsg); } @@ -1084,8 +1082,8 @@ function _adodb_debug_execute(&$zthis, $sql, $inputarr) } else if (!$qID) { if ($zthis->debug === -99) - if ($inBrowser) ADOConnection::outp( "
\n($dbt): ".htmlspecialchars($sqlTxt)."   $ss\n
\n",false); /// Moodle XHTML - else ADOConnection::outp("-----
\n($dbt): ".$sqlTxt."$ss\n-----
\n",false); + if ($inBrowser) ADOConnection::outp( "
\n($dbt): ".htmlspecialchars($sqlTxt)."   $ss\n
\n",false); + else ADOConnection::outp("-----
\n($dbt): ".$sqlTxt."$ss\n-----
\n",false); ADOConnection::outp($zthis->ErrorNo() .': '. $zthis->ErrorMsg()); } @@ -1102,11 +1100,11 @@ function _adodb_backtrace($printOrArr=true,$levels=9999,$skippy=0,$ishtml=null) if ($ishtml === null) $html = (isset($_SERVER['HTTP_USER_AGENT'])); else $html = $ishtml; - $fmt = ($html) ? " %% line %4d, file: %s" : "%% line %4d, file: %s"; /// Moodle XHTML + $fmt = ($html) ? " %% line %4d, file: %s" : "%% line %4d, file: %s"; $MAXSTRLEN = 128; - $s = ($html) ? '
' : ''; /// Moodle XHTML
+	$s = ($html) ? '
' : '';
 	
 	if (is_array($printOrArr)) $traceArr = $printOrArr;
 	else $traceArr = debug_backtrace();
@@ -1192,4 +1190,4 @@ function _adodb_find_from($sql)
 }
 */
 
-?>
+?>
\ No newline at end of file
diff --git a/lib/adodb/adodb-memcache.lib.inc.php b/lib/adodb/adodb-memcache.lib.inc.php
index f50dbdb942..dad4c38f9c 100644
--- a/lib/adodb/adodb-memcache.lib.inc.php
+++ b/lib/adodb/adodb-memcache.lib.inc.php
@@ -65,7 +65,7 @@ $db->CacheExecute($sql);
 
 			$memcache = new MemCache;
 			
-			if (!is_array($this->hosts)) $this->hosts = array($hosts);
+			if (!is_array($this->hosts)) $this->hosts = array($this->hosts);
 		
 			$failcnt = 0;
 			foreach($this->hosts as $host) {
diff --git a/lib/adodb/adodb-pager.inc.php b/lib/adodb/adodb-pager.inc.php
index f542c3ccb6..d6980c107d 100644
--- a/lib/adodb/adodb-pager.inc.php
+++ b/lib/adodb/adodb-pager.inc.php
@@ -1,7 +1,7 @@
 RecordCount() is used. 
@@ -377,6 +377,7 @@
 
 	var $sysDate = false; /// name of function that returns the current date
 	var $sysTimeStamp = false; /// name of function that returns the current timestamp
+	var $sysUTimeStamp = false; // name of function that returns the current timestamp accurate to the microsecond or nearest fraction
 	var $arrayClass = 'ADORecordSet_array'; /// name of class used to generate array recordsets, which are pre-downloaded recordsets
 	
 	var $noNullStrings = false; /// oracle specific stuff - if true ensures that '' is converted to ' '
@@ -515,9 +516,6 @@
 		
 		$this->_isPersistentConnection = false;	
 			
-		global $ADODB_CACHE;
-		if (empty($ADODB_CACHE)) $this->_CreateCache();
-		
 		if ($forceNew) {
 			if ($rez=$this->_nconnect($this->host, $this->user, $this->password, $this->database)) return true;
 		} else {
@@ -584,9 +582,6 @@
 			
 		$this->_isPersistentConnection = true;	
 		
-		global $ADODB_CACHE;
-		if (empty($ADODB_CACHE)) $this->_CreateCache();
-		
 		if ($rez = $this->_pconnect($this->host, $this->user, $this->password, $this->database)) return true;
 		if (isset($rez)) {
 			$err = $this->ErrorMsg();
@@ -721,7 +716,7 @@
 	*  @param $table	name of table to lock
 	*  @param $where	where clause to use, eg: "WHERE row=12". If left empty, will escalate to table lock
 	*/
-	function RowLock($table,$where)
+	function RowLock($table,$where,$col='1 as ignore')
 	{
 		return false;
 	}
@@ -1710,6 +1705,8 @@
 	{
 	global $ADODB_CACHE_DIR, $ADODB_CACHE;
 		
+		if (empty($ADODB_CACHE)) return false;
+		
 		if (!$sql) {
 			 $ADODB_CACHE->flushall($this->debug);
 	         return;
@@ -1766,6 +1763,8 @@
 	{
 	global $ADODB_CACHE;
 	
+		if (empty($ADODB_CACHE)) $this->_CreateCache();
+		
 		if (!is_numeric($secs2cache)) {
 			$inputarr = $sql;
 			$sql = $secs2cache;
@@ -1878,6 +1877,7 @@
 		$rs = $this->SelectLimit($sql,1);
 		if (!$rs) return $false; // table does not exist
 		$rs->tableName = $table;
+		$rs->sql = $sql;
 		
 		switch((string) $mode) {
 		case 'UPDATE':
@@ -2439,6 +2439,9 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
 		if (empty($d) && $d !== 0) return 'null';
 		if ($isfld) return $d;
 		
+		if (is_object($d)) return $d->format($this->fmtDate);
+		
+		
 		if (is_string($d) && !is_numeric($d)) {
 			if ($d === 'null' || strncmp($d,"'",1) === 0) return $d;
 			if ($this->isoDates) return "'$d'";
@@ -2476,6 +2479,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
 	{
 		if (empty($ts) && $ts !== 0) return 'null';
 		if ($isfld) return $ts;
+		if (is_object($ts)) return $ts->format($this->fmtTimeStamp);
 		
 		# strlen(14) allows YYYYMMDDHHMMSS format
 		if (!is_string($ts) || (is_numeric($ts) && strlen($ts)<14)) 
@@ -2604,9 +2608,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
 		// undo magic quotes for "
 		$s = str_replace('\\"','"',$s);
 		
-		// moodle change start - see readme_moodle.txt
 		if ($this->replaceQuote == "\\'" || ini_get('magic_quotes_sybase'))  // ' already quoted, no need to change anything
-		// moodle change end - see readme_moodle.txt
 			return $s;
 		else {// change \' to '' for sybase/mssql
 			$s = str_replace('\\\\','\\',$s);
@@ -2640,9 +2642,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
 		// undo magic quotes for "
 		$s = str_replace('\\"','"',$s);
 		
-		// moodle change start - see readme_moodle.txt
 		if ($this->replaceQuote == "\\'" || ini_get('magic_quotes_sybase'))  // ' already quoted, no need to change anything
-		// moodle change end - see readme_moodle.txt
 			return "'$s'";
 		else {// change \' to '' for sybase/mssql
 			$s = str_replace('\\\\','\\',$s);
@@ -4258,6 +4258,18 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
 					case 'socket': $obj->socket = $v; break;
 					#oci8
 					case 'nls_date_format': $obj->NLS_DATE_FORMAT = $v; break;
+					case 'cachesecs': $obj->cacheSecs = $v; break;
+					case 'memcache': 
+						$varr = explode(':',$v);
+						$vlen = sizeof($varr);
+						if ($vlen == 0) break;	
+						$obj->memCache = true;
+						$obj->memCacheHost = explode(',',$varr[0]);
+						if ($vlen == 1) break;	
+						$obj->memCachePort = $varr[1];
+						if ($vlen == 2) break;	
+						$obj->memCacheCompress = $varr[2] ?  true : false;
+						break;
 					}
 				}
 				if (empty($persist))
diff --git a/lib/adodb/datadict/datadict-access.inc.php b/lib/adodb/datadict/datadict-access.inc.php
index e4d1c23a89..8cd25d568f 100644
--- a/lib/adodb/datadict/datadict-access.inc.php
+++ b/lib/adodb/datadict/datadict-access.inc.php
@@ -1,7 +1,7 @@
 fields[] = false;
 				break;
+			case 20:
+			case 21: // bigint (64 bit)
+    			$this->fields[] = (float) $f->value; // if 64 bit PHP, could use (int)
+    			break;
 			case 6: // currency is not supported properly;
 				ADOConnection::outp( ''.$f->Name.': currency type not supported by PHP');
 				$this->fields[] = (float) $f->value;
diff --git a/lib/adodb/drivers/adodb-ado_access.inc.php b/lib/adodb/drivers/adodb-ado_access.inc.php
index 7640af30c3..3a827a5d95 100644
--- a/lib/adodb/drivers/adodb-ado_access.inc.php
+++ b/lib/adodb/drivers/adodb-ado_access.inc.php
@@ -1,6 +1,6 @@
 ADODB_ado();
 	}
 	
-	function BeginTrans() { return false;}
+	/*function BeginTrans() { return false;}
 	
 	function CommitTrans() { return false;}
 	
-	function RollbackTrans() { return false;}
+	function RollbackTrans() { return false;}*/
 
 }
 
diff --git a/lib/adodb/drivers/adodb-ado_mssql.inc.php b/lib/adodb/drivers/adodb-ado_mssql.inc.php
index e9bb7c270a..08319846b0 100644
--- a/lib/adodb/drivers/adodb-ado_mssql.inc.php
+++ b/lib/adodb/drivers/adodb-ado_mssql.inc.php
@@ -1,6 +1,6 @@
 _haserrorfunctions = ADODB_PHPVER >= 0x4050;
+    $this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200;
+  }
+
+  // returns true or false
+  function _connect($argDSN, $argUsername, $argPassword, $argDatabasename)
+  {
+          global $php_errormsg;
+
+    if (!function_exists('ads_connect')) return null;
+
+    if ($this->debug && $argDatabasename && $this->databaseType != 'vfp') {
+      ADOConnection::outp("For Advantage Connect(), $argDatabasename is not used. Place dsn in 1st parameter.");
+    }
+    if (isset($php_errormsg)) $php_errormsg = '';
+    if ($this->curmode === false) $this->_connectionID = ads_connect($argDSN,$argUsername,$argPassword);
+    else $this->_connectionID = ads_connect($argDSN,$argUsername,$argPassword,$this->curmode);
+    $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
+    if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
+
+    return $this->_connectionID != false;
+  }
+
+  // returns true or false
+  function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
+  {
+  global $php_errormsg;
+
+    if (!function_exists('ads_connect')) return null;
+
+    if (isset($php_errormsg)) $php_errormsg = '';
+    $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
+    if ($this->debug && $argDatabasename) {
+            ADOConnection::outp("For PConnect(), $argDatabasename is not used. Place dsn in 1st parameter.");
+    }
+  //  print "dsn=$argDSN u=$argUsername p=$argPassword
"; flush(); + if ($this->curmode === false) $this->_connectionID = ads_connect($argDSN,$argUsername,$argPassword); + else $this->_connectionID = ads_pconnect($argDSN,$argUsername,$argPassword,$this->curmode); + + $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; + if ($this->_connectionID && $this->autoRollback) @ads_rollback($this->_connectionID); + if (isset($this->connectStmt)) $this->Execute($this->connectStmt); + + return $this->_connectionID != false; + } + + // returns the Server version and Description + function ServerInfo() + { + + if (!empty($this->host) && ADODB_PHPVER >= 0x4300) { + $stmt = $this->Prepare('EXECUTE PROCEDURE sp_mgGetInstallInfo()'); + $res = $this->Execute($stmt); + if(!$res) + print $this->ErrorMsg(); + else{ + $ret["version"]= $res->fields[3]; + $ret["description"]="Advantage Database Server"; + return $ret; + } + } + else { + return ADOConnection::ServerInfo(); + } + } + + + // returns true or false + function CreateSequence( $seqname,$start=1) + { + $res = $this->Execute("CREATE TABLE $seqname ( ID autoinc( 1 ) ) IN DATABASE"); + if(!$res){ + print $this->ErrorMsg(); + return false; + } + else + return true; + + } + + // returns true or false + function DropSequence($seqname) + { + $res = $this->Execute("DROP TABLE $seqname"); + if(!$res){ + print $this->ErrorMsg(); + return false; + } + else + return true; + } + + + // returns the generated ID or false + // checks if the table already exists, else creates the table and inserts a record into the table + // and gets the ID number of the last inserted record. + function GenID($seqname,$start=1) + { + $go = $this->Execute("select * from $seqname"); + if (!$go){ + $res = $this->Execute("CREATE TABLE $seqname ( ID autoinc( 1 ) ) IN DATABASE"); + if(!res){ + print $this->ErrorMsg(); + return false; + } + } + $res = $this->Execute("INSERT INTO $seqname VALUES( DEFAULT )"); + if(!$res){ + print $this->ErrorMsg(); + return false; + } + else{ + $gen = $this->Execute("SELECT LastAutoInc( STATEMENT ) FROM system.iota"); + $ret = $gen->fields[0]; + return $ret; + } + + } + + + + + function ErrorMsg() + { + if ($this->_haserrorfunctions) { + if ($this->_errorMsg !== false) return $this->_errorMsg; + if (empty($this->_connectionID)) return @ads_errormsg(); + return @ads_errormsg($this->_connectionID); + } else return ADOConnection::ErrorMsg(); + } + + + function ErrorNo() + { + + if ($this->_haserrorfunctions) { + if ($this->_errorCode !== false) { + // bug in 4.0.6, error number can be corrupted string (should be 6 digits) + return (strlen($this->_errorCode)<=2) ? 0 : $this->_errorCode; + } + + if (empty($this->_connectionID)) $e = @ads_error(); + else $e = @ads_error($this->_connectionID); + + // bug in 4.0.6, error number can be corrupted string (should be 6 digits) + // so we check and patch + if (strlen($e)<=2) return 0; + return $e; + } else return ADOConnection::ErrorNo(); + } + + + + function BeginTrans() + { + if (!$this->hasTransactions) return false; + if ($this->transOff) return true; + $this->transCnt += 1; + $this->_autocommit = false; + return ads_autocommit($this->_connectionID,false); + } + + function CommitTrans($ok=true) + { + if ($this->transOff) return true; + if (!$ok) return $this->RollbackTrans(); + if ($this->transCnt) $this->transCnt -= 1; + $this->_autocommit = true; + $ret = ads_commit($this->_connectionID); + ads_autocommit($this->_connectionID,true); + return $ret; + } + + function RollbackTrans() + { + if ($this->transOff) return true; + if ($this->transCnt) $this->transCnt -= 1; + $this->_autocommit = true; + $ret = ads_rollback($this->_connectionID); + ads_autocommit($this->_connectionID,true); + return $ret; + } + + + // Returns tables,Views or both on succesfull execution. Returns + // tables by default on succesfull execustion. + function &MetaTables($ttype) + { + $recordSet1 = $this->Execute("select * from system.tables"); + if(!$recordSet1){ + print $this->ErrorMsg(); + return false; + } + $recordSet2 = $this->Execute("select * from system.views"); + if(!$recordSet2){ + print $this->ErrorMsg(); + return false; + } + $i=0; + while (!$recordSet1->EOF){ + $arr["$i"] = $recordSet1->fields[0]; + $recordSet1->MoveNext(); + $i=$i+1; + } + if($ttype=='FALSE'){ + while (!$recordSet2->EOF){ + $arr["$i"] = $recordSet2->fields[0]; + $recordSet2->MoveNext(); + $i=$i+1; + } + return $arr; + } + elseif($ttype=='VIEWS'){ + while (!$recordSet2->EOF){ + $arrV["$i"] = $recordSet2->fields[0]; + $recordSet2->MoveNext(); + $i=$i+1; + } + return $arrV; + } + else{ + return $arr; + } + + } + + function &MetaPrimaryKeys($table) + { + $recordSet = $this->Execute("select table_primary_key from system.tables where name='$table'"); + if(!$recordSet){ + print $this->ErrorMsg(); + return false; + } + $i=0; + while (!$recordSet->EOF){ + $arr["$i"] = $recordSet->fields[0]; + $recordSet->MoveNext(); + $i=$i+1; + } + return $arr; + } + +/* +See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/odbcdatetime_data_type_changes.asp +/ SQL data type codes / +#define SQL_UNKNOWN_TYPE 0 +#define SQL_CHAR 1 +#define SQL_NUMERIC 2 +#define SQL_DECIMAL 3 +#define SQL_INTEGER 4 +#define SQL_SMALLINT 5 +#define SQL_FLOAT 6 +#define SQL_REAL 7 +#define SQL_DOUBLE 8 +#if (ODBCVER >= 0x0300) +#define SQL_DATETIME 9 +#endif +#define SQL_VARCHAR 12 + + +/ One-parameter shortcuts for date/time data types / +#if (ODBCVER >= 0x0300) +#define SQL_TYPE_DATE 91 +#define SQL_TYPE_TIME 92 +#define SQL_TYPE_TIMESTAMP 93 + +#define SQL_UNICODE (-95) +#define SQL_UNICODE_VARCHAR (-96) +#define SQL_UNICODE_LONGVARCHAR (-97) +*/ + function ODBCTypes($t) + { + switch ((integer)$t) { + case 1: + case 12: + case 0: + case -95: + case -96: + return 'C'; + case -97: + case -1: //text + return 'X'; + case -4: //image + return 'B'; + + case 9: + case 91: + return 'D'; + + case 10: + case 11: + case 92: + case 93: + return 'T'; + + case 4: + case 5: + case -6: + return 'I'; + + case -11: // uniqidentifier + return 'R'; + case -7: //bit + return 'L'; + + default: + return 'N'; + } + } + + function &MetaColumns($table) + { + global $ADODB_FETCH_MODE; + + $false = false; + if ($this->uCaseTables) $table = strtoupper($table); + $schema = ''; + $this->_findschema($table,$schema); + + $savem = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + + /*if (false) { // after testing, confirmed that the following does not work becoz of a bug + $qid2 = ads_tables($this->_connectionID); + $rs = new ADORecordSet_ads($qid2); + $ADODB_FETCH_MODE = $savem; + if (!$rs) return false; + $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change; + $rs->_fetch(); + + while (!$rs->EOF) { + if ($table == strtoupper($rs->fields[2])) { + $q = $rs->fields[0]; + $o = $rs->fields[1]; + break; + } + $rs->MoveNext(); + } + $rs->Close(); + + $qid = ads_columns($this->_connectionID,$q,$o,strtoupper($table),'%'); + } */ + + switch ($this->databaseType) { + case 'access': + case 'vfp': + $qid = ads_columns($this->_connectionID);#,'%','',strtoupper($table),'%'); + break; + + + case 'db2': + $colname = "%"; + $qid = ads_columns($this->_connectionID, "", $schema, $table, $colname); + break; + + default: + $qid = @ads_columns($this->_connectionID,'%','%',strtoupper($table),'%'); + if (empty($qid)) $qid = ads_columns($this->_connectionID); + break; + } + if (empty($qid)) return $false; + + $rs = new ADORecordSet_ads($qid); + $ADODB_FETCH_MODE = $savem; + + if (!$rs) return $false; + $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change; + $rs->_fetch(); + + $retarr = array(); + + /* + $rs->fields indices + 0 TABLE_QUALIFIER + 1 TABLE_SCHEM + 2 TABLE_NAME + 3 COLUMN_NAME + 4 DATA_TYPE + 5 TYPE_NAME + 6 PRECISION + 7 LENGTH + 8 SCALE + 9 RADIX + 10 NULLABLE + 11 REMARKS + */ + while (!$rs->EOF) { + // adodb_pr($rs->fields); + if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) { + $fld = new ADOFieldObject(); + $fld->name = $rs->fields[3]; + $fld->type = $this->ODBCTypes($rs->fields[4]); + + // ref: http://msdn.microsoft.com/library/default.asp?url=/archive/en-us/dnaraccgen/html/msdn_odk.asp + // access uses precision to store length for char/varchar + if ($fld->type == 'C' or $fld->type == 'X') { + if ($this->databaseType == 'access') + $fld->max_length = $rs->fields[6]; + else if ($rs->fields[4] <= -95) // UNICODE + $fld->max_length = $rs->fields[7]/2; + else + $fld->max_length = $rs->fields[7]; + } else + $fld->max_length = $rs->fields[7]; + $fld->not_null = !empty($rs->fields[10]); + $fld->scale = $rs->fields[8]; + $retarr[strtoupper($fld->name)] = $fld; + } else if (sizeof($retarr)>0) + break; + $rs->MoveNext(); + } + $rs->Close(); //-- crashes 4.03pl1 -- why? + + if (empty($retarr)) $retarr = false; + return $retarr; + } + + // Returns an array of columns names for a given table + function &MetaColumnNames($table) + { + $recordSet = $this->Execute("select name from system.columns where parent='$table'"); + if(!$recordSet){ + print $this->ErrorMsg(); + return false; + } + else{ + $i=0; + while (!$recordSet->EOF){ + $arr["FIELD$i"] = $recordSet->fields[0]; + $recordSet->MoveNext(); + $i=$i+1; + } + return $arr; + } + } + + + function Prepare($sql) + { + if (! $this->_bindInputArray) return $sql; // no binding + $stmt = ads_prepare($this->_connectionID,$sql); + if (!$stmt) { + // we don't know whether odbc driver is parsing prepared stmts, so just return sql + return $sql; + } + return array($sql,$stmt,false); + } + + /* returns queryID or false */ + function _query($sql,$inputarr=false) + { + GLOBAL $php_errormsg; + if (isset($php_errormsg)) $php_errormsg = ''; + $this->_error = ''; + + if ($inputarr) { + if (is_array($sql)) { + $stmtid = $sql[1]; + } else { + $stmtid = ads_prepare($this->_connectionID,$sql); + + if ($stmtid == false) { + $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; + return false; + } + } + + if (! ads_execute($stmtid,$inputarr)) { + //@ads_free_result($stmtid); + if ($this->_haserrorfunctions) { + $this->_errorMsg = ads_errormsg(); + $this->_errorCode = ads_error(); + } + return false; + } + + } else if (is_array($sql)) { + $stmtid = $sql[1]; + if (!ads_execute($stmtid)) { + //@ads_free_result($stmtid); + if ($this->_haserrorfunctions) { + $this->_errorMsg = ads_errormsg(); + $this->_errorCode = ads_error(); + } + return false; + } + } else + { + + $stmtid = ads_exec($this->_connectionID,$sql); + + } + + $this->_lastAffectedRows = 0; + + if ($stmtid) + { + + if (@ads_num_fields($stmtid) == 0) { + $this->_lastAffectedRows = ads_num_rows($stmtid); + $stmtid = true; + + } else { + + $this->_lastAffectedRows = 0; + ads_binmode($stmtid,$this->binmode); + ads_longreadlen($stmtid,$this->maxblobsize); + + } + + if ($this->_haserrorfunctions) + { + + $this->_errorMsg = ''; + $this->_errorCode = 0; + } + else + $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; + } + else + { + if ($this->_haserrorfunctions) { + $this->_errorMsg = ads_errormsg(); + $this->_errorCode = ads_error(); + } else + $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; + } + + return $stmtid; + + } + + /* + Insert a null into the blob field of the table first. + Then use UpdateBlob to store the blob. + + Usage: + + $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)'); + $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1'); + */ + function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB') + { + $sql = "UPDATE $table SET $column=? WHERE $where"; + $stmtid = ads_prepare($this->_connectionID,$sql); + if ($stmtid == false){ + $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; + return false; + } + if (! ads_execute($stmtid,array($val),array(SQL_BINARY) )){ + if ($this->_haserrorfunctions){ + $this->_errorMsg = ads_errormsg(); + $this->_errorCode = ads_error(); + } + return false; + } + return TRUE; + } + + // returns true or false + function _close() + { + $ret = @ads_close($this->_connectionID); + $this->_connectionID = false; + return $ret; + } + + function _affectedrows() + { + return $this->_lastAffectedRows; + } + +} + +/*-------------------------------------------------------------------------------------- + Class Name: Recordset +--------------------------------------------------------------------------------------*/ + +class ADORecordSet_ads extends ADORecordSet { + + var $bind = false; + var $databaseType = "ads"; + var $dataProvider = "ads"; + var $useFetchArray; + var $_has_stupid_odbc_fetch_api_change; + + function ADORecordSet_ads($id,$mode=false) + { + if ($mode === false) { + global $ADODB_FETCH_MODE; + $mode = $ADODB_FETCH_MODE; + } + $this->fetchMode = $mode; + + $this->_queryID = $id; + + // the following is required for mysql odbc driver in 4.3.1 -- why? + $this->EOF = false; + $this->_currentRow = -1; + //$this->ADORecordSet($id); + } + + + // returns the field object + function &FetchField($fieldOffset = -1) + { + + $off=$fieldOffset+1; // offsets begin at 1 + + $o= new ADOFieldObject(); + $o->name = @ads_field_name($this->_queryID,$off); + $o->type = @ads_field_type($this->_queryID,$off); + $o->max_length = @ads_field_len($this->_queryID,$off); + if (ADODB_ASSOC_CASE == 0) $o->name = strtolower($o->name); + else if (ADODB_ASSOC_CASE == 1) $o->name = strtoupper($o->name); + return $o; + } + + /* Use associative array to get fields array */ + function Fields($colname) + { + if ($this->fetchMode & ADODB_FETCH_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)]]; + } + + + function _initrs() + { + global $ADODB_COUNTRECS; + $this->_numOfRows = ($ADODB_COUNTRECS) ? @ads_num_rows($this->_queryID) : -1; + $this->_numOfFields = @ads_num_fields($this->_queryID); + // some silly drivers such as db2 as/400 and intersystems cache return _numOfRows = 0 + if ($this->_numOfRows == 0) $this->_numOfRows = -1; + //$this->useFetchArray = $this->connection->useFetchArray; + $this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200; + } + + function _seek($row) + { + return false; + } + + // speed up SelectLimit() by switching to ADODB_FETCH_NUM as ADODB_FETCH_ASSOC is emulated + function &GetArrayLimit($nrows,$offset=-1) + { + if ($offset <= 0) { + $rs =& $this->GetArray($nrows); + return $rs; + } + $savem = $this->fetchMode; + $this->fetchMode = ADODB_FETCH_NUM; + $this->Move($offset); + $this->fetchMode = $savem; + + if ($this->fetchMode & ADODB_FETCH_ASSOC) { + $this->fields =& $this->GetRowAssoc(ADODB_ASSOC_CASE); + } + + $results = array(); + $cnt = 0; + while (!$this->EOF && $nrows != $cnt) { + $results[$cnt++] = $this->fields; + $this->MoveNext(); + } + + return $results; + } + + + function MoveNext() + { + if ($this->_numOfRows != 0 && !$this->EOF) { + $this->_currentRow++; + + if ($this->_has_stupid_odbc_fetch_api_change) + $rez = @ads_fetch_into($this->_queryID,$this->fields); + else { + $row = 0; + $rez = @ads_fetch_into($this->_queryID,$row,$this->fields); + } + if ($rez) { + if ($this->fetchMode & ADODB_FETCH_ASSOC) { + $this->fields =& $this->GetRowAssoc(ADODB_ASSOC_CASE); + } + return true; + } + } + $this->fields = false; + $this->EOF = true; + return false; + } + + function _fetch() + { + + if ($this->_has_stupid_odbc_fetch_api_change) + $rez = @ads_fetch_into($this->_queryID,$this->fields); + else { + $row = 0; + $rez = @ads_fetch_into($this->_queryID,$row,$this->fields); + } + if ($rez) { + if ($this->fetchMode & ADODB_FETCH_ASSOC) { + $this->fields =& $this->GetRowAssoc(ADODB_ASSOC_CASE); + } + return true; + } + $this->fields = false; + return false; + } + + function _close() + { + return @ads_free_result($this->_queryID); + } + +} +?> \ No newline at end of file diff --git a/lib/adodb/drivers/adodb-borland_ibase.inc.php b/lib/adodb/drivers/adodb-borland_ibase.inc.php index ce55f28711..301fd19755 100644 --- a/lib/adodb/drivers/adodb-borland_ibase.inc.php +++ b/lib/adodb/drivers/adodb-borland_ibase.inc.php @@ -1,6 +1,6 @@ binmode); - if ($argDatabasename) { - $this->_connectionID = db2_connect($argDatabasename,$argUsername,$argPassword); + if ($argDatabasename && empty($argDSN)) { + + if (stripos($argDatabasename,'UID=') && stripos($argDatabasename,'PWD=')) $this->_connectionID = db2_connect($argDatabasename,null,null); + else $this->_connectionID = db2_connect($argDatabasename,$argUsername,$argPassword); } else { - $this->_connectionID = db2_connect($argDSN,$argUsername,$argPassword); + if ($argDatabasename) $schema = $argDatabasename; + if (stripos($argDSN,'UID=') && stripos($argDSN,'PWD=')) $this->_connectionID = db2_connect($argDSN,null,null); + else $this->_connectionID = db2_connect($argDSN,$argUsername,$argPassword); } if (isset($php_errormsg)) $php_errormsg = ''; @@ -86,9 +94,9 @@ class ADODB_db2 extends ADOConnection { // an array of valid options. So far, we don't use them. $this->_errorMsg = @db2_conn_errormsg(); - if (isset($this->connectStmt)) $this->Execute($this->connectStmt); + if ($this->_connectionID && isset($schema)) $this->Execute("SET SCHEMA=$schema"); return $this->_connectionID != false; } @@ -106,10 +114,14 @@ class ADODB_db2 extends ADOConnection { if (isset($php_errormsg)) $php_errormsg = ''; $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : ''; - if ($argDatabasename) { - $this->_connectionID = db2_pconnect($argDatabasename,$argUsername,$argPassword); + if ($argDatabasename && empty($argDSN)) { + + if (stripos($argDatabasename,'UID=') && stripos($argDatabasename,'PWD=')) $this->_connectionID = db2_pconnect($argDatabasename,null,null); + else $this->_connectionID = db2_pconnect($argDatabasename,$argUsername,$argPassword); } else { - $this->_connectionID = db2_pconnect($argDSN,$argUsername,$argPassword); + if ($argDatabasename) $schema = $argDatabasename; + if (stripos($argDSN,'UID=') && stripos($argDSN,'PWD=')) $this->_connectionID = db2_pconnect($argDSN,null,null); + else $this->_connectionID = db2_pconnect($argDSN,$argUsername,$argPassword); } if (isset($php_errormsg)) $php_errormsg = ''; @@ -117,6 +129,7 @@ class ADODB_db2 extends ADOConnection { if ($this->_connectionID && $this->autoRollback) @db2_rollback($this->_connectionID); if (isset($this->connectStmt)) $this->Execute($this->connectStmt); + if ($this->_connectionID && isset($schema)) $this->Execute("SET SCHEMA=$schema"); return $this->_connectionID != false; } @@ -223,7 +236,6 @@ class ADODB_db2 extends ADOConnection { return ADOConnection::ServerInfo(); } } - function CreateSequence($seqname='adodbseq',$start=1) { @@ -239,6 +251,25 @@ class ADODB_db2 extends ADOConnection { return $this->Execute(sprintf($this->_dropSeqSQL,$seqname)); } + function SelectLimit($sql,$nrows=-1,$offset=-1,$inputArr=false) + { + $nrows = (integer) $nrows; + if ($offset <= 0) { + // could also use " OPTIMIZE FOR $nrows ROWS " + if ($nrows >= 0) $sql .= " FETCH FIRST $nrows ROWS ONLY "; + $rs = $this->Execute($sql,$inputArr); + } else { + if ($offset > 0 && $nrows < 0); + else { + $nrows += $offset; + $sql .= " FETCH FIRST $nrows ROWS ONLY "; + } + $rs = ADOConnection::SelectLimit($sql,-1,$offset,$inputArr); + } + + return $rs; + } + /* This algorithm is not very efficient, but works even if table locking is not available. @@ -407,7 +438,6 @@ class ADODB_db2 extends ADOConnection { } $arr = $rs->GetArray(); - $rs->Close(); $arr2 = array(); @@ -417,12 +447,13 @@ class ADODB_db2 extends ADOConnection { for ($i=0; $i < sizeof($arr); $i++) { if (!$arr[$i][2]) continue; $type = $arr[$i][3]; + $owner = $arr[$i][1]; $schemaval = ($schema) ? $arr[$i][1].'.' : ''; if ($ttype) { if ($isview) { if (strncmp($type,'V',1) === 0) $arr2[] = $schemaval.$arr[$i][2]; - } else if (strncmp($type,'SYS',3) !== 0) $arr2[] = $schemaval.$arr[$i][2]; - } else if (strncmp($type,'SYS',3) !== 0) $arr2[] = $schemaval.$arr[$i][2]; + } else if (strncmp($owner,'SYS',3) !== 0) $arr2[] = $schemaval.$arr[$i][2]; + } else if (strncmp($owner,'SYS',3) !== 0) $arr2[] = $schemaval.$arr[$i][2]; } return $arr2; } @@ -495,7 +526,7 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/db2/htm/db2 } } - function MetaColumns($table) + function MetaColumns($table, $normalize=true) { global $ADODB_FETCH_MODE; @@ -591,6 +622,7 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/db2/htm/db2 return $retarr; } + function Prepare($sql) { if (! $this->_bindInputArray) return $sql; // no binding diff --git a/lib/adodb/drivers/adodb-db2oci.inc.php b/lib/adodb/drivers/adodb-db2oci.inc.php new file mode 100644 index 0000000000..32f2132242 --- /dev/null +++ b/lib/adodb/drivers/adodb-db2oci.inc.php @@ -0,0 +1,230 @@ + $_COLONSZ) return $p; + $_COLONARR[] = $v; + return '?'; +} + +// smart remapping of :0, :1 bind vars to ? ? +function _colonscope($sql,$arr) +{ +global $_COLONARR,$_COLONSZ; + + $_COLONARR = array(); + $_COLONSZ = sizeof($arr); + + $sql2 = preg_replace("/(:[0-9]+)/e","_colontrack('\\1')",$sql); + + if (empty($_COLONARR)) return array($sql,$arr); + + foreach($_COLONARR as $k => $v) { + $arr2[] = $arr[$v]; + } + + return array($sql2,$arr2); +} +*/ + +/* + Smart remapping of :0, :1 bind vars to ? ? + + Handles colons in comments -- and / * * / and in quoted strings. +*/ + +function _colonparser($sql,$arr) +{ + $lensql = strlen($sql); + $arrsize = sizeof($arr); + $state = 'NORM'; + $at = 1; + $ch = $sql[0]; + $ch2 = @$sql[1]; + $sql2 = ''; + $arr2 = array(); + $nprev = 0; + + + while (strlen($ch)) { + + switch($ch) { + case '/': + if ($state == 'NORM' && $ch2 == '*') { + $state = 'COMMENT'; + + $at += 1; + $ch = $ch2; + $ch2 = $at < $lensql ? $sql[$at] : ''; + } + break; + + case '*': + if ($state == 'COMMENT' && $ch2 == '/') { + $state = 'NORM'; + + $at += 1; + $ch = $ch2; + $ch2 = $at < $lensql ? $sql[$at] : ''; + } + break; + + case "\n": + case "\r": + if ($state == 'COMMENT2') $state = 'NORM'; + break; + + case "'": + do { + $at += 1; + $ch = $ch2; + $ch2 = $at < $lensql ? $sql[$at] : ''; + } while ($ch !== "'"); + break; + + case ':': + if ($state == 'COMMENT' || $state == 'COMMENT2') break; + + //echo "$at=$ch $ch2, "; + if ('0' <= $ch2 && $ch2 <= '9') { + $n = ''; + $nat = $at; + do { + $at += 1; + $ch = $ch2; + $n .= $ch; + $ch2 = $at < $lensql ? $sql[$at] : ''; + } while ('0' <= $ch && $ch <= '9'); + #echo "$n $arrsize ] "; + $n = (integer) $n; + if ($n < $arrsize) { + $sql2 .= substr($sql,$nprev,$nat-$nprev-1).'?'; + $nprev = $at-1; + $arr2[] = $arr[$n]; + } + } + break; + + case '-': + if ($state == 'NORM') { + if ($ch2 == '-') $state = 'COMMENT2'; + $at += 1; + $ch = $ch2; + $ch2 = $at < $lensql ? $sql[$at] : ''; + } + break; + } + + $at += 1; + $ch = $ch2; + $ch2 = $at < $lensql ? $sql[$at] : ''; + } + + if ($nprev == 0) { + $sql2 = $sql; + } else { + $sql2 .= substr($sql,$nprev); + } + + return array($sql2,$arr2); +} + +class ADODB_db2oci extends ADODB_db2 { + var $databaseType = "db2oci"; + var $sysTimeStamp = 'sysdate'; + var $sysDate = 'trunc(sysdate)'; + var $_bindInputArray = true; + + function ADODB_db2oci() + { + parent::ADODB_db2(); + } + + function Param($name,$type=false) + { + return ':'.$name; + } + + + function MetaTables($ttype=false,$schema=false) + { + global $ADODB_FETCH_MODE; + + $savem = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + $qid = db2_tables($this->_connectionID); + + $rs = new ADORecordSet_db2($qid); + + $ADODB_FETCH_MODE = $savem; + if (!$rs) { + $false = false; + return $false; + } + + $arr = $rs->GetArray(); + $rs->Close(); + $arr2 = array(); + // adodb_pr($arr); + if ($ttype) { + $isview = strncmp($ttype,'V',1) === 0; + } + for ($i=0; $i < sizeof($arr); $i++) { + if (!$arr[$i][2]) continue; + $type = $arr[$i][3]; + $schemaval = ($schema) ? $arr[$i][1].'.' : ''; + $name = $schemaval.$arr[$i][2]; + $owner = $arr[$i][1]; + if (substr($name,0,8) == 'EXPLAIN_') continue; + if ($ttype) { + if ($isview) { + if (strncmp($type,'V',1) === 0) $arr2[] = $name; + } else if (strncmp($type,'T',1) === 0 && strncmp($owner,'SYS',3) !== 0) $arr2[] = $name; + } else if (strncmp($type,'T',1) === 0 && strncmp($owner,'SYS',3) !== 0) $arr2[] = $name; + } + return $arr2; + } + + function _Execute($sql, $inputarr=false ) + { + if ($inputarr) list($sql,$inputarr) = _colonparser($sql, $inputarr); + return parent::_Execute($sql, $inputarr); + } +}; + + +class ADORecordSet_db2oci extends ADORecordSet_db2 { + + var $databaseType = "db2oci"; + + function ADORecordSet_db2oci($id,$mode=false) + { + return $this->ADORecordSet_db2($id,$mode); + } +} + +} //define +?> \ No newline at end of file diff --git a/lib/adodb/drivers/adodb-fbsql.inc.php b/lib/adodb/drivers/adodb-fbsql.inc.php index b40281b7b6..13bbd86c47 100644 --- a/lib/adodb/drivers/adodb-fbsql.inc.php +++ b/lib/adodb/drivers/adodb-fbsql.inc.php @@ -80,7 +80,7 @@ class ADODB_fbsql extends ADOConnection { return true; } - function MetaColumns($table) + function MetaColumns($table, $normalize=true) { if ($this->metaColumnsSQL) { diff --git a/lib/adodb/drivers/adodb-firebird.inc.php b/lib/adodb/drivers/adodb-firebird.inc.php index 09f7e4a659..d234a6201a 100644 --- a/lib/adodb/drivers/adodb-firebird.inc.php +++ b/lib/adodb/drivers/adodb-firebird.inc.php @@ -1,6 +1,6 @@ autoCommit) $this->BeginTrans(); $this->Execute("UPDATE $table SET $col=$col WHERE $where "); // is this correct - jlim? @@ -476,7 +476,7 @@ class ADODB_ibase extends ADOConnection { } //OPN STUFF end // returns array of ADOFieldObjects for current table - function MetaColumns($table) + function MetaColumns($table, $normalize=true) { global $ADODB_FETCH_MODE; diff --git a/lib/adodb/drivers/adodb-informix72.inc.php b/lib/adodb/drivers/adodb-informix72.inc.php index 25dee2b527..dd49123ff6 100644 --- a/lib/adodb/drivers/adodb-informix72.inc.php +++ b/lib/adodb/drivers/adodb-informix72.inc.php @@ -1,6 +1,6 @@ _autocommit) $this->BeginTrans(); - return $this->GetOne("select $flds from $tables where $where for update"); + return $this->GetOne("select $col from $tables where $where for update"); } /* Returns: the last error message from previous database operation @@ -147,7 +147,7 @@ class ADODB_informix72 extends ADOConnection { } - function MetaColumns($table) + function MetaColumns($table, $normalize=true) { global $ADODB_FETCH_MODE; @@ -369,7 +369,7 @@ class ADORecordset_informix72 extends ADORecordSet { foreach($fp as $k => $v) { $o = new ADOFieldObject; $o->name = $k; - $arr = split(';',$v); //"SQLTYPE;length;precision;scale;ISNULLABLE" + $arr = explode(';',$v); //"SQLTYPE;length;precision;scale;ISNULLABLE" $o->type = $arr[0]; $o->max_length = $arr[1]; $this->_fieldprops[] = $o; diff --git a/lib/adodb/drivers/adodb-ldap.inc.php b/lib/adodb/drivers/adodb-ldap.inc.php index db42b78b2e..d6ebb40751 100644 --- a/lib/adodb/drivers/adodb-ldap.inc.php +++ b/lib/adodb/drivers/adodb-ldap.inc.php @@ -1,6 +1,6 @@ port); if ( strstr( $host, ':' ) ) { - $conn_info = split( ':', $host ); + $conn_info = explode( ':', $host ); } $this->_connectionID = @ldap_connect( $conn_info[0], $conn_info[1] ); diff --git a/lib/adodb/drivers/adodb-mssql.inc.php b/lib/adodb/drivers/adodb-mssql.inc.php index 7cf51201df..21de19a618 100644 --- a/lib/adodb/drivers/adodb-mssql.inc.php +++ b/lib/adodb/drivers/adodb-mssql.inc.php @@ -1,6 +1,6 @@ qstr("Don't bother",magic_quotes_runtime()); + * + * @param s the string to quote + * @param [magic_quotes] if $s is GET/POST var, set to get_magic_quotes_gpc(). + * This undoes the stupidity of magic quotes for GPC. + * + * @return quoted string to be sent back to database + */ + function qstr($s,$magic_quotes=false) + { + if (!$magic_quotes) { + return "'".str_replace("'",$this->replaceQuote,$s)."'"; + } + + // undo magic quotes for " unless sybase is on + $sybase = ini_get('magic_quotes_sybase'); + if (!$sybase) { + $s = str_replace('\\"','"',$s); + if ($this->replaceQuote == "\\'") // ' already quoted, no need to change anything + return "'$s'"; + else {// change \' to '' for sybase/mssql + $s = str_replace('\\\\','\\',$s); + return "'".str_replace("\\'",$this->replaceQuote,$s)."'"; + } + } else { + return "'".$s."'"; + } + } +// moodle change end - see readme_moodle.txt + function _affectedrows() { return $this->GetOne('select @@rowcount'); @@ -331,14 +366,14 @@ class ADODB_mssql extends ADOConnection { See http://www.swynk.com/friends/achigrik/SQL70Locks.asp */ - function RowLock($tables,$where,$flds='top 1 null as ignore') + function RowLock($tables,$where,$col='top 1 null as ignore') { if (!$this->transCnt) $this->BeginTrans(); - return $this->GetOne("select $flds from $tables with (ROWLOCK,HOLDLOCK) where $where"); + return $this->GetOne("select $col from $tables with (ROWLOCK,HOLDLOCK) where $where"); } - function MetaIndexes($table,$primary=false) + function MetaIndexes($table,$primary=false, $owner=false) { $table = $this->qstr($table); @@ -738,46 +773,6 @@ order by constraint_name, referenced_table_name, keyno"; } return $rez; } - -// moodle change start - see readme_moodle.txt - /** - * Correctly quotes a string so that all strings are escaped. We prefix and append - * to the string single-quotes. - * An example is $db->qstr("Don't bother",magic_quotes_runtime()); - * - * @param s the string to quote - * @param [magic_quotes] if $s is GET/POST var, set to get_magic_quotes_gpc(). - * This undoes the stupidity of magic quotes for GPC. - * - * @return quoted string to be sent back to database - */ - function qstr($s,$magic_quotes=false) - { - if (!$magic_quotes) { - - if ($this->replaceQuote[0] == '\\'){ - // only since php 4.0.5 - $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s); - //$s = str_replace("\0","\\\0", str_replace('\\','\\\\',$s)); - } - return "'".str_replace("'",$this->replaceQuote,$s)."'"; - } - - // undo magic quotes for " unless sybase is on - $sybase = ini_get('magic_quotes_sybase'); - if (!$sybase) { - $s = str_replace('\\"','"',$s); - if ($this->replaceQuote == "\\'") // ' already quoted, no need to change anything - return "'$s'"; - else {// change \' to '' for sybase/mssql - $s = str_replace('\\\\','\\',$s); - return "'".str_replace("\\'",$this->replaceQuote,$s)."'"; - } - } else { - return "'".$s."'"; - } - } -// moodle change end - see readme_moodle.txt // returns true or false function _close() @@ -1101,4 +1096,4 @@ order by constraint_name, ordinal_position http://www.databasejournal.com/scripts/article.php/1440551 */ -?> +?> \ No newline at end of file diff --git a/lib/adodb/drivers/adodb-mssqlnative.inc.php b/lib/adodb/drivers/adodb-mssqlnative.inc.php index 96885de51f..920d947e2e 100644 --- a/lib/adodb/drivers/adodb-mssqlnative.inc.php +++ b/lib/adodb/drivers/adodb-mssqlnative.inc.php @@ -1,6 +1,6 @@ transCnt) $this->BeginTrans(); - return $this->GetOne("select $flds from $tables with (ROWLOCK,HOLDLOCK) where $where"); + return $this->GetOne("select $col from $tables with (ROWLOCK,HOLDLOCK) where $where"); } function SelectDB($dbName) diff --git a/lib/adodb/drivers/adodb-mysql.inc.php b/lib/adodb/drivers/adodb-mysql.inc.php index 07f9524ab1..751e8bd0dd 100644 --- a/lib/adodb/drivers/adodb-mysql.inc.php +++ b/lib/adodb/drivers/adodb-mysql.inc.php @@ -1,6 +1,6 @@ sysDate; $fraction = $dayFraction * 24 * 3600; - return $date . ' + INTERVAL ' . $fraction.' SECOND'; + return '('. $date . ' + INTERVAL ' . $fraction.' SECOND)'; // return "from_unixtime(unix_timestamp($date)+$fraction)"; } @@ -394,7 +394,7 @@ class ADODB_mysql extends ADOConnection { return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename); } - function MetaColumns($table) + function MetaColumns($table, $normalize=true) { $this->_findschema($table,$schema); if ($schema) { diff --git a/lib/adodb/drivers/adodb-mysqli.inc.php b/lib/adodb/drivers/adodb-mysqli.inc.php index 72616f6f90..d4c3a33762 100644 --- a/lib/adodb/drivers/adodb-mysqli.inc.php +++ b/lib/adodb/drivers/adodb-mysqli.inc.php @@ -1,6 +1,6 @@ transCnt==0) $this->BeginTrans(); if ($where) $where = ' where '.$where; - $rs = $this->Execute("select $flds from $tables $where for update"); + $rs = $this->Execute("select $col from $tables $where for update"); return !empty($rs); } @@ -526,7 +527,7 @@ class ADODB_mysqli extends ADOConnection { return $foreign_keys; } - function MetaColumns($table) + function MetaColumns($table, $normalize=true) { $false = false; if (!$this->metaColumnsSQL) @@ -684,15 +685,23 @@ class ADODB_mysqli extends ADOConnection { return $mysql_res; */ - if( $rs = mysqli_multi_query($this->_connectionID, $sql.';') )//Contributed by "Geisel Sierote" - { - $rs = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->_connectionID ) : @mysqli_use_result( $this->_connectionID ); - return $rs ? $rs : true; // mysqli_more_results( $this->_connectionID ) + if ($this->multiQuery) { + $rs = mysqli_multi_query($this->_connectionID, $sql.';'); + if ($rs) { + $rs = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->_connectionID ) : @mysqli_use_result( $this->_connectionID ); + return $rs ? $rs : true; // mysqli_more_results( $this->_connectionID ) + } } else { - if($this->debug) - ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg()); - return false; + $rs = mysqli_query($this->_connectionID, $sql, $ADODB_COUNTRECS ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT); + + if ($rs) return $rs; } + + if($this->debug) + ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg()); + + return false; + } /* Returns: the last error message from previous database operation */ @@ -947,6 +956,19 @@ class ADORecordSet_mysqli extends ADORecordSet{ function _close() { + //if results are attached to this pointer from Stored Proceedure calls, the next standard query will die 2014 + //only a problem with persistant connections + + //mysqli_next_result($this->connection->_connectionID); trashes the DB side attached results. + + while(mysqli_more_results($this->connection->_connectionID)){ + @mysqli_next_result($this->connection->_connectionID); + } + + //Because you can have one attached result, without tripping mysqli_more_results + @mysqli_next_result($this->connection->_connectionID); + + mysqli_free_result($this->_queryID); $this->_queryID = false; } diff --git a/lib/adodb/drivers/adodb-mysqlpo.inc.php b/lib/adodb/drivers/adodb-mysqlpo.inc.php index 22c93598b3..b52ff9608a 100644 --- a/lib/adodb/drivers/adodb-mysqlpo.inc.php +++ b/lib/adodb/drivers/adodb-mysqlpo.inc.php @@ -1,7 +1,7 @@ transCnt==0) $this->BeginTrans(); if ($where) $where = ' where '.$where; - $rs = $this->Execute("select $flds from $tables $where for update"); + $rs = $this->Execute("select $col from $tables $where for update"); return !empty($rs); } diff --git a/lib/adodb/drivers/adodb-mysqlt.inc.php b/lib/adodb/drivers/adodb-mysqlt.inc.php index 58ce56b728..f14dc05857 100644 --- a/lib/adodb/drivers/adodb-mysqlt.inc.php +++ b/lib/adodb/drivers/adodb-mysqlt.inc.php @@ -1,7 +1,7 @@ transCnt==0) $this->BeginTrans(); if ($where) $where = ' where '.$where; - $rs = $this->Execute("select $flds from $tables $where for update"); + $rs = $this->Execute("select $col from $tables $where for update"); return !empty($rs); } diff --git a/lib/adodb/drivers/adodb-netezza.inc.php b/lib/adodb/drivers/adodb-netezza.inc.php index 372d288f49..8b789433b8 100644 --- a/lib/adodb/drivers/adodb-netezza.inc.php +++ b/lib/adodb/drivers/adodb-netezza.inc.php @@ -1,6 +1,6 @@ rsPrefix .= 'ext_'; } - /* function MetaColumns($table) added by smondino@users.sourceforge.net*/ - function MetaColumns($table) + /* function MetaColumns($table, $normalize=true) added by smondino@users.sourceforge.net*/ + function MetaColumns($table, $normalize=true) { global $ADODB_FETCH_MODE; @@ -281,8 +281,13 @@ NATSOFT.DOMAIN = { if (empty($d) && $d !== 0) return 'null'; if ($isfld) return 'TO_DATE('.$d.",'".$this->dateformat."')"; + if (is_string($d)) $d = ADORecordSet::UnixDate($d); - return "TO_DATE(".adodb_date($this->fmtDate,$d).",'".$this->dateformat."')"; + + if (is_object($d)) $ds = $d->format($this->fmtDate); + else $ds = adodb_date($this->fmtDate,$d); + + return "TO_DATE(".$ds.",'".$this->dateformat."')"; } function BindDate($d) @@ -293,12 +298,15 @@ NATSOFT.DOMAIN = return substr($d,1,strlen($d)-2); } - function BindTimeStamp($d) + function BindTimeStamp($ts) { - $d = ADOConnection::DBTimeStamp($d); - if (strncmp($d,"'",1)) return $d; + if (empty($ts) && $ts !== 0) return 'null'; + if (is_string($ts)) $ts = ADORecordSet::UnixTimeStamp($ts); - return substr($d,1,strlen($d)-2); + if (is_object($ts)) $tss = $ts->format("'Y-m-d H:i:s'"); + else $tss = adodb_date("'Y-m-d H:i:s'",$ts); + + return $tss; } // format and return date string in database timestamp format @@ -307,13 +315,17 @@ NATSOFT.DOMAIN = if (empty($ts) && $ts !== 0) return 'null'; if ($isfld) return 'TO_DATE(substr('.$ts.",1,19),'RRRR-MM-DD, HH24:MI:SS')"; if (is_string($ts)) $ts = ADORecordSet::UnixTimeStamp($ts); - return 'TO_DATE('.adodb_date("'Y-m-d H:i:s'",$ts).",'RRRR-MM-DD, HH24:MI:SS')"; + + if (is_object($ts)) $tss = $ts->format("'Y-m-d H:i:s'"); + else $tss = adodb_date("'Y-m-d H:i:s'",$ts); + + return 'TO_DATE('.$tss.",'RRRR-MM-DD, HH24:MI:SS')"; } - function RowLock($tables,$where,$flds='1 as ignore') + function RowLock($tables,$where,$col='1 as ignore') { if ($this->autoCommit) $this->BeginTrans(); - return $this->GetOne("select $flds from $tables where $where for update"); + return $this->GetOne("select $col from $tables where $where for update"); } function MetaTables($ttype=false,$showSchema=false,$mask=false) @@ -1282,18 +1294,15 @@ SELECT /*+ RULE */ distinct b.column_name } return "'".str_replace("'",$this->replaceQuote,$s)."'"; } -// moodle change start - see readme_moodle.txt // undo magic quotes for " unless sybase is on - $sybase = ini_get('magic_quotes_sybase'); - if (!$sybase) { + if (!ini_get('magic_quotes_sybase')) { $s = str_replace('\\"','"',$s); $s = str_replace('\\\\','\\',$s); return "'".str_replace("\\'",$this->replaceQuote,$s)."'"; } else { return "'".$s."'"; } -// moodle change end - see readme_moodle.txt } } @@ -1551,7 +1560,7 @@ class ADORecordset_oci8 extends ADORecordSet { case 'NCHAR': case 'NVARCHAR': case 'NVARCHAR2': - if (isset($this) && $len <= $this->blobSize) return 'C'; + if ($len <= $this->blobSize) return 'C'; case 'NCLOB': case 'LONG': @@ -1604,4 +1613,4 @@ class ADORecordSet_ext_oci8 extends ADORecordSet_oci8 { return adodb_movenext($this); } } -?> +?> \ No newline at end of file diff --git a/lib/adodb/drivers/adodb-oci8.old.inc.php b/lib/adodb/drivers/adodb-oci8.old.inc.php deleted file mode 100644 index 6e63c2a3a0..0000000000 --- a/lib/adodb/drivers/adodb-oci8.old.inc.php +++ /dev/null @@ -1,1532 +0,0 @@ - - - 13 Nov 2000 jlim - removed all ora_* references. -*/ - -// security - hide paths -if (!defined('ADODB_DIR')) die(); - -/* -NLS_Date_Format -Allows you to use a date format other than the Oracle Lite default. When a literal -character string appears where a date value is expected, the Oracle Lite database -tests the string to see if it matches the formats of Oracle, SQL-92, or the value -specified for this parameter in the POLITE.INI file. Setting this parameter also -defines the default format used in the TO_CHAR or TO_DATE functions when no -other format string is supplied. - -For Oracle the default is dd-mon-yy or dd-mon-yyyy, and for SQL-92 the default is -yy-mm-dd or yyyy-mm-dd. - -Using 'RR' in the format forces two-digit years less than or equal to 49 to be -interpreted as years in the 21st century (2000–2049), and years over 50 as years in -the 20th century (1950–1999). Setting the RR format as the default for all two-digit -year entries allows you to become year-2000 compliant. For example: -NLS_DATE_FORMAT='RR-MM-DD' - -You can also modify the date format using the ALTER SESSION command. -*/ - -# define the LOB descriptor type for the given type -# returns false if no LOB descriptor -function oci_lob_desc($type) { - switch ($type) { - case OCI_B_BFILE: $result = OCI_D_FILE; break; - case OCI_B_CFILEE: $result = OCI_D_FILE; break; - case OCI_B_CLOB: $result = OCI_D_LOB; break; - case OCI_B_BLOB: $result = OCI_D_LOB; break; - case OCI_B_ROWID: $result = OCI_D_ROWID; break; - default: $result = false; break; - } - return $result; -} - -class ADODB_oci8 extends ADOConnection { - var $databaseType = 'oci8'; - var $dataProvider = 'oci8'; - var $replaceQuote = "''"; // string to use to replace quotes - var $concat_operator='||'; - var $sysDate = "TRUNC(SYSDATE)"; - var $sysTimeStamp = 'SYSDATE'; - var $metaDatabasesSQL = "SELECT USERNAME FROM ALL_USERS WHERE USERNAME NOT IN ('SYS','SYSTEM','DBSNMP','OUTLN') ORDER BY 1"; - var $_stmt; - var $_commit = OCI_COMMIT_ON_SUCCESS; - var $_initdate = true; // init date to YYYY-MM-DD - var $metaTablesSQL = "select table_name,table_type from cat where table_type in ('TABLE','VIEW') and table_name not like 'BIN\$%'"; // bin$ tables are recycle bin tables - var $metaColumnsSQL = "select cname,coltype,width, SCALE, PRECISION, NULLS, DEFAULTVAL from col where tname='%s' order by colno"; //changed by smondino@users.sourceforge. net - var $_bindInputArray = true; - var $hasGenID = true; - var $_genIDSQL = "SELECT (%s.nextval) FROM DUAL"; - var $_genSeqSQL = "CREATE SEQUENCE %s START WITH %s"; - var $_dropSeqSQL = "DROP SEQUENCE %s"; - var $hasAffectedRows = true; - var $random = "abs(mod(DBMS_RANDOM.RANDOM,10000001)/10000000)"; - var $noNullStrings = false; - var $connectSID = false; - var $_bind = false; - var $_nestedSQL = true; - var $_hasOCIFetchStatement = false; - var $_getarray = false; // currently not working - var $leftOuter = ''; // oracle wierdness, $col = $value (+) for LEFT OUTER, $col (+)= $value for RIGHT OUTER - var $session_sharing_force_blob = false; // alter session on updateblob if set to true - var $firstrows = true; // enable first rows optimization on SelectLimit() - var $selectOffsetAlg1 = 100; // when to use 1st algorithm of selectlimit. - var $NLS_DATE_FORMAT = 'YYYY-MM-DD'; // To include time, use 'RRRR-MM-DD HH24:MI:SS' - var $dateformat = 'YYYY-MM-DD'; // DBDate format - var $useDBDateFormatForTextInput=false; - var $datetime = false; // MetaType('DATE') returns 'D' (datetime==false) or 'T' (datetime == true) - var $_refLOBs = array(); - - // var $ansiOuter = true; // if oracle9 - - function ADODB_oci8() - { - $this->_hasOCIFetchStatement = ADODB_PHPVER >= 0x4200; - if (defined('ADODB_EXTENSION')) $this->rsPrefix .= 'ext_'; - } - - /* function MetaColumns($table) added by smondino@users.sourceforge.net*/ - function MetaColumns($table) - { - global $ADODB_FETCH_MODE; - - $false = false; - $save = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false); - - $rs = $this->Execute(sprintf($this->metaColumnsSQL,strtoupper($table))); - - if (isset($savem)) $this->SetFetchMode($savem); - $ADODB_FETCH_MODE = $save; - if (!$rs) { - return $false; - } - $retarr = array(); - while (!$rs->EOF) { //print_r($rs->fields); - $fld = new ADOFieldObject(); - $fld->name = $rs->fields[0]; - $fld->type = $rs->fields[1]; - $fld->max_length = $rs->fields[2]; - $fld->scale = $rs->fields[3]; - if ($rs->fields[1] == 'NUMBER') { - if ($rs->fields[3] == 0) $fld->type = 'INT'; - $fld->max_length = $rs->fields[4]; - } - $fld->not_null = (strncmp($rs->fields[5], 'NOT',3) === 0); - $fld->binary = (strpos($fld->type,'BLOB') !== false); - $fld->default_value = $rs->fields[6]; - - if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld; - else $retarr[strtoupper($fld->name)] = $fld; - $rs->MoveNext(); - } - $rs->Close(); - if (empty($retarr)) - return $false; - else - return $retarr; - } - - function Time() - { - $rs = $this->Execute("select TO_CHAR($this->sysTimeStamp,'YYYY-MM-DD HH24:MI:SS') from dual"); - if ($rs && !$rs->EOF) return $this->UnixTimeStamp(reset($rs->fields)); - - return false; - } - -/* - - Multiple modes of connection are supported: - - a. Local Database - $conn->Connect(false,'scott','tiger'); - - b. From tnsnames.ora - $conn->Connect(false,'scott','tiger',$tnsname); - $conn->Connect($tnsname,'scott','tiger'); - - c. Server + service name - $conn->Connect($serveraddress,'scott,'tiger',$service_name); - - d. Server + SID - $conn->connectSID = true; - $conn->Connect($serveraddress,'scott,'tiger',$SID); - - -Example TNSName: ---------------- -NATSOFT.DOMAIN = - (DESCRIPTION = - (ADDRESS_LIST = - (ADDRESS = (PROTOCOL = TCP)(HOST = kermit)(PORT = 1523)) - ) - (CONNECT_DATA = - (SERVICE_NAME = natsoft.domain) - ) - ) - - There are 3 connection modes, 0 = non-persistent, 1 = persistent, 2 = force new connection - -*/ - function _connect($argHostname, $argUsername, $argPassword, $argDatabasename,$mode=0) - { - if (!function_exists('OCIPLogon')) return null; - - - $this->_errorMsg = false; - $this->_errorCode = false; - - if($argHostname) { // added by Jorma Tuomainen - if (empty($argDatabasename)) $argDatabasename = $argHostname; - else { - if(strpos($argHostname,":")) { - $argHostinfo=explode(":",$argHostname); - $argHostname=$argHostinfo[0]; - $argHostport=$argHostinfo[1]; - } else { - $argHostport = empty($this->port)? "1521" : $this->port; - } - - if ($this->connectSID) { - $argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname - .")(PORT=$argHostport))(CONNECT_DATA=(SID=$argDatabasename)))"; - } else - $argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname - .")(PORT=$argHostport))(CONNECT_DATA=(SERVICE_NAME=$argDatabasename)))"; - } - } - - //if ($argHostname) print "

Connect: 1st argument should be left blank for $this->databaseType

"; - if ($mode==1) { - $this->_connectionID = ($this->charSet) ? - OCIPLogon($argUsername,$argPassword, $argDatabasename,$this->charSet) - : - OCIPLogon($argUsername,$argPassword, $argDatabasename) - ; - if ($this->_connectionID && $this->autoRollback) OCIrollback($this->_connectionID); - } else if ($mode==2) { - $this->_connectionID = ($this->charSet) ? - OCINLogon($argUsername,$argPassword, $argDatabasename,$this->charSet) - : - OCINLogon($argUsername,$argPassword, $argDatabasename); - - } else { - $this->_connectionID = ($this->charSet) ? - OCILogon($argUsername,$argPassword, $argDatabasename,$this->charSet) - : - OCILogon($argUsername,$argPassword, $argDatabasename); - } - if (!$this->_connectionID) return false; - if ($this->_initdate) { - $this->Execute("ALTER SESSION SET NLS_DATE_FORMAT='".$this->NLS_DATE_FORMAT."'"); - } - - // looks like: - // Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production With the Partitioning option JServer Release 8.1.7.0.0 - Production - // $vers = OCIServerVersion($this->_connectionID); - // if (strpos($vers,'8i') !== false) $this->ansiOuter = true; - return true; - } - - function ServerInfo() - { - $arr['compat'] = $this->GetOne('select value from sys.database_compatible_level'); - $arr['description'] = @OCIServerVersion($this->_connectionID); - $arr['version'] = ADOConnection::_findvers($arr['description']); - return $arr; - } - // returns true or false - function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) - { - return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename,1); - } - - // returns true or false - function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename) - { - return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename,2); - } - - function _affectedrows() - { - if (is_resource($this->_stmt)) return @OCIRowCount($this->_stmt); - return 0; - } - - function IfNull( $field, $ifNull ) - { - return " NVL($field, $ifNull) "; // if Oracle - } - - // format and return date string in database date format - function DBDate($d) - { - if (empty($d) && $d !== 0) return 'null'; - - if (is_string($d)) $d = ADORecordSet::UnixDate($d); - return "TO_DATE(".adodb_date($this->fmtDate,$d).",'".$this->dateformat."')"; - } - - function BindDate($d) - { - $d = ADOConnection::DBDate($d); - if (strncmp($d,"'",1)) return $d; - - return substr($d,1,strlen($d)-2); - } - - function BindTimeStamp($d) - { - $d = ADOConnection::DBTimeStamp($d); - if (strncmp($d,"'",1)) return $d; - - return substr($d,1,strlen($d)-2); - } - - // format and return date string in database timestamp format - function DBTimeStamp($ts) - { - if (empty($ts) && $ts !== 0) return 'null'; - if (is_string($ts)) $ts = ADORecordSet::UnixTimeStamp($ts); - return 'TO_DATE('.adodb_date("'Y-m-d H:i:s'",$ts).",'RRRR-MM-DD, HH24:MI:SS')"; - } - - function RowLock($tables,$where,$flds='1 as ignore') - { - if ($this->autoCommit) $this->BeginTrans(); - return $this->GetOne("select $flds from $tables where $where for update"); - } - - function MetaTables($ttype=false,$showSchema=false,$mask=false) - { - if ($mask) { - $save = $this->metaTablesSQL; - $mask = $this->qstr(strtoupper($mask)); - $this->metaTablesSQL .= " AND upper(table_name) like $mask"; - } - $ret = ADOConnection::MetaTables($ttype,$showSchema); - - if ($mask) { - $this->metaTablesSQL = $save; - } - return $ret; - } - - // Mark Newnham - function MetaIndexes ($table, $primary = FALSE, $owner=false) - { - // save old fetch mode - global $ADODB_FETCH_MODE; - - $save = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - - if ($this->fetchMode !== FALSE) { - $savem = $this->SetFetchMode(FALSE); - } - - // get index details - $table = strtoupper($table); - - // get Primary index - $primary_key = ''; - - $false = false; - $rs = $this->Execute(sprintf("SELECT * FROM ALL_CONSTRAINTS WHERE UPPER(TABLE_NAME)='%s' AND CONSTRAINT_TYPE='P'",$table)); - if ($row = $rs->FetchRow()) - $primary_key = $row[1]; //constraint_name - - if ($primary==TRUE && $primary_key=='') { - if (isset($savem)) - $this->SetFetchMode($savem); - $ADODB_FETCH_MODE = $save; - return $false; //There is no primary key - } - - $rs = $this->Execute(sprintf("SELECT ALL_INDEXES.INDEX_NAME, ALL_INDEXES.UNIQUENESS, ALL_IND_COLUMNS.COLUMN_POSITION, ALL_IND_COLUMNS.COLUMN_NAME FROM ALL_INDEXES,ALL_IND_COLUMNS WHERE UPPER(ALL_INDEXES.TABLE_NAME)='%s' AND ALL_IND_COLUMNS.INDEX_NAME=ALL_INDEXES.INDEX_NAME",$table)); - - - if (!is_object($rs)) { - if (isset($savem)) - $this->SetFetchMode($savem); - $ADODB_FETCH_MODE = $save; - return $false; - } - - $indexes = array (); - // parse index data into array - - while ($row = $rs->FetchRow()) { - if ($primary && $row[0] != $primary_key) continue; - if (!isset($indexes[$row[0]])) { - $indexes[$row[0]] = array( - 'unique' => ($row[1] == 'UNIQUE'), - 'columns' => array() - ); - } - $indexes[$row[0]]['columns'][$row[2] - 1] = $row[3]; - } - - // sort columns by order in the index - foreach ( array_keys ($indexes) as $index ) { - ksort ($indexes[$index]['columns']); - } - - if (isset($savem)) { - $this->SetFetchMode($savem); - $ADODB_FETCH_MODE = $save; - } - return $indexes; - } - - function BeginTrans() - { - if ($this->transOff) return true; - $this->transCnt += 1; - $this->autoCommit = false; - $this->_commit = OCI_DEFAULT; - - if ($this->_transmode) $this->Execute("SET TRANSACTION ".$this->_transmode); - return true; - } - - function CommitTrans($ok=true) - { - if ($this->transOff) return true; - if (!$ok) return $this->RollbackTrans(); - - if ($this->transCnt) $this->transCnt -= 1; - $ret = OCIcommit($this->_connectionID); - $this->_commit = OCI_COMMIT_ON_SUCCESS; - $this->autoCommit = true; - return $ret; - } - - function RollbackTrans() - { - if ($this->transOff) return true; - if ($this->transCnt) $this->transCnt -= 1; - $ret = OCIrollback($this->_connectionID); - $this->_commit = OCI_COMMIT_ON_SUCCESS; - $this->autoCommit = true; - return $ret; - } - - - function SelectDB($dbName) - { - return false; - } - - function ErrorMsg() - { - if ($this->_errorMsg !== false) return $this->_errorMsg; - - if (is_resource($this->_stmt)) $arr = @OCIError($this->_stmt); - if (empty($arr)) { - if (is_resource($this->_connectionID)) $arr = @OCIError($this->_connectionID); - else $arr = @OCIError(); - if ($arr === false) return ''; - } - $this->_errorMsg = $arr['message']; - $this->_errorCode = $arr['code']; - return $this->_errorMsg; - } - - function ErrorNo() - { - if ($this->_errorCode !== false) return $this->_errorCode; - - if (is_resource($this->_stmt)) $arr = @OCIError($this->_stmt); - if (empty($arr)) { - $arr = @OCIError($this->_connectionID); - if ($arr == false) $arr = @OCIError(); - if ($arr == false) return ''; - } - - $this->_errorMsg = $arr['message']; - $this->_errorCode = $arr['code']; - - return $arr['code']; - } - - // Format date column in sql string given an input format that understands Y M D - function SQLDate($fmt, $col=false) - { - if (!$col) $col = $this->sysTimeStamp; - $s = 'TO_CHAR('.$col.",'"; - - $len = strlen($fmt); - for ($i=0; $i < $len; $i++) { - $ch = $fmt[$i]; - switch($ch) { - case 'Y': - case 'y': - $s .= 'YYYY'; - break; - case 'Q': - case 'q': - $s .= 'Q'; - break; - - case 'M': - $s .= 'Mon'; - break; - - case 'm': - $s .= 'MM'; - break; - case 'D': - case 'd': - $s .= 'DD'; - break; - - case 'H': - $s.= 'HH24'; - break; - - case 'h': - $s .= 'HH'; - break; - - case 'i': - $s .= 'MI'; - break; - - case 's': - $s .= 'SS'; - break; - - case 'a': - case 'A': - $s .= 'AM'; - break; - - case 'w': - $s .= 'D'; - break; - - case 'l': - $s .= 'DAY'; - break; - - case 'W': - $s .= 'WW'; - break; - - default: - // handle escape characters... - if ($ch == '\\') { - $i++; - $ch = substr($fmt,$i,1); - } - if (strpos('-/.:;, ',$ch) !== false) $s .= $ch; - else $s .= '"'.$ch.'"'; - - } - } - return $s. "')"; - } - - function GetRandRow($sql, $arr = false) - { - $sql = "SELECT * FROM ($sql ORDER BY dbms_random.value) WHERE rownum = 1"; - - return $this->GetRow($sql,$arr); - } - - /* - This algorithm makes use of - - a. FIRST_ROWS hint - The FIRST_ROWS hint explicitly chooses the approach to optimize response time, - that is, minimum resource usage to return the first row. Results will be returned - as soon as they are identified. - - b. Uses rownum tricks to obtain only the required rows from a given offset. - As this uses complicated sql statements, we only use this if the $offset >= 100. - This idea by Tomas V V Cox. - - This implementation does not appear to work with oracle 8.0.5 or earlier. Comment - out this function then, and the slower SelectLimit() in the base class will be used. - */ - function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0) - { - // seems that oracle only supports 1 hint comment in 8i - if ($this->firstrows) { - if (strpos($sql,'/*+') !== false) - $sql = str_replace('/*+ ','/*+FIRST_ROWS ',$sql); - else - $sql = preg_replace('/^[ \t\n]*select/i','SELECT /*+FIRST_ROWS*/',$sql); - } - - if ($offset < $this->selectOffsetAlg1 && 0 < $nrows && $nrows < 1000) { - if ($nrows > 0) { - if ($offset > 0) $nrows += $offset; - //$inputarr['adodb_rownum'] = $nrows; - if ($this->databaseType == 'oci8po') { - $sql = "select * from (".$sql.") where rownum <= ?"; - } else { - $sql = "select * from (".$sql.") where rownum <= :adodb_offset"; - } - $inputarr['adodb_offset'] = $nrows; - $nrows = -1; - } - // note that $nrows = 0 still has to work ==> no rows returned - - $rs = ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache); - return $rs; - - } else { - // Algorithm by Tomas V V Cox, from PEAR DB oci8.php - - // Let Oracle return the name of the columns - $q_fields = "SELECT * FROM (".$sql.") WHERE NULL = NULL"; - - $false = false; - if (! $stmt_arr = $this->Prepare($q_fields)) { - return $false; - } - $stmt = $stmt_arr[1]; - - if (is_array($inputarr)) { - foreach($inputarr as $k => $v) { - if (is_array($v)) { - if (sizeof($v) == 2) // suggested by g.giunta@libero. - OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1]); - else - OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1],$v[2]); - } else { - $len = -1; - if ($v === ' ') $len = 1; - if (isset($bindarr)) { // is prepared sql, so no need to ocibindbyname again - $bindarr[$k] = $v; - } else { // dynamic sql, so rebind every time - OCIBindByName($stmt,":$k",$inputarr[$k],$len); - } - } - } - } - - if (!OCIExecute($stmt, OCI_DEFAULT)) { - OCIFreeStatement($stmt); - return $false; - } - - $ncols = OCINumCols($stmt); - for ( $i = 1; $i <= $ncols; $i++ ) { - $cols[] = '"'.OCIColumnName($stmt, $i).'"'; - } - $result = false; - - OCIFreeStatement($stmt); - $fields = implode(',', $cols); - $nrows += $offset; - $offset += 1; // in Oracle rownum starts at 1 - - if ($this->databaseType == 'oci8po') { - $sql = "SELECT $fields FROM". - "(SELECT rownum as adodb_rownum, $fields FROM". - " ($sql) WHERE rownum <= ?". - ") WHERE adodb_rownum >= ?"; - } else { - $sql = "SELECT $fields FROM". - "(SELECT rownum as adodb_rownum, $fields FROM". - " ($sql) WHERE rownum <= :adodb_nrows". - ") WHERE adodb_rownum >= :adodb_offset"; - } - $inputarr['adodb_nrows'] = $nrows; - $inputarr['adodb_offset'] = $offset; - - if ($secs2cache>0) $rs = $this->CacheExecute($secs2cache, $sql,$inputarr); - else $rs = $this->Execute($sql,$inputarr); - return $rs; - } - - } - - /** - * Usage: - * Store BLOBs and CLOBs - * - * Example: to store $var in a blob - * - * $conn->Execute('insert into TABLE (id,ablob) values(12,empty_blob())'); - * $conn->UpdateBlob('TABLE', 'ablob', $varHoldingBlob, 'ID=12', 'BLOB'); - * - * $blobtype supports 'BLOB' and 'CLOB', but you need to change to 'empty_clob()'. - * - * to get length of LOB: - * select DBMS_LOB.GETLENGTH(ablob) from TABLE - * - * If you are using CURSOR_SHARING = force, it appears this will case a segfault - * under oracle 8.1.7.0. Run: - * $db->Execute('ALTER SESSION SET CURSOR_SHARING=EXACT'); - * before UpdateBlob() then... - */ - - function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB') - { - - //if (strlen($val) < 4000) return $this->Execute("UPDATE $table SET $column=:blob WHERE $where",array('blob'=>$val)) != false; - - switch(strtoupper($blobtype)) { - default: ADOConnection::outp("UpdateBlob: Unknown blobtype=$blobtype"); return false; - case 'BLOB': $type = OCI_B_BLOB; break; - case 'CLOB': $type = OCI_B_CLOB; break; - } - - if ($this->databaseType == 'oci8po') - $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO ?"; - else - $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO :blob"; - - $desc = OCINewDescriptor($this->_connectionID, OCI_D_LOB); - $arr['blob'] = array($desc,-1,$type); - if ($this->session_sharing_force_blob) $this->Execute('ALTER SESSION SET CURSOR_SHARING=EXACT'); - $commit = $this->autoCommit; - if ($commit) $this->BeginTrans(); - $rs = $this->_Execute($sql,$arr); - if ($rez = !empty($rs)) $desc->save($val); - $desc->free(); - if ($commit) $this->CommitTrans(); - if ($this->session_sharing_force_blob) $this->Execute('ALTER SESSION SET CURSOR_SHARING=FORCE'); - - if ($rez) $rs->Close(); - return $rez; - } - - /** - * Usage: store file pointed to by $var in a blob - */ - function UpdateBlobFile($table,$column,$val,$where,$blobtype='BLOB') - { - switch(strtoupper($blobtype)) { - default: ADOConnection::outp( "UpdateBlob: Unknown blobtype=$blobtype"); return false; - case 'BLOB': $type = OCI_B_BLOB; break; - case 'CLOB': $type = OCI_B_CLOB; break; - } - - if ($this->databaseType == 'oci8po') - $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO ?"; - else - $sql = "UPDATE $table set $column=EMPTY_{$blobtype}() WHERE $where RETURNING $column INTO :blob"; - - $desc = OCINewDescriptor($this->_connectionID, OCI_D_LOB); - $arr['blob'] = array($desc,-1,$type); - - $this->BeginTrans(); - $rs = ADODB_oci8::Execute($sql,$arr); - if ($rez = !empty($rs)) $desc->savefile($val); - $desc->free(); - $this->CommitTrans(); - - if ($rez) $rs->Close(); - return $rez; - } - - /** - * Execute SQL - * - * @param sql SQL statement to execute, or possibly an array holding prepared statement ($sql[0] will hold sql text) - * @param [inputarr] holds the input data to bind to. Null elements will be set to null. - * @return RecordSet or false - */ - function Execute($sql,$inputarr=false) - { - if ($this->fnExecute) { - $fn = $this->fnExecute; - $ret = $fn($this,$sql,$inputarr); - if (isset($ret)) return $ret; - } - if ($inputarr) { - #if (!is_array($inputarr)) $inputarr = array($inputarr); - - $element0 = reset($inputarr); - - # is_object check because oci8 descriptors can be passed in - if (is_array($element0) && !is_object(reset($element0))) { - if (is_string($sql)) - $stmt = $this->Prepare($sql); - else - $stmt = $sql; - - foreach($inputarr as $arr) { - $ret = $this->_Execute($stmt,$arr); - if (!$ret) return $ret; - } - } else { - $ret = $this->_Execute($sql,$inputarr); - } - - } else { - $ret = $this->_Execute($sql,false); - } - - return $ret; - } - - /* - Example of usage: - - $stmt = $this->Prepare('insert into emp (empno, ename) values (:empno, :ename)'); - */ - function Prepare($sql,$cursor=false) - { - static $BINDNUM = 0; - - $stmt = OCIParse($this->_connectionID,$sql); - - if (!$stmt) { - $this->_errorMsg = false; - $this->_errorCode = false; - $arr = @OCIError($this->_connectionID); - if ($arr === false) return false; - - $this->_errorMsg = $arr['message']; - $this->_errorCode = $arr['code']; - return false; - } - - $BINDNUM += 1; - - $sttype = @OCIStatementType($stmt); - if ($sttype == 'BEGIN' || $sttype == 'DECLARE') { - return array($sql,$stmt,0,$BINDNUM, ($cursor) ? OCINewCursor($this->_connectionID) : false); - } - return array($sql,$stmt,0,$BINDNUM); - } - - /* - Call an oracle stored procedure and returns a cursor variable as a recordset. - Concept by Robert Tuttle robert@ud.com - - Example: - Note: we return a cursor variable in :RS2 - $rs = $db->ExecuteCursor("BEGIN adodb.open_tab(:RS2); END;",'RS2'); - - $rs = $db->ExecuteCursor( - "BEGIN :RS2 = adodb.getdata(:VAR1); END;", - 'RS2', - array('VAR1' => 'Mr Bean')); - - */ - function ExecuteCursor($sql,$cursorName='rs',$params=false) - { - if (is_array($sql)) $stmt = $sql; - else $stmt = ADODB_oci8::Prepare($sql,true); # true to allocate OCINewCursor - - if (is_array($stmt) && sizeof($stmt) >= 5) { - $hasref = true; - $ignoreCur = false; - $this->Parameter($stmt, $ignoreCur, $cursorName, false, -1, OCI_B_CURSOR); - if ($params) { - foreach($params as $k => $v) { - $this->Parameter($stmt,$params[$k], $k); - } - } - } else - $hasref = false; - - $rs = $this->Execute($stmt); - if ($rs) { - if ($rs->databaseType == 'array') OCIFreeCursor($stmt[4]); - else if ($hasref) $rs->_refcursor = $stmt[4]; - } - return $rs; - } - - /* - Bind a variable -- very, very fast for executing repeated statements in oracle. - Better than using - for ($i = 0; $i < $max; $i++) { - $p1 = ?; $p2 = ?; $p3 = ?; - $this->Execute("insert into table (col0, col1, col2) values (:0, :1, :2)", - array($p1,$p2,$p3)); - } - - Usage: - $stmt = $DB->Prepare("insert into table (col0, col1, col2) values (:0, :1, :2)"); - $DB->Bind($stmt, $p1); - $DB->Bind($stmt, $p2); - $DB->Bind($stmt, $p3); - for ($i = 0; $i < $max; $i++) { - $p1 = ?; $p2 = ?; $p3 = ?; - $DB->Execute($stmt); - } - - Some timings: - ** Test table has 3 cols, and 1 index. Test to insert 1000 records - Time 0.6081s (1644.60 inserts/sec) with direct OCIParse/OCIExecute - Time 0.6341s (1577.16 inserts/sec) with ADOdb Prepare/Bind/Execute - Time 1.5533s ( 643.77 inserts/sec) with pure SQL using Execute - - Now if PHP only had batch/bulk updating like Java or PL/SQL... - - Note that the order of parameters differs from OCIBindByName, - because we default the names to :0, :1, :2 - */ - function Bind(&$stmt,&$var,$size=4000,$type=false,$name=false,$isOutput=false) - { - - if (!is_array($stmt)) return false; - - if (($type == OCI_B_CURSOR) && sizeof($stmt) >= 5) { - return OCIBindByName($stmt[1],":".$name,$stmt[4],$size,$type); - } - - if ($name == false) { - if ($type !== false) $rez = OCIBindByName($stmt[1],":".$stmt[2],$var,$size,$type); - else $rez = OCIBindByName($stmt[1],":".$stmt[2],$var,$size); // +1 byte for null terminator - $stmt[2] += 1; - } else if (oci_lob_desc($type)) { - if ($this->debug) { - ADOConnection::outp("Bind: name = $name"); - } - //we have to create a new Descriptor here - $numlob = count($this->_refLOBs); - $this->_refLOBs[$numlob]['LOB'] = OCINewDescriptor($this->_connectionID, oci_lob_desc($type)); - $this->_refLOBs[$numlob]['TYPE'] = $isOutput; - - $tmp = $this->_refLOBs[$numlob]['LOB']; - $rez = OCIBindByName($stmt[1], ":".$name, $tmp, -1, $type); - if ($this->debug) { - ADOConnection::outp("Bind: descriptor has been allocated, var (".$name.") binded"); - } - - // if type is input then write data to lob now - if ($isOutput == false) { - $var = $this->BlobEncode($var); - $tmp->WriteTemporary($var); - $this->_refLOBs[$numlob]['VAR'] = $var; - if ($this->debug) { - ADOConnection::outp("Bind: LOB has been written to temp"); - } - } else { - $this->_refLOBs[$numlob]['VAR'] = $var; - } - $rez = $tmp; - } else { - if ($this->debug) - ADOConnection::outp("Bind: name = $name"); - - if ($type !== false) $rez = OCIBindByName($stmt[1],":".$name,$var,$size,$type); - else $rez = OCIBindByName($stmt[1],":".$name,$var,$size); // +1 byte for null terminator - } - - return $rez; - } - - function Param($name,$type=false) - { - return ':'.$name; - } - - /* - Usage: - $stmt = $db->Prepare('select * from table where id =:myid and group=:group'); - $db->Parameter($stmt,$id,'myid'); - $db->Parameter($stmt,$group,'group'); - $db->Execute($stmt); - - @param $stmt Statement returned by Prepare() or PrepareSP(). - @param $var PHP variable to bind to - @param $name Name of stored procedure variable name to bind to. - @param [$isOutput] Indicates direction of parameter 0/false=IN 1=OUT 2= IN/OUT. This is ignored in oci8. - @param [$maxLen] Holds an maximum length of the variable. - @param [$type] The data type of $var. Legal values depend on driver. - - See OCIBindByName documentation at php.net. - */ - function Parameter(&$stmt,&$var,$name,$isOutput=false,$maxLen=4000,$type=false) - { - if ($this->debug) { - $prefix = ($isOutput) ? 'Out' : 'In'; - $ztype = (empty($type)) ? 'false' : $type; - ADOConnection::outp( "{$prefix}Parameter(\$stmt, \$php_var='$var', \$name='$name', \$maxLen=$maxLen, \$type=$ztype);"); - } - return $this->Bind($stmt,$var,$maxLen,$type,$name,$isOutput); - } - - /* - returns query ID if successful, otherwise false - this version supports: - - 1. $db->execute('select * from table'); - - 2. $db->prepare('insert into table (a,b,c) values (:0,:1,:2)'); - $db->execute($prepared_statement, array(1,2,3)); - - 3. $db->execute('insert into table (a,b,c) values (:a,:b,:c)',array('a'=>1,'b'=>2,'c'=>3)); - - 4. $db->prepare('insert into table (a,b,c) values (:0,:1,:2)'); - $db->bind($stmt,1); $db->bind($stmt,2); $db->bind($stmt,3); - $db->execute($stmt); - */ - function _query($sql,$inputarr) - { - if (is_array($sql)) { // is prepared sql - $stmt = $sql[1]; - - // we try to bind to permanent array, so that OCIBindByName is persistent - // and carried out once only - note that max array element size is 4000 chars - if (is_array($inputarr)) { - $bindpos = $sql[3]; - if (isset($this->_bind[$bindpos])) { - // all tied up already - $bindarr = $this->_bind[$bindpos]; - } else { - // one statement to bind them all - $bindarr = array(); - foreach($inputarr as $k => $v) { - $bindarr[$k] = $v; - OCIBindByName($stmt,":$k",$bindarr[$k],is_string($v) && strlen($v)>4000 ? -1 : 4000); - } - $this->_bind[$bindpos] = $bindarr; - } - } - } else { - $stmt=OCIParse($this->_connectionID,$sql); - } - - $this->_stmt = $stmt; - if (!$stmt) return false; - - if (defined('ADODB_PREFETCH_ROWS')) @OCISetPrefetch($stmt,ADODB_PREFETCH_ROWS); - - if (is_array($inputarr)) { - foreach($inputarr as $k => $v) { - if (is_array($v)) { - if (sizeof($v) == 2) // suggested by g.giunta@libero. - OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1]); - else - OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1],$v[2]); - - if ($this->debug==99) { - if (is_object($v[0])) - echo "name=:$k",' len='.$v[1],' type='.$v[2],'
'; - else - echo "name=:$k",' var='.$inputarr[$k][0],' len='.$v[1],' type='.$v[2],'
'; - - } - } else { - $len = -1; - if ($v === ' ') $len = 1; - if (isset($bindarr)) { // is prepared sql, so no need to ocibindbyname again - $bindarr[$k] = $v; - } else { // dynamic sql, so rebind every time - OCIBindByName($stmt,":$k",$inputarr[$k],$len); - } - } - } - } - - $this->_errorMsg = false; - $this->_errorCode = false; - if (OCIExecute($stmt,$this->_commit)) { -//OCIInternalDebug(1); - if (count($this -> _refLOBs) > 0) { - - foreach ($this -> _refLOBs as $key => $value) { - if ($this -> _refLOBs[$key]['TYPE'] == true) { - $tmp = $this -> _refLOBs[$key]['LOB'] -> load(); - if ($this -> debug) { - ADOConnection::outp("OUT LOB: LOB has been loaded.
"); - } - //$_GLOBALS[$this -> _refLOBs[$key]['VAR']] = $tmp; - $this -> _refLOBs[$key]['VAR'] = $tmp; - } else { - $this->_refLOBs[$key]['LOB']->save($this->_refLOBs[$key]['VAR']); - $this -> _refLOBs[$key]['LOB']->free(); - unset($this -> _refLOBs[$key]); - if ($this->debug) { - ADOConnection::outp("IN LOB: LOB has been saved.
"); - } - } - } - } - - switch (@OCIStatementType($stmt)) { - case "SELECT": - return $stmt; - - case 'DECLARE': - case "BEGIN": - if (is_array($sql) && !empty($sql[4])) { - $cursor = $sql[4]; - if (is_resource($cursor)) { - $ok = OCIExecute($cursor); - return $cursor; - } - return $stmt; - } else { - if (is_resource($stmt)) { - OCIFreeStatement($stmt); - return true; - } - return $stmt; - } - break; - default : - // ociclose -- no because it could be used in a LOB? - return true; - } - } - return false; - } - - // returns true or false - function _close() - { - if (!$this->_connectionID) return; - - if (!$this->autoCommit) OCIRollback($this->_connectionID); - if (count($this->_refLOBs) > 0) { - foreach ($this ->_refLOBs as $key => $value) { - $this->_refLOBs[$key]['LOB']->free(); - unset($this->_refLOBs[$key]); - } - } - OCILogoff($this->_connectionID); - - $this->_stmt = false; - $this->_connectionID = false; - } - - function MetaPrimaryKeys($table, $owner=false,$internalKey=false) - { - if ($internalKey) return array('ROWID'); - - // tested with oracle 8.1.7 - $table = strtoupper($table); - if ($owner) { - $owner_clause = "AND ((a.OWNER = b.OWNER) AND (a.OWNER = UPPER('$owner')))"; - $ptab = 'ALL_'; - } else { - $owner_clause = ''; - $ptab = 'USER_'; - } - $sql = " -SELECT /*+ RULE */ distinct b.column_name - FROM {$ptab}CONSTRAINTS a - , {$ptab}CONS_COLUMNS b - WHERE ( UPPER(b.table_name) = ('$table')) - AND (UPPER(a.table_name) = ('$table') and a.constraint_type = 'P') - $owner_clause - AND (a.constraint_name = b.constraint_name)"; - - $rs = $this->Execute($sql); - if ($rs && !$rs->EOF) { - $arr = $rs->GetArray(); - $a = array(); - foreach($arr as $v) { - $a[] = reset($v); - } - return $a; - } - else return false; - } - - // http://gis.mit.edu/classes/11.521/sqlnotes/referential_integrity.html - function MetaForeignKeys($table, $owner=false) - { - global $ADODB_FETCH_MODE; - - $save = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - $table = $this->qstr(strtoupper($table)); - if (!$owner) { - $owner = $this->user; - $tabp = 'user_'; - } else - $tabp = 'all_'; - - $owner = ' and owner='.$this->qstr(strtoupper($owner)); - - $sql = -"select constraint_name,r_owner,r_constraint_name - from {$tabp}constraints - where constraint_type = 'R' and table_name = $table $owner"; - - $constraints = $this->GetArray($sql); - $arr = false; - foreach($constraints as $constr) { - $cons = $this->qstr($constr[0]); - $rowner = $this->qstr($constr[1]); - $rcons = $this->qstr($constr[2]); - $cols = $this->GetArray("select column_name from {$tabp}cons_columns where constraint_name=$cons $owner order by position"); - $tabcol = $this->GetArray("select table_name,column_name from {$tabp}cons_columns where owner=$rowner and constraint_name=$rcons order by position"); - - if ($cols && $tabcol) - for ($i=0, $max=sizeof($cols); $i < $max; $i++) { - $arr[$tabcol[$i][0]] = $cols[$i][0].'='.$tabcol[$i][1]; - } - } - $ADODB_FETCH_MODE = $save; - - return $arr; - } - - - function CharMax() - { - return 4000; - } - - function TextMax() - { - return 4000; - } - - /** - * Quotes a string. - * An example is $db->qstr("Don't bother",magic_quotes_runtime()); - * - * @param s the string to quote - * @param [magic_quotes] if $s is GET/POST var, set to get_magic_quotes_gpc(). - * This undoes the stupidity of magic quotes for GPC. - * - * @return quoted string to be sent back to database - */ - function qstr($s,$magic_quotes=false) - { - //$nofixquotes=false; - - if ($this->noNullStrings && strlen($s)==0)$s = ' '; - if (!$magic_quotes) { - if ($this->replaceQuote[0] == '\\'){ - $s = str_replace('\\','\\\\',$s); - } - return "'".str_replace("'",$this->replaceQuote,$s)."'"; - } - - // undo magic quotes for " - $s = str_replace('\\"','"',$s); - - $s = str_replace('\\\\','\\',$s); - return "'".str_replace("\\'",$this->replaceQuote,$s)."'"; - - } - -} - -/*-------------------------------------------------------------------------------------- - Class Name: Recordset ---------------------------------------------------------------------------------------*/ - -class ADORecordset_oci8 extends ADORecordSet { - - var $databaseType = 'oci8'; - var $bind=false; - var $_fieldobjs; - - //var $_arr = false; - - function ADORecordset_oci8($queryID,$mode=false) - { - if ($mode === false) { - global $ADODB_FETCH_MODE; - $mode = $ADODB_FETCH_MODE; - } - switch ($mode) - { - case ADODB_FETCH_ASSOC:$this->fetchMode = OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break; - case ADODB_FETCH_DEFAULT: - case ADODB_FETCH_BOTH:$this->fetchMode = OCI_NUM+OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break; - case ADODB_FETCH_NUM: - default: - $this->fetchMode = OCI_NUM+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break; - } - - $this->adodbFetchMode = $mode; - $this->_queryID = $queryID; - } - - - function Init() - { - if ($this->_inited) return; - - $this->_inited = true; - if ($this->_queryID) { - - $this->_currentRow = 0; - @$this->_initrs(); - $this->EOF = !$this->_fetch(); - - /* - // based on idea by Gaetano Giunta to detect unusual oracle errors - // see http://phplens.com/lens/lensforum/msgs.php?id=6771 - $err = OCIError($this->_queryID); - if ($err && $this->connection->debug) ADOConnection::outp($err); - */ - - if (!is_array($this->fields)) { - $this->_numOfRows = 0; - $this->fields = array(); - } - } else { - $this->fields = array(); - $this->_numOfRows = 0; - $this->_numOfFields = 0; - $this->EOF = true; - } - } - - function _initrs() - { - $this->_numOfRows = -1; - $this->_numOfFields = OCInumcols($this->_queryID); - if ($this->_numOfFields>0) { - $this->_fieldobjs = array(); - $max = $this->_numOfFields; - for ($i=0;$i<$max; $i++) $this->_fieldobjs[] = $this->_FetchField($i); - } - } - - /* Returns: an object containing field information. - Get column information in the Recordset object. fetchField() can be used in order to obtain information about - fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by - fetchField() is retrieved. */ - - function _FetchField($fieldOffset = -1) - { - $fld = new ADOFieldObject; - $fieldOffset += 1; - $fld->name =OCIcolumnname($this->_queryID, $fieldOffset); - $fld->type = OCIcolumntype($this->_queryID, $fieldOffset); - $fld->max_length = OCIcolumnsize($this->_queryID, $fieldOffset); - switch($fld->type) { - case 'NUMBER': - $p = OCIColumnPrecision($this->_queryID, $fieldOffset); - $sc = OCIColumnScale($this->_queryID, $fieldOffset); - if ($p != 0 && $sc == 0) $fld->type = 'INT'; - break; - - case 'CLOB': - case 'NCLOB': - case 'BLOB': - $fld->max_length = -1; - break; - } - return $fld; - } - - /* For some reason, OCIcolumnname fails when called after _initrs() so we cache it */ - function FetchField($fieldOffset = -1) - { - return $this->_fieldobjs[$fieldOffset]; - } - - - /* - // 10% speedup to move MoveNext to child class - function _MoveNext() - { - //global $ADODB_EXTENSION;if ($ADODB_EXTENSION) return @adodb_movenext($this); - - if ($this->EOF) return false; - - $this->_currentRow++; - if(@OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode)) - return true; - $this->EOF = true; - - return false; - } */ - - - function MoveNext() - { - if (@OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode)) { - $this->_currentRow += 1; - return true; - } - if (!$this->EOF) { - $this->_currentRow += 1; - $this->EOF = true; - } - return false; - } - - /* - # does not work as first record is retrieved in _initrs(), so is not included in GetArray() - function GetArray($nRows = -1) - { - global $ADODB_OCI8_GETARRAY; - - if (true || !empty($ADODB_OCI8_GETARRAY)) { - # does not support $ADODB_ANSI_PADDING_OFF - - //OCI_RETURN_NULLS and OCI_RETURN_LOBS is set by OCIfetchstatement - switch($this->adodbFetchMode) { - case ADODB_FETCH_NUM: - - $ncols = @OCIfetchstatement($this->_queryID, $results, 0, $nRows, OCI_FETCHSTATEMENT_BY_ROW+OCI_NUM); - $results = array_merge(array($this->fields),$results); - return $results; - - case ADODB_FETCH_ASSOC: - if (ADODB_ASSOC_CASE != 2 || $this->databaseType != 'oci8') break; - - $ncols = @OCIfetchstatement($this->_queryID, $assoc, 0, $nRows, OCI_FETCHSTATEMENT_BY_ROW); - $results = array_merge(array($this->fields),$assoc); - return $results; - - default: - break; - } - } - - $results = ADORecordSet::GetArray($nRows); - return $results; - - } */ - - /* Optimize SelectLimit() by using OCIFetch() instead of OCIFetchInto() */ - function GetArrayLimit($nrows,$offset=-1) - { - if ($offset <= 0) { - $arr = $this->GetArray($nrows); - return $arr; - } - $arr = array(); - for ($i=1; $i < $offset; $i++) - if (!@OCIFetch($this->_queryID)) return $arr; - - if (!@OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode)) return $arr;; - $results = array(); - $cnt = 0; - while (!$this->EOF && $nrows != $cnt) { - $results[$cnt++] = $this->fields; - $this->MoveNext(); - } - - return $results; - } - - - /* Use associative array to get fields array */ - function 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)]]; - } - - - - function _seek($row) - { - return false; - } - - function _fetch() - { - return @OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode); - } - - /* close() only needs to be called if you are worried about using too much memory while your script - is running. All associated result memory for the specified result identifier will automatically be freed. */ - - function _close() - { - if ($this->connection->_stmt === $this->_queryID) $this->connection->_stmt = false; - if (!empty($this->_refcursor)) { - OCIFreeCursor($this->_refcursor); - $this->_refcursor = false; - } - @OCIFreeStatement($this->_queryID); - $this->_queryID = false; - - } - - function MetaType($t,$len=-1) - { - if (is_object($t)) { - $fieldobj = $t; - $t = $fieldobj->type; - $len = $fieldobj->max_length; - } - switch (strtoupper($t)) { - case 'VARCHAR': - case 'VARCHAR2': - case 'CHAR': - case 'VARBINARY': - case 'BINARY': - case 'NCHAR': - case 'NVARCHAR': - case 'NVARCHAR2': - if (isset($this) && $len <= $this->blobSize) return 'C'; - - case 'NCLOB': - case 'LONG': - case 'LONG VARCHAR': - case 'CLOB': - return 'X'; - - case 'LONG RAW': - case 'LONG VARBINARY': - case 'BLOB': - return 'B'; - - case 'DATE': - return ($this->connection->datetime) ? 'T' : 'D'; - - - case 'TIMESTAMP': return 'T'; - - case 'INT': - case 'SMALLINT': - case 'INTEGER': - return 'I'; - - default: return 'N'; - } - } -} - -class ADORecordSet_ext_oci8 extends ADORecordSet_oci8 { - function ADORecordSet_ext_oci8($queryID,$mode=false) - { - if ($mode === false) { - global $ADODB_FETCH_MODE; - $mode = $ADODB_FETCH_MODE; - } - switch ($mode) - { - case ADODB_FETCH_ASSOC:$this->fetchMode = OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break; - case ADODB_FETCH_DEFAULT: - case ADODB_FETCH_BOTH:$this->fetchMode = OCI_NUM+OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break; - case ADODB_FETCH_NUM: - default: $this->fetchMode = OCI_NUM+OCI_RETURN_NULLS+OCI_RETURN_LOBS; break; - } - $this->adodbFetchMode = $mode; - $this->_queryID = $queryID; - } - - function MoveNext() - { - return adodb_movenext($this); - } -} -?> diff --git a/lib/adodb/drivers/adodb-oci8po.inc.php b/lib/adodb/drivers/adodb-oci8po.inc.php index 60a49a12ba..90be872f4a 100644 --- a/lib/adodb/drivers/adodb-oci8po.inc.php +++ b/lib/adodb/drivers/adodb-oci8po.inc.php @@ -1,6 +1,6 @@ GetOne($this->identitySQL); } - function RowLock($tables,$where,$flds='1 as ignore') + function RowLock($tables,$where,$col='1 as ignore') { if ($this->_autocommit) $this->BeginTrans(); - return $this->GetOne("select $flds from $tables where $where for update"); + return $this->GetOne("select $col from $tables where $where for update"); } function MetaTables($ttype=false,$showSchema=false, $qtable="%", $qschema="%") diff --git a/lib/adodb/drivers/adodb-odbc_mssql.inc.php b/lib/adodb/drivers/adodb-odbc_mssql.inc.php index 97f4cd02ef..c8e261b9f1 100644 --- a/lib/adodb/drivers/adodb-odbc_mssql.inc.php +++ b/lib/adodb/drivers/adodb-odbc_mssql.inc.php @@ -1,6 +1,6 @@ qstr($table); diff --git a/lib/adodb/drivers/adodb-odbc_oracle.inc.php b/lib/adodb/drivers/adodb-odbc_oracle.inc.php index 356082654f..9d2d527f4b 100644 --- a/lib/adodb/drivers/adodb-odbc_oracle.inc.php +++ b/lib/adodb/drivers/adodb-odbc_oracle.inc.php @@ -1,6 +1,6 @@ odbc_driver) { case ODB_DRIVER_MSSQL: diff --git a/lib/adodb/drivers/adodb-odbtp_unicode.inc.php b/lib/adodb/drivers/adodb-odbtp_unicode.inc.php index ad26c528bd..0e2e6768d5 100644 --- a/lib/adodb/drivers/adodb-odbtp_unicode.inc.php +++ b/lib/adodb/drivers/adodb-odbtp_unicode.inc.php @@ -1,6 +1,6 @@ fmtDate,$d).",'YYYY-MM-DD')"; + if (is_object($d)) $ds = $d->format($this->fmtDate); + else $ds = adodb_date($this->fmtDate,$d); + return 'TO_DATE('.$ds.",'YYYY-MM-DD')"; } // format and return date string in database timestamp format function DBTimeStamp($ts) { - if (is_string($ts)) $d = ADORecordSet::UnixTimeStamp($ts); - return 'TO_DATE('.adodb_date($this->fmtTimeStamp,$ts).",'RRRR-MM-DD, HH:MI:SS AM')"; + if (is_string($ts)) $ts = ADORecordSet::UnixTimeStamp($ts); + if (is_object($ts)) $ds = $ts->format($this->fmtDate); + else $ds = adodb_date($this->fmtTimeStamp,$ts); + return 'TO_DATE('.$ds.",'RRRR-MM-DD, HH:MI:SS AM')"; } @@ -286,9 +290,9 @@ class ADORecordset_oracle extends ADORecordSet { function _fetch($ignore_fields=false) { // should remove call by reference, but ora_fetch_into requires it in 4.0.3pl1 if ($this->fetchMode & ADODB_FETCH_ASSOC) - return @ora_fetch_into($this->_queryID,&$this->fields,ORA_FETCHINTO_NULLS|ORA_FETCHINTO_ASSOC); + return @ora_fetch_into($this->_queryID,$this->fields,ORA_FETCHINTO_NULLS|ORA_FETCHINTO_ASSOC); else - return @ora_fetch_into($this->_queryID,&$this->fields,ORA_FETCHINTO_NULLS); + return @ora_fetch_into($this->_queryID,$this->fields,ORA_FETCHINTO_NULLS); } /* close() only needs to be called if you are worried about using too much memory while your script diff --git a/lib/adodb/drivers/adodb-pdo.inc.php b/lib/adodb/drivers/adodb-pdo.inc.php index cdbe617edb..d88456f710 100644 --- a/lib/adodb/drivers/adodb-pdo.inc.php +++ b/lib/adodb/drivers/adodb-pdo.inc.php @@ -1,6 +1,6 @@ pdoDriver = $parentDriver; $parentDriver->_bindInputArray = true; - $parentDriver->hasTransactions = true; + $parentDriver->hasTransactions = false; // // should be set to false because of PDO SQLite driver not supporting changing autocommit mode $parentDriver->hasInsertID = true; } @@ -40,7 +41,7 @@ class ADODB_pdo_sqlite extends ADODB_pdo { { $parent = $this->pdoDriver; @($ver = array_pop($parent->GetCol("SELECT sqlite_version()"))); - @($end = array_pop($parent->GetCol("PRAGMA encoding"))); + @($enc = array_pop($parent->GetCol("PRAGMA encoding"))); $arr['version'] = $ver; $arr['description'] = 'SQLite '; @@ -143,7 +144,7 @@ class ADODB_pdo_sqlite extends ADODB_pdo { // mark newnham - function MetaColumns($tab,$normalize=true)) + function MetaColumns($tab,$normalize=true) { global $ADODB_FETCH_MODE; @@ -184,7 +185,19 @@ class ADODB_pdo_sqlite extends ADODB_pdo { function MetaTables($ttype=false,$showSchema=false,$mask=false) { $parent = $this->pdoDriver; - return $parent->GetCol($this->metaTablesSQL); - } + + if ($mask) { + $save = $this->metaTablesSQL; + $mask = $this->qstr(strtoupper($mask)); + $this->metaTablesSQL .= " AND name LIKE $mask"; + } + + $ret = $parent->GetCol($this->metaTablesSQL); + + if ($mask) { + $this->metaTablesSQL = $save; + } + return $ret; + } } ?> \ No newline at end of file diff --git a/lib/adodb/drivers/adodb-postgres.inc.php b/lib/adodb/drivers/adodb-postgres.inc.php index ffd885b33e..b4e69b685d 100644 --- a/lib/adodb/drivers/adodb-postgres.inc.php +++ b/lib/adodb/drivers/adodb-postgres.inc.php @@ -1,6 +1,6 @@ _connectionID, "begin ".$this->_transmode); } - function RowLock($tables,$where,$flds='1 as ignore') + function RowLock($tables,$where,$col='1 as ignore') { if (!$this->transCnt) $this->BeginTrans(); - return $this->GetOne("select $flds from $tables where $where for update"); + return $this->GetOne("select $col from $tables where $where for update"); } // returns true/false. @@ -459,7 +460,10 @@ select viewname,'V' from pg_views where viewname like $mask"; if (10 <= $len && $len <= 12) $date = 'date '.$date; else $date = 'timestamp '.$date; } - return "($date+interval'$dayFraction days')"; + + + return "($date+interval'".($dayFraction * 1440)." minutes')"; + #return "($date+interval'$dayFraction days')"; } @@ -661,7 +665,7 @@ WHERE (c2.relname=\'%s\' or c2.relname=lower(\'%s\'))'; if (strlen($db) == 0) $db = 'template1'; $db = adodb_addslashes($db); if ($str) { - $host = split(":", $str); + $host = explode(":", $str); if ($host[0]) $str = "host=".adodb_addslashes($host[0]); else $str = ''; if (isset($host[1])) $str .= " port=$host[1]"; @@ -1052,7 +1056,7 @@ class ADORecordSet_postgres64 extends ADORecordSet{ case 'INT4': case 'INT2': if (isset($fieldobj) && - empty($fieldobj->primary_key) && empty($fieldobj->unique)) return 'I'; + empty($fieldobj->primary_key) && (!$this->connection->uniqueIisR || empty($fieldobj->unique))) return 'I'; case 'OID': case 'SERIAL': diff --git a/lib/adodb/drivers/adodb-postgres7.inc.php b/lib/adodb/drivers/adodb-postgres7.inc.php index 63fc9a14c3..57fb9a632d 100644 --- a/lib/adodb/drivers/adodb-postgres7.inc.php +++ b/lib/adodb/drivers/adodb-postgres7.inc.php @@ -1,6 +1,6 @@ fetchMode !== false) $savem = $this->SetFetchMode(false); - $rs = $this->Execute("PRAGMA table_info('$tab')"); + $rs = $this->Execute("PRAGMA table_info('$table')"); if (isset($savem)) $this->SetFetchMode($savem); if (!$rs) { $ADODB_FETCH_MODE = $save; diff --git a/lib/adodb/drivers/adodb-sqlitepo.inc.php b/lib/adodb/drivers/adodb-sqlitepo.inc.php index a4daab7cc4..79d809ec63 100644 --- a/lib/adodb/drivers/adodb-sqlitepo.inc.php +++ b/lib/adodb/drivers/adodb-sqlitepo.inc.php @@ -1,6 +1,6 @@ _hastrans) $this->BeginTrans(); $tables = str_replace(',',' HOLDLOCK,',$tables); - return $this->GetOne("select $flds from $tables HOLDLOCK where $where"); + return $this->GetOne("select $col from $tables HOLDLOCK where $where"); } diff --git a/lib/adodb/drivers/adodb-sybase_ase.inc.php b/lib/adodb/drivers/adodb-sybase_ase.inc.php index ca6db057a5..13f7bdd5f9 100644 --- a/lib/adodb/drivers/adodb-sybase_ase.inc.php +++ b/lib/adodb/drivers/adodb-sybase_ase.inc.php @@ -1,6 +1,6 @@