00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 if (!defined('ADODB_DIR')) die();
00047
00048 function adodb_addslashes($s)
00049 {
00050 $len = strlen($s);
00051 if ($len == 0) return "''";
00052 if (strncmp($s,"'",1) === 0 && substr($s,$len-1) == "'") return $s;
00053
00054 return "'".addslashes($s)."'";
00055 }
00056
00057 class ADODB_postgres64 extends ADOConnection{
00058 var $databaseType = 'postgres64';
00059 var $dataProvider = 'postgres';
00060 var $hasInsertID = true;
00061 var $_resultid = false;
00062 var $concat_operator='||';
00063 var $metaDatabasesSQL = "select datname from pg_database where datname not in ('template0','template1') order by 1";
00064 var $metaTablesSQL = "select tablename,'T' from pg_tables where tablename not like 'pg\_%'
00065 and tablename not in ('sql_features', 'sql_implementation_info', 'sql_languages',
00066 'sql_packages', 'sql_sizing', 'sql_sizing_profiles')
00067 union
00068 select viewname,'V' from pg_views where viewname not like 'pg\_%'";
00069
00070 var $isoDates = true;
00071 var $sysDate = "CURRENT_DATE";
00072 var $sysTimeStamp = "CURRENT_TIMESTAMP";
00073 var $blobEncodeType = 'C';
00074 var $metaColumnsSQL = "SELECT a.attname,t.typname,a.attlen,a.atttypmod,a.attnotnull,a.atthasdef,a.attnum
00075 FROM pg_class c, pg_attribute a,pg_type t
00076 WHERE relkind in ('r','v') AND (c.relname='%s' or c.relname = lower('%s')) and a.attname not like '....%%'
00077 AND a.attnum > 0 AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";
00078
00079
00080 var $metaColumnsSQL1 = "SELECT a.attname, t.typname, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, a.attnum
00081 FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n
00082 WHERE relkind in ('r','v') AND (c.relname='%s' or c.relname = lower('%s'))
00083 and c.relnamespace=n.oid and n.nspname='%s'
00084 and a.attname not like '....%%' AND a.attnum > 0
00085 AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";
00086
00087
00088 var $metaKeySQL = "SELECT ic.relname AS index_name, a.attname AS column_name,i.indisunique AS unique_key, i.indisprimary AS primary_key
00089 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'";
00090
00091 var $hasAffectedRows = true;
00092 var $hasLimit = false;
00093
00094 var $true = 'TRUE';
00095 var $false = 'FALSE';
00096 var $fmtDate = "'Y-m-d'";
00097 var $fmtTimeStamp = "'Y-m-d H:i:s'";
00098 var $hasMoveFirst = true;
00099 var $hasGenID = true;
00100 var $_genIDSQL = "SELECT NEXTVAL('%s')";
00101 var $_genSeqSQL = "CREATE SEQUENCE %s START %s";
00102 var $_dropSeqSQL = "DROP SEQUENCE %s";
00103 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";
00104 var $random = 'random()';
00105 var $autoRollback = true;
00106
00107
00108 var $_bindInputArray = false;
00109 var $disableBlobs = false;
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 function ADODB_postgres64()
00120 {
00121
00122 }
00123
00124 function ServerInfo()
00125 {
00126 if (isset($this->version)) return $this->version;
00127
00128 $arr['description'] = $this->GetOne("select version()");
00129 $arr['version'] = ADOConnection::_findvers($arr['description']);
00130 $this->version = $arr;
00131 return $arr;
00132 }
00133
00134 function IfNull( $field, $ifNull )
00135 {
00136 return " coalesce($field, $ifNull) ";
00137 }
00138
00139
00140 function pg_insert_id($tablename,$fieldname)
00141 {
00142 $result=pg_exec($this->_connectionID, "SELECT last_value FROM ${tablename}_${fieldname}_seq");
00143 if ($result) {
00144 $arr = @pg_fetch_row($result,0);
00145 pg_freeresult($result);
00146 if (isset($arr[0])) return $arr[0];
00147 }
00148 return false;
00149 }
00150
00151
00152
00153
00154
00155 function _insertid($table,$column)
00156 {
00157 if (!is_resource($this->_resultid) || get_resource_type($this->_resultid) !== 'pgsql result') return false;
00158 $oid = pg_getlastoid($this->_resultid);
00159
00160 return empty($table) || empty($column) ? $oid : $this->GetOne("SELECT $column FROM $table WHERE oid=".(int)$oid);
00161 }
00162
00163
00164
00165 function _affectedrows()
00166 {
00167 if (!is_resource($this->_resultid) || get_resource_type($this->_resultid) !== 'pgsql result') return false;
00168 return pg_cmdtuples($this->_resultid);
00169 }
00170
00171
00172
00173 function BeginTrans()
00174 {
00175 if ($this->transOff) return true;
00176 $this->transCnt += 1;
00177 return @pg_Exec($this->_connectionID, "begin ".$this->_transmode);
00178 }
00179
00180 function RowLock($tables,$where,$flds='1 as ignore')
00181 {
00182 if (!$this->transCnt) $this->BeginTrans();
00183 return $this->GetOne("select $flds from $tables where $where for update");
00184 }
00185
00186
00187 function CommitTrans($ok=true)
00188 {
00189 if ($this->transOff) return true;
00190 if (!$ok) return $this->RollbackTrans();
00191
00192 $this->transCnt -= 1;
00193 return @pg_Exec($this->_connectionID, "commit");
00194 }
00195
00196
00197 function RollbackTrans()
00198 {
00199 if ($this->transOff) return true;
00200 $this->transCnt -= 1;
00201 return @pg_Exec($this->_connectionID, "rollback");
00202 }
00203
00204 function &MetaTables($ttype=false,$showSchema=false,$mask=false)
00205 {
00206 $info = $this->ServerInfo();
00207 if ($info['version'] >= 7.3) {
00208 $this->metaTablesSQL = "select tablename,'T' from pg_tables where tablename not like 'pg\_%'
00209 and schemaname not in ( 'pg_catalog','information_schema')
00210 union
00211 select viewname,'V' from pg_views where viewname not like 'pg\_%' and schemaname not in ( 'pg_catalog','information_schema') ";
00212 }
00213 if ($mask) {
00214 $save = $this->metaTablesSQL;
00215 $mask = $this->qstr(strtolower($mask));
00216 if ($info['version']>=7.3)
00217 $this->metaTablesSQL = "
00218 select tablename,'T' from pg_tables where tablename like $mask and schemaname not in ( 'pg_catalog','information_schema')
00219 union
00220 select viewname,'V' from pg_views where viewname like $mask and schemaname not in ( 'pg_catalog','information_schema') ";
00221 else
00222 $this->metaTablesSQL = "
00223 select tablename,'T' from pg_tables where tablename like $mask
00224 union
00225 select viewname,'V' from pg_views where viewname like $mask";
00226 }
00227 $ret =& ADOConnection::MetaTables($ttype,$showSchema);
00228
00229 if ($mask) {
00230 $this->metaTablesSQL = $save;
00231 }
00232 return $ret;
00233 }
00234
00235
00236
00237 function qstr($s,$magic_quotes=false)
00238 {
00239 if (!$magic_quotes) {
00240 if (ADODB_PHPVER >= 0x5200) {
00241 return "'".pg_escape_string($this->_connectionID,$s)."'";
00242 }
00243 if (ADODB_PHPVER >= 0x4200) {
00244 return "'".pg_escape_string($s)."'";
00245 }
00246 if ($this->replaceQuote[0] == '\\'){
00247 $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\\000"),$s);
00248 }
00249 return "'".str_replace("'",$this->replaceQuote,$s)."'";
00250 }
00251
00252
00253 $s = str_replace('\\"','"',$s);
00254 return "'$s'";
00255 }
00256
00257
00258
00259
00260 function SQLDate($fmt, $col=false)
00261 {
00262 if (!$col) $col = $this->sysTimeStamp;
00263 $s = 'TO_CHAR('.$col.",'";
00264
00265 $len = strlen($fmt);
00266 for ($i=0; $i < $len; $i++) {
00267 $ch = $fmt[$i];
00268 switch($ch) {
00269 case 'Y':
00270 case 'y':
00271 $s .= 'YYYY';
00272 break;
00273 case 'Q':
00274 case 'q':
00275 $s .= 'Q';
00276 break;
00277
00278 case 'M':
00279 $s .= 'Mon';
00280 break;
00281
00282 case 'm':
00283 $s .= 'MM';
00284 break;
00285 case 'D':
00286 case 'd':
00287 $s .= 'DD';
00288 break;
00289
00290 case 'H':
00291 $s.= 'HH24';
00292 break;
00293
00294 case 'h':
00295 $s .= 'HH';
00296 break;
00297
00298 case 'i':
00299 $s .= 'MI';
00300 break;
00301
00302 case 's':
00303 $s .= 'SS';
00304 break;
00305
00306 case 'a':
00307 case 'A':
00308 $s .= 'AM';
00309 break;
00310
00311 case 'w':
00312 $s .= 'D';
00313 break;
00314
00315 case 'l':
00316 $s .= 'DAY';
00317 break;
00318
00319 case 'W':
00320 $s .= 'WW';
00321 break;
00322
00323 default:
00324
00325 if ($ch == '\\') {
00326 $i++;
00327 $ch = substr($fmt,$i,1);
00328 }
00329 if (strpos('-/.:;, ',$ch) !== false) $s .= $ch;
00330 else $s .= '"'.$ch.'"';
00331
00332 }
00333 }
00334 return $s. "')";
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 function UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB')
00348 {
00349 pg_exec ($this->_connectionID, "begin");
00350
00351 $fd = fopen($path,'r');
00352 $contents = fread($fd,filesize($path));
00353 fclose($fd);
00354
00355 $oid = pg_lo_create($this->_connectionID);
00356 $handle = pg_lo_open($this->_connectionID, $oid, 'w');
00357 pg_lo_write($handle, $contents);
00358 pg_lo_close($handle);
00359
00360
00361 pg_exec($this->_connectionID, "commit");
00362 $rs = ADOConnection::UpdateBlob($table,$column,$oid,$where,$blobtype);
00363 $rez = !empty($rs);
00364 return $rez;
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 function BlobDelete( $blob )
00376 {
00377 pg_exec ($this->_connectionID, "begin");
00378 $result = @pg_lo_unlink($blob);
00379 pg_exec ($this->_connectionID, "commit");
00380 return( $result );
00381 }
00382
00383
00384
00385
00386 function GuessOID($oid)
00387 {
00388 if (strlen($oid)>16) return false;
00389 return is_numeric($oid);
00390 }
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404 function BlobDecode($blob,$maxsize=false,$hastrans=true)
00405 {
00406 if (!$this->GuessOID($blob)) return $blob;
00407
00408 if ($hastrans) @pg_exec($this->_connectionID,"begin");
00409 $fd = @pg_lo_open($this->_connectionID,$blob,"r");
00410 if ($fd === false) {
00411 if ($hastrans) @pg_exec($this->_connectionID,"commit");
00412 return $blob;
00413 }
00414 if (!$maxsize) $maxsize = $this->maxblobsize;
00415 $realblob = @pg_loread($fd,$maxsize);
00416 @pg_loclose($fd);
00417 if ($hastrans) @pg_exec($this->_connectionID,"commit");
00418 return $realblob;
00419 }
00420
00421
00422
00423
00424
00425
00426
00427
00428 function BlobEncode($blob)
00429 {
00430 if (ADODB_PHPVER >= 0x5200) return pg_escape_bytea($this->_connectionID, $blob);
00431 if (ADODB_PHPVER >= 0x4200) return pg_escape_bytea($blob);
00432
00433
00434 $badch = array(chr(92),chr(0),chr(39)); # \ null '
00435 $fixch = array('\\\\134','\\\\000','\\\\047');
00436 return adodb_str_replace($badch,$fixch,$blob);
00437
00438
00439 }
00440
00441
00442 function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
00443 {
00444
00445 if ($blobtype == 'CLOB') {
00446 return $this->Execute("UPDATE $table SET $column=" . $this->qstr($val) . " WHERE $where");
00447 }
00448
00449 return $this->Execute("UPDATE $table SET $column='".$this->BlobEncode($val)."'::bytea WHERE $where");
00450 }
00451
00452 function OffsetDate($dayFraction,$date=false)
00453 {
00454 if (!$date) $date = $this->sysDate;
00455 else if (strncmp($date,"'",1) == 0) {
00456 $len = strlen($date);
00457 if (10 <= $len && $len <= 12) $date = 'date '.$date;
00458 else $date = 'timestamp '.$date;
00459 }
00460 return "($date+interval'$dayFraction days')";
00461 }
00462
00463
00464
00465
00466
00467 function &MetaColumns($table,$normalize=true)
00468 {
00469 global $ADODB_FETCH_MODE;
00470
00471 $schema = false;
00472 $false = false;
00473 $this->_findschema($table,$schema);
00474
00475 if ($normalize) $table = strtolower($table);
00476
00477 $save = $ADODB_FETCH_MODE;
00478 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
00479 if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
00480
00481 if ($schema) $rs =& $this->Execute(sprintf($this->metaColumnsSQL1,$table,$table,$schema));
00482 else $rs =& $this->Execute(sprintf($this->metaColumnsSQL,$table,$table));
00483 if (isset($savem)) $this->SetFetchMode($savem);
00484 $ADODB_FETCH_MODE = $save;
00485
00486 if ($rs === false) {
00487 return $false;
00488 }
00489 if (!empty($this->metaKeySQL)) {
00490
00491
00492
00493
00494
00495 $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
00496
00497 $rskey = $this->Execute(sprintf($this->metaKeySQL,($table)));
00498
00499 $keys =& $rskey->GetArray();
00500 if (isset($savem)) $this->SetFetchMode($savem);
00501 $ADODB_FETCH_MODE = $save;
00502
00503 $rskey->Close();
00504 unset($rskey);
00505 }
00506
00507 $rsdefa = array();
00508 if (!empty($this->metaDefaultsSQL)) {
00509 $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
00510 $sql = sprintf($this->metaDefaultsSQL, ($table));
00511 $rsdef = $this->Execute($sql);
00512 if (isset($savem)) $this->SetFetchMode($savem);
00513 $ADODB_FETCH_MODE = $save;
00514
00515 if ($rsdef) {
00516 while (!$rsdef->EOF) {
00517 $num = $rsdef->fields['num'];
00518 $s = $rsdef->fields['def'];
00519 if (strpos($s,'::')===false && substr($s, 0, 1) == "'") {
00520 $s = substr($s, 1);
00521 $s = substr($s, 0, strlen($s) - 1);
00522 }
00523
00524 $rsdefa[$num] = $s;
00525 $rsdef->MoveNext();
00526 }
00527 } else {
00528 ADOConnection::outp( "==> SQL => " . $sql);
00529 }
00530 unset($rsdef);
00531 }
00532
00533 $retarr = array();
00534 while (!$rs->EOF) {
00535 $fld = new ADOFieldObject();
00536 $fld->name = $rs->fields[0];
00537 $fld->type = $rs->fields[1];
00538 $fld->max_length = $rs->fields[2];
00539 $fld->attnum = $rs->fields[6];
00540
00541 if ($fld->max_length <= 0) $fld->max_length = $rs->fields[3]-4;
00542 if ($fld->max_length <= 0) $fld->max_length = -1;
00543 if ($fld->type == 'numeric') {
00544 $fld->scale = $fld->max_length & 0xFFFF;
00545 $fld->max_length >>= 16;
00546 }
00547
00548
00549 $fld->has_default = ($rs->fields[5] == 't');
00550 if ($fld->has_default) {
00551 $fld->default_value = $rsdefa[$rs->fields[6]];
00552 }
00553
00554
00555 $fld->not_null = $rs->fields[4] == 't';
00556
00557
00558
00559 if (is_array($keys)) {
00560 foreach($keys as $key) {
00561 if ($fld->name == $key['column_name'] AND $key['primary_key'] == 't')
00562 $fld->primary_key = true;
00563 if ($fld->name == $key['column_name'] AND $key['unique_key'] == 't')
00564 $fld->unique = true;
00565 }
00566 }
00567
00568 if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;
00569 else $retarr[($normalize) ? strtoupper($fld->name) : $fld->name] = $fld;
00570
00571 $rs->MoveNext();
00572 }
00573 $rs->Close();
00574 if (empty($retarr))
00575 return $false;
00576 else
00577 return $retarr;
00578
00579 }
00580
00581 function &MetaIndexes ($table, $primary = FALSE)
00582 {
00583 global $ADODB_FETCH_MODE;
00584
00585 $schema = false;
00586 $this->_findschema($table,$schema);
00587
00588 if ($schema) {
00589 $sql = '
00590 SELECT c.relname as "Name", i.indisunique as "Unique", i.indkey as "Columns"
00591 FROM pg_catalog.pg_class c
00592 JOIN pg_catalog.pg_index i ON i.indexrelid=c.oid
00593 JOIN pg_catalog.pg_class c2 ON c2.oid=i.indrelid
00594 ,pg_namespace n
00595 WHERE (c2.relname=\'%s\' or c2.relname=lower(\'%s\')) and c.relnamespace=c2.relnamespace and c.relnamespace=n.oid and n.nspname=\'%s\'';
00596 } else {
00597 $sql = '
00598 SELECT c.relname as "Name", i.indisunique as "Unique", i.indkey as "Columns"
00599 FROM pg_catalog.pg_class c
00600 JOIN pg_catalog.pg_index i ON i.indexrelid=c.oid
00601 JOIN pg_catalog.pg_class c2 ON c2.oid=i.indrelid
00602 WHERE (c2.relname=\'%s\' or c2.relname=lower(\'%s\'))';
00603 }
00604
00605 if ($primary == FALSE) {
00606 $sql .= ' AND i.indisprimary=false;';
00607 }
00608
00609 $save = $ADODB_FETCH_MODE;
00610 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
00611 if ($this->fetchMode !== FALSE) {
00612 $savem = $this->SetFetchMode(FALSE);
00613 }
00614
00615 $rs = $this->Execute(sprintf($sql,$table,$table,$schema));
00616 if (isset($savem)) {
00617 $this->SetFetchMode($savem);
00618 }
00619 $ADODB_FETCH_MODE = $save;
00620
00621 if (!is_object($rs)) {
00622 $false = false;
00623 return $false;
00624 }
00625
00626 $col_names = $this->MetaColumnNames($table,true,true);
00627
00628
00629 $indexes = array();
00630 while ($row = $rs->FetchRow()) {
00631 $columns = array();
00632 foreach (explode(' ', $row[2]) as $col) {
00633 $columns[] = $col_names[$col];
00634 }
00635
00636 $indexes[$row[0]] = array(
00637 'unique' => ($row[1] == 't'),
00638 'columns' => $columns
00639 );
00640 }
00641 return $indexes;
00642 }
00643
00644
00645
00646
00647
00648
00649 function _connect($str,$user='',$pwd='',$db='',$ctype=0)
00650 {
00651
00652 if (!function_exists('pg_connect')) return null;
00653
00654 $this->_errorMsg = false;
00655
00656 if ($user || $pwd || $db) {
00657 $user = adodb_addslashes($user);
00658 $pwd = adodb_addslashes($pwd);
00659 if (strlen($db) == 0) $db = 'template1';
00660 $db = adodb_addslashes($db);
00661 if ($str) {
00662 $host = split(":", $str);
00663 if ($host[0]) $str = "host=".adodb_addslashes($host[0]);
00664 else $str = '';
00665 if (isset($host[1])) $str .= " port=$host[1]";
00666 else if (!empty($this->port)) $str .= " port=".$this->port;
00667 }
00668 if ($user) $str .= " user=".$user;
00669 if ($pwd) $str .= " password=".$pwd;
00670 if ($db) $str .= " dbname=".$db;
00671 }
00672
00673
00674
00675 if ($ctype === 1) {
00676 $this->_connectionID = pg_pconnect($str);
00677 } else {
00678 if ($ctype === -1) {
00679 static $ncnt;
00680
00681 if (empty($ncnt)) $ncnt = 1;
00682 else $ncnt += 1;
00683
00684 $str .= str_repeat(' ',$ncnt);
00685 }
00686 $this->_connectionID = pg_connect($str);
00687 }
00688 if ($this->_connectionID === false) return false;
00689 $this->Execute("set datestyle='ISO'");
00690
00691 $info = $this->ServerInfo();
00692 $this->pgVersion = (float) substr($info['version'],0,3);
00693 if ($this->pgVersion >= 7.1) {
00694 $this->_nestedSQL = true;
00695 }
00696 return true;
00697 }
00698
00699 function _nconnect($argHostname, $argUsername, $argPassword, $argDatabaseName)
00700 {
00701 return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabaseName,-1);
00702 }
00703
00704
00705
00706
00707
00708
00709 function _pconnect($str,$user='',$pwd='',$db='')
00710 {
00711 return $this->_connect($str,$user,$pwd,$db,1);
00712 }
00713
00714
00715
00716 function _query($sql,$inputarr)
00717 {
00718 $this->_errorMsg = false;
00719 if ($inputarr) {
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733 $plan = 'P'.md5($sql);
00734
00735 $execp = '';
00736 foreach($inputarr as $v) {
00737 if ($execp) $execp .= ',';
00738 if (is_string($v)) {
00739 if (strncmp($v,"'",1) !== 0) $execp .= $this->qstr($v);
00740 } else {
00741 $execp .= $v;
00742 }
00743 }
00744
00745 if ($execp) $exsql = "EXECUTE $plan ($execp)";
00746 else $exsql = "EXECUTE $plan";
00747
00748
00749 $rez = @pg_exec($this->_connectionID,$exsql);
00750 if (!$rez) {
00751 # Perhaps plan does not exist? Prepare/compile plan.
00752 $params = '';
00753 foreach($inputarr as $v) {
00754 if ($params) $params .= ',';
00755 if (is_string($v)) {
00756 $params .= 'VARCHAR';
00757 } else if (is_integer($v)) {
00758 $params .= 'INTEGER';
00759 } else {
00760 $params .= "REAL";
00761 }
00762 }
00763 $sqlarr = explode('?',$sql);
00764
00765 $sql = '';
00766 $i = 1;
00767 foreach($sqlarr as $v) {
00768 $sql .= $v.' $'.$i;
00769 $i++;
00770 }
00771 $s = "PREPARE $plan ($params) AS ".substr($sql,0,strlen($sql)-2);
00772
00773 pg_exec($this->_connectionID,$s);
00774
00775 }
00776
00777 $rez = pg_exec($this->_connectionID,$exsql);
00778 } else {
00779
00780 $rez = pg_exec($this->_connectionID,$sql);
00781 }
00782
00783 if ($rez && pg_numfields($rez) <= 0) {
00784 if (is_resource($this->_resultid) && get_resource_type($this->_resultid) === 'pgsql result') {
00785 pg_freeresult($this->_resultid);
00786 }
00787 $this->_resultid = $rez;
00788 return true;
00789 }
00790
00791 return $rez;
00792 }
00793
00794 function _errconnect()
00795 {
00796 if (defined('DB_ERROR_CONNECT_FAILED')) return DB_ERROR_CONNECT_FAILED;
00797 else return 'Database connection failed';
00798 }
00799
00800
00801 function ErrorMsg()
00802 {
00803 if ($this->_errorMsg !== false) return $this->_errorMsg;
00804 if (ADODB_PHPVER >= 0x4300) {
00805 if (!empty($this->_resultid)) {
00806 $this->_errorMsg = @pg_result_error($this->_resultid);
00807 if ($this->_errorMsg) return $this->_errorMsg;
00808 }
00809
00810 if (!empty($this->_connectionID)) {
00811 $this->_errorMsg = @pg_last_error($this->_connectionID);
00812 } else $this->_errorMsg = $this->_errconnect();
00813 } else {
00814 if (empty($this->_connectionID)) $this->_errconnect();
00815 else $this->_errorMsg = @pg_errormessage($this->_connectionID);
00816 }
00817 return $this->_errorMsg;
00818 }
00819
00820 function ErrorNo()
00821 {
00822 $e = $this->ErrorMsg();
00823 if (strlen($e)) {
00824 return ADOConnection::MetaError($e);
00825 }
00826 return 0;
00827 }
00828
00829
00830 function _close()
00831 {
00832 if ($this->transCnt) $this->RollbackTrans();
00833 if ($this->_resultid) {
00834 @pg_freeresult($this->_resultid);
00835 $this->_resultid = false;
00836 }
00837 @pg_close($this->_connectionID);
00838 $this->_connectionID = false;
00839 return true;
00840 }
00841
00842
00843
00844
00845
00846 function CharMax()
00847 {
00848 return 1000000000;
00849 }
00850
00851
00852
00853
00854 function TextMax()
00855 {
00856 return 1000000000;
00857 }
00858
00859
00860 }
00861
00862
00863
00864
00865
00866 class ADORecordSet_postgres64 extends ADORecordSet{
00867 var $_blobArr;
00868 var $databaseType = "postgres64";
00869 var $canSeek = true;
00870 function ADORecordSet_postgres64($queryID,$mode=false)
00871 {
00872 if ($mode === false) {
00873 global $ADODB_FETCH_MODE;
00874 $mode = $ADODB_FETCH_MODE;
00875 }
00876 switch ($mode)
00877 {
00878 case ADODB_FETCH_NUM: $this->fetchMode = PGSQL_NUM; break;
00879 case ADODB_FETCH_ASSOC:$this->fetchMode = PGSQL_ASSOC; break;
00880
00881 case ADODB_FETCH_DEFAULT:
00882 case ADODB_FETCH_BOTH:
00883 default: $this->fetchMode = PGSQL_BOTH; break;
00884 }
00885 $this->adodbFetchMode = $mode;
00886 $this->ADORecordSet($queryID);
00887 }
00888
00889 function &GetRowAssoc($upper=true)
00890 {
00891 if ($this->fetchMode == PGSQL_ASSOC && !$upper) return $this->fields;
00892 $row =& ADORecordSet::GetRowAssoc($upper);
00893 return $row;
00894 }
00895
00896 function _initrs()
00897 {
00898 global $ADODB_COUNTRECS;
00899 $qid = $this->_queryID;
00900 $this->_numOfRows = ($ADODB_COUNTRECS)? @pg_numrows($qid):-1;
00901 $this->_numOfFields = @pg_numfields($qid);
00902
00903
00904
00905 if (empty($this->connection->noBlobs))
00906 for ($i=0, $max = $this->_numOfFields; $i < $max; $i++) {
00907 if (pg_fieldtype($qid,$i) == 'bytea') {
00908 $this->_blobArr[$i] = pg_fieldname($qid,$i);
00909 }
00910 }
00911 }
00912
00913
00914 function Fields($colname)
00915 {
00916 if ($this->fetchMode != PGSQL_NUM) return @$this->fields[$colname];
00917
00918 if (!$this->bind) {
00919 $this->bind = array();
00920 for ($i=0; $i < $this->_numOfFields; $i++) {
00921 $o = $this->FetchField($i);
00922 $this->bind[strtoupper($o->name)] = $i;
00923 }
00924 }
00925 return $this->fields[$this->bind[strtoupper($colname)]];
00926 }
00927
00928 function &FetchField($off = 0)
00929 {
00930
00931
00932 $o= new ADOFieldObject();
00933 $o->name = @pg_fieldname($this->_queryID,$off);
00934 $o->type = @pg_fieldtype($this->_queryID,$off);
00935 $o->max_length = @pg_fieldsize($this->_queryID,$off);
00936 return $o;
00937 }
00938
00939 function _seek($row)
00940 {
00941 return @pg_fetch_row($this->_queryID,$row);
00942 }
00943
00944 function _decode($blob)
00945 {
00946 eval('$realblob="'.adodb_str_replace(array('"','$'),array('\"','\$'),$blob).'";');
00947 return $realblob;
00948 }
00949
00950 function _fixblobs()
00951 {
00952 if ($this->fetchMode == PGSQL_NUM || $this->fetchMode == PGSQL_BOTH) {
00953 foreach($this->_blobArr as $k => $v) {
00954 $this->fields[$k] = ADORecordSet_postgres64::_decode($this->fields[$k]);
00955 }
00956 }
00957 if ($this->fetchMode == PGSQL_ASSOC || $this->fetchMode == PGSQL_BOTH) {
00958 foreach($this->_blobArr as $k => $v) {
00959 $this->fields[$v] = ADORecordSet_postgres64::_decode($this->fields[$v]);
00960 }
00961 }
00962 }
00963
00964 // 10% speedup to move MoveNext to child class
00965 function MoveNext()
00966 {
00967 if (!$this->EOF) {
00968 $this->_currentRow++;
00969 if ($this->_numOfRows < 0 || $this->_numOfRows > $this->_currentRow) {
00970 $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);
00971 if (is_array($this->fields) && $this->fields) {
00972 if (isset($this->_blobArr)) $this->_fixblobs();
00973 return true;
00974 }
00975 }
00976 $this->fields = false;
00977 $this->EOF = true;
00978 }
00979 return false;
00980 }
00981
00982 function _fetch()
00983 {
00984
00985 if ($this->_currentRow >= $this->_numOfRows && $this->_numOfRows >= 0)
00986 return false;
00987
00988 $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);
00989
00990 if ($this->fields && isset($this->_blobArr)) $this->_fixblobs();
00991
00992 return (is_array($this->fields));
00993 }
00994
00995 function _close()
00996 {
00997 return @pg_freeresult($this->_queryID);
00998 }
00999
01000 function MetaType($t,$len=-1,$fieldobj=false)
01001 {
01002 if (is_object($t)) {
01003 $fieldobj = $t;
01004 $t = $fieldobj->type;
01005 $len = $fieldobj->max_length;
01006 }
01007 switch (strtoupper($t)) {
01008 case 'MONEY': // stupid, postgres expects money to be a string
01009 case 'INTERVAL':
01010 case 'CHAR':
01011 case 'CHARACTER':
01012 case 'VARCHAR':
01013 case 'NAME':
01014 case 'BPCHAR':
01015 case '_VARCHAR':
01016 case 'INET':
01017 case 'MACADDR':
01018 if ($len <= $this->blobSize) return 'C';
01019
01020 case 'TEXT':
01021 return 'X';
01022
01023 case 'IMAGE': // user defined type
01024 case 'BLOB': // user defined type
01025 case 'BIT': // This is a bit string, not a single bit, so don't return 'L'
01026 case 'VARBIT':
01027 case 'BYTEA':
01028 return 'B';
01029
01030 case 'BOOL':
01031 case 'BOOLEAN':
01032 return 'L';
01033
01034 case 'DATE':
01035 return 'D';
01036
01037
01038 case 'TIMESTAMP WITHOUT TIME ZONE':
01039 case 'TIME':
01040 case 'DATETIME':
01041 case 'TIMESTAMP':
01042 case 'TIMESTAMPTZ':
01043 return 'T';
01044
01045 case 'SMALLINT':
01046 case 'BIGINT':
01047 case 'INTEGER':
01048 case 'INT8':
01049 case 'INT4':
01050 case 'INT2':
01051 if (isset($fieldobj) &&
01052 empty($fieldobj->primary_key) && empty($fieldobj->unique)) return 'I';
01053
01054 case 'OID':
01055 case 'SERIAL':
01056 return 'R';
01057
01058 default:
01059 return 'N';
01060 }
01061 }
01062
01063 }
01064 ?>