Skip to content

Commit a0a4e22

Browse files
authored
Merge pull request #26 from grongierisc/main_origin
Add new pagination LIMIT and OFFSET if IRIS 2025.1 and fix #24
2 parents 83c14e1 + 5953a9f commit a0a4e22

File tree

3 files changed

+528
-15
lines changed

3 files changed

+528
-15
lines changed

sqlalchemy_iris/base.py

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -408,10 +408,21 @@ def visit_exists_unary_operator(
408408
return "EXISTS(%s)" % self.process(element.element, **kw)
409409

410410
def limit_clause(self, select, **kw):
411-
return ""
411+
# handle the limit and offset clauses
412+
if select._has_row_limiting_clause and not self._use_top(select):
413+
limit_clause = self._get_limit_or_fetch(select)
414+
offset_clause = select._offset_clause
412415

413-
def fetch_clause(self, select, **kw):
414-
return ""
416+
if limit_clause is not None:
417+
if offset_clause is not None:
418+
return " LIMIT %s OFFSET %s" % (
419+
self.process(limit_clause, **kw),
420+
self.process(offset_clause, **kw),
421+
)
422+
else:
423+
return " LIMIT %s" % self.process(limit_clause, **kw)
424+
else:
425+
return ""
415426

416427
def visit_empty_set_expr(self, type_, **kw):
417428
return "SELECT 1 WHERE 1!=1"
@@ -541,16 +552,39 @@ def translate_select_structure(self, select_stmt, **kwargs):
541552
if not (select._has_row_limiting_clause and not self._use_top(select)):
542553
return select
543554

544-
"""Look for ``LIMIT`` and OFFSET in a select statement, and if
545-
so tries to wrap it in a subquery with ``row_number()`` criterion.
555+
# check the current version of the iris server
556+
server_version = self.dialect.server_version_info
546557

547-
"""
558+
if server_version is None or server_version < (2025, 1):
559+
return self._handle_legacy_pagination(select, select_stmt)
560+
else:
561+
return self._handle_modern_pagination(select, select_stmt)
562+
563+
def _get_default_order_by(self, select_stmt, select):
564+
"""Get default ORDER BY clauses when none are specified."""
548565
_order_by_clauses = [
549566
sql_util.unwrap_label_reference(elem)
550567
for elem in select._order_by_clause.clauses
551568
]
569+
552570
if not _order_by_clauses:
553-
_order_by_clauses = [text("%id")]
571+
# If no ORDER BY clause, use the primary key
572+
if select_stmt.froms and isinstance(select_stmt.froms[0], schema.Table):
573+
table = select.froms[0]
574+
if table.primary_key and table.primary_key.columns:
575+
_order_by_clauses = [
576+
sql_util.unwrap_label_reference(c)
577+
for c in table.primary_key.columns
578+
]
579+
else:
580+
# If no primary key, use the id column
581+
_order_by_clauses = [text("%id")]
582+
583+
return _order_by_clauses
584+
585+
def _handle_legacy_pagination(self, select, select_stmt):
586+
"""Handle pagination for IRIS versions before 2025.1 using ROW_NUMBER()."""
587+
_order_by_clauses = self._get_default_order_by(select_stmt, select)
554588

555589
limit_clause = self._get_limit_or_fetch(select)
556590
offset_clause = select._offset_clause
@@ -566,6 +600,7 @@ def translate_select_structure(self, select_stmt, **kwargs):
566600

567601
iris_rn = sql.column(label)
568602
limitselect = sql.select(*[c for c in select.c if c.key != label])
603+
569604
if offset_clause is not None:
570605
if limit_clause is not None:
571606
limitselect = limitselect.where(
@@ -574,9 +609,23 @@ def translate_select_structure(self, select_stmt, **kwargs):
574609
else:
575610
limitselect = limitselect.where(iris_rn > offset_clause)
576611
else:
577-
limitselect = limitselect.where(iris_rn <= (limit_clause))
612+
limitselect = limitselect.where(iris_rn <= limit_clause)
613+
578614
return limitselect
579615

616+
def _handle_modern_pagination(self, select, select_stmt):
617+
"""Handle pagination for IRIS 2025.1+ using native LIMIT/OFFSET."""
618+
_order_by_clauses = self._get_default_order_by(select_stmt, select)
619+
620+
new_select = select._generate().order_by(*_order_by_clauses)
621+
622+
# Apply limit if present
623+
if select._limit_clause is not None:
624+
new_select = new_select.limit(select._limit_clause)
625+
626+
return new_select
627+
628+
580629
def order_by_clause(self, select, **kw):
581630
order_by = self.process(select._order_by_clause, **kw)
582631

0 commit comments

Comments
 (0)