old mode 100755
new mode 100644
| | |
| | | // +----------------------------------------------------------------------+ |
| | | // | PHP versions 4 and 5 | |
| | | // +----------------------------------------------------------------------+ |
| | | // | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox, | |
| | | // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | |
| | | // | Stig. S. Bakken, Lukas Smith | |
| | | // | All rights reserved. | |
| | | // +----------------------------------------------------------------------+ |
| | |
| | | // | Author: Paul Cooper <pgc@ucecom.com> | |
| | | // +----------------------------------------------------------------------+ |
| | | // |
| | | // $Id$ |
| | | // $Id: pgsql.php 292715 2009-12-28 14:06:34Z quipo $ |
| | | |
| | | require_once 'MDB2/Driver/Manager/Common.php'; |
| | | |
| | |
| | | /** |
| | | * create a new database |
| | | * |
| | | * @param string $name name of the database that should be created |
| | | * @param string $name name of the database that should be created |
| | | * @param array $options array with charset info |
| | | * |
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure |
| | | * @access public |
| | | **/ |
| | | function createDatabase($name) |
| | | */ |
| | | function createDatabase($name, $options = array()) |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | | if (PEAR::isError($db)) { |
| | | return $db; |
| | | } |
| | | |
| | | return $db->standaloneQuery("CREATE DATABASE $name"); |
| | | $name = $db->quoteIdentifier($name, true); |
| | | $query = 'CREATE DATABASE ' . $name; |
| | | if (!empty($options['charset'])) { |
| | | $query .= ' WITH ENCODING ' . $db->quote($options['charset'], 'text'); |
| | | } |
| | | return $db->standaloneQuery($query, null, true); |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ alterDatabase() |
| | | |
| | | /** |
| | | * alter an existing database |
| | | * |
| | | * @param string $name name of the database that is intended to be changed |
| | | * @param array $options array with name, owner info |
| | | * |
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure |
| | | * @access public |
| | | */ |
| | | function alterDatabase($name, $options = array()) |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | | if (PEAR::isError($db)) { |
| | | return $db; |
| | | } |
| | | |
| | | $query = 'ALTER DATABASE '. $db->quoteIdentifier($name, true); |
| | | if (!empty($options['name'])) { |
| | | $query .= ' RENAME TO ' . $options['name']; |
| | | } |
| | | if (!empty($options['owner'])) { |
| | | $query .= ' OWNER TO ' . $options['owner']; |
| | | } |
| | | return $db->standaloneQuery($query, null, true); |
| | | } |
| | | |
| | | // }}} |
| | |
| | | * @param string $name name of the database that should be dropped |
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure |
| | | * @access public |
| | | **/ |
| | | */ |
| | | function dropDatabase($name) |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | |
| | | return $db; |
| | | } |
| | | |
| | | return $db->standaloneQuery("DROP DATABASE $name"); |
| | | $name = $db->quoteIdentifier($name, true); |
| | | $query = "DROP DATABASE $name"; |
| | | return $db->standaloneQuery($query, null, true); |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ _getAdvancedFKOptions() |
| | | |
| | | /** |
| | | * Return the FOREIGN KEY query section dealing with non-standard options |
| | | * as MATCH, INITIALLY DEFERRED, ON UPDATE, ... |
| | | * |
| | | * @param array $definition |
| | | * @return string |
| | | * @access protected |
| | | */ |
| | | function _getAdvancedFKOptions($definition) |
| | | { |
| | | $query = ''; |
| | | if (!empty($definition['match'])) { |
| | | $query .= ' MATCH '.$definition['match']; |
| | | } |
| | | if (!empty($definition['onupdate'])) { |
| | | $query .= ' ON UPDATE '.$definition['onupdate']; |
| | | } |
| | | if (!empty($definition['ondelete'])) { |
| | | $query .= ' ON DELETE '.$definition['ondelete']; |
| | | } |
| | | if (!empty($definition['deferrable'])) { |
| | | $query .= ' DEFERRABLE'; |
| | | } else { |
| | | $query .= ' NOT DEFERRABLE'; |
| | | } |
| | | if (!empty($definition['initiallydeferred'])) { |
| | | $query .= ' INITIALLY DEFERRED'; |
| | | } else { |
| | | $query .= ' INITIALLY IMMEDIATE'; |
| | | } |
| | | return $query; |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ truncateTable() |
| | | |
| | | /** |
| | | * Truncate an existing table (if the TRUNCATE TABLE syntax is not supported, |
| | | * it falls back to a DELETE FROM TABLE query) |
| | | * |
| | | * @param string $name name of the table that should be truncated |
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure |
| | | * @access public |
| | | */ |
| | | function truncateTable($name) |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | | if (PEAR::isError($db)) { |
| | | return $db; |
| | | } |
| | | |
| | | $name = $db->quoteIdentifier($name, true); |
| | | return $db->exec("TRUNCATE TABLE $name"); |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ vacuum() |
| | | |
| | | /** |
| | | * Optimize (vacuum) all the tables in the db (or only the specified table) |
| | | * and optionally run ANALYZE. |
| | | * |
| | | * @param string $table table name (all the tables if empty) |
| | | * @param array $options an array with driver-specific options: |
| | | * - timeout [int] (in seconds) [mssql-only] |
| | | * - analyze [boolean] [pgsql and mysql] |
| | | * - full [boolean] [pgsql-only] |
| | | * - freeze [boolean] [pgsql-only] |
| | | * |
| | | * @return mixed MDB2_OK success, a MDB2 error on failure |
| | | * @access public |
| | | */ |
| | | function vacuum($table = null, $options = array()) |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | | if (PEAR::isError($db)) { |
| | | return $db; |
| | | } |
| | | $query = 'VACUUM'; |
| | | |
| | | if (!empty($options['full'])) { |
| | | $query .= ' FULL'; |
| | | } |
| | | if (!empty($options['freeze'])) { |
| | | $query .= ' FREEZE'; |
| | | } |
| | | if (!empty($options['analyze'])) { |
| | | $query .= ' ANALYZE'; |
| | | } |
| | | |
| | | if (!empty($table)) { |
| | | $query .= ' '.$db->quoteIdentifier($table, true); |
| | | } |
| | | return $db->exec($query); |
| | | } |
| | | |
| | | // }}} |
| | |
| | | /** |
| | | * alter an existing table |
| | | * |
| | | * @param string $name name of the table that is intended to be changed. |
| | | * @param array $changes associative array that contains the details of each type |
| | | * of change that is intended to be performed. The types of |
| | | * changes that are currently supported are defined as follows: |
| | | * @param string $name name of the table that is intended to be changed. |
| | | * @param array $changes associative array that contains the details of each type |
| | | * of change that is intended to be performed. The types of |
| | | * changes that are currently supported are defined as follows: |
| | | * |
| | | * name |
| | | * name |
| | | * |
| | | * New name for the table. |
| | | * New name for the table. |
| | | * |
| | | * add |
| | | * add |
| | | * |
| | | * Associative array with the names of fields to be added as |
| | | * indexes of the array. The value of each entry of the array |
| | | * should be set to another associative array with the properties |
| | | * of the fields to be added. The properties of the fields should |
| | | * be the same as defined by the Metabase parser. |
| | | * Associative array with the names of fields to be added as |
| | | * indexes of the array. The value of each entry of the array |
| | | * should be set to another associative array with the properties |
| | | * of the fields to be added. The properties of the fields should |
| | | * be the same as defined by the MDB2 parser. |
| | | * |
| | | * |
| | | * remove |
| | | * remove |
| | | * |
| | | * Associative array with the names of fields to be removed as indexes |
| | | * of the array. Currently the values assigned to each entry are ignored. |
| | | * An empty array should be used for future compatibility. |
| | | * Associative array with the names of fields to be removed as indexes |
| | | * of the array. Currently the values assigned to each entry are ignored. |
| | | * An empty array should be used for future compatibility. |
| | | * |
| | | * rename |
| | | * rename |
| | | * |
| | | * Associative array with the names of fields to be renamed as indexes |
| | | * of the array. The value of each entry of the array should be set to |
| | | * another associative array with the entry named name with the new |
| | | * field name and the entry named Declaration that is expected to contain |
| | | * the portion of the field declaration already in DBMS specific SQL code |
| | | * as it is used in the CREATE TABLE statement. |
| | | * Associative array with the names of fields to be renamed as indexes |
| | | * of the array. The value of each entry of the array should be set to |
| | | * another associative array with the entry named name with the new |
| | | * field name and the entry named Declaration that is expected to contain |
| | | * the portion of the field declaration already in DBMS specific SQL code |
| | | * as it is used in the CREATE TABLE statement. |
| | | * |
| | | * change |
| | | * change |
| | | * |
| | | * Associative array with the names of the fields to be changed as indexes |
| | | * of the array. Keep in mind that if it is intended to change either the |
| | | * name of a field and any other properties, the change array entries |
| | | * should have the new names of the fields as array indexes. |
| | | * Associative array with the names of the fields to be changed as indexes |
| | | * of the array. Keep in mind that if it is intended to change either the |
| | | * name of a field and any other properties, the change array entries |
| | | * should have the new names of the fields as array indexes. |
| | | * |
| | | * The value of each entry of the array should be set to another associative |
| | | * array with the properties of the fields to that are meant to be changed as |
| | | * array entries. These entries should be assigned to the new values of the |
| | | * respective properties. The properties of the fields should be the same |
| | | * as defined by the Metabase parser. |
| | | * The value of each entry of the array should be set to another associative |
| | | * array with the properties of the fields to that are meant to be changed as |
| | | * array entries. These entries should be assigned to the new values of the |
| | | * respective properties. The properties of the fields should be the same |
| | | * as defined by the MDB2 parser. |
| | | * |
| | | * Example |
| | | * array( |
| | | * 'name' => 'userlist', |
| | | * 'add' => array( |
| | | * 'quota' => array( |
| | | * 'type' => 'integer', |
| | | * 'unsigned' => 1 |
| | | * ) |
| | | * ), |
| | | * 'remove' => array( |
| | | * 'file_limit' => array(), |
| | | * 'time_limit' => array() |
| | | * ), |
| | | * 'change' => array( |
| | | * 'gender' => array( |
| | | * 'default' => 'M', |
| | | * ) |
| | | * ), |
| | | * 'rename' => array( |
| | | * 'sex' => array( |
| | | * 'name' => 'gender', |
| | | * ) |
| | | * ) |
| | | * ) |
| | | * @param boolean $check indicates whether the function should just check if the DBMS driver |
| | | * can perform the requested table alterations if the value is true or |
| | | * actually perform them otherwise. |
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure |
| | | * Example |
| | | * array( |
| | | * 'name' => 'userlist', |
| | | * 'add' => array( |
| | | * 'quota' => array( |
| | | * 'type' => 'integer', |
| | | * 'unsigned' => 1 |
| | | * ) |
| | | * ), |
| | | * 'remove' => array( |
| | | * 'file_limit' => array(), |
| | | * 'time_limit' => array() |
| | | * ), |
| | | * 'change' => array( |
| | | * 'name' => array( |
| | | * 'length' => '20', |
| | | * 'definition' => array( |
| | | * 'type' => 'text', |
| | | * 'length' => 20, |
| | | * ), |
| | | * ) |
| | | * ), |
| | | * 'rename' => array( |
| | | * 'sex' => array( |
| | | * 'name' => 'gender', |
| | | * 'definition' => array( |
| | | * 'type' => 'text', |
| | | * 'length' => 1, |
| | | * 'default' => 'M', |
| | | * ), |
| | | * ) |
| | | * ) |
| | | * ) |
| | | * |
| | | * @param boolean $check indicates whether the function should just check if the DBMS driver |
| | | * can perform the requested table alterations if the value is true or |
| | | * actually perform them otherwise. |
| | | * @access public |
| | | **/ |
| | | * |
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure |
| | | */ |
| | | function alterTable($name, $changes, $check) |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | |
| | | case 'remove': |
| | | case 'change': |
| | | case 'name': |
| | | break; |
| | | case 'rename': |
| | | break; |
| | | default: |
| | | return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, |
| | | 'alterTable: change type "'.$change_name.'\" not yet supported'); |
| | | return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null, |
| | | 'change type "'.$change_name.'\" not yet supported', __FUNCTION__); |
| | | } |
| | | } |
| | | |
| | |
| | | return MDB2_OK; |
| | | } |
| | | |
| | | $query = (array_key_exists('name', $changes) ? 'RENAME TO '.$changes['name'] : ''); |
| | | $name = $db->quoteIdentifier($name, true); |
| | | |
| | | if (array_key_exists('add', $changes)) { |
| | | foreach ($changes['add'] as $field_name => $field) { |
| | | $type_declaration = $db->getDeclaration($field['type'], $field_name, $field); |
| | | if (PEAR::isError($type_declaration)) { |
| | | return $err; |
| | | } |
| | | if ($query) { |
| | | $query.= ', '; |
| | | } |
| | | $query.= 'ADD ' . $type_declaration; |
| | | } |
| | | } |
| | | |
| | | if (array_key_exists('remove', $changes)) { |
| | | if (!empty($changes['remove']) && is_array($changes['remove'])) { |
| | | foreach ($changes['remove'] as $field_name => $field) { |
| | | if ($query) { |
| | | $query.= ', '; |
| | | $field_name = $db->quoteIdentifier($field_name, true); |
| | | $query = 'DROP ' . $field_name; |
| | | $result = $db->exec("ALTER TABLE $name $query"); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | $query.= 'DROP ' . $field_name; |
| | | } |
| | | } |
| | | |
| | | if (array_key_exists('change', $changes)) { |
| | | // missing support to change DEFAULT and NULLability |
| | | if (!empty($changes['rename']) && is_array($changes['rename'])) { |
| | | foreach ($changes['rename'] as $field_name => $field) { |
| | | $field_name = $db->quoteIdentifier($field_name, true); |
| | | $result = $db->exec("ALTER TABLE $name RENAME COLUMN $field_name TO ".$db->quoteIdentifier($field['name'], true)); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!empty($changes['add']) && is_array($changes['add'])) { |
| | | foreach ($changes['add'] as $field_name => $field) { |
| | | $query = 'ADD ' . $db->getDeclaration($field['type'], $field_name, $field); |
| | | $result = $db->exec("ALTER TABLE $name $query"); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!empty($changes['change']) && is_array($changes['change'])) { |
| | | foreach ($changes['change'] as $field_name => $field) { |
| | | if ($query) { |
| | | $query.= ', '; |
| | | $field_name = $db->quoteIdentifier($field_name, true); |
| | | if (!empty($field['definition']['type'])) { |
| | | $server_info = $db->getServerVersion(); |
| | | if (PEAR::isError($server_info)) { |
| | | return $server_info; |
| | | } |
| | | if (is_array($server_info) && $server_info['major'] < 8) { |
| | | return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null, |
| | | 'changing column type for "'.$change_name.'\" requires PostgreSQL 8.0 or above', __FUNCTION__); |
| | | } |
| | | $db->loadModule('Datatype', null, true); |
| | | $type = $db->datatype->getTypeDeclaration($field['definition']); |
| | | $query = "ALTER $field_name TYPE $type USING CAST($field_name AS $type)"; |
| | | $result = $db->exec("ALTER TABLE $name $query"); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | } |
| | | $db->loadModule('Datatype'); |
| | | $query.= "ALTER $field_name TYPE ".$db->datatype->getTypeDeclaration($field); |
| | | if (array_key_exists('default', $field['definition'])) { |
| | | $query = "ALTER $field_name SET DEFAULT ".$db->quote($field['definition']['default'], $field['definition']['type']); |
| | | $result = $db->exec("ALTER TABLE $name $query"); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | } |
| | | if (array_key_exists('notnull', $field['definition'])) { |
| | | $query = "ALTER $field_name ".($field['definition']['notnull'] ? 'SET' : 'DROP').' NOT NULL'; |
| | | $result = $db->exec("ALTER TABLE $name $query"); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!$query) { |
| | | return MDB2_OK; |
| | | if (!empty($changes['name'])) { |
| | | $change_name = $db->quoteIdentifier($changes['name'], true); |
| | | $result = $db->exec("ALTER TABLE $name RENAME TO ".$change_name); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | } |
| | | |
| | | return $db->query("ALTER TABLE $name $query"); |
| | | return MDB2_OK; |
| | | } |
| | | |
| | | // }}} |
| | |
| | | /** |
| | | * list all databases |
| | | * |
| | | * @return mixed data array on success, a MDB2 error on failure |
| | | * @return mixed array of database names on success, a MDB2 error on failure |
| | | * @access public |
| | | **/ |
| | | */ |
| | | function listDatabases() |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | |
| | | return $db; |
| | | } |
| | | |
| | | $result = $db->standaloneQuery('SELECT datname FROM pg_database'); |
| | | if (!MDB2::isResultCommon($result)) { |
| | | return $result; |
| | | $query = 'SELECT datname FROM pg_database'; |
| | | $result2 = $db->standaloneQuery($query, array('text'), false); |
| | | if (!MDB2::isResultCommon($result2)) { |
| | | return $result2; |
| | | } |
| | | |
| | | $col = $result->fetchCol(); |
| | | $result->free(); |
| | | return $col; |
| | | $result = $result2->fetchCol(); |
| | | $result2->free(); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
| | | $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); |
| | | } |
| | | return $result; |
| | | } |
| | | |
| | | // }}} |
| | |
| | | /** |
| | | * list all users |
| | | * |
| | | * @return mixed data array on success, a MDB2 error on failure |
| | | * @return mixed array of user names on success, a MDB2 error on failure |
| | | * @access public |
| | | **/ |
| | | */ |
| | | function listUsers() |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | |
| | | return $db; |
| | | } |
| | | |
| | | $result = $db->standaloneQuery('SELECT usename FROM pg_user'); |
| | | if (!MDB2::isResultCommon($result)) { |
| | | return $result; |
| | | $query = 'SELECT usename FROM pg_user'; |
| | | $result2 = $db->standaloneQuery($query, array('text'), false); |
| | | if (!MDB2::isResultCommon($result2)) { |
| | | return $result2; |
| | | } |
| | | |
| | | $col = $result->fetchCol(); |
| | | $result->free(); |
| | | return $col; |
| | | $result = $result2->fetchCol(); |
| | | $result2->free(); |
| | | return $result; |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ listViews() |
| | | |
| | | /** |
| | | * list the views in the database |
| | | * list all views in the current database |
| | | * |
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure |
| | | * @return mixed array of view names on success, a MDB2 error on failure |
| | | * @access public |
| | | **/ |
| | | */ |
| | | function listViews() |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | |
| | | return $db; |
| | | } |
| | | |
| | | $query = 'SELECT viewname FROM pg_views'; |
| | | return $db->queryCol($query); |
| | | $query = "SELECT viewname |
| | | FROM pg_views |
| | | WHERE schemaname NOT IN ('pg_catalog', 'information_schema') |
| | | AND viewname !~ '^pg_'"; |
| | | $result = $db->queryCol($query); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
| | | $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); |
| | | } |
| | | return $result; |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ listTableViews() |
| | | |
| | | /** |
| | | * list the views in the database that reference a given table |
| | | * |
| | | * @param string table for which all referenced views should be found |
| | | * @return mixed array of view names on success, a MDB2 error on failure |
| | | * @access public |
| | | */ |
| | | function listTableViews($table) |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | | if (PEAR::isError($db)) { |
| | | return $db; |
| | | } |
| | | |
| | | $query = 'SELECT viewname FROM pg_views NATURAL JOIN pg_tables'; |
| | | $query.= ' WHERE tablename ='.$db->quote($table, 'text'); |
| | | $result = $db->queryCol($query); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
| | | $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); |
| | | } |
| | | return $result; |
| | | } |
| | | |
| | | // }}} |
| | |
| | | /** |
| | | * list all functions in the current database |
| | | * |
| | | * @return mixed data array on success, a MDB2 error on failure |
| | | * @return mixed array of function names on success, a MDB2 error on failure |
| | | * @access public |
| | | */ |
| | | function listFunctions() |
| | |
| | | AND tp.typname <> 'trigger' |
| | | AND pr.pronamespace IN |
| | | (SELECT oid FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema')"; |
| | | return $db->queryCol($query); |
| | | $result = $db->queryCol($query); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
| | | $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); |
| | | } |
| | | return $result; |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ listTableTriggers() |
| | | |
| | | /** |
| | | * list all triggers in the database that reference a given table |
| | | * |
| | | * @param string table for which all referenced triggers should be found |
| | | * @return mixed array of trigger names on success, a MDB2 error on failure |
| | | * @access public |
| | | */ |
| | | function listTableTriggers($table = null) |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | | if (PEAR::isError($db)) { |
| | | return $db; |
| | | } |
| | | |
| | | $query = 'SELECT trg.tgname AS trigger_name |
| | | FROM pg_trigger trg, |
| | | pg_class tbl |
| | | WHERE trg.tgrelid = tbl.oid'; |
| | | if (null !== $table) { |
| | | $table = $db->quote(strtoupper($table), 'text'); |
| | | $query .= " AND UPPER(tbl.relname) = $table"; |
| | | } |
| | | $result = $db->queryCol($query); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
| | | $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); |
| | | } |
| | | return $result; |
| | | } |
| | | |
| | | // }}} |
| | |
| | | /** |
| | | * list all tables in the current database |
| | | * |
| | | * @return mixed data array on success, a MDB2 error on failure |
| | | * @return mixed array of table names on success, a MDB2 error on failure |
| | | * @access public |
| | | **/ |
| | | */ |
| | | function listTables() |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | |
| | | . ' (SELECT 1 FROM pg_user' |
| | | . ' WHERE usesysid = c.relowner)' |
| | | . " AND c.relname !~ '^pg_'"; |
| | | return $db->queryCol($query); |
| | | $result = $db->queryCol($query); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
| | | $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); |
| | | } |
| | | return $result; |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ listTableFields() |
| | | |
| | | /** |
| | | * list all fields in a tables in the current database |
| | | * list all fields in a table in the current database |
| | | * |
| | | * @param string $table name of table that should be used in method |
| | | * @return mixed data array on success, a MDB2 error on failure |
| | | * @return mixed array of field names on success, a MDB2 error on failure |
| | | * @access public |
| | | */ |
| | | function listTableFields($table) |
| | |
| | | return $db; |
| | | } |
| | | |
| | | $result = $db->query("SELECT * FROM $table"); |
| | | list($schema, $table) = $this->splitTableSchema($table); |
| | | |
| | | $table = $db->quoteIdentifier($table, true); |
| | | if (!empty($schema)) { |
| | | $table = $db->quoteIdentifier($schema, true) . '.' .$table; |
| | | } |
| | | $db->setLimit(1); |
| | | $result2 = $db->query("SELECT * FROM $table"); |
| | | if (PEAR::isError($result2)) { |
| | | return $result2; |
| | | } |
| | | $result = $result2->getColumnNames(); |
| | | $result2->free(); |
| | | if (PEAR::isError($result)) { |
| | | return $result; |
| | | } |
| | | $columns = $result->getColumnNames(); |
| | | $result->free(); |
| | | if (PEAR::isError($columns)) { |
| | | return $columns; |
| | | } |
| | | return array_flip($columns); |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ createIndex() |
| | | |
| | | /** |
| | | * get the stucture of a field into an array |
| | | * |
| | | * @param string $table name of the table on which the index is to be created |
| | | * @param string $name name of the index to be created |
| | | * @param array $definition associative array that defines properties of the index to be created. |
| | | * Currently, only one property named FIELDS is supported. This property |
| | | * is also an associative with the names of the index fields as array |
| | | * indexes. Each entry of this array is set to another type of associative |
| | | * array that specifies properties of the index that are specific to |
| | | * each field. |
| | | * |
| | | * Currently, only the sorting property is supported. It should be used |
| | | * to define the sorting direction of the index. It may be set to either |
| | | * ascending or descending. |
| | | * |
| | | * Not all DBMS support index sorting direction configuration. The DBMS |
| | | * drivers of those that do not support it ignore this property. Use the |
| | | * function supports() to determine whether the DBMS driver can manage indexes. |
| | | * |
| | | * Example |
| | | * array( |
| | | * 'fields' => array( |
| | | * 'user_name' => array( |
| | | * 'sorting' => 'ascending' |
| | | * ), |
| | | * 'last_login' => array() |
| | | * ) |
| | | * ) |
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure |
| | | * @access public |
| | | */ |
| | | function createIndex($table, $name, $definition) |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | | if (PEAR::isError($db)) { |
| | | return $db; |
| | | } |
| | | |
| | | if (array_key_exists('primary', $definition) && $definition['primary']) { |
| | | $query = "ALTER TABLE $table ADD CONSTRAINT $name PRIMARY KEY ("; |
| | | } else { |
| | | $query = 'CREATE'; |
| | | if (array_key_exists('unique', $definition) && $definition['unique']) { |
| | | $query.= ' UNIQUE'; |
| | | } |
| | | $query.= " INDEX $name ON $table ("; |
| | | } |
| | | $query.= implode(', ', array_keys($definition['fields'])); |
| | | $query.= ')'; |
| | | |
| | | return $db->query($query); |
| | | return array_flip($result); |
| | | } |
| | | |
| | | // }}} |
| | |
| | | /** |
| | | * list all indexes in a table |
| | | * |
| | | * @param string $table name of table that should be used in method |
| | | * @return mixed data array on success, a MDB2 error on failure |
| | | * @param string $table name of table that should be used in method |
| | | * @return mixed array of index names on success, a MDB2 error on failure |
| | | * @access public |
| | | */ |
| | | function listTableIndexes($table) |
| | |
| | | return $db; |
| | | } |
| | | |
| | | $subquery = "SELECT indexrelid FROM pg_index, pg_class"; |
| | | $subquery.= " WHERE (pg_class.relname='$table') AND (pg_class.oid=pg_index.indrelid)"; |
| | | return $db->queryCol("SELECT relname FROM pg_class WHERE oid IN ($subquery)"); |
| | | list($schema, $table) = $this->splitTableSchema($table); |
| | | |
| | | $table = $db->quote($table, 'text'); |
| | | $subquery = "SELECT indexrelid |
| | | FROM pg_index |
| | | LEFT JOIN pg_class ON pg_class.oid = pg_index.indrelid |
| | | LEFT JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid |
| | | WHERE pg_class.relname = $table |
| | | AND indisunique != 't' |
| | | AND indisprimary != 't'"; |
| | | if (!empty($schema)) { |
| | | $subquery .= ' AND pg_namespace.nspname = '.$db->quote($schema, 'text'); |
| | | } |
| | | $query = "SELECT relname FROM pg_class WHERE oid IN ($subquery)"; |
| | | $indexes = $db->queryCol($query, 'text'); |
| | | if (PEAR::isError($indexes)) { |
| | | return $indexes; |
| | | } |
| | | |
| | | $result = array(); |
| | | foreach ($indexes as $index) { |
| | | $index = $this->_fixIndexName($index); |
| | | if (!empty($index)) { |
| | | $result[$index] = true; |
| | | } |
| | | } |
| | | |
| | | if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
| | | $result = array_change_key_case($result, $db->options['field_case']); |
| | | } |
| | | return array_keys($result); |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ dropConstraint() |
| | | |
| | | /** |
| | | * drop existing constraint |
| | | * |
| | | * @param string $table name of table that should be used in method |
| | | * @param string $name name of the constraint to be dropped |
| | | * @param string $primary hint if the constraint is primary |
| | | * |
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure |
| | | * @access public |
| | | */ |
| | | function dropConstraint($table, $name, $primary = false) |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | | if (PEAR::isError($db)) { |
| | | return $db; |
| | | } |
| | | |
| | | // is it an UNIQUE index? |
| | | $query = 'SELECT relname |
| | | FROM pg_class |
| | | WHERE oid IN ( |
| | | SELECT indexrelid |
| | | FROM pg_index, pg_class |
| | | WHERE pg_class.relname = '.$db->quote($table, 'text').' |
| | | AND pg_class.oid = pg_index.indrelid |
| | | AND indisunique = \'t\') |
| | | EXCEPT |
| | | SELECT conname |
| | | FROM pg_constraint, pg_class |
| | | WHERE pg_constraint.conrelid = pg_class.oid |
| | | AND relname = '. $db->quote($table, 'text'); |
| | | $unique = $db->queryCol($query, 'text'); |
| | | if (PEAR::isError($unique) || empty($unique)) { |
| | | // not an UNIQUE index, maybe a CONSTRAINT |
| | | return parent::dropConstraint($table, $name, $primary); |
| | | } |
| | | |
| | | if (in_array($name, $unique)) { |
| | | return $db->exec('DROP INDEX '.$db->quoteIdentifier($name, true)); |
| | | } |
| | | $idxname = $db->getIndexName($name); |
| | | if (in_array($idxname, $unique)) { |
| | | return $db->exec('DROP INDEX '.$db->quoteIdentifier($idxname, true)); |
| | | } |
| | | return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null, |
| | | $name . ' is not an existing constraint for table ' . $table, __FUNCTION__); |
| | | } |
| | | |
| | | // }}} |
| | | // {{{ listTableConstraints() |
| | | |
| | | /** |
| | | * list all constraints in a table |
| | | * |
| | | * @param string $table name of table that should be used in method |
| | | * @return mixed array of constraint names on success, a MDB2 error on failure |
| | | * @access public |
| | | */ |
| | | function listTableConstraints($table) |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | | if (PEAR::isError($db)) { |
| | | return $db; |
| | | } |
| | | |
| | | list($schema, $table) = $this->splitTableSchema($table); |
| | | |
| | | $table = $db->quote($table, 'text'); |
| | | $query = 'SELECT conname |
| | | FROM pg_constraint |
| | | LEFT JOIN pg_class ON pg_constraint.conrelid = pg_class.oid |
| | | LEFT JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid |
| | | WHERE relname = ' .$table; |
| | | if (!empty($schema)) { |
| | | $query .= ' AND pg_namespace.nspname = ' . $db->quote($schema, 'text'); |
| | | } |
| | | $query .= ' |
| | | UNION DISTINCT |
| | | SELECT relname |
| | | FROM pg_class |
| | | WHERE oid IN ( |
| | | SELECT indexrelid |
| | | FROM pg_index |
| | | LEFT JOIN pg_class ON pg_class.oid = pg_index.indrelid |
| | | LEFT JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid |
| | | WHERE pg_class.relname = '.$table.' |
| | | AND indisunique = \'t\''; |
| | | if (!empty($schema)) { |
| | | $query .= ' AND pg_namespace.nspname = ' . $db->quote($schema, 'text'); |
| | | } |
| | | $query .= ')'; |
| | | $constraints = $db->queryCol($query); |
| | | if (PEAR::isError($constraints)) { |
| | | return $constraints; |
| | | } |
| | | |
| | | $result = array(); |
| | | foreach ($constraints as $constraint) { |
| | | $constraint = $this->_fixIndexName($constraint); |
| | | if (!empty($constraint)) { |
| | | $result[$constraint] = true; |
| | | } |
| | | } |
| | | |
| | | if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE |
| | | && $db->options['field_case'] == CASE_LOWER |
| | | ) { |
| | | $result = array_change_key_case($result, $db->options['field_case']); |
| | | } |
| | | return array_keys($result); |
| | | } |
| | | |
| | | // }}} |
| | |
| | | * @param string $start start value of the sequence; default is 1 |
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure |
| | | * @access public |
| | | **/ |
| | | */ |
| | | function createSequence($seq_name, $start = 1) |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | |
| | | return $db; |
| | | } |
| | | |
| | | $sequence_name = $db->getSequenceName($seq_name); |
| | | return $db->query("CREATE SEQUENCE $sequence_name INCREMENT 1". |
| | | $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true); |
| | | return $db->exec("CREATE SEQUENCE $sequence_name INCREMENT 1". |
| | | ($start < 1 ? " MINVALUE $start" : '')." START $start"); |
| | | } |
| | | |
| | |
| | | * @param string $seq_name name of the sequence to be dropped |
| | | * @return mixed MDB2_OK on success, a MDB2 error on failure |
| | | * @access public |
| | | **/ |
| | | */ |
| | | function dropSequence($seq_name) |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | |
| | | return $db; |
| | | } |
| | | |
| | | $sequence_name = $db->getSequenceName($seq_name); |
| | | return $db->query("DROP SEQUENCE $sequence_name"); |
| | | $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true); |
| | | return $db->exec("DROP SEQUENCE $sequence_name"); |
| | | } |
| | | |
| | | // }}} |
| | |
| | | /** |
| | | * list all sequences in the current database |
| | | * |
| | | * @return mixed data array on success, a MDB2 error on failure |
| | | * @return mixed array of sequence names on success, a MDB2 error on failure |
| | | * @access public |
| | | **/ |
| | | */ |
| | | function listSequences() |
| | | { |
| | | $db =& $this->getDBInstance(); |
| | |
| | | if (PEAR::isError($table_names)) { |
| | | return $table_names; |
| | | } |
| | | $sequences = array(); |
| | | for ($i = 0, $j = count($table_names); $i < $j; ++$i) { |
| | | if ($sqn = $this->_isSequenceName($table_names[$i])) |
| | | $sequences[] = $sqn; |
| | | $result = array(); |
| | | foreach ($table_names as $table_name) { |
| | | $result[] = $this->_fixSequenceName($table_name); |
| | | } |
| | | return $sequences; |
| | | if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { |
| | | $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); |
| | | } |
| | | return $result; |
| | | } |
| | | } |
| | | ?> |
| | | ?> |