diff --git a/crates/lib-dialects/src/trino.rs b/crates/lib-dialects/src/trino.rs index 1821fae38..24739e1c8 100644 --- a/crates/lib-dialects/src/trino.rs +++ b/crates/lib-dialects/src/trino.rs @@ -47,7 +47,10 @@ pub fn dialect(config: Option<&Value>) -> Dialect { trino_dialect.insert_lexer_matchers( // Regexp Replace w/ Lambda: https://trino.io/docs/422/functions/regexp.html - vec![Matcher::string("right_arrow", "->", SyntaxKind::RightArrow)], + vec![ + Matcher::string("right_arrow", "->", SyntaxKind::RightArrow), + Matcher::string("fat_right_arrow", "=>", SyntaxKind::FatRightArrow), + ], "like_operator", ); @@ -659,21 +662,440 @@ pub fn dialect(config: Option<&Value>) -> Dialect { .to_matchable(), ); + // Trino does not support these, and the inherited ANSI grammar references + // keywords that are not in Trino's keyword sets, which would panic on lookup. + trino_dialect.add([ + ( + "TemporaryTransientGrammar".into(), + Nothing::new().to_matchable().into(), + ), + ( + "PrimaryKeyGrammar".into(), + Nothing::new().to_matchable().into(), + ), + ( + "ForeignKeyGrammar".into(), + Nothing::new().to_matchable().into(), + ), + ( + "UniqueKeyGrammar".into(), + Nothing::new().to_matchable().into(), + ), + ( + "TemporaryGrammar".into(), + Nothing::new().to_matchable().into(), + ), + ( + "ExecuteArrowSegment".into(), + StringParser::new("=>", SyntaxKind::ExecuteArrow) + .to_matchable() + .into(), + ), + ]); + + // Trino only supports a subset of the ANSI statements. Listing them + // explicitly avoids inheriting branches (such as sequences) whose grammar + // refers to keywords Trino does not define. trino_dialect.replace_grammar( "StatementSegment", - super::ansi::statement_segment().copy( - Some(vec![ - Ref::new("AnalyzeStatementSegment").to_matchable(), - Ref::new("CommentOnStatementSegment").to_matchable(), - ]), - None, - None, - Some(vec![Ref::new("TransactionStatementSegment").to_matchable()]), - Vec::new(), - false, - ), + one_of(vec![ + Ref::new("AlterTableStatementSegment").to_matchable(), + Ref::new("AnalyzeStatementSegment").to_matchable(), + Ref::new("CommentOnStatementSegment").to_matchable(), + Ref::new("CreateFunctionStatementSegment").to_matchable(), + Ref::new("CreateRoleStatementSegment").to_matchable(), + Ref::new("CreateSchemaStatementSegment").to_matchable(), + Ref::new("CreateTableStatementSegment").to_matchable(), + Ref::new("CreateViewStatementSegment").to_matchable(), + Ref::new("DeleteStatementSegment").to_matchable(), + Ref::new("DescribeStatementSegment").to_matchable(), + Ref::new("DropFunctionStatementSegment").to_matchable(), + Ref::new("DropRoleStatementSegment").to_matchable(), + Ref::new("DropSchemaStatementSegment").to_matchable(), + Ref::new("DropTableStatementSegment").to_matchable(), + Ref::new("DropViewStatementSegment").to_matchable(), + Ref::new("ExplainStatementSegment").to_matchable(), + Ref::new("InsertStatementSegment").to_matchable(), + Ref::new("MergeStatementSegment").to_matchable(), + Ref::new("SelectableGrammar").to_matchable(), + Ref::new("SetSchemaStatementSegment").to_matchable(), + Ref::new("TransactionStatementSegment").to_matchable(), + Ref::new("UpdateStatementSegment").to_matchable(), + Ref::new("UseStatementSegment").to_matchable(), + Ref::new("SetSessionStatementSegment").to_matchable(), + ]) + .to_matchable(), ); + // A `CREATE TABLE` statement. + // https://trino.io/docs/current/sql/create-table.html + trino_dialect.replace_grammar( + "CreateTableStatementSegment", + Sequence::new(vec![ + Ref::keyword("CREATE").to_matchable(), + Ref::new("OrReplaceGrammar").optional().to_matchable(), + Ref::keyword("TABLE").to_matchable(), + Ref::new("IfNotExistsGrammar").optional().to_matchable(), + Ref::new("TableReferenceSegment").to_matchable(), + // Columns and comment syntax + Bracketed::new(vec![ + Delimited::new(vec![ + Ref::new("ColumnReferenceSegment").to_matchable(), + Ref::new("ColumnDefinitionSegment").to_matchable(), + Sequence::new(vec![ + Ref::keyword("LIKE").to_matchable(), + Ref::new("TableReferenceSegment").to_matchable(), + Sequence::new(vec![ + one_of(vec![ + Ref::keyword("INCLUDING").to_matchable(), + Ref::keyword("EXCLUDING").to_matchable(), + ]) + .to_matchable(), + Ref::keyword("PROPERTIES").to_matchable(), + ]) + .config(|config| { + config.optional(); + }) + .to_matchable(), + ]) + .to_matchable(), + ]) + .to_matchable(), + ]) + .config(|config| { + config.optional(); + }) + .to_matchable(), + Ref::new("CommentClauseSegment").optional().to_matchable(), + Sequence::new(vec![ + Ref::keyword("WITH").to_matchable(), + Bracketed::new(vec![ + Delimited::new(vec![ + Ref::new("ParameterNameSegment").to_matchable(), + Ref::new("EqualsSegment").to_matchable(), + Ref::new("ExpressionSegment").to_matchable(), + ]) + .to_matchable(), + ]) + .to_matchable(), + ]) + .config(|config| { + config.optional(); + }) + .to_matchable(), + // Create AS syntax + Sequence::new(vec![ + Ref::keyword("AS").to_matchable(), + optionally_bracketed(vec![Ref::new("SelectableGrammar").to_matchable()]) + .to_matchable(), + ]) + .config(|config| { + config.optional(); + }) + .to_matchable(), + // Create like syntax + Sequence::new(vec![ + Ref::keyword("WITH").to_matchable(), + Ref::keyword("NO").optional().to_matchable(), + Ref::keyword("DATA").to_matchable(), + ]) + .config(|config| { + config.optional(); + }) + .to_matchable(), + ]) + .to_matchable(), + ); + + // A column definition, e.g. for CREATE TABLE or ALTER TABLE. + trino_dialect.replace_grammar( + "ColumnDefinitionSegment", + Sequence::new(vec![ + Ref::new("SingleIdentifierGrammar").to_matchable(), + Ref::new("DatatypeSegment").to_matchable(), + AnyNumberOf::new(vec![ + Sequence::new(vec![ + Ref::keyword("NOT").to_matchable(), + Ref::keyword("NULL").to_matchable(), + ]) + .to_matchable(), + Ref::new("CommentClauseSegment").to_matchable(), + Sequence::new(vec![ + Ref::keyword("WITH").to_matchable(), + Bracketed::new(vec![ + Delimited::new(vec![ + Ref::new("ParameterNameSegment").to_matchable(), + Ref::new("EqualsSegment").to_matchable(), + Ref::new("ExpressionSegment").to_matchable(), + ]) + .to_matchable(), + ]) + .to_matchable(), + ]) + .to_matchable(), + ]) + .config(|config| { + config.max_times_per_element = Some(1); + }) + .to_matchable(), + ]) + .to_matchable(), + ); + + // A `COMMIT`, `ROLLBACK` or `START TRANSACTION` statement. + // https://trino.io/docs/current/sql/commit.html + // https://trino.io/docs/current/sql/rollback.html + // https://trino.io/docs/current/sql/start-transaction.html + trino_dialect.replace_grammar( + "TransactionStatementSegment", + one_of(vec![ + Sequence::new(vec![ + Ref::keyword("COMMIT").to_matchable(), + Ref::keyword("WORK").optional().to_matchable(), + ]) + .to_matchable(), + Sequence::new(vec![ + Ref::keyword("ROLLBACK").to_matchable(), + Ref::keyword("WORK").optional().to_matchable(), + ]) + .to_matchable(), + Sequence::new(vec![ + Ref::keyword("START").to_matchable(), + Ref::keyword("TRANSACTION").to_matchable(), + Delimited::new(vec![ + Sequence::new(vec![ + Ref::keyword("ISOLATION").to_matchable(), + Ref::keyword("LEVEL").to_matchable(), + one_of(vec![ + Sequence::new(vec![ + Ref::keyword("READ").to_matchable(), + Ref::keyword("UNCOMMITTED").to_matchable(), + ]) + .to_matchable(), + Sequence::new(vec![ + Ref::keyword("READ").to_matchable(), + Ref::keyword("COMMITTED").to_matchable(), + ]) + .to_matchable(), + Sequence::new(vec![ + Ref::keyword("REPEATABLE").to_matchable(), + Ref::keyword("READ").to_matchable(), + ]) + .to_matchable(), + Ref::keyword("SERIALIZABLE").to_matchable(), + ]) + .to_matchable(), + ]) + .to_matchable(), + Sequence::new(vec![ + Ref::keyword("READ").to_matchable(), + one_of(vec![ + Ref::keyword("ONLY").to_matchable(), + Ref::keyword("WRITE").to_matchable(), + ]) + .to_matchable(), + ]) + .to_matchable(), + ]) + .config(|config| { + config.optional(); + }) + .to_matchable(), + ]) + .to_matchable(), + ]) + .to_matchable(), + ); + + // An `INSERT` statement. Trino has no `OVERWRITE`. + // https://trino.io/docs/current/sql/insert.html + trino_dialect.replace_grammar( + "InsertStatementSegment", + Sequence::new(vec![ + Ref::keyword("INSERT").to_matchable(), + Ref::keyword("INTO").to_matchable(), + Ref::new("TableReferenceSegment").to_matchable(), + one_of(vec![ + Ref::new("SelectableGrammar").to_matchable(), + Sequence::new(vec![ + Ref::new("BracketedColumnReferenceListGrammar").to_matchable(), + Ref::new("SelectableGrammar").to_matchable(), + ]) + .to_matchable(), + Ref::new("DefaultValuesGrammar").to_matchable(), + ]) + .to_matchable(), + ]) + .to_matchable(), + ); + + // An `ALTER TABLE` statement. + // https://trino.io/docs/current/sql/alter-table.html + trino_dialect.replace_grammar( + "AlterTableStatementSegment", + Sequence::new(vec![ + Ref::keyword("ALTER").to_matchable(), + Ref::keyword("TABLE").to_matchable(), + Ref::new("IfExistsGrammar").optional().to_matchable(), + Ref::new("TableReferenceSegment").to_matchable(), + one_of(vec![ + Sequence::new(vec![ + Ref::keyword("RENAME").to_matchable(), + Ref::keyword("TO").to_matchable(), + Ref::new("TableReferenceSegment").to_matchable(), + ]) + .to_matchable(), + Sequence::new(vec![ + Ref::keyword("ADD").to_matchable(), + Ref::keyword("COLUMN").to_matchable(), + Ref::new("IfNotExistsGrammar").optional().to_matchable(), + Ref::new("ColumnDefinitionSegment").to_matchable(), + one_of(vec![ + Ref::keyword("FIRST").to_matchable(), + Ref::keyword("LAST").to_matchable(), + Sequence::new(vec![ + Ref::keyword("AFTER").to_matchable(), + Ref::new("ColumnReferenceSegment").to_matchable(), + ]) + .to_matchable(), + ]) + .config(|config| { + config.optional(); + }) + .to_matchable(), + ]) + .to_matchable(), + Sequence::new(vec![ + Ref::keyword("DROP").to_matchable(), + Ref::keyword("COLUMN").to_matchable(), + Ref::new("IfExistsGrammar").optional().to_matchable(), + Ref::new("ColumnReferenceSegment").to_matchable(), + ]) + .to_matchable(), + Sequence::new(vec![ + Ref::keyword("RENAME").to_matchable(), + Ref::keyword("COLUMN").to_matchable(), + Ref::new("IfExistsGrammar").optional().to_matchable(), + Ref::new("ColumnReferenceSegment").to_matchable(), + Ref::keyword("TO").to_matchable(), + Ref::new("ColumnReferenceSegment").to_matchable(), + ]) + .to_matchable(), + Sequence::new(vec![ + Ref::keyword("ALTER").to_matchable(), + Ref::keyword("COLUMN").to_matchable(), + Ref::new("ColumnReferenceSegment").to_matchable(), + one_of(vec![ + Sequence::new(vec![ + Ref::keyword("SET").to_matchable(), + Ref::keyword("DATA").to_matchable(), + Ref::keyword("TYPE").to_matchable(), + Ref::new("DatatypeSegment").to_matchable(), + ]) + .to_matchable(), + Sequence::new(vec![ + Ref::keyword("DROP").to_matchable(), + Ref::keyword("NOT").to_matchable(), + Ref::keyword("NULL").to_matchable(), + ]) + .to_matchable(), + ]) + .to_matchable(), + ]) + .to_matchable(), + Sequence::new(vec![ + Ref::keyword("SET").to_matchable(), + Ref::keyword("AUTHORIZATION").to_matchable(), + one_of(vec![ + Ref::new("RoleReferenceSegment").to_matchable(), + Sequence::new(vec![ + Ref::keyword("USER").to_matchable(), + Ref::new("RoleReferenceSegment").to_matchable(), + ]) + .to_matchable(), + Sequence::new(vec![ + Ref::keyword("ROLE").to_matchable(), + Ref::new("RoleReferenceSegment").to_matchable(), + ]) + .to_matchable(), + ]) + .to_matchable(), + ]) + .to_matchable(), + Sequence::new(vec![ + Ref::keyword("SET").to_matchable(), + Ref::keyword("PROPERTIES").to_matchable(), + Delimited::new(vec![ + Sequence::new(vec![ + Ref::new("ParameterNameSegment").to_matchable(), + Ref::new("EqualsSegment").to_matchable(), + Ref::new("ExpressionSegment").to_matchable(), + ]) + .to_matchable(), + ]) + .to_matchable(), + ]) + .to_matchable(), + Sequence::new(vec![ + Ref::keyword("EXECUTE").to_matchable(), + Ref::new("FunctionNameSegment").to_matchable(), + Bracketed::new(vec![ + Delimited::new(vec![ + Sequence::new(vec![ + Ref::new("ParameterNameSegment").to_matchable(), + Ref::new("ExecuteArrowSegment").to_matchable(), + Ref::new("ExpressionSegment").to_matchable(), + ]) + .to_matchable(), + ]) + .to_matchable(), + ]) + .config(|config| { + config.optional(); + }) + .to_matchable(), + Sequence::new(vec![ + Ref::keyword("WHERE").to_matchable(), + Ref::new("ExpressionSegment").to_matchable(), + ]) + .config(|config| { + config.optional(); + }) + .to_matchable(), + ]) + .to_matchable(), + ]) + .to_matchable(), + ]) + .to_matchable(), + ); + + trino_dialect.add([( + // A `SET SESSION` statement. + // https://trino.io/docs/current/sql/set-session.html + "SetSessionStatementSegment".into(), + NodeMatcher::new(SyntaxKind::SetSessionStatement, |_| { + Sequence::new(vec![ + Ref::keyword("SET").to_matchable(), + Ref::keyword("SESSION").to_matchable(), + Sequence::new(vec![ + Ref::new("ParameterNameSegment").to_matchable(), + Ref::new("DotSegment").to_matchable(), + ]) + .config(|config| { + config.optional(); + }) + .to_matchable(), + Ref::new("ParameterNameSegment").to_matchable(), + Ref::new("EqualsSegment").to_matchable(), + Ref::new("ExpressionSegment").to_matchable(), + ]) + .to_matchable() + }) + .to_matchable() + .into(), + )]); + trino_dialect.add([ // An 'ANALYZE' statement. // As per docs https://trino.io/docs/current/sql/analyze.html diff --git a/crates/lib-dialects/src/trino_keywords.rs b/crates/lib-dialects/src/trino_keywords.rs index 593877ecb..e21652e09 100644 --- a/crates/lib-dialects/src/trino_keywords.rs +++ b/crates/lib-dialects/src/trino_keywords.rs @@ -33,6 +33,7 @@ FALSE FOR FROM FULL +FUNCTION GROUP GROUPING HAVING diff --git a/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/alter_table.sql b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/alter_table.sql new file mode 100644 index 000000000..18ab7d186 --- /dev/null +++ b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/alter_table.sql @@ -0,0 +1,35 @@ +ALTER TABLE t1 RENAME TO t2; +ALTER TABLE IF EXISTS t1 RENAME TO t2; + +ALTER TABLE t1 ADD COLUMN col1 VARCHAR; +ALTER TABLE t1 ADD COLUMN IF NOT EXISTS col1 VARCHAR; +ALTER TABLE t1 ADD COLUMN col1 VARCHAR NOT NULL; +ALTER TABLE t1 ADD COLUMN col1 VARCHAR COMMENT 'comment'; +ALTER TABLE t1 ADD COLUMN col1 VARCHAR WITH (x = 'y'); +ALTER TABLE t1 ADD COLUMN col1 VARCHAR FIRST; +ALTER TABLE t1 ADD COLUMN col1 VARCHAR LAST; +ALTER TABLE t1 ADD COLUMN col1 VARCHAR AFTER col2; + +ALTER TABLE t1 DROP COLUMN col1; +ALTER TABLE t1 DROP COLUMN IF EXISTS col1; + +ALTER TABLE t1 RENAME COLUMN col1 TO col2; +ALTER TABLE t1 RENAME COLUMN IF EXISTS col1 TO col2; + +ALTER TABLE t1 ALTER COLUMN col1 SET DATA TYPE INTEGER; +ALTER TABLE t1 ALTER COLUMN col1 SET DATA TYPE VARCHAR(100); + +ALTER TABLE t1 ALTER COLUMN col1 DROP NOT NULL; + +ALTER TABLE t1 SET AUTHORIZATION u1; +ALTER TABLE t1 SET AUTHORIZATION USER u1; +ALTER TABLE t1 SET AUTHORIZATION ROLE r1; + +ALTER TABLE t1 SET PROPERTIES x = 'y'; +ALTER TABLE t1 SET PROPERTIES x = DEFAULT; +ALTER TABLE t1 SET PROPERTIES foo = 123, bar = 456; + +ALTER TABLE t1 EXECUTE func; +ALTER TABLE t1 EXECUTE func(x => 'y'); +ALTER TABLE t1 EXECUTE func(foo => 123, bar => 456); +ALTER TABLE t1 EXECUTE func(x => 'y') WHERE col1 > 0; diff --git a/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/alter_table.yml b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/alter_table.yml new file mode 100644 index 000000000..5815e42fa --- /dev/null +++ b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/alter_table.yml @@ -0,0 +1,414 @@ +file: +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: RENAME + - keyword: TO + - table_reference: + - naked_identifier: t2 +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - keyword: IF + - keyword: EXISTS + - table_reference: + - naked_identifier: t1 + - keyword: RENAME + - keyword: TO + - table_reference: + - naked_identifier: t2 +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: ADD + - keyword: COLUMN + - column_definition: + - naked_identifier: col1 + - data_type: + - keyword: VARCHAR +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: ADD + - keyword: COLUMN + - keyword: IF + - keyword: NOT + - keyword: EXISTS + - column_definition: + - naked_identifier: col1 + - data_type: + - keyword: VARCHAR +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: ADD + - keyword: COLUMN + - column_definition: + - naked_identifier: col1 + - data_type: + - keyword: VARCHAR + - keyword: NOT + - keyword: 'NULL' +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: ADD + - keyword: COLUMN + - column_definition: + - naked_identifier: col1 + - data_type: + - keyword: VARCHAR + - comment_clause: + - keyword: COMMENT + - quoted_literal: '''comment''' +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: ADD + - keyword: COLUMN + - column_definition: + - naked_identifier: col1 + - data_type: + - keyword: VARCHAR + - keyword: WITH + - bracketed: + - start_bracket: ( + - expression: + - column_reference: + - naked_identifier: x + - comparison_operator: + - raw_comparison_operator: = + - quoted_literal: '''y''' + - end_bracket: ) +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: ADD + - keyword: COLUMN + - column_definition: + - naked_identifier: col1 + - data_type: + - keyword: VARCHAR + - keyword: FIRST +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: ADD + - keyword: COLUMN + - column_definition: + - naked_identifier: col1 + - data_type: + - keyword: VARCHAR + - keyword: LAST +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: ADD + - keyword: COLUMN + - column_definition: + - naked_identifier: col1 + - data_type: + - keyword: VARCHAR + - keyword: AFTER + - column_reference: + - naked_identifier: col2 +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: DROP + - keyword: COLUMN + - column_reference: + - naked_identifier: col1 +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: DROP + - keyword: COLUMN + - keyword: IF + - keyword: EXISTS + - column_reference: + - naked_identifier: col1 +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: RENAME + - keyword: COLUMN + - column_reference: + - naked_identifier: col1 + - keyword: TO + - column_reference: + - naked_identifier: col2 +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: RENAME + - keyword: COLUMN + - keyword: IF + - keyword: EXISTS + - column_reference: + - naked_identifier: col1 + - keyword: TO + - column_reference: + - naked_identifier: col2 +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: ALTER + - keyword: COLUMN + - column_reference: + - naked_identifier: col1 + - keyword: SET + - keyword: DATA + - keyword: TYPE + - data_type: + - keyword: INTEGER +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: ALTER + - keyword: COLUMN + - column_reference: + - naked_identifier: col1 + - keyword: SET + - keyword: DATA + - keyword: TYPE + - data_type: + - keyword: VARCHAR + - bracketed_arguments: + - bracketed: + - start_bracket: ( + - numeric_literal: '100' + - end_bracket: ) +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: ALTER + - keyword: COLUMN + - column_reference: + - naked_identifier: col1 + - keyword: DROP + - keyword: NOT + - keyword: 'NULL' +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: SET + - keyword: AUTHORIZATION + - role_reference: + - naked_identifier: u1 +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: SET + - keyword: AUTHORIZATION + - keyword: USER + - role_reference: + - naked_identifier: u1 +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: SET + - keyword: AUTHORIZATION + - keyword: ROLE + - role_reference: + - naked_identifier: r1 +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: SET + - keyword: PROPERTIES + - parameter: x + - comparison_operator: + - raw_comparison_operator: = + - expression: + - quoted_literal: '''y''' +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: SET + - keyword: PROPERTIES + - parameter: x + - comparison_operator: + - raw_comparison_operator: = + - expression: + - column_reference: + - naked_identifier: DEFAULT +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: SET + - keyword: PROPERTIES + - parameter: foo + - comparison_operator: + - raw_comparison_operator: = + - expression: + - numeric_literal: '123' + - comma: ',' + - parameter: bar + - comparison_operator: + - raw_comparison_operator: = + - expression: + - numeric_literal: '456' +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: EXECUTE + - function_name: + - function_name_identifier: func +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: EXECUTE + - function_name: + - function_name_identifier: func + - bracketed: + - start_bracket: ( + - parameter: x + - execute_arrow: => + - expression: + - quoted_literal: '''y''' + - end_bracket: ) +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: EXECUTE + - function_name: + - function_name_identifier: func + - bracketed: + - start_bracket: ( + - parameter: foo + - execute_arrow: => + - expression: + - numeric_literal: '123' + - comma: ',' + - parameter: bar + - execute_arrow: => + - expression: + - numeric_literal: '456' + - end_bracket: ) +- statement_terminator: ; +- statement: + - alter_table_statement: + - keyword: ALTER + - keyword: TABLE + - table_reference: + - naked_identifier: t1 + - keyword: EXECUTE + - function_name: + - function_name_identifier: func + - bracketed: + - start_bracket: ( + - parameter: x + - execute_arrow: => + - expression: + - quoted_literal: '''y''' + - end_bracket: ) + - keyword: WHERE + - expression: + - column_reference: + - naked_identifier: col1 + - comparison_operator: + - raw_comparison_operator: '>' + - numeric_literal: '0' +- statement_terminator: ; diff --git a/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/commit.sql b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/commit.sql new file mode 100644 index 000000000..a3f09c359 --- /dev/null +++ b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/commit.sql @@ -0,0 +1,3 @@ +COMMIT; + +COMMIT WORK; diff --git a/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/commit.yml b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/commit.yml new file mode 100644 index 000000000..2221ee95b --- /dev/null +++ b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/commit.yml @@ -0,0 +1,10 @@ +file: +- statement: + - transaction_statement: + - keyword: COMMIT +- statement_terminator: ; +- statement: + - transaction_statement: + - keyword: COMMIT + - keyword: WORK +- statement_terminator: ; diff --git a/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/create_table.sql b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/create_table.sql new file mode 100644 index 000000000..e8ccc7459 --- /dev/null +++ b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/create_table.sql @@ -0,0 +1,68 @@ +CREATE TABLE a ( + str varchar +); + +create table if not exists foo.bar.baz +( +date_nk date, +date_ts timestamp, +site varchar(30), +partition_date date +) +with ( +format = 'parquet', +partitioned_by = array ['partition_date'] +); + +CREATE TABLE orders ( + orderkey bigint, + orderstatus varchar, + totalprice double, + orderdate date +) +WITH (format = 'ORC') +; + +CREATE TABLE IF NOT EXISTS orders ( + orderkey bigint, + orderstatus varchar, + totalprice double COMMENT 'Price in cents.', + shipmentstatus varchar not null, + orderdate date +) +COMMENT 'A table to keep track of orders.' +; + +CREATE TABLE bigger_orders ( + another_orderkey bigint, + LIKE orders, + another_orderdate date +) +; + +CREATE TABLE orders_column_aliased (order_date, total_price) +AS +SELECT orderdate, totalprice +FROM orders +; + +CREATE TABLE orders_by_date +COMMENT 'Summary of orders by date' +WITH (format = 'ORC') +AS +SELECT orderdate, sum(totalprice) AS price +FROM orders +GROUP BY orderdate +; + +CREATE TABLE IF NOT EXISTS orders_by_date AS +SELECT orderdate, sum(totalprice) AS price +FROM orders +GROUP BY orderdate +; + +CREATE TABLE empty_nation AS +SELECT * +FROM nation +WITH NO DATA +; diff --git a/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/create_table.yml b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/create_table.yml new file mode 100644 index 000000000..34fb3cff1 --- /dev/null +++ b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/create_table.yml @@ -0,0 +1,344 @@ +file: +- statement: + - create_table_statement: + - keyword: CREATE + - keyword: TABLE + - table_reference: + - naked_identifier: a + - bracketed: + - start_bracket: ( + - column_definition: + - naked_identifier: str + - data_type: + - keyword: varchar + - end_bracket: ) +- statement_terminator: ; +- statement: + - create_table_statement: + - keyword: create + - keyword: table + - keyword: if + - keyword: not + - keyword: exists + - table_reference: + - naked_identifier: foo + - dot: . + - naked_identifier: bar + - dot: . + - naked_identifier: baz + - bracketed: + - start_bracket: ( + - column_definition: + - naked_identifier: date_nk + - data_type: + - keyword: date + - comma: ',' + - column_definition: + - naked_identifier: date_ts + - data_type: + - keyword: timestamp + - comma: ',' + - column_definition: + - naked_identifier: site + - data_type: + - keyword: varchar + - bracketed_arguments: + - bracketed: + - start_bracket: ( + - numeric_literal: '30' + - end_bracket: ) + - comma: ',' + - column_definition: + - naked_identifier: partition_date + - data_type: + - keyword: date + - end_bracket: ) + - keyword: with + - bracketed: + - start_bracket: ( + - expression: + - column_reference: + - naked_identifier: format + - comparison_operator: + - raw_comparison_operator: = + - quoted_literal: '''parquet''' + - comma: ',' + - expression: + - column_reference: + - naked_identifier: partitioned_by + - comparison_operator: + - raw_comparison_operator: = + - typed_array_literal: + - array_type: + - keyword: array + - array_literal: + - start_square_bracket: '[' + - quoted_literal: '''partition_date''' + - end_square_bracket: ']' + - end_bracket: ) +- statement_terminator: ; +- statement: + - create_table_statement: + - keyword: CREATE + - keyword: TABLE + - table_reference: + - naked_identifier: orders + - bracketed: + - start_bracket: ( + - column_definition: + - naked_identifier: orderkey + - data_type: + - keyword: bigint + - comma: ',' + - column_definition: + - naked_identifier: orderstatus + - data_type: + - keyword: varchar + - comma: ',' + - column_definition: + - naked_identifier: totalprice + - data_type: + - keyword: double + - comma: ',' + - column_definition: + - naked_identifier: orderdate + - data_type: + - keyword: date + - end_bracket: ) + - keyword: WITH + - bracketed: + - start_bracket: ( + - expression: + - column_reference: + - naked_identifier: format + - comparison_operator: + - raw_comparison_operator: = + - quoted_literal: '''ORC''' + - end_bracket: ) +- statement_terminator: ; +- statement: + - create_table_statement: + - keyword: CREATE + - keyword: TABLE + - keyword: IF + - keyword: NOT + - keyword: EXISTS + - table_reference: + - naked_identifier: orders + - bracketed: + - start_bracket: ( + - column_definition: + - naked_identifier: orderkey + - data_type: + - keyword: bigint + - comma: ',' + - column_definition: + - naked_identifier: orderstatus + - data_type: + - keyword: varchar + - comma: ',' + - column_definition: + - naked_identifier: totalprice + - data_type: + - keyword: double + - comment_clause: + - keyword: COMMENT + - quoted_literal: '''Price in cents.''' + - comma: ',' + - column_definition: + - naked_identifier: shipmentstatus + - data_type: + - keyword: varchar + - keyword: not + - keyword: 'null' + - comma: ',' + - column_definition: + - naked_identifier: orderdate + - data_type: + - keyword: date + - end_bracket: ) + - comment_clause: + - keyword: COMMENT + - quoted_literal: '''A table to keep track of orders.''' +- statement_terminator: ; +- statement: + - create_table_statement: + - keyword: CREATE + - keyword: TABLE + - table_reference: + - naked_identifier: bigger_orders + - bracketed: + - start_bracket: ( + - column_definition: + - naked_identifier: another_orderkey + - data_type: + - keyword: bigint + - comma: ',' + - keyword: LIKE + - table_reference: + - naked_identifier: orders + - comma: ',' + - column_definition: + - naked_identifier: another_orderdate + - data_type: + - keyword: date + - end_bracket: ) +- statement_terminator: ; +- statement: + - create_table_statement: + - keyword: CREATE + - keyword: TABLE + - table_reference: + - naked_identifier: orders_column_aliased + - bracketed: + - start_bracket: ( + - column_reference: + - naked_identifier: order_date + - comma: ',' + - column_reference: + - naked_identifier: total_price + - end_bracket: ) + - keyword: AS + - select_statement: + - select_clause: + - keyword: SELECT + - select_clause_element: + - column_reference: + - naked_identifier: orderdate + - comma: ',' + - select_clause_element: + - column_reference: + - naked_identifier: totalprice + - from_clause: + - keyword: FROM + - from_expression: + - from_expression_element: + - table_expression: + - table_reference: + - naked_identifier: orders +- statement_terminator: ; +- statement: + - create_table_statement: + - keyword: CREATE + - keyword: TABLE + - table_reference: + - naked_identifier: orders_by_date + - comment_clause: + - keyword: COMMENT + - quoted_literal: '''Summary of orders by date''' + - keyword: WITH + - bracketed: + - start_bracket: ( + - expression: + - column_reference: + - naked_identifier: format + - comparison_operator: + - raw_comparison_operator: = + - quoted_literal: '''ORC''' + - end_bracket: ) + - keyword: AS + - select_statement: + - select_clause: + - keyword: SELECT + - select_clause_element: + - column_reference: + - naked_identifier: orderdate + - comma: ',' + - select_clause_element: + - function: + - function_name: + - function_name_identifier: sum + - function_contents: + - bracketed: + - start_bracket: ( + - expression: + - column_reference: + - naked_identifier: totalprice + - end_bracket: ) + - alias_expression: + - alias_operator: + - keyword: AS + - naked_identifier: price + - from_clause: + - keyword: FROM + - from_expression: + - from_expression_element: + - table_expression: + - table_reference: + - naked_identifier: orders + - groupby_clause: + - keyword: GROUP + - keyword: BY + - column_reference: + - naked_identifier: orderdate +- statement_terminator: ; +- statement: + - create_table_statement: + - keyword: CREATE + - keyword: TABLE + - keyword: IF + - keyword: NOT + - keyword: EXISTS + - table_reference: + - naked_identifier: orders_by_date + - keyword: AS + - select_statement: + - select_clause: + - keyword: SELECT + - select_clause_element: + - column_reference: + - naked_identifier: orderdate + - comma: ',' + - select_clause_element: + - function: + - function_name: + - function_name_identifier: sum + - function_contents: + - bracketed: + - start_bracket: ( + - expression: + - column_reference: + - naked_identifier: totalprice + - end_bracket: ) + - alias_expression: + - alias_operator: + - keyword: AS + - naked_identifier: price + - from_clause: + - keyword: FROM + - from_expression: + - from_expression_element: + - table_expression: + - table_reference: + - naked_identifier: orders + - groupby_clause: + - keyword: GROUP + - keyword: BY + - column_reference: + - naked_identifier: orderdate +- statement_terminator: ; +- statement: + - create_table_statement: + - keyword: CREATE + - keyword: TABLE + - table_reference: + - naked_identifier: empty_nation + - keyword: AS + - select_statement: + - select_clause: + - keyword: SELECT + - select_clause_element: + - wildcard_expression: + - wildcard_identifier: + - star: '*' + - from_clause: + - keyword: FROM + - from_expression: + - from_expression_element: + - table_expression: + - table_reference: + - naked_identifier: nation + - keyword: WITH + - keyword: NO + - keyword: DATA +- statement_terminator: ; diff --git a/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/insert.sql b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/insert.sql new file mode 100644 index 000000000..4920fbdc6 --- /dev/null +++ b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/insert.sql @@ -0,0 +1,7 @@ +INSERT INTO t1 SELECT * FROM t2; + +INSERT INTO t1 VALUES (1, 'San Francisco'); + +INSERT INTO t1 (a,b,c) SELECT * FROM t2; + +INSERT INTO t1 (a,b,c) VALUES (26, 'POLAND', 3); diff --git a/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/insert.yml b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/insert.yml new file mode 100644 index 000000000..2d4c99d9f --- /dev/null +++ b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/insert.yml @@ -0,0 +1,99 @@ +file: +- statement: + - insert_statement: + - keyword: INSERT + - keyword: INTO + - table_reference: + - naked_identifier: t1 + - select_statement: + - select_clause: + - keyword: SELECT + - select_clause_element: + - wildcard_expression: + - wildcard_identifier: + - star: '*' + - from_clause: + - keyword: FROM + - from_expression: + - from_expression_element: + - table_expression: + - table_reference: + - naked_identifier: t2 +- statement_terminator: ; +- statement: + - insert_statement: + - keyword: INSERT + - keyword: INTO + - table_reference: + - naked_identifier: t1 + - values_clause: + - keyword: VALUES + - expression: + - bracketed: + - start_bracket: ( + - numeric_literal: '1' + - comma: ',' + - quoted_literal: '''San Francisco''' + - end_bracket: ) +- statement_terminator: ; +- statement: + - insert_statement: + - keyword: INSERT + - keyword: INTO + - table_reference: + - naked_identifier: t1 + - bracketed: + - start_bracket: ( + - column_reference: + - naked_identifier: a + - comma: ',' + - column_reference: + - naked_identifier: b + - comma: ',' + - column_reference: + - naked_identifier: c + - end_bracket: ) + - select_statement: + - select_clause: + - keyword: SELECT + - select_clause_element: + - wildcard_expression: + - wildcard_identifier: + - star: '*' + - from_clause: + - keyword: FROM + - from_expression: + - from_expression_element: + - table_expression: + - table_reference: + - naked_identifier: t2 +- statement_terminator: ; +- statement: + - insert_statement: + - keyword: INSERT + - keyword: INTO + - table_reference: + - naked_identifier: t1 + - bracketed: + - start_bracket: ( + - column_reference: + - naked_identifier: a + - comma: ',' + - column_reference: + - naked_identifier: b + - comma: ',' + - column_reference: + - naked_identifier: c + - end_bracket: ) + - values_clause: + - keyword: VALUES + - expression: + - bracketed: + - start_bracket: ( + - numeric_literal: '26' + - comma: ',' + - quoted_literal: '''POLAND''' + - comma: ',' + - numeric_literal: '3' + - end_bracket: ) +- statement_terminator: ; diff --git a/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/rollback.sql b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/rollback.sql new file mode 100644 index 000000000..77013a810 --- /dev/null +++ b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/rollback.sql @@ -0,0 +1,3 @@ +ROLLBACK; + +ROLLBACK WORK; diff --git a/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/rollback.yml b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/rollback.yml new file mode 100644 index 000000000..3eb95ee93 --- /dev/null +++ b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/rollback.yml @@ -0,0 +1,10 @@ +file: +- statement: + - transaction_statement: + - keyword: ROLLBACK +- statement_terminator: ; +- statement: + - transaction_statement: + - keyword: ROLLBACK + - keyword: WORK +- statement_terminator: ; diff --git a/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/set_session.sql b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/set_session.sql new file mode 100644 index 000000000..379bc0ef0 --- /dev/null +++ b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/set_session.sql @@ -0,0 +1,3 @@ +SET SESSION name = 'expression'; + +SET SESSION catalog.value = 100; diff --git a/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/set_session.yml b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/set_session.yml new file mode 100644 index 000000000..e80f091e9 --- /dev/null +++ b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/set_session.yml @@ -0,0 +1,23 @@ +file: +- statement: + - set_session_statement: + - keyword: SET + - keyword: SESSION + - parameter: name + - comparison_operator: + - raw_comparison_operator: = + - expression: + - quoted_literal: '''expression''' +- statement_terminator: ; +- statement: + - set_session_statement: + - keyword: SET + - keyword: SESSION + - parameter: catalog + - dot: . + - parameter: value + - comparison_operator: + - raw_comparison_operator: = + - expression: + - numeric_literal: '100' +- statement_terminator: ; diff --git a/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/start_transaction.sql b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/start_transaction.sql new file mode 100644 index 000000000..a3d42ead8 --- /dev/null +++ b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/start_transaction.sql @@ -0,0 +1,5 @@ +START TRANSACTION; +START TRANSACTION ISOLATION LEVEL REPEATABLE READ; +START TRANSACTION READ WRITE; +START TRANSACTION ISOLATION LEVEL READ COMMITTED, READ ONLY; +START TRANSACTION READ WRITE, ISOLATION LEVEL SERIALIZABLE; diff --git a/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/start_transaction.yml b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/start_transaction.yml new file mode 100644 index 000000000..6ddb5134e --- /dev/null +++ b/crates/lib-dialects/test/fixtures/dialects/trino/sqlfluff/start_transaction.yml @@ -0,0 +1,45 @@ +file: +- statement: + - transaction_statement: + - keyword: START + - keyword: TRANSACTION +- statement_terminator: ; +- statement: + - transaction_statement: + - keyword: START + - keyword: TRANSACTION + - keyword: ISOLATION + - keyword: LEVEL + - keyword: REPEATABLE + - keyword: READ +- statement_terminator: ; +- statement: + - transaction_statement: + - keyword: START + - keyword: TRANSACTION + - keyword: READ + - keyword: WRITE +- statement_terminator: ; +- statement: + - transaction_statement: + - keyword: START + - keyword: TRANSACTION + - keyword: ISOLATION + - keyword: LEVEL + - keyword: READ + - keyword: COMMITTED + - comma: ',' + - keyword: READ + - keyword: ONLY +- statement_terminator: ; +- statement: + - transaction_statement: + - keyword: START + - keyword: TRANSACTION + - keyword: READ + - keyword: WRITE + - comma: ',' + - keyword: ISOLATION + - keyword: LEVEL + - keyword: SERIALIZABLE +- statement_terminator: ;