Skip to content

Commit 55a31f9

Browse files
authored
fix(parser):adapt union sql has order/limit (#30)
* fix(parser):adapt union sql has order/limit * fix(parser):adapt union sql has order/limit in oceanbase/mysql
1 parent 3611afa commit 55a31f9

File tree

4 files changed

+51
-22
lines changed

4 files changed

+51
-22
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ __pycache__/
2626
######################
2727
*.sqlite
2828
*.log
29+
logs/
2930

3031
# OS generated files #
3132
######################

parser/mysql_parser/parser.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -281,14 +281,14 @@ def p_cursor_specification(p):
281281
query.where,
282282
query.group_by,
283283
query.having,
284-
p[2],
285-
limit,
286-
offset,
284+
order_by=query.order_by if query.order_by else p[2],
285+
limit=query.limit if query.limit else limit,
286+
offset=query.offset if query.offset else offset,
287287
for_update=query.for_update if query.for_update else for_update,
288288
nowait_or_wait=query.nowait_or_wait if query.nowait_or_wait else nowait_or_wait
289289
),
290-
limit=limit,
291-
offset=offset
290+
limit=query.limit if query.limit else limit,
291+
offset=query.offset if query.offset else offset
292292
)
293293
else:
294294
p[0] = Query(p.lineno(1), p.lexpos(1),
@@ -303,11 +303,11 @@ def p_subquery(p):
303303
if p_limit:
304304
offset = p_limit[0]
305305
limit = p_limit[1]
306-
306+
a = p[2]
307307
if isinstance(p[2], QuerySpecification):
308-
p[2].limit = limit
309-
p[2].offset = offset
310-
p[2].order_by = p[3] or []
308+
p[2].limit = p[2].limit if p[2].limit else limit
309+
p[2].offset = p[2].offset if p[2].offset else offset
310+
p[2].order_by = p[2].order_by if p[2].order_by else p[3] or []
311311
p[0] = SubqueryExpression(p.lineno(1), p.lexpos(1), query=p[2])
312312

313313

@@ -461,7 +461,7 @@ def _item_list(p):
461461

462462

463463
def p_query_spec(p):
464-
r"""query_spec : SELECT select_items table_expression_opt"""
464+
r"""query_spec : SELECT select_items table_expression_opt order_by_opt limit_opt"""
465465
select_items = p[2]
466466
table_expression_opt = p[3]
467467
from_relations = table_expression_opt.from_ if table_expression_opt else None
@@ -472,6 +472,13 @@ def p_query_spec(p):
472472
for_update = None
473473
nowait_or_wait = None
474474

475+
p_limit = p[5]
476+
offset = 0
477+
limit = 0
478+
if p_limit:
479+
offset = p_limit[0]
480+
limit = p_limit[1]
481+
475482
if p_for_update:
476483
for_update = p_for_update[0]
477484
nowait_or_wait = p_for_update[1]
@@ -490,7 +497,11 @@ def p_query_spec(p):
490497
group_by=group_by,
491498
having=having,
492499
for_update=for_update,
493-
nowait_or_wait=nowait_or_wait)
500+
nowait_or_wait=nowait_or_wait,
501+
order_by=p[4],
502+
limit=limit,
503+
offset=offset
504+
)
494505

495506

496507
def p_where_opt(p):

parser/oceanbase_parser/parser.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -275,14 +275,14 @@ def p_cursor_specification(p):
275275
query.where,
276276
query.group_by,
277277
query.having,
278-
p[2],
279-
limit,
280-
offset,
278+
order_by=query.order_by if query.order_by else p[2],
279+
limit=query.limit if query.limit else limit,
280+
offset=query.offset if query.offset else offset,
281281
for_update=query.for_update if query.for_update else for_update,
282282
nowait_or_wait=query.nowait_or_wait if query.nowait_or_wait else nowait_or_wait
283283
),
284-
limit=limit,
285-
offset=offset
284+
limit=query.limit if query.limit else limit,
285+
offset=query.offset if query.offset else offset
286286
)
287287
else:
288288
p[0] = Query(p.lineno(1), p.lexpos(1),
@@ -299,9 +299,9 @@ def p_subquery(p):
299299
limit = p_limit[1]
300300

301301
if isinstance(p[2], QuerySpecification):
302-
p[2].limit = limit
303-
p[2].offset = offset
304-
p[2].order_by = p[3] or []
302+
p[2].limit = p[2].limit if p[2].limit else limit
303+
p[2].offset = p[2].offset if p[2].offset else offset
304+
p[2].order_by = p[2].order_by if p[2].order_by else p[3] or []
305305
p[0] = SubqueryExpression(p.lineno(1), p.lexpos(1), query=p[2])
306306

307307

@@ -454,7 +454,7 @@ def _item_list(p):
454454

455455

456456
def p_query_spec(p):
457-
r"""query_spec : SELECT select_items table_expression_opt"""
457+
r"""query_spec : SELECT select_items table_expression_opt order_by_opt limit_opt"""
458458
select_items = p[2]
459459
table_expression_opt = p[3]
460460
from_relations = table_expression_opt.from_ if table_expression_opt else None
@@ -465,6 +465,13 @@ def p_query_spec(p):
465465
for_update = None
466466
nowait_or_wait = None
467467

468+
p_limit = p[5]
469+
offset = 0
470+
limit = 0
471+
if p_limit:
472+
offset = p_limit[0]
473+
limit = p_limit[1]
474+
468475
if p_for_update:
469476
for_update = p_for_update[0]
470477
nowait_or_wait = p_for_update[1]
@@ -483,7 +490,10 @@ def p_query_spec(p):
483490
group_by=group_by,
484491
having=having,
485492
for_update=for_update,
486-
nowait_or_wait=nowait_or_wait)
493+
nowait_or_wait=nowait_or_wait,
494+
order_by=p[4],
495+
limit=limit,
496+
offset=offset)
487497

488498

489499
def p_where_opt(p):

test/parser/test_parser_dml.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,6 @@ def test_limit_question_mark(self):
283283
result = oceanbase_parser.parse("""
284284
SELECT * FROM `antinvoice93`.einv_base_info WHERE einv_source = ? ORDER BY gmt_create DESC LIMIT ?
285285
""")
286-
assert result.limit == '?'
287286
assert result.query_body.limit == '?'
288287

289288
def test_subquery_limit(self):
@@ -449,6 +448,14 @@ def test_double_type(self):
449448
result = oceanbase_parser.parse(sql)
450449
assert isinstance(result, Statement)
451450

451+
def test_union_has_order_limit(self):
452+
sql = """
453+
( select 球员id from 球员夺冠次数 order by 冠军次数 asc limit 3 ) union ( select 球员id from 球员夺冠次数 order by 亚军次数 desc limit 5 )
454+
"""
455+
sql = Utils.remove_sql_text_affects_parser(sql)
456+
result = oceanbase_parser.parse(sql)
457+
assert isinstance(result, Statement)
458+
452459

453460
if __name__ == '__main__':
454461
unittest.main()

0 commit comments

Comments
 (0)