Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion converter_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@
STORAGE_ENGINE_PORT = os.getenv("STORAGE_ENGINE_PORT", 9005)
SKIP_COMMENT = os.getenv("SKIP_COMMENT", "True") # Always strip multi-line comments
FIX_QUOTE_ESCAPES = os.getenv("FIX_QUOTE_ESCAPES", "False") # Fix '' inside single-quoted strings
E6_EXECUTOR_TYPE = os.getenv(
"E6_EXECUTOR_TYPE", "java"
) # "java" divides TO_UNIX_TIMESTAMP by 1000; "native" does not

storage_service_client = None

Expand All @@ -65,10 +68,11 @@
logger.info("Storage Service Client is created")
logger.info(
"Environment flags — ENABLE_GUARDRAIL: %s, SKIP_COMMENT: %s, FIX_QUOTE_ESCAPES: %s, "
"STORAGE_ENGINE_URL: %s, STORAGE_ENGINE_PORT: %s",
"E6_EXECUTOR_TYPE: %s, STORAGE_ENGINE_URL: %s, STORAGE_ENGINE_PORT: %s",
ENABLE_GUARDRAIL,
SKIP_COMMENT,
FIX_QUOTE_ESCAPES,
E6_EXECUTOR_TYPE,
STORAGE_ENGINE_URL,
STORAGE_ENGINE_PORT,
)
Expand Down
16 changes: 10 additions & 6 deletions sqlglot/dialects/e6.py
Original file line number Diff line number Diff line change
Expand Up @@ -2626,22 +2626,26 @@ def to_unix_timestamp_sql(
time_expr = expression.this
format_expr = expression.args.get("format")

# Java executor returns milliseconds so divide by 1000 to get seconds.
# Native executor already returns seconds (matches Databricks) so skip the division.
is_native = os.getenv("E6_EXECUTOR_TYPE", "java").lower() == "native"

if format_expr:
format_str = format_expr.this
for key, value in E6().TIME_MAPPING_FOR_PARSE_FUNCTIONS.items():
format_str = format_str.replace(key, value)

# Generate final function with or without format argument
if format_str:
# Build expression tree for TO_UNIX_TIMESTAMP(PARSE_DATETIME(...)) / 1000
parse_datetime_expr = exp.Anonymous(
this="PARSE_DATETIME", expressions=[exp.Literal.string(format_str), time_expr]
)
to_unix_expr = exp.Anonymous(
this="TO_UNIX_TIMESTAMP", expressions=[parse_datetime_expr]
)
div_expr = exp.Div(this=to_unix_expr, expression=exp.Literal.number("1000"))
return self.sql(div_expr)
if is_native:
return self.sql(to_unix_expr)
return self.sql(exp.Div(this=to_unix_expr, expression=exp.Literal.number("1000")))

# Wrap argument in CAST(... AS TIMESTAMP) since E6's TO_UNIX_TIMESTAMP
# only accepts TIMESTAMP/DATE types, not integers or strings
Expand All @@ -2651,10 +2655,10 @@ def to_unix_timestamp_sql(
):
time_expr = exp.Cast(this=time_expr, to=exp.DataType.build("TIMESTAMP"))

# Build expression tree for TO_UNIX_TIMESTAMP(CAST(... AS TIMESTAMP)) / 1000
to_unix_expr = exp.Anonymous(this="TO_UNIX_TIMESTAMP", expressions=[time_expr])
div_expr = exp.Div(this=to_unix_expr, expression=exp.Literal.number("1000"))
return self.sql(div_expr)
if is_native:
return self.sql(to_unix_expr)
return self.sql(exp.Div(this=to_unix_expr, expression=exp.Literal.number("1000")))

def lateral_sql(self, expression: exp.Lateral) -> str:
expression.set("view", True)
Expand Down
24 changes: 24 additions & 0 deletions tests/dialects/test_e6.py
Original file line number Diff line number Diff line change
Expand Up @@ -2453,6 +2453,30 @@ def test_unixtime_functions(self):
},
)

def test_unix_timestamp_native_executor(self):
# With E6_EXECUTOR_TYPE=native, TO_UNIX_TIMESTAMP is emitted without /1000
# because NE already returns seconds. Default (java) keeps the /1000 divisor.
os.environ["E6_EXECUTOR_TYPE"] = "native"
try:
# no-format branch
self.validate_all(
"SELECT TO_UNIX_TIMESTAMP(CAST(A AS TIMESTAMP))",
read={"databricks": "SELECT UNIX_TIMESTAMP(A)"},
)
# format branch (PARSE_DATETIME)
self.validate_all(
"SELECT TO_UNIX_TIMESTAMP(PARSE_DATETIME('%Y-%m-%d', '2016-04-08'))",
read={"databricks": "SELECT unix_timestamp('2016-04-08', 'yyyy-MM-dd')"},
)
finally:
os.environ.pop("E6_EXECUTOR_TYPE", None)

# Default (flag unset) -> java behavior, /1000 preserved
self.validate_all(
"SELECT TO_UNIX_TIMESTAMP(CAST(A AS TIMESTAMP)) / 1000",
read={"databricks": "SELECT UNIX_TIMESTAMP(A)"},
)

def test_timestamp_seconds(self):
# Test basic TIMESTAMP_SECONDS with integer literal
self.validate_all(
Expand Down
Loading