[ Index ]
 

Code source de eGroupWare 1.2.106-2

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

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

   1  <?php
   2  /*
   3   V4.65 22 July 2005  (c) 2000-2005 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 G: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  
 160          if ($oid === false && $table && $column)    // table might not use oid's, default for 8.1+
 161          {
 162              // try the standard sequence name first, due to table renames etc. this might not be the correct one
 163              if (!($ret = $this->GetOne($sql='SELECT currval('.$this->qstr($table.'_'.$column.'_seq').')'))) {
 164                  // now we read the sequence name from the database itself, that is a lot slower!
 165                  $cols = $this->MetaColumns($table);
 166                  $fld = $cols[strtoupper($column)];
 167                  if ($fld->primary_key && $fld->has_default && 
 168                      preg_match("/nextval\('([^']+)'::text\)/",$fld->default_value,$matches)) {
 169                      $ret = $this->GetOne($sql='SELECT currval('.$this->qstr($matches[1]).')');
 170                  }
 171              }
 172              return $ret;
 173          }
 174          // to really return the id, we need the table and column-name, else we can only return the oid != id
 175          return empty($table) || empty($column) ? $oid : $this->GetOne("SELECT $column FROM $table WHERE oid=".(int)$oid);
 176      }
 177  
 178  // I get this error with PHP before 4.0.6 - jlim
 179  // Warning: This compilation does not support pg_cmdtuples() in d:/inetpub/wwwroot/php/adodb/adodb-postgres.inc.php on line 44
 180     function _affectedrows()
 181     {
 182             if (!is_resource($this->_resultid) || get_resource_type($this->_resultid) !== 'pgsql result') return false;
 183             return pg_cmdtuples($this->_resultid);
 184     }
 185     
 186      
 187          // returns true/false
 188  	function BeginTrans()
 189      {
 190          if ($this->transOff) return true;
 191          $this->transCnt += 1;
 192          return @pg_Exec($this->_connectionID, "begin");
 193      }
 194      
 195  	function RowLock($tables,$where,$flds='1 as ignore') 
 196      {
 197          if (!$this->transCnt) $this->BeginTrans();
 198          return $this->GetOne("select $flds from $tables where $where for update");
 199      }
 200  
 201      // returns true/false. 
 202  	function CommitTrans($ok=true) 
 203      { 
 204          if ($this->transOff) return true;
 205          if (!$ok) return $this->RollbackTrans();
 206          
 207          $this->transCnt -= 1;
 208          return @pg_Exec($this->_connectionID, "commit");
 209      }
 210      
 211      // returns true/false
 212  	function RollbackTrans()
 213      {
 214          if ($this->transOff) return true;
 215          $this->transCnt -= 1;
 216          return @pg_Exec($this->_connectionID, "rollback");
 217      }
 218      
 219      function &MetaTables($ttype=false,$showSchema=false,$mask=false) 
 220      {
 221          $info = $this->ServerInfo();
 222          if ($info['version'] >= 7.3) {
 223              $this->metaTablesSQL = "select tablename,'T' from pg_tables where tablename not like 'pg\_%'
 224                and schemaname  not in ( 'pg_catalog','information_schema')
 225      union 
 226          select viewname,'V' from pg_views where viewname not like 'pg\_%'  and schemaname  not in ( 'pg_catalog','information_schema') ";
 227          }
 228          if ($mask) {
 229              $save = $this->metaTablesSQL;
 230              $mask = $this->qstr(strtolower($mask));
 231              if ($info['version']>=7.3)
 232                  $this->metaTablesSQL = "
 233  select tablename,'T' from pg_tables where tablename like $mask and schemaname not in ( 'pg_catalog','information_schema')  
 234   union 
 235  select viewname,'V' from pg_views where viewname like $mask and schemaname  not in ( 'pg_catalog','information_schema')  ";
 236              else
 237                  $this->metaTablesSQL = "
 238  select tablename,'T' from pg_tables where tablename like $mask 
 239   union 
 240  select viewname,'V' from pg_views where viewname like $mask";
 241          }
 242          $ret =& ADOConnection::MetaTables($ttype,$showSchema);
 243          
 244          if ($mask) {
 245              $this->metaTablesSQL = $save;
 246          }
 247          return $ret;
 248      }
 249      
 250      /*
 251      // if magic quotes disabled, use pg_escape_string()
 252      function qstr($s,$magic_quotes=false)
 253      {
 254          if (!$magic_quotes) {
 255              if (ADODB_PHPVER >= 0x4200) {
 256                  return  "'".pg_escape_string($s)."'";
 257              }
 258              if ($this->replaceQuote[0] == '\\'){
 259                  $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
 260              }
 261              return  "'".str_replace("'",$this->replaceQuote,$s)."'"; 
 262          }
 263          
 264          // undo magic quotes for "
 265          $s = str_replace('\\"','"',$s);
 266          return "'$s'";
 267      }
 268      */
 269      
 270      
 271      // Format date column in sql string given an input format that understands Y M D
 272  	function SQLDate($fmt, $col=false)
 273      {    
 274          if (!$col) $col = $this->sysTimeStamp;
 275          $s = 'TO_CHAR('.$col.",'";
 276          
 277          $len = strlen($fmt);
 278          for ($i=0; $i < $len; $i++) {
 279              $ch = $fmt[$i];
 280              switch($ch) {
 281              case 'Y':
 282              case 'y':
 283                  $s .= 'YYYY';
 284                  break;
 285              case 'Q':
 286              case 'q':
 287                  $s .= 'Q';
 288                  break;
 289                  
 290              case 'M':
 291                  $s .= 'Mon';
 292                  break;
 293                  
 294              case 'm':
 295                  $s .= 'MM';
 296                  break;
 297              case 'D':
 298              case 'd':
 299                  $s .= 'DD';
 300                  break;
 301              
 302              case 'H':
 303                  $s.= 'HH24';
 304                  break;
 305                  
 306              case 'h':
 307                  $s .= 'HH';
 308                  break;
 309                  
 310              case 'i':
 311                  $s .= 'MI';
 312                  break;
 313              
 314              case 's':
 315                  $s .= 'SS';
 316                  break;
 317              
 318              case 'a':
 319              case 'A':
 320                  $s .= 'AM';
 321                  break;
 322                  
 323              case 'w':
 324                  $s .= 'D';
 325                  break;
 326              
 327              case 'l':
 328                  $s .= 'DAY';
 329                  break;
 330                  
 331              default:
 332              // handle escape characters...
 333                  if ($ch == '\\') {
 334                      $i++;
 335                      $ch = substr($fmt,$i,1);
 336                  }
 337                  if (strpos('-/.:;, ',$ch) !== false) $s .= $ch;
 338                  else $s .= '"'.$ch.'"';
 339                  
 340              }
 341          }
 342          return $s. "')";
 343      }
 344      
 345      
 346      
 347      /* 
 348      * Load a Large Object from a file 
 349      * - the procedure stores the object id in the table and imports the object using 
 350      * postgres proprietary blob handling routines 
 351      *
 352      * contributed by Mattia Rossi mattia@technologist.com
 353      * modified for safe mode by juraj chlebec
 354      */ 
 355  	function UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB') 
 356      { 
 357          pg_exec ($this->_connectionID, "begin"); 
 358          
 359          $fd = fopen($path,'r');
 360          $contents = fread($fd,filesize($path));
 361          fclose($fd);
 362          
 363          $oid = pg_lo_create($this->_connectionID);
 364          $handle = pg_lo_open($this->_connectionID, $oid, 'w');
 365          pg_lo_write($handle, $contents);
 366          pg_lo_close($handle);
 367          
 368          // $oid = pg_lo_import ($path); 
 369          pg_exec($this->_connectionID, "commit"); 
 370          $rs = ADOConnection::UpdateBlob($table,$column,$oid,$where,$blobtype); 
 371          $rez = !empty($rs); 
 372          return $rez; 
 373      } 
 374      
 375      /*
 376          Hueristic - not guaranteed to work.
 377      */
 378  	function GuessOID($oid)
 379      {
 380          if (strlen($oid)>16) return false;
 381          return is_numeric($oid);
 382      }
 383      
 384      /* 
 385      * If an OID is detected, then we use pg_lo_* to open the oid file and read the
 386      * real blob from the db using the oid supplied as a parameter. If you are storing
 387      * blobs using bytea, we autodetect and process it so this function is not needed.
 388      *
 389      * contributed by Mattia Rossi mattia@technologist.com
 390      *
 391      * see http://www.postgresql.org/idocs/index.php?largeobjects.html
 392      *
 393      * Since adodb 4.54, this returns the blob, instead of sending it to stdout. Also
 394      * added maxsize parameter, which defaults to $db->maxblobsize if not defined.
 395      */ 
 396  	function BlobDecode($blob,$maxsize=false,$hastrans=true) 
 397      {
 398          if (!$this->GuessOID($blob)) return $blob;
 399          
 400          if ($hastrans) @pg_exec($this->_connectionID,"begin"); 
 401          $fd = @pg_lo_open($this->_connectionID,$blob,"r");
 402          if ($fd === false) {
 403              if ($hastrans) @pg_exec($this->_connectionID,"commit");
 404              return $blob;
 405          }
 406          if (!$maxsize) $maxsize = $this->maxblobsize;
 407          $realblob = @pg_loread($fd,$maxsize); 
 408          @pg_loclose($fd); 
 409          if ($hastrans) @pg_exec($this->_connectionID,"commit"); 
 410          return $realblob;
 411      } 
 412      
 413      /* 
 414          See http://www.postgresql.org/idocs/index.php?datatype-binary.html
 415           
 416          NOTE: SQL string literals (input strings) must be preceded with two backslashes 
 417          due to the fact that they must pass through two parsers in the PostgreSQL 
 418          backend.
 419      */
 420  	function BlobEncode($blob)
 421      {
 422          if (ADODB_PHPVER >= 0x4200) return pg_escape_bytea($blob);
 423          
 424          /*92=backslash, 0=null, 39=single-quote*/
 425          $badch = array(chr(92),chr(0),chr(39)); # \  null  '
 426          $fixch = array('\\\\134','\\\\000','\\\\047');
 427          return adodb_str_replace($badch,$fixch,$blob);
 428          
 429          // note that there is a pg_escape_bytea function only for php 4.2.0 or later
 430      }
 431      
 432      // assumes bytea for blob, and varchar for clob
 433  	function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
 434      {
 435      
 436          if ($blobtype == 'CLOB') {
 437              return $this->Execute("UPDATE $table SET $column=" . $this->qstr($val) . " WHERE $where");
 438          }
 439          // do not use bind params which uses qstr(), as blobencode() already quotes data
 440          return $this->Execute("UPDATE $table SET $column='".$this->BlobEncode($val)."'::bytea WHERE $where");
 441      }
 442      
 443  	function OffsetDate($dayFraction,$date=false)
 444      {        
 445          if (!$date) $date = $this->sysDate;
 446          return "($date+interval'$dayFraction days')";
 447      }
 448      
 449  
 450      // for schema support, pass in the $table param "$schema.$tabname".
 451      // converts field names to lowercase, $upper is ignored
 452      function &MetaColumns($table,$normalize=true) 
 453      {
 454      global $ADODB_FETCH_MODE;
 455      
 456          $schema = false;
 457          $false = false;
 458          $this->_findschema($table,$schema);
 459          
 460          if ($normalize) $table = strtolower($table);
 461  
 462          $save = $ADODB_FETCH_MODE;
 463          $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
 464          if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
 465          
 466          if ($schema) $rs =& $this->Execute(sprintf($this->metaColumnsSQL1,$table,$table,$schema));
 467          else $rs =& $this->Execute(sprintf($this->metaColumnsSQL,$table,$table));
 468          if (isset($savem)) $this->SetFetchMode($savem);
 469          $ADODB_FETCH_MODE = $save;
 470          
 471          if ($rs === false) {
 472              return $false;
 473          }
 474          if (!empty($this->metaKeySQL)) {
 475              // If we want the primary keys, we have to issue a separate query
 476              // Of course, a modified version of the metaColumnsSQL query using a 
 477              // LEFT JOIN would have been much more elegant, but postgres does 
 478              // not support OUTER JOINS. So here is the clumsy way.
 479              
 480              $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
 481              
 482              $rskey = $this->Execute(sprintf($this->metaKeySQL,($table)));
 483              // fetch all result in once for performance.
 484              $keys =& $rskey->GetArray();
 485              if (isset($savem)) $this->SetFetchMode($savem);
 486              $ADODB_FETCH_MODE = $save;
 487              
 488              $rskey->Close();
 489              unset($rskey);
 490          }
 491  
 492          $rsdefa = array();
 493          if (!empty($this->metaDefaultsSQL)) {
 494              $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
 495              $sql = sprintf($this->metaDefaultsSQL, ($table));
 496              $rsdef = $this->Execute($sql);
 497              if (isset($savem)) $this->SetFetchMode($savem);
 498              $ADODB_FETCH_MODE = $save;
 499              
 500              if ($rsdef) {
 501                  while (!$rsdef->EOF) {
 502                      $num = $rsdef->fields['num'];
 503                      $s = $rsdef->fields['def'];
 504                      if (strpos($s,'::')===false && substr($s, 0, 1) == "'") { /* quoted strings hack... for now... fixme */
 505                          $s = substr($s, 1);
 506                          $s = substr($s, 0, strlen($s) - 1);
 507                      }
 508  
 509                      $rsdefa[$num] = $s;
 510                      $rsdef->MoveNext();
 511                  }
 512              } else {
 513                  ADOConnection::outp( "==> SQL => " . $sql);
 514              }
 515              unset($rsdef);
 516          }
 517      
 518          $retarr = array();
 519          while (!$rs->EOF) {     
 520              $fld = new ADOFieldObject();
 521              $fld->name = $rs->fields[0];
 522              $fld->type = $rs->fields[1];
 523              $fld->max_length = $rs->fields[2];
 524              if ($fld->max_length <= 0) $fld->max_length = $rs->fields[3]-4;
 525              if ($fld->max_length <= 0) $fld->max_length = -1;
 526              if ($fld->type == 'numeric') {
 527                  $fld->scale = $fld->max_length & 0xFFFF;
 528                  $fld->max_length >>= 16;
 529              }
 530              // dannym
 531              // 5 hasdefault; 6 num-of-column
 532              $fld->has_default = ($rs->fields[5] == 't');
 533              if ($fld->has_default) {
 534                  $fld->default_value = $rsdefa[$rs->fields[6]];
 535              }
 536  
 537              //Freek
 538              if ($rs->fields[4] == 't') {
 539                  $fld->not_null = true;
 540              }
 541              
 542              // Freek
 543              if (is_array($keys)) {
 544                  foreach($keys as $key) {
 545                      if ($fld->name == $key['column_name'] AND $key['primary_key'] == 't') 
 546                          $fld->primary_key = true;
 547                      if ($fld->name == $key['column_name'] AND $key['unique_key'] == 't') 
 548                          $fld->unique = true; // What name is more compatible?
 549                  }
 550              }
 551              
 552              if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;    
 553              else $retarr[($normalize) ? strtoupper($fld->name) : $fld->name] = $fld;
 554              
 555              $rs->MoveNext();
 556          }
 557          $rs->Close();
 558          if (empty($retarr))
 559              return  $false;
 560          else
 561              return $retarr;    
 562          
 563      }
 564  
 565        function &MetaIndexes ($table, $primary = FALSE)
 566        {
 567           global $ADODB_FETCH_MODE;
 568                  
 569                  $schema = false;
 570                  $this->_findschema($table,$schema);
 571  
 572                  if ($schema) { // requires pgsql 7.3+ - pg_namespace used.
 573                      $sql = '
 574  SELECT c.relname as "Name", i.indisunique as "Unique", i.indkey as "Columns" 
 575  FROM pg_catalog.pg_class c 
 576  JOIN pg_catalog.pg_index i ON i.indexrelid=c.oid 
 577  JOIN pg_catalog.pg_class c2 ON c2.oid=i.indrelid
 578      ,pg_namespace n 
 579  WHERE (c2.relname=\'%s\' or c2.relname=lower(\'%s\')) and c.relnamespace=c2.relnamespace and c.relnamespace=n.oid and n.nspname=\'%s\' AND i.indisprimary=false';
 580                  } else {
 581                      $sql = '
 582  SELECT c.relname as "Name", i.indisunique as "Unique", i.indkey as "Columns"
 583  FROM pg_catalog.pg_class c
 584  JOIN pg_catalog.pg_index i ON i.indexrelid=c.oid
 585  JOIN pg_catalog.pg_class c2 ON c2.oid=i.indrelid
 586  WHERE c2.relname=\'%s\' or c2.relname=lower(\'%s\')';
 587                  }
 588                              
 589                  if ($primary == FALSE) {
 590                      $sql .= ' AND i.indisprimary=false;';
 591                  }
 592                  
 593                  $save = $ADODB_FETCH_MODE;
 594                  $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
 595                  if ($this->fetchMode !== FALSE) {
 596                          $savem = $this->SetFetchMode(FALSE);
 597                  }
 598                  
 599                  $rs = $this->Execute(sprintf($sql,$table,$table,$schema));
 600                  if (isset($savem)) {
 601                          $this->SetFetchMode($savem);
 602                  }
 603                  $ADODB_FETCH_MODE = $save;
 604  
 605                  if (!is_object($rs)) {
 606                      $false = false;
 607                      return $false;
 608                  }
 609                  
 610                  $col_names = $this->MetaColumnNames($table,true);
 611                  $indexes = array();
 612                  while ($row = $rs->FetchRow()) {
 613                          $columns = array();
 614                          foreach (explode(' ', $row[2]) as $col) {
 615                                  $columns[] = $col_names[$col - 1];
 616                          }
 617                          
 618                          $indexes[$row[0]] = array(
 619                                  'unique' => ($row[1] == 't'),
 620                                  'columns' => $columns
 621                          );
 622                  }
 623                  return $indexes;
 624          }
 625  
 626      // returns true or false
 627      //
 628      // examples:
 629      //     $db->Connect("host=host1 user=user1 password=secret port=4341");
 630      //     $db->Connect('host1','user1','secret');
 631  	function _connect($str,$user='',$pwd='',$db='',$ctype=0)
 632      {
 633          
 634          if (!function_exists('pg_pconnect')) return null;
 635          
 636          $this->_errorMsg = false;
 637          
 638          if ($user || $pwd || $db) {
 639              $user = adodb_addslashes($user);
 640              $pwd = adodb_addslashes($pwd);
 641              if (strlen($db) == 0) $db = 'template1';
 642              $db = adodb_addslashes($db);
 643                 if ($str)  {
 644                   $host = split(":", $str);
 645                  if ($host[0]) $str = "host=".adodb_addslashes($host[0]);
 646                  else $str = 'host=localhost';
 647                  if (isset($host[1])) $str .= " port=$host[1]";
 648                  else if (!empty($this->port)) $str .= " port=".$this->port;
 649              }
 650                     if ($user) $str .= " user=".$user;
 651                     if ($pwd)  $str .= " password=".$pwd;
 652                  if ($db)   $str .= " dbname=".$db;
 653          }
 654  
 655          //if ($user) $linea = "user=$user host=$linea password=$pwd dbname=$db port=5432";
 656          
 657          if ($ctype === 1) { // persistent
 658              $this->_connectionID = pg_pconnect($str);
 659          } else {
 660              if ($ctype === -1) { // nconnect, we trick pgsql ext by changing the connection str
 661              static $ncnt;
 662              
 663                  if (empty($ncnt)) $ncnt = 1;
 664                  else $ncnt += 1;
 665                  
 666                  $str .= str_repeat(' ',$ncnt);
 667              }
 668              $this->_connectionID = pg_connect($str);
 669          }
 670          if ($this->_connectionID === false) return false;
 671          $this->Execute("set datestyle='ISO'");
 672          return true;
 673      }
 674      
 675  	function _nconnect($argHostname, $argUsername, $argPassword, $argDatabaseName)
 676      {
 677           return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabaseName,-1);
 678      }
 679       
 680      // returns true or false
 681      //
 682      // examples:
 683      //     $db->PConnect("host=host1 user=user1 password=secret port=4341");
 684      //     $db->PConnect('host1','user1','secret');
 685  	function _pconnect($str,$user='',$pwd='',$db='')
 686      {
 687          return $this->_connect($str,$user,$pwd,$db,1);
 688      }
 689      
 690  
 691      // returns queryID or false
 692  	function _query($sql,$inputarr)
 693      {
 694          
 695          if ($inputarr) {
 696          /*
 697              It appears that PREPARE/EXECUTE is slower for many queries.
 698              
 699              For query executed 1000 times:
 700              "select id,firstname,lastname from adoxyz 
 701                  where firstname not like ? and lastname not like ? and id = ?"
 702                  
 703              with plan = 1.51861286163 secs
 704              no plan =   1.26903700829 secs
 705  
 706              
 707  
 708          */
 709              $plan = 'P'.md5($sql);
 710                  
 711              $execp = '';
 712              foreach($inputarr as $v) {
 713                  if ($execp) $execp .= ',';
 714                  if (is_string($v)) {
 715                      if (strncmp($v,"'",1) !== 0) $execp .= $this->qstr($v);
 716                  } else {
 717                      $execp .= $v;
 718                  }
 719              }
 720              
 721              if ($execp) $exsql = "EXECUTE $plan ($execp)";
 722              else $exsql = "EXECUTE $plan";
 723              
 724              $rez = @pg_exec($this->_connectionID,$exsql);
 725              if (!$rez) {
 726              # Perhaps plan does not exist? Prepare/compile plan.
 727                  $params = '';
 728                  foreach($inputarr as $v) {
 729                      if ($params) $params .= ',';
 730                      if (is_string($v)) {
 731                          $params .= 'VARCHAR';
 732                      } else if (is_integer($v)) {
 733                          $params .= 'INTEGER';
 734                      } else {
 735                          $params .= "REAL";
 736                      }
 737                  }
 738                  $sqlarr = explode('?',$sql);
 739                  //print_r($sqlarr);
 740                  $sql = '';
 741                  $i = 1;
 742                  foreach($sqlarr as $v) {
 743                      $sql .= $v.' $'.$i;
 744                      $i++;
 745                  }
 746                  $s = "PREPARE $plan ($params) AS ".substr($sql,0,strlen($sql)-2);        
 747                  //adodb_pr($s);
 748                  pg_exec($this->_connectionID,$s);
 749                  echo $this->ErrorMsg();
 750              }
 751              
 752              $rez = pg_exec($this->_connectionID,$exsql);
 753          } else {
 754              $this->_errorMsg = false;
 755              //adodb_backtrace();
 756              $rez = pg_exec($this->_connectionID,$sql);
 757          }
 758          // check if no data returned, then no need to create real recordset
 759          if ($rez && pg_numfields($rez) <= 0) {
 760              if (is_resource($this->_resultid) && get_resource_type($this->_resultid) === 'pgsql result') {
 761                  pg_freeresult($this->_resultid);
 762              }
 763              $this->_resultid = $rez;
 764              return true;
 765          }
 766          
 767          return $rez;
 768      }
 769      
 770  
 771      /*    Returns: the last error message from previous database operation    */    
 772  	function ErrorMsg() 
 773      {
 774          if ($this->_errorMsg !== false) return $this->_errorMsg;
 775          if (ADODB_PHPVER >= 0x4300) {
 776              if (!empty($this->_resultid)) {
 777                  $this->_errorMsg = @pg_result_error($this->_resultid);
 778                  if ($this->_errorMsg) return $this->_errorMsg;
 779              }
 780              
 781              if (!empty($this->_connectionID)) {
 782                  $this->_errorMsg = @pg_last_error($this->_connectionID);
 783              } else $this->_errorMsg = @pg_last_error();
 784          } else {
 785              if (empty($this->_connectionID)) $this->_errorMsg = @pg_errormessage();
 786              else $this->_errorMsg = @pg_errormessage($this->_connectionID);
 787          }
 788          return $this->_errorMsg;
 789      }
 790      
 791  	function ErrorNo()
 792      {
 793          $e = $this->ErrorMsg();
 794          if (strlen($e)) {
 795              return ADOConnection::MetaError($e);
 796           }
 797           return 0;
 798      }
 799  
 800      // returns true or false
 801  	function _close()
 802      {
 803          if ($this->transCnt) $this->RollbackTrans();
 804          if ($this->_resultid) {
 805              @pg_freeresult($this->_resultid);
 806              $this->_resultid = false;
 807          }
 808          @pg_close($this->_connectionID);
 809          $this->_connectionID = false;
 810          return true;
 811      }
 812      
 813      
 814      /*
 815      * Maximum size of C field
 816      */
 817  	function CharMax()
 818      {
 819          return 1000000000;  // should be 1 Gb?
 820      }
 821      
 822      /*
 823      * Maximum size of X field
 824      */
 825  	function TextMax()
 826      {
 827          return 1000000000; // should be 1 Gb?
 828      }
 829      
 830          
 831  }
 832      
 833  /*--------------------------------------------------------------------------------------
 834       Class Name: Recordset
 835  --------------------------------------------------------------------------------------*/
 836  
 837  class ADORecordSet_postgres64 extends ADORecordSet{
 838      var $_blobArr;
 839      var $databaseType = "postgres64";
 840      var $canSeek = true;
 841  	function ADORecordSet_postgres64($queryID,$mode=false) 
 842      {
 843          if ($mode === false) { 
 844              global $ADODB_FETCH_MODE;
 845              $mode = $ADODB_FETCH_MODE;
 846          }
 847          switch ($mode)
 848          {
 849          case ADODB_FETCH_NUM: $this->fetchMode = PGSQL_NUM; break;
 850          case ADODB_FETCH_ASSOC:$this->fetchMode = PGSQL_ASSOC; break;
 851          
 852          case ADODB_FETCH_DEFAULT:
 853          case ADODB_FETCH_BOTH:
 854          default: $this->fetchMode = PGSQL_BOTH; break;
 855          }
 856          $this->adodbFetchMode = $mode;
 857          $this->ADORecordSet($queryID);
 858      }
 859      
 860      function &GetRowAssoc($upper=true)
 861      {
 862          if ($this->fetchMode == PGSQL_ASSOC && !$upper) return $this->fields;
 863          $row =& ADORecordSet::GetRowAssoc($upper);
 864          return $row;
 865      }
 866  
 867  	function _initrs()
 868      {
 869      global $ADODB_COUNTRECS;
 870          $qid = $this->_queryID;
 871          $this->_numOfRows = ($ADODB_COUNTRECS)? @pg_numrows($qid):-1;
 872          $this->_numOfFields = @pg_numfields($qid);
 873          
 874          // cache types for blob decode check
 875          // apparently pg_fieldtype actually performs an sql query on the database to get the type.
 876          if (empty($this->connection->noBlobs))
 877          for ($i=0, $max = $this->_numOfFields; $i < $max; $i++) {  
 878              if (pg_fieldtype($qid,$i) == 'bytea') {
 879                  $this->_blobArr[$i] = pg_fieldname($qid,$i);
 880              }
 881          }
 882      }
 883  
 884          /* Use associative array to get fields array */
 885  	function Fields($colname)
 886      {
 887          if ($this->fetchMode != PGSQL_NUM) return @$this->fields[$colname];
 888          
 889          if (!$this->bind) {
 890              $this->bind = array();
 891              for ($i=0; $i < $this->_numOfFields; $i++) {
 892                  $o = $this->FetchField($i);
 893                  $this->bind[strtoupper($o->name)] = $i;
 894              }
 895          }
 896           return $this->fields[$this->bind[strtoupper($colname)]];
 897      }
 898  
 899      function &FetchField($off = 0) 
 900      {
 901          // offsets begin at 0
 902          
 903          $o= new ADOFieldObject();
 904          $o->name = @pg_fieldname($this->_queryID,$off);
 905          $o->type = @pg_fieldtype($this->_queryID,$off);
 906          $o->max_length = @pg_fieldsize($this->_queryID,$off);
 907          return $o;    
 908      }
 909  
 910  	function _seek($row)
 911      {
 912          return @pg_fetch_row($this->_queryID,$row);
 913      }
 914      
 915  	function _decode($blob)
 916      {
 917          eval('$realblob="'.adodb_str_replace(array('"','$'),array('\"','\$'),$blob).'";');
 918          return $realblob;    
 919      }
 920      
 921  	function _fixblobs()
 922      {
 923          if ($this->fetchMode == PGSQL_NUM || $this->fetchMode == PGSQL_BOTH) {
 924              foreach($this->_blobArr as $k => $v) {
 925                  $this->fields[$k] = ADORecordSet_postgres64::_decode($this->fields[$k]);
 926              }
 927          }
 928          if ($this->fetchMode == PGSQL_ASSOC || $this->fetchMode == PGSQL_BOTH) {
 929              foreach($this->_blobArr as $k => $v) {
 930                  $this->fields[$v] = ADORecordSet_postgres64::_decode($this->fields[$v]);
 931              }
 932          }
 933      }
 934      
 935      // 10% speedup to move MoveNext to child class
 936  	function MoveNext() 
 937      {
 938          if (!$this->EOF) {
 939              $this->_currentRow++;
 940              if ($this->_numOfRows < 0 || $this->_numOfRows > $this->_currentRow) {
 941                  $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);
 942                  if (is_array($this->fields) && $this->fields) {
 943                      if (isset($this->_blobArr)) $this->_fixblobs();
 944                      return true;
 945                  }
 946              }
 947              $this->fields = false;
 948              $this->EOF = true;
 949          }
 950          return false;
 951      }        
 952      
 953  	function _fetch()
 954      {
 955                  
 956          if ($this->_currentRow >= $this->_numOfRows && $this->_numOfRows >= 0)
 957              return false;
 958  
 959          $this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);
 960          
 961          if ($this->fields && isset($this->_blobArr)) $this->_fixblobs();
 962              
 963          return (is_array($this->fields));
 964      }
 965  
 966  	function _close() 
 967      { 
 968          return @pg_freeresult($this->_queryID);
 969      }
 970  
 971  	function MetaType($t,$len=-1,$fieldobj=false)
 972      {
 973          if (is_object($t)) {
 974              $fieldobj = $t;
 975              $t = $fieldobj->type;
 976              $len = $fieldobj->max_length;
 977          }
 978          switch (strtoupper($t)) {
 979                  case 'MONEY': // stupid, postgres expects money to be a string
 980                  case 'INTERVAL':
 981                  case 'CHAR':
 982                  case 'CHARACTER':
 983                  case 'VARCHAR':
 984                  case 'NAME':
 985                     case 'BPCHAR':
 986                  case '_VARCHAR':
 987                  case 'INET':
 988                      if ($len <= $this->blobSize) return 'C';
 989                  
 990                  case 'TEXT':
 991                      return 'X';
 992          
 993                  case 'IMAGE': // user defined type
 994                  case 'BLOB': // user defined type
 995                  case 'BIT':    // This is a bit string, not a single bit, so don't return 'L'
 996                  case 'VARBIT':
 997                  case 'BYTEA':
 998                      return 'B';
 999                  
1000                  case 'BOOL':
1001                  case 'BOOLEAN':
1002                      return 'L';
1003                  
1004                  case 'DATE':
1005                      return 'D';
1006                  
1007                  case 'TIME':
1008                  case 'DATETIME':
1009                  case 'TIMESTAMP':
1010                  case 'TIMESTAMPTZ':
1011                      return 'T';
1012                  
1013                  case 'SMALLINT': 
1014                  case 'BIGINT': 
1015                  case 'INTEGER': 
1016                  case 'INT8': 
1017                  case 'INT4':
1018                  case 'INT2':
1019                      if (isset($fieldobj) &&
1020                  empty($fieldobj->primary_key) && empty($fieldobj->unique)) return 'I';
1021                  
1022                  case 'OID':
1023                  case 'SERIAL':
1024                      return 'R';
1025                  
1026                   default:
1027                       return 'N';
1028              }
1029      }
1030  
1031  }
1032  ?>


Généré le : Sun Feb 25 17:20:01 2007 par Balluche grâce à PHPXref 0.7