packages/ztd-query-sqlite/src/Rewrite/Returning/SqliteReturningProjectionParser.php
1<?php
2
3declare(strict_types=1);
4
5namespace ZtdQuery\Platform\Sqlite\Rewrite\Returning;
6
7use ZtdQuery\Exception\UnsupportedSqlException;
8use ZtdQuery\Platform\Sqlite\Sql\Returning\ReturningItemParser;
9use ZtdQuery\Rewrite\ReturningProjection;
10use ZtdQuery\Sql\SqlTokenStream;
11
12/**
13 * Extracts RETURNING expressions and their output column names.
14 */
15final class SqliteReturningProjectionParser
16{
17 /**
18 * Parses the supplied SQL into its supported structured representation.
19 * @throws UnsupportedSqlException
20 */
21 public function parse(string $sql): ?ReturningProjection
22 {
23 $clause = SqlTokenStream::tokenize($sql, \ZtdQuery\Platform\Sqlite\Sql\SqliteLexerProfile::create())->topLevelClause(['RETURNING']);
24 if ($clause === null) {
25 return null;
26 }
27
28 $items = [];
29 foreach (SqlTokenStream::tokenize(rtrim($clause, "; \t\n\r\0\x0B"), \ZtdQuery\Platform\Sqlite\Sql\SqliteLexerProfile::create())->splitTopLevel() as $expression) {
30 $item = (new ReturningItemParser())->parseItem($expression);
31 if ($item === null) {
32 throw new UnsupportedSqlException(
33 $sql,
34 'RETURNING supports columns, qualified columns, aliases, and wildcard projections',
35 );
36 }
37 $items[] = $item;
38 }
39
40 if ($items === []) {
41 throw new UnsupportedSqlException($sql, 'RETURNING requires a projection');
42 }
43
44 return ReturningProjection::fromItems($items);
45 }
46
47}
48