342503

From: Damien Tournoud <damien@tournoud.net>


---

 includes/database/database.inc     |    4 +-
 includes/database/mysql/schema.inc |   19 ++++++---
 includes/database/pgsql/schema.inc |    8 ----
 includes/database/schema.inc       |   77 ++++++++++++++++++++++++++----------
 4 files changed, 71 insertions(+), 37 deletions(-)


diff --git includes/database/database.inc includes/database/database.inc
index 9178273..4e21d62 100644
--- includes/database/database.inc
+++ includes/database/database.inc
@@ -309,7 +309,7 @@ abstract class DatabaseConnection extends PDO {
    * Queries sent to Drupal should wrap all table names in curly brackets. This
    * function searches for this syntax and adds Drupal's table prefix to all
    * tables, allowing Drupal to coexist with other systems in the same database
-   * if necessary.
+   * and/or schema if necessary.
    *
    * @param $sql
    *   A string containing a partial or entire SQL query.
@@ -353,7 +353,7 @@ abstract class DatabaseConnection extends PDO {
    *   A PDO prepared statement ready for its execute() method.
    */
   protected function prepareQuery($query) {
-    $query = self::prefixTables($query);
+    $query = $this->prefixTables($query);
     if (empty($this->preparedStatements[$query])) {
       // Call PDO::prepare.
       $this->preparedStatements[$query] = parent::prepare($query);
diff --git includes/database/mysql/schema.inc includes/database/mysql/schema.inc
index 0cd51e3..1e8d80b 100644
--- includes/database/mysql/schema.inc
+++ includes/database/mysql/schema.inc
@@ -14,14 +14,21 @@
 
 class DatabaseSchema_mysql extends DatabaseSchema {
 
-  public function tableExists($table) {
-    return (bool) $this->connection->query("SHOW TABLES LIKE '{" . $table . "}'", array(), array())->fetchField();
-  }
+  protected function buildTableNameCondition($table_name, $operator = '=') {
+    $info = Database::getConnectionInfo();
 
-  public function columnExists($table, $column) {
-    return (bool) $this->connection->query("SHOW COLUMNS FROM {" . $this->connection->escapeTable($table) . "} LIKE '" . $this->connection->escapeTable($column) . "'", array(), array())->fetchField();
-  }
+    if (strpos($table_name, '.')) {
+      list($schema, $table_name) = explode('.', $table_name);
+    }
+    else {
+      $schema = $info['default']['database'];
+    }
 
+    $condition = db_and()
+      ->condition('table_schema', $schema);
+      ->condition('table_name', $table_name);
+    return $condition;
+  }
 
   /**
    * Generate SQL to create a new table from a Drupal schema definition.
diff --git includes/database/pgsql/schema.inc includes/database/pgsql/schema.inc
index 687cc8c..2190720 100644
--- includes/database/pgsql/schema.inc
+++ includes/database/pgsql/schema.inc
@@ -13,14 +13,6 @@
 
 class DatabaseSchema_pgsql extends DatabaseSchema {
 
-  public function tableExists($table) {
-    return (bool) db_result(db_query("SELECT COUNT(*) FROM pg_class WHERE relname = '{" . db_escape_table($table) . "}'"));
-  }
-
-  public function columnExists($table, $column) {
-    return (bool) db_result(db_query("SELECT COUNT(pg_attribute.attname) FROM pg_class, pg_attribute WHERE pg_attribute.attrelid = pg_class.oid AND pg_class.relname = '{" . db_escape_table($table) . "}' AND attname = '" . db_escape_table($column) . "'"));
-  }
-
   /**
    * Generate SQL to create a new table from a Drupal schema definition.
    *
diff --git includes/database/schema.inc includes/database/schema.inc
index e408d21..f351cdd 100644
--- includes/database/schema.inc
+++ includes/database/schema.inc
@@ -125,14 +125,68 @@ abstract class DatabaseSchema {
   }
 
   /**
+   * Build a condition to match a table name against a standard information_schema.
+   *
+   * @param $table_name
+   *   The name of the table to explode.
+   * @param $operator
+   *   The operator to apply on the 'table' part of the condition.
+   * @return
+   *   A DatabaseCondition object.
+   */
+  protected function buildTableNameCondition($table_name, $operator = '=') {
+    $info = Database::getConnectionInfo();
+
+    if (strpos($table_name, '.')) {
+      list($schema, $table_name) = explode('.', $table_name);
+    }
+    else {
+      $schema = 'default';
+    }
+
+    $condition = db_and()
+      ->condition('table_catalog', $info['default']['database']);
+      ->condition('table_schema', $schema);
+      ->condition('table_name', $table_name);
+    return $condition;
+  }
+
+  /**
    * Check if a table exists.
    */
-  abstract public function tableExists($table);
+  public function tableExists($table) {
+    $condition = $this->buildTableNameCondition($table);
+    $condition->compile($this->connection);
+
+    return db_query("SELECT table_name FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments)->fetchField();
+  }
+
+  /**
+   * Find all tables that are like the specified base table name.
+   *
+   * @param $table_expression
+   *   An SQL expression, for example "simpletest%" (without the quotes).
+   *   BEWARE: this is not prefixed, the caller should take care of that.
+   * @return
+   *   Array, both the keys and the values are the matching tables.
+   */
+  public function findTables($table_expression) {
+    $condition = $this->buildTableNameCondition($table_expression, 'LIKE');
+    $condition->compile($this->connection);
+
+    return db_query("SELECT table_name FROM information_schema.tables WHERE " . (string) $condition, $condition->arguments)->fetchAllKeyed(0, 0);
+  }
 
   /**
    * Check if a column exists in the given table.
    */
-  abstract public function columnExists($table, $column);
+  public function columnExists($table, $column) {
+    $condition = $this->buildTableNameCondition($table);
+    $condition->condition('column_name', $column);
+    $condition->compile($this->connection);
+
+    return db_query("SELECT column_name FROM information_schema.columns WHERE " . (string) $condition, $condition->arguments)->fetchAllKeyed(0, 0);
+  }
 
   /**
    * This maps a generic data type in combination with its data size
@@ -404,25 +458,6 @@ abstract class DatabaseSchema {
     }
     return $ret;
   }
-
-  /**
-   * Find all tables that are like the specified base table name.
-   *
-   * @param $table_expression
-   *   An SQL expression, for example "simpletest%" (without the quotes).
-   *   BEWARE: this is not prefixed, the caller should take care of that.
-   * @return
-   *   Array, both the keys and the values are the matching tables.
-   */
-  public function findTables($table_expression) {
-    global $db_prefix;
-    $info = Database::getConnectionInfo();
-    $result = db_query("SELECT table_name FROM information_schema.tables WHERE table_schema = :database AND table_name LIKE :table_name", array(
-      ':database' => $info['default']['database'],
-      ':table_name' => $table_expression,
-    ));
-    return $result->fetchAllKeyed(0, 0);
-  }
 }
 
 /**
