1use super::{
39 AccessControlSyntax, AggregateCallSyntax, CallSyntax, CaretOperator, Casing,
40 ColumnDefinitionSyntax, CommentSyntax, ConstraintSyntax, CreateTableClauseSyntax,
41 DoubleAmpersand, ExistenceGuards, ExpressionSyntax, FeatureSet, GroupingSyntax,
42 IdentifierQuote, IdentifierSyntax, IndexAlterSyntax, JoinSyntax, KeywordOperators, KeywordSet,
43 MaintenanceSyntax, MutationSyntax, NullOrdering, NumericLiteralSyntax, OperatorSyntax,
44 ParameterSyntax, PipeOperator, PredicateSyntax, QueryTailSyntax, RESERVED_BARE_ALIAS,
45 RESERVED_COLUMN_NAME, RESERVED_FUNCTION_NAME, RESERVED_TYPE_NAME, STANDARD_BYTE_CLASSES,
46 SelectSyntax, SessionVariableSyntax, ShowSyntax, StatementDdlGates, StringFuncForms,
47 StringLiteralSyntax, TableExpressionSyntax, TableFactorSyntax, TargetSpelling,
48 TransactionSyntax, TypeNameSyntax, UtilitySyntax, ViewSequenceClauseSyntax,
49};
50use crate::precedence::{STANDARD_BINDING_POWERS, STANDARD_SET_OPERATION_BINDING_POWERS};
51
52pub const CLICKHOUSE_IDENTIFIER_QUOTES: &[IdentifierQuote] = &[
59 IdentifierQuote::Symmetric('"'),
60 IdentifierQuote::Symmetric('`'),
61];
62
63impl SelectSyntax {
64 pub const CLICKHOUSE: Self = Self {
71 distinct_on: false,
72 select_into: false,
73 empty_target_list: false,
74 qualify: false,
75 alias_string_literals: false,
76 bare_alias_string_literals: false,
77 union_by_name: false,
78 wildcard_modifiers: false,
79 wildcard_replace: false,
80 intersect_all: true,
81 except_all: true,
82 qualified_wildcard_alias: false,
83 from_first: false,
84 explicit_table: true,
85 parenthesized_query_operands: true,
86 values_rows_require_equal_arity: false,
87 values_row_constructor: true,
88 as_alias_rejects_reserved: false,
89 trailing_comma: false,
90 prefix_colon_alias: false,
91 lateral_view_clause: false,
92 connect_by_clause: false,
93 };
94}
95
96impl QueryTailSyntax {
97 pub const CLICKHOUSE: Self = Self {
99 limit_by_clause: true,
100 settings_clause: true,
101 format_clause: true,
102 fetch_first: true,
103 limit_offset_comma: false,
104 locking_clauses: false,
105 key_lock_strengths: false,
106 stacked_locking_clauses: false,
107 using_sample: false,
108 leading_offset: true,
109 limit_expressions: true,
110 limit_percent: false,
111 with_ties_requires_order_by: false,
112 pipe_syntax: false,
113 for_xml_json_clause: false,
114 };
115}
116
117impl GroupingSyntax {
118 pub const CLICKHOUSE: Self = Self {
120 grouping_sets: true,
121 with_rollup: false,
122 order_by_using: false,
123 group_by_all: false,
124 group_by_set_quantifier: false,
125 order_by_all: false,
126 };
127}
128
129impl TypeNameSyntax {
130 pub const CLICKHOUSE: Self = Self {
137 nullable_type: true,
138 low_cardinality_type: true,
139 fixed_string_type: true,
140 datetime64_type: true,
141 nested_type: true,
142 bit_width_integer_names: true,
143 extended_scalar_type_names: false,
144 enum_type: false,
145 set_type: false,
146 numeric_modifiers: false,
147 integer_display_width: false,
148 composite_types: false,
149 varchar_requires_length: false,
150 zoned_temporal_types: true,
151 empty_type_parens: false,
152 character_set_annotation: false,
153 signed_type_modifier: false,
154 liberal_type_names: false,
155 string_type_modifiers: false,
156 angle_bracket_types: false,
157 };
158}
159
160impl FeatureSet {
161 pub const CLICKHOUSE: Self = Self {
164 identifier_casing: Casing::Preserve,
167 identifier_quotes: CLICKHOUSE_IDENTIFIER_QUOTES,
169 default_null_ordering: NullOrdering::NullsLast,
170 reserved_column_name: RESERVED_COLUMN_NAME,
174 reserved_function_name: RESERVED_FUNCTION_NAME,
175 reserved_type_name: RESERVED_TYPE_NAME,
176 reserved_bare_alias: RESERVED_BARE_ALIAS,
177 reserved_as_label: KeywordSet::EMPTY,
178 catalog_qualified_names: true,
179 byte_classes: STANDARD_BYTE_CLASSES,
180 binding_powers: STANDARD_BINDING_POWERS,
181 set_operation_powers: STANDARD_SET_OPERATION_BINDING_POWERS,
182 string_literals: StringLiteralSyntax::ANSI,
186 numeric_literals: NumericLiteralSyntax::ANSI,
187 parameters: ParameterSyntax::ANSI,
188 session_variables: SessionVariableSyntax::ANSI,
189 identifier_syntax: IdentifierSyntax::ANSI,
190 table_expressions: TableExpressionSyntax::ANSI,
191 join_syntax: JoinSyntax::ANSI,
192 table_factor_syntax: TableFactorSyntax::ANSI,
193 expression_syntax: ExpressionSyntax::ANSI,
194 operator_syntax: OperatorSyntax::ANSI,
195 call_syntax: CallSyntax::ANSI,
196 string_func_forms: StringFuncForms::ANSI,
197 aggregate_call_syntax: AggregateCallSyntax::ANSI,
198 predicate_syntax: PredicateSyntax::ANSI,
199 pipe_operator: PipeOperator::StringConcat,
200 double_ampersand: DoubleAmpersand::Unsupported,
201 keyword_operators: KeywordOperators::Unsupported,
202 caret_operator: CaretOperator::Unsupported,
203 hash_bitwise_xor: false,
204 comment_syntax: CommentSyntax::ANSI,
205 mutation_syntax: MutationSyntax::ANSI,
206 statement_ddl_gates: StatementDdlGates::ANSI,
207 view_sequence_clause_syntax: ViewSequenceClauseSyntax::ANSI,
208 create_table_clause_syntax: CreateTableClauseSyntax::ANSI,
209 column_definition_syntax: ColumnDefinitionSyntax::ANSI,
210 constraint_syntax: ConstraintSyntax::ANSI,
211 index_alter_syntax: IndexAlterSyntax::ANSI,
212 existence_guards: ExistenceGuards::ANSI,
213 select_syntax: SelectSyntax::CLICKHOUSE,
216 query_tail_syntax: QueryTailSyntax::CLICKHOUSE,
217 grouping_syntax: GroupingSyntax::CLICKHOUSE,
218 utility_syntax: UtilitySyntax::ANSI,
219 transaction_syntax: TransactionSyntax::ANSI,
220 show_syntax: ShowSyntax::ANSI,
221 maintenance_syntax: MaintenanceSyntax::ANSI,
222 access_control_syntax: AccessControlSyntax::ANSI,
223 type_name_syntax: TypeNameSyntax::CLICKHOUSE,
224 target_spelling: TargetSpelling::Ansi,
228 };
229}
230
231pub const CLICKHOUSE: FeatureSet = FeatureSet::CLICKHOUSE;
233
234const _: () = assert!(FeatureSet::CLICKHOUSE.is_lexically_consistent());
242const _: () = assert!(FeatureSet::CLICKHOUSE.has_satisfied_feature_dependencies());
246const _: () = assert!(FeatureSet::CLICKHOUSE.has_no_grammar_conflict());
247
248#[cfg(test)]
249mod tests {
250 use super::*;
251
252 #[test]
253 fn clickhouse_is_ansi_plus_the_nine_gates_and_two_lexical_facts() {
254 let ansi = FeatureSet::ANSI;
261 let ch = FeatureSet::CLICKHOUSE;
262
263 assert_eq!(ch.identifier_casing, Casing::Preserve);
265 assert_ne!(ch.identifier_casing, ansi.identifier_casing);
266 assert_eq!(ch.identifier_quotes, CLICKHOUSE_IDENTIFIER_QUOTES);
267 assert_ne!(ch.identifier_quotes, ansi.identifier_quotes);
268 assert!(!ch.string_literals.double_quoted_strings);
271
272 assert_eq!(ch.query_tail_syntax, QueryTailSyntax::CLICKHOUSE);
274 assert_ne!(ch.query_tail_syntax, ansi.query_tail_syntax);
275 assert_eq!(ch.type_name_syntax, TypeNameSyntax::CLICKHOUSE);
276 assert_ne!(ch.type_name_syntax, ansi.type_name_syntax);
277
278 assert_eq!(ch.string_literals, ansi.string_literals);
280 assert_eq!(ch.numeric_literals, ansi.numeric_literals);
281 assert_eq!(ch.parameters, ansi.parameters);
282 assert_eq!(ch.session_variables, ansi.session_variables);
283 assert_eq!(ch.identifier_syntax, ansi.identifier_syntax);
284 assert_eq!(ch.table_expressions, ansi.table_expressions);
285 assert_eq!(ch.expression_syntax, ansi.expression_syntax);
286 assert_eq!(ch.operator_syntax, ansi.operator_syntax);
287 assert_eq!(ch.call_syntax, ansi.call_syntax);
288 assert_eq!(ch.predicate_syntax, ansi.predicate_syntax);
289 assert_eq!(ch.mutation_syntax, ansi.mutation_syntax);
290 assert_eq!(ch.statement_ddl_gates, ansi.statement_ddl_gates);
291 assert_eq!(
292 ch.create_table_clause_syntax,
293 ansi.create_table_clause_syntax
294 );
295 assert_eq!(ch.column_definition_syntax, ansi.column_definition_syntax);
296 assert_eq!(ch.constraint_syntax, ansi.constraint_syntax);
297 assert_eq!(ch.index_alter_syntax, ansi.index_alter_syntax);
298 assert_eq!(ch.existence_guards, ansi.existence_guards);
299 assert_eq!(ch.utility_syntax, ansi.utility_syntax);
300 assert_eq!(ch.reserved_column_name, ansi.reserved_column_name);
301 assert_eq!(ch.reserved_function_name, ansi.reserved_function_name);
302 assert_eq!(ch.reserved_type_name, ansi.reserved_type_name);
303 assert_eq!(ch.reserved_bare_alias, ansi.reserved_bare_alias);
304 assert_eq!(ch.byte_classes, ansi.byte_classes);
305 assert_eq!(ch.binding_powers, ansi.binding_powers);
306 assert_eq!(ch.target_spelling, ansi.target_spelling);
307 }
308
309 #[test]
310 fn clickhouse_enables_exactly_the_nine_staged_gates() {
311 let ansi = FeatureSet::ANSI;
315 let ch = FeatureSet::CLICKHOUSE;
316
317 assert!(ch.query_tail_syntax.limit_by_clause && !ansi.query_tail_syntax.limit_by_clause);
318 assert!(ch.query_tail_syntax.settings_clause && !ansi.query_tail_syntax.settings_clause);
319 assert!(ch.query_tail_syntax.format_clause && !ansi.query_tail_syntax.format_clause);
320
321 assert!(ch.type_name_syntax.nullable_type && !ansi.type_name_syntax.nullable_type);
322 assert!(
323 ch.type_name_syntax.low_cardinality_type && !ansi.type_name_syntax.low_cardinality_type
324 );
325 assert!(ch.type_name_syntax.fixed_string_type && !ansi.type_name_syntax.fixed_string_type);
326 assert!(ch.type_name_syntax.datetime64_type && !ansi.type_name_syntax.datetime64_type);
327 assert!(ch.type_name_syntax.nested_type && !ansi.type_name_syntax.nested_type);
328 assert!(
329 ch.type_name_syntax.bit_width_integer_names
330 && !ansi.type_name_syntax.bit_width_integer_names
331 );
332
333 assert_eq!(
336 QueryTailSyntax {
337 limit_by_clause: false,
338 settings_clause: false,
339 format_clause: false,
340 ..ch.query_tail_syntax
341 },
342 ansi.query_tail_syntax,
343 );
344 assert_eq!(
345 TypeNameSyntax {
346 nullable_type: false,
347 low_cardinality_type: false,
348 fixed_string_type: false,
349 datetime64_type: false,
350 nested_type: false,
351 bit_width_integer_names: false,
352 ..ch.type_name_syntax
353 },
354 ansi.type_name_syntax,
355 );
356 }
357
358 #[test]
359 fn clickhouse_is_lexically_consistent_and_dependency_clean() {
360 let ch = FeatureSet::CLICKHOUSE;
364 assert_eq!(ch.lexical_conflict(), None);
365 assert!(ch.is_lexically_consistent());
366 assert_eq!(ch.feature_dependencies(), None);
367 assert!(ch.has_satisfied_feature_dependencies());
368 assert_eq!(ch.grammar_conflict(), None);
369 assert!(ch.has_no_grammar_conflict());
370 }
371 #[test]
372 fn clickhouse_closed_delta_axes_match_documented_set() {
373 crate::dialect::closed_delta::assert_closed_delta(
374 &FeatureSet::ANSI,
375 &FeatureSet::CLICKHOUSE,
376 &[
377 "identifier_casing",
378 "identifier_quotes",
379 "query_tail_syntax",
380 "type_name_syntax",
381 ],
382 );
383 }
384}