summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Pott2016-05-27 14:16:27 (GMT)
committerAlex Pott2016-05-27 14:16:27 (GMT)
commit9233946397f6a77b2bed390ce426f23658066ea0 (patch)
treebd1bf12e6bec1421a0ce4628be99ea1fdfff09b8
parentfbe287dc6a7c47bb1f1d917dfceb5083dd4aadec (diff)
Issue #2726747 by DuaelFr: pgsql improperly escape table names leading to a fatal error
-rw-r--r--core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php51
-rw-r--r--core/tests/Drupal/Tests/Core/Database/Driver/pgsql/PostgresqlConnectionTest.php5
2 files changed, 32 insertions, 24 deletions
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
index 4688cde..8049796 100644
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Connection.php
@@ -210,13 +210,8 @@ class Connection extends DatabaseConnection {
// need to be escaped.
$escaped = $this->escapeTable($table) . '.' . $this->escapeAlias($column);
}
- elseif (preg_match('/[A-Z]/', $escaped)) {
- // Quote the field name for case-sensitivity.
- $escaped = '"' . $escaped . '"';
- }
- elseif (in_array(strtolower($escaped), $this->postgresqlReservedKeyWords)) {
- // Quote the field name for PostgreSQL reserved key words.
- $escaped = '"' . $escaped . '"';
+ else {
+ $escaped = $this->doEscape($escaped);
}
return $escaped;
@@ -227,16 +222,7 @@ class Connection extends DatabaseConnection {
*/
public function escapeAlias($field) {
$escaped = preg_replace('/[^A-Za-z0-9_]+/', '', $field);
-
- // Escape the alias in quotes for case-sensitivity.
- if (preg_match('/[A-Z]/', $escaped)) {
- $escaped = '"' . $escaped . '"';
- }
- elseif (in_array(strtolower($escaped), $this->postgresqlReservedKeyWords)) {
- // Quote the alias name for PostgreSQL reserved key words.
- $escaped = '"' . $escaped . '"';
- }
-
+ $escaped = $this->doEscape($escaped);
return $escaped;
}
@@ -246,16 +232,33 @@ class Connection extends DatabaseConnection {
public function escapeTable($table) {
$escaped = parent::escapeTable($table);
+ // Ensure that each part (database, schema and table) of the table name is
+ // properly and independently escaped.
+ $parts = explode('.', $escaped);
+ $parts = array_map([$this, 'doEscape'], $parts);
+ $escaped = implode('.', $parts);
+
+ return $escaped;
+ }
+
+ /**
+ * Escape a string if needed.
+ *
+ * @param $string
+ * The string to escape.
+ * @return string
+ * The escaped string.
+ */
+ protected function doEscape($string) {
// Quote identifier to make it case-sensitive.
- if (preg_match('/[A-Z]/', $escaped)) {
- $escaped = '"' . $escaped . '"';
+ if (preg_match('/[A-Z]/', $string)) {
+ $string = '"' . $string . '"';
}
- elseif (in_array(strtolower($escaped), $this->postgresqlReservedKeyWords)) {
- // Quote the table name for PostgreSQL reserved key words.
- $escaped = '"' . $escaped . '"';
+ elseif (in_array(strtolower($string), $this->postgresqlReservedKeyWords)) {
+ // Quote the string for PostgreSQL reserved key words.
+ $string = '"' . $string . '"';
}
-
- return $escaped;
+ return $string;
}
public function driver() {
diff --git a/core/tests/Drupal/Tests/Core/Database/Driver/pgsql/PostgresqlConnectionTest.php b/core/tests/Drupal/Tests/Core/Database/Driver/pgsql/PostgresqlConnectionTest.php
index 2bf2639..883f851 100644
--- a/core/tests/Drupal/Tests/Core/Database/Driver/pgsql/PostgresqlConnectionTest.php
+++ b/core/tests/Drupal/Tests/Core/Database/Driver/pgsql/PostgresqlConnectionTest.php
@@ -40,6 +40,11 @@ class PostgresqlConnectionTest extends UnitTestCase {
array('"camelCase"', 'camelCase'),
array('"camelCase"', '"camelCase"'),
array('"camelCase"', 'camel/Case'),
+ // Sometimes, table names are following the pattern database.schema.table.
+ array('"camelCase".nocase.nocase', 'camelCase.nocase.nocase'),
+ array('nocase."camelCase".nocase', 'nocase.camelCase.nocase'),
+ array('nocase.nocase."camelCase"', 'nocase.nocase.camelCase'),
+ array('"camelCase"."camelCase"."camelCase"', 'camelCase.camelCase.camelCase'),
);
}