Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 25ca219

Browse files
Merge branch '5.11.x'
Signed-off-by: Maurício Meneghini Fauth <mauricio@mfauth.net>
2 parents 52c51e3 + 26851b6 commit 25ca219

File tree

4 files changed

+87
-4
lines changed

4 files changed

+87
-4
lines changed

‎psalm.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
resolveFromConfigFile="true"
99
findUnusedBaselineEntry="true"
1010
findUnusedCode="true"
11+
ensureOverrideAttribute="false"
12+
strictBinaryOperands="false"
1113
>
1214
<projectFiles>
1315
<file name="bin/sql-parser"/>
@@ -25,6 +27,7 @@
2527
</plugins>
2628

2729
<issueHandlers>
30+
<ClassMustBeFinal errorLevel="suppress"/>
2831
<UnusedClass>
2932
<errorLevel type="suppress">
3033
<file name="tests/benchmarks/UtfStringBench.php"/>

‎src/Components/JoinKeyword.php

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use PhpMyAdmin\SqlParser\Component;
88
use PhpMyAdmin\SqlParser\Parsers\Conditions;
9+
use PhpMyAdmin\SqlParser\Parsers\IndexHints;
910

1011
use function array_search;
1112

@@ -59,29 +60,40 @@ final class JoinKeyword implements Component
5960
*/
6061
public ArrayObj|null $using = null;
6162

63+
/**
64+
* Index hints
65+
*
66+
* @var IndexHint[]
67+
*/
68+
public array $indexHints = [];
69+
6270
/**
6371
* @see JoinKeyword::JOINS
6472
*
65-
* @param string|null $type Join type
66-
* @param Expression|null $expr join expression
67-
* @param Condition[]|null $on join conditions
68-
* @param ArrayObj|null $using columns joined
73+
* @param string|null $type Join type
74+
* @param Expression|null $expr join expression
75+
* @param Condition[]|null $on join conditions
76+
* @param ArrayObj|null $using columns joined
77+
* @param IndexHint[] $indexHints index hints
6978
*/
7079
public function __construct(
7180
string|null $type = null,
7281
Expression|null $expr = null,
7382
array|null $on = null,
7483
ArrayObj|null $using = null,
84+
array $indexHints = [],
7585
) {
7686
$this->type = $type;
7787
$this->expr = $expr;
7888
$this->on = $on;
7989
$this->using = $using;
90+
$this->indexHints = $indexHints;
8091
}
8192

8293
public function build(): string
8394
{
8495
return array_search($this->type, self::JOINS) . '' . $this->expr
96+
. ($this->indexHints !== [] ? '' . IndexHints::buildAll($this->indexHints) : '')
8597
. (! empty($this->on) ? ' ON ' . Conditions::buildAll($this->on) : '')
8698
. (! empty($this->using) ? ' USING ' . $this->using->build() : '');
8799
}

‎src/Parsers/JoinKeywords.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public static function parse(Parser $parser, TokensList $list, array $options =
3939
*
4040
* 1 -----------------------[ expr ]----------------------> 2
4141
*
42+
* 2 -------------------[ index_hints ]-------------------> 2
4243
* 2 ------------------------[ ON ]-----------------------> 3
4344
* 2 -----------------------[ USING ]---------------------> 4
4445
*
@@ -90,6 +91,12 @@ public static function parse(Parser $parser, TokensList $list, array $options =
9091
case 'USING':
9192
$state = 4;
9293
break;
94+
case 'USE':
95+
case 'IGNORE':
96+
case 'FORCE':
97+
// Adding index hint on the JOIN clause.
98+
$expr->indexHints = IndexHints::parse($parser, $list);
99+
break;
93100
default:
94101
if (empty(JoinKeyword::JOINS[$token->keyword])) {
95102
/* Next clause is starting */

‎tests/Builder/SelectStatementTest.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,4 +353,65 @@ public function testBuilderSurroundedByParanthesisWithLimit(): void
353353
$stmt->build(),
354354
);
355355
}
356+
357+
public function testBuilderSelectFromWithForceIndex(): void
358+
{
359+
$query = 'SELECT *'
360+
. ' FROM uno FORCE INDEX (id)';
361+
$parser = new Parser($query);
362+
$stmt = $parser->statements[0];
363+
364+
self::assertSame($query, $stmt->build());
365+
}
366+
367+
/**
368+
* Ensures issue #497 is fixed.
369+
*/
370+
public function testBuilderSelectFromJoinWithForceIndex(): void
371+
{
372+
$query = 'SELECT *'
373+
. ' FROM uno'
374+
. ' JOIN dos FORCE INDEX (two_id) ON dos.id = uno.id';
375+
$parser = new Parser($query);
376+
$stmt = $parser->statements[0];
377+
378+
self::assertSame($query, $stmt->build());
379+
}
380+
381+
/**
382+
* Ensures issue #593 is fixed.
383+
*/
384+
public function testBuilderSelectFromInnerJoinWithForceIndex(): void
385+
{
386+
$query = 'SELECT a.id, a.name, b.order_id, b.total'
387+
. ' FROM customers a'
388+
. ' INNER JOIN orders b FORCE INDEX (idx_customer_id)'
389+
. ' ON a.id = b.customer_id'
390+
. " WHERE a.status = 'active'";
391+
392+
$parser = new Parser($query);
393+
$stmt = $parser->statements[0];
394+
395+
$expectedQuery = 'SELECT a.id, a.name, b.order_id, b.total'
396+
. ' FROM customers AS `a`'
397+
. ' INNER JOIN orders AS `b` FORCE INDEX (idx_customer_id)'
398+
. ' ON a.id = b.customer_id'
399+
. " WHERE a.status = 'active'";
400+
401+
self::assertSame($expectedQuery, $stmt->build());
402+
}
403+
404+
public function testBuilderSelectAllFormsOfIndexHints(): void
405+
{
406+
$query = 'SELECT *'
407+
. ' FROM one USE INDEX (col1) IGNORE INDEX (col1, col2) FORCE INDEX (col1, col2, col3)'
408+
. ' INNER JOIN two USE INDEX (col3) IGNORE INDEX (col2, col3) FORCE INDEX (col1, col2, col3)'
409+
. ' ON one.col1 = two.col2'
410+
. ' WHERE 1 = 1';
411+
412+
$parser = new Parser($query);
413+
$stmt = $parser->statements[0];
414+
415+
self::assertSame($query, $stmt->build());
416+
}
356417
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /