Skip to content

Commit fd4c482

Browse files
committed
fix to_timedelta compiler
1 parent 3a4be75 commit fd4c482

File tree

3 files changed

+52
-12
lines changed

3 files changed

+52
-12
lines changed

bigframes/core/compile/sqlglot/expressions/unary_compiler.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import sqlglot.expressions as sge
2323

2424
from bigframes import operations as ops
25+
from bigframes.core.compile.constants import UNIT_TO_US_CONVERSION_FACTORS
2526
from bigframes.core.compile.sqlglot.expressions.op_registration import OpRegistration
2627
from bigframes.core.compile.sqlglot.expressions.typed_expr import TypedExpr
2728

@@ -618,7 +619,11 @@ def _(op: ops.ToTimestampOp, expr: TypedExpr) -> sge.Expression:
618619

619620
@UNARY_OP_REGISTRATION.register(ops.ToTimedeltaOp)
620621
def _(op: ops.ToTimedeltaOp, expr: TypedExpr) -> sge.Expression:
621-
return sge.Interval(this=expr.expr, unit=sge.Identifier(this="SECOND"))
622+
value = expr.expr
623+
factor = UNIT_TO_US_CONVERSION_FACTORS[op.unit]
624+
if factor != 1:
625+
value = sge.Mul(this=value, expression=sge.convert(factor))
626+
return sge.Interval(this=value, unit=sge.Identifier(this="MICROSECOND"))
622627

623628

624629
@UNARY_OP_REGISTRATION.register(ops.UnixMicros)
Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,37 @@
11
WITH `bfcte_0` AS (
22
SELECT
3-
`int64_col` AS `bfcol_0`
3+
`int64_col` AS `bfcol_0`,
4+
`rowindex` AS `bfcol_1`
45
FROM `bigframes-dev`.`sqlglot_test`.`scalar_types`
56
), `bfcte_1` AS (
67
SELECT
78
*,
8-
INTERVAL `bfcol_0` SECOND AS `bfcol_1`
9+
`bfcol_1` AS `bfcol_4`,
10+
`bfcol_0` AS `bfcol_5`,
11+
INTERVAL `bfcol_0` MICROSECOND AS `bfcol_6`
912
FROM `bfcte_0`
13+
), `bfcte_2` AS (
14+
SELECT
15+
*,
16+
`bfcol_4` AS `bfcol_10`,
17+
`bfcol_5` AS `bfcol_11`,
18+
`bfcol_6` AS `bfcol_12`,
19+
INTERVAL (`bfcol_5` * 1000000) MICROSECOND AS `bfcol_13`
20+
FROM `bfcte_1`
21+
), `bfcte_3` AS (
22+
SELECT
23+
*,
24+
`bfcol_10` AS `bfcol_18`,
25+
`bfcol_11` AS `bfcol_19`,
26+
`bfcol_12` AS `bfcol_20`,
27+
`bfcol_13` AS `bfcol_21`,
28+
INTERVAL (`bfcol_11` * 604800000000) MICROSECOND AS `bfcol_22`
29+
FROM `bfcte_2`
1030
)
1131
SELECT
12-
`bfcol_1` AS `int64_col`
13-
FROM `bfcte_1`
32+
`bfcol_18` AS `rowindex`,
33+
`bfcol_19` AS `int64_col`,
34+
`bfcol_20` AS `duration_us`,
35+
`bfcol_21` AS `duration_s`,
36+
`bfcol_22` AS `duration_w`
37+
FROM `bfcte_3`

tests/unit/core/compile/sqlglot/expressions/test_unary_compiler.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import typing
16+
1517
import pytest
1618

1719
from bigframes import operations as ops
@@ -21,14 +23,21 @@
2123
pytest.importorskip("pytest_snapshot")
2224

2325

24-
def _apply_unary_op(obj: bpd.DataFrame, op: ops.UnaryOp, arg: str) -> str:
26+
def _apply_unary_op(
27+
obj: bpd.DataFrame, ops: ops.UnaryOp | typing.Sequence[ops.UnaryOp], arg: str
28+
) -> str:
2529
array_value = obj._block.expr
26-
op_expr = op.as_expr(arg)
27-
result, col_ids = array_value.compute_values([op_expr])
30+
if not isinstance(ops, typing.Sequence):
31+
ops = [ops]
32+
op_expr = [op.as_expr(arg) for op in ops]
33+
result, col_ids = array_value.compute_values(op_expr)
2834

2935
# Rename columns for deterministic golden SQL results.
30-
assert len(col_ids) == 1
31-
result = result.rename_columns({col_ids[0]: arg}).select_columns([arg])
36+
rename_cols = {
37+
col_id: arg if index == 0 else f"{arg}_{index}"
38+
for index, col_id in enumerate(col_ids)
39+
}
40+
result = result.rename_columns(rename_cols).select_columns([arg])
3241

3342
sql = result.session._executor.to_sql(result, enable_cache=False)
3443
return sql
@@ -599,9 +608,11 @@ def test_to_timestamp(scalar_types_df: bpd.DataFrame, snapshot):
599608

600609
def test_to_timedelta(scalar_types_df: bpd.DataFrame, snapshot):
601610
bf_df = scalar_types_df[["int64_col"]]
602-
sql = _apply_unary_op(bf_df, ops.ToTimedeltaOp("s"), "int64_col")
611+
bf_df["duration_us"] = bpd.to_timedelta(bf_df["int64_col"], "us")
612+
bf_df["duration_s"] = bpd.to_timedelta(bf_df["int64_col"], "s")
613+
bf_df["duration_w"] = bpd.to_timedelta(bf_df["int64_col"], "W")
603614

604-
snapshot.assert_match(sql, "out.sql")
615+
snapshot.assert_match(bf_df.sql, "out.sql")
605616

606617

607618
def test_unix_micros(scalar_types_df: bpd.DataFrame, snapshot):

0 commit comments

Comments
 (0)