Skip to content
Draft
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
8 changes: 7 additions & 1 deletion pkg-py/src/commons/_definitions/_emit_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
"weeks": "604800000000",
}

_NULL_DATETIME = {"snowflake": "TIMESTAMP_TZ", "databricks": "TIMESTAMP"}

_SIMPLE_FUNCTIONS = {
"length": "length",
"lower": "lower",
Expand Down Expand Up @@ -424,11 +426,15 @@ def _temporal_shift(node: Ir, state: _State, selected: str | None) -> str | None
interval becomes a count of microseconds.
"""
attrs = node.attrs
dialect = state.dialect
# The checker accepts an untyped NULL as the interval, which shifts to
# NULL. Neither warehouse adds a bare NULL to a date, so it is typed.
if node.type == "datetime" and "null" in (attrs["lhs"].kind, attrs["rhs"].kind):
return f"CAST(NULL AS {_NULL_DATETIME[dialect]})"
lhs_interval = attrs["lhs"].type == "interval"
rhs_interval = attrs["rhs"].type == "interval"
if not lhs_interval and not rhs_interval:
return None
dialect = state.dialect
if lhs_interval and attrs["op"] == "-":
_unsupported(
dialect,
Expand Down
2 changes: 2 additions & 0 deletions pkg-r/NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# commons (development version)

* A definition that adds `NULL` to a date, such as `created + NULL`, now compiles to SQL that Snowflake accepts. It compiles to a typed `NULL` timestamp (#441).

* A definition that divides by a compound expression, such as `amount / (ratio * 2)`, now compiles to the correct Snowflake and Databricks SQL. The parentheses around the divisor were dropped, so the query divided by `ratio` alone (#439).

* `commons()` gains a `mode` argument. With `mode = "trusted only"`, the agent answers only with trusted calculations. It never writes its own SQL or R, and it tells the user when no trusted calculation answers a question. These answers carry no provenance markers.
Expand Down
16 changes: 16 additions & 0 deletions pkg-r/R/definition-emit-sql.R
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,17 @@ definition_sql_similar <- function(node, state, dialect, selected) {
}

definition_sql_temporal_shift <- function(node, state, dialect, selected) {
# The checker accepts an untyped NULL as the interval, which shifts to
# NULL. Neither warehouse adds a bare NULL to a date, so it is typed.
if (
identical(node$type, "datetime") &&
"null" %in% c(node$lhs$kind, node$rhs$kind)
) {
return(sprintf(
"CAST(NULL AS %s)",
definition_sql_null_datetime[[dialect]]
))
}
lhs_interval <- identical(node$lhs$type, "interval")
rhs_interval <- identical(node$rhs$type, "interval")
if (!lhs_interval && !rhs_interval) {
Expand Down Expand Up @@ -775,6 +786,11 @@ definition_sql_abort_unsupported <- function(dialect, what, why) {
)
}

definition_sql_null_datetime <- list(
snowflake = "TIMESTAMP_TZ",
databricks = "TIMESTAMP"
)

definition_sql_nan_note <- list(
snowflake = paste(
"Snowflake orders a NaN as equal to itself and greater than every number,",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@
"survey::dynamic match": {
"SQL(snowflake)": { "notes_contain": ["newline characters"] }
},
"survey::nullable date shift": {
"SQL(snowflake)": { "code": "CAST(NULL AS TIMESTAMP_TZ)" },
"SQL(databricks)": { "code": "CAST(NULL AS TIMESTAMP)" }
},
"survey::negative quotient": {
"SQL(snowflake)": {
"code_contains": [
Expand Down
4 changes: 4 additions & 0 deletions tests/shared/definition-warehouse-sql.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@
"survey::dynamic match": {
"SQL(snowflake)": { "notes_contain": ["newline characters"] }
},
"survey::nullable date shift": {
"SQL(snowflake)": { "code": "CAST(NULL AS TIMESTAMP_TZ)" },
"SQL(databricks)": { "code": "CAST(NULL AS TIMESTAMP)" }
},
"survey::negative quotient": {
"SQL(snowflake)": {
"code_contains": [
Expand Down
Loading