lower_value, upper_value = range_
except (ValueError, TypeError) as ve:
raise exc.ArgumentError("2-tuple expected for range/rows") from ve
+
+ lower_type = type_api.INTEGERTYPE if isinstance(lower_value, int) else type_api.NUMERICTYPE
+ upper_type = type_api.INTEGERTYPE if isinstance(upper_value, int) else type_api.NUMERICTYPE
if lower_value is None:
self.lower_type = _FrameClauseType.RANGE_UNBOUNDED
self.lower_bind = None
+ elif lower_value == 0:
+ self.lower_type = _FrameClauseType.RANGE_CURRENT
+ self.lower_bind = None
+ elif lower_value < 0:
+ self.lower_type = _FrameClauseType.RANGE_PRECEDING
+ self.lower_bind = literal(abs(lower_value), lower_type)
else:
- if lower_value == 0:
- self.lower_type = _FrameClauseType.RANGE_CURRENT
- self.lower_bind = None
- elif lower_value < 0:
- self.lower_type = _FrameClauseType.RANGE_PRECEDING
- self.lower_bind = literal(abs(lower_value), type_api.NULLTYPE)
- else:
- self.lower_type = _FrameClauseType.RANGE_FOLLOWING
- self.lower_bind = literal(lower_value, type_api.NULLTYPE)
+ self.lower_type = _FrameClauseType.RANGE_FOLLOWING
+ self.lower_bind = literal(lower_value, lower_type)
if upper_value is None:
self.upper_type = _FrameClauseType.RANGE_UNBOUNDED
self.upper_bind = None
+ elif upper_value == 0:
+ self.upper_type = _FrameClauseType.RANGE_CURRENT
+ self.upper_bind = None
+ elif upper_value < 0:
+ self.upper_type = _FrameClauseType.RANGE_PRECEDING
+ self.upper_bind = literal(abs(upper_value), upper_type)
else:
- if upper_value == 0:
- self.upper_type = _FrameClauseType.RANGE_CURRENT
- self.upper_bind = None
- elif upper_value < 0:
- self.upper_type = _FrameClauseType.RANGE_PRECEDING
- self.upper_bind = literal(abs(upper_value), type_api.NULLTYPE)
- else:
- self.upper_type = _FrameClauseType.RANGE_FOLLOWING
- self.upper_bind = literal(upper_value, type_api.NULLTYPE)
+ self.upper_type = _FrameClauseType.RANGE_FOLLOWING
+ self.upper_bind = literal(upper_value, upper_type)
class WithinGroup(ColumnElement[_T]):
_ColumnExpressionArgument[Any],
]
] = None,
- range_: Optional[typing_Tuple[Optional[int], Optional[int]]] = None,
+ range_: Optional[typing_Tuple[Optional[Any], Optional[Any]]] = None,
rows: Optional[typing_Tuple[Optional[int], Optional[int]]] = None,
groups: Optional[typing_Tuple[Optional[int], Optional[int]]] = None,
) -> Over[_T]:
partition_by: Optional[_ByArgument] = None,
order_by: Optional[_ByArgument] = None,
rows: Optional[Tuple[Optional[int], Optional[int]]] = None,
- range_: Optional[Tuple[Optional[int], Optional[int]]] = None,
+ range_: Optional[Tuple[Optional[Any], Optional[Any]]] = None,
groups: Optional[Tuple[Optional[int], Optional[int]]] = None,
) -> Over[_T]:
"""Produce an OVER clause against this function.
from ... import TupleType
from ... import union
from ... import values
+from ... import Float
from ...exc import DatabaseError
from ...exc import ProgrammingError
Column("id", Integer, primary_key=True),
Column("col1", Integer),
Column("col2", Integer),
+ Column("col3", Float),
)
@classmethod
def insert_data(cls, connection):
connection.execute(
cls.tables.some_table.insert(),
- [{"id": i, "col1": i, "col2": i * 5} for i in range(1, 50)],
+ [{"id": i, "col1": i, "col2": i * 5, "col3": i + 0.5} for i in range(1, 50)],
)
def test_window(self, connection):
eq_(rows, [(95,) for i in range(19)])
+ def test_window_range(self, connection):
+ some_table = self.tables.some_table
+ rows = connection.execute(
+ select(
+ func.max(some_table.c.col3).over(
+ partition_by=[some_table.c.col3],
+ order_by=[some_table.c.col3.asc()],
+ range_=(-1.25, 1.25),
+ )
+ ).where(some_table.c.col1 < 20)
+ ).all()
+
+ eq_(rows, [(i + 1.5,) for i in range(19)])
+
def test_window_rows_between_w_caching(self, connection):
some_table = self.tables.some_table
column("myid", Integer),
column("name", String),
column("description", String),
+ column("myfloat", Float),
)
checkparams={"name_1": "foo", "param_1": 1, "param_2": 5},
)
+ self.assert_compile(
+ select(
+ func.rank()
+ .filter(table1.c.name > "foo")
+ .over(range_=(-3.14, 2.71), partition_by=["myfloat"])
+ ),
+ "SELECT rank() FILTER (WHERE mytable.name > :name_1) "
+ "OVER (PARTITION BY mytable.myfloat RANGE BETWEEN :param_1 "
+ "PRECEDING AND :param_2 FOLLOWING) "
+ "AS anon_1 FROM mytable",
+ checkparams={"name_1": "foo", "param_1": 3.14, "param_2": 2.71},
+ )
+
def test_funcfilter_windowing_range_positional(self):
self.assert_compile(
select(