Skip to content

Commit

Permalink
Add handling of index hints on join clauses too. Fixes phpmyadmin#593
Browse files Browse the repository at this point in the history
  • Loading branch information
niconoe- committed Feb 3, 2025
1 parent b14fd66 commit 11756e6
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 5 deletions.
27 changes: 22 additions & 5 deletions src/Components/JoinKeyword.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,20 +72,29 @@ class JoinKeyword extends Component
*/
public $using;

/**
* Index hints
*
* @var IndexHint[]
*/
public $indexHints = [];

/**
* @see JoinKeyword::$JOINS
*
* @param string $type Join type
* @param Expression $expr join expression
* @param Condition[] $on join conditions
* @param ArrayObj $using columns joined
* @param string $type Join type
* @param Expression $expr join expression
* @param Condition[] $on join conditions
* @param ArrayObj $using columns joined
* @param IndexHint[] $indexHints index hints
*/
public function __construct($type = null, $expr = null, $on = null, $using = null)
public function __construct($type = null, $expr = null, $on = null, $using = null, $indexHints = [])
{
$this->type = $type;
$this->expr = $expr;
$this->on = $on;
$this->using = $using;
$this->indexHints = $indexHints;
}

/**
Expand All @@ -110,6 +119,7 @@ public static function parse(Parser $parser, TokensList $list, array $options =
*
* 1 -----------------------[ expr ]----------------------> 2
*
* 2 -------------------[ index_hints ]-------------------> 2
* 2 ------------------------[ ON ]-----------------------> 3
* 2 -----------------------[ USING ]---------------------> 4
*
Expand Down Expand Up @@ -163,6 +173,12 @@ public static function parse(Parser $parser, TokensList $list, array $options =
case 'USING':
$state = 4;
break;
case 'USE':
case 'IGNORE':
case 'FORCE':
// Adding index hint on the JOIN clause.
$expr->indexHints = IndexHint::parse($parser, $list);
break;
default:
if (empty(static::$JOINS[$token->keyword])) {
/* Next clause is starting */
Expand Down Expand Up @@ -210,6 +226,7 @@ public static function build($component, array $options = [])
$ret = [];
foreach ($component as $c) {
$ret[] = array_search($c->type, static::$JOINS) . ' ' . $c->expr
. ($c->indexHints !== [] ? ' ' . IndexHint::build($c->indexHints) : '')
. (! empty($c->on)
? ' ON ' . Condition::build($c->on) : '')
. (! empty($c->using)
Expand Down
61 changes: 61 additions & 0 deletions tests/Builder/SelectStatementTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -353,4 +353,65 @@ public function testBuilderSurroundedByParanthesisWithLimit(): void
$stmt->build()
);
}

public function testBuilderSelectFromWithForceIndex(): void
{
$query = 'SELECT *'
. ' FROM uno FORCE INDEX (id)';
$parser = new Parser($query);
$stmt = $parser->statements[0];

self::assertSame($query, $stmt->build());
}

/**
* Ensures issue #497 is fixed.
*/
public function testBuilderSelectFromJoinWithForceIndex(): void
{
$query = 'SELECT *'
. ' FROM uno'
. ' JOIN dos FORCE INDEX (two_id) ON dos.id = uno.id';
$parser = new Parser($query);
$stmt = $parser->statements[0];

self::assertSame($query, $stmt->build());
}

/**
* Ensures issue #593 is fixed.
*/
public function testBuilderSelectFromInnerJoinWithForceIndex(): void
{
$query = 'SELECT a.id, a.name, b.order_id, b.total'
. ' FROM customers a'
. ' INNER JOIN orders b FORCE INDEX (idx_customer_id)'
. ' ON a.id = b.customer_id'
. " WHERE a.status = 'active'";

$parser = new Parser($query);
$stmt = $parser->statements[0];

$expectedQuery = 'SELECT a.id, a.name, b.order_id, b.total'
. ' FROM customers AS `a`'
. ' INNER JOIN orders AS `b` FORCE INDEX (idx_customer_id)'
. ' ON a.id = b.customer_id'
. " WHERE a.status = 'active'";

self::assertSame($expectedQuery, $stmt->build());
}

public function testBuilderSelectAllFormsOfIndexHints(): void
{
$query = 'SELECT *'
. ' FROM one USE INDEX (col1) IGNORE INDEX (col1, col2) FORCE INDEX (col1, col2, col3)'
. ' INNER JOIN two USE INDEX (col3) IGNORE INDEX (col2, col3) FORCE INDEX (col1, col2, col3)'
. ' ON one.col1 = two.col2'
. ' WHERE 1 = 1';

$parser = new Parser($query);
$stmt = $parser->statements[0];

self::assertSame($query, $stmt->build());
}
}

0 comments on commit 11756e6

Please sign in to comment.