]> git.mjollnir.org Git - moodle.git/commitdiff
Upgrading ADOdb to 4.11 ... there were lots of little bug fixes
authormoodler <moodler>
Fri, 30 Jan 2004 03:11:47 +0000 (03:11 +0000)
committermoodler <moodler>
Fri, 30 Jan 2004 03:11:47 +0000 (03:11 +0000)
115 files changed:
lib/adodb/adodb-csvlib.inc.php
lib/adodb/adodb-datadict.inc.php
lib/adodb/adodb-error.inc.php
lib/adodb/adodb-errorhandler.inc.php
lib/adodb/adodb-errorpear.inc.php
lib/adodb/adodb-exceptions.inc.php [new file with mode: 0644]
lib/adodb/adodb-iterator.inc.php [new file with mode: 0644]
lib/adodb/adodb-lib.inc.php
lib/adodb/adodb-pager.inc.php
lib/adodb/adodb-pear.inc.php
lib/adodb/adodb-perf.inc.php
lib/adodb/adodb-php4.inc.php [new file with mode: 0644]
lib/adodb/adodb-time.inc.php
lib/adodb/adodb.inc.php
lib/adodb/datadict/datadict-access.inc.php
lib/adodb/datadict/datadict-db2.inc.php
lib/adodb/datadict/datadict-generic.inc.php
lib/adodb/datadict/datadict-ibase.inc.php
lib/adodb/datadict/datadict-informix.inc.php
lib/adodb/datadict/datadict-mssql.inc.php
lib/adodb/datadict/datadict-mysql.inc.php
lib/adodb/datadict/datadict-oci8.inc.php
lib/adodb/datadict/datadict-postgres.inc.php
lib/adodb/datadict/datadict-sybase.inc.php
lib/adodb/docs-adodb.htm
lib/adodb/docs-datadict.htm
lib/adodb/docs-perf.htm
lib/adodb/docs-session.htm
lib/adodb/drivers/adodb-access.inc.php
lib/adodb/drivers/adodb-ado.inc.php
lib/adodb/drivers/adodb-ado_access.inc.php
lib/adodb/drivers/adodb-ado_mssql.inc.php
lib/adodb/drivers/adodb-borland_ibase.inc.php
lib/adodb/drivers/adodb-csv.inc.php
lib/adodb/drivers/adodb-db2.inc.php
lib/adodb/drivers/adodb-fbsql.inc.php
lib/adodb/drivers/adodb-firebird.inc.php
lib/adodb/drivers/adodb-ibase.inc.php
lib/adodb/drivers/adodb-informix.inc.php
lib/adodb/drivers/adodb-informix72.inc.php
lib/adodb/drivers/adodb-mssql.inc.php
lib/adodb/drivers/adodb-mssqlpo.inc.php
lib/adodb/drivers/adodb-mysql.inc.php
lib/adodb/drivers/adodb-mysqli.inc.php [new file with mode: 0644]
lib/adodb/drivers/adodb-mysqlt.inc.php
lib/adodb/drivers/adodb-oci8.inc.php
lib/adodb/drivers/adodb-oci805.inc.php
lib/adodb/drivers/adodb-oci8po.inc.php
lib/adodb/drivers/adodb-odbc.inc.php
lib/adodb/drivers/adodb-odbc_mssql.inc.php
lib/adodb/drivers/adodb-odbc_oracle.inc.php
lib/adodb/drivers/adodb-oracle.inc.php
lib/adodb/drivers/adodb-postgres.inc.php
lib/adodb/drivers/adodb-postgres64.inc.php
lib/adodb/drivers/adodb-postgres7.inc.php
lib/adodb/drivers/adodb-proxy.inc.php
lib/adodb/drivers/adodb-sapdb.inc.php
lib/adodb/drivers/adodb-sqlanywhere.inc.php
lib/adodb/drivers/adodb-sqlite.inc.php
lib/adodb/drivers/adodb-sybase.inc.php
lib/adodb/drivers/adodb-vfp.inc.php
lib/adodb/lang/adodb-ca.inc.php [new file with mode: 0644]
lib/adodb/lang/adodb-cn.inc.php [new file with mode: 0644]
lib/adodb/lang/adodb-de.inc.php [new file with mode: 0644]
lib/adodb/lang/adodb-fr.inc.php
lib/adodb/lang/adodb-it.inc.php
lib/adodb/license.txt
lib/adodb/perf/perf-db2.inc.php
lib/adodb/perf/perf-informix.inc.php
lib/adodb/perf/perf-mssql.inc.php
lib/adodb/perf/perf-mysql.inc.php
lib/adodb/perf/perf-oci8.inc.php
lib/adodb/perf/perf-postgres.inc.php
lib/adodb/pivottable.inc.php
lib/adodb/rsfilter.inc.php
lib/adodb/server.php
lib/adodb/session/adodb-compress-bzip2.php [new file with mode: 0644]
lib/adodb/session/adodb-compress-gzip.php [new file with mode: 0644]
lib/adodb/session/adodb-cryptsession.php [new file with mode: 0644]
lib/adodb/session/adodb-encrypt-mcrypt.php [new file with mode: 0644]
lib/adodb/session/adodb-encrypt-md5.php [new file with mode: 0644]
lib/adodb/session/adodb-encrypt-secret.php [new file with mode: 0644]
lib/adodb/session/adodb-sess.txt [new file with mode: 0644]
lib/adodb/session/adodb-session-clob.php [new file with mode: 0644]
lib/adodb/session/adodb-session.php [new file with mode: 0644]
lib/adodb/session/adodb-sessions.mysql.sql [new file with mode: 0644]
lib/adodb/session/adodb-sessions.oracle.clob.sql [new file with mode: 0644]
lib/adodb/session/adodb-sessions.oracle.sql [new file with mode: 0644]
lib/adodb/session/crypt.inc.php [new file with mode: 0644]
lib/adodb/tests/benchmark.php
lib/adodb/tests/client.php
lib/adodb/tests/test-datadict.php
lib/adodb/tests/test-pgblob.php [new file with mode: 0644]
lib/adodb/tests/test-php5.php [new file with mode: 0644]
lib/adodb/tests/test-xmlschema.php
lib/adodb/tests/test.php
lib/adodb/tests/test2.php
lib/adodb/tests/test3.php
lib/adodb/tests/test4.php
lib/adodb/tests/test5.php
lib/adodb/tests/test_rs_array.php [new file with mode: 0644]
lib/adodb/tests/testcache.php
lib/adodb/tests/testdatabases.inc.php
lib/adodb/tests/testgenid.php
lib/adodb/tests/testmssql.php
lib/adodb/tests/testoci8.php
lib/adodb/tests/testoci8cursor.php
lib/adodb/tests/testpaging.php
lib/adodb/tests/testpear.php
lib/adodb/tests/testsessions.php
lib/adodb/tests/tmssql.php
lib/adodb/tips_portable_sql.htm
lib/adodb/toexport.inc.php
lib/adodb/tohtml.inc.php
lib/adodb/tute.htm

index ba59b6bcaa8b40d0e3af557e6898a8d0451a7b83..37c46794cebed0c916f06158fa139331d05642e5 100644 (file)
@@ -3,7 +3,7 @@ global $ADODB_INCLUDED_CSV;
 $ADODB_INCLUDED_CSV = 1;\r
 \r
 /* \r
-  V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+  V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. See License.txt. \r
@@ -83,8 +83,8 @@ $ADODB_INCLUDED_CSV = 1;
 */\r
        function &csv2rs($url,&$err,$timeout=0)\r
        {\r
-               $fp = @fopen($url,'r');\r
                $err = false;\r
+               $fp = @fopen($url,'r');\r
                if (!$fp) {\r
                        $err = $url.' file/URL not found';\r
                        return false;\r
index 0c73094f245ef2a07357d1c6fa4579fad4f46e70..db9c2016dfa7a6a3d91f1e3e8010a6ad0d1196d1 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
 \r
 /**\r
-  V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+  V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
 */\r
 function Lens_ParseTest()\r
 {\r
-$str = "ACOL NUMBER(32,2) DEFAULT 'The \"cow\" (and Jim''s dog) jumps over the moon' PRIMARY, INTI INT AUTO DEFAULT 0";\r
+$str = "`zcol ACOL` NUMBER(32,2) DEFAULT 'The \"cow\" (and Jim''s dog) jumps over the moon' PRIMARY, INTI INT AUTO DEFAULT 0";\r
 print "<p>$str</p>";\r
 $a= Lens_ParseArgs($str);\r
 print "<pre>";\r
 print_r($a);\r
 print "</pre>";\r
 }\r
+\r
+if (!function_exists('ctype_alnum')) {\r
+       function ctype_alnum($text) {\r
+               return preg_match('/^[a-z0-9]*$/i', $text);\r
+       }\r
+}\r
+\r
 //Lens_ParseTest();\r
 \r
 /**\r
        Parse arguments, treat "text" (text) and 'text' as quotation marks.\r
        To escape, use "" or '' or ))\r
        \r
+       Will read in "abc def" sans quotes, as: abc def\r
+       Same with 'abc def'.\r
+       However if `abc def`, then will read in as `abc def`\r
+       \r
        @param endstmtchar    Character that indicates end of statement\r
        @param tokenchars     Include the following characters in tokens apart from A-Z and 0-9 \r
        @returns 2 dimensional array containing parsed tokens.\r
@@ -63,7 +74,9 @@ function Lens_ParseArgs($args,$endstmtchar=',',$tokenchars='_.-')
                        \r
                        $tokarr[] = $ch;\r
                        break;\r
-                       \r
+               \r
+               case '`':\r
+                       if ($intoken) $tokarr[] = $ch;\r
                case '(':\r
                case ')':       \r
                case '"':\r
@@ -98,6 +111,7 @@ function Lens_ParseArgs($args,$endstmtchar=',',$tokenchars='_.-')
                                $quoted = true;\r
                                $intoken = true;\r
                                $tokarr = array();\r
+                               if ($ch == '`') $tokarr[] = '`';\r
                        }\r
                        break;\r
                        \r
@@ -143,14 +157,14 @@ function Lens_ParseArgs($args,$endstmtchar=',',$tokenchars='_.-')
 class ADODB_DataDict {\r
        var $connection;\r
        var $debug = false;\r
-       var $dropTable = "DROP TABLE %s";\r
+       var $dropTable = 'DROP TABLE %s';\r
+       var $dropIndex = 'DROP INDEX %s';\r
        var $addCol = ' ADD';\r
        var $alterCol = ' ALTER COLUMN';\r
        var $dropCol = ' DROP COLUMN';\r
        var $schema = false;\r
        var $serverInfo = array();\r
        var $autoIncrement = false;\r
-       var $quote = '';\r
        var $dataProvider;\r
        var $blobSize = 100;    /// any varchar/char field this size or greater is treated as a blob\r
                                                        /// in other words, we use a text area for editting.\r
@@ -170,9 +184,9 @@ class ADODB_DataDict {
                return $this->connection->MetaTables();\r
        }\r
        \r
-       function &MetaColumns($tab)\r
+       function &MetaColumns($tab,$schema=false,$upper=true)\r
        {\r
-               return $this->connection->MetaColumns($tab);\r
+               return $this->connection->MetaColumns($tab,$schema,$upper);\r
        }\r
        \r
        function &MetaPrimaryKeys($tab,$owner=false,$intkey=false)\r
@@ -180,11 +194,34 @@ class ADODB_DataDict {
                return $this->connection->MetaPrimaryKeys($tab.$owner,$intkey);\r
        }\r
        \r
+       function &MetaIndexes($table, $primary = false, $owner = false)\r
+       {\r
+               return $this->connection->MetaIndexes($table, $primary, $owner);\r
+       }\r
+       \r
        function MetaType($t,$len=-1,$fieldobj=false)\r
        {\r
                return ADORecordSet::MetaType($t,$len,$fieldobj);\r
        }\r
        \r
+       function NameQuote($name)\r
+       {\r
+               if ( !is_object($this->connection) ) {\r
+                       return $name;\r
+               }\r
+               \r
+               $replace = $this->connection->nameQuote .'$1'. $this->connection->nameQuote;\r
+               return preg_replace('/^`([^`]+)`$/', $replace, $name);\r
+       }\r
+       \r
+       function TableName($name)\r
+       {\r
+               if ( $this->schema ) {\r
+                       return $this->NameQuote($this->schema) .'.'. $this->NameQuote($name);\r
+               }\r
+               return $this->NameQuote($name);\r
+       }\r
+       \r
        // Executes the sql array returned by GetTableSQL and GetIndexSQL\r
        function ExecuteSQLArray($sql, $continueOnError = true)\r
        {\r
@@ -231,9 +268,12 @@ class ADODB_DataDict {
        function CreateDatabase($dbname,$options=false)\r
        {\r
                $options = $this->_Options($options);\r
-               if (!preg_match('/^[a-z0-9A-Z_]*$/',$dbname)) $dbname = $this->quote.$dbname.$this->quote;\r
-               $s = 'CREATE DATABASE '.$dbname;\r
-               if (isset($options[$this->upperName])) $s .= ' '.$options[$this->upperName];\r
+               $sql = array();\r
+               \r
+               $s = 'CREATE DATABASE ' . $this->NameQuote($dbname);\r
+               if (isset($options[$this->upperName]))\r
+                       $s .= ' '.$options[$this->upperName];\r
+               \r
                $sql[] = $s;\r
                return $sql;\r
        }\r
@@ -243,8 +283,12 @@ class ADODB_DataDict {
        */\r
        function CreateIndexSQL($idxname, $tabname, $flds, $idxoptions = false)\r
        {\r
-               if ($this->schema) $tabname = $this->schema.'.'.$tabname;\r
-               return $this->_IndexSQL($idxname, $tabname, $flds, $this->_Options($idxoptions));\r
+               return $this->_IndexSQL($this->NameQuote($idxname), $this->TableName($tabname), $flds, $this->_Options($idxoptions));\r
+       }\r
+       \r
+       function DropIndexSQL ($idxname, $tabname = NULL)\r
+       {\r
+               return array(sprintf($this->dropIndex, $this->NameQuote($idxname)));\r
        }\r
        \r
        function SetSchema($schema)\r
@@ -253,44 +297,44 @@ class ADODB_DataDict {
        }\r
        \r
        function AddColumnSQL($tabname, $flds)\r
-       {       \r
-               if ($this->schema) $tabname = $this->schema.'.'.$tabname;\r
+       {\r
+               $tabname = $this->TableName ($tabname);\r
                $sql = array();\r
                list($lines,$pkey) = $this->_GenFields($flds);\r
+               $alter = 'ALTER TABLE ' . $tabname . ' ' . $this->addCol . ' ';\r
                foreach($lines as $v) {\r
-                       $sql[] = "ALTER TABLE $tabname $this->addCol $v";\r
+                       $sql[] = $alter . $v;\r
                }\r
                return $sql;\r
        }\r
        \r
        function AlterColumnSQL($tabname, $flds)\r
        {\r
-               if ($this->schema) $tabname = $this->schema.'.'.$tabname;\r
+               $tabname = $this->TableName ($tabname);\r
                $sql = array();\r
                list($lines,$pkey) = $this->_GenFields($flds);\r
-\r
+               $alter = 'ALTER TABLE ' . $tabname . ' ' . $this->alterCol . ' ';\r
                foreach($lines as $v) {\r
-                       $sql[] = "ALTER TABLE $tabname $this->alterCol $v";\r
+                       $sql[] = $alter . $v;\r
                }\r
                return $sql;\r
        }\r
        \r
        function DropColumnSQL($tabname, $flds)\r
        {\r
-               if ($this->schema) $tabname = $this->schema.'.'.$tabname;\r
+               $tabname = $this->TableName ($tabname);\r
                if (!is_array($flds)) $flds = explode(',',$flds);\r
                $sql = array();\r
+               $alter = 'ALTER TABLE ' . $tabname . ' ' . $this->dropCol . ' ';\r
                foreach($flds as $v) {\r
-                       $sql[] = "ALTER TABLE $tabname $this->dropCol $v";\r
+                       $sql[] = $alter . $v;\r
                }\r
                return $sql;\r
        }\r
        \r
        function DropTableSQL($tabname)\r
        {\r
-               if ($this->schema) $tabname = $this->schema.'.'.$tabname;\r
-               $sql[] = sprintf($this->dropTable,$tabname);\r
-               return $sql;\r
+               return array (sprintf($this->dropTable, $this->TableName($tabname)));\r
        }\r
        \r
        /*\r
@@ -299,11 +343,11 @@ class ADODB_DataDict {
        function CreateTableSQL($tabname, $flds, $tableoptions=false)\r
        {\r
                if (!$tableoptions) $tableoptions = array();\r
-       \r
+               \r
                list($lines,$pkey) = $this->_GenFields($flds);\r
                \r
                $taboptions = $this->_Options($tableoptions);\r
-               if ($this->schema) $tabname = $this->schema.'.'.$tabname;\r
+               $tabname = $this->TableName ($tabname);\r
                $sql = $this->_TableSQL($tabname,$lines,$pkey,$taboptions);\r
                \r
                $tsql = $this->_Triggers($tabname,$taboptions);\r
@@ -370,7 +414,9 @@ class ADODB_DataDict {
                                case 'NAME':    $fname = $v; break;\r
                                case '1':\r
                                case 'TYPE':    $ty = $v; $ftype = $this->ActualType(strtoupper($v)); break;\r
-                               case 'SIZE':    $dotat = strpos($v,'.');\r
+                               \r
+                               case 'SIZE':    \r
+                                                               $dotat = strpos($v,'.'); if ($dotat === false) $dotat = strpos($v,',');\r
                                                                if ($dotat === false) $fsize = $v;\r
                                                                else {\r
                                                                        $fsize = substr($v,0,$dotat);\r
@@ -399,6 +445,8 @@ class ADODB_DataDict {
                                return false;\r
                        }\r
                        \r
+                       $fname = $this->NameQuote($fname);\r
+                       \r
                        if (!strlen($ftype)) {\r
                                if ($this->debug) ADOConnection::outp("Undefined TYPE for field '$fname'");\r
                                return false;\r
@@ -456,7 +504,7 @@ class ADODB_DataDict {
        {\r
                if (strlen($fsize) && $ty != 'X' && $ty != 'B' && strpos($ftype,'(') === false) {\r
                        $ftype .= "(".$fsize;\r
-                       if ($fprec) $ftype .= ",".$fprec;\r
+                       if (strlen($fprec)) $ftype .= ",".$fprec;\r
                        $ftype .= ')';\r
                }\r
                return $ftype;\r
@@ -475,14 +523,28 @@ class ADODB_DataDict {
        \r
        function _IndexSQL($idxname, $tabname, $flds, $idxoptions)\r
        {\r
-               if (isset($idxoptions['REPLACE'])) $sql[] = "DROP INDEX $idxname";\r
-               if (isset($idxoptions['UNIQUE'])) $unique = ' UNIQUE';\r
-               else $unique = '';\r
+               $sql = array();\r
                \r
-               if (is_array($flds)) $flds = implode(', ',$flds);\r
-               $s = "CREATE$unique INDEX $idxname ON $tabname ";\r
-               if (isset($idxoptions[$this->upperName])) $s .= $idxoptions[$this->upperName];\r
-               $s .= "($flds)";\r
+               if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {\r
+                       $sql[] = sprintf ($this->dropIndex, $idxname);\r
+                       if ( isset($idxoptions['DROP']) )\r
+                               return $sql;\r
+               }\r
+               \r
+               if ( empty ($flds) ) {\r
+                       return $sql;\r
+               }\r
+               \r
+               $unique = isset($idxoptions['UNIQUE']) ? ' UNIQUE' : '';\r
+               \r
+               $s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname . ' ';\r
+               \r
+               if ( isset($idxoptions[$this->upperName]) )\r
+                       $s .= $idxoptions[$this->upperName];\r
+               \r
+               if ( is_array($flds) )\r
+                       $flds = implode(', ',$flds);\r
+               $s .= '(' . $flds . ')';\r
                $sql[] = $s;\r
                \r
                return $sql;\r
@@ -497,12 +559,15 @@ class ADODB_DataDict {
        {\r
                $sql = array();\r
                \r
-               if (isset($tableoptions['REPLACE'])) {\r
+               if (isset($tableoptions['REPLACE']) || isset ($tableoptions['DROP'])) {\r
                        $sql[] = sprintf($this->dropTable,$tabname);\r
                        if ($this->autoIncrement) {\r
-                               $sInc = $this->_DropAutoIncrement($tabname);                    \r
+                               $sInc = $this->_DropAutoIncrement($tabname);\r
                                if ($sInc) $sql[] = $sInc;\r
                        }\r
+                       if ( isset ($tableoptions['DROP']) ) {\r
+                               return $sql;\r
+                       }\r
                }\r
                $s = "CREATE TABLE $tabname (\n";\r
                $s .= implode(",\n", $lines);\r
@@ -557,15 +622,21 @@ own.
 */\r
        function ChangeTableSQL($tablename, $flds,$tableoptions=false)\r
        {\r
-               if ($this->schema) $tabname = $this->schema.'.'.$tablename;\r
-               else $tabname = $tablename;\r
+               $tabname = $this->TableName ($tablename);\r
                \r
                $conn = &$this->connection;\r
-               if (!$conn) return false;\r
+               if (!is_object ($conn)) {\r
+                       return false;\r
+               }\r
                \r
                $colarr = &$conn->MetaColumns($tabname);\r
-               if (!$colarr) return $this->CreateTableSQL($tablename,$flds,$tableoptions);\r
-               foreach($colarr as $col) $cols[strtoupper($col->name)] = " ALTER ";\r
+               if (!$colarr) {\r
+                       return $this->CreateTableSQL($tablename,$flds,$tableoptions);\r
+               }\r
+               \r
+               foreach($colarr as $col) {\r
+                       $cols[strtoupper($col->name)] = " ALTER ";\r
+               }\r
                \r
                $sql = array();\r
                list($lines,$pkey) = $this->_GenFields($flds);\r
index 7ecd7bba755a9431901e66b8dde0d796254baea8..f874caf922cd7844d5078f7282840cc3a64f84c5 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /** \r
- * @version V4.01 23 Oct 2003 (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+ * @version V4.11 27 Jan 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
  * Released under both BSD license and Lesser GPL library license. \r
  * Whenever there is any discrepancy between the two licenses, \r
  * the BSD license will take precedence. \r
@@ -94,12 +94,12 @@ function adodb_error_pg($errormsg)
             '/Relation [\"\'].*[\"\'] already exists|Cannot insert a duplicate key into (a )?unique index.*/'      => DB_ERROR_ALREADY_EXISTS,\r
             '/divide by zero$/'                     => DB_ERROR_DIVZERO,\r
             '/pg_atoi: error in .*: can\'t parse /' => DB_ERROR_INVALID_NUMBER,\r
-            '/ttribute [\"\'].*[\"\'] not found$|Relation [\"\'].*[\"\'] does not have attribute [\"\'].*[\"\']/' => DB_ERROR_NOSUCHFIELD,\r
+            '/ttribute [\"\'].*[\"\'] not found|Relation [\"\'].*[\"\'] does not have attribute [\"\'].*[\"\']/' => DB_ERROR_NOSUCHFIELD,\r
             '/parser: parse error at or near \"/'   => DB_ERROR_SYNTAX,\r
             '/referential integrity violation/'     => DB_ERROR_CONSTRAINT\r
         );\r
-   \r
-    foreach ($error_regexps as $regexp => $code) {\r
+       reset($error_regexps);\r
+    while (list($regexp,$code) = each($error_regexps)) {\r
         if (preg_match($regexp, $errormsg)) {\r
             return $code;\r
         }\r
@@ -190,6 +190,7 @@ static $MAP = array(
 function adodb_error_oci8()\r
 {\r
 static $MAP = array(\r
+                        1 => DB_ERROR_ALREADY_EXISTS,\r
             900 => DB_ERROR_SYNTAX,\r
             904 => DB_ERROR_NOSUCHFIELD,\r
             923 => DB_ERROR_SYNTAX,\r
@@ -199,7 +200,7 @@ static $MAP = array(
             1722 => DB_ERROR_INVALID_NUMBER,\r
             2289 => DB_ERROR_NOSUCHTABLE,\r
             2291 => DB_ERROR_CONSTRAINT,\r
-            2449 => DB_ERROR_CONSTRAINT,\r
+            2449 => DB_ERROR_CONSTRAINT\r
         );\r
           \r
        return $MAP;\r
index c0489c9ae2533af40006920b0a4c5d94529e9cc1..f57263f0c1d22644261e491e4b36f18ca0ded2f0 100644 (file)
@@ -1,9 +1,9 @@
 <?php\r
 /**\r
- * @version V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+ * @version V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
  * Released under both BSD license and Lesser GPL library license.\r
-  Whenever there is any discrepancy between the two licenses,\r
-  the BSD license will take precedence.\r
* Whenever there is any discrepancy between the two licenses,\r
* the BSD license will take precedence.\r
  *\r
  * Set tabs to 4 for best viewing.\r
  *\r
@@ -16,7 +16,7 @@ if (!defined('ADODB_ERROR_HANDLER_TYPE')) define('ADODB_ERROR_HANDLER_TYPE',E_US
 \r
 define('ADODB_ERROR_HANDLER','ADODB_Error_Handler');\r
 \r
-  /**\r
+/**\r
 * Default Error Handler. This will be called with the following params\r
 *\r
 * @param $dbms         the RDBMS you are connecting to\r
@@ -24,8 +24,9 @@ define('ADODB_ERROR_HANDLER','ADODB_Error_Handler');
 * @param $errno                the native error number from the database\r
 * @param $errmsg       the native error msg from the database\r
 * @param $p1           $fn specific parameter - see below\r
-* @param $P2           $fn specific parameter - see below\r
-       */\r
+* @param $p2           $fn specific parameter - see below\r
+* @param $thisConn     $current connection object - can be false if no connection object created\r
+*/\r
 function ADODB_Error_Handler($dbms, $fn, $errno, $errmsg, $p1, $p2, &$thisConnection)\r
 {\r
        if (error_reporting() == 0) return; // obey @ protocol\r
index 66dc2b839bc9503b6ac87d2bc5b16abee0fd8e8c..c83f73334a19e71bc9b46d6d9f95d829b09d6565 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /** \r
- * @version V4.01 23 Oct 2003 (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+ * @version V4.11 27 Jan 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
  * Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
diff --git a/lib/adodb/adodb-exceptions.inc.php b/lib/adodb/adodb-exceptions.inc.php
new file mode 100644 (file)
index 0000000..0e70ac1
--- /dev/null
@@ -0,0 +1,77 @@
+<?php\r
+\r
+/**\r
+ * @version V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+ * Released under both BSD license and Lesser GPL library license.\r
+ * Whenever there is any discrepancy between the two licenses,\r
+ * the BSD license will take precedence.\r
+ *\r
+ * Set tabs to 4 for best viewing.\r
+ *\r
+ * Latest version is available at http://php.weblogs.com\r
+ *\r
+ * Exception-handling code using PHP5 exceptions (try-catch-throw).\r
+ */\r
+       \r
+if (!defined('ADODB_ERROR_HANDLER_TYPE')) define('ADODB_ERROR_HANDLER_TYPE',E_USER_ERROR); \r
+define('ADODB_ERROR_HANDLER','adodb_throw');\r
+\r
+class ADODB_Exception extends Exception {\r
+var $dbms;\r
+var $fn;\r
+var $sql = '';\r
+var $params = '';\r
+var $host = '';\r
+var $database = '';\r
+\r
+       function __construct($dbms, $fn, $errno, $errmsg, $p1, $p2, $thisConnection)\r
+       {\r
+               switch($fn) {\r
+               case 'EXECUTE':\r
+                       $this->sql = $p1;\r
+                       $this->params = $p2;\r
+                       $s = "$dbms error: [$errno: $errmsg] in $fn(\"$p1\")\n";\r
+                       break;\r
+       \r
+               case 'PCONNECT':\r
+               case 'CONNECT':\r
+                       $user = $thisConnection->user;\r
+                       $s = "$dbms error: [$errno: $errmsg] in $fn($p1, '$user', '****', $p2)\n";\r
+                       break;\r
+               default:\r
+                       $s = "$dbms error: [$errno: $errmsg] in $fn($p1, $p2)\n";\r
+                       break;\r
+               }\r
+       \r
+               $this->dbms = $dbms;\r
+               $this->host = $thisConnection->host;\r
+               $this->database = $thisConnection->database;\r
+               $this->fn = $fn;\r
+               $this->msg = $errmsg;\r
+                               \r
+               parent::__construct($s,$errno);\r
+       }\r
+}\r
+\r
+/**\r
+* Default Error Handler. This will be called with the following params\r
+*\r
+* @param $dbms         the RDBMS you are connecting to\r
+* @param $fn           the name of the calling function (in uppercase)\r
+* @param $errno                the native error number from the database\r
+* @param $errmsg       the native error msg from the database\r
+* @param $p1           $fn specific parameter - see below\r
+* @param $P2           $fn specific parameter - see below\r
+*/\r
+\r
+function adodb_throw($dbms, $fn, $errno, $errmsg, $p1, $p2, $thisConnection)\r
+{\r
+global $ADODB_EXCEPTION;\r
+\r
+       if (is_string($ADODB_EXCEPTION)) $errfn = $ADODB_EXCEPTION;\r
+       else $errfn = 'ADODB_EXCEPTION';\r
+       throw new $errfn($dbms, $fn, $errno, $errmsg, $p1, $p2, $thisConnection);\r
+}\r
+\r
+\r
+?>
\ No newline at end of file
diff --git a/lib/adodb/adodb-iterator.inc.php b/lib/adodb/adodb-iterator.inc.php
new file mode 100644 (file)
index 0000000..1817fad
--- /dev/null
@@ -0,0 +1,56 @@
+<?php\r
+\r
+/*\r
+  V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+  Released under both BSD license and Lesser GPL library license. \r
+  Whenever there is any discrepancy between the two licenses, \r
+  the BSD license will take precedence.\r
+  \r
+  Set tabs to 4.\r
+  \r
+  PHP5 Iterator Class:\r
+  \r
+               $rs = $db->Execute("select * from adoxyz");\r
+               foreach($rs as $k => $v) {\r
+                       echo $k; print_r($v); echo "<br>";\r
+               }\r
+ */\r
\r
+class ADODB_Iterator implements Iterator {\r
+\r
+    private $rs;\r
+\r
+    function __construct($rs) \r
+       {\r
+        $this->rs = $rs;\r
+    }\r
+    function rewind() \r
+       {\r
+        $this->rs->MoveFirst();\r
+    }\r
+    function hasMore() \r
+       {\r
+        return !$this->rs->EOF;\r
+    }\r
+    function key() \r
+       {\r
+        return $this->rs->_currentRow;\r
+    }\r
+    function current() \r
+       {\r
+        return $this->rs->fields;\r
+    }\r
+    function next() \r
+       {\r
+        $this->rs->MoveNext();\r
+    }\r
+}\r
+\r
+\r
+class ADODB_BASE_RS implements IteratorAggregate {\r
+    function getIterator() {\r
+        return new ADODB_Iterator($this);\r
+    }\r
+} \r
+\r
+?>
\ No newline at end of file
index 7720ee1265624a8d9fc6c881d43bd7d193f2606d..1c8d360d519fadb77ce747b9bf13fee7a3fbce2d 100644 (file)
@@ -4,7 +4,7 @@ global $ADODB_INCLUDED_LIB;
 $ADODB_INCLUDED_LIB = 1;\r
 \r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. See License.txt. \r
@@ -19,7 +19,7 @@ V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights rese
 function _array_change_key_case($an_array)\r
 {\r
        if (is_array($an_array)) {\r
-       foreach($an_array as $key => $value)\r
+               foreach($an_array as $key=>$value)\r
                $new_array[strtoupper($key)] = $value;\r
 \r
                return $new_array;\r
@@ -28,6 +28,75 @@ function _array_change_key_case($an_array)
        return $an_array;\r
 }\r
 \r
+function _adodb_replace(&$zthis, $table, $fieldArray, $keyCol, $autoQuote, $has_autoinc)\r
+{\r
+               if (count($fieldArray) == 0) return 0;\r
+               $first = true;\r
+               $uSet = '';\r
+               \r
+               if (!is_array($keyCol)) {\r
+                       $keyCol = array($keyCol);\r
+               }\r
+               foreach($fieldArray as $k => $v) {\r
+                       if ($autoQuote && !is_numeric($v) and strncmp($v,"'",1) !== 0 and strcasecmp($v,'null')!=0) {\r
+                               $v = $zthis->qstr($v);\r
+                               $fieldArray[$k] = $v;\r
+                       }\r
+                       if (in_array($k,$keyCol)) continue; // skip UPDATE if is key\r
+                       \r
+                       if ($first) {\r
+                               $first = false;                 \r
+                               $uSet = "$k=$v";\r
+                       } else\r
+                               $uSet .= ",$k=$v";\r
+               }\r
+                \r
+               $where = false;\r
+               foreach ($keyCol as $v) {\r
+                       if ($where) $where .= " and $v=$fieldArray[$v]";\r
+                       else $where = "$v=$fieldArray[$v]";\r
+               }\r
+               \r
+               if ($uSet && $where) {\r
+                       $update = "UPDATE $table SET $uSet WHERE $where";\r
+                       \r
+                       $rs = $zthis->Execute($update);\r
+                       if ($rs) {\r
+                               if ($zthis->poorAffectedRows) {\r
+                               /*\r
+                                The Select count(*) wipes out any errors that the update would have returned. \r
+                               http://phplens.com/lens/lensforum/msgs.php?id=5696\r
+                               */\r
+                                       if ($zthis->ErrorNo()<>0) return 0;\r
+                                       \r
+                               # affected_rows == 0 if update field values identical to old values\r
+                               # for mysql - which is silly. \r
+                       \r
+                                       $cnt = $zthis->GetOne("select count(*) from $table where $where");\r
+                                       if ($cnt > 0) return 1; // record already exists\r
+                               } else\r
+                                        if (($zthis->Affected_Rows()>0)) return 1;\r
+                       }\r
+               }\r
+       //      print "<p>Error=".$this->ErrorNo().'<p>';\r
+               $first = true;\r
+               foreach($fieldArray as $k => $v) {\r
+                       if ($has_autoinc && in_array($k,$keyCol)) continue; // skip autoinc col\r
+                       \r
+                       if ($first) {\r
+                               $first = false;                 \r
+                               $iCols = "$k";\r
+                               $iVals = "$v";\r
+                       } else {\r
+                               $iCols .= ",$k";\r
+                               $iVals .= ",$v";\r
+                       }                               \r
+               }\r
+               $insert = "INSERT INTO $table ($iCols) VALUES ($iVals)"; \r
+               $rs = $zthis->Execute($insert);\r
+               return ($rs) ? 2 : 0;\r
+}\r
+\r
 // Requires $ADODB_FETCH_MODE = ADODB_FETCH_NUM\r
 function _adodb_getmenu(&$zthis, $name,$defstr='',$blank1stItem=true,$multiple=false,\r
                        $size=0, $selectAttr='',$compareFields0=true)\r
@@ -138,9 +207,12 @@ function _adodb_getcount(&$zthis, $sql,$inputarr=false,$secs2cache=0)
                if ($qryRecs !== false) return $qryRecs;\r
        }\r
        \r
+       //--------------------------------------------\r
        // query rewrite failed - so try slower way...\r
+       \r
+       // strip off unneeded ORDER BY\r
        $rewritesql = preg_replace('/(\sORDER\s+BY\s.*)/is','',$sql); \r
-       $rstest = &$zthis->Execute($rewritesql);\r
+       $rstest = &$zthis->Execute($rewritesql,$inputarr);\r
        if ($rstest) {\r
                $qryRecs = $rstest->RecordCount();\r
                if ($qryRecs == -1) { \r
@@ -400,79 +472,78 @@ function _adodb_getinsertsql(&$zthis,&$rs,$arrFields,$magicq=false)
        $values = '';\r
        $fields = '';\r
        $arrFields = _array_change_key_case($arrFields);\r
+       \r
        if (!$rs) {\r
-                       printf(ADODB_BAD_RS,'GetInsertSQL');\r
-                       return false;\r
-               }\r
+               printf(ADODB_BAD_RS,'GetInsertSQL');\r
+               return false;\r
+       }\r
 \r
-               $fieldInsertedCount = 0;\r
-       \r
-               \r
-               // Loop through all of the fields in the recordset\r
-               for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++) {\r
+       $fieldInsertedCount = 0;\r
 \r
-                       // Get the field from the recordset\r
-                       $field = $rs->FetchField($i);\r
-                       // If the recordset field is one\r
-                       // of the fields passed in then process.\r
-                       $upperfname = strtoupper($field->name);\r
-                       if (adodb_key_exists($upperfname,$arrFields)) {\r
-       \r
-                               // Set the counter for the number of fields that will be inserted.\r
-                               $fieldInsertedCount++;\r
+       // Loop through all of the fields in the recordset\r
+       for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++) {\r
 \r
-                               // Get the name of the fields to insert\r
-                               $fields .= $field->name . ", ";\r
-                               \r
-                               $mt = $rs->MetaType($field->type);\r
-                               \r
-                               // "mike" <mike@partner2partner.com> patch and "Ryan Bailey" <rebel@windriders.com> \r
-                               //PostgreSQL uses a 't' or 'f' and therefore needs to be processed as a string ('C') type field.\r
-                               if ((strncmp($zthis->databaseType,"postgres",8) === 0) && ($mt == "L")) $mt = "C";\r
-\r
-                               // Based on the datatype of the field\r
-                               // Format the value properly for the database\r
-                               if ((defined('ADODB_FORCE_NULLS') && is_null($arrFields[$upperfname])) || $arrFields[$upperfname] === 'null') \r
-                                               $values .= "null, ";\r
-                               else            \r
-                               switch($mt) {\r
-                                       case "C":\r
-                                       case "X":\r
-                                       case 'B':\r
-                                               $values .= $zthis->qstr($arrFields[$upperfname],$magicq) . ", ";\r
-                                               break;\r
-                                       case "D":\r
-                                               $values .= $zthis->DBDate($arrFields[$upperfname]) . ", ";\r
-                                               break;\r
-                                       case "T":\r
-                                               $values .= $zthis->DBTimeStamp($arrFields[$upperfname]) . ", ";\r
-                                               break;\r
-                                       default:\r
-                                               $val = $arrFields[$upperfname];\r
-                                               if (!is_numeric($val)) $val = (float) $val;\r
-                                               $values .= $val . ", ";\r
-                                               break;\r
-                               };\r
-                       };\r
-               };\r
+               // Get the field from the recordset\r
+               $field = $rs->FetchField($i);\r
+               // If the recordset field is one\r
+               // of the fields passed in then process.\r
+               $upperfname = strtoupper($field->name);\r
+               if (adodb_key_exists($upperfname,$arrFields)) {\r
 \r
-               // If there were any inserted fields then build the rest of the insert query.\r
-               if ($fieldInsertedCount > 0) {\r
-                       // Get the table name from the existing query.\r
-                       preg_match("/FROM\s+".ADODB_TABLE_REGEX."/is", $rs->sql, $tableName);\r
+                       // Set the counter for the number of fields that will be inserted.\r
+                       $fieldInsertedCount++;\r
+\r
+                       // Get the name of the fields to insert\r
+                       $fields .= $field->name . ", ";\r
+                       \r
+                       $mt = $rs->MetaType($field->type);\r
+                       \r
+                       // "mike" <mike@partner2partner.com> patch and "Ryan Bailey" <rebel@windriders.com> \r
+                       //PostgreSQL uses a 't' or 'f' and therefore needs to be processed as a string ('C') type field.\r
+                       if ((strncmp($zthis->databaseType,"postgres",8) === 0) && ($mt == "L")) $mt = "C";\r
+\r
+                       // Based on the datatype of the field\r
+                       // Format the value properly for the database\r
+                       if ((defined('ADODB_FORCE_NULLS') && is_null($arrFields[$upperfname])) || $arrFields[$upperfname] === 'null') \r
+                                       $values .= "null, ";\r
+                       else            \r
+                       switch($mt) {\r
+                               case "C":\r
+                               case "X":\r
+                               case 'B':\r
+                                       $values .= $zthis->qstr($arrFields[$upperfname],$magicq) . ", ";\r
+                                       break;\r
+                               case "D":\r
+                                       $values .= $zthis->DBDate($arrFields[$upperfname]) . ", ";\r
+                                       break;\r
+                               case "T":\r
+                                       $values .= $zthis->DBTimeStamp($arrFields[$upperfname]) . ", ";\r
+                                       break;\r
+                               default:\r
+                                       $val = $arrFields[$upperfname];\r
+                                       if (!is_numeric($val)) $val = (float) $val;\r
+                                       $values .= $val . ", ";\r
+                                       break;\r
+                       };\r
+               };\r
+       };\r
 \r
-                       // Strip off the comma and space on the end of both the fields\r
-                       // and their values.\r
-                       $fields = substr($fields, 0, -2);\r
-                       $values = substr($values, 0, -2);\r
+       // If there were any inserted fields then build the rest of the insert query.\r
+       if ($fieldInsertedCount <= 0)  return false;\r
+       \r
+       // Get the table name from the existing query.\r
+       preg_match("/FROM\s+".ADODB_TABLE_REGEX."/is", $rs->sql, $tableName);\r
 \r
-                       // Append the fields and their values to the insert query.\r
-                       $insertSQL = "INSERT INTO " . $tableName[1] . " ( $fields ) VALUES ( $values )";\r
+       // Strip off the comma and space on the end of both the fields\r
+       // and their values.\r
+       $fields = substr($fields, 0, -2);\r
+       $values = substr($values, 0, -2);\r
 \r
-                       return $insertSQL;\r
+       // Append the fields and their values to the insert query.\r
+       $insertSQL = "INSERT INTO " . $tableName[1] . " ( $fields ) VALUES ( $values )";\r
 \r
-               } else {\r
-                       return false;\r
-               };\r
+       return $insertSQL;\r
 }\r
+\r
+\r
 ?>
\ No newline at end of file
index e96c5497d12078cf3b2c2644c70b891eaf2b9510..ebff53faf125881cf97aee33d90f2764482c1124 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /*\r
-       V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+       V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
          Released under both BSD license and Lesser GPL library license. \r
          Whenever there is any discrepancy between the two licenses, \r
          the BSD license will take precedence. \r
index fa272fc1aab6eee16f49564792838e6c54ac50da..3c97dc5c16ef0f486cb9cecc124f9c9f4b21eacc 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /** \r
- * @version V4.01 23 Oct 2003 (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+ * @version V4.11 27 Jan 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
  * Released under both BSD license and Lesser GPL library license. \r
  * Whenever there is any discrepancy between the two licenses, \r
  * the BSD license will take precedence. \r
@@ -175,7 +175,7 @@ class DB
                if($persist) $ok = $obj->PConnect($dsninfo['hostspec'], $dsninfo['username'],$dsninfo['password'],$dsninfo['database']);\r
                else  $ok = $obj->Connect($dsninfo['hostspec'], $dsninfo['username'],$dsninfo['password'],$dsninfo['database']);\r
                \r
-               if (!$ok) return ADODB_PEAR_Error();\r
+               if (!$ok) $obj = ADODB_PEAR_Error();\r
                return $obj;\r
        }\r
 \r
index bedd98f8124b0c23ec16a2c49f7b1ceceaa06baf..9c0efd24d79f83d1f30bf9b7e1c04f5ffe577ea1 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. See License.txt. \r
@@ -19,6 +19,7 @@ V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights rese
 if (!defined(ADODB_DIR)) include_once(dirname(__FILE__).'/adodb.inc.php');\r
 include_once(ADODB_DIR.'/tohtml.inc.php');\r
 \r
+\r
 /* return microtime value as a float */\r
 function adodb_microtime()\r
 {\r
@@ -32,6 +33,7 @@ function& adodb_log_sql(&$conn,$sql,$inputarr)
 {\r
 global $HTTP_SERVER_VARS;\r
        \r
+    $perf_table = adodb_perf::table();\r
        $conn->fnExecute = false;\r
        $t0 = microtime();\r
        $rs =& $conn->Execute($sql,$inputarr);\r
@@ -58,8 +60,12 @@ global $HTTP_SERVER_VARS;
                        $tracer = '';\r
                        $errM = '';\r
                        $errN = 0;\r
-                       $conn->lastInsID = $conn->Insert_ID();\r
-               \r
+                       $dbg = $conn->debug;\r
+                       $conn->debug = false;\r
+                       if (!is_object($rs) || $rs->dataProvider == 'empty') \r
+                               $conn->_affected = $conn->affected_rows(true);\r
+                       $conn->lastInsID = @$conn->Insert_ID();\r
+                       $conn->debug = $dbg;\r
                }\r
                if (isset($HTTP_SERVER_VARS['HTTP_HOST'])) {\r
                        $tracer .= '<br>'.$HTTP_SERVER_VARS['HTTP_HOST'];\r
@@ -89,7 +95,7 @@ global $HTTP_SERVER_VARS;
                $conn->debug = 0;\r
                \r
                if ($conn->dataProvider == 'oci8' && $dbT != 'oci8po') {\r
-                       $isql = "insert into adodb_logsql values($conn->sysTimeStamp,:b,:c,:d,:e,:f)";\r
+                       $isql = "insert into $perf_table values($conn->sysTimeStamp,:b,:c,:d,:e,:f)";\r
                } else if ($dbT == 'odbc_mssql' || $dbT == 'informix') {\r
                        $timer = $arr['f'];\r
                        if ($dbT == 'informix') $sql2 = substr($sql2,0,230);\r
@@ -99,13 +105,12 @@ global $HTTP_SERVER_VARS;
                        $params = $conn->qstr($arr['d']);\r
                        $tracer = $conn->qstr($arr['e']);\r
                        \r
-                       $isql = "insert into adodb_logsql (created,sql0,sql1,params,tracer,timer) values($conn->sysTimeStamp,$sql1,$sql2,$params,$tracer,$timer)";\r
+                       $isql = "insert into $perf_table (created,sql0,sql1,params,tracer,timer) values($conn->sysTimeStamp,$sql1,$sql2,$params,$tracer,$timer)";\r
                        if ($dbT == 'informix') $isql = str_replace(chr(10),' ',$isql);\r
                        $arr = false;\r
                } else {\r
-                       $isql = "insert into adodb_logsql (created,sql0,sql1,params,tracer,timer) values( $conn->sysTimeStamp,?,?,?,?,?)";\r
+                       $isql = "insert into $perf_table (created,sql0,sql1,params,tracer,timer) values( $conn->sysTimeStamp,?,?,?,?,?)";\r
                }\r
-               $conn->_affected = $conn->affected_rows(true);\r
                $ok = $conn->Execute($isql,$arr);\r
                $conn->debug = $saved;\r
                \r
@@ -118,7 +123,7 @@ global $HTTP_SERVER_VARS;
                        if ($perf) {\r
                                if ($perf->CreateLogTable()) $ok = $conn->Execute($isql,$arr);\r
                        } else {\r
-                               $ok = $conn->Execute("create table adodb_logsql (\r
+                               $ok = $conn->Execute("create table $perf_table (\r
                                created varchar(50),\r
                                sql0 varchar(250), \r
                                sql1 varchar(4000),\r
@@ -165,7 +170,18 @@ class adodb_perf {
        var $explain = true;\r
        var $helpurl = "<a href=http://phplens.com/adodb/reference.functions.fnexecute.and.fncacheexecute.properties.html#logsql>LogSQL help</a>";\r
        var $createTableSQL = false;\r
+       var $maxLength = 2000;\r
        \r
+    // Sets the tablename to be used            \r
+    function table($newtable = false)\r
+    {\r
+        static $_table;\r
+\r
+        if (!empty($newtable))  $_table = $newtable;\r
+               if (empty($_table)) $_table = 'adodb_logsql';\r
+        return $_table;\r
+    }\r
+\r
        // returns array with info to calculate CPU Load\r
        function _CPULoad()\r
        {\r
@@ -285,10 +301,14 @@ Committed_AS:   348732 kB
        \r
        function Tracer($sql)\r
        {\r
+        $perf_table = adodb_perf::table();\r
+               $saveE = $this->conn->fnExecute;\r
+               $this->conn->fnExecute = false;\r
+                       \r
                $sqlq = $this->conn->qstr($sql);\r
                $arr = $this->conn->GetArray(\r
 "select count(*),tracer \r
-       from adodb_logsql where sql1=$sqlq \r
+       from $perf_table where sql1=$sqlq \r
        group by tracer\r
        order by 1 desc");\r
                $s = '';\r
@@ -298,11 +318,17 @@ Committed_AS:   348732 kB
                                $s .= sprintf("%4d",$k[0]).' &nbsp; '.strip_tags($k[1]).'<br>';\r
                        }\r
                }\r
+               $this->conn->fnExecute = $saveE;\r
                return $s;\r
        }\r
 \r
-       function Explain($sql)\r
-       {\r
+       /* \r
+               Explain Plan for $sql.\r
+               If only a snippet of the $sql is passed in, then $partial will hold the crc32 of the \r
+                       actual sql.\r
+       */\r
+       function Explain($sql,$partial=false)\r
+       {       \r
                return false;\r
        }\r
        \r
@@ -314,7 +340,8 @@ Committed_AS:   348732 kB
                $s = '<h3>Invalid SQL</h3>';\r
                $saveE = $this->conn->fnExecute;\r
                $this->conn->fnExecute = false;\r
-               $rs =& $this->conn->SelectLimit("select distinct count(*),sql1,tracer as error_msg from adodb_logsql where tracer like 'ERROR:%' group by sql1,tracer order by 1 desc",$numsql);//,$numsql);\r
+        $perf_table = adodb_perf::table();\r
+               $rs =& $this->conn->SelectLimit("select distinct count(*),sql1,tracer as error_msg from $perf_table where tracer like 'ERROR:%' group by sql1,tracer order by 1 desc",$numsql);//,$numsql);\r
                $this->conn->fnExecute = $saveE;\r
                if ($rs) {\r
                        $s .= rs2html($rs,false,false,false,false);\r
@@ -323,6 +350,7 @@ Committed_AS:   348732 kB
                \r
                return $s;\r
        }\r
+\r
        \r
        /*\r
                This script identifies the longest running SQL\r
@@ -331,11 +359,13 @@ Committed_AS:   348732 kB
        {\r
                global $ADODB_FETCH_MODE,$HTTP_GET_VARS;\r
                \r
+            $perf_table = adodb_perf::table();\r
                        $saveE = $this->conn->fnExecute;\r
                        $this->conn->fnExecute = false;\r
                        \r
                        if (isset($HTTP_GET_VARS['exps']) && isset($HTTP_GET_VARS['sql'])) {\r
-                               echo "<a name=explain></a>".$this->Explain($HTTP_GET_VARS['sql'])."\n";\r
+                               $partial = !empty($HTTP_GET_VARS['part']);\r
+                               echo "<a name=explain></a>".$this->Explain($HTTP_GET_VARS['sql'],$partial)."\n";\r
                        }\r
                        \r
                        if (isset($HTTP_GET_VARS['sql'])) return;\r
@@ -346,7 +376,7 @@ Committed_AS:   348732 kB
                        //$this->conn->debug=1;\r
                        $rs =& $this->conn->SelectLimit(\r
                        "select avg(timer) as avg_timer,$sql1,count(*),max(timer) as max_timer,min(timer) as min_timer\r
-                               from adodb_logsql\r
+                               from $perf_table\r
                                where {$this->conn->upperCase}({$this->conn->substr}(sql0,1,5)) not in ('DROP ','INSER','COMMI','CREAT')\r
                                and (tracer is null or tracer not like 'ERROR:%')\r
                                group by sql1\r
@@ -358,14 +388,19 @@ Committed_AS:   348732 kB
                        $s = "<h3>Suspicious SQL</h3>\r
 <font size=1>The following SQL have high average execution times</font><br>\r
 <table border=1 bgcolor=white><tr><td><b>Avg Time</b><td><b>Count</b><td><b>SQL</b><td><b>Max</b><td><b>Min</b></tr>\n";\r
+                       $max = $this->maxLength;\r
                        while (!$rs->EOF) {\r
-                               $sql = trim($rs->fields[1]);\r
-                               \r
-                               $prefix = "<a target=sql".rand()." href=\"?hidem=1&exps=1&sql=".rawurlencode($sql)."&x#explain\">";\r
+                               $sql = $rs->fields[1];\r
+                               $raw = urlencode($sql);\r
+                               if (strlen($raw)>$max-100) {\r
+                                       $sql2 = substr($sql,0,$max-500);\r
+                                       $raw = urlencode($sql2).'&part='.crc32($sql);\r
+                               }\r
+                               $prefix = "<a target=sql".rand()." href=\"?hidem=1&exps=1&sql=".$raw."&x#explain\">";\r
                                $suffix = "</a>";\r
-                               if ($this->explain == false || strlen($prefix)>2000) {\r
+                               if ($this->explain == false || strlen($prefix)>$max) {\r
+                                       $suffix = ' ... <i>String too long for GET parameter: '.strlen($prefix).'</i>';\r
                                        $prefix = '';\r
-                                       $suffix = '';\r
                                }\r
                                $s .= "<tr><td>".round($rs->fields[0],6)."<td align=right>".$rs->fields[2]."<td><font size=-1>".$prefix.htmlspecialchars($sql).$suffix."</font>".\r
                                        "<td>".$rs->fields[3]."<td>".$rs->fields[4]."</tr>";\r
@@ -401,11 +436,13 @@ Committed_AS:   348732 kB
        {\r
                global $HTTP_GET_VARS,$ADODB_FETCH_MODE;\r
                \r
+            $perf_table = adodb_perf::table();\r
                        $saveE = $this->conn->fnExecute;\r
                        $this->conn->fnExecute = false;\r
                        \r
                        if (isset($HTTP_GET_VARS['expe']) && isset($HTTP_GET_VARS['sql'])) {\r
-                               echo "<a name=explain></a>".$this->Explain($HTTP_GET_VARS['sql'])."\n";\r
+                               $partial = !empty($HTTP_GET_VARS['part']);\r
+                               echo "<a name=explain></a>".$this->Explain($HTTP_GET_VARS['sql'],$partial)."\n";\r
                        }\r
                        \r
                        if (isset($HTTP_GET_VARS['sql'])) return;\r
@@ -415,7 +452,7 @@ Committed_AS:   348732 kB
                        $ADODB_FETCH_MODE = ADODB_FETCH_NUM;\r
                        $rs =& $this->conn->SelectLimit(\r
                        "select sum(timer) as total,$sql1,count(*),max(timer) as max_timer,min(timer) as min_timer\r
-                               from adodb_logsql\r
+                               from $perf_table\r
                                where {$this->conn->upperCase}({$this->conn->substr}(sql0,1,5))  not in ('DROP ','INSER','COMMI','CREAT')\r
                                and (tracer is null or tracer not like 'ERROR:%')\r
                                group by sql1\r
@@ -427,12 +464,17 @@ Committed_AS:   348732 kB
                        $s = "<h3>Expensive SQL</h3>\r
 <font size=1>Tuning the following SQL will reduce the server load substantially</font><br>\r
 <table border=1 bgcolor=white><tr><td><b>Load</b><td><b>Count</b><td><b>SQL</b><td><b>Max</b><td><b>Min</b></tr>\n";\r
+                       $max = $this->maxLength;\r
                        while (!$rs->EOF) {\r
                                $sql = $rs->fields[1];\r
-                               \r
-                               $prefix = "<a target=sqle".rand()." href=\"?hidem=1&expe=1&sql=".rawurlencode($sql)."&x#explain\">";\r
+                               $raw = urlencode($sql);\r
+                               if (strlen($raw)>$max-100) {\r
+                                       $sql2 = substr($sql,0,$max-500);\r
+                                       $raw = urlencode($sql2).'&part='.crc32($sql);\r
+                               }\r
+                               $prefix = "<a target=sqle".rand()." href=\"?hidem=1&expe=1&sql=".$raw."&x#explain\">";\r
                                $suffix = "</a>";\r
-                               if($this->explain == false || strlen($prefix>2000)) {\r
+                               if($this->explain == false || strlen($prefix>$max)) {\r
                                        $prefix = '';\r
                                        $suffix = '';\r
                                }\r
@@ -529,8 +571,9 @@ Committed_AS:   348732 kB
        \r
        function UI($pollsecs=5)\r
        {\r
-       global $HTTP_GET_VARS,$HTTP_SERVER_VARS;\r
+       global $HTTP_GET_VARS,$HTTP_SERVER_VARS,$HTTP_POST_VARS;\r
        \r
+    $perf_table = adodb_perf::table();\r
        $conn = $this->conn;\r
        \r
        $app = $conn->host;\r
@@ -541,7 +584,7 @@ Committed_AS:   348732 kB
        $savelog = $this->conn->LogSQL(false);  \r
        $info = $conn->ServerInfo();\r
        if (isset($HTTP_GET_VARS['clearsql'])) {\r
-               $this->conn->Execute('delete from adodb_logsql');\r
+               $this->conn->Execute('delete from $perf_table');\r
        }\r
        $this->conn->LogSQL($savelog);\r
        \r
@@ -558,6 +601,7 @@ Committed_AS:   348732 kB
        \r
        \r
        if (isset($HTTP_GET_VARS['do'])) $do = $HTTP_GET_VARS['do'];\r
+       else if (isset($HTTP_POST_VARS['do'])) $do = $HTTP_POST_VARS['do'];\r
         else if (isset($HTTP_GET_VARS['sql'])) $do = 'viewsql';\r
         else $do = 'stats';\r
         \r
@@ -568,11 +612,14 @@ Committed_AS:   348732 kB
        if ($do == 'viewsql') $form = "<td><form># SQL:<input type=hidden value=viewsql name=do> <input type=text size=4 name=nsql value=$nsql><input type=submit value=Go></td></form>";\r
        else $form = "<td>&nbsp;</td>";\r
        \r
+       $allowsql = !defined('ADODB_PERF_NO_RUN_SQL');\r
+       \r
        if  (empty($HTTP_GET_VARS['hidem']))\r
        echo "<table border=1 width=100% bgcolor=lightyellow><tr><td colspan=2>\r
        <b><a href=http://php.weblogs.com/adodb?perf=1>ADOdb</a> Performance Monitor</b> for $app</tr><tr><td>\r
        <a href=?do=stats>Performance Stats</a> &nbsp; <a href=?do=viewsql>View SQL</a>\r
         &nbsp; <a href=?do=tables>View Tables</a> &nbsp; <a href=?do=poll>Poll Stats</a>",\r
+        $allowsql ? ' &nbsp; <a href=?do=dosql>Run SQL</a>' : '',\r
         "$form",\r
         "</tr></table>";\r
 \r
@@ -581,7 +628,7 @@ Committed_AS:   348732 kB
                default:\r
                case 'stats':\r
                        echo $this->HealthCheck();\r
-                       \r
+                       $this->conn->debug=1;\r
                        echo $this->CheckMemory();\r
                        break;\r
                case 'poll':\r
@@ -592,6 +639,12 @@ Committed_AS:   348732 kB
                        echo "<pre>";\r
                        $this->Poll($pollsecs);\r
                        break;\r
+               \r
+               case 'dosql':\r
+                       if (!$allowsql) break;\r
+                       \r
+                       $this->DoSQLForm();\r
+                       break;\r
                case 'viewsql':\r
                        if (empty($HTTP_GET_VARS['hidem']))\r
                                echo "&nbsp; <a href=\"?do=viewsql&clearsql=1\">Clear SQL Log</a><br>";\r
@@ -747,8 +800,103 @@ Committed_AS:   348732 kB
                $this->conn->LogSQL($savelog);\r
                return ($ok) ? true : false;\r
        }\r
-}\r
+       \r
+       function DoSQLForm()\r
+       {\r
+       global $HTTP_SERVER_VARS,$HTTP_GET_VARS,$HTTP_POST_VARS,$HTTP_SESSION_VARS;\r
+       \r
+               $HTTP_VARS = array_merge($HTTP_GET_VARS,$HTTP_POST_VARS);\r
+               \r
+               $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];\r
+               $sql = isset($HTTP_VARS['sql']) ? $HTTP_VARS['sql'] : '';\r
 \r
+               if (isset($HTTP_SESSION_VARS['phplens_sqlrows'])) $rows = $HTTP_SESSION_VARS['phplens_sqlrows'];\r
+               else $rows = 3;\r
+               \r
+               if (isset($HTTP_VARS['SMALLER'])) {\r
+                       $rows /= 2;\r
+                       if ($rows < 3) $rows = 3;\r
+                       $HTTP_SESSION_VARS['phplens_sqlrows'] = $rows;\r
+               }\r
+               if (isset($HTTP_VARS['BIGGER'])) {\r
+                       $rows *= 2;\r
+                       $HTTP_SESSION_VARS['phplens_sqlrows'] = $rows;\r
+               }\r
+               \r
+?>\r
+\r
+<form method="POST" action="<?php echo $PHP_SELF ?>">\r
+<table><tr>\r
+<td> Form size: <input type="submit" value=" &lt; " name="SMALLER"><input type="submit" value=" &gt; &gt; " name="BIGGER">\r
+</td>\r
+<td align=right>\r
+<input type="submit" value=" Run SQL Below " name="RUN"><input type=hidden name=do value=dosql>\r
+</td></tr>\r
+  <tr>\r
+  <td colspan=2><textarea rows=<?php print $rows; ?> name="sql" cols="80"><?php print htmlspecialchars($sql) ?></textarea>\r
+  </td>\r
+  </tr>\r
+ </table>\r
+</form>\r
+\r
+<?php\r
+               if (!isset($HTTP_VARS['sql'])) return;\r
+               \r
+               $sql = $this->undomq(trim($sql));\r
+               if (substr($sql,strlen($sql)-1) === ';') {\r
+                       $print = true;\r
+                       $sqla = $this->SplitSQL($sql);\r
+               } else  {\r
+                       $print = false;\r
+                       $sqla = array($sql);\r
+               }\r
+               foreach($sqla as $sqls) {\r
+\r
+                       if (!$sqls) continue;\r
+                       \r
+                       if ($print) {\r
+                               print "<p>".htmlspecialchars($sqls)."</p>";\r
+                               flush();\r
+                       }\r
+                       $savelog = $this->conn->LogSQL(false);\r
+                       $rs = $this->conn->Execute($sqls);\r
+                       $this->conn->LogSQL($savelog);\r
+                       if ($rs && is_object($rs) && !$rs->EOF) {\r
+                               rs2html($rs);\r
+                               while ($rs->NextRecordSet()) {\r
+                                       print "<table width=98% bgcolor=#C0C0FF><tr><td>&nbsp;</td></tr></table>";\r
+                                       rs2html($rs);\r
+                               }\r
+                       } else {\r
+                               $e1 = (integer) $this->conn->ErrorNo();\r
+                               $e2 = $this->conn->ErrorMsg();\r
+                               if (($e1) || ($e2)) {\r
+                                       if (empty($e1)) $e1 = '-1'; // postgresql fix\r
+                                       print ' &nbsp; '.$e1.': '.$e2;\r
+                               } else {\r
+                                       print "<p>No Recordset returned<br></p>";\r
+                               }\r
+                       }\r
+               } // foreach\r
+       }\r
+       \r
+       function SplitSQL($sql)\r
+       {\r
+               $arr = explode(';',$sql);\r
+               return $arr;\r
+       }\r
+       \r
+       function undomq(&$m) \r
+       {\r
+       if (get_magic_quotes_gpc()) {\r
+               // undo the damage\r
+               $m = str_replace('\\\\','\\',$m);\r
+               $m = str_replace('\"','"',$m);\r
+               $m = str_replace('\\\'','\'',$m);\r
+       }\r
+       return $m;\r
+}\r
+}\r
 \r
 \r
 \r
diff --git a/lib/adodb/adodb-php4.inc.php b/lib/adodb/adodb-php4.inc.php
new file mode 100644 (file)
index 0000000..ef2f55e
--- /dev/null
@@ -0,0 +1,16 @@
+<?php\r
+\r
+/*\r
+  V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+  Released under both BSD license and Lesser GPL library license. \r
+  Whenever there is any discrepancy between the two licenses, \r
+  the BSD license will take precedence.\r
+  \r
+  Set tabs to 4.\r
+*/\r
+\r
+\r
+class ADODB_BASE_RS {\r
+}\r
+\r
+?>
\ No newline at end of file
index 5ea9c9eef9a5bc4221dae7f371c8ae0504f62ef6..15545f12fe1a6f8997205b0b12e9f02d9855fe50 100644 (file)
@@ -23,7 +23,7 @@ This library replaces native functions as follows:
        date()     with  adodb_date() \r
        gmdate()   with  adodb_gmdate()\r
        mktime()   with  adodb_mktime()\r
-       gmmktime() with  adodb_gmmktime()45\r
+       gmmktime() with  adodb_gmmktime()\r
 </pre>\r
        \r
 The parameters are identical, except that adodb_date() accepts a subset\r
@@ -56,7 +56,7 @@ adodb_mktime(0,0,0,10,15,1582) - adodb_mktime(0,0,0,10,4,1582)
 COPYRIGHT\r
 \r
 (c) 2003 John Lim and released under BSD-style license except for code by jackbbs,\r
-which includes adodb_mktime, adodb_get_gmt_different, adodb_is_leap_year\r
+which includes adodb_mktime, adodb_get_gmt_diff, adodb_is_leap_year\r
 and originally found at http://www.php.net/manual/en/function.mktime.php\r
 \r
 =============================================================================\r
@@ -174,6 +174,9 @@ c. Implement daylight savings, which looks awfully complicated, see
 \r
 \r
 CHANGELOG\r
+- 26 Oct 2003 0.11\r
+Because of daylight savings problems (some systems apply daylight savings to \r
+January!!!), changed adodb_get_gmt_diff() to ignore daylight savings.\r
 \r
 - 9 Aug 2003 0.10\r
 Fixed bug with dates after 2038. \r
@@ -231,7 +234,7 @@ First implementation.
 /*\r
        Version Number\r
 */\r
-define('ADODB_DATE_VERSION',0.10);\r
+define('ADODB_DATE_VERSION',0.11);\r
 \r
 /*\r
        We check for Windows as only +ve ints are accepted as dates on Windows.\r
@@ -496,13 +499,13 @@ function adodb_year_digit_check($y)
 /**\r
  get local time zone offset from GMT\r
 */\r
-function adodb_get_gmt_different() \r
+function adodb_get_gmt_diff() \r
 {\r
-static $DIFF;\r
-       if (isset($DIFF)) return $DIFF;\r
+static $TZ;\r
+       if (isset($TZ)) return $TZ;\r
        \r
-       $DIFF = mktime(0,0,0,1,2,1970) - gmmktime(0,0,0,1,2,1970);\r
-       return $DIFF;\r
+       $TZ = mktime(0,0,0,1,2,1970,0) - gmmktime(0,0,0,1,2,1970,0);\r
+       return $TZ;\r
 }\r
 \r
 /**\r
@@ -527,7 +530,7 @@ function adodb_getdate($d=false,$fast=false)
 */\r
 function _adodb_getdate($origd=false,$fast=false,$is_gmt=false)\r
 {\r
-       $d =  $origd - ($is_gmt ? 0 : adodb_get_gmt_different());\r
+       $d =  $origd - ($is_gmt ? 0 : adodb_get_gmt_diff());\r
        \r
        $_day_power = 86400;\r
        $_hour_power = 3600;\r
@@ -709,7 +712,7 @@ function adodb_date($fmt,$d=false,$is_gmt=false)
                        \r
                        if ($secs < 10) $dates .= ':0'.$secs; else $dates .= ':'.$secs;\r
                        \r
-                       $gmt = adodb_get_gmt_different();\r
+                       $gmt = adodb_get_gmt_diff();\r
                        $dates .= sprintf(' %s%04d',($gmt<0)?'+':'-',abs($gmt)/36); break;\r
                                \r
                case 'Y': $dates .= $year; break;\r
@@ -738,9 +741,9 @@ function adodb_date($fmt,$d=false,$is_gmt=false)
                        \r
                // HOUR\r
                case 'Z':\r
-                       $dates .= ($is_gmt) ? 0 : -adodb_get_gmt_different(); break;\r
+                       $dates .= ($is_gmt) ? 0 : -adodb_get_gmt_diff(); break;\r
                case 'O': \r
-                       $gmt = ($is_gmt) ? 0 : adodb_get_gmt_different();\r
+                       $gmt = ($is_gmt) ? 0 : adodb_get_gmt_diff();\r
                        $dates .= sprintf('%s%04d',($gmt<0)?'+':'-',abs($gmt)/36); break;\r
                        \r
                case 'H': \r
@@ -820,7 +823,7 @@ function adodb_mktime($hr,$min,$sec,$mon,$day,$year,$is_dst=false,$is_gmt=false)
                                return @mktime($hr,$min,$sec,$mon,$day,$year);\r
        }\r
        \r
-       $gmt_different = ($is_gmt) ? 0 : adodb_get_gmt_different();\r
+       $gmt_different = ($is_gmt) ? 0 : adodb_get_gmt_diff();\r
        \r
        $hr = intval($hr);\r
        $min = intval($min);\r
index 4f40b6a2af456411e2d93ed704c1288e2ce7b84f..46a72684e5c423bef41165485071853785ed831c 100644 (file)
@@ -2,7 +2,7 @@
 /*\r
  * Set tabs to 4 for best viewing.\r
  * \r
- * Latest version is available at http://php.weblogs.com\r
+ * Latest version is available at http://php.weblogs.com/adodb\r
  * \r
  * This is the main include file for ADOdb.\r
  * Database specific drivers are stored in the adodb/drivers/adodb-*.inc.php\r
@@ -14,7 +14,7 @@
 /**\r
        \mainpage       \r
        \r
-        @version V4.01 23 Oct 2003 (c) 2000-2003 John Lim (jlim\@natsoft.com.my). All rights reserved.\r
+        @version V4.11 27 Jan 2004 (c) 2000-2004 John Lim (jlim\@natsoft.com.my). All rights reserved.\r
 \r
        Released under both BSD license and Lesser GPL library license. You can choose which license\r
        you prefer.\r
        // CONSTANT DEFINITIONS\r
        //==============================================================================================        \r
 \r
-       define('ADODB_BAD_RS','<p>Bad $rs in %s. Connection or SQL invalid. Try using $connection->debug=true;</p>');\r
-       \r
-       define('ADODB_FETCH_DEFAULT',0);\r
-       define('ADODB_FETCH_NUM',1);\r
-       define('ADODB_FETCH_ASSOC',2);\r
-       define('ADODB_FETCH_BOTH',3);\r
-       \r
-       /*\r
-       Controls ADODB_FETCH_ASSOC field-name case. Default is 2, use native case-names.\r
-       This currently works only with mssql, odbc, oci8po and ibase derived drivers.\r
-       \r
-               0 = assoc lowercase field names. $rs->fields['orderid']\r
-               1 = assoc uppercase field names. $rs->fields['ORDERID']\r
-               2 = use native-case field names. $rs->fields['OrderID']\r
-       */\r
-       //if (!defined('ADODB_ASSOC_CASE')) define('ADODB_ASSOC_CASE',2);\r
-       \r
-       // allow [ ] @ ` and . in table names\r
-       define('ADODB_TABLE_REGEX','([]0-9a-z_\`\.\@\[-]*)');\r
-       \r
-       \r
-       if (!defined('ADODB_PREFETCH_ROWS')) define('ADODB_PREFETCH_ROWS',10);\r
 \r
        /** \r
         * Set ADODB_DIR to the directory where this file resides...\r
         */\r
        if (!defined('ADODB_DIR')) define('ADODB_DIR',dirname(__FILE__));\r
        \r
-       if (!defined('TIMESTAMP_FIRST_YEAR')) define('TIMESTAMP_FIRST_YEAR',100);\r
-       \r
        //==============================================================================================        \r
        // GLOBAL VARIABLES\r
        //==============================================================================================        \r
 \r
        GLOBAL \r
                $ADODB_vers,            // database version\r
-               $ADODB_Database,        // last database driver used\r
                $ADODB_COUNTRECS,       // count number of records returned - slows down query\r
                $ADODB_CACHE_DIR,       // directory to cache recordsets\r
                $ADODB_EXTENSION,   // ADODB extension installed\r
        // GLOBAL SETUP\r
        //==============================================================================================        \r
        \r
-       if (strnatcmp(PHP_VERSION,'4.3.0')>=0) {\r
-               define('ADODB_PHPVER',0x4300);\r
-       } else if (strnatcmp(PHP_VERSION,'4.2.0')>=0) {\r
-               define('ADODB_PHPVER',0x4200);\r
-       } else if (strnatcmp(PHP_VERSION,'4.0.5')>=0) {\r
-               define('ADODB_PHPVER',0x4050);\r
-       } else {\r
-               define('ADODB_PHPVER',0x4000);\r
-       }\r
        $ADODB_EXTENSION = defined('ADODB_EXTENSION');\r
-       //if (extension_loaded('dbx')) define('ADODB_DBX',1);\r
+       if (!$ADODB_EXTENSION || ADODB_EXTENSION < 4.0) {\r
+               \r
+               define('ADODB_BAD_RS','<p>Bad $rs in %s. Connection or SQL invalid. Try using $connection->debug=true;</p>');\r
+       \r
+       // allow [ ] @ ` and . in table names\r
+               define('ADODB_TABLE_REGEX','([]0-9a-z_\`\.\@\[-]*)');\r
+       \r
+       // prefetching used by oracle\r
+               if (!defined('ADODB_PREFETCH_ROWS')) define('ADODB_PREFETCH_ROWS',10);\r
+       \r
+       \r
+       /*\r
+       Controls ADODB_FETCH_ASSOC field-name case. Default is 2, use native case-names.\r
+       This currently works only with mssql, odbc, oci8po and ibase derived drivers.\r
+       \r
+               0 = assoc lowercase field names. $rs->fields['orderid']\r
+               1 = assoc uppercase field names. $rs->fields['ORDERID']\r
+               2 = use native-case field names. $rs->fields['OrderID']\r
+       */\r
+       \r
+               define('ADODB_FETCH_DEFAULT',0);\r
+               define('ADODB_FETCH_NUM',1);\r
+               define('ADODB_FETCH_ASSOC',2);\r
+               define('ADODB_FETCH_BOTH',3);\r
+               \r
+               if (!defined('TIMESTAMP_FIRST_YEAR')) define('TIMESTAMP_FIRST_YEAR',100);\r
+       \r
+               if (strnatcmp(PHP_VERSION,'4.3.0')>=0) {\r
+                       define('ADODB_PHPVER',0x4300);\r
+               } else if (strnatcmp(PHP_VERSION,'4.2.0')>=0) {\r
+                       define('ADODB_PHPVER',0x4200);\r
+               } else if (strnatcmp(PHP_VERSION,'4.0.5')>=0) {\r
+                       define('ADODB_PHPVER',0x4050);\r
+               } else {\r
+                       define('ADODB_PHPVER',0x4000);\r
+               }\r
+       }\r
+       \r
+       //if (!defined('ADODB_ASSOC_CASE')) define('ADODB_ASSOC_CASE',2);\r
+       \r
        \r
        /**\r
                Accepts $src and $dest arrays, replacing string $data\r
        {\r
        GLOBAL \r
                $ADODB_vers,            // database version\r
-               $ADODB_Database,        // last database driver used\r
                $ADODB_COUNTRECS,       // count number of records returned - slows down query\r
                $ADODB_CACHE_DIR,       // directory to cache recordsets\r
                $ADODB_FETCH_MODE;\r
                // Initialize random number generator for randomizing cache flushes\r
                srand(((double)microtime())*1000000);\r
                \r
-               /**\r
-                * Name of last database driver loaded into memory. Set by ADOLoadCode().\r
-                */\r
-               $ADODB_Database = '';\r
-               \r
                /**\r
                 * ADODB version as a string.\r
                 */\r
-               $ADODB_vers = 'V4.01 23 Oct 2003 (c) 2000-2003 John Lim (jlim#natsoft.com.my). All rights reserved. Released BSD & LGPL.';\r
+               $ADODB_vers = 'V4.11 27 Jan 2004 (c) 2000-2004 John Lim (jlim#natsoft.com.my). All rights reserved. Released BSD & LGPL.';\r
        \r
                /**\r
                 * Determines whether recordset->RecordCount() is used. \r
                 * Set to false for highest performance -- RecordCount() will always return -1 then\r
                 * for databases that provide "virtual" recordcounts...\r
                 */\r
-               $ADODB_COUNTRECS = true; \r
+               if (!isset($ADODB_COUNTRECS)) $ADODB_COUNTRECS = true; \r
        }\r
        \r
        \r
        var $debug = false;             /// if set to true will output sql statements\r
        var $maxblobsize = 256000;      /// maximum size of blobs or large text fields -- some databases die otherwise like foxpro\r
        var $concat_operator = '+'; /// default concat operator -- change to || for Oracle/Interbase    \r
+       var $substr = 'substr';         /// substring operator\r
+       var $length = 'length';         /// string length operator\r
+       var $random = 'rand()';         /// random function\r
+       var $upperCase = false;         /// uppercase function\r
        var $fmtDate = "'Y-m-d'";       /// used by DBDate() as the default date format used by the database\r
        var $fmtTimeStamp = "'Y-m-d, h:i:s A'"; /// used by DBTimeStamp as the default timestamp fmt.\r
        var $true = '1';                        /// string that represents TRUE for a database\r
        var $false = '0';                       /// string that represents FALSE for a database\r
        var $replaceQuote = "\\'";      /// string to use to replace quotes\r
+       var $nameQuote = '"';           /// string to use to quote identifiers and names\r
        var $charSet=false;             /// character set to use - only for interbase\r
        var $metaDatabasesSQL = '';\r
        var $metaTablesSQL = '';\r
        //--\r
        var $genID = 0;                         /// sequence id used by GenID();\r
        var $raiseErrorFn = false;      /// error function to call\r
-       var $upperCase = false;         /// uppercase function to call for searching/where\r
        var $isoDates = false; /// accepts dates in ISO format\r
        var $cacheSecs = 3600; /// cache for 1 hour\r
        var $sysDate = false; /// name of function that returns the current date\r
        */\r
        function outp($msg,$newline=true)\r
        {\r
-       global $HTTP_SERVER_VARS;\r
+       global $HTTP_SERVER_VARS,$ADODB_FLUSH;\r
        \r
                if (defined('ADODB_OUTP')) {\r
                        $fn = ADODB_OUTP;\r
                \r
                if (isset($HTTP_SERVER_VARS['HTTP_USER_AGENT'])) echo $msg;\r
                else echo strip_tags($msg);\r
-               flush();\r
+               if (!empty($ADODB_FLUSH) && ob_get_length() !== false) flush(); //  dp not flush if output buffering enabled - useless - thx to Jesse Mullan \r
+               \r
        }\r
        \r
        /**\r
         *                      if the database does not support prepare.\r
         *\r
         */     \r
-       function PrepareSP($sql)\r
+       function PrepareSP($sql,$param=false)\r
        {\r
-               return $this->Prepare($sql);\r
+               return $this->Prepare($sql,$param);\r
        }\r
        \r
        /**\r
        {\r
                return '?';\r
        }\r
+       \r
+       /*\r
+               InParameter and OutParameter are self-documenting versions of Parameter().\r
+       */\r
+       function InParameter(&$stmt,&$var,$name,$maxLen=4000,$type=false)\r
+       {\r
+               return $this->Parameter($stmt,$var,$name,false,$maxLen,$type);\r
+       }\r
+       \r
+       /*\r
+       */\r
+       function OutParameter(&$stmt,&$var,$name,$maxLen=4000,$type=false)\r
+       {\r
+               return $this->Parameter($stmt,$var,$name,true,$maxLen,$type);\r
+       \r
+       }\r
+       \r
        /* \r
        Usage in oracle\r
                $stmt = $db->Prepare('select * from table where id =:myid and group=:group');\r
        */\r
        function StartTrans($errfn = 'ADODB_TransMonitor')\r
        {\r
-               \r
                if ($this->transOff > 0) {\r
                        $this->transOff += 1;\r
                        return;\r
                \r
                $this->transOff = 0;\r
                if ($this->_transOK && $autoComplete) {\r
-                       $this->CommitTrans();\r
-                       if ($this->debug) ADOConnection::outp("Smart Commit occurred");\r
+                       if (!$this->CommitTrans()) {\r
+                               $this->_transOK = false;\r
+                               if ($this->debug) ADOConnection::outp("Smart Commit failed");\r
+                       } else\r
+                               if ($this->debug) ADOConnection::outp("Smart Commit occurred");\r
                } else {\r
                        $this->RollbackTrans();\r
                        if ($this->debug) ADOCOnnection::outp("Smart Rollback occurred");\r
                        \r
                        if (!is_array($sql) && !$this->_bindInputArray) {\r
                                $sqlarr = explode('?',$sql);\r
-                               \r
+                                       \r
                                if (!$array_2d) $inputarr = array($inputarr);\r
-                               while(list(,$arr) = each($inputarr)) {\r
+                               foreach($inputarr as $arr) {\r
                                        $sql = ''; $i = 0;\r
-                                       reset($arr);\r
-                                       while(list(,$v) = each($arr)) {\r
+                                       foreach($arr as $v) {\r
                                                $sql .= $sqlarr[$i];\r
                                                // from Ron Baldwin <ron.baldwin@sourceprose.com>\r
                                                // Only quote string types      \r
                                                $i += 1;\r
                                        }\r
                                        $sql .= $sqlarr[$i];\r
+                                       \r
                                        if ($i+1 != sizeof($sqlarr))    \r
                                                ADOConnection::outp( "Input Array does not match ?: ".htmlspecialchars($sql));\r
-                                       \r
+               \r
                                        $ret =& $this->_Execute($sql,false);\r
                                        if (!$ret) return $ret;\r
-                               }\r
-                               \r
+                               }       \r
                        } else {\r
-                               \r
                                if ($array_2d) {\r
                                        $stmt = $this->Prepare($sql);\r
-                                       while(list(,$arr) = each($inputarr)) {\r
+                                       foreach($inputarr as $arr) {\r
                                                $ret =& $this->_Execute($stmt,$arr);\r
                                                if (!$ret) return $ret;\r
                                        }\r
                } else {\r
                        $ret =& $this->_Execute($sql,false);\r
                }\r
-               \r
+\r
                return $ret;\r
        }\r
        \r
                // debug version of query\r
                if ($this->debug) {\r
                global $HTTP_SERVER_VARS;\r
-               \r
                        $ss = '';\r
                        if ($inputarr) {\r
-                               foreach ($inputarr as $kk => $vv)  {\r
+                               foreach($inputarr as $kk=>$vv) {\r
                                        if (is_string($vv) && strlen($vv)>64) $vv = substr($vv,0,64).'...';\r
                                        $ss .= "($kk=>'$vv') ";\r
                                }\r
                                else ADOConnection::outp( "<hr />\n($this->databaseType): ".htmlspecialchars($sqlTxt)." &nbsp; <code>$ss</code>\n<hr />\n",false);\r
                        else\r
                                ADOConnection::outp(  "=----\n($this->databaseType): ".($sqlTxt)." \n-----\n",false);\r
-                       flush();\r
                        \r
                        $this->_queryID = $this->_query($sql,$inputarr);\r
                        /* \r
                                        $err = $this->ErrorNo();\r
                                        if ($err) {\r
                                                ADOConnection::outp($err.': '.$emsg);\r
-                                               flush();\r
                                        }\r
                                }\r
                        } else \r
                                        $e = $this->ErrorNo();\r
                                        $m = $this->ErrorMsg();\r
                                        ADOConnection::outp($e .': '. $m );\r
-                                       flush();\r
                                }\r
                } else {\r
                        // non-debug version of query\r
                if (empty($this->_genSeqSQL)) return false;\r
                return $this->Execute(sprintf($this->_genSeqSQL,$seqname,$startID));\r
        }\r
-       \r
+\r
        function DropSequence($seqname)\r
        {\r
                if (empty($this->_dropSeqSQL)) return false;\r
         * @param startID               if sequence does not exist, start at this ID\r
         * @return              0 if not supported, otherwise a sequence id\r
         */\r
-\r
        function GenID($seqname='adodbseq',$startID=1)\r
        {\r
                if (!$this->hasGenID) {\r
                }\r
                \r
                $getnext = sprintf($this->_genIDSQL,$seqname);\r
+               \r
+               $holdtransOK = $this->_transOK;\r
                $rs = @$this->Execute($getnext);\r
                if (!$rs) {\r
+                       $this->_transOK = $holdtransOK; //if the status was ok before reset\r
                        $createseq = $this->Execute(sprintf($this->_genSeqSQL,$seqname,$startID));\r
                        $rs = $this->Execute($getnext);\r
                }\r
        /**\r
         * @return  the last inserted ID. Not all databases support this.\r
         */ \r
-               function Insert_ID()\r
-               {\r
-                       if ($this->_logsql && $this->lastInsID) return $this->lastInsID;\r
-                       if ($this->hasInsertID) return $this->_insertid();\r
-                       if ($this->debug) ADOConnection::outp( '<p>Insert_ID error</p>');\r
-                       return false;\r
+       function Insert_ID()\r
+       {\r
+               if ($this->_logsql && $this->lastInsID) return $this->lastInsID;\r
+               if ($this->hasInsertID) return $this->_insertid();\r
+               if ($this->debug) {\r
+                       ADOConnection::outp( '<p>Insert_ID error</p>');\r
+                       adodb_backtrace();\r
                }\r
-       \r
-       \r
+               return false;\r
+       }\r
+\r
+\r
        /**\r
         * Portable Insert ID. Pablo Roca <pabloroca@mvps.org>\r
         *\r
         * @return  the last inserted ID. All databases support this. But aware possible\r
         * problems in multiuser environments. Heavy test this before deploying.\r
         */ \r
-               function PO_Insert_ID($table="", $id="") \r
-               {\r
-                  if ($this->hasInsertID){\r
-                          return $this->Insert_ID();\r
-                  } else {\r
-                          return $this->GetOne("SELECT MAX($id) FROM $table");\r
-                  }\r
-               }       \r
-       \r
-               \r
-        /**\r
-        * @return  # rows affected by UPDATE/DELETE\r
-        */ \r
-        function Affected_Rows()\r
-        {\r
-                 if ($this->hasAffectedRows) {\r
-                               if ($this->fnExecute === 'adodb_log_sql') {\r
-                               \r
-                                       if ($this->_logsql && $this->_affected !== false) return $this->_affected;\r
-                               }\r
-                               $val = $this->_affectedrows();\r
-                               return ($val < 0) ? false : $val;\r
-                 }\r
+       function PO_Insert_ID($table="", $id="") \r
+       {\r
+          if ($this->hasInsertID){\r
+                  return $this->Insert_ID();\r
+          } else {\r
+                  return $this->GetOne("SELECT MAX($id) FROM $table");\r
+          }\r
+       }\r
+\r
+       /**\r
+       * @return # rows affected by UPDATE/DELETE\r
+       */ \r
+       function Affected_Rows()\r
+       {\r
+               if ($this->hasAffectedRows) {\r
+                       if ($this->fnExecute === 'adodb_log_sql') {\r
+                               if ($this->_logsql && $this->_affected !== false) return $this->_affected;\r
+                       }\r
+                       $val = $this->_affectedrows();\r
+                       return ($val < 0) ? false : $val;\r
+               }\r
                                  \r
-                 if ($this->debug) ADOConnection::outp( '<p>Affected_Rows error</p>',false);\r
-                 return false;\r
-        }\r
+               if ($this->debug) ADOConnection::outp( '<p>Affected_Rows error</p>',false);\r
+               return false;\r
+       }\r
        \r
        \r
        /**\r
                        }\r
                }\r
                if (sizeof($p)) return $p;\r
+               if (function_exists('ADODB_VIEW_PRIMARYKEYS'))\r
+                       return ADODB_VIEW_PRIMARYKEYS($this->databaseType, $this->database, $table, $owner);\r
                return false;\r
        }\r
        \r
                return $rs;\r
        }\r
        \r
+       /**\r
+       * Create serializable recordset. Breaks rs link to connection.\r
+       *\r
+       * @param rs                     the recordset to serialize\r
+       */\r
+       function &SerializableRS(&$rs)\r
+       {\r
+               $rs2 =& $this->_rs2rs($rs);\r
+               $ignore = false;\r
+               $rs2->connection =& $ignore;\r
+               \r
+               return $rs2;\r
+       }\r
        \r
        /**\r
        * Convert database recordset to an array recordset\r
                $rv = false;\r
                $rs = &$this->Execute($sql, $inputarr);\r
                if ($rs) {\r
+                       $rv = array();\r
                        if ($trim) {\r
                                while (!$rs->EOF) {\r
                                        $rv[] = trim(reset($rs->fields));\r
                \r
                $ADODB_COUNTRECS = $crecs;\r
                if ($rs) {\r
-                       $arr = array();\r
                        if (!$rs->EOF) $arr = $rs->fields;\r
+                       else $arr = array();\r
                        $rs->Close();\r
                        return $arr;\r
                }\r
        \r
        function Replace($table, $fieldArray, $keyCol, $autoQuote=false, $has_autoinc=false)\r
        {\r
-               if (count($fieldArray) == 0) return 0;\r
-               $first = true;\r
-               $uSet = '';\r
-               \r
-               if (!is_array($keyCol)) {\r
-                       $keyCol = array($keyCol);\r
-               }\r
-               foreach($fieldArray as $k => $v) {\r
-                       if ($autoQuote && !is_numeric($v) and strncmp($v,"'",1) !== 0 and strcasecmp($v,'null')!=0) {\r
-                               $v = $this->qstr($v);\r
-                               $fieldArray[$k] = $v;\r
-                       }\r
-                       if (in_array($k,$keyCol)) continue; // skip UPDATE if is key\r
-                       \r
-                       if ($first) {\r
-                               $first = false;                 \r
-                               $uSet = "$k=$v";\r
-                       } else\r
-                               $uSet .= ",$k=$v";\r
-               }\r
-                \r
-               $first = true;\r
-               foreach ($keyCol as $v) {\r
-                       if ($first) {\r
-                               $first = false;\r
-                               $where = "$v=$fieldArray[$v]";\r
-                       } else {\r
-                               $where .= " and $v=$fieldArray[$v]";\r
-                       }\r
-               }\r
-               \r
-               if ($uSet) {\r
-                       $update = "UPDATE $table SET $uSet WHERE $where";\r
+               global $ADODB_INCLUDED_LIB;\r
+               if (empty($ADODB_INCLUDED_LIB)) include_once(ADODB_DIR.'/adodb-lib.inc.php');\r
                \r
-                       $rs = $this->Execute($update);\r
-                       if ($rs) {\r
-                               if ($this->poorAffectedRows) {\r
-                               /*\r
-                                The Select count(*) wipes out any errors that the update would have returned. \r
-                               http://phplens.com/lens/lensforum/msgs.php?id=5696\r
-                               */\r
-                                       if ($this->ErrorNo()<>0) return 0;\r
-                                       \r
-                               # affected_rows == 0 if update field values identical to old values\r
-                               # for mysql - which is silly. \r
-                       \r
-                                       $cnt = $this->GetOne("select count(*) from $table where $where");\r
-                                       if ($cnt > 0) return 1; // record already exists\r
-                               } else\r
-                                        if (($this->Affected_Rows()>0)) return 1;\r
-                       }\r
-                               \r
-               }\r
-       //      print "<p>Error=".$this->ErrorNo().'<p>';\r
-               $first = true;\r
-               foreach($fieldArray as $k => $v) {\r
-                       if ($has_autoinc && in_array($k,$keyCol)) continue; // skip autoinc col\r
-                       \r
-                       if ($first) {\r
-                               $first = false;                 \r
-                               $iCols = "$k";\r
-                               $iVals = "$v";\r
-                       } else {\r
-                               $iCols .= ",$k";\r
-                               $iVals .= ",$v";\r
-                       }                               \r
-               }\r
-               $insert = "INSERT INTO $table ($iCols) VALUES ($iVals)"; \r
-               $rs = $this->Execute($insert);\r
-               return ($rs) ? 2 : 0;\r
+               return _adodb_replace($this, $table, $fieldArray, $keyCol, $autoQuote, $has_autoinc);\r
        }\r
        \r
        \r
                        if ($sql === false) $sql = -1;\r
                        if ($offset == -1) $offset = false;\r
                                                                          // sql,       nrows, offset,inputarr\r
-                       $rs =& $this->SelectLimit($secs2cache,$sql,$nrows,$offset,$inputarr,$this->cacheSecs);\r
+                       $rs =& $this->SelectLimit($secs2cache,$sql,$nrows,$offset,$this->cacheSecs);\r
                } else {\r
                        if ($sql === false) ADOConnection::outp( "Warning: \$sql missing from CacheSelectLimit()");\r
                        $rs =& $this->SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);\r
                }\r
        }\r
 \r
-       /*\r
-       * Maximum size of C field\r
-       *\r
-       function CharMax()\r
-       {\r
-               return 255; // make it conservative if not defined\r
-       }\r
-       \r
-       \r
-       /*\r
-       * Maximum size of X field\r
-       *\r
-       function TextMax()\r
-       {\r
-               return 4000; // make it conservative if not defined\r
-       }\r
-       */\r
        \r
        /**\r
         * Close Connection\r
        }\r
        \r
        \r
+       function _findschema(&$table,&$schema)\r
+       {\r
+               if (!$schema && ($at = strpos($table,'.')) !== false) {\r
+                       $schema = substr($table,0,$at);\r
+                       $table = substr($table,$at+1);\r
+               }\r
+       }\r
+       \r
        /**\r
         * List columns in a database as an array of ADOFieldObjects. \r
         * See top of file for definition of object.\r
         *\r
         * @param table table name to query\r
         * @param upper uppercase table name (required by some databases)\r
+        * @schema is optional database schema to use - not supported by all databases.\r
         *\r
         * @return  array of ADOFieldObjects for current table.\r
-        */ \r
+        */\r
        function &MetaColumns($table,$upper=true) \r
        {\r
        global $ADODB_FETCH_MODE;\r
-\r
+               \r
                if (!empty($this->metaColumnsSQL)) {\r
+               \r
+                       $schema = false;\r
+                       $this->_findschema($table,$schema);\r
+               \r
                        $save = $ADODB_FETCH_MODE;\r
                        $ADODB_FETCH_MODE = ADODB_FETCH_NUM;\r
                        if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);\r
                return false;\r
        }\r
        \r
+    /**\r
+      * List indexes on a table as an array.\r
+      * @param table        table name to query\r
+      * @param primary include primary keys.\r
+         *\r
+      * @return array of indexes on current table.\r
+      */\r
+     function &MetaIndexes($table, $primary = false, $owner = false)\r
+     {\r
+             return FALSE;\r
+     }\r
+\r
        /**\r
         * List columns names in a table as an array. \r
         * @param table table name to query\r
                if (empty($d) && $d !== 0) return 'null';\r
 \r
                if (is_string($d) && !is_numeric($d)) {\r
-                       if ($d === 'null') return $d;\r
+                       if ($d === 'null' || strncmp($d,"'",1) === 0) return $d;\r
                        if ($this->isoDates) return "'$d'";\r
                        $d = ADOConnection::UnixDate($d);\r
                }\r
        {\r
                if (empty($ts) && $ts !== 0) return 'null';\r
 \r
-               if (is_string($ts) && !is_numeric($ts)) {\r
-                       if ($ts === 'null') return $ts;\r
-                       if ($this->isoDates) return "'$ts'";\r
-                       else $ts = ADOConnection::UnixTimeStamp($ts);\r
-               }\r
-                       \r
+               # strlen(14) allows YYYYMMDDHHMMSS format\r
+               if (!is_string($ts) || (is_numeric($ts) && strlen($ts)<14)) \r
+                       return adodb_date($this->fmtTimeStamp,$ts);\r
+               \r
+               if ($ts === 'null') return $ts;\r
+               if ($this->isoDates && strlen($ts) !== 14) return "'$ts'";\r
+               \r
+               $ts = ADOConnection::UnixTimeStamp($ts);\r
                return adodb_date($this->fmtTimeStamp,$ts);\r
        }\r
        \r
         */\r
        function UserTimeStamp($v,$fmt='Y-m-d H:i:s')\r
        {\r
-               if (is_numeric($v)) return adodb_date($fmt,$v);\r
+               # strlen(14) allows YYYYMMDDHHMMSS format\r
+               if (is_numeric($v) && strlen($v)<14) return adodb_date($fmt,$v);\r
                $tt = $this->UnixTimeStamp($v);\r
                // $tt == -1 if pre TIMESTAMP_FIRST_YEAR\r
                if (($tt === false || $tt == -1) && $v != false) return $v;\r
        //==============================================================================================        \r
        // CLASS ADORecordSet\r
        //==============================================================================================        \r
-       \r
 \r
+       if (PHP_VERSION < 5) include_once(ADODB_DIR.'/adodb-php4.inc.php');\r
+       else include_once(ADODB_DIR.'/adodb-iterator.inc.php');\r
    /**\r
         * RecordSet class that represents the dataset returned by the database.\r
         * To keep memory overhead low, this class holds only the current row in memory.\r
         * No prefetching of data is done, so the RecordCount() can return -1 ( which\r
         * means recordcount not known).\r
         */\r
-       class ADORecordSet {\r
+       class ADORecordSet extends ADODB_BASE_RS {\r
        /*\r
         * public variables     \r
         */\r
        var $dataProvider = "native";\r
        var $fields = false;    /// holds the current row data\r
        var $blobSize = 100;    /// any varchar/char field this size or greater is treated as a blob\r
-                                                       /// in other words, we use a text area for editting.\r
+                                                       /// in other words, we use a text area for editing.\r
        var $canSeek = false;   /// indicates that seek is supported\r
        var $sql;                               /// sql text\r
        var $EOF = false;               /// Indicates that the current record position is after the last record in a Recordset object. \r
         */\r
        function UserTimeStamp($v,$fmt='Y-m-d H:i:s')\r
        {\r
-               if (is_numeric($v)) return adodb_date($fmt,$v);\r
+               if (is_numeric($v) && strlen($v)<14) return adodb_date($fmt,$v);\r
                $tt = $this->UnixTimeStamp($v);\r
                // $tt == -1 if pre TIMESTAMP_FIRST_YEAR\r
                if (($tt === false || $tt == -1) && $v != false) return $v;\r
    */\r
        function &GetRowAssoc($upper=1)\r
        {\r
-        \r
+               $record = array();\r
+        //     if (!$this->fields) return $record;\r
+               \r
                if (!$this->bind) {\r
                        $this->GetAssocKeys($upper);\r
                }\r
                \r
-               $record = array();\r
-               reset($this->bind);\r
-               while(list($k,$v) = each($this->bind)) {\r
-               //echo " $k $v, ";\r
-               //foreach($this->bind as $k => $v) {\r
+               foreach($this->bind as $k => $v) {\r
                        $record[$k] = $this->fields[$v];\r
                }\r
 \r
                'TIMESTAMPTZ' => 'T',\r
                'T' => 'T',\r
                ##\r
+               'BOOL' => 'L',\r
                'BOOLEAN' => 'L', \r
                'BIT' => 'L',\r
                'L' => 'L',\r
                case 'C':\r
                \r
                        // is the char field is too long, return as text field... \r
-                       if (!empty($this->blobSize)) {\r
+                       if ($this->blobSize >= 0) {\r
                                if ($len > $this->blobSize) return 'X';\r
                        } else if ($len > 250) {\r
                                return 'X';\r
                if ($status != false) $this->_atLastPage = $status;\r
                return $this->_atLastPage;\r
        }\r
+       \r
 } // end class ADORecordSet\r
        \r
        //==============================================================================================        \r
                \r
                \r
                /**\r
-                * Setup the Array. Later we will have XML-Data and CSV handlers\r
+                * Setup the array.\r
                 *\r
                 * @param array         is a 2-dimensional array holding the data.\r
                 *                      The first row should hold the column names \r
                        if ($colnames) {\r
                                $this->_skiprow1 = false;\r
                                $this->_colnames = $colnames;\r
-                       } else $this->_colnames = $array[0];\r
-                       \r
+                       } else  {\r
+                               $this->_skiprow1 = true;\r
+                               $this->_colnames = $array[0];\r
+                       }\r
                        $this->Init();\r
                }\r
                /**\r
                        \r
                function _seek($row)\r
                {\r
-                       if (sizeof($this->_array) && $row < $this->_numOfRows) {\r
+                       if (sizeof($this->_array) && 0 <= $row && $row < $this->_numOfRows) {\r
+                               $this->_currentRow = $row;\r
+                               if ($this->_skiprow1) $row += 1;\r
                                $this->fields = $this->_array[$row];\r
                                return true;\r
                        }\r
                                $this->_currentRow++;\r
                                \r
                                $pos = $this->_currentRow;\r
-                               if ($this->_skiprow1) $pos += 1;\r
                                \r
                                if ($this->_numOfRows <= $pos) {\r
                                        if (!$this->compat) $this->fields = false;\r
                                } else {\r
+                                       if ($this->_skiprow1) $pos += 1;\r
                                        $this->fields = $this->_array[$pos];\r
                                        return true;\r
                                }               \r
                function _fetch()\r
                {\r
                        $pos = $this->_currentRow;\r
-                       if ($this->_skiprow1) $pos += 1;\r
                        \r
                        if ($this->_numOfRows <= $pos) {\r
                                if (!$this->compat) $this->fields = false;\r
                                return false;\r
                        }\r
-\r
+                       if ($this->_skiprow1) $pos += 1;\r
                        $this->fields = $this->_array[$pos];\r
                        return true;\r
                }\r
        //==============================================================================================                        \r
        \r
        /**\r
-        * Synonym for ADOLoadCode.\r
+        * Synonym for ADOLoadCode. Private function. Do not use.\r
         *\r
         * @deprecated\r
         */\r
        }\r
                \r
        /**\r
-        * Load the code for a specific database driver\r
+        * Load the code for a specific database driver. Private function. Do not use.\r
         */\r
        function ADOLoadCode($dbType) \r
        {\r
-       GLOBAL $ADODB_Database;\r
+       global $ADODB_LASTDB;\r
        \r
                if (!$dbType) return false;\r
-               $ADODB_Database = strtolower($dbType);\r
-               switch ($ADODB_Database) {\r
-                       case 'maxsql': $ADODB_Database = 'mysqlt'; break;\r
+               $db = strtolower($dbType);\r
+               switch ($db) {\r
+                       case 'maxsql': $db = 'mysqlt'; break;\r
                        case 'postgres':\r
-                       case 'pgsql': $ADODB_Database = 'postgres7'; break;\r
+                       case 'pgsql': $db = 'postgres7'; break;\r
                }\r
-               // Karsten Kraus <Karsten.Kraus@web.de> \r
-               return @include_once(ADODB_DIR."/drivers/adodb-".$ADODB_Database.".inc.php");           \r
+               $ok = @include_once(ADODB_DIR."/drivers/adodb-".$db.".inc.php");\r
+               $ADODB_LASTDB = $db;\r
+               \r
+               if ($ok) return $db;\r
+               \r
+               $file = ADODB_DIR."/drivers/adodb-".$db.".inc.php";\r
+               if (file_exists($file)) ADOConnection::outp("Missing file: $file");\r
+               else ADOConnection::outp("Syntax error in file: $file");\r
+               return false;\r
        }\r
 \r
        /**\r
         */\r
        function &ADONewConnection($db='')\r
        {\r
-       GLOBAL $ADODB_Database,$ADODB_NEWCONNECTION;\r
+       GLOBAL $ADODB_NEWCONNECTION, $ADODB_LASTDB;\r
                \r
                if (!defined('ADODB_ASSOC_CASE')) define('ADODB_ASSOC_CASE',2);\r
                $errorfn = (defined('ADODB_ERROR_HANDLER')) ? ADODB_ERROR_HANDLER : false;\r
                        }\r
                }\r
                \r
-               $rez = true;\r
-               if ($db) {\r
-                       if ($ADODB_Database != $db) ADOLoadCode($db);\r
-               } else { \r
-                       if (!empty($ADODB_Database)) {\r
-                               ADOLoadCode($ADODB_Database);\r
-                       } else {\r
-                                $rez = false;\r
-                       }\r
-               }\r
+               if (!isset($ADODB_LASTDB)) $ADODB_LASTDB = '';\r
+               if (empty($db)) $db = $ADODB_LASTDB;\r
+               \r
+               if ($db != $ADODB_LASTDB) $db = ADOLoadCode($db);\r
                \r
-               if (!$rez) {\r
+               if (!$db) {\r
                         if ($errorfn) {\r
                                // raise an error\r
+                               $ignore = false;\r
                                $errorfn('ADONewConnection', 'ADONewConnection', -998,\r
                                                 "could not load the database driver for '$db",\r
-                                                $dbtype);\r
+                                                $db,false,$ignore);\r
                        } else\r
                                 ADOConnection::outp( "<p>ADONewConnection: Unable to load database driver '$db'</p>",false);\r
                                \r
                        return false;\r
                }\r
                \r
-               $cls = 'ADODB_'.$ADODB_Database;\r
+               $cls = 'ADODB_'.$db;\r
+               if (!class_exists($cls)) {\r
+                       adodb_backtrace();\r
+                       return false;\r
+               }\r
+               \r
                $obj =& new $cls();\r
                if ($errorfn) $obj->raiseErrorFn = $errorfn;\r
                \r
                $dict->dataProvider = $conn->dataProvider;\r
                $dict->connection = &$conn;\r
                $dict->upperName = strtoupper($drivername);\r
+               $dict->quote = $conn->nameQuote;\r
                if (is_resource($conn->_connectionID))\r
                        $dict->serverInfo = $conn->ServerInfo();\r
                \r
                if (strncmp(PHP_OS,'WIN',3) === 0) {\r
                        // skip the decimal place\r
                        $mtime = substr(str_replace(' ','_',microtime()),2); \r
-                       // unlink will let some latencies develop, so uniqid() is more random\r
-                       @unlink($filename);\r
                        // getmypid() actually returns 0 on Win98 - never mind!\r
                        $tmpname = $filename.uniqid($mtime).getmypid();\r
                        if (!($fd = fopen($tmpname,'a'))) return false;\r
                        if (!fwrite($fd,$contents)) $ok = false;\r
                        fclose($fd);\r
                        chmod($tmpname,0644);\r
+                       // the tricky moment\r
+                       @unlink($filename);\r
                        if (!@rename($tmpname,$filename)) {\r
                                unlink($tmpname);\r
                                $ok = false;\r
                return $ok;\r
        }\r
        \r
-\r
+       /*\r
+               Perform a print_r, with pre tags for better formatting.\r
+       */\r
        function adodb_pr($var)\r
        {\r
-               echo " <pre>\n";print_r($var);echo "</pre>\n";\r
+               if (isset($_SERVER['HTTP_USER_AGENT'])) { \r
+                       echo " <pre>\n";print_r($var);echo "</pre>\n";\r
+               } else\r
+                       print_r($var);\r
        }\r
        \r
-       function adodb_backtrace($print=true,$levels=9999)\r
+       /*\r
+               Perform a stack-crawl and pretty print it.\r
+               \r
+               @param printOrArr  Pass in a boolean to indicate print, or an $exception->trace array (assumes that print is true then).\r
+               @param levels Number of levels to display\r
+       */\r
+       function adodb_backtrace($printOrArr=true,$levels=9999)\r
        {\r
                $s = '';\r
-               if (PHPVERSION() >= 4.3) {\r
+               if (PHPVERSION() < 4.3) return;\r
+                \r
+               $html =  (isset($_SERVER['HTTP_USER_AGENT']));\r
+               $fmt =  ($html) ? "</font><font color=#808080 size=-1> %% line %4d, file: <a href=\"file:/%s\">%s</a></font>" : "%% line %4d, file: %s";\r
+\r
+               $MAXSTRLEN = 64;\r
+       \r
+               $s = ($html) ? '<pre align=left>' : '';\r
                \r
-                       $MAXSTRLEN = 64;\r
+               if (is_array($printOrArr)) $traceArr = $printOrArr;\r
+               else $traceArr = debug_backtrace();\r
+               array_shift($traceArr);\r
+               $tabs = sizeof($traceArr)-1;\r
                \r
-                       $s = '<pre align=left>';\r
-                       $traceArr = debug_backtrace();\r
-                       array_shift($traceArr);\r
-                       $tabs = sizeof($traceArr)-1;\r
+               foreach ($traceArr as $arr) {\r
+                       $levels -= 1;\r
+                       if ($levels < 0) break;\r
                        \r
-                       foreach ($traceArr as $arr) {\r
-                               $levels -= 1;\r
-                               if ($levels < 0) break;\r
-                               \r
-                               $args = array();\r
-                               for ($i=0; $i < $tabs; $i++) $s .= ' &nbsp; ';\r
-                               $tabs -= 1;\r
-                               $s .= '<font face="Courier New,Courier">';\r
-                               if (isset($arr['class'])) $s .= $arr['class'].'.';\r
-                               if (isset($arr['args']))\r
-                                foreach($arr['args'] as $v) {\r
-                                       if (is_null($v)) $args[] = 'null';\r
-                                       else if (is_array($v)) $args[] = 'Array['.sizeof($v).']';\r
-                                       else if (is_object($v)) $args[] = 'Object:'.get_class($v);\r
-                                       else if (is_bool($v)) $args[] = $v ? 'true' : 'false';\r
-                                       else {\r
-                                               $v = (string) @$v;\r
-                                               $str = htmlspecialchars(substr($v,0,$MAXSTRLEN));\r
-                                               if (strlen($v) > $MAXSTRLEN) $str .= '...';\r
-                                               $args[] = $str;\r
-                                       }\r
+                       $args = array();\r
+                       for ($i=0; $i < $tabs; $i++) $s .=  ($html) ? ' &nbsp; ' : "\t";\r
+                       $tabs -= 1;\r
+                       if ($html) $s .= '<font face="Courier New,Courier">';\r
+                       if (isset($arr['class'])) $s .= $arr['class'].'.';\r
+                       if (isset($arr['args']))\r
+                        foreach($arr['args'] as $v) {\r
+                               if (is_null($v)) $args[] = 'null';\r
+                               else if (is_array($v)) $args[] = 'Array['.sizeof($v).']';\r
+                               else if (is_object($v)) $args[] = 'Object:'.get_class($v);\r
+                               else if (is_bool($v)) $args[] = $v ? 'true' : 'false';\r
+                               else {\r
+                                       $v = (string) @$v;\r
+                                       $str = htmlspecialchars(substr($v,0,$MAXSTRLEN));\r
+                                       if (strlen($v) > $MAXSTRLEN) $str .= '...';\r
+                                       $args[] = $str;\r
                                }\r
-                               $s .= $arr['function'].'('.implode(', ',$args).')';\r
-                               $s .= @sprintf("</font><font color=#808080 size=-1> %% line %4d, file: <a href=\"file:/%s\">%s</a></font>",\r
-                                       $arr['line'],$arr['file'],$arr['file']);\r
-                               $s .= "\n";\r
-                       }       \r
-                       $s .= '</pre>';\r
-                       if ($print) print $s;\r
-               }\r
+                       }\r
+                       $s .= $arr['function'].'('.implode(', ',$args).')';\r
+                       \r
+                       \r
+                       $s .= @sprintf($fmt, $arr['line'],$arr['file'],basename($arr['file']));\r
+                               \r
+                       $s .= "\n";\r
+               }       \r
+               if ($html) $s .= '</pre>';\r
+               if ($printOrArr) print $s;\r
+               \r
                return $s;\r
        }\r
-\r
        \r
 } // defined\r
 ?>
\ No newline at end of file
index 39ba17da1ef48f8529ecc846630c9bba20f095e4..f1760c941ba9e8beef18897d5226b937dcf42895 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
 \r
 /**\r
-  V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+  V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
index bffca670185049ef1cb4ab99d4e67f47fa294bf8..48f2f331e94aba1b41fdbacf5ed2d1d091361517 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
 \r
 /**\r
-  V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+  V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
index 9f2f116b039bb1e88d4d11603b52087dc7619020..23267cceafa0b160d5630cc9c9644de0af3885ba 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
 \r
 /**\r
-  V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+  V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
index 86b0be1dcd2de2308d98729c5ab03e0606dd8715..6feb613eef07b9e1e6cdd752d406385ff065f9e0 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
 \r
 /**\r
-  V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+  V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
index d051e566c3eb355b1847b0b429e466bd9af87f8d..2fcaf922f2dfd632455c402d27bc3c26703b033d 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
 \r
 /**\r
-  V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+  V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
index cfe413580bbfdabaa9d6ef0874fbdb8fb9b8309d..bddb6c8421de8a1aa046aeab7b795664d7104e6d 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
 \r
 /**\r
-  V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+  V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
@@ -13,7 +13,6 @@
 class ADODB2_mssql extends ADODB_DataDict {\r
        var $databaseType = 'mssql';\r
        \r
-       \r
        function MetaType($t,$len=-1,$fieldobj=false)\r
        {\r
                if (is_object($t)) {\r
@@ -69,8 +68,8 @@ class ADODB2_mssql extends ADODB_DataDict {
        \r
        \r
        function AddColumnSQL($tabname, $flds)\r
-       {       \r
-               if ($this->schema) $tabname = $this->schema.'.'.$tabname;\r
+       {\r
+               $tabname = $this->TableName ($tabname);\r
                $f = array();\r
                list($lines,$pkey) = $this->_GenFields($flds);\r
                $s = "ALTER TABLE $tabname $this->addCol";\r
@@ -82,9 +81,10 @@ class ADODB2_mssql extends ADODB_DataDict {
                return $sql;\r
        }\r
        \r
+       /*\r
        function AlterColumnSQL($tabname, $flds)\r
        {\r
-               if ($this->schema) $tabname = $this->schema.'.'.$tabname;\r
+               $tabname = $this->TableName ($tabname);\r
                $sql = array();\r
                list($lines,$pkey) = $this->_GenFields($flds);\r
                foreach($lines as $v) {\r
@@ -93,13 +93,15 @@ class ADODB2_mssql extends ADODB_DataDict {
 \r
                return $sql;\r
        }\r
+       */\r
        \r
        function DropColumnSQL($tabname, $flds)\r
        {\r
-               if ($this->schema) $tabname = $this->schema.'.'.$tabname;\r
-               if (!is_array($flds)) $flds = explode(',',$flds);\r
+               $tabname = $this->TableName ($tabname);\r
+               if (!is_array($flds))\r
+                       $flds = explode(',',$flds);\r
                $f = array();\r
-               $s = "ALTER TABLE $tabname";\r
+               $s = 'ALTER TABLE ' . $tabname;\r
                foreach($flds as $v) {\r
                        $f[] = "\n$this->dropCol $v";\r
                }\r
@@ -194,15 +196,29 @@ CREATE TABLE
 */\r
        function _IndexSQL($idxname, $tabname, $flds, $idxoptions)\r
        {\r
-               if (isset($idxoptions['REPLACE'])) $sql[] = "DROP INDEX $tabname.$idxname";\r
-               if (isset($idxoptions['UNIQUE'])) $unique = ' UNIQUE';\r
-               else $unique = '';\r
-               if (is_array($flds)) $flds = implode(', ',$flds);\r
-               if (isset($idxoptions['CLUSTERED'])) $clustered = ' CLUSTERED';\r
-               else $clustered = '';\r
+               $sql = array();\r
+               \r
+               if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {\r
+                       $sql[] = sprintf ($this->dropIndex, $tabname . '.' . $idxname);\r
+                       if ( isset($idxoptions['DROP']) )\r
+                               return $sql;\r
+               }\r
+               \r
+               if ( empty ($flds) ) {\r
+                       return $sql;\r
+               }\r
+               \r
+               $unique = isset($idxoptions['UNIQUE']) ? ' UNIQUE' : '';\r
+               $clustered = isset($idxoptions['CLUSTERED']) ? ' CLUSTERED' : '';\r
                \r
-               $s = "CREATE$unique$clustered INDEX $idxname ON $tabname ($flds)";\r
-               if (isset($idxoptions[$this->upperName])) $s .= $idxoptions[$this->upperName];\r
+               if ( is_array($flds) )\r
+                       $flds = implode(', ',$flds);\r
+               $s = 'CREATE' . $unique . $clustered . ' INDEX ' . $idxname . ' ON ' . $tabname . ' (' . $flds . ')';\r
+               \r
+               if ( isset($idxoptions[$this->upperName]) )\r
+                       $s .= $idxoptions[$this->upperName];\r
+               \r
+\r
                $sql[] = $s;\r
                \r
                return $sql;\r
index 068821a5c742694e0a22678b6812d83e76ee4370..2eed142e664bda19c5281d331b10796c903a83cf 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
 \r
 /**\r
-  V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+  V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
@@ -13,7 +13,8 @@
 class ADODB2_mysql extends ADODB_DataDict {\r
        var $databaseType = 'mysql';\r
        var $alterCol = ' MODIFY COLUMN';\r
-       var $quote = '`';\r
+       \r
+       var $dropIndex = 'DROP INDEX %s ON %s';\r
        \r
        function MetaType($t,$len=-1,$fieldobj=false)\r
        {\r
@@ -84,6 +85,7 @@ class ADODB2_mysql extends ADODB_DataDict {
                case 'T': return 'DATETIME';\r
                case 'L': return 'TINYINT';\r
                \r
+               case 'R':\r
                case 'I': return 'INTEGER';\r
                case 'I1': return 'TINYINT';\r
                case 'I2': return 'SMALLINT';\r
@@ -130,17 +132,40 @@ class ADODB2_mysql extends ADODB_DataDict {
                ON tbl_name (col_name[(length)],... )\r
        */\r
        \r
+       function DropIndexSQL ($idxname, $tabname)\r
+       {\r
+               return array(sprintf($this->dropIndex, $this->NameQuote($idxname), $this->TableName($tabname)));\r
+       }\r
+       \r
        function _IndexSQL($idxname, $tabname, $flds, $idxoptions)\r
        {\r
-               //if (isset($idxoptions['REPLACE'])) $sql[] = "DROP INDEX IF EXISTS $idxname";\r
-               if (isset($idxoptions['REPLACE'])) $sql[] = "DROP INDEX $idxname ON $tabname";\r
-               if (isset($idxoptions['FULLTEXT'])) $unique = ' FULLTEXT';\r
-               else if (isset($idxoptions['UNIQUE'])) $unique = ' UNIQUE';\r
-               else $unique = '';\r
+               $sql = array();\r
+               \r
+               if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {\r
+                       $sql[] = sprintf ($this->dropIndex, $idxname, $tabname);\r
+                       if ( isset($idxoptions['DROP']) )\r
+                               return $sql;\r
+               }\r
+               \r
+               if ( empty ($flds) ) {\r
+                       return $sql;\r
+               }\r
+               \r
+               if (isset($idxoptions['FULLTEXT'])) {\r
+                       $unique = ' FULLTEXT';\r
+               } elseif (isset($idxoptions['UNIQUE'])) {\r
+                       $unique = ' UNIQUE';\r
+               } else {\r
+                       $unique = '';\r
+               }\r
+               \r
+               if ( is_array($flds) )\r
+                       $flds = implode(', ',$flds);\r
+               $s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname . ' (' . $flds . ')';\r
+               \r
+               if ( isset($idxoptions[$this->upperName]) )\r
+                       $s .= $idxoptions[$this->upperName];\r
                \r
-               if (is_array($flds)) $flds = implode(', ',$flds);\r
-               $s = "CREATE$unique INDEX $idxname ON $tabname ($flds)";\r
-               if (isset($idxoptions[$this->upperName])) $s .= $idxoptions[$this->upperName];\r
                $sql[] = $s;\r
                \r
                return $sql;\r
index 17d71e12eca1b7bd1950c32390588f82d6602541..e3afdd8067ffcbc614bf782fcc7602d4089a262a 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
 \r
 /**\r
-  V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+  V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
@@ -40,7 +40,7 @@ class ADODB2_oci8 extends ADODB_DataDict {
                        return 'X2';\r
                        \r
                case 'NCLOB':\r
-               case 'CLOB';\r
+               case 'CLOB':\r
                        return 'XL';\r
                \r
                case 'LONG RAW':\r
@@ -211,18 +211,37 @@ end;
        \r
        function _IndexSQL($idxname, $tabname, $flds,$idxoptions)\r
        {\r
-               if (isset($idxoptions['REPLACE'])) $sql[] = "DROP INDEX $idxname";\r
+               $sql = array();\r
+               \r
+               if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {\r
+                       $sql[] = sprintf ($this->dropIndex, $idxname);\r
+                       if ( isset($idxoptions['DROP']) )\r
+                               return $sql;\r
+               }\r
+               \r
+               if ( empty ($flds) ) {\r
+                       return $sql;\r
+               }\r
+               \r
                if (isset($idxoptions['BITMAP'])) {\r
                        $unique = ' BITMAP'; \r
-               } else if (isset($idxoptions['UNIQUE'])) \r
+               } elseif (isset($idxoptions['UNIQUE'])) {\r
                        $unique = ' UNIQUE';\r
-               else \r
+               } else {\r
                        $unique = '';\r
+               }\r
+               \r
+               if ( is_array($flds) )\r
+                       $flds = implode(', ',$flds);\r
+               $s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname . ' (' . $flds . ')';\r
+               \r
+               if ( isset($idxoptions[$this->upperName]) )\r
+                       $s .= $idxoptions[$this->upperName];\r
                \r
-               if (is_array($flds)) $flds = implode(', ',$flds);\r
-               $s = "CREATE$unique INDEX $idxname ON $tabname ($flds)";\r
-               if (isset($idxoptions[$this->upperName])) $s .= $idxoptions[$this->upperName];\r
-               if (isset($idxoptions['oci8'])) $s .= $idxoptions['oci8'];\r
+               if (isset($idxoptions['oci8']))\r
+                       $s .= $idxoptions['oci8'];\r
+               \r
+\r
                $sql[] = $s;\r
                \r
                return $sql;\r
index 89914501a8f12d0f9e218b1d5cf8106c4011cc14..6279227fe05fad1c97d4d45b4cf61ea28a4637dc 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
 \r
 /**\r
-  V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+  V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
@@ -181,15 +181,31 @@ CREATE [ UNIQUE ] INDEX index_name ON table
        */\r
        function _IndexSQL($idxname, $tabname, $flds, $idxoptions)\r
        {\r
-               if (isset($idxoptions['REPLACE'])) $sql[] = "DROP INDEX $idxname";\r
-               if (isset($idxoptions['UNIQUE'])) $unique = ' UNIQUE';\r
-               else $unique = '';\r
+               $sql = array();\r
                \r
-               if (is_array($flds)) $flds = implode(', ',$flds);\r
-               $s = "CREATE$unique INDEX $idxname ON $tabname ";\r
-               if (isset($idxoptions['HASH'])) $s .= 'USING HASH ';\r
-               if (isset($idxoptions[$this->upperName])) $s .= $idxoptions[$this->upperName];\r
-               $s .= "($flds)";\r
+               if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {\r
+                       $sql[] = sprintf ($this->dropIndex, $idxname);\r
+                       if ( isset($idxoptions['DROP']) )\r
+                               return $sql;\r
+               }\r
+               \r
+               if ( empty ($flds) ) {\r
+                       return $sql;\r
+               }\r
+               \r
+               $unique = isset($idxoptions['UNIQUE']) ? ' UNIQUE' : '';\r
+               \r
+               $s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname . ' ';\r
+               \r
+               if (isset($idxoptions['HASH']))\r
+                       $s .= 'USING HASH ';\r
+               \r
+               if ( isset($idxoptions[$this->upperName]) )\r
+                       $s .= $idxoptions[$this->upperName];\r
+               \r
+               if ( is_array($flds) )\r
+                       $flds = implode(', ',$flds);\r
+               $s .= '(' . $flds . ')';\r
                $sql[] = $s;\r
                \r
                return $sql;\r
index 053581216280174e83659963b84d5772a7ce875e..37d1874b90432ccb1f001a4d3620b8c2fec4b362 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
 \r
 /**\r
-  V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+  V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
@@ -69,8 +69,8 @@ class ADODB2_sybase extends ADODB_DataDict {
        \r
        \r
        function AddColumnSQL($tabname, $flds)\r
-       {       \r
-               if ($this->schema) $tabname = $this->schema.'.'.$tabname;\r
+       {\r
+               $tabname = $this->TableName ($tabname);\r
                $f = array();\r
                list($lines,$pkey) = $this->_GenFields($flds);\r
                $s = "ALTER TABLE $tabname $this->addCol";\r
@@ -84,7 +84,7 @@ class ADODB2_sybase extends ADODB_DataDict {
        \r
        function AlterColumnSQL($tabname, $flds)\r
        {\r
-               if ($this->schema) $tabname = $this->schema.'.'.$tabname;\r
+               $tabname = $this->TableName ($tabname);\r
                $sql = array();\r
                list($lines,$pkey) = $this->_GenFields($flds);\r
                foreach($lines as $v) {\r
@@ -96,7 +96,7 @@ class ADODB2_sybase extends ADODB_DataDict {
        \r
        function DropColumnSQL($tabname, $flds)\r
        {\r
-               if ($this->schema) $tabname = $this->schema.'.'.$tabname;\r
+               $tabname = $this->TableName ($tabname);\r
                if (!is_array($flds)) $flds = explode(',',$flds);\r
                $f = array();\r
                $s = "ALTER TABLE $tabname";\r
@@ -194,15 +194,28 @@ CREATE TABLE
 */\r
        function _IndexSQL($idxname, $tabname, $flds, $idxoptions)\r
        {\r
-               if (isset($idxoptions['REPLACE'])) $sql[] = "DROP INDEX $tabname.$idxname";\r
-               if (isset($idxoptions['UNIQUE'])) $unique = ' UNIQUE';\r
-               else $unique = '';\r
-               if (is_array($flds)) $flds = implode(', ',$flds);\r
-               if (isset($idxoptions['CLUSTERED'])) $clustered = ' CLUSTERED';\r
-               else $clustered = '';\r
+               $sql = array();\r
+               \r
+               if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {\r
+                       $sql[] = sprintf ($this->dropIndex, $tabname . '.' . $idxname);\r
+                       if ( isset($idxoptions['DROP']) )\r
+                               return $sql;\r
+               }\r
                \r
-               $s = "CREATE$unique$clustered INDEX $idxname ON $tabname ($flds)";\r
-               if (isset($idxoptions[$this->upperName])) $s .= $idxoptions[$this->upperName];\r
+               if ( empty ($flds) ) {\r
+                       return $sql;\r
+               }\r
+               \r
+               $unique = isset($idxoptions['UNIQUE']) ? ' UNIQUE' : '';\r
+               $clustered = isset($idxoptions['CLUSTERED']) ? ' CLUSTERED' : '';\r
+               \r
+               if ( is_array($flds) )\r
+                       $flds = implode(', ',$flds);\r
+               $s = 'CREATE' . $unique . $clustered . ' INDEX ' . $idxname . ' ON ' . $tabname . ' (' . $flds . ')';\r
+               \r
+               if ( isset($idxoptions[$this->upperName]) )\r
+                       $s .= $idxoptions[$this->upperName];\r
+\r
                $sql[] = $s;\r
                \r
                return $sql;\r
index ed41f28f89964c732e814ff1ac60dfe18494c3b8..65b808eb25dbb1a0f4832a4c927b2c1882aca012 100644 (file)
@@ -11,7 +11,7 @@
 <body bgcolor="#FFFFFF">\r
 \r
 <h2>ADOdb Library for PHP</h2>\r
-<p>V4.01 23 Oct 2003 (c) 2000-2003 John Lim (jlim#natsoft.com)</p>\r
+<p>V4.11 27 Jan 2004 (c) 2000-2004 John Lim (jlim#natsoft.com)</p>\r
 <p><font size="1">This software is dual licensed using BSD-Style and LGPL. This \r
   means you can use it in compiled proprietary and commercial products.</font></p>\r
        <p>Useful ADOdb links:  <a href=http://php.weblogs.com/adodb>Download</a> &nbsp; <a href=http://php.weblogs.com/adodb_manual>Other Docs</a>\r
        <a href="#users">How People are using ADOdb</a><br>\r
        <a href="#bugs">Feature Requests and Bug Reports</a><br>\r
        </b><b><a href="#install">Installation</a><br>\r
-       <a href="#coding">Initializing Code and Connection Examples</a></b><br>\r
-       <b><a href="#hack">Hacking ADOdb Safely</a></b><br>\r
-        <font size="2"><a href=#adonewconnection>ADONewConnection</a></font> \r
+       <a href="#mininstall">Minimum Install</a><br>\r
+       <a href="#coding">Initializing Code and Connection Examples</a><br>\r
+       <font size="2"><a href=#adonewconnection>ADONewConnection</a></font> \r
        <font size="2"><a href=#adonewconnection>NewADOConnection</a></font><br>\r
+       <a href="#speed">High Speed ADOdb - tuning tips</a></b><br>\r
+       <b><a href="#hack">Hacking and Modifying ADOdb Safely</a><br>\r
+       <a href="#php5">PHP5 Features</a></b><br>\r
+       <font size="2"><a href=#php5iterators>foreach iterators</a> <a href=#php5exceptions>exceptions</a></font><br>\r
        <b> <a href="#drivers">Supported Databases</a></b><br>\r
-       <b> <a href="#quickstart">Tutorial</a></b><br>\r
+       <b> <a href="#quickstart">Tutorials</a></b><br>\r
        <a href="#ex1">Example 1: Select</a><br>\r
        <a href="#ex2">Example 2: Advanced Select</a><br>\r
        <a href="#ex3">Example 3: Insert</a><br>\r
@@ -45,7 +49,7 @@
        <a href="#caching">Caching</a><br>\r
        <a href="#pivot">Pivot Tables</a></b> \r
 <p><a href="#ref"><b>REFERENCE</b></a>\r
-<p> <font size="2">Variables: <a href="#adodb_countrecs">$ADODB_COUNTRECS</a> \r
+<p> <font size="2">Variables: <a href="#adodb_countrecs">$ADODB_COUNTRECS</a> <a href=#adodb_ansi_padding_off>$ADODB_ANSI_PADDING_OFF</a>\r
   <a href="#adodb_cache_dir">$ADODB_CACHE_DIR</a> </font><font size="2"><a href=#adodb_fetch_mode>$ADODB_FETCH_MODE</a> \r
   <a href=#adodb_lang>$ADODB_LANG</a><br>\r
   Constants: </font><font size="2"><a href=#adodb_assoc_case>ADODB_ASSOC_CASE</a> \r
@@ -56,7 +60,8 @@
   Executing SQL: <a href="#execute">Execute</a> <a href="#cacheexecute"><i>CacheExecute</i></a> \r
   <a href="#SelectLimit">SelectLimit</a> <a href="#cacheSelectLimit"><i>CacheSelectLimit</i></a> \r
   <a href="#param">Param</a> <a href="#prepare">Prepare</a> <a href=#preparesp>PrepareSP</a> \r
-  <a href="#parameter">Parameter</a><br>\r
+  <a href="#inparameter">InParameter</a> <a href="#outparameter">OutParameter</a>\r
+  <br>\r
   &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#getone">GetOne</a> \r
   <a href="#cachegetone"><i>CacheGetOne</i></a> <a href="#getrow">GetRow</a> <a href="#cachegetrow"><i>CacheGetRow</i></a> \r
   <a href="#getall">GetAll</a> <a href="#cachegetall"><i>CacheGetAll</i></a> <a href="#getcol">GetCol</a> \r
   &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#executecursor">ExecuteCursor</a> \r
   (oci8 only)<br>\r
   Generates SQL strings: <a href="#getupdatesql">GetUpdateSQL</a> <a href="#getinsertsql">GetInsertSQL</a> \r
-  <a href="#concat">Concat</a> <a href="#ifnull">IfNull</a> <a href="#substr">substr</a> <a href="#qstr"></a><a href="#param">Param</a> \r
+  <a href="#concat">Concat</a> <a href="#ifnull">IfNull</a> <a href="#length">length</a> <a href="#random">random</a> <a href="#substr">substr</a> \r
+  <a href="#qstr">qstr</a> <a href="#param">Param</a> \r
   <a href="#prepare"></a><a href="#OffsetDate">OffsetDate</a> <a href="#SQLDate">SQLDate</a> \r
-  <a href="#dbdate">DBDate</a> <a href="#dbtimestamp"></a> <a href="#dbtimestamp">DBTimeStamp</a><br>\r
+  <a href="#dbdate">DBDate</a> <a href="#dbtimestamp"></a> <a href="#dbtimestamp">DBTimeStamp</a>\r
+  <br>\r
   Blobs: <a href="#updateblob">UpdateBlob</a> <a href="#updateclob">UpdateClob</a> \r
   <a href="#updateblobfile">UpdateBlobFile</a> <a href="#blobencode">BlobEncode</a> \r
   <a href="#blobdecode">BlobDecode</a><br>\r
   <a href="#begintrans">BeginTrans</a> <a href="#committrans">CommitTrans</a> \r
   <a href="#rollbacktrans">RollbackTrans</a> <br>\r
   Fetching Data: </font> <font size="2"><a href="#setfetchmode">SetFetchMode</a><br>\r
-  Strings: <a href="#concat">concat</a> <a href="#qstr">qstr</a> <a href="#quote">quote</a> <a href="#substr">substr</a><br>\r
+  Strings: <a href="#concat">concat</a> <a href="#length">length</a>  <a href="#qstr">qstr</a> <a href="#quote">quote</a> <a href="#substr">substr</a><br>\r
   Dates: <a href="#dbdate">DBDate</a> <a href="#dbtimestamp">DBTimeStamp</a> <a href="#unixdate">UnixDate</a> \r
   <a href="#unixtimestamp">UnixTimeStamp</a> <a href="#OffsetDate">OffsetDate</a> \r
   <a href="#SQLDate">SQLDate</a> <br>\r
-  Row Management: <a href="#affected_rows">Affected_Rows</a> <a href="#inserted_id">Insert_ID</a> \r
+  Row Management: <a href="#affected_rows">Affected_Rows</a> <a href="#inserted_id">Insert_ID</a>  <a href=#rowlock>RowLock</a>\r
   <a href="#genid">GenID</a> <a href=#createseq>CreateSequence</a> <a href=#dropseq>DropSequence</a> \r
   <br>\r
   Error Handling: <a href="#errormsg">ErrorMsg</a> <a href="#errorno">ErrorNo</a> \r
   <a href="#serverinfo">ServerInfo</a> <br>\r
   Statistics and Query-Rewriting: <a href="#logsql">LogSQL</a> <a href="#fnexecute">fnExecute \r
   and fnCacheExecute</a><br>\r
-  </font><font size="2">Deprecated: <a href="#bind">Bind</a> <a href="#blankrecordset">BlankRecordSet</a></font><br>\r
+  </font><font size="2">Deprecated: <a href="#bind">Bind</a> <a href="#blankrecordset">BlankRecordSet</a>\r
+  <a href="#parameter">Parameter</a></font>\r
   <a href="#adorecordSet"><b><br>\r
   ADORecordSet</b></a><br>\r
   <font size="2">\r
@@ -176,7 +184,7 @@ visit <a href="http://php.weblogs.com/adodb-cool-applications">http://php.weblog
 <p>Make sure you are running PHP 4.0.4 or later. \r
   Unpack all the files into a directory accessible by your webserver.</p>\r
 <p>To test, try modifying some of the tutorial examples. Make sure you customize \r
-  the connection settings correctly. You can debug using:</p>\r
+  the connection settings correctly. You can debug using <i>$db->debug = true</i> as shown below:</p>\r
 <pre>&lt;?php\r
        include('adodb/adodb.inc.php');\r
        $db = <a href="#adonewconnection">ADONewConnection</a>($dbdriver); # eg 'mysql' or 'postgres'\r
@@ -187,18 +195,32 @@ visit <a href="http://php.weblogs.com/adodb-cool-applications">http://php.weblog
        print_r($rs-><a href="#getrows">GetRows</a>());\r
        print &quot;&lt;/pre&gt;&quot;;\r
 ?&gt;</pre>\r
-<h3>Code Initialization<a name="coding"></a></h3>\r
+\r
+ <h3>Minimum Install<a name=mininstall></a></h3>\r
+<p>For developers who want to release a minimal install of ADOdb, you will need:\r
+<ul>\r
+<li>adodb.inc.php\r
+<li>adodb-lib.inc.php\r
+<li>adodb-time.inc.php\r
+<li>adodb-csvlib.inc.php (if you use cached recordsets - CacheExecute(), etc)\r
+<li>adodb-error.inc.php and lang/adodb-$lang.inc.php (if you use MetaError())\r
+<li>drivers/adodb-$database.inc.php\r
+<li>license.txt (for legal reasons)\r
+</ul>\r
+\r
+<h3>Code Initialization Examples<a name="coding"></a></h3>\r
 <p>When running ADOdb, at least two files are loaded. First is adodb/adodb.inc.php, \r
  which contains all functions used by all database classes. The code specific \r
  to a particular database is in the adodb/driver/adodb-????.inc.php file.</p>\r
+ <a name="adonewconnection">\r
 <p>For example, to connect to a mysql database:</p>\r
 <pre>\r
 include('/path/to/set/here/adodb.inc.php');\r
 $conn = &amp;ADONewConnection('mysql');\r
 </pre>\r
 <p>Whenever you need to connect to a database, you create a Connection object \r
-  using the <a name="adonewconnection">ADONewConnection</a>($driver) function. \r
-  NewADOConnection($driver) is an alternative name for the same function.</p>\r
+  using the <b>ADONewConnection</b></a>($driver) function. \r
+  <b>NewADOConnection</b>($driver) is an alternative name for the same function.</p>\r
 \r
 <p>At this point, you are not connected to the database. You will first need to decide\r
 whether to use <i>persistent</i> or <i>non-persistent</i> connections. The advantage of <i>persistent</i>\r
@@ -215,6 +237,7 @@ the creation of a new connection.
 PHP will share the same connection. This can cause problems if the connections are meant to \r
 different databases. The solution is to always use different userid's for different databases,\r
  or use NConnect().\r
+\r
 <h3>Examples of Connecting to Databases</h3>\r
 <h4>MySQL and Most Other Database Drivers</h4>\r
 <p>MySQL connections are very straightforward, and the parameters are identical \r
@@ -240,19 +263,24 @@ You define the database in the $host parameter:
        $conn = &ADONewConnection('ibase'); \r
        $conn->PConnect('localhost:c:\ibase\employee.gdb','sysdba','masterkey');\r
 </pre>\r
-\r
+<h4>SQLite</h4>\r
+Sqlite will create database if it does not exist.\r
+<pre>\r
+       $conn = &ADONewConnection('sqlite'); \r
+       $conn->PConnect('c:\path\to\sqlite.db'); # sqlite will create if does not exist\r
+</pre>\r
 <h4>Oracle</h4>\r
 <p>With Oracle, you can connect in multiple ways.</p>\r
 <p>a. PHP and Oracle reside on the same machine, use default SID.</p>\r
 <pre>  $conn-&gt;Connect(false, 'scott', 'tiger');</pre>\r
-<p>b. TNS Name defined, eg. 'TNSDB'</p>\r
-<pre>  $conn-&gt;PConnect(false, 'scott', 'tiger', TNSDB');\r
+<p>b. TNS Name defined, eg. 'myTNS'</p>\r
+<pre>  $conn-&gt;PConnect(false, 'scott', 'tiger', 'myTNS');\r
 </pre>\r
 <p>or</p>\r
-<pre>  $conn-&gt;PConnect('TNSDB', 'scott', 'tiger');</pre>\r
-<p>c. Host address and SID</p>\r
+<pre>  $conn-&gt;PConnect('myTNS', 'scott', 'tiger');</pre>\r
+<p>c. Host Address and SID</p>\r
 <pre>  $conn-&gt;Connect('192.168.0.1', 'scott', 'tiger', 'SID');</pre>\r
-<p>d. Host address and Service Name</p>\r
+<p>d. Host Address and Service Name</p>\r
 <pre>  $conn-&gt;Connect('192.168.0.1', 'scott', 'tiger', 'servicename');</pre>\r
 <a name=dsnless></a>\r
 <h4>DSN-less ODBC (access and mssql examples)</h4>\r
@@ -262,7 +290,7 @@ You define the database in the $host parameter:
 <p>For Microsoft Access:</a></p>\r
 <pre>\r
        $db =& ADONewConnection('access');\r
-       $dsn = <strong>"Driver=&#123;Microsoft Access Driver (*.mdb)&#125;;Dbq=d:\northwind.mdb;Uid=Admin;Pwd=;";</strong>\r
+       $dsn = <strong>"Driver=&#123;Microsoft Access Driver (*.mdb)&#125;;Dbq=d:\\northwind.mdb;Uid=Admin;Pwd=;";</strong>\r
        $db->Connect($dsn);\r
 </pre>\r
 For Microsoft SQL Server: \r
@@ -278,7 +306,6 @@ using the ADOdb library and Microsoft's ADO:
 <pre>\r
 &lt;?php\r
        include('adodb.inc.php'); \r
-       ADOLoadCode("ado_mssql");\r
        $db = &ADONewConnection("ado_mssql");\r
        print "&lt;h1>Connecting DSN-less $db->databaseType...&lt;/h1>";\r
                \r
@@ -290,10 +317,36 @@ using the ADOdb library and Microsoft's ADO:
        $arr = $rs->GetArray();\r
        print_r($arr);\r
 ?>\r
-</pre>\r
-\r
-<p></p><a name=hack></a>\r
-<h1>Hacking ADOdb Safely</h1>\r
+</pre><a name=speed></a>\r
+<h2>High Speed ADOdb - tuning tips</h2>\r
+<p>ADOdb is a big class library, yet it <a href=http://phplens.com/lens/adodb/>consistently beats</a> all other PHP class \r
+  libraries in performance. This is because it is designed in a layered fashion, \r
+  like an onion, with the fastest functions in the innermost layer. Stick to the \r
+  following functions for best performance:</p>\r
+<table width="40%" border="1" align="center">\r
+  <tr>\r
+    <td><div align="center"><b>Innermost Layer</b></div></td>\r
+  </tr>\r
+  <tr> \r
+    <td><p align="center">Connect, PConnect, NConnect<br>\r
+        Execute, CacheExecute<br>\r
+        SelectLimit, SelectLimit<br>\r
+        MoveNext, Close <br>\r
+               qstr, Affected_Rows, Insert_ID</p></td>\r
+  </tr>\r
+</table>\r
+<p>The fastest way to access the fields is by accessing the array $recordset->fields \r
+  directly. Also set the global variables <a href="#adodb_fetch_mode">$ADODB_FETCH_MODE</a> \r
+  = ADODB_FETCH_NUM, and (for oci8, ibase/firebird and odbc) <a href="#adodb_countrecs">$ADODB_COUNTRECS</a> = false \r
+  before you connect to your database. At the time of writing (Dec 2003).</p>\r
+<p>Consider using bind parameters if your database supports it, as it improves \r
+  query plan reuse. Use ADOdb's performance tuning system to identify bottlenecks \r
+  quickly. At the time of writing (Dec 2003), this means oci8 and odbc drivers.</p>\r
+<p>Lastly make sure you have a PHP accelerator cache installed such as APC, Turck \r
+  MMCache, Zend Accelerator or ionCube.</p>\r
+ <p>Informix tips: Disable scrollable cursors with $db->cursorType = 0.\r
+<p><a name=hack></a> </p>\r
+<h2>Hacking ADOdb Safely</h2>\r
 <p>You might want to modify ADOdb for your own purposes. Luckily you can\r
 still maintain backward compatibility by sub-classing ADOdb and using the $ADODB_NEWCONNECTION\r
 variable. $ADODB_NEWCONNECTION allows you to override the behaviour of ADONewConnection().\r
@@ -339,6 +392,35 @@ include_once('adodb.inc.php');
 \r
 </pre>\r
 <p>Don't forget to call the constructor of the parent class.\r
+<a name="php5">\r
+<h2>PHP5 Features</h2>\r
+ ADOdb 4.02 or later will transparently determine which version of PHP you are using.\r
+If PHP5 is detected, the following features become available:\r
+<ul>\r
+<a name="php5iterators">\r
+<li><b>Foreach iterators</b>: This is a very natural way of going through a recordset:\r
+<pre>\r
+       $ADODB_FETCH_MODE = ADODB_FETCH_NUM;\r
+       $rs = $db->Execute($sql);\r
+       foreach($rs as $k => $row) {\r
+               echo "r1=".$row[0]." r2=".$row[1]."&lt;br>";\r
+       }\r
+</pre>\r
+<p>\r
+<a name="php5exceptions">\r
+<li><b>Exceptions</b>: Just include <i>adodb-exceptions.inc.php</i> and you can now \r
+catch exceptions on errors as they occur.\r
+<pre>\r
+       <b>include("../adodb-exceptions.inc.php");</b> \r
+       include("../adodb.inc.php");     \r
+       try { \r
+               $db = NewADOConnection("oci8"); \r
+               $db->Connect('','scott','bad-password'); \r
+       } catch (exception $e) { \r
+               var_dump($e); \r
+       } \r
+</pre>\r
+</ul> \r
 <h3><a name="drivers"></a>Databases Supported</h3>\r
 <table width="100%" border="1">\r
   <tr valign="top"> \r
@@ -641,7 +723,7 @@ include_once('adodb.inc.php');
   </tr>\r
   <p> \r
 </table>\r
-<h3></h3>\r
+\r
 <p>The &quot;Tested&quot; column indicates how extensively the code has been tested \r
   and used. <br>\r
   A = well tested and used by many people<br>\r
@@ -659,7 +741,7 @@ include_once('adodb.inc.php');
   is executed, so you can selectively choose which recordsets to count.</p>\r
 <p> \r
 <hr>\r
-<h1>Tutorial<a name="quickstart"></a></h1>\r
+<h1>Tutorials<a name="quickstart"></a></h1>\r
 <h3>Example 1: Select Statement<a name="ex1"></a></h3>\r
 <p>Task: Connect to the Access Northwind DSN, display the first 2 columns of each \r
   row.</p>\r
@@ -1124,7 +1206,7 @@ include('tohtml.inc.php');
 $c = NewADOConnection('mysql');\r
 $c->PConnect('localhost','root','','northwind');\r
 $rs=$c->Execute('select * from productsz'); #invalid table productsz');\r
-if ($rs) $rs2html($rs);\r
+if ($rs) rs2html($rs);\r
 ?>\r
 </pre>\r
 <p> If you want to log the error message, you can do so by defining the following \r
@@ -1145,7 +1227,7 @@ include('tohtml.inc.php');
 $c = NewADOConnection('mysql');\r
 $c->PConnect('localhost','root','','northwind');\r
 $rs=$c->Execute('select * from productsz'); ## invalid table productsz\r
-if ($rs) $rs2html($rs);\r
+if ($rs) rs2html($rs);\r
 ?>\r
 </pre>\r
 The following message will be logged in the error.log file: \r
@@ -1164,7 +1246,7 @@ include('tohtml.inc.php');
 $c = NewADOConnection('mysql');\r
 $c->PConnect('localhost','root','','northwind');\r
 $rs=$c->Execute('select * from productsz'); #invalid table productsz');\r
-if ($rs) $rs2html($rs);\r
+if ($rs) rs2html($rs);\r
 else &#123;\r
        <b>$e = ADODB_Pear_Error();\r
        echo '&lt;p>',$e->message,'&lt;/p>';</b>\r
@@ -1237,7 +1319,7 @@ $<font color="#663300">rs</font> = $<font color="#663300">conn</font>->CacheExec
 </font> <p><font color="#000000">Since ADOdb 2.30, we support the generation of \r
 SQL to create pivot tables, also known as cross-tabulations. For further explanation \r
 read this DevShed <a href=http://www.devshed.com/Server_Side/MySQL/MySQLWiz/>Cross-Tabulation \r
-tutorial</a>. We assume that your database supports the SQL case-when expression. </font></p> \r
+tutorial. We assume that your database supports the SQL case-when expression. </font></p> \r
 <font color="#000000"> \r
 <p>In this example, we will use the Northwind database from Microsoft. In the \r
   database, we have a products table, and we want to analyze this table by <i>suppliers \r
@@ -1396,6 +1478,10 @@ tutorial</a>. We assume that your database supports the SQL case-when expression
 <p>chown -R apache /path/to/adodb/cache<br>\r
   chgrp -R apache /path/to/adodb/cache </p>\r
 <font color="#000000">\r
+<h3><a name="adodb_ansi_padding_off"></a>$ADODB_ANSI_PADDING_OFF</h3>\r
+<p>Determines whether to right trim CHAR fields (and also VARCHAR for ibase/firebird).\r
+Set to true to trim. Default is false. Currently works for oci8po, ibase and firebird \r
+drivers. Added in ADOdb 4.01.\r
 <h3><font color="#000000"><a name="adodb_lang"></a></font>$ADODB_LANG</h3>\r
 <p>Determines the language used in MetaErrorMsg(). The default is 'en', for English. \r
 To find out what languages are supported, see the files \r
@@ -1562,7 +1648,7 @@ ADODB_NEVER_PERSIST  before you call PConnect.
 <p><b>NConnect<a name="nconnect"></a>($host,[$user],[$password],[$database])</b></p>\r
 <p>Always force a new connection. In contrast, PHP sometimes reuses connections \r
        when you use Connect() or PConnect(). Currently works only on mysql (PHP 4.3.0 \r
-       or later) and oci8-derived drivers. For other drivers, NConnect() works like \r
+       or later), postgresql and oci8-derived drivers. For other drivers, NConnect() works like \r
        Connect(). \r
 <font color="#000000"> \r
 <p><b>Execute<a name="execute"></a>($sql,$inputarr=false)</b></p>\r
@@ -1587,6 +1673,7 @@ ADODB_NEVER_PERSIST  before you call PConnect.
 Variable binding speeds the compilation and caching of SQL statements, leading \r
 to higher performance. Currently Oracle, Interbase and ODBC supports variable binding. \r
 Interbase/ODBC style ? binding is emulated in databases that do not support binding. \r
+Note that you do not have to quote strings if you use binding.\r
 <p> Variable binding in the odbc, interbase and oci8po drivers. \r
 <pre>\r
 $rs = $db->Execute('select * from table where val=?', array('10'));\r
@@ -1654,7 +1741,7 @@ only with SELECT statements.
     # $rs is now just like any other ADOdb recordset object<br>    rs2html($rs);</pre>\r
 <p>ExecuteCursor() is a helper function that does the following internally: \r
 <pre>\r
-       $stmt = $db->Prepare("BEGIN :RS := SP_FOO(); END;");\r
+       $stmt = $db->Prepare("BEGIN :RS := SP_FOO(); END;", true); \r
        $db->Parameter($stmt, $cur, 'RS', false, -1, OCI_B_CURSOR);\r
        $rs = $db->Execute($stmt);</pre>\r
 <p><b>SelectLimit<a name="selectlimit"></a>($sql,$numrows=-1,$offset=-1,$inputarr=false)</b></p>\r
@@ -2048,7 +2135,7 @@ convention.
 for ($i=0; $i &lt; $max; $i++)<br></font>      $DB-&gt;<font color="#000000">Execute($stmt,array((string) rand(), $i));\r
 </font></pre>\r
 <font color="#000000"> \r
-<p>Also see PrepareSP() and Parameter() below. Only supported internally by interbase, \r
+<p>Also see InParameter(), OutParameter() and PrepareSP() below. Only supported internally by interbase, \r
   oci8 and selected ODBC-based drivers, otherwise it is emulated. There is no \r
   performance advantage to using Prepare() with emulation. \r
 <p> Important: Due to limitations or bugs in PHP, if you are getting errors when \r
@@ -2059,6 +2146,19 @@ for ($i=0; $i &lt; $max; $i++)<br></font>        $DB-&gt;<font color="#000000">Execute(
   the function that checks whether a $field is null for the given database, and \r
   if null, change the value returned to $nullReplacementValue. Eg.</p>\r
 <pre>$sql = <font color="#993300">'SELECT '</font>.$db-&gt;IfNull('name', <font color="#993300">&quot;'- unknown -'&quot;</font>).<font color="#993300"> ' FROM table'</font>;</pre>\r
+\r
+<p><b>length<a name="length"></a></b></p>\r
+<p>This is not a function, but a property. Some databases have "length" and others "len"\r
+as the function to measure the length of a string. To use this property:\r
+<pre>\r
+  $sql = <font color="#993300">"SELECT "</font>.$db->length.<font color="#993300">"(field) from table"</font>;\r
+  $rs = $db->Execute($sql);\r
+</pre>\r
+\r
+<p><b>random<a name="random"></a></b></p>\r
+<p>This is not a function, but a property. This is a string that holds the sql to\r
+generate a random number between 0.0 and 1.0 inclusive.\r
+\r
 <p><b>substr<a name="substr"></a></b></p>\r
 <p>This is not a function, but a property. Some databases have "substr" and others "substring"\r
 as the function to retrieve a sub-string. To use this property:\r
@@ -2068,6 +2168,8 @@ as the function to retrieve a sub-string. To use this property:
 </pre>\r
 <p>For all databases, the 1st parameter of <i>substr</i> is the field, the 2nd is the\r
 offset (1-based) to the beginning of the sub-string, and the 3rd is the length of the sub-string.\r
+\r
+\r
 <p><b>Param<a name="param"></a>($name )</b></p>\r
 <p>Generates a bind placeholder portably. For most databases, the bind placeholder \r
   is "?". However some databases use named bind parameters such as Oracle, eg \r
@@ -2086,12 +2188,72 @@ $stmt = $DB-&gt;Execute($stmt,array('one','two'));
   PrepareSP() allows you to do so. \r
 <p>Returns the same array or $sql string as Prepare( ) above. If you do not need \r
   to bind to return values, you should use Prepare( ) instead.</p>\r
-<p>For examples of usage of PrepareSP( ), see Parameter( ) below. \r
+<p>For examples of usage of PrepareSP( ), see InParameter( ) below. \r
 <p>Note: in the mssql driver, preparing stored procedures requires a special function \r
   call, mssql_init( ), which is called by this function. PrepareSP( ) is available \r
   in all other drivers, and is emulated by calling Prepare( ). </p>\r
+<p><b> InParameter<a name="inparameter"></a>($stmt, $var, $name,\r
+  $maxLen = 4000, $type = false )</b></p>\r
+Binds a PHP variable as input to a stored procedure variable. The parameter <i>$stmt</i>\r
+ is the value returned by PrepareSP(), <i>$var</i> is the PHP variable you want to bind, $name\r
+ is the name of the stored procedure variable. Optional is <i>$maxLen</i>, the maximum length of the\r
+ data to bind, and $type which is database dependant. \r
+ Consult <a href=http://php.net/mssql_bind>mssql_bind</a> and <a href=http://php.net/ocibindbyname>ocibindbyname</a> docs\r
+  at php.net for more info on legal values for $type. \r
+ <p>\r
+InParameter() is a wrapper function that calls Parameter() with $isOutput=false. \r
+The advantage of this function is that it is self-documenting, because\r
+the $isOutput parameter is no longer needed.  Only for mssql \r
+  and oci8 currently.\r
+  <p>Here is an example using oci8:\r
+  <pre><font color="green"># For oracle, Prepare and PrepareSP are identical</font>\r
+$stmt = $db-&gt;PrepareSP(\r
+       <font color="#993300">&quot;declare RETVAL integer; \r
+       begin\r
+       :RETVAL := </font><font color="#993300">SP_RUNSOMETHING</font><font color="#993300">(:myid,:group);\r
+       end;&quot;</font>);\r
+$db-&gt;InParameter($stmt,$id,'myid');\r
+$db-&gt;InParameter($stmt,$group,'group',64);\r
+$db-&gt;OutParameter($stmt,$ret,'RETVAL');<br>$db-&gt;Execute($stmt);\r
+</pre>\r
+<p> The same example using mssql:</p>\r
+</font> \r
+<pre><font color="#000000"><font color="green"># @RETVAL = SP_RUNSOMETHING @myid,@group</font>\r
+$stmt = $db-&gt;PrepareSP(<font color="#993333">'<font color="#993300">SP_RUNSOMETHING</font>'</font>); <br><font color="green"># note that the parameter name does not have @ in front!</font>\r
+$db-&gt;InParameter($stmt,$id,'myid');\r
+$db-&gt;InParameter($stmt,$group,'group',64);\r
+<font color="green"># return value in mssql - RETVAL is hard-coded name</font> \r
+$db-&gt;OutParameter($stmt,$ret,'RETVAL');\r
+$db-&gt;Execute($stmt); </font></pre>\r
+\r
+<p>Note that the only difference between the oci8 and mssql implementations is $sql.</p>\r
+  <p>\r
+ If $type parameter is set to false, in mssql, $type will be dynamicly determined \r
+based on the type of the PHP variable passed <font face="Courier New, Courier, mono">(string \r
+=&gt; SQLCHAR, boolean =&gt;SQLINT1, integer =&gt;SQLINT4 or float/double=&gt;SQLFLT8)</font>.\r
+<p> \r
+In oci8, $type can be set to OCI_B_FILE (Binary-File), OCI_B_CFILE (Character-File), \r
+OCI_B_CLOB (Character-LOB), OCI_B_BLOB (Binary-LOB) and OCI_B_ROWID (ROWID). To \r
+pass in a null, use<font face="Courier New, Courier, mono"> $db-&gt;Parameter($stmt, \r
+$null=null, 'param')</font>. \r
+  <p><b> OutParameter<a name="outparameter"></a>($stmt, $var, $name, \r
+  $maxLen = 4000, $type = false )</b></p>\r
+  Binds a PHP variable as output from a stored procedure variable. The parameter <i>$stmt</i>\r
+ is the value returned by PrepareSP(), <i>$var</i> is the PHP variable you want to bind, <i>$name</i>\r
+ is the name of the stored procedure variable. Optional is <i>$maxLen</i>, the maximum length of the\r
+ data to bind, and <i>$type</i> which is database dependant. \r
+  <p>\r
+  OutParameter() is a wrapper function that calls Parameter() with $isOutput=true. \r
+  The advantage of this function is that it is self-documenting, because\r
+the $isOutput parameter is no longer needed.  Only for mssql \r
+  and oci8 currently.\r
+<p>\r
+For an example, see <a href=#inparameter>InParameter</a>.\r
+\r
 <p><b> Parameter<a name="parameter"></a>($stmt, $var, $name, $isOutput=false, \r
   $maxLen = 4000, $type = false )</b></p>\r
+<p>Note: This function is deprecated, because of the new InParameter() and OutParameter() functions.\r
+These are superior because they are self-documenting, unlike Parameter().\r
 <p>Adds a bind parameter suitable for return values or special data handling (eg. \r
   LOBs) after a statement has been prepared using PrepareSP(). Only for mssql \r
   and oci8 currently. The parameters are:<br>\r
@@ -2105,25 +2267,6 @@ $stmt = $DB-&gt;Execute($stmt,array('one','two'));
   [$<b>type</b>] Consult <a href="http://php.net/mssql_bind">mssql_bind</a> and \r
   <a href="http://php.net/ocibindbyname">ocibindbyname</a> docs at php.net for \r
   more info on legal values for type.</p>\r
-<p> Example:</p>\r
-</font> \r
-<pre><font color="#000000"><font color="green"># @RETVAL = SP_RUNSOMETHING @myid,@group</font><br>$stmt = $db-&gt;PrepareSP(<font color="#993333">'<font color="#993300">SP_RUNSOMETHING</font>'</font>); <br><font color="green"># note that the parameter name does not have @ in front!</font><br>$db-&gt;Parameter($stmt,$id,'myid'); <br>$db-&gt;Parameter($stmt,$group,'group',false,64);<br><font color="green"># return value in mssql - RETVAL is hard-coded name</font> <br>$db-&gt;Parameter($stmt,$ret,'RETVAL',true); <br>$db-&gt;Execute($stmt); </font></pre>\r
-<p><font color="#000000">An oci8 example: </font></p>\r
-<font color="#000000"> \r
-<pre><font color="green"># For oracle, Prepare and PrepareSP are identical</font>\r
-$stmt = $db-&gt;PrepareSP(\r
-       <font color="#993300">&quot;declare RETVAL integer; <br>         begin <br>             :RETVAL := </font><font color="#993300">SP_RUNSOMETHING</font><font color="#993300">(:myid,:group); <br>         end;&quot;</font>);<br>$db-&gt;Parameter($stmt,$id,'myid');<br>$db-&gt;Parameter($stmt,$group,'group',false,64);\r
-$db-&gt;Parameter($stmt,$ret,'RETVAL',true);<br>$db-&gt;Execute($stmt);\r
-</pre>\r
-<p>Note that the only difference between the oci8 and mssql implementations is \r
-  the syntax of $sql.</p>\r
-If $type parameter is set to false, in mssql, $type will be dynamicly determined \r
-based on the type of the PHP variable passed <font face="Courier New, Courier, mono">(string \r
-=&gt; SQLCHAR, boolean =&gt;SQLINT1, integer =&gt;SQLINT4 or float/double=&gt;SQLFLT8)</font>. \r
-In oci8, $type can be set to OCI_B_FILE (Binary-File), OCI_B_CFILE (Character-File), \r
-OCI_B_CLOB (Character-LOB), OCI_B_BLOB (Binary-LOB) and OCI_B_ROWID (ROWID). To \r
-pass in a null, use<font face="Courier New, Courier, mono"> $db-&gt;Parameter($stmt, \r
-$null=null, 'param')</font>. \r
 <p>Lastly, in oci8, bind parameters can be reused without calling PrepareSP( ) \r
   or Parameters again. This is not possible with mssql. An oci8 example:</p>\r
 <pre>$id = 0; $i = 0;\r
@@ -2231,7 +2374,17 @@ Usage:
        echo $perf->SuspiciousSQL();\r
        echo $perf->ExpensiveSQL();\r
 </pre>\r
-<p>Also see <a href=docs-perf.htm>Performance Monitor</a>. \r
+<p>One limitation of logging is that rollback also prevents SQL from being logged.\r
+<p>\r
+If you prefer to use another name for the table used to store the SQL, you can override it by calling \r
+adodb_perf::table($tablename), where $tablename is the new table name (you will still need to manually\r
+create the table yourself). An example:\r
+<pre>\r
+       include('adodb.inc.php');\r
+       include('adodb-perf.inc.php');\r
+       adodb_perf::table('my_logsql_table');\r
+</pre>\r
+Also see <a href=docs-perf.htm>Performance Monitor</a>. \r
 <p><font color="#000000"><b>fnExecute and fnCacheExecute properties<a name="fnexecute" id="fnexecute"></a></b></font></p>\r
 <p>These two properties allow you to define bottleneck functions for all sql statements \r
   processed by ADOdb. This allows you to perform statistical analysis and query-rewriting \r
@@ -2318,8 +2471,18 @@ printf(&quot;&lt;p&gt;Total queries=%d; total cached=%d&lt;/p&gt;&quot;,$EXECS+$
 <p>Returns the last autonumbering ID inserted. Returns false if function not supported. \r
 </p>\r
 <p>Only supported by databases that support auto-increment or object id's, such \r
-  as PostgreSQL, MySQL and MSSQL currently. PostgreSQL returns the OID, which \r
+  as PostgreSQL, MySQL and MS SQL Server currently. PostgreSQL returns the OID, which \r
   can change on a database reload.</p>\r
+<p><b>RowLock<a name="rowlock"></a>($table,$where)</b></p>\r
+<p>Lock a table row for the duration of a transaction. For example to lock record $id in table1:\r
+<pre>\r
+       $DB->StartTrans();\r
+       $DB->RowLock("table1","rowid=$id");\r
+       $DB->Execute($sql1);\r
+       $DB->Execute($sql2);\r
+       $DB->CompleteTrans();\r
+</pre>\r
+<p>Supported in db2, interbase, informix, mssql, oci8, postgres, sybase.\r
 <p><b>MetaDatabases<a name="metadatabases"></a>()</b></p>\r
 <p>Returns a list of databases available on the server as an array. You have to \r
   connect to the server first. Only available for ODBC, MySQL and ADO.</p>\r
@@ -2333,10 +2496,15 @@ printf(&quot;&lt;p&gt;Total queries=%d; total cached=%d&lt;/p&gt;&quot;,$EXECS+$
 <p>You can define a mask for matching. For example, setting $mask = 'TMP%' will \r
   match all tables that begin with 'TMP'. Currently only mssql, oci8, odbc_mssql \r
   and postgres* support $mask. \r
-<p><b>MetaColumns<a name="metacolumns"></a>($table)</b></p>\r
+<p><b>MetaColumns<a name="metacolumns"></a>($table,$toupper=true)</b></p>\r
 <p>Returns an array of ADOFieldObject's, one field object for every column of \r
-  $table. Currently Sybase does not recognise date types, and ADO cannot identify \r
-  the correct data type (so we default to varchar).. </p>\r
+  $table. A field object is a class instance with (name, type, max_length) defined.\r
+  Currently Sybase does not recognise date types, and ADO cannot identify \r
+  the correct data type (so we default to varchar).   \r
+ <p> The $toupper parameter determines whether we uppercase the table name \r
+ (required for some databases).\r
+ <p>For schema support, pass in the $table parameter, "$schema.$tablename". This is only\r
+ supported for selected databases.\r
 <p><b>MetaColumnNames<a name="metacolumnames"></a>($table)</b></p>\r
 <p>Returns an array of column names for $table. \r
 <p><font color="#000000"><b>MetaPrimaryKeys<a name="metaprimarykeys"></a>($table, \r
@@ -2344,6 +2512,24 @@ printf(&quot;&lt;p&gt;Total queries=%d; total cached=%d&lt;/p&gt;&quot;,$EXECS+$
 <p><font color="#000000">Returns an array containing column names that are the \r
   primary keys of $table. Supported by mysql, odbc (including db2, odbc_mssql, \r
   etc), mssql, postgres, interbase/firebird, oci8 currently. </font><font color="#000000"> \r
+<p>Views (and some tables) have primary keys, but sometimes this information is not available from the\r
+database. You can define a function  ADODB_View_PrimaryKeys($databaseType, $database, $view, $owner) that\r
+should return an array containing the fields that make up the primary key. If that function exists,\r
+it will be called when MetaPrimaryKeys() cannot find a primary key for a table or view.\r
+<pre>\r
+// In this example: dbtype = 'oci8', $db = 'mydb', $view = 'dataView', $owner = false \r
+function ADODB_View_PrimaryKeys($dbtype,$db,$view,$owner)\r
+{\r
+       switch(strtoupper($view)) {\r
+       case 'DATAVIEW': return array('DATAID');\r
+       default: return false;\r
+       }\r
+}\r
+\r
+$db = NewADOConnection('oci8');\r
+$db->Connect('localhost','root','','mydb'); \r
+$db->MetaPrimaryKeys('dataView');\r
+</pre>\r
 <p><font color="#000000"><b>ServerInfo<a name="serverinfo" id="serverinfo"></a>($table)</b></font></font> \r
 <p><font color="#000000">Returns an array of containing two elements 'description' \r
   and 'version'. The 'description' element contains the string description of \r
@@ -2437,12 +2623,12 @@ for GetArray() for compatibility with Microsoft ADO.
   time the selection is based on the 2nd column, which holds the values to return \r
   to the Web server. \r
 <p><b>UserDate<a name="userdate"></a>($str, [$fmt])</b></p>\r
-<p>Converts the date string $<b>str</b> to another format.UserDate calls UnixDate \r
-  to parse $<b>str</b>, and $<b>fmt</b> defaults to Y-m-d if not defined.</p>\r
+<p>Converts the date string $<i>str</i> to another format. The date format is Y-m-d,\r
+or Unix timestamp format. The default $<i>fmt</i> is Y-m-d.</p>\r
 <p><b>UserTimeStamp<a name="usertimestamp"></a>($str, [$fmt])</b></p>\r
 <p>Converts the timestamp string $<b>str</b> to another format. The timestamp \r
-  format is Y-m-d H:i:s, as in '2002-02-28 23:00:12'. UserTimeStamp calls UnixTimeStamp \r
-  to parse $<b>str</b>, and $<b>fmt</b> defaults to Y-m-d H:i:s if not defined. \r
+  format is Y-m-d H:i:s, as in '2002-02-28 23:00:12', or Unix timestamp format.\r
+   UserTimeStamp calls UnixTimeStamp to parse $<i>str</i>, and $<i>fmt</i> defaults to Y-m-d H:i:s if not defined. \r
 </p>\r
 <p><b>UnixDate<a name="unixdate"></a>($str)</b></p>\r
 <p>Parses the date string $<b>str</b> and returns it in unix mktime format (eg. \r
@@ -2454,8 +2640,8 @@ for GetArray() for compatibility with Microsoft ADO.
 <p><b>UnixTimeStamp<a name="unixtimestamp"></a>($str)</b></p>\r
 <p>Parses the timestamp string $<b>str</b> and returns it in unix mktime format \r
   (eg. a number indicating the seconds after January 1st, 1970). Expects the date \r
-  to be in Y-m-d H:i:s format, except for Sybase and Microsoft SQL Server, where \r
-  M d Y h:i:sA is also accepted (the 3 letter month strings are controlled by \r
+  to be in "Y-m-d, H:i:s" (1970-12-24, 00:00:00) or "Y-m-d H:i:s" (1970-12-24 00:00:00) or "YmdHis" (19701225000000) format, except for Sybase and Microsoft SQL Server, where \r
+  "M d Y h:i:sA" (Dec 25 1970 00:00:00AM) is also accepted (the 3 letter month strings are controlled by \r
   a global array, which might need localisation).</p>\r
 </font> \r
 <p><font color="#000000">This function is available in both ADORecordSet and ADOConnection \r
@@ -2669,7 +2855,12 @@ For example, $db-&gt;MetaType('char') will return 'C'.
   parameter, instead of $nativeDBType. </font></p>\r
 <font color="#000000"> \r
 <p><b>Close( )<a name="rsclose"></a></b></p>\r
-<p>Close the recordset.</p>\r
+<p>Closes the recordset, cleaning all memory and resources associated with the recordset. \r
+<p>\r
+If memory management is not an issue, you do not need to call this function as recordsets\r
+are closed for you by PHP at the end of the script. \r
+SQL statements such as INSERT/UPDATE/DELETE do not really return a recordset, so you do not have to call Close()\r
+for such SQL statements.</p>\r
 <hr>\r
 <h3>function rs2html<a name="rs2html"></a>($adorecordset,[$tableheader_attributes], \r
   [$col_titles])</h3>\r
@@ -2778,17 +2969,93 @@ $<font color="#663300">rs</font>   = $<font color="#663300">conn</font>->Execute
 <p>See the <a href=http://php.weblogs.com/adodb-todo-roadmap>RoadMap</a> article.</p>\r
 <p>Also see the ADOdb <a href=http://php.weblogs.com/adodb_csv>proxy</a> article \r
   for bridging Windows and Unix databases using http remote procedure calls. For \r
-  your education, visit <a href=http://palslib.com/>palslib.com for database info, \r
+  your education, visit <a href=http://palslib.com/>palslib.com</a> for database info, \r
   and read this article on <a href=http://phplens.com/lens/php-book/optimizing-debugging-php.php>Optimizing \r
   PHP</a>. </p>\r
-</font> \r
-<h2>Change Log<a name="Changes"></a><a name="changelog"></a></h2>\r
+</font>\r
+<h2>Change Log<a name="Changes"></a><a name="changes"></a><a name="changelog"></a></h2>\r
+<p><b>4.11 27 Jan 2004</b>\r
+<p>Table misspelt in perf-oci8.inc.php. Changed v$conn_cache_advice to v$db_cache_advice. Reported by Steve W.\r
+<p>UserTimeStamp and DBTimeStamp did not handle YYYYMMDDHHMMSS format properly. Reported by Mike Muir. Fixed.\r
+<p>Changed oci8 Prepare(). Does not auto-allocate OCINewCursor automatically, unless 2nd param is set to true.\r
+This will break backward compat, if Prepare/Execute is used instead of ExecuteCursor. Reported by Chris Jones.\r
+<p>Added InParameter() and OutParameter(). Wrapper functions to Parameter(), but nicer because they\r
+are self-documenting.\r
+<p>Added 'R' handling in ActualType() to datadict-mysql.inc.php\r
+<p>Added ADOConnection::SerializableRS($rs). Returns a recordset that can be serialized in a session.\r
+<p>Added "Run SQL" to performance UI().\r
+<p>Misc spelling corrections in adodb-mysqli.inc.php, adodb-oci8.inc.php and datadict-oci8.inc.php, from Heinz Hombergs.\r
+<p>MetaIndexes() for ibase contributed by Heinz Hombergs.\r
+<p><b>4.10 12 Jan 2004</b>\r
+<p>Dan Cech contributed extensive changes to data dictionary to support name quoting (with `), and drop table/index.\r
+<p>Informix added cursorType property. Default remains IFX_SCROLL, but you can change to 0 (non-scrollable cursor) for performance.\r
+<p>Added ADODB_View_PrimaryKeys() for returning view primary keys to MetaPrimaryKeys().\r
+<p>Simplified chinese file, adodb-cn.inc.php from cysoft.\r
+<p>Added check for ctype_alnum in adodb-datadict.inc.php. Thx to Jason Judge.\r
+<p>Added connection parameter to ibase Prepare(). Fix by Daniel Hassan.\r
+<p>Added nameQuote for quoting identifiers and names to connection obj. Requested by Jason Judge. Also the\r
+data dictionary parser now detects `field name` and generates column names with spaces correctly.\r
+<p>BOOL type not recognised correctly as L. Fixed.\r
+<p>Fixed paths in ADODB_DIR for session files, and back-ported it to 4.05 (15 Dec 2003)\r
+<p>Added Schema to postgresql MetaTables. Thx to col#gear.hu\r
+<p>Empty postgresql recordsets that had blob fields did not set EOF properly. Fixed.\r
+<p>CacheSelectLimit internal parameters to SelectLimit were wrong. Thx to Nio.\r
+<p>Modified adodb_pr() and adodb_backtrace() to support command-line usage (eg. no html).\r
+<p>Fixed some fr and it lang errors. Thx to Gaetano G.\r
+<p>Added contrib directory, with adodb rs to xmlrpc convertor by Gaetano G.\r
+<p>Fixed array recordset bugs when _skiprow1 is true. Thx to Gaetano G.\r
+<p>Fixed pivot table code when count is false.\r
+<p>\r
+\r
+<p><b>4.05 13 Dec 2003 </b>\r
+<p>Added MetaIndexes - thx to Dan Cech.\r
+<p>Rewritten session code by Ross Smith. Moved code to adodb/session directory.\r
+<p>Added function exists check on connecting to most drivers, so we don't crash with the unknown function error.\r
+<p>Smart Transactions failed with GenID() when it no seq table has been created because the sql\r
+       statement fails. Fix by Mark Newnham.\r
+<p>Added $db->length, which holds name of function that returns strlen.\r
+<p>Fixed error handling for bad driver in ADONewConnection - passed too few params to error-handler.\r
+<p>Datadict did not handle types like 16.0 properly in _GetSize. Fixed.\r
+<p>Oci8 driver SelectLimit() bug &= instead of =& used. Thx to Swen Thümmler.\r
+<p>Jesse Mullan suggested not flushing outp when output buffering enabled. Due to Apache 2.0 bug. Added.\r
+<p>MetaTables/MetaColumns return ref bug with PHP5 fixed in adodb-datadict.inc.php.\r
+<p>New mysqli driver contributed by Arjen de Rijke. Based on adodb 3.40 driver.\r
+Then jlim added BeginTrans, CommitTrans, RollbackTrans, IfNull, SQLDate. Also fixed return ref bug.\r
+<p>$ADODB_FLUSH added, if true then force flush in debugging outp. Default is false.  In earlier\r
+versions, outp defaulted to flush, which is not compat with apache 2.0.\r
+<p>Mysql driver's GenID() function did not work when when sql logging is on. Fixed.\r
+<p>$ADODB_SESSION_TBL not declared as global var. Not available if adodb-session.inc.php included in function. Fixed.\r
+<p>The input array not passed to Execute() in _adodb_getcount(). Fixed.\r
+<p><b>4.04 13 Nov 2003 </b>\r
+<p>Switched back to foreach - faster than list-each.\r
+<p>Fixed bug in ado driver - wiping out $this->fields with date fields.\r
+<p>Performance Monitor, View SQL, Explain Plan did not work if strlen($SQL)>max($_GET length). Fixed.\r
+<p>Performance monitor, oci8 driver added memory sort ratio.\r
+<p>Added random property, returns SQL to generate a floating point number between 0 and 1;\r
+<p><b>4.03 6 Nov 2003 </b>\r
+<p>The path to adodb-php4.inc.php and adodb-iterators.inc.php was not setup properly.\r
+<p>Patched SQLDate in interbase to support hours/mins/secs. Thx to ari kuorikoski.\r
+<p>Force autorollback for pgsql persistent connections - \r
+apparently pgsql did not autorollback properly before 4.3.4. See http://bugs.php.net/bug.php?id=25404\r
+<p><b>4.02 5 Nov 2003 </b>\r
+<p>Some errors in adodb_error_pg() fixed. Thx to Styve.\r
+<p>Spurious Insert_ID() error was generated by LogSQL(). Fixed.\r
+<p>Insert_ID was interfering with Affected_Rows() and Replace()  when LogSQL() enabled. Fixed.\r
+<p>More foreach loops optimized with list/each.\r
+<p>Null dates not handled properly in ADO driver (it becomes 31 Dec 1969!).\r
+<p>Heinz Hombergs contributed patches for mysql MetaColumns - adding scale, made\r
+interbase MetaColumns work with firebird/interbase, and added lang/adodb-de.inc.php.\r
+<p>Added INFORMIXSERVER environment variable.\r
+<p>Added $ADODB_ANSI_PADDING_OFF for interbase/firebird.\r
+<p>PHP 5 beta 2 compat check. Foreach (Iterator) support. Exceptions support.\r
 <p><b>4.01 23 Oct 2003 </b>\r
-<p>Informix ErrorNo() fixed.\r
+<p>Fixed bug in rs2html(), tohtml.inc.php, that generated blank table cells.\r
+<p>Fixed insert_id() incorrectly generated when logsql() enabled.\r
 <p>Modified PostgreSQL _fixblobs to use list/each instead of foreach.\r
+<p>Informix ErrorNo() implemented correctly.\r
 <p>Modified several places to use list/each, including GetRowAssoc().\r
-<p>Fixed insert_id() incorrectly generated when logsql() enabled.\r
 <p>Added UserTimeStamp() to connection class.\r
+<p>Added $ADODB_ANSI_PADDING_OFF for oci8po.\r
 <p><b>4.00 20 Oct 2003 </b>\r
 <p>Upgraded adodb-xmlschema to 1 Oct 2003 snapshot.\r
 <p>Fix to rs2html warning message. Thx to Filo.\r
index 6840245a363af21e1e6aea7ef1fb5e022e998e77..a5192d48ab2efd001f08f4728b5f7b66f08c48fc 100644 (file)
@@ -11,7 +11,7 @@
 <body bgcolor="#FFFFFF">\r
 \r
 <h2>ADOdb Data Dictionary Library for PHP</h2>\r
-<p> V4.01 23 Oct 2003 (c) 2000-2003 John Lim (<a href="mailto:jlim#natsoft.com.my">jlim#natsoft.com.my</a>)</p>\r
+<p> V4.11 27 Jan 2004 (c) 2000-2004 John Lim (<a href="mailto:jlim#natsoft.com.my">jlim#natsoft.com.my</a>)</p>\r
 <p><font size=1>This software is dual licensed using BSD-Style and LGPL. This \r
   means you can use it in compiled proprietary and commercial products.</font></p>\r
 <p>Useful ADOdb links:  <a href=http://php.weblogs.com/adodb?dd=1>Download</a> &nbsp; <a href=http://php.weblogs.com/adodb_manual?dd=1>Other Docs</a>\r
@@ -65,9 +65,10 @@ $dict-><strong>ExecuteSQLArray</strong>($sqlarray);
 <p>    The older (and still supported) format of $fldarray is a 2-dimensional array, where each row in the \r
        1st dimension represents one field. Each row has this format:\r
 <pre>  array($fieldname, $type, [,$colsize] [,$otheroptions]*)</pre>\r
-       The first 2 fields must be the field name and the field type. The field type\r
-       can be a portable type codes or the actual type for that database. \r
-       <p>\r
+       \r
+<p>The first 2 fields must be the field name and the field type. The field type\r
+       can be a portable type codes or the actual type for that database.</p>\r
+<p>\r
        Legal portable type codes include:\r
 <pre>\r
 C:  varchar\r
@@ -97,40 +98,41 @@ N:  Numeric or decimal number
 <p>\r
        The $otheroptions include the following keywords (case-insensitive):\r
 <pre>\r
-AUTO                   For autoincrement number. Emulated with triggers if not available.\r
+AUTO            For autoincrement number. Emulated with triggers if not available.\r
                                Sets NOTNULL also.\r
-AUTOINCREMENT  Same as auto.\r
-KEY                    Primary key field. Sets NOTNULL also. Compound keys are supported.\r
+AUTOINCREMENT   Same as auto.\r
+KEY             Primary key field. Sets NOTNULL also. Compound keys are supported.\r
 PRIMARY                Same as KEY.\r
-DEF                    Synonym for DEFAULT for lazy typists.\r
-DEFAULT                The default value. Character strings are auto-quoted unless\r
-                               the string begins and ends with spaces, eg ' SYSDATE '.\r
-NOTNULL                If field is not null.\r
-DEFDATE                Set default value to call function to get today's date.\r
-DEFTIMESTAMP   Set default to call function to get today's datetime.\r
-NOQUOTE                Prevents autoquoting of default string values.\r
-CONSTRAINTS    Additional constraints defined at the end of the field\r
-                               definition.\r
+DEF             Synonym for DEFAULT for lazy typists.\r
+DEFAULT         The default value. Character strings are auto-quoted unless\r
+                the string begins and ends with spaces, eg ' SYSDATE '.\r
+NOTNULL         If field is not null.\r
+DEFDATE         Set default value to call function to get today's date.\r
+DEFTIMESTAMP    Set default to call function to get today's datetime.\r
+NOQUOTE         Prevents autoquoting of default string values.\r
+CONSTRAINTS     Additional constraints defined at the end of the field\r
+                definition.\r
 </pre>\r
 <p> The Data Dictonary accepts two formats, the older array specification: </p>\r
 <pre>\r
 $flds = array(\r
-       array('COLNAME', 'DECIMAL', '8.4', 'DEFAULT' => 0, 'NotNull'),\r
-       array('ID',      'I'      , 'AUTO'),\r
-       array('MYDATE',  'D'      , 'DEFDATE'),\r
-       array('NAME',    'C'      ,'32', \r
+       array('COLNAME',   'DECIMAL', '8.4', 'DEFAULT' => 0, 'NotNull'),\r
+       array('id',        'I'      , 'AUTO'),\r
+       array('`MY DATE`', 'D'      , 'DEFDATE'),\r
+       array('NAME',      'C'      , '32', \r
                  'CONSTRAINTS' => 'FOREIGN KEY REFERENCES reftable')\r
 );  </pre>\r
 Or the simpler declarative format:\r
 <pre> $flds = "\r
 <font color="#660000"><strong> COLNAME DECIMAL(8.4) DEFAULT 0 NotNull,\r
ID I AUTO,\r
MYDATE D DEFDATE, \r
id I AUTO,\r
`MY DATE` D DEFDATE, \r
  NAME C(32) CONSTRAINTS 'FOREIGN KEY REFERENCES reftable' </strong></font>\r
 "; \r
 </pre>\r
 <p>\r
-       The $taboptarray is the 3rd parameter of the CreateTableSQL function. \r
+       Note that if you have special characters in the field name (e.g. My Date), you should enclose it in back-quotes. Normally field names are not case-sensitive, but if you enclose it in back-quotes, some databases treat the names as case-sensitive, and some don't. So be careful.\r
+<p>The $taboptarray is the 3rd parameter of the CreateTableSQL function. \r
        This contains table specific settings. Legal keywords include:\r
         \r
 <ul>\r
@@ -138,6 +140,9 @@ Or the simpler declarative format:
                Indicates that the previous table definition should be removed (dropped)together \r
                with ALL data. See first example below.<br>\r
        </li>\r
+       <li>DROP <br>\r
+               Drop table. Useful for removing unused tables.<br>\r
+       </li>\r
        <li>CONSTRAINTS <br>\r
                Define this as the key, with the constraint as the value. See the postgresql \r
                example below. Additional constraints defined for the whole table. You \r
@@ -177,6 +182,7 @@ Or the simpler declarative format:
        UNIQUE                  Make unique index\r
        FULLTEXT                Make fulltext index (only mysql)\r
        HASH                    Create hash index (only postgres)\r
+       DROP            Drop legacy index\r
        </pre>  \r
 <p> <strong>function AddColumnSQL($tabname, $flds)</strong>\r
 <p>Add one or more columns. Not guaranteed to work under all situations.\r
index 05c909cf9a107a0828bfe7a231666bb6ffee7ee5..bfcaa774338b696328c017be93062adf5a35370c 100644 (file)
@@ -7,7 +7,7 @@
 \r
 <body>\r
 <h3>The ADOdb Performance Monitoring Library</h3>\r
-<p>V4.01 23 Oct 2003 (c) 2000-2003 John Lim (jlim#natsoft.com.my)</p>\r
+<p>V4.11 27 Jan 2004 (c) 2000-2004 John Lim (jlim#natsoft.com.my)</p>\r
 <p><font size="1">This software is dual licensed using BSD-Style and LGPL. This \r
   means you can use it in compiled proprietary and commercial products.</font></p>\r
   <p>Useful ADOdb links:  <a href=http://php.weblogs.com/adodb?perf=1>Download</a> &nbsp; <a href=http://php.weblogs.com/adodb_manual?perf=1>Other Docs</a>\r
index 16ca8cdc5fe0cfa54e29d7311f380ce17393cc24..04204789a62fc520cc5f2bd4af74a81dcf582598 100644 (file)
@@ -3,22 +3,23 @@
 <title>ADODB Session Management Manual</title>\r
 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">\r
 <XSTYLE\r
-       body,td {font-family:Arial,Helvetica,sans-serif;font-size:11pt}\r
-       pre {font-size:9pt}\r
-       .toplink {font-size:8pt}\r
-       />\r
-</head>        \r
+    body,td {font-family:Arial,Helvetica,sans-serif;font-size:11pt}\r
+    pre {font-size:9pt}\r
+    .toplink {font-size:8pt}\r
+    />\r
+</head>    \r
 <body bgcolor="#FFFFFF">\r
 <h3>ADODB Session Management Manual</h3>\r
 <p>\r
-V4.01 23 Oct 2003 (c) 2000-2003 John Lim (jlim#natsoft.com.my)\r
+V4.11 27 Jan 2004 (c) 2000-2004 John Lim (jlim#natsoft.com.my)\r
 <p> <font size=1>This software is dual licensed using BSD-Style and LGPL. This \r
   means you can use it in compiled proprietary and commercial products. </font> \r
 <p>Useful ADOdb links:  <a href=http://php.weblogs.com/adodb>Download</a> &nbsp; <a href=http://php.weblogs.com/adodb_manual>Other Docs</a>\r
 \r
 <h3>Introduction</h3>\r
-<p>PHP is packed with good features. One of the most popular is session variables. \r
-These are variables that persist throughout a session, as the user moves from page to page. Session variables are great holders of state information and other useful stuff.\r
+<p> \r
+We store state information specific to a user or web client in session variables. These session variables \r
+ persist throughout a session, as the user moves from page to page. \r
 <p>\r
 To use session variables, call session_start() at the beginning of your web page, \r
 before your HTTP headers are sent. Then for every variable you want to keep alive \r
@@ -35,13 +36,15 @@ the session handler will keep track of the session by using a cookie. You can sa
 <p>Then the ADOdb session handler provides you with the above additional capabilities \r
   by storing the session information as records in a database table that can be \r
   shared across multiple servers. \r
+<p><b>Important Upgrade Notice:</b> Since ADOdb 4.05, the session files have been moved to its own folder, adodb/session. This is a rewrite\r
+of the session code by Ross Smith. The old session code is in adodb/session/old. \r
 <h4>ADOdb Session Handler Features</h4>\r
 <ul>\r
 <li>Ability to define a notification function that is called when a session expires. Typically\r
 used to detect session logout and release global resources.\r
 <li>Optimization of database writes. We crc32 the session data and only perform an update\r
 to the session data if there is a data change.\r
-<li>Support for large amounts of session data with CLOBs (see adodb-session-clob.inc.php). Useful\r
+<li>Support for large amounts of session data with CLOBs (see adodb-session-clob.php). Useful\r
 for Oracle.\r
 <li>Support for encrypted session data, see adodb-cryptsession.inc.php. Enabling encryption \r
 is simply a matter of including adodb-cryptsession.inc.php instead of adodb-session.inc.php.\r
@@ -49,110 +52,161 @@ is simply a matter of including adodb-cryptsession.inc.php instead of adodb-sess
 <h3>Setup</h3>\r
 <p>There are 3 session management files that you can use:\r
 <pre>\r
-adodb-session.inc.php        : The default\r
-adodb-session-clob.inc.php   : Use this if you are storing DATA in clobs\r
-adodb-cryptsession.inc.php   : Use this if you want to store encrypted session data in the database\r
+adodb-session.php        : The default\r
+adodb-session-clob.php   : Use this if you are storing DATA in clobs\r
+adodb-cryptsession.php   : Use this if you want to store encrypted session data in the database\r
 \r
 <strong>Examples</strong>\r
\r
-       GLOBAL $HTTP_SESSION_VARS;\r
-       include('adodb.inc.php');\r
-       include('adodb-session.php');\r
-       session_start();\r
-       session_register('AVAR');\r
-       $HTTP_SESSION_VARS['AVAR'] += 1;\r
-       print "<p>\$HTTP_SESSION_VARS['AVAR']={$HTTP_SESSION_VARS['AVAR']}</p>";\r
-       \r
+ <font color=#004040>\r
+    include('adodb/adodb.inc.php');\r
+    \r
+<b>    $ADODB_SESSION_DRIVER='mysql';\r
+    $ADODB_SESSION_CONNECT='localhost';\r
+    $ADODB_SESSION_USER ='scott';\r
+    $ADODB_SESSION_PWD ='tiger';\r
+    $ADODB_SESSION_DB ='sessiondb';</b>\r
+    \r
+    <b>include('adodb/session/adodb-session.php');</b>\r
+    session_start();\r
+    \r
+    #\r
+    # Test session vars, the following should increment on refresh\r
+    #\r
+    $_SESSION['AVAR'] += 1;\r
+    print "&lt;p>\$_SESSION['AVAR']={$_SESSION['AVAR']}&lt;/p>";\r
+</font>\r
 To force non-persistent connections, call adodb_session_open first before session_start():\r
-\r
-       GLOBAL $HTTP_SESSION_VARS;\r
-       include('adodb.inc.php');\r
-       include('adodb-session.php');\r
-       adodb_sess_open(false,false,false);\r
-       session_start();\r
-       session_register('AVAR');\r
-       $HTTP_SESSION_VARS['AVAR'] += 1;\r
-       print "<p>\$HTTP_SESSION_VARS['AVAR']={$HTTP_SESSION_VARS['AVAR']}</p>";\r
-\r
+ <font color=#004040>\r
+    include('adodb/adodb.inc.php');\r
+    \r
+<b>    $ADODB_SESSION_DRIVER='mysql';\r
+    $ADODB_SESSION_CONNECT='localhost';\r
+    $ADODB_SESSION_USER ='scott';\r
+    $ADODB_SESSION_PWD ='tiger';\r
+    $ADODB_SESSION_DB ='sessiondb';</b>\r
+    \r
+    <b>include('adodb/session/adodb-session.php');\r
+    adodb_sess_open(false,false,false);</b>\r
+    session_start();\r
+ </font color=#004040>\r
 To use a encrypted sessions, simply replace the file:\r
-\r
-       GLOBAL $HTTP_SESSION_VARS;\r
-       include('adodb.inc.php');\r
-       include('adodb-cryptsession.php');\r
-       session_start();\r
-       \r
-And the same technique for adodb-session-clob.inc.php:\r
-\r
-       GLOBAL $HTTP_SESSION_VARS;\r
-       include('adodb.inc.php');\r
-       include('adodb-session-clob.php');\r
-       session_start();\r
-       \r
+ <font color=#004040>\r
+    include('adodb/adodb.inc.php');\r
+    \r
+<b>    $ADODB_SESSION_DRIVER='mysql';\r
+    $ADODB_SESSION_CONNECT='localhost';\r
+    $ADODB_SESSION_USER ='scott';\r
+    $ADODB_SESSION_PWD ='tiger';\r
+    $ADODB_SESSION_DB ='sessiondb';\r
+    \r
+    include('adodb/session/adodb-cryptsession.php');</b>\r
+    session_start();\r
+    </font>\r
+And the same technique for adodb-session-clob.php:\r
+ <font color=#004040>\r
+    include('adodb/adodb.inc.php');\r
+    \r
+<b>    $ADODB_SESSION_DRIVER='mysql';\r
+    $ADODB_SESSION_CONNECT='localhost';\r
+    $ADODB_SESSION_USER ='scott';\r
+    $ADODB_SESSION_PWD ='tiger';\r
+    $ADODB_SESSION_DB ='sessiondb';\r
+    \r
+    include('adodb/session/adodb-session-clob.php');</b>\r
+    session_start();\r
+    </font>\r
  <h4>Installation</h4>\r
  1. Create this table in your database (syntax might vary depending on your db):\r
- <a name=sessiontab></a>\r
+ <a name=sessiontab></a> <font color=#004040>\r
   create table sessions (\r
-          SESSKEY char(32) not null,\r
-          EXPIRY int(11) unsigned not null,\r
-          EXPIREREF varchar(64),\r
-          DATA text not null,\r
-         primary key (sesskey)\r
-  );\r
+       SESSKEY char(32) not null,\r
+       EXPIRY int(11) unsigned not null,\r
+       EXPIREREF varchar(64),\r
+       DATA text not null,\r
+      primary key (sesskey)\r
+  );</font>\r
   \r
-  For the adodb-session-clob.inc.php version, create this:\r
-  \r
-       create table sessions (\r
-          SESSKEY char(32) not null,\r
-          EXPIRY int(11) unsigned not null,\r
-          EXPIREREF varchar(64),\r
-          DATA CLOB,\r
-         primary key (sesskey)\r
-  );\r
+  For the adodb-session-clob.php version, create this:\r
+   <font color=#004040>\r
+    create table sessions (\r
+       SESSKEY char(32) not null,\r
+       EXPIRY int(11) unsigned not null,\r
+       EXPIREREF varchar(64),\r
+       DATA CLOB,\r
+      primary key (sesskey)\r
+  );</font>\r
 \r
   2. Then define the following parameters. You can either modify\r
      this file, or define them before this file is included:\r
-        \r
-       $ADODB_SESSION_DRIVER='database driver, eg. mysql or ibase';\r
-       $ADODB_SESSION_CONNECT='server to connect to';\r
-       $ADODB_SESSION_USER ='user';\r
-       $ADODB_SESSION_PWD ='password';\r
-       $ADODB_SESSION_DB ='database';\r
-       $ADODB_SESSION_TBL = 'sessions'\r
-       \r
-  3. Recommended is PHP 4.0.6 or later. There are documented\r
-        session bugs in earlier versions of PHP.\r
-\r
-    <h4>Notifications</h4>\r
-    If you want to receive notifications when a session expires, then\r
-    you can tag a session with an <a href="#sessiontab">EXPIREREF</a> tag (see the definition of\r
-    the sessions table above), and before the session record is deleted, \r
-    we can call a function that will pass the contents of the EXPIREREF\r
-    field as the first parameter, and the session key as the 2nd parameter.\r
-        \r
-    To do this, define a notification function, say NotifyFn:\r
+      <font color=#004040>\r
+    $ADODB_SESSION_DRIVER='database driver, eg. mysql or ibase';\r
+    $ADODB_SESSION_CONNECT='server to connect to';\r
+    $ADODB_SESSION_USER ='user';\r
+    $ADODB_SESSION_PWD ='password';\r
+    $ADODB_SESSION_DB ='database';\r
+    $ADODB_SESSION_TBL = 'sessions'; # setting this is optional\r
+       </font>\r
+    When the session is created, $<b>ADODB_SESS_CONN</b> holds the connection object.\r
     \r
-       function NotifyFn($expireref, $sesskey)\r
-       {\r
-       }\r
-    \r
-    Then you need to define a global variable $ADODB_SESSION_EXPIRE_NOTIFY.\r
-    This is an array with 2 elements, the first being the name of the variable\r
+  3. Recommended is PHP 4.0.6 or later. There are documented session bugs \r
+  in earlier versions of PHP.\r
+</pre>\r
+\r
+    <h3>Notifications</h3>\r
+<p>If you want to receive notification when a session expires, then\r
+     tag the session record with a <a href="#sessiontab">EXPIREREF</a> tag (see the \r
+    definition of the sessions table above).  Before any session record is deleted,\r
+       ADOdb will call a notification function, passing in the EXPIREREF.\r
+<p>\r
+When a session is first created, we check a global variable $ADODB_SESSION_EXPIRE_NOTIFY.\r
+    This is an array with 2 elements, the first being the name of the session variable\r
     you would like to store in the EXPIREREF field, and the 2nd is the \r
     notification function's name.\r
-    \r
-    In this example, we want to be notified when a user's session \r
-    has expired, so we store the user id in the global variable $USERID, \r
-    store this value in the EXPIREREF field:\r
-    \r
-       $ADODB_SESSION_EXPIRE_NOTIFY = array('USERID','NotifyFn');\r
-    \r
-    Then when the NotifyFn is called, we are passed the $USERID as the first\r
-    parameter, eg. NotifyFn($userid, $sesskey).\r
-       \r
-       NOTE: When you want to change the EXPIREREF, you will need to modify a session\r
-       variable to force a database record update because we checksum the session\r
-       variables, and only perform the update when the checksum changes.\r
+       <p>\r
+        Suppose we want to be notified when a user's session \r
+    has expired, based on the userid. The user id in the global session variable $USERID.\r
+       The function name is 'NotifyFn'. So we define:\r
+    <pre> <font color=#004040>\r
+        $ADODB_SESSION_EXPIRE_NOTIFY = array('USERID','NotifyFn');\r
+    </font></pre>\r
+    And when the NotifyFn is called (when the session expires), we pass the $USERID \r
+    as the first parameter, eg. NotifyFn($userid, $sesskey). The session key (which is \r
+       the primary key of the record in the sessions table) is the 2nd parameter.\r
+  <p>\r
+    Here is an example of a Notification function that deletes some records in the database\r
+       and temporary files:\r
+    <pre><font color=#004040>\r
+        function NotifyFn($expireref, $sesskey)\r
+        {\r
+        global $ADODB_SESS_CONN; # the session connection object\r
+\r
+          $user = $ADODB_SESS_CONN->qstr($expireref);\r
+          $ADODB_SESS_CONN->Execute("delete from shopping_cart where user=$user");\r
+          system("rm /work/tmpfiles/$expireref/*");\r
+        }</font>\r
+    </pre>\r
+       <p>\r
\r
+    <p>\r
+    NOTE: If you want to change the EXPIREREF after the session record has been\r
+    created, you will need to modify any session variable to force a database\r
+    record update.\r
+<h4>Compression/Encryption Schemes</h4>\r
+Since ADOdb 4.05, thanks to Ross Smith,  multiple encryption and compression schemes are supported.\r
+  Currently, supported:\r
+<pre>\r
+  MD5Crypt (crypt.inc.php)\r
+  MCrypt\r
+  Secure (Horde's emulation of MCrypt, if MCrypt module is not available.)\r
+  GZip\r
+  BZip2\r
+</pre>\r
+These are stackable. E.g. \r
+<pre>\r
+ADODB_Session::filter(new ADODB_Compress_Bzip2());\r
+ADODB_Session::filter(new ADODB_Encrypt_MD5());\r
 </pre>\r
+will compress and then encrypt the record in the database.\r
 <p>\r
 Also see the <a href=docs-adodb.htm>core ADOdb documentation</a>.\r
 </body>\r
index e1078ee5d9557f731ed8898b1f7951c0b0306c32..fca5a8328571c0c27d811de640336ffd33ebb7ba 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. See License.txt. \r
index 3100d058465a210b8c64276a2d9e3e1f05d21474..ad49f6406ec66c4af5ab05f62c999b3728c27872 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
@@ -193,6 +193,9 @@ class ADODB_ado extends ADOConnection {
                return $arr;\r
        }\r
        \r
+\r
+\r
+       \r
        /* returns queryID or false */\r
        function &_query($sql,$inputarr=false) \r
        {\r
@@ -543,15 +546,18 @@ class ADORecordSet_ado extends ADORecordSet {
 \r
                        switch($t) {\r
                        case 135: // timestamp\r
-                               $this->fields[] = date('Y-m-d H:i:s',(integer)$f->value);\r
-                               break;\r
-                               \r
+                               if (!strlen((string)$f->value)) $this->fields[] = false;\r
+                               else $this->fields[] = adodb_date('Y-m-d H:i:s',(float)$f->value);\r
+                               break;                  \r
                        case 133:// A date value (yyyymmdd) \r
-                               $val = $f->value;\r
-                               $this->fields[] = substr($val,0,4).'-'.substr($val,4,2).'-'.substr($val,6,2);\r
+                               if ($val = $f->value) {\r
+                                       $this->fields[] = substr($val,0,4).'-'.substr($val,4,2).'-'.substr($val,6,2);\r
+                               } else\r
+                                       $this->fields[] = false;\r
                                break;\r
                        case 7: // adDate\r
-                               $this->fields[] = date('Y-m-d',(integer)$f->value);\r
+                               if (!strlen((string)$f->value)) $this->fields[] = false;\r
+                               else $this->fields[] = adodb_date('Y-m-d',(float)$f->value);\r
                                break;\r
                        case 1: // null\r
                                $this->fields[] = false;\r
@@ -577,7 +583,25 @@ class ADORecordSet_ado extends ADORecordSet {
                return true;\r
        }\r
        \r
-       \r
+               function NextRecordSet()\r
+               {\r
+                       $rs = $this->_queryID;\r
+                       $this->_queryID = $rs->NextRecordSet();\r
+                       //$this->_queryID = $this->_QueryId->NextRecordSet();\r
+                       if ($this->_queryID == null) return false;\r
+                       \r
+                       $this->_currentRow = -1;\r
+                       $this->_currentPage = -1;\r
+                       $this->bind = false;\r
+                       $this->fields = false;\r
+                       $this->_flds = false;\r
+                       $this->_tarr = false;\r
+                       \r
+                       $this->_inited = false;\r
+                       $this->Init();\r
+                       return true;\r
+               }\r
+\r
        function _close() {\r
                $this->_flds = false;\r
                @$this->_queryID->Close();// by Pete Dishman (peterd@telephonetics.co.uk)\r
index 4cb590e79f7035f434b8916efba11dd2f53bc7e7..946714defab5c7da5d3c9c4c149ae49e875729d4 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
 Released under both BSD license and Lesser GPL library license. \r
 Whenever there is any discrepancy between the two licenses, \r
 the BSD license will take precedence. See License.txt. \r
index 0e8b676ce8f8d965d3531a917cdbc67c069eb772..e09bca54d1aba8cc2321b7a5d2190ec58c914564 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
@@ -27,6 +27,9 @@ class  ADODB_ado_mssql extends ADODB_ado {
        var $leftOuter = '*=';\r
        var $rightOuter = '=*';\r
        var $ansiOuter = true; // for mssql7 or later\r
+       var $substr = "substring";\r
+       var $length = 'len';\r
+       var $upperCase = 'upper';\r
        \r
        //var $_inTransaction = 1; // always open recordsets, so no transaction problems.\r
        \r
index b585cc5e3af4c00aa4b3e9efb4dfeff8ea10a94c..8598e16e7e70c985205ffd6ff4a7846dc5637062 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
index 1f584af46afd13c05b47ce0540544d6a1d0904a4..d0b61014c1f6931156c74f1eb6911a8d95e8113d 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /*\r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
@@ -118,8 +118,6 @@ class ADODB_csv extends ADOConnection {
                        foreach($inputarr as $v) {\r
 \r
                                $sql .= $sqlarr[$i];\r
-                               // from Ron Baldwin <ron.baldwin@sourceprose.com>\r
-                               // Only quote string types      \r
                                if (gettype($v) == 'string')\r
                                        $sql .= $this->qstr($v);\r
                                else if ($v === null)\r
index be68a98f750c6e81231c4a053ce826ded6129b02..24f67020339a4f40b6ce12c046766fc04dc63054 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
@@ -84,7 +84,6 @@ class ADODB_DB2 extends ADODB_odbc {
        var $identitySQL = 'values IDENTITY_VAL_LOCAL()';\r
        var $_bindInputArray = true;\r
        var $upperCase = 'upper';\r
-       var $substr = 'substr';\r
        \r
        \r
        function ADODB_DB2()\r
@@ -248,15 +247,17 @@ class ADODB_DB2 extends ADODB_odbc {
                        if ($offset <= 0) {\r
                        // could also use " OPTIMIZE FOR $nrows ROWS "\r
                                if ($nrows >= 0) $sql .=  " FETCH FIRST $nrows ROWS ONLY ";\r
-                               return $this->Execute($sql,false);\r
+                               $rs =& $this->Execute($sql,false);\r
                        } else {\r
                                if ($offset > 0 && $nrows < 0);\r
                                else {\r
                                        $nrows += $offset;\r
                                        $sql .=  " FETCH FIRST $nrows ROWS ONLY ";\r
                                }\r
-                               return ADOConnection::SelectLimit($sql,-1,$offset);\r
+                               $rs =& ADOConnection::SelectLimit($sql,-1,$offset);\r
                        }\r
+                       \r
+                       return $rs;\r
                }\r
        \r
 };\r
index 459a8533a73bc7fb9f7c53a72b108f589b6c6ecb..46a4460db875a29810a778c67740b1d2ecf22333 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /*\r
- @version V4.01 23 Oct 2003 (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+ @version V4.11 27 Jan 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
  Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
index 2edf263ae7321ae76e6a2efd97d35f9c6c5e0d25..58ea10f9e1f6fb69955d5960e891b28b843d3ea8 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
@@ -45,10 +45,12 @@ class ADODB_firebird extends ADODB_ibase {
                $str .=($offset>=0) ? "SKIP $offset " : '';\r
                \r
                $sql = preg_replace('/^[ \t]*select/i',$str,$sql); \r
-               return ($secs) ? \r
-                               $this->CacheExecute($secs,$sql,$inputarr)\r
-                       :       \r
-                               $this->Execute($sql,$inputarr);\r
+               if ($secs)\r
+                       $rs =& $this->CacheExecute($secs,$sql,$inputarr);\r
+               else\r
+                       $rs =& $this->Execute($sql,$inputarr);\r
+                       \r
+               return $rs;\r
        }\r
        \r
        \r
index 6a44559fe645645988c41fe66283a225dc6d8902..d42b1d70892675e74388623ad0bbe33077204d8c 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /*\r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.  \r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.  \r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
@@ -28,13 +28,15 @@ class ADODB_ibase extends ADOConnection {
        var $databaseType = "ibase";\r
        var $dataProvider = "ibase";\r
        var $replaceQuote = "''"; // string to use to replace quotes\r
-       var $ibase_timefmt = '%Y-%m-%d';\r
+       var $ibase_timefmt = '%Y-%m-%d'; // For hours,mins,secs change to '%Y-%m-%d %H:%M:%S';\r
        var $fmtDate = "'Y-m-d'";\r
        var $fmtTimeStamp = "'Y-m-d, H:i:s'";\r
        var $concat_operator='||';\r
        var $_transactionID;\r
        var $metaTablesSQL = "select rdb\$relation_name from rdb\$relations where rdb\$relation_name not like 'RDB\$%'";\r
-       var $metaColumnsSQL = "select a.rdb\$field_name,b.rdb\$field_type,b.rdb\$field_length from rdb\$relation_fields a join rdb\$fields b on a.rdb\$field_source=b.rdb\$field_name where rdb\$relation_name ='%s'";\r
+       //OPN STUFF start\r
+       var $metaColumnsSQL = "select a.rdb\$field_name, a.rdb\$null_flag, a.rdb\$default_source, b.rdb\$field_length, b.rdb\$field_scale, b.rdb\$field_sub_type, b.rdb\$field_precision, b.rdb\$field_type from rdb\$relation_fields a, rdb\$fields b where a.rdb\$field_source = b.rdb\$field_name and a.rdb\$relation_name = '%s' order by a.rdb\$field_position asc";\r
+       //OPN STUFF end\r
        var $ibasetrans;\r
        var $hasGenID = true;\r
        var $_bindInputArray = true;\r
@@ -120,6 +122,60 @@ class ADODB_ibase extends ADOConnection {
                return $ret;\r
        }\r
        \r
+       function &MetaIndexes ($table, $primary = FALSE, $owner=false)\r
+       {\r
+        // save old fetch mode\r
+        global $ADODB_FETCH_MODE;\r
+        \r
+        $save = $ADODB_FETCH_MODE;\r
+        $ADODB_FETCH_MODE = ADODB_FETCH_NUM;\r
+        if ($this->fetchMode !== FALSE) {\r
+               $savem = $this->SetFetchMode(FALSE);\r
+        }\r
+        $table = strtoupper($table);\r
+        $sql = "SELECT * FROM RDB\$INDICES WHERE RDB\$RELATION_NAME = '".$table."'";\r
+        if (!$primary) {\r
+               $sql .= " AND RDB\$INDEX_NAME NOT LIKE 'RDB\$%'";\r
+        } else {\r
+               $sql .= " AND RDB\$INDEX_NAME NOT LIKE 'RDB\$FOREIGN%'";\r
+        }\r
+        // get index details\r
+        $rs = $this->Execute($sql);\r
+        if (!is_object($rs)) {\r
+               // restore fetchmode\r
+               if (isset($savem)) {\r
+                   $this->SetFetchMode($savem);\r
+               }\r
+               $ADODB_FETCH_MODE = $save;\r
+            return FALSE;\r
+        }\r
+        \r
+        $indexes = array ();\r
+               while ($row = $rs->FetchRow()) {\r
+                       $index = $row[0];\r
+             if (!isset($indexes[$index])) {\r
+                       if (is_null($row[3])) {$row[3] = 0;}\r
+                     $indexes[$index] = array(\r
+                             'unique' => ($row[3] == 1),\r
+                             'columns' => array()\r
+                     );\r
+             }\r
+                       $sql = "SELECT * FROM RDB\$INDEX_SEGMENTS WHERE RDB\$INDEX_NAME = '".$name."' ORDER BY RDB\$FIELD_POSITION ASC";\r
+                       $rs1 = $this->Execute($sql);\r
+            while ($row1 = $rs1->FetchRow()) {\r
+               $indexes[$index]['columns'][$row1[2]] = $row1[1];\r
+               }\r
+               }\r
+        // restore fetchmode\r
+        if (isset($savem)) {\r
+            $this->SetFetchMode($savem);\r
+        }\r
+        $ADODB_FETCH_MODE = $save;\r
+        \r
+        return $indexes;\r
+       }\r
+\r
+       \r
        // See http://community.borland.com/article/0,1410,25844,00.html\r
        function RowLock($tables,$where,$col)\r
        {\r
@@ -128,52 +184,7 @@ class ADODB_ibase extends ADOConnection {
                return 1;\r
        }\r
        \r
-       /*// use delete and insert instead\r
-       function Replace($table, $fieldArray, $keyCol,$autoQuote=false)\r
-       {\r
-               if (count($fieldArray) == 0) return 0;\r
-\r
-               if (!is_array($keyCol)) {\r
-                       $keyCol = array($keyCol);\r
-               }\r
-               \r
-               if ($autoQuote)\r
-                       foreach($fieldArray as $k => $v) {\r
-                               if (!is_numeric($v) and $v[0] != "'" and strcasecmp($v,'null')!=0) {\r
-                                       $v = $this->qstr($v);\r
-                                       $fieldArray[$k] = $v;\r
-                               }\r
-                       }\r
-                       \r
-               $first = true;\r
-               foreach ($keyCol as $v) {\r
-                       if ($first) {\r
-                               $first = false;\r
-                               $where = "$v=$fieldArray[$v]";\r
-                       } else {\r
-                               $where .= " and $v=$fieldArray[$v]";\r
-                       }\r
-               }\r
-                       \r
-               $first = true;\r
-               foreach($fieldArray as $k => $v) {\r
-                       if ($first) {\r
-                               $first = false;                 \r
-                               $iCols = "$k";\r
-                               $iVals = "$v";\r
-                       } else {\r
-                               $iCols .= ",$k";\r
-                               $iVals .= ",$v";\r
-                       }                               \r
-               }\r
-               $this->BeginTrans();\r
-                       $this->Execute("DELETE FROM $table WHERE $where");\r
-                       $ok = $this->Execute("INSERT INTO $table ($iCols) VALUES ($iVals)");\r
-               $this->CommitTrans();\r
-               \r
-               return ($ok) ? 2 : 0;\r
-       }\r
-       */\r
+       \r
        function CreateSequence($seqname,$startID=1)\r
        {\r
                $ok = $this->Execute(("INSERT INTO RDB\$GENERATORS (RDB\$GENERATOR_NAME) VALUES (UPPER('$seqname'))" ));\r
@@ -228,6 +239,7 @@ class ADODB_ibase extends ADOConnection {
           // returns true or false\r
        function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)\r
        {  \r
+               if (!function_exists('ibase_pconnect')) return false;\r
                if ($argDatabasename) $argHostname .= ':'.$argDatabasename;\r
                $this->_connectionID = ibase_connect($argHostname,$argUsername,$argPassword,$this->charSet,$this->buffers,$this->dialect);\r
                if ($this->dialect != 1) { // http://www.ibphoenix.com/ibp_60_del_id_ds.html\r
@@ -244,6 +256,7 @@ class ADODB_ibase extends ADOConnection {
           // returns true or false\r
        function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)\r
        {\r
+               if (!function_exists('ibase_pconnect')) return false;\r
                if ($argDatabasename) $argHostname .= ':'.$argDatabasename;\r
                $this->_connectionID = ibase_pconnect($argHostname,$argUsername,$argPassword,$this->charSet,$this->buffers,$this->dialect);\r
                if ($this->dialect != 1) { // http://www.ibphoenix.com/ibp_60_del_id_ds.html\r
@@ -261,7 +274,7 @@ class ADODB_ibase extends ADOConnection {
        function Prepare($sql)\r
        {\r
        //      return $sql;\r
-               $stmt = ibase_prepare($sql);\r
+               $stmt = ibase_prepare($this->_connectionID,$sql);\r
                if (!$stmt) return false;\r
                return array($sql,$stmt);\r
        }\r
@@ -335,6 +348,101 @@ class ADODB_ibase extends ADOConnection {
                return @ibase_close($this->_connectionID);\r
         }\r
        \r
+       //OPN STUFF start\r
+       function _ConvertFieldType(&$fld, $ftype, $flen, $fscale, $fsubtype, $fprecision, $isInterbase6)\r
+       {\r
+               $fscale = abs($fscale);\r
+               $fld->max_length = $flen;\r
+               $fld->scale = null;\r
+               switch($ftype){\r
+                       case 7: \r
+                       case 8:\r
+                               if ($isInterbase6) {\r
+                                   switch($fsubtype){\r
+                                       case 0: \r
+                                               $fld->type = ($ftype == 7 ? 'smallint' : 'integer');\r
+                                               break;\r
+                                       case 1: \r
+                                               $fld->type = 'numeric';\r
+                                                       $fld->max_length = $fprecision;\r
+                                                       $fld->scale = $fscale;\r
+                                               break;\r
+                                       case 2:\r
+                                               $fld->type = 'decimal';\r
+                                                       $fld->max_length = $fprecision;\r
+                                                       $fld->scale = $fscale;\r
+                                               break;\r
+                                   } // switch\r
+                               } else {\r
+                                       if ($fscale !=0) {\r
+                                           $fld->type = 'decimal';\r
+                                               $fld->scale = $fscale;\r
+                                               $fld->max_length = ($ftype == 7 ? 4 : 9);\r
+                                       } else {\r
+                                               $fld->type = ($ftype == 7 ? 'smallint' : 'integer');\r
+                                       }\r
+                               }\r
+                               break;\r
+                       case 16: \r
+                               if ($isInterbase6) {\r
+                                   switch($fsubtype){\r
+                                       case 0: \r
+                                               $fld->type = 'decimal';\r
+                                                       $fld->max_length = 18;\r
+                                                       $fld->scale = 0;\r
+                                               break;\r
+                                       case 1: \r
+                                               $fld->type = 'numeric';\r
+                                                       $fld->max_length = $fprecision;\r
+                                                       $fld->scale = $fscale;\r
+                                               break;\r
+                                       case 2:\r
+                                               $fld->type = 'decimal';\r
+                                                       $fld->max_length = $fprecision;\r
+                                                       $fld->scale = $fscale;\r
+                                               break;\r
+                                   } // switch\r
+                               }\r
+                               break;\r
+                       case 10:\r
+                               $fld->type = 'float';\r
+                               break;\r
+                       case 14:\r
+                               $fld->type = 'char';\r
+                               break;\r
+                       case 27:\r
+                               if ($fscale !=0) {\r
+                                   $fld->type = 'decimal';\r
+                                       $fld->max_length = 15;\r
+                                       $fld->scale = 5;\r
+                               } else {\r
+                                       $fld->type = 'double';\r
+                               }\r
+                               break;\r
+                       case 35:\r
+                               if ($isInterbase6) {\r
+                                   $fld->type = 'timestamp';\r
+                               } else {\r
+                                       $fld->type = 'date';\r
+                               }\r
+                               break;\r
+                       case 12:\r
+                       case 13:\r
+                               $fld->type = 'date';\r
+                               break;\r
+                       case 37:\r
+                               $fld->type = 'varchar';\r
+                               break;\r
+                       case 40:\r
+                               $fld->type = 'cstring';\r
+                               break;\r
+                       case 261:\r
+                               $fld->type = 'blob';\r
+                               $fld->max_length = -1;\r
+                               break;\r
+               } // switch\r
+       }\r
+       //OPN STUFF end\r
                // returns array of ADOFieldObjects for current table\r
        function &MetaColumns($table) \r
        {\r
@@ -351,31 +459,41 @@ class ADODB_ibase extends ADOConnection {
                        if ($rs === false) return false;\r
 \r
                        $retarr = array();\r
+                       //OPN STUFF start\r
+                       $isInterbase6 = ($this->dialect==3 ? true : false);\r
+                       //OPN STUFF end\r
                        while (!$rs->EOF) { //print_r($rs->fields);\r
                                $fld = new ADOFieldObject();\r
                                $fld->name = trim($rs->fields[0]);\r
-                               $tt = $rs->fields[1];\r
-                               switch($tt)\r
-                               {\r
-                               case 7:\r
-                               case 8:\r
-                               case 9:$tt = 'INTEGER'; break;\r
-                               case 10:\r
-                               case 27:\r
-                               case 11:$tt = 'FLOAT'; break;\r
-                               default:\r
-                               case 40:\r
-                               case 14:$tt = 'CHAR'; break;\r
-                               case 35:$tt = 'DATE'; break;\r
-                               case 37:$tt = 'VARCHAR'; break;\r
-                               case 261:$tt = 'BLOB'; break;\r
-                               case 14: $tt = 'TEXT'; break;\r
-                               case 13:\r
-                               case 35:$tt = 'TIMESTAMP'; break;\r
+                               //OPN STUFF start\r
+                               $this->_ConvertFieldType($fld, $rs->fields[7], $rs->fields[3], $rs->fields[4], $rs->fields[5], $rs->fields[6], $isInterbase6);\r
+                               if (isset($rs->fields[1]) && $rs->fields[1]) {\r
+                                       $fld->not_null = true;\r
+                               }                               \r
+                               if (isset($rs->fields[2])) {\r
+                                       \r
+                                       $fld->has_default = true;\r
+                                       $d = substr($rs->fields[2],strlen('default '));\r
+                                       switch ($fld->type)\r
+                                       {\r
+                                       case 'smallint':\r
+                                       case 'integer': $fld->default_value = (int) $d; break;\r
+                                       case 'char': \r
+                                       case 'blob':\r
+                                       case 'text':\r
+                                       case 'varchar': $fld->default_value = (string) substr($d,1,strlen($d)-2); break;\r
+                                       case 'double':\r
+                                       case 'float': $fld->default_value = (float) $d; break;\r
+                                       default: $fld->default_value = $d; break;\r
+                                       }\r
+                       //      case 35:$tt = 'TIMESTAMP'; break;\r
                                }\r
-                               $fld->type = $tt;\r
-                               $fld->max_length = $rs->fields[2];\r
-                               \r
+                               if ((isset($rs->fields[5])) && ($fld->type == 'blob')) {\r
+                                       $fld->sub_type = $rs->fields[5];\r
+                               } else {\r
+                                       $fld->sub_type = null;\r
+                               }\r
+                               //OPN STUFF end\r
                                if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;     \r
                                else $retarr[strtoupper($fld->name)] = $fld;\r
                                \r
@@ -517,6 +635,19 @@ class ADODB_ibase extends ADOConnection {
                        case 'd':\r
                                $s .= "(extract(day from $col))";\r
                                break;\r
+                       case 'H':\r
+                       case 'h':\r
+                         $s .= "(extract(hour from $col))";\r
+                         break;                        \r
+                       case 'I':\r
+                       case 'i':\r
+                         $s .= "(extract(minute from $col))";\r
+                         break;                \r
+                       case 'S':\r
+                       case 's':\r
+                         $s .= "CAST((extract(second from $col)) AS INTEGER)";\r
+                         break;        \r
+\r
                        default:\r
                                if ($ch == '\\') {\r
                                        $i++;\r
@@ -593,7 +724,11 @@ class ADORecordset_ibase extends ADORecordSet
                }\r
                // OPN stuff start - optimized\r
                // fix missing nulls and decode blobs automatically\r
-\r
+       \r
+               global $ADODB_ANSI_PADDING_OFF;\r
+               //$ADODB_ANSI_PADDING_OFF=1;\r
+               $rtrim = !empty($ADODB_ANSI_PADDING_OFF);\r
+               \r
                for ($i=0, $max = $this->_numOfFields; $i < $max; $i++) { \r
                        if ($this->_cacheType[$i]=="BLOB") {\r
                                if (isset($f[$i])) { \r
@@ -604,7 +739,9 @@ class ADORecordset_ibase extends ADORecordSet
                        } else { \r
                                if (!isset($f[$i])) { \r
                                        $f[$i] = null; \r
-                               } \r
+                               } else if ($rtrim && is_string($f[$i])) {\r
+                                       $f[$i] = rtrim($f[$i]);\r
+                               }\r
                        } \r
                } \r
                // OPN stuff end \r
index 7f3ed4ac041d5ceaaf4a1c0d33522eb0f864e8f3..0473f950028ea61c5fb812a0ae50046e05edf162 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /**\r
-* @version V4.01 23 Oct 2003 (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+* @version V4.11 27 Jan 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
 * Released under both BSD license and Lesser GPL library license.\r
 * Whenever there is any discrepancy between the two licenses,\r
 * the BSD license will take precedence.\r
index 4e090e95700bc307ef14bccadc3a5eb8067a33bb..f9110793544ba4ae1c3231e13c92433ce975ec5b 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /*\r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim. All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim. All rights reserved.\r
   Released under both BSD license and Lesser GPL library license.\r
   Whenever there is any discrepancy between the two licenses,\r
   the BSD license will take precedence.\r
@@ -14,6 +14,8 @@ V4.01 23 Oct 2003  (c) 2000-2003 John Lim. All rights reserved.
 \r
 */\r
 \r
+if (!defined('IFX_SCROLL')) define('IFX_SCROLL',1);\r
+\r
 class ADODB_informix72 extends ADOConnection {\r
        var $databaseType = "informix72";\r
        var $dataProvider = "informix";\r
@@ -40,6 +42,7 @@ class ADODB_informix72 extends ADOConnection {
        var $_bindInputArray = true;  // set to true if ADOConnection.Execute() permits binding of array parameters.\r
        var $sysDate = 'TODAY';\r
        var $sysTimeStamp = 'CURRENT';\r
+       var $cursorType = IFX_SCROLL; // IFX_SCROLL or IFX_HOLD or 0\r
    \r
        function ADODB_informix72()\r
        {\r
@@ -179,7 +182,11 @@ class ADODB_informix72 extends ADOConnection {
        // returns true or false\r
    function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)\r
        {\r
+               if (!function_exists('ifx_connect')) return false;\r
+               \r
                $dbs = $argDatabasename . "@" . $argHostname;\r
+               if ($argHostname) putenv("INFORMIXSERVER=$argHostname"); \r
+               putenv("INFORMIXSERVER=$argHostname"); \r
                $this->_connectionID = ifx_connect($dbs,$argUsername,$argPassword);\r
                if ($this->_connectionID === false) return false;\r
                #if ($argDatabasename) return $this->SelectDB($argDatabasename);\r
@@ -189,7 +196,10 @@ class ADODB_informix72 extends ADOConnection {
        // returns true or false\r
    function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)\r
        {\r
+               if (!function_exists('ifx_connect')) return false;\r
+               \r
                $dbs = $argDatabasename . "@" . $argHostname;\r
+               if ($argHostname) putenv("INFORMIXSERVER=$argHostname"); \r
                $this->_connectionID = ifx_pconnect($dbs,$argUsername,$argPassword);\r
                if ($this->_connectionID === false) return false;\r
                #if ($argDatabasename) return $this->SelectDB($argDatabasename);\r
@@ -225,10 +235,10 @@ class ADODB_informix72 extends ADOConnection {
          // to be able to call "move", or "movefirst" statements\r
          if (!$ADODB_COUNTRECS && preg_match("/^\s*select/is", $sql)) {\r
                 if ($inputarr) {\r
-                       $this->lastQuery = ifx_query($sql,$this->_connectionID, IFX_SCROLL, $tab);\r
+                       $this->lastQuery = ifx_query($sql,$this->_connectionID, $this->cursorType, $tab);\r
                 }\r
                 else {\r
-                       $this->lastQuery = ifx_query($sql,$this->_connectionID, IFX_SCROLL);\r
+                       $this->lastQuery = ifx_query($sql,$this->_connectionID, $this->cursorType);\r
                 }\r
          }\r
          else {\r
index 69fa7d4fb8fff95a91e6e308fce40475585e82f7..7a0247b649966c9edd6da000b007869c348e0d0a 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
@@ -75,6 +75,7 @@ class ADODB_mssql extends ADOConnection {
        var $fmtTimeStamp = "'Y-m-d h:i:sA'";\r
        var $hasInsertID = true;\r
        var $substr = "substring";\r
+       var $length = 'len';\r
        var $upperCase = 'upper';\r
        var $hasAffectedRows = true;\r
        var $metaDatabasesSQL = "select name from sysdatabases where name <> 'master'";\r
@@ -100,6 +101,7 @@ class ADODB_mssql extends ADOConnection {
        var $uniqueOrderBy = true;\r
        var $_bindInputArray = true;\r
        \r
+       \r
        function ADODB_mssql() \r
        {               \r
                $this->_has_mssql_init = (strnatcmp(PHP_VERSION,'4.1.0')>=0);\r
@@ -197,11 +199,14 @@ class ADODB_mssql extends ADOConnection {
                if ($nrows > 0 && $offset <= 0) {\r
                        $sql = preg_replace(\r
                                '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop." $nrows ",$sql);\r
-                       return $this->Execute($sql,$inputarr);\r
+                       $rs =& $this->Execute($sql,$inputarr);\r
                } else\r
-                       return ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);\r
+                       $rs =& ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);\r
+       \r
+               return $rs;\r
        }\r
        \r
+       \r
        // Format date column in sql string given an input format that understands Y M D\r
        function SQLDate($fmt, $col=false)\r
        {       \r
@@ -430,6 +435,7 @@ order by constraint_name, referenced_table_name, keyno";
        // returns true or false\r
        function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)\r
        {\r
+               if (!function_exists('mssql_pconnect')) return false;\r
                $this->_connectionID = mssql_connect($argHostname,$argUsername,$argPassword);\r
                if ($this->_connectionID === false) return false;\r
                if ($argDatabasename) return $this->SelectDB($argDatabasename);\r
@@ -440,6 +446,7 @@ order by constraint_name, referenced_table_name, keyno";
        // returns true or false\r
        function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)\r
        {\r
+               if (!function_exists('mssql_pconnect')) return false;\r
                $this->_connectionID = mssql_pconnect($argHostname,$argUsername,$argPassword);\r
                if ($this->_connectionID === false) return false;\r
                \r
@@ -511,7 +518,9 @@ order by constraint_name, referenced_table_name, keyno";
                        }\r
                \r
                if  ($this->debug) {\r
-                       ADOConnection::outp( "Parameter(\$stmt, \$php_var='$var', \$name='$name'); (type=$type)");\r
+                       $prefix = ($isOutput) ? 'Out' : 'In';\r
+                       $ztype = (empty($type)) ? 'false' : $type;\r
+                       ADOConnection::outp( "{$prefix}Parameter(\$stmt, \$php_var='$var', \$name='$name', \$maxLen=$maxLen, \$type=$ztype);");\r
                }\r
                /*\r
                        See http://phplens.com/lens/lensforum/msgs.php?id=7231\r
index 747abdd95c88fe1860a10e1642826d3b80daf7ba..d727def5fe0340b04afe510560398d859a2d0fab 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /**\r
-* @version V4.01 23 Oct 2003 (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+* @version V4.11 27 Jan 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
 * Released under both BSD license and Lesser GPL library license.\r
 * Whenever there is any discrepancy between the two licenses,\r
 * the BSD license will take precedence.\r
index 17389c3a2eaa310c9a32c4fe67fb186a14865a2b..e5b79ad631c424288148da249af9da4991bf2537 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /*\r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
@@ -34,9 +34,8 @@ class ADODB_mysql extends ADOConnection {
        var $forceNewConnect = false;\r
        var $poorAffectedRows = true;\r
        var $clientFlags = 0;\r
-       var $dbxDriver = 1;\r
        var $substr = "substring";\r
-       var $lastInsID = false;\r
+       var $nameQuote = '`';           /// string to use to quote identifiers and names\r
        \r
        function ADODB_mysql() \r
        {                       \r
@@ -44,7 +43,7 @@ class ADODB_mysql extends ADOConnection {
        \r
        function ServerInfo()\r
        {\r
-               $arr['description'] = $this->GetOne("select version()");\r
+               $arr['description'] = ADOConnection::GetOne("select version()");\r
                $arr['version'] = ADOConnection::_findvers($arr['description']);\r
                return $arr;\r
        }\r
@@ -69,6 +68,59 @@ class ADODB_mysql extends ADOConnection {
                return $ret;\r
        }\r
        \r
+       \r
+       function &MetaIndexes ($table, $primary = FALSE, $owner=false)\r
+       {\r
+        // save old fetch mode\r
+        global $ADODB_FETCH_MODE;\r
+        \r
+        $save = $ADODB_FETCH_MODE;\r
+        $ADODB_FETCH_MODE = ADODB_FETCH_NUM;\r
+        if ($this->fetchMode !== FALSE) {\r
+               $savem = $this->SetFetchMode(FALSE);\r
+        }\r
+        \r
+        // get index details\r
+        $rs = $this->Execute(sprintf('SHOW INDEXES FROM %s',$table));\r
+        \r
+        // restore fetchmode\r
+        if (isset($savem)) {\r
+                $this->SetFetchMode($savem);\r
+        }\r
+        $ADODB_FETCH_MODE = $save;\r
+        \r
+        if (!is_object($rs)) {\r
+                return FALSE;\r
+        }\r
+        \r
+        $indexes = array ();\r
+        \r
+        // parse index data into array\r
+        while ($row = $rs->FetchRow()) {\r
+                if ($primary == FALSE AND $row[2] == 'PRIMARY') {\r
+                        continue;\r
+                }\r
+                \r
+                if (!isset($indexes[$row[2]])) {\r
+                        $indexes[$row[2]] = array(\r
+                                'unique' => ($row[1] == 0),\r
+                                'columns' => array()\r
+                        );\r
+                }\r
+                \r
+                $indexes[$row[2]]['columns'][$row[3] - 1] = $row[4];\r
+        }\r
+        \r
+        // sort columns by order in the index\r
+        foreach ( array_keys ($indexes) as $index )\r
+        {\r
+                ksort ($indexes[$index]['columns']);\r
+        }\r
+        \r
+        return $indexes;\r
+       }\r
+\r
+       \r
        // if magic quotes disabled, use mysql_real_escape_string()\r
        function qstr($s,$magic_quotes=false)\r
        {\r
@@ -128,14 +180,19 @@ class ADODB_mysql extends ADOConnection {
                return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));\r
        }\r
        \r
+\r
        function GenID($seqname='adodbseq',$startID=1)\r
        {\r
                // post-nuke sets hasGenID to false\r
                if (!$this->hasGenID) return false;\r
                \r
+               $savelog = $this->_logsql;\r
+               $this->_logsql = false;\r
                $getnext = sprintf($this->_genIDSQL,$seqname);\r
+               $holdtransOK = $this->_transOK; // save the current status\r
                $rs = @$this->Execute($getnext);\r
                if (!$rs) {\r
+                       if ($holdtransOK) $this->_transOK = true; //if the status was ok before reset\r
                        $u = strtoupper($seqname);\r
                        $this->Execute(sprintf($this->_genSeqSQL,$seqname));\r
                        $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));\r
@@ -145,6 +202,7 @@ class ADODB_mysql extends ADOConnection {
                \r
                if ($rs) $rs->Close();\r
                \r
+               $this->_logsql = $savelog;\r
                return $this->genID;\r
        }\r
        \r
@@ -240,14 +298,6 @@ class ADODB_mysql extends ADOConnection {
        {\r
                $s = "";\r
                $arr = func_get_args();\r
-               $first = true;\r
-               /*\r
-               foreach($arr as $a) {\r
-                       if ($first) {\r
-                               $s = $a;\r
-                               $first = false;\r
-                       } else $s .= ','.$a;\r
-               }*/\r
                \r
                // suggestion by andrew005@mnogo.ru\r
                $s = implode(',',$arr); \r
@@ -320,18 +370,34 @@ class ADODB_mysql extends ADOConnection {
                                $fld->name = $rs->fields[0];\r
                                $type = $rs->fields[1];\r
                                \r
+                               \r
                                // split type into type(length):\r
-                               if (preg_match("/^(.+)\((\d+)/", $type, $query_array)) {\r
+                               $fld->scale = null;\r
+                               if (strpos($type,',') && preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) {\r
+                                       $fld->type = $query_array[1];\r
+                                       $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;\r
+                                       $fld->scale = is_numeric($query_array[3]) ? $query_array[3] : -1;\r
+                               } elseif (preg_match("/^(.+)\((\d+)/", $type, $query_array)) {\r
                                        $fld->type = $query_array[1];\r
                                        $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;\r
                                } else {\r
                                        $fld->max_length = -1;\r
                                        $fld->type = $type;\r
                                }\r
+                               /*\r
+                               // split type into type(length):\r
+                               if (preg_match("/^(.+)\((\d+)/", $type, $query_array)) {\r
+                                       $fld->type = $query_array[1];\r
+                                       $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;\r
+                               } else {\r
+                                       $fld->max_length = -1;\r
+                                       $fld->type = $type;\r
+                               }*/\r
                                $fld->not_null = ($rs->fields[2] != 'YES');\r
                                $fld->primary_key = ($rs->fields[3] == 'PRI');\r
                                $fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);\r
                                $fld->binary = (strpos($fld->type,'blob') !== false);\r
+                               \r
                                if (!$fld->binary) {\r
                                        $d = $rs->fields[4];\r
                                        if ($d != "" && $d != "NULL") {\r
@@ -366,9 +432,11 @@ class ADODB_mysql extends ADOConnection {
        {\r
                $offsetStr =($offset>=0) ? "$offset," : '';\r
                \r
-               return ($secs) ? $this->CacheExecute($secs,$sql." LIMIT $offsetStr$nrows",$inputarr)\r
-                       : $this->Execute($sql." LIMIT $offsetStr$nrows",$inputarr);\r
-               \r
+               if ($secs)\r
+                       $rs =& $this->CacheExecute($secs,$sql." LIMIT $offsetStr$nrows",$inputarr);\r
+               else\r
+                       $rs =& $this->Execute($sql." LIMIT $offsetStr$nrows",$inputarr);\r
+               return $rs;\r
        }\r
        \r
        \r
@@ -484,7 +552,8 @@ class ADORecordSet_mysql extends ADORecordSet{
        function &GetRowAssoc($upper=true)\r
        {\r
                if ($this->fetchMode == MYSQL_ASSOC && !$upper) return $this->fields;\r
-               return ADORecordSet::GetRowAssoc($upper);\r
+               $row =& ADORecordSet::GetRowAssoc($upper);\r
+               return $row;\r
        }\r
        \r
        /* Use associative array to get fields array */\r
@@ -575,6 +644,7 @@ class ADORecordSet_mysql extends ADORecordSet{
                case 'BLOB':\r
                case 'MEDIUMBLOB':\r
                        return !empty($fieldobj->binary) ? 'B' : 'X';\r
+                       \r
                case 'YEAR':\r
                case 'DATE': return 'D';\r
                \r
diff --git a/lib/adodb/drivers/adodb-mysqli.inc.php b/lib/adodb/drivers/adodb-mysqli.inc.php
new file mode 100644 (file)
index 0000000..a9daa02
--- /dev/null
@@ -0,0 +1,828 @@
+<?php\r
+/*\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+  Released under both BSD license and Lesser GPL library license. \r
+  Whenever there is any discrepancy between the two licenses, \r
+  the BSD license will take precedence.\r
+  Set tabs to 8.\r
+  \r
+  MySQL code that does not support transactions. Use mysqlt if you need transactions.\r
+  Requires mysql client. Works on Windows and Unix.\r
\r
+21 October 2003: MySQLi extension implementation by Arjen de Rijke (a.de.rijke@xs4all.nl)\r
+Based on adodb 3.40\r
+*/ \r
+if (! defined("_ADODB_MYSQL_LAYER")) {\r
+ define("_ADODB_MYSQL_LAYER", 1 );\r
\r
+class ADODB_mysqli extends ADOConnection {\r
+       var $databaseType = 'mysqli';\r
+       var $dataProvider = 'native';\r
+       var $hasInsertID = true;\r
+       var $hasAffectedRows = true;    \r
+       var $metaTablesSQL = "SHOW TABLES";     \r
+       var $metaColumnsSQL = "SHOW COLUMNS FROM %s";\r
+       var $fmtTimeStamp = "'Y-m-d H:i:s'";\r
+       var $hasLimit = true;\r
+       var $hasMoveFirst = true;\r
+       var $hasGenID = true;\r
+       var $upperCase = 'upper';\r
+       var $isoDates = true; // accepts dates in ISO format\r
+       var $sysDate = 'CURDATE()';\r
+       var $sysTimeStamp = 'NOW()';\r
+       var $hasTransactions = false;\r
+       var $forceNewConnect = false;\r
+       var $poorAffectedRows = true;\r
+       var $clientFlags = 0;\r
+       var $executeOnly = true;\r
+       var $substr = "substring";\r
+       var $nameQuote = '`';           /// string to use to quote identifiers and names\r
+       //var $_bindInputArray = true;\r
+       \r
+       function ADODB_mysqli() \r
+       {                       \r
+         if(!extension_loaded("mysqli"))\r
+           {\r
+             trigger_error("You must have the MySQLi extension.", E_USER_ERROR);\r
+           }\r
+       }\r
+       \r
+       function IfNull( $field, $ifNull ) \r
+       {\r
+               return " IFNULL($field, $ifNull) "; // if MySQL\r
+       }\r
+       \r
+       function ServerInfo()\r
+       {\r
+               $arr['description'] = $this->GetOne("select version()");\r
+               $arr['version'] = ADOConnection::_findvers($arr['description']);\r
+               return $arr;\r
+       }\r
+       \r
+       \r
+       function BeginTrans()\r
+       {         \r
+               if ($this->transOff) return true;\r
+               $this->transCnt += 1;\r
+               $this->Execute('SET AUTOCOMMIT=0');\r
+               $this->Execute('BEGIN');\r
+               return true;\r
+       }\r
+       \r
+       function CommitTrans($ok=true) \r
+       {\r
+               if ($this->transOff) return true; \r
+               if (!$ok) return $this->RollbackTrans();\r
+               \r
+               if ($this->transCnt) $this->transCnt -= 1;\r
+               $this->Execute('COMMIT');\r
+               $this->Execute('SET AUTOCOMMIT=1');\r
+               return true;\r
+       }\r
+       \r
+       function RollbackTrans()\r
+       {\r
+               if ($this->transOff) return true;\r
+               if ($this->transCnt) $this->transCnt -= 1;\r
+               $this->Execute('ROLLBACK');\r
+               $this->Execute('SET AUTOCOMMIT=1');\r
+               return true;\r
+       }\r
+       \r
+       // if magic quotes disabled, use mysql_real_escape_string()\r
+       // From readme.htm:\r
+       // Quotes a string to be sent to the database. The $magic_quotes_enabled\r
+       // parameter may look funny, but the idea is if you are quoting a \r
+       // string extracted from a POST/GET variable, then \r
+       // pass get_magic_quotes_gpc() as the second parameter. This will \r
+       // ensure that the variable is not quoted twice, once by qstr and once \r
+       // by the magic_quotes_gpc.\r
+       //\r
+       //Eg. $s = $db->qstr(HTTP_GET_VARS['name'],get_magic_quotes_gpc());\r
+       function qstr($s, $magic_quotes = false)\r
+       {\r
+         if (!$magic_quotes) {\r
+           if (ADODB_PHPVER >= 0x5000) {\r
+           //  $this->_connectionID = $this->mysqli_resolve_link($this->_connectionID);\r
+             return "'" . mysqli_real_escape_string($this->_connectionID, $s) . "'";\r
+           }\r
+           else\r
+             {\r
+               trigger_error("phpver < 5 not implemented", E_USER_ERROR);\r
+             }\r
+           \r
+           if ($this->replaceQuote[0] == '\\')\r
+             {\r
+               $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);\r
+             }\r
+           return  "'".str_replace("'",$this->replaceQuote,$s)."'"; \r
+         }\r
+         // undo magic quotes for "\r
+         $s = str_replace('\\"','"',$s);\r
+         return "'$s'";\r
+       }\r
+       \r
+       function _insertid()\r
+       {\r
+//       $this->_connectionID = $this->mysqli_resolve_link($this->_connectionID);\r
+         $result = @mysqli_insert_id($this->_connectionID);\r
+         if ($result == -1){\r
+             if ($this->debug) ADOConnection::outp("mysqli_insert_id() failed : "  . $this->ErrorMsg());\r
+         }\r
+         return $result;\r
+       }\r
+       \r
+       // Only works for INSERT, UPDATE and DELETE query's\r
+       function _affectedrows()\r
+       {\r
+       //  $this->_connectionID = $this->mysqli_resolve_link($this->_connectionID);\r
+         $result =  @mysqli_affected_rows($this->_connectionID);\r
+         if ($result == -1) {\r
+             if ($this->debug) ADOConnection::outp("mysqli_affected_rows() failed : "  . $this->ErrorMsg());\r
+         }\r
+         return $result;\r
+       }\r
+  \r
+       // See http://www.mysql.com/doc/M/i/Miscellaneous_functions.html\r
+       // Reference on Last_Insert_ID on the recommended way to simulate sequences\r
+       var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);";\r
+       var $_genSeqSQL = "create table %s (id int not null)";\r
+       var $_genSeq2SQL = "insert into %s values (%s)";\r
+       var $_dropSeqSQL = "drop table %s";\r
+       \r
+       function CreateSequence($seqname='adodbseq',$startID=1)\r
+       {\r
+               if (empty($this->_genSeqSQL)) return false;\r
+               $u = strtoupper($seqname);\r
+               \r
+               $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));\r
+               if (!$ok) return false;\r
+               return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));\r
+       }\r
+       \r
+       function GenID($seqname='adodbseq',$startID=1)\r
+       {\r
+               // post-nuke sets hasGenID to false\r
+               if (!$this->hasGenID) return false;\r
+               \r
+               $getnext = sprintf($this->_genIDSQL,$seqname);\r
+               $holdtransOK = $this->_transOK; // save the current status\r
+               $rs = @$this->Execute($getnext);\r
+               if (!$rs) {\r
+                       if ($holdtransOK) $this->_transOK = true; //if the status was ok before reset\r
+                       $u = strtoupper($seqname);\r
+                       $this->Execute(sprintf($this->_genSeqSQL,$seqname));\r
+                       $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));\r
+                       $rs = $this->Execute($getnext);\r
+               }\r
+               $this->genID = mysqli_insert_id($this->_connectionID);\r
+               \r
+               if ($rs) $rs->Close();\r
+               \r
+               return $this->genID;\r
+       }\r
+       \r
+       function &MetaDatabases()\r
+         {\r
+           $query = "SHOW DATABASES";\r
+           $ret =& $this->Execute($query);\r
+               return $ret;\r
+         }\r
+\r
+         \r
+       function &MetaIndexes ($table, $primary = FALSE)\r
+       {\r
+               // save old fetch mode\r
+               global $ADODB_FETCH_MODE;\r
+               \r
+               $save = $ADODB_FETCH_MODE;\r
+               $ADODB_FETCH_MODE = ADODB_FETCH_NUM;\r
+               if ($this->fetchMode !== FALSE) {\r
+                      $savem = $this->SetFetchMode(FALSE);\r
+               }\r
+               \r
+               // get index details\r
+               $rs = $this->Execute(sprintf('SHOW INDEXES FROM %s',$table));\r
+               \r
+               // restore fetchmode\r
+               if (isset($savem)) {\r
+                       $this->SetFetchMode($savem);\r
+               }\r
+               $ADODB_FETCH_MODE = $save;\r
+               \r
+               if (!is_object($rs)) {\r
+                       return FALSE;\r
+               }\r
+               \r
+               $indexes = array ();\r
+               \r
+               // parse index data into array\r
+               while ($row = $rs->FetchRow()) {\r
+                       if ($primary == FALSE AND $row[2] == 'PRIMARY') {\r
+                               continue;\r
+                       }\r
+                       \r
+                       if (!isset($indexes[$row[2]])) {\r
+                               $indexes[$row[2]] = array(\r
+                                       'unique' => ($row[1] == 0),\r
+                                       'columns' => array()\r
+                               );\r
+                       }\r
+                       \r
+                       $indexes[$row[2]]['columns'][$row[3] - 1] = $row[4];\r
+               }\r
+               \r
+               // sort columns by order in the index\r
+               foreach ( array_keys ($indexes) as $index )\r
+               {\r
+                       ksort ($indexes[$index]['columns']);\r
+               }\r
+               \r
+               return $indexes;\r
+       }\r
+\r
+       \r
+       // Format date column in sql string given an input format that understands Y M D\r
+       function SQLDate($fmt, $col=false)\r
+       {       \r
+               if (!$col) $col = $this->sysTimeStamp;\r
+               $s = 'DATE_FORMAT('.$col.",'";\r
+               $concat = false;\r
+               $len = strlen($fmt);\r
+               for ($i=0; $i < $len; $i++) {\r
+                       $ch = $fmt[$i];\r
+                       switch($ch) {\r
+                       case 'Y':\r
+                       case 'y':\r
+                               $s .= '%Y';\r
+                               break;\r
+                       case 'Q':\r
+                       case 'q':\r
+                               $s .= "'),Quarter($col)";\r
+                               \r
+                               if ($len > $i+1) $s .= ",DATE_FORMAT($col,'";\r
+                               else $s .= ",('";\r
+                               $concat = true;\r
+                               break;\r
+                       case 'M':\r
+                               $s .= '%b';\r
+                               break;\r
+                               \r
+                       case 'm':\r
+                               $s .= '%m';\r
+                               break;\r
+                       case 'D':\r
+                       case 'd':\r
+                               $s .= '%d';\r
+                               break;\r
+                       \r
+                       case 'H': \r
+                               $s .= '%H';\r
+                               break;\r
+                               \r
+                       case 'h':\r
+                               $s .= '%I';\r
+                               break;\r
+                               \r
+                       case 'i':\r
+                               $s .= '%i';\r
+                               break;\r
+                               \r
+                       case 's':\r
+                               $s .= '%s';\r
+                               break;\r
+                               \r
+                       case 'a':\r
+                       case 'A':\r
+                               $s .= '%p';\r
+                               break;\r
+                               \r
+                       default:\r
+                               \r
+                               if ($ch == '\\') {\r
+                                       $i++;\r
+                                       $ch = substr($fmt,$i,1);\r
+                               }\r
+                               $s .= $ch;\r
+                               break;\r
+                       }\r
+               }\r
+               $s.="')";\r
+               if ($concat) $s = "CONCAT($s)";\r
+               return $s;\r
+       }\r
+       \r
+       // returns concatenated string\r
+       // much easier to run "mysqld --ansi" or "mysqld --sql-mode=PIPES_AS_CONCAT" and use || operator\r
+       function Concat()\r
+       {\r
+               $s = "";\r
+               $arr = func_get_args();\r
+               \r
+               // suggestion by andrew005@mnogo.ru\r
+               $s = implode(',',$arr); \r
+               if (strlen($s) > 0) return "CONCAT($s)";\r
+               else return '';\r
+       }\r
+       \r
+       // dayFraction is a day in floating point\r
+       function OffsetDate($dayFraction,$date=false)\r
+       {               \r
+               if (!$date) \r
+                 $date = $this->sysDate;\r
+               return "from_unixtime(unix_timestamp($date)+($dayFraction)*24*3600)";\r
+       }\r
+       \r
+       // returns true or false\r
+       // To add: parameter int $port,\r
+       //         parameter string $socket\r
+       function _connect($argHostname = NULL, \r
+                         $argUsername = NULL, \r
+                         $argPassword = NULL, \r
+                         $argDatabasename = NULL)\r
+         {\r
+           // @ means: error surpression on\r
+           $this->_connectionID = @mysqli_init();\r
+           \r
+           if (is_null($this->_connectionID))\r
+           {\r
+             // mysqli_init only fails if insufficient memory\r
+             if ($this->debug) \r
+               ADOConnection::outp("mysqli_init() failed : "  . $this->ErrorMsg());\r
+             return false;\r
+           }\r
+           // Set connection options\r
+           // Not implemented now\r
+           // mysqli_options($this->_connection,,);\r
+           if (mysqli_real_connect($this->_connectionID,\r
+                                   $argHostname,\r
+                                   $argUsername,\r
+                                   $argPassword,\r
+                                   $argDatabasename))\r
+             {\r
+               if ($argDatabasename) \r
+                 {\r
+                   return $this->SelectDB($argDatabasename);\r
+                 }\r
+               \r
+               return true;\r
+             }\r
+           else\r
+             {\r
+               if ($this->debug) \r
+                 ADOConnection::outp("Could't connect : "  . $this->ErrorMsg());\r
+               return false;\r
+             }\r
+         }\r
+       \r
+       // returns true or false\r
+       // How to force a persistent connection\r
+       function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)\r
+         {\r
+           // not implemented in mysqli (yet)?\r
+           $this->_connectionID = mysqli_connect($argHostname,\r
+                                                 $argUsername,\r
+                                                 $argPassword,\r
+                                                 $argDatabasename);\r
+           if ($this->_connectionID === false) return false;\r
+           //      if ($this->autoRollback) $this->RollbackTrans();\r
+           if ($argDatabasename) return $this->SelectDB($argDatabasename);\r
+           return true;        \r
+         }\r
+       \r
+       // When is this used? Close old connection first?\r
+       // In _connect(), check $this->forceNewConnect? \r
+       function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)\r
+         {\r
+           $this->forceNewConnect = true;\r
+           $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);\r
+         }\r
+       \r
+       function &MetaColumns($table) \r
+       {\r
+         if ($this->metaColumnsSQL) {\r
+           global $ADODB_FETCH_MODE;\r
+           $save = $ADODB_FETCH_MODE;\r
+           $rs = false;\r
+           switch($ADODB_FETCH_MODE)\r
+             {\r
+             case ADODB_FETCH_NUM:\r
+               $ADODB_FETCH_MODE = ADODB_FETCH_NUM;\r
+               $rs = $this->Execute(sprintf($this->metaColumnsSQL,\r
+                                            $table));\r
+               \r
+               $ADODB_FETCH_MODE = $save;\r
+               if ($rs === false) break;\r
+               $retarr = array();\r
+               while (!$rs->EOF){\r
+                 $fld = new ADOFieldObject();\r
+                 $fld->name = $rs->fields[0];\r
+                 $fld->type = $rs->fields[1];\r
+                 // split type into type(length):\r
+                 if (preg_match("/^(.+)\((\d+)\)$/", $fld->type, $query_array))\r
+                   {\r
+                     $fld->type = $query_array[1];\r
+                     $fld->max_length = $query_array[2];\r
+                   }\r
+                 else\r
+                   {\r
+                     $fld->max_length = -1;\r
+                   }\r
+                 $fld->not_null = ($rs->fields[2] != 'YES');\r
+                 $fld->primary_key = ($rs->fields[3] == 'PRI');\r
+                 $fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);\r
+                 $fld->binary = (strpos($fld->type,'blob') !== false);\r
+                 if (!$fld->binary) \r
+                   {\r
+                     $d = $rs->fields[4];\r
+                     $d = $rs->fields['Default'];\r
+                     if ($d != "" && $d != "NULL")\r
+                       {\r
+                         $fld->has_default = true;\r
+                         $fld->default_value = $d;\r
+                       } \r
+                     else \r
+                       {\r
+                         $fld->has_default = false;\r
+                       }\r
+                   }\r
+                 $retarr[strtoupper($fld->name)] = $fld;       \r
+                 $rs->MoveNext();\r
+               }\r
+               break;\r
+             case ADODB_FETCH_ASSOC:\r
+             case ADODB_FETCH_DEFAULT:\r
+             case ADODB_FETCH_BOTH:\r
+               $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;\r
+               $rs = $this->Execute(sprintf($this->metaColumnsSQL,\r
+                                            $table));\r
+               $ADODB_FETCH_MODE = $save;\r
+               if ($rs === false) break;\r
+               $retarr = array();\r
+               while (!$rs->EOF){\r
+                 $fld = new ADOFieldObject();\r
+                 $fld->name = $rs->fields['Field'];\r
+                 $fld->type = $rs->fields['Type'];\r
+                               \r
+                 // split type into type(length):\r
+                 if (preg_match("/^(.+)\((\d+)\)$/", $fld->type, $query_array))\r
+                   {\r
+                     $fld->type = $query_array[1];\r
+                     $fld->max_length = $query_array[2];\r
+                   }\r
+                 else\r
+                   {\r
+                     $fld->max_length = -1;\r
+                   }\r
+                 $fld->not_null = ($rs->fields['Null'] != 'YES');\r
+                 $fld->primary_key = ($rs->fields['Key'] == 'PRI');\r
+                 $fld->auto_increment = (strpos($rs->fields['Extra'], 'auto_increment') !== false);\r
+                 $fld->binary = (strpos($fld->type,'blob') !== false);\r
+                 if (!$fld->binary) \r
+                   {\r
+                     $d = $rs->fields['Default'];\r
+                     if ($d != "" && $d != "NULL")\r
+                       {\r
+                         $fld->has_default = true;\r
+                         $fld->default_value = $d;\r
+                       } \r
+                     else \r
+                       {\r
+                         $fld->has_default = false;\r
+                       }\r
+                   }\r
+                 $retarr[strtoupper($fld->name)] = $fld;       \r
+                 $rs->MoveNext();\r
+               }\r
+               break;\r
+             default:\r
+             }\r
+           \r
+           if ($rs === false) return false;\r
+           $rs->Close();\r
+           return $retarr;     \r
+         }\r
+         return false;\r
+       }\r
+               \r
+       // returns true or false\r
+       function SelectDB($dbName) \r
+       {\r
+//         $this->_connectionID = $this->mysqli_resolve_link($this->_connectionID);\r
+           $this->databaseName = $dbName;\r
+           if ($this->_connectionID) {\r
+               $result = @mysqli_select_db($this->_connectionID, $dbName);\r
+                       if (!$result) {\r
+                       ADOConnection::outp("Select of database " . $dbName . " failed. " . $this->ErrorMsg());\r
+                       }\r
+                       return $result;         \r
+               }\r
+           return false;       \r
+       }\r
+       \r
+       // parameters use PostgreSQL convention, not MySQL\r
+       function &SelectLimit($sql,\r
+                             $nrows = -1,\r
+                             $offset = -1,\r
+                             $inputarr = false, \r
+                             $arg3 = false,\r
+                             $secs = 0)\r
+       {\r
+               $offsetStr = ($offset >= 0) ? "$offset," : '';\r
+               \r
+               if ($secs)\r
+                       $rs =& $this->CacheExecute($secs, $sql . " LIMIT $offsetStr$nrows" , $inputarr , $arg3);\r
+               else\r
+                       $rs =& $this->Execute($sql . " LIMIT $offsetStr$nrows" , $inputarr , $arg3);\r
+                       \r
+               return $rs;\r
+       }\r
+       \r
+       \r
+       function Prepare($sql)\r
+       {\r
+               return $sql;\r
+               \r
+               $stmt = mysqli_prepare($this->_connectionID,$sql);\r
+               if (!$stmt) return false;\r
+               return array($sql,$stmt);\r
+       }\r
+       \r
+       \r
+       // returns queryID or false\r
+       function _query($sql, $inputarr)\r
+       {\r
+       global $ADODB_COUNTRECS;\r
+       \r
+               if (is_array($sql)) {\r
+                       $stmt = $sql[1];\r
+                       foreach($inputarr as $k => $v) {\r
+                               if (is_string($v)) $a[] = MYSQLI_BIND_STRING;\r
+                               else if (is_integer($v)) $a[] = MYSQLI_BIND_INT; \r
+                               else $a[] = MYSQLI_BIND_DOUBLE;\r
+                               \r
+                               $fnarr =& array_merge( array($stmt,$a) , $inputarr);\r
+                               $ret = call_user_func_array('mysqli_bind_param',$fnarr);\r
+                       }\r
+                       $ret = mysqli_execute($stmt);\r
+                       return $ret;\r
+               }\r
+               if (!$mysql_res =  mysqli_query($this->_connectionID, $sql, ($ADODB_COUNTRECS) ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT)) {\r
+                   if ($this->debug) ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg());\r
+                   return false;\r
+               }\r
+               \r
+               return $mysql_res;\r
+       }\r
+\r
+       /*      Returns: the last error message from previous database operation        */      \r
+       function ErrorMsg() \r
+         {\r
+           if (empty($this->_connectionID)) \r
+             $this->_errorMsg = @mysqli_error();\r
+           else \r
+             $this->_errorMsg = @mysqli_error($this->_connectionID);\r
+           return $this->_errorMsg;\r
+         }\r
+       \r
+       /*      Returns: the last error number from previous database operation */      \r
+       function ErrorNo() \r
+         {\r
+           if (empty($this->_connectionID))  \r
+             return @mysqli_errno();\r
+           else \r
+             return @mysqli_errno($this->_connectionID);\r
+         }\r
+       \r
+       // returns true or false\r
+       function _close()\r
+         {\r
+           @mysqli_close($this->_connectionID);\r
+           $this->_connectionID = false;\r
+         }\r
+\r
+       /*\r
+       * Maximum size of C field\r
+       */\r
+       function CharMax()\r
+       {\r
+               return 255; \r
+       }\r
+       \r
+       /*\r
+       * Maximum size of X field\r
+       */\r
+       function TextMax()\r
+       {\r
+         return 4294967295; \r
+       }\r
+\r
+\r
+}\r
\r
+/*--------------------------------------------------------------------------------------\r
+        Class Name: Recordset\r
+--------------------------------------------------------------------------------------*/\r
+\r
+class ADORecordSet_mysqli extends ADORecordSet{        \r
+       \r
+       var $databaseType = "mysqli";\r
+       var $canSeek = true;\r
+       \r
+       function ADORecordSet_mysqli($queryID, $mode = false) \r
+       {\r
+         if ($mode === false) \r
+           { \r
+             global $ADODB_FETCH_MODE;\r
+             $mode = $ADODB_FETCH_MODE;\r
+           }\r
+         switch ($mode)\r
+           {\r
+           case ADODB_FETCH_NUM: \r
+             $this->fetchMode = MYSQLI_NUM; \r
+             break;\r
+           case ADODB_FETCH_ASSOC:\r
+             $this->fetchMode = MYSQLI_ASSOC; \r
+             break;\r
+           case ADODB_FETCH_DEFAULT:\r
+           case ADODB_FETCH_BOTH:\r
+           default:\r
+             $this->fetchMode = MYSQLI_ASSOC; \r
+             break;\r
+           }\r
+         $this->ADORecordSet($queryID);        \r
+       }\r
+       \r
+       function _initrs()\r
+       {\r
+           // mysqli_num_rows only return correct number, depens\r
+           // on the use of mysql_store_result and mysql_use_result\r
+           if (!$this->Connection->executeOnly) {\r
+                       $this->_numOfRows = @mysqli_num_rows($this->_queryID);\r
+                       $this->_numOfFields = @mysqli_num_fields($this->_queryID);\r
+           }\r
+           else {\r
+                       $this->_numOfRows = 0;\r
+                       $this->_numOfFields = 0;\r
+           }\r
+       }\r
+       \r
+       function &FetchField($fieldOffset = -1) \r
+       {       \r
+         $fieldnr = $fieldOffset;\r
+         if ($fieldOffset != -1) {\r
+           $fieldOffset = mysqi_field_seek($this->_queryID, $fieldnr);\r
+         }\r
+         $o = mysqli_fetch_field($this->_queryID);\r
+         return $o;\r
+       }\r
+\r
+       function &GetRowAssoc($upper = true)\r
+       {\r
+         if ($this->fetchMode == MYSQLI_ASSOC && !$upper) \r
+           return $this->fields;\r
+         $row =& ADORecordSet::GetRowAssoc($upper);\r
+         return $row;\r
+       }\r
+       \r
+       /* Use associative array to get fields array */\r
+       function Fields($colname)\r
+       {       \r
+         if ($this->fetchMode != MYSQLI_NUM) \r
+           return @$this->fields[$colname];\r
+               \r
+         if (!$this->bind) {\r
+           $this->bind = array();\r
+           for ($i = 0; $i < $this->_numOfFields; $i++) {\r
+             $o = $this->FetchField($i);\r
+             $this->bind[strtoupper($o->name)] = $i;\r
+           }\r
+         }\r
+         return $this->fields[$this->bind[strtoupper($colname)]];\r
+       }\r
+       \r
+       function _seek($row)\r
+       {\r
+         if ($this->_numOfRows == 0) \r
+           return false;\r
+\r
+         if ($row < 0)\r
+           return false;\r
+\r
+         mysqli_data_seek($this->_queryID, $row);\r
+         $this->EOF = false;\r
+         return true;\r
+       }\r
+               \r
+       // 10% speedup to move MoveNext to child class\r
+       // This is the only implementation that works now (23-10-2003).\r
+       // Other functions return no or the wrong results.\r
+       function MoveNext() \r
+       {\r
+         if ($this->EOF) \r
+           return false;\r
+         $this->_currentRow++;\r
+         switch($this->fetchMode)\r
+           {\r
+           case MYSQLI_NUM:\r
+             $this->fields = mysqli_fetch_array($this->_queryID);\r
+             break;\r
+           case MYSQLI_ASSOC:\r
+           case MYSQLI_BOTH:\r
+             $this->fields = mysqli_fetch_assoc($this->_queryID);\r
+             break;\r
+           default:\r
+           }\r
+         if (is_array($this->fields)) \r
+           return true;\r
+         $this->EOF = true;\r
+         return false;\r
+       }       \r
+       \r
+       function _fetch()\r
+       {\r
+         // mysqli_fetch_array($this->_queryID, MYSQLI_NUM) does not\r
+         // work (22-10-2003). But mysqli_fetch_array($this->_queryID) gives\r
+         // int resulttype should default to MYSQLI_BOTH,but give MYSQLI_NUM.\r
+\r
+         //      $this->fields =  mysqli_fetch_fields($this->_queryID);\r
+         //      $this->fields =  mysqli_fetch_array($this->_queryID); //, $this->fetchMode);\r
+                 \r
+         $this->fields =  mysqli_fetch_assoc($this->_queryID); // $this->fetchMode);\r
+         return is_array($this->fields);\r
+       }\r
+       \r
+       function _close() \r
+       {\r
+         mysqli_free_result($this->_queryID); \r
+         $this->_queryID = false;      \r
+       }\r
+       \r
+       function MetaType($t, $len = -1, $fieldobj = false)\r
+       {\r
+         if (is_object($t)) \r
+           {\r
+             $fieldobj = $t;\r
+             $t = $fieldobj->type;\r
+             $len = $fieldobj->max_length;\r
+           }\r
+               \r
+         $len = -1; // mysql max_length is not accurate\r
+         switch (strtoupper($t)) {\r
+         case 'STRING': \r
+         case 'CHAR':\r
+         case 'VARCHAR': \r
+         case 'TINYBLOB': \r
+         case 'TINYTEXT': \r
+         case 'ENUM': \r
+         case 'SET': \r
+           if ($len <= $this->blobSize) return 'C';\r
+           \r
+         case 'TEXT':\r
+         case 'LONGTEXT': \r
+         case 'MEDIUMTEXT':\r
+           return 'X';\r
+                       \r
+           // php_mysql extension always returns 'blob' even if 'text'\r
+           // so we have to check whether binary...\r
+         case 'IMAGE':\r
+         case 'LONGBLOB': \r
+         case 'BLOB':\r
+         case 'MEDIUMBLOB':\r
+           return !empty($fieldobj->binary) ? 'B' : 'X';\r
+         case 'YEAR':\r
+         case 'DATE': \r
+           return 'D';\r
+               \r
+         case 'TIME':\r
+         case 'DATETIME':\r
+         case 'TIMESTAMP': return 'T';\r
+               \r
+         case 'INT': \r
+         case 'INTEGER':\r
+         case 'BIGINT':\r
+         case 'TINYINT':\r
+         case 'MEDIUMINT':\r
+         case 'SMALLINT': \r
+                       \r
+           if (!empty($fieldobj->primary_key)) return 'R';\r
+           else return 'I';\r
+           // Added floating-point types\r
+           // Maybe not necessery.\r
+         case 'FLOAT':\r
+         case 'DOUBLE':\r
+           //          case 'DOUBLE PRECISION':\r
+         case 'DECIMAL':\r
+         case 'DEC':\r
+         case 'FIXED':\r
+         default: \r
+           return 'N';\r
+         }\r
+       }\r
+       \r
+\r
+}\r
\r
+}\r
+\r
+?>
\ No newline at end of file
index 2c3dc95b5e36c117236aa94026a2a39d8a3e88df..8b82ea50ba721fe86c41e5fddf7712fc4e36e9f5 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
 \r
 /*\r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
index 03ff2d280a9fd0192e7fc700de9c0e7c09ad3ba0..ae6563e2d8a861bf8dc0e1c18dd9de3af1d027fa 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
 /*\r
 \r
-  version V4.01 23 Oct 2003 (c) 2000-2003 John Lim. All rights reserved.\r
+  version V4.11 27 Jan 2004 (c) 2000-2004 John Lim. All rights reserved.\r
 \r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
@@ -33,9 +33,8 @@ year entries allows you to become year-2000 compliant. For example:
 NLS_DATE_FORMAT='RR-MM-DD'\r
 \r
 You can also modify the date format using the ALTER SESSION command. \r
-\r
-\r
 */\r
+\r
 class ADODB_oci8 extends ADOConnection {\r
        var $databaseType = 'oci8';\r
        var $dataProvider = 'oci8';\r
@@ -55,8 +54,7 @@ class ADODB_oci8 extends ADOConnection {
        var $_genSeqSQL = "CREATE SEQUENCE %s START WITH %s";\r
        var $_dropSeqSQL = "DROP SEQUENCE %s";\r
        var $hasAffectedRows = true;\r
-       var $upperCase = 'upper';\r
-       var $substr = 'substr';\r
+       var $random = "abs(mod(DBMS_RANDOM.RANDOM,10000001)/10000000)";\r
        var $noNullStrings = false;\r
        var $connectSID = false;\r
        var $_bind = false;\r
@@ -150,6 +148,9 @@ NATSOFT.DOMAIN =
 */\r
        function _connect($argHostname, $argUsername, $argPassword, $argDatabasename,$mode=0)\r
        {\r
+               if (!function_exists('OCIPLogon')) return false;\r
+               \r
+               \r
         $this->_errorMsg = false;\r
                $this->_errorCode = false;\r
                \r
@@ -207,6 +208,8 @@ NATSOFT.DOMAIN =
                return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename,1);\r
        }\r
        \r
+       \r
+       \r
        // returns true or false\r
        function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)\r
        {\r
@@ -438,7 +441,9 @@ NATSOFT.DOMAIN =
                        }\r
                        // note that $nrows = 0 still has to work ==> no rows returned\r
 \r
-                       return ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);\r
+                       $rs =& ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);\r
+                       return $rs;\r
+                       \r
                } else {\r
                         // Algorithm by Tomas V V Cox, from PEAR DB oci8.php\r
                        \r
@@ -449,8 +454,7 @@ NATSOFT.DOMAIN =
                         }\r
                         \r
                         if (is_array($inputarr)) {\r
-                                reset($inputarr);\r
-                                while (list($k,$v) = each($inputarr)) {\r
+                               foreach($inputarr as $k => $v) {\r
                                        if (is_array($v)) {\r
                                                if (sizeof($v) == 2) // suggested by g.giunta@libero.\r
                                                        OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1]);\r
@@ -498,8 +502,9 @@ NATSOFT.DOMAIN =
                                $inputarr['adodb_nrows'] = $nrows;\r
                                $inputarr['adodb_offset'] = $offset;\r
                                \r
-                       if ($secs2cache>0) return $this->CacheExecute($secs2cache, $sql,$inputarr);\r
-                       else return $this->Execute($sql,$inputarr);\r
+                       if ($secs2cache>0) $rs =& $this->CacheExecute($secs2cache, $sql,$inputarr);\r
+                       else $rs =& $this->Execute($sql,$inputarr);\r
+                       return $rs;\r
                }\r
        \r
        }\r
@@ -589,7 +594,7 @@ NATSOFT.DOMAIN =
                \r
                $stmt = $this->Prepare('insert into emp (empno, ename) values (:empno, :ename)');\r
        */\r
-       function Prepare($sql)\r
+       function Prepare($sql,$cursor=false)\r
        {\r
        static $BINDNUM = 0;\r
        \r
@@ -600,7 +605,7 @@ NATSOFT.DOMAIN =
                $BINDNUM += 1;\r
                \r
                if (@OCIStatementType($stmt) == 'BEGIN') {\r
-                       return array($sql,$stmt,0,$BINDNUM,OCINewCursor($this->_connectionID));\r
+                       return array($sql,$stmt,0,$BINDNUM, ($cursor) ? false : OCINewCursor($this->_connectionID));\r
                } \r
                \r
                return array($sql,$stmt,0,$BINDNUM);\r
@@ -623,13 +628,12 @@ NATSOFT.DOMAIN =
        */\r
        function &ExecuteCursor($sql,$cursorName='rs',$params=false)\r
        {\r
-               $stmt = ADODB_oci8::Prepare($sql);\r
+               $stmt = ADODB_oci8::Prepare($sql,true); # true to allocate OCINewCursor\r
                        \r
                if (is_array($stmt) && sizeof($stmt) >= 5) {\r
                        $this->Parameter($stmt, $ignoreCur, $cursorName, false, -1, OCI_B_CURSOR);\r
                        if ($params) {\r
-                               reset($params);\r
-                               while (list($k,$v) = each($params)) {\r
+                               foreach($params as $k => $v) {\r
                                        $this->Parameter($stmt,$params[$k], $k);\r
                                }\r
                        }\r
@@ -711,7 +715,9 @@ NATSOFT.DOMAIN =
        function Parameter(&$stmt,&$var,$name,$isOutput=false,$maxLen=4000,$type=false)\r
        {\r
                        if  ($this->debug) {\r
-                               ADOConnection::outp( "Parameter(\$stmt, \$php_var='$var', \$name='$name');");\r
+                               $prefix = ($isOutput) ? 'Out' : 'In';\r
+                               $ztype = (empty($type)) ? 'false' : $type;\r
+                               ADOConnection::outp( "{$prefix}Parameter(\$stmt, \$php_var='$var', \$name='$name', \$maxLen=$maxLen, \$type=$ztype);");\r
                        }\r
                        return $this->Bind($stmt,$var,$maxLen,$type,$name);\r
        }\r
@@ -747,8 +753,7 @@ NATSOFT.DOMAIN =
                                } else {\r
                                // one statement to bind them all\r
                                        $bindarr = array();\r
-                                       reset($inputarr);\r
-                                       while(list($k,$v) = each($inputarr)) {\r
+                                       foreach($inputarr as $k => $v) {\r
                                                $bindarr[$k] = $v;\r
                                                OCIBindByName($stmt,":$k",$bindarr[$k],4000);\r
                                        }\r
@@ -765,8 +770,7 @@ NATSOFT.DOMAIN =
                if (defined('ADODB_PREFETCH_ROWS')) @OCISetPrefetch($stmt,ADODB_PREFETCH_ROWS);\r
                        \r
                if (is_array($inputarr)) {\r
-                       reset($inputarr);\r
-                       while(list($k,$v) = each($inputarr)) {\r
+                       foreach($inputarr as $k => $v) {\r
                                if (is_array($v)) {\r
                                        if (sizeof($v) == 2) // suggested by g.giunta@libero.\r
                                                OCIBindByName($stmt,":$k",$inputarr[$k][0],$v[1]);\r
@@ -795,17 +799,17 @@ NATSOFT.DOMAIN =
                                        return $stmt;\r
                                        \r
                 case "BEGIN":\r
-                    if (is_array($sql) && isset($sql[4])) {\r
+                    if (is_array($sql) && !empty($sql[4])) {\r
                                                $cursor = $sql[4];\r
                                                if (is_resource($cursor)) {\r
-                                                       OCIExecute($cursor);                                            \r
+                                                       $ok = OCIExecute($cursor);      \r
                                return $cursor;\r
                                                }\r
                                                return $stmt;\r
                     } else {\r
                                                if (is_resource($stmt)) {\r
-                                                               OCIFreeStatement($stmt);\r
-                                                               return true;\r
+                                                       OCIFreeStatement($stmt);\r
+                                                       return true;\r
                                                }\r
                         return $stmt;\r
                     }\r
@@ -984,10 +988,10 @@ class ADORecordset_oci8 extends ADORecordSet {
                \r
                $this->_inited = true;\r
                if ($this->_queryID) {\r
-                                               \r
+                       \r
                        $this->_currentRow = 0;\r
                        @$this->_initrs();\r
-                       $this->EOF = !$this->_fetch();  \r
+                       $this->EOF = !$this->_fetch();\r
                        \r
                        /*\r
                        // based on idea by Gaetano Giunta to detect unusual oracle errors\r
@@ -1065,7 +1069,10 @@ class ADORecordset_oci8 extends ADORecordSet {
        /* Optimize SelectLimit() by using OCIFetch() instead of OCIFetchInto() */\r
        function &GetArrayLimit($nrows,$offset=-1) \r
        {\r
-               if ($offset <= 0) return $this->GetArray($nrows);\r
+               if ($offset <= 0) {\r
+                       $arr =& $this->GetArray($nrows);\r
+                       return $arr;\r
+               }\r
                for ($i=1; $i < $offset; $i++) \r
                        if (!@OCIFetch($this->_queryID)) return array();\r
                        \r
@@ -1139,7 +1146,7 @@ class ADORecordset_oci8 extends ADORecordSet {
                case 'NCLOB':\r
                case 'LONG':\r
                case 'LONG VARCHAR':\r
-               case 'CLOB';\r
+               case 'CLOB':\r
                return 'X';\r
                \r
                case 'LONG RAW':\r
index 704de4175cef7702928e218c9d91eb8e91f2e366..4dde2b363b8f07d1c1ff23a69cc49c42202d91fc 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /** \r
- * @version V4.01 23 Oct 2003 (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+ * @version V4.11 27 Jan 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
  * Released under both BSD license and Lesser GPL library license. \r
  * Whenever there is any discrepancy between the two licenses, \r
  * the BSD license will take precedence. \r
index a8e08e8eb29466222f5e1b1fe45b0bdffbafa696..2d91f8a722fe2df6f48ea84512587649a97edd83 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /*\r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim. All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim. All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
@@ -112,10 +112,18 @@ class ADORecordset_oci8po extends ADORecordset_oci8 {
        // 10% speedup to move MoveNext to child class\r
        function MoveNext() \r
        {\r
+       \r
                if (!$this->EOF) {              \r
                        $this->_currentRow++;\r
                        if(@OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode)) {\r
+                       global $ADODB_ANSI_PADDING_OFF;\r
+       \r
                                if ($this->fetchMode & OCI_ASSOC) $this->_updatefields();\r
+                               if (!empty($ADODB_ANSI_PADDING_OFF)) {\r
+                                       foreach($this->fields as $k => $v) {\r
+                                               if (is_string($v)) $this->fields[$k] = rtrim($v);\r
+                                       }\r
+                               }\r
                                return true;\r
                        }\r
                        $this->EOF = true;\r
@@ -150,7 +158,7 @@ class ADORecordset_oci8po extends ADORecordset_oci8 {
                $arr = array();\r
                $lowercase = (ADODB_ASSOC_CASE == 0);\r
                \r
-               foreach ($this->fields as $k => $v) {\r
+               foreach($this->fields as $k => $v) {\r
                        if (is_integer($k)) $arr[$k] = $v;\r
                        else {\r
                                if ($lowercase)\r
@@ -166,7 +174,14 @@ class ADORecordset_oci8po extends ADORecordset_oci8 {
        {\r
                $ret = @OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode);\r
                if ($ret) {\r
-                       if ($this->fetchMode & OCI_ASSOC) $this->_updatefields();\r
+               global $ADODB_ANSI_PADDING_OFF;\r
+       \r
+                               if ($this->fetchMode & OCI_ASSOC) $this->_updatefields();\r
+                               if (!empty($ADODB_ANSI_PADDING_OFF)) {\r
+                                       foreach($this->fields as $k => $v) {\r
+                                               if (is_string($v)) $this->fields[$k] = rtrim($v);\r
+                                       }\r
+                               }\r
                }\r
                return $ret;\r
        }\r
index b9b8ac01f5368172ab12fb28c5399952afc43635..aff3efa390f4cf15d86cc66d4f4c125e37411bf0 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
@@ -156,6 +156,9 @@ class ADODB_odbc extends ADOConnection {
        function _connect($argDSN, $argUsername, $argPassword, $argDatabasename)\r
        {\r
        global $php_errormsg;\r
+               \r
+               if (!function_exists('odbc_connect')) return false;\r
+               \r
                if ($this->debug && $argDatabasename) {\r
                        ADOConnection::outp("For odbc Connect(), $argDatabasename is not used. Place dsn in 1st parameter.");\r
                }\r
@@ -173,6 +176,9 @@ class ADODB_odbc extends ADOConnection {
        function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)\r
        {\r
        global $php_errormsg;\r
+       \r
+               if (!function_exists('odbc_connect')) return false;\r
+               \r
                $php_errormsg = '';\r
                if ($this->debug && $argDatabasename) {\r
                        ADOConnection::outp("For odbc PConnect(), $argDatabasename is not used. Place dsn in 1st parameter.");\r
@@ -352,7 +358,9 @@ class ADODB_odbc extends ADOConnection {
        global $ADODB_FETCH_MODE;\r
        \r
                $table = strtoupper($table);\r
-\r
+               $schema = false;\r
+               $this->_findschema($table,$schema);\r
+               \r
                $savem = $ADODB_FETCH_MODE;\r
                $ADODB_FETCH_MODE = ADODB_FETCH_NUM;\r
        \r
@@ -394,7 +402,6 @@ class ADODB_odbc extends ADOConnection {
                \r
                if (!$rs) return false;\r
                \r
-               //print_r($rs);\r
                $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;\r
                $rs->_fetch();\r
                $retarr = array();\r
@@ -415,8 +422,8 @@ class ADODB_odbc extends ADOConnection {
                11 REMARKS\r
                */\r
                while (!$rs->EOF) {\r
-                       //print_r($rs->fields);\r
-                       if (strtoupper($rs->fields[2]) == $table) {\r
+                       //adodb_pr($rs->fields);\r
+                       if (strtoupper($rs->fields[2]) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) {\r
                                $fld = new ADOFieldObject();\r
                                $fld->name = $rs->fields[3];\r
                                $fld->type = $this->ODBCTypes($rs->fields[4]);\r
@@ -632,7 +639,10 @@ class ADORecordSet_odbc extends ADORecordSet {
        // speed up SelectLimit() by switching to ADODB_FETCH_NUM as ADODB_FETCH_ASSOC is emulated\r
        function &GetArrayLimit($nrows,$offset=-1) \r
        {\r
-               if ($offset <= 0) return $this->GetArray($nrows);\r
+               if ($offset <= 0) {\r
+                       $rs =& $this->GetArray($nrows);\r
+                       return $rs;\r
+               }\r
                $savem = $this->fetchMode;\r
                $this->fetchMode = ADODB_FETCH_NUM;\r
                $this->Move($offset);\r
index 19a0b2cfef1d9ea0763625408cbb26d05d2be96d..435bd73465fb61b2105b57c4a6fd521a6fe793ad 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
@@ -31,6 +31,7 @@ class  ADODB_odbc_mssql extends ADODB_odbc {
        var $rightOuter = '=*';\r
        var $upperCase = 'upper';\r
        var $substr = 'substring';\r
+       var $length = 'len';\r
        var $ansiOuter = true; // for mssql7 or later\r
        var $identitySQL = 'select @@IDENTITY'; // 'select SCOPE_IDENTITY'; # for mssql 2000\r
        var $hasInsertID = true;\r
@@ -157,9 +158,11 @@ order by constraint_name, referenced_table_name, keyno";
                if ($nrows > 0 && $offset <= 0) {\r
                        $sql = preg_replace(\r
                                '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop." $nrows ",$sql);\r
-                       return $this->Execute($sql,$inputarr);\r
+                       $rs =& $this->Execute($sql,$inputarr);\r
                } else\r
-                       return ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);\r
+                       $rs =& ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);\r
+                       \r
+               return $rs;\r
        }\r
        \r
        // Format date column in sql string given an input format that understands Y M D\r
index 8647b1baea73e690e94e427f828150c9fa045e1e..293af7653f08cb0a341a9b59441bce647b47f951 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
index b724ff17450229ae9b1fe57d40ef5ef9b95b5977..ec7b81165b08357f95c5a65a48d9cc7983b74dda 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /*\r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
index be049c4f11f93389ed95a1e28b33bd32fc7aa526..81ad7a0d4e6b806588ec0a53b9614f86e229d59c 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /*\r
- V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+ V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
index d8ac97c9d3b79982339332b7f55db8c82561a762..a259257d6974b07a17f0184e96d39fb6a81d8c72 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /*\r
- V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+ V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
@@ -69,8 +69,17 @@ class ADODB_postgres64 extends ADOConnection{
                FROM pg_class c, pg_attribute a,pg_type t \r
                WHERE relkind = 'r' AND (c.relname='%s' or c.relname = lower('%s')) and a.attname not like '....%%'\r
 AND a.attnum > 0 AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";\r
+\r
+       var $metaColumnsSQL1 = "SELECT a.attname, t.typname, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, a.attnum \r
+FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n \r
+WHERE relkind = 'r' AND (c.relname='%s' or c.relname = lower('%s'))\r
+ and c.relnamespace=n.oid and n.nspname='%s' \r
+       and a.attname not like '....%%' AND a.attnum > 0 \r
+       AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";\r
+       \r
        // get primary key etc -- from Freek Dijkstra\r
-       var $metaKeySQL = "SELECT ic.relname AS index_name, a.attname AS column_name,i.indisunique AS unique_key, i.indisprimary AS primary_key FROM pg_class bc, pg_class ic, pg_index i, pg_attribute a WHERE bc.oid = i.indrelid AND ic.oid = i.indexrelid AND (i.indkey[0] = a.attnum OR i.indkey[1] = a.attnum OR i.indkey[2] = a.attnum OR i.indkey[3] = a.attnum OR i.indkey[4] = a.attnum OR i.indkey[5] = a.attnum OR i.indkey[6] = a.attnum OR i.indkey[7] = a.attnum) AND a.attrelid = bc.oid AND bc.relname = '%s'";\r
+       var $metaKeySQL = "SELECT ic.relname AS index_name, a.attname AS column_name,i.indisunique AS unique_key, i.indisprimary AS primary_key \r
+       FROM pg_class bc, pg_class ic, pg_index i, pg_attribute a WHERE bc.oid = i.indrelid AND ic.oid = i.indexrelid AND (i.indkey[0] = a.attnum OR i.indkey[1] = a.attnum OR i.indkey[2] = a.attnum OR i.indkey[3] = a.attnum OR i.indkey[4] = a.attnum OR i.indkey[5] = a.attnum OR i.indkey[6] = a.attnum OR i.indkey[7] = a.attnum) AND a.attrelid = bc.oid AND bc.relname = '%s'";\r
        \r
        var $hasAffectedRows = true;\r
        var $hasLimit = false;  // set to true for pgsql 7 only. support pgsql/mysql SELECT * FROM TABLE LIMIT 10\r
@@ -85,8 +94,9 @@ AND a.attnum > 0 AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum
        var $_genSeqSQL = "CREATE SEQUENCE %s START %s";\r
        var $_dropSeqSQL = "DROP SEQUENCE %s";\r
        var $metaDefaultsSQL = "SELECT d.adnum as num, d.adsrc as def from pg_attrdef d, pg_class c where d.adrelid=c.oid and c.relname='%s' order by d.adnum";\r
-       var $upperCase = 'upper';\r
-       var $substr = "substr";\r
+       var $random = 'random()';               /// random function\r
+       var $autoRollback = true; // apparently pgsql does not autorollback properly before 4.3.4\r
+                                                       // http://bugs.php.net/bug.php?id=25404\r
        \r
        // The last (fmtTimeStamp is not entirely correct: \r
        // PostgreSQL also has support for time zones, \r
@@ -145,7 +155,7 @@ a different OID if a database must be reloaded. */
                if (!is_resource($this->_resultid) || get_resource_type($this->_resultid) !== 'pgsql result') return false;\r
                return pg_cmdtuples($this->_resultid);\r
    }\r
-\r
+   \r
        \r
                // returns true/false\r
        function BeginTrans()\r
@@ -348,6 +358,8 @@ select viewname,'V' from pg_views where viewname like $mask";
        function BlobEncode($blob)\r
        {\r
                if (ADODB_PHPVER >= 0x4200) return pg_escape_bytea($blob);\r
+               \r
+               /*92=backslash, 0=null, 39=single-quote*/\r
                $badch = array(chr(92),chr(0),chr(39)); # \  null  '\r
                $fixch = array('\\\\134','\\\\000','\\\\047');\r
                return adodb_str_replace($badch,$fixch,$blob);\r
@@ -357,8 +369,8 @@ select viewname,'V' from pg_views where viewname like $mask";
        \r
        function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')\r
        {\r
-               return $this->Execute("UPDATE $table SET $column=? WHERE $where",\r
-                       array($this->BlobEncode($val))) != false;\r
+               // do not use bind params which uses qstr(), as blobencode() already quotes data\r
+               return $this->Execute("UPDATE $table SET $column='".$this->BlobEncode($val)."'::bytea WHERE $where");\r
        }\r
        \r
        function OffsetDate($dayFraction,$date=false)\r
@@ -368,111 +380,177 @@ select viewname,'V' from pg_views where viewname like $mask";
        }\r
        \r
 \r
-       // converts field names to lowercase \r
-       function &MetaColumns($table) \r
+       // for schema support, pass in the $table param "$schema.$tabname".\r
+       // converts field names to lowercase, $upper is ignored\r
+       function &MetaColumns($table,$upper=true) \r
        {\r
        global $ADODB_FETCH_MODE;\r
        \r
-               //if (strncmp(PHP_OS,'WIN',3) === 0);\r
+               $schema = false;\r
+               $this->_findschema($table,$schema);\r
+               \r
                $table = strtolower($table);\r
-       \r
-               if (!empty($this->metaColumnsSQL)) { \r
-                       $save = $ADODB_FETCH_MODE;\r
-                       $ADODB_FETCH_MODE = ADODB_FETCH_NUM;\r
-                       if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);\r
-                       $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table,$table));\r
+\r
+               $save = $ADODB_FETCH_MODE;\r
+               $ADODB_FETCH_MODE = ADODB_FETCH_NUM;\r
+               if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);\r
+               \r
+               if ($schema) $rs =& $this->Execute(sprintf($this->metaColumnsSQL1,$table,$table,$schema));\r
+               else $rs =& $this->Execute(sprintf($this->metaColumnsSQL,$table,$table));\r
+               if (isset($savem)) $this->SetFetchMode($savem);\r
+               $ADODB_FETCH_MODE = $save;\r
+               \r
+               if ($rs === false) return false;\r
+               \r
+               if (!empty($this->metaKeySQL)) {\r
+                       // If we want the primary keys, we have to issue a separate query\r
+                       // Of course, a modified version of the metaColumnsSQL query using a \r
+                       // LEFT JOIN would have been much more elegant, but postgres does \r
+                       // not support OUTER JOINS. So here is the clumsy way.\r
+                       \r
+                       $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;\r
+                       \r
+                       $rskey = $this->Execute(sprintf($this->metaKeySQL,($table)));\r
+                       // fetch all result in once for performance.\r
+                       $keys =& $rskey->GetArray();\r
                        if (isset($savem)) $this->SetFetchMode($savem);\r
                        $ADODB_FETCH_MODE = $save;\r
                        \r
-                       if ($rs === false) return false;\r
-                       \r
-                       if (!empty($this->metaKeySQL)) {\r
-                               // If we want the primary keys, we have to issue a separate query\r
-                               // Of course, a modified version of the metaColumnsSQL query using a \r
-                               // LEFT JOIN would have been much more elegant, but postgres does \r
-                               // not support OUTER JOINS. So here is the clumsy way.\r
-                               \r
-                               $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;\r
-                               \r
-                               $rskey = $this->Execute(sprintf($this->metaKeySQL,($table)));\r
-                               // fetch all result in once for performance.\r
-                               $keys =& $rskey->GetArray();\r
-                               if (isset($savem)) $this->SetFetchMode($savem);\r
-                               $ADODB_FETCH_MODE = $save;\r
-                               \r
-                               $rskey->Close();\r
-                               unset($rskey);\r
-                       }\r
+                       $rskey->Close();\r
+                       unset($rskey);\r
+               }\r
 \r
-                       $rsdefa = array();\r
-                       if (!empty($this->metaDefaultsSQL)) {\r
-                               $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;\r
-                               $sql = sprintf($this->metaDefaultsSQL, ($table));\r
-                               $rsdef = $this->Execute($sql);\r
-                               if (isset($savem)) $this->SetFetchMode($savem);\r
-                               $ADODB_FETCH_MODE = $save;\r
-                               \r
-                               if ($rsdef) {\r
-                                       while (!$rsdef->EOF) {\r
-                                               $num = $rsdef->fields['num'];\r
-                                               $s = $rsdef->fields['def'];\r
-                                               if (substr($s, 0, 1) == "'") { /* quoted strings hack... for now... fixme */\r
-                                                       $s = substr($s, 1);\r
-                                                       $s = substr($s, 0, strlen($s) - 1);\r
-                                               }\r
-       \r
-                                               $rsdefa[$num] = $s;\r
-                                               $rsdef->MoveNext();\r
+               $rsdefa = array();\r
+               if (!empty($this->metaDefaultsSQL)) {\r
+                       $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;\r
+                       $sql = sprintf($this->metaDefaultsSQL, ($table));\r
+                       $rsdef = $this->Execute($sql);\r
+                       if (isset($savem)) $this->SetFetchMode($savem);\r
+                       $ADODB_FETCH_MODE = $save;\r
+                       \r
+                       if ($rsdef) {\r
+                               while (!$rsdef->EOF) {\r
+                                       $num = $rsdef->fields['num'];\r
+                                       $s = $rsdef->fields['def'];\r
+                                       if (substr($s, 0, 1) == "'") { /* quoted strings hack... for now... fixme */\r
+                                               $s = substr($s, 1);\r
+                                               $s = substr($s, 0, strlen($s) - 1);\r
                                        }\r
-                               } else {\r
-                                       ADOConnection::outp( "==> SQL => " . $sql);\r
+\r
+                                       $rsdefa[$num] = $s;\r
+                                       $rsdef->MoveNext();\r
                                }\r
-                               unset($rsdef);\r
+                       } else {\r
+                               ADOConnection::outp( "==> SQL => " . $sql);\r
+                       }\r
+                       unset($rsdef);\r
+               }\r
+       \r
+               $retarr = array();\r
+               while (!$rs->EOF) {     \r
+                       $fld = new ADOFieldObject();\r
+                       $fld->name = $rs->fields[0];\r
+                       $fld->type = $rs->fields[1];\r
+                       $fld->max_length = $rs->fields[2];\r
+                       if ($fld->max_length <= 0) $fld->max_length = $rs->fields[3]-4;\r
+                       if ($fld->max_length <= 0) $fld->max_length = -1;\r
+                       \r
+                       // dannym\r
+                       // 5 hasdefault; 6 num-of-column\r
+                       $fld->has_default = ($rs->fields[5] == 't');\r
+                       if ($fld->has_default) {\r
+                               $fld->default_value = $rsdefa[$rs->fields[6]];\r
                        }\r
-               \r
-                       $retarr = array();\r
-                       while (!$rs->EOF) {     \r
-                               $fld = new ADOFieldObject();\r
-                               $fld->name = $rs->fields[0];\r
-                               $fld->type = $rs->fields[1];\r
-                               $fld->max_length = $rs->fields[2];\r
-                               if ($fld->max_length <= 0) $fld->max_length = $rs->fields[3]-4;\r
-                               if ($fld->max_length <= 0) $fld->max_length = -1;\r
-                               \r
-                               // dannym\r
-                               // 5 hasdefault; 6 num-of-column\r
-                               $fld->has_default = ($rs->fields[5] == 't');\r
-                               if ($fld->has_default) {\r
-                                       $fld->default_value = $rsdefa[$rs->fields[6]];\r
-                               }\r
 \r
-                               //Freek\r
-                               if ($rs->fields[4] == $this->true) {\r
-                                       $fld->not_null = true;\r
-                               }\r
-                               \r
-                               // Freek\r
-                               if (is_array($keys)) {\r
-                                       reset ($keys);\r
-                                       while (list($x,$key) = each($keys)) {\r
-                                               if ($fld->name == $key['column_name'] AND $key['primary_key'] == $this->true) \r
-                                                       $fld->primary_key = true;\r
-                                               if ($fld->name == $key['column_name'] AND $key['unique_key'] == $this->true) \r
-                                                       $fld->unique = true; // What name is more compatible?\r
-                                       }\r
+                       //Freek\r
+                       if ($rs->fields[4] == $this->true) {\r
+                               $fld->not_null = true;\r
+                       }\r
+                       \r
+                       // Freek\r
+                       if (is_array($keys)) {\r
+                               foreach($keys as $key) {\r
+                                       if ($fld->name == $key['column_name'] AND $key['primary_key'] == $this->true) \r
+                                               $fld->primary_key = true;\r
+                                       if ($fld->name == $key['column_name'] AND $key['unique_key'] == $this->true) \r
+                                               $fld->unique = true; // What name is more compatible?\r
                                }\r
-                               \r
-                               if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;     \r
-                               else $retarr[strtoupper($fld->name)] = $fld;\r
-                               \r
-                               $rs->MoveNext();\r
                        }\r
-                       $rs->Close();\r
-                       return $retarr; \r
+                       \r
+                       if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;     \r
+                       else $retarr[($upper) ? strtoupper($fld->name) : $fld->name] = $fld;\r
+                       \r
+                       $rs->MoveNext();\r
                }\r
-               return false;\r
+               $rs->Close();\r
+               return $retarr; \r
+               \r
        }\r
 \r
+         function &MetaIndexes ($table, $primary = FALSE)\r
+      {\r
+         global $ADODB_FETCH_MODE;\r
+                \r
+                               $schema = false;\r
+                               $this->_findschema($table,$schema);\r
+                               \r
+                               if ($schema) { // requires pgsql 7.3+ - pg_namespace used.\r
+                                       $sql = '\r
+SELECT c.relname as "Name", i.indisunique as "Unique", i.indkey as "Columns" \r
+FROM pg_catalog.pg_class c \r
+JOIN pg_catalog.pg_index i ON i.indexrelid=c.oid \r
+JOIN pg_catalog.pg_class c2 ON c2.oid=i.indrelid\r
+       ,pg_namespace n \r
+WHERE c2.relname=\'%s\' and c.relnamespace=c2.relnamespace and c.relnamespace=n.oid and n.nspname=\'%s\' AND i.indisprimary=false';\r
+                               } else {\r
+                       $sql = '\r
+SELECT c.relname as "Name", i.indisunique as "Unique", i.indkey as "Columns"\r
+FROM pg_catalog.pg_class c\r
+JOIN pg_catalog.pg_index i ON i.indexrelid=c.oid\r
+JOIN pg_catalog.pg_class c2 ON c2.oid=i.indrelid\r
+WHERE c2.relname=\'%s\'';\r
+                       }\r
+                                           \r
+                if ($primary == FALSE) {\r
+                        $sql .= ' AND i.indisprimary=false;';\r
+                }\r
+                \r
+                $save = $ADODB_FETCH_MODE;\r
+                $ADODB_FETCH_MODE = ADODB_FETCH_NUM;\r
+                if ($this->fetchMode !== FALSE) {\r
+                        $savem = $this->SetFetchMode(FALSE);\r
+                }\r
+                \r
+                $rs = $this->Execute(sprintf($sql,$table,$schema));\r
+                \r
+                if (isset($savem)) {\r
+                        $this->SetFetchMode($savem);\r
+                }\r
+                $ADODB_FETCH_MODE = $save;\r
+                \r
+                if (!is_object($rs)) {\r
+                        return FALSE;\r
+                }\r
+                \r
+                $col_names = $this->MetaColumnNames($table);\r
+                $indexes = array();\r
+                \r
+                while ($row = $rs->FetchRow()) {\r
+                        $columns = array();\r
+                        \r
+                        foreach (explode(' ', $row[2]) as $col) {\r
+                                $columns[] = $col_names[$col - 1];\r
+                        }\r
+                        \r
+                        $indexes[$row[0]] = array(\r
+                                'unique' => ($row[1] == 't'),\r
+                                'columns' => $columns\r
+                        );\r
+                }\r
+                \r
+                return $indexes;\r
+        }\r
+\r
        // returns true or false\r
        //\r
        // examples:\r
@@ -480,6 +558,9 @@ select viewname,'V' from pg_views where viewname like $mask";
        //      $db->Connect('host1','user1','secret');\r
        function _connect($str,$user='',$pwd='',$db='',$ctype=0)\r
        {\r
+               \r
+               if (!function_exists('pg_pconnect')) return false;\r
+               \r
                $this->_errorMsg = false;\r
                \r
                if ($user || $pwd || $db) {\r
@@ -687,7 +768,8 @@ class ADORecordSet_postgres64 extends ADORecordSet{
        function &GetRowAssoc($upper=true)\r
        {\r
                if ($this->fetchMode == PGSQL_ASSOC && !$upper) return $this->fields;\r
-               return ADORecordSet::GetRowAssoc($upper);\r
+               $row =& ADORecordSet::GetRowAssoc($upper);\r
+               return $row;\r
        }\r
 \r
        function _initrs()\r
@@ -746,14 +828,12 @@ class ADORecordSet_postgres64 extends ADORecordSet{
        function _fixblobs()\r
        {\r
                if ($this->fetchMode == PGSQL_NUM || $this->fetchMode == PGSQL_BOTH) {\r
-                       reset($this->_blobArr);\r
-                       while(list($k,$v) = each($this->_blobArr)) {\r
+                       foreach($this->_blobArr as $k => $v) {\r
                                $this->fields[$k] = ADORecordSet_postgres64::_decode($this->fields[$k]);\r
                        }\r
                }\r
                if ($this->fetchMode == PGSQL_ASSOC || $this->fetchMode == PGSQL_BOTH) {\r
-                       reset($this->_blobArr);\r
-                       while(list($k,$v) = each($this->_blobArr)) {\r
+                       foreach($this->_blobArr as $k => $v) {\r
                                $this->fields[$v] = ADORecordSet_postgres64::_decode($this->fields[$v]);\r
                        }\r
                }\r
@@ -766,9 +846,8 @@ class ADORecordSet_postgres64 extends ADORecordSet{
                        $this->_currentRow++;\r
                        if ($this->_numOfRows < 0 || $this->_numOfRows > $this->_currentRow) {\r
                                $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);\r
-                       \r
-                               if (is_array($this->fields)) {\r
-                                       if (isset($this->_blobArr)) $this->_fixblobs();\r
+                               if (is_array($this->fields) && $this->fields) {\r
+                                       if ($this->fields && isset($this->_blobArr)) $this->_fixblobs();\r
                                        return true;\r
                                }\r
                        }\r
@@ -780,11 +859,13 @@ class ADORecordSet_postgres64 extends ADORecordSet{
        \r
        function _fetch()\r
        {\r
+                               \r
                if ($this->_currentRow >= $this->_numOfRows && $this->_numOfRows >= 0)\r
                return false;\r
 \r
                $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);\r
-               if (isset($this->_blobArr)) $this->_fixblobs();\r
+               \r
+       if ($this->fields && isset($this->_blobArr)) $this->_fixblobs();\r
                        \r
                return (is_array($this->fields));\r
        }\r
index 8e923eefd30b91254caaad463a2ccf3835aa2862..2b9eb235f030ae6e40aaf87838fd52723b1df18b 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /*\r
- V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+ V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
@@ -28,12 +28,14 @@ class ADODB_postgres7 extends ADODB_postgres64 {
        // which makes obsolete the LIMIT limit,offset syntax\r
         function &SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0) \r
         {\r
-         $offsetStr = ($offset >= 0) ? " OFFSET $offset" : '';\r
-         $limitStr  = ($nrows >= 0)  ? " LIMIT $nrows" : '';\r
-         return $secs2cache ?\r
-          $this->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr)\r
-         :\r
-          $this->Execute($sql."$limitStr$offsetStr",$inputarr);\r
+                $offsetStr = ($offset >= 0) ? " OFFSET $offset" : '';\r
+                $limitStr  = ($nrows >= 0)  ? " LIMIT $nrows" : '';\r
+                if ($secs2cache)\r
+                       $rs =& $this->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr);\r
+                else\r
+                       $rs =& $this->Execute($sql."$limitStr$offsetStr",$inputarr);\r
+               \r
+               return $rs;\r
         }\r
        /*\r
        function Prepare($sql)\r
@@ -135,7 +137,7 @@ class ADORecordSet_postgres7 extends ADORecordSet_postgres64{
                                $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);\r
                        \r
                                if (is_array($this->fields)) {\r
-                                       if (isset($this->_blobArr)) $this->_fixblobs();\r
+                                       if ($this->fields && isset($this->_blobArr)) $this->_fixblobs();\r
                                        return true;\r
                                }\r
                        }\r
index c53e057d6574d063506195f38bd716a099f840cf..c589ce96ada5e82916bf2e10f8a8f5782bc07684 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /*\r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
index a75c11c859a15eb22219d8e8a9ebe596bede612d..c7408968c8cc4a09a40fb5472b1c227f2d0299f0 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
index bf0a940221b6c38ea97fe0a92a99707c9ebf86f3..d68de25825a2028c8e2e1bd12768931b8a3f2161 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-version V4.01 23 Oct 2003 (c) 2000-2003  John Lim (jlim@natsoft.com.my). All rights\r
+version V4.11 27 Jan 2004 (c) 2000-2004  John Lim (jlim@natsoft.com.my). All rights\r
 reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
index 0228c2c98ce2a8e8f8e2cdc987b0e5c563d6e17a..db2d3d8c49ca73063e34e9ad4f731c0b5ba36985 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /*\r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
@@ -126,6 +126,8 @@ class ADODB_sqlite extends ADOConnection {
        // returns true or false\r
        function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)\r
        {\r
+               if (!function_exists('sqlite_open')) return false;\r
+               \r
                $this->_connectionID = sqlite_open($argHostname);\r
                if ($this->_connectionID === false) return false;\r
                $this->_createFunctions();\r
@@ -135,6 +137,8 @@ class ADODB_sqlite extends ADOConnection {
        // returns true or false\r
        function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)\r
        {\r
+               if (!function_exists('sqlite_open')) return false;\r
+               \r
                $this->_connectionID = sqlite_popen($argHostname);\r
                if ($this->_connectionID === false) return false;\r
                $this->_createFunctions();\r
@@ -156,10 +160,12 @@ class ADODB_sqlite extends ADOConnection {
        {\r
                $offsetStr = ($offset >= 0) ? " OFFSET $offset" : '';\r
                $limitStr  = ($nrows >= 0)  ? " LIMIT $nrows" : ($offset >= 0 ? ' LIMIT 999999999' : '');\r
-               return $secs2cache ?\r
-                       $this->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr)\r
-               :\r
-                       $this->Execute($sql."$limitStr$offsetStr",$inputarr);\r
+               if ($secs2cache)\r
+                       $rs =& $this->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr);\r
+               else\r
+                       $rs =& $this->Execute($sql."$limitStr$offsetStr",$inputarr);\r
+                       \r
+               return $rs;\r
        }\r
        \r
        /*\r
index 1291162ad1c99601f0dae2548135193045c1b97b..b16266749789bd81bb781b5d0e99571132e3dc52 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim. All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim. All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
@@ -115,6 +115,8 @@ class ADODB_sybase extends ADOConnection {
        // returns true or false\r
        function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)\r
        {\r
+               if (!function_exists('sybase_connect')) return false;\r
+               \r
                $this->_connectionID = sybase_connect($argHostname,$argUsername,$argPassword);\r
                if ($this->_connectionID === false) return false;\r
                if ($argDatabasename) return $this->SelectDB($argDatabasename);\r
@@ -123,6 +125,8 @@ class ADODB_sybase extends ADOConnection {
        // returns true or false\r
        function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)\r
        {\r
+               if (!function_exists('sybase_connect')) return false;\r
+               \r
                $this->_connectionID = sybase_pconnect($argHostname,$argUsername,$argPassword);\r
                if ($this->_connectionID === false) return false;\r
                if ($argDatabasename) return $this->SelectDB($argDatabasename);\r
@@ -143,14 +147,15 @@ class ADODB_sybase extends ADOConnection {
        // See http://www.isug.com/Sybase_FAQ/ASE/section6.2.html#6.2.12\r
        function &SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0) \r
        {\r
-               if ($secs2cache > 0) // we do not cache rowcount, so we have to load entire recordset\r
-                       return ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);\r
-               \r
+               if ($secs2cache > 0) {// we do not cache rowcount, so we have to load entire recordset\r
+                       $rs =& ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);\r
+                       return $rs;\r
+               }\r
                $cnt = ($nrows > 0) ? $nrows : 0;\r
                if ($offset > 0 && $cnt) $cnt += $offset;\r
                \r
                $this->Execute("set rowcount $cnt"); \r
-               $rs = &ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);\r
+               $rs =ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);\r
                $this->Execute("set rowcount 0"); \r
                \r
                return $rs;\r
index 42dddf9d1626cb87c14fc135f90d74dc1b8e3aca..86e1e752abb0e466e5bd91a55368dc92df3a958f 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
diff --git a/lib/adodb/lang/adodb-ca.inc.php b/lib/adodb/lang/adodb-ca.inc.php
new file mode 100644 (file)
index 0000000..3e6a449
--- /dev/null
@@ -0,0 +1,35 @@
+<?php\r
+// Catalan language\r
+// contributed by "Josep Lladonosa" jlladono#pie.xtec.es\r
+$ADODB_LANG_ARRAY = array (\r
+                       'LANG'                      => 'ca',\r
+            DB_ERROR                    => 'error desconegut',\r
+            DB_ERROR_ALREADY_EXISTS     => 'ja existeix',\r
+            DB_ERROR_CANNOT_CREATE      => 'no es pot crear',\r
+            DB_ERROR_CANNOT_DELETE      => 'no es pot esborrar',\r
+            DB_ERROR_CANNOT_DROP        => 'no es pot eliminar',\r
+            DB_ERROR_CONSTRAINT         => 'violació de constraint',\r
+            DB_ERROR_DIVZERO            => 'divisió per zero',\r
+            DB_ERROR_INVALID            => 'no és vàlid',\r
+            DB_ERROR_INVALID_DATE       => 'la data o l\'hora no són vàlides',\r
+            DB_ERROR_INVALID_NUMBER     => 'el nombre no és vàlid',\r
+            DB_ERROR_MISMATCH           => 'no hi ha coincidència',\r
+            DB_ERROR_NODBSELECTED       => 'cap base de dades seleccionada',\r
+            DB_ERROR_NOSUCHFIELD        => 'camp inexistent',\r
+            DB_ERROR_NOSUCHTABLE        => 'taula inexistent',\r
+            DB_ERROR_NOT_CAPABLE        => 'l\'execució secundària de DB no pot',\r
+            DB_ERROR_NOT_FOUND          => 'no trobat',\r
+            DB_ERROR_NOT_LOCKED         => 'no blocat',\r
+            DB_ERROR_SYNTAX             => 'error de sintaxi',\r
+            DB_ERROR_UNSUPPORTED        => 'no suportat',\r
+            DB_ERROR_VALUE_COUNT_ON_ROW => 'el nombre de columnes no coincideix amb el nombre de valors en la fila',\r
+            DB_ERROR_INVALID_DSN        => 'el DSN no és vàlid',\r
+            DB_ERROR_CONNECT_FAILED     => 'connexió fallida',\r
+            0                         => 'cap error', // DB_OK\r
+            DB_ERROR_NEED_MORE_DATA     => 'les dades subministrades són insuficients',\r
+            DB_ERROR_EXTENSION_NOT_FOUND=> 'extensió no trobada',\r
+            DB_ERROR_NOSUCHDB           => 'base de dades inexistent',\r
+            DB_ERROR_ACCESS_VIOLATION   => 'permisos insuficients'\r
+);\r
+?>\r
+               
\ No newline at end of file
diff --git a/lib/adodb/lang/adodb-cn.inc.php b/lib/adodb/lang/adodb-cn.inc.php
new file mode 100644 (file)
index 0000000..eb8c7de
--- /dev/null
@@ -0,0 +1,35 @@
+<?php\r
+// Chinese language file contributed by "Cuiyan (cysoft)" cysoft#php.net.\r
+// Encode by GB2312\r
+// Simplified Chinese\r
+$ADODB_LANG_ARRAY = array (\r
+                       'LANG'                      => 'cn',\r
+            DB_ERROR                    => 'δ֪´íÎó',\r
+            DB_ERROR_ALREADY_EXISTS     => 'ÒѾ­´æÔÚ',\r
+            DB_ERROR_CANNOT_CREATE      => '²»ÄÜ´´½¨',\r
+            DB_ERROR_CANNOT_DELETE      => '²»ÄÜɾ³ý',\r
+            DB_ERROR_CANNOT_DROP        => '²»ÄܶªÆú',\r
+            DB_ERROR_CONSTRAINT         => 'Ô¼ÊøÏÞÖÆ',\r
+            DB_ERROR_DIVZERO            => '±»0³ý',\r
+            DB_ERROR_INVALID            => 'ÎÞЧ',\r
+            DB_ERROR_INVALID_DATE       => 'ÎÞЧµÄÈÕÆÚ»òÕßʱ¼ä',\r
+            DB_ERROR_INVALID_NUMBER     => 'ÎÞЧµÄÊý×Ö',\r
+            DB_ERROR_MISMATCH           => '²»Æ¥Åä',\r
+            DB_ERROR_NODBSELECTED       => 'ûÓÐÊý¾Ý¿â±»Ñ¡Ôñ',\r
+            DB_ERROR_NOSUCHFIELD        => 'ûÓÐÏàÓ¦µÄ×Ö¶Î',\r
+            DB_ERROR_NOSUCHTABLE        => 'ûÓÐÏàÓ¦µÄ±í',\r
+            DB_ERROR_NOT_CAPABLE        => 'Êý¾Ý¿âºǫ́²»¼æÈÝ',\r
+            DB_ERROR_NOT_FOUND          => 'ûÓз¢ÏÖ',\r
+            DB_ERROR_NOT_LOCKED         => 'ûÓб»Ëø¶¨',\r
+            DB_ERROR_SYNTAX             => 'Óï·¨´íÎó',\r
+            DB_ERROR_UNSUPPORTED        => '²»Ö§³Ö',\r
+            DB_ERROR_VALUE_COUNT_ON_ROW => 'ÔÚÐÐÉÏÀÛ¼ÆÖµ',\r
+            DB_ERROR_INVALID_DSN        => 'ÎÞЧµÄÊý¾ÝÔ´ (DSN)',\r
+            DB_ERROR_CONNECT_FAILED     => 'Á¬½Óʧ°Ü',\r
+            0                         => 'ûÓдíÎó', // DB_OK\r
+            DB_ERROR_NEED_MORE_DATA     => 'ÌṩµÄÊý¾Ý²»ÄÜ·ûºÏÒªÇó',\r
+            DB_ERROR_EXTENSION_NOT_FOUND=> 'À©Õ¹Ã»Óб»·¢ÏÖ',\r
+            DB_ERROR_NOSUCHDB           => 'ûÓÐÏàÓ¦µÄÊý¾Ý¿â',\r
+            DB_ERROR_ACCESS_VIOLATION   => 'ûÓкÏÊʵÄȨÏÞ'\r
+);\r
+?>
\ No newline at end of file
diff --git a/lib/adodb/lang/adodb-de.inc.php b/lib/adodb/lang/adodb-de.inc.php
new file mode 100644 (file)
index 0000000..244cb2f
--- /dev/null
@@ -0,0 +1,33 @@
+<?php\r
+// contributed by "Heinz Hombergs" <opn@hhombergs.de>\r
+$ADODB_LANG_ARRAY = array (\r
+                       'LANG'                      => 'de',\r
+                       DB_ERROR                    => 'Unbekannter Fehler',\r
+            DB_ERROR_ALREADY_EXISTS     => 'existiert bereits',\r
+            DB_ERROR_CANNOT_CREATE      => 'kann nicht erstellen',\r
+            DB_ERROR_CANNOT_DELETE      => 'kann nicht l&ouml;schen',\r
+            DB_ERROR_CANNOT_DROP        => 'Tabelle oder Index konnte nicht gel&ouml;scht werden',\r
+            DB_ERROR_CONSTRAINT         => 'Constraint Verletzung',\r
+            DB_ERROR_DIVZERO            => 'Division durch Null',\r
+            DB_ERROR_INVALID            => 'ung&uml;ltig',\r
+            DB_ERROR_INVALID_DATE       => 'ung&uml;ltiges Datum oder Zeit',\r
+            DB_ERROR_INVALID_NUMBER     => 'ung&uml;ltige Zahl',\r
+            DB_ERROR_MISMATCH           => 'Unvertr&auml;glichkeit',\r
+            DB_ERROR_NODBSELECTED       => 'keine Dantebank ausgew&auml;hlt',\r
+            DB_ERROR_NOSUCHFIELD        => 'Feld nicht vorhanden',\r
+            DB_ERROR_NOSUCHTABLE        => 'Tabelle nicht vorhanden',\r
+            DB_ERROR_NOT_CAPABLE        => 'Funktion nicht installiert',\r
+            DB_ERROR_NOT_FOUND          => 'nicht gefunden',\r
+            DB_ERROR_NOT_LOCKED         => 'nicht gesperrt',\r
+            DB_ERROR_SYNTAX             => 'Syntaxfehler',\r
+            DB_ERROR_UNSUPPORTED        => 'nicht Unterst&uml;tzt',\r
+            DB_ERROR_VALUE_COUNT_ON_ROW => 'Anzahl der zur&uml;ckgelieferten Felder entspricht nicht der Anzahl der Felder in der Abfrage',\r
+            DB_ERROR_INVALID_DSN        => 'ung&uml;ltiger DSN',\r
+            DB_ERROR_CONNECT_FAILED     => 'Verbindung konnte nicht hergestellt werden',\r
+            0                         => 'kein Fehler', // DB_OK\r
+            DB_ERROR_NEED_MORE_DATA     => 'Nicht gen&uml;gend Daten geliefert',\r
+            DB_ERROR_EXTENSION_NOT_FOUND=> 'erweiterung nicht gefunden',\r
+            DB_ERROR_NOSUCHDB           => 'keine Datenbank',\r
+            DB_ERROR_ACCESS_VIOLATION   => 'ungen&uml;gende Rechte'\r
+);\r
+?>
\ No newline at end of file
index 9d7e98f20b4a02bd433bd009a18a974ee7445172..066a2a5e5b7e2b100ea1d44baf761806a19dcb94 100644 (file)
@@ -28,6 +28,6 @@ $ADODB_LANG_ARRAY = array (
        DB_ERROR_NEED_MORE_DATA     => 'donn&eacute;es fournies insuffisantes',\r
        DB_ERROR_EXTENSION_NOT_FOUND=> 'extension non trouv&eacute;e',\r
        DB_ERROR_NOSUCHDB           => 'base de donn&eacute;es inconnue',\r
-       DB_ERROR_ACCESS_VIOLATION   => 'droits ynsuffisants'\r
+       DB_ERROR_ACCESS_VIOLATION   => 'droits insuffisants'\r
 );\r
 ?>
\ No newline at end of file
index 71dcb88599b837beb6f3aa651d8cb66cbd35d681..20c5b93b630a36a8f1c040aee5984224fb8f042a 100644 (file)
@@ -8,10 +8,10 @@ $ADODB_LANG_ARRAY = array (
             DB_ERROR_CANNOT_CREATE      => 'non posso creare',\r
             DB_ERROR_CANNOT_DELETE      => 'non posso cancellare',\r
             DB_ERROR_CANNOT_DROP        => 'non posso eliminare',\r
-            DB_ERROR_CONSTRAINT         => 'viiolazione constraint',\r
+            DB_ERROR_CONSTRAINT         => 'violazione constraint',\r
             DB_ERROR_DIVZERO            => 'divisione per zero',\r
             DB_ERROR_INVALID            => 'non valido',\r
-            DB_ERROR_INVALID_DATE       => 'date od ora non valido',\r
+            DB_ERROR_INVALID_DATE       => 'data od ora non valida',\r
             DB_ERROR_INVALID_NUMBER     => 'numero non valido',\r
             DB_ERROR_MISMATCH           => 'diversi',\r
             DB_ERROR_NODBSELECTED       => 'nessun database selezionato',\r
@@ -26,9 +26,9 @@ $ADODB_LANG_ARRAY = array (
             DB_ERROR_INVALID_DSN        => 'DSN non valido',\r
             DB_ERROR_CONNECT_FAILED     => 'connessione fallita',\r
             0                           => 'nessun errore', // DB_OK\r
-            DB_ERROR_NEED_MORE_DATA     => 'dati inseriti insufficenti',\r
+            DB_ERROR_NEED_MORE_DATA     => 'dati inseriti insufficienti',\r
             DB_ERROR_EXTENSION_NOT_FOUND=> 'estensione non trovata',\r
             DB_ERROR_NOSUCHDB           => 'database non trovato',\r
-            DB_ERROR_ACCESS_VIOLATION   => 'permessi insufficenti'\r
+            DB_ERROR_ACCESS_VIOLATION   => 'permessi insufficienti'\r
 );\r
 ?>
\ No newline at end of file
index b05750301beb6d4b665de3e0aaa4ea0f3825eb70..65831629fa7075f0e9c630b7958ed11aa4a49e5c 100644 (file)
@@ -13,12 +13,27 @@ All rights reserved.
 Redistribution and use in source and binary forms, with or without modification, \r
 are permitted provided that the following conditions are met:\r
 \r
-Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. \r
-Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. \r
-Neither the name of the John Lim nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. \r
+Redistributions of source code must retain the above copyright notice, this list \r
+of conditions and the following disclaimer. \r
+\r
+Redistributions in binary form must reproduce the above copyright notice, this list \r
+of conditions and the following disclaimer in the documentation and/or other materials \r
+provided with the distribution. \r
+\r
+Neither the name of the John Lim nor the names of its contributors may be used to \r
+endorse or promote products derived from this software without specific prior written \r
+permission. \r
 \r
 DISCLAIMER:\r
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY \r
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \r
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL \r
+JOHN LIM OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, \r
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF \r
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) \r
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, \r
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS \r
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
 \r
 ==========================================================\r
 GNU LESSER GENERAL PUBLIC LICENSE\r
index bc73ab3a6f89b72d0d730800df959b8480289cb3..64e26222d0723d61d7b8880362d5feba569def3b 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. See License.txt. \r
@@ -59,9 +59,19 @@ class perf_db2 extends adodb_perf{
                $this->conn =& $conn;\r
        }\r
        \r
-       function Explain($sql)\r
+       function Explain($sql,$partial=false)\r
        {\r
                $save = $this->conn->LogSQL(false);\r
+               if ($partial) {\r
+                       $sqlq = $this->conn->qstr($sql.'%');\r
+                       $arr = $this->conn->GetArray("select distinct sql1 from adodb_logsql where sql1 like $sqlq");\r
+                       if ($arr) {\r
+                               foreach($arr as $row) {\r
+                                       $sql = reset($row);\r
+                                       if (crc32($sql) == $partial) break;\r
+                               }\r
+                       }\r
+               }\r
                $qno = rand();\r
                $ok = $this->conn->Execute("EXPLAIN PLAN SET QUERYNO=$qno FOR $sql");\r
                ob_start();\r
index 3ee4b923dc9aa08d179a4629bcfc9250197fb039..2b2923b86877a8a1d2256e2ca67284b45f372fd2 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. See License.txt. \r
index ddf0f8f0178ed9c0c0deccb7fd2389151ae02a4a..1cf7d6906a973e4d1a0e9804ff1245ffd84d6ab3 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
 \r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. See License.txt. \r
@@ -71,8 +71,21 @@ class perf_mssql extends adodb_perf{
                $this->conn =& $conn;\r
        }\r
        \r
-       function Explain($sql)\r
+       function Explain($sql,$partial=false)\r
        {\r
+               \r
+               $save = $this->conn->LogSQL(false);\r
+               if ($partial) {\r
+                       $sqlq = $this->conn->qstr($sql.'%');\r
+                       $arr = $this->conn->GetArray("select distinct sql1 from adodb_logsql where sql1 like $sqlq");\r
+                       if ($arr) {\r
+                               foreach($arr as $row) {\r
+                                       $sql = reset($row);\r
+                                       if (crc32($sql) == $partial) break;\r
+                               }\r
+                       }\r
+               }\r
+               \r
                $s = '<p><b>Explain</b>: '.htmlspecialchars($sql).'</p>';\r
                $this->conn->Execute("SET SHOWPLAN_ALL ON;");\r
                $sql = str_replace('?',"''",$sql);\r
@@ -96,7 +109,7 @@ class perf_mssql extends adodb_perf{
                }\r
                \r
                $this->conn->Execute("SET SHOWPLAN_ALL OFF;");\r
-               \r
+               $this->conn->LogSQL($save);\r
                $s .= $this->Tracer($sql);\r
                return $s;\r
        }\r
index 9e038c6dd4c948042bc64ae80f327b894ebb6a5f..bfa1883d4f1aed46a38178b1f372e151f40c452b 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. See License.txt. \r
@@ -83,13 +83,32 @@ class perf_mysql extends adodb_perf{
                $this->conn =& $conn;\r
        }\r
        \r
-       function Explain($sql)\r
+       function Explain($sql,$partial=false)\r
        {\r
+               \r
                if (strtoupper(substr(trim($sql),0,6)) !== 'SELECT') return '<p>Unable to EXPLAIN non-select statement</p>';\r
+               $save = $this->conn->LogSQL(false);\r
+               if ($partial) {\r
+                       $sqlq = $this->conn->qstr($sql.'%');\r
+                       $arr = $this->conn->GetArray("select distinct sql1 from adodb_logsql where sql1 like $sqlq");\r
+                       if ($arr) {\r
+                               foreach($arr as $row) {\r
+                                       $sql = reset($row);\r
+                                       if (crc32($sql) == $partial) break;\r
+                               }\r
+                       }\r
+               }\r
                $sql = str_replace('?',"''",$sql);\r
+               \r
+               if ($partial) {\r
+                       $sqlq = $this->conn->qstr($sql.'%');\r
+                       $sql = $this->conn->GetOne("select sql1 from adodb_logsql where sql1 like $sqlq");\r
+               }\r
+               \r
                $s = '<p><b>Explain</b>: '.htmlspecialchars($sql).'</p>';\r
                $rs = $this->conn->Execute('EXPLAIN '.$sql);\r
                $s .= rs2html($rs,false,false,false,false);\r
+               $this->conn->LogSQL($save);\r
                $s .= $this->Tracer($sql);\r
                return $s;\r
        }\r
@@ -207,7 +226,9 @@ class perf_mysql extends adodb_perf{
        {\r
        global $HTTP_SESSION_VARS;\r
        \r
-               $stat = $this->conn->GetOne('show innodb status');\r
+               $rs = $this->conn->Execute('show innodb status');\r
+               if (!$rs || $rs->EOF) return 0;\r
+               $stat = $rs->fields[0];\r
                $at = strpos($stat,'Buffer pool hit rate');\r
                $stat = substr($stat,$at,200);\r
                if (preg_match('!Buffer pool hit rate\s*([0-9]*) / ([0-9]*)!',$stat,$arr)) {\r
index e301a225c2b4f8009aec490c90de491e8816f484..cc1151ea575cda83b7e55ee224355fff18e9c979 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. See License.txt. \r
@@ -47,6 +47,15 @@ class perf_oci8 extends ADODB_perf{
                 sum(getmisses))))*100,2)\r
                from  v\$rowcache",\r
                'increase <i>shared_pool_size</i> if too ratio low'),\r
+               \r
+               'memory sort ratio' => array('RATIOH',\r
+               "SELECT ROUND((100 * b.VALUE) /DECODE ((a.VALUE + b.VALUE), \r
+       0,1,(a.VALUE + b.VALUE)),2)\r
+FROM   v\$sysstat a, \r
+       v\$sysstat b\r
+WHERE  a.name = 'sorts (disk)'\r
+AND    b.name = 'sorts (memory)'",\r
+       "% of memory sorts compared to disk sorts - should be over 95%"),\r
 \r
        'IO',\r
                'data reads' => array('IO',\r
@@ -176,7 +185,7 @@ class perf_oci8 extends ADODB_perf{
                return reset($rs->fields);\r
        }\r
        \r
-       function Explain($sql) \r
+       function Explain($sql,$partial=false\r
        {\r
                $savelog = $this->conn->LogSQL(false);\r
                $rs =& $this->conn->SelectLimit("select ID FROM PLAN_TABLE");\r
@@ -216,6 +225,17 @@ CREATE TABLE PLAN_TABLE (
                $rs->Close();\r
        //      $this->conn->debug=1;\r
        \r
+               if ($partial) {\r
+                       $sqlq = $this->conn->qstr($sql.'%');\r
+                       $arr = $this->conn->GetArray("select distinct distinct sql1 from adodb_logsql where sql1 like $sqlq");\r
+                       if ($arr) {\r
+                               foreach($arr as $row) {\r
+                                       $sql = reset($row);\r
+                                       if (crc32($sql) == $partial) break;\r
+                               }\r
+                       }\r
+               }\r
+               \r
                $s = "<p><b>Explain</b>: ".htmlspecialchars($sql)."</p>";       \r
                \r
                $this->conn->BeginTrans();\r
@@ -239,7 +259,7 @@ CONNECT BY prior id=parent_id and statement_id='$id'");
                $s .= rs2html($rs,false,false,false,false);\r
                $this->conn->RollbackTrans();\r
                $this->conn->LogSQL($savelog);\r
-               $s .= $this->Tracer($sql);\r
+               $s .= $this->Tracer($sql,$partial);\r
                return $s;\r
        }\r
        \r
@@ -256,17 +276,18 @@ select  a.size_for_estimate as cache_mb_estimate,
                '- BETTER - '\r
        else ' ' end as currsize, \r
    a.estd_physical_read_factor-b.estd_physical_read_factor as best_when_0\r
-   from (select size_for_estimate,size_factor,estd_physical_read_factor,rownum  r from v\$conn_cache_advice) a , \r
-   (select size_for_estimate,size_factor,estd_physical_read_factor,rownum r from v\$conn_cache_advice) b where a.r = b.r-1");\r
+   from (select size_for_estimate,size_factor,estd_physical_read_factor,rownum  r from v\$db_cache_advice) a , \r
+   (select size_for_estimate,size_factor,estd_physical_read_factor,rownum r from v\$db_cache_advice) b where a.r = b.r-1");\r
                if (!$rs) return false;\r
                \r
                /*\r
-               The v$conn_cache_advice utility show the marginal changes in physical data block reads for different sizes of db_cache_size\r
+               The v$db_cache_advice utility show the marginal changes in physical data block reads for different sizes of db_cache_size\r
                */\r
                $s = "<h3>Data Cache Estimate</h3>";\r
                if ($rs->EOF) {\r
                        $s .= "<p>Cache that is 50% of current size is still too big</p>";\r
                } else {\r
+                       $s .= "Ideal size of Data Cache is when \"best_when_0\" changes from a positive number and becomes zero.";\r
                        $s .= rs2html($rs,false,false,false,false);\r
                }\r
                return $s;\r
@@ -360,7 +381,8 @@ order by
 \r
                global $ADODB_CACHE_MODE,$HTTP_GET_VARS;\r
                if (isset($HTTP_GET_VARS['expsixora']) && isset($HTTP_GET_VARS['sql'])) {\r
-                               echo "<a name=explain></a>".$this->Explain($HTTP_GET_VARS['sql'])."\n";\r
+                               $partial = empty($HTTP_GET_VARS['part']);\r
+                               echo "<a name=explain></a>".$this->Explain($HTTP_GET_VARS['sql'],$partial)."\n";\r
                }\r
 \r
                if (isset($HTTP_GET_VARS['sql'])) return $this->_SuspiciousSQL();\r
@@ -385,7 +407,7 @@ order by
        // code thanks to Ixora. \r
        // http://www.ixora.com.au/scripts/query_opt.htm\r
        // requires oracle 8.1.7 or later\r
-       function& ExpensiveSQL($numsql = 10)\r
+       function ExpensiveSQL($numsql = 10)\r
        {\r
                $sql = "\r
 select\r
@@ -424,11 +446,14 @@ order by
 ";\r
                global $ADODB_CACHE_MODE,$HTTP_GET_VARS;\r
                if (isset($HTTP_GET_VARS['expeixora']) && isset($HTTP_GET_VARS['sql'])) {\r
-                               echo "<a name=explain></a>".$this->Explain($HTTP_GET_VARS['sql'])."\n";\r
+                       $partial = empty($HTTP_GET_VARS['part']);       \r
+                       echo "<a name=explain></a>".$this->Explain($HTTP_GET_VARS['sql'],$partial)."\n";\r
                }\r
                \r
-               if (isset($HTTP_GET_VARS['sql'])) return $this->_ExpensiveSQL();\r
-               \r
+               if (isset($HTTP_GET_VARS['sql'])) {\r
+                        $var =& $this->_ExpensiveSQL();\r
+                        return $var;\r
+               }\r
                $save = $ADODB_CACHE_MODE;\r
                $ADODB_CACHE_MODE = ADODB_FETCH_NUM;\r
                $savelog = $this->conn->LogSQL(false);\r
index f0d97b1a5a7dd59705a916e2ffc87a97e5c1e8fe..5ae20e4d2a7d04ae8972b1c54edec138ac3f688f 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
 \r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. See License.txt. \r
@@ -88,10 +88,21 @@ class perf_postgres extends adodb_perf{
                $this->conn =& $conn;\r
        }\r
        \r
-       function Explain($sql)\r
+       function Explain($sql,$partial=false)\r
        {\r
-               $sql = str_replace('?',"''",$sql);\r
                $save = $this->conn->LogSQL(false);\r
+               \r
+               if ($partial) {\r
+                       $sqlq = $this->conn->qstr($sql.'%');\r
+                       $arr = $this->conn->GetArray("select distinct distinct sql1 from adodb_logsql where sql1 like $sqlq");\r
+                       if ($arr) {\r
+                               foreach($arr as $row) {\r
+                                       $sql = reset($row);\r
+                                       if (crc32($sql) == $partial) break;\r
+                               }\r
+                       }\r
+               }\r
+               $sql = str_replace('?',"''",$sql);\r
                $s = '<p><b>Explain</b>: '.htmlspecialchars($sql).'</p>';\r
                $rs = $this->conn->Execute('EXPLAIN '.$sql);\r
                $this->conn->LogSQL($save);\r
@@ -102,7 +113,7 @@ class perf_postgres extends adodb_perf{
                                $rs->MoveNext();\r
                        }\r
                $s .= '</pre>';\r
-               $s .= $this->Tracer($sql);\r
+               $s .= $this->Tracer($sql,$partial);\r
                return $s;\r
        }\r
 }\r
index 96834f37232dc421867fba8bbc47feccf3c305d0..f9c547f11b7c53654c78c2bd883a37840beed127 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /** \r
- * @version V4.01 23 Oct 2003 (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+ * @version V4.11 27 Jan 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
  * Released under both BSD license and Lesser GPL library license. \r
  * Whenever there is any discrepancy between the two licenses, \r
  * the BSD license will take precedence. \r
@@ -71,7 +71,8 @@
        \r
        if ($showcount)\r
                $sel .= "\n\tSUM(1) as Total";\r
-       \r
+       else\r
+               $sel = substr($sel,0,strlen($sel)-2);\r
        \r
        $sql = "SELECT $sel \nFROM $tables $where \nGROUP BY $rowfields";\r
        return $sql;\r
index 6c23d52b7f3f6f7cc9aa506f30d4ad89984045e3..25ff1c71fa0b77b0fe47b185ac96d1a37acf385d 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /** \r
- * @version V4.01 23 Oct 2003 (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+ * @version V4.11 27 Jan 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
  * Released under both BSD license and Lesser GPL library license. \r
  * Whenever there is any discrepancy between the two licenses, \r
  * the BSD license will take precedence. \r
index 43b47f8117b37cd8a836a3ea4fb3e55bd01cded4..dc5c4ff89c8486330468505251f78adf0ed78c4b 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
 \r
 /** \r
- * @version V4.01 23 Oct 2003 (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+ * @version V4.11 27 Jan 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
  * Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
diff --git a/lib/adodb/session/adodb-compress-bzip2.php b/lib/adodb/session/adodb-compress-bzip2.php
new file mode 100644 (file)
index 0000000..77e0bd9
--- /dev/null
@@ -0,0 +1,120 @@
+<?php\r
+\r
+// $CVSHeader$\r
+\r
+/*\r
+V4.01 23 Oct 2003  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+         Contributed by Ross Smith (adodb@netebb.com). \r
+  Released under both BSD license and Lesser GPL library license.\r
+  Whenever there is any discrepancy between the two licenses,\r
+  the BSD license will take precedence.\r
+         Set tabs to 4 for best viewing.\r
+\r
+*/\r
+\r
+if (!function_exists('bzcompress')) {\r
+       trigger_error('bzip2 functions are not available', E_USER_ERROR);\r
+       return 0;\r
+}\r
+\r
+/*\r
+*/\r
+class ADODB_Compress_Bzip2 {\r
+       /**\r
+        */\r
+       var $_block_size = null;\r
+\r
+       /**\r
+        */\r
+       var $_work_level = null;\r
+\r
+       /**\r
+        */\r
+       var $_min_length = 1;\r
+\r
+       /**\r
+        */\r
+       function getBlockSize() {\r
+               return $this->_block_size;\r
+       }\r
+\r
+       /**\r
+        */\r
+       function setBlockSize($block_size) {\r
+               assert('$block_size >= 1');\r
+               assert('$block_size <= 9');\r
+               $this->_block_size = (int) $block_size;\r
+       }\r
+\r
+       /**\r
+        */\r
+       function getWorkLevel() {\r
+               return $this->_work_level;\r
+       }\r
+\r
+       /**\r
+        */\r
+       function setWorkLevel($work_level) {\r
+               assert('$work_level >= 0');\r
+               assert('$work_level <= 250');\r
+               $this->_work_level = (int) $work_level;\r
+       }\r
+\r
+       /**\r
+        */\r
+       function getMinLength() {\r
+               return $this->_min_length;\r
+       }\r
+\r
+       /**\r
+        */\r
+       function setMinLength($min_length) {\r
+               assert('$min_length >= 0');\r
+               $this->_min_length = (int) $min_length;\r
+       }\r
+\r
+       /**\r
+        */\r
+       function ADODB_Compress_Bzip2($block_size = null, $work_level = null, $min_length = null) {\r
+               if (!is_null($block_size)) {\r
+                       $this->setBlockSize($block_size);\r
+               }\r
+\r
+               if (!is_null($work_level)) {\r
+                       $this->setWorkLevel($work_level);\r
+               }\r
+\r
+               if (!is_null($min_length)) {\r
+                       $this->setMinLength($min_length);\r
+               }\r
+       }\r
+\r
+       /**\r
+        */\r
+       function write($data, $key) {\r
+               if (strlen($data) < $this->_min_length) {\r
+                       return $data;\r
+               }\r
+\r
+               if (!is_null($this->_block_size)) {\r
+                       if (!is_null($this->_work_level)) {\r
+                               return bzcompress($data, $this->_block_size, $this->_work_level);\r
+                       } else {\r
+                               return bzcompress($data, $this->_block_size);\r
+                       }\r
+               }\r
+\r
+               return bzcompress($data);\r
+       }\r
+\r
+       /**\r
+        */\r
+       function read($data, $key) {\r
+               return $data ? bzdecompress($data) : $data;\r
+       }\r
+\r
+}\r
+\r
+return 1;\r
+\r
+?>\r
diff --git a/lib/adodb/session/adodb-compress-gzip.php b/lib/adodb/session/adodb-compress-gzip.php
new file mode 100644 (file)
index 0000000..c5e568e
--- /dev/null
@@ -0,0 +1,94 @@
+<?php\r
+\r
+// $CVSHeader$\r
+\r
+/*\r
+V4.01 23 Oct 2003  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+         Contributed by Ross Smith (adodb@netebb.com). \r
+  Released under both BSD license and Lesser GPL library license.\r
+  Whenever there is any discrepancy between the two licenses,\r
+  the BSD license will take precedence.\r
+         Set tabs to 4 for best viewing.\r
+\r
+*/\r
+\r
+if (!function_exists('gzcompress')) {\r
+       trigger_error('gzip functions are not available', E_USER_ERROR);\r
+       return 0;\r
+}\r
+\r
+/*\r
+*/\r
+class ADODB_Compress_Gzip {\r
+       /**\r
+        */\r
+       var $_level = null;\r
+\r
+       /**\r
+        */\r
+       var $_min_length = 1;\r
+\r
+       /**\r
+        */\r
+       function getLevel() {\r
+               return $this->_level;\r
+       }\r
+\r
+       /**\r
+        */\r
+       function setLevel($level) {\r
+               assert('$level >= 0');\r
+               assert('$level <= 9');\r
+               $this->_level = (int) $level;\r
+       }\r
+\r
+       /**\r
+        */\r
+       function getMinLength() {\r
+               return $this->_min_length;\r
+       }\r
+\r
+       /**\r
+        */\r
+       function setMinLength($min_length) {\r
+               assert('$min_length >= 0');\r
+               $this->_min_length = (int) $min_length;\r
+       }\r
+\r
+       /**\r
+        */\r
+       function ADODB_Compress_Gzip($level = null, $min_length = null) {\r
+               if (!is_null($level)) {\r
+                       $this->setLevel($level);\r
+               }\r
+\r
+               if (!is_null($min_length)) {\r
+                       $this->setMinLength($min_length);\r
+               }\r
+       }\r
+\r
+       /**\r
+        */\r
+       function write($data, $key) {\r
+               if (strlen($data) < $this->_min_length) {\r
+                       return $data;\r
+               }\r
+\r
+               if (!is_null($this->_level)) {\r
+                       return gzcompress($data, $this->_level);\r
+               } else {\r
+                       return gzcompress($data);\r
+               }\r
+       }\r
+\r
+       /**\r
+        */\r
+       function read($data, $key) {\r
+               return $data ? gzuncompress($data) : $data;\r
+       }\r
+\r
+}\r
+\r
+return 1;\r
+\r
+?>
\ No newline at end of file
diff --git a/lib/adodb/session/adodb-cryptsession.php b/lib/adodb/session/adodb-cryptsession.php
new file mode 100644 (file)
index 0000000..c0ffc3c
--- /dev/null
@@ -0,0 +1,25 @@
+<?php\r
+\r
+// $CVSHeader$\r
+\r
+/*\r
+V4.01 23 Oct 2003  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+         Contributed by Ross Smith (adodb@netebb.com). \r
+  Released under both BSD license and Lesser GPL library license.\r
+  Whenever there is any discrepancy between the two licenses,\r
+  the BSD license will take precedence.\r
+         Set tabs to 4 for best viewing.\r
+*/\r
+\r
+/*\r
+\r
+This file is provided for backwards compatibility purposes\r
+\r
+*/\r
+\r
+require_once dirname(__FILE__) . '/adodb-session.php';\r
+require_once  ADODB_SESSION . '/adodb-encrypt-md5.php';\r
+\r
+ADODB_Session::filter(new ADODB_Encrypt_MD5());\r
+\r
+?>
\ No newline at end of file
diff --git a/lib/adodb/session/adodb-encrypt-mcrypt.php b/lib/adodb/session/adodb-encrypt-mcrypt.php
new file mode 100644 (file)
index 0000000..2083436
--- /dev/null
@@ -0,0 +1,110 @@
+<?php\r
+\r
+// $CVSHeader$\r
+\r
+/*\r
+V4.01 23 Oct 2003  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+         Contributed by Ross Smith (adodb@netebb.com). \r
+  Released under both BSD license and Lesser GPL library license.\r
+  Whenever there is any discrepancy between the two licenses,\r
+  the BSD license will take precedence.\r
+         Set tabs to 4 for best viewing.\r
+\r
+*/\r
+\r
+if (!function_exists('mcrypt_encrypt')) {\r
+       trigger_error('Mcrypt functions are not available', E_USER_ERROR);\r
+       return 0;\r
+}\r
+\r
+/**\r
+ */\r
+class ADODB_Encrypt_MCrypt {\r
+       /**\r
+        */\r
+       var $_cipher;\r
+\r
+       /**\r
+        */\r
+       var $_mode;\r
+\r
+       /**\r
+        */\r
+       var $_source;\r
+\r
+       /**\r
+        */\r
+       function getCipher() {\r
+               return $this->_cipher;\r
+       }\r
+\r
+       /**\r
+        */\r
+       function setCipher($cipher) {\r
+               $this->_cipher = $cipher;\r
+       }\r
+\r
+       /**\r
+        */\r
+       function getMode() {\r
+               return $this->_mode;\r
+       }\r
+\r
+       /**\r
+        */\r
+       function setMode($mode) {\r
+               $this->_mode = $mode;\r
+       }\r
+\r
+       /**\r
+        */\r
+       function getSource() {\r
+               return $this->_source;\r
+       }\r
+\r
+       /**\r
+        */\r
+       function setSource($source) {\r
+               $this->_source = $source;\r
+       }\r
+\r
+       /**\r
+        */\r
+       function ADODB_Encrypt_MCrypt($cipher = null, $mode = null, $source = null) {\r
+               if (!$cipher) {\r
+                       $cipher = MCRYPT_RIJNDAEL_256;\r
+               }\r
+               if (!$mode) {\r
+                       $mode = MCRYPT_MODE_ECB;\r
+               }\r
+               if (!$source) {\r
+                       $source = MCRYPT_RAND;\r
+               }\r
+\r
+               $this->_cipher = $cipher;\r
+               $this->_mode = $mode;\r
+               $this->_source = $source;\r
+       }\r
+\r
+       /**\r
+        */\r
+       function write($data, $key) {\r
+               $iv_size = mcrypt_get_iv_size($this->_cipher, $this->_mode);\r
+               $iv = mcrypt_create_iv($iv_size, $this->_source);\r
+               return mcrypt_encrypt($this->_cipher, $key, $data, $this->_mode, $iv);\r
+       }\r
+\r
+       /**\r
+        */\r
+       function read($data, $key) {\r
+               $iv_size = mcrypt_get_iv_size($this->_cipher, $this->_mode);\r
+               $iv = mcrypt_create_iv($iv_size, $this->_source);\r
+               $rv = mcrypt_decrypt($this->_cipher, $key, $data, $this->_mode, $iv);\r
+               return rtrim($rv, "\0");\r
+       }\r
+\r
+}\r
+\r
+return 1;\r
+\r
+?>\r
diff --git a/lib/adodb/session/adodb-encrypt-md5.php b/lib/adodb/session/adodb-encrypt-md5.php
new file mode 100644 (file)
index 0000000..8a7e939
--- /dev/null
@@ -0,0 +1,38 @@
+<?php\r
+\r
+// $CVSHeader$\r
+\r
+/*\r
+V4.01 23 Oct 2003  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+         Contributed by Ross Smith (adodb@netebb.com). \r
+  Released under both BSD license and Lesser GPL library license.\r
+  Whenever there is any discrepancy between the two licenses,\r
+  the BSD license will take precedence.\r
+         Set tabs to 4 for best viewing.\r
+\r
+*/\r
+\r
+include_once ADODB_SESSION . '/crypt.inc.php';\r
+\r
+/**\r
+ */\r
+class ADODB_Encrypt_MD5 {\r
+       /**\r
+        */\r
+       function write($data, $key) {\r
+               $md5crypt =& new MD5Crypt();\r
+               return $md5crypt->encrypt($data, $key);\r
+       }\r
+\r
+       /**\r
+        */\r
+       function read($data, $key) {\r
+               $md5crypt =& new MD5Crypt();\r
+               return $md5crypt->decrypt($data, $key);\r
+       }\r
+\r
+}\r
+\r
+return 1;\r
+\r
+?>
\ No newline at end of file
diff --git a/lib/adodb/session/adodb-encrypt-secret.php b/lib/adodb/session/adodb-encrypt-secret.php
new file mode 100644 (file)
index 0000000..f979c7a
--- /dev/null
@@ -0,0 +1,50 @@
+<?php\r
+\r
+// $CVSHeader$\r
+\r
+/*\r
+V4.01 23 Oct 2003  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+         Contributed by Ross Smith (adodb@netebb.com). \r
+  Released under both BSD license and Lesser GPL library license.\r
+  Whenever there is any discrepancy between the two licenses,\r
+  the BSD license will take precedence.\r
+         Set tabs to 4 for best viewing.\r
+\r
+*/\r
+\r
+@define('HORDE_BASE', dirname(dirname(dirname(__FILE__))) . '/horde');\r
+\r
+if (!is_dir(HORDE_BASE)) {\r
+       trigger_error(sprintf('Directory not found: \'%s\'', HORDE_BASE), E_USER_ERROR);\r
+       return 0;\r
+}\r
+\r
+include_once HORDE_BASE . '/lib/Horde.php';\r
+include_once HORDE_BASE . '/lib/Secret.php';\r
+\r
+/**\r
+\r
+NOTE: On Windows 2000 SP4 with PHP 4.3.1, MCrypt 2.4.x, and Apache 1.3.28,\r
+the session didn't work properly.\r
+\r
+This may be resolved with 4.3.3.\r
+\r
+ */\r
+class ADODB_Encrypt_Secret {\r
+       /**\r
+        */\r
+       function write($data, $key) {\r
+               return Secret::write($key, $data);\r
+       }\r
+\r
+       /**\r
+        */\r
+       function read($data, $key) {\r
+               return Secret::read($key, $data);\r
+       }\r
+\r
+}\r
+\r
+return 1;\r
+\r
+?>\r
diff --git a/lib/adodb/session/adodb-sess.txt b/lib/adodb/session/adodb-sess.txt
new file mode 100644 (file)
index 0000000..d23dac4
--- /dev/null
@@ -0,0 +1,131 @@
+John,\r
+\r
+I have been an extremely satisfied ADODB user for several years now.\r
+\r
+To give you something back for all your hard work, I've spent the last 3\r
+days rewriting the adodb-session.php code.\r
+\r
+----------\r
+What's New\r
+----------\r
+\r
+Here's a list of the new code's benefits:\r
+\r
+* Combines the functionality of the three files:\r
+\r
+adodb-session.php\r
+adodb-session-clob.php\r
+adodb-cryptsession.php\r
+\r
+each with very similar functionality, into a single file adodb-session.php.\r
+This will ease maintenance and support issues.\r
+\r
+* Supports multiple encryption and compression schemes.\r
+  Currently, we support:\r
+\r
+  MD5Crypt (crypt.inc.php)\r
+  MCrypt\r
+  Secure (Horde's emulation of MCrypt, if MCrypt module is not available.)\r
+  GZip\r
+  BZip2\r
+\r
+These can be stacked, so if you want to compress and then encrypt your\r
+session data, it's easy.\r
+Also, the built-in MCrypt functions will be *much* faster, and more secure,\r
+than the MD5Crypt code.\r
+\r
+* adodb-session.php contains a single class ADODB_Session that encapsulates\r
+all functionality.\r
+  This eliminates the use of global vars and defines (though they are\r
+supported for backwards compatibility).\r
+\r
+* All user defined parameters are now static functions in the ADODB_Session\r
+class.\r
+\r
+New parameters include:\r
+\r
+* encryptionKey(): Define the encryption key used to encrypt the session.\r
+Originally, it was a hard coded string.\r
+\r
+* persist(): Define if the database will be opened in persistent mode.\r
+Originally, the user had to call adodb_sess_open().\r
+\r
+* dataFieldName(): Define the field name used to store the session data, as\r
+'DATA' appears to be a reserved word in the following cases:\r
+       ANSI SQL\r
+       IBM DB2\r
+       MS SQL Server\r
+       Postgres\r
+       SAP\r
+\r
+* filter(): Used to support multiple, simulataneous encryption/compression\r
+schemes.\r
+\r
+* Debug support is improved thru _rsdump() function, which is called after\r
+every database call.\r
+\r
+------------\r
+What's Fixed\r
+------------\r
+\r
+The new code includes several bug fixes and enhancements:\r
+\r
+* sesskey is compared in BINARY mode for MySQL, to avoid problems with\r
+session keys that differ only by case.\r
+  Of course, the user should define the sesskey field as BINARY, to\r
+correctly fix this problem, otherwise performance will suffer.\r
+\r
+* In ADODB_Session::gc(), if $expire_notify is true, the multiple DELETES in\r
+the original code have been optimized to a single DELETE.\r
+\r
+* In ADODB_Session::destroy(), since "SELECT expireref, sesskey FROM $table\r
+WHERE sesskey = $qkey" will only return a single value, we don't loop on the\r
+result, we simply process the row, if any.\r
+\r
+* We close $rs after every use.\r
+\r
+---------------\r
+What's the Same\r
+---------------\r
+\r
+I know backwards compatibility is *very* important to you.  Therefore, the\r
+new code is 100% backwards compatible.\r
+\r
+If you like my code, but don't "trust" it's backwards compatible, maybe we\r
+offer it as beta code, in a new directory for a release or two?\r
+\r
+------------\r
+What's To Do\r
+------------\r
+\r
+I've vascillated over whether to use a single function to get/set\r
+parameters:\r
+\r
+$user = ADODB_Session::user();         // get\r
+ADODB_Session::user($user);            // set\r
+\r
+or to use separate functions (which is the PEAR/Java way):\r
+\r
+$user = ADODB_Session::getUser();\r
+ADODB_Session::setUser($user);\r
+\r
+I've chosen the former as it's makes for a simpler API, and reduces the\r
+amount of code, but I'd be happy to change it to the latter.\r
+\r
+Also, do you think the class should be a singleton class, versus a static\r
+class?\r
+\r
+Let me know if you find this code useful, and will be including it in the\r
+next release of ADODB.\r
+\r
+If so, I will modify the current documentation to detail the new\r
+functionality.  To that end, what file(s) contain the documentation?  Please\r
+send them to me if they are not publically available.\r
+\r
+Also, if there is *anything* in the code that you like to see changed, let\r
+me know.\r
+\r
+Thanks,\r
+\r
+Ross\r
+\r
diff --git a/lib/adodb/session/adodb-session-clob.php b/lib/adodb/session/adodb-session-clob.php
new file mode 100644 (file)
index 0000000..425adfb
--- /dev/null
@@ -0,0 +1,24 @@
+<?php\r
+\r
+// $CVSHeader$\r
+\r
+/*\r
+V4.01 23 Oct 2003  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+         Contributed by Ross Smith (adodb@netebb.com). \r
+  Released under both BSD license and Lesser GPL library license.\r
+  Whenever there is any discrepancy between the two licenses,\r
+  the BSD license will take precedence.\r
+         Set tabs to 4 for best viewing.\r
+*/\r
+\r
+/*\r
+\r
+This file is provided for backwards compatibility purposes\r
+\r
+*/\r
+\r
+require_once dirname(__FILE__) . '/adodb-session.php';\r
+\r
+ADODB_Session::clob('CLOB');\r
+\r
+?>
\ No newline at end of file
diff --git a/lib/adodb/session/adodb-session.php b/lib/adodb/session/adodb-session.php
new file mode 100644 (file)
index 0000000..7cba4f8
--- /dev/null
@@ -0,0 +1,817 @@
+<?php\r
+\r
+// $CVSHeader$\r
+\r
+/*\r
+V4.01 23 Oct 2003  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+         Contributed by Ross Smith (adodb@netebb.com). \r
+  Released under both BSD license and Lesser GPL library license.\r
+  Whenever there is any discrepancy between the two licenses,\r
+  the BSD license will take precedence.\r
+         Set tabs to 4 for best viewing.\r
+*/\r
+\r
+/*\r
+       You may want to rename the 'data' field to 'session_data' as\r
+       'data' appears to be a reserved word for one or more of the following:\r
+               ANSI SQL\r
+               IBM DB2\r
+               MS SQL Server\r
+               Postgres\r
+               SAP\r
+\r
+       If you do, then execute:\r
+\r
+               ADODB_Session::dataFieldName('session_data');\r
+\r
+*/\r
+\r
+if (!defined('_ADODB_LAYER')) {\r
+       require_once realpath(dirname(__FILE__) . '/../adodb.inc.php');\r
+}\r
+\r
+if (defined('ADODB_SESSION')) return 1;\r
+\r
+define('ADODB_SESSION', dirname(__FILE__));\r
+\r
+/*!\r
+       \static\r
+*/\r
+class ADODB_Session {\r
+       /////////////////////\r
+       // getter/setter methods\r
+       /////////////////////\r
+\r
+       /*!\r
+       */\r
+       function driver($driver = null) {\r
+               static $_driver = 'mysql';\r
+               static $set = false;\r
+\r
+               if (!is_null($driver)) {\r
+                       $_driver = trim($driver);\r
+                       $set = true;\r
+               } elseif (!$set) {\r
+                       // backwards compatibility\r
+                       if (isset($GLOBALS['ADODB_SESSION_DRIVER'])) {\r
+                               return $GLOBALS['ADODB_SESSION_DRIVER'];\r
+                       }\r
+               }\r
+\r
+               return $_driver;\r
+       }\r
+\r
+       /*!\r
+       */\r
+       function host($host = null) {\r
+               static $_host = 'localhost';\r
+               static $set = false;\r
+\r
+               if (!is_null($host)) {\r
+                       $_host = trim($host);\r
+                       $set = true;\r
+               } elseif (!$set) {\r
+                       // backwards compatibility\r
+                       if (isset($GLOBALS['ADODB_SESSION_CONNECT'])) {\r
+                               return $GLOBALS['ADODB_SESSION_CONNECT'];\r
+                       }\r
+               }\r
+\r
+               return $_host;\r
+       }\r
+\r
+       /*!\r
+       */\r
+       function user($user = null) {\r
+               static $_user = 'root';\r
+               static $set = false;\r
+\r
+               if (!is_null($user)) {\r
+                       $_user = trim($user);\r
+                       $set = true;\r
+               } elseif (!$set) {\r
+                       // backwards compatibility\r
+                       if (isset($GLOBALS['ADODB_SESSION_USER'])) {\r
+                               return $GLOBALS['ADODB_SESSION_USER'];\r
+                       }\r
+               }\r
+\r
+               return $_user;\r
+       }\r
+\r
+       /*!\r
+       */\r
+       function password($password = null) {\r
+               static $_password = '';\r
+               static $set = false;\r
+\r
+               if (!is_null($password)) {\r
+                       $_password = $password;\r
+                       $set = true;\r
+               } elseif (!$set) {\r
+                       // backwards compatibility\r
+                       if (isset($GLOBALS['ADODB_SESSION_PWD'])) {\r
+                               return $GLOBALS['ADODB_SESSION_PWD'];\r
+                       }\r
+               }\r
+\r
+               return $_password;\r
+       }\r
+\r
+       /*!\r
+       */\r
+       function database($database = null) {\r
+               static $_database = 'xphplens_2';\r
+               static $set = false;\r
+\r
+               if (!is_null($database)) {\r
+                       $_database = trim($database);\r
+                       $set = true;\r
+               } elseif (!$set) {\r
+                       // backwards compatibility\r
+                       if (isset($GLOBALS['ADODB_SESSION_DB'])) {\r
+                               return $GLOBALS['ADODB_SESSION_DB'];\r
+                       }\r
+               }\r
+\r
+               return $_database;\r
+       }\r
+\r
+       /*!\r
+       */\r
+       function persist($persist = null) {\r
+               static $_persist = true;\r
+\r
+               if (!is_null($persist)) {\r
+                       $_persist = trim($persist);\r
+               }\r
+\r
+               return $_persist;\r
+       }\r
+\r
+       /*!\r
+       */\r
+       function lifetime($lifetime = null) {\r
+               static $_lifetime;\r
+               static $set = false;\r
+\r
+               if (!is_null($lifetime)) {\r
+                       $_lifetime = (int) $lifetime;\r
+                       $set = true;\r
+               } elseif (!$set) {\r
+                       // backwards compatibility\r
+                       if (isset($GLOBALS['ADODB_SESS_LIFE'])) {\r
+                               return $GLOBALS['ADODB_SESS_LIFE'];\r
+                       }\r
+               }\r
+               if (!$_lifetime) {\r
+                       $_lifetime = ini_get('session.gc_maxlifetime');\r
+                       if ($_lifetime <= 1) {\r
+                               // bug in PHP 4.0.3 pl 1  -- how about other versions?\r
+                               //print "<h3>Session Error: PHP.INI setting <i>session.gc_maxlifetime</i>not set: $lifetime</h3>";\r
+                               $_lifetime = 1440;\r
+                       }\r
+               }\r
+\r
+               return $_lifetime;\r
+       }\r
+\r
+       /*!\r
+       */\r
+       function debug($debug = null) {\r
+               static $_debug = false;\r
+               static $set = false;\r
+\r
+               if (!is_null($debug)) {\r
+                       $_debug = (bool) $debug;\r
+\r
+                       $conn = ADODB_Session::_conn();\r
+                       if ($conn) {\r
+                               $conn->debug = $_debug;\r
+                       }\r
+                       $set = true;\r
+               } elseif (!$set) {\r
+                       // backwards compatibility\r
+                       if (isset($GLOBALS['ADODB_SESS_DEBUG'])) {\r
+                               return $GLOBALS['ADODB_SESS_DEBUG'];\r
+                       }\r
+               }\r
+\r
+               return $_debug;\r
+       }\r
+\r
+       /*!\r
+       */\r
+       function expireNotify($expire_notify = null) {\r
+               static $_expire_notify;\r
+               static $set = false;\r
+\r
+               if (!is_null($expire_notify)) {\r
+                       $_expire_notify = $expire_notify;\r
+                       $set = true;\r
+               } elseif (!$set) {\r
+                       // backwards compatibility\r
+                       if (isset($GLOBALS['ADODB_SESSION_EXPIRE_NOTIFY'])) {\r
+                               return $GLOBALS['ADODB_SESSION_EXPIRE_NOTIFY'];\r
+                       }\r
+               }\r
+\r
+               return $_expire_notify;\r
+       }\r
+\r
+       /*!\r
+       */\r
+       function table($table = null) {\r
+               static $_table = 'sessions';\r
+               static $set = false;\r
+\r
+               if (!is_null($table)) {\r
+                       $_table = trim($table);\r
+                       $set = true;\r
+               } elseif (!$set) {\r
+                       // backwards compatibility\r
+                       if (isset($GLOBALS['ADODB_SESSION_TBL'])) {\r
+                               return $GLOBALS['ADODB_SESSION_TBL'];\r
+                       }\r
+               }\r
+\r
+               return $_table;\r
+       }\r
+\r
+       /*!\r
+       */\r
+       function optimize($optimize = null) {\r
+               static $_optimize = false;\r
+               static $set = false;\r
+\r
+               if (!is_null($optimize)) {\r
+                       $_optimize = (bool) $optimize;\r
+                       $set = true;\r
+               } elseif (!$set) {\r
+                       // backwards compatibility\r
+                       if (defined('ADODB_SESSION_OPTIMIZE')) {\r
+                               return true;\r
+                       }\r
+               }\r
+\r
+               return $_optimize;\r
+       }\r
+\r
+       /*!\r
+       */\r
+       function syncSeconds($sync_seconds = null) {\r
+               static $_sync_seconds = 60;\r
+               static $set = false;\r
+\r
+               if (!is_null($sync_seconds)) {\r
+                       $_sync_seconds = (int) $sync_seconds;\r
+                       $set = true;\r
+               } elseif (!$set) {\r
+                       // backwards compatibility\r
+                       if (defined('ADODB_SESSION_SYNCH_SECS')) {\r
+                               return ADODB_SESSION_SYNCH_SECS;\r
+                       }\r
+               }\r
+\r
+               return $_sync_seconds;\r
+       }\r
+\r
+       /*!\r
+       */\r
+       function clob($clob = null) {\r
+               static $_clob = false;\r
+               static $set = false;\r
+\r
+               if (!is_null($clob)) {\r
+                       $_clob = strtolower(trim($clob));\r
+                       $set = true;\r
+               } elseif (!$set) {\r
+                       // backwards compatibility\r
+                       if (isset($GLOBALS['ADODB_SESSION_USE_LOBS'])) {\r
+                               return $GLOBALS['ADODB_SESSION_USE_LOBS'];\r
+                       }\r
+               }\r
+\r
+               return $_clob;\r
+       }\r
+\r
+       /*!\r
+       */\r
+       function dataFieldName($data_field_name = null) {\r
+               static $_data_field_name = 'data';\r
+\r
+               if (!is_null($data_field_name)) {\r
+                       $_data_field_name = trim($data_field_name);\r
+               }\r
+\r
+               return $_data_field_name;\r
+       }\r
+\r
+       /*!\r
+       */\r
+       function filter($filter = null) {\r
+               static $_filter = array();\r
+\r
+               if (!is_null($filter)) {\r
+                       if (!is_array($filter)) {\r
+                               $filter = array($filter);\r
+                       }\r
+                       $_filter = $filter;\r
+               }\r
+\r
+               return $_filter;\r
+       }\r
+\r
+       /*!\r
+       */\r
+       function encryptionKey($encryption_key = null) {\r
+               static $_encryption_key = 'CRYPTED ADODB SESSIONS ROCK!';\r
+\r
+               if (!is_null($encryption_key)) {\r
+                       $_encryption_key = $encryption_key;\r
+               }\r
+\r
+               return $_encryption_key;\r
+       }\r
+\r
+       /////////////////////\r
+       // private methods\r
+       /////////////////////\r
+\r
+       /*!\r
+       */\r
+       function &_conn($conn=null) {\r
+               return $GLOBALS['ADODB_SESS_CONN'];\r
+       }\r
+\r
+       /*!\r
+       */\r
+       function _crc($crc = null) {\r
+               static $_crc = false;\r
+\r
+               if (!is_null($crc)) {\r
+                       $_crc = $crc;\r
+               }\r
+\r
+               return $_crc;\r
+       }\r
+\r
+       /*!\r
+       */\r
+       function _init() {\r
+               session_module_name('user');\r
+               session_set_save_handler(\r
+                       array('ADODB_Session', 'open'),\r
+                       array('ADODB_Session', 'close'),\r
+                       array('ADODB_Session', 'read'),\r
+                       array('ADODB_Session', 'write'),\r
+                       array('ADODB_Session', 'destroy'),\r
+                       array('ADODB_Session', 'gc')\r
+               );\r
+       }\r
+\r
+\r
+       /*!\r
+       */\r
+       function _sessionKey() {\r
+               // use this function to create the encryption key for crypted sessions\r
+               // crypt the used key, ADODB_Session::encryptionKey() as key and session_id() as salt\r
+               return crypt(ADODB_Session::encryptionKey(), session_id());\r
+       }\r
+\r
+       /*!\r
+       */\r
+       function _dumprs($rs) {\r
+               $conn   =& ADODB_Session::_conn();\r
+               $debug  = ADODB_Session::debug();\r
+\r
+               if (!$conn) {\r
+                       return;\r
+               }\r
+\r
+               if (!$debug) {\r
+                       return;\r
+               }\r
+\r
+               if (!$rs) {\r
+                       echo "<br />\$rs is null or false<br />\n";\r
+                       return;\r
+               }\r
+\r
+               //echo "<br />\nAffected_Rows=",$conn->Affected_Rows(),"<br />\n";\r
+\r
+               if (!is_object($rs)) {\r
+                       return;\r
+               }\r
+\r
+               require_once ADODB_SESSION.'/../tohtml.inc.php';\r
+               rs2html($rs);\r
+       }\r
+\r
+       /////////////////////\r
+       // public methods\r
+       /////////////////////\r
+\r
+       /*!\r
+               Create the connection to the database.\r
+\r
+               If $conn already exists, reuse that connection\r
+       */\r
+       function open($save_path, $session_name, $persist = null) {\r
+               $conn =& ADODB_Session::_conn();\r
+\r
+               if ($conn) {\r
+                       return true;\r
+               }\r
+\r
+               $database       = ADODB_Session::database();\r
+               $debug          = ADODB_Session::debug();\r
+               $driver         = ADODB_Session::driver();\r
+               $host           = ADODB_Session::host();\r
+               $password       = ADODB_Session::password();\r
+               $user           = ADODB_Session::user();\r
+\r
+               if (!is_null($persist)) {\r
+                       $persist = (bool) $persist;\r
+                       ADODB_Session::persist($persist);\r
+               } else {\r
+                       $persist = ADODB_Session::persist();\r
+               }\r
+\r
+# these can all be defaulted to in php.ini\r
+#              assert('$database');\r
+#              assert('$driver');\r
+#              assert('$host');\r
+\r
+               // cannot use =& below - do not know why...\r
+               $conn = ADONewConnection($driver);\r
+\r
+               if ($debug) {\r
+                       $conn->debug = true;\r
+//                     ADOConnection::outp( " driver=$driver user=$user pwd=$password db=$database ");\r
+               }\r
+\r
+               if ($persist) {\r
+                       $ok = $conn->PConnect($host, $user, $password, $database);\r
+               } else {\r
+                       $ok = $conn->Connect($host, $user, $password, $database);\r
+               }\r
+\r
+               if ($ok) $GLOBALS['ADODB_SESS_CONN'] =& $conn;\r
+               else\r
+                       ADOConnection::outp('<p>Session: connection failed</p>', false);\r
+               \r
+\r
+               return $ok;\r
+       }\r
+\r
+       /*!\r
+               Close the connection\r
+       */\r
+       function close() {\r
+               $conn =& ADODB_Session::_conn();\r
+\r
+               if ($conn) {\r
+                       $conn->Close();\r
+               }\r
+\r
+               return true;\r
+       }\r
+\r
+       /*\r
+               Slurp in the session variables and return the serialized string\r
+       */\r
+       function read($key) {\r
+               $conn   =& ADODB_Session::_conn();\r
+               $data   = ADODB_Session::dataFieldName();\r
+               $filter = ADODB_Session::filter();\r
+               $table  = ADODB_Session::table();\r
+\r
+               if (!$conn) {\r
+                       return '';\r
+               }\r
+\r
+               assert('$table');\r
+\r
+               $qkey = $conn->quote($key);\r
+               $binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : '';\r
+\r
+               $sql = "SELECT $data FROM $table WHERE $binary sesskey = $qkey AND expiry >= " . time();\r
+               $rs =& $conn->Execute($sql);\r
+               //ADODB_Session::_dumprs($rs);\r
+               if ($rs) {\r
+                       if ($rs->EOF) {\r
+                               $v = '';\r
+                       } else {\r
+                               $v = reset($rs->fields);\r
+                               $filter = array_reverse($filter);\r
+                               foreach ($filter as $f) {\r
+                                       if (is_object($f)) {\r
+                                               $v = $f->read($v, ADODB_Session::_sessionKey());\r
+                                       }\r
+                               }\r
+                               $v = rawurldecode($v);\r
+                       }\r
+\r
+                       $rs->Close();\r
+\r
+                       ADODB_Session::_crc(strlen($v) . crc32($v));\r
+                       return $v;\r
+               }\r
+\r
+               return '';\r
+       }\r
+\r
+       /*!\r
+               Write the serialized data to a database.\r
+\r
+               If the data has not been modified since the last read(), we do not write.\r
+       */\r
+       function write($key, $val) {\r
+               $clob                   = ADODB_Session::clob();\r
+               $conn                   =& ADODB_Session::_conn();\r
+               $crc                    = ADODB_Session::_crc();\r
+               $data                   = ADODB_Session::dataFieldName();\r
+               $debug                  = ADODB_Session::debug();\r
+               $driver                 = ADODB_Session::driver();\r
+               $expire_notify  = ADODB_Session::expireNotify();\r
+               $filter                 = ADODB_Session::filter();\r
+               $lifetime               = ADODB_Session::lifetime();\r
+               $table                  = ADODB_Session::table();\r
+\r
+               if (!$conn) {\r
+                       return false;\r
+               }\r
+\r
+               assert('$table');\r
+\r
+               $expiry = time() + $lifetime;\r
+\r
+               $qkey = $conn->quote($key);\r
+               $binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : '';\r
+\r
+               // crc32 optimization since adodb 2.1\r
+               // now we only update expiry date, thx to sebastian thom in adodb 2.32\r
+               if ($crc !== false && $crc == (strlen($val) . crc32($val))) {\r
+                       if ($debug) {\r
+                               echo '<p>Session: Only updating date - crc32 not changed</p>';\r
+                       }\r
+                       $sql = "UPDATE $table SET expiry = $expiry WHERE $binary sesskey = $qkey AND expiry >= " . time();\r
+                       $rs =& $conn->Execute($sql);\r
+                       ADODB_Session::_dumprs($rs);\r
+                       if ($rs) {\r
+                               $rs->Close();\r
+                       }\r
+                       return true;\r
+               }\r
+               $val = rawurlencode($val);\r
+               foreach ($filter as $f) {\r
+                       if (is_object($f)) {\r
+                               $val = $f->write($val, ADODB_Session::_sessionKey());\r
+                       }\r
+               }\r
+\r
+               $arr = array('sesskey' => $key, 'expiry' => $expiry, $data => $val, 'expireref' => '');\r
+               if ($expire_notify) {\r
+                       $var = reset($expire_notify);\r
+                       global $$var;\r
+                       if (isset($$var)) {\r
+                               $arr['expireref'] = $$var;\r
+                       }\r
+               }\r
+\r
+               if (!$clob) {   // no lobs, simply use replace()\r
+                       $rs = $conn->Replace($table, $arr, 'sesskey', $autoQuote = true);\r
+                       ADODB_Session::_dumprs($rs);\r
+               } else {\r
+                       // what value shall we insert/update for lob row?\r
+                       switch ($driver) {\r
+                               // empty_clob or empty_lob for oracle dbs\r
+                               case 'oracle':\r
+                               case 'oci8':\r
+                               case 'oci8po':\r
+                               case 'oci805':\r
+                                       $lob_value = sprintf('empty_%s()', strtolower($clob));\r
+                                       break;\r
+\r
+                               // null for all other\r
+                               default:\r
+                                       $lob_value = 'null';\r
+                                       break;\r
+                       }\r
+\r
+                       // do we insert or update? => as for sesskey\r
+                       $rs =& $conn->Execute("SELECT COUNT(*) AS cnt FROM $table WHERE $binary sesskey = $qkey");\r
+                       ADODB_Session::_dumprs($rs);\r
+                       if ($rs && reset($rs->fields) > 0) {\r
+                               $sql = "UPDATE $table SET expiry = $expiry, $data = $lob_value WHERE  sesskey = $qkey";\r
+                       } else {\r
+                               $sql = "INSERT INTO $table (expiry, $data, sesskey) VALUES ($expiry, $lob_value, $qkey)";\r
+                       }\r
+                       if ($rs) {\r
+                               $rs->Close();\r
+                       }\r
+\r
+                       $err = '';\r
+                       $rs1 =& $conn->Execute($sql);\r
+                       ADODB_Session::_dumprs($rs1);\r
+                       if (!$rs1) {\r
+                               $err = $conn->ErrorMsg()."\n";\r
+                       }\r
+                       $rs2 =& $conn->UpdateBlob($table, $data, $val, " sesskey=$qkey", strtoupper($clob));\r
+                       ADODB_Session::_dumprs($rs2);\r
+                       if (!$rs2) {\r
+                               $err .= $conn->ErrorMsg()."\n";\r
+                       }\r
+                       $rs = ($rs && $rs2) ? true : false;\r
+                       if ($rs1) {\r
+                               $rs1->Close();\r
+                       }\r
+                       if (is_object($rs2)) {\r
+                               $rs2->Close();\r
+                       }\r
+               }\r
+\r
+               if (!$rs) {\r
+                       ADOConnection::outp('<p>Session Replace: ' . $conn->ErrorMsg() . '</p>', false);\r
+                       return false;\r
+               }  else {\r
+                       // bug in access driver (could be odbc?) means that info is not committed\r
+                       // properly unless select statement executed in Win2000\r
+                       if ($conn->databaseType == 'access') {\r
+                               $sql = "SELECT sesskey FROM $table WHERE $binary sesskey = $qkey";\r
+                               $rs =& $conn->Execute($sql);\r
+                               ADODB_Session::_dumprs($rs);\r
+                               if ($rs) {\r
+                                       $rs->Close();\r
+                               }\r
+                       }\r
+               }\r
+               return $rs ? true : false;\r
+       }\r
+\r
+       /*!\r
+       */\r
+       function destroy($key) {\r
+               $conn                   =& ADODB_Session::_conn();\r
+               $table                  = ADODB_Session::table();\r
+               $expire_notify  = ADODB_Session::expireNotify();\r
+\r
+               if (!$conn) {\r
+                       return false;\r
+               }\r
+\r
+               assert('$table');\r
+\r
+               $qkey = $conn->quote($key);\r
+               $binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : '';\r
+\r
+               if ($expire_notify) {\r
+                       reset($expire_notify);\r
+                       $fn = next($expire_notify);\r
+                       $savem = $conn->SetFetchMode(ADODB_FETCH_NUM);\r
+                       $sql = "SELECT expireref, sesskey FROM $table WHERE $binary sesskey = $qkey";\r
+                       $rs =& $conn->Execute($sql);\r
+                       ADODB_Session::_dumprs($rs);\r
+                       $conn->SetFetchMode($savem);\r
+                       if (!$rs) {\r
+                               return false;\r
+                       }\r
+                       if (!$rs->EOF) {\r
+                               $ref = $rs->fields[0];\r
+                               $key = $rs->fields[1];\r
+                               assert('$ref');\r
+                               assert('$key');\r
+                               $fn($ref, $key);\r
+                       }\r
+                       $rs->Close();\r
+               }\r
+\r
+               $sql = "DELETE FROM $table WHERE $binary sesskey = $qkey";\r
+               $rs =& $conn->Execute($sql);\r
+               ADODB_Session::_dumprs($rs);\r
+               if ($rs) {\r
+                       $rs->Close();\r
+               }\r
+\r
+               return $rs ? true : false;\r
+       }\r
+\r
+       /*!\r
+       */\r
+       function gc($maxlifetime) {\r
+               $conn                   =& ADODB_Session::_conn();\r
+               $debug                  = ADODB_Session::debug();\r
+               $expire_notify  = ADODB_Session::expireNotify();\r
+               $optimize               = ADODB_Session::optimize();\r
+               $sync_seconds   = ADODB_Session::syncSeconds();\r
+               $table                  = ADODB_Session::table();\r
+\r
+               if (!$conn) {\r
+                       return false;\r
+               }\r
+\r
+               assert('$table');\r
+\r
+               $time                   = time();\r
+\r
+               $binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : '';\r
+\r
+               if ($expire_notify) {\r
+                       reset($expire_notify);\r
+                       $fn = next($expire_notify);\r
+                       $savem = $conn->SetFetchMode(ADODB_FETCH_NUM);\r
+                       $sql = "SELECT expireref, sesskey FROM $table WHERE expiry < $time";\r
+                       $rs =& $conn->Execute($sql);\r
+                       ADODB_Session::_dumprs($rs);\r
+                       $conn->SetFetchMode($savem);\r
+                       if ($rs) {\r
+                               $conn->BeginTrans();\r
+                               $keys = array();\r
+                               while (!$rs->EOF) {\r
+                                       $ref = $rs->fields[0];\r
+                                       $key = $rs->fields[1];\r
+                                       $fn($ref, $key);\r
+                                       $del = $conn->Execute("DELETE FROM $table WHERE sesskey='$key'");\r
+                                       $rs->MoveNext();\r
+                               }\r
+                               $rs->Close();\r
+                               \r
+                               $conn->CommitTrans();\r
+                       }\r
+               } else {\r
+                       $sql = "DELETE FROM $table WHERE expiry < $time";\r
+                       $rs =& $conn->Execute($sql);\r
+                       ADODB_Session::_dumprs($rs);\r
+                       if ($rs) {\r
+                               $rs->Close();\r
+                       }\r
+                       if ($debug) {\r
+                               ADOConnection::outp("<p><b>Garbage Collection</b>: $sql</p>");\r
+                       }\r
+               }\r
+\r
+               // suggested by Cameron, "GaM3R" <gamr@outworld.cx>\r
+               if ($optimize) {\r
+                       $driver = ADODB_Session::driver();\r
+\r
+                       if (preg_match('/mysql/i', $driver)) {\r
+                               $sql = "OPTIMIZE TABLE $table";\r
+                       }\r
+                       if (preg_match('/postgres/i', $driver)) {\r
+                               $sql = "VACUUM $table";\r
+                       }\r
+                       if (!empty($sql)) {\r
+                               $conn->Execute($sql);\r
+                       }\r
+               }\r
+\r
+               if ($sync_seconds) {\r
+                       $sql = 'SELECT ';\r
+                       if ($conn->dataProvider === 'oci8') {\r
+                               $sql .= "TO_CHAR({$conn->sysTimeStamp}, 'RRRR-MM-DD HH24:MI:SS')";\r
+                       } else {\r
+                               $sql .= $conn->sysTimeStamp;\r
+                       }\r
+                       $sql .= " FROM $table";\r
+\r
+                       $rs =& $conn->SelectLimit($sql, 1);\r
+                       if ($rs && !$rs->EOF) {\r
+                               $dbts = reset($rs->fields);\r
+                               $rs->Close();\r
+                               $dbt = $conn->UnixTimeStamp($dbts);\r
+                               $t = time();\r
+\r
+                               if (abs($dbt - $t) >= $sync_seconds) {\r
+                                       global $HTTP_SERVER_VARS;\r
+                                       $msg = __FILE__ .\r
+                                               ": Server time for webserver {$HTTP_SERVER_VARS['HTTP_HOST']} not in synch with database: " .\r
+                                               " database=$dbt ($dbts), webserver=$t (diff=". (abs($dbt - $t) / 3600) . ' hours)';\r
+                                       error_log($msg);\r
+                                       if ($debug) {\r
+                                               ADOConnection::outp("<p>$msg</p>");\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+               return true;\r
+       }\r
+\r
+}\r
+\r
+ADODB_Session::_init();\r
+\r
+\r
+// for backwards compatability only\r
+function adodb_sess_open($save_path, $session_name, $persist = true) {\r
+       return ADODB_Session::open($save_path, $session_name, $persist);\r
+}\r
+\r
+// for backwards compatability only\r
+function adodb_sess_gc($t)\r
+{      \r
+       return ADODB_Session::gc($t);\r
+}\r
+\r
+?>\r
diff --git a/lib/adodb/session/adodb-sessions.mysql.sql b/lib/adodb/session/adodb-sessions.mysql.sql
new file mode 100644 (file)
index 0000000..f90de44
--- /dev/null
@@ -0,0 +1,16 @@
+-- $CVSHeader$
+
+CREATE DATABASE /*! IF NOT EXISTS */ adodb_sessions;
+
+USE adodb_sessions;
+
+DROP TABLE /*! IF EXISTS */ sessions;
+
+CREATE TABLE /*! IF NOT EXISTS */ sessions (
+       sesskey         CHAR(32)        /*! BINARY */ NOT NULL DEFAULT '',
+       expiry          INT(11)         /*! UNSIGNED */ NOT NULL DEFAULT 0,
+       expireref       VARCHAR(64)     DEFAULT '',
+       data            LONGTEXT        DEFAULT '',
+       PRIMARY KEY     (sesskey),
+       INDEX expiry (expiry)
+);
diff --git a/lib/adodb/session/adodb-sessions.oracle.clob.sql b/lib/adodb/session/adodb-sessions.oracle.clob.sql
new file mode 100644 (file)
index 0000000..c5c4f2d
--- /dev/null
@@ -0,0 +1,15 @@
+-- $CVSHeader$
+
+DROP TABLE adodb_sessions;
+
+CREATE TABLE sessions (
+       sesskey         CHAR(32)        DEFAULT '' NOT NULL,
+       expiry          INT             DEFAULT 0 NOT NULL,
+       expireref       VARCHAR(64)     DEFAULT '',
+       data            CLOB            DEFAULT '',
+       PRIMARY KEY     (sesskey)
+);
+
+CREATE INDEX ix_expiry ON sessions (expiry);
+
+QUIT;
diff --git a/lib/adodb/session/adodb-sessions.oracle.sql b/lib/adodb/session/adodb-sessions.oracle.sql
new file mode 100644 (file)
index 0000000..8fd5a34
--- /dev/null
@@ -0,0 +1,16 @@
+-- $CVSHeader$
+
+DROP TABLE adodb_sessions;
+
+CREATE TABLE sessions (
+       sesskey         CHAR(32)        DEFAULT '' NOT NULL,
+       expiry          INT             DEFAULT 0 NOT NULL,
+       expireref       VARCHAR(64)     DEFAULT '',
+       data            VARCHAR(4000)   DEFAULT '',
+       PRIMARY KEY     (sesskey),
+       INDEX expiry (expiry)
+);
+
+CREATE INDEX ix_expiry ON sessions (expiry);
+
+QUIT;
diff --git a/lib/adodb/session/crypt.inc.php b/lib/adodb/session/crypt.inc.php
new file mode 100644 (file)
index 0000000..7266ab6
--- /dev/null
@@ -0,0 +1,64 @@
+<?php\r
+//      Session Encryption by Ari Kuorikoski <ari.kuorikoski@finebyte.com>\r
+class MD5Crypt{\r
+               function keyED($txt,$encrypt_key)\r
+               {\r
+                               $encrypt_key = md5($encrypt_key);\r
+                               $ctr=0;\r
+                               $tmp = "";\r
+                               for ($i=0;$i<strlen($txt);$i++){\r
+                                               if ($ctr==strlen($encrypt_key)) $ctr=0;\r
+                                               $tmp.= substr($txt,$i,1) ^ substr($encrypt_key,$ctr,1);\r
+                                               $ctr++;\r
+                               }\r
+                               return $tmp;\r
+               }\r
+\r
+               function Encrypt($txt,$key)\r
+               {\r
+                               srand((double)microtime()*1000000);\r
+                               $encrypt_key = md5(rand(0,32000));\r
+                               $ctr=0;\r
+                               $tmp = "";\r
+                               for ($i=0;$i<strlen($txt);$i++)\r
+                               {\r
+                               if ($ctr==strlen($encrypt_key)) $ctr=0;\r
+                               $tmp.= substr($encrypt_key,$ctr,1) .\r
+                               (substr($txt,$i,1) ^ substr($encrypt_key,$ctr,1));\r
+                               $ctr++;\r
+                               }\r
+                               return base64_encode($this->keyED($tmp,$key));\r
+               }\r
+\r
+               function Decrypt($txt,$key)\r
+               {\r
+                               $txt = $this->keyED(base64_decode($txt),$key);\r
+                               $tmp = "";\r
+                               for ($i=0;$i<strlen($txt);$i++){\r
+                                               $md5 = substr($txt,$i,1);\r
+                                               $i++;\r
+                                               $tmp.= (substr($txt,$i,1) ^ $md5);\r
+                               }\r
+                               return $tmp;\r
+               }\r
+\r
+               function RandPass()\r
+               {\r
+                               $randomPassword = "";\r
+                               srand((double)microtime()*1000000);\r
+                               for($i=0;$i<8;$i++)\r
+                               {\r
+                                               $randnumber = rand(48,120);\r
+\r
+                                               while (($randnumber >= 58 && $randnumber <= 64) || ($randnumber >= 91 && $randnumber <= 96))\r
+                                               {\r
+                                                               $randnumber = rand(48,120);\r
+                                               }\r
+\r
+                                               $randomPassword .= chr($randnumber);\r
+                               }\r
+                               return $randomPassword;\r
+               }\r
+\r
+}\r
+?>
\ No newline at end of file
index 76db3c12a0b069ec76c4de9ea1f05fab14ad0c25..484b9cc78b965d7426b6a4fe341a835f7f9601b0 100644 (file)
@@ -8,7 +8,7 @@
 <body>\r
 <?php \r
 /*\r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
index 0248ba318b2756fe840b19f105225a38c101e716..c89051ade3370926c3385c48cfa9e583a4163003 100644 (file)
@@ -2,7 +2,7 @@
 <body bgcolor=white>\r
 <?php\r
 /** \r
- * V4.01 23 Oct 2003  (c) 2001-2002 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+ * V4.11 27 Jan 2004  (c) 2001-2002 John Lim (jlim@natsoft.com.my). All rights reserved.\r
  * Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
index 7bcf7d06523423e7c6e76d487bef45e1329a0a6e..176a1f3fd308ecfdbebfec1014b27f791e83ceb9 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
 /*\r
 \r
-  V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+  V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
diff --git a/lib/adodb/tests/test-pgblob.php b/lib/adodb/tests/test-pgblob.php
new file mode 100644 (file)
index 0000000..b592757
--- /dev/null
@@ -0,0 +1,35 @@
+<?php\r
+include_once('../adodb.inc.php');\r
+$db = NewADOConnection('postgres7');\r
+$db->Connect('localhost','tester','test','test') || die("failed connection");\r
+\r
+$enc = "GIF89a%01%00%01%00%80%FF%00%C0%C0%C0%00%00%00%21%F9%04%01%00%00%00%00%2C%00%00%00%00%01%00%01%00%00%01%012%00%3Bt_clear.gif%0D";\r
+$val = rawurldecode($enc);\r
+$db->debug=1;\r
+\r
+### TEST BEGINS\r
+\r
+$db->Execute("insert into photos (id,name) values(9999,'dot.gif')");\r
+$db->UpdateBlob('photos','photo',$val,'id=9999');\r
+$v = $db->GetOne('select photo from photos where id=9999');\r
+\r
+\r
+### CLEANUP\r
+\r
+$db->Execute("delete from photos where id=9999");\r
+\r
+### VALIDATION\r
+\r
+if ($v !== $val) echo "<b>*** ERROR: Inserted value does not match downloaded val<b>";\r
+else echo "<b>*** OK: Passed</b>";\r
+\r
+echo "<pre>";\r
+echo "INSERTED: ", $enc;\r
+echo "<hr>";\r
+echo"RETURNED: ", rawurlencode($v);\r
+echo "<hr><p>";\r
+echo "INSERTED: ", $val;\r
+echo "<hr>";\r
+echo "RETURNED: ", $v;\r
+\r
+?>
\ No newline at end of file
diff --git a/lib/adodb/tests/test-php5.php b/lib/adodb/tests/test-php5.php
new file mode 100644 (file)
index 0000000..033f667
--- /dev/null
@@ -0,0 +1,56 @@
+<?php\r
+/*\r
+  V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+  Released under both BSD license and Lesser GPL library license. \r
+  Whenever there is any discrepancy between the two licenses, \r
+  the BSD license will take precedence.\r
+  Set tabs to 8.\r
+ */\r
+\r
+\r
+error_reporting(E_ALL);\r
+\r
+$path = dirname(__FILE__);\r
+\r
+include("$path/../adodb-exceptions.inc.php");\r
+include("$path/../adodb.inc.php");     \r
+\r
+try {\r
+\r
+$dbt = 'oci8';\r
+\r
+switch($dbt) {\r
+case 'oci8':\r
+       $db = NewADOConnection("oci8");\r
+       $db->Connect('','scott','natsoft');\r
+       break;\r
+default:\r
+case 'mysql':\r
+       $db = NewADOConnection("mysql");\r
+       $db->Connect('localhost','root','','test');\r
+       break;\r
+}\r
+\r
+$db->debug=1;\r
+\r
+$cnt = $db->GetOne("select count(*) from adoxyz");\r
+$rs = $db->Execute("select * from adoxyz order by id");\r
+\r
+$i = 0;\r
+foreach($rs as  $v) {\r
+       $i += 1;\r
+       echo "$i: "; adodb_pr($v); adodb_pr($rs->fields);\r
+       flush();\r
+}\r
+\r
+if ($i != $cnt) die("actual cnt is $i, cnt should be $cnt\n");\r
+\r
+\r
+$rs = $db->Execute("select bad from badder");\r
+\r
+} catch (exception $e) {\r
+       adodb_pr($e);\r
+       $e = adodb_backtrace($e->trace);\r
+}\r
+\r
+?>
\ No newline at end of file
index 80058f71b6f3632de76ba396a661dfa0090e8ecb..aa3b4e8be9bbe544a28082a25a058cdab704ce30 100644 (file)
@@ -1,6 +1,6 @@
 <?PHP\r
 \r
-// V4.01 23 Oct 2003\r
+// V4.11 27 Jan 2004\r
 \r
 error_reporting(E_ALL);\r
 \r
index 70cd45cd856263b6e42aec7d19f03304186aa798..d1d6fe3f58aa028c5462364e7da34c6a656d5ba1 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
@@ -10,7 +10,7 @@ V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights rese
 */\r
 \r
 error_reporting(E_ALL);\r
-\r
+$ADODB_FLUSH = true;\r
 \r
 define('ADODB_ASSOC_CASE',0);\r
 \r
@@ -28,7 +28,7 @@ function CheckWS($conn)
 {\r
 global $ADODB_EXTENSION;\r
 \r
-       include_once('../adodb-session.php');\r
+       include_once('../session/adodb-session.php');\r
        \r
        $saved = $ADODB_EXTENSION;\r
        $db = ADONewConnection($conn);\r
@@ -118,6 +118,7 @@ FROM `nuke_stories` `t1`, `nuke_authors` `t2`, `nuke_stories_cat` `t3`, `nuke_to
        flush();\r
        print "<i>date1</i> (1969-02-20) = ".$db->DBDate('1969-2-20');\r
        print "<br><i>date1</i> (1999-02-20) = ".$db->DBDate('1999-2-20');\r
+       print "<br><i>date1.1</i> 1999 = ".$db->DBDate("'1999'");\r
        print "<br><i>date2</i> (1970-1-2) = ".$db->DBDate(24*3600)."<p>";\r
        print "<i>ts1</i> (1999-02-20 13:40:50) = ".$db->DBTimeStamp('1999-2-20 1:40:50 pm');\r
        print "<br><i>ts1.1</i> (1999-02-20 13:40:00) = ".$db->DBTimeStamp('1999-2-20 13:40');\r
@@ -126,6 +127,10 @@ FROM `nuke_stories` `t1`, `nuke_authors` `t2`, `nuke_stories_cat` `t3`, `nuke_to
        print "<br> Fractional TS (1999-2-20 13:40:50.91): ".$db->DBTimeStamp($db->UnixTimeStamp('1999-2-20 13:40:50.91+1'));\r
         $dd = $db->UnixDate('1999-02-20');\r
        print "<br>unixdate</i> 1999-02-20 = ".date('Y-m-d',$dd)."<p>";\r
+       print "<br><i>ts4</i> =".($db->UnixTimeStamp("19700101000101")+8*3600);\r
+       print "<br><i>ts5</i> =".$db->DBTimeStamp($db->UnixTimeStamp("20040110092123"));\r
+       print "<br><i>ts6</i> =".$db->UserTimeStamp("20040110092123");\r
+       print "<br><i>ts6</i> =".$db->DBTimeStamp("20040110092123");\r
        flush();\r
        // mssql too slow in failing bad connection\r
        if (false && $db->databaseType != 'mssql') {\r
@@ -260,8 +265,18 @@ FROM `nuke_stories` `t1`, `nuke_authors` `t2`, `nuke_stories_cat` `t3`, `nuke_to
                $a = $db->MetaColumns('ADOXYZ');\r
                if ($a===false) print "<b>MetaColumns not supported</b></p>";\r
                else {\r
-                       print "<p>Columns of ADOXYZ: ";\r
-                       foreach($a as $v) print " ($v->name $v->type $v->max_length) ";\r
+                       print "<p>Columns of ADOXYZ: <font size=1><br>";\r
+                       foreach($a as $v) {print_r($v); echo "<br>";}\r
+                       echo "</font>";\r
+               }\r
+               \r
+               print "<p>Testing MetaIndexes</p>";\r
+               $a = $db->MetaIndexes('ADOXYZ',true);\r
+               if ($a===false) print "<b>MetaIndexes not supported</b></p>";\r
+               else {\r
+                       print "<p>Indexes of ADOXYZ: <font size=1><br>";\r
+                       foreach($a as $v) {print_r($v); echo "<br>";}\r
+                       echo "</font>";\r
                }\r
                print "<p>Testing MetaPrimaryKeys</p>";\r
                $a = $db->MetaPrimaryKeys('ADOXYZ');\r
@@ -329,8 +344,8 @@ GO
                $yr = '1998';\r
                \r
                $stmt = $db->PrepareSP('SalesByCategory');\r
-               $db->Parameter($stmt,$cat,'CategoryName');\r
-               $db->Parameter($stmt,$yr,'OrdYear');\r
+               $db->InParameter($stmt,$cat,'CategoryName');\r
+               $db->InParameter($stmt,$yr,'OrdYear');\r
                $rs = $db->Execute($stmt);\r
                rs2html($rs);\r
                \r
@@ -338,8 +353,8 @@ GO
                $yr = 1998;\r
                \r
                $stmt = $db->PrepareSP('SalesByCategory');\r
-               $db->Parameter($stmt,$cat,'CategoryName');\r
-               $db->Parameter($stmt,$yr,'OrdYear');\r
+               $db->InParameter($stmt,$cat,'CategoryName');\r
+               $db->InParameter($stmt,$yr,'OrdYear');\r
                $rs = $db->Execute($stmt);\r
                rs2html($rs);\r
                \r
@@ -362,9 +377,9 @@ GO
                $days = 10;\r
                $begin_date = '';\r
                $end_date = '';\r
-               $db->Parameter($stmt,$days,'days', false, 4, SQLINT4); \r
-               $db->Parameter($stmt,$begin_date,'start', 1, 20, SQLVARCHAR ); \r
-               $db->Parameter($stmt,$end_date,'end', 1, 20, SQLVARCHAR ); \r
+               $db->InParameter($stmt,$days,'days', 4, SQLINT4); \r
+               $db->OutParameter($stmt,$begin_date,'start', 20, SQLVARCHAR ); \r
+               $db->OutParameter($stmt,$end_date,'end', 20, SQLVARCHAR ); \r
                $db->Execute($stmt);\r
                if (empty($begin_date) or empty($end_date)) {\r
                        Err("MSSQL SP Test for OUT Failed");\r
@@ -388,6 +403,7 @@ GO
 CREATE OR REPLACE PACKAGE adodb AS\r
 TYPE TabType IS REF CURSOR RETURN tab%ROWTYPE;\r
 PROCEDURE open_tab (tabcursor IN OUT TabType,tablenames in varchar);\r
+PROCEDURE data_out(input IN varchar, output OUT varchar); \r
 END adodb;\r
 /\r
 \r
@@ -396,12 +412,16 @@ PROCEDURE open_tab (tabcursor IN OUT TabType,tablenames in varchar) IS
        BEGIN\r
                OPEN tabcursor FOR SELECT * FROM tab where tname like tablenames;\r
        END open_tab;\r
+       \r
+PROCEDURE data_out(input IN varchar, output OUT varchar) IS\r
+       BEGIN\r
+               output := 'Cinta Hati '||input;\r
+       END;\r
 END adodb;\r
-\r
 /\r
-*/             \r
+*/\r
                $stmt = $db->Prepare("BEGIN adodb.open_tab(:RS,'A%'); END;");\r
-               $db->Parameter($stmt, $cur, 'RS', false, -1, OCI_B_CURSOR);\r
+               $db->InParameter($stmt, $cur, 'RS', -1, OCI_B_CURSOR);\r
                $rs = $db->Execute($stmt);\r
        \r
                if ($rs && !$rs->EOF) {\r
@@ -410,15 +430,22 @@ END adodb;
                        print "<b>Error in using Cursor Variables 1</b><p>";\r
                }\r
                \r
-               $rs = $db->ExecuteCursor("BEGIN adodb.open_tab(:RS2,:TAB); END;",'RS2',array('TAB'=>'A%'));\r
-               if ($rs && !$rs->EOF) {\r
-                       print "Test 2 RowCount: ".$rs->RecordCount()."<p>";\r
+               \r
+               print "<h4>Testing Stored Procedures for oci8</h4>";\r
+               \r
+               $stmt = $db->PrepareSP("BEGIN adodb.data_out(:a1, :a2); END;");\r
+               $a1 = 'Malaysia';\r
+               //$a2 = ''; # a2 doesn't even need to be defined!\r
+               $db->InParameter($stmt,$a1,'a1');\r
+               $db->OutParameter($stmt,$a2,'a2');\r
+               $rs = $db->Execute($stmt);\r
+               if ($rs) {\r
+                       if ($a2 !== 'Cinta Hati Malaysia') print "<b>Stored Procedure Error: a2 = $a2</b><p>";\r
+                       else echo  "OK: a2=$a2<p>";\r
                } else {\r
-                       print "<b>Error in using Cursor Variables 2</b><p>";\r
+                       print "<b>Error in using Stored Procedure IN/Out Variables</b><p>";\r
                }\r
                \r
-               print "<h4>Testing Stored Procedures for oci8</h4>";\r
-\r
                \r
                $tname = 'A%';\r
                \r
@@ -530,6 +557,7 @@ END adodb;
        $db->Execute("insert into ADOXYZ (id,firstname,lastname,created) values ($i*10+9,'Steven','Oey',$time )");\r
        } // for\r
        if (1) {\r
+       $db->debug=1;\r
        $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;\r
        $cnt = $db->GetOne("select count(*) from ADOXYZ");\r
        $rs = $db->Execute('update ADOXYZ set id=id+1');        \r
@@ -555,23 +583,24 @@ END adodb;
                print "<p><b>Error on RecordCount. Should be 0. Was ".$rs->RecordCount()."</b></p>"; \r
                print_r($rs->fields);\r
        }\r
-       $rs = &$db->Execute("select id,firstname,lastname,created from ADOXYZ order by id");\r
-       if ($rs) {\r
-               if ($rs->RecordCount() != 50) {\r
-                       print "<p><b>RecordCount returns ".$rs->RecordCount()."</b></p>";\r
-                       $poc = $rs->PO_RecordCount('ADOXYZ');\r
-                       if ($poc == 50) print "<p> &nbsp; &nbsp; PO_RecordCount passed</p>";\r
-                       else print "<p><b>PO_RecordCount returns wrong value: $poc</b></p>";\r
-               } else print "<p>RecordCount() passed</p>";\r
-               if (isset($rs->fields['firstname'])) print '<p>The fields columns can be indexed by column name.</p>';\r
-               else {\r
-                       Err( '<p>The fields columns <i>cannot</i> be indexed by column name.</p>');\r
-                       print_r($rs->fields);\r
+       if ($db->databaseType !== 'odbc') {\r
+               $rs = &$db->Execute("select id,firstname,lastname,created,".$db->random." from ADOXYZ order by id");\r
+               if ($rs) {\r
+                       if ($rs->RecordCount() != 50) {\r
+                               print "<p><b>RecordCount returns ".$rs->RecordCount()."</b></p>";\r
+                               $poc = $rs->PO_RecordCount('ADOXYZ');\r
+                               if ($poc == 50) print "<p> &nbsp; &nbsp; PO_RecordCount passed</p>";\r
+                               else print "<p><b>PO_RecordCount returns wrong value: $poc</b></p>";\r
+                       } else print "<p>RecordCount() passed</p>";\r
+                       if (isset($rs->fields['firstname'])) print '<p>The fields columns can be indexed by column name.</p>';\r
+                       else {\r
+                               Err( '<p>The fields columns <i>cannot</i> be indexed by column name.</p>');\r
+                               print_r($rs->fields);\r
+                       }\r
+                       if (empty($HTTP_GET_VARS['hide'])) rs2html($rs);\r
                }\r
-               if (empty($HTTP_GET_VARS['hide'])) rs2html($rs);\r
+               else print "<b>Error in Execute of SELECT with random</b></p>";\r
        }\r
-       else print "<b>Error in Execute of SELECT</b></p>";\r
-       \r
        $val = $db->GetOne("select count(*) from ADOXYZ");\r
         if ($val == 50) print "<p>GetOne returns ok</p>";\r
         else print "<p><b>Fail: GetOne returns $val</b></p>";\r
@@ -1076,6 +1105,7 @@ END adodb;
                err('**** RSFilter failed');\r
                print_r($rs->fields);\r
        }\r
+       \r
        rs2html($rs);\r
                \r
        $db->debug=1;\r
@@ -1138,7 +1168,10 @@ END adodb;
                'firstname',    # row fields\r
                'lastname',             # column fields \r
                false,                  # join\r
-               'ID'                    # sum\r
+               'ID',                   # sum\r
+               'Sum ',                 # label for sum\r
+               'sum',                  # aggregate function\r
+               true\r
        );\r
        $rs = $db->Execute($sql);\r
        if ($rs) rs2html($rs);\r
@@ -1205,13 +1238,16 @@ END adodb;
                if ($ds != date("d m Y")) Err("Bad UserDate: ".$ds);\r
                else echo "Passed UserDate: $ds<p>";\r
        }\r
-       \r
-       $rs = $db->SelectLimit("select ".$db->sysTimeStamp." from adoxyz",1);\r
+       $db->debug=1;\r
+       if ($db->dataProvider == 'oci8') \r
+               $rs = $db->SelectLimit("select to_char(".$db->sysTimeStamp.",'YYYY-MM-DD HH24:MI:SS') from adoxyz",1);\r
+       else \r
+               $rs = $db->SelectLimit("select ".$db->sysTimeStamp." from adoxyz",1);\r
        $date = $rs->fields[0];\r
        if (!$date) Err("Bad sysTimeStamp");\r
        else {\r
                $ds = $db->UserTimeStamp($date,"H \\h\\r\\s-d m Y");\r
-               if ($ds != date("H \\h\\r\\s-d m Y")) Err("Bad UserTimeStamp: ".$ds);\r
+               if ($ds != date("H \\h\\r\\s-d m Y")) Err("Bad UserTimeStamp: ".$ds.", correct is ".date("H \\h\\r\\s-d m Y"));\r
                else echo "Passed UserTimeStamp: $ds<p>";\r
                \r
                $date = 100;\r
@@ -1408,6 +1444,6 @@ include('./testdatabases.inc.php');
 include_once('../adodb-time.inc.php');\r
 adodb_date_test();\r
 ?>\r
-<p><i>ADODB Database Library  (c) 2000-2003 John Lim. All rights reserved. Released under BSD and LGPL.</i></p>\r
+<p><i>ADODB Database Library  (c) 2000-2004 John Lim. All rights reserved. Released under BSD and LGPL.</i></p>\r
 </body>\r
 </html>\r
index 266fdd82591fbb2625e12aee79919bf668aeff1a..177aa8e94e9d81a4a3c3af3b619aca1b4375cb0e 100644 (file)
@@ -8,7 +8,7 @@
 <body>\r
 <?php\r
 /*\r
-  V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+  V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
index 122c712ca1f3a6c79882e522aa6512f1b05c1f6f..36754ed8558fe31a64eb22214a44cdad8547038e 100644 (file)
@@ -1,32 +1,44 @@
-<code>\r
 <?php\r
 /*\r
-  V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+  V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
   Set tabs to 8.\r
  */\r
-#\r
-# Code to test Move\r
-#\r
-include("../adodb.inc.php");   \r
 \r
-$c1 = &ADONewConnection('postgres');\r
-if (!$c1->PConnect("susetikus","tester","test","test")) \r
-       die("Cannot connect to database");\r
 \r
-# select * from last table in DB\r
-$rs = $c1->Execute("select * from adoxyz order by 1"); \r
+error_reporting(E_ALL);\r
+\r
+$path = dirname(__FILE__);\r
+\r
+include("$path/../adodb-exceptions.inc.php");\r
+include("$path/../adodb.inc.php");     \r
+\r
+try {\r
+$db = NewADOConnection("oci8");\r
+$db->Connect('','scott','natsoft');\r
+$db->debug=1;\r
+\r
+$cnt = $db->GetOne("select count(*) from adoxyz");\r
+$rs = $db->Execute("select * from adoxyz order by id");\r
 \r
 $i = 0;\r
-$max = $rs->RecordCount();\r
-if ($max == -1) "RecordCount returns -1<br>";\r
-while (!$rs->EOF and $i < $max) {\r
-       $rs->Move($i);\r
-       print_r( $rs->fields);\r
-       print '<BR>';\r
-       $i++;\r
+foreach($rs as $k => $v) {\r
+       $i += 1;\r
+       echo $k; adodb_pr($v);\r
+       flush();\r
 }\r
-?>\r
-</code>
\ No newline at end of file
+\r
+if ($i != $cnt) die("actual cnt is $i, cnt should be $cnt\n");\r
+\r
+\r
+\r
+$rs = $db->Execute("select bad from badder");\r
+\r
+} catch (exception $e) {\r
+       adodb_pr($e);\r
+       $e = adodb_backtrace($e->trace);\r
+}\r
+\r
+?>
\ No newline at end of file
index 7648ddd8bd701196e228b09d5506ed4a09235315..9a261b13a108dfb31232e42189d0bc6f86e669af 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
 \r
 /** \r
- * @version V4.01 23 Oct 2003 (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+ * @version V4.11 27 Jan 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
  * Released under both BSD license and Lesser GPL library license. \r
  * Whenever there is any discrepancy between the two licenses, \r
  * the BSD license will take precedence. \r
@@ -63,6 +63,7 @@ FROM ADOXYZ WHERE lastname=".$conn->qstr($record['lastname']);
 \r
 $rs = $conn->Execute($sql); // Execute the query and get the existing record to update\r
 if (!$rs) print "<p>No record found!</p>";\r
+\r
 $record = array(); // Initialize an array to hold the record data to update\r
 \r
 // Set the values for the fields in the record\r
index 3c1ef063db3d028a00ff7e17c39ae758cedbfac3..5308f2b1386493fed5da50c41b770698c49bbc3d 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
diff --git a/lib/adodb/tests/test_rs_array.php b/lib/adodb/tests/test_rs_array.php
new file mode 100644 (file)
index 0000000..99f1fa3
--- /dev/null
@@ -0,0 +1,47 @@
+<?php\r
+\r
+include_once('../adodb.inc.php');\r
+$rs = new ADORecordSet_array();\r
+\r
+$array = array(\r
+array ('Name', 'Age'),\r
+array ('John', '12'),\r
+array ('Jill', '8'),\r
+array ('Bill', '49')\r
+);\r
+\r
+$typearr = array('C','I');\r
+\r
+\r
+$rs->InitArray($array,$typearr);\r
+\r
+while (!$rs->EOF) {\r
+       print_r($rs->fields);echo "<br>";\r
+       $rs->MoveNext();\r
+}\r
+\r
+echo "<hr> 1 Seek<br>";\r
+$rs->Move(1);\r
+while (!$rs->EOF) {\r
+       print_r($rs->fields);echo "<br>";\r
+       $rs->MoveNext();\r
+}\r
+\r
+echo "<hr> 2 Seek<br>";\r
+$rs->Move(2);\r
+while (!$rs->EOF) {\r
+       print_r($rs->fields);echo "<br>";\r
+       $rs->MoveNext();\r
+}\r
+\r
+echo "<hr> 3 Seek<br>";\r
+$rs->Move(3);\r
+while (!$rs->EOF) {\r
+       print_r($rs->fields);echo "<br>";\r
+       $rs->MoveNext();\r
+}\r
+\r
+\r
+\r
+die();\r
+?>
\ No newline at end of file
index 7881e836fe825da128943109256f8c12874b6aed..c926a2a32ed371e1c5849ac88fdfe1ce2b3a0885 100644 (file)
@@ -2,7 +2,7 @@
 <body>\r
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
index 276332ab7f9560caf4f1878d23b6e0dc32dc7f85..7357e87de8ec00b7f667c4e58ab7ab61b9c39c62 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
   \r
 /*\r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
@@ -212,8 +212,7 @@ if (!empty($testdb2)) {
 }\r
 \r
 \r
-\r
-ADOLoadCode("odbc_mssql");\r
+ADOLoadCode('odbc_mssql');\r
 if (!empty($testmssql)) { // MS SQL Server via ODBC\r
        $db = ADONewConnection();\r
        \r
@@ -250,13 +249,16 @@ if (!empty($testmssql) && !empty($testado) ) { // ADO ACCESS MSSQL -- thru ODBC
 \r
 ADOLoadCode("mssqlpo");\r
 if (!empty($testmssql)) { // MS SQL Server -- the extension is buggy -- probably better to use ODBC\r
-       $db = ADONewConnection();\r
+       $db = ADONewConnection("mssqlpo");\r
        //$db->debug=1;\r
        print "<h1>Connecting $db->databaseType...</h1>";\r
        \r
-       $db->PConnect('tigress','adodb','natsoft','northwind');\r
-       \r
-       if (true or @$db->PConnect("mangrove", "sa", "natsoft", "ai")) {\r
+       $ok = $db->PConnect('tigress','adodb','natsoft','northwind');\r
+       //$rs = $db->Execute("exec sp_ddate");\r
+       //print_r($rs->fields);\r
+       //die();\r
+\r
+       if ($ok or @$db->PConnect("mangrove", "sa", "natsoft", "ai")) {\r
                AutoDetect_MSSQL_Date_Order($db);\r
        //      $db->Execute('drop table adoxyz');\r
                testdb($db,"create table ADOXYZ (id int, firstname char(24) null, lastname char(24) null,created datetime null)");\r
@@ -271,7 +273,7 @@ if (!empty($testmssql) && !empty($testado)) { // ADO ACCESS MSSQL with OLEDB pro
        //$db->debug=1;\r
        $myDSN="SERVER=tigress;DATABASE=northwind;Trusted_Connection=yes";\r
        //$myDSN='SERVER=(local)\NetSDK;DATABASE=northwind;';\r
-       if ($db->PConnect($myDSN, "sa", "natsoft", 'SQLOLEDB'))\r
+       if ($db->PConnect($myDSN, "adodb", "natsoft", 'SQLOLEDB'))\r
                testdb($db,"create table ADOXYZ (id int, firstname char(24), lastname char(24),created datetime)");\r
        else print "ERROR: MSSQL test 2 requires a MS SQL 7 on a server='mangrove', userid='sa', password='', database='ai'";\r
 \r
index f1f946349f890dbebdb9a7ccd67c145d90b90407..05554dd29d77cb4c5572bdc449fb75065af5e820 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /*\r
-       V4.01 23 Oct 2003 \r
+       V4.11 27 Jan 2004 \r
        \r
        Run multiple copies of this php script at the same time\r
        to test unique generation of id's in multiuser mode\r
index b259a69d4a99498f5f1501c076b561681cedb830..b54b850c32255fd1d551bcb6ba5e0542824ea9fd 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
 \r
 /** \r
- * @version V4.01 23 Oct 2003 (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+ * @version V4.11 27 Jan 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
  * Released under both BSD license and Lesser GPL library license. \r
  * Whenever there is any discrepancy between the two licenses, \r
  * the BSD license will take precedence. \r
index 39c049d00009bac26ca73e893f022768714f2c34..bf743acb2fea0963f549c8314e85a6a8564db9a4 100644 (file)
@@ -2,7 +2,7 @@
 <body>\r
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
index 51bb4624fa0bd8955949f1a12074b50e5612fc94..19afa3628d36975224842bf822b131c7742d0783 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
@@ -45,38 +45,65 @@ include('../tohtml.inc.php');
 \r
        error_reporting(E_ALL);\r
        $db = ADONewConnection('oci8');\r
-       $db->PConnect('','scott','tiger');\r
-       $db->debug = true;\r
+       $db->PConnect('','scott','natsoft');\r
+       $db->debug = 99;\r
 \r
 \r
+/*\r
+-- TEST PACKAGE\r
+CREATE OR REPLACE PACKAGE adodb AS\r
+TYPE TabType IS REF CURSOR RETURN tab%ROWTYPE;\r
+PROCEDURE open_tab (tabcursor IN OUT TabType,tablenames in varchar);\r
+PROCEDURE data_out(input IN varchar, output OUT varchar); \r
+END adodb;\r
+/\r
 \r
-       #---------------------------------------------------------------\r
-       # EXAMPLE 1\r
-       # explicitly use Parameter function\r
-       #---------------------------------------------------------------\r
-       $stmt = $db->Prepare("BEGIN adodb.open_tab(:RS,'%'); END;");\r
-       $db->Parameter($stmt, $cur, 'RS', false, -1, OCI_B_CURSOR);\r
-       $rs = $db->Execute($stmt);\r
+CREATE OR REPLACE PACKAGE BODY adodb AS\r
+PROCEDURE open_tab (tabcursor IN OUT TabType,tablenames in varchar) IS\r
+       BEGIN\r
+               OPEN tabcursor FOR SELECT * FROM tab where tname like tablenames;\r
+       END open_tab;\r
        \r
+PROCEDURE data_out(input IN varchar, output OUT varchar) IS\r
+       BEGIN\r
+               output := 'Cinta Hati '||input;\r
+       END;\r
+END adodb;\r
+/\r
+*/\r
+       $stmt = $db->Prepare("BEGIN adodb.open_tab(:RS,'A%'); END;");\r
+       $db->InParameter($stmt, $cur, 'RS', -1, OCI_B_CURSOR);\r
+       $rs = $db->Execute($stmt);\r
+\r
        if ($rs && !$rs->EOF) {\r
                print "Test 1 RowCount: ".$rs->RecordCount()."<p>";\r
        } else {\r
                print "<b>Error in using Cursor Variables 1</b><p>";\r
        }\r
        \r
-       #---------------------------------------------------------------\r
-       # EXAMPLE 2\r
-       # Equivalent of above example 1 using ExecuteCursor($sql,$rsname)\r
-       #---------------------------------------------------------------\r
-       $rs = $db->ExecuteCursor(\r
-               "BEGIN adodb.open_tab(:RS,'%'); END;", # pl/sql script\r
-               'RS');                                 # cursor name\r
-               \r
-       if ($rs && !$rs->EOF) {\r
-               print "Test 2 RowCount: ".$rs->RecordCount()."<p>";\r
-               rs2html($rs);\r
+       \r
+       print "<h4>Testing Stored Procedures for oci8</h4>";\r
+       \r
+       $stmt = $db->PrepareSP("BEGIN adodb.data_out(:a1, :a2); END;",true);\r
+       $a1 = 'Malaysia';\r
+       //$a2 = ''; # a2 doesn't even need to be defined!\r
+       $db->InParameter($stmt,$a1,'a1');\r
+       $db->OutParameter($stmt,$a2,'a2');\r
+       $rs = $db->Execute($stmt);\r
+       if ($rs) {\r
+               if ($a2 !== 'Cinta Hati Malaysia') print "<b>Stored Procedure Error: a2 = $a2</b><p>";\r
+               else echo  "OK: a2=$a2<p>";\r
        } else {\r
-               print "<b>Error in using Cursor Variables 2</b><p>";\r
+               print "<b>Error in using Stored Procedure IN/Out Variables</b><p>";\r
        }\r
+       \r
+       \r
+       $tname = 'A%';\r
+       \r
+       $stmt = $db->PrepareSP('select * from tab where tname like :tablename');\r
+       $db->Parameter($stmt,$tname,'tablename');\r
+       $rs = $db->Execute($stmt);\r
+       rs2html($rs);\r
+               \r
                \r
 ?>
\ No newline at end of file
index b0bbcfd2fc7e783502becc81474da1c463eae1c1..3cf29aaf7d3a0078e063226745cb82b4c179ba55 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
index 48d37934131e33630b61494d8ea9929581030b9e..d3bd9d6469f40885273a8237d903c609fee144b2 100644 (file)
@@ -1,6 +1,6 @@
 <?php\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
index 42d659270647ac3227cae1119a1c99d977aa23c5..597987c18eed02d5d3bab44a937060ac44745236 100644 (file)
@@ -1,6 +1,7 @@
 <?php\r
+\r
 /* \r
-V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence. \r
@@ -16,38 +17,50 @@ function NotifyExpire($ref,$key)
 \r
 //-------------------------------------------------------------------\r
        \r
+       \r
+#### CONNECTION\r
        $ADODB_SESSION_DRIVER='oci8';\r
        $ADODB_SESSION_CONNECT='';\r
        $ADODB_SESSION_USER ='scott';\r
        $ADODB_SESSION_PWD ='natsoft';\r
        $ADODB_SESSION_DB ='';\r
+       \r
+       \r
+### TURN DEBUGGING ON\r
+       $ADODB_SESS_DEBUG = true;\r
 \r
+       \r
+#### SETUP NOTIFICATION\r
        $USER = 'JLIM'.rand();\r
        $ADODB_SESSION_EXPIRE_NOTIFY = array('USER','NotifyExpire');\r
+\r
        \r
-       GLOBAL $HTTP_SESSION_VARS;\r
+#### INIT\r
        ob_start();\r
        error_reporting(E_ALL);\r
-       \r
-       $ADODB_SESS_DEBUG = true;\r
-       include('../adodb-session.php');\r
+       include('../session/adodb-cryptsession.php');\r
        session_start();\r
-       \r
-       print "<h3>PHP ".PHP_VERSION."</h3>";\r
-       \r
+\r
+\r
+### SETUP SESSION VARIABLES \r
        $HTTP_SESSION_VARS['MONKEY'] = array('1','abc',44.41);\r
        if (!isset($HTTP_GET_VARS['nochange'])) @$HTTP_SESSION_VARS['AVAR'] += 1;\r
+\r
        \r
+### START DISPLAY\r
+       print "<h3>PHP ".PHP_VERSION."</h3>";\r
        print "<p><b>\$HTTP_SESSION_VARS['AVAR']={$HTTP_SESSION_VARS['AVAR']}</b></p>";\r
        \r
+       print "<hr> <b>Cookies</b>: ";\r
+       print_r($HTTP_COOKIE_VARS);\r
+       \r
+### RANDOMLY PERFORM Garbage Collection\r
        if (rand() % 10 == 0) {\r
        \r
-               print "<p>GC</p>";\r
+               print "<hr><p><b>Garbage Collection</b></p>";\r
                adodb_sess_gc(10);\r
                \r
                print "<p>Random session destroy</p>";\r
                session_destroy();\r
        }\r
-       print "<hr>";\r
-       print_r($HTTP_COOKIE_VARS);\r
 ?>
\ No newline at end of file
index a3b743ca1f4127e535a74206322213777f625c20..e20db41ed29513a2a0e92f9750fec6a6c27b408d 100644 (file)
@@ -1,65 +1,65 @@
-<?php
-error_reporting(E_ALL);
-ini_set('mssql.datetimeconvert',0); 
-
-function tmssql()
-{
-       print "<h3>mssql</h3>";
-       $db = mssql_connect('JAGUAR\vsdotnet','adodb','natsoft') or die('No Connection');
-       mssql_select_db('northwind',$db);
-       
-       $rs = mssql_query('select getdate() as date',$db);
-       $o = mssql_fetch_row($rs);
-       print_r($o);
-       mssql_free_result($rs);
-       
-       print "<p>Delete</p>"; flush();
-       $rs2 = mssql_query('delete from adoxyz',$db);
-       $p = mssql_num_rows($rs2);
-       mssql_free_result($rs2);
-
-}
-
-function tpear()
-{
-include_once('DB.php');
-
-       print "<h3>PEAR</h3>";
-       $username = 'adodb';
-       $password = 'natsoft';
-       $hostname = 'JAGUAR\vsdotnet';
-       $databasename = 'northwind';
-       
-       $dsn = "mssql://$username:$password@$hostname/$databasename";
-       $conn = &DB::connect($dsn);
-       print "date=".$conn->GetOne('select getdate()')."<br>";
-       @$conn->query('create table tester (id integer)');
-       print "<p>Delete</p>"; flush();
-       $rs = $conn->query('delete from tester');
-       print "date=".$conn->GetOne('select getdate()')."<br>";
-}
-
-function tadodb()
-{
-include_once('../adodb.inc.php');
-
-       print "<h3>ADOdb</h3>";
-       $conn = NewADOConnection('mssql');
-       $conn->Connect('JAGUAR\vsdotnet','adodb','natsoft','northwind');
-//     $conn->debug=1;
-       print "date=".$conn->GetOne('select getdate()')."<br>";
-       $conn->Execute('create table tester (id integer)');
-       print "<p>Delete</p>"; flush();
-       $rs = $conn->Execute('delete from tester');
-       print "date=".$conn->GetOne('select getdate()')."<br>";
-}
-?>
-<a href=tmssql.php?do=tmssql>mssql</a>
-<a href=tmssql.php?do=tpear>pear</a>
-<a href=tmssql.php?do=tadodb>adodb</a>
-<?php
-if (!empty($_GET['do'])) {
-       $do = $_GET['do'];
-       $do();
-}
+<?php\r
+error_reporting(E_ALL);\r
+ini_set('mssql.datetimeconvert',0); \r
+\r
+function tmssql()\r
+{\r
+       print "<h3>mssql</h3>";\r
+       $db = mssql_connect('JAGUAR\vsdotnet','adodb','natsoft') or die('No Connection');\r
+       mssql_select_db('northwind',$db);\r
+       \r
+       $rs = mssql_query('select getdate() as date',$db);\r
+       $o = mssql_fetch_row($rs);\r
+       print_r($o);\r
+       mssql_free_result($rs);\r
+       \r
+       print "<p>Delete</p>"; flush();\r
+       $rs2 = mssql_query('delete from adoxyz',$db);\r
+       $p = mssql_num_rows($rs2);\r
+       mssql_free_result($rs2);\r
+\r
+}\r
+\r
+function tpear()\r
+{\r
+include_once('DB.php');\r
+\r
+       print "<h3>PEAR</h3>";\r
+       $username = 'adodb';\r
+       $password = 'natsoft';\r
+       $hostname = 'JAGUAR\vsdotnet';\r
+       $databasename = 'northwind';\r
+       \r
+       $dsn = "mssql://$username:$password@$hostname/$databasename";\r
+       $conn = &DB::connect($dsn);\r
+       print "date=".$conn->GetOne('select getdate()')."<br>";\r
+       @$conn->query('create table tester (id integer)');\r
+       print "<p>Delete</p>"; flush();\r
+       $rs = $conn->query('delete from tester');\r
+       print "date=".$conn->GetOne('select getdate()')."<br>";\r
+}\r
+\r
+function tadodb()\r
+{\r
+include_once('../adodb.inc.php');\r
+\r
+       print "<h3>ADOdb</h3>";\r
+       $conn = NewADOConnection('mssql');\r
+       $conn->Connect('JAGUAR\vsdotnet','adodb','natsoft','northwind');\r
+//     $conn->debug=1;\r
+       print "date=".$conn->GetOne('select getdate()')."<br>";\r
+       $conn->Execute('create table tester (id integer)');\r
+       print "<p>Delete</p>"; flush();\r
+       $rs = $conn->Execute('delete from tester');\r
+       print "date=".$conn->GetOne('select getdate()')."<br>";\r
+}\r
+?>\r
+<a href=tmssql.php?do=tmssql>mssql</a>\r
+<a href=tmssql.php?do=tpear>pear</a>\r
+<a href=tmssql.php?do=tadodb>adodb</a>\r
+<?php\r
+if (!empty($_GET['do'])) {\r
+       $do = $_GET['do'];\r
+       $do();\r
+}\r
 ?>
\ No newline at end of file
index e0dd414914f72131750af24cd1ea32fa2e28c1f6..fc438fb0ffdfa80586d0faffb2c49d52caf4c3ee 100644 (file)
@@ -8,7 +8,9 @@
 <body bgcolor=white>\r
 <table width=100% border=0><tr><td><h2>Tips on Writing Portable SQL &nbsp;</h2></td><td>\r
  <div align=right><img src="cute_icons_for_site/adodb.gif"></div></td></tr></table>\r
\r
+  <p>Updated 18 Sep 2003. Added Portable Native SQL section.\r
+<p>\r
+\r
  If you are writing an application that is used in multiple environments and \r
   operating systems, you need to plan to support multiple databases. This article \r
   is based on my experiences with multiple database systems, stretching from 4th \r
@@ -166,17 +168,18 @@ the correct placeholder (available since ADOdb 3.92):
 $stmt = $DB-&gt;Prepare($sql);\r
 $stmt = $DB-&gt;Execute($stmt,array('one','two'));\r
 </font></pre>\r
+<a name="native"></a>\r
 <h2>Portable Native SQL</h2>\r
 <p>ADOdb provides the following functions for portably generating SQL functions \r
   as strings to be merged into your SQL statements (some are only available since \r
   ADOdb 3.92): </p>\r
-<table width="75%" border="1">\r
+<table width="75%" border="1" align=center>\r
   <tr> \r
-    <td><b>Function</b></td>\r
+    <td width=30%><b>Function</b></td>\r
     <td><b>Description</b></td>\r
   </tr>\r
   <tr> \r
-    <td height="63">DBDate($date)</td>\r
+    <td>DBDate($date)</td>\r
     <td>Pass in a UNIX timestamp or ISO date and it will convert it to a date \r
       string formatted for INSERT/UPDATE</td>\r
   </tr>\r
@@ -207,6 +210,26 @@ $stmt = $DB-&gt;Execute($stmt,array('one','two'));
     <td>Param($name)</td>\r
     <td>Generates bind placeholders, using ? or named conventions as appropriate.</td>\r
   </tr>\r
+  <tr><td>$db->sysDate</td><td>Property that holds the SQL function that returns today's date</td>\r
+</tr>\r
+<tr><td>$db->sysTimeStamp</td><td>Property that holds the SQL function that returns the current\r
+timestamp (date+time).\r
+</td>\r
+</tr>\r
+<tr>\r
+<td>$db->concat_operator</td><td>Property that holds the concatenation operator\r
+</td>\r
+</tr>\r
+<tr><td>$db->length</td><td>Property that holds the name of the SQL strlen function.\r
+</td></tr>\r
+\r
+<tr><td>$db->upperCase</td><td>Property that holds the name of the SQL strtoupper function.\r
+</td></tr>\r
+<tr><td>$db->random</td><td>Property that holds the SQL to generate a random number between 0.00 and 1.00.\r
+</td>\r
+</tr>\r
+<tr><td>$db->substr</td><td>Property that holds the name of the SQL substring function.\r
+</td></tr>\r
 </table>\r
 <p>&nbsp; </p>\r
 <h2>DDL and Tuning</h2>\r
@@ -269,6 +292,9 @@ $conn->UpdateBlob('blobtable','blobcol',$blobvalue,'id=1');
   ambiguities when you use the ANY and EXISTS operators. However if your database \r
   has significant amounts of missing or unknown data, using nulls might be a good \r
   idea. \r
+  <p>\r
+  ADOdb also supports a portable <a href=http://phplens.com/adodb/reference.functions.concat.html#ifnull>IfNull</a> function, so you can define what to display\r
+  if the field contains a null.\r
 <h3><b>Stored Procedures</b></h3>\r
 <p>Stored procedures are another problem area. Some databases allow recordsets \r
   to be returned in a stored procedure (Microsoft SQL Server and Sybase), and \r
index 05fd2036f7e988fef02f5b21d7a5f8d22af1be70..c5a63fc54e87801e4d878e09f690b03c678cfdd1 100644 (file)
@@ -1,7 +1,7 @@
 <?php\r
 \r
 /** \r
- * @version V4.01 23 Oct 2003 (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+ * @version V4.11 27 Jan 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
  * Released under both BSD license and Lesser GPL library license. \r
  * Whenever there is any discrepancy between the two licenses, \r
  * the BSD license will take precedence. \r
@@ -72,7 +72,8 @@ function _adodb_export(&$rs,$sep,$sepreplace,$fp=false,$addtitles=true,$quote =
        \r
        if ($addtitles) {\r
                $fieldTypes = $rs->FieldTypesArray();\r
-               foreach($fieldTypes as $o) {\r
+               reset($fieldTypes);\r
+               while(list(,$o) = each($fieldTypes)) {\r
                        \r
                        $v = $o->name;\r
                        if ($escquote) $v = str_replace($quote,$escquotequote,$v);\r
index cf08639b5fe23f34d6fa92994eefef3b1db70e4f..d42c7d8993dbed1cbb9868c592b185457cf91995 100644 (file)
@@ -1,6 +1,6 @@
 <?php \r
 /*\r
-  V4.01 23 Oct 2003  (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.\r
+  V4.11 27 Jan 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.\r
   Released under both BSD license and Lesser GPL library license. \r
   Whenever there is any discrepancy between the two licenses, \r
   the BSD license will take precedence.\r
@@ -49,7 +49,7 @@ GLOBAL $gSQLMaxRows,$gSQLBlockRows;
        //else $docnt = true;\r
        $typearr = array();\r
        $ncols = $rs->FieldCount();\r
-       $hdr = "<TABLE COLS=$ncols $ztabhtml>\n\n";\r
+       $hdr = "<TABLE COLS=$ncols $ztabhtml><tr>\n\n";\r
        for ($i=0; $i < $ncols; $i++) { \r
                $field = $rs->FetchField($i);\r
                if ($zheaderarray) $fname = $zheaderarray[$i];\r
@@ -60,7 +60,7 @@ GLOBAL $gSQLMaxRows,$gSQLBlockRows;
                if (strlen($fname)==0) $fname = '&nbsp;';\r
                $hdr .= "<TH>$fname</TH>";\r
        }\r
-\r
+       $hdr .= "\n</tr>";\r
        if ($echo) print $hdr."\n\n";\r
        else $html = $hdr;\r
        \r
index 3f2261e62de9808f5ac794d12c6ab860a1b1dee7..b060a98513b9192bf12c564c989021419a4b4e6e 100644 (file)
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-
-<html>
-<head>
-       <title>Tutorial: Moving from MySQL to ADODB</title>
-</head>
-
-<body bgcolor=white>
-<h1>Tutorial: Moving from MySQL to ADODB</h1>
-
-<pre>          You say eether and I say eyether, 
-               You say neether and I say nyther; 
-               Eether, eyether, neether, nyther - 
-               Let's call the whole thing off ! 
-<br>
-               You like potato and I like po-tah-to, 
-               You like tomato and I like to-mah-to; 
-               Potato, po-tah-to, tomato, to-mah-to - 
-               Let's call the whole thing off ! 
-</pre>
-<p>I love this song, especially the version with Louis Armstrong and Ella singing 
-  duet. It is all about how hard it is for two people in love to be compatible 
-  with each other. It's about compromise and finding a common ground, and that's 
-  what this article is all about. 
-<p>PHP is all about creating dynamic web-sites with the least fuss and the most 
-  fun. To create these websites we need to use databases to retrieve login information, 
-  to splash dynamic news onto the web page and store forum postings. So let's 
-  say we were using the popular MySQL database for this. Your company has done 
-  such a fantastic job that the Web site is more popular than your wildest dreams. 
-  You find that MySQL cannot scale to handle the workload; time to switch databases. 
-<p> Unfortunately in PHP every database is accessed slightly differently. To connect 
-  to MySQL, you would use <i>mysql_connect()</i>; when you decide to upgrade to 
-  Oracle or Microsoft SQL Server, you would use <i>ocilogon() </i>or <i>mssql_connect()</i> 
-  respectively. What is worse is that the parameters you use for the different 
-  connect functions are different also.. One database says po-tato, the other 
-  database says pota-to. Oh-oh. 
-<h3>Let's NOT call the whole thing off</h3>
-<p>A database wrapper library such as ADODB comes in handy when you need to ensure portability. It provides 
-  you with a common API to communicate with any supported database so you don't have to call things off. <p>
-
-<p>ADODB stands for Active Data Objects DataBase (sorry computer guys are sometimes 
-  not very original). ADODB currently supports MySQL, PostgreSQL, Oracle, Interbase, 
-  Microsoft SQL Server, Access, FoxPro, Sybase, ODBC and ADO. You can download 
-  ADODB from <a href=http://php.weblogs.com/adodb></a><a href="http://php.weblogs.com/adodb">http://php.weblogs.com/adodb</a>.
-<h3>MySQL Example</h3>
-<p>The most common database used with PHP is MySQL, so I guess you should be familiar 
-  with the following code. It connects to a MySQL server at <i>localhost</i>, 
-  database <i>mydb</i>, and executes an SQL select statement. The results are 
-  printed, one line per row. 
-<pre><font color="#666600">$db = <b>mysql_connect</b>(&quot;localhost&quot;, &quot;root&quot;, &quot;password&quot;);
-<b>mysql_select_db</b>(&quot;mydb&quot;,$db);</font>
-<font color="#660000">$result = <b>mysql_query</b>(&quot;SELECT * FROM employees&quot;,$db)</font><code><font color="#663300">;
-if ($result === false) die(&quot;failed&quot;);</font></code> 
-<font color="#006666"><b>while</b> ($fields =<b> mysql_fetch_row</b>($result)) &#123;
- <b>for</b> ($i=0, $max=sizeof($fields); $i &lt; $max; $i++) &#123;
-               <b>print</b> $fields[$i].' ';
- &#125;
- <b>print</b> &quot;&lt;br&gt;\n&quot;;
-&#125;</font> 
-</pre>
-<p>The above code has been color-coded by section. The first section is the connection 
-  phase. The second is the execution of the SQL, and the last section is displaying 
-  the fields. The <i>while</i> loop scans the rows of the result, while the <i>for</i> 
-  loop scans the fields in one row.</p>
-<p>Here is the equivalent code in ADODB</p>
-<pre><b><font color="#666600"> include(&quot;adodb.inc.php&quot;);</font></b><font color="#666600">
- $db = <b>NewADOConnection</b>('mysql');
- $db-&gt;<b>Connect</b>(&quot;localhost&quot;, &quot;root&quot;, &quot;password&quot;, &quot;mydb&quot;);</font>
- <font color="#663300">$result = $db-&gt;<b>Execute</b>(&quot;SELECT * FROM employees&quot;);
- </font><font color="#663300"></font><code><font color="#663300">if ($result === false) die(&quot;failed&quot;)</font></code><code><font color="#663300">;</font></code>  
- <font color="#006666"><b>while</b> (!$result-&gt;EOF) &#123;
-       <b>for</b> ($i=0, $max=$result-&gt;<b>FieldCount</b>(); $i &lt; $max; $i++)
-                  <b>print</b> $result-&gt;fields[$i].' ';
-       $result-&gt;<b>MoveNext</b>();
-       <b>print</b> &quot;&lt;br&gt;\n&quot;;
- &#125;</font> </pre>
-<p></p>
-<p>Now porting to Oracle is as simple as changing the second line to <code>NewADOConnection('oracle')</code>. 
-  Let's walk through the code...</p>
-<h3>Connecting to the Database</h3>
-<p></p>
-<pre><b><font color="#666600">include(&quot;adodb.inc.php&quot;);</font></b><font color="#666600">
-$db = <b>NewADOConnection</b>('mysql');
-$db-&gt;<b>Connect</b>(&quot;localhost&quot;, &quot;root&quot;, &quot;password&quot;, &quot;mydb&quot;);</font></pre>
-<p>The connection code is a bit more sophisticated than MySQL's because our needs 
-  are more sophisticated. In ADODB, we use an object-oriented approach to managing 
-  the complexity of handling multiple databases. We have different classes to 
-  handle different databases. If you aren't familiar with object-oriented programing, 
-  don't worry -- the complexity is all hidden away in the<code> NewADOConnection()</code> 
-  function.</p>
-<p>To conserve memory, we only load the PHP code specific to the database you 
-  are connecting to. We do this by calling <code>NewADOConnection(databasedriver)</code>. 
-  Legal database drivers include <i>mysql, mssql, oracle, oci8, postgres, sybase, 
-  vfp, access, ibase </i>and many others.</p>
-<p>Then we create a new instance of the connection class by calling <code>NewADOConnection()</code>. 
-  Finally we connect to the database using <code>$db-&gt;Connect(). </code></p>
-<h3>Executing the SQL</h3>
-<p><code><font color="#663300">$result = $db-&gt;<b>Execute</b>(&quot;SELECT * 
-  FROM employees&quot;);<br>
-  if ($result === false) die(&quot;failed&quot;)</font></code><code><font color="#663300">;</font></code> 
-  <br>
-</p>
-<p>Sending the SQL statement to the server is straight forward. Execute() will 
-  return a recordset object on successful execution. You should check $result 
-  as we do above.
-<p>An issue that confuses beginners is the fact that we have two types of objects 
-  in ADODB, the connection object and the recordset object. When do we use each?
-<p>The connection object ($db) is responsible for connecting to the database, 
-  formatting your SQL and querying the database server. The recordset object ($result) 
-  is responsible for retrieving the results and formatting the reply as text or 
-  as an array.
-<p>The only thing I need to add is that ADODB provides several helper functions 
-  for making INSERT and UPDATE statements easier, which we will cover in the Advanced 
-  section. 
-<h3>Retrieving the Data<br>
-</h3>
-<pre><font color="#006666"><b>while</b> (!$result-&gt;EOF) &#123;
-   <b>for</b> ($i=0, $max=$result-&gt;<b>FieldCount</b>(); $i &lt; $max; $i++)
-          <b>print</b> $result-&gt;fields[$i].' ';
-   $result-&gt;<b>MoveNext</b>();
-   <b>print</b> &quot;&lt;br&gt;\n&quot;;
-&#125;</font></pre>
-<p>The paradigm for getting the data is that it's like reading a file. For every 
-  line, we check first whether we have reached the end-of-file (EOF). While not 
-  end-of-file, loop through each field in the row. Then move to the next line 
-  (MoveNext) and repeat. 
-<p>The <code>$result-&gt;fields[]</code> array is generated by the PHP database 
-  extension. Some database extensions do not index the array by field name. 
-  To force indexing by name - that is associative arrays - 
-  use the $ADODB_FETCH_MODE global variable. 
-<pre>
-       $<b>ADODB_FETCH_MODE</b> = ADODB_FETCH_NUM;
-       $rs1 = $db->Execute('select * from table');
-       $<b>ADODB_FETCH_MODE</b> = ADODB_FETCH_ASSOC;
-       $rs2 = $db->Execute('select * from table');
-       print_r($rs1->fields); // shows <i>array([0]=>'v0',[1] =>'v1')</i>
-       print_r($rs2->fields); // shows <i>array(['col1']=>'v0',['col2'] =>'v1')</i>
-</pre>
-<p>
-As you can see in the above example, both recordsets store and use different fetch modes
-based on the $ADODB_FETCH_MODE setting when the recordset was created by Execute().</p>
-<h2>ADOConnection<a name="ADOConnection"></a></h2>
-<p>Object that performs the connection to the database, executes SQL statements 
-  and has a set of utility functions for standardising the format of SQL statements 
-  for issues such as concatenation and date formats.</p>
-  
-<h3>Other Useful Functions</h3>
-<p><code>$recordset-&gt;Move($pos)</code> scrolls to that particular row. ADODB supports forward 
-  scrolling for all databases. Some databases will not support backwards scrolling. 
-  This is normally not a problem as you can always cache records to simulate backwards 
-  scrolling. 
-<p><code>$recordset-&gt;RecordCount()</code> returns the number of records accessed by the 
-  SQL statement. Some databases will return -1 because it is not supported. 
-<p><code>$recordset-&gt;GetArray()</code> returns the result as an array. 
-<p><code>rs2html($recordset)</code> is a function that is generates a HTML table based on the 
-  $recordset passed to it. An example with the relevant lines in bold:
-<pre>   include('adodb.inc.php'); 
-   <b>include('tohtml.inc.php');</b> /* includes the rs2html function */
-   $conn = &amp;ADONewConnection('mysql'); 
-   $conn-&gt;PConnect('localhost','userid','password','database');
-   $rs = $conn-&gt;Execute('select * from table');
-  <b> rs2html($rs)</b>; /* recordset to html table */ </pre>
-<p>There are many other helper functions that are listed in the documentation available at <a href="http://php.weblogs.com/adodb_manual"></a><a href="http://php.weblogs.com/adodb_manual">http://php.weblogs.com/adodb_manual</a>. 
-<h2>Advanced Material</h2>
-<h3>Inserts and Updates </h3>
-<p>Let's say you want to insert the following data into a database. 
-<p><b>ID</b> = 3<br>
-  <b>TheDate</b>=mktime(0,0,0,8,31,2001) /* 31st August 2001 */<br>
-  <b>Note</b>= sugar why don't we call it off 
-<p>When you move to another database, your insert might no longer work.</p>
-<p>The first problem is that each database has a different default date format. 
-  MySQL expects YYYY-MM-DD format, while other databases have different defaults. 
-  ADODB has a function called DBDate() that addresses this issue by converting 
-  converting the date to the correct format.</p>
-<p>The next problem is that the <b>don't</b> in the Note needs to be quoted. In 
-  MySQL, we use <b>don\'t</b> but in some other databases (Sybase, Access, Microsoft 
-  SQL Server) we use <b>don''t. </b>The qstr() function addresses this issue.</p>
-<p>So how do we use the functions? Like this:</p>
-<pre>$sql = &quot;INSERT INTO table (id, thedate,note) values (&quot; 
-   . $<b>ID</b> . ','
-   . $db-&gt;DBDate($<b>TheDate</b>) .','
-   . $db-&gt;qstr($<b>Note</b>).&quot;)&quot;;
-$db-&gt;Execute($sql);</pre>
-<p>ADODB also supports <code>$connection-&gt;Affected_Rows()</code> (returns the 
-  number of rows affected by last update or delete) and <code>$recordset-&gt;Insert_ID()</code> 
-  (returns last autoincrement number generated by an insert statement). Be forewarned 
-  that not all databases support the two functions.<br>
-</p>
-<h3>MetaTypes</h3>
-<p>You can find out more information about each of the fields (I use the words 
-  fields and columns interchangebly) you are selecting by calling the recordset 
-  method <code>FetchField($fieldoffset)</code>. This will return an object with 
-  3 properties: name, type and max_length. 
-<pre>For example:</pre>
-<pre>$recordset = $conn-&gt;Execute(&quot;select adate from table&quot;);<br>$f0 = $recordset-&gt;FetchField(0);
-</pre>
-<p>Then <code>$f0-&gt;name</code> will hold <i>'adata'</i>, <code>$f0-&gt;type</code> 
-  will be set to '<i>date'</i>. If the max_length is unknown, it will be set to 
-  -1. 
-<p>One problem with handling different databases is that each database often calls 
-  the same type by a different name. For example a <i>timestamp</i> type is called 
-  <i>datetime</i> in one database and <i>time</i> in another. So ADODB has a special 
-  <code>MetaType($type, $max_length)</code> function that standardises the types 
-  to the following: 
-<p>C: character and varchar types<br>
-  X: text or long character (eg. more than 255 bytes wide).<br>
-  B: blob or binary image<br>
-  D: date<br>
-  T: timestamp<br>
-  L: logical (boolean)<br>
-  I: integer<br>
-  N: numeric (float, double, money) 
-<p>In the above date example, 
-<p><code>$recordset = $conn-&gt;Execute(&quot;select adate from table&quot;);<br>
-  $f0 = $recordset-&gt;FetchField(0);<br>
-  $type = $recordset-&gt;MetaType($f0-&gt;type, $f0-&gt;max_length);<br>
-  print $type; /* should print 'D'</code> */
-<p> 
-<p><b>Select Limit and Top Support</b> 
-<p>ADODB has a function called $connection->SelectLimit($sql,$nrows,$offset) that allows
-you to retrieve a subset of the recordset. This will take advantage of native
-SELECT TOP on Microsoft products and SELECT ... LIMIT with PostgreSQL and MySQL, and
-emulated if the database does not support it.
-<p><b>Caching Support</b> 
-<p>ADODB allows you to cache recordsets in your file system, and only requery the database
-server after a certain timeout period with $connection->CacheExecute($secs2cache,$sql) and 
-$connection->CacheSelectLimit($secs2cache,$sql,$nrows,$offset).
-<p><b>PHP4 Session Handler Support</b> 
-<p>ADODB also supports PHP4 session handlers. You can store your session variables 
-  in a database for true scalability using ADODB. For further information, visit 
-  <a href="http://php.weblogs.com/adodb-sessions"></a><a href="http://php.weblogs.com/adodb-sessions">http://php.weblogs.com/adodb-sessions</a>
-<h3>Commercial Use Encouraged</h3>
-<p>If you plan to write commercial PHP applications that you want to resell, you should consider ADODB. It has been released using the lesser GPL, which means you can legally include it in commercial applications, while keeping your code proprietary. Commercial use of ADODB is strongly encouraged! We are using it internally for this reason.<p>
-
-<h2>Conclusion</h2>
-<p>As a thank you for finishing this article, here are the complete lyrics for 
-  <i>let's call the whole thing off</i>.<br>
-  <br>
-<pre>
-   Refrain 
-<br>
-               You say eether and I say eyether, 
-               You say neether and I say nyther; 
-               Eether, eyether, neether, nyther - 
-               Let's call the whole thing off ! 
-<br>
-               You like potato and I like po-tah-to, 
-               You like tomato and I like to-mah-to; 
-               Potato, po-tah-to, tomato, to-mah-to - 
-               Let's call the whole thing off ! 
-<br>
-But oh, if we call the whole thing off, then we must part. 
-And oh, if we ever part, then that might break my heart. 
-<br>
-               So, if you like pajamas and I like pa-jah-mas, 
-               I'll wear pajamas and give up pa-jah-mas. 
-               For we know we 
-               Need each other, so we 
-               Better call the calling off off. 
-               Let's call the whole thing off ! 
-<br>
-   Second Refrain 
-<br>
-               You say laughter and I say lawfter, 
-               You say after and I say awfter; 
-               Laughter, lawfter, after, awfter - 
-               Let's call the whole thing off ! 
-<br>
-               You like vanilla and I like vanella, 
-               You, sa's'parilla and I sa's'parella; 
-               Vanilla, vanella, choc'late, strawb'ry - 
-               Let's call the whole thing off ! 
-<br>
-But oh, if we call the whole thing off, then we must part. 
-And oh, if we ever part, then that might break my heart. 
-<br>
-               So, if you go for oysters and I go for ersters, 
-               I'll order oysters and cancel the ersters. 
-               For we know we 
-               Need each other, so we 
-               Better call the calling off off. 
-               Let's call the whole thing off ! 
-  </pre>
-<p><font size=2>Song and lyrics by George and Ira Gershwin, introduced by Fred Astaire and Ginger Rogers
-in the film "Shall We Dance?"  </font><p>
-<p>
-(c)2001-2002 John Lim.
-
-</body>
-</html>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">\r
+\r
+<html>\r
+<head>\r
+       <title>Tutorial: Moving from MySQL to ADODB</title>\r
+</head>\r
+\r
+<body bgcolor=white>\r
+<h1>Tutorial: Moving from MySQL to ADODB</h1>\r
+\r
+<pre>          You say eether and I say eyether, \r
+               You say neether and I say nyther; \r
+               Eether, eyether, neether, nyther - \r
+               Let's call the whole thing off ! \r
+<br>\r
+               You like potato and I like po-tah-to, \r
+               You like tomato and I like to-mah-to; \r
+               Potato, po-tah-to, tomato, to-mah-to - \r
+               Let's call the whole thing off ! \r
+</pre>\r
+<p>I love this song, especially the version with Louis Armstrong and Ella singing \r
+  duet. It is all about how hard it is for two people in love to be compatible \r
+  with each other. It's about compromise and finding a common ground, and that's \r
+  what this article is all about. \r
+<p>PHP is all about creating dynamic web-sites with the least fuss and the most \r
+  fun. To create these websites we need to use databases to retrieve login information, \r
+  to splash dynamic news onto the web page and store forum postings. So let's \r
+  say we were using the popular MySQL database for this. Your company has done \r
+  such a fantastic job that the Web site is more popular than your wildest dreams. \r
+  You find that MySQL cannot scale to handle the workload; time to switch databases. \r
+<p> Unfortunately in PHP every database is accessed slightly differently. To connect \r
+  to MySQL, you would use <i>mysql_connect()</i>; when you decide to upgrade to \r
+  Oracle or Microsoft SQL Server, you would use <i>ocilogon() </i>or <i>mssql_connect()</i> \r
+  respectively. What is worse is that the parameters you use for the different \r
+  connect functions are different also.. One database says po-tato, the other \r
+  database says pota-to. Oh-oh. \r
+<h3>Let's NOT call the whole thing off</h3>\r
+<p>A database wrapper library such as ADODB comes in handy when you need to ensure portability. It provides \r
+  you with a common API to communicate with any supported database so you don't have to call things off. <p>\r
+\r
+<p>ADODB stands for Active Data Objects DataBase (sorry computer guys are sometimes \r
+  not very original). ADODB currently supports MySQL, PostgreSQL, Oracle, Interbase, \r
+  Microsoft SQL Server, Access, FoxPro, Sybase, ODBC and ADO. You can download \r
+  ADODB from <a href=http://php.weblogs.com/adodb></a><a href="http://php.weblogs.com/adodb">http://php.weblogs.com/adodb</a>.\r
+<h3>MySQL Example</h3>\r
+<p>The most common database used with PHP is MySQL, so I guess you should be familiar \r
+  with the following code. It connects to a MySQL server at <i>localhost</i>, \r
+  database <i>mydb</i>, and executes an SQL select statement. The results are \r
+  printed, one line per row. \r
+<pre><font color="#666600">$db = <b>mysql_connect</b>(&quot;localhost&quot;, &quot;root&quot;, &quot;password&quot;);\r
+<b>mysql_select_db</b>(&quot;mydb&quot;,$db);</font>\r
+<font color="#660000">$result = <b>mysql_query</b>(&quot;SELECT * FROM employees&quot;,$db)</font><code><font color="#663300">;\r
+if ($result === false) die(&quot;failed&quot;);</font></code> \r
+<font color="#006666"><b>while</b> ($fields =<b> mysql_fetch_row</b>($result)) &#123;\r
+ <b>for</b> ($i=0, $max=sizeof($fields); $i &lt; $max; $i++) &#123;\r
+               <b>print</b> $fields[$i].' ';\r
+ &#125;\r
+ <b>print</b> &quot;&lt;br&gt;\n&quot;;\r
+&#125;</font> \r
+</pre>\r
+<p>The above code has been color-coded by section. The first section is the connection \r
+  phase. The second is the execution of the SQL, and the last section is displaying \r
+  the fields. The <i>while</i> loop scans the rows of the result, while the <i>for</i> \r
+  loop scans the fields in one row.</p>\r
+<p>Here is the equivalent code in ADODB</p>\r
+<pre><b><font color="#666600"> include(&quot;adodb.inc.php&quot;);</font></b><font color="#666600">\r
+ $db = <b>NewADOConnection</b>('mysql');\r
+ $db-&gt;<b>Connect</b>(&quot;localhost&quot;, &quot;root&quot;, &quot;password&quot;, &quot;mydb&quot;);</font>\r
+ <font color="#663300">$result = $db-&gt;<b>Execute</b>(&quot;SELECT * FROM employees&quot;);\r
+ </font><font color="#663300"></font><code><font color="#663300">if ($result === false) die(&quot;failed&quot;)</font></code><code><font color="#663300">;</font></code>  \r
+ <font color="#006666"><b>while</b> (!$result-&gt;EOF) &#123;\r
+       <b>for</b> ($i=0, $max=$result-&gt;<b>FieldCount</b>(); $i &lt; $max; $i++)\r
+                  <b>print</b> $result-&gt;fields[$i].' ';\r
+       $result-&gt;<b>MoveNext</b>();\r
+       <b>print</b> &quot;&lt;br&gt;\n&quot;;\r
+ &#125;</font> </pre>\r
+<p></p>\r
+<p>Now porting to Oracle is as simple as changing the second line to <code>NewADOConnection('oracle')</code>. \r
+  Let's walk through the code...</p>\r
+<h3>Connecting to the Database</h3>\r
+<p></p>\r
+<pre><b><font color="#666600">include(&quot;adodb.inc.php&quot;);</font></b><font color="#666600">\r
+$db = <b>NewADOConnection</b>('mysql');\r
+$db-&gt;<b>Connect</b>(&quot;localhost&quot;, &quot;root&quot;, &quot;password&quot;, &quot;mydb&quot;);</font></pre>\r
+<p>The connection code is a bit more sophisticated than MySQL's because our needs \r
+  are more sophisticated. In ADODB, we use an object-oriented approach to managing \r
+  the complexity of handling multiple databases. We have different classes to \r
+  handle different databases. If you aren't familiar with object-oriented programing, \r
+  don't worry -- the complexity is all hidden away in the<code> NewADOConnection()</code> \r
+  function.</p>\r
+<p>To conserve memory, we only load the PHP code specific to the database you \r
+  are connecting to. We do this by calling <code>NewADOConnection(databasedriver)</code>. \r
+  Legal database drivers include <i>mysql, mssql, oracle, oci8, postgres, sybase, \r
+  vfp, access, ibase </i>and many others.</p>\r
+<p>Then we create a new instance of the connection class by calling <code>NewADOConnection()</code>. \r
+  Finally we connect to the database using <code>$db-&gt;Connect(). </code></p>\r
+<h3>Executing the SQL</h3>\r
+<p><code><font color="#663300">$result = $db-&gt;<b>Execute</b>(&quot;SELECT * \r
+  FROM employees&quot;);<br>\r
+  if ($result === false) die(&quot;failed&quot;)</font></code><code><font color="#663300">;</font></code> \r
+  <br>\r
+</p>\r
+<p>Sending the SQL statement to the server is straight forward. Execute() will \r
+  return a recordset object on successful execution. You should check $result \r
+  as we do above.\r
+<p>An issue that confuses beginners is the fact that we have two types of objects \r
+  in ADODB, the connection object and the recordset object. When do we use each?\r
+<p>The connection object ($db) is responsible for connecting to the database, \r
+  formatting your SQL and querying the database server. The recordset object ($result) \r
+  is responsible for retrieving the results and formatting the reply as text or \r
+  as an array.\r
+<p>The only thing I need to add is that ADODB provides several helper functions \r
+  for making INSERT and UPDATE statements easier, which we will cover in the Advanced \r
+  section. \r
+<h3>Retrieving the Data<br>\r
+</h3>\r
+<pre><font color="#006666"><b>while</b> (!$result-&gt;EOF) &#123;\r
+   <b>for</b> ($i=0, $max=$result-&gt;<b>FieldCount</b>(); $i &lt; $max; $i++)\r
+          <b>print</b> $result-&gt;fields[$i].' ';\r
+   $result-&gt;<b>MoveNext</b>();\r
+   <b>print</b> &quot;&lt;br&gt;\n&quot;;\r
+&#125;</font></pre>\r
+<p>The paradigm for getting the data is that it's like reading a file. For every \r
+  line, we check first whether we have reached the end-of-file (EOF). While not \r
+  end-of-file, loop through each field in the row. Then move to the next line \r
+  (MoveNext) and repeat. \r
+<p>The <code>$result-&gt;fields[]</code> array is generated by the PHP database \r
+  extension. Some database extensions do not index the array by field name. \r
+  To force indexing by name - that is associative arrays - \r
+  use the $ADODB_FETCH_MODE global variable. \r
+<pre>\r
+       $<b>ADODB_FETCH_MODE</b> = ADODB_FETCH_NUM;\r
+       $rs1 = $db->Execute('select * from table');\r
+       $<b>ADODB_FETCH_MODE</b> = ADODB_FETCH_ASSOC;\r
+       $rs2 = $db->Execute('select * from table');\r
+       print_r($rs1->fields); // shows <i>array([0]=>'v0',[1] =>'v1')</i>\r
+       print_r($rs2->fields); // shows <i>array(['col1']=>'v0',['col2'] =>'v1')</i>\r
+</pre>\r
+<p>\r
+As you can see in the above example, both recordsets store and use different fetch modes\r
+based on the $ADODB_FETCH_MODE setting when the recordset was created by Execute().</p>\r
+<h2>ADOConnection<a name="ADOConnection"></a></h2>\r
+<p>Object that performs the connection to the database, executes SQL statements \r
+  and has a set of utility functions for standardising the format of SQL statements \r
+  for issues such as concatenation and date formats.</p>\r
+  \r
+<h3>Other Useful Functions</h3>\r
+<p><code>$recordset-&gt;Move($pos)</code> scrolls to that particular row. ADODB supports forward \r
+  scrolling for all databases. Some databases will not support backwards scrolling. \r
+  This is normally not a problem as you can always cache records to simulate backwards \r
+  scrolling. \r
+<p><code>$recordset-&gt;RecordCount()</code> returns the number of records accessed by the \r
+  SQL statement. Some databases will return -1 because it is not supported. \r
+<p><code>$recordset-&gt;GetArray()</code> returns the result as an array. \r
+<p><code>rs2html($recordset)</code> is a function that is generates a HTML table based on the \r
+  $recordset passed to it. An example with the relevant lines in bold:\r
+<pre>   include('adodb.inc.php'); \r
+   <b>include('tohtml.inc.php');</b> /* includes the rs2html function */\r
+   $conn = &amp;ADONewConnection('mysql'); \r
+   $conn-&gt;PConnect('localhost','userid','password','database');\r
+   $rs = $conn-&gt;Execute('select * from table');\r
+  <b> rs2html($rs)</b>; /* recordset to html table */ </pre>\r
+<p>There are many other helper functions that are listed in the documentation available at <a href="http://php.weblogs.com/adodb_manual"></a><a href="http://php.weblogs.com/adodb_manual">http://php.weblogs.com/adodb_manual</a>. \r
+<h2>Advanced Material</h2>\r
+<h3>Inserts and Updates </h3>\r
+<p>Let's say you want to insert the following data into a database. \r
+<p><b>ID</b> = 3<br>\r
+  <b>TheDate</b>=mktime(0,0,0,8,31,2001) /* 31st August 2001 */<br>\r
+  <b>Note</b>= sugar why don't we call it off \r
+<p>When you move to another database, your insert might no longer work.</p>\r
+<p>The first problem is that each database has a different default date format. \r
+  MySQL expects YYYY-MM-DD format, while other databases have different defaults. \r
+  ADODB has a function called DBDate() that addresses this issue by converting \r
+  converting the date to the correct format.</p>\r
+<p>The next problem is that the <b>don't</b> in the Note needs to be quoted. In \r
+  MySQL, we use <b>don\'t</b> but in some other databases (Sybase, Access, Microsoft \r
+  SQL Server) we use <b>don''t. </b>The qstr() function addresses this issue.</p>\r
+<p>So how do we use the functions? Like this:</p>\r
+<pre>$sql = &quot;INSERT INTO table (id, thedate,note) values (&quot; \r
+   . $<b>ID</b> . ','\r
+   . $db-&gt;DBDate($<b>TheDate</b>) .','\r
+   . $db-&gt;qstr($<b>Note</b>).&quot;)&quot;;\r
+$db-&gt;Execute($sql);</pre>\r
+<p>ADODB also supports <code>$connection-&gt;Affected_Rows()</code> (returns the \r
+  number of rows affected by last update or delete) and <code>$recordset-&gt;Insert_ID()</code> \r
+  (returns last autoincrement number generated by an insert statement). Be forewarned \r
+  that not all databases support the two functions.<br>\r
+</p>\r
+<h3>MetaTypes</h3>\r
+<p>You can find out more information about each of the fields (I use the words \r
+  fields and columns interchangebly) you are selecting by calling the recordset \r
+  method <code>FetchField($fieldoffset)</code>. This will return an object with \r
+  3 properties: name, type and max_length. \r
+<pre>For example:</pre>\r
+<pre>$recordset = $conn-&gt;Execute(&quot;select adate from table&quot;);<br>$f0 = $recordset-&gt;FetchField(0);\r
+</pre>\r
+<p>Then <code>$f0-&gt;name</code> will hold <i>'adata'</i>, <code>$f0-&gt;type</code> \r
+  will be set to '<i>date'</i>. If the max_length is unknown, it will be set to \r
+  -1. \r
+<p>One problem with handling different databases is that each database often calls \r
+  the same type by a different name. For example a <i>timestamp</i> type is called \r
+  <i>datetime</i> in one database and <i>time</i> in another. So ADODB has a special \r
+  <code>MetaType($type, $max_length)</code> function that standardises the types \r
+  to the following: \r
+<p>C: character and varchar types<br>\r
+  X: text or long character (eg. more than 255 bytes wide).<br>\r
+  B: blob or binary image<br>\r
+  D: date<br>\r
+  T: timestamp<br>\r
+  L: logical (boolean)<br>\r
+  I: integer<br>\r
+  N: numeric (float, double, money) \r
+<p>In the above date example, \r
+<p><code>$recordset = $conn-&gt;Execute(&quot;select adate from table&quot;);<br>\r
+  $f0 = $recordset-&gt;FetchField(0);<br>\r
+  $type = $recordset-&gt;MetaType($f0-&gt;type, $f0-&gt;max_length);<br>\r
+  print $type; /* should print 'D'</code> */\r
+<p> \r
+<p><b>Select Limit and Top Support</b> \r
+<p>ADODB has a function called $connection->SelectLimit($sql,$nrows,$offset) that allows\r
+you to retrieve a subset of the recordset. This will take advantage of native\r
+SELECT TOP on Microsoft products and SELECT ... LIMIT with PostgreSQL and MySQL, and\r
+emulated if the database does not support it.\r
+<p><b>Caching Support</b> \r
+<p>ADODB allows you to cache recordsets in your file system, and only requery the database\r
+server after a certain timeout period with $connection->CacheExecute($secs2cache,$sql) and \r
+$connection->CacheSelectLimit($secs2cache,$sql,$nrows,$offset).\r
+<p><b>PHP4 Session Handler Support</b> \r
+<p>ADODB also supports PHP4 session handlers. You can store your session variables \r
+  in a database for true scalability using ADODB. For further information, visit \r
+  <a href="http://php.weblogs.com/adodb-sessions"></a><a href="http://php.weblogs.com/adodb-sessions">http://php.weblogs.com/adodb-sessions</a>\r
+<h3>Commercial Use Encouraged</h3>\r
+<p>If you plan to write commercial PHP applications that you want to resell, you should consider ADODB. It has been released using the lesser GPL, which means you can legally include it in commercial applications, while keeping your code proprietary. Commercial use of ADODB is strongly encouraged! We are using it internally for this reason.<p>\r
+\r
+<h2>Conclusion</h2>\r
+<p>As a thank you for finishing this article, here are the complete lyrics for \r
+  <i>let's call the whole thing off</i>.<br>\r
+  <br>\r
+<pre>\r
+   Refrain \r
+<br>\r
+               You say eether and I say eyether, \r
+               You say neether and I say nyther; \r
+               Eether, eyether, neether, nyther - \r
+               Let's call the whole thing off ! \r
+<br>\r
+               You like potato and I like po-tah-to, \r
+               You like tomato and I like to-mah-to; \r
+               Potato, po-tah-to, tomato, to-mah-to - \r
+               Let's call the whole thing off ! \r
+<br>\r
+But oh, if we call the whole thing off, then we must part. \r
+And oh, if we ever part, then that might break my heart. \r
+<br>\r
+               So, if you like pajamas and I like pa-jah-mas, \r
+               I'll wear pajamas and give up pa-jah-mas. \r
+               For we know we \r
+               Need each other, so we \r
+               Better call the calling off off. \r
+               Let's call the whole thing off ! \r
+<br>\r
+   Second Refrain \r
+<br>\r
+               You say laughter and I say lawfter, \r
+               You say after and I say awfter; \r
+               Laughter, lawfter, after, awfter - \r
+               Let's call the whole thing off ! \r
+<br>\r
+               You like vanilla and I like vanella, \r
+               You, sa's'parilla and I sa's'parella; \r
+               Vanilla, vanella, choc'late, strawb'ry - \r
+               Let's call the whole thing off ! \r
+<br>\r
+But oh, if we call the whole thing off, then we must part. \r
+And oh, if we ever part, then that might break my heart. \r
+<br>\r
+               So, if you go for oysters and I go for ersters, \r
+               I'll order oysters and cancel the ersters. \r
+               For we know we \r
+               Need each other, so we \r
+               Better call the calling off off. \r
+               Let's call the whole thing off ! \r
+  </pre>\r
+<p><font size=2>Song and lyrics by George and Ira Gershwin, introduced by Fred Astaire and Ginger Rogers\r
+in the film "Shall We Dance?"  </font><p>\r
+<p>\r
+(c)2001-2002 John Lim.\r
+\r
+</body>\r
+</html>\r