? 885014.patch
Index: includes/entity.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/entity.inc,v
retrieving revision 1.13
diff -u -p -r1.13 entity.inc
--- includes/entity.inc	22 Aug 2010 16:11:12 -0000	1.13
+++ includes/entity.inc	31 Aug 2010 13:37:27 -0000
@@ -480,6 +480,24 @@ class EntityFieldQuery {
    * @see EntityFieldQuery::range()
    */
   public $range = array();
+  
+  /**
+   * The query pager data.
+   *
+   * @var array
+   *
+   * @see EntityFieldQuery::pager()
+   */
+  public $pager = array();
+  
+  /**
+   * Tablesort.
+   *
+   * @var array
+   *
+   * @see EntityFieldQuery::tablesort
+   */
+  public $tablesort = array();
 
   /**
    * Query behavior for deleted data.
@@ -801,6 +819,54 @@ class EntityFieldQuery {
     );
     return $this;
   }
+  
+  /**
+   * Enable a pager for the query.
+   *
+   * @param $limit
+   *   An integer specifying the number of elements per page.  If passed a false
+   *   value (FALSE, 0, NULL), the pager is disabled.
+   * @param $element
+   *   An optional integer to distinguish between multiple pagers on one page.
+   *
+   * @return EntityFieldQuery
+   *   The called object.
+   */
+  public function pager($limit = 10, $element = NULL) {
+    $this->pager = array(
+      'limit' => $limit,
+      'element' => $element,
+    );
+    return $this;
+  }
+  
+  /**
+   * Enable sortable tables for this query.
+   *
+   * @param $header
+   *   An EFQ Header array that is transformed into an SQL header for orderByHeader
+   *
+   * @return EntityFieldQuery
+   *   The called object.
+   */
+  public function tablesort($header) {
+    // If we have any ordering by fields, we need to populate $this->fields
+    // and save the $index for later use.
+    foreach ($header as $key => $options) {
+      if (!is_array($options)) {
+        continue;
+      }
+      
+      if (isset($options['field'])) {
+        $index = count($this->fields);
+        $this->fields[$index] = field_info_field($options['field']['field_name']);
+        $header[$key]['field']['index'] = $index;
+      }  
+    }
+    
+    $this->tablesort = $header;
+    return $this;
+  }
 
   /**
    * Filters on the data being deleted.
@@ -1033,6 +1099,33 @@ class EntityFieldQuery {
       }
     }
     $this->processProperty($select_query, $base_table);
+    
+    if (isset($this->pager['limit'])) {
+      $select_query = $select_query->extend('PagerDefault');
+      $select_query->limit($this->pager['limit']);
+      $select_query->element($this->pager['element']);
+    }
+    
+    if (count($this->tablesort)) {
+      $select_query = $select_query->extend('TableSort');
+      
+      foreach ($this->tablesort as $key => $options) {
+        if (!is_array($options)) {
+          continue;
+        }
+        
+        if (isset($options['entity'])) {
+          $this->tablesort[$key]['field'] = $id_map[$options['entity']];
+          unset($this->tablesort[$key]['entity']);
+        } else if (isset($options['property'])) {
+          $this->tablesort[$key]['field'] = "$base_table." . $options['property'];
+          unset($this->tablesort[$key]['property']);
+        }
+      }
+      
+      $select_query->orderByHeader($this->tablesort);
+    }
+    
     return $this->finishQuery($select_query);
   }
 
Index: modules/field/modules/field_sql_storage/field_sql_storage.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/field_sql_storage/field_sql_storage.module,v
retrieving revision 1.51
diff -u -p -r1.51 field_sql_storage.module
--- modules/field/modules/field_sql_storage/field_sql_storage.module	22 Aug 2010 16:11:12 -0000	1.51
+++ modules/field/modules/field_sql_storage/field_sql_storage.module	31 Aug 2010 13:37:29 -0000
@@ -549,8 +549,16 @@ function field_sql_storage_field_storage
   if (isset($query->deleted)) {
     $select_query->condition("$field_base_table.deleted", (int) $query->deleted);
   }
+  
+  // Check to see if the tablesort has a "property" attribute
+  $has_tablesort_property = FALSE;
+  foreach ($query->tablesort as $key => $options) {
+    if (is_array($options) && isset($options['property'])) {
+      $has_tablesort_property = TRUE;
+    }
+  }
 
-  if ($query->propertyConditions || $query->propertyOrder) {
+  if ($query->propertyConditions || $query->propertyOrder || $has_tablesort_property) {
     if (empty($query->entityConditions['entity_type']['value'])) {
       throw new EntityFieldQueryException('Property conditions and orders must have an entity type defined.');
     }
@@ -567,6 +575,40 @@ function field_sql_storage_field_storage
     $sql_field = $key == 'entity_type' ? 'fcet.type' : "$field_base_table.$key";
     $query->orderBy($sql_field, $direction);
   }
+  
+  // Transform the tablesort header into a format that TableSort can understand
+  if (count($query->tablesort)) {
+    foreach ($query->tablesort as $key => $options) {
+      if (!is_array($options)) {
+        continue;
+      }
+      
+      if (isset($options['field'])) {
+        $field_name = $options['field']['field_name'];
+        $field = field_info_field($field_name);
+        $index = $options['field']['index'];
+        $table_alias = $table_aliases[$index];
+        $query->tablesort[$key]['field'] = "$table_alias." . _field_sql_storage_columnname($field['field_name'], $options['field']['column']);
+      } else if (isset($options['entity'])) {
+        $query->tablesort[$key]['field'] = $options['entity'] == 'entity_type' ? 'fcet.type' : "$field_base_table." . $options['entity'];
+        unset($query->tablesort[$key]['entity']);
+      } else if (isset($options['property'])) {
+        $query->tablesort[$key]['field'] = "$entity_base_table." . $options['property'];  
+        unset($query->tablesort[$key]['property']);
+      }
+    }
+    
+    $select_query = $select_query->extend('TableSort');
+    $select_query->orderByHeader($query->tablesort);
+  }
+  
+  // Add a pager.
+  if (isset($query->pager['limit'])) {
+    $select_query = $select_query->extend('PagerDefault');
+    $select_query->limit($query->pager['limit']);
+    $select_query->element($query->pager['element']);
+  }
+
   return $query->finishQuery($select_query, $id_key);
 }
 
