packages/ztd-query-core/tests/Fake/FakeSqlLexerProfiles.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Fake;
6
7use ZtdQuery\Exception\InvalidDefinitionException;
8use ZtdQuery\Sql\Profile\SqlCommentProfile;
9use ZtdQuery\Sql\Profile\SqlParameterProfile;
10use ZtdQuery\Sql\Profile\SqlQuoteProfile;
11use ZtdQuery\Sql\Profile\SqlSymbolProfile;
12use ZtdQuery\Sql\SqlLexerProfile;
13
14/**
15 * Lexical configurations used to exercise the neutral scanner and its readers.
16 */
17final class FakeSqlLexerProfiles
18{
19    /**
20     * @param list<string> $lineCommentPrefixes
21     * @param list<string> $whitespaceDelimitedLineCommentPrefixes
22     * @param array<string, string> $blockCommentPairs
23     * @param array<string, string> $stringQuotePairs
24     * @param array<string, string> $identifierQuotePairs
25     * @param array<string, list<string>> $namedParameterSeparators
26     * @param array<string, string> $namedParameterSuffixPatterns
27     * @param array<string, list<string>> $namedParameterForbiddenPredecessors
28     * @param list<string> $backslashEscapedStringPrefixes
29     * @param list<string> $positionalParameterPatterns
30     * @param array{string, string}|null $bracketPair
31     * @param array{string, string} $nestingPair
32     */
33    public static function custom(
34        array $lineCommentPrefixes = ['--'],
35        array $whitespaceDelimitedLineCommentPrefixes = [],
36        array $blockCommentPairs = ['/*' => '*/'],
37        array $stringQuotePairs = ["'" => "'"],
38        array $identifierQuotePairs = ['"' => '"'],
39        array $namedParameterSeparators = [],
40        array $namedParameterSuffixPatterns = [],
41        array $namedParameterForbiddenPredecessors = [],
42        array $backslashEscapedStringPrefixes = [],
43        array $positionalParameterPatterns = [],
44        ?string $dollarQuoteDelimiterPattern = null,
45        string $numericLiteralPattern = '/^[0-9]+/',
46        string $identifierStartPattern = '/^[_A-Za-z]$/',
47        string $identifierPartPattern = '/^[_A-Za-z0-9]$/',
48        ?array $bracketPair = null,
49        array $nestingPair = ['(', ')'],
50        string $statementDelimiter = ';',
51        string $listDelimiter = ',',
52        bool $nestedBlockComments = false,
53        bool $backslashEscapedStrings = false,
54    ): SqlLexerProfile {
55        return new SqlLexerProfile(
56            lineCommentPrefixes: $lineCommentPrefixes,
57            whitespaceDelimitedLineCommentPrefixes: $whitespaceDelimitedLineCommentPrefixes,
58            blockCommentPairs: $blockCommentPairs,
59            stringQuotePairs: $stringQuotePairs,
60            identifierQuotePairs: $identifierQuotePairs,
61            namedParameterSeparators: $namedParameterSeparators,
62            namedParameterSuffixPatterns: $namedParameterSuffixPatterns,
63            namedParameterForbiddenPredecessors: $namedParameterForbiddenPredecessors,
64            backslashEscapedStringPrefixes: $backslashEscapedStringPrefixes,
65            positionalParameterPatterns: $positionalParameterPatterns,
66            dollarQuoteDelimiterPattern: $dollarQuoteDelimiterPattern,
67            numericLiteralPattern: $numericLiteralPattern,
68            identifierStartPattern: $identifierStartPattern,
69            identifierPartPattern: $identifierPartPattern,
70            bracketPair: $bracketPair,
71            nestingPair: $nestingPair,
72            statementDelimiter: $statementDelimiter,
73            listDelimiter: $listDelimiter,
74            nestedBlockComments: $nestedBlockComments,
75            backslashEscapedStrings: $backslashEscapedStrings,
76        );
77    }
78
79    /**
80     * Provides ordinary quoted SQL with nested comments and brackets.
81     */
82    public static function standard(): SqlLexerProfile
83    {
84        return new SqlLexerProfile(
85            lineCommentPrefixes: ['--'],
86            whitespaceDelimitedLineCommentPrefixes: [],
87            blockCommentPairs: ['/*' => '*/'],
88            stringQuotePairs: ["'" => "'"],
89            identifierQuotePairs: ['"' => '"'],
90            namedParameterSeparators: [],
91            namedParameterSuffixPatterns: [],
92            namedParameterForbiddenPredecessors: [],
93            backslashEscapedStringPrefixes: [],
94            positionalParameterPatterns: [],
95            dollarQuoteDelimiterPattern: null,
96            numericLiteralPattern: '/^(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)(?:[eE][+-]?[0-9]+)?/',
97            identifierStartPattern: '/^[_A-Za-z\x80-\xFF]$/',
98            identifierPartPattern: '/^[_A-Za-z0-9\x80-\xFF]$/',
99            bracketPair: ['[', ']'],
100            nestingPair: ['(', ')'],
101            statementDelimiter: ';',
102            listDelimiter: ',',
103            nestedBlockComments: true,
104            backslashEscapedStrings: false,
105        );
106    }
107
108    /**
109     * Exercises all configurable lexical capabilities in one profile.
110     */
111    public static function allCapabilities(): SqlLexerProfile
112    {
113        return new SqlLexerProfile(
114            lineCommentPrefixes: ['--', '#'],
115            whitespaceDelimitedLineCommentPrefixes: [],
116            blockCommentPairs: ['/*' => '*/'],
117            stringQuotePairs: ["'" => "'"],
118            identifierQuotePairs: ['"' => '"', '`' => '`', '[' => ']'],
119            namedParameterSeparators: [':' => ['::']],
120            namedParameterSuffixPatterns: [':' => '/^\([^ \t\n\r\0\x0B)]*\)/'],
121            namedParameterForbiddenPredecessors: [':' => [':']],
122            backslashEscapedStringPrefixes: ['E', 'e'],
123            positionalParameterPatterns: ['/^\$[0-9]+/', '/^\?[0-9]*/'],
124            dollarQuoteDelimiterPattern: '/^\$(?:[_A-Za-z][_A-Za-z0-9]*)?\$/',
125            numericLiteralPattern: '/^(?:0[xX]_?[0-9A-Fa-f](?:_?[0-9A-Fa-f])*|(?:[0-9](?:_?[0-9])*)(?:\.(?:[0-9](?:_?[0-9])*)?)?(?:[eE][+-]?[0-9](?:_?[0-9])*)?)/',
126            identifierStartPattern: '/^[_A-Za-z\x80-\xFF]$/',
127            identifierPartPattern: '/^[_A-Za-z0-9$\x80-\xFF]$/',
128            bracketPair: ['[', ']'],
129            nestingPair: ['(', ')'],
130            statementDelimiter: ';',
131            listDelimiter: ',',
132            nestedBlockComments: true,
133            backslashEscapedStrings: true,
134        );
135    }
136    /**
137     * How a dialect writes a comment, built around whatever one test is about.
138     *
139     * @param list<string> $lineCommentPrefixes
140     * @param list<string> $whitespaceDelimitedLineCommentPrefixes
141     * @param array<string, string> $blockCommentPairs
142     *
143     * @throws InvalidDefinitionException When the lexical data is not something a scanner could use
144     */
145    public static function comments(
146        array $lineCommentPrefixes = ['--'],
147        array $whitespaceDelimitedLineCommentPrefixes = [],
148        array $blockCommentPairs = ['/*' => '*/'],
149        bool $nestedBlockComments = false,
150    ): SqlCommentProfile {
151        return new SqlCommentProfile(
152            lineCommentPrefixes: $lineCommentPrefixes,
153            whitespaceDelimitedLineCommentPrefixes: $whitespaceDelimitedLineCommentPrefixes,
154            blockCommentPairs: $blockCommentPairs,
155            nestedBlockComments: $nestedBlockComments,
156        );
157    }
158
159    /**
160     * How a dialect quotes, built around whatever one test is about.
161     *
162     * @param array<string, string> $stringQuotePairs
163     * @param array<string, string> $identifierQuotePairs
164     * @param list<string> $backslashEscapedStringPrefixes
165     *
166     * @throws InvalidDefinitionException When the lexical data is not something a scanner could use
167     */
168    public static function quotes(
169        array $stringQuotePairs = ["'" => "'"],
170        array $identifierQuotePairs = ['"' => '"'],
171        ?string $dollarQuoteDelimiterPattern = null,
172        array $backslashEscapedStringPrefixes = [],
173        bool $backslashEscapedStrings = false,
174    ): SqlQuoteProfile {
175        return new SqlQuoteProfile(
176            stringQuotePairs: $stringQuotePairs,
177            identifierQuotePairs: $identifierQuotePairs,
178            dollarQuoteDelimiterPattern: $dollarQuoteDelimiterPattern,
179            backslashEscapedStringPrefixes: $backslashEscapedStringPrefixes,
180            backslashEscapedStrings: $backslashEscapedStrings,
181        );
182    }
183
184    /**
185     * How a dialect writes a placeholder, built around whatever one test is about.
186     *
187     * @param list<string> $positionalParameterPatterns
188     * @param array<string, list<string>> $namedParameterSeparators
189     * @param array<string, string> $namedParameterSuffixPatterns
190     * @param array<string, list<string>> $namedParameterForbiddenPredecessors
191     *
192     * @throws InvalidDefinitionException When the lexical data is not something a scanner could use
193     */
194    public static function parameters(
195        array $positionalParameterPatterns = [],
196        array $namedParameterSeparators = [],
197        array $namedParameterSuffixPatterns = [],
198        array $namedParameterForbiddenPredecessors = [],
199    ): SqlParameterProfile {
200        return new SqlParameterProfile(
201            positionalParameterPatterns: $positionalParameterPatterns,
202            namedParameterSeparators: $namedParameterSeparators,
203            namedParameterSuffixPatterns: $namedParameterSuffixPatterns,
204            namedParameterForbiddenPredecessors: $namedParameterForbiddenPredecessors,
205        );
206    }
207
208    /**
209     * How a dialect spells what is written plainly, built around whatever one test is about.
210     *
211     * @param array{string, string}|null $bracketPair
212     * @param array{string, string} $nestingPair
213     *
214     * @throws InvalidDefinitionException When the lexical data is not something a scanner could use
215     */
216    public static function symbols(
217        string $numericLiteralPattern = '/^[0-9]+/',
218        string $identifierStartPattern = '/^[_A-Za-z]$/',
219        string $identifierPartPattern = '/^[_A-Za-z0-9]$/',
220        ?array $bracketPair = null,
221        array $nestingPair = ['(', ')'],
222        string $statementDelimiter = ';',
223        string $listDelimiter = ',',
224    ): SqlSymbolProfile {
225        return new SqlSymbolProfile(
226            numericLiteralPattern: $numericLiteralPattern,
227            identifierStartPattern: $identifierStartPattern,
228            identifierPartPattern: $identifierPartPattern,
229            bracketPair: $bracketPair,
230            nestingPair: $nestingPair,
231            statementDelimiter: $statementDelimiter,
232            listDelimiter: $listDelimiter,
233        );
234    }
235}
236