squonk_ast/dialect/hive.rs
1// SPDX-License-Identifier: MIT
2// Copyright (c) 2026 Moderately AI Inc.
3
4//! The Hive / HiveQL dialect preset (ANSI-derived, deliberately conservative).
5//!
6//! Apache Hive's HiveQL diverges widely across its type, function, and statement surface, and
7//! — unlike the five shipped oracle-compared presets — this workspace has **no Hive oracle**,
8//! so over-acceptance cannot be measured. Conservatism is therefore the honesty bar: this
9//! preset derives from [`FeatureSet::ANSI`], the strict standard baseline, and enables only the
10//! Hive surface that already has a modelled, tested parser gate and clear documentary evidence
11//! — in the headline case the flag's *own* doc names Hive as a motivating dialect. Every other
12//! axis keeps its ANSI value; a reader can predict from this module exactly what Hive accepts
13//! beyond the standard, and unsupported Hive syntax is a clean reject routed to a focused
14//! follow-up ticket, never a silent over-accept.
15//!
16//! # What this preset adds over ANSI
17//!
18//! Two grammar gates carry the headline Hive surface:
19//!
20//! - [`sided_semi_anti_join`](JoinSyntax::sided_semi_anti_join) — the
21//! `{LEFT|RIGHT} {SEMI|ANTI} JOIN` sided semi-/anti-join spelling, whose flag doc names
22//! Spark/Hive/Databricks as the motivating family. Hive is the dialect that *originated* the
23//! `LEFT SEMI JOIN`; the Databricks preset already turned this flag on, and Hive is the
24//! second engine preset to enable it. The leading `LEFT`/`RIGHT` is already a reserved join
25//! side, so no reserved-word interplay is needed (the preceding factor's alias can never
26//! swallow it). See the over-acceptance deferral note below.
27//! - [`lateral_view_clause`](SelectSyntax::lateral_view_clause) — the
28//! `LATERAL VIEW [OUTER] explode(col) t [AS a, b]` table-generating clause Hive
29//! originated (LanguageManual LateralView: `fromClause: FROM baseTable (lateralView)*`).
30//! The derived-table `LATERAL` factor stays off, so `LATERAL` leads only this clause
31//! under the preset. See the `AS`-optional over-acceptance deferral note below.
32//!
33//! # The two lexical facts over ANSI
34//!
35//! - **Backtick identifier quoting.** Hive quotes identifiers with the backtick `` `name` ``
36//! alone (its default `hive.support.quoted.identifiers=column` mode), and its `"…"` and `'…'`
37//! are *both* string literals — HiveQL string literals may be written with single or double
38//! quotes. So [`HIVE_IDENTIFIER_QUOTES`] lists only the backtick (unlike the
39//! SQLite/Databricks/MSSQL bracket-or-double-quote sets, and unlike ANSI's `"…"`), and
40//! [`double_quoted_strings`](StringLiteralSyntax::double_quoted_strings) is correspondingly
41//! **on** so `"x"` lexes as a string, never an identifier — exactly the MySQL default
42//! (`ANSI_QUOTES` off) lexis, and the same shape the BigQuery preset ships. The two facts are
43//! coupled: `"` has a single claimant (the string scanner) precisely because it is absent
44//! from the quote set, the [`DoubleQuoteStringVersusIdentifier`](super::LexicalConflict)
45//! hazard the `const` assert below rules out. The backtick likewise has a single claimant —
46//! no enabled expression grammar lexes a backtick.
47//! - **Case folding.** Hive resolves unquoted identifiers case-insensitively (its metastore
48//! lowercases table and column names), so [`identifier_casing`](FeatureSet::identifier_casing)
49//! is [`Casing::Lower`] — the value the [`Casing`] doc prescribes for the "case-preserving
50//! storage, case-insensitive comparison" model it describes for MySQL/T-SQL columns. Hive is
51//! uniformly case-insensitive (it lacks even the case-sensitive-table split that paragraph
52//! flags as the single-fold known limitation), so the fit is exact. The interned text still
53//! renders exactly as written; the fold is identity-only and never affects acceptance.
54//!
55//! # Deliberately deferred (conservative reject)
56//!
57//! - **`RIGHT`/`ANTI` sided joins.** Classic Hive documents only `LEFT SEMI JOIN` (and later
58//! `LEFT ANTI JOIN`); the atomic [`sided_semi_anti_join`](JoinSyntax::sided_semi_anti_join) flag also admits the `RIGHT`-sided
59//! spelling and the `ANTI` flavour across both sides — a known conservative-direction
60//! over-acceptance a future side-refinement (or a Hive oracle) would tighten. This mirrors
61//! the deferral the Databricks preset recorded for the same atomic flag; captured on the
62//! owning ticket rather than split into a narrower gate that no measured boundary yet
63//! justifies.
64//! - **`AS`-less lateral-view column aliases.** Hive's grammar requires the `AS` before a
65//! lateral view's column aliases; Spark's spells it `AS?`, and the one atomic
66//! [`lateral_view_clause`](SelectSyntax::lateral_view_clause) gate accepts the wider
67//! Spark bound — a known conservative-direction over-acceptance for this preset, the
68//! same class as the sided-join deferral above (see the [`LateralView`](crate::ast::LateralView)
69//! acceptance-bound doc); captured on the owning ticket.
70//!
71//! Everything else Hive (the `STRUCT`/`ARRAY<…>`/`MAP<…>` complex type surface,
72//! `TRANSFORM`/`MAP`/`REDUCE` script operators, `DISTRIBUTE BY`/`SORT BY`/`CLUSTER BY` clauses,
73//! `TABLESAMPLE` bucketing, backslash string escapes, …) has no modelled gate and is a clean
74//! reject routed to follow-up tickets, never a silent over-accept.
75
76use super::{
77 AccessControlSyntax, AggregateCallSyntax, CallSyntax, CaretOperator, Casing,
78 ColumnDefinitionSyntax, CommentSyntax, ConstraintSyntax, CreateTableClauseSyntax,
79 DoubleAmpersand, ExistenceGuards, ExpressionSyntax, FeatureSet, GroupingSyntax,
80 IdentifierQuote, IdentifierSyntax, IndexAlterSyntax, JoinSyntax, KeywordOperators, KeywordSet,
81 MaintenanceSyntax, MutationSyntax, NullOrdering, NumericLiteralSyntax, OperatorSyntax,
82 ParameterSyntax, PipeOperator, PredicateSyntax, QueryTailSyntax, RESERVED_BARE_ALIAS,
83 RESERVED_COLUMN_NAME, RESERVED_FUNCTION_NAME, RESERVED_TYPE_NAME, STANDARD_BYTE_CLASSES,
84 SelectSyntax, SessionVariableSyntax, ShowSyntax, StatementDdlGates, StringFuncForms,
85 StringLiteralSyntax, TableExpressionSyntax, TableFactorSyntax, TargetSpelling,
86 TransactionSyntax, TypeNameSyntax, UtilitySyntax, ViewSequenceClauseSyntax,
87};
88use crate::precedence::{STANDARD_BINDING_POWERS, STANDARD_SET_OPERATION_BINDING_POWERS};
89
90/// Hive identifier quoting: the backtick `` `…` `` alone. Hive spells a quoted identifier
91/// `` `a` `` (its default `hive.support.quoted.identifiers=column` mode); its `"a"` and `'a'`
92/// are *both* string constants, so `"` is deliberately absent here (and
93/// [`StringLiteralSyntax::HIVE`] turns `double_quoted_strings` on so `"` unambiguously lexes a
94/// string) — the same backtick-only lexis MySQL uses under its default `ANSI_QUOTES`-off mode.
95pub const HIVE_IDENTIFIER_QUOTES: &[IdentifierQuote] = &[IdentifierQuote::Symmetric('`')];
96
97impl StringLiteralSyntax {
98 /// Hive string surface: the ANSI baseline plus `"…"` double-quoted string constants (HiveQL
99 /// string literals may be written with single *or* double quotes, reserving the backtick
100 /// for identifiers). Enabling this is what lets [`HIVE_IDENTIFIER_QUOTES`] drop `"` from the
101 /// quote set without stranding the byte. Every other string knob is conservatively ANSI —
102 /// Hive's backslash escape sequences have no Hive-citing flag doc or oracle here and are
103 /// deferred rather than guessed at (`backslash_escapes` stays off).
104 pub const HIVE: Self = Self {
105 double_quoted_strings: true,
106 escape_strings: false,
107 dollar_quoted_strings: false,
108 national_strings: false,
109 backslash_escapes: false,
110 unicode_strings: false,
111 bit_string_literals: false,
112 blob_literals: false,
113 charset_introducers: false,
114 same_line_adjacent_concat: false,
115 };
116}
117
118impl TableExpressionSyntax {
119 /// Hive table-expression surface: the ANSI baseline plus the sided
120 /// `{LEFT|RIGHT} {SEMI|ANTI} JOIN` family, whose flag doc names Hive as a motivating
121 /// dialect (Hive originated `LEFT SEMI JOIN`). The side-less DuckDB spelling
122 /// (`semi_anti_join`) stays off — it is a different engine family and needs `SEMI`/`ANTI`
123 /// bare-alias reservation modelling not done here. Every other table knob is conservatively
124 /// ANSI.
125 pub const HIVE: Self = Self {
126 only: false,
127 table_sample: false,
128 parenthesized_joins: true,
129 table_alias_column_lists: true,
130 join_using_alias: false,
131 index_hints: false,
132 table_hints: false,
133 partition_selection: false,
134 base_table_alias_column_lists: true,
135 string_literal_aliases: false,
136 aliased_parenthesized_join: true,
137 bare_table_alias_is_bare_label: false,
138 table_version: false,
139 table_json_path: false,
140 indexed_by: false,
141 prefix_colon_alias: false,
142 };
143}
144
145impl JoinSyntax {
146 /// The `HIVE` preset for join syntax.
147 pub const HIVE: Self = Self {
148 sided_semi_anti_join: true,
149 stacked_join_qualifiers: true,
150 full_outer_join: true,
151 natural_cross_join: false,
152 straight_join: false,
153 asof_join: false,
154 positional_join: false,
155 semi_anti_join: false,
156 apply_join: false,
157 recursive_search_cycle: false,
158 recursive_union_rejects_order_limit: false,
159 recursive_using_key: false,
160 };
161}
162
163impl TableFactorSyntax {
164 /// The `HIVE` preset for table factor syntax.
165 pub const HIVE: Self = Self {
166 lateral: false,
167 table_functions: false,
168 rows_from: false,
169 unnest: false,
170 unnest_with_offset: false,
171 table_function_ordinality: false,
172 special_function_table_source: true,
173 pivot: false,
174 unpivot: false,
175 show_ref: false,
176 from_values: false,
177 json_table: false,
178 xml_table: false,
179 table_expr_factor: false,
180 pivot_value_sources: false,
181 match_recognize: false,
182 open_json: false,
183 };
184}
185
186impl SelectSyntax {
187 /// Hive SELECT surface: the ANSI baseline plus the `LATERAL VIEW` table-generating
188 /// clause Hive originated (LanguageManual LateralView). The derived-table `LATERAL`
189 /// factor ([`TableFactorSyntax::HIVE`]) stays off, so `LATERAL` leads only this
190 /// clause under the preset. Every other SELECT knob is conservatively ANSI.
191 pub const HIVE: Self = Self {
192 lateral_view_clause: true,
193 distinct_on: false,
194 select_into: false,
195 empty_target_list: false,
196 qualify: false,
197 alias_string_literals: false,
198 bare_alias_string_literals: false,
199 union_by_name: false,
200 wildcard_modifiers: false,
201 wildcard_replace: false,
202 intersect_all: true,
203 except_all: true,
204 qualified_wildcard_alias: false,
205 from_first: false,
206 explicit_table: true,
207 parenthesized_query_operands: true,
208 values_rows_require_equal_arity: false,
209 values_row_constructor: true,
210 as_alias_rejects_reserved: false,
211 trailing_comma: false,
212 prefix_colon_alias: false,
213 connect_by_clause: false,
214 };
215}
216
217impl FeatureSet {
218 /// Hive / HiveQL as ANSI-derived dialect data (see the module docs for the full derivation
219 /// rationale and the conservatism bar).
220 pub const HIVE: Self = Self {
221 // Hive resolves unquoted identifiers case-insensitively (its metastore lowercases table
222 // and column names); `Casing::Lower` is the exact fit (Hive lacks even the
223 // case-sensitive-table split the `Casing` known-limitation paragraph flags). Identity
224 // only — the interned text still renders exactly as written, so this never affects
225 // acceptance.
226 identifier_casing: Casing::Lower,
227 // The lexical delta over ANSI: backtick-only identifier quoting (with `"` handed to the
228 // string scanner via `double_quoted_strings` below).
229 identifier_quotes: HIVE_IDENTIFIER_QUOTES,
230 default_null_ordering: NullOrdering::NullsLast,
231 // No reserved-set delta over ANSI — this conservative preset adds no keyword
232 // reservation (the sided-join gate rides the already-reserved LEFT/RIGHT join sides).
233 reserved_column_name: RESERVED_COLUMN_NAME,
234 reserved_function_name: RESERVED_FUNCTION_NAME,
235 reserved_type_name: RESERVED_TYPE_NAME,
236 reserved_bare_alias: RESERVED_BARE_ALIAS,
237 reserved_as_label: KeywordSet::EMPTY,
238 catalog_qualified_names: true,
239 byte_classes: STANDARD_BYTE_CLASSES,
240 binding_powers: STANDARD_BINDING_POWERS,
241 set_operation_powers: STANDARD_SET_OPERATION_BINDING_POWERS,
242 // `"…"` double-quoted strings (the coupled half of the backtick-only identifier lexis).
243 string_literals: StringLiteralSyntax::HIVE,
244 numeric_literals: NumericLiteralSyntax::ANSI,
245 parameters: ParameterSyntax::ANSI,
246 session_variables: SessionVariableSyntax::ANSI,
247 identifier_syntax: IdentifierSyntax::ANSI,
248 // The sided `{LEFT|RIGHT} {SEMI|ANTI} JOIN` family — the capstone this preset exposes.
249 table_expressions: TableExpressionSyntax::HIVE,
250 join_syntax: JoinSyntax::HIVE,
251 table_factor_syntax: TableFactorSyntax::HIVE,
252 expression_syntax: ExpressionSyntax::ANSI,
253 operator_syntax: OperatorSyntax::ANSI,
254 call_syntax: CallSyntax::ANSI,
255 string_func_forms: StringFuncForms::ANSI,
256 aggregate_call_syntax: AggregateCallSyntax::ANSI,
257 predicate_syntax: PredicateSyntax::ANSI,
258 pipe_operator: PipeOperator::StringConcat,
259 double_ampersand: DoubleAmpersand::Unsupported,
260 keyword_operators: KeywordOperators::Unsupported,
261 caret_operator: CaretOperator::Unsupported,
262 hash_bitwise_xor: false,
263 comment_syntax: CommentSyntax::ANSI,
264 mutation_syntax: MutationSyntax::ANSI,
265 statement_ddl_gates: StatementDdlGates::ANSI,
266 view_sequence_clause_syntax: ViewSequenceClauseSyntax::ANSI,
267 create_table_clause_syntax: CreateTableClauseSyntax::ANSI,
268 column_definition_syntax: ColumnDefinitionSyntax::ANSI,
269 constraint_syntax: ConstraintSyntax::ANSI,
270 index_alter_syntax: IndexAlterSyntax::ANSI,
271 existence_guards: ExistenceGuards::ANSI,
272 // The `LATERAL VIEW` table-generating clause — the second capstone this preset
273 // exposes; every other SELECT knob is conservatively ANSI.
274 select_syntax: SelectSyntax::HIVE,
275 query_tail_syntax: QueryTailSyntax::ANSI,
276 grouping_syntax: GroupingSyntax::ANSI,
277 utility_syntax: UtilitySyntax::ANSI,
278 transaction_syntax: TransactionSyntax::ANSI,
279 show_syntax: ShowSyntax::ANSI,
280 maintenance_syntax: MaintenanceSyntax::ANSI,
281 access_control_syntax: AccessControlSyntax::ANSI,
282 type_name_syntax: TypeNameSyntax::ANSI,
283 // No Hive-specific Tier-1 output spelling yet; render the portable ANSI canonical type
284 // names (a `TargetSpelling::Hive` is render work a later ticket owns).
285 target_spelling: TargetSpelling::Ansi,
286 };
287}
288
289/// Prefer [`FeatureSet::HIVE`] for struct update.
290pub const HIVE: FeatureSet = FeatureSet::HIVE;
291
292// Compile-time proof the Hive preset claims no shared tokenizer trigger twice. Beyond ANSI it
293// adds one lexical trigger — the backtick identifier opener — with a single claimant (no
294// enabled expression grammar lexes a backtick), and it hands `"` to the string scanner
295// (`double_quoted_strings` on) *while dropping `"` from the identifier quote set*, so `"` also
296// keeps a single claimant. The sided-join gate is contextual keyword grammar with no tokenizer
297// trigger. Kept as a ratchet so a future Hive delta that *does* add a contending trigger (e.g.
298// re-listing `"` as an identifier quote) fails the build here.
299const _: () = assert!(FeatureSet::HIVE.is_lexically_consistent());
300// The two sibling self-consistency registries are ratcheted the same way, so the
301// parse-entry `debug_assert!` folds all three to dead code for this preset: no refinement
302// flag rides an unset base, and no two features contend for one parser-position head.
303const _: () = assert!(FeatureSet::HIVE.has_satisfied_feature_dependencies());
304const _: () = assert!(FeatureSet::HIVE.has_no_grammar_conflict());
305
306#[cfg(test)]
307mod tests {
308 use super::*;
309
310 #[test]
311 fn hive_is_ansi_plus_the_two_gates_and_two_lexical_facts() {
312 // The preset is ANSI with a documented, closed set of divergent axes: the two lexical
313 // facts (case-folding, backtick-only quoting coupled with double-quoted strings), the
314 // enabled table-expression gate, and the enabled SELECT gate. Asserting the whole rest
315 // equals ANSI keeps the "ANSI-derived, every delta documented" claim honest against a
316 // future stray edit. Bind to locals so the const reads are not flagged by clippy's
317 // `assertions_on_constants`.
318 let ansi = FeatureSet::ANSI;
319 let hive = FeatureSet::HIVE;
320
321 // The two lexical facts.
322 assert_eq!(hive.identifier_casing, Casing::Lower);
323 assert_ne!(hive.identifier_casing, ansi.identifier_casing);
324 assert_eq!(hive.identifier_quotes, HIVE_IDENTIFIER_QUOTES);
325 assert_ne!(hive.identifier_quotes, ansi.identifier_quotes);
326 // The coupling: `"` is dropped from the quote set and handed to the string scanner.
327 assert!(hive.string_literals.double_quoted_strings);
328 assert!(
329 !hive
330 .identifier_quotes
331 .iter()
332 .any(|quote| quote.open() == '"')
333 );
334 // Backtick is the sole identifier quote; no bracket (unlike SQLite/MSSQL) and no `"`.
335 assert!(
336 hive.identifier_quotes
337 .iter()
338 .any(|quote| quote.open() == '`')
339 );
340 assert_eq!(hive.identifier_quotes.len(), 1);
341
342 // The one divergent string sub-preset (the double-quote coupling).
343 assert_eq!(hive.string_literals, StringLiteralSyntax::HIVE);
344 assert_ne!(hive.string_literals, ansi.string_literals);
345 // The divergent table-expression sub-preset.
346 assert_eq!(hive.table_expressions, TableExpressionSyntax::HIVE);
347 assert_eq!(hive.join_syntax, JoinSyntax::HIVE);
348 assert_ne!(hive.join_syntax, ansi.join_syntax);
349 // The divergent SELECT sub-preset (the LATERAL VIEW clause).
350 assert_eq!(hive.select_syntax, SelectSyntax::HIVE);
351 assert_ne!(hive.select_syntax, ansi.select_syntax);
352
353 // No reserved-set delta: every position is inherited verbatim from ANSI.
354 assert_eq!(hive.reserved_column_name, ansi.reserved_column_name);
355 assert_eq!(hive.reserved_function_name, ansi.reserved_function_name);
356 assert_eq!(hive.reserved_type_name, ansi.reserved_type_name);
357 assert_eq!(hive.reserved_bare_alias, ansi.reserved_bare_alias);
358 assert_eq!(hive.reserved_as_label, KeywordSet::EMPTY);
359
360 // Everything else is inherited verbatim from ANSI.
361 assert_eq!(hive.numeric_literals, ansi.numeric_literals);
362 assert_eq!(hive.parameters, ansi.parameters);
363 assert_eq!(hive.expression_syntax, ansi.expression_syntax);
364 assert_eq!(hive.session_variables, ansi.session_variables);
365 assert_eq!(hive.identifier_syntax, ansi.identifier_syntax);
366 assert_eq!(hive.operator_syntax, ansi.operator_syntax);
367 assert_eq!(hive.call_syntax, ansi.call_syntax);
368 assert_eq!(hive.predicate_syntax, ansi.predicate_syntax);
369 assert_eq!(hive.mutation_syntax, ansi.mutation_syntax);
370 assert_eq!(hive.statement_ddl_gates, ansi.statement_ddl_gates);
371 assert_eq!(
372 hive.create_table_clause_syntax,
373 ansi.create_table_clause_syntax
374 );
375 assert_eq!(hive.column_definition_syntax, ansi.column_definition_syntax);
376 assert_eq!(hive.constraint_syntax, ansi.constraint_syntax);
377 assert_eq!(hive.index_alter_syntax, ansi.index_alter_syntax);
378 assert_eq!(hive.existence_guards, ansi.existence_guards);
379 assert_eq!(hive.utility_syntax, ansi.utility_syntax);
380 assert_eq!(hive.type_name_syntax, ansi.type_name_syntax);
381 assert_eq!(hive.byte_classes, ansi.byte_classes);
382 assert_eq!(hive.binding_powers, ansi.binding_powers);
383 assert_eq!(hive.target_spelling, ansi.target_spelling);
384 assert_eq!(hive.default_null_ordering, ansi.default_null_ordering);
385 }
386
387 #[test]
388 fn hive_enables_exactly_the_two_gates_and_double_quote_string() {
389 // The capstones: the sided semi-/anti-join family, the LATERAL VIEW clause, and
390 // double-quoted strings are on, and each is off in the ANSI base it derives from.
391 // Forcing the flags back off recovers the ANSI sub-presets verbatim.
392 let ansi = FeatureSet::ANSI;
393 let hive = FeatureSet::HIVE;
394
395 assert!(hive.join_syntax.sided_semi_anti_join);
396 assert!(!ansi.join_syntax.sided_semi_anti_join);
397 // The side-less DuckDB spelling stays off (a different engine family).
398 assert!(!hive.join_syntax.semi_anti_join);
399 // The LATERAL VIEW clause; the derived-table LATERAL factor stays off, so
400 // `LATERAL` leads only the view clause under this preset.
401 assert!(hive.select_syntax.lateral_view_clause && !ansi.select_syntax.lateral_view_clause);
402 assert!(!hive.table_factor_syntax.lateral);
403 assert!(
404 hive.string_literals.double_quoted_strings
405 && !ansi.string_literals.double_quoted_strings
406 );
407 // The backtick opener is the lexical gate (an identifier-quote delta, not a bool).
408 assert!(
409 hive.identifier_quotes
410 .iter()
411 .any(|quote| quote.open() == '`')
412 );
413 assert!(
414 !ansi
415 .identifier_quotes
416 .iter()
417 .any(|quote| quote.open() == '`')
418 );
419
420 assert_eq!(
421 JoinSyntax {
422 sided_semi_anti_join: false,
423 ..hive.join_syntax
424 },
425 ansi.join_syntax,
426 );
427 assert_eq!(
428 SelectSyntax {
429 lateral_view_clause: false,
430 ..hive.select_syntax
431 },
432 ansi.select_syntax,
433 );
434 assert_eq!(
435 StringLiteralSyntax {
436 double_quoted_strings: false,
437 ..hive.string_literals
438 },
439 ansi.string_literals,
440 );
441 }
442
443 #[test]
444 fn hive_is_lexically_consistent_and_dependency_clean() {
445 // Both self-consistency registries must be clean: the backtick quote has a single
446 // claimant, `"` is handed to the string scanner (dropped from the quote set), and the
447 // sided-join gate rides no unset base flag.
448 let hive = FeatureSet::HIVE;
449 assert_eq!(hive.lexical_conflict(), None);
450 assert!(hive.is_lexically_consistent());
451 assert_eq!(hive.feature_dependencies(), None);
452 assert!(hive.has_satisfied_feature_dependencies());
453 assert_eq!(hive.grammar_conflict(), None);
454 assert!(hive.has_no_grammar_conflict());
455 }
456 #[test]
457 fn hive_closed_delta_axes_match_documented_set() {
458 crate::dialect::closed_delta::assert_closed_delta(
459 &FeatureSet::ANSI,
460 &FeatureSet::HIVE,
461 &[
462 "identifier_casing",
463 "identifier_quotes",
464 "string_literals",
465 "join_syntax",
466 "select_syntax",
467 ],
468 );
469 }
470}