46 if (!defined(
'ADODB_DIR'))
die();
51 if ($len == 0)
return "''";
52 if (strncmp($s,
"'",1) === 0 && substr($s,$len-1) ==
"'")
return $s;
54 return "'".addslashes($s).
"'";
63 var
$metaDatabasesSQL =
"select datname from pg_database where datname not in ('template0','template1') order by 1";
64 var
$metaTablesSQL =
"select tablename,'T' from pg_tables where tablename not like 'pg\_%' 65 and tablename not in ('sql_features', 'sql_implementation_info', 'sql_languages', 66 'sql_packages', 'sql_sizing', 'sql_sizing_profiles') 68 select viewname,'V' from pg_views where viewname not like 'pg\_%'";
74 var
$metaColumnsSQL =
"SELECT a.attname,t.typname,a.attlen,a.atttypmod,a.attnotnull,a.atthasdef,a.attnum 75 FROM pg_class c, pg_attribute a,pg_type t 76 WHERE relkind in ('r','v') AND (c.relname='%s' or c.relname = lower('%s')) and a.attname not like '....%%' 77 AND a.attnum > 0 AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";
80 var
$metaColumnsSQL1 =
"SELECT a.attname, t.typname, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, a.attnum 81 FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n 82 WHERE relkind in ('r','v') AND (c.relname='%s' or c.relname = lower('%s')) 83 and c.relnamespace=n.oid and n.nspname='%s' 84 and a.attname not like '....%%' AND a.attnum > 0 85 AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";
88 var
$metaKeySQL =
"SELECT ic.relname AS index_name, a.attname AS column_name,i.indisunique AS unique_key, i.indisprimary AS primary_key 89 FROM pg_class bc, pg_class ic, pg_index i, pg_attribute a 90 WHERE bc.oid = i.indrelid AND ic.oid = i.indexrelid 91 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) 92 AND a.attrelid = bc.oid AND bc.relname = '%s'";
106 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";
132 if (isset($this->version))
return $this->version;
134 $arr[
'description'] = $this->GetOne(
"select version()");
135 $arr[
'version'] = ADOConnection::_findvers($arr[
'description']);
136 $this->version = $arr;
142 return " coalesce($field, $ifNull) ";
148 $result=pg_exec($this->_connectionID,
"SELECT last_value FROM ${tablename}_${fieldname}_seq");
150 $arr = @pg_fetch_row(
$result,0);
152 if (isset($arr[0]))
return $arr[0];
163 if (!is_resource($this->_resultid) || get_resource_type($this->_resultid) !==
'pgsql result')
return false;
164 $oid = pg_getlastoid($this->_resultid);
166 return empty($table) || empty($column) ? $oid : $this->GetOne(
"SELECT $column FROM $table WHERE oid=".(
int)$oid);
173 if (!is_resource($this->_resultid) || get_resource_type($this->_resultid) !==
'pgsql result')
return false;
174 return pg_cmdtuples($this->_resultid);
181 if ($this->transOff)
return true;
182 $this->transCnt += 1;
183 return @pg_Exec($this->_connectionID,
"begin ".$this->_transmode);
186 function RowLock($tables,$where,$col=
'1 as adodbignore')
189 return $this->GetOne(
"select $col from $tables where $where for update");
195 if ($this->transOff)
return true;
198 $this->transCnt -= 1;
199 return @pg_Exec($this->_connectionID,
"commit");
205 if ($this->transOff)
return true;
206 $this->transCnt -= 1;
207 return @pg_Exec($this->_connectionID,
"rollback");
210 function MetaTables($ttype=
false,$showSchema=
false,$mask=
false)
213 if ($info[
'version'] >= 7.3) {
214 $this->metaTablesSQL =
" 215 select table_name,'T' from information_schema.tables where table_schema not in ( 'pg_catalog','information_schema') 217 select table_name,'V' from information_schema.views where table_schema not in ( 'pg_catalog','information_schema') ";
221 $mask = $this->
qstr(strtolower($mask));
222 if ($info[
'version']>=7.3)
223 $this->metaTablesSQL =
" 224 select table_name,'T' from information_schema.tables where table_name like $mask and table_schema not in ( 'pg_catalog','information_schema') 226 select table_name,'V' from information_schema.views where table_name like $mask and table_schema not in ( 'pg_catalog','information_schema') ";
228 $this->metaTablesSQL =
" 229 select tablename,'T' from pg_tables where tablename like $mask 231 select viewname,'V' from pg_views where viewname like $mask";
233 $ret = ADOConnection::MetaTables($ttype,$showSchema);
236 $this->metaTablesSQL = $save;
243 function qstr($s,$magic_quotes=
false)
245 if (is_bool($s))
return $s ?
'true' :
'false';
247 if (!$magic_quotes) {
248 if (ADODB_PHPVER >= 0x5200 && $this->_connectionID) {
249 return "'".pg_escape_string($this->_connectionID,$s).
"'";
251 if (ADODB_PHPVER >= 0x4200) {
252 return "'".pg_escape_string($s).
"'";
254 if ($this->replaceQuote[0] ==
'\\'){
255 $s = adodb_str_replace(array(
'\\',
"\0"),array(
'\\\\',
"\\\\000"),$s);
257 return "'".str_replace(
"'",$this->replaceQuote,$s).
"'";
261 $s = str_replace(
'\\"',
'"',$s);
271 $s =
'TO_CHAR('.$col.
",'";
274 for ($i=0; $i < $len; $i++) {
335 $ch = substr($fmt,$i,1);
337 if (strpos(
'-/.:;, ',$ch) !==
false) $s .= $ch;
338 else $s .=
'"'.$ch.
'"';
357 pg_exec ($this->_connectionID,
"begin");
359 $fd = fopen($path,
'r');
360 $contents = fread($fd,filesize($path));
363 $oid = pg_lo_create($this->_connectionID);
364 $handle = pg_lo_open($this->_connectionID, $oid,
'w');
365 pg_lo_write($handle, $contents);
366 pg_lo_close($handle);
369 pg_exec($this->_connectionID,
"commit");
370 $rs = ADOConnection::UpdateBlob($table,$column,$oid,$where,$blobtype);
385 pg_exec ($this->_connectionID,
"begin");
386 $result = @pg_lo_unlink($blob);
387 pg_exec ($this->_connectionID,
"commit");
396 if (strlen($oid)>16)
return false;
397 return is_numeric($oid);
414 if (!$this->
GuessOID($blob))
return $blob;
416 if ($hastrans) @pg_exec($this->_connectionID,
"begin");
417 $fd = @pg_lo_open($this->_connectionID,$blob,
"r");
419 if ($hastrans) @pg_exec($this->_connectionID,
"commit");
422 if (!$maxsize) $maxsize = $this->maxblobsize;
423 $realblob = @pg_loread($fd,$maxsize);
425 if ($hastrans) @pg_exec($this->_connectionID,
"commit");
438 if (ADODB_PHPVER >= 0x5200)
return pg_escape_bytea($this->_connectionID, $blob);
439 if (ADODB_PHPVER >= 0x4200)
return pg_escape_bytea($blob);
442 $badch = array(chr(92),chr(0),chr(39)); # \ null
' 443 $fixch = array('\\\\134
','\\\\000
','\\\\047
'); 444 return adodb_str_replace($badch,$fixch,$blob); 446 // note that there is a pg_escape_bytea function only for php 4.2.0 or later 449 // assumes bytea for blob, and varchar for clob 450 function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB
') 452 if ($blobtype == 'CLOB
') { 453 return $this->Execute("UPDATE $table SET $column=" . $this->qstr($val) . " WHERE $where"); 455 // do not use bind params which uses qstr(), as blobencode() already quotes data 456 return $this->Execute("UPDATE $table SET $column='".$this->BlobEncode($val)."'::bytea WHERE $where"); 459 function OffsetDate($dayFraction,$date=false) 461 if (!$date) $date = $this->sysDate; 462 else if (strncmp($date,"'",1) == 0) { 463 $len = strlen($date); 464 if (10 <= $len && $len <= 12) $date = 'date '.$date; 465 else $date = 'timestamp '.$date; 469 return "($date+interval
'".($dayFraction * 1440)." minutes')
"; 470 #return "($date+interval
'$dayFraction days')
"; 474 // for schema support, pass in the $table param "$schema.$tabname
". 475 // converts field names to lowercase, $upper is ignored 476 // see http://phplens.com/lens/lensforum/msgs.php?id=14018 for more info 477 function MetaColumns($table,$normalize=true) 479 global $ADODB_FETCH_MODE; 483 $this->_findschema($table,$schema); 485 if ($normalize) $table = strtolower($table); 487 $save = $ADODB_FETCH_MODE; 488 $ADODB_FETCH_MODE = ADODB_FETCH_NUM; 489 if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false); 491 if ($schema) $rs = $this->Execute(sprintf($this->metaColumnsSQL1,$table,$table,$schema)); 492 else $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table,$table,$table)); 493 if (isset($savem)) $this->SetFetchMode($savem); 494 $ADODB_FETCH_MODE = $save; 499 if (!empty($this->metaKeySQL)) { 500 // If we want the primary keys, we have to issue a separate query 501 // Of course, a modified version of the metaColumnsSQL query using a 502 // LEFT JOIN would have been much more elegant, but postgres does 503 // not support OUTER JOINS. So here is the clumsy way. 505 $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC; 507 $rskey = $this->Execute(sprintf($this->metaKeySQL,($table))); 508 // fetch all result in once for performance. 509 $keys = $rskey->GetArray(); 510 if (isset($savem)) $this->SetFetchMode($savem); 511 $ADODB_FETCH_MODE = $save; 518 if (!empty($this->metaDefaultsSQL)) { 519 $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC; 520 $sql = sprintf($this->metaDefaultsSQL, ($table)); 521 $rsdef = $this->Execute($sql); 522 if (isset($savem)) $this->SetFetchMode($savem); 523 $ADODB_FETCH_MODE = $save; 526 while (!$rsdef->EOF) { 527 $num = $rsdef->fields['num']; 528 $s = $rsdef->fields['def']; 529 if (strpos($s,'::')===false && substr($s, 0, 1) == "'") { /* quoted strings hack... for now... fixme */ 531 $s = substr($s, 0, strlen($s) - 1); 538 ADOConnection::outp( "==> SQL => " . $sql); 545 $fld = new ADOFieldObject(); 546 $fld->name = $rs->fields[0]; 547 $fld->type = $rs->fields[1]; 548 $fld->max_length = $rs->fields[2]; 549 $fld->attnum = $rs->fields[6]; 551 if ($fld->max_length <= 0) $fld->max_length = $rs->fields[3]-4; 552 if ($fld->max_length <= 0) $fld->max_length = -1; 553 if ($fld->type == 'numeric
') { 554 $fld->scale = $fld->max_length & 0xFFFF; 555 $fld->max_length >>= 16; 558 // 5 hasdefault; 6 num-of-column 559 $fld->has_default = ($rs->fields[5] == 't
'); 560 if ($fld->has_default) { 561 $fld->default_value = $rsdefa[$rs->fields[6]]; 565 $fld->not_null = $rs->fields[4] == 't
'; 569 if (is_array($keys)) { 570 foreach($keys as $key) { 571 if ($fld->name == $key['column_name
'] AND $key['primary_key
'] == 't
') 572 $fld->primary_key = true; 573 if ($fld->name == $key['column_name
'] AND $key['unique_key
'] == 't
') 574 $fld->unique = true; // What name is more compatible? 578 if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld; 579 else $retarr[($normalize) ? strtoupper($fld->name) : $fld->name] = $fld; 591 function Param($name,$type='C
') 596 // Reset param num if $name is false 599 return '$
'.$this->_pnum; 602 function MetaIndexes ($table, $primary = FALSE, $owner = false) 604 global $ADODB_FETCH_MODE; 607 $this->_findschema($table,$schema); 609 if ($schema) { // requires pgsql 7.3+ - pg_namespace used. 611 SELECT c.relname as
"Name", i.indisunique as
"Unique", i.indkey as
"Columns" 612 FROM pg_catalog.pg_class c
613 JOIN pg_catalog.pg_index i ON i.indexrelid=c.oid
614 JOIN pg_catalog.pg_class c2 ON c2.oid=i.indrelid
616 WHERE (c2.relname=\
'%s\' or c2.relname=lower(\'%s\')) 617 and c.relnamespace=c2.relnamespace 618 and c.relnamespace=n.oid 619 and n.nspname=\'%s\'';
622 SELECT c.relname as "Name", i.indisunique as "Unique", i.indkey as "Columns" 623 FROM pg_catalog.pg_class c 624 JOIN pg_catalog.pg_index i ON i.indexrelid=c.oid 625 JOIN pg_catalog.pg_class c2 ON c2.oid=i.indrelid 626 WHERE (c2.relname=\'%s\' or c2.relname=lower(\'%s\'))';
629 if ($primary == FALSE) {
630 $sql .=
' AND i.indisprimary=false;';
633 $save = $ADODB_FETCH_MODE;
634 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
635 if ($this->fetchMode !== FALSE) {
636 $savem = $this->SetFetchMode(FALSE);
639 $rs = $this->Execute(sprintf(
$sql,$table,$table,$schema));
641 $this->SetFetchMode($savem);
643 $ADODB_FETCH_MODE = $save;
645 if (!is_object(
$rs)) {
650 $col_names = $this->MetaColumnNames($table,
true,
true);
654 while ($row =
$rs->FetchRow()) {
656 foreach (explode(
' ', $row[2]) as $col) {
657 $columns[] = $col_names[$col];
660 $indexes[$row[0]] = array(
661 'unique' => ($row[1] ==
't'),
662 'columns' => $columns
675 if (!function_exists(
'pg_connect'))
return null;
677 $this->_errorMsg =
false;
679 if ($user ||
$pwd || $db) {
682 if (strlen($db) == 0) $db =
'template1';
685 $host = explode(
":", $str);
686 if (
$host[0]) $str =
"host=".adodb_addslashes(
$host[0]);
688 if (isset(
$host[1])) $str .=
" port=$host[1]";
689 else if (!empty($this->port)) $str .=
" port=".$this->port;
691 if ($user) $str .=
" user=".$user;
692 if (
$pwd) $str .=
" password=".$pwd;
693 if ($db) $str .=
" dbname=".$db;
699 $this->_connectionID = pg_pconnect($str);
704 if (empty($ncnt)) $ncnt = 1;
707 $str .= str_repeat(
' ',$ncnt);
709 $this->_connectionID = pg_connect($str);
711 if ($this->_connectionID ===
false)
return false;
712 $this->Execute(
"set datestyle='ISO'");
715 $this->pgVersion = (float) substr($info[
'version'],0,3);
716 if ($this->pgVersion >= 7.1) {
717 $this->_nestedSQL =
true;
720 # PostgreSQL 9.0 changed the default output for bytea from 'escape' to 'hex' 721 # PHP does not handle 'hex' properly ('x74657374' is returned as 't657374') 722 # https://bugs.php.net/bug.php?id=59831 states this is in fact not a bug, 723 # so we manually set bytea_output 724 if (version_compare($info[
'version'],
'9.0',
'>=')) {
725 $this->Execute(
'set bytea_output=escape');
731 function _nconnect($argHostname, $argUsername, $argPassword, $argDatabaseName)
733 return $this->
_connect($argHostname, $argUsername, $argPassword, $argDatabaseName,-1);
751 $this->_errorMsg =
false;
766 $plan =
'P'.md5(
$sql);
769 foreach($inputarr as $v) {
770 if ($execp) $execp .=
',';
772 if (strncmp($v,
"'",1) !== 0) $execp .= $this->
qstr($v);
778 if ($execp) $exsql =
"EXECUTE $plan ($execp)";
779 else $exsql =
"EXECUTE $plan";
782 $rez = @pg_exec($this->_connectionID,$exsql);
784 # Perhaps plan does not exist? Prepare/compile plan. 786 foreach($inputarr as $v) {
787 if ($params) $params .=
',';
789 $params .=
'VARCHAR';
790 }
else if (is_integer($v)) {
791 $params .=
'INTEGER';
796 $sqlarr = explode(
'?',
$sql);
800 foreach($sqlarr as $v) {
804 $s =
"PREPARE $plan ($params) AS ".substr(
$sql,0,strlen(
$sql)-2);
806 $rez = pg_exec($this->_connectionID,$s);
810 $rez = pg_exec($this->_connectionID,$exsql);
813 $rez = pg_exec($this->_connectionID,
$sql);
816 if ($rez && pg_numfields($rez) <= 0) {
817 if (is_resource($this->_resultid) && get_resource_type($this->_resultid) ===
'pgsql result') {
818 pg_freeresult($this->_resultid);
820 $this->_resultid = $rez;
829 if (defined(
'DB_ERROR_CONNECT_FAILED'))
return DB_ERROR_CONNECT_FAILED;
830 else return 'Database connection failed';
836 if ($this->_errorMsg !==
false)
return $this->_errorMsg;
837 if (ADODB_PHPVER >= 0x4300) {
838 if (!empty($this->_resultid)) {
839 $this->_errorMsg = @pg_result_error($this->_resultid);
840 if ($this->_errorMsg)
return $this->_errorMsg;
843 if (!empty($this->_connectionID)) {
844 $this->_errorMsg = @pg_last_error($this->_connectionID);
847 if (empty($this->_connectionID)) $this->
_errconnect();
848 else $this->_errorMsg = @pg_errormessage($this->_connectionID);
850 return $this->_errorMsg;
857 return ADOConnection::MetaError($e);
866 if ($this->_resultid) {
867 @pg_freeresult($this->_resultid);
868 $this->_resultid =
false;
870 @pg_close($this->_connectionID);
871 $this->_connectionID =
false;
901 var $databaseType =
"postgres64";
906 if ($mode ===
false) {
907 global $ADODB_FETCH_MODE;
908 $mode = $ADODB_FETCH_MODE;
912 case ADODB_FETCH_NUM: $this->fetchMode = PGSQL_NUM;
break;
913 case ADODB_FETCH_ASSOC:$this->fetchMode = PGSQL_ASSOC;
break;
915 case ADODB_FETCH_DEFAULT:
916 case ADODB_FETCH_BOTH:
917 default: $this->fetchMode = PGSQL_BOTH;
break;
919 $this->adodbFetchMode = $mode;
922 $this->ADORecordSet($queryID);
927 if ($this->fetchMode == PGSQL_ASSOC && !$upper)
return $this->fields;
928 $row = ADORecordSet::GetRowAssoc($upper);
935 global $ADODB_COUNTRECS;
936 $qid = $this->_queryID;
937 $this->_numOfRows = ($ADODB_COUNTRECS)? @pg_numrows($qid):-1;
938 $this->_numOfFields = @pg_numfields($qid);
942 if (empty($this->connection->noBlobs))
943 for ($i=0, $max = $this->_numOfFields; $i < $max; $i++) {
944 if (pg_fieldtype($qid,$i) ==
'bytea') {
945 $this->_blobArr[$i] = pg_fieldname($qid,$i);
953 if ($this->fetchMode != PGSQL_NUM)
return @$this->fields[$colname];
956 $this->bind = array();
957 for ($i=0; $i < $this->_numOfFields; $i++) {
958 $o = $this->FetchField($i);
959 $this->bind[strtoupper($o->name)] = $i;
962 return $this->fields[$this->bind[strtoupper($colname)]];
969 $o=
new ADOFieldObject();
970 $o->name = @pg_fieldname($this->_queryID,$off);
971 $o->type = @pg_fieldtype($this->_queryID,$off);
972 $o->max_length = @pg_fieldsize($this->_queryID,$off);
978 return @pg_fetch_row($this->_queryID,$row);
983 if ($blob === NULL)
return NULL;
985 return pg_unescape_bytea($blob);
990 if ($this->fetchMode == PGSQL_NUM || $this->fetchMode == PGSQL_BOTH) {
991 foreach($this->_blobArr as $k => $v) {
995 if ($this->fetchMode == PGSQL_ASSOC || $this->fetchMode == PGSQL_BOTH) {
996 foreach($this->_blobArr as $k => $v) {
1006 $this->_currentRow++;
1007 if ($this->_numOfRows < 0 || $this->_numOfRows > $this->_currentRow) {
1008 $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);
1009 if (is_array($this->fields) && $this->fields) {
1010 if (isset($this->_blobArr)) $this->_fixblobs();
1014 $this->fields =
false;
1023 if ($this->_currentRow >= $this->_numOfRows && $this->_numOfRows >= 0)
1026 $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);
1028 if ($this->fields && isset($this->_blobArr)) $this->_fixblobs();
1030 return (is_array($this->fields));
1035 return @pg_freeresult($this->_queryID);
1040 if (is_object($t)) {
1042 $t = $fieldobj->type;
1043 $len = $fieldobj->max_length;
1045 switch (strtoupper($t)) {
1056 if ($len <= $this->blobSize)
return 'C';
1076 case 'TIMESTAMP WITHOUT TIME ZONE':
1089 if (isset($fieldobj) &&
1090 empty($fieldobj->primary_key) && (!$this->connection->uniqueIisR || empty($fieldobj->unique)))
return 'I';
_connect($str, $user='', $pwd='', $db='', $ctype=0)
MetaTables($ttype=false, $showSchema=false, $mask=false)
__construct($queryID, $mode=false)
MetaType($t, $len=-1, $fieldobj=false)
if(isset($_REQUEST['nrows'])) else $rs
pg_insert_id($tablename, $fieldname)
UpdateBlobFile($table, $column, $path, $where, $blobtype='BLOB')
_nconnect($argHostname, $argUsername, $argPassword, $argDatabaseName)
_insertid($table, $column)
BlobDecode($blob, $maxsize=false, $hastrans=true)
if($list_of_literals) if(!empty($literals)) if(!empty($literals)) $result
Analyse literals to prepend the N char to them if their contents aren't numeric.
$autoRollback
random function
SQLDate($fmt, $col=false)
_pconnect($str, $user='', $pwd='', $db='')
qstr($s, $magic_quotes=false)
_query($sql, $inputarr=false)
RowLock($tables, $where, $col='1 as adodbignore')