[ Index ]
 

Code source de vtiger CRM 5.0.2

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

title

Body

[fermer]

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

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


Généré le : Sun Feb 25 10:22:19 2007 par Balluche grâce à PHPXref 0.7