? sites/default/files ? sites/default/settings.php Index: INSTALL.pgsql.txt =================================================================== RCS file: /cvs/drupal/drupal/INSTALL.pgsql.txt,v retrieving revision 1.8 diff -u -p -r1.8 INSTALL.pgsql.txt --- INSTALL.pgsql.txt 27 Jul 2009 19:42:54 -0000 1.8 +++ INSTALL.pgsql.txt 17 Aug 2009 05:31:43 -0000 @@ -26,3 +26,19 @@ Note that the database must be created w createdb --encoding=UTF8 --owner=username databasename If there are no errors then the command was successful + +3. CREATE A SCHEMA OR SCHEMAS (Optional Advanced) + + Drupal will run across different schemas within your database if you so wish. + By default, Drupal runs inside the 'public' schema but you can use $db_prefix + inside settings.php to define a schema for drupal to inside of or specify tables + that are shared inside of a separate schema. Drupal will not create schemas for + you, infact the user that drupal runs as should not be allowed to. You'll need + execute the SQL below as a superuser (such as a postgres user) and replace + 'drupaluser' with the username that drupal uses to connect to PostgreSQL with + and replace schema_name with a schema name you wish to use such as 'shared': + + CREATE SCHEMA schema_name AUTHORIZATION drupaluser; + + Do this for as many schemas as you need. See default.settings.php for how to + set which tables use which schemas. Index: includes/database/database.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database/database.inc,v retrieving revision 1.71 diff -u -p -r1.71 database.inc --- includes/database/database.inc 10 Aug 2009 21:00:31 -0000 1.71 +++ includes/database/database.inc 17 Aug 2009 05:31:44 -0000 @@ -426,6 +426,25 @@ abstract class DatabaseConnection extend } /** + * Find the prefix for a table + * + * This is not used in prefixTables due to performance reasons. + */ + public function tablePrefix($table = 'default') { + global $db_prefix; + if (is_array($db_prefix)) { + if (isset($db_prefix[$table])) { + return $db_prefix[$table]; + } + elseif (isset($db_prefix['default'])) { + return isset($db_prefix['default']); + } + return ''; + } + return $db_prefix; + } + + /** * Prepare a query string and return the prepared statement. * * This method caches prepared statements, reusing them when Index: includes/database/pgsql/schema.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database/pgsql/schema.inc,v retrieving revision 1.18 diff -u -p -r1.18 schema.inc --- includes/database/pgsql/schema.inc 10 Aug 2009 21:00:31 -0000 1.18 +++ includes/database/pgsql/schema.inc 17 Aug 2009 05:31:44 -0000 @@ -68,6 +68,25 @@ class DatabaseSchema_pgsql extends Datab } return $this->tableInformation[$key]; } + + /** + * Get information about the table name and schema from the db_prefix. + */ + protected function getPrefixInfo($table = 'default') { + $info = array( + 'schema' => 'public', + 'table' => $table, + 'prefix' => $this->connection->tablePrefix($table) + ); + if (($pos = strpos($info['prefix'], '.')) !== FALSE) { + $info['schema'] = substr($info['prefix'], 0, $pos); + $info['table'] = substr($info['prefix'], ++$pos) . $table; + } + else { + $info['table'] = $info['prefix'] . $table; + } + return $info; + } /** * Generate SQL to create a new table from a Drupal schema definition. @@ -91,7 +110,7 @@ class DatabaseSchema_pgsql extends Datab } 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_keys[] = 'CONSTRAINT ' . $this->_prefixNonTable($name, $key_name, 'key') . ' UNIQUE (' . implode(', ', $key) . ')'; } } @@ -277,7 +296,12 @@ class DatabaseSchema_pgsql extends Datab * The new name for the table. */ function renameTable(&$ret, $table, $new_name) { - $ret[] = update_sql('ALTER TABLE {' . $table . '} RENAME TO {' . $new_name . '}'); + // The new name of a table doesn't need to be referenced by schema. + // In the situation where the db_prefix is something like schema.prefix, + // the query will fail. So we must figure this out here instead of wrapping + // the new column in curly braces. + $prefixInfo = $this->getPrefixInfo($new_name); + $ret[] = update_sql('ALTER TABLE {' . $table . '} RENAME TO ' . $prefixInfo['table']); } /** @@ -418,8 +442,24 @@ class DatabaseSchema_pgsql extends Datab * The table to be altered. */ public function dropPrimaryKey(&$ret, $table) { - $ret[] = update_sql('ALTER TABLE {' . $table . '} DROP CONSTRAINT {' . $table . '}_pkey'); + $ret[] = update_sql('ALTER TABLE {' . $table . '} DROP CONSTRAINT ' . $this->_primaryKeyName($table) . '_pkey'); + } + + /** + * Get the name of the primary key + * + * Because the db_prefix may include a schema scope to it and primary keys + * are not references by schema scope, we cannot simply use {$table}_pkey but + * must figure this out for ourselves. + */ + protected function _primaryKeyName($table) { + // Check if the schema is in the prefix. + if (strpos($this->connection->tablePrefix($table), '.') === FALSE) { + return '{' . $table . '}_pkey'; + } + return $table . '_pkey'; } + /** * Add a unique key. @@ -434,8 +474,7 @@ class DatabaseSchema_pgsql extends Datab * An array of field names. */ function addUniqueKey(&$ret, $table, $name, $fields) { - $name = '{' . $table . '}_' . $name . '_key'; - $ret[] = update_sql('ALTER TABLE {' . $table . '} ADD CONSTRAINT ' . $name . ' UNIQUE (' . implode(',', $fields) . ')'); + $ret[] = update_sql('ALTER TABLE {' . $table . '} ADD CONSTRAINT ' . $this->_prefixNonTable($table, $name, 'key') . ' UNIQUE (' . implode(',', $fields) . ')'); } /** @@ -449,8 +488,7 @@ class DatabaseSchema_pgsql extends Datab * The name of the key. */ public function dropUniqueKey(&$ret, $table, $name) { - $name = '{' . $table . '}_' . $name . '_key'; - $ret[] = update_sql('ALTER TABLE {' . $table . '} DROP CONSTRAINT ' . $name); + $ret[] = update_sql('ALTER TABLE {' . $table . '} DROP CONSTRAINT ' . $this->_prefixNonTable($table, $name, 'key')); } /** @@ -578,11 +616,28 @@ class DatabaseSchema_pgsql extends Datab } protected function _createIndexSql($table, $name, $fields) { - $query = 'CREATE INDEX {' . $table . '}_' . $name . '_idx ON {' . $table . '} ('; + $query = 'CREATE INDEX "' . $this->_prefixNonTable($table, $name) . '" ON {' . $table . '} ('; $query .= $this->_createKeySql($fields) . ')'; return $query; } + /** + * Create the name for an index or constraint. + * + * Because the PostgreSQL driver supports using multiple schemas or storing + * Drupal within a schema that is not the public schema, INDEXs cannot simply + * be wrapped with '{' and '}' otherwise we may end up with schema.index which + * is not supported syntax. This function does a bit of logic on top to stop + * that from happening. + */ + protected function _prefixNonTable($table, $name, $suffix = 'idx') { + $prefixInfo = $this->getPrefixInfo($table); + // Just a nice way to create the index name + $index = implode('_', array($prefixInfo['table'], $name, $suffix)); + // remove the '.' if there is one. + return strtr($index, array('.' => '_')); + } + protected function _createKeys(&$ret, $table, $new_keys) { if (isset($new_keys['primary key'])) { $this->addPrimaryKey($ret, $table, $new_keys['primary key']); @@ -603,11 +658,11 @@ class DatabaseSchema_pgsql extends Datab * Retrieve a table or column comment. */ public function getComment($table, $column = NULL) { - $table = $this->connection->prefixTables('{' . $table . '}'); + $prefixInfo = $this->getPrefixInfo($table); // Don't use {} around pg_class, pg_attribute tables. if (isset($column)) { - return db_query('SELECT col_description(oid, attnum) FROM pg_class, pg_attribute WHERE attrelid = oid AND relname = ? AND attname = ?', array($table, $column))->fetchField(); + return db_query('SELECT col_description(oid, attnum) FROM pg_class, pg_attribute WHERE attrelid = oid AND relname = ? AND attname = ?', array($prefixInfo['table'], $column))->fetchField(); } - return db_query('SELECT obj_description(oid, ?) FROM pg_class WHERE relname = ?', array('pg_class', $table))->fetchField(); + return db_query('SELECT obj_description(oid, ?) FROM pg_class WHERE relname = ?', array('pg_class', $prefixInfo['table']))->fetchField(); } } Index: sites/default/default.settings.php =================================================================== RCS file: /cvs/drupal/drupal/sites/default/default.settings.php,v retrieving revision 1.28 diff -u -p -r1.28 default.settings.php --- sites/default/default.settings.php 16 Aug 2009 23:20:43 -0000 1.28 +++ sites/default/default.settings.php 17 Aug 2009 05:31:45 -0000 @@ -130,6 +130,17 @@ * 'authmap' => 'shared_', * ); * + * For PostgreSQL, you can also specify a schema as a part of the + * prefix if the schema's already exist, for example: + * + * $db_prefix = array( + * 'default' => 'main.', + * 'users' => 'shared.', + * 'sessions' => 'shared.', + * 'role' => 'shared.', + * 'authmap' => 'shared.', + * ); + * * Database configuration format: * $databases['default']['default'] = array( * 'driver' => 'mysql',