? 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',
