use super::{
AccessControlSyntax, AggregateCallSyntax, CallSyntax, CaretOperator, Casing,
ColumnDefinitionSyntax, CommentSyntax, ConstraintSyntax, CreateTableClauseSyntax,
DoubleAmpersand, ExistenceGuards, ExpressionSyntax, FeatureSet, GroupingSyntax,
IdentifierSyntax, IndexAlterSyntax, JoinSyntax, Keyword, KeywordOperators, KeywordSet,
MaintenanceSyntax, MutationSyntax, NullOrdering, NumericLiteralSyntax, OperatorSyntax,
ParameterSyntax, PipeOperator, PredicateSyntax, QueryTailSyntax, RESERVED_BARE_ALIAS,
RESERVED_COLUMN_NAME, RESERVED_FUNCTION_NAME, RESERVED_TYPE_NAME, STANDARD_BYTE_CLASSES,
STANDARD_IDENTIFIER_QUOTES, SelectSyntax, SessionVariableSyntax, ShowSyntax, StatementDdlGates,
StringFuncForms, StringLiteralSyntax, TableExpressionSyntax, TableFactorSyntax, TargetSpelling,
TypeNameSyntax, UtilitySyntax,
};
use crate::precedence::{STANDARD_BINDING_POWERS, STANDARD_SET_OPERATION_BINDING_POWERS};
pub const SNOWFLAKE_QUALIFY_RESERVATION: KeywordSet =
KeywordSet::from_keywords(&[Keyword::Qualify]);
pub const SNOWFLAKE_TABLE_OPERATOR_RESERVATION: KeywordSet =
KeywordSet::from_keywords(&[Keyword::Pivot, Keyword::Unpivot, Keyword::MatchRecognize]);
pub const SNOWFLAKE_RESERVED_COLUMN_NAME: KeywordSet = RESERVED_COLUMN_NAME
.union(SNOWFLAKE_QUALIFY_RESERVATION)
.union(SNOWFLAKE_TABLE_OPERATOR_RESERVATION);
pub const SNOWFLAKE_RESERVED_FUNCTION_NAME: KeywordSet =
RESERVED_FUNCTION_NAME.union(SNOWFLAKE_QUALIFY_RESERVATION);
pub const SNOWFLAKE_RESERVED_TYPE_NAME: KeywordSet =
RESERVED_TYPE_NAME.union(SNOWFLAKE_QUALIFY_RESERVATION);
pub const SNOWFLAKE_RESERVED_BARE_ALIAS: KeywordSet =
RESERVED_BARE_ALIAS.union(SNOWFLAKE_QUALIFY_RESERVATION);
impl SelectSyntax {
pub const SNOWFLAKE: Self = Self {
qualify: true,
connect_by_clause: true,
..SelectSyntax::ANSI
};
}
impl QueryTailSyntax {
pub const SNOWFLAKE: Self = Self {
..QueryTailSyntax::ANSI
};
}
impl TableFactorSyntax {
pub const SNOWFLAKE: Self = Self {
pivot_value_sources: true,
match_recognize: true,
..TableFactorSyntax::ANSI
};
}
impl GroupingSyntax {
pub const SNOWFLAKE: Self = Self {
group_by_all: true,
..GroupingSyntax::ANSI
};
}
impl UtilitySyntax {
pub const SNOWFLAKE: Self = Self {
copy_into: true,
stage_references: true,
..UtilitySyntax::ANSI
};
}
impl ExpressionSyntax {
pub const SNOWFLAKE: Self = Self {
semi_structured_access: true,
..ExpressionSyntax::ANSI
};
}
impl FeatureSet {
pub const SNOWFLAKE: Self = Self {
identifier_casing: Casing::Upper,
identifier_quotes: STANDARD_IDENTIFIER_QUOTES,
default_null_ordering: NullOrdering::NullsLast,
reserved_column_name: SNOWFLAKE_RESERVED_COLUMN_NAME,
reserved_function_name: SNOWFLAKE_RESERVED_FUNCTION_NAME,
reserved_type_name: SNOWFLAKE_RESERVED_TYPE_NAME,
reserved_bare_alias: SNOWFLAKE_RESERVED_BARE_ALIAS,
reserved_as_label: KeywordSet::EMPTY,
catalog_qualified_names: true,
byte_classes: STANDARD_BYTE_CLASSES,
binding_powers: STANDARD_BINDING_POWERS,
set_operation_powers: STANDARD_SET_OPERATION_BINDING_POWERS,
string_literals: StringLiteralSyntax::ANSI,
numeric_literals: NumericLiteralSyntax::ANSI,
parameters: ParameterSyntax::ANSI,
session_variables: SessionVariableSyntax::ANSI,
identifier_syntax: IdentifierSyntax::ANSI,
table_expressions: TableExpressionSyntax {
table_json_path: true,
..TableExpressionSyntax::ANSI
},
join_syntax: JoinSyntax::ANSI,
table_factor_syntax: TableFactorSyntax::SNOWFLAKE,
expression_syntax: ExpressionSyntax::SNOWFLAKE,
operator_syntax: OperatorSyntax::ANSI,
call_syntax: CallSyntax::ANSI,
string_func_forms: StringFuncForms::ANSI,
aggregate_call_syntax: AggregateCallSyntax::ANSI,
predicate_syntax: PredicateSyntax::ANSI,
pipe_operator: PipeOperator::StringConcat,
double_ampersand: DoubleAmpersand::Unsupported,
keyword_operators: KeywordOperators::Unsupported,
caret_operator: CaretOperator::Unsupported,
hash_bitwise_xor: false,
comment_syntax: CommentSyntax::ANSI,
mutation_syntax: MutationSyntax::ANSI,
statement_ddl_gates: StatementDdlGates::ANSI,
create_table_clause_syntax: CreateTableClauseSyntax::ANSI,
column_definition_syntax: ColumnDefinitionSyntax::ANSI,
constraint_syntax: ConstraintSyntax::ANSI,
index_alter_syntax: IndexAlterSyntax::ANSI,
existence_guards: ExistenceGuards::ANSI,
select_syntax: SelectSyntax::SNOWFLAKE,
query_tail_syntax: QueryTailSyntax::SNOWFLAKE,
grouping_syntax: GroupingSyntax::SNOWFLAKE,
utility_syntax: UtilitySyntax::SNOWFLAKE,
show_syntax: ShowSyntax::ANSI,
maintenance_syntax: MaintenanceSyntax::ANSI,
access_control_syntax: AccessControlSyntax::ANSI,
type_name_syntax: TypeNameSyntax::ANSI,
target_spelling: TargetSpelling::Ansi,
};
}
pub const SNOWFLAKE: FeatureSet = FeatureSet::SNOWFLAKE;
const _: () = assert!(FeatureSet::SNOWFLAKE.is_lexically_consistent());
const _: () = assert!(FeatureSet::SNOWFLAKE.has_satisfied_feature_dependencies());
const _: () = assert!(FeatureSet::SNOWFLAKE.has_no_grammar_conflict());
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn snowflake_is_ansi_plus_the_four_gates_and_the_qualify_reservation() {
let ansi = FeatureSet::ANSI;
let sf = FeatureSet::SNOWFLAKE;
assert_eq!(sf.select_syntax, SelectSyntax::SNOWFLAKE);
assert_ne!(sf.select_syntax, ansi.select_syntax);
assert_eq!(sf.expression_syntax, ExpressionSyntax::SNOWFLAKE);
assert_ne!(sf.expression_syntax, ansi.expression_syntax);
assert_eq!(sf.reserved_column_name, SNOWFLAKE_RESERVED_COLUMN_NAME);
assert_ne!(sf.reserved_column_name, ansi.reserved_column_name);
assert_eq!(sf.reserved_function_name, SNOWFLAKE_RESERVED_FUNCTION_NAME);
assert_ne!(sf.reserved_function_name, ansi.reserved_function_name);
assert_eq!(sf.reserved_type_name, SNOWFLAKE_RESERVED_TYPE_NAME);
assert_ne!(sf.reserved_type_name, ansi.reserved_type_name);
assert_eq!(sf.reserved_bare_alias, SNOWFLAKE_RESERVED_BARE_ALIAS);
assert_ne!(sf.reserved_bare_alias, ansi.reserved_bare_alias);
assert_eq!(
sf.reserved_column_name
.difference(SNOWFLAKE_QUALIFY_RESERVATION)
.difference(SNOWFLAKE_TABLE_OPERATOR_RESERVATION),
ansi.reserved_column_name,
);
assert!(sf.reserved_column_name.contains(Keyword::Qualify));
assert!(sf.reserved_bare_alias.contains(Keyword::Qualify));
for kw in [Keyword::Pivot, Keyword::Unpivot, Keyword::MatchRecognize] {
assert!(sf.reserved_column_name.contains(kw));
assert!(!sf.reserved_function_name.contains(kw));
assert!(!sf.reserved_type_name.contains(kw));
assert!(!sf.reserved_bare_alias.contains(kw));
}
assert_eq!(
sf.reserved_function_name,
RESERVED_FUNCTION_NAME.union(SNOWFLAKE_QUALIFY_RESERVATION),
);
assert_eq!(
sf.reserved_type_name,
RESERVED_TYPE_NAME.union(SNOWFLAKE_QUALIFY_RESERVATION),
);
assert_eq!(
sf.reserved_bare_alias,
RESERVED_BARE_ALIAS.union(SNOWFLAKE_QUALIFY_RESERVATION),
);
assert_eq!(sf.reserved_as_label, KeywordSet::EMPTY);
assert_eq!(sf.identifier_casing, Casing::Upper);
assert_eq!(sf.identifier_casing, ansi.identifier_casing);
assert_eq!(sf.identifier_quotes, ansi.identifier_quotes);
assert!(!sf.parameters.named_colon);
assert_eq!(sf.string_literals, ansi.string_literals);
assert_eq!(sf.numeric_literals, ansi.numeric_literals);
assert_eq!(sf.parameters, ansi.parameters);
assert_eq!(sf.session_variables, ansi.session_variables);
assert_eq!(sf.identifier_syntax, ansi.identifier_syntax);
assert_eq!(
TableExpressionSyntax {
table_json_path: false,
..sf.table_expressions
},
ansi.table_expressions,
);
assert!(sf.table_expressions.table_json_path);
assert_eq!(sf.operator_syntax, ansi.operator_syntax);
assert_eq!(sf.call_syntax, ansi.call_syntax);
assert_eq!(sf.predicate_syntax, ansi.predicate_syntax);
assert_eq!(sf.mutation_syntax, ansi.mutation_syntax);
assert_eq!(sf.statement_ddl_gates, ansi.statement_ddl_gates);
assert_eq!(
sf.create_table_clause_syntax,
ansi.create_table_clause_syntax
);
assert_eq!(sf.column_definition_syntax, ansi.column_definition_syntax);
assert_eq!(sf.constraint_syntax, ansi.constraint_syntax);
assert_eq!(sf.index_alter_syntax, ansi.index_alter_syntax);
assert_eq!(sf.existence_guards, ansi.existence_guards);
assert_eq!(sf.utility_syntax, UtilitySyntax::SNOWFLAKE);
assert_ne!(sf.utility_syntax, ansi.utility_syntax);
assert!(sf.utility_syntax.copy_into);
assert!(sf.utility_syntax.stage_references);
assert_eq!(
UtilitySyntax {
copy_into: false,
stage_references: false,
..sf.utility_syntax
},
ansi.utility_syntax,
);
assert_eq!(sf.type_name_syntax, ansi.type_name_syntax);
assert_eq!(sf.byte_classes, ansi.byte_classes);
assert_eq!(sf.binding_powers, ansi.binding_powers);
assert_eq!(sf.target_spelling, ansi.target_spelling);
}
#[test]
fn snowflake_enables_exactly_the_four_staged_gates() {
let ansi = FeatureSet::ANSI;
let sf = FeatureSet::SNOWFLAKE;
assert!(sf.expression_syntax.semi_structured_access);
assert!(!ansi.expression_syntax.semi_structured_access);
assert!(sf.select_syntax.qualify && !ansi.select_syntax.qualify);
assert!(sf.select_syntax.connect_by_clause && !ansi.select_syntax.connect_by_clause);
assert!(sf.grouping_syntax.group_by_all && !ansi.grouping_syntax.group_by_all);
assert!(!sf.grouping_syntax.order_by_all);
assert_eq!(
sf.grouping_syntax.order_by_all,
ansi.grouping_syntax.order_by_all
);
assert_eq!(
SelectSyntax {
qualify: false,
connect_by_clause: false,
..sf.select_syntax
},
ansi.select_syntax,
);
assert_eq!(
GroupingSyntax {
group_by_all: false,
..sf.grouping_syntax
},
ansi.grouping_syntax,
);
assert_eq!(
ExpressionSyntax {
semi_structured_access: false,
..sf.expression_syntax
},
ansi.expression_syntax,
);
}
#[test]
fn snowflake_is_lexically_consistent_and_dependency_clean() {
let sf = FeatureSet::SNOWFLAKE;
assert_eq!(sf.lexical_conflict(), None);
assert!(sf.is_lexically_consistent());
assert_eq!(sf.feature_dependencies(), None);
assert!(sf.has_satisfied_feature_dependencies());
assert_eq!(sf.grammar_conflict(), None);
assert!(sf.has_no_grammar_conflict());
}
}