| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 | 
							- <?php
 
- /**
 
-  * @file
 
-  * Database interface code for PostgreSQL database servers.
 
-  */
 
- /**
 
-  * @addtogroup database
 
-  * @{
 
-  */
 
- /**
 
-  * The name by which to obtain a lock for retrive the next insert id.
 
-  */
 
- define('POSTGRESQL_NEXTID_LOCK', 1000);
 
- class DatabaseConnection_pgsql extends DatabaseConnection {
 
-   public function __construct(array $connection_options = array()) {
 
-     // This driver defaults to transaction support, except if explicitly passed FALSE.
 
-     $this->transactionSupport = !isset($connection_options['transactions']) || ($connection_options['transactions'] !== FALSE);
 
-     // Transactional DDL is always available in PostgreSQL,
 
-     // but we'll only enable it if standard transactions are.
 
-     $this->transactionalDDLSupport = $this->transactionSupport;
 
-     // Default to TCP connection on port 5432.
 
-     if (empty($connection_options['port'])) {
 
-       $connection_options['port'] = 5432;
 
-     }
 
-     // PostgreSQL in trust mode doesn't require a password to be supplied.
 
-     if (empty($connection_options['password'])) {
 
-       $connection_options['password'] = NULL;
 
-     }
 
-     // If the password contains a backslash it is treated as an escape character
 
-     // http://bugs.php.net/bug.php?id=53217
 
-     // so backslashes in the password need to be doubled up.
 
-     // The bug was reported against pdo_pgsql 1.0.2, backslashes in passwords
 
-     // will break on this doubling up when the bug is fixed, so check the version
 
-     //elseif (phpversion('pdo_pgsql') < 'version_this_was_fixed_in') {
 
-     else {
 
-       $connection_options['password'] = str_replace('\\', '\\\\', $connection_options['password']);
 
-     }
 
-     $this->connectionOptions = $connection_options;
 
-     $dsn = 'pgsql:host=' . $connection_options['host'] . ' dbname=' . $connection_options['database'] . ' port=' . $connection_options['port'];
 
-     // Allow PDO options to be overridden.
 
-     $connection_options += array(
 
-       'pdo' => array(),
 
-     );
 
-     $connection_options['pdo'] += array(
 
-       // Prepared statements are most effective for performance when queries
 
-       // are recycled (used several times). However, if they are not re-used,
 
-       // prepared statements become ineffecient. Since most of Drupal's
 
-       // prepared queries are not re-used, it should be faster to emulate
 
-       // the preparation than to actually ready statements for re-use. If in
 
-       // doubt, reset to FALSE and measure performance.
 
-       PDO::ATTR_EMULATE_PREPARES => TRUE,
 
-       // Convert numeric values to strings when fetching.
 
-       PDO::ATTR_STRINGIFY_FETCHES => TRUE,
 
-     );
 
-     parent::__construct($dsn, $connection_options['username'], $connection_options['password'], $connection_options['pdo']);
 
-     // Force PostgreSQL to use the UTF-8 character set by default.
 
-     $this->exec("SET NAMES 'UTF8'");
 
-     // Execute PostgreSQL init_commands.
 
-     if (isset($connection_options['init_commands'])) {
 
-       $this->exec(implode('; ', $connection_options['init_commands']));
 
-     }
 
-   }
 
-   public function prepareQuery($query) {
 
-     // mapConditionOperator converts LIKE operations to ILIKE for consistency
 
-     // with MySQL. However, Postgres does not support ILIKE on bytea (blobs)
 
-     // fields.
 
-     // To make the ILIKE operator work, we type-cast bytea fields into text.
 
-     // @todo This workaround only affects bytea fields, but the involved field
 
-     //   types involved in the query are unknown, so there is no way to
 
-     //   conditionally execute this for affected queries only.
 
-     return parent::prepareQuery(preg_replace('/ ([^ ]+) +(I*LIKE|NOT +I*LIKE) /i', ' ${1}::text ${2} ', $query));
 
-   }
 
-   public function query($query, array $args = array(), $options = array()) {
 
-     $options += $this->defaultOptions();
 
-     // The PDO PostgreSQL driver has a bug which
 
-     // doesn't type cast booleans correctly when
 
-     // parameters are bound using associative
 
-     // arrays.
 
-     // See http://bugs.php.net/bug.php?id=48383
 
-     foreach ($args as &$value) {
 
-       if (is_bool($value)) {
 
-         $value = (int) $value;
 
-       }
 
-     }
 
-     try {
 
-       if ($query instanceof DatabaseStatementInterface) {
 
-         $stmt = $query;
 
-         $stmt->execute(NULL, $options);
 
-       }
 
-       else {
 
-         $this->expandArguments($query, $args);
 
-         $stmt = $this->prepareQuery($query);
 
-         $stmt->execute($args, $options);
 
-       }
 
-       switch ($options['return']) {
 
-         case Database::RETURN_STATEMENT:
 
-           return $stmt;
 
-         case Database::RETURN_AFFECTED:
 
-           return $stmt->rowCount();
 
-         case Database::RETURN_INSERT_ID:
 
-           return $this->lastInsertId($options['sequence_name']);
 
-         case Database::RETURN_NULL:
 
-           return;
 
-         default:
 
-           throw new PDOException('Invalid return directive: ' . $options['return']);
 
-       }
 
-     }
 
-     catch (PDOException $e) {
 
-       if ($options['throw_exception']) {
 
-         // Add additional debug information.
 
-         if ($query instanceof DatabaseStatementInterface) {
 
-           $e->query_string = $stmt->getQueryString();
 
-         }
 
-         else {
 
-           $e->query_string = $query;
 
-         }
 
-         $e->args = $args;
 
-         throw $e;
 
-       }
 
-       return NULL;
 
-     }
 
-   }
 
-   public function queryRange($query, $from, $count, array $args = array(), array $options = array()) {
 
-     return $this->query($query . ' LIMIT ' . (int) $count . ' OFFSET ' . (int) $from, $args, $options);
 
-   }
 
-   public function queryTemporary($query, array $args = array(), array $options = array()) {
 
-     $tablename = $this->generateTemporaryTableName();
 
-     $this->query('CREATE TEMPORARY TABLE {' . $tablename . '} AS ' . $query, $args, $options);
 
-     return $tablename;
 
-   }
 
-   public function driver() {
 
-     return 'pgsql';
 
-   }
 
-   public function databaseType() {
 
-     return 'pgsql';
 
-   }
 
-   public function mapConditionOperator($operator) {
 
-     static $specials;
 
-     // Function calls not allowed in static declarations, thus this method.
 
-     if (!isset($specials)) {
 
-       $specials = array(
 
-         // In PostgreSQL, 'LIKE' is case-sensitive. For case-insensitive LIKE
 
-         // statements, we need to use ILIKE instead.
 
-         'LIKE' => array('operator' => 'ILIKE'),
 
-         'NOT LIKE' => array('operator' => 'NOT ILIKE'),
 
-       );
 
-     }
 
-     return isset($specials[$operator]) ? $specials[$operator] : NULL;
 
-   }
 
-   /**
 
-    * Retrive a the next id in a sequence.
 
-    *
 
-    * PostgreSQL has built in sequences. We'll use these instead of inserting
 
-    * and updating a sequences table.
 
-    */
 
-   public function nextId($existing = 0) {
 
-     // Retrive the name of the sequence. This information cannot be cached
 
-     // because the prefix may change, for example, like it does in simpletests.
 
-     $sequence_name = $this->makeSequenceName('sequences', 'value');
 
-     // When PostgreSQL gets a value too small then it will lock the table,
 
-     // retry the INSERT and if it's still too small then alter the sequence.
 
-     $id = $this->query("SELECT nextval('" . $sequence_name . "')")->fetchField();
 
-     if ($id > $existing) {
 
-       return $id;
 
-     }
 
-     // PostgreSQL advisory locks are simply locks to be used by an
 
-     // application such as Drupal. This will prevent other Drupal proccesses
 
-     // from altering the sequence while we are.
 
-     $this->query("SELECT pg_advisory_lock(" . POSTGRESQL_NEXTID_LOCK . ")");
 
-     // While waiting to obtain the lock, the sequence may have been altered
 
-     // so lets try again to obtain an adequate value.
 
-     $id = $this->query("SELECT nextval('" . $sequence_name . "')")->fetchField();
 
-     if ($id > $existing) {
 
-       $this->query("SELECT pg_advisory_unlock(" . POSTGRESQL_NEXTID_LOCK . ")");
 
-       return $id;
 
-     }
 
-     // Reset the sequence to a higher value than the existing id.
 
-     $this->query("ALTER SEQUENCE " . $sequence_name . " RESTART WITH " . ($existing + 1));
 
-     // Retrive the next id. We know this will be as high as we want it.
 
-     $id = $this->query("SELECT nextval('" . $sequence_name . "')")->fetchField();
 
-     $this->query("SELECT pg_advisory_unlock(" . POSTGRESQL_NEXTID_LOCK . ")");
 
-     return $id;
 
-   }
 
- }
 
- /**
 
-  * @} End of "addtogroup database".
 
-  */
 
 
  |