use sqruff_lib_core::dialects::base::Dialect;
use sqruff_lib_core::dialects::init::DialectKind;
use sqruff_lib_core::dialects::syntax::SyntaxKind;
use sqruff_lib_core::helpers::{Config, ToMatchable};
use sqruff_lib_core::parser::grammar::anyof::{one_of, optionally_bracketed, AnyNumberOf};
use sqruff_lib_core::parser::grammar::base::{Anything, Nothing, Ref};
use sqruff_lib_core::parser::grammar::delimited::Delimited;
use sqruff_lib_core::parser::grammar::sequence::{Bracketed, Sequence};
use sqruff_lib_core::parser::matchable::MatchableTrait;
use sqruff_lib_core::parser::node_matcher::NodeMatcher;
use sqruff_lib_core::parser::parsers::TypedParser;
use sqruff_lib_core::parser::segments::meta::MetaSegment;
use sqruff_lib_core::parser::types::ParseMode;
use sqruff_lib_core::vec_of_erased;
use crate::sqlite_keywords::{RESERVED_KEYWORDS, UNRESERVED_KEYWORDS};
pub fn dialect() -> Dialect {
raw_dialect().config(|dialect| dialect.expand())
}
pub fn raw_dialect() -> Dialect {
let sqlite_dialect = super::ansi::raw_dialect();
let mut sqlite_dialect = sqlite_dialect;
sqlite_dialect.name = DialectKind::Sqlite;
sqlite_dialect.sets_mut("reserved_keywords").clear();
sqlite_dialect
.sets_mut("reserved_keywords")
.extend(RESERVED_KEYWORDS);
sqlite_dialect.sets_mut("unreserved_keywords").clear();
sqlite_dialect
.sets_mut("unreserved_keywords")
.extend(UNRESERVED_KEYWORDS);
sqlite_dialect.add([
(
"BooleanBinaryOperatorGrammar".into(),
one_of(vec_of_erased![
Ref::new("AndOperatorGrammar"),
Ref::new("OrOperatorGrammar"),
Ref::keyword("REGEXP")
])
.to_matchable()
.into(),
),
(
"PrimaryKeyGrammar".into(),
Sequence::new(vec_of_erased![
Ref::keyword("PRIMARY"),
Ref::keyword("KEY"),
Sequence::new(vec_of_erased![Ref::keyword("AUTOINCREMENT")]).config(|config| {
config.optional();
})
])
.to_matchable()
.into(),
),
(
"TemporaryTransientGrammar".into(),
Ref::new("TemporaryGrammar").to_matchable().into(),
),
(
"DateTimeLiteralGrammar".into(),
Sequence::new(vec_of_erased![
one_of(vec_of_erased![
Ref::keyword("DATE"),
Ref::keyword("DATETIME")
]),
TypedParser::new(SyntaxKind::SingleQuote, SyntaxKind::DateConstructorLiteral)
])
.to_matchable()
.into(),
),
(
"BaseExpressionElementGrammar".into(),
one_of(vec_of_erased![
Ref::new("LiteralGrammar"),
Ref::new("BareFunctionSegment"),
Ref::new("FunctionSegment"),
Ref::new("ColumnReferenceSegment"),
Ref::new("ExpressionSegment"),
Sequence::new(vec_of_erased![
Ref::new("DatatypeSegment"),
Ref::new("LiteralGrammar")
])
])
.to_matchable()
.into(),
),
(
"AutoIncrementGrammar".into(),
Nothing::new().to_matchable().into(),
),
(
"CommentClauseSegment".into(),
Nothing::new().to_matchable().into(),
),
(
"IntervalExpressionSegment".into(),
Nothing::new().to_matchable().into(),
),
(
"TimeZoneGrammar".into(),
Nothing::new().to_matchable().into(),
),
(
"FetchClauseSegment".into(),
Nothing::new().to_matchable().into(),
),
(
"TrimParametersGrammar".into(),
Nothing::new().to_matchable().into(),
),
(
"LikeGrammar".into(),
Sequence::new(vec_of_erased![Ref::keyword("LIKE")])
.to_matchable()
.into(),
),
(
"OverlapsClauseSegment".into(),
Nothing::new().to_matchable().into(),
),
(
"MLTableExpressionSegment".into(),
Nothing::new().to_matchable().into(),
),
(
"MergeIntoLiteralGrammar".into(),
Nothing::new().to_matchable().into(),
),
(
"SamplingExpressionSegment".into(),
Nothing::new().to_matchable().into(),
),
(
"OrderByClauseTerminators".into(),
one_of(vec_of_erased![
Ref::keyword("LIMIT"),
Ref::keyword("WINDOW"),
Ref::new("FrameClauseUnitGrammar")
])
.to_matchable()
.into(),
),
(
"WhereClauseTerminatorGrammar".into(),
one_of(vec_of_erased![
Ref::keyword("LIMIT"),
Sequence::new(vec_of_erased![Ref::keyword("GROUP"), Ref::keyword("BY")]),
Sequence::new(vec_of_erased![Ref::keyword("ORDER"), Ref::keyword("BY")]),
Ref::keyword("WINDOW")
])
.to_matchable()
.into(),
),
(
"FromClauseTerminatorGrammar".into(),
one_of(vec_of_erased![
Ref::keyword("WHERE"),
Ref::keyword("LIMIT"),
Sequence::new(vec_of_erased![Ref::keyword("GROUP"), Ref::keyword("BY")]),
Sequence::new(vec_of_erased![Ref::keyword("ORDER"), Ref::keyword("BY")]),
Ref::keyword("WINDOW"),
Ref::new("SetOperatorSegment"),
Ref::new("WithNoSchemaBindingClauseSegment"),
Ref::new("WithDataClauseSegment")
])
.to_matchable()
.into(),
),
(
"GroupByClauseTerminatorGrammar".into(),
one_of(vec_of_erased![
Sequence::new(vec_of_erased![Ref::keyword("ORDER"), Ref::keyword("BY")]),
Ref::keyword("LIMIT"),
Ref::keyword("HAVING"),
Ref::keyword("WINDOW")
])
.to_matchable()
.into(),
),
(
"PostFunctionGrammar".into(),
Ref::new("FilterClauseGrammar").to_matchable().into(),
),
(
"IgnoreRespectNullsGrammar".into(),
Nothing::new().to_matchable().into(),
),
(
"SelectClauseTerminatorGrammar".into(),
one_of(vec_of_erased![
Ref::keyword("FROM"),
Ref::keyword("WHERE"),
Sequence::new(vec_of_erased![Ref::keyword("ORDER"), Ref::keyword("BY")]),
Ref::keyword("LIMIT"),
Ref::new("SetOperatorSegment")
])
.to_matchable()
.into(),
),
(
"FunctionContentsGrammar".into(),
AnyNumberOf::new(vec_of_erased![
Ref::new("ExpressionSegment"),
Sequence::new(vec_of_erased![
Ref::new("ExpressionSegment"),
Ref::keyword("AS"),
Ref::new("DatatypeSegment")
]),
Sequence::new(vec_of_erased![
Ref::new("TrimParametersGrammar"),
Ref::new("ExpressionSegment")
.optional()
.exclude(Ref::keyword("FROM"))
.config(|config| {
config.exclude = Ref::keyword("FROM").to_matchable().into();
}),
Ref::keyword("FROM"),
Ref::new("ExpressionSegment")
]),
Sequence::new(vec_of_erased![
one_of(vec_of_erased![
Ref::new("DatetimeUnitSegment"),
Ref::new("ExpressionSegment")
]),
Ref::keyword("FROM"),
Ref::new("ExpressionSegment")
]),
Sequence::new(vec_of_erased![
Ref::keyword("DISTINCT").optional(),
one_of(vec_of_erased![
Ref::new("StarSegment"),
Delimited::new(vec_of_erased![Ref::new(
"FunctionContentsExpressionGrammar"
)])
])
]),
Ref::new("OrderByClauseSegment"),
Sequence::new(vec_of_erased![
one_of(vec_of_erased![
Ref::new("QuotedLiteralSegment"),
Ref::new("SingleIdentifierGrammar"),
Ref::new("ColumnReferenceSegment")
]),
Ref::keyword("IN"),
one_of(vec_of_erased![
Ref::new("QuotedLiteralSegment"),
Ref::new("SingleIdentifierGrammar"),
Ref::new("ColumnReferenceSegment")
])
]),
Ref::new("IndexColumnDefinitionSegment")
])
.to_matchable()
.into(),
),
(
"Expression_A_Unary_Operator_Grammar".into(),
one_of(vec_of_erased![
Ref::new("SignedSegmentGrammar")
.exclude(Sequence::new(vec_of_erased![Ref::new(
"QualifiedNumericLiteralSegment"
)]))
.config(|config| {
config.exclude = Sequence::new(vec_of_erased![Ref::new(
"QualifiedNumericLiteralSegment"
)])
.to_matchable()
.into();
}),
Ref::new("TildeSegment"),
Ref::new("NotOperatorGrammar")
])
.to_matchable()
.into(),
),
(
"IsClauseGrammar".into(),
one_of(vec_of_erased![
Ref::keyword("NULL"),
Ref::new("BooleanLiteralGrammar")
])
.to_matchable()
.into(),
),
]);
sqlite_dialect.add([(
"SetOperatorSegment".into(),
NodeMatcher::new(
SyntaxKind::SetOperator,
one_of(vec_of_erased![
Sequence::new(vec_of_erased![
Ref::keyword("UNION"),
one_of(vec_of_erased![
Ref::keyword("DISTINCT"),
Ref::keyword("ALL")
])
.config(|config| {
config.optional();
})
]),
Sequence::new(vec_of_erased![
one_of(vec_of_erased![
Ref::keyword("INTERSECT"),
Ref::keyword("EXCEPT")
]),
Ref::keyword("ALL").optional()
])
])
.config(|config| {
config.exclude = Sequence::new(vec_of_erased![
Ref::keyword("EXCEPT"),
Bracketed::new(vec_of_erased![Anything::new()])
])
.to_matchable()
.into();
})
.to_matchable(),
)
.to_matchable()
.into(),
)]);
sqlite_dialect.replace_grammar(
"DatatypeSegment",
one_of(vec_of_erased![
Sequence::new(vec_of_erased![
Ref::keyword("DOUBLE"),
Ref::keyword("PRECISION")
]),
Sequence::new(vec_of_erased![
Ref::keyword("UNSIGNED"),
Ref::keyword("BIG"),
Ref::keyword("INT")
]),
Sequence::new(vec_of_erased![
one_of(vec_of_erased![
Sequence::new(vec_of_erased![
one_of(vec_of_erased![
Ref::keyword("VARYING"),
Ref::keyword("NATIVE")
]),
one_of(vec_of_erased![Ref::keyword("CHARACTER")])
]),
Ref::new("DatatypeIdentifierSegment")
]),
Ref::new("BracketedArguments").optional()
])
])
.to_matchable(),
);
sqlite_dialect.add([(
"TableEndClauseSegment".into(),
NodeMatcher::new(
SyntaxKind::TableEndClauseSegment,
Delimited::new(vec_of_erased![
Sequence::new(vec_of_erased![
Ref::keyword("WITHOUT"),
Ref::keyword("ROWID")
]),
Ref::keyword("STRICT")
])
.to_matchable(),
)
.to_matchable()
.into(),
)]);
sqlite_dialect.replace_grammar(
"ValuesClauseSegment",
Sequence::new(vec_of_erased![
Ref::keyword("VALUES"),
Delimited::new(vec_of_erased![Sequence::new(vec_of_erased![
Bracketed::new(vec_of_erased![Delimited::new(vec_of_erased![
Ref::keyword("DEFAULT"),
Ref::new("ExpressionSegment")
])])
.config(|config| {
config.parse_mode(ParseMode::Greedy);
})
])])
])
.to_matchable(),
);
sqlite_dialect.add([
(
"IndexColumnDefinitionSegment".into(),
NodeMatcher::new(
SyntaxKind::IndexColumnDefinition,
Sequence::new(vec_of_erased![
one_of(vec_of_erased![
Ref::new("SingleIdentifierGrammar"),
Ref::new("ExpressionSegment")
]),
one_of(vec_of_erased![Ref::keyword("ASC"), Ref::keyword("DESC")]).config(
|config| {
config.optional();
}
)
])
.to_matchable(),
)
.to_matchable()
.into(),
),
(
"InsertStatementSegment".into(),
NodeMatcher::new(
SyntaxKind::InsertStatement,
Sequence::new(vec_of_erased![
one_of(vec_of_erased![
Sequence::new(vec_of_erased![
Ref::keyword("INSERT"),
Sequence::new(vec_of_erased![
Ref::keyword("OR"),
one_of(vec_of_erased![
Ref::keyword("ABORT"),
Ref::keyword("FAIL"),
Ref::keyword("IGNORE"),
Ref::keyword("REPLACE"),
Ref::keyword("ROLLBACK")
])
])
.config(|config| {
config.optional();
})
]),
Ref::keyword("REPLACE")
]),
Ref::keyword("INTO"),
Ref::new("TableReferenceSegment"),
Ref::new("BracketedColumnReferenceListGrammar").optional(),
one_of(vec_of_erased![
Ref::new("ValuesClauseSegment"),
optionally_bracketed(vec_of_erased![Ref::new("SelectableGrammar")]),
Ref::new("DefaultValuesGrammar")
]),
Ref::new("ReturningClauseSegment").optional()
])
.to_matchable(),
)
.to_matchable()
.into(),
),
]);
let column_constraint = sqlite_dialect
.grammar("ColumnConstraintSegment")
.match_grammar()
.unwrap()
.copy(
Some(vec_of_erased![
one_of(vec_of_erased![
Ref::keyword("DEFERRABLE"),
Sequence::new(vec_of_erased![
Ref::keyword("NOT"),
Ref::keyword("DEFERRABLE")
])
])
.config(|config| {
config.optional();
}),
one_of(vec_of_erased![
Sequence::new(vec_of_erased![
Ref::keyword("INITIALLY"),
Ref::keyword("DEFERRED")
]),
Sequence::new(vec_of_erased![
Ref::keyword("INITIALLY"),
Ref::keyword("IMMEDIATE")
])
])
.config(|config| {
config.optional();
})
]),
None,
None,
None,
Vec::new(),
false,
);
sqlite_dialect.replace_grammar("ColumnConstraintSegment", column_constraint);
sqlite_dialect.replace_grammar(
"TableConstraintSegment",
Sequence::new(vec_of_erased![
Sequence::new(vec_of_erased![
Ref::keyword("CONSTRAINT"),
Ref::new("ObjectReferenceSegment")
])
.config(|config| {
config.optional();
}),
one_of(vec_of_erased![
Sequence::new(vec_of_erased![
Ref::keyword("CHECK"),
Bracketed::new(vec_of_erased![Ref::new("ExpressionSegment")])
]),
Sequence::new(vec_of_erased![
Ref::keyword("UNIQUE"),
Ref::new("BracketedColumnReferenceListGrammar")
]),
Sequence::new(vec_of_erased![
Ref::new("PrimaryKeyGrammar"),
Ref::new("BracketedColumnReferenceListGrammar")
]),
Sequence::new(vec_of_erased![
Ref::new("ForeignKeyGrammar"),
Ref::new("BracketedColumnReferenceListGrammar"),
Ref::new("ReferenceDefinitionGrammar")
])
]),
one_of(vec_of_erased![
Ref::keyword("DEFERRABLE"),
Sequence::new(vec_of_erased![
Ref::keyword("NOT"),
Ref::keyword("DEFERRABLE")
])
])
.config(|config| {
config.optional();
}),
one_of(vec_of_erased![
Sequence::new(vec_of_erased![
Ref::keyword("INITIALLY"),
Ref::keyword("DEFERRED")
]),
Sequence::new(vec_of_erased![
Ref::keyword("INITIALLY"),
Ref::keyword("IMMEDIATE")
])
])
.config(|config| {
config.optional();
})
])
.to_matchable(),
);
sqlite_dialect.replace_grammar(
"TransactionStatementSegment",
Sequence::new(vec_of_erased![
one_of(vec_of_erased![
Ref::keyword("BEGIN"),
Ref::keyword("COMMIT"),
Ref::keyword("ROLLBACK"),
Ref::keyword("END")
]),
one_of(vec_of_erased![Ref::keyword("TRANSACTION")]).config(|config| {
config.optional();
}),
Sequence::new(vec_of_erased![
Ref::keyword("TO"),
Ref::keyword("SAVEPOINT"),
Ref::new("ObjectReferenceSegment")
])
.config(|config| {
config.optional();
})
])
.to_matchable(),
);
sqlite_dialect.add([(
"PragmaReferenceSegment".into(),
NodeMatcher::new(
SyntaxKind::PragmaReference,
sqlite_dialect
.grammar("ObjectReferenceSegment")
.match_grammar()
.unwrap(),
)
.to_matchable()
.into(),
)]);
sqlite_dialect.add([(
"PragmaStatementSegment".into(),
NodeMatcher::new(SyntaxKind::PragmaStatement, {
let pragma_value = one_of(vec_of_erased![
Ref::new("LiteralGrammar"),
Ref::new("BooleanLiteralGrammar"),
Ref::keyword("YES"),
Ref::keyword("NO"),
Ref::keyword("ON"),
Ref::keyword("OFF"),
Ref::keyword("NONE"),
Ref::keyword("FULL"),
Ref::keyword("INCREMENTAL"),
Ref::keyword("DELETE"),
Ref::keyword("TRUNCATE"),
Ref::keyword("PERSIST"),
Ref::keyword("MEMORY"),
Ref::keyword("WAL"),
Ref::keyword("NORMAL"),
Ref::keyword("EXCLUSIVE"),
Ref::keyword("FAST"),
Ref::keyword("EXTRA"),
Ref::keyword("DEFAULT"),
Ref::keyword("FILE"),
Ref::keyword("PASSIVE"),
Ref::keyword("RESTART"),
Ref::keyword("RESET")
]);
Sequence::new(vec_of_erased![
Ref::keyword("PRAGMA"),
Ref::new("PragmaReferenceSegment"),
Bracketed::new(vec_of_erased![pragma_value.clone()]).config(|config| {
config.optional();
}),
Sequence::new(vec_of_erased![
Ref::new("EqualsSegment"),
optionally_bracketed(vec_of_erased![pragma_value])
])
.config(|config| {
config.optional();
})
])
.to_matchable()
})
.to_matchable()
.into(),
)]);
sqlite_dialect.replace_grammar(
"CreateTriggerStatementSegment",
Sequence::new(vec_of_erased![
Ref::keyword("CREATE"),
Ref::new("TemporaryGrammar").optional(),
Ref::keyword("TRIGGER"),
Ref::new("IfNotExistsGrammar").optional(),
Ref::new("TriggerReferenceSegment"),
one_of(vec_of_erased![
Ref::keyword("BEFORE"),
Ref::keyword("AFTER"),
Sequence::new(vec_of_erased![Ref::keyword("INSTEAD"), Ref::keyword("OF")])
])
.config(|config| {
config.optional();
}),
one_of(vec_of_erased![
Ref::keyword("DELETE"),
Ref::keyword("INSERT"),
Sequence::new(vec_of_erased![
Ref::keyword("UPDATE"),
Sequence::new(vec_of_erased![
Ref::keyword("OF"),
Delimited::new(vec_of_erased![Ref::new("ColumnReferenceSegment")])
])
.config(|config| {
config.optional();
})
])
]),
Ref::keyword("ON"),
Ref::new("TableReferenceSegment"),
Sequence::new(vec_of_erased![
Ref::keyword("FOR"),
Ref::keyword("EACH"),
Ref::keyword("ROW")
])
.config(|config| {
config.optional();
}),
Sequence::new(vec_of_erased![
Ref::keyword("WHEN"),
Bracketed::new(vec_of_erased![Ref::new("ExpressionSegment")])
])
.config(|config| {
config.optional();
}),
Ref::keyword("BEGIN"),
Delimited::new(vec_of_erased![
Ref::new("UpdateStatementSegment"),
Ref::new("InsertStatementSegment"),
Ref::new("DeleteStatementSegment"),
Ref::new("SelectableGrammar")
])
.config(|config| {
config.delimiter(
AnyNumberOf::new(vec_of_erased![Ref::new("DelimiterGrammar")]).config(
|config| {
config.min_times = 1;
},
),
);
config.allow_trailing = true;
}),
Ref::keyword("END")
])
.to_matchable(),
);
sqlite_dialect.add([(
"UnorderedSelectStatementSegment".into(),
NodeMatcher::new(
SyntaxKind::SelectStatement,
Sequence::new(vec_of_erased![
Ref::new("SelectClauseSegment"),
MetaSegment::dedent(),
Ref::new("FromClauseSegment").optional(),
Ref::new("WhereClauseSegment").optional(),
Ref::new("GroupByClauseSegment").optional(),
Ref::new("HavingClauseSegment").optional(),
Ref::new("OverlapsClauseSegment").optional(),
Ref::new("NamedWindowSegment").optional()
])
.to_matchable(),
)
.to_matchable()
.into(),
)]);
sqlite_dialect.add([(
"SelectStatementSegment".into(),
NodeMatcher::new(
SyntaxKind::SelectStatement,
sqlite_dialect
.grammar("UnorderedSelectStatementSegment")
.match_grammar()
.unwrap()
.copy(
Some(vec_of_erased![
Ref::new("OrderByClauseSegment").optional(),
Ref::new("FetchClauseSegment").optional(),
Ref::new("LimitClauseSegment").optional(),
Ref::new("NamedWindowSegment").optional(),
]),
None,
None,
None,
Vec::new(),
false,
),
)
.to_matchable()
.into(),
)]);
sqlite_dialect.replace_grammar(
"CreateIndexStatementSegment",
Sequence::new(vec_of_erased![
Ref::keyword("CREATE"),
Ref::keyword("UNIQUE").optional(),
Ref::keyword("INDEX"),
Ref::new("IfNotExistsGrammar").optional(),
Ref::new("IndexReferenceSegment"),
Ref::keyword("ON"),
Ref::new("TableReferenceSegment"),
Sequence::new(vec_of_erased![Bracketed::new(vec_of_erased![
Delimited::new(vec_of_erased![Ref::new("IndexColumnDefinitionSegment")])
])]),
Ref::new("WhereClauseSegment").optional()
])
.to_matchable(),
);
sqlite_dialect.replace_grammar(
"StatementSegment",
one_of(vec_of_erased![
Ref::new("AlterTableStatementSegment"),
Ref::new("CreateIndexStatementSegment"),
Ref::new("CreateTableStatementSegment"),
Ref::new("CreateTriggerStatementSegment"),
Ref::new("CreateViewStatementSegment"),
Ref::new("DeleteStatementSegment"),
Ref::new("DropIndexStatementSegment"),
Ref::new("DropTableStatementSegment"),
Ref::new("DropTriggerStatementSegment"),
Ref::new("DropViewStatementSegment"),
Ref::new("ExplainStatementSegment"),
Ref::new("InsertStatementSegment"),
Ref::new("PragmaStatementSegment"),
Ref::new("SelectableGrammar"),
Ref::new("TransactionStatementSegment"),
Ref::new("UpdateStatementSegment"),
Bracketed::new(vec_of_erased![Ref::new("StatementSegment")])
])
.to_matchable(),
);
sqlite_dialect.add([(
"ReturningClauseSegment".into(),
Sequence::new(vec_of_erased![
Ref::keyword("RETURNING"),
one_of(vec_of_erased![
Ref::new("StarSegment"),
Delimited::new(vec_of_erased![Sequence::new(vec_of_erased![
Ref::new("ExpressionSegment"),
Ref::new("AsAliasExpressionSegment").optional(),
])])
])
])
.to_matchable()
.into(),
)]);
sqlite_dialect.add([(
"AsAliasExpressionSegment".into(),
NodeMatcher::new(
SyntaxKind::AliasExpression,
Sequence::new(vec_of_erased![
MetaSegment::indent(),
Ref::keyword("AS"),
Ref::new("SingleIdentifierGrammar"),
MetaSegment::dedent(),
])
.to_matchable(),
)
.to_matchable()
.into(),
)]);
sqlite_dialect
}