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