Documentation TYPO3 par Ameos

adodb-postgres64.inc.php

00001 <?php
00002 /*
00003  V4.93 10 Oct 2006  (c) 2000-2006 John Lim (jlim#natsoft.com.my). All rights reserved.
00004   Released under both BSD license and Lesser GPL library license. 
00005   Whenever there is any discrepancy between the two licenses, 
00006   the BSD license will take precedence.
00007   Set tabs to 8.
00008   
00009   Original version derived from Alberto Cerezal (acerezalp@dbnet.es) - DBNet Informatica & Comunicaciones. 
00010   08 Nov 2000 jlim - Minor corrections, removing mysql stuff
00011   09 Nov 2000 jlim - added insertid support suggested by "Christopher Kings-Lynne" <chriskl@familyhealth.com.au>
00012                                         jlim - changed concat operator to || and data types to MetaType to match documented pgsql types 
00013                         see http://www.postgresql.org/devel-corner/docs/postgres/datatype.htm  
00014   22 Nov 2000 jlim - added changes to FetchField() and MetaTables() contributed by "raser" <raser@mail.zen.com.tw>
00015   27 Nov 2000 jlim - added changes to _connect/_pconnect from ideas by "Lennie" <leen@wirehub.nl>
00016   15 Dec 2000 jlim - added changes suggested by Additional code changes by "Eric G. Werk" egw@netguide.dk. 
00017   31 Jan 2002 jlim - finally installed postgresql. testing
00018   01 Mar 2001 jlim - Freek Dijkstra changes, also support for text type
00019   
00020   See http://www.varlena.com/varlena/GeneralBits/47.php
00021   
00022         -- What indexes are on my table?
00023         select * from pg_indexes where tablename = 'tablename';
00024         
00025         -- What triggers are on my table?
00026         select c.relname as "Table", t.tgname as "Trigger Name", 
00027            t.tgconstrname as "Constraint Name", t.tgenabled as "Enabled",
00028            t.tgisconstraint as "Is Constraint", cc.relname as "Referenced Table",
00029            p.proname as "Function Name"
00030         from pg_trigger t, pg_class c, pg_class cc, pg_proc p
00031         where t.tgfoid = p.oid and t.tgrelid = c.oid
00032            and t.tgconstrrelid = cc.oid
00033            and c.relname = 'tablename';
00034         
00035         -- What constraints are on my table?
00036         select r.relname as "Table", c.conname as "Constraint Name",
00037            contype as "Constraint Type", conkey as "Key Columns",
00038            confkey as "Foreign Columns", consrc as "Source"
00039         from pg_class r, pg_constraint c
00040         where r.oid = c.conrelid
00041            and relname = 'tablename';
00042 
00043 */
00044 
00045 // security - hide paths
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; // already quoted
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         //"select tablename from pg_tables where tablename not like 'pg_%' order by 1";
00070         var $isoDates = true; // accepts dates in ISO format
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         // used when schema defined
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         // get primary key etc -- from Freek Dijkstra
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;  // set to true for pgsql 7 only. support pgsql/mysql SELECT * FROM TABLE LIMIT 10
00093         // below suggested by Freek Dijkstra 
00094         var $true = 'TRUE';             // string that represents TRUE for a database
00095         var $false = 'FALSE';           // string that represents FALSE for a database
00096         var $fmtDate = "'Y-m-d'";       // used by DBDate() as the default date format used by the database
00097         var $fmtTimeStamp = "'Y-m-d H:i:s'"; // used by DBTimeStamp as the default timestamp fmt.
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; // apparently pgsql does not autorollback properly before php 4.3.4
00106                                                         // http://bugs.php.net/bug.php?id=25404
00107                                                         
00108         var $_bindInputArray = false; // requires postgresql 7.3+ and ability to modify database
00109         var $disableBlobs = false; // set to true to disable blob checking, resulting in 2-5% improvement in performance.
00110         
00111         // The last (fmtTimeStamp is not entirely correct: 
00112         // PostgreSQL also has support for time zones, 
00113         // and writes these time in this format: "2001-03-01 18:59:26+02". 
00114         // There is no code for the "+02" time zone information, so I just left that out. 
00115         // I'm not familiar enough with both ADODB as well as Postgres 
00116         // to know what the concequences are. The other values are correct (wheren't in 0.94)
00117         // -- Freek Dijkstra 
00118 
00119         function ADODB_postgres64() 
00120         {
00121         // changes the metaColumnsSQL, adds columns: attnum[6]
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         // get the last id - never tested
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 /* Warning from http://www.php.net/manual/function.pg-getlastoid.php:
00152 Using a OID as a unique identifier is not generally wise. 
00153 Unless you are very careful, you might end up with a tuple having 
00154 a different OID if a database must be reloaded. */
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                 // to really return the id, we need the table and column-name, else we can only return the oid != id
00160                 return empty($table) || empty($column) ? $oid : $this->GetOne("SELECT $column FROM $table WHERE oid=".(int)$oid);
00161         }
00162 
00163 // I get this error with PHP before 4.0.6 - jlim
00164 // Warning: This compilation does not support pg_cmdtuples() in adodb-postgres.inc.php on line 44
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                 // returns true/false
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         // returns true/false. 
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         // returns true/false
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         // if magic quotes disabled, use pg_escape_string()
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                 // undo magic quotes for "
00253                 $s = str_replace('\\"','"',$s);
00254                 return "'$s'";
00255         }
00256         
00257         
00258         
00259         // Format date column in sql string given an input format that understands Y M D
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                         // handle escape characters...
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         * Load a Large Object from a file 
00341         * - the procedure stores the object id in the table and imports the object using 
00342         * postgres proprietary blob handling routines 
00343         *
00344         * contributed by Mattia Rossi mattia@technologist.com
00345         * modified for safe mode by juraj chlebec
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                 // $oid = pg_lo_import ($path); 
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         * Deletes/Unlinks a Blob from the database, otherwise it 
00369         * will be left behind
00370         *
00371         * Returns TRUE on success or FALSE on failure.
00372         *
00373         * contributed by Todd Rogers todd#windfox.net
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                 Hueristic - not guaranteed to work.
00385         */
00386         function GuessOID($oid)
00387         {
00388                 if (strlen($oid)>16) return false;
00389                 return is_numeric($oid);
00390         }
00391         
00392         /* 
00393         * If an OID is detected, then we use pg_lo_* to open the oid file and read the
00394         * real blob from the db using the oid supplied as a parameter. If you are storing
00395         * blobs using bytea, we autodetect and process it so this function is not needed.
00396         *
00397         * contributed by Mattia Rossi mattia@technologist.com
00398         *
00399         * see http://www.postgresql.org/idocs/index.php?largeobjects.html
00400         *
00401         * Since adodb 4.54, this returns the blob, instead of sending it to stdout. Also
00402         * added maxsize parameter, which defaults to $db->maxblobsize if not defined.
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                 See http://www.postgresql.org/idocs/index.php?datatype-binary.html
00423                 
00424                 NOTE: SQL string literals (input strings) must be preceded with two backslashes 
00425                 due to the fact that they must pass through two parsers in the PostgreSQL 
00426                 backend.
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                 /*92=backslash, 0=null, 39=single-quote*/
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                 // note that there is a pg_escape_bytea function only for php 4.2.0 or later
00439         }
00440         
00441         // assumes bytea for blob, and varchar for clob
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                 // do not use bind params which uses qstr(), as blobencode() already quotes data
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         // for schema support, pass in the $table param "$schema.$tabname".
00465         // converts field names to lowercase, $upper is ignored
00466         // see http://phplens.com/lens/lensforum/msgs.php?id=14018 for more info
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                         // If we want the primary keys, we have to issue a separate query
00491                         // Of course, a modified version of the metaColumnsSQL query using a 
00492                         // LEFT JOIN would have been much more elegant, but postgres does 
00493                         // not support OUTER JOINS. So here is the clumsy way.
00494                         
00495                         $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
00496                         
00497                         $rskey = $this->Execute(sprintf($this->metaKeySQL,($table)));
00498                         // fetch all result in once for performance.
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) == "'") { /* quoted strings hack... for now... fixme */
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                         // dannym
00548                         // 5 hasdefault; 6 num-of-column
00549                         $fld->has_default = ($rs->fields[5] == 't');
00550                         if ($fld->has_default) {
00551                                 $fld->default_value = $rsdefa[$rs->fields[6]];
00552                         }
00553 
00554                         //Freek
00555                         $fld->not_null = $rs->fields[4] == 't';
00556                         
00557                         
00558                         // Freek
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; // What name is more compatible?
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) { // requires pgsql 7.3+ - pg_namespace used.
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                                 //3rd param is use attnum, 
00628                                 // see http://sourceforge.net/tracker/index.php?func=detail&aid=1451245&group_id=42718&atid=433976
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         // returns true or false
00645         //
00646         // examples:
00647         //      $db->Connect("host=host1 user=user1 password=secret port=4341");
00648         //      $db->Connect('host1','user1','secret');
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                 //if ($user) $linea = "user=$user host=$linea password=$pwd dbname=$db port=5432";
00674                 
00675                 if ($ctype === 1) { // persistent
00676                         $this->_connectionID = pg_pconnect($str);
00677                 } else {
00678                         if ($ctype === -1) { // nconnect, we trick pgsql ext by changing the connection str
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) { // good till version 999
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         // returns true or false
00705         //
00706         // examples:
00707         //      $db->PConnect("host=host1 user=user1 password=secret port=4341");
00708         //      $db->PConnect('host1','user1','secret');
00709         function _pconnect($str,$user='',$pwd='',$db='')
00710         {
00711                 return $this->_connect($str,$user,$pwd,$db,1);
00712         }
00713         
00714 
00715         // returns queryID or false
00716         function _query($sql,$inputarr)
00717         {
00718                 $this->_errorMsg = false;
00719                 if ($inputarr) {
00720                 /*
00721                         It appears that PREPARE/EXECUTE is slower for many queries.
00722                         
00723                         For query executed 1000 times:
00724                         "select id,firstname,lastname from adoxyz 
00725                                 where firstname not like ? and lastname not like ? and id = ?"
00726                                 
00727                         with plan = 1.51861286163 secs
00728                         no plan =   1.26903700829 secs
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                                 //print_r($sqlarr);
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                                 //adodb_pr($s);
00773                                 pg_exec($this->_connectionID,$s);
00774                                 //echo $this->ErrorMsg();
00775                         }
00776                         
00777                         $rez = pg_exec($this->_connectionID,$exsql);
00778                 } else {
00779                         //adodb_backtrace();
00780                         $rez = pg_exec($this->_connectionID,$sql);
00781                 }
00782                 // check if no data returned, then no need to create real recordset
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         /*      Returns: the last error message from previous database operation        */      
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         // returns true or false
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         * Maximum size of C field
00845         */
00846         function CharMax()
00847         {
00848                 return 1000000000;  // should be 1 Gb?
00849         }
00850         
00851         /*
00852         * Maximum size of X field
00853         */
00854         function TextMax()
00855         {
00856                 return 1000000000; // should be 1 Gb?
00857         }
00858         
00859                 
00860 }
00861         
00862 /*--------------------------------------------------------------------------------------
00863          Class Name: Recordset
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                 // cache types for blob decode check
00904                 // apparently pg_fieldtype actually performs an sql query on the database to get the type.
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                 /* Use associative array to get fields array */
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                 // offsets begin at 0
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 ?>


Généré par L'expert TYPO3 avec  doxygen 1.4.6