Skip to content

Commit 698539f

Browse files
committed
feat: add offset param to SQLizer.select_custom_fields
1 parent 8172d1f commit 698539f

File tree

7 files changed

+76
-11
lines changed

7 files changed

+76
-11
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ await AccountMgr.select_custom_fields(
6868
groups=["locale", "gender"],
6969
having="cnt > 0",
7070
orders=["locale", "-gender"],
71+
offset=0,
7172
limit=10,
7273
)
7374
```
@@ -80,7 +81,7 @@ Generate sql and execute
8081
GROUP BY locale, gender
8182
HAVING cnt > 0
8283
ORDER BY locale ASC, gender DESC
83-
LIMIT 10
84+
LIMIT 0, 10
8485
```
8586

8687
### **update_json_field**

examples/service/routers/account.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ async def query_group_by_locale_view(
6060
groups=["locale", "gender"],
6161
having="cnt > 0",
6262
orders=["locale", "-gender"],
63+
offset=0,
6364
limit=10,
6465
)
6566
return {"dicts": dicts}

fastapi_esql/orm/base_manager.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ async def select_custom_fields(
6666
groups: Optional[List[str]] = None,
6767
having: Optional[str] = None,
6868
orders: Optional[List[str]] = None,
69+
offset: Optional[int] = None,
6970
limit: int = 0,
7071
conn: Optional[BaseDBAsyncClient] = None,
7172
):
@@ -76,6 +77,7 @@ async def select_custom_fields(
7677
groups,
7778
having,
7879
orders,
80+
offset,
7981
limit,
8082
cls.model,
8183
)

fastapi_esql/utils/sqlizer.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ def select_custom_fields(
117117
groups: Optional[List[str]] = None,
118118
having: Optional[str] = None,
119119
orders: Optional[List[str]] = None,
120+
offset: Optional[int] = None,
120121
limit: int = 0,
121122
model: Optional[Model] = None,
122123
) -> Optional[str]:
@@ -128,8 +129,8 @@ def select_custom_fields(
128129
group_by = f" GROUP BY {', '.join(groups)}" if groups else ""
129130
having_ = f" HAVING {having}" if having else ""
130131
order_by = f" ORDER BY {cls.resolve_orders(orders)}" if orders else ""
131-
limit_ = f" LIMIT {limit}" if limit else ""
132-
# NOTE Doesn't support `offset` parameter due to it's bad performance
132+
offset_ = "" if offset is None else f"{offset}, "
133+
limit_ = f" LIMIT {offset_}{limit}" if limit else ""
133134
extras = [group_by, having_, order_by, limit_]
134135

135136
sql = """

tests/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,6 @@ def init_test_orm():
3232
}
3333
}
3434
asyncio.run(Tortoise.init(config=config))
35+
36+
37+
init_test_orm()

tests/test_metaclass.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@ class TestSingleton(TestCase):
1515

1616
def test_inheritance(self):
1717
c0, c1 = Child(), Child()
18-
print(id(c0), id(c1))
1918
assert c0 is c1
2019

2120
def test_parent_and_child(self):
2221
p0, p1 = Parent(), Parent()
2322
c = Child()
24-
print(id(p0), id(p0), id(c))
2523
assert p0 is p1
2624
assert p0 is not c

tests/test_sqlizer.py

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
Q, QsParsingError, WrongParamsError,
77
)
88

9-
from . import init_test_orm
109
from examples.service.models.demo import Account
1110

1211

@@ -33,6 +32,9 @@ def test_no_default(self):
3332

3433
class TestSQLizer(TestCase):
3534

35+
model = Account
36+
table = Account.Meta.table
37+
3638
def test_resolve_wheres(self):
3739
with self.assertRaises(WrongParamsError):
3840
SQLizer.resolve_wheres(object())
@@ -41,22 +43,21 @@ def test_resolve_wheres(self):
4143
assert SQLizer.resolve_wheres(
4244
f"id IN ({','.join(map(str, aids))}) AND gender=1"
4345
) == "id IN (1,2,3) AND gender=1"
44-
init_test_orm()
4546
assert SQLizer.resolve_wheres(
46-
Q(Q(id__in=aids), Q(gender=1), join_type="AND"), Account
47+
Q(Q(id__in=aids), Q(gender=1), join_type="AND"), self.model
4748
) == "`id` IN (1,2,3) AND `gender`=1"
4849
assert SQLizer.resolve_wheres(
49-
{"id__in": aids, "gender": 1}, Account
50+
{"id__in": aids, "gender": 1}, self.model
5051
) == "`id` IN (1,2,3) AND `gender`=1"
5152
assert SQLizer.resolve_wheres(
52-
[Q(id__in=aids), Q(gender=1)], Account
53+
[Q(id__in=aids), Q(gender=1)], self.model
5354
) == "`id` IN (1,2,3) AND `gender`=1"
5455

5556
with self.assertRaises(WrongParamsError):
5657
SQLizer.resolve_wheres(set())
5758

5859
with self.assertRaises(QsParsingError):
59-
SQLizer.resolve_wheres({}, Account)
60+
SQLizer.resolve_wheres({}, self.model)
6061

6162
def test_resolve_orders(self):
6263
orders = SQLizer.resolve_orders(["-created_at", "name"])
@@ -82,3 +83,61 @@ def test_sqlize_value(self):
8283
assert SQLizer.sqlize_value(("a", "b", "c")) == """'["a", "b", "c"]'"""
8384

8485
assert SQLizer.sqlize_value(datetime(2023, 1, 1, 12, 30)) == "'2023-01-01 12:30:00'"
86+
87+
def test_select_custom_fields(self):
88+
aids = [1, 2, 3]
89+
basic_sql = SQLizer.select_custom_fields(
90+
self.table,
91+
fields=[
92+
"id", "extend ->> '$.last_login.ipv4' ipv4",
93+
"extend ->> '$.last_login.start_datetime' start_datetime",
94+
"CAST(extend ->> '$.last_login.online_sec' AS SIGNED) online_sec"
95+
],
96+
wheres=f"id IN ({','.join(map(str, aids))}) AND gender=1",
97+
model=self.model,
98+
)
99+
assert basic_sql == """
100+
SELECT
101+
id, extend ->> '$.last_login.ipv4' ipv4, extend ->> '$.last_login.start_datetime' start_datetime, CAST(extend ->> '$.last_login.online_sec' AS SIGNED) online_sec
102+
FROM account
103+
WHERE id IN (1,2,3) AND gender=1
104+
"""
105+
106+
complex_sql = SQLizer.select_custom_fields(
107+
self.table,
108+
fields=[
109+
"locale", "gender", "COUNT(1) cnt"
110+
],
111+
wheres=Q(id__range=[1, 12]),
112+
groups=["locale", "gender"],
113+
having="cnt > 0",
114+
orders=["locale", "-gender"],
115+
limit=10,
116+
model=self.model,
117+
)
118+
assert complex_sql == """
119+
SELECT
120+
locale, gender, COUNT(1) cnt
121+
FROM account
122+
WHERE `id` BETWEEN 1 AND 12
123+
GROUP BY locale, gender
124+
HAVING cnt > 0
125+
ORDER BY locale ASC, gender DESC
126+
LIMIT 10"""
127+
128+
paging_sql = SQLizer.select_custom_fields(
129+
self.table,
130+
fields=[
131+
"locale", "gender"
132+
],
133+
wheres=Q(id__range=[1, 12]),
134+
offset=100,
135+
limit=5,
136+
model=self.model,
137+
)
138+
assert paging_sql == """
139+
SELECT
140+
locale, gender
141+
FROM account
142+
WHERE `id` BETWEEN 1 AND 12
143+
LIMIT 100, 5"""

0 commit comments

Comments
 (0)