Index: query.php
===================================================================
--- query.php	(revision 17389)
+++ query.php	(working copy)
@@ -878,6 +878,15 @@
 	var $request;
 
 	/**
+	 * Get quick post database query.
+	 *
+	 * @since 3.1
+	 * @access public
+	 * @var string
+	 */
+	var $quick_request;
+
+	/**
 	 * List of posts.
 	 *
 	 * @since 1.5.0
@@ -1887,7 +1896,8 @@
 		$join = '';
 		$search = '';
 		$groupby = '';
-		$fields = '';
+		$fields = "$wpdb->posts.ID"; // see #10964
+		$quick_fields = "$wpdb->posts.*";
 		$post_status_join = false;
 		$page = 1;
 
@@ -2506,19 +2516,33 @@
 
 		$orderby = $q['orderby'];
 
+		// Set up quick_* defaults from the standard placeholders, before filtering
+		$quick_distinct = $distinct;
+		$quick_where = $where;
+		$quick_join = $join;
+		$quick_groupby = $groupby;
+
 		$pieces = array( 'where', 'groupby', 'join', 'orderby', 'distinct', 'fields', 'limits' );
 
 		// Apply post-paging filters on where and join.  Only plugins that
 		// manipulate paging queries should use these hooks.
 		if ( !$q['suppress_filters'] ) {
-			$where		= apply_filters_ref_array( 'posts_where_paged',	array( $where, &$this ) );
-			$groupby	= apply_filters_ref_array( 'posts_groupby',		array( $groupby, &$this ) );
-			$join		= apply_filters_ref_array( 'posts_join_paged',	array( $join, &$this ) );
-			$orderby	= apply_filters_ref_array( 'posts_orderby',		array( $orderby, &$this ) );
-			$distinct	= apply_filters_ref_array( 'posts_distinct',	array( $distinct, &$this ) );
-			$limits		= apply_filters_ref_array( 'post_limits',		array( $limits, &$this ) );
-			$fields		= apply_filters_ref_array( 'posts_fields',		array( $fields, &$this ) );
+			$where		= apply_filters_ref_array( 'posts_where_paged',	array( $where, &$this, false ) );
+			$groupby	= apply_filters_ref_array( 'posts_groupby',		array( $groupby, &$this, false ) );
+			$join		= apply_filters_ref_array( 'posts_join_paged',	array( $join, &$this, false ) );
+			$orderby	= apply_filters_ref_array( 'posts_orderby',		array( $orderby, &$this, false ) );
+			$distinct	= apply_filters_ref_array( 'posts_distinct',	array( $distinct, &$this, false ) );
+			$limits		= apply_filters_ref_array( 'post_limits',		array( $limits, &$this, false ) );
+			$fields		= apply_filters_ref_array( 'posts_fields',		array( $fields, &$this, false ) );
 
+			$quick_where	= apply_filters_ref_array( 'posts_where_paged',	array( $quick_where, &$this, true ) );
+			$quick_groupby	= apply_filters_ref_array( 'posts_groupby',		array( $quick_groupby, &$this, true ) );
+			$quick_join		= apply_filters_ref_array( 'posts_join_paged',	array( $quick_join, &$this, true ) );
+			$quick_orderby	= apply_filters_ref_array( 'posts_orderby',		array( $quick_orderby, &$this, true ) );
+			$quick_distinct	= apply_filters_ref_array( 'posts_distinct',	array( $quick_distinct, &$this, true ) );
+			$quick_limits	= apply_filters_ref_array( 'post_limits',		array( $quick_limits, &$this, true ) );
+			$quick_fields	= apply_filters_ref_array( 'posts_fields',		array( $quick_fields, &$this, true ) );
+
 			// Filter all clauses at once, for convenience
 			$clauses = (array) apply_filters_ref_array( 'posts_clauses', array( compact( $pieces ), &$this ) );
 			foreach ( $pieces as $piece )
@@ -2530,14 +2554,22 @@
 
 		// Filter again for the benefit of caching plugins.  Regular plugins should use the hooks above.
 		if ( !$q['suppress_filters'] ) {
-			$where		= apply_filters_ref_array( 'posts_where_request',		array( $where, &$this ) );
-			$groupby	= apply_filters_ref_array( 'posts_groupby_request',		array( $groupby, &$this ) );
-			$join		= apply_filters_ref_array( 'posts_join_request',		array( $join, &$this ) );
-			$orderby	= apply_filters_ref_array( 'posts_orderby_request',		array( $orderby, &$this ) );
-			$distinct	= apply_filters_ref_array( 'posts_distinct_request',	array( $distinct, &$this ) );
-			$fields		= apply_filters_ref_array( 'posts_fields_request',		array( $fields, &$this ) );
-			$limits		= apply_filters_ref_array( 'post_limits_request',		array( $limits, &$this ) );
+			$where		= apply_filters_ref_array( 'posts_where_request',		array( $where, &$this, false ) );
+			$groupby	= apply_filters_ref_array( 'posts_groupby_request',		array( $groupby, &$this, false ) );
+			$join		= apply_filters_ref_array( 'posts_join_request',		array( $join, &$this, false ) );
+			$orderby	= apply_filters_ref_array( 'posts_orderby_request',		array( $orderby, &$this, false ) );
+			$distinct	= apply_filters_ref_array( 'posts_distinct_request',	array( $distinct, &$this, false ) );
+			$fields		= apply_filters_ref_array( 'posts_fields_request',		array( $fields, &$this, false ) );
+			$limits		= apply_filters_ref_array( 'post_limits_request',		array( $limits, &$this, false ) );
 
+			$quick_where	= apply_filters_ref_array( 'posts_where_request',		array( $quick_where, &$this, true ) );
+			$quick_groupby	= apply_filters_ref_array( 'posts_groupby_request',		array( $quick_groupby, &$this, true ) );
+			$quick_join		= apply_filters_ref_array( 'posts_join_request',		array( $quick_join, &$this, true ) );
+			$quick_orderby	= apply_filters_ref_array( 'posts_orderby_request',		array( $quick_orderby, &$this, true ) );
+			$quick_distinct	= apply_filters_ref_array( 'posts_distinct_request',	array( $quick_distinct, &$this, true ) );
+			$quick_fields	= apply_filters_ref_array( 'posts_fields_request',		array( $quick_fields, &$this, true ) );
+			$quick_limits	= apply_filters_ref_array( 'post_limits_request',		array( $quick_limits, &$this, true ) );
+
 			// Filter all clauses at once, for convenience
 			$clauses = (array) apply_filters_ref_array( 'posts_clauses_request', array( compact( $pieces ), &$this ) );
 			foreach ( $pieces as $piece )
@@ -2546,6 +2578,8 @@
 
 		if ( ! empty($groupby) )
 			$groupby = 'GROUP BY ' . $groupby;
+		if ( ! empty($quick_groupby) ) 
+			$quick_groupby = 'GROUP BY ' . $quick_groupby;
 		if ( !empty( $orderby ) )
 			$orderby = 'ORDER BY ' . $orderby;
 
@@ -2553,28 +2587,70 @@
 		if ( !$q['no_found_rows'] && !empty($limits) )
 			$found_rows = 'SQL_CALC_FOUND_ROWS';
 
-		$this->request = " SELECT $found_rows $distinct $fields FROM $wpdb->posts $join WHERE 1=1 $where $groupby $orderby $limits";
-		if ( !$q['suppress_filters'] )
-			$this->request = apply_filters_ref_array('posts_request', array( $this->request, &$this ) );
+		if ( empty($limits) ) {
+			// Do a direct query, as there is no benefit in fetching a huge load of IDs in an IN clause
+			$this->request = " SELECT $distinct $fields FROM $wpdb->posts $join WHERE 1=1 $where $groupby $orderby";
+			$this->quick_request = " SELECT $quick_distinct $quick_fields FROM $wpdb->posts $quick_join WHERE 1=1 $quick_where $quick_groupby $orderby";
 
-		if ( 'ids' == $q['fields'] ) {
-			$this->posts = $wpdb->get_col($this->request);
+			if ( 'ids' == $q['fields'] ) {
+				$this->posts = $wpdb->get_col($this->request);
 
-			return $this->posts;
-		}
+				return $this->posts;
+			}
 
-		if ( 'id=>parent' == $q['fields'] ) {
-			$this->posts = $wpdb->get_results($this->request);
+			if ( 'id=>parent' == $q['fields'] ) {
+				$this->posts = $wpdb->get_results($this->request);
 
-			$r = array();
-			foreach ( $this->posts as $post )
-				$r[ $post->ID ] = $post->post_parent;
+				$r = array();
+				foreach ( $this->posts as $post )
+					$r[ $post->ID ] = $post->post_parent;
 
-			return $r;
+				return $r;
+			}
+
+			if ( !$q['suppress_filters'] ) {
+					$this->request = apply_filters_ref_array( 'posts_request', array( $this->request, &$this, false ) );
+					$this->quick_request = apply_filters_ref_array( 'posts_request', array( $this->quick_request, &$this, true ) );
+			}
+
+			$this->posts = $wpdb->get_results($this->quick_request);
+
+			$this->found_posts = count($this->posts);
+			$this->found_posts = apply_filters_ref_array( 'found_posts', array( $this->found_posts, &$this ) );
+			$this->max_num_pages = ceil( $this->found_posts / $q['posts_per_page'] );
+		} else {
+			$this->request = " SELECT $found_rows $distinct $fields FROM $wpdb->posts $join WHERE 1=1 $where $groupby $orderby $limits";
+			if ( !$q['suppress_filters'] )
+					$this->request = apply_filters_ref_array( 'posts_request', array( $this->request, &$this, false ) );
+
+			$post_ids = $wpdb->get_col($this->request);
+
+			if ( empty($post_ids) ) {
+					$this->found_posts = 0;
+					$this->found_posts = apply_filters_ref_array( 'found_posts', array( $this->found_posts, &$this ) );
+					$this->max_num_pages = ceil( $this->found_posts / $q['posts_per_page'] );
+
+					$this->quick_request = " SELECT $quick_distinct $quick_fields FROM $wpdb->posts $quick_join WHERE 1=1 $quick_where $quick_groupby $orderby";
+					if ( !$q['suppress_filters'] )
+							$this->quick_request = apply_filters_ref_array('posts_request', array( $this->quick_request, &$this, true ) );
+
+					$this->posts = array(); // no point in querying, since there are no posts
+			} else {
+					$found_posts_query = apply_filters_ref_array( 'found_posts_query', array( 'SELECT FOUND_ROWS()', &$this ) );
+					$this->found_posts = $wpdb->get_var( $found_posts_query );
+					$this->found_posts = apply_filters_ref_array( 'found_posts', array( $this->found_posts, &$this ) );
+					$this->max_num_pages = ceil( $this->found_posts / $q['posts_per_page'] );
+
+					$post_ids = implode(',', $post_ids);
+					$this->quick_request = " SELECT $quick_distinct $quick_fields FROM $wpdb->posts $quick_join WHERE 1 = 1 $quick_where AND $wpdb->posts.ID IN ($post_ids) $quick_groupby ORDER BY FIELD( $wpdb->posts.ID, $post_ids ) ";
+
+					if ( !$q['suppress_filters'] )
+							$this->quick_request = apply_filters_ref_array( 'posts_request', array( $this->quick_request, &$this, true ) );
+
+					$this->posts = $wpdb->get_results($this->quick_request);
+			}
 		}
 
-		$this->posts = $wpdb->get_results($this->request);
-
 		// Raw results filter.  Prior to status checks.
 		if ( !$q['suppress_filters'] )
 			$this->posts = apply_filters_ref_array('posts_results', array( $this->posts, &$this ) );
