diff --git a/includes/common.inc b/includes/common.inc
index 0437ec1..ca5c6aa 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -7138,6 +7138,22 @@ function _drupal_schema_initialize(&$schema, $module, $remove_descriptions = TRU
 }
 
 /**
+ * Retrieves the type for every field in a table schema.
+ *
+ * @param $table
+ *   The name of the table from which to retrieve type information.
+ *
+ * @return
+ *   An array of types, keyed by field name.
+ */
+function drupal_schema_field_types($table) {
+  $table_schema = drupal_get_schema($table);
+  foreach ($table_schema['fields'] as $field_name => $field_info) {
+    $field_types[$field_name] = isset($field_info['type']) ? $field_info['type'] : NULL;
+  }
+}
+
+/**
  * Retrieves a list of fields from a table schema.
  *
  * The returned list is suitable for use in an SQL query.
@@ -7762,6 +7778,7 @@ function entity_get_info($entity_type = NULL) {
         // DrupalEntityControllerInterface::buildQuery().
         if (isset($entity_info[$name]['base table'])) {
           $entity_info[$name]['schema_fields_sql']['base table'] = drupal_schema_fields_sql($entity_info[$name]['base table']);
+          $entity_info[$name]['schema_fields_sql']['base table field types'] = drupal_schema_field_types($entity_info[$name]['base table']);
           if (isset($entity_info[$name]['revision table'])) {
             $entity_info[$name]['schema_fields_sql']['revision table'] = drupal_schema_fields_sql($entity_info[$name]['revision table']);
           }
diff --git a/includes/entity.inc b/includes/entity.inc
index 27434d0..952b7d9 100644
--- a/includes/entity.inc
+++ b/includes/entity.inc
@@ -183,6 +183,11 @@ class DrupalDefaultEntityController implements DrupalEntityControllerInterface {
       }
     }
 
+    // Ensure integer entity IDs are valid.
+    if (!empty($ids)) {
+      $ids = $this->cleanIds($ids);
+    }
+
     // Load any remaining entities from the database. This is the case if $ids
     // is set to FALSE (so we load all entities), if there are any ids left to
     // load, if loading a revision, or if $conditions was passed without $ids.
@@ -224,6 +229,35 @@ class DrupalDefaultEntityController implements DrupalEntityControllerInterface {
   }
 
   /**
+   * Ensures integer entity IDs are valid.
+   *
+   * The identifier sanitization provided by this method has been introduced
+   * as Drupal used to rely on the database to facilitate this, which worked
+   * correctly with MySQL but led to errors with other DBMS such as PostgreSQL.
+   *
+   * @param array $ids
+   *   The entity IDs to verify.
+   *
+   * @return array
+   *   The sanitized list of entity IDs.
+   */
+  protected function cleanIds(&$ids) {
+    $entity_info = entity_get_info($this->entityType);
+    $id_type = $entity_info['base table field types'][$this->idKey];
+    if ($id_type == 'serial' || $id_type == 'int') {
+      $ids = array_filter($ids, array($this, 'filterIds'));
+      $ids = array_map('intval', $ids);
+    }
+  }
+
+  /**
+   * Callback for array_filter that removes non-integer IDs.
+   */
+  protected function filterIds($ids) {
+    return is_numeric($id) && $id == (int) $id;
+  }
+
+  /**
    * Builds the query to load the entity.
    *
    * This has full revision support. For entities requiring special queries,
diff --git a/modules/system/system.api.php b/modules/system/system.api.php
index 164647b..a11c72c 100644
--- a/modules/system/system.api.php
+++ b/modules/system/system.api.php
@@ -75,6 +75,8 @@ function hook_hook_info_alter(&$hooks) {
  *     Leave blank to use the DrupalDefaultEntityController implementation.
  *   - base table: (used by DrupalDefaultEntityController) The name of the
  *     entity type's base table.
+ *   - base table field types: The field types in the fields in the entity type's
+ *     base table.
  *   - revision table: The name of the entity type's revision table (if any).
  *   - static cache: (used by DrupalDefaultEntityController) FALSE to disable
  *     static caching of entities during a page request. Defaults to TRUE.
diff --git a/modules/system/system.test b/modules/system/system.test
index 3e26bae..d4c98f0 100644
--- a/modules/system/system.test
+++ b/modules/system/system.test
@@ -1068,6 +1068,11 @@ class PageNotFoundTestCase extends DrupalWebTestCase {
     );
     $node = $this->drupalCreateNode($edit);
 
+    // As node IDs must be integers, make sure requests for non-integer IDs
+    // return a page not found error.
+    $this->drupalGet('node/invalid');
+    $this->assertResponse(404);
+
     // Use a custom 404 page.
     $this->drupalPost('admin/config/system/site-information', array('site_404' => 'node/' . $node->nid), t('Save configuration'));
 
