Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions sqlglot/dialects/snowflake.py
Original file line number Diff line number Diff line change
Expand Up @@ -1324,6 +1324,9 @@ class Tokenizer(tokens.Tokenizer):
"TIMESTAMP_TZ": TokenType.TIMESTAMPTZ,
"TOP": TokenType.TOP,
"WAREHOUSE": TokenType.WAREHOUSE,
# https://docs.snowflake.com/en/sql-reference/data-types-numeric#float
# FLOAT is a synonym for DOUBLE in Snowflake
"FLOAT": TokenType.DOUBLE,
}
KEYWORDS.pop("/*+")

Expand Down Expand Up @@ -1573,6 +1576,15 @@ def values_sql(self, expression: exp.Values, values_as_table: bool = True) -> st
return super().values_sql(expression, values_as_table=values_as_table)

def datatype_sql(self, expression: exp.DataType) -> str:
# Check if this is a FLOAT type nested inside a VECTOR type
# VECTOR only accepts FLOAT (not DOUBLE), INT, and STRING as element types
# https://docs.snowflake.com/en/sql-reference/data-types-vector
if expression.is_type(exp.DataType.Type.DOUBLE):
parent = expression.parent
if isinstance(parent, exp.DataType) and parent.is_type(exp.DataType.Type.VECTOR):
# Preserve FLOAT for VECTOR types instead of mapping to synonym DOUBLE
return "FLOAT"

expressions = expression.expressions
if expressions and expression.is_type(*exp.DataType.STRUCT_TYPES):
for field_type in expressions:
Expand Down
8 changes: 4 additions & 4 deletions sqlglot/typing/snowflake.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def _annotate_median(self: TypeAnnotator, expression: exp.Median) -> exp.Median:
"""Annotate MEDIAN function with correct return type.

Based on Snowflake documentation:
- If the expr is FLOAT -> annotate as FLOAT
- If the expr is FLOAT/DOUBLE -> annotate as DOUBLE (FLOAT is a synonym for DOUBLE)
- If the expr is NUMBER(p, s) -> annotate as NUMBER(min(p+3, 38), min(s+3, 37))
"""
# First annotate the argument to get its type
Expand All @@ -119,9 +119,9 @@ def _annotate_median(self: TypeAnnotator, expression: exp.Median) -> exp.Median:
# Get the input type
input_type = expression.this.type

if input_type.is_type(exp.DataType.Type.FLOAT):
# If input is FLOAT, return FLOAT
self._set_type(expression, exp.DataType.Type.FLOAT)
if input_type.is_type(exp.DataType.Type.DOUBLE, exp.DataType.Type.FLOAT):
# If input is FLOAT/DOUBLE, return DOUBLE (FLOAT is normalized to DOUBLE in Snowflake)
self._set_type(expression, exp.DataType.Type.DOUBLE)
else:
# If input is NUMBER(p, s), return NUMBER(min(p+3, 38), min(s+3, 37))
exprs = input_type.expressions
Expand Down
9 changes: 8 additions & 1 deletion tests/dialects/test_snowflake.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ def test_snowflake(self):
self.validate_identity("$x") # parameter
self.validate_identity("a$b") # valid snowflake identifier
self.validate_identity("SELECT REGEXP_LIKE(a, b, c)")
self.validate_identity("CREATE TABLE foo (bar FLOAT AUTOINCREMENT START 0 INCREMENT 1)")
self.validate_identity("CREATE TABLE foo (bar DOUBLE AUTOINCREMENT START 0 INCREMENT 1)")
self.validate_identity("COMMENT IF EXISTS ON TABLE foo IS 'bar'")
self.validate_identity("SELECT CONVERT_TIMEZONE('UTC', 'America/Los_Angeles', col)")
self.validate_identity("SELECT CURRENT_ORGANIZATION_NAME()")
Expand Down Expand Up @@ -1797,6 +1797,13 @@ def test_snowflake(self):
"duckdb": "SET VARIABLE a = 1",
},
)
self.validate_all(
"CAST(6.43 AS FLOAT)",
write={
"snowflake": "CAST(6.43 AS DOUBLE)",
"duckdb": "CAST(6.43 AS DOUBLE)",
},
)

def test_null_treatment(self):
self.validate_all(
Expand Down