Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add handling for Redshift CONVERT function data type argument #3653

Merged
merged 1 commit into from Jul 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
73 changes: 73 additions & 0 deletions src/sqlfluff/dialects/dialect_redshift.py
Expand Up @@ -2308,3 +2308,76 @@ class SelectClauseModifierSegment(postgres.SelectClauseModifierSegment):
match_grammar = postgres.SelectClauseModifierSegment.match_grammar.copy(
insert=[Sequence("TOP", Ref("NumericLiteralSegment"))],
)


class ConvertFunctionNameSegment(BaseSegment):
"""CONVERT function name segment.

Function taking a data type identifier and an expression.
An alternative to CAST.
"""

type = "function_name"
match_grammar = Sequence("CONVERT")


class FunctionSegment(ansi.FunctionSegment):
"""A scalar or aggregate function.

Maybe in the future we should distinguish between
aggregate functions and other functions. For now
we treat them the same because they look the same
for our purposes.
"""

type = "function"
match_grammar: Matchable = OneOf(
Sequence(
# Treat functions which take date parts separately
# So those functions parse date parts as DatetimeUnitSegment
# rather than identifiers.
Sequence(
Ref("DatePartFunctionNameSegment"),
Bracketed(
Delimited(
Ref("DatetimeUnitSegment"),
Ref(
"FunctionContentsGrammar",
# The brackets might be empty for some functions...
optional=True,
ephemeral_name="FunctionContentsGrammar",
),
)
),
),
),
Sequence(
Sequence(
Ref(
"FunctionNameSegment",
exclude=OneOf(
Ref("DatePartFunctionNameSegment"),
Ref("ValuesClauseSegment"),
Ref("ConvertFunctionNameSegment"),
),
),
Bracketed(
Ref(
"FunctionContentsGrammar",
# The brackets might be empty for some functions...
optional=True,
ephemeral_name="FunctionContentsGrammar",
)
),
),
Ref("PostFunctionGrammar", optional=True),
),
Sequence(
Ref("ConvertFunctionNameSegment"),
Bracketed(
Ref("DatatypeSegment"),
Ref("CommaSegment"),
Ref("ExpressionSegment"),
),
),
)
78 changes: 36 additions & 42 deletions test/fixtures/dialects/redshift/redshift_cast_conversion.yml
Expand Up @@ -3,7 +3,7 @@
# 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: d88e5f09aebf827225e0e8212e0629860009f8d5ac1bdb6f8df8abbd37bcbda4
_hash: 29b2bd2f7511b32a80bbd5d7ef8cfdc99ef123a566c1f35099f3d97b439675da
file:
- statement:
select_statement:
Expand Down Expand Up @@ -37,17 +37,16 @@ file:
select_clause_element:
function:
function_name:
function_name_identifier: convert
keyword: convert
bracketed:
- start_bracket: (
- expression:
column_reference:
identifier: integer
- comma: ','
- expression:
start_bracket: (
data_type:
keyword: integer
comma: ','
expression:
column_reference:
identifier: col1
- end_bracket: )
end_bracket: )
from_clause:
keyword: from
from_expression:
Expand Down Expand Up @@ -109,17 +108,17 @@ file:
select_clause_element:
function:
function_name:
function_name_identifier: convert
keyword: convert
bracketed:
- start_bracket: (
- expression:
column_reference:
identifier: timestamptz
- comma: ','
- expression:
start_bracket: (
data_type:
datetime_type_identifier:
keyword: timestamptz
comma: ','
expression:
column_reference:
identifier: col1
- end_bracket: )
end_bracket: )
from_clause:
keyword: from
from_expression:
Expand Down Expand Up @@ -187,26 +186,22 @@ file:
select_clause_element:
function:
function_name:
function_name_identifier: convert
keyword: convert
bracketed:
- start_bracket: (
- expression:
function:
function_name:
function_name_identifier: decimal
bracketed:
- start_bracket: (
- expression:
literal: '38'
- comma: ','
- expression:
literal: '2'
- end_bracket: )
- comma: ','
- expression:
start_bracket: (
data_type:
keyword: decimal
bracketed:
- start_bracket: (
- literal: '38'
- comma: ','
- literal: '2'
- end_bracket: )
comma: ','
expression:
column_reference:
identifier: col1
- end_bracket: )
end_bracket: )
from_clause:
keyword: from
from_expression:
Expand Down Expand Up @@ -273,17 +268,16 @@ file:
select_clause_element:
function:
function_name:
function_name_identifier: convert
keyword: convert
bracketed:
- start_bracket: (
- expression:
column_reference:
identifier: interval
- comma: ','
- expression:
start_bracket: (
data_type:
keyword: interval
comma: ','
expression:
column_reference:
identifier: col1
- end_bracket: )
end_bracket: )
from_clause:
keyword: from
from_expression:
Expand Down
13 changes: 13 additions & 0 deletions test/fixtures/rules/std_rule_cases/L027.yml
Expand Up @@ -336,3 +336,16 @@ test_pass_ansi:
INNER JOIN mapping_table ON (mapping_table.other_fk = other_table.id_pk)
WHERE mapping_table.kind = my_table.kind
)

test_pass_redshift_convert:
# This was failing in issue 3651.
pass_str: |
SELECT
sellers.name,
CONVERT(integer, sales.pricepaid) AS price
FROM sales
LEFT JOIN sellers ON sales.sellerid = sellers.sellerid
WHERE sales.salesid = 100
configs:
core:
dialect: redshift