diff --git a/includes/entity.inc b/includes/entity.inc
index 9ee7889cfb7ca439e77cfdb44282b68e19584a0a..f363c31137248e7f413e96ebe6970d8bd7d83885 100644
--- a/includes/entity.inc
+++ b/includes/entity.inc
@@ -457,6 +457,21 @@ class EntityFieldQuery {
    */
   public $fieldConditions = array();
 
+  /**
+   * List of field meta conditions (language and delta).
+   *
+   * Field conditions operate on columns specified by hook_field_schema(),
+   * the meta conditions operate on columns added by the system: delta
+   * and language. These can not be mixed with the field conditions because
+   * field columns can have any name including delta and language.
+   *
+   * @var array
+   *
+   * @see EntityFieldQuery::fieldLanguageCondition()
+   * @see EntityFieldQuery::fielDeltaCondition()
+   */
+  public $fieldMetaConditions = array();
+
   /**
    * List of property conditions.
    *
@@ -613,6 +628,90 @@ public function entityCondition($name, $value, $operator = NULL) {
   /**
    * Adds a condition on field values.
    *
+   * @param $type
+   *   The condition array the given conditions should be added to.
+   * @param $field
+   *   Either a field name or a field array.
+   * @param $column
+   *   The column that should hold the value to be matched.
+   * @param $value
+   *   The value to test the column value against.
+   * @param $operator
+   *   The operator to be used to test the given value.
+   * @param $delta_group
+   *   An arbitrary identifier: conditions in the same group must have the same
+   *   $delta_group.
+   * @param $language_group
+   *   An arbitrary identifier: conditions in the same group must have the same
+   *   $language_group.
+   *
+   * @return EntityFieldQuery
+   *   The called object.
+   *
+   * @see EntityFieldQuery::addFieldCondition
+   * @see EntityFieldQuery::deleted
+   */
+  public function fieldCondition($field, $column = NULL, $value = NULL, $operator = NULL, $delta_group = NULL, $language_group = NULL) {
+    return $this->addFieldCondition($this->fieldConditions, $field, $column, $value, $operator, $delta_group, $language_group);
+  }
+
+  /**
+   * Adds a condition on the field language column.
+   *
+   * @param $field
+   *   Either a field name or a field array.
+   * @param $value
+   *   The value to test the column value against.
+   * @param $operator
+   *   The operator to be used to test the given value.
+   * @param $delta_group
+   *   An arbitrary identifier: conditions in the same group must have the same
+   *   $delta_group.
+   * @param $language_group
+   *   An arbitrary identifier: conditions in the same group must have the same
+   *   $language_group.
+   *
+   * @return EntityFieldQuery
+   *   The called object.
+   *
+   * @see EntityFieldQuery::addFieldCondition
+   * @see EntityFieldQuery::deleted
+   */
+  public function fieldLanguageCondition($field, $value = NULL, $operator = NULL, $delta_group = NULL, $language_group = NULL) {
+    return $this->addFieldCondition($this->fieldMetaConditions, $field, 'language', $value, $operator, $delta_group, $language_group);
+  }
+
+  /**
+   * Adds a condition on the field delta column.
+   *
+   * @param $field
+   *   Either a field name or a field array.
+   * @param $value
+   *   The value to test the column value against.
+   * @param $operator
+   *   The operator to be used to test the given value.
+   * @param $delta_group
+   *   An arbitrary identifier: conditions in the same group must have the same
+   *   $delta_group.
+   * @param $language_group
+   *   An arbitrary identifier: conditions in the same group must have the same
+   *   $language_group.
+   *
+   * @return EntityFieldQuery
+   *   The called object.
+   *
+   * @see EntityFieldQuery::addFieldCondition
+   * @see EntityFieldQuery::deleted
+   */
+  public function fieldDeltaCondition($field, $value = NULL, $operator = NULL, $delta_group = NULL, $language_group = NULL) {
+    return $this->addFieldCondition($this->fieldMetaConditions, $field, 'delta', $value, $operator, $delta_group, $language_group);
+  }
+
+  /**
+   * Adds the given condition to the proper condition array.
+   *
+   * @param $conditions
+   *   A reference to an array of conditions.
    * @param $field
    *   Either a field name or a field array.
    * @param $column
@@ -649,7 +748,7 @@ public function entityCondition($name, $value, $operator = NULL) {
    * @return EntityFieldQuery
    *   The called object.
    */
-  public function fieldCondition($field, $column = NULL, $value = NULL, $operator = NULL, $delta_group = NULL, $language_group = NULL) {
+  protected function addFieldCondition(&$conditions, $field, $column = NULL, $value = NULL, $operator = NULL, $delta_group = NULL, $language_group = NULL) {
     if (is_scalar($field)) {
       $field_definition = field_info_field($field);
       if (empty($field_definition)) {
@@ -657,11 +756,11 @@ public function fieldCondition($field, $column = NULL, $value = NULL, $operator
       }
       $field = $field_definition;
     }
-    // Ensure the same index is used for fieldConditions as for fields.
+    // Ensure the same index is used for field conditions as for fields.
     $index = count($this->fields);
     $this->fields[$index] = $field;
     if (isset($column)) {
-      $this->fieldConditions[$index] = array(
+      $conditions[$index] = array(
         'field' => $field,
         'column' => $column,
         'value' => $value,
diff --git a/modules/field/modules/field_sql_storage/field_sql_storage.module b/modules/field/modules/field_sql_storage/field_sql_storage.module
index 6f49167ec0061129207803a05dbff567354c03b4..89aeca66f2fc73f72c39d33b4dd38f9a8241fd8f 100644
--- a/modules/field/modules/field_sql_storage/field_sql_storage.module
+++ b/modules/field/modules/field_sql_storage/field_sql_storage.module
@@ -468,7 +468,6 @@ function field_sql_storage_field_storage_purge($entity_type, $entity, $field, $i
  * Implements hook_field_storage_query().
  */
 function field_sql_storage_field_storage_query(EntityFieldQuery $query) {
-  $groups = array();
   if ($query->age == FIELD_LOAD_CURRENT) {
     $tablename_function = '_field_sql_storage_tablename';
     $id_key = 'entity_id';
@@ -499,26 +498,12 @@ function field_sql_storage_field_storage_query(EntityFieldQuery $query) {
     }
   }
 
-  // Add field conditions.
-  foreach ($query->fieldConditions as $key => $condition) {
-    $table_alias = $table_aliases[$key];
-    $field = $condition['field'];
-    // Add the specified condition.
-    $sql_field = "$table_alias." . _field_sql_storage_columnname($field['field_name'], $condition['column']);
-    $query->addCondition($select_query, $sql_field, $condition);
-    // Add delta / language group conditions.
-    foreach (array('delta', 'language') as $column) {
-      if (isset($condition[$column . '_group'])) {
-        $group_name = $condition[$column . '_group'];
-        if (!isset($groups[$column][$group_name])) {
-          $groups[$column][$group_name] = $table_alias;
-        }
-        else {
-          $select_query->where("$table_alias.$column = " . $groups[$column][$group_name] . ".$column");
-        }
-      }
-    }
-  }
+  // Add field conditions. We need a fresh grouping cache.
+  drupal_static_reset('_field_sql_storage_query_field_conditions');
+  _field_sql_storage_query_field_conditions($query, $select_query, $query->fieldConditions, $table_aliases, '_field_sql_storage_columnname');
+
+  // Add field meta conditions.
+  _field_sql_storage_query_field_conditions($query, $select_query, $query->fieldMetaConditions, $table_aliases, function ($field_name, $column) { return $column; });
 
   if (isset($query->deleted)) {
     $select_query->condition("$field_base_table.deleted", (int) $query->deleted);
@@ -591,6 +576,44 @@ function _field_sql_storage_query_join_entity(SelectQuery $select_query, $entity
   return $entity_base_table;
 }
 
+/**
+ * Adds field (meta) conditions to the given query objects respecting groupings.
+ *
+ * @param EntityFieldQuery $query
+ *   The field query object to be processed.
+ * @param SelectQuery $select_query
+ *   The SelectQuery that should get grouping conditions.
+ * @param condtions
+ *   The conditions to be added.
+ * @param $table_aliases
+ *   An associative array of table aliases keyed by field index.
+ * @param $column_callback
+ *   A callback that should return the column name to be used for the field
+ *   conditions. Accepts a field name and a field column name as parameters.
+ */
+function _field_sql_storage_query_field_conditions(EntityFieldQuery $query, SelectQuery $select_query, $conditions, $table_aliases, $column_callback) {
+  $groups = &drupal_static(__FUNCTION__, array());
+  foreach ($conditions as $key => $condition) {
+    $table_alias = $table_aliases[$key];
+    $field = $condition['field'];
+    // Add the specified condition.
+    $sql_field = "$table_alias." . $column_callback($field['field_name'], $condition['column']);
+    $query->addCondition($select_query, $sql_field, $condition);
+    // Add delta / language group conditions.
+    foreach (array('delta', 'language') as $column) {
+      if (isset($condition[$column . '_group'])) {
+        $group_name = $condition[$column . '_group'];
+        if (!isset($groups[$column][$group_name])) {
+          $groups[$column][$group_name] = $table_alias;
+        }
+        else {
+          $select_query->where("$table_alias.$column = " . $groups[$column][$group_name] . ".$column");
+        }
+      }
+    }
+  }
+}
+
 /**
  * Implements hook_field_storage_delete_revision().
  *
diff --git a/modules/simpletest/tests/entity_query.test b/modules/simpletest/tests/entity_query.test
index d28d5a35c9361fb88ddb92f88462ec90d064f026..0fe8106ef6c141d1425ecb86d65f94c605732667 100644
--- a/modules/simpletest/tests/entity_query.test
+++ b/modules/simpletest/tests/entity_query.test
@@ -1049,6 +1049,133 @@ class EntityFieldQueryTestCase extends DrupalWebTestCase {
     $this->assertTrue($pass, t("Can't query the universe."));
   }
 
+  /**
+   * Tests field meta conditions.
+   */
+  function testEntityFieldQueryMetaConditions() {
+    // Make a test field translatable.
+    $this->fields[0]['translatable'] = TRUE;
+    field_update_field($this->fields[0]);
+    field_test_entity_info_translatable('test_entity', TRUE);
+    drupal_static_reset('field_available_languages');
+
+    // Create more items with different languages.
+    $entity = new stdClass();
+    $entity->ftid = 1;
+    $entity->ftvid = 1;
+    $entity->fttype = 'test_bundle';
+    $j = 0;
+
+    foreach (array(LANGUAGE_NONE, 'en') as $langcode) {
+      for ($i = 0; $i < 4; $i++) {
+        $entity->{$this->field_names[0]}[$langcode][$i]['value'] = $i + $j;
+      }
+      $j += 4;
+    }
+
+    field_attach_update('test_entity', $entity);
+
+    // Test delta field meta condition.
+    $query = new EntityFieldQuery();
+    $query
+      ->entityCondition('entity_type', 'test_entity', '=')
+      ->fieldDeltaCondition($this->fields[0], 0, '>');
+    $this->assertEntityFieldQuery($query, array(
+      array('test_entity', 1),
+    ), t('Test with a delta meta condition.'));
+
+    // Test language field meta condition.
+    $query = new EntityFieldQuery();
+    $query
+      ->entityCondition('entity_type', 'test_entity', '=')
+      ->fieldLanguageCondition($this->fields[0], LANGUAGE_NONE, '!=');
+    $this->assertEntityFieldQuery($query, array(
+      array('test_entity', 1),
+    ), t('Test with a language meta condition.'));
+
+    // Test delta grouping.
+    $query = new EntityFieldQuery();
+    $query
+      ->entityCondition('entity_type', 'test_entity', '=')
+      ->fieldCondition($this->fields[0], 'value', 0, '=', 'group')
+      ->fieldDeltaCondition($this->fields[0], 1, '<', 'group');
+    $this->assertEntityFieldQuery($query, array(
+      array('test_entity', 1),
+    ), t('Test with a grouped delta meta condition.'));
+
+    $query = new EntityFieldQuery();
+    $query
+      ->entityCondition('entity_type', 'test_entity', '=')
+      ->fieldCondition($this->fields[0], 'value', 0, '=', 'group')
+      ->fieldDeltaCondition($this->fields[0], 1, '>=', 'group');
+    $this->assertEntityFieldQuery($query, array(), t('Test with a grouped delta meta condition (empty result set).'));
+
+    // Test language grouping.
+    $query = new EntityFieldQuery();
+    $query
+      ->entityCondition('entity_type', 'test_entity', '=')
+      ->fieldCondition($this->fields[0], 'value', 0, '=', NULL, 'group')
+      ->fieldLanguageCondition($this->fields[0], 'en', '!=', NULL, 'group');
+    $this->assertEntityFieldQuery($query, array(
+      array('test_entity', 1),
+    ), t('Test with a grouped language meta condition.'));
+
+    $query = new EntityFieldQuery();
+    $query
+      ->entityCondition('entity_type', 'test_entity', '=')
+      ->fieldCondition($this->fields[0], 'value', 0, '=', NULL, 'group')
+      ->fieldLanguageCondition($this->fields[0], LANGUAGE_NONE, '!=', NULL, 'group');
+    $this->assertEntityFieldQuery($query, array(), t('Test with a grouped language meta condition (empty result set).'));
+
+    // Test delta and language grouping.
+    $query = new EntityFieldQuery();
+    $query
+      ->entityCondition('entity_type', 'test_entity', '=')
+      ->fieldCondition($this->fields[0], 'value', 0, '=', 'delta', 'language')
+      ->fieldDeltaCondition($this->fields[0], 1, '<', 'delta', 'language')
+      ->fieldLanguageCondition($this->fields[0], 'en', '!=', 'delta', 'language');
+    $this->assertEntityFieldQuery($query, array(
+      array('test_entity', 1),
+    ), t('Test with a grouped delta + language meta condition.'));
+
+    $query = new EntityFieldQuery();
+    $query
+      ->entityCondition('entity_type', 'test_entity', '=')
+      ->fieldCondition($this->fields[0], 'value', 0, '=', 'delta', 'language')
+      ->fieldDeltaCondition($this->fields[0], 1, '>=', 'delta', 'language')
+      ->fieldLanguageCondition($this->fields[0], 'en', '!=', 'delta', 'language');
+    $this->assertEntityFieldQuery($query, array(), t('Test with a grouped delta + language meta condition (empty result set, delta condition unsatisifed).'));
+
+    $query = new EntityFieldQuery();
+    $query
+      ->entityCondition('entity_type', 'test_entity', '=')
+      ->fieldCondition($this->fields[0], 'value', 0, '=', 'delta', 'language')
+      ->fieldDeltaCondition($this->fields[0], 1, '<', 'delta', 'language')
+      ->fieldLanguageCondition($this->fields[0], LANGUAGE_NONE, '!=', 'delta', 'language');
+    $this->assertEntityFieldQuery($query, array(), t('Test with a grouped delta + language meta condition (empty result set, language condition unsatisifed).'));
+
+    $query = new EntityFieldQuery();
+    $query
+      ->entityCondition('entity_type', 'test_entity', '=')
+      ->fieldCondition($this->fields[0], 'value', 0, '=', 'delta', 'language')
+      ->fieldDeltaCondition($this->fields[0], 1, '>=', 'delta', 'language')
+      ->fieldLanguageCondition($this->fields[0], LANGUAGE_NONE, '!=', 'delta', 'language');
+    $this->assertEntityFieldQuery($query, array(), t('Test with a grouped delta + language meta condition (empty result set, both conditions unsatisifed).'));
+
+    // Test grouping with another field to ensure that grouping cache is reset
+    // properly.
+    $query = new EntityFieldQuery();
+    $query
+      ->entityCondition('entity_type', 'test_entity_bundle', '=')
+      ->fieldCondition($this->fields[1], 'shape', 'circle', '=', 'delta', 'language')
+      ->fieldCondition($this->fields[1], 'color', 'blue', '=', 'delta', 'language')
+      ->fieldDeltaCondition($this->fields[1], 1, '=', 'delta', 'language')
+      ->fieldLanguageCondition($this->fields[1], LANGUAGE_NONE, '=', 'delta', 'language');
+    $this->assertEntityFieldQuery($query, array(
+      array('test_entity_bundle', 5),
+    ), t('Test grouping cache.'));
+  }
+
   /**
    * Tests the routing feature of EntityFieldQuery.
    */