-<?php\r
-/*\r
- V3.31 17 March 2003 (c) 2000-2003 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
- Original version derived from Alberto Cerezal (acerezalp@dbnet.es) - DBNet Informatica & Comunicaciones. \r
- 08 Nov 2000 jlim - Minor corrections, removing mysql stuff\r
- 09 Nov 2000 jlim - added insertid support suggested by "Christopher Kings-Lynne" <chriskl@familyhealth.com.au>\r
- jlim - changed concat operator to || and data types to MetaType to match documented pgsql types \r
- see http://www.postgresql.org/devel-corner/docs/postgres/datatype.htm \r
- 22 Nov 2000 jlim - added changes to FetchField() and MetaTables() contributed by "raser" <raser@mail.zen.com.tw>\r
- 27 Nov 2000 jlim - added changes to _connect/_pconnect from ideas by "Lennie" <leen@wirehub.nl>\r
- 15 Dec 2000 jlim - added changes suggested by Additional code changes by "Eric G. Werk" egw@netguide.dk. \r
- 31 Jan 2002 jlim - finally installed postgresql. testing\r
- 01 Mar 2001 jlim - Freek Dijkstra changes, also support for text type\r
-*/\r
-\r
-class ADODB_postgres64 extends ADOConnection{\r
- var $databaseType = 'postgres64';\r
- var $dataProvider = 'postgres';\r
- var $hasInsertID = true;\r
- var $_resultid = false;\r
- var $concat_operator='||';\r
- var $metaTablesSQL = "select tablename from pg_tables where tablename not like 'pg\_%' order by 1";\r
- //"select tablename from pg_tables where tablename not like 'pg_%' order by 1";\r
- var $isoDates = true; // accepts dates in ISO format\r
- var $sysDate = "CURRENT_DATE";\r
- var $sysTimeStamp = "CURRENT_TIMESTAMP";\r
- var $blobEncodeType = 'C';\r
-/*\r
-# show tables and views suggestion\r
-"SELECT c.relname AS tablename FROM pg_class c \r
- WHERE (c.relhasrules AND (EXISTS (\r
- SELECT r.rulename FROM pg_rewrite r WHERE r.ev_class = c.oid AND bpchar(r.ev_type) = '1'\r
- ))) OR (c.relkind = 'v') AND c.relname NOT LIKE 'pg_%' \r
-UNION \r
-SELECT tablename FROM pg_tables WHERE tablename NOT LIKE 'pg_%' ORDER BY 1"\r
-*/\r
- var $metaColumnsSQL = "SELECT a.attname,t.typname,a.attlen,a.atttypmod,a.attnotnull,a.atthasdef,a.attnum FROM pg_class c, pg_attribute a,pg_type t WHERE relkind = 'r' AND c.relname='%s' AND a.attnum > 0 AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";\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
- \r
- var $hasAffectedRows = true;\r
- var $hasLimit = false; // set to true for pgsql 7 only. support pgsql/mysql SELECT * FROM TABLE LIMIT 10\r
- // below suggested by Freek Dijkstra \r
- var $true = 't'; // string that represents TRUE for a database\r
- var $false = 'f'; // string that represents FALSE for a database\r
- var $fmtDate = "'Y-m-d'"; // used by DBDate() as the default date format used by the database\r
- var $fmtTimeStamp = "'Y-m-d G:i:s'"; // used by DBTimeStamp as the default timestamp fmt.\r
- var $hasMoveFirst = true;\r
- var $hasGenID = true;\r
- var $_genIDSQL = "SELECT NEXTVAL('%s')";\r
- 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
- \r
- \r
- // The last (fmtTimeStamp is not entirely correct: \r
- // PostgreSQL also has support for time zones, \r
- // and writes these time in this format: "2001-03-01 18:59:26+02". \r
- // There is no code for the "+02" time zone information, so I just left that out. \r
- // I'm not familiar enough with both ADODB as well as Postgres \r
- // to know what the concequences are. The other values are correct (wheren't in 0.94)\r
- // -- Freek Dijkstra \r
-\r
- function ADODB_postgres64() \r
- {\r
- // changes the metaColumnsSQL, adds columns: attnum[6]\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
- // get the last id - never tested\r
- function pg_insert_id($tablename,$fieldname)\r
- {\r
- $result=pg_exec($this->_connectionID, "SELECT last_value FROM ${tablename}_${fieldname}_seq");\r
- if ($result) {\r
- $arr = @pg_fetch_row($result,0);\r
- pg_freeresult($result);\r
- if (isset($arr[0])) return $arr[0];\r
- }\r
- return false;\r
- }\r
- \r
-/* Warning from http://www.php.net/manual/function.pg-getlastoid.php:\r
-Using a OID as a unique identifier is not generally wise. \r
-Unless you are very careful, you might end up with a tuple having \r
-a different OID if a database must be reloaded. */\r
- function _insertid()\r
- {\r
- if (!is_resource($this->_resultid)) return false;\r
- return pg_getlastoid($this->_resultid);\r
- }\r
-\r
-// I get this error with PHP before 4.0.6 - jlim\r
-// Warning: This compilation does not support pg_cmdtuples() in d:/inetpub/wwwroot/php/adodb/adodb-postgres.inc.php on line 44\r
- function _affectedrows()\r
- {\r
- if (!is_resource($this->_resultid)) return false;\r
- return pg_cmdtuples($this->_resultid);\r
- }\r
-\r
- \r
- // returns true/false\r
- function BeginTrans()\r
- {\r
- if ($this->transOff) return true;\r
- $this->transCnt += 1;\r
- return @pg_Exec($this->_connectionID, "begin");\r
- }\r
- \r
- function RowLock($tables,$where) \r
- {\r
- if (!$this->transCnt) $this->BeginTrans();\r
- return $this->GetOne("select 1 as ignore from $tables where $where for update");\r
- }\r
-\r
- // returns true/false. \r
- function CommitTrans($ok=true) \r
- { \r
- if ($this->transOff) return true;\r
- if (!$ok) return $this->RollbackTrans();\r
- \r
- $this->transCnt -= 1;\r
- return @pg_Exec($this->_connectionID, "commit");\r
- }\r
- \r
- // returns true/false\r
- function RollbackTrans()\r
- {\r
- if ($this->transOff) return true;\r
- $this->transCnt -= 1;\r
- return @pg_Exec($this->_connectionID, "rollback");\r
- }\r
- \r
- // if magic quotes disabled, use pg_escape_string()\r
- function qstr($s,$magic_quotes=false)\r
- {\r
- if (!$magic_quotes) {\r
- if (ADODB_PHPVER >= 0x4200) {\r
- return "'".pg_escape_string($s)."'";\r
- }\r
- if ($this->replaceQuote[0] == '\\'){\r
- $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);\r
- }\r
- return "'".str_replace("'",$this->replaceQuote,$s)."'"; \r
- }\r
- \r
- // undo magic quotes for "\r
- $s = str_replace('\\"','"',$s);\r
- return "'$s'";\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->sysDate;\r
- $s = '';\r
- \r
- $len = strlen($fmt);\r
- for ($i=0; $i < $len; $i++) {\r
- if ($s) $s .= '||';\r
- $ch = $fmt[$i];\r
- switch($ch) {\r
- case 'Y':\r
- case 'y':\r
- $s .= "date_part('year',$col)";\r
- break;\r
- case 'Q':\r
- case 'q':\r
- $s .= "date_part('quarter',$col)";\r
- break;\r
- \r
- case 'M':\r
- case 'm':\r
- $s .= "lpad(date_part('month',$col),2,'0')";\r
- break;\r
- case 'D':\r
- case 'd':\r
- $s .= "lpad(date_part('day',$col),2,'0')";\r
- break;\r
- default:\r
- if ($ch == '\\') {\r
- $i++;\r
- $ch = substr($fmt,$i,1);\r
- }\r
- $s .= $this->qstr($ch);\r
- break;\r
- }\r
- }\r
- return $s;\r
- }\r
- \r
- /* \r
- * Load a Large Object from a file \r
- * - the procedure stores the object id in the table and imports the object using \r
- * postgres proprietary blob handling routines \r
- *\r
- * contributed by Mattia Rossi mattia@technologist.com\r
- */ \r
- function UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB') \r
- { \r
- pg_exec ($this->_connectionID, "begin"); \r
- $oid = pg_lo_import ($path); \r
- pg_exec ($this->_connectionID, "commit"); \r
- $rs = ADOConnection::UpdateBlob($table,$column,$oid,$where,$blobtype); \r
- $rez = !empty($rs); \r
- return $rez; \r
- } \r
- \r
- /* \r
- * If an OID is detected, then we use pg_lo_* to open the oid file and read the\r
- * real blob from the db using the oid supplied as a parameter. If you are storing\r
- * blobs using bytea, we autodetect and process it so this function is not needed.\r
- *\r
- * contributed by Mattia Rossi mattia@technologist.com\r
- *\r
- * see http://www.postgresql.org/idocs/index.php?largeobjects.html\r
- */ \r
- function BlobDecode( $blob) \r
- { \r
- @pg_exec("begin"); \r
- $fd = @pg_lo_open($blob,"r");\r
- if ($fd === false) {\r
- @pg_exec("commit");\r
- return $blob;\r
- }\r
- $realblob = @pg_loreadall($fd); \r
- @pg_loclose($fd); \r
- @pg_exec("commit"); \r
- return $realblob;\r
- } \r
- \r
- /* \r
- See http://www.postgresql.org/idocs/index.php?datatype-binary.html\r
- \r
- NOTE: SQL string literals (input strings) must be preceded with two backslashes \r
- due to the fact that they must pass through two parsers in the PostgreSQL \r
- backend.\r
- */\r
- function BlobEncode($blob)\r
- { // requires php 4.0.5\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
- \r
- // note that there is a pg_escape_bytea function only for php 4.2.0 or later\r
- }\r
- \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
- }\r
- \r
- function OffsetDate($dayFraction,$date=false)\r
- { \r
- if (!$date) $date = $this->sysDate;\r
- return "($date+interval'$dayFraction days')";\r
- }\r
- \r
-\r
- // converts field names to lowercase \r
- function &MetaColumns($table) \r
- {\r
- global $ADODB_FETCH_MODE;\r
- \r
- if (!empty($this->metaColumnsSQL)) { \r
- // the following is the only difference -- we lowercase it\r
- $save = $ADODB_FETCH_MODE;\r
- $ADODB_FETCH_MODE = ADODB_FETCH_NUM;\r
- \r
- $rs = $this->Execute(sprintf($this->metaColumnsSQL,($table)));\r
- \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
- \r
- $ADODB_FETCH_MODE = $save;\r
- \r
- $rskey->Close();\r
- unset($rskey);\r
- }\r
-\r
- $rsdefa = array();\r
- if (!empty($this->metaDefaultsSQL)) {\r
- $sql = sprintf($this->metaDefaultsSQL, ($table));\r
- $rsdef = $this->Execute($sql);\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
- }\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
- //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
- }\r
- \r
- $retarr[strtoupper($fld->name)] = $fld; \r
- \r
- $rs->MoveNext();\r
- }\r
- $rs->Close();\r
- return $retarr; \r
- }\r
- return false;\r
- }\r
-\r
- function &MetaDatabases()\r
- {\r
- $arr = array();\r
- $sql="select datname from pg_database";\r
- $rs = $this->Execute($sql);\r
- if (!$rs) return false;\r
- while (!$rs->EOF) {\r
- $arr[] = reset($rs->fields);\r
- $rs->MoveNext();\r
- }\r
- \r
- return $arr;\r
- }\r
-\r
-\r
- // returns true or false\r
- //\r
- // examples:\r
- // $db->Connect("host=host1 user=user1 password=secret port=4341");\r
- // $db->Connect('host1','user1','secret');\r
- function _connect($str,$user='',$pwd='',$db='')\r
- { \r
- if ($user || $pwd || $db) {\r
- if ($str) {\r
- $host = split(":", $str);\r
- if ($host[0]) $str = "host='" . addslashes($host[0]) . "'";\r
- else $str = 'localhost';\r
- if (isset($host[1])) $str .= " port='" . addslashes($host[1]) . "'";\r
- }\r
- if ($user) $str .= " user='" . addslashes($user) . "'";\r
- if ($pwd) $str .= " password='" . addslashes($pwd) . "'";\r
- if ($db) $str .= " dbname='" . addslashes($db) . "'";\r
- }\r
- \r
- //if ($user) $linea = "user=$user host=$linea password=$pwd dbname=$db port=5432";\r
- $this->_connectionID = pg_connect($str);\r
- if ($this->_connectionID === false) return false;\r
- $this->Execute("set datestyle='ISO'");\r
- return true;\r
- }\r
- \r
- // returns true or false\r
- //\r
- // examples:\r
- // $db->PConnect("host=host1 user=user1 password=secret port=4341");\r
- // $db->PConnect('host1','user1','secret');\r
- function _pconnect($str,$user='',$pwd='',$db='')\r
- {\r
- if ($user || $pwd || $db) {\r
- if ($str) {\r
- $host = split(":", $str);\r
- if ($host[0]) $str = "host='" . addslashes($host[0]) . "'";\r
- else $str = 'localhost';\r
- if (isset($host[1])) $str .= " port='" . addslashes($host[1]) . "'";\r
- }\r
- if ($user) $str .= " user='" . addslashes($user) . "'";\r
- if ($pwd) $str .= " password='" . addslashes($pwd) . "'";\r
- if ($db) $str .= " dbname='" . addslashes($db) . "'";\r
- }//print $str;\r
- $this->_connectionID = pg_pconnect($str);\r
- if ($this->_connectionID === false) return false;\r
- $this->Execute("set datestyle='ISO'");\r
- return true;\r
- }\r
-\r
- // returns queryID or false\r
- function _query($sql,$inputarr)\r
- {\r
- $rez = pg_Exec($this->_connectionID,$sql);\r
- // check if no data returned, then no need to create real recordset\r
- if ($rez && pg_numfields($rez) <= 0) {\r
- $this->_resultid = $rez;\r
- return true;\r
- }\r
- return $rez;\r
- }\r
- \r
-\r
- /* Returns: the last error message from previous database operation */ \r
- function ErrorMsg() \r
- {\r
- if (ADODB_PHPVER >= 0x4300) {\r
- if (!empty($this->_resultid)) {\r
- $this->_errorMsg = @pg_result_error($this->_resultid);\r
- if ($this->_errorMsg) return $this->_errorMsg;\r
- }\r
- \r
- if (!empty($this->_connectionID)) {\r
- $this->_errorMsg = @pg_last_error($this->_connectionID);\r
- } else $this->_errorMsg = @pg_last_error();\r
- } else {\r
- if (empty($this->_connectionID)) $this->_errorMsg = @pg_errormessage();\r
- else $this->_errorMsg = @pg_errormessage($this->_connectionID);\r
- }\r
- return $this->_errorMsg;\r
- }\r
- \r
- function ErrorNo()\r
- {\r
- return (strlen($this->ErrorMsg())) ? -1 : 0;\r
- }\r
-\r
- // returns true or false\r
- function _close()\r
- {\r
- if ($this->transCnt) $this->RollbackTrans();\r
- $this->_resultid = false;\r
- @pg_close($this->_connectionID);\r
- $this->_connectionID = false;\r
- return true;\r
- }\r
- \r
- \r
- /*\r
- * Maximum size of C field\r
- */\r
- function CharMax()\r
- {\r
- return 1000000000; // should be 1 Gb?\r
- }\r
- \r
- /*\r
- * Maximum size of X field\r
- */\r
- function TextMax()\r
- {\r
- return 1000000000; // should be 1 Gb?\r
- }\r
- \r
- \r
-}\r
- \r
-/*--------------------------------------------------------------------------------------\r
- Class Name: Recordset\r
---------------------------------------------------------------------------------------*/\r
-\r
-class ADORecordSet_postgres64 extends ADORecordSet{\r
- var $_blobArr;\r
- var $databaseType = "postgres64";\r
- var $canSeek = true;\r
- function ADORecordSet_postgres64($queryID,$mode=false) \r
- {\r
- if ($mode === false) { \r
- global $ADODB_FETCH_MODE;\r
- $mode = $ADODB_FETCH_MODE;\r
- }\r
- switch ($mode)\r
- {\r
- case ADODB_FETCH_NUM: $this->fetchMode = PGSQL_NUM; break;\r
- case ADODB_FETCH_ASSOC:$this->fetchMode = PGSQL_ASSOC; break;\r
- default:\r
- case ADODB_FETCH_DEFAULT:\r
- case ADODB_FETCH_BOTH:$this->fetchMode = PGSQL_BOTH; break;\r
- }\r
- $this->ADORecordSet($queryID);\r
- }\r
- \r
- function &GetRowAssoc($upper=true)\r
- {\r
- if ($this->fetchMode == PGSQL_ASSOC && !$upper) return $rs->fields;\r
- return ADORecordSet::GetRowAssoc($upper);\r
- }\r
-\r
- function _initrs()\r
- {\r
- global $ADODB_COUNTRECS;\r
- $this->_numOfRows = ($ADODB_COUNTRECS)? @pg_numrows($this->_queryID):-1;\r
- $this->_numOfFields = @pg_numfields($this->_queryID);\r
- \r
- // cache types for blob decode check\r
- for ($i=0, $max = $this->_numOfFields; $i < $max; $i++) { \r
- $f1 = $this->FetchField($i);\r
- if ($f1->type == 'bytea') $this->_blobArr[$i] = $f1->name;\r
- } \r
- }\r
-\r
- /* Use associative array to get fields array */\r
- function Fields($colname)\r
- {\r
- if ($this->fetchMode != PGSQL_NUM) 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 &FetchField($fieldOffset = 0) \r
- {\r
- $off=$fieldOffset; // offsets begin at 0\r
- \r
- $o= new ADOFieldObject();\r
- $o->name = @pg_fieldname($this->_queryID,$off);\r
- $o->type = @pg_fieldtype($this->_queryID,$off);\r
- $o->max_length = @pg_fieldsize($this->_queryID,$off);\r
- //print_r($o); \r
- //print "off=$off name=$o->name type=$o->type len=$o->max_length<br>";\r
- return $o; \r
- }\r
-\r
- function _seek($row)\r
- {\r
- return @pg_fetch_row($this->_queryID,$row);\r
- }\r
- \r
- function _decode($blob)\r
- {\r
- \r
- eval('$realblob="'.adodb_str_replace(array('"','$'),array('\"','\$'),$blob).'";');\r
- return $realblob;\r
- \r
- }\r
- function _fixblobs()\r
- {\r
- if ($this->fetchMode == PGSQL_NUM || $this->fetchMode == PGSQL_BOTH) {\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
- foreach($this->_blobArr as $k => $v) {\r
- $this->fields[$v] = ADORecordSet_postgres64::_decode($this->fields[$v]);\r
- }\r
- }\r
- }\r
- \r
- // 10% speedup to move MoveNext to child class\r
- function MoveNext() \r
- {\r
- if (!$this->EOF) {\r
- $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
- return true;\r
- }\r
- }\r
- $this->fields = false;\r
- $this->EOF = true;\r
- }\r
- return false;\r
- } \r
- \r
- function _fetch()\r
- {\r
- if ($this->_currentRow >= $this->_numOfRows && $this->_numOfRows != -1)\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
- return (is_array($this->fields));\r
- }\r
-\r
- function _close() \r
- {\r
- return @pg_freeresult($this->_queryID);\r
- }\r
-\r
- function MetaType($t,$len=-1,$fieldobj=false)\r
- {\r
- if (is_object($t)) {\r
- $fieldobj = $t;\r
- $t = $fieldobj->type;\r
- $len = $fieldobj->max_length;\r
- }\r
- switch (strtoupper($t)) {\r
- case 'INTERVAL':\r
- case 'CHAR':\r
- case 'CHARACTER':\r
- case 'VARCHAR':\r
- case 'NAME':\r
- case 'BPCHAR':\r
- if ($len <= $this->blobSize) return 'C';\r
- \r
- case 'TEXT':\r
- return 'X';\r
- \r
- case 'IMAGE': // user defined type\r
- case 'BLOB': // user defined type\r
- case 'BIT': // This is a bit string, not a single bit, so don't return 'L'\r
- case 'VARBIT':\r
- case 'BYTEA':\r
- return 'B';\r
- \r
- case 'BOOL':\r
- case 'BOOLEAN':\r
- return 'L';\r
- \r
- case 'DATE':\r
- return 'D';\r
- \r
- case 'TIME':\r
- case 'DATETIME':\r
- case 'TIMESTAMP':\r
- case 'TIMESTAMPTZ':\r
- return 'T';\r
- \r
- case 'SMALLINT': \r
- case 'BIGINT': \r
- case 'INTEGER': \r
- case 'INT8': \r
- case 'INT4':\r
- case 'INT2':\r
- if (isset($fieldobj) &&\r
- empty($fieldobj->primary_key) && empty($fieldobj->unique)) return 'I';\r
- \r
- case 'OID':\r
- case 'SERIAL':\r
- return 'R';\r
- \r
- default:\r
- return 'N';\r
- }\r
- }\r
-\r
-}\r
-?>\r
+<?php
+/*
+ V3.31 17 March 2003 (c) 2000-2003 John Lim (jlim@natsoft.com.my). All rights reserved.
+ Released under both BSD license and Lesser GPL library license.
+ Whenever there is any discrepancy between the two licenses,
+ the BSD license will take precedence.
+ Set tabs to 8.
+
+ Original version derived from Alberto Cerezal (acerezalp@dbnet.es) - DBNet Informatica & Comunicaciones.
+ 08 Nov 2000 jlim - Minor corrections, removing mysql stuff
+ 09 Nov 2000 jlim - added insertid support suggested by "Christopher Kings-Lynne" <chriskl@familyhealth.com.au>
+ jlim - changed concat operator to || and data types to MetaType to match documented pgsql types
+ see http://www.postgresql.org/devel-corner/docs/postgres/datatype.htm
+ 22 Nov 2000 jlim - added changes to FetchField() and MetaTables() contributed by "raser" <raser@mail.zen.com.tw>
+ 27 Nov 2000 jlim - added changes to _connect/_pconnect from ideas by "Lennie" <leen@wirehub.nl>
+ 15 Dec 2000 jlim - added changes suggested by Additional code changes by "Eric G. Werk" egw@netguide.dk.
+ 31 Jan 2002 jlim - finally installed postgresql. testing
+ 01 Mar 2001 jlim - Freek Dijkstra changes, also support for text type
+*/
+
+class ADODB_postgres64 extends ADOConnection{
+ var $databaseType = 'postgres64';
+ var $dataProvider = 'postgres';
+ var $hasInsertID = true;
+ var $_resultid = false;
+ var $concat_operator='||';
+ var $metaTablesSQL = "select tablename from pg_tables where tablename not like 'pg\_%' order by 1";
+ //"select tablename from pg_tables where tablename not like 'pg_%' order by 1";
+ var $isoDates = true; // accepts dates in ISO format
+ var $sysDate = "CURRENT_DATE";
+ var $sysTimeStamp = "CURRENT_TIMESTAMP";
+ var $blobEncodeType = 'C';
+/*
+# show tables and views suggestion
+"SELECT c.relname AS tablename FROM pg_class c
+ WHERE (c.relhasrules AND (EXISTS (
+ SELECT r.rulename FROM pg_rewrite r WHERE r.ev_class = c.oid AND bpchar(r.ev_type) = '1'
+ ))) OR (c.relkind = 'v') AND c.relname NOT LIKE 'pg_%'
+UNION
+SELECT tablename FROM pg_tables WHERE tablename NOT LIKE 'pg_%' ORDER BY 1"
+*/
+ var $metaColumnsSQL = "SELECT a.attname,t.typname,a.attlen,a.atttypmod,a.attnotnull,a.atthasdef,a.attnum FROM pg_class c, pg_attribute a,pg_type t WHERE relkind = 'r' AND c.relname='%s' AND a.attnum > 0 AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";
+ // get primary key etc -- from Freek Dijkstra
+ 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'";
+
+ var $hasAffectedRows = true;
+ var $hasLimit = false; // set to true for pgsql 7 only. support pgsql/mysql SELECT * FROM TABLE LIMIT 10
+ // below suggested by Freek Dijkstra
+ var $true = 't'; // string that represents TRUE for a database
+ var $false = 'f'; // string that represents FALSE for a database
+ var $fmtDate = "'Y-m-d'"; // used by DBDate() as the default date format used by the database
+ var $fmtTimeStamp = "'Y-m-d G:i:s'"; // used by DBTimeStamp as the default timestamp fmt.
+ var $hasMoveFirst = true;
+ var $hasGenID = true;
+ var $_genIDSQL = "SELECT NEXTVAL('%s')";
+ var $_genSeqSQL = "CREATE SEQUENCE %s START %s";
+ var $_dropSeqSQL = "DROP SEQUENCE %s";
+ 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";
+
+
+ // The last (fmtTimeStamp is not entirely correct:
+ // PostgreSQL also has support for time zones,
+ // and writes these time in this format: "2001-03-01 18:59:26+02".
+ // There is no code for the "+02" time zone information, so I just left that out.
+ // I'm not familiar enough with both ADODB as well as Postgres
+ // to know what the concequences are. The other values are correct (wheren't in 0.94)
+ // -- Freek Dijkstra
+
+ function ADODB_postgres64()
+ {
+ // changes the metaColumnsSQL, adds columns: attnum[6]
+ }
+
+ function ServerInfo()
+ {
+ $arr['description'] = $this->GetOne("select version()");
+ $arr['version'] = ADOConnection::_findvers($arr['description']);
+ return $arr;
+ }
+
+ // get the last id - never tested
+ function pg_insert_id($tablename,$fieldname)
+ {
+ $result=pg_exec($this->_connectionID, "SELECT last_value FROM ${tablename}_${fieldname}_seq");
+ if ($result) {
+ $arr = @pg_fetch_row($result,0);
+ pg_freeresult($result);
+ if (isset($arr[0])) return $arr[0];
+ }
+ return false;
+ }
+
+/* Warning from http://www.php.net/manual/function.pg-getlastoid.php:
+Using a OID as a unique identifier is not generally wise.
+Unless you are very careful, you might end up with a tuple having
+a different OID if a database must be reloaded. */
+ function _insertid()
+ {
+ if (!is_resource($this->_resultid)) return false;
+ return pg_getlastoid($this->_resultid);
+ }
+
+// I get this error with PHP before 4.0.6 - jlim
+// Warning: This compilation does not support pg_cmdtuples() in d:/inetpub/wwwroot/php/adodb/adodb-postgres.inc.php on line 44
+ function _affectedrows()
+ {
+ if (!is_resource($this->_resultid)) return false;
+ return pg_cmdtuples($this->_resultid);
+ }
+
+
+ // returns true/false
+ function BeginTrans()
+ {
+ if ($this->transOff) return true;
+ $this->transCnt += 1;
+ return @pg_Exec($this->_connectionID, "begin");
+ }
+
+ function RowLock($tables,$where)
+ {
+ if (!$this->transCnt) $this->BeginTrans();
+ return $this->GetOne("select 1 as ignore from $tables where $where for update");
+ }
+
+ // returns true/false.
+ function CommitTrans($ok=true)
+ {
+ if ($this->transOff) return true;
+ if (!$ok) return $this->RollbackTrans();
+
+ $this->transCnt -= 1;
+ return @pg_Exec($this->_connectionID, "commit");
+ }
+
+ // returns true/false
+ function RollbackTrans()
+ {
+ if ($this->transOff) return true;
+ $this->transCnt -= 1;
+ return @pg_Exec($this->_connectionID, "rollback");
+ }
+
+ // if magic quotes disabled, use pg_escape_string()
+ function qstr($s,$magic_quotes=false)
+ {
+ if (!$magic_quotes) {
+ if (ADODB_PHPVER >= 0x4200) {
+ return "'".pg_escape_string($s)."'";
+ }
+ if ($this->replaceQuote[0] == '\\'){
+ $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
+ }
+ return "'".str_replace("'",$this->replaceQuote,$s)."'";
+ }
+
+ // undo magic quotes for "
+ $s = str_replace('\\"','"',$s);
+ return "'$s'";
+ }
+
+ // Format date column in sql string given an input format that understands Y M D
+ function SQLDate($fmt, $col=false)
+ {
+ if (!$col) $col = $this->sysDate;
+ $s = '';
+
+ $len = strlen($fmt);
+ for ($i=0; $i < $len; $i++) {
+ if ($s) $s .= '||';
+ $ch = $fmt[$i];
+ switch($ch) {
+ case 'Y':
+ case 'y':
+ $s .= "date_part('year',$col)";
+ break;
+ case 'Q':
+ case 'q':
+ $s .= "date_part('quarter',$col)";
+ break;
+
+ case 'M':
+ case 'm':
+ $s .= "lpad(date_part('month',$col),2,'0')";
+ break;
+ case 'D':
+ case 'd':
+ $s .= "lpad(date_part('day',$col),2,'0')";
+ break;
+ default:
+ if ($ch == '\\') {
+ $i++;
+ $ch = substr($fmt,$i,1);
+ }
+ $s .= $this->qstr($ch);
+ break;
+ }
+ }
+ return $s;
+ }
+
+ /*
+ * Load a Large Object from a file
+ * - the procedure stores the object id in the table and imports the object using
+ * postgres proprietary blob handling routines
+ *
+ * contributed by Mattia Rossi mattia@technologist.com
+ */
+ function UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB')
+ {
+ pg_exec ($this->_connectionID, "begin");
+ $oid = pg_lo_import ($path);
+ pg_exec ($this->_connectionID, "commit");
+ $rs = ADOConnection::UpdateBlob($table,$column,$oid,$where,$blobtype);
+ $rez = !empty($rs);
+ return $rez;
+ }
+
+ /*
+ * If an OID is detected, then we use pg_lo_* to open the oid file and read the
+ * real blob from the db using the oid supplied as a parameter. If you are storing
+ * blobs using bytea, we autodetect and process it so this function is not needed.
+ *
+ * contributed by Mattia Rossi mattia@technologist.com
+ *
+ * see http://www.postgresql.org/idocs/index.php?largeobjects.html
+ */
+ function BlobDecode( $blob)
+ {
+ @pg_exec("begin");
+ $fd = @pg_lo_open($blob,"r");
+ if ($fd === false) {
+ @pg_exec("commit");
+ return $blob;
+ }
+ $realblob = @pg_loreadall($fd);
+ @pg_loclose($fd);
+ @pg_exec("commit");
+ return $realblob;
+ }
+
+ /*
+ See http://www.postgresql.org/idocs/index.php?datatype-binary.html
+
+ NOTE: SQL string literals (input strings) must be preceded with two backslashes
+ due to the fact that they must pass through two parsers in the PostgreSQL
+ backend.
+ */
+ function BlobEncode($blob)
+ { // requires php 4.0.5
+ $badch = array(chr(92),chr(0),chr(39)); # \ null '
+ $fixch = array('\\\\134','\\\\000','\\\\047');
+ return adodb_str_replace($badch,$fixch,$blob);
+
+ // note that there is a pg_escape_bytea function only for php 4.2.0 or later
+ }
+
+ function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
+ {
+ return $this->Execute("UPDATE $table SET $column=? WHERE $where",
+ array($this->BlobEncode($val))) != false;
+ }
+
+ function OffsetDate($dayFraction,$date=false)
+ {
+ if (!$date) $date = $this->sysDate;
+ return "($date+interval'$dayFraction days')";
+ }
+
+
+ // converts field names to lowercase
+ function &MetaColumns($table)
+ {
+ global $ADODB_FETCH_MODE;
+
+ if (!empty($this->metaColumnsSQL)) {
+ // the following is the only difference -- we lowercase it
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ $rs = $this->Execute(sprintf($this->metaColumnsSQL,($table)));
+
+ $ADODB_FETCH_MODE = $save;
+
+ if ($rs === false) return false;
+
+ if (!empty($this->metaKeySQL)) {
+ // If we want the primary keys, we have to issue a separate query
+ // Of course, a modified version of the metaColumnsSQL query using a
+ // LEFT JOIN would have been much more elegant, but postgres does
+ // not support OUTER JOINS. So here is the clumsy way.
+
+ $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
+
+ $rskey = $this->Execute(sprintf($this->metaKeySQL,($table)));
+ // fetch all result in once for performance.
+ $keys = $rskey->GetArray();
+
+ $ADODB_FETCH_MODE = $save;
+
+ $rskey->Close();
+ unset($rskey);
+ }
+
+ $rsdefa = array();
+ if (!empty($this->metaDefaultsSQL)) {
+ $sql = sprintf($this->metaDefaultsSQL, ($table));
+ $rsdef = $this->Execute($sql);
+ if ($rsdef) {
+ while (!$rsdef->EOF) {
+ $num = $rsdef->Fields('num');
+ $s = $rsdef->Fields('def');
+ if (substr($s, 0, 1) == "'") { /* quoted strings hack... for now... fixme */
+ $s = substr($s, 1);
+ $s = substr($s, 0, strlen($s) - 1);
+ }
+
+ $rsdefa[$num] = $s;
+ $rsdef->MoveNext();
+ }
+ } else {
+ ADOConnection::outp( "==> SQL => " . $sql);
+ }
+ unset($rsdef);
+ }
+
+ $retarr = array();
+ while (!$rs->EOF) {
+ $fld = new ADOFieldObject();
+ $fld->name = $rs->fields[0];
+ $fld->type = $rs->fields[1];
+ $fld->max_length = $rs->fields[2];
+ if ($fld->max_length <= 0) $fld->max_length = $rs->fields[3]-4;
+ if ($fld->max_length <= 0) $fld->max_length = -1;
+
+ // dannym
+ // 5 hasdefault; 6 num-of-column
+ $fld->has_default = ($rs->fields[5] == 't');
+ if ($fld->has_default) {
+ $fld->default_value = $rsdefa[$rs->fields[6]];
+ }
+
+ //Freek
+ if ($rs->fields[4] == $this->true) {
+ $fld->not_null = true;
+ }
+
+ // Freek
+ if (is_array($keys)) {
+ reset ($keys);
+ while (list($x,$key) = each($keys)) {
+ if ($fld->name == $key['column_name'] AND $key['primary_key'] == $this->true)
+ $fld->primary_key = true;
+ if ($fld->name == $key['column_name'] AND $key['unique_key'] == $this->true)
+ $fld->unique = true; // What name is more compatible?
+ }
+ }
+
+ $retarr[strtoupper($fld->name)] = $fld;
+
+ $rs->MoveNext();
+ }
+ $rs->Close();
+ return $retarr;
+ }
+ return false;
+ }
+
+ function &MetaDatabases()
+ {
+ $arr = array();
+ $sql="select datname from pg_database";
+ $rs = $this->Execute($sql);
+ if (!$rs) return false;
+ while (!$rs->EOF) {
+ $arr[] = reset($rs->fields);
+ $rs->MoveNext();
+ }
+
+ return $arr;
+ }
+
+
+ // returns true or false
+ //
+ // examples:
+ // $db->Connect("host=host1 user=user1 password=secret port=4341");
+ // $db->Connect('host1','user1','secret');
+ function _connect($str,$user='',$pwd='',$db='')
+ {
+ if ($user || $pwd || $db) {
+ if ($str) {
+ $host = split(":", $str);
+ if ($host[0]) $str = "host='" . addslashes($host[0]) . "'";
+ else $str = 'localhost';
+ if (isset($host[1])) $str .= " port='" . addslashes($host[1]) . "'";
+ }
+ if ($user) $str .= " user='" . addslashes($user) . "'";
+ if ($pwd) $str .= " password='" . addslashes($pwd) . "'";
+ if ($db) $str .= " dbname='" . addslashes($db) . "'";
+ }
+
+ //if ($user) $linea = "user=$user host=$linea password=$pwd dbname=$db port=5432";
+ $this->_connectionID = @pg_connect($str);
+ if ($this->_connectionID === false) return false;
+ $this->Execute("set datestyle='ISO'");
+ return true;
+ }
+
+ // returns true or false
+ //
+ // examples:
+ // $db->PConnect("host=host1 user=user1 password=secret port=4341");
+ // $db->PConnect('host1','user1','secret');
+ function _pconnect($str,$user='',$pwd='',$db='')
+ {
+ if ($user || $pwd || $db) {
+ if ($str) {
+ $host = split(":", $str);
+ if ($host[0]) $str = "host='" . addslashes($host[0]) . "'";
+ else $str = 'localhost';
+ if (isset($host[1])) $str .= " port='" . addslashes($host[1]) . "'";
+ }
+ if ($user) $str .= " user='" . addslashes($user) . "'";
+ if ($pwd) $str .= " password='" . addslashes($pwd) . "'";
+ if ($db) $str .= " dbname='" . addslashes($db) . "'";
+ }//print $str;
+ $this->_connectionID = @pg_pconnect($str);
+ if ($this->_connectionID === false) return false;
+ $this->Execute("set datestyle='ISO'");
+ return true;
+ }
+
+ // returns queryID or false
+ function _query($sql,$inputarr)
+ {
+ $rez = pg_Exec($this->_connectionID,$sql);
+ // check if no data returned, then no need to create real recordset
+ if ($rez && pg_numfields($rez) <= 0) {
+ $this->_resultid = $rez;
+ return true;
+ }
+ return $rez;
+ }
+
+
+ /* Returns: the last error message from previous database operation */
+ function ErrorMsg()
+ {
+ if (ADODB_PHPVER >= 0x4300) {
+ if (!empty($this->_resultid)) {
+ $this->_errorMsg = @pg_result_error($this->_resultid);
+ if ($this->_errorMsg) return $this->_errorMsg;
+ }
+
+ if (!empty($this->_connectionID)) {
+ $this->_errorMsg = @pg_last_error($this->_connectionID);
+ } else $this->_errorMsg = @pg_last_error();
+ } else {
+ if (empty($this->_connectionID)) $this->_errorMsg = @pg_errormessage();
+ else $this->_errorMsg = @pg_errormessage($this->_connectionID);
+ }
+ return $this->_errorMsg;
+ }
+
+ function ErrorNo()
+ {
+ return (strlen($this->ErrorMsg())) ? -1 : 0;
+ }
+
+ // returns true or false
+ function _close()
+ {
+ if ($this->transCnt) $this->RollbackTrans();
+ $this->_resultid = false;
+ @pg_close($this->_connectionID);
+ $this->_connectionID = false;
+ return true;
+ }
+
+
+ /*
+ * Maximum size of C field
+ */
+ function CharMax()
+ {
+ return 1000000000; // should be 1 Gb?
+ }
+
+ /*
+ * Maximum size of X field
+ */
+ function TextMax()
+ {
+ return 1000000000; // should be 1 Gb?
+ }
+
+
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+class ADORecordSet_postgres64 extends ADORecordSet{
+ var $_blobArr;
+ var $databaseType = "postgres64";
+ var $canSeek = true;
+ function ADORecordSet_postgres64($queryID,$mode=false)
+ {
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+ switch ($mode)
+ {
+ case ADODB_FETCH_NUM: $this->fetchMode = PGSQL_NUM; break;
+ case ADODB_FETCH_ASSOC:$this->fetchMode = PGSQL_ASSOC; break;
+ default:
+ case ADODB_FETCH_DEFAULT:
+ case ADODB_FETCH_BOTH:$this->fetchMode = PGSQL_BOTH; break;
+ }
+ $this->ADORecordSet($queryID);
+ }
+
+ function &GetRowAssoc($upper=true)
+ {
+ if ($this->fetchMode == PGSQL_ASSOC && !$upper) return $rs->fields;
+ return ADORecordSet::GetRowAssoc($upper);
+ }
+
+ function _initrs()
+ {
+ global $ADODB_COUNTRECS;
+ $this->_numOfRows = ($ADODB_COUNTRECS)? @pg_numrows($this->_queryID):-1;
+ $this->_numOfFields = @pg_numfields($this->_queryID);
+
+ // cache types for blob decode check
+ for ($i=0, $max = $this->_numOfFields; $i < $max; $i++) {
+ $f1 = $this->FetchField($i);
+ if ($f1->type == 'bytea') $this->_blobArr[$i] = $f1->name;
+ }
+ }
+
+ /* Use associative array to get fields array */
+ function Fields($colname)
+ {
+ if ($this->fetchMode != PGSQL_NUM) return @$this->fields[$colname];
+
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i=0; $i < $this->_numOfFields; $i++) {
+ $o = $this->FetchField($i);
+ $this->bind[strtoupper($o->name)] = $i;
+ }
+ }
+ return $this->fields[$this->bind[strtoupper($colname)]];
+ }
+
+ function &FetchField($fieldOffset = 0)
+ {
+ $off=$fieldOffset; // offsets begin at 0
+
+ $o= new ADOFieldObject();
+ $o->name = @pg_fieldname($this->_queryID,$off);
+ $o->type = @pg_fieldtype($this->_queryID,$off);
+ $o->max_length = @pg_fieldsize($this->_queryID,$off);
+ //print_r($o);
+ //print "off=$off name=$o->name type=$o->type len=$o->max_length<br>";
+ return $o;
+ }
+
+ function _seek($row)
+ {
+ return @pg_fetch_row($this->_queryID,$row);
+ }
+
+ function _decode($blob)
+ {
+
+ eval('$realblob="'.adodb_str_replace(array('"','$'),array('\"','\$'),$blob).'";');
+ return $realblob;
+
+ }
+ function _fixblobs()
+ {
+ if ($this->fetchMode == PGSQL_NUM || $this->fetchMode == PGSQL_BOTH) {
+ foreach($this->_blobArr as $k => $v) {
+ $this->fields[$k] = ADORecordSet_postgres64::_decode($this->fields[$k]);
+ }
+ }
+ if ($this->fetchMode == PGSQL_ASSOC || $this->fetchMode == PGSQL_BOTH) {
+ foreach($this->_blobArr as $k => $v) {
+ $this->fields[$v] = ADORecordSet_postgres64::_decode($this->fields[$v]);
+ }
+ }
+ }
+
+ // 10% speedup to move MoveNext to child class
+ function MoveNext()
+ {
+ if (!$this->EOF) {
+ $this->_currentRow++;
+ if ($this->_numOfRows < 0 || $this->_numOfRows > $this->_currentRow) {
+ $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);
+
+ if (is_array($this->fields)) {
+ if (isset($this->_blobArr)) $this->_fixblobs();
+ return true;
+ }
+ }
+ $this->fields = false;
+ $this->EOF = true;
+ }
+ return false;
+ }
+
+ function _fetch()
+ {
+ if ($this->_currentRow >= $this->_numOfRows && $this->_numOfRows != -1)
+ return false;
+
+ $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);
+ if (isset($this->_blobArr)) $this->_fixblobs();
+
+ return (is_array($this->fields));
+ }
+
+ function _close()
+ {
+ return @pg_freeresult($this->_queryID);
+ }
+
+ function MetaType($t,$len=-1,$fieldobj=false)
+ {
+ if (is_object($t)) {
+ $fieldobj = $t;
+ $t = $fieldobj->type;
+ $len = $fieldobj->max_length;
+ }
+ switch (strtoupper($t)) {
+ case 'INTERVAL':
+ case 'CHAR':
+ case 'CHARACTER':
+ case 'VARCHAR':
+ case 'NAME':
+ case 'BPCHAR':
+ if ($len <= $this->blobSize) return 'C';
+
+ case 'TEXT':
+ return 'X';
+
+ case 'IMAGE': // user defined type
+ case 'BLOB': // user defined type
+ case 'BIT': // This is a bit string, not a single bit, so don't return 'L'
+ case 'VARBIT':
+ case 'BYTEA':
+ return 'B';
+
+ case 'BOOL':
+ case 'BOOLEAN':
+ return 'L';
+
+ case 'DATE':
+ return 'D';
+
+ case 'TIME':
+ case 'DATETIME':
+ case 'TIMESTAMP':
+ case 'TIMESTAMPTZ':
+ return 'T';
+
+ case 'SMALLINT':
+ case 'BIGINT':
+ case 'INTEGER':
+ case 'INT8':
+ case 'INT4':
+ case 'INT2':
+ if (isset($fieldobj) &&
+ empty($fieldobj->primary_key) && empty($fieldobj->unique)) return 'I';
+
+ case 'OID':
+ case 'SERIAL':
+ return 'R';
+
+ default:
+ return 'N';
+ }
+ }
+
+}
+?>