2008-08-21 19:36:39 +00:00
< ? php
// $Id$
/**
* @ file
* Database schema code for PostgreSQL database servers .
*/
/**
* @ ingroup schemaapi
* @ {
*/
class DatabaseSchema_pgsql extends DatabaseSchema {
2009-02-24 16:34:46 +00:00
/**
* A cache of information about blob columns and sequences of tables .
*
* This is collected by DatabaseConnection_pgsql -> queryTableInformation (),
* by introspecting the database .
*
2009-04-20 20:02:31 +00:00
* @ see DatabaseConnection_pgsql -> queryTableInformation ()
2009-02-24 16:34:46 +00:00
* @ var array
*/
protected $tableInformation = array ();
/**
* Fetch the list of blobs and sequences used on a table .
*
* We introspect the database to collect the information required by insert
* and update queries .
*
* @ param $table_name
* The non - prefixed name of the table .
* @ return
* An object with two member variables :
* - 'blob_fields' that lists all the blob fields in the table .
* - 'sequences' that lists the sequences used in that table .
*/
public function queryTableInformation ( $table ) {
// Generate a key to reference this table's information on.
$key = $this -> connection -> prefixTables ( '{' . $table . '}' );
if ( ! strpos ( $key , '.' )) {
$key = 'public.' . $key ;
}
if ( ! isset ( $this -> tableInformation [ $key ])) {
// Split the key into schema and table for querying.
2009-04-20 20:02:31 +00:00
list ( $schema , $table_name ) = explode ( '.' , $key );
2009-02-24 16:34:46 +00:00
$table_information = ( object ) array (
'blob_fields' => array (),
'sequences' => array (),
);
2009-05-29 01:51:46 +00:00
// Don't use {} around information_schema.columns table.
2009-09-29 15:13:57 +00:00
$result = $this -> connection -> query ( " SELECT column_name, data_type, column_default FROM information_schema.columns WHERE table_schema = :schema AND table_name = :table AND (data_type = 'bytea' OR (numeric_precision IS NOT NULL AND column_default LIKE :default)) " , array (
':schema' => $schema ,
':table' => $table_name ,
':default' => '%nextval%' ,
));
2009-02-24 16:34:46 +00:00
foreach ( $result as $column ) {
if ( $column -> data_type == 'bytea' ) {
$table_information -> blob_fields [ $column -> column_name ] = TRUE ;
}
2009-04-20 20:02:31 +00:00
elseif ( preg_match ( " /nextval \ ('([^']+)'/ " , $column -> column_default , $matches )) {
2009-02-24 16:34:46 +00:00
// We must know of any sequences in the table structure to help us
// return the last insert id. If there is more than 1 sequences the
// first one (index 0 of the sequences array) will be used.
$table_information -> sequences [] = $matches [ 1 ];
}
}
$this -> tableInformation [ $key ] = $table_information ;
}
return $this -> tableInformation [ $key ];
}
2008-08-21 19:36:39 +00:00
/**
* Generate SQL to create a new table from a Drupal schema definition .
*
* @ param $name
* The name of the table to create .
* @ param $table
* A Schema API table definition array .
* @ return
* An array of SQL statements to create the table .
*/
protected function createTableSql ( $name , $table ) {
$sql_fields = array ();
foreach ( $table [ 'fields' ] as $field_name => $field ) {
$sql_fields [] = $this -> createFieldSql ( $field_name , $this -> processField ( $field ));
}
$sql_keys = array ();
if ( isset ( $table [ 'primary key' ]) && is_array ( $table [ 'primary key' ])) {
$sql_keys [] = 'PRIMARY KEY (' . implode ( ', ' , $table [ 'primary key' ]) . ')' ;
}
if ( isset ( $table [ 'unique keys' ]) && is_array ( $table [ 'unique keys' ])) {
foreach ( $table [ 'unique keys' ] as $key_name => $key ) {
$sql_keys [] = 'CONSTRAINT {' . $name . '}_' . $key_name . '_key UNIQUE (' . implode ( ', ' , $key ) . ')' ;
}
}
$sql = " CREATE TABLE { " . $name . " } ( \n \t " ;
$sql .= implode ( " , \n \t " , $sql_fields );
if ( count ( $sql_keys ) > 0 ) {
$sql .= " , \n \t " ;
}
$sql .= implode ( " , \n \t " , $sql_keys );
$sql .= " \n ) " ;
$statements [] = $sql ;
if ( isset ( $table [ 'indexes' ]) && is_array ( $table [ 'indexes' ])) {
foreach ( $table [ 'indexes' ] as $key_name => $key ) {
$statements [] = $this -> _createIndexSql ( $name , $key_name , $key );
}
}
2009-03-14 20:34:17 +00:00
// Add table comment.
if ( ! empty ( $table [ 'description' ])) {
$statements [] = 'COMMENT ON TABLE {' . $name . '} IS ' . $this -> prepareComment ( $table [ 'description' ]);
}
// Add column comments.
foreach ( $table [ 'fields' ] as $field_name => $field ) {
if ( ! empty ( $field [ 'description' ])) {
$statements [] = 'COMMENT ON COLUMN {' . $name . '}.' . $field_name . ' IS ' . $this -> prepareComment ( $field [ 'description' ]);
}
}
2008-08-21 19:36:39 +00:00
return $statements ;
}
/**
* Create an SQL string for a field to be used in table creation or
* alteration .
*
* Before passing a field out of a schema definition into this
* function it has to be processed by _db_process_field () .
*
* @ param $name
* Name of the field .
* @ param $spec
* The field specification , as per the schema data structure format .
*/
protected function createFieldSql ( $name , $spec ) {
$sql = $name . ' ' . $spec [ 'pgsql_type' ];
if ( $spec [ 'type' ] == 'serial' ) {
unset ( $spec [ 'not null' ]);
}
2009-07-09 10:12:14 +00:00
if ( in_array ( $spec [ 'type' ], array ( 'varchar' , 'char' , 'text' )) && isset ( $spec [ 'length' ])) {
2008-08-21 19:36:39 +00:00
$sql .= '(' . $spec [ 'length' ] . ')' ;
}
elseif ( isset ( $spec [ 'precision' ]) && isset ( $spec [ 'scale' ])) {
$sql .= '(' . $spec [ 'precision' ] . ', ' . $spec [ 'scale' ] . ')' ;
}
2010-02-07 05:23:32 +00:00
if ( ! empty ( $spec [ 'unsigned' ])) {
$sql .= " CHECK ( $name >= 0) " ;
}
2008-08-21 19:36:39 +00:00
if ( isset ( $spec [ 'not null' ]) && $spec [ 'not null' ]) {
$sql .= ' NOT NULL' ;
}
if ( isset ( $spec [ 'default' ])) {
$default = is_string ( $spec [ 'default' ]) ? " ' " . $spec [ 'default' ] . " ' " : $spec [ 'default' ];
$sql .= " default $default " ;
}
return $sql ;
}
/**
* Set database - engine specific properties for a field .
*
* @ param $field
* A field description array , as specified in the schema documentation .
*/
protected function processField ( $field ) {
if ( ! isset ( $field [ 'size' ])) {
$field [ 'size' ] = 'normal' ;
}
// Set the correct database-engine specific datatype.
if ( ! isset ( $field [ 'pgsql_type' ])) {
$map = $this -> getFieldTypeMap ();
$field [ 'pgsql_type' ] = $map [ $field [ 'type' ] . ':' . $field [ 'size' ]];
}
2008-12-26 11:04:39 +00:00
if ( ! empty ( $field [ 'unsigned' ])) {
// Unsigned datatypes are not supported in PostgreSQL 8.3. In MySQL,
// they are used to ensure a positive number is inserted and it also
2009-01-26 14:08:44 +00:00
// doubles the maximum integer size that can be stored in a field.
// The PostgreSQL schema in Drupal creates a check constraint
// to ensure that a value inserted is >= 0. To provide the extra
2008-12-26 11:04:39 +00:00
// integer capacity, here, we bump up the column field size.
if ( ! isset ( $map )) {
$map = $this -> getFieldTypeMap ();
}
switch ( $field [ 'pgsql_type' ]) {
case 'smallint' :
$field [ 'pgsql_type' ] = $map [ 'int:medium' ];
break ;
case 'int' :
$field [ 'pgsql_type' ] = $map [ 'int:big' ];
break ;
}
}
2008-08-21 19:36:39 +00:00
if ( $field [ 'type' ] == 'serial' ) {
unset ( $field [ 'not null' ]);
}
return $field ;
}
/**
* This maps a generic data type in combination with its data size
* to the engine - specific data type .
*/
function getFieldTypeMap () {
2008-12-20 18:24:41 +00:00
// Put :normal last so it gets preserved by array_flip. This makes
2008-08-21 19:36:39 +00:00
// it much easier for modules (such as schema.module) to map
// database types back into schema types.
2009-04-14 06:22:10 +00:00
// $map does not use drupal_static as its value never changes.
static $map = array (
2008-08-21 19:36:39 +00:00
'varchar:normal' => 'varchar' ,
'char:normal' => 'character' ,
'text:tiny' => 'text' ,
'text:small' => 'text' ,
'text:medium' => 'text' ,
'text:big' => 'text' ,
'text:normal' => 'text' ,
'int:tiny' => 'smallint' ,
'int:small' => 'smallint' ,
'int:medium' => 'int' ,
'int:big' => 'bigint' ,
'int:normal' => 'int' ,
'float:tiny' => 'real' ,
'float:small' => 'real' ,
'float:medium' => 'real' ,
'float:big' => 'double precision' ,
'float:normal' => 'real' ,
'numeric:normal' => 'numeric' ,
'blob:big' => 'bytea' ,
'blob:normal' => 'bytea' ,
2009-08-22 19:43:12 +00:00
'date:normal' => 'date' ,
2009-03-30 04:55:59 +00:00
'datetime:normal' => 'timestamp without time zone' ,
2009-09-29 15:13:57 +00:00
2009-08-22 19:43:12 +00:00
'time:normal' => 'time without time zone' ,
2008-08-21 19:36:39 +00:00
'serial:tiny' => 'serial' ,
'serial:small' => 'serial' ,
'serial:medium' => 'serial' ,
'serial:big' => 'bigserial' ,
'serial:normal' => 'serial' ,
);
return $map ;
}
protected function _createKeySql ( $fields ) {
2009-09-29 15:13:57 +00:00
$return = array ();
2008-08-21 19:36:39 +00:00
foreach ( $fields as $field ) {
if ( is_array ( $field )) {
2009-09-29 15:13:57 +00:00
$return [] = 'substr(' . $field [ 0 ] . ', 1, ' . $field [ 1 ] . ')' ;
2008-08-21 19:36:39 +00:00
}
else {
2009-09-29 15:13:57 +00:00
$return [] = '"' . $field . '"' ;
2008-08-21 19:36:39 +00:00
}
}
2009-09-29 15:13:57 +00:00
return implode ( ', ' , $return );
2008-08-21 19:36:39 +00:00
}
2009-09-29 15:13:57 +00:00
function renameTable ( $table , $new_name ) {
2010-02-23 18:46:21 +00:00
// Get the schema and tablename for the old table.
$old_full_name = $this -> connection -> prefixTables ( '{' . $table . '}' );
list ( $old_schema , $old_table_name ) = strpos ( $old_full_name , '.' ) ? explode ( '.' , $old_full_name ) : array ( 'public' , $old_full_name );
// Index names and constraint names are global in PostgreSQL, so we need to
// rename them when renaming the table.
$indexes = $this -> connection -> query ( 'SELECT indexname FROM pg_indexes WHERE schemaname = :schema AND tablename = :table' , array ( ':schema' => $old_schema , ':table' => $old_table_name ));
foreach ( $indexes as $index ) {
if ( preg_match ( '/^' . preg_quote ( $old_full_name ) . '_(.*)_idx$/' , $index -> indexname , $matches )) {
$index_name = $matches [ 1 ];
$this -> connection -> query ( 'ALTER INDEX ' . $index -> indexname . ' RENAME TO {' . $new_name . '}_' . $index_name . '_idx' );
}
}
// Now rename the table.
2009-12-15 08:30:53 +00:00
$this -> connection -> query ( 'ALTER TABLE {' . $table . '} RENAME TO {' . $new_name . '}' );
2008-08-21 19:36:39 +00:00
}
2009-09-29 15:13:57 +00:00
public function dropTable ( $table ) {
2009-12-15 08:30:53 +00:00
$this -> connection -> query ( 'DROP TABLE {' . $table . '}' );
2008-08-21 19:36:39 +00:00
}
/**
* Add a new field to a table .
*
* @ param $table
* Name of the table to be altered .
* @ param $field
* Name of the field to be added .
* @ param $spec
* The field specification array , as taken from a schema definition .
* The specification may also contain the key 'initial' , the newly
* created field will be set to the value of the key in all rows .
* This is most useful for creating NOT NULL columns with no default
* value in existing tables .
* @ param $keys_new
* Optional keys and indexes specification to be created on the
* table along with adding the field . The format is the same as a
2008-12-20 18:24:41 +00:00
* table specification but without the 'fields' element . If you are
2008-08-21 19:36:39 +00:00
* adding a type 'serial' field , you MUST specify at least one key
2009-04-20 20:02:31 +00:00
* or index including it in this array . See db_change_field () for more
2008-08-21 19:36:39 +00:00
* explanation why .
2009-04-20 20:02:31 +00:00
*
* @ see db_change_field ()
2008-08-21 19:36:39 +00:00
*/
2009-09-29 15:13:57 +00:00
public function addField ( $table , $field , $spec , $new_keys = array ()) {
2008-08-21 19:36:39 +00:00
$fixnull = FALSE ;
if ( ! empty ( $spec [ 'not null' ]) && ! isset ( $spec [ 'default' ])) {
$fixnull = TRUE ;
$spec [ 'not null' ] = FALSE ;
}
$query = 'ALTER TABLE {' . $table . '} ADD COLUMN ' ;
2008-11-26 13:42:25 +00:00
$query .= $this -> createFieldSql ( $field , $this -> processField ( $spec ));
2009-09-29 15:13:57 +00:00
$this -> connection -> query ( $query );
2008-08-21 19:36:39 +00:00
if ( isset ( $spec [ 'initial' ])) {
2009-09-29 15:13:57 +00:00
$this -> connection -> update ( $table )
-> fields ( array ( $field , $spec [ 'initial' ]))
-> execute ();
2008-08-21 19:36:39 +00:00
}
if ( $fixnull ) {
2009-12-15 08:30:53 +00:00
$this -> connection -> query ( " ALTER TABLE { " . $table . " } ALTER $field SET NOT NULL " );
2008-08-21 19:36:39 +00:00
}
if ( isset ( $new_keys )) {
2009-09-29 15:13:57 +00:00
$this -> _createKeys ( $table , $new_keys );
2008-08-21 19:36:39 +00:00
}
2009-03-14 20:34:17 +00:00
// Add column comment.
if ( ! empty ( $spec [ 'description' ])) {
2009-12-15 08:30:53 +00:00
$this -> connection -> query ( 'COMMENT ON COLUMN {' . $table . '}.' . $field . ' IS ' . $this -> prepareComment ( $spec [ 'description' ]));
2009-03-14 20:34:17 +00:00
}
2008-08-21 19:36:39 +00:00
}
/**
* Drop a field .
*
* @ param $table
* The table to be altered .
* @ param $field
* The field to be dropped .
*/
2009-09-29 15:13:57 +00:00
public function dropField ( $table , $field ) {
2009-12-15 08:30:53 +00:00
$this -> connection -> query ( 'ALTER TABLE {' . $table . '} DROP COLUMN "' . $field . '"' );
2008-08-21 19:36:39 +00:00
}
/**
* Set the default value for a field .
*
* @ param $table
* The table to be altered .
* @ param $field
* The field to be altered .
* @ param $default
* Default value to be set . NULL for 'default NULL' .
*/
2009-09-29 15:13:57 +00:00
public function fieldSetDefault ( $table , $field , $default ) {
2008-11-26 13:42:25 +00:00
if ( is_null ( $default )) {
2008-08-21 19:36:39 +00:00
$default = 'NULL' ;
}
else {
$default = is_string ( $default ) ? " ' $default ' " : $default ;
}
2009-09-29 15:13:57 +00:00
$this -> connection -> query ( 'ALTER TABLE {' . $table . '} ALTER COLUMN "' . $field . '" SET DEFAULT ' . $default );
2008-08-21 19:36:39 +00:00
}
/**
* Set a field to have no default value .
*
* @ param $table
* The table to be altered .
* @ param $field
* The field to be altered .
*/
2009-09-29 15:13:57 +00:00
public function fieldSetNoDefault ( $table , $field ) {
2009-12-15 08:30:53 +00:00
$this -> connection -> query ( 'ALTER TABLE {' . $table . '} ALTER COLUMN "' . $field . '" DROP DEFAULT' );
}
public function indexExists ( $table , $name ) {
2010-02-23 05:07:18 +00:00
$index_name = '{' . $table . '}_' . $name . '_idx' ;
2010-02-17 05:26:10 +00:00
return $this -> connection -> query ( " SELECT COUNT(indexname) FROM pg_indexes WHERE indexname = ' $index_name ' " ) -> fetchField ();
2008-08-21 19:36:39 +00:00
}
/**
* Add a primary key .
*
* @ param $table
* The table to be altered .
* @ param $fields
* Fields for the primary key .
*/
2009-09-29 15:13:57 +00:00
public function addPrimaryKey ( $table , $fields ) {
2009-12-15 08:30:53 +00:00
$this -> connection -> query ( 'ALTER TABLE {' . $table . '} ADD PRIMARY KEY (' . implode ( ',' , $fields ) . ')' );
2008-08-21 19:36:39 +00:00
}
/**
* Drop the primary key .
*
* @ param $table
* The table to be altered .
*/
2009-09-29 15:13:57 +00:00
public function dropPrimaryKey ( $table ) {
2009-12-15 08:30:53 +00:00
$this -> connection -> query ( 'ALTER TABLE {' . $table . '} DROP CONSTRAINT {' . $table . '}_pkey' );
2008-08-21 19:36:39 +00:00
}
/**
* Add a unique key .
*
* @ param $table
* The table to be altered .
* @ param $name
* The name of the key .
* @ param $fields
* An array of field names .
*/
2009-09-29 15:13:57 +00:00
function addUniqueKey ( $table , $name , $fields ) {
2008-08-21 19:36:39 +00:00
$name = '{' . $table . '}_' . $name . '_key' ;
2009-09-29 15:13:57 +00:00
$this -> connection -> query ( 'ALTER TABLE {' . $table . '} ADD CONSTRAINT "' . $name . '" UNIQUE (' . implode ( ',' , $fields ) . ')' );
2008-08-21 19:36:39 +00:00
}
/**
* Drop a unique key .
*
* @ param $table
* The table to be altered .
* @ param $name
* The name of the key .
*/
2009-09-29 15:13:57 +00:00
public function dropUniqueKey ( $table , $name ) {
2008-08-21 19:36:39 +00:00
$name = '{' . $table . '}_' . $name . '_key' ;
2009-09-29 15:13:57 +00:00
$this -> connection -> query ( 'ALTER TABLE {' . $table . '} DROP CONSTRAINT "' . $name . '"' );
2008-08-21 19:36:39 +00:00
}
/**
* Add an index .
*
* @ param $table
* The table to be altered .
* @ param $name
* The name of the index .
* @ param $fields
* An array of field names .
*/
2009-09-29 15:13:57 +00:00
public function addIndex ( $table , $name , $fields ) {
2009-12-15 08:30:53 +00:00
$this -> connection -> query ( $this -> _createIndexSql ( $table , $name , $fields ));
2008-08-21 19:36:39 +00:00
}
/**
* Drop an index .
*
* @ param $table
* The table to be altered .
* @ param $name
* The name of the index .
*/
2009-09-29 15:13:57 +00:00
public function dropIndex ( $table , $name ) {
2008-08-21 19:36:39 +00:00
$name = '{' . $table . '}_' . $name . '_idx' ;
2009-09-29 15:13:57 +00:00
$this -> connection -> query ( 'DROP INDEX ' . $name );
2008-08-21 19:36:39 +00:00
}
/**
* Change a field definition .
*
* IMPORTANT NOTE : To maintain database portability , you have to explicitly
* recreate all indices and primary keys that are using the changed field .
*
* That means that you have to drop all affected keys and indexes with
* db_drop_ { primary_key , unique_key , index }() before calling db_change_field () .
* To recreate the keys and indices , pass the key definitions as the
* optional $new_keys argument directly to db_change_field () .
*
* For example , suppose you have :
* @ code
* $schema [ 'foo' ] = array (
* 'fields' => array (
* 'bar' => array ( 'type' => 'int' , 'not null' => TRUE )
* ),
* 'primary key' => array ( 'bar' )
* );
* @ endcode
* and you want to change foo . bar to be type serial , leaving it as the
2008-12-20 18:24:41 +00:00
* primary key . The correct sequence is :
2008-08-21 19:36:39 +00:00
* @ code
2009-09-29 15:13:57 +00:00
* db_drop_primary_key ( 'foo' );
* db_change_field ( 'foo' , 'bar' , 'bar' ,
2008-08-21 19:36:39 +00:00
* array ( 'type' => 'serial' , 'not null' => TRUE ),
* array ( 'primary key' => array ( 'bar' )));
* @ endcode
*
* The reasons for this are due to the different database engines :
*
* On PostgreSQL , changing a field definition involves adding a new field
* and dropping an old one which * causes any indices , primary keys and
* sequences ( from serial - type fields ) that use the changed field to be dropped .
*
* On MySQL , all type 'serial' fields must be part of at least one key
2008-12-20 18:24:41 +00:00
* or index as soon as they are created . You cannot use
2008-08-21 19:36:39 +00:00
* db_add_ { primary_key , unique_key , index }() for this purpose because
* the ALTER TABLE command will fail to add the column without a key
2008-12-20 18:24:41 +00:00
* or index specification . The solution is to use the optional
2008-08-21 19:36:39 +00:00
* $new_keys argument to create the key or index at the same time as
* field .
*
* You could use db_add_ { primary_key , unique_key , index }() in all cases
* unless you are converting a field to be type serial . You can use
* the $new_keys argument in all cases .
*
* @ param $table
* Name of the table .
* @ param $field
* Name of the field to change .
* @ param $field_new
* New name for the field ( set to the same as $field if you don ' t want to change the name ) .
* @ param $spec
* The field specification for the new field .
* @ param $new_keys
* Optional keys and indexes specification to be created on the
* table along with changing the field . The format is the same as a
* table specification but without the 'fields' element .
*/
2009-09-29 15:13:57 +00:00
public function changeField ( $table , $field , $field_new , $spec , $new_keys = array ()) {
$this -> connection -> query ( 'ALTER TABLE {' . $table . '} RENAME "' . $field . '" TO "' . $field . '_old"' );
2008-08-21 19:36:39 +00:00
$not_null = isset ( $spec [ 'not null' ]) ? $spec [ 'not null' ] : FALSE ;
unset ( $spec [ 'not null' ]);
2009-03-31 01:42:45 +00:00
if ( ! array_key_exists ( 'size' , $spec )) {
$spec [ 'size' ] = 'normal' ;
}
2009-09-29 15:13:57 +00:00
$this -> addField ( $table , " $field_new " , $spec );
2008-08-21 19:36:39 +00:00
2009-03-31 01:42:45 +00:00
// We need to typecast the new column to best be able to transfer the data
// Schema_pgsql::getFieldTypeMap() will return possibilities that are not
// 'cast-able' such as 'serial' - so they need to be casted int instead.
$map = $this -> getFieldTypeMap ();
$typecast = $map [ $spec [ 'type' ] . ':' . $spec [ 'size' ]];
if ( in_array ( $typecast , array ( 'serial' , 'bigserial' , 'numeric' ))) {
$typecast = 'int' ;
}
2009-09-29 15:13:57 +00:00
$this -> connection -> query ( " UPDATE { " . $table . " } SET $field_new = CAST( " . $field . " _old as " . $typecast . " ) " );
2008-08-21 19:36:39 +00:00
if ( $not_null ) {
2009-12-15 08:30:53 +00:00
$this -> connection -> query ( " ALTER TABLE { " . $table . " } ALTER $field_new SET NOT NULL " );
2008-08-21 19:36:39 +00:00
}
2009-09-29 15:13:57 +00:00
$this -> dropField ( $table , $field . '_old' );
2008-08-21 19:36:39 +00:00
if ( isset ( $new_keys )) {
2009-09-29 15:13:57 +00:00
$this -> _createKeys ( $table , $new_keys );
2008-08-21 19:36:39 +00:00
}
}
protected function _createIndexSql ( $table , $name , $fields ) {
2009-08-17 06:52:02 +00:00
$query = 'CREATE INDEX "{' . $table . '}_' . $name . '_idx" ON {' . $table . '} (' ;
2008-08-21 19:36:39 +00:00
$query .= $this -> _createKeySql ( $fields ) . ')' ;
return $query ;
}
2009-09-29 15:13:57 +00:00
protected function _createKeys ( $table , $new_keys ) {
2008-08-21 19:36:39 +00:00
if ( isset ( $new_keys [ 'primary key' ])) {
2009-09-29 15:13:57 +00:00
$this -> addPrimaryKey ( $table , $new_keys [ 'primary key' ]);
2008-08-21 19:36:39 +00:00
}
if ( isset ( $new_keys [ 'unique keys' ])) {
foreach ( $new_keys [ 'unique keys' ] as $name => $fields ) {
2009-09-29 15:13:57 +00:00
$this -> addUniqueKey ( $table , $name , $fields );
2008-08-21 19:36:39 +00:00
}
}
if ( isset ( $new_keys [ 'indexes' ])) {
foreach ( $new_keys [ 'indexes' ] as $name => $fields ) {
2009-09-29 15:13:57 +00:00
$this -> addIndex ( $table , $name , $fields );
2008-08-21 19:36:39 +00:00
}
}
}
2009-03-14 20:34:17 +00:00
/**
* Retrieve a table or column comment .
*/
public function getComment ( $table , $column = NULL ) {
$table = $this -> connection -> prefixTables ( '{' . $table . '}' );
2009-05-25 13:42:56 +00:00
// Don't use {} around pg_class, pg_attribute tables.
2009-03-14 20:34:17 +00:00
if ( isset ( $column )) {
2010-02-17 05:26:10 +00:00
return $this -> connection -> query ( 'SELECT col_description(oid, attnum) FROM pg_class, pg_attribute WHERE attrelid = oid AND relname = ? AND attname = ?' , array ( $table , $column )) -> fetchField ();
}
else {
return $this -> connection -> query ( 'SELECT obj_description(oid, ?) FROM pg_class WHERE relname = ?' , array ( 'pg_class' , $table )) -> fetchField ();
2009-03-14 20:34:17 +00:00
}
}
2008-08-21 19:36:39 +00:00
}