Skip to content

Commit 090ce8e

Browse files
refactor: Define window column expression type (#2081)
1 parent 2821fd0 commit 090ce8e

File tree

10 files changed

+324
-219
lines changed

10 files changed

+324
-219
lines changed

bigframes/core/agg_expressions.py

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from typing import Callable, Mapping, TypeVar
2323

2424
from bigframes import dtypes
25-
from bigframes.core import expression
25+
from bigframes.core import expression, window_spec
2626
import bigframes.core.identifiers as ids
2727
import bigframes.operations.aggregations as agg_ops
2828

@@ -149,3 +149,68 @@ def replace_args(
149149
self, larg: expression.Expression, rarg: expression.Expression
150150
) -> BinaryAggregation:
151151
return BinaryAggregation(self.op, larg, rarg)
152+
153+
154+
@dataclasses.dataclass(frozen=True)
155+
class WindowExpression(expression.Expression):
156+
analytic_expr: Aggregation
157+
window: window_spec.WindowSpec
158+
159+
@property
160+
def column_references(self) -> typing.Tuple[ids.ColumnId, ...]:
161+
return tuple(
162+
itertools.chain.from_iterable(
163+
map(lambda x: x.column_references, self.inputs)
164+
)
165+
)
166+
167+
@functools.cached_property
168+
def is_resolved(self) -> bool:
169+
return all(input.is_resolved for input in self.inputs)
170+
171+
@property
172+
def output_type(self) -> dtypes.ExpressionType:
173+
return self.analytic_expr.output_type
174+
175+
@property
176+
def inputs(
177+
self,
178+
) -> typing.Tuple[expression.Expression, ...]:
179+
return (self.analytic_expr, *self.window.expressions)
180+
181+
@property
182+
def free_variables(self) -> typing.Tuple[str, ...]:
183+
return tuple(
184+
itertools.chain.from_iterable(map(lambda x: x.free_variables, self.inputs))
185+
)
186+
187+
@property
188+
def is_const(self) -> bool:
189+
return all(child.is_const for child in self.inputs)
190+
191+
def transform_children(
192+
self: WindowExpression,
193+
t: Callable[[expression.Expression], expression.Expression],
194+
) -> WindowExpression:
195+
return WindowExpression(
196+
self.analytic_expr.transform_children(t),
197+
self.window.transform_exprs(t),
198+
)
199+
200+
def bind_variables(
201+
self: WindowExpression,
202+
bindings: Mapping[str, expression.Expression],
203+
allow_partial_bindings: bool = False,
204+
) -> WindowExpression:
205+
return self.transform_children(
206+
lambda x: x.bind_variables(bindings, allow_partial_bindings)
207+
)
208+
209+
def bind_refs(
210+
self: WindowExpression,
211+
bindings: Mapping[ids.ColumnId, expression.Expression],
212+
allow_partial_bindings: bool = False,
213+
) -> WindowExpression:
214+
return self.transform_children(
215+
lambda x: x.bind_refs(bindings, allow_partial_bindings)
216+
)

bigframes/core/blocks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1177,7 +1177,7 @@ def apply_analytic(
11771177
block = self
11781178
if skip_null_groups:
11791179
for key in window.grouping_keys:
1180-
block = block.filter(ops.notnull_op.as_expr(key.id.name))
1180+
block = block.filter(ops.notnull_op.as_expr(key))
11811181
expr, result_id = block._expr.project_window_expr(
11821182
agg_expr,
11831183
window,

0 commit comments

Comments
 (0)