use super::keyword::Keyword;
use super::{
AccessControlSyntax, AggregateCallSyntax, CallSyntax, CaretOperator, Casing,
ColumnDefinitionSyntax, CommentSyntax, ConstraintSyntax, CreateTableClauseSyntax,
DoubleAmpersand, ExistenceGuards, ExpressionSyntax, FeatureSet, GroupingSyntax,
IdentifierQuote, IdentifierSyntax, IndexAlterSyntax, JoinSyntax, KeywordOperators, KeywordSet,
MaintenanceSyntax, MutationSyntax, NullOrdering, NumericLiteralSyntax, OperatorSyntax,
ParameterSyntax, PipeOperator, PredicateSyntax, QueryTailSyntax, SQLITE_BYTE_CLASSES,
SelectSyntax, SessionVariableSyntax, ShowSyntax, StatementDdlGates, StringFuncForms,
StringLiteralSyntax, TableExpressionSyntax, TableFactorSyntax, TargetSpelling,
TransactionSyntax, TypeNameSyntax, UtilitySyntax, ViewSequenceClauseSyntax,
};
use crate::precedence::{
Assoc, BindingPower, BindingPowerTable, STANDARD_SET_OPERATION_BINDING_POWERS,
};
pub const SQLITE_IDENTIFIER_QUOTES: &[IdentifierQuote] = &[
IdentifierQuote::Symmetric('"'),
IdentifierQuote::Symmetric('`'),
IdentifierQuote::Asymmetric {
open: '[',
close: ']',
},
];
const SQLITE_STRUCTURAL_RESERVED: &[Keyword] = &[
Keyword::Add,
Keyword::All,
Keyword::Alter,
Keyword::And,
Keyword::As,
Keyword::Between,
Keyword::Case,
Keyword::Check,
Keyword::Collate,
Keyword::Commit,
Keyword::Constraint,
Keyword::Create,
Keyword::Default,
Keyword::Deferrable,
Keyword::Delete,
Keyword::Distinct,
Keyword::Drop,
Keyword::Else,
Keyword::Escape,
Keyword::Except,
Keyword::Exists,
Keyword::Foreign,
Keyword::From,
Keyword::Group,
Keyword::Having,
Keyword::In,
Keyword::Index,
Keyword::Insert,
Keyword::Intersect,
Keyword::Into,
Keyword::Is,
Keyword::Join,
Keyword::Limit,
Keyword::Not,
Keyword::Null,
Keyword::On,
Keyword::Or,
Keyword::Order,
Keyword::Primary,
Keyword::References,
Keyword::Select,
Keyword::Set,
Keyword::Table,
Keyword::Then,
Keyword::To,
Keyword::Transaction,
Keyword::Union,
Keyword::Unique,
Keyword::Update,
Keyword::Using,
Keyword::Values,
Keyword::When,
Keyword::Where,
];
const SQLITE_JOIN_KEYWORDS: &[Keyword] = &[
Keyword::Cross,
Keyword::Inner,
Keyword::Left,
Keyword::Natural,
Keyword::Outer,
Keyword::Right,
Keyword::Full,
];
const SQLITE_RESIDUAL_NAME_AND_BARE: &[Keyword] = &[Keyword::Returning, Keyword::Nothing];
const SQLITE_RESIDUAL_NAME_ONLY: &[Keyword] = &[Keyword::Isnull, Keyword::Notnull];
pub const SQLITE_RESERVED_COLUMN_NAME: KeywordSet =
KeywordSet::from_keywords(SQLITE_STRUCTURAL_RESERVED)
.union(KeywordSet::from_keywords(SQLITE_RESIDUAL_NAME_AND_BARE))
.union(KeywordSet::from_keywords(SQLITE_RESIDUAL_NAME_ONLY));
pub const SQLITE_RESERVED_FUNCTION_NAME: KeywordSet = SQLITE_RESERVED_COLUMN_NAME;
pub const SQLITE_RESERVED_TYPE_NAME: KeywordSet =
SQLITE_RESERVED_COLUMN_NAME.union(KeywordSet::from_keywords(SQLITE_JOIN_KEYWORDS));
pub const SQLITE_RESERVED_BARE_ALIAS: KeywordSet =
KeywordSet::from_keywords(SQLITE_STRUCTURAL_RESERVED)
.union(KeywordSet::from_keywords(SQLITE_JOIN_KEYWORDS))
.union(KeywordSet::from_keywords(SQLITE_RESIDUAL_NAME_AND_BARE));
pub const SQLITE_RESERVED_AS_LABEL: KeywordSet = SQLITE_RESERVED_COLUMN_NAME;
impl StringLiteralSyntax {
pub const SQLITE: Self = Self {
escape_strings: false,
dollar_quoted_strings: false,
national_strings: false,
double_quoted_strings: false,
backslash_escapes: false,
unicode_strings: false,
bit_string_literals: false,
blob_literals: true,
charset_introducers: false,
same_line_adjacent_concat: false,
};
}
impl NumericLiteralSyntax {
pub const SQLITE: Self = Self {
hex_integers: true,
octal_integers: false,
binary_integers: false,
underscore_separators: true,
money_literals: false,
radix_leading_underscore: false,
reject_trailing_junk: true,
};
}
impl CommentSyntax {
pub const SQLITE: Self = Self {
nested_block_comments: false,
unterminated_block_comment_at_eof: true,
line_comment_hash: false,
line_comment_ends_at_carriage_return: false,
versioned_comments: None,
};
}
impl ParameterSyntax {
pub const SQLITE: Self = Self {
positional_dollar: false,
positional_dollar_large: false,
anonymous_question: true,
named_colon: true,
named_at: true,
named_dollar: true,
numbered_question: true,
};
}
impl IdentifierSyntax {
pub const SQLITE: Self = Self {
non_ascii: super::NonAsciiIdentifierSyntax::Any,
dollar_in_identifiers: true,
string_literal_identifiers: true,
string_literal_table_names: false,
empty_quoted_identifiers: true,
};
}
impl TypeNameSyntax {
pub const SQLITE: Self = Self {
integer_display_width: true,
liberal_type_names: true,
string_type_modifiers: false,
extended_scalar_type_names: false,
enum_type: false,
set_type: false,
numeric_modifiers: false,
composite_types: false,
varchar_requires_length: false,
zoned_temporal_types: true,
empty_type_parens: false,
character_set_annotation: false,
signed_type_modifier: false,
nullable_type: false,
low_cardinality_type: false,
fixed_string_type: false,
datetime64_type: false,
nested_type: false,
bit_width_integer_names: false,
angle_bracket_types: false,
};
}
impl TableExpressionSyntax {
pub const SQLITE: Self = Self {
table_alias_column_lists: false,
bare_table_alias_is_bare_label: true,
indexed_by: true,
only: false,
table_sample: false,
parenthesized_joins: true,
join_using_alias: false,
index_hints: false,
table_hints: false,
partition_selection: false,
base_table_alias_column_lists: true,
string_literal_aliases: false,
aliased_parenthesized_join: true,
table_version: false,
table_json_path: false,
prefix_colon_alias: false,
};
}
impl JoinSyntax {
pub const SQLITE: Self = Self {
stacked_join_qualifiers: false,
natural_cross_join: true,
full_outer_join: true,
straight_join: false,
asof_join: false,
positional_join: false,
semi_anti_join: false,
sided_semi_anti_join: false,
apply_join: false,
recursive_search_cycle: false,
recursive_union_rejects_order_limit: false,
recursive_using_key: false,
};
}
impl TableFactorSyntax {
pub const SQLITE: Self = Self {
table_functions: true,
lateral: false,
rows_from: false,
unnest: false,
unnest_with_offset: false,
table_function_ordinality: false,
special_function_table_source: true,
pivot: false,
unpivot: false,
show_ref: false,
from_values: false,
json_table: false,
xml_table: false,
table_expr_factor: false,
pivot_value_sources: false,
match_recognize: false,
open_json: false,
};
}
impl ExpressionSyntax {
pub const SQLITE: Self = Self {
typecast_operator: false,
subscript: false,
slice_step: false,
collate: true,
at_time_zone: false,
semi_structured_access: false,
array_constructor: false,
multidim_array_literals: false,
collection_literals: false,
row_constructor: false,
struct_constructor: false,
field_selection: false,
field_wildcard: false,
typed_string_literals: false,
typed_interval_literal: false,
relaxed_interval_syntax: false,
mysql_interval_operator: false,
positional_column: false,
lambda_keyword: false,
};
}
impl PredicateSyntax {
pub const SQLITE: Self = Self {
empty_in_list: true,
null_test_two_word_postfix: true,
is_distinct_from: true,
like: true,
ilike: false,
similar_to: false,
overlaps_period_predicate: false,
unparenthesized_in_list: false,
pattern_match_quantifier: false,
between_symmetric: false,
is_normalized: false,
};
}
impl OperatorSyntax {
pub const SQLITE: Self = Self {
operator_construct: false,
containment_operators: false,
json_arrow_operators: true,
jsonb_operators: false,
double_equals: true,
integer_divide_slash: false,
starts_with_operator: false,
is_general_equality: true,
truth_value_tests: false,
null_safe_equals: false,
lambda_expressions: false,
bitwise_operators: true,
quantified_comparisons: false,
quantified_comparison_lists: false,
quantified_arbitrary_operator: false,
custom_operators: false,
null_test_postfix: true,
postfix_operators: false,
};
}
impl CallSyntax {
pub const SQLITE: Self = Self {
named_argument: false,
utc_special_functions: false,
columns_expression: false,
extract_from_syntax: false,
try_cast: false,
restricted_cast_targets: false,
extract_string_field: false,
method_chaining: false,
sqljson_constructors_require_argument: false,
sqljson_expression_functions: false,
xml_expression_functions: false,
variadic_argument: false,
merge_action_function: false,
convert_function: false,
};
}
impl StringFuncForms {
pub const SQLITE: Self = Self {
substring_from_for: false,
substring_leading_for: false,
substring_similar: false,
substring_plain_call_requires_2_or_3_args: false,
substr_from_for: false,
position_in: false,
position_asymmetric_operands: false,
overlay_placing: false,
overlay_requires_placing: false,
trim_from: false,
trim_list_syntax: false,
collation_for_expression: false,
ceil_to_field: false,
floor_to_field: false,
match_against: false,
};
}
impl AggregateCallSyntax {
pub const SQLITE: Self = Self {
group_concat_separator: false,
within_group: false,
aggregate_filter: true,
filter_optional_where: false,
aggregate_args_require_adjacent_paren: false,
null_treatment: false,
aggregate_calls_reject_empty_arguments: false,
over_requires_windowable_function: false,
window_function_tail: false,
standalone_argument_order_by: false,
};
}
impl MutationSyntax {
pub const SQLITE: Self = Self {
insert_ignore: false,
insert_overwrite: false,
returning: true,
on_conflict: true,
on_duplicate_key_update: false,
multi_column_assignment: false,
update_tuple_value_row_arity: false,
where_current_of: false,
merge: false,
replace_into: true,
insert_set: false,
update_delete_tails: false,
joined_update_delete: false,
or_conflict_action: true,
insert_column_matching: false,
delete_using: false,
update_from: true,
delete_using_target_alias: true,
cte_before_insert: true,
cte_before_merge: false,
data_modifying_ctes: false,
merge_when_not_matched_by: false,
merge_insert_default_values: false,
merge_insert_overriding: false,
merge_insert_multirow: false,
merge_update_set_star: false,
merge_insert_star_by_name: false,
merge_error_action: false,
update_set_qualified_column: true,
};
}
impl StatementDdlGates {
pub const SQLITE: Self = Self {
colocation_groups: false,
create_trigger: true,
create_macro: false,
create_secret: false,
create_type: false,
create_virtual_table: true,
create_sequence: false,
extension_ddl: false,
transform_ddl: false,
alter_system: false,
tablespace_ddl: false,
logfile_group_ddl: false,
schemas: false,
schema_elements: false,
databases: false,
drop_database: false,
materialized_views: false,
routines: false,
or_replace: false,
create_or_replace_table: false,
compound_statements: false,
alter_database: false,
alter_database_options: false,
server_definition: false,
alter_instance: false,
spatial_reference_system: false,
resource_group: false,
alter_sequence: false,
alter_object_set_schema: false,
};
}
impl ViewSequenceClauseSyntax {
pub const SQLITE: Self = Self {
materialized_view_to: false,
create_sequence_cache: false,
temporary_views: true,
recursive_views: false,
view_definition_options: false,
};
}
impl CreateTableClauseSyntax {
pub const SQLITE: Self = Self {
table_options: false,
without_rowid_table_option: true,
strict_table_option: true,
storage_parameters: false,
on_commit: false,
create_table_as_with_data: true,
create_table_as_execute: false,
declarative_partitioning: false,
table_inheritance: false,
like_source_table: false,
statement_level_table_like: false,
unlogged_tables: false,
table_access_method: false,
without_oids: false,
typed_tables: false,
};
}
impl ColumnDefinitionSyntax {
pub const SQLITE: Self = Self {
generated_column_shorthand: true,
column_conflict_resolution_clause: true,
typeless_column_definitions: true,
typeless_generated_columns: false,
joined_autoincrement_attribute: true,
inline_primary_key_ordering: true,
named_column_collate_constraint: true,
identity_columns: false,
compact_identity_columns: false,
default_expression_requires_parens: false,
column_default_requires_b_expr: false,
column_collation: true,
column_storage: false,
};
}
impl ConstraintSyntax {
pub const SQLITE: Self = Self {
deferrable_constraints: true,
named_inline_non_check_constraints: true,
bare_constraint_name: true,
exclusion_constraints: false,
constraint_no_inherit_not_valid: false,
index_constraint_parameters: false,
constraint_column_collate_order: true,
referential_action_cascade_set: true,
check_constraint_subqueries: false,
};
}
impl IndexAlterSyntax {
pub const SQLITE: Self = Self {
rename_constraint: false,
alter_table_set_options: false,
drop_primary_key: false,
alter_column_add_identity: false,
index_storage_parameters: false,
drop_behavior: false,
index_drop_on_table: false,
index_concurrently: false,
index_using_method: false,
partial_index: true,
index_if_not_exists: true,
index_nulls_order: true,
alter_table_extended: false,
alter_nested_column_paths: false,
alter_existence_guards: false,
alter_column_set_data_type: false,
routine_arg_types: false,
routine_arg_defaults: false,
routine_arg_modes: false,
routine_language_string: false,
alter_table_multiple_actions: false,
};
}
impl ExistenceGuards {
pub const SQLITE: Self = Self {
if_exists: true,
view_if_not_exists: true,
create_database_if_not_exists: false,
};
}
impl SelectSyntax {
pub const SQLITE: Self = Self {
distinct_on: false,
select_into: false,
empty_target_list: false,
qualify: false,
alias_string_literals: true,
bare_alias_string_literals: true,
union_by_name: false,
wildcard_modifiers: false,
wildcard_replace: false,
intersect_all: false,
except_all: false,
qualified_wildcard_alias: false,
from_first: false,
explicit_table: false,
values_rows_require_equal_arity: true,
parenthesized_query_operands: false,
values_row_constructor: true,
as_alias_rejects_reserved: false,
trailing_comma: false,
prefix_colon_alias: false,
lateral_view_clause: false,
connect_by_clause: false,
};
}
impl QueryTailSyntax {
pub const SQLITE: Self = Self {
fetch_first: false,
limit_offset_comma: true,
locking_clauses: false,
key_lock_strengths: false,
stacked_locking_clauses: false,
using_sample: false,
leading_offset: false,
limit_expressions: true,
limit_percent: false,
with_ties_requires_order_by: false,
pipe_syntax: false,
limit_by_clause: false,
settings_clause: false,
format_clause: false,
for_xml_json_clause: false,
};
}
impl GroupingSyntax {
pub const SQLITE: Self = Self {
grouping_sets: false,
with_rollup: false,
order_by_using: false,
group_by_all: false,
group_by_set_quantifier: false,
order_by_all: false,
};
}
impl UtilitySyntax {
pub const SQLITE: Self = Self {
copy: false,
copy_into: false,
stage_references: false,
comment_on: false,
comment_if_exists: false,
pragma: true,
attach: true,
kill: false,
handler_statements: false,
plugin_component_statements: false,
shutdown: false,
restart: false,
clone: false,
import_table: false,
help_statement: false,
binlog: false,
key_cache_statements: false,
use_statement: false,
use_qualified_name: false,
use_string_literal_name: false,
prepared_statements: false,
prepare_typed_parameters: false,
prepared_statements_from: false,
call: false,
call_bare_name: false,
load_extension: false,
load_bare_name: false,
load_data: false,
reset_scope: false,
detach_if_exists: false,
do_statement: false,
do_expression_list: false,
lock_tables: false,
lock_instance: false,
rename_statement: false,
signal_diagnostics: false,
export_import_database: false,
update_extensions: false,
flush: false,
purge_binary_logs: false,
replication_statements: false,
};
}
impl TransactionSyntax {
pub const SQLITE: Self = Self {
start_transaction: false,
start_transaction_block_optional: false,
transaction_work_keyword: false,
begin_transaction_keyword: true,
commit_transaction_keyword: true,
rollback_transaction_keyword: true,
transaction_name: true,
begin_transaction_modes: false,
transaction_savepoints: true,
set_transaction: false,
transaction_isolation_mode: false,
transaction_access_mode: false,
transaction_deferrable_mode: false,
start_transaction_isolation_mode: false,
start_transaction_deferrable_mode: false,
start_transaction_consistent_snapshot: false,
transaction_multiple_modes: false,
transaction_modes_require_commas: false,
transaction_modes_reject_duplicates: false,
abort_transaction_alias: false,
end_transaction_alias: true,
transaction_release: false,
transaction_chain: false,
release_savepoint_keyword_optional: true,
begin_transaction_mode: true,
xa_transactions: false,
};
}
impl ShowSyntax {
pub const SQLITE: Self = Self {
describe: false,
describe_summarize: false,
session_statements: false,
set_value_reserved_words: KeywordSet::EMPTY,
set_value_on_keyword: false,
set_value_null_keyword: false,
show_tables: false,
show_columns: false,
show_create_table: false,
show_functions: false,
show_routine_status: false,
show_verbose: false,
show_admin: false,
};
}
impl MaintenanceSyntax {
pub const SQLITE: Self = Self {
vacuum: true,
vacuum_analyze: false,
reindex: true,
analyze: true,
analyze_columns: false,
checkpoint: false,
checkpoint_database: false,
table_maintenance: false,
};
}
impl AccessControlSyntax {
pub const SQLITE: Self = Self {
alter_role_rename: false,
access_control: false,
access_control_extended_objects: false,
user_role_management: false,
access_control_account_grants: false,
};
}
pub const SQLITE_BINDING_POWERS: BindingPowerTable = BindingPowerTable {
or: BindingPower {
left: 10,
right: 11,
assoc: Assoc::Left,
},
xor: BindingPower {
left: 15,
right: 16,
assoc: Assoc::Left,
},
and: BindingPower {
left: 20,
right: 21,
assoc: Assoc::Left,
},
comparison: BindingPower {
left: 40,
right: 41,
assoc: Assoc::Left,
},
range_predicate_override: None,
is_predicate_override: None,
double_equals: BindingPower {
left: 40,
right: 41,
assoc: Assoc::Left,
},
additive: BindingPower {
left: 50,
right: 51,
assoc: Assoc::Left,
},
multiplicative: BindingPower {
left: 60,
right: 61,
assoc: Assoc::Left,
},
exponent: BindingPower {
left: 65,
right: 66,
assoc: Assoc::Left,
},
string_concat: BindingPower {
left: 45,
right: 46,
assoc: Assoc::Left,
},
any_operator: BindingPower {
left: 45,
right: 46,
assoc: Assoc::Left,
},
json_get: BindingPower {
left: 45,
right: 46,
assoc: Assoc::Left,
},
bitwise_or: BindingPower {
left: 45,
right: 46,
assoc: Assoc::Left,
},
bitwise_and: BindingPower {
left: 45,
right: 46,
assoc: Assoc::Left,
},
bitwise_shift: BindingPower {
left: 45,
right: 46,
assoc: Assoc::Left,
},
bitwise_xor: BindingPower {
left: 45,
right: 46,
assoc: Assoc::Left,
},
prefix_not: 30,
prefix_sign: 80,
prefix_bitwise_not: 80,
at_time_zone: BindingPower {
left: 70,
right: 71,
assoc: Assoc::Left,
},
collate: BindingPower {
left: 74,
right: 75,
assoc: Assoc::Left,
},
subscript: BindingPower {
left: 84,
right: 85,
assoc: Assoc::Left,
},
typecast: BindingPower {
left: 88,
right: 89,
assoc: Assoc::Left,
},
field_selection: BindingPower {
left: 92,
right: 93,
assoc: Assoc::Left,
},
};
impl FeatureSet {
pub const SQLITE: Self = Self {
identifier_casing: Casing::Lower,
identifier_quotes: SQLITE_IDENTIFIER_QUOTES,
default_null_ordering: NullOrdering::NullsFirst,
reserved_column_name: SQLITE_RESERVED_COLUMN_NAME,
reserved_function_name: SQLITE_RESERVED_FUNCTION_NAME,
reserved_type_name: SQLITE_RESERVED_TYPE_NAME,
reserved_bare_alias: SQLITE_RESERVED_BARE_ALIAS,
reserved_as_label: SQLITE_RESERVED_AS_LABEL,
catalog_qualified_names: false,
byte_classes: SQLITE_BYTE_CLASSES,
binding_powers: SQLITE_BINDING_POWERS,
set_operation_powers: STANDARD_SET_OPERATION_BINDING_POWERS,
string_literals: StringLiteralSyntax::SQLITE,
numeric_literals: NumericLiteralSyntax::SQLITE,
parameters: ParameterSyntax::SQLITE,
session_variables: SessionVariableSyntax::ANSI,
identifier_syntax: IdentifierSyntax::SQLITE,
table_expressions: TableExpressionSyntax::SQLITE,
join_syntax: JoinSyntax::SQLITE,
table_factor_syntax: TableFactorSyntax::SQLITE,
expression_syntax: ExpressionSyntax::SQLITE,
operator_syntax: OperatorSyntax::SQLITE,
call_syntax: CallSyntax::SQLITE,
string_func_forms: StringFuncForms::SQLITE,
aggregate_call_syntax: AggregateCallSyntax::SQLITE,
predicate_syntax: PredicateSyntax::SQLITE,
pipe_operator: PipeOperator::StringConcat,
double_ampersand: DoubleAmpersand::Unsupported,
keyword_operators: KeywordOperators::Sqlite,
caret_operator: CaretOperator::Unsupported,
hash_bitwise_xor: false,
comment_syntax: CommentSyntax::SQLITE,
mutation_syntax: MutationSyntax::SQLITE,
statement_ddl_gates: StatementDdlGates::SQLITE,
view_sequence_clause_syntax: ViewSequenceClauseSyntax::SQLITE,
create_table_clause_syntax: CreateTableClauseSyntax::SQLITE,
column_definition_syntax: ColumnDefinitionSyntax::SQLITE,
constraint_syntax: ConstraintSyntax::SQLITE,
index_alter_syntax: IndexAlterSyntax::SQLITE,
existence_guards: ExistenceGuards::SQLITE,
select_syntax: SelectSyntax::SQLITE,
query_tail_syntax: QueryTailSyntax::SQLITE,
grouping_syntax: GroupingSyntax::SQLITE,
utility_syntax: UtilitySyntax::SQLITE,
transaction_syntax: TransactionSyntax::SQLITE,
show_syntax: ShowSyntax::SQLITE,
maintenance_syntax: MaintenanceSyntax::SQLITE,
access_control_syntax: AccessControlSyntax::SQLITE,
type_name_syntax: TypeNameSyntax::SQLITE,
target_spelling: TargetSpelling::Ansi,
};
}
pub const SQLITE: FeatureSet = FeatureSet::SQLITE;
const _: () = assert!(FeatureSet::SQLITE.is_lexically_consistent());
const _: () = assert!(FeatureSet::SQLITE.has_satisfied_feature_dependencies());
const _: () = assert!(FeatureSet::SQLITE.has_no_grammar_conflict());
#[cfg(test)]
mod tests {
use super::super::{
LexicalConflict, RESERVED_BARE_ALIAS, RESERVED_COLUMN_NAME, RESERVED_FUNCTION_NAME,
RESERVED_TYPE_NAME,
};
use super::*;
use crate::ast::{BinaryOperator, EqualsSpelling, RegexpSpelling};
use crate::precedence::STANDARD_BINDING_POWERS;
#[test]
fn sqlite_reserved_set_is_smaller_than_ansi_freeing_sqlite_identifiers() {
for keyword in [Keyword::Desc, Keyword::Asc, Keyword::End, Keyword::Analyze] {
assert!(
!SQLITE_RESERVED_COLUMN_NAME.contains(keyword),
"{keyword:?} must be a free SQLite identifier",
);
assert!(!SQLITE_RESERVED_FUNCTION_NAME.contains(keyword));
assert!(!SQLITE_RESERVED_TYPE_NAME.contains(keyword));
assert!(!SQLITE_RESERVED_BARE_ALIAS.contains(keyword));
}
assert!(
RESERVED_COLUMN_NAME.contains(Keyword::Desc)
|| RESERVED_BARE_ALIAS.contains(Keyword::Desc),
"DESC should be reserved somewhere under the ANSI/PostgreSQL model",
);
for keyword in [
Keyword::Select,
Keyword::From,
Keyword::Where,
Keyword::Join,
] {
assert!(SQLITE_RESERVED_COLUMN_NAME.contains(keyword));
}
for keyword in [Keyword::Glob, Keyword::Match, Keyword::Regexp] {
assert!(!SQLITE_RESERVED_FUNCTION_NAME.contains(keyword));
}
let _ = (RESERVED_FUNCTION_NAME, RESERVED_TYPE_NAME);
}
#[test]
fn sqlite_join_keywords_are_reserved_by_position_not_uniformly() {
for keyword in [
Keyword::Cross,
Keyword::Inner,
Keyword::Left,
Keyword::Natural,
Keyword::Outer,
Keyword::Right,
Keyword::Full,
] {
assert!(
!SQLITE_RESERVED_COLUMN_NAME.contains(keyword),
"{keyword:?} must be admissible as a SQLite table/column name",
);
assert!(!SQLITE_RESERVED_FUNCTION_NAME.contains(keyword));
assert!(!SQLITE_RESERVED_AS_LABEL.contains(keyword));
assert!(
SQLITE_RESERVED_BARE_ALIAS.contains(keyword),
"{keyword:?} must be reserved as a SQLite bare alias (the JOIN guard)",
);
assert!(SQLITE_RESERVED_TYPE_NAME.contains(keyword));
}
}
#[test]
fn sqlite_name_reserved_residuals_are_reserved_as_a_name_but_isnull_notnull_bare_admit() {
for keyword in [
Keyword::Returning,
Keyword::Nothing,
Keyword::Isnull,
Keyword::Notnull,
] {
assert!(
SQLITE_RESERVED_COLUMN_NAME.contains(keyword),
"{keyword:?} must be reserved as a SQLite name",
);
assert!(SQLITE_RESERVED_AS_LABEL.contains(keyword));
assert!(SQLITE_RESERVED_FUNCTION_NAME.contains(keyword));
assert!(SQLITE_RESERVED_TYPE_NAME.contains(keyword));
}
assert!(SQLITE_RESERVED_BARE_ALIAS.contains(Keyword::Returning));
assert!(SQLITE_RESERVED_BARE_ALIAS.contains(Keyword::Nothing));
assert!(!SQLITE_RESERVED_BARE_ALIAS.contains(Keyword::Isnull));
assert!(!SQLITE_RESERVED_BARE_ALIAS.contains(Keyword::Notnull));
}
#[test]
fn sqlite_preset_is_lexically_consistent_with_double_quote_resolved_to_identifier() {
assert!(FeatureSet::SQLITE.is_lexically_consistent());
assert_eq!(FeatureSet::SQLITE.lexical_conflict(), None);
let with_dqs = FeatureSet::SQLITE.with(super::super::FeatureDelta::EMPTY.string_literals(
StringLiteralSyntax {
double_quoted_strings: true,
..StringLiteralSyntax::SQLITE
},
));
assert_eq!(
with_dqs.lexical_conflict(),
Some(LexicalConflict::DoubleQuoteStringVersusIdentifier),
);
}
#[test]
fn sqlite_named_dollar_parameter_never_meets_dollar_quoting() {
let with_dollar_quote = FeatureSet::SQLITE.with(
super::super::FeatureDelta::EMPTY.string_literals(StringLiteralSyntax {
dollar_quoted_strings: true,
..StringLiteralSyntax::SQLITE
}),
);
assert_eq!(
with_dollar_quote.lexical_conflict(),
Some(LexicalConflict::NamedDollarParameterVersusDollarQuotedString),
);
}
#[test]
fn sqlite_keyword_operators_map_glob_match_regexp() {
assert_eq!(
KeywordOperators::Sqlite.binary_operator(Keyword::Glob),
Some(BinaryOperator::Glob),
);
assert_eq!(
KeywordOperators::Sqlite.binary_operator(Keyword::Match),
Some(BinaryOperator::Match),
);
assert_eq!(
KeywordOperators::Sqlite.binary_operator(Keyword::Regexp),
Some(BinaryOperator::Regexp(RegexpSpelling::Regexp)),
);
assert_eq!(
KeywordOperators::Sqlite.binary_operator(Keyword::Div),
None,
"DIV is MySQL's, not SQLite's",
);
}
#[test]
fn sqlite_comparison_row_is_left_associative_carrying_the_new_operators() {
let mut expected = STANDARD_BINDING_POWERS;
expected.comparison.assoc = Assoc::Left;
expected.double_equals.assoc = Assoc::Left;
expected.prefix_bitwise_not = expected.prefix_sign;
assert_eq!(SQLITE_BINDING_POWERS, expected);
for op in [
BinaryOperator::BitwiseOr,
BinaryOperator::BitwiseAnd,
BinaryOperator::BitwiseShiftLeft,
BinaryOperator::BitwiseShiftRight,
] {
assert_eq!(
SQLITE_BINDING_POWERS.binary(&op),
STANDARD_BINDING_POWERS.binary(&op),
);
}
for op in [
BinaryOperator::Eq(EqualsSpelling::Single),
BinaryOperator::Eq(EqualsSpelling::Double),
BinaryOperator::Glob,
BinaryOperator::Match,
BinaryOperator::Regexp(RegexpSpelling::Regexp),
] {
let bp = SQLITE_BINDING_POWERS.binary(&op);
assert_eq!(bp.assoc, Assoc::Left, "{op:?} rides the comparison row");
assert_eq!(bp.left, 40, "{op:?} keeps the STANDARD left rank");
assert_eq!(bp.right, 41, "{op:?} keeps the STANDARD right rank");
}
}
}