Skip to content

Commit e0bc87a

Browse files
committed
Adding support for limit offset
1 parent 5e657eb commit e0bc87a

4 files changed

Lines changed: 60 additions & 6 deletions

File tree

json_sql/apply_test.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
)
2626

2727

28-
class TestEvalExpression(TestCase):
28+
class TestApplyExpression(TestCase):
2929
def test_addition(self):
3030
expression = PlusExpression(
3131
left=NameExpression(name="a"),
@@ -87,7 +87,7 @@ def test_boolean(self):
8787
self.assertEqual(result, True)
8888

8989

90-
class TestEvalWhere(TestCase):
90+
class TestApplyWhere(TestCase):
9191
def test_where_no_context(self):
9292
where = Where(
9393
expression=GreaterThanExpression(
@@ -149,7 +149,7 @@ def test_with_context(self):
149149
)
150150

151151

152-
class TestEvalOrderBy(TestCase):
152+
class TestApplyOrderBy(TestCase):
153153
def test_order_by(self):
154154
order_by = OrderBy(
155155
fields=[
@@ -182,7 +182,7 @@ def test_order_by(self):
182182
)
183183

184184

185-
class TestEvalGroupBy(TestCase):
185+
class TestApplyGroupBy(TestCase):
186186
def test_group_by(self):
187187
group_by = GroupBy(
188188
fields=[
@@ -216,7 +216,7 @@ def test_group_by(self):
216216
)
217217

218218

219-
class TestEvalLimit(TestCase):
219+
class TestApplyLimit(TestCase):
220220
def test_limit(self):
221221
data = [
222222
{"name": "Alice", "age": 20},

json_sql/parser.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
Ast,
55
Select,
66
SelectField,
7+
Limit,
78
IntExpression,
89
SelectWildcard,
910
From,
@@ -186,6 +187,29 @@ def parse_fields(tokens: List[Token]) -> Tuple[List[SelectField], List[Token]]:
186187
return fields, tokens
187188

188189

190+
def parse_limit(tokens: List[Token]) -> Tuple[Limit, List[Token]]:
191+
if not tokens or tokens[0].type != "keyword" or tokens[0].value.upper() != "LIMIT":
192+
return None, tokens
193+
194+
tokens = tokens[1:]
195+
limit_token = tokens[0]
196+
assert limit_token.type == "int", f"Expected limit value, got {limit_token}"
197+
limit_value = limit_token.value
198+
limit_int = int(limit_value)
199+
tokens = tokens[1:]
200+
201+
if tokens and tokens[0].type == "keyword" and tokens[0].value.upper() == "OFFSET":
202+
tokens = tokens[1:]
203+
offset_token = tokens[0]
204+
assert offset_token.type == "int", f"Expected offset value, got {offset_token}"
205+
offset_value = offset_token.value
206+
offset_int = int(offset_value)
207+
tokens = tokens[1:]
208+
return Limit(limit=limit_int, offset=offset_int), tokens
209+
else:
210+
return Limit(limit=limit_int), tokens
211+
212+
189213
def parse_select(tokens: List[Token]) -> Tuple[Select, List[Token]]:
190214
if not tokens or tokens[0].type != "keyword" or tokens[0].value.upper() != "SELECT":
191215
raise ValueError("Expected SELECT statement")
@@ -194,12 +218,14 @@ def parse_select(tokens: List[Token]) -> Tuple[Select, List[Token]]:
194218
from_part, tokens = parse_from(tokens)
195219
where_part, tokens = parse_where(tokens)
196220
order_part, tokens = parse_order(tokens)
221+
limit_part, tokens = parse_limit(tokens)
197222

198223
return Select(
199224
field_parts=field_parts,
200225
from_part=from_part,
201226
where_part=where_part,
202227
order_part=order_part,
228+
limit_part=limit_part,
203229
), tokens
204230

205231

json_sql/parser_test.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from unittest import TestCase
2-
from .parser import parse, parse_expression, parse_from
2+
from .parser import parse, parse_expression, parse_from, parse_limit
33
from .lexer import scan
44
from .ast import (
55
Select,
@@ -13,6 +13,7 @@
1313
StringExpression,
1414
Where,
1515
OrderBy,
16+
Limit,
1617
OrderField,
1718
)
1819

@@ -159,3 +160,28 @@ def test_with_alias(self):
159160
),
160161
)
161162
self.assertEqual(tokens, [])
163+
164+
165+
class LimitTest(TestCase):
166+
def test_limit(self):
167+
tokens = scan("LIMIT 10")
168+
ast, tokens = parse_limit(tokens)
169+
self.assertEqual(
170+
ast,
171+
Limit(
172+
limit=10,
173+
),
174+
)
175+
self.assertEqual(tokens, [])
176+
177+
def test_limit_with_offset(self):
178+
tokens = scan("LIMIT 10 OFFSET 5")
179+
ast, tokens = parse_limit(tokens)
180+
self.assertEqual(
181+
ast,
182+
Limit(
183+
limit=10,
184+
offset=5,
185+
),
186+
)
187+
self.assertEqual(tokens, [])

json_sql/tokens.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"IS",
3131
"NULL",
3232
"EXISTS",
33+
"OFFSET",
3334
"DISTINCT",
3435
"ORDER BY",
3536
"GROUP BY",
@@ -43,6 +44,7 @@
4344
"CROSS JOIN",
4445
"NATURAL JOIN",
4546
"JOIN",
47+
"LIMIT",
4648
]
4749

4850

0 commit comments

Comments
 (0)