Skip to content

Commit

Permalink
refactor: always rewrite first -> first_value/last -> last_value
Browse files Browse the repository at this point in the history
…for SQL window functions
  • Loading branch information
jcrist committed Mar 6, 2024
1 parent 513242a commit cf29fad
Show file tree
Hide file tree
Showing 10 changed files with 19 additions and 72 deletions.
4 changes: 0 additions & 4 deletions ibis/backends/bigquery/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
exclude_unsupported_window_frame_from_ops,
exclude_unsupported_window_frame_from_rank,
exclude_unsupported_window_frame_from_row_number,
rewrite_first_to_first_value,
rewrite_last_to_last_value,
rewrite_sample_as_filter,
)
from ibis.common.temporal import DateUnit, IntervalUnit, TimestampUnit, TimeUnit
Expand All @@ -33,8 +31,6 @@ class BigQueryCompiler(SQLGlotCompiler):
udf_type_mapper = BigQueryUDFType
rewrites = (
rewrite_sample_as_filter,
rewrite_first_to_first_value,
rewrite_last_to_last_value,
exclude_unsupported_window_frame_from_ops,
exclude_unsupported_window_frame_from_row_number,
exclude_unsupported_window_frame_from_rank,
Expand Down
4 changes: 0 additions & 4 deletions ibis/backends/flink/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
exclude_unsupported_window_frame_from_ops,
exclude_unsupported_window_frame_from_rank,
exclude_unsupported_window_frame_from_row_number,
rewrite_first_to_first_value,
rewrite_last_to_last_value,
rewrite_sample_as_filter,
)

Expand All @@ -30,8 +28,6 @@ class FlinkCompiler(SQLGlotCompiler):
exclude_unsupported_window_frame_from_row_number,
exclude_unsupported_window_frame_from_ops,
exclude_unsupported_window_frame_from_rank,
rewrite_first_to_first_value,
rewrite_last_to_last_value,
*SQLGlotCompiler.rewrites,
)

Expand Down
4 changes: 0 additions & 4 deletions ibis/backends/impala/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
from ibis.backends.sql.dialects import Impala
from ibis.backends.sql.rewrites import (
rewrite_empty_order_by_window,
rewrite_first_to_first_value,
rewrite_last_to_last_value,
rewrite_sample_as_filter,
)

Expand All @@ -25,8 +23,6 @@ class ImpalaCompiler(SQLGlotCompiler):
type_mapper = ImpalaType
rewrites = (
rewrite_sample_as_filter,
rewrite_first_to_first_value,
rewrite_last_to_last_value,
rewrite_empty_order_by_window,
*SQLGlotCompiler.rewrites,
)
Expand Down
4 changes: 0 additions & 4 deletions ibis/backends/mssql/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
exclude_unsupported_window_frame_from_row_number,
p,
replace,
rewrite_first_to_first_value,
rewrite_last_to_last_value,
rewrite_sample_as_filter,
)
from ibis.common.deferred import var
Expand Down Expand Up @@ -66,8 +64,6 @@ class MSSQLCompiler(SQLGlotCompiler):
type_mapper = MSSQLType
rewrites = (
rewrite_sample_as_filter,
rewrite_first_to_first_value,
rewrite_last_to_last_value,
exclude_unsupported_window_frame_from_ops,
exclude_unsupported_window_frame_from_row_number,
rewrite_rows_range_order_by_window,
Expand Down
4 changes: 0 additions & 4 deletions ibis/backends/mysql/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
exclude_unsupported_window_frame_from_rank,
exclude_unsupported_window_frame_from_row_number,
rewrite_empty_order_by_window,
rewrite_first_to_first_value,
rewrite_last_to_last_value,
rewrite_sample_as_filter,
)
from ibis.common.patterns import replace
Expand Down Expand Up @@ -53,8 +51,6 @@ class MySQLCompiler(SQLGlotCompiler):
rewrites = (
rewrite_limit,
rewrite_sample_as_filter,
rewrite_first_to_first_value,
rewrite_last_to_last_value,
exclude_unsupported_window_frame_from_ops,
exclude_unsupported_window_frame_from_rank,
exclude_unsupported_window_frame_from_row_number,
Expand Down
4 changes: 0 additions & 4 deletions ibis/backends/oracle/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
replace_log2,
replace_log10,
rewrite_empty_order_by_window,
rewrite_first_to_first_value,
rewrite_last_to_last_value,
rewrite_sample_as_filter,
)

Expand All @@ -33,8 +31,6 @@ class OracleCompiler(SQLGlotCompiler):
rewrites = (
exclude_unsupported_window_frame_from_row_number,
exclude_unsupported_window_frame_from_ops,
rewrite_first_to_first_value,
rewrite_last_to_last_value,
rewrite_empty_order_by_window,
rewrite_sample_as_filter,
replace_log2,
Expand Down
4 changes: 0 additions & 4 deletions ibis/backends/snowflake/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
replace_log2,
replace_log10,
rewrite_empty_order_by_window,
rewrite_first_to_first_value,
rewrite_last_to_last_value,
)


Expand All @@ -39,8 +37,6 @@ class SnowflakeCompiler(SQLGlotCompiler):
rewrites = (
exclude_unsupported_window_frame_from_row_number,
exclude_unsupported_window_frame_from_ops,
rewrite_first_to_first_value,
rewrite_last_to_last_value,
rewrite_empty_order_by_window,
replace_log2,
replace_log10,
Expand Down
37 changes: 15 additions & 22 deletions ibis/backends/sql/rewrites.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,23 @@ def sort_to_select(_, **kwargs):

@replace(p.WindowFunction)
def window_function_to_window(_, **kwargs):
"""Convert a WindowFunction node to a Window node."""
"""Convert a WindowFunction node to a Window node.
Also rewrites first -> first_value, last -> last_value.
"""
func = _.func
if isinstance(func, (ops.First, ops.Last)):
if func.where is not None:
raise com.UnsupportedOperationError(
f"`{type(func).__name__.lower()}` with `where` is unsupported "
"in a window function"
)
cls = FirstValue if isinstance(func, ops.First) else LastValue
func = cls(func.arg)

return Window(
how=_.frame.how,
func=_.func,
func=func,
start=_.frame.start,
end=_.frame.end,
group_by=_.frame.group_by,
Expand Down Expand Up @@ -292,26 +305,6 @@ def rewrite_sample_as_filter(_, **kwargs):
return ops.Filter(_.parent, (ops.LessEqual(ops.RandomScalar(), _.fraction),))


@replace(p.WindowFunction(p.First(x, where=y)))
def rewrite_first_to_first_value(_, x, y, **kwargs):
"""Rewrite Ibis's first to first_value when used in a window function."""
if y is not None:
raise com.UnsupportedOperationError(
"`first` with `where` is unsupported in a window function"
)
return _.copy(func=FirstValue(x))


@replace(p.WindowFunction(p.Last(x, where=y)))
def rewrite_last_to_last_value(_, x, y, **kwargs):
"""Rewrite Ibis's last to last_value when used in a window function."""
if y is not None:
raise com.UnsupportedOperationError(
"`last` with `where` is unsupported in a window function"
)
return _.copy(func=LastValue(x))


@replace(p.WindowFunction(frame=y @ p.WindowFrame(order_by=())))
def rewrite_empty_order_by_window(_, y, **kwargs):
return _.copy(frame=y.copy(order_by=(ops.NULL,)))
Expand Down
13 changes: 2 additions & 11 deletions ibis/backends/sqlite/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@
from ibis.backends.sql.compiler import NULL, SQLGlotCompiler
from ibis.backends.sql.datatypes import SQLiteType
from ibis.backends.sql.dialects import SQLite
from ibis.backends.sql.rewrites import (
rewrite_first_to_first_value,
rewrite_last_to_last_value,
rewrite_sample_as_filter,
)
from ibis.backends.sql.rewrites import rewrite_sample_as_filter
from ibis.common.temporal import DateUnit, IntervalUnit


Expand All @@ -24,12 +20,7 @@ class SQLiteCompiler(SQLGlotCompiler):

dialect = SQLite
type_mapper = SQLiteType
rewrites = (
rewrite_sample_as_filter,
rewrite_first_to_first_value,
rewrite_last_to_last_value,
*SQLGlotCompiler.rewrites,
)
rewrites = (rewrite_sample_as_filter, *SQLGlotCompiler.rewrites)

NAN = NULL
POS_INF = sge.Literal.number("1e999")
Expand Down
13 changes: 2 additions & 11 deletions ibis/backends/trino/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,15 @@
)
from ibis.backends.sql.datatypes import TrinoType
from ibis.backends.sql.dialects import Trino
from ibis.backends.sql.rewrites import (
exclude_unsupported_window_frame_from_ops,
rewrite_first_to_first_value,
rewrite_last_to_last_value,
)
from ibis.backends.sql.rewrites import exclude_unsupported_window_frame_from_ops


class TrinoCompiler(SQLGlotCompiler):
__slots__ = ()

dialect = Trino
type_mapper = TrinoType
rewrites = (
rewrite_first_to_first_value,
rewrite_last_to_last_value,
exclude_unsupported_window_frame_from_ops,
*SQLGlotCompiler.rewrites,
)
rewrites = (exclude_unsupported_window_frame_from_ops, *SQLGlotCompiler.rewrites)
quoted = True

NAN = sg.func("nan")
Expand Down

0 comments on commit cf29fad

Please sign in to comment.