diff --git a/src/sqlfluff/dialects/dialect_duckdb.py b/src/sqlfluff/dialects/dialect_duckdb.py index 4b41b37b118..51e71a996fc 100644 --- a/src/sqlfluff/dialects/dialect_duckdb.py +++ b/src/sqlfluff/dialects/dialect_duckdb.py @@ -10,6 +10,7 @@ BinaryOperatorSegment, Bracketed, CodeSegment, + ComparisonOperatorSegment, Dedent, Delimited, IdentifierSegment, @@ -74,6 +75,7 @@ duckdb_dialect.add( LambdaArrowSegment=StringParser("->", SymbolSegment, type="lambda_arrow"), OrIgnoreGrammar=Sequence("OR", "IGNORE"), + EqualsSegment_a=StringParser("==", ComparisonOperatorSegment), ) duckdb_dialect.replace( @@ -142,6 +144,13 @@ "single_quote", IdentifierSegment, type="quoted_identifier", casefold=str.lower ), ListComprehensionGrammar=Ref("ListComprehensionExpressionSegment"), + ComparisonOperatorGrammar=ansi_dialect.get_grammar( + "ComparisonOperatorGrammar" + ).copy( + insert=[ + Ref("EqualsSegment_a"), + ] + ), ) duckdb_dialect.insert_lexer_matchers( @@ -173,6 +182,7 @@ "escape_replacements": [(r'""', '"')], }, ), + RegexLexer("equals", r"==?", CodeSegment), ] ) diff --git a/test/fixtures/dialects/duckdb/double_equal.sql b/test/fixtures/dialects/duckdb/double_equal.sql new file mode 100644 index 00000000000..427afdd1590 --- /dev/null +++ b/test/fixtures/dialects/duckdb/double_equal.sql @@ -0,0 +1,7 @@ +SELECT + COALESCE( + MAX(CASE WHEN col1 == 'A' THEN cola END), + MAX(CASE WHEN col1 == 'B' THEN colb END), + MAX(CASE WHEN col1 = 'C' THEN colb END) + ) AS result +FROM my_table; diff --git a/test/fixtures/dialects/duckdb/double_equal.yml b/test/fixtures/dialects/duckdb/double_equal.yml new file mode 100644 index 00000000000..0117b453457 --- /dev/null +++ b/test/fixtures/dialects/duckdb/double_equal.yml @@ -0,0 +1,102 @@ +# YML test files are auto-generated from SQL files and should not be edited by +# hand. To help enforce this, the "hash" field in the file must match a hash +# computed by SQLFluff when running the tests. Please run +# `python test/generate_parse_fixture_yml.py` to generate them after adding or +# altering SQL files. +_hash: 8f84857317f2db485136f25707f1a315933c79426a5b55ed8d253d5370903bfd +file: + statement: + select_statement: + select_clause: + keyword: SELECT + select_clause_element: + function: + function_name: + function_name_identifier: COALESCE + function_contents: + bracketed: + - start_bracket: ( + - expression: + function: + function_name: + function_name_identifier: MAX + function_contents: + bracketed: + start_bracket: ( + expression: + case_expression: + - keyword: CASE + - when_clause: + - keyword: WHEN + - expression: + column_reference: + naked_identifier: col1 + comparison_operator: == + quoted_literal: "'A'" + - keyword: THEN + - expression: + column_reference: + naked_identifier: cola + - keyword: END + end_bracket: ) + - comma: ',' + - expression: + function: + function_name: + function_name_identifier: MAX + function_contents: + bracketed: + start_bracket: ( + expression: + case_expression: + - keyword: CASE + - when_clause: + - keyword: WHEN + - expression: + column_reference: + naked_identifier: col1 + comparison_operator: == + quoted_literal: "'B'" + - keyword: THEN + - expression: + column_reference: + naked_identifier: colb + - keyword: END + end_bracket: ) + - comma: ',' + - expression: + function: + function_name: + function_name_identifier: MAX + function_contents: + bracketed: + start_bracket: ( + expression: + case_expression: + - keyword: CASE + - when_clause: + - keyword: WHEN + - expression: + column_reference: + naked_identifier: col1 + comparison_operator: + raw_comparison_operator: '=' + quoted_literal: "'C'" + - keyword: THEN + - expression: + column_reference: + naked_identifier: colb + - keyword: END + end_bracket: ) + - end_bracket: ) + alias_expression: + keyword: AS + naked_identifier: result + from_clause: + keyword: FROM + from_expression: + from_expression_element: + table_expression: + table_reference: + naked_identifier: my_table + statement_terminator: ;