Source for file postgresql.php
Documentation is available at postgresql.php
* @package Joomla.Platform
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE
* PostgreSQL database driver
* @package Joomla.Platform
* The database driver name
public $name =
'postgresql';
* Quote for named objects
* The null/zero date string
* The minimum supported database version.
protected static $dbMinimum =
'8.3.18';
* Operator used for concatenation
* JDatabaseDriverPostgresqlQuery object returned by getQuery
* @var JDatabaseDriverPostgresqlQuery
* Database object constructor
* @param array $options List of options used to configure the connection
$options['host'] =
(isset
($options['host'])) ?
$options['host'] :
'localhost';
$options['user'] =
(isset
($options['user'])) ?
$options['user'] :
'';
$options['password'] =
(isset
($options['password'])) ?
$options['password'] :
'';
$options['database'] =
(isset
($options['database'])) ?
$options['database'] :
'';
// Finalize initialization
* Database object destructor
* Connects to the database if needed.
* @return void Returns void if the database connected successfully.
* @throws RuntimeException
// Make sure the postgresql extension for PHP is installed and enabled.
throw
new RuntimeException('PHP extension pg_connect is not available.');
// Build the DSN for the connection.
$dsn =
"host={$this->options['host']} dbname={
$this->options['database']} user={
$this->options['user']} password={
$this->options['password']}";
// Attempt to connect to the server.
throw
new RuntimeException('Error connecting to PGSQL database.');
pg_set_error_verbosity($this->connection, PGSQL_ERRORS_DEFAULT);
pg_query('SET standard_conforming_strings=off');
* Disconnects the database.
* Method to escape a string for usage in an SQL statement.
* @param string $text The string to be escaped.
* @param boolean $extra Optional parameter to provide extra escaping.
* @return string The escaped string.
public function escape($text, $extra =
false)
$result =
pg_escape_string($this->connection, $text);
* Test to see if the PostgreSQL connector is available
* @return boolean True on success, false otherwise.
public static function test()
* Determines if the connection to the server is active.
* Drops a table from the database.
* @param string $tableName The name of the database table to drop.
* @param boolean $ifExists Optionally specify that the table must exist before it is dropped.
* @throws RuntimeException
public function dropTable($tableName, $ifExists =
true)
$this->setQuery('DROP TABLE ' .
($ifExists ?
'IF EXISTS ' :
'') .
$this->quoteName($tableName));
* Get the number of affected rows for the previous executed SQL statement.
* @return integer The number of affected rows in the previous operation
return pg_affected_rows($this->cursor);
* Method to get the database collation in use by sampling a text field of a table in the database.
* @return mixed The collation in use by the database or boolean false if not supported.
* @throws RuntimeException
return $array[0]['lc_collate'];
* Get the number of returned rows for the previous executed SQL statement.
* @param resource $cur An optional database cursor resource to extract the row count from.
* @return integer The number of returned rows.
return pg_num_rows((int)
$cur ?
$cur :
$this->cursor);
* Get the current or query, or new JDatabaseQuery object.
* @param boolean $new False to return the last query set, True to return a new JDatabaseQuery object.
* @param boolean $asObj False to return last query as string, true to get JDatabaseQueryPostgresql object.
* @return JDatabaseQuery The current query object or a new object extending the JDatabaseQuery class.
* @throws RuntimeException
public function getQuery($new =
false, $asObj =
false)
// Make sure we have a query class for this driver.
throw
new RuntimeException('JDatabaseQueryPostgresql Class not found.');
* Shows the table CREATE statement that creates the given tables.
* This is unsuported by PostgreSQL.
* @param mixed $tables A table name or a list of table names.
* @return string An empty char because this function is not supported by PostgreSQL.
* Retrieves field information about a given table.
* @param string $table The name of the database table.
* @param boolean $typeOnly True to only return field types.
* @return array An array of fields for the database table.
* @throws RuntimeException
SELECT a.attname AS "column_name",
pg_catalog.format_type(a.atttypid, a.atttypmod) as "type",
CASE WHEN a.attnotnull IS TRUE
CASE WHEN pg_catalog.pg_get_expr(adef.adbin, adef.adrelid, true) IS NOT NULL
THEN pg_catalog.pg_get_expr(adef.adbin, adef.adrelid, true)
CASE WHEN pg_catalog.col_description(a.attrelid, a.attnum) IS NULL
ELSE pg_catalog.col_description(a.attrelid, a.attnum)
FROM pg_catalog.pg_attribute a
LEFT JOIN pg_catalog.pg_attrdef adef ON a.attrelid=adef.adrelid AND a.attnum=adef.adnum
LEFT JOIN pg_catalog.pg_type t ON a.atttypid=t.oid
(SELECT oid FROM pg_catalog.pg_class WHERE relname=' .
$this->quote($tableSub) .
'
AND relnamespace = (SELECT oid FROM pg_catalog.pg_namespace WHERE
AND a.attnum > 0 AND NOT a.attisdropped
foreach ($fields as $field)
$result[$field->column_name] =
preg_replace("/[(0-9)]/", '', $field->type);
foreach ($fields as $field)
$result[$field->column_name] =
$field;
/* Change Postgresql's NULL::* type with PHP's null one */
foreach ($fields as $field)
* Get the details list of keys for a table.
* @param string $table The name of the table.
* @return array An array of the column specification for the table.
* @throws RuntimeException
// To check if table exists and prevent SQL injection
// Get the details columns information.
SELECT indexname AS "idxName", indisprimary AS "isPrimary", indisunique AS "isUnique",
CASE WHEN indisprimary = true THEN
( SELECT \'ALTER TABLE \' || tablename || \' ADD \' || pg_catalog.pg_get_constraintdef(const.oid, true)
FROM pg_constraint AS const WHERE const.conname= pgClassFirst.relname )
ELSE pg_catalog.pg_get_indexdef(indexrelid, 0, true)
LEFT JOIN pg_class AS pgClassFirst ON indexname=pgClassFirst.relname
LEFT JOIN pg_index AS pgIndex ON pgClassFirst.oid=pgIndex.indexrelid
WHERE tablename=' .
$this->quote($table) .
' ORDER BY indkey'
* Method to get an array of all tables in the database.
* @return array An array of all the tables in the database.
* @throws RuntimeException
->from('information_schema.tables')
->where('table_type=' .
$this->quote('BASE TABLE'))
->where('table_schema NOT IN (' .
$this->quote('pg_catalog') .
', ' .
$this->quote('information_schema') .
')')
->order('table_name ASC');
* Get the details list of sequences for a table.
* @param string $table The name of the table.
* @return array An array of sequences specification for the table.
* @throws RuntimeException
// To check if table exists and prevent SQL injection
's.relname', 'n.nspname', 't.relname', 'a.attname', 'info.data_type', 'info.minimum_value', 'info.maximum_value',
'info.increment', 'info.cycle_option'
$as =
array('sequence', 'schema', 'table', 'column', 'data_type', 'minimum_value', 'maximum_value', 'increment', 'cycle_option');
$name[] .=
'info.start_value';
// Get the details columns information.
->join('LEFT', "pg_depend d ON d.objid=s.oid AND d.classid='pg_class'::regclass AND d.refclassid='pg_class'::regclass")
->join('LEFT', 'pg_class t ON t.oid=d.refobjid')
->join('LEFT', 'pg_namespace n ON n.oid=t.relnamespace')
->join('LEFT', 'pg_attribute a ON a.attrelid=t.oid AND a.attnum=d.refobjsubid')
->join('LEFT', 'information_schema.sequences AS info ON info.sequence_name=s.relname')
->where("s.relkind='S' AND d.deptype='a' AND t.relname=" .
$this->quote($table));
* Get the version of the database connector.
* @return string The database connector version.
return $version['server'];
* Method to get the auto-incremented value from the last INSERT statement.
* To be called after the INSERT statement, it's MANDATORY to have a sequence on
* every primary key table.
* To get the auto incremented value it's possible to call this function after
* INSERT INTO query, or use INSERT INTO with RETURNING clause.
* @example with insertid() call:
* $query = $this->getQuery(true)
* ->columns('title,start_date,description')
* ->values("'testTitle2nd','1971-01-01','testDescription2nd'");
* $this->setQuery($query);
* $id = $this->insertid();
* @example with RETURNING clause:
* $query = $this->getQuery(true)
* ->columns('title,start_date,description')
* ->values("'testTitle2nd','1971-01-01','testDescription2nd'")
* $this->setQuery($query);
* $id = $this->loadResult();
* @return integer The value of the auto-increment field from the last inserted row.
$insertQuery =
$this->getQuery(false, true);
$table =
$insertQuery->__get('insert')->getElements();
/* find sequence column name */
$colNameQuery->select('column_default')
->from('information_schema.columns')
->where("column_default LIKE '%nextval%'");
$changedColName =
str_replace('nextval', 'currval', $colName);
$insertidQuery->select($changedColName);
* Locks a table in the database.
* @param string $tableName The name of the table to unlock.
* @return JDatabaseDriverPostgresql Returns this object to support chaining.
* @throws RuntimeException
$this->setQuery('LOCK TABLE ' .
$this->quoteName($tableName) .
' IN ACCESS EXCLUSIVE MODE')->execute();
* Execute the SQL statement.
* @return mixed A database cursor resource on success, boolean false on failure.
* @throws RuntimeException
// Take a local copy so that we don't modify the original query and cause issues later
$query .=
' LIMIT ' .
$this->limit .
' OFFSET ' .
$this->offset;
// Increment the query counter.
// Reset the error values.
// If debugging is enabled then let's log the query.
// Add the query to the object queue.
// Execute the query. Error suppression is used here to prevent warnings/notices that the connection has been lost.
if (defined('DEBUG_BACKTRACE_IGNORE_ARGS'))
// If an error occurred handle it.
// Check if the server was disconnected.
// If connect fails, ignore that exception and throw the normal exception.
catch
(RuntimeException $e)
// Get the error number and message.
$this->errorNum = (int)
pg_result_error_field($this->cursor, PGSQL_DIAG_SQLSTATE) .
' ';
// Throw the normal query exception.
throw
new RuntimeException($this->errorMsg);
// Since we were able to reconnect, run the query again.
// The server was not disconnected.
// Get the error number and message.
$this->errorNum = (int)
pg_result_error_field($this->cursor, PGSQL_DIAG_SQLSTATE) .
' ';
// Throw the normal query exception.
throw
new RuntimeException($this->errorMsg);
* Renames a table in the database.
* @param string $oldTable The name of the table to be renamed
* @param string $newTable The new name for the table.
* @param string $backup Not used by PostgreSQL.
* @param string $prefix Not used by PostgreSQL.
* @return JDatabaseDriverPostgresql Returns this object to support chaining.
* @throws RuntimeException
public function renameTable($oldTable, $newTable, $backup =
null, $prefix =
null)
// To check if table exists and prevent SQL injection
// Origin Table does not exist
// Origin Table not found
throw
new RuntimeException('Table not found in Postgresql database.');
WHERE pg_class.relname=' .
$this->quote($oldTable, true) .
'
AND pg_class.oid=pg_index.indrelid );'
foreach ($oldIndexes as $oldIndex)
$changedIdxName =
str_replace($oldTable, $newTable, $oldIndex);
$this->setQuery('ALTER INDEX ' .
$this->escape($oldIndex) .
' RENAME TO ' .
$this->escape($changedIdxName));
WHERE nspname NOT LIKE \'pg_%\'
AND nspname != \'information_schema\'
AND relname LIKE \'%' .
$oldTable .
'%\' ;'
foreach ($oldSequences as $oldSequence)
$changedSequenceName =
str_replace($oldTable, $newTable, $oldSequence);
$this->setQuery('ALTER SEQUENCE ' .
$this->escape($oldSequence) .
' RENAME TO ' .
$this->escape($changedSequenceName));
$this->setQuery('ALTER TABLE ' .
$this->escape($oldTable) .
' RENAME TO ' .
$this->escape($newTable));
* Selects the database, but redundant for PostgreSQL
* @param string $database Database name to select.
* @return boolean Always true
public function select($database)
* Custom settings for UTF support
* @return integer Zero on success, -1 on failure
return pg_set_client_encoding($this->connection, 'UTF8');
* This function return a field value as a prepared string to be used in a SQL statement.
* @param array $columns Array of table's column returned by ::getTableColumns.
* @param string $field_name The table field's name.
* @param string $field_value The variable value to quote and return.
* @return string The quoted string.
public function sqlValue($columns, $field_name, $field_value)
switch ($columns[$field_name])
elseif ($field_value ==
'f')
$val =
strlen($field_value) ==
0 ?
'NULL' :
$field_value;
case 'timestamp without time zone':
$val =
$this->quote($field_value);
$val =
$this->quote($field_value);
* Method to commit a transaction.
* @param boolean $toSavepoint If true, commit to the last savepoint.
* @throws RuntimeException
if ($this->setQuery('COMMIT')->execute())
* Method to roll back a transaction.
* @param boolean $toSavepoint If true, rollback to the last savepoint.
* @throws RuntimeException
if ($this->setQuery('ROLLBACK')->execute())
* Method to initialize a transaction.
* @param boolean $asSavepoint If true and a transaction is already active, a savepoint will be created.
* @throws RuntimeException
if ($this->setQuery('START TRANSACTION')->execute())
* Method to fetch a row from the result set cursor as an array.
* @param mixed $cursor The optional result set cursor from which to fetch the row.
* @return mixed Either the next row from the result set or false if there are no more rows.
return pg_fetch_row($cursor ?
$cursor :
$this->cursor);
* Method to fetch a row from the result set cursor as an associative array.
* @param mixed $cursor The optional result set cursor from which to fetch the row.
* @return mixed Either the next row from the result set or false if there are no more rows.
return pg_fetch_assoc($cursor ?
$cursor :
$this->cursor);
* Method to fetch a row from the result set cursor as an object.
* @param mixed $cursor The optional result set cursor from which to fetch the row.
* @param string $class The class name to use for the returned row object.
* @return mixed Either the next row from the result set or false if there are no more rows.
protected function fetchObject($cursor =
null, $class =
'stdClass')
return pg_fetch_object(is_null($cursor) ?
$this->cursor :
$cursor, null, $class);
* Method to free up the memory used for the result set.
* @param mixed $cursor The optional result set cursor from which to fetch the row.
pg_free_result($cursor ?
$cursor :
$this->cursor);
* Inserts a row into a table based on an object's properties.
* @param string $table The name of the database table to insert into.
* @param object &$object A reference to an object whose public properties match the table fields.
* @param string $key The name of the primary key. If provided the object property is updated.
* @return boolean True on success.
* @throws RuntimeException
// Iterate over the object variables to build the query fields and values.
// Only process non-null scalars.
// Ignore any internal fields.
// Prepare and sanitize the fields and values for the database query.
$values[] =
$this->sqlValue($columns, $k, $v);
// Create the base insert statement.
// Set the query and execute the insert.
// Set the query and execute the insert.
* Test to see if the PostgreSQL connector is available.
* @return boolean True on success, false otherwise.
* Returns an array containing database's table list.
* @return array The database's table list.
->from('information_schema.tables')
->where('table_type = ' .
$this->quote('BASE TABLE'))
->where('table_schema NOT IN (' .
$this->quote('pg_catalog') .
', ' .
$this->quote('information_schema') .
' )');
* Get the substring position inside a string
* @param string $substring The string being sought
* @param string $string The string/column being searched
* @return integer The position of $substring in $string
$query =
"SELECT POSITION( $substring IN $string )";
return $position['position'];
* Generate a random value
* @return float The random generated number
return $random['random'];
* Get the query string to alter the database character set.
* @param string $dbName The database name
* @return string The query that alter the database query string
$query =
'ALTER DATABASE ' .
$this->quoteName($dbName) .
' SET CLIENT_ENCODING TO ' .
$this->quote('UTF8');
* Get the query string to create new Database in correct PostgreSQL syntax.
* @param object $options object coming from "initialise" function to pass user and database name to database driver.
* @param boolean $utf True if the database supports the UTF-8 character set, not used in PostgreSQL "CREATE DATABASE" query.
* @return string The query that creates database, owned by $options['user']
$query =
'CREATE DATABASE ' .
$this->quoteName($options->db_name) .
' OWNER ' .
$this->quoteName($options->db_user);
$query .=
' ENCODING ' .
$this->quote('UTF-8');
* This function replaces a string identifier <var>$prefix</var> with the string held is the
* <var>tablePrefix</var> class variable.
* @param string $query The SQL statement to prepare.
* @param string $prefix The common table prefix.
* @return string The processed SQL statement.
// Sequence name quoted with ' ' but need to be replaced
if (strpos($query, 'currval'))
$query =
explode('currval', $query);
for ($nIndex =
1; $nIndex <
count($query); $nIndex =
$nIndex +
2)
$query =
implode('currval', $query);
// Sequence name quoted with ' ' but need to be replaced
if (strpos($query, 'nextval'))
$query =
explode('nextval', $query);
for ($nIndex =
1; $nIndex <
count($query); $nIndex =
$nIndex +
2)
$query =
implode('nextval', $query);
// Sequence name quoted with ' ' but need to be replaced
$query =
explode('setval', $query);
for ($nIndex =
1; $nIndex <
count($query); $nIndex =
$nIndex +
2)
$query =
implode('setval', $query);
$explodedQuery =
explode('\'', $query);
for ($nIndex =
0; $nIndex <
count($explodedQuery); $nIndex =
$nIndex +
2)
if (strpos($explodedQuery[$nIndex], $prefix))
$replacedQuery =
implode('\'', $explodedQuery);
* Method to release a savepoint.
* @param string $savepointName Savepoint's name to release
* Method to create a savepoint.
* @param string $savepointName Savepoint's name to create
* Unlocks tables in the database, this command does not exist in PostgreSQL,
* it is automatically done on commit or rollback.
* @return JDatabaseDriverPostgresql Returns this object to support chaining.
* @throws RuntimeException
* Updates a row in a table based on an object's properties.
* @param string $table The name of the database table to update.
* @param object &$object A reference to an object whose public properties match the table fields.
* @param array $key The name of the primary key.
* @param boolean $nulls True to update null fields or false to ignore them.
* @return boolean True on success.
* @throws RuntimeException
public function updateObject($table, &$object, $key, $nulls =
false)
// Create the base update statement.
$statement =
'UPDATE ' .
$this->quoteName($table) .
' SET %s WHERE %s';
// Iterate over the object variables to build the query fields/value pairs.
// Only process scalars that are not internal fields.
// Set the primary key to the WHERE clause instead of a field to update.
$key_val =
$this->sqlValue($columns, $k, $v);
$where[] =
$this->quoteName($k) .
'=' .
$key_val;
// Prepare and sanitize the fields and values for the database query.
// If the value is null and we want to update nulls then set it.
// If the value is null and we do not want to update nulls then ignore this field.
// The field is not null so we prep it for update.
$val =
$this->sqlValue($columns, $k, $v);
// Add the field to be updated.
$fields[] =
$this->quoteName($k) .
'=' .
$val;
// We don't have any fields to update.
// Set the query and execute the update.
Documentation generated on Tue, 19 Nov 2013 15:11:08 +0100 by phpDocumentor 1.4.3