Skip to content

Commit 4a882f4

Browse files
ruff
1 parent 28cd7b9 commit 4a882f4

4 files changed

Lines changed: 126 additions & 69 deletions

File tree

packages/bigframes/bigframes/core/compile/substrait/compiler.py

Lines changed: 64 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,6 @@ def _compile_concat(self, node: nodes.ConcatNode) -> algebra_pb2.Rel:
313313
def _compile_aggregate(self, node: nodes.AggregateNode) -> algebra_pb2.Rel:
314314
input_rel = self._compile_node(node.child)
315315

316-
import bigframes.dtypes as dtypes
317316
import bigframes.operations.aggregations as agg_ops
318317

319318
child_ids = list(node.child.ids)
@@ -390,7 +389,7 @@ def _compile_aggregate(self, node: nodes.AggregateNode) -> algebra_pb2.Rel:
390389
idx = child_ids.index(col_id)
391390
field_expr = algebra_pb2.Expression()
392391
field_expr.selection.direct_reference.struct_field.field = idx
393-
392+
394393
arg = measure.measure.arguments.add()
395394
arg.value.CopyFrom(field_expr)
396395
except ValueError:
@@ -406,7 +405,9 @@ def _compile_aggregate(self, node: nodes.AggregateNode) -> algebra_pb2.Rel:
406405
not_null_op.scalar_function.function_reference = self._EXTENSIONS[
407406
"is_not_null"
408407
]
409-
json_format.ParseDict({"bool": {}}, not_null_op.scalar_function.output_type)
408+
json_format.ParseDict(
409+
{"bool": {}}, not_null_op.scalar_function.output_type
410+
)
410411
not_null_op.scalar_function.arguments.add().value.CopyFrom(key_expr)
411412
not_null_exprs.append(not_null_op)
412413

@@ -417,7 +418,9 @@ def _compile_aggregate(self, node: nodes.AggregateNode) -> algebra_pb2.Rel:
417418
and_expr.scalar_function.function_reference = self._EXTENSIONS[
418419
"and"
419420
]
420-
json_format.ParseDict({"bool": {}}, and_expr.scalar_function.output_type)
421+
json_format.ParseDict(
422+
{"bool": {}}, and_expr.scalar_function.output_type
423+
)
421424
and_expr.scalar_function.arguments.add().value.CopyFrom(expr)
422425
and_expr.scalar_function.arguments.add().value.CopyFrom(e)
423426
expr = and_expr
@@ -450,57 +453,89 @@ def _compile_window(self, node: nodes.WindowOpNode) -> algebra_pb2.Rel:
450453
expr.selection.direct_reference.struct_field.field = idx
451454

452455
# 2. Map window frame bounds (RowsWindowBounds / RangeWindowBounds / None)
453-
bounds_type = algebra_pb2.Expression.WindowFunction.BoundsType.BOUNDS_TYPE_UNSPECIFIED
456+
bounds_type = (
457+
algebra_pb2.Expression.WindowFunction.BoundsType.BOUNDS_TYPE_UNSPECIFIED
458+
)
454459
lower_bound = algebra_pb2.Expression.WindowFunction.Bound()
455460
upper_bound = algebra_pb2.Expression.WindowFunction.Bound()
456461

457462
if node.window_spec.bounds is not None:
458463
if isinstance(node.window_spec.bounds, window_spec.RowsWindowBounds):
459-
bounds_type = algebra_pb2.Expression.WindowFunction.BoundsType.BOUNDS_TYPE_ROWS
460-
464+
bounds_type = (
465+
algebra_pb2.Expression.WindowFunction.BoundsType.BOUNDS_TYPE_ROWS
466+
)
467+
461468
# Lower bound mapping
462469
start = node.window_spec.bounds.start
463470
if start is None:
464-
lower_bound.unbounded.CopyFrom(algebra_pb2.Expression.WindowFunction.Bound.Unbounded())
471+
lower_bound.unbounded.CopyFrom(
472+
algebra_pb2.Expression.WindowFunction.Bound.Unbounded()
473+
)
465474
elif start == 0:
466-
lower_bound.current_row.CopyFrom(algebra_pb2.Expression.WindowFunction.Bound.CurrentRow())
475+
lower_bound.current_row.CopyFrom(
476+
algebra_pb2.Expression.WindowFunction.Bound.CurrentRow()
477+
)
467478
elif start < 0:
468479
lower_bound.preceding.offset = -start
469480
else:
470481
lower_bound.following.offset = start
471-
482+
472483
# Upper bound mapping
473484
end = node.window_spec.bounds.end
474485
if end is None:
475-
upper_bound.unbounded.CopyFrom(algebra_pb2.Expression.WindowFunction.Bound.Unbounded())
486+
upper_bound.unbounded.CopyFrom(
487+
algebra_pb2.Expression.WindowFunction.Bound.Unbounded()
488+
)
476489
elif end == 0:
477-
upper_bound.current_row.CopyFrom(algebra_pb2.Expression.WindowFunction.Bound.CurrentRow())
490+
upper_bound.current_row.CopyFrom(
491+
algebra_pb2.Expression.WindowFunction.Bound.CurrentRow()
492+
)
478493
elif end < 0:
479494
upper_bound.preceding.offset = -end
480495
else:
481496
upper_bound.following.offset = end
482497

483498
elif isinstance(node.window_spec.bounds, window_spec.RangeWindowBounds):
484-
bounds_type = algebra_pb2.Expression.WindowFunction.BoundsType.BOUNDS_TYPE_RANGE
499+
bounds_type = (
500+
algebra_pb2.Expression.WindowFunction.BoundsType.BOUNDS_TYPE_RANGE
501+
)
485502
start = node.window_spec.bounds.start
486503
if start is None:
487-
lower_bound.unbounded.CopyFrom(algebra_pb2.Expression.WindowFunction.Bound.Unbounded())
504+
lower_bound.unbounded.CopyFrom(
505+
algebra_pb2.Expression.WindowFunction.Bound.Unbounded()
506+
)
488507
elif start == pd.Timedelta(0):
489-
lower_bound.current_row.CopyFrom(algebra_pb2.Expression.WindowFunction.Bound.CurrentRow())
508+
lower_bound.current_row.CopyFrom(
509+
algebra_pb2.Expression.WindowFunction.Bound.CurrentRow()
510+
)
490511
else:
491-
raise NotImplementedError("Range window bounds with non-zero offsets are not supported yet")
512+
raise NotImplementedError(
513+
"Range window bounds with non-zero offsets are not supported yet"
514+
)
492515

493516
end = node.window_spec.bounds.end
494517
if end is None:
495-
upper_bound.unbounded.CopyFrom(algebra_pb2.Expression.WindowFunction.Bound.Unbounded())
518+
upper_bound.unbounded.CopyFrom(
519+
algebra_pb2.Expression.WindowFunction.Bound.Unbounded()
520+
)
496521
elif end == pd.Timedelta(0):
497-
upper_bound.current_row.CopyFrom(algebra_pb2.Expression.WindowFunction.Bound.CurrentRow())
522+
upper_bound.current_row.CopyFrom(
523+
algebra_pb2.Expression.WindowFunction.Bound.CurrentRow()
524+
)
498525
else:
499-
raise NotImplementedError("Range window bounds with non-zero offsets are not supported yet")
526+
raise NotImplementedError(
527+
"Range window bounds with non-zero offsets are not supported yet"
528+
)
500529
else:
501-
bounds_type = algebra_pb2.Expression.WindowFunction.BoundsType.BOUNDS_TYPE_ROWS
502-
lower_bound.unbounded.CopyFrom(algebra_pb2.Expression.WindowFunction.Bound.Unbounded())
503-
upper_bound.unbounded.CopyFrom(algebra_pb2.Expression.WindowFunction.Bound.Unbounded())
530+
bounds_type = (
531+
algebra_pb2.Expression.WindowFunction.BoundsType.BOUNDS_TYPE_ROWS
532+
)
533+
lower_bound.unbounded.CopyFrom(
534+
algebra_pb2.Expression.WindowFunction.Bound.Unbounded()
535+
)
536+
upper_bound.unbounded.CopyFrom(
537+
algebra_pb2.Expression.WindowFunction.Bound.Unbounded()
538+
)
504539

505540
# 3. Project each window aggregation expression as a WindowFunction expression
506541
for agg_idx, col_def in enumerate(node.agg_exprs):
@@ -553,7 +588,9 @@ def _compile_window(self, node: nodes.WindowOpNode) -> algebra_pb2.Rel:
553588
win_func.phase = algebra_pb2.AGGREGATION_PHASE_INITIAL_TO_RESULT
554589

555590
bound_expr = ex.bind_schema_fields(agg, node.child.field_by_id)
556-
type_dict = self._convert_type(dtypes.dtype_for_etype(bound_expr.output_type))
591+
type_dict = self._convert_type(
592+
dtypes.dtype_for_etype(bound_expr.output_type)
593+
)
557594
json_format.ParseDict(type_dict, win_func.output_type)
558595

559596
if distinct or isinstance(agg.op, agg_ops.NuniqueOp):
@@ -574,7 +611,9 @@ def _compile_window(self, node: nodes.WindowOpNode) -> algebra_pb2.Rel:
574611
# Set sorting keys (sorts)
575612
for ord_expr in node.window_spec.ordering:
576613
sort_field = win_func.sorts.add()
577-
sort_pb = self._compile_expression(ord_expr.scalar_expression, node.child)
614+
sort_pb = self._compile_expression(
615+
ord_expr.scalar_expression, node.child
616+
)
578617
sort_field.expr.CopyFrom(sort_pb)
579618

580619
is_asc = ord_expr.direction.is_ascending
@@ -596,7 +635,7 @@ def _compile_window(self, node: nodes.WindowOpNode) -> algebra_pb2.Rel:
596635
idx = child_ids.index(col_id)
597636
field_expr = algebra_pb2.Expression()
598637
field_expr.selection.direct_reference.struct_field.field = idx
599-
638+
600639
arg = win_func.arguments.add()
601640
arg.value.CopyFrom(field_expr)
602641
except ValueError:

packages/bigframes/bigframes/core/rewrite/substrait_agg.py

Lines changed: 52 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,16 @@
1515
from __future__ import annotations
1616

1717
import dataclasses
18-
from typing import cast, Dict, Tuple
1918

19+
import bigframes.dtypes as dtypes
20+
import bigframes.operations as ops
21+
import bigframes.operations.aggregations as agg_ops
2022
from bigframes.core import (
2123
agg_expressions,
2224
expression,
2325
identifiers,
2426
nodes,
2527
)
26-
import bigframes.dtypes as dtypes
27-
import bigframes.operations as ops
28-
import bigframes.operations.aggregations as agg_ops
2928

3029

3130
def rewrite_substrait_aggregations(node: nodes.BigFrameNode) -> nodes.BigFrameNode:
@@ -58,22 +57,21 @@ def rewrite_substrait_aggregations(node: nodes.BigFrameNode) -> nodes.BigFrameNo
5857
is_bool = col_dtype == dtypes.BOOL_DTYPE
5958
if isinstance(
6059
agg.op, (agg_ops.StdOp, agg_ops.VarOp, agg_ops.PopVarOp)
61-
) or (
62-
isinstance(agg.op, agg_ops.MeanOp)
63-
and is_bool
64-
):
60+
) or (isinstance(agg.op, agg_ops.MeanOp) and is_bool):
6561
cast_aggs.append((agg_idx, col_id, dtypes.FLOAT_DTYPE))
6662
elif isinstance(agg.op, agg_ops.SumOp) and is_bool:
6763
cast_aggs.append((agg_idx, col_id, dtypes.INT_DTYPE))
6864

6965
# If we need pre-projection (casts or size constants)
7066
if size_aggs or cast_aggs:
7167
assignments = []
72-
68+
7369
cast_agg_to_col_id = {}
7470
for agg_idx, col_id, target_dtype in cast_aggs:
7571
new_id = identifiers.ColumnId(f"bf_cast_{col_id.name}_{agg_idx}")
76-
cast_expr = ops.AsTypeOp(to_type=target_dtype).as_expr(expression.deref(col_id.name))
72+
cast_expr = ops.AsTypeOp(to_type=target_dtype).as_expr(
73+
expression.deref(col_id.name)
74+
)
7775
assignments.append((cast_expr, new_id))
7876
cast_agg_to_col_id[(agg_idx, col_id)] = new_id
7977

@@ -103,10 +101,12 @@ def rewrite_substrait_aggregations(node: nodes.BigFrameNode) -> nodes.BigFrameNo
103101
new_exprs = []
104102
for col_id in agg.column_references:
105103
if (agg_idx, col_id) in cast_agg_to_col_id:
106-
new_exprs.append(expression.deref(cast_agg_to_col_id[(agg_idx, col_id)].name))
104+
new_exprs.append(
105+
expression.deref(cast_agg_to_col_id[(agg_idx, col_id)].name)
106+
)
107107
else:
108108
new_exprs.append(expression.deref(col_id.name))
109-
109+
110110
if isinstance(agg, agg_expressions.UnaryAggregation):
111111
rewritten_agg = agg_expressions.UnaryAggregation(
112112
agg.op, new_exprs[0]
@@ -132,16 +132,20 @@ def rewrite_substrait_aggregations(node: nodes.BigFrameNode) -> nodes.BigFrameNo
132132
output_ids = group_ids + agg_ids
133133

134134
expected_types = [item.dtype for item in node.schema.items]
135-
135+
136136
assignments = []
137137
selection_pairs = []
138138
for idx, (out_id, target_dtype) in enumerate(zip(output_ids, expected_types)):
139139
cast_id = identifiers.ColumnId(f"bf_out_cast_{out_id.name}")
140-
cast_expr = ops.AsTypeOp(to_type=target_dtype).as_expr(expression.deref(out_id.name))
140+
cast_expr = ops.AsTypeOp(to_type=target_dtype).as_expr(
141+
expression.deref(out_id.name)
142+
)
141143
assignments.append((cast_expr, cast_id))
142-
143-
selection_pairs.append((nodes.AliasedRef(expression.deref(cast_id.name), out_id), out_id))
144-
144+
145+
selection_pairs.append(
146+
(nodes.AliasedRef(expression.deref(cast_id.name), out_id), out_id)
147+
)
148+
145149
post_project = nodes.ProjectionNode(
146150
node,
147151
assignments=tuple(assignments),
@@ -150,7 +154,7 @@ def rewrite_substrait_aggregations(node: nodes.BigFrameNode) -> nodes.BigFrameNo
150154
post_project,
151155
input_output_pairs=tuple(ref for ref, _ in selection_pairs),
152156
)
153-
157+
154158
return post_selection
155159

156160

@@ -170,7 +174,7 @@ def rewrite_substrait_windows(node: nodes.BigFrameNode) -> nodes.BigFrameNode:
170174
# Collect size and cast requirements for the window agg expressions
171175
size_aggs = []
172176
cast_aggs = []
173-
177+
174178
for agg_idx, col_def in enumerate(node.agg_exprs):
175179
agg = col_def.expression
176180
if isinstance(agg.op, (agg_ops.SizeOp, agg_ops.SizeUnaryOp)):
@@ -182,22 +186,21 @@ def rewrite_substrait_windows(node: nodes.BigFrameNode) -> nodes.BigFrameNode:
182186
is_bool = col_dtype == dtypes.BOOL_DTYPE
183187
if isinstance(
184188
agg.op, (agg_ops.StdOp, agg_ops.VarOp, agg_ops.PopVarOp)
185-
) or (
186-
isinstance(agg.op, agg_ops.MeanOp)
187-
and is_bool
188-
):
189+
) or (isinstance(agg.op, agg_ops.MeanOp) and is_bool):
189190
cast_aggs.append((agg_idx, col_id, dtypes.FLOAT_DTYPE))
190191
elif isinstance(agg.op, agg_ops.SumOp) and is_bool:
191192
cast_aggs.append((agg_idx, col_id, dtypes.INT_DTYPE))
192193

193194
# If we need pre-projection (casts or size constants)
194195
if size_aggs or cast_aggs:
195196
assignments = []
196-
197+
197198
cast_agg_to_col_id = {}
198199
for agg_idx, col_id, target_dtype in cast_aggs:
199200
new_id = identifiers.ColumnId(f"bf_window_cast_{col_id.name}_{agg_idx}")
200-
cast_expr = ops.AsTypeOp(to_type=target_dtype).as_expr(expression.deref(col_id.name))
201+
cast_expr = ops.AsTypeOp(to_type=target_dtype).as_expr(
202+
expression.deref(col_id.name)
203+
)
201204
assignments.append((cast_expr, new_id))
202205
cast_agg_to_col_id[(agg_idx, col_id)] = new_id
203206

@@ -220,7 +223,7 @@ def rewrite_substrait_windows(node: nodes.BigFrameNode) -> nodes.BigFrameNode:
220223
for agg_idx, col_def in enumerate(node.agg_exprs):
221224
agg = col_def.expression
222225
out_col_id = col_def.id
223-
226+
224227
if isinstance(agg.op, (agg_ops.SizeOp, agg_ops.SizeUnaryOp)):
225228
new_col_id = size_agg_to_col_id[agg_idx]
226229
rewritten_agg = agg_expressions.UnaryAggregation(
@@ -230,10 +233,12 @@ def rewrite_substrait_windows(node: nodes.BigFrameNode) -> nodes.BigFrameNode:
230233
new_exprs = []
231234
for col_id in agg.column_references:
232235
if (agg_idx, col_id) in cast_agg_to_col_id:
233-
new_exprs.append(expression.deref(cast_agg_to_col_id[(agg_idx, col_id)].name))
236+
new_exprs.append(
237+
expression.deref(cast_agg_to_col_id[(agg_idx, col_id)].name)
238+
)
234239
else:
235240
new_exprs.append(expression.deref(col_id.name))
236-
241+
237242
if isinstance(agg, agg_expressions.UnaryAggregation):
238243
rewritten_agg = agg_expressions.UnaryAggregation(
239244
agg.op, new_exprs[0]
@@ -245,9 +250,7 @@ def rewrite_substrait_windows(node: nodes.BigFrameNode) -> nodes.BigFrameNode:
245250
else:
246251
rewritten_agg = agg
247252

248-
rewritten_agg_exprs.append(
249-
nodes.ColumnDef(rewritten_agg, out_col_id)
250-
)
253+
rewritten_agg_exprs.append(nodes.ColumnDef(rewritten_agg, out_col_id))
251254

252255
node = dataclasses.replace(
253256
node,
@@ -256,24 +259,32 @@ def rewrite_substrait_windows(node: nodes.BigFrameNode) -> nodes.BigFrameNode:
256259
)
257260

258261
# Post-projection to enforce output schema types for newly introduced window columns:
259-
child_output_ids = list(node.child.ids) if not isinstance(child, nodes.ProjectionNode) else list(child.child.ids)
260-
262+
child_output_ids = (
263+
list(node.child.ids)
264+
if not isinstance(child, nodes.ProjectionNode)
265+
else list(child.child.ids)
266+
)
267+
261268
assignments = []
262269
selection_pairs = []
263-
270+
264271
for child_id in child_output_ids:
265272
selection_pairs.append((nodes.AliasedRef.identity(child_id), child_id))
266-
273+
267274
for col_def, field in zip(node.agg_exprs, node.added_fields):
268275
out_id = col_def.id
269276
target_dtype = field.dtype
270-
277+
271278
cast_id = identifiers.ColumnId(f"bf_window_out_cast_{out_id.name}")
272-
cast_expr = ops.AsTypeOp(to_type=target_dtype).as_expr(expression.deref(out_id.name))
279+
cast_expr = ops.AsTypeOp(to_type=target_dtype).as_expr(
280+
expression.deref(out_id.name)
281+
)
273282
assignments.append((cast_expr, cast_id))
274-
275-
selection_pairs.append((nodes.AliasedRef(expression.deref(cast_id.name), out_id), out_id))
276-
283+
284+
selection_pairs.append(
285+
(nodes.AliasedRef(expression.deref(cast_id.name), out_id), out_id)
286+
)
287+
277288
post_project = nodes.ProjectionNode(
278289
node,
279290
assignments=tuple(assignments),
@@ -282,5 +293,5 @@ def rewrite_substrait_windows(node: nodes.BigFrameNode) -> nodes.BigFrameNode:
282293
post_project,
283294
input_output_pairs=tuple(ref for ref, _ in selection_pairs),
284295
)
285-
296+
286297
return post_selection

0 commit comments

Comments
 (0)