resolved conflicts

This commit is contained in:
2025-03-31 03:46:05 +03:00
6454 changed files with 1520539 additions and 9 deletions
@@ -0,0 +1,94 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use PhpMyAdmin\SqlParser\Components\Array2d;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Tests\TestCase;
class Array2dTest extends TestCase
{
public function testParse(): void
{
$parser = new Parser();
$arrays = Array2d::parse($parser, $this->getTokensList('(1, 2) +'));
$this->assertEquals(
[
1,
2,
],
$arrays[0]->values
);
}
public function testBuild(): void
{
$arrays = Array2d::parse(new Parser(), $this->getTokensList('(1, 2), (3, 4), (5, 6)'));
$this->assertEquals(
'(1, 2), (3, 4), (5, 6)',
Array2d::build($arrays)
);
}
public function testParseErr1(): void
{
$parser = new Parser();
Array2d::parse($parser, $this->getTokensList('(1, 2 +'));
$this->assertCount(1, $parser->errors);
$this->assertEquals('A closing bracket was expected.', $parser->errors[0]->getMessage());
}
public function testParseErr2(): void
{
$parser = new Parser();
Array2d::parse($parser, $this->getTokensList('(1, 2 TABLE'));
$this->assertCount(1, $parser->errors);
$this->assertEquals('A closing bracket was expected.', $parser->errors[0]->getMessage());
}
public function testParseErr3(): void
{
$parser = new Parser();
Array2d::parse($parser, $this->getTokensList(')'));
$this->assertCount(1, $parser->errors);
$this->assertEquals(
'An opening bracket followed by a set of values was expected.',
$parser->errors[0]->getMessage()
);
}
public function testParseErr4(): void
{
$parser = new Parser();
Array2d::parse($parser, $this->getTokensList('TABLE'));
$this->assertCount(1, $parser->errors);
$this->assertEquals(
'An opening bracket followed by a set of values was expected.',
$parser->errors[0]->getMessage()
);
}
public function testParseErr5(): void
{
$parser = new Parser();
Array2d::parse($parser, $this->getTokensList('(1, 2),'));
$this->assertCount(1, $parser->errors);
$this->assertEquals(
'An opening bracket followed by a set of values was expected.',
$parser->errors[0]->getMessage()
);
}
public function testParseErr6(): void
{
$parser = new Parser();
Array2d::parse($parser, $this->getTokensList('(1, 2),(3)'));
$this->assertCount(1, $parser->errors);
$this->assertEquals(
'2 values were expected, but found 1.',
$parser->errors[0]->getMessage()
);
}
}
@@ -0,0 +1,60 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use PhpMyAdmin\SqlParser\Components\ArrayObj;
use PhpMyAdmin\SqlParser\Components\Expression;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Tests\TestCase;
class ArrayObjTest extends TestCase
{
public function testBuildRaw(): void
{
$component = new ArrayObj(['a', 'b'], []);
$this->assertEquals('(a, b)', ArrayObj::build($component));
}
public function testBuildValues(): void
{
$component = new ArrayObj([], ['a', 'b']);
$this->assertEquals('(a, b)', ArrayObj::build($component));
}
public function testParseType(): void
{
$components = ArrayObj::parse(
new Parser(),
$this->getTokensList('(1 + 2, 3 + 4)'),
[
'type' => Expression::class,
'typeOptions' => ['breakOnParentheses' => true],
]
);
$this->assertInstanceOf(Expression::class, $components[0]);
$this->assertInstanceOf(Expression::class, $components[1]);
$this->assertEquals($components[0]->expr, '1 + 2');
$this->assertEquals($components[1]->expr, '3 + 4');
}
/**
* @dataProvider parseProvider
*/
public function testParse(string $test): void
{
$this->runParserTest($test);
}
/**
* @return string[][]
*/
public static function parseProvider(): array
{
return [
['parser/parseArrayErr1'],
['parser/parseArrayErr3'],
];
}
}
@@ -0,0 +1,128 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use PhpMyAdmin\SqlParser\Components\CaseExpression;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Tests\TestCase;
class CaseExpressionTest extends TestCase
{
public function testParseBuild(): void
{
$caseExprQuery = 'case 1 when 1 then "Some" else "Other" end';
$component = CaseExpression::parse(
new Parser(),
$this->getTokensList($caseExprQuery)
);
$this->assertEquals(
CaseExpression::build($component),
'CASE 1 WHEN 1 THEN "Some" ELSE "Other" END'
);
}
public function testParseBuild2(): void
{
$caseExprQuery = 'case when 1=1 then "India" else "Other" end';
$component = CaseExpression::parse(
new Parser(),
$this->getTokensList($caseExprQuery)
);
$this->assertEquals(
CaseExpression::build($component),
'CASE WHEN 1=1 THEN "India" ELSE "Other" END'
);
}
public function testParseBuild3(): void
{
$caseExprQuery = 'case 1 when 1 then "Some" '
. 'when 2 then "SomeOther" else "Other" end';
$component = CaseExpression::parse(
new Parser(),
$this->getTokensList($caseExprQuery)
);
$this->assertEquals(
CaseExpression::build($component),
'CASE 1 WHEN 1 THEN "Some" WHEN 2 THEN "SomeOther" ELSE "Other" END'
);
}
public function testParseBuild4(): void
{
$caseExprQuery = 'case 1 when 1 then "Some" '
. 'when 2 then "SomeOther" end';
$component = CaseExpression::parse(
new Parser(),
$this->getTokensList($caseExprQuery)
);
$this->assertEquals(
CaseExpression::build($component),
'CASE 1 WHEN 1 THEN "Some" WHEN 2 THEN "SomeOther" END'
);
}
public function testParseBuild5(): void
{
$caseExprQuery = 'case when 1=1 then "Some" '
. 'when 1=2 then "SomeOther" else "Other" end';
$component = CaseExpression::parse(
new Parser(),
$this->getTokensList($caseExprQuery)
);
$this->assertEquals(
CaseExpression::build($component),
'CASE WHEN 1=1 THEN "Some" WHEN 1=2 THEN "SomeOther" ELSE "Other" END'
);
}
public function testParseBuild6(): void
{
$caseExprQuery = 'case when 1=1 then "Some" '
. 'when 1=2 then "SomeOther" end';
$component = CaseExpression::parse(
new Parser(),
$this->getTokensList($caseExprQuery)
);
$this->assertEquals(
CaseExpression::build($component),
'CASE WHEN 1=1 THEN "Some" WHEN 1=2 THEN "SomeOther" END'
);
}
public function testParseBuild7(): void
{
$caseExprQuery = 'case when 1=1 then "Some" '
. 'when 1=2 then "SomeOther" end AS foo';
$component = CaseExpression::parse(
new Parser(),
$this->getTokensList($caseExprQuery)
);
$this->assertEquals(
CaseExpression::build($component),
'CASE WHEN 1=1 THEN "Some" WHEN 1=2 THEN "SomeOther" END AS `foo`'
);
}
public function testParseBuild8(): void
{
$caseExprQuery = 'case when 1=1 then "Some" '
. 'when 1=2 then "SomeOther" end foo';
$component = CaseExpression::parse(
new Parser(),
$this->getTokensList($caseExprQuery)
);
$this->assertEquals(
CaseExpression::build($component),
'CASE WHEN 1=1 THEN "Some" WHEN 1=2 THEN "SomeOther" END AS `foo`'
);
}
public function testBuildWithIncompleteCaseExpression(): void
{
$incompleteCaseExpressionComponent = new CaseExpression();
$this->assertEquals('CASE END', CaseExpression::build($incompleteCaseExpressionComponent));
}
}
@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use PhpMyAdmin\SqlParser\Component;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Tests\TestCase;
use PhpMyAdmin\SqlParser\TokensList;
use Throwable;
class ComponentTest extends TestCase
{
/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testParse(): void
{
$this->expectExceptionMessage('Not implemented yet.');
$this->expectException(Throwable::class);
Component::parse(new Parser(), new TokensList());
}
public function testBuild(): void
{
$this->expectExceptionMessage('Not implemented yet.');
$this->expectException(Throwable::class);
Component::build(null);
}
}
@@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use PhpMyAdmin\SqlParser\Components\Condition;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Tests\TestCase;
class ConditionTest extends TestCase
{
public function testParse(): void
{
$component = Condition::parse(new Parser(), $this->getTokensList('/* id = */ id = 10'));
$this->assertEquals($component[0]->expr, 'id = 10');
}
public function testParseBetween(): void
{
$component = Condition::parse(
new Parser(),
$this->getTokensList('(id BETWEEN 10 AND 20) OR (id BETWEEN 30 AND 40)')
);
$this->assertEquals($component[0]->expr, '(id BETWEEN 10 AND 20)');
$this->assertEquals($component[1]->expr, 'OR');
$this->assertEquals($component[2]->expr, '(id BETWEEN 30 AND 40)');
}
public function testParseAnd(): void
{
$component = Condition::parse(
new Parser(),
$this->getTokensList("`col` LIKE 'AND'")
);
$this->assertEquals(
"`col` LIKE 'AND'",
Condition::build($component)
);
}
}
@@ -0,0 +1,162 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use PhpMyAdmin\SqlParser\Components\CreateDefinition;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Statements\CreateStatement;
use PhpMyAdmin\SqlParser\Tests\TestCase;
class CreateDefinitionTest extends TestCase
{
public function testParse(): void
{
$component = CreateDefinition::parse(
new Parser(),
$this->getTokensList('(str TEXT, FULLTEXT INDEX indx (str))')
);
$this->assertEquals('str', $component[0]->name);
$this->assertEquals('FULLTEXT INDEX', $component[1]->key->type);
$this->assertEquals('indx', $component[1]->key->name);
$this->assertEquals('FULLTEXT INDEX `indx` (`str`)', (string) $component[1]);
}
public function testParse2(): void
{
$component = CreateDefinition::parse(
new Parser(),
$this->getTokensList('(str TEXT NOT NULL INVISIBLE)')
);
$this->assertEquals('str', $component[0]->name);
$this->assertEquals('TEXT', $component[0]->type->name);
$this->assertTrue($component[0]->options->has('INVISIBLE'));
$this->assertTrue($component[0]->options->has('NOT NULL'));
}
public function testParseErr1(): void
{
$parser = new Parser();
$component = CreateDefinition::parse(
$parser,
$this->getTokensList('(str TEXT, FULLTEXT INDEX indx (str)')
);
$this->assertCount(2, $component);
$this->assertEquals(
'A closing bracket was expected.',
$parser->errors[0]->getMessage()
);
}
public function testParseErr2(): void
{
$parser = new Parser();
CreateDefinition::parse(
$parser,
$this->getTokensList(')')
);
$this->assertEquals(
'An opening bracket was expected.',
$parser->errors[0]->getMessage()
);
}
public function testBuild(): void
{
$parser = new Parser(
'CREATE TABLE `payment` (' .
'-- snippet' . "\n" .
'`customer_id` smallint(5) unsigned NOT NULL,' .
'CONSTRAINT `fk_payment_customer` FOREIGN KEY (`customer_id`) ' .
'REFERENCES `customer` (`customer_id`) ON UPDATE CASCADE' .
') ENGINE=InnoDB"'
);
$this->assertInstanceOf(CreateStatement::class, $parser->statements[0]);
$this->assertEquals(
'CONSTRAINT `fk_payment_customer` FOREIGN KEY (`customer_id`) ' .
'REFERENCES `customer` (`customer_id`) ON UPDATE CASCADE',
CreateDefinition::build($parser->statements[0]->fields[1])
);
}
public function testBuild2(): void
{
$parser = new Parser(
'CREATE TABLE `payment` (' .
'-- snippet' . "\n" .
'`customer_id` smallint(5) unsigned NOT NULL,' .
'`customer_data` longtext CHARACTER SET utf8mb4 CHARSET utf8mb4_bin NOT NULL ' .
'CHECK (json_valid(customer_data)),CONSTRAINT `fk_payment_customer` FOREIGN KEY ' .
'(`customer_id`) REFERENCES `customer` (`customer_id`) ON UPDATE CASCADE' .
') ENGINE=InnoDB"'
);
$this->assertInstanceOf(CreateStatement::class, $parser->statements[0]);
$this->assertEquals(
'CONSTRAINT `fk_payment_customer` FOREIGN KEY (`customer_id`) ' .
'REFERENCES `customer` (`customer_id`) ON UPDATE CASCADE',
CreateDefinition::build($parser->statements[0]->fields[2])
);
}
public function testBuild3(): void
{
$parser = new Parser(
'DROP TABLE IF EXISTS `searches`;'
. 'CREATE TABLE `searches` ('
. ' `id` int(10) unsigned NOT NULL AUTO_INCREMENT,'
. ' `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,'
. ' `public_name` varchar(120) COLLATE utf8_unicode_ci NOT NULL,'
. ' `group_id` smallint(5) unsigned NOT NULL DEFAULT \'0\','
. ' `shortdesc` tinytext COLLATE utf8_unicode_ci,'
. ' `show_separators` tinyint(1) NOT NULL DEFAULT \'0\','
. ' `show_separators_two` tinyint(1) NOT NULL DEFAULT FALSE,'
. ' `deleted` tinyint(1) NOT NULL DEFAULT \'0\','
. ' PRIMARY KEY (`id`)'
. ') ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ;'
. ''
. 'ALTER TABLE `searches` ADD `admins_only` BOOLEAN NOT NULL DEFAULT FALSE AFTER `show_separators`;'
);
$this->assertInstanceOf(CreateStatement::class, $parser->statements[1]);
$this->assertEquals(
'`public_name` varchar(120) COLLATE utf8_unicode_ci NOT NULL',
CreateDefinition::build($parser->statements[1]->fields[2])
);
$this->assertEquals(
'`show_separators` tinyint(1) NOT NULL DEFAULT \'0\'',
CreateDefinition::build($parser->statements[1]->fields[5])
);
$this->assertEquals(
'`show_separators_two` tinyint(1) NOT NULL DEFAULT FALSE',
CreateDefinition::build($parser->statements[1]->fields[6])
);
}
public function testBuildWithInvisibleKeyword(): void
{
$parser = new Parser(
'CREATE TABLE `payment` (' .
'-- snippet' . "\n" .
'`customer_id` smallint(5) unsigned NOT NULL INVISIBLE,' .
'`customer_data` longtext CHARACTER SET utf8mb4 CHARSET utf8mb4_bin NOT NULL ' .
'CHECK (json_valid(customer_data)),CONSTRAINT `fk_payment_customer` FOREIGN KEY ' .
'(`customer_id`) REFERENCES `customer` (`customer_id`) ON UPDATE CASCADE' .
') ENGINE=InnoDB"'
);
$this->assertInstanceOf(CreateStatement::class, $parser->statements[0]);
$this->assertEquals(
'`customer_id` smallint(5) UNSIGNED NOT NULL INVISIBLE',
CreateDefinition::build($parser->statements[0]->fields[0])
);
}
public function testBuildWithCompressed(): void
{
$query = 'CREATE TABLE `user` ( `message2` TEXT COMPRESSED )';
$parser = new Parser($query);
$stmt = $parser->statements[0];
$this->assertEquals("CREATE TABLE `user` (\n `message2` text COMPRESSED\n) ", $stmt->build());
}
}
@@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use PhpMyAdmin\SqlParser\Components\ExpressionArray;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Tests\TestCase;
class ExpressionArrayTest extends TestCase
{
public function testParse(): void
{
$component = ExpressionArray::parse(
new Parser(),
$this->getTokensList('(expr)'),
['breakOnParentheses' => true]
);
$this->assertEquals([], $component);
}
public function testParse2(): void
{
$component = ExpressionArray::parse(
new Parser(),
$this->getTokensList('(expr) +'),
['parenthesesDelimited' => true]
);
$this->assertCount(1, $component);
$this->assertEquals('(expr)', $component[0]->expr);
}
public function testParseWithCommentsNoOptions(): void
{
$component = ExpressionArray::parse(
new Parser(),
$this->getTokensList('(expr) -- comment ?')
);
$this->assertCount(1, $component);
$this->assertEquals('(expr)', $component[0]->expr);
}
public function testParseWithCommentsAndOptions(): void
{
$component = ExpressionArray::parse(
new Parser(),
$this->getTokensList('(expr -- comment ?)'),
['parenthesesDelimited' => true]
);
$this->assertCount(1, $component);
$this->assertEquals('(expr', $component[0]->expr);
}
}
@@ -0,0 +1,154 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use PhpMyAdmin\SqlParser\Components\Expression;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Tests\TestCase;
class ExpressionTest extends TestCase
{
public function testParse(): void
{
$component = Expression::parse(new Parser(), $this->getTokensList('IF(film_id > 0, film_id, film_id)'));
$this->assertEquals($component->expr, 'IF(film_id > 0, film_id, film_id)');
}
public function testParse2(): void
{
$component = Expression::parse(new Parser(), $this->getTokensList('col`test`'));
$this->assertEquals($component->expr, 'col');
}
public function testParse3(): void
{
$component = Expression::parse(new Parser(), $this->getTokensList('col xx'));
$this->assertEquals($component->alias, 'xx');
$component = Expression::parse(new Parser(), $this->getTokensList('col y'));
$this->assertEquals($component->alias, 'y');
$component = Expression::parse(new Parser(), $this->getTokensList('avg.col FROM (SELECT ev.col FROM ev)'));
$this->assertEquals($component->table, 'avg');
$this->assertEquals($component->expr, 'avg.col');
$component = Expression::parse(new Parser(), $this->getTokensList('x.id FROM (SELECT a.id FROM a) x'));
$this->assertEquals($component->table, 'x');
$this->assertEquals($component->expr, 'x.id');
}
/**
* @dataProvider parseErrProvider
*/
public function testParseErr(string $expr, string $error): void
{
$parser = new Parser();
Expression::parse($parser, $this->getTokensList($expr));
$errors = $this->getErrorsAsArray($parser);
$this->assertEquals($errors[0][0], $error);
}
/**
* @return string[][]
*/
public static function parseErrProvider(): array
{
return [
/*
[
'(1))',
'Unexpected closing bracket.',
],
*/
[
'tbl..col',
'Unexpected dot.',
],
[
'id AS AS id2',
'An alias was expected.',
],
[
'id`id2`\'id3\'',
'An alias was previously found.',
],
[
'(id) id2 id3',
'An alias was previously found.',
],
];
}
public function testBuild(): void
{
$component = [
new Expression('1 + 2', 'three'),
new Expression('1 + 3', 'four'),
];
$this->assertEquals(
Expression::build($component),
'1 + 2 AS `three`, 1 + 3 AS `four`'
);
}
/**
* @return string[][]
*/
public static function mysqlCommandsProvider(): array
{
return [
[
'/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;',
'SET @OLD_CHARACTER_SET_CLIENT = @@CHARACTER_SET_CLIENT',
],
[
'/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;',
'SET @OLD_CHARACTER_SET_RESULTS = @@CHARACTER_SET_RESULTS',
],
[
'/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;',
'SET @OLD_COLLATION_CONNECTION = @@COLLATION_CONNECTION',
],
[
'/*!40101 SET NAMES utf8 */;',
'SET NAMES utf8',
],
[
'/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;',
'SET @OLD_TIME_ZONE = @@TIME_ZONE',
],
[
"/*!40103 SET TIME_ZONE='+00:00' */;",
"SET TIME_ZONE = '+00:00'",
],
[
'/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;',
'SET @OLD_UNIQUE_CHECKS = @@UNIQUE_CHECKS, UNIQUE_CHECKS = 0',
],
[
'/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;',
'SET @OLD_FOREIGN_KEY_CHECKS = @@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS = 0',
],
[
"/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;",
"SET @OLD_SQL_MODE = @@SQL_MODE, SQL_MODE = 'NO_AUTO_VALUE_ON_ZERO'",
],
[
'/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;',
'SET @OLD_SQL_NOTES = @@SQL_NOTES, SQL_NOTES = 0',
],
];
}
/**
* @dataProvider mysqlCommandsProvider
*/
public function testMysqlCommands(string $expr, string $expected): void
{
$parser = new Parser($expr, true);
$parser->parse();
self::assertSame($expected, $parser->statements[0]->build());
}
}
@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use PhpMyAdmin\SqlParser\Components\ArrayObj;
use PhpMyAdmin\SqlParser\Components\FunctionCall;
use PhpMyAdmin\SqlParser\Tests\TestCase;
class FunctionCallTest extends TestCase
{
public function testBuildArray(): void
{
$component = new FunctionCall('func', ['a', 'b']);
$this->assertEquals('func(a, b)', FunctionCall::build($component));
}
public function testBuildArrayObj(): void
{
$component = new FunctionCall('func', new ArrayObj(['a', 'b']));
$this->assertEquals('func(a, b)', FunctionCall::build($component));
}
}
@@ -0,0 +1,76 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use Generator;
use PhpMyAdmin\SqlParser\Components\Expression;
use PhpMyAdmin\SqlParser\Components\GroupKeyword;
use PhpMyAdmin\SqlParser\Tests\TestCase;
use function array_map;
class GroupKeywordTest extends TestCase
{
/**
* @return Generator<string, array{GroupKeyword|array<GroupKeyword>, string}>
*/
public static function provideExpressions(): Generator
{
yield 'With no expression at all' => [[], ''];
yield 'With single simple expression' => [
self::makeComponentFrom('a'),
'a',
];
yield 'With multiple simple expressions' => [
self::makeComponentsFrom('a', 'b', 'c'),
'a, b, c',
];
yield 'With single untrimmed expression' => [
self::makeComponentFrom(' o '),
'o',
];
yield 'With single untrimmed expression having several kinds of whitespaces' => [
self::makeComponentFrom(" \n\r foo \t\v\x00 "),
'foo',
];
yield 'With multiple untrimmed expressions' => [
self::makeComponentsFrom(' x', ' y ', 'z '),
'x, y, z',
];
yield 'With multiple untrimmed expression having several kinds of whitespaces' => [
self::makeComponentsFrom(" \n\r\t\v\x00foo", " \n\r\tbar\v\x00", "baz \n\r\t\v\x00"),
'foo, bar, baz',
];
}
/**
* @param GroupKeyword|array<GroupKeyword> $component
*
* @dataProvider provideExpressions
*/
public function testBuild($component, string $expected): void
{
$this->assertSame($expected, GroupKeyword::build($component));
}
private static function makeComponentFrom(string $string): GroupKeyword
{
return new GroupKeyword(new Expression($string));
}
/**
* @return array<GroupKeyword>
*/
private static function makeComponentsFrom(string ...$string): array
{
return array_map([self::class, 'makeComponentFrom'], $string);
}
}
@@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use PhpMyAdmin\SqlParser\Components\IntoKeyword;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Tests\TestCase;
class IntoKeywordTest extends TestCase
{
public function testParse(): void
{
$component = IntoKeyword::parse(new Parser(), $this->getTokensList('OUTFILE "/tmp/outfile.txt"'));
$this->assertEquals($component->type, 'OUTFILE');
$this->assertEquals($component->dest, '/tmp/outfile.txt');
}
public function testBuild(): void
{
$component = IntoKeyword::parse(new Parser(), $this->getTokensList('tbl(`col1`, `col2`)'));
$this->assertEquals('tbl(`col1`, `col2`)', IntoKeyword::build($component));
}
public function testBuildValues(): void
{
$component = IntoKeyword::parse(new Parser(), $this->getTokensList('@a1, @a2, @a3'));
$this->assertEquals('@a1, @a2, @a3', IntoKeyword::build($component));
}
public function testBuildOutfile(): void
{
$component = IntoKeyword::parse(new Parser(), $this->getTokensList('OUTFILE "/tmp/outfile.txt"'));
$this->assertEquals('OUTFILE "/tmp/outfile.txt"', IntoKeyword::build($component));
}
public function testParseErr1(): void
{
$component = IntoKeyword::parse(new Parser(), $this->getTokensList('OUTFILE;'));
$this->assertEquals($component->type, 'OUTFILE');
}
}
@@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use PhpMyAdmin\SqlParser\Components\JoinKeyword;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Tests\TestCase;
class JoinKeywordTest extends TestCase
{
public function testParseIncomplete(): void
{
$component = JoinKeyword::parse(new Parser(), $this->getTokensList('JOIN a'));
$this->assertCount(1, $component);
$this->assertEquals('a', $component[0]->expr->expr);
$this->assertNull($component[0]->on);
$this->assertNull($component[0]->using);
}
public function testParseIncompleteUsing(): void
{
$component = JoinKeyword::parse(new Parser(), $this->getTokensList('JOIN table2 USING (id)'));
$this->assertCount(1, $component);
$this->assertEquals('table2', $component[0]->expr->expr);
$this->assertNull($component[0]->on);
$this->assertEquals(['id'], $component[0]->using->values);
}
public function testBuild(): void
{
$component = JoinKeyword::parse(
new Parser(),
$this->getTokensList(
'LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4) ' .
'ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)'
)
);
$this->assertEquals(
'LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4) ' .
'ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)',
JoinKeyword::build($component)
);
}
}
@@ -0,0 +1,374 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use PhpMyAdmin\SqlParser\Components\Expression;
use PhpMyAdmin\SqlParser\Components\Key;
use PhpMyAdmin\SqlParser\Components\OptionsArray;
use PhpMyAdmin\SqlParser\Exceptions\ParserException;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Tests\TestCase;
use PhpMyAdmin\SqlParser\Token;
class KeyTest extends TestCase
{
public function testParse(): void
{
$component = Key::parse(
new Parser(),
$this->getTokensList('')
);
$this->assertNull($component->type);
$this->assertNull($component->options);
$this->assertNull($component->name);
$this->assertNull($component->expr);
$this->assertSame([], $component->columns);
$this->assertSame(
'()',
Key::build($component)
);
}
public function testParseKeyWithoutOptions(): void
{
$component = Key::parse(
new Parser(),
$this->getTokensList('KEY `alias_type_idx` (`alias_type`),')
);
$this->assertEquals('KEY', $component->type);
$this->assertEquals('alias_type_idx', $component->name);
$this->assertEquals(new OptionsArray(), $component->options);
$this->assertNull($component->expr);
$this->assertSame([['name' => 'alias_type']], $component->columns);
$this->assertSame(
'KEY `alias_type_idx` (`alias_type`)',
Key::build($component)
);
}
public function testParseKeyWithLengthWithoutOptions(): void
{
$component = Key::parse(
new Parser(),
$this->getTokensList('KEY `alias_type_idx` (`alias_type`(10)),')
);
$this->assertEquals('KEY', $component->type);
$this->assertEquals('alias_type_idx', $component->name);
$this->assertEquals(new OptionsArray(), $component->options);
$this->assertNull($component->expr);
$this->assertSame([['name' => 'alias_type', 'length' => 10]], $component->columns);
$this->assertSame(
'KEY `alias_type_idx` (`alias_type`(10))',
Key::build($component)
);
}
public function testParseKeyWithLengthWithoutOptionsWithOrder(): void
{
$component = Key::parse(
new Parser(),
$this->getTokensList('KEY `alias_type_idx` (`alias_type`(10) ASC),')
);
$this->assertEquals('KEY', $component->type);
$this->assertEquals('alias_type_idx', $component->name);
$this->assertEquals(new OptionsArray(), $component->options);
$this->assertNull($component->expr);
$this->assertSame([['name' => 'alias_type', 'length' => 10, 'order' => 'ASC']], $component->columns);
$this->assertSame(
'KEY `alias_type_idx` (`alias_type`(10) ASC)',
Key::build($component)
);
}
public function testParseKeyWithoutOptionsWithOrderLowercase(): void
{
$component = Key::parse(
new Parser(),
$this->getTokensList('KEY `alias_type_idx` (`alias_type` desc),')
);
$this->assertEquals('KEY', $component->type);
$this->assertEquals('alias_type_idx', $component->name);
$this->assertEquals(new OptionsArray(), $component->options);
$this->assertNull($component->expr);
$this->assertSame([['name' => 'alias_type', 'order' => 'DESC']], $component->columns);
$this->assertSame(
'KEY `alias_type_idx` (`alias_type` DESC)',
Key::build($component)
);
}
public function testParseKeyWithoutOptionsWithOrder(): void
{
$component = Key::parse(
new Parser(),
$this->getTokensList('KEY `alias_type_idx` (`alias_type` DESC),')
);
$this->assertEquals('KEY', $component->type);
$this->assertEquals('alias_type_idx', $component->name);
$this->assertEquals(new OptionsArray(), $component->options);
$this->assertNull($component->expr);
$this->assertSame([['name' => 'alias_type', 'order' => 'DESC']], $component->columns);
$this->assertSame(
'KEY `alias_type_idx` (`alias_type` DESC)',
Key::build($component)
);
}
public function testParseKeyWithLengthWithOptions(): void
{
$component = Key::parse(
new Parser(),
$this->getTokensList('KEY `alias_type_idx` (`alias_type`(10)) COMMENT \'my comment\',')
);
$this->assertEquals('KEY', $component->type);
$this->assertEquals('alias_type_idx', $component->name);
$this->assertEquals(new OptionsArray(
[
4 => [
'name' => 'COMMENT',
'equals' => false,
'expr' => '\'my comment\'',
'value' => 'my comment',
],
]
), $component->options);
$this->assertNull($component->expr);
$this->assertSame([['name' => 'alias_type', 'length' => 10]], $component->columns);
$this->assertSame(
'KEY `alias_type_idx` (`alias_type`(10)) COMMENT \'my comment\'',
Key::build($component)
);
}
public function testParseKeyWithLengthWithAllOptions(): void
{
$component = Key::parse(
new Parser(),
$this->getTokensList(
// This is not a vary plausible example but it runs
// Only ENGINE_ATTRIBUTE gives a not supported error but is still a valid syntax
'KEY `alias_type_idx` (`alias_type`(10))'
. ' COMMENT \'my comment\' VISIBLE KEY_BLOCK_SIZE=1'
. ' INVISIBLE ENGINE_ATTRIBUTE \'foo\' SECONDARY_ENGINE_ATTRIBUTE=\'bar\' USING BTREE,'
)
);
$this->assertEquals('KEY', $component->type);
$this->assertEquals('alias_type_idx', $component->name);
$this->assertEquals(new OptionsArray(
[
1 => [
'name' => 'KEY_BLOCK_SIZE',
'equals' => true,
'expr' => '1',
'value' => '1',
],
2 => [
'name' => 'USING',
'equals' => false,
'expr' => 'BTREE',
'value' => 'BTREE',
],
4 => [
'name' => 'COMMENT',
'equals' => false,
'expr' => '\'my comment\'',
'value' => 'my comment',
],
5 => [
'name' => 'ENGINE_ATTRIBUTE',
'equals' => true,
'expr' => '\'foo\'',
'value' => 'foo',
],
6 => 'VISIBLE',
12 => 'INVISIBLE',
13 => [
'name' => 'SECONDARY_ENGINE_ATTRIBUTE',
'equals' => true,
'expr' => '\'bar\'',
'value' => 'bar',
],
]
), $component->options);
$this->assertNull($component->expr);
$this->assertSame([['name' => 'alias_type', 'length' => 10]], $component->columns);
}
public function testParseKeyExpressionWithoutOptions(): void
{
$component = Key::parse(
new Parser(),
$this->getTokensList(
'KEY `updated_tz_ind2` ((convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'GB\'))),'
)
);
$this->assertEquals('KEY', $component->type);
$this->assertEquals('updated_tz_ind2', $component->name);
$this->assertEquals(new OptionsArray(), $component->options);
$expr = new Expression('(convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'GB\'))');
$expr->function = 'convert_tz';
$this->assertEquals($expr, $component->expr);
$this->assertSame([], $component->columns);
$this->assertSame(
'KEY `updated_tz_ind2` ((convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'GB\'))) ',
Key::build($component)
);
}
public function testParseKeyExpressionWithOptions(): void
{
$component = Key::parse(
new Parser(),
$this->getTokensList(
'KEY `updated_tz_ind2`'
. ' ((convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'GB\')))'
. ' COMMENT \'my comment\','
)
);
$this->assertEquals('KEY', $component->type);
$this->assertEquals('updated_tz_ind2', $component->name);
$this->assertEquals(new OptionsArray(
[
4 => [
'name' => 'COMMENT',
'equals' => false,
'expr' => '\'my comment\'',
'value' => 'my comment',
],
]
), $component->options);
$expr = new Expression('(convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'GB\'))');
$expr->function = 'convert_tz';
$this->assertEquals($expr, $component->expr);
$this->assertSame([], $component->columns);
$this->assertSame(
'KEY `updated_tz_ind2`'
. ' ((convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'GB\')))'
. ' COMMENT \'my comment\'',
Key::build($component)
);
}
public function testParseKeyExpressionWithOptionsError(): void
{
$parser = new Parser();
$component = Key::parse(
$parser,
$this->getTokensList(
'KEY `updated_tz_ind2` (()convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'GB\')))'
. ' COMMENT \'my comment\','
)
);
$this->assertEquals('KEY', $component->type);
$this->assertEquals('updated_tz_ind2', $component->name);
$this->assertEquals(new OptionsArray(
[]
), $component->options);
$t = new Token('convert_tz', Token::TYPE_KEYWORD, 33);
$t->position = 25;
$this->assertEquals([
new ParserException(
'Unexpected token.',
$t
),
], $parser->errors);
$expr = new Expression('(convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'GB\'))');
$expr->function = 'convert_tz';
$this->assertEquals('()(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'GB\')', $component->expr);
$this->assertSame([], $component->columns);
$this->assertSame(
'KEY `updated_tz_ind2` (()(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'GB\')) ',
Key::build($component)
);
}
public function testParseKeyOneExpressionWithOptions(): void
{
$parser = new Parser();
$component = Key::parse(
$parser,
$this->getTokensList(
'KEY `updated_tz_ind2`'
. ' ('
. '(convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'GB\')), '
. '(convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'FR\'))'
. ')'
. ' COMMENT \'my comment\','
)
);
$this->assertEquals('KEY', $component->type);
$this->assertEquals('updated_tz_ind2', $component->name);
$this->assertEquals(new OptionsArray(
[
4 => [
'name' => 'COMMENT',
'equals' => false,
'expr' => '\'my comment\'',
'value' => 'my comment',
],
]
), $component->options);
$this->assertSame([], $parser->errors);
$expr = new Expression(
'(convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'GB\')),'
. ' (convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'FR\'))'
);
$expr->function = 'convert_tz';
$this->assertEquals($expr, $component->expr);
$this->assertSame([], $component->columns);
$this->assertSame(
'KEY `updated_tz_ind2` ((convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'GB\')),'
. ' (convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'FR\'))'
. ') COMMENT \'my comment\'',
Key::build($component)
);
}
public function testParseKeyMultipleExpressionsWithOptions(): void
{
$parser = new Parser();
$component = Key::parse(
$parser,
$this->getTokensList(
'KEY `updated_tz_ind2`'
. ' ('
. '(convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'GB\')), '
. '(convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'FR\')), '
. '(convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'RU\'))'
. ')'
. ' COMMENT \'my comment\','
)
);
$this->assertEquals('KEY', $component->type);
$this->assertEquals('updated_tz_ind2', $component->name);
$this->assertEquals(new OptionsArray(
[
4 => [
'name' => 'COMMENT',
'equals' => false,
'expr' => '\'my comment\'',
'value' => 'my comment',
],
]
), $component->options);
$expr = new Expression(
'(convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'GB\')),'
. ' (convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'FR\')),'
. ' (convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'RU\'))'
);
$expr->function = 'convert_tz';
$this->assertEquals($expr, $component->expr);
$this->assertSame([], $component->columns);
$this->assertSame([], $parser->errors);
$this->assertSame(
'KEY `updated_tz_ind2` ((convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'GB\')),'
. ' (convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'FR\')),'
. ' (convert_tz(`cache_updated`,_utf8mb4\'GMT\',_utf8mb4\'RU\'))'
. ') COMMENT \'my comment\'',
Key::build($component)
);
}
}
@@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use PhpMyAdmin\SqlParser\Components\Limit;
use PhpMyAdmin\SqlParser\Tests\TestCase;
class LimitTest extends TestCase
{
public function testBuildWithoutOffset(): void
{
$component = new Limit(1);
$this->assertEquals(Limit::build($component), '0, 1');
}
public function testBuildWithOffset(): void
{
$component = new Limit(1, 2);
$this->assertEquals(Limit::build($component), '2, 1');
}
/**
* @dataProvider parseProvider
*/
public function testParse(string $test): void
{
$this->runParserTest($test);
}
/**
* @return string[][]
*/
public static function parseProvider(): array
{
return [
['parser/parseLimitErr1'],
['parser/parseLimitErr2'],
];
}
}
@@ -0,0 +1,73 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use PhpMyAdmin\SqlParser\Components\LockExpression;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Tests\TestCase;
class LockExpressionTest extends TestCase
{
public function testParse(): void
{
$component = LockExpression::parse(new Parser(), $this->getTokensList('table1 AS t1 READ LOCAL'));
$this->assertNotNull($component->table);
$this->assertEquals($component->table->table, 'table1');
$this->assertEquals($component->table->alias, 't1');
$this->assertEquals($component->type, 'READ LOCAL');
}
public function testParse2(): void
{
$component = LockExpression::parse(new Parser(), $this->getTokensList('table1 LOW_PRIORITY WRITE'));
$this->assertNotNull($component->table);
$this->assertEquals($component->table->table, 'table1');
$this->assertEquals($component->type, 'LOW_PRIORITY WRITE');
}
/**
* @dataProvider parseErrProvider
*/
public function testParseErr(string $expr, string $error): void
{
$parser = new Parser();
LockExpression::parse($parser, $this->getTokensList($expr));
$errors = $this->getErrorsAsArray($parser);
$this->assertEquals($errors[0][0], $error);
}
/**
* @return string[][]
*/
public static function parseErrProvider(): array
{
return [
[
'table1 AS t1',
'Unexpected end of LOCK expression.',
],
[
'table1 AS t1 READ WRITE',
'Unexpected keyword.',
],
[
'table1 AS t1 READ 2',
'Unexpected token.',
],
];
}
public function testBuild(): void
{
$component = [
LockExpression::parse(new Parser(), $this->getTokensList('table1 AS t1 READ LOCAL')),
LockExpression::parse(new Parser(), $this->getTokensList('table2 LOW_PRIORITY WRITE')),
];
$this->assertEquals(
LockExpression::build($component),
'table1 AS `t1` READ LOCAL, table2 LOW_PRIORITY WRITE'
);
}
}
@@ -0,0 +1,134 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use PhpMyAdmin\SqlParser\Components\OptionsArray;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Tests\TestCase;
class OptionsArrayTest extends TestCase
{
public function testParse(): void
{
$component = OptionsArray::parse(
new Parser(),
$this->getTokensList('A B = /*comment*/ (test) C'),
[
'A' => 1,
'B' => [
2,
'var',
],
'C' => 3,
]
);
$this->assertEquals(
[
1 => 'A',
2 => [
'name' => 'B',
'expr' => '(test)',
'value' => 'test',
'equals' => true,
],
3 => 'C',
],
$component->options
);
}
public function testParseExpr(): void
{
$component = OptionsArray::parse(
new Parser(),
$this->getTokensList('SUM = (3 + 5) RESULT = 8'),
[
'SUM' => [
1,
'expr',
['parenthesesDelimited' => true],
],
'RESULT' => [
2,
'var',
],
]
);
$this->assertEquals('(3 + 5)', (string) $component->has('SUM', true));
$this->assertEquals('8', $component->has('RESULT'));
}
public function testHas(): void
{
$component = OptionsArray::parse(
new Parser(),
$this->getTokensList('A B = /*comment*/ (test) C'),
[
'A' => 1,
'B' => [
2,
'var',
],
'C' => 3,
]
);
$this->assertTrue($component->has('A'));
$this->assertEquals('test', $component->has('B'));
$this->assertTrue($component->has('C'));
$this->assertFalse($component->has('D'));
}
public function testRemove(): void
{
/* Assertion 1 */
$component = new OptionsArray(['a', 'b', 'c']);
$this->assertTrue($component->remove('b'));
$this->assertFalse($component->remove('d'));
$this->assertEquals($component->options, [0 => 'a', 2 => 'c']);
/* Assertion 2 */
$component = OptionsArray::parse(
new Parser(),
$this->getTokensList('A B = /*comment*/ (test) C'),
[
'A' => 1,
'B' => [
2,
'var',
],
'C' => 3,
]
);
$this->assertEquals('test', $component->has('B'));
$component->remove('B');
$this->assertFalse($component->has('B'));
}
public function testMerge(): void
{
$component = new OptionsArray(['a']);
$component->merge(['b', 'c']);
$this->assertEquals($component->options, ['a', 'b', 'c']);
}
public function testBuild(): void
{
$component = new OptionsArray(
[
'ALL',
'SQL_CALC_FOUND_ROWS',
[
'name' => 'MAX_STATEMENT_TIME',
'value' => '42',
'equals' => true,
],
]
);
$this->assertEquals(
OptionsArray::build($component),
'ALL SQL_CALC_FOUND_ROWS MAX_STATEMENT_TIME=42'
);
}
}
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use PhpMyAdmin\SqlParser\Components\Expression;
use PhpMyAdmin\SqlParser\Components\OrderKeyword;
use PhpMyAdmin\SqlParser\Tests\TestCase;
class OrderKeywordTest extends TestCase
{
public function testBuild(): void
{
$this->assertEquals(
OrderKeyword::build(
[
new OrderKeyword(new Expression('a'), 'ASC'),
new OrderKeyword(new Expression('b'), 'DESC'),
]
),
'a ASC, b DESC'
);
}
}
@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use PhpMyAdmin\SqlParser\Components\ParameterDefinition;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Tests\TestCase;
class ParameterDefinitionTest extends TestCase
{
public function testParse(): void
{
$component = ParameterDefinition::parse(
new Parser(),
$this->getTokensList('(a INT, b INT')
);
$this->assertEquals('a', $component[0]->name);
$this->assertEquals('b', $component[1]->name);
}
public function testParseComplex(): void
{
$parser = new Parser();
$component = ParameterDefinition::parse(
$parser,
$this->getTokensList('CREATE DEFINER=`root`@`%` PROCEDURE `foo`( $bar int )')
);
$this->assertEquals('$bar', $component[0]->name);
}
}
@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use PhpMyAdmin\SqlParser\Components\PartitionDefinition;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Tests\TestCase;
class PartitionDefinitionTest extends TestCase
{
public function testParse(): void
{
$component = PartitionDefinition::parse(
new Parser(),
$this->getTokensList('PARTITION p0 VALUES LESS THAN(1990)')
);
$this->assertFalse($component->isSubpartition);
$this->assertEquals('p0', $component->name);
$this->assertEquals('LESS THAN', $component->type);
$this->assertEquals('(1990)', $component->expr->expr);
}
public function testParseNameWithUnderscore(): void
{
$component = PartitionDefinition::parse(
new Parser(),
$this->getTokensList('PARTITION 2017_12 VALUES LESS THAN (\'2018-01-01 00:00:00\') ENGINE = MyISAM')
);
$this->assertFalse($component->isSubpartition);
$this->assertEquals('2017_12', $component->name);
$this->assertEquals('LESS THAN', $component->type);
$this->assertEquals('(\'2018-01-01 00:00:00\')', $component->expr->expr);
}
}
@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use PhpMyAdmin\SqlParser\Components\Expression;
use PhpMyAdmin\SqlParser\Components\Reference;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Tests\TestCase;
class ReferenceTest extends TestCase
{
public function testParse(): void
{
$component = Reference::parse(new Parser(), $this->getTokensList('tbl (id)'));
$this->assertEquals('tbl', $component->table->table);
$this->assertEquals(['id'], $component->columns);
}
public function testBuild(): void
{
$component = new Reference(new Expression('`tbl`'), ['id']);
$this->assertEquals('`tbl` (`id`)', Reference::build($component));
}
}
@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\SqlParser\Tests\Components;
use PhpMyAdmin\SqlParser\Components\RenameOperation;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Tests\TestCase;
class RenameOperationTest extends TestCase
{
public function testBuild(): void
{
$component = RenameOperation::parse(new Parser(), $this->getTokensList('a TO b, c TO d'));
$this->assertEquals(RenameOperation::build($component), 'a TO b, c TO d');
}
}