Skip to content

Commit 56ffd42

Browse files
Add support for standard LIMIT and OFFSET syntax (#167)
Signed-off-by: Balram Choudhary <bchoudhary@rocketsoftware.com>
1 parent 229aad9 commit 56ffd42

File tree

1 file changed

+40
-32
lines changed

1 file changed

+40
-32
lines changed

ibm_db_sa/base.py

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -397,18 +397,32 @@ def visit_mod_binary(self, binary, operator, **kw):
397397
self.process(binary.right))
398398

399399
def limit_clause(self, select, **kwargs):
400-
if (select._limit is not None) and (select._offset is None):
401-
return " FETCH FIRST %s ROWS ONLY" % select._limit
402-
else:
403-
return ""
400+
limit = select._limit
401+
offset = select._offset or 0
402+
403+
if limit is not None:
404+
if offset > 0:
405+
return f" LIMIT {limit} OFFSET {offset}"
406+
else:
407+
return f" LIMIT {limit}"
408+
return ""
404409

405410
def visit_select(self, select, **kwargs):
406411
limit, offset = select._limit, select._offset
407412
sql_ori = compiler.SQLCompiler.visit_select(self, select, **kwargs)
413+
414+
if ('LIMIT' in sql_ori.upper()) or ('FETCH FIRST' in sql_ori.upper()):
415+
return sql_ori
416+
417+
if limit is not None:
418+
sql = re.sub(r'FETCH FIRST \d+ ROWS ONLY', '', sql_ori, flags=re.IGNORECASE).strip()
419+
limit_offset_clause = self.limit_clause(select, **kwargs)
420+
sql += limit_offset_clause
421+
return sql
422+
408423
if offset is not None:
409424
__rownum = 'Z.__ROWNUM'
410425
sql_split = re.split(r"[\s+]FROM ", sql_ori, 1)
411-
sql_sec = ""
412426
sql_sec = " \nFROM %s " % (sql_split[1])
413427

414428
dummyVal = "Z.__db2_"
@@ -420,45 +434,39 @@ def visit_select(self, select, **kwargs):
420434

421435
sql_select_token = sql_split[0].split(",")
422436
i = 0
423-
while (i < len(sql_select_token)):
437+
while i < len(sql_select_token):
424438
if sql_select_token[i].count("TIMESTAMP(DATE(SUBSTR(CHAR(") == 1:
425-
sql_sel = "%s \"%s%d\"," % (sql_sel, dummyVal, i + 1)
426-
sql_pri = '%s %s,%s,%s,%s AS "%s%d",' % (
427-
sql_pri,
428-
sql_select_token[i],
429-
sql_select_token[i + 1],
430-
sql_select_token[i + 2],
431-
sql_select_token[i + 3],
432-
dummyVal, i + 1)
433-
i = i + 4
439+
sql_sel = f'{sql_sel} "{dummyVal}{i + 1}",'
440+
sql_pri = f'{sql_pri} {sql_select_token[i]},{sql_select_token[i + 1]},{sql_select_token[i + 2]},{sql_select_token[i + 3]} AS "{dummyVal}{i + 1}",'
441+
i += 4
434442
continue
435443

436444
if sql_select_token[i].count(" AS ") == 1:
437445
temp_col_alias = sql_select_token[i].split(" AS ")
438-
sql_pri = '%s %s,' % (sql_pri, sql_select_token[i])
439-
sql_sel = "%s %s," % (sql_sel, temp_col_alias[1])
440-
i = i + 1
446+
sql_pri = f'{sql_pri} {sql_select_token[i]},'
447+
sql_sel = f'{sql_sel} {temp_col_alias[1]},'
448+
i += 1
441449
continue
442450

443-
sql_pri = '%s %s AS "%s%d",' % (sql_pri, sql_select_token[i], dummyVal, i + 1)
444-
sql_sel = "%s \"%s%d\"," % (sql_sel, dummyVal, i + 1)
445-
i = i + 1
451+
sql_pri = f'{sql_pri} {sql_select_token[i]} AS "{dummyVal}{i + 1}",'
452+
sql_sel = f'{sql_sel} "{dummyVal}{i + 1}",'
453+
i += 1
446454

447-
sql_pri = sql_pri[:len(sql_pri) - 1]
448-
sql_pri = "%s%s" % (sql_pri, sql_sec)
449-
sql_sel = sql_sel[:len(sql_sel) - 1]
450-
sql = '%s, ( ROW_NUMBER() OVER() ) AS "%s" FROM ( %s ) AS M' % (sql_sel, __rownum, sql_pri)
451-
sql = '%s FROM ( %s ) Z WHERE' % (sql_sel, sql)
455+
sql_pri = sql_pri.rstrip(",")
456+
sql_pri = f"{sql_pri}{sql_sec}"
457+
sql_sel = sql_sel.rstrip(",")
458+
sql = f'{sql_sel}, ( ROW_NUMBER() OVER() ) AS "{__rownum}" FROM ( {sql_pri} ) AS M'
459+
sql = f'{sql_sel} FROM ( {sql} ) Z WHERE'
452460

453461
if offset != 0:
454-
sql = '%s "%s" > %d' % (sql, __rownum, offset)
462+
sql = f'{sql} "{__rownum}" > {offset}'
455463
if offset != 0 and limit is not None:
456-
sql = '%s AND ' % (sql)
464+
sql = f'{sql} AND '
457465
if limit is not None:
458-
sql = '%s "%s" <= %d' % (sql, __rownum, offset + limit)
459-
return "( %s )" % (sql,)
460-
else:
461-
return sql_ori
466+
sql = f'{sql} "{__rownum}" <= {offset + limit}'
467+
return f"( {sql} )"
468+
469+
return sql_ori
462470

463471
def visit_sequence(self, sequence, **kw):
464472
if sequence.schema:

0 commit comments

Comments
 (0)