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