Skip to content

Commit 1c2828b

Browse files
committed
Add WHERE to SHOW INDEX syntax
1 parent 6d9d426 commit 1c2828b

File tree

5 files changed

+97
-31
lines changed

5 files changed

+97
-31
lines changed

src/FakePdoStatementTrait.php

+8-1
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,14 @@ function ($row) {
244244
break;
245245

246246
case Query\ShowIndexQuery::class:
247-
$this->result = Processor\ShowIndexProcessor::process($this->conn, $parsed_query->table);
247+
$this->result = self::processResult(
248+
$this->conn,
249+
Processor\ShowIndexProcessor::process(
250+
$this->conn,
251+
new Processor\Scope(array_merge($params ?? [], $this->boundValues)),
252+
$parsed_query
253+
)
254+
);
248255
break;
249256

250257
default:

src/Parser/ShowParser.php

+16-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<?php
2+
23
namespace Vimeo\MysqlEngine\Parser;
34

45
use Vimeo\MysqlEngine\Query\ShowIndexQuery;
@@ -59,7 +60,7 @@ public function parse()
5960

6061
}
6162

62-
private function parseShowTables()
63+
private function parseShowTables(): ShowTablesQuery
6364
{
6465
$this->pointer++;
6566

@@ -78,7 +79,7 @@ private function parseShowTables()
7879
return new ShowTablesQuery($token->value, $this->sql);
7980
}
8081

81-
private function parseShowIndex()
82+
private function parseShowIndex(): ShowIndexQuery
8283
{
8384
$this->pointer++;
8485

@@ -90,6 +91,18 @@ private function parseShowIndex()
9091
if ($token === null || $token->type !== TokenType::IDENTIFIER) {
9192
throw new ParserException("Expected table name after FROM");
9293
}
93-
return new ShowIndexQuery($token->value, $this->sql);
94+
95+
$query = new ShowIndexQuery($token->value, $this->sql);
96+
$this->pointer++;
97+
98+
if ($this->pointer < count($this->tokens)) {
99+
if ($this->tokens[$this->pointer]->value !== 'WHERE') {
100+
throw new ParserException("Parser error: expected SHOW INDEX FROM [TABLE_NAME] WHERE");
101+
}
102+
$expression_parser = new ExpressionParser($this->tokens, $this->pointer);
103+
list($this->pointer, $expression) = $expression_parser->buildWithPointer();
104+
$query->whereClause = $expression;
105+
}
106+
return $query;
94107
}
95108
}

src/Processor/ShowIndexProcessor.php

+30-17
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,53 @@
55

66

77
use Vimeo\MysqlEngine\FakePdoInterface;
8+
use Vimeo\MysqlEngine\Query\ShowIndexQuery;
9+
use Vimeo\MysqlEngine\Schema\Column;
810

911
class ShowIndexProcessor extends Processor
1012
{
1113
public static function process(
1214
FakePdoInterface $conn,
13-
string $table
14-
): array
15-
{
16-
$result = [];
17-
[$database, $table] = Processor::parseTableName($conn, $table);
15+
Scope $scope,
16+
ShowIndexQuery $stmt
17+
): QueryResult {
18+
[$database, $table] = Processor::parseTableName($conn, $stmt->table);
1819
$table_definition = $conn->getServer()->getTableDefinition(
1920
$database,
2021
$table
2122
);
23+
$columns = [
24+
'Table' => new Column\Varchar(255),
25+
'Non_unique' => new Column\TinyInt(true, 1),
26+
'Key_name' => new Column\Varchar(255),
27+
'Seq_in_index' => new Column\intColumn(true, 4),
28+
'Column_name' => new Column\Varchar(255),
29+
'Collation' => new Column\Char(1),
30+
'Cardinality' => new Column\intColumn(true, 4),
31+
'Sub_part' => new Column\intColumn(true, 4),
32+
'Packed' => new Column\TinyInt(true, 1),
33+
'Null' => new Column\Varchar(3),
34+
'Index_type' => new Column\Varchar(5),
35+
'Comment' => new Column\Varchar(255),
36+
'Index_comment' => new Column\Varchar(255)
37+
];
38+
$rows = [];
2239
foreach ($table_definition->indexes as $name => $index) {
2340
foreach ($index->columns as $i => $column) {
24-
$result[] = [
41+
$rows[] = [
2542
'Table' => $table_definition->name,
2643
'Non_unique' => $index->type === 'INDEX' ? 1 : 0,
2744
'Key_name' => $name,
28-
'Seq_in_index' => $i+1,
45+
'Seq_in_index' => $i + 1,
2946
'Column_name' => $column,
47+
// Index には "direction" がない(CreateIndex の $cols にはある)ため null
48+
'Collation' => null,
3049
/*
31-
* https://dev.mysql.com/doc/refman/5.6/ja/create-index.html
32-
* index_col_name の指定を ASC または DESC で終了させることができます。
33-
* これらのキーワードは、インデックス値の昇順または降順での格納を指定する将来の拡張のために許可されています。
34-
* 現在、これらは解析されますが、無視されます。インデックス値は、常に昇順で格納されます。
35-
*/
36-
'Collation' => 'A',
37-
/*
38-
* https://dev.mysql.com/doc/refman/5.6/ja/analyze-table.html
50+
* https://dev.mysql.com/doc/refman/8.0/en/analyze-table.html
3951
* ANALYZE TABLE が未実装のため null
4052
*/
4153
'Cardinality' => null,
42-
// Index には "length" がない(CreateIndex の $cols にはある)ため null
54+
// Index には "length" がない(CreateIndex の $cols にはある)ため null
4355
'Sub_part' => null,
4456
// PACK_KEYS が未実装のため null
4557
'Packed' => null,
@@ -53,6 +65,7 @@ public static function process(
5365
];
5466
}
5567
}
56-
return $result;
68+
$result = self::applyWhere($conn, $scope, $stmt->whereClause, new QueryResult($rows, $columns));
69+
return new QueryResult(array_merge($result->rows), $result->columns);
5770
}
5871
}

src/Query/ShowIndexQuery.php

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33

44
final class ShowIndexQuery
55
{
6+
/**
7+
* @var ?Expression
8+
*/
9+
public $whereClause = null;
10+
611
/**
712
* @var string
813
*/

tests/ShowIndexParseTest.php

+38-10
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,63 @@
11
<?php
2+
23
namespace Vimeo\MysqlEngine\Tests;
34

4-
class ShowIndexParseTest extends \PHPUnit\Framework\TestCase
5+
use PHPUnit\Framework\TestCase;
6+
use Vimeo\MysqlEngine\Parser\SQLParser;
7+
use Vimeo\MysqlEngine\Query\SelectQuery;
8+
use Vimeo\MysqlEngine\Query\ShowIndexQuery;
9+
10+
class ShowIndexParseTest extends TestCase
511
{
612
public function testSimpleParse()
713
{
8-
$query = 'SHOW INDEX FROM foo';
14+
$query = 'SHOW INDEX FROM `foo`';
915

10-
$show_query = \Vimeo\MysqlEngine\Parser\SQLParser::parse($query);
16+
$show_query = SQLParser::parse($query);
1117

12-
$this->assertInstanceOf(\Vimeo\MysqlEngine\Query\ShowIndexQuery::class, $show_query);
18+
$this->assertInstanceOf(ShowIndexQuery::class, $show_query);
1319
$this->assertSame('foo', $show_query->table);
1420
}
1521

1622
public function testIndexesParse()
1723
{
18-
$query = 'SHOW INDEXES FROM foo';
24+
$query = 'SHOW INDEXES FROM `foo`';
1925

20-
$show_query = \Vimeo\MysqlEngine\Parser\SQLParser::parse($query);
26+
$show_query = SQLParser::parse($query);
2127

22-
$this->assertInstanceOf(\Vimeo\MysqlEngine\Query\ShowIndexQuery::class, $show_query);
28+
$this->assertInstanceOf(ShowIndexQuery::class, $show_query);
2329
$this->assertSame('foo', $show_query->table);
2430
}
2531

2632
public function testKeysParse()
2733
{
28-
$query = 'SHOW KEYS FROM foo';
34+
$query = 'SHOW KEYS FROM `foo`';
2935

30-
$show_query = \Vimeo\MysqlEngine\Parser\SQLParser::parse($query);
36+
$show_query = SQLParser::parse($query);
3137

32-
$this->assertInstanceOf(\Vimeo\MysqlEngine\Query\ShowIndexQuery::class, $show_query);
38+
$this->assertInstanceOf(ShowIndexQuery::class, $show_query);
3339
$this->assertSame('foo', $show_query->table);
3440
}
41+
42+
public function testParseInvalid()
43+
{
44+
$query = 'SHOW INDEX FROM `foo';
45+
46+
$this->expectException(\Vimeo\MysqlEngine\Parser\LexerException::class);
47+
48+
$select_query = \Vimeo\MysqlEngine\Parser\SQLParser::parse($query);
49+
50+
$this->assertInstanceOf(SelectQuery::class, $select_query);
51+
}
52+
53+
public function testWhereParse()
54+
{
55+
$query = "SHOW INDEX FROM `foo` WHERE `Key_name` = 'PRIMARY'";
56+
57+
$show_query = SQLParser::parse($query);
58+
59+
$this->assertInstanceOf(ShowIndexQuery::class, $show_query);
60+
$this->assertSame('foo', $show_query->table);
61+
}
62+
3563
}

0 commit comments

Comments
 (0)