packages/sql-semantics/tests/Unit/Core/Analysis/ValueReaderTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Core\Analysis;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\Medium;
9use PHPUnit\Framework\Attributes\UsesClass;
10use PHPUnit\Framework\TestCase;
11use SqlSemantics\Platform\PostgreSql\Dialect as PostgreSqlDialect;
12use SqlSemantics\Platform\Sqlite\Dialect as SqliteDialect;
13use WeakReference;
14
15#[CoversClass(\SqlSemantics\Core\Analysis\ValueReader::class)]
16#[UsesClass(\SqlSemantics\Core\Analysis\Analyzer::class)]
17#[UsesClass(\SqlSemantics\Core\AnalysisException::class)]
18#[UsesClass(\SqlSemantics\Facade\Semantics::class)]
19#[UsesClass(\SqlSemantics\Statement\Element::class)]
20#[UsesClass(\SqlSemantics\Statement\Statement::class)]
21#[UsesClass(\SqlSemantics\Statement\Writer::class)]
22#[UsesClass(\SqlSemantics\Statement\Assertion::class)]
23#[UsesClass(\SqlSemantics\Statement\ImmutableGraph::class)]
24#[UsesClass(\SqlSemantics\Statement\Comments::class)]
25#[UsesClass(\SqlSemantics\Core\Analysis\TriviaReader::class)]
26#[UsesClass(\SqlSemantics\Core\Analysis\SourceComments::class)]
27#[UsesClass(\SqlSemantics\Core\Ast\DialectParser::class)]
28#[UsesClass(\SqlSemantics\Platform\MySql\Platform::class)]
29#[UsesClass(\SqlSemantics\Platform\PostgreSql\Platform::class)]
30#[UsesClass(\SqlSemantics\Platform\Sqlite\Platform::class)]
31#[Medium]
32final class ValueReaderTest extends TestCase
33{
34 public function testReadReleasesParserObjectsAfterLowering(): void
35 {
36 $parser = SqliteDialect::Sqlite->platform()->parser();
37 $tree = $parser->parse('SELECT 123');
38 $treeReference = WeakReference::create($tree);
39 $tokenReference = WeakReference::create($tree->tokens()[1]);
40 $value = SqliteDialect::Sqlite->platform()->values($parser->version())->read($tree);
41 unset($tree);
42 self::assertNull($treeReference->get());
43 self::assertNull($tokenReference->get());
44 self::assertInstanceOf(\SqlSemantics\Statement\Command::class, $value);
45 self::assertSame('SELECT 123', (new \SqlSemantics\Statement\Statement($value))->toString());
46 }
47
48 public function testFromFileLoadsTheDatabasePackageVocabulary(): void
49 {
50 $parser = PostgreSqlDialect::PostgreSql->platform()->parser();
51 $value = PostgreSqlDialect::PostgreSql->platform()->values($parser->version())->read($parser->parse('VALUES (42)'));
52 self::assertInstanceOf(\SqlSemantics\Statement\Command::class, $value);
53 self::assertSame('VALUES( 42 )', (new \SqlSemantics\Statement\Statement($value))->toString());
54 }
55
56 public function testStatementGivesTheOuterCommentsToTheStatementAndTheInnerOnesToValues(): void
57 {
58 $parser = SqliteDialect::Sqlite->platform()->parser();
59 $statement = SqliteDialect::Sqlite->platform()->values($parser->version())->statement($parser->parse('/* lead */ SELECT /* a */ 1 -- end'));
60 self::assertSame(['/* lead */'], $statement->comments->before(\SqlSemantics\Statement\Statement::BEFORE));
61 self::assertSame(['-- end'], $statement->comments->before(\SqlSemantics\Statement\Statement::AFTER));
62 self::assertSame('/* lead */ SELECT /* a */ 1 -- end', $statement->toString());
63 self::assertSame('SELECT /* a */ 1', \SqlSemantics\Statement\Writer::render($statement->command));
64 }
65
66 public function testLowerKeepsACommentInTheOutermostValueWhoseSymbolItPrecedes(): void
67 {
68 $parser = SqliteDialect::Sqlite->platform()->parser();
69 $tree = $parser->parse('SELECT foo /* a */ FROM items');
70 $reader = SqliteDialect::Sqlite->platform()->values($parser->version());
71 $command = $reader->lower($tree, (new \SqlSemantics\Core\Analysis\TriviaReader())->read($tree), true);
72 self::assertInstanceOf(\SqlSemantics\Statement\Model\Sqlite\Value\EcmdWithCmdxSemi_b7577a8f::class, $command);
73 $select = $command->cmdx;
74 self::assertInstanceOf(\SqlSemantics\Statement\Model\Sqlite\Value\OneselectWithSelectDistinctSelcollistFromWhereOptGroupbyOptHavingOptOrderbyOptLimitOpt_218e0475::class, $select);
75 self::assertSame([3], $select->comments->positions());
76 self::assertSame(['/* a */'], $select->comments->before(3));
77 self::assertSame('SELECT foo /* a */ FROM items', \SqlSemantics\Statement\Writer::render($command));
78 self::assertSame('SELECT foo FROM items', \SqlSemantics\Statement\Writer::render($command->withCmdx($select->withComments(new \SqlSemantics\Statement\Comments()))));
79 }
80}
81