Index: wp-includes/link-template.php
===================================================================
--- wp-includes/link-template.php	(revision 27032)
+++ wp-includes/link-template.php	(working copy)
@@ -1128,79 +1128,106 @@
  * @return mixed       Post object if successful. Null if global $post is not set. Empty string if no corresponding post exists.
  */
 function get_adjacent_post( $in_same_term = false, $excluded_terms = '', $previous = true, $taxonomy = 'category' ) {
-	global $wpdb;
-
-	if ( ( ! $post = get_post() ) || ! taxonomy_exists( $taxonomy ) )
+	if ( ( ! $post = get_post() ) || ! taxonomy_exists( $taxonomy ) ) {
 		return null;
+	}
 
-	$current_post_date = $post->post_date;
+	$current_post_date = get_post_field( 'post_date', $post );
 
-	$join = '';
-	$posts_in_ex_terms_sql = '';
-	if ( $in_same_term || ! empty( $excluded_terms ) ) {
-		$join = " INNER JOIN $wpdb->term_relationships AS tr ON p.ID = tr.object_id INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id";
+	// Query basics
+	$args = array(
+		'posts_per_page'   => 1,
+		'post_status'      => 'publish',
+		'post_type'        => 'post',
+		'orderby'          => 'date',
+		'order'            => $previous ? 'DESC' : 'ASC',
+		'no_found_rows'    => true,
+		'cache_results'    => true,
+		'suppress_filters' => false,
+	);
 
-		if ( $in_same_term ) {
-			if ( ! is_object_in_taxonomy( $post->post_type, $taxonomy ) )
-				return '';
-			$term_array = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'ids' ) );
-			if ( ! $term_array || is_wp_error( $term_array ) )
-				return '';
-			$join .= $wpdb->prepare( " AND tt.taxonomy = %s AND tt.term_id IN (" . implode( ',', array_map( 'intval', $term_array ) ) . ")", $taxonomy );
+	// Query pieces
+	$tax_query = array();
+
+	// Set up for requests limited to posts that share terms
+	if ( $in_same_term ) {
+		$terms = get_the_terms( get_the_ID(), $taxonomy );
+
+		if ( is_array( $terms ) && ! empty( $terms ) ) {
+			$terms = wp_list_pluck( $terms, 'term_id' );
+			$terms = array_values( $terms );
+			$terms = array_map( 'intval', $terms );
+		} else {
+			unset( $terms );
 		}
+	}
 
-		$posts_in_ex_terms_sql = $wpdb->prepare( "AND tt.taxonomy = %s", $taxonomy );
-		if ( ! empty( $excluded_terms ) ) {
-			if ( ! is_array( $excluded_terms ) ) {
-				// back-compat, $excluded_terms used to be $excluded_terms with IDs separated by " and "
-				if ( false !== strpos( $excluded_terms, ' and ' ) ) {
-					_deprecated_argument( __FUNCTION__, '3.3', sprintf( __( 'Use commas instead of %s to separate excluded terms.' ), "'and'" ) );
-					$excluded_terms = explode( ' and ', $excluded_terms );
-				} else {
-					$excluded_terms = explode( ',', $excluded_terms );
-				}
+	// Handle excluded terms
+	if ( ! empty( $excluded_terms ) ) {
+		if ( ! is_array( $excluded_terms ) ) {
+			// back-compat, $excluded_terms used to be IDs separated by " and "
+			if ( false !== strpos( $excluded_terms, ' and ' ) ) {
+				_deprecated_argument( __FUNCTION__, '3.3', sprintf( __( 'Use commas instead of %s to separate excluded terms.' ), "'and'" ) );
+				$excluded_terms = explode( ' and ', $excluded_terms );
+			} else {
+				$excluded_terms = explode( ',', $excluded_terms );
 			}
+		}
 
-			$excluded_terms = array_map( 'intval', $excluded_terms );
+		$excluded_terms = array_map( 'intval', $excluded_terms );
 
-			if ( ! empty( $term_array ) ) {
-				$excluded_terms = array_diff( $excluded_terms, $term_array );
-				$posts_in_ex_terms_sql = '';
-			}
+		$tax_query[] = array(
+			'taxonomy' => $tax_query,
+			'slugs'    => $excluded_terms,
+			'compare'  => 'NOT IN',
+		);
+	}
 
-			if ( ! empty( $excluded_terms ) ) {
-				$posts_in_ex_terms_sql = $wpdb->prepare( " AND tt.taxonomy = %s AND tt.term_id NOT IN (" . implode( $excluded_terms, ',' ) . ')', $taxonomy );
-			}
+	// If requesting same term, ensure that excluded terms don't appear in term list list
+	if ( isset( $terms ) ) {
+		if ( isset( $excluded_terms ) && is_array( $excluded_terms ) ) {
+			$terms = array_diff( $terms, $excluded_terms );
 		}
+
+		if ( ! empty( $terms ) ) {
+			$tax_query[] = array(
+				'taxonomy' => $taxonomy,
+				'terms'    => $terms,
+			);
+		}
 	}
 
-	$adjacent = $previous ? 'previous' : 'next';
-	$op = $previous ? '<' : '>';
-	$order = $previous ? 'DESC' : 'ASC';
+	// If we have a tax query, add it to our query args
+	if ( ! empty( $tax_query ) ) {
+		$args['tax_query'] = $tax_query;
+	}
 
-	$join  = apply_filters( "get_{$adjacent}_post_join", $join, $in_same_term, $excluded_terms );
-	$where = apply_filters( "get_{$adjacent}_post_where", $wpdb->prepare( "WHERE p.post_date $op %s AND p.post_type = %s AND p.post_status = 'publish' $posts_in_ex_terms_sql", $current_post_date, $post->post_type), $in_same_term, $excluded_terms );
-	$sort  = apply_filters( "get_{$adjacent}_post_sort", "ORDER BY p.post_date $order LIMIT 1" );
-
-	$query = "SELECT p.ID FROM $wpdb->posts AS p $join $where $sort";
-	$query_key = 'adjacent_post_' . md5( $query );
-	$result = wp_cache_get( $query_key, 'counts' );
-	if ( false !== $result ) {
-		if ( $result )
-			$result = get_post( $result );
-		return $result;
+	// And now, the date constraint
+	if ( $previous ) {
+		$args['date_query'][] = array(
+			'before'    => $current_post_date,
+			'inclusive' => true,
+		);
+	} else {
+		$args['date_query'][] = array(
+			'after'     => $current_post_date,
+			'inclusive' => true,
+		);
 	}
 
-	$result = $wpdb->get_var( $query );
-	if ( null === $result )
-		$result = '';
+	// Ensure the current post isn't returned, since we're using an inclusive date query
+	$args['post__not_in'] = array( get_the_ID() );
 
-	wp_cache_set( $query_key, $result, 'counts' );
+	// Get the posts and return either the post object or null
+	$args = apply_filters( 'get_adjacent_post_args', $args, compact( 'in_same_term', 'excluded_terms', 'previous', 'taxonony' ) );
 
-	if ( $result )
-		$result = get_post( $result );
+	$results = get_posts( $args );
 
-	return $result;
+	if ( is_array( $results ) && ! empty( $results ) ) {
+		return array_shift( $results );
+	} else {
+		return '';
+	}
 }
 
 /**
