Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/wp-includes/class-wp-tax-query.php
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,29 @@ public function get_sql_for_clause( &$clause, $parent_query ) {
return $sql;
}

/*
* Individual joins avoid a correlated subquery for small term intersections.
* Limit total taxonomy joins to three because additional joins can cost more
* than the subquery for common terms.
*/
if ( 3 >= count( $terms ) + count( $this->table_aliases ) ) {
foreach ( $terms as $term ) {
$i = count( $this->table_aliases );
$alias = $i ? 'tt' . $i : $wpdb->term_relationships;

$this->table_aliases[] = $alias;

$join = " LEFT JOIN $wpdb->term_relationships";
$join .= $i ? " AS $alias" : '';
$join .= " ON ($this->primary_table.$this->primary_id_column = $alias.object_id)";

$sql['join'][] = $join;
$sql['where'][] = "$alias.term_taxonomy_id IN ($term)";
}

return $sql;
}

$num_terms = count( $terms );

$terms = implode( ',', $terms );
Expand Down
94 changes: 94 additions & 0 deletions tests/phpunit/tests/term/taxQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,100 @@ public function test_get_sql_operator_and_empty_terms() {
_unregister_taxonomy( 'wptests_tax' );
}

/**
* @ticket 16706
*/
public function test_get_sql_operator_and_uses_joins_for_three_or_fewer_terms() {
$tq = new WP_Tax_Query(
array(
array(
'field' => 'term_taxonomy_id',
'operator' => 'AND',
'terms' => range( 1, 3 ),
),
)
);

global $wpdb;
$sql = $tq->get_sql( $wpdb->posts, 'ID' );

$this->assertSame( 3, substr_count( $sql['join'], 'JOIN' ) );
$this->assertStringNotContainsString( 'SELECT COUNT(1)', $sql['where'] );
}

/**
* @ticket 16706
*/
public function test_get_sql_operator_and_uses_subquery_for_more_than_three_terms() {
$tq = new WP_Tax_Query(
array(
array(
'field' => 'term_taxonomy_id',
'operator' => 'AND',
'terms' => range( 1, 4 ),
),
)
);

global $wpdb;
$sql = $tq->get_sql( $wpdb->posts, 'ID' );

$this->assertSame( '', $sql['join'] );
$this->assertStringContainsString( 'SELECT COUNT(1)', $sql['where'] );
}

/**
* @ticket 16706
*/
public function test_get_sql_operator_and_limits_total_joins_across_clauses() {
$tq = new WP_Tax_Query(
array(
array(
'field' => 'term_taxonomy_id',
'operator' => 'AND',
'terms' => range( 1, 2 ),
),
array(
'field' => 'term_taxonomy_id',
'operator' => 'AND',
'terms' => range( 3, 4 ),
),
)
);

global $wpdb;
$sql = $tq->get_sql( $wpdb->posts, 'ID' );

$this->assertSame( 2, substr_count( $sql['join'], 'JOIN' ) );
$this->assertStringContainsString( 'SELECT COUNT(1)', $sql['where'] );
}

/**
* @ticket 16706
*/
public function test_get_sql_operator_and_counts_existing_in_join_toward_limit() {
$tq = new WP_Tax_Query(
array(
array(
'field' => 'term_taxonomy_id',
'operator' => 'IN',
'terms' => 1,
),
array(
'field' => 'term_taxonomy_id',
'operator' => 'AND',
'terms' => range( 2, 4 ),
),
)
);

global $wpdb;
$sql = $tq->get_sql( $wpdb->posts, 'ID' );

$this->assertSame( 1, substr_count( $sql['join'], 'JOIN' ) );
$this->assertStringContainsString( 'SELECT COUNT(1)', $sql['where'] );
}

/**
* @ticket 18105
* @covers WP_Tax_Query::get_sql
Expand Down
Loading