Skip to content

Commit

Permalink
refactor: move FirstValue/LastValue to SQL-specific IR
Browse files Browse the repository at this point in the history
  • Loading branch information
jcrist committed Mar 6, 2024
1 parent 3a8c7cc commit 513242a
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 33 deletions.
6 changes: 4 additions & 2 deletions ibis/backends/oracle/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from ibis.backends.sql.datatypes import OracleType
from ibis.backends.sql.dialects import Oracle
from ibis.backends.sql.rewrites import (
FirstValue,
LastValue,
exclude_unsupported_window_frame_from_ops,
exclude_unsupported_window_frame_from_row_number,
replace_log2,
Expand Down Expand Up @@ -409,8 +411,8 @@ def visit_Window(self, op, *, how, func, start, end, group_by, order_by):
ops.Correlation, # "corr",
ops.Count, # "count",
ops.Covariance, # "covar_pop", "covar_samp",
ops.FirstValue, # "first_value",
ops.LastValue, # "last_value",
FirstValue, # "first_value",
LastValue, # "last_value",
ops.Max, # "max",
ops.Min, # "min",
ops.NthValue, # "nth_value",
Expand Down
9 changes: 0 additions & 9 deletions ibis/backends/pandas/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,15 +452,6 @@ def agg(df, order_keys):

return agg

@classmethod
def visit(cls, op: ops.FirstValue | ops.LastValue, arg):
i = 0 if isinstance(op, ops.FirstValue) else -1

def agg(df, order_keys):
return df[arg.name].iat[i]

return agg

@classmethod
def visit(
cls, op: ops.AnalyticVectorizedUDF, func, func_args, input_type, return_type
Expand Down
6 changes: 4 additions & 2 deletions ibis/backends/sql/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import ibis.expr.datatypes as dt
import ibis.expr.operations as ops
from ibis.backends.sql.rewrites import (
FirstValue,
LastValue,
add_one_to_nth_value_input,
add_order_by_to_empty_ranking_window_functions,
empty_in_values_right_side,
Expand Down Expand Up @@ -235,15 +237,15 @@ class SQLGlotCompiler(abc.ABC):
ops.DenseRank: "dense_rank",
ops.Exp: "exp",
ops.First: "first",
ops.FirstValue: "first_value",
FirstValue: "first_value",
ops.GroupConcat: "group_concat",
ops.IfElse: "if",
ops.IsInf: "isinf",
ops.IsNan: "isnan",
ops.JSONGetItem: "json_extract",
ops.LPad: "lpad",
ops.Last: "last",
ops.LastValue: "last_value",
LastValue: "last_value",
ops.Levenshtein: "levenshtein",
ops.Ln: "ln",
ops.Log10: "log",
Expand Down
26 changes: 24 additions & 2 deletions ibis/backends/sql/rewrites.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,28 @@ def schema(self):
return Schema({k: v.dtype for k, v in self.selections.items()})


@public
class FirstValue(ops.Analytic):
"""Retrieve the first element."""

arg: ops.Column[dt.Any]

@attribute
def dtype(self):
return self.arg.dtype


@public
class LastValue(ops.Analytic):
"""Retrieve the last element."""

arg: ops.Column[dt.Any]

@attribute
def dtype(self):
return self.arg.dtype


@public
class Window(ops.Value):
"""Window modelled after SQL's window statements."""
Expand Down Expand Up @@ -277,7 +299,7 @@ def rewrite_first_to_first_value(_, x, y, **kwargs):
raise com.UnsupportedOperationError(
"`first` with `where` is unsupported in a window function"
)
return _.copy(func=ops.FirstValue(x))
return _.copy(func=FirstValue(x))


@replace(p.WindowFunction(p.Last(x, where=y)))
Expand All @@ -287,7 +309,7 @@ def rewrite_last_to_last_value(_, x, y, **kwargs):
raise com.UnsupportedOperationError(
"`last` with `where` is unsupported in a window function"
)
return _.copy(func=ops.LastValue(x))
return _.copy(func=LastValue(x))


@replace(p.WindowFunction(frame=y @ p.WindowFrame(order_by=())))
Expand Down
18 changes: 0 additions & 18 deletions ibis/expr/operations/analytic.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,24 +89,6 @@ class NTile(Analytic):
dtype = dt.int64


@public
class FirstValue(Analytic):
"""Retrieve the first element."""

arg: Column[dt.Any]

dtype = rlz.dtype_like("arg")


@public
class LastValue(Analytic):
"""Retrieve the last element."""

arg: Column[dt.Any]

dtype = rlz.dtype_like("arg")


@public
class NthValue(Analytic):
"""Retrieve the Nth element."""
Expand Down

0 comments on commit 513242a

Please sign in to comment.