# PgSQL.class.php

Go to the documentation of this file.

    00001 <?php
    00002 /***************************************************************************
    00003  *   Copyright (C) 2004-2009 by Konstantin V. Arkhipov                     *
    00004  *                                                                         *
    00005  *   This program is free software; you can redistribute it and/or modify  *
    00006  *   it under the terms of the GNU Lesser General Public License as        *
    00007  *   published by the Free Software Foundation; either version 3 of the    *
    00008  *   License, or (at your option) any later version.                       *
    00009  *                                                                         *
    00010  ***************************************************************************/
    00011
    00019     final class PgSQL extends DB
    00020     {
    00024         public static function getDialect()
    00025         {
    00026             return PostgresDialect::me();
    00027         }
    00028
    00032         public function connect()
    00033         {
    00034             $conn =
    00035                 "host={$this->hostname} user={$this->username}"
    00036                 .($this->password ? " password={$this->password}" : null)
    00037                 .($this->basename ? " dbname={$this->basename}" : null)
    00038                 .($this->port ? " port={$this->port}" : null);
    00039
    00040             if ($this->persistent)
    00041                 $this->link = pg_pconnect($conn);
    00042             else
    00043                 $this->link = pg_connect($conn);
    00044
    00045             if (!$this->link)
    00046                 throw new DatabaseException(
    00047                     'can not connect to PostgreSQL server: '.pg_errormessage()
    00048                 );
    00049
    00050             if ($this->encoding)
    00051                 $this->setDbEncoding();
    00052
    00053             pg_set_error_verbosity($this->link, PGSQL_ERRORS_VERBOSE);
    00054
    00055             return $this;
    00056         }
    00057
    00061         public function disconnect()
    00062         {
    00063             if ($this->isConnected())
    00064                 pg_close($this->link);
    00065
    00066             return $this;
    00067         }
    00068
    00069         public function isConnected()
    00070         {
    00071             return is_resource($this->link);
    00072         }
    00073
    00078         public function obtainSequence($sequence)
    00079         {
    00080             $res = $this->queryRaw("select nextval('{$sequence}') as seq");
    00081             $row = pg_fetch_assoc($res);
    00082             pg_free_result($res);
    00083             return $row['seq'];
    00084         }
    00085
    00089         public function setDbEncoding()
    00090         {
    00091             pg_set_client_encoding($this->link, $this->encoding);
    00092
    00093             return $this;
    00094         }
    00095
    00100         public function queryRaw($queryString)
    00101         {
    00102             try {
    00103                 return pg_query($this->link, $queryString);
    00104             } catch (BaseException $e) {
    00105                 // manual parsing, since pg_send_query() and
    00106                 // pg_get_result() is too slow in our case
    00107                 list($error, ) = explode("\n", pg_errormessage($this->link));
    00108                 $code = substr($error, 8, 5);
    00109
    00110                 if ($code == PostgresError::UNIQUE_VIOLATION) {
    00111                     $e = 'DuplicateObjectException';
    00112                     $code = null;
    00113                 } else
    00114                     $e = 'PostgresDatabaseException';
    00115
    00116                 throw new $e($error.' - '.$queryString, $code);
    00117             }
    00118         }
    00119
    00124         public function queryCount(Query $query)
    00125         {
    00126             return pg_affected_rows($this->queryNull($query));
    00127         }
    00128
    00129         public function queryRow(Query $query)
    00130         {
    00131             $res = $this->query($query);
    00132
    00133             if ($this->checkSingle($res)) {
    00134                 $ret = pg_fetch_assoc($res);
    00135                 pg_free_result($res);
    00136                 return $ret;
    00137             } else
    00138                 return null;
    00139         }
    00140
    00141         public function queryColumn(Query $query)
    00142         {
    00143             $res = $this->query($query);
    00144
    00145             if ($res) {
    00146                 $array = array();
    00147
    00148                 while ($row = pg_fetch_row($res))
    00149                     $array[] = $row[0];
    00150
    00151                 pg_free_result($res);
    00152                 return $array;
    00153             } else
    00154                 return null;
    00155         }
    00156
    00157         public function querySet(Query $query)
    00158         {
    00159             $res = $this->query($query);
    00160
    00161             if ($res) {
    00162                 $array = array();
    00163
    00164                 while ($row = pg_fetch_assoc($res))
    00165                     $array[] = $row;
    00166
    00167                 pg_free_result($res);
    00168                 return $array;
    00169             } else
    00170                 return null;
    00171         }
    00172
    00173         public function hasSequences()
    00174         {
    00175             return true;
    00176         }
    00177
    00182         public function getTableInfo($table)
    00183         {
    00184             static $types = array(
    00185                 'time'          => DataType::TIME,
    00186                 'date'          => DataType::DATE,
    00187                 'timestamp'     => DataType::TIMESTAMP,
    00188
    00189                 'bool'          => DataType::BOOLEAN,
    00190
    00191                 'int2'          => DataType::SMALLINT,
    00192                 'int4'          => DataType::INTEGER,
    00193                 'int8'          => DataType::BIGINT,
    00194                 'numeric'       => DataType::NUMERIC,
    00195
    00196                 'float4'        => DataType::REAL,
    00197                 'float8'        => DataType::DOUBLE,
    00198
    00199                 'varchar'       => DataType::VARCHAR,
    00200                 'bpchar'        => DataType::CHAR,
    00201                 'text'          => DataType::TEXT,
    00202
    00203                 'bytea'         => DataType::BINARY,
    00204
    00205                 // unhandled types, not ours anyway
    00206                 'tsvector'      => null,
    00207                 'inet'          => null,
    00208                 'ltree'         => null,
    00209                 'hstore'        => null,
    00210             );
    00211
    00212             try {
    00213                 $res = pg_meta_data($this->link, $table);
    00214             } catch (BaseException $e) {
    00215                 throw new ObjectNotFoundException(
    00216                     "unknown table '{$table}'"
    00217                 );
    00218             }
    00219
    00220             $table = new DBTable($table);
    00221
    00222             foreach ($res as $name => $info) {
    00223
    00224                 Assert::isTrue(
    00225                     array_key_exists($info['type'], $types),
    00226
    00227                     'unknown type "'
    00228                     .$types[$info['type']]
    00229                     .'" found in column "'.$name.'"'
    00230                 );
    00231
    00232                 if (empty($types[$info['type']]))
    00233                     continue;
    00234
    00235                 $column =
    00236                     new DBColumn(
    00237                         DataType::create($types[$info['type']])->
    00238                         setNull(!$info['not null']),
    00239
    00240                         $name
    00241                     );
    00242
    00243                 $table->addColumn($column);
    00244             }
    00245
    00246             return $table;
    00247         }
    00248
    00249         private function checkSingle($result)
    00250         {
    00251             if (pg_num_rows($result) > 1)
    00252                 throw new TooManyRowsException(
    00253                     'query returned too many rows (we need only one)'
    00254                 );
    00255
    00256             return $result;
    00257         }
    00258     }
    00259 ?>