[ Index ]
 

Code source de Mantis 1.1.0rc3

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/core/adodb/drivers/ -> adodb-postgres64.inc.php (source)

   1  <?php
   2  /*
   3   V4.94 23 Jan 2007  (c) 2000-2007 John Lim (jlim#natsoft.com.my). All rights reserved.
   4    Released under both BSD license and Lesser GPL library license. 
   5    Whenever there is any discrepancy between the two licenses, 
   6    the BSD license will take precedence.
   7    Set tabs to 8.
   8    
   9    Original version derived from Alberto Cerezal (acerezalp@dbnet.es) - DBNet Informatica & Comunicaciones. 
  10    08 Nov 2000 jlim - Minor corrections, removing mysql stuff
  11    09 Nov 2000 jlim - added insertid support suggested by "Christopher Kings-Lynne" <chriskl@familyhealth.com.au>
  12                      jlim - changed concat operator to || and data types to MetaType to match documented pgsql types 
  13               see http://www.postgresql.org/devel-corner/docs/postgres/datatype.htm  
  14    22 Nov 2000 jlim - added changes to FetchField() and MetaTables() contributed by "raser" <raser@mail.zen.com.tw>
  15    27 Nov 2000 jlim - added changes to _connect/_pconnect from ideas by "Lennie" <leen@wirehub.nl>
  16    15 Dec 2000 jlim - added changes suggested by Additional code changes by "Eric G. Werk" egw@netguide.dk. 
  17    31 Jan 2002 jlim - finally installed postgresql. testing
  18    01 Mar 2001 jlim - Freek Dijkstra changes, also support for text type
  19    
  20    See http://www.varlena.com/varlena/GeneralBits/47.php
  21    
  22      -- What indexes are on my table?
  23      select * from pg_indexes where tablename = 'tablename';
  24      
  25      -- What triggers are on my table?
  26      select c.relname as "Table", t.tgname as "Trigger Name", 
  27         t.tgconstrname as "Constraint Name", t.tgenabled as "Enabled",
  28         t.tgisconstraint as "Is Constraint", cc.relname as "Referenced Table",
  29         p.proname as "Function Name"
  30      from pg_trigger t, pg_class c, pg_class cc, pg_proc p
  31      where t.tgfoid = p.oid and t.tgrelid = c.oid
  32         and t.tgconstrrelid = cc.oid
  33         and c.relname = 'tablename';
  34      
  35      -- What constraints are on my table?
  36      select r.relname as "Table", c.conname as "Constraint Name",
  37         contype as "Constraint Type", conkey as "Key Columns",
  38         confkey as "Foreign Columns", consrc as "Source"
  39      from pg_class r, pg_constraint c
  40      where r.oid = c.conrelid
  41         and relname = 'tablename';
  42  
  43  */
  44  
  45  // security - hide paths
  46  if (!defined('ADODB_DIR')) die();
  47  
  48  function adodb_addslashes($s)
  49  {
  50      $len = strlen($s);
  51      if ($len == 0) return "''";
  52      if (strncmp($s,"'",1) === 0 && substr($s,$len-1) == "'") return $s; // already quoted
  53      
  54      return "'".addslashes($s)."'";
  55  }
  56  
  57  class ADODB_postgres64 extends ADOConnection{
  58      var $databaseType = 'postgres64';
  59      var $dataProvider = 'postgres';
  60      var $hasInsertID = true;
  61      var $_resultid = false;
  62        var $concat_operator='||';
  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') 
  67      union 
  68          select viewname,'V' from pg_views where viewname not like 'pg\_%'";
  69      //"select tablename from pg_tables where tablename not like 'pg_%' order by 1";
  70      var $isoDates = true; // accepts dates in ISO format
  71      var $sysDate = "CURRENT_DATE";
  72      var $sysTimeStamp = "CURRENT_TIMESTAMP";
  73      var $blobEncodeType = 'C';
  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";
  78  
  79      // used when schema defined
  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";
  86      
  87      // get primary key etc -- from Freek Dijkstra
  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 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'";
  90      
  91      var $hasAffectedRows = true;
  92      var $hasLimit = false;    // set to true for pgsql 7 only. support pgsql/mysql SELECT * FROM TABLE LIMIT 10
  93      // below suggested by Freek Dijkstra 
  94      var $true = 'TRUE';        // string that represents TRUE for a database
  95      var $false = 'FALSE';        // string that represents FALSE for a database
  96      var $fmtDate = "'Y-m-d'";    // used by DBDate() as the default date format used by the database
  97      var $fmtTimeStamp = "'Y-m-d H:i:s'"; // used by DBTimeStamp as the default timestamp fmt.
  98      var $hasMoveFirst = true;
  99      var $hasGenID = true;
 100      var $_genIDSQL = "SELECT NEXTVAL('%s')";
 101      var $_genSeqSQL = "CREATE SEQUENCE %s START %s";
 102      var $_dropSeqSQL = "DROP SEQUENCE %s";
 103      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";
 104      var $random = 'random()';        /// random function
 105      var $autoRollback = true; // apparently pgsql does not autorollback properly before php 4.3.4
 106                              // http://bugs.php.net/bug.php?id=25404
 107                              
 108      var $_bindInputArray = false; // requires postgresql 7.3+ and ability to modify database
 109      var $disableBlobs = false; // set to true to disable blob checking, resulting in 2-5% improvement in performance.
 110      
 111      // The last (fmtTimeStamp is not entirely correct: 
 112      // PostgreSQL also has support for time zones, 
 113      // and writes these time in this format: "2001-03-01 18:59:26+02". 
 114      // There is no code for the "+02" time zone information, so I just left that out. 
 115      // I'm not familiar enough with both ADODB as well as Postgres 
 116      // to know what the concequences are. The other values are correct (wheren't in 0.94)
 117      // -- Freek Dijkstra 
 118  
 119  	function ADODB_postgres64() 
 120      {
 121      // changes the metaColumnsSQL, adds columns: attnum[6]
 122      }
 123      
 124  	function ServerInfo()
 125      {
 126          if (isset($this->version)) return $this->version;
 127          
 128          $arr['description'] = $this->GetOne("select version()");
 129          $arr['version'] = ADOConnection::_findvers($arr['description']);
 130          $this->version = $arr;
 131          return $arr;
 132      }
 133  
 134  	function IfNull( $field, $ifNull ) 
 135      {
 136          return " coalesce($field, $ifNull) "; 
 137      }
 138  
 139      // get the last id - never tested
 140  	function pg_insert_id($tablename,$fieldname)
 141      {
 142          $result=pg_exec($this->_connectionID, "SELECT last_value FROM $tablename}_$fieldname}_seq");
 143          if ($result) {
 144              $arr = @pg_fetch_row($result,0);
 145              pg_freeresult($result);
 146              if (isset($arr[0])) return $arr[0];
 147          }
 148          return false;
 149      }
 150      
 151  /* Warning from http://www.php.net/manual/function.pg-getlastoid.php:
 152  Using a OID as a unique identifier is not generally wise. 
 153  Unless you are very careful, you might end up with a tuple having 
 154  a different OID if a database must be reloaded. */
 155  	function _insertid($table,$column)
 156      {
 157          if (!is_resource($this->_resultid) || get_resource_type($this->_resultid) !== 'pgsql result') return false;
 158          $oid = pg_getlastoid($this->_resultid);
 159          // to really return the id, we need the table and column-name, else we can only return the oid != id
 160          return empty($table) || empty($column) ? $oid : $this->GetOne("SELECT $column FROM $table WHERE oid=".(int)$oid);
 161      }
 162  
 163  // I get this error with PHP before 4.0.6 - jlim
 164  // Warning: This compilation does not support pg_cmdtuples() in adodb-postgres.inc.php on line 44
 165     function _affectedrows()
 166     {
 167             if (!is_resource($this->_resultid) || get_resource_type($this->_resultid) !== 'pgsql result') return false;
 168             return pg_cmdtuples($this->_resultid);
 169     }
 170     
 171      
 172          // returns true/false
 173  	function BeginTrans()
 174      {
 175          if ($this->transOff) return true;
 176          $this->transCnt += 1;
 177          return @pg_Exec($this->_connectionID, "begin ".$this->_transmode);
 178      }
 179      
 180  	function RowLock($tables,$where,$flds='1 as ignore') 
 181      {
 182          if (!$this->transCnt) $this->BeginTrans();
 183          return $this->GetOne("select $flds from $tables where $where for update");
 184      }
 185  
 186      // returns true/false. 
 187  	function CommitTrans($ok=true) 
 188      { 
 189          if ($this->transOff) return true;
 190          if (!$ok) return $this->RollbackTrans();
 191          
 192          $this->transCnt -= 1;
 193          return @pg_Exec($this->_connectionID, "commit");
 194      }
 195      
 196      // returns true/false
 197  	function RollbackTrans()
 198      {
 199          if ($this->transOff) return true;
 200          $this->transCnt -= 1;
 201          return @pg_Exec($this->_connectionID, "rollback");
 202      }
 203      
 204      function &MetaTables($ttype=false,$showSchema=false,$mask=false) 
 205      {
 206          $info = $this->ServerInfo();
 207          if ($info['version'] >= 7.3) {
 208              $this->metaTablesSQL = "select tablename,'T' from pg_tables where tablename not like 'pg\_%'
 209                and schemaname  not in ( 'pg_catalog','information_schema')
 210      union 
 211          select viewname,'V' from pg_views where viewname not like 'pg\_%'  and schemaname  not in ( 'pg_catalog','information_schema') ";
 212          }
 213          if ($mask) {
 214              $save = $this->metaTablesSQL;
 215              $mask = $this->qstr(strtolower($mask));
 216              if ($info['version']>=7.3)
 217                  $this->metaTablesSQL = "
 218  select tablename,'T' from pg_tables where tablename like $mask and schemaname not in ( 'pg_catalog','information_schema')  
 219   union 
 220  select viewname,'V' from pg_views where viewname like $mask and schemaname  not in ( 'pg_catalog','information_schema')  ";
 221              else
 222                  $this->metaTablesSQL = "
 223  select tablename,'T' from pg_tables where tablename like $mask 
 224   union 
 225  select viewname,'V' from pg_views where viewname like $mask";
 226          }
 227          $ret =& ADOConnection::MetaTables($ttype,$showSchema);
 228          
 229          if ($mask) {
 230              $this->metaTablesSQL = $save;
 231          }
 232          return $ret;
 233      }
 234      
 235      
 236      // if magic quotes disabled, use pg_escape_string()
 237  	function qstr($s,$magic_quotes=false)
 238      {
 239          if (!$magic_quotes) {
 240              if (ADODB_PHPVER >= 0x5200) {
 241                  return  "'".pg_escape_string($this->_connectionID,$s)."'";
 242              } 
 243              if (ADODB_PHPVER >= 0x4200) {
 244                  return  "'".pg_escape_string($s)."'";
 245              }
 246              if ($this->replaceQuote[0] == '\\'){
 247                  $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\\000"),$s);
 248              }
 249              return  "'".str_replace("'",$this->replaceQuote,$s)."'"; 
 250          }
 251          
 252          // undo magic quotes for "
 253          $s = str_replace('\\"','"',$s);
 254          return "'$s'";
 255      }
 256      
 257      
 258      
 259      // Format date column in sql string given an input format that understands Y M D
 260  	function SQLDate($fmt, $col=false)
 261      {    
 262          if (!$col) $col = $this->sysTimeStamp;
 263          $s = 'TO_CHAR('.$col.",'";
 264          
 265          $len = strlen($fmt);
 266          for ($i=0; $i < $len; $i++) {
 267              $ch = $fmt[$i];
 268              switch($ch) {
 269              case 'Y':
 270              case 'y':
 271                  $s .= 'YYYY';
 272                  break;
 273              case 'Q':
 274              case 'q':
 275                  $s .= 'Q';
 276                  break;
 277                  
 278              case 'M':
 279                  $s .= 'Mon';
 280                  break;
 281                  
 282              case 'm':
 283                  $s .= 'MM';
 284                  break;
 285              case 'D':
 286              case 'd':
 287                  $s .= 'DD';
 288                  break;
 289              
 290              case 'H':
 291                  $s.= 'HH24';
 292                  break;
 293                  
 294              case 'h':
 295                  $s .= 'HH';
 296                  break;
 297                  
 298              case 'i':
 299                  $s .= 'MI';
 300                  break;
 301              
 302              case 's':
 303                  $s .= 'SS';
 304                  break;
 305              
 306              case 'a':
 307              case 'A':
 308                  $s .= 'AM';
 309                  break;
 310                  
 311              case 'w':
 312                  $s .= 'D';
 313                  break;
 314              
 315              case 'l':
 316                  $s .= 'DAY';
 317                  break;
 318              
 319               case 'W':
 320                  $s .= 'WW';
 321                  break;
 322  
 323              default:
 324              // handle escape characters...
 325                  if ($ch == '\\') {
 326                      $i++;
 327                      $ch = substr($fmt,$i,1);
 328                  }
 329                  if (strpos('-/.:;, ',$ch) !== false) $s .= $ch;
 330                  else $s .= '"'.$ch.'"';
 331                  
 332              }
 333          }
 334          return $s. "')";
 335      }
 336      
 337      
 338      
 339      /* 
 340      * Load a Large Object from a file 
 341      * - the procedure stores the object id in the table and imports the object using 
 342      * postgres proprietary blob handling routines 
 343      *
 344      * contributed by Mattia Rossi mattia@technologist.com
 345      * modified for safe mode by juraj chlebec
 346      */ 
 347  	function UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB') 
 348      { 
 349          pg_exec ($this->_connectionID, "begin"); 
 350          
 351          $fd = fopen($path,'r');
 352          $contents = fread($fd,filesize($path));
 353          fclose($fd);
 354          
 355          $oid = pg_lo_create($this->_connectionID);
 356          $handle = pg_lo_open($this->_connectionID, $oid, 'w');
 357          pg_lo_write($handle, $contents);
 358          pg_lo_close($handle);
 359          
 360          // $oid = pg_lo_import ($path); 
 361          pg_exec($this->_connectionID, "commit"); 
 362          $rs = ADOConnection::UpdateBlob($table,$column,$oid,$where,$blobtype); 
 363          $rez = !empty($rs); 
 364          return $rez; 
 365      } 
 366      
 367      /*
 368      * Deletes/Unlinks a Blob from the database, otherwise it 
 369      * will be left behind
 370      *
 371      * Returns TRUE on success or FALSE on failure.
 372      *
 373      * contributed by Todd Rogers todd#windfox.net
 374      */
 375  	function BlobDelete( $blob )
 376      {
 377          pg_exec ($this->_connectionID, "begin");
 378          $result = @pg_lo_unlink($blob);
 379          pg_exec ($this->_connectionID, "commit");
 380          return( $result );
 381      }
 382  
 383      /*
 384          Hueristic - not guaranteed to work.
 385      */
 386  	function GuessOID($oid)
 387      {
 388          if (strlen($oid)>16) return false;
 389          return is_numeric($oid);
 390      }
 391      
 392      /* 
 393      * If an OID is detected, then we use pg_lo_* to open the oid file and read the
 394      * real blob from the db using the oid supplied as a parameter. If you are storing
 395      * blobs using bytea, we autodetect and process it so this function is not needed.
 396      *
 397      * contributed by Mattia Rossi mattia@technologist.com
 398      *
 399      * see http://www.postgresql.org/idocs/index.php?largeobjects.html
 400      *
 401      * Since adodb 4.54, this returns the blob, instead of sending it to stdout. Also
 402      * added maxsize parameter, which defaults to $db->maxblobsize if not defined.
 403      */ 
 404  	function BlobDecode($blob,$maxsize=false,$hastrans=true) 
 405      {
 406          if (!$this->GuessOID($blob)) return $blob;
 407          
 408          if ($hastrans) @pg_exec($this->_connectionID,"begin"); 
 409          $fd = @pg_lo_open($this->_connectionID,$blob,"r");
 410          if ($fd === false) {
 411              if ($hastrans) @pg_exec($this->_connectionID,"commit");
 412              return $blob;
 413          }
 414          if (!$maxsize) $maxsize = $this->maxblobsize;
 415          $realblob = @pg_loread($fd,$maxsize); 
 416          @pg_loclose($fd); 
 417          if ($hastrans) @pg_exec($this->_connectionID,"commit"); 
 418          return $realblob;
 419      }
 420      
 421      /* 
 422          See http://www.postgresql.org/idocs/index.php?datatype-binary.html
 423           
 424          NOTE: SQL string literals (input strings) must be preceded with two backslashes 
 425          due to the fact that they must pass through two parsers in the PostgreSQL 
 426          backend.
 427      */
 428  	function BlobEncode($blob)
 429      {
 430          if (ADODB_PHPVER >= 0x5200) return pg_escape_bytea($this->_connectionID, $blob);
 431          if (ADODB_PHPVER >= 0x4200) return pg_escape_bytea($blob);
 432          
 433          /*92=backslash, 0=null, 39=single-quote*/
 434          $badch = array(chr(92),chr(0),chr(39)); # \  null  '
 435          $fixch = array('\\\\134','\\\\000','\\\\047');
 436          return adodb_str_replace($badch,$fixch,$blob);
 437          
 438          // note that there is a pg_escape_bytea function only for php 4.2.0 or later
 439      }
 440      
 441      // assumes bytea for blob, and varchar for clob
 442  	function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
 443      {
 444      
 445          if ($blobtype == 'CLOB') {
 446              return $this->Execute("UPDATE $table SET $column=" . $this->qstr($val) . " WHERE $where");
 447          }
 448          // do not use bind params which uses qstr(), as blobencode() already quotes data
 449          return $this->Execute("UPDATE $table SET $column='".$this->BlobEncode($val)."'::bytea WHERE $where");
 450      }
 451      
 452  	function OffsetDate($dayFraction,$date=false)
 453      {        
 454          if (!$date) $date = $this->sysDate;
 455          else if (strncmp($date,"'",1) == 0) {
 456              $len = strlen($date);
 457              if (10 <= $len && $len <= 12) $date = 'date '.$date;
 458              else $date = 'timestamp '.$date;
 459          }
 460          return "($date+interval'$dayFraction days')";
 461      }
 462      
 463  
 464      // for schema support, pass in the $table param "$schema.$tabname".
 465      // converts field names to lowercase, $upper is ignored
 466      // see http://phplens.com/lens/lensforum/msgs.php?id=14018 for more info
 467      function &MetaColumns($table,$normalize=true) 
 468      {
 469      global $ADODB_FETCH_MODE;
 470      
 471          $schema = false;
 472          $false = false;
 473          $this->_findschema($table,$schema);
 474          
 475          if ($normalize) $table = strtolower($table);
 476  
 477          $save = $ADODB_FETCH_MODE;
 478          $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
 479          if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
 480          
 481          if ($schema) $rs =& $this->Execute(sprintf($this->metaColumnsSQL1,$table,$table,$schema));
 482          else $rs =& $this->Execute(sprintf($this->metaColumnsSQL,$table,$table));
 483          if (isset($savem)) $this->SetFetchMode($savem);
 484          $ADODB_FETCH_MODE = $save;
 485          
 486          if ($rs === false) {
 487              return $false;
 488          }
 489          if (!empty($this->metaKeySQL)) {
 490              // If we want the primary keys, we have to issue a separate query
 491              // Of course, a modified version of the metaColumnsSQL query using a 
 492              // LEFT JOIN would have been much more elegant, but postgres does 
 493              // not support OUTER JOINS. So here is the clumsy way.
 494              
 495              $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
 496              
 497              $rskey = $this->Execute(sprintf($this->metaKeySQL,($table)));
 498              // fetch all result in once for performance.
 499              $keys =& $rskey->GetArray();
 500              if (isset($savem)) $this->SetFetchMode($savem);
 501              $ADODB_FETCH_MODE = $save;
 502              
 503              $rskey->Close();
 504              unset($rskey);
 505          }
 506  
 507          $rsdefa = array();
 508          if (!empty($this->metaDefaultsSQL)) {
 509              $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
 510              $sql = sprintf($this->metaDefaultsSQL, ($table));
 511              $rsdef = $this->Execute($sql);
 512              if (isset($savem)) $this->SetFetchMode($savem);
 513              $ADODB_FETCH_MODE = $save;
 514              
 515              if ($rsdef) {
 516                  while (!$rsdef->EOF) {
 517                      $num = $rsdef->fields['num'];
 518                      $s = $rsdef->fields['def'];
 519                      if (strpos($s,'::')===false && substr($s, 0, 1) == "'") { /* quoted strings hack... for now... fixme */
 520                          $s = substr($s, 1);
 521                          $s = substr($s, 0, strlen($s) - 1);
 522                      }
 523  
 524                      $rsdefa[$num] = $s;
 525                      $rsdef->MoveNext();
 526                  }
 527              } else {
 528                  ADOConnection::outp( "==> SQL => " . $sql);
 529              }
 530              unset($rsdef);
 531          }
 532      
 533          $retarr = array();
 534          while (!$rs->EOF) {     
 535              $fld = new ADOFieldObject();
 536              $fld->name = $rs->fields[0];
 537              $fld->type = $rs->fields[1];
 538              $fld->max_length = $rs->fields[2];
 539              $fld->attnum = $rs->fields[6];
 540              
 541              if ($fld->max_length <= 0) $fld->max_length = $rs->fields[3]-4;
 542              if ($fld->max_length <= 0) $fld->max_length = -1;
 543              if ($fld->type == 'numeric') {
 544                  $fld->scale = $fld->max_length & 0xFFFF;
 545                  $fld->max_length >>= 16;
 546              }
 547              // dannym
 548              // 5 hasdefault; 6 num-of-column
 549              $fld->has_default = ($rs->fields[5] == 't');
 550              if ($fld->has_default) {
 551                  $fld->default_value = $rsdefa[$rs->fields[6]];
 552              }
 553  
 554              //Freek
 555              $fld->not_null = $rs->fields[4] == 't';
 556              
 557              
 558              // Freek
 559              if (is_array($keys)) {
 560                  foreach($keys as $key) {
 561                      if ($fld->name == $key['column_name'] AND $key['primary_key'] == 't') 
 562                          $fld->primary_key = true;
 563                      if ($fld->name == $key['column_name'] AND $key['unique_key'] == 't') 
 564                          $fld->unique = true; // What name is more compatible?
 565                  }
 566              }
 567              
 568              if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;    
 569              else $retarr[($normalize) ? strtoupper($fld->name) : $fld->name] = $fld;
 570              
 571              $rs->MoveNext();
 572          }
 573          $rs->Close();
 574          if (empty($retarr))
 575              return  $false;
 576          else
 577              return $retarr;    
 578          
 579      }
 580  
 581        function &MetaIndexes ($table, $primary = FALSE)
 582        {
 583           global $ADODB_FETCH_MODE;
 584                  
 585                  $schema = false;
 586                  $this->_findschema($table,$schema);
 587  
 588                  if ($schema) { // requires pgsql 7.3+ - pg_namespace used.
 589                      $sql = '
 590  SELECT c.relname as "Name", i.indisunique as "Unique", i.indkey as "Columns" 
 591  FROM pg_catalog.pg_class c 
 592  JOIN pg_catalog.pg_index i ON i.indexrelid=c.oid 
 593  JOIN pg_catalog.pg_class c2 ON c2.oid=i.indrelid
 594      ,pg_namespace n 
 595  WHERE (c2.relname=\'%s\' or c2.relname=lower(\'%s\')) and c.relnamespace=c2.relnamespace and c.relnamespace=n.oid and n.nspname=\'%s\'';
 596                  } else {
 597                      $sql = '
 598  SELECT c.relname as "Name", i.indisunique as "Unique", i.indkey as "Columns"
 599  FROM pg_catalog.pg_class c
 600  JOIN pg_catalog.pg_index i ON i.indexrelid=c.oid
 601  JOIN pg_catalog.pg_class c2 ON c2.oid=i.indrelid
 602  WHERE (c2.relname=\'%s\' or c2.relname=lower(\'%s\'))';
 603                  }
 604                              
 605                  if ($primary == FALSE) {
 606                      $sql .= ' AND i.indisprimary=false;';
 607                  }
 608                  
 609                  $save = $ADODB_FETCH_MODE;
 610                  $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
 611                  if ($this->fetchMode !== FALSE) {
 612                          $savem = $this->SetFetchMode(FALSE);
 613                  }
 614                  
 615                  $rs = $this->Execute(sprintf($sql,$table,$table,$schema));
 616                  if (isset($savem)) {
 617                          $this->SetFetchMode($savem);
 618                  }
 619                  $ADODB_FETCH_MODE = $save;
 620  
 621                  if (!is_object($rs)) {
 622                      $false = false;
 623                      return $false;
 624                  }
 625                  
 626                  $col_names = $this->MetaColumnNames($table,true,true); 
 627                  //3rd param is use attnum, 
 628                  // see http://sourceforge.net/tracker/index.php?func=detail&aid=1451245&group_id=42718&atid=433976
 629                  $indexes = array();
 630                  while ($row = $rs->FetchRow()) {
 631                          $columns = array();
 632                          foreach (explode(' ', $row[2]) as $col) {
 633                                  $columns[] = $col_names[$col];
 634                          }
 635                          
 636                          $indexes[$row[0]] = array(
 637                                  'unique' => ($row[1] == 't'),
 638                                  'columns' => $columns
 639                          );
 640                  }
 641                  return $indexes;
 642          }
 643  
 644      // returns true or false
 645      //
 646      // examples:
 647      //     $db->Connect("host=host1 user=user1 password=secret port=4341");
 648      //     $db->Connect('host1','user1','secret');
 649  	function _connect($str,$user='',$pwd='',$db='',$ctype=0)
 650      {
 651          
 652          if (!function_exists('pg_connect')) return null;
 653          
 654          $this->_errorMsg = false;
 655          
 656          if ($user || $pwd || $db) {
 657              $user = adodb_addslashes($user);
 658              $pwd = adodb_addslashes($pwd);
 659              if (strlen($db) == 0) $db = 'template1';
 660              $db = adodb_addslashes($db);
 661                 if ($str)  {
 662                   $host = split(":", $str);
 663                  if ($host[0]) $str = "host=".adodb_addslashes($host[0]);
 664                  else $str = '';
 665                  if (isset($host[1])) $str .= " port=$host[1]";
 666                  else if (!empty($this->port)) $str .= " port=".$this->port;
 667              }
 668                     if ($user) $str .= " user=".$user;
 669                     if ($pwd)  $str .= " password=".$pwd;
 670                  if ($db)   $str .= " dbname=".$db;
 671          }
 672  
 673          //if ($user) $linea = "user=$user host=$linea password=$pwd dbname=$db port=5432";
 674          
 675          if ($ctype === 1) { // persistent
 676              $this->_connectionID = pg_pconnect($str);
 677          } else {
 678              if ($ctype === -1) { // nconnect, we trick pgsql ext by changing the connection str
 679              static $ncnt;
 680              
 681                  if (empty($ncnt)) $ncnt = 1;
 682                  else $ncnt += 1;
 683                  
 684                  $str .= str_repeat(' ',$ncnt);
 685              }
 686              $this->_connectionID = pg_connect($str);
 687          }
 688          if ($this->_connectionID === false) return false;
 689          $this->Execute("set datestyle='ISO'");
 690          
 691          $info = $this->ServerInfo();
 692          $this->pgVersion = (float) substr($info['version'],0,3);
 693          if ($this->pgVersion >= 7.1) { // good till version 999
 694              $this->_nestedSQL = true;
 695          }
 696          return true;
 697      }
 698      
 699  	function _nconnect($argHostname, $argUsername, $argPassword, $argDatabaseName)
 700      {
 701           return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabaseName,-1);
 702      }
 703       
 704      // returns true or false
 705      //
 706      // examples:
 707      //     $db->PConnect("host=host1 user=user1 password=secret port=4341");
 708      //     $db->PConnect('host1','user1','secret');
 709  	function _pconnect($str,$user='',$pwd='',$db='')
 710      {
 711          return $this->_connect($str,$user,$pwd,$db,1);
 712      }
 713      
 714  
 715      // returns queryID or false
 716  	function _query($sql,$inputarr)
 717      {
 718          $this->_errorMsg = false;
 719          if ($inputarr) {
 720          /*
 721              It appears that PREPARE/EXECUTE is slower for many queries.
 722              
 723              For query executed 1000 times:
 724              "select id,firstname,lastname from adoxyz 
 725                  where firstname not like ? and lastname not like ? and id = ?"
 726                  
 727              with plan = 1.51861286163 secs
 728              no plan =   1.26903700829 secs
 729  
 730              
 731  
 732          */
 733              $plan = 'P'.md5($sql);
 734                  
 735              $execp = '';
 736              foreach($inputarr as $v) {
 737                  if ($execp) $execp .= ',';
 738                  if (is_string($v)) {
 739                      if (strncmp($v,"'",1) !== 0) $execp .= $this->qstr($v);
 740                  } else {
 741                      $execp .= $v;
 742                  }
 743              }
 744              
 745              if ($execp) $exsql = "EXECUTE $plan ($execp)";
 746              else $exsql = "EXECUTE $plan";
 747              
 748              
 749              $rez = @pg_exec($this->_connectionID,$exsql);
 750              if (!$rez) {
 751              # Perhaps plan does not exist? Prepare/compile plan.
 752                  $params = '';
 753                  foreach($inputarr as $v) {
 754                      if ($params) $params .= ',';
 755                      if (is_string($v)) {
 756                          $params .= 'VARCHAR';
 757                      } else if (is_integer($v)) {
 758                          $params .= 'INTEGER';
 759                      } else {
 760                          $params .= "REAL";
 761                      }
 762                  }
 763                  $sqlarr = explode('?',$sql);
 764                  //print_r($sqlarr);
 765                  $sql = '';
 766                  $i = 1;
 767                  foreach($sqlarr as $v) {
 768                      $sql .= $v.' $'.$i;
 769                      $i++;
 770                  }
 771                  $s = "PREPARE $plan ($params) AS ".substr($sql,0,strlen($sql)-2);        
 772                  //adodb_pr($s);
 773                  $rez = pg_exec($this->_connectionID,$s);
 774                  //echo $this->ErrorMsg();
 775              }
 776              if ($rez)
 777                  $rez = pg_exec($this->_connectionID,$exsql);
 778          } else {
 779              //adodb_backtrace();
 780              $rez = pg_exec($this->_connectionID,$sql);
 781          }
 782          // check if no data returned, then no need to create real recordset
 783          if ($rez && pg_numfields($rez) <= 0) {
 784              if (is_resource($this->_resultid) && get_resource_type($this->_resultid) === 'pgsql result') {
 785                  pg_freeresult($this->_resultid);
 786              }
 787              $this->_resultid = $rez;
 788              return true;
 789          }
 790          
 791          return $rez;
 792      }
 793      
 794  	function _errconnect()
 795      {
 796          if (defined('DB_ERROR_CONNECT_FAILED')) return DB_ERROR_CONNECT_FAILED;
 797          else return 'Database connection failed';
 798      }
 799  
 800      /*    Returns: the last error message from previous database operation    */    
 801  	function ErrorMsg() 
 802      {
 803          if ($this->_errorMsg !== false) return $this->_errorMsg;
 804          if (ADODB_PHPVER >= 0x4300) {
 805              if (!empty($this->_resultid)) {
 806                  $this->_errorMsg = @pg_result_error($this->_resultid);
 807                  if ($this->_errorMsg) return $this->_errorMsg;
 808              }
 809              
 810              if (!empty($this->_connectionID)) {
 811                  $this->_errorMsg = @pg_last_error($this->_connectionID);
 812              } else $this->_errorMsg = $this->_errconnect();
 813          } else {
 814              if (empty($this->_connectionID)) $this->_errconnect();
 815              else $this->_errorMsg = @pg_errormessage($this->_connectionID);
 816          }
 817          return $this->_errorMsg;
 818      }
 819      
 820  	function ErrorNo()
 821      {
 822          $e = $this->ErrorMsg();
 823          if (strlen($e)) {
 824              return ADOConnection::MetaError($e);
 825           }
 826           return 0;
 827      }
 828  
 829      // returns true or false
 830  	function _close()
 831      {
 832          if ($this->transCnt) $this->RollbackTrans();
 833          if ($this->_resultid) {
 834              @pg_freeresult($this->_resultid);
 835              $this->_resultid = false;
 836          }
 837          @pg_close($this->_connectionID);
 838          $this->_connectionID = false;
 839          return true;
 840      }
 841      
 842      
 843      /*
 844      * Maximum size of C field
 845      */
 846  	function CharMax()
 847      {
 848          return 1000000000;  // should be 1 Gb?
 849      }
 850      
 851      /*
 852      * Maximum size of X field
 853      */
 854  	function TextMax()
 855      {
 856          return 1000000000; // should be 1 Gb?
 857      }
 858      
 859          
 860  }
 861      
 862  /*--------------------------------------------------------------------------------------
 863       Class Name: Recordset
 864  --------------------------------------------------------------------------------------*/
 865  
 866  class ADORecordSet_postgres64 extends ADORecordSet{
 867      var $_blobArr;
 868      var $databaseType = "postgres64";
 869      var $canSeek = true;
 870  	function ADORecordSet_postgres64($queryID,$mode=false) 
 871      {
 872          if ($mode === false) { 
 873              global $ADODB_FETCH_MODE;
 874              $mode = $ADODB_FETCH_MODE;
 875          }
 876          switch ($mode)
 877          {
 878          case ADODB_FETCH_NUM: $this->fetchMode = PGSQL_NUM; break;
 879          case ADODB_FETCH_ASSOC:$this->fetchMode = PGSQL_ASSOC; break;
 880          
 881          case ADODB_FETCH_DEFAULT:
 882          case ADODB_FETCH_BOTH:
 883          default: $this->fetchMode = PGSQL_BOTH; break;
 884          }
 885          $this->adodbFetchMode = $mode;
 886          $this->ADORecordSet($queryID);
 887      }
 888      
 889      function &GetRowAssoc($upper=true)
 890      {
 891          if ($this->fetchMode == PGSQL_ASSOC && !$upper) return $this->fields;
 892          $row =& ADORecordSet::GetRowAssoc($upper);
 893          return $row;
 894      }
 895  
 896  	function _initrs()
 897      {
 898      global $ADODB_COUNTRECS;
 899          $qid = $this->_queryID;
 900          $this->_numOfRows = ($ADODB_COUNTRECS)? @pg_numrows($qid):-1;
 901          $this->_numOfFields = @pg_numfields($qid);
 902          
 903          // cache types for blob decode check
 904          // apparently pg_fieldtype actually performs an sql query on the database to get the type.
 905          if (empty($this->connection->noBlobs))
 906          for ($i=0, $max = $this->_numOfFields; $i < $max; $i++) {  
 907              if (pg_fieldtype($qid,$i) == 'bytea') {
 908                  $this->_blobArr[$i] = pg_fieldname($qid,$i);
 909              }
 910          }
 911      }
 912  
 913          /* Use associative array to get fields array */
 914  	function Fields($colname)
 915      {
 916          if ($this->fetchMode != PGSQL_NUM) return @$this->fields[$colname];
 917          
 918          if (!$this->bind) {
 919              $this->bind = array();
 920              for ($i=0; $i < $this->_numOfFields; $i++) {
 921                  $o = $this->FetchField($i);
 922                  $this->bind[strtoupper($o->name)] = $i;
 923              }
 924          }
 925           return $this->fields[$this->bind[strtoupper($colname)]];
 926      }
 927  
 928      function &FetchField($off = 0) 
 929      {
 930          // offsets begin at 0
 931          
 932          $o= new ADOFieldObject();
 933          $o->name = @pg_fieldname($this->_queryID,$off);
 934          $o->type = @pg_fieldtype($this->_queryID,$off);
 935          $o->max_length = @pg_fieldsize($this->_queryID,$off);
 936          return $o;    
 937      }
 938  
 939  	function _seek($row)
 940      {
 941          return @pg_fetch_row($this->_queryID,$row);
 942      }
 943      
 944  	function _decode($blob)
 945      {
 946          eval('$realblob="'.adodb_str_replace(array('"','$'),array('\"','\$'),$blob).'";');
 947          return $realblob;    
 948      }
 949      
 950  	function _fixblobs()
 951      {
 952          if ($this->fetchMode == PGSQL_NUM || $this->fetchMode == PGSQL_BOTH) {
 953              foreach($this->_blobArr as $k => $v) {
 954                  $this->fields[$k] = ADORecordSet_postgres64::_decode($this->fields[$k]);
 955              }
 956          }
 957          if ($this->fetchMode == PGSQL_ASSOC || $this->fetchMode == PGSQL_BOTH) {
 958              foreach($this->_blobArr as $k => $v) {
 959                  $this->fields[$v] = ADORecordSet_postgres64::_decode($this->fields[$v]);
 960              }
 961          }
 962      }
 963      
 964      // 10% speedup to move MoveNext to child class
 965  	function MoveNext() 
 966      {
 967          if (!$this->EOF) {
 968              $this->_currentRow++;
 969              if ($this->_numOfRows < 0 || $this->_numOfRows > $this->_currentRow) {
 970                  $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);
 971                  if (is_array($this->fields) && $this->fields) {
 972                      if (isset($this->_blobArr)) $this->_fixblobs();
 973                      return true;
 974                  }
 975              }
 976              $this->fields = false;
 977              $this->EOF = true;
 978          }
 979          return false;
 980      }        
 981      
 982  	function _fetch()
 983      {
 984                  
 985          if ($this->_currentRow >= $this->_numOfRows && $this->_numOfRows >= 0)
 986              return false;
 987  
 988          $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);
 989          
 990          if ($this->fields && isset($this->_blobArr)) $this->_fixblobs();
 991              
 992          return (is_array($this->fields));
 993      }
 994  
 995  	function _close() 
 996      { 
 997          return @pg_freeresult($this->_queryID);
 998      }
 999  
1000  	function MetaType($t,$len=-1,$fieldobj=false)
1001      {
1002          if (is_object($t)) {
1003              $fieldobj = $t;
1004              $t = $fieldobj->type;
1005              $len = $fieldobj->max_length;
1006          }
1007          switch (strtoupper($t)) {
1008                  case 'MONEY': // stupid, postgres expects money to be a string
1009                  case 'INTERVAL':
1010                  case 'CHAR':
1011                  case 'CHARACTER':
1012                  case 'VARCHAR':
1013                  case 'NAME':
1014                     case 'BPCHAR':
1015                  case '_VARCHAR':
1016                  case 'INET':
1017                  case 'MACADDR':
1018                      if ($len <= $this->blobSize) return 'C';
1019                  
1020                  case 'TEXT':
1021                      return 'X';
1022          
1023                  case 'IMAGE': // user defined type
1024                  case 'BLOB': // user defined type
1025                  case 'BIT':    // This is a bit string, not a single bit, so don't return 'L'
1026                  case 'VARBIT':
1027                  case 'BYTEA':
1028                      return 'B';
1029                  
1030                  case 'BOOL':
1031                  case 'BOOLEAN':
1032                      return 'L';
1033                  
1034                  case 'DATE':
1035                      return 'D';
1036                  
1037                  
1038                  case 'TIMESTAMP WITHOUT TIME ZONE':
1039                  case 'TIME':
1040                  case 'DATETIME':
1041                  case 'TIMESTAMP':
1042                  case 'TIMESTAMPTZ':
1043                      return 'T';
1044                  
1045                  case 'SMALLINT': 
1046                  case 'BIGINT': 
1047                  case 'INTEGER': 
1048                  case 'INT8': 
1049                  case 'INT4':
1050                  case 'INT2':
1051                      if (isset($fieldobj) &&
1052                  empty($fieldobj->primary_key) && empty($fieldobj->unique)) return 'I';
1053                  
1054                  case 'OID':
1055                  case 'SERIAL':
1056                      return 'R';
1057                  
1058                   default:
1059                       return 'N';
1060              }
1061      }
1062  
1063  }
1064  ?>


Généré le : Thu Nov 29 09:42:17 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics