diff --git a/includes/database/mysql/schema.inc b/includes/database/mysql/schema.inc
index cba41eb5f7c085e58d38bbb18c0b0ca7815f44c1..ff1d99ba8d0773e7c2f35f561bb302e477e63645 100644
--- a/includes/database/mysql/schema.inc
+++ b/includes/database/mysql/schema.inc
@@ -132,7 +132,7 @@ protected function createTableSql($name, $table) {
   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', 'TINYTEXT', 'MEDIUMTEXT', 'LONGTEXT', 'TEXT')) && isset($spec['length'])) {
       $sql .= '(' . $spec['length'] . ')';
     }
     elseif (isset($spec['precision']) && isset($spec['scale'])) {
@@ -143,8 +143,13 @@ protected function createFieldSql($name, $spec) {
       $sql .= ' unsigned';
     }
 
-    if (!empty($spec['not null'])) {
-      $sql .= ' NOT NULL';
+    if (isset($spec['not null'])) {
+      if ($spec['not null']) {
+        $sql .= ' NOT NULL';
+      }
+      else {
+        $sql .= ' NULL';
+      }
     }
 
     if (!empty($spec['auto_increment'])) {
@@ -187,12 +192,16 @@ protected function processField($field) {
     }
 
     // Set the correct database-engine specific datatype.
-    if (!isset($field['mysql_type'])) {
+    // In case one is already provided, force it to uppercase.
+    if (isset($field['mysql_type'])) {
+      $field['mysql_type'] = drupal_strtoupper($field['mysql_type']);
+    }
+    else {
       $map = $this->getFieldTypeMap();
       $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 a/includes/database/pgsql/schema.inc b/includes/database/pgsql/schema.inc
index cfdb312775a3d4207c5df018ef23313b4b1a2368..2ad720ed7ff423c46fcb5baf1700afaa527367db 100644
--- a/includes/database/pgsql/schema.inc
+++ b/includes/database/pgsql/schema.inc
@@ -145,11 +145,11 @@ protected function createTableSql($name, $table) {
   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', 'character', 'text')) && isset($spec['length'])) {
       $sql .= '(' . $spec['length'] . ')';
     }
     elseif (isset($spec['precision']) && isset($spec['scale'])) {
@@ -160,8 +160,13 @@ protected function createFieldSql($name, $spec) {
       $sql .= " CHECK ($name >= 0)";
     }
 
-    if (isset($spec['not null']) && $spec['not null']) {
-      $sql .= ' NOT NULL';
+    if (isset($spec['not null'])) {
+      if ($spec['not null']) {
+        $sql .= ' NOT NULL';
+      }
+      else {
+        $sql .= ' NULL';
+      }
     }
     if (isset($spec['default'])) {
       $default = is_string($spec['default']) ? "'" . $spec['default'] . "'" : $spec['default'];
@@ -181,11 +186,17 @@ protected function processField($field) {
     if (!isset($field['size'])) {
       $field['size'] = 'normal';
     }
+
     // Set the correct database-engine specific datatype.
-    if (!isset($field['pgsql_type'])) {
+    // In case one is already provided, force it to lowercase.
+    if (isset($field['pgsql_type'])) {
+      $field['pgsql_type'] = drupal_strtolower($field['pgsql_type']);
+    }
+    else {
       $map = $this->getFieldTypeMap();
       $field['pgsql_type'] = $map[$field['type'] . ':' . $field['size']];
     }
+
     if (!empty($field['unsigned'])) {
       // Unsigned datatypes are not supported in PostgreSQL 8.3. In MySQL,
       // they are used to ensure a positive number is inserted and it also
@@ -205,7 +216,7 @@ protected function processField($field) {
           break;
       }
     }
-    if ($field['type'] == 'serial') {
+    if (isset($field['type']) && $field['type'] == 'serial') {
       unset($field['not null']);
     }
     return $field;
@@ -462,19 +473,25 @@ public function changeField($table, $field, $field_new, $spec, $new_keys = array
       $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 a/includes/database/sqlite/schema.inc b/includes/database/sqlite/schema.inc
index 2d87de6575d13ee50be21a61c8ab5af19ac0d8f2..6830e6b19757b16caa57a994e0a3585b19b627f0 100644
--- a/includes/database/sqlite/schema.inc
+++ b/includes/database/sqlite/schema.inc
@@ -74,7 +74,7 @@ protected function createColumsSql($tablename, $schema) {
 
     // 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]);
         }
@@ -116,13 +116,18 @@ protected function processField($field) {
     if (!isset($field['size'])) {
       $field['size'] = 'normal';
     }
+
     // Set the correct database-engine specific datatype.
-    if (!isset($field['sqlite_type'])) {
+    // In case one is already provided, force it to uppercase.
+    if (isset($field['sqlite_type'])) {
+      $field['sqlite_type'] = drupal_strtoupper($field['sqlite_type']);
+    }
+    else {
       $map = $this->getFieldTypeMap();
       $field['sqlite_type'] = $map[$field['type'] . ':' . $field['size']];
     }
 
-    if ($field['type'] == 'serial') {
+    if (isset($field['type']) && $field['type'] == 'serial') {
       $field['auto_increment'] = TRUE;
     }
 
@@ -150,12 +155,17 @@ protected function createFieldSql($name, $spec) {
     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', 'TEXT')) && isset($spec['length'])) {
         $sql .= '(' . $spec['length'] . ')';
       }
 
-      if (!empty($spec['not null'])) {
-        $sql .= ' NOT NULL';
+      if (isset($spec['not null'])) {
+        if ($spec['not null']) {
+          $sql .= ' NOT NULL';
+        }
+        else {
+          $sql .= ' NULL';
+        }
       }
 
       if (!empty($spec['unsigned'])) {
diff --git a/modules/simpletest/tests/schema.test b/modules/simpletest/tests/schema.test
index 8c6fa7f46f2a417a30c3d53c45c3c54e69523cd1..7570ab9d822f835619ddc9f330f0dc5e0fc7ae96 100644
--- a/modules/simpletest/tests/schema.test
+++ b/modules/simpletest/tests/schema.test
@@ -112,6 +112,25 @@ class SchemaTestCase extends DrupalWebTestCase {
 
     $count = db_query('SELECT COUNT(*) FROM {test_table}')->fetchField();
     $this->assertEqual($count, 2, t('There were two rows.'));
+
+    // Use database specific data type and ensure that table is created.
+    $table_specification = array(
+      'description' => 'Schema table description.',
+      'fields' => array(
+        'timestamp'  => array(
+          'mysql_type' => 'timestamp',
+          'pgsql_type' => 'timestamp',
+          'sqlite_type' => 'datetime',
+          'not null' => FALSE,
+          'default' => NULL,
+        ),
+      ),
+    );
+    try {
+      db_create_table('test_timestamp', $table_specification);
+    }
+    catch (Exception $e) {}
+    $this->assertTrue(db_table_exists('test_timestamp'), t('Table with database specific datatype was created.'));
   }
 
   function tryInsert($table = 'test_table') {