#927828: Some schema code incorrectly rely on the generic type instead of the engine-specific type

From: Damien Tournoud <damien@commerceguys.com>


---
 database/mysql/schema.inc  |    4 ++--
 database/pgsql/schema.inc  |   24 +++++++++++++++---------
 database/sqlite/schema.inc |    6 +++---
 3 files changed, 20 insertions(+), 14 deletions(-)

diff --git includes/database/mysql/schema.inc includes/database/mysql/schema.inc
index f042a21..7eea863 100644
--- includes/database/mysql/schema.inc
+++ includes/database/mysql/schema.inc
@@ -132,7 +132,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
   protected function createFieldSql($name, $spec) {
     $sql = "`" . $name . "` " . $spec['mysql_type'];
 
-    if (in_array($spec['type'], array('varchar', 'char', 'text')) && isset($spec['length'])) {
+    if (in_array($spec['mysql_type'], array('varchar', 'char', 'text')) && isset($spec['length'])) {
       $sql .= '(' . $spec['length'] . ')';
     }
     elseif (isset($spec['precision']) && isset($spec['scale'])) {
@@ -192,7 +192,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
       $field['mysql_type'] = $map[$field['type'] . ':' . $field['size']];
     }
 
-    if ($field['type'] == 'serial') {
+    if (isset($field['type']) && $field['type'] == 'serial') {
       $field['auto_increment'] = TRUE;
     }
 
diff --git includes/database/pgsql/schema.inc includes/database/pgsql/schema.inc
index cb08207..6240eb5 100644
--- includes/database/pgsql/schema.inc
+++ includes/database/pgsql/schema.inc
@@ -145,11 +145,11 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
   protected function createFieldSql($name, $spec) {
     $sql = $name . ' ' . $spec['pgsql_type'];
 
-    if ($spec['type'] == 'serial') {
+    if (isset($spec['type']) && $spec['type'] == 'serial') {
       unset($spec['not null']);
     }
 
-    if (in_array($spec['type'], array('varchar', 'char', 'text')) && isset($spec['length'])) {
+    if (in_array($spec['pgsql_type'], array('varchar', 'char', 'text')) && isset($spec['length'])) {
       $sql .= '(' . $spec['length'] . ')';
     }
     elseif (isset($spec['precision']) && isset($spec['scale'])) {
@@ -205,7 +205,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
           break;
       }
     }
-    if ($field['type'] == 'serial') {
+    if (isset($field['type']) && $field['type'] == 'serial') {
       unset($field['not null']);
     }
     return $field;
@@ -462,19 +462,25 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
       $spec['size'] = 'normal';
     }
 
+    // Map type definition to the PostgreSQL type.
+    if (!isset($spec['pgsql_type'])) {
+      $map = $this->getFieldTypeMap();
+      $spec['pgsql_type'] = $map[$spec['type'] . ':' . $spec['size']];
+    }
+
     // 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'))) {
+    if (in_array($spec['pgsql_type'], array('serial', 'bigserial', 'numeric'))) {
       $typecast = 'int';
     }
+    else {
+      $typecast = $spec['pgsql_type'];
+    }
+
     $this->connection->query('ALTER TABLE {' . $table . '} ALTER "' . $field . '" TYPE ' . $typecast . ' USING "' . $field . '"::' . $typecast);
 
-    // Map type definition to the PostgreSQL type.
-    $pgsql_type = $map[$spec['type'] . ':' . $spec['size']];
-    if (in_array($pgsql_type, array('serial', 'bigserial'))) {
+    if (in_array($spec['pgsql_type'], array('serial', 'bigserial'))) {
       // Type "serial" is known to PostgreSQL, but *only* during table creation,
       // not when altering. Because of that, the sequence needs to be created
       // and initialized by hand.
diff --git includes/database/sqlite/schema.inc includes/database/sqlite/schema.inc
index 13881e0..094d930 100644
--- includes/database/sqlite/schema.inc
+++ includes/database/sqlite/schema.inc
@@ -74,7 +74,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
 
     // Add the SQL statement for each field.
     foreach ($schema['fields'] as $name => $field) {
-      if ($field['type'] == 'serial') {
+      if (isset($field['type']) && $field['type'] == 'serial') {
         if (isset($schema['primary key']) && ($key = array_search($name, $schema['primary key'])) !== FALSE) {
           unset($schema['primary key'][$key]);
         }
@@ -122,7 +122,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
       $field['sqlite_type'] = $map[$field['type'] . ':' . $field['size']];
     }
 
-    if ($field['type'] == 'serial') {
+    if (isset($field['type']) && $field['type'] == 'serial') {
       $field['auto_increment'] = TRUE;
     }
 
@@ -150,7 +150,7 @@ class DatabaseSchema_sqlite extends DatabaseSchema {
     else {
       $sql = $name . ' ' . $spec['sqlite_type'];
 
-      if (in_array($spec['type'], array('varchar', 'char', 'text')) && isset($spec['length'])) {
+      if (in_array($spec['sqlite_type'], array('varchar', 'char', 'text')) && isset($spec['length'])) {
         $sql .= '(' . $spec['length'] . ')';
       }
 
