Skip to content

Commit 486c61c

Browse files
authored
1411 Replace SelectRaw, GroupByRaw and OrderByRaw with QueryString (#1412)
* replace SelectRaw, GroupByRaw and OrderByRaw with QueryString * fix typo in docstring
1 parent 793b9d7 commit 486c61c

8 files changed

Lines changed: 92 additions & 81 deletions

File tree

docs/src/piccolo/query_clauses/group_by.rst

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,23 @@ These work the same as ``Count``. See :ref:`aggregate functions <AggregateFuncti
4242

4343
-------------------------------------------------------------------------------
4444

45-
``GroupByRaw``
46-
--------------
45+
Advanced
46+
--------
4747

48-
For more complex cases, use ``GroupByRaw`` to group by a raw SQL expression or
49-
an alias created by ``SelectRaw``. For example:
48+
For more complex cases, use :class:`QueryString <piccolo.querystring.QueryString>`
49+
to group by a raw SQL expression or an alias created in a select query. For
50+
example:
5051

5152
.. code-block:: python
5253
53-
from piccolo.query import GroupByRaw, SelectRaw
5454
from piccolo.query.functions.aggregate import Count
55+
from piccolo.querystring import QueryString
5556
5657
await Band.select(
57-
SelectRaw("DATE(created_at) AS created_date"),
58+
QueryString("DATE(created_at) AS created_date"),
5859
Count(),
5960
).group_by(
60-
GroupByRaw("created_date")
61+
QueryString("created_date")
6162
)
6263
6364
As with other raw query helpers, only use trusted SQL strings.

docs/src/piccolo/query_clauses/order_by.rst

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,25 +63,29 @@ descending, then you can do so using multiple ``order_by`` statements:
6363
ascending=False
6464
)
6565
66-
``OrderByRaw``
67-
~~~~~~~~~~~~~~
66+
Advanced
67+
~~~~~~~~
6868

6969
SQL's ``ORDER BY`` clause is surprisingly rich in functionality, and there may
7070
be situations where you want to specify the ``ORDER BY`` explicitly using SQL.
71-
To do this use ``OrderByRaw``.
71+
To do this use :class:`QueryString <piccolo.querystring.QueryString>`.
7272

7373
In the example below, we are ordering the results randomly:
7474

7575
.. code-block:: python
7676
77-
from piccolo.query import OrderByRaw
77+
from piccolo.querystring import QueryString
7878
7979
await Band.select(Band.name).order_by(
80-
OrderByRaw('random()'),
80+
QueryString('random()'),
8181
)
8282
8383
The above is equivalent to the following SQL:
8484

8585
.. code-block:: sql
8686
8787
SELECT "band"."name" FROM band ORDER BY random() ASC
88+
89+
.. note::
90+
We used to use ``OrderByRaw`` for this (which still works for
91+
backwards compatibility).

docs/src/piccolo/query_types/select.rst

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,8 @@ And can use aliases for aggregate functions like this:
293293
294294
-------------------------------------------------------------------------------
295295

296-
SelectRaw
297-
---------
296+
Advanced
297+
--------
298298

299299
In certain situations you may want to have raw SQL in your select query.
300300

@@ -303,16 +303,21 @@ isn't supported by Piccolo:
303303

304304
.. code-block:: python
305305
306-
from piccolo.query import SelectRaw
306+
from piccolo.querystring import QueryString
307307
308308
>>> await Band.select(
309309
... Band.name,
310-
... SelectRaw("log(popularity) AS log_popularity")
310+
... QueryString("log(popularity) AS log_popularity")
311311
... )
312312
[{'name': 'Pythonistas', 'log_popularity': 3.0}]
313313
314314
.. warning:: Only use SQL that you trust.
315315

316+
.. note::
317+
We used to use ``SelectRaw`` for this, which still works, but you can just
318+
pass :class:`QueryString <piccolo.querystring.QueryString>` in directly
319+
now.
320+
316321
-------------------------------------------------------------------------------
317322

318323
Query clauses

piccolo/query/__init__.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
TableExists,
1818
Update,
1919
)
20-
from .methods.select import SelectRaw
21-
from .mixins import GroupByRaw, OrderByRaw
20+
from .methods.select import SelectRaw # for backwards compatibility
21+
from .mixins import OrderByRaw # for backwards compatibility
2222

2323
__all__ = [
2424
"Alter",
@@ -29,7 +29,6 @@
2929
"Delete",
3030
"DropIndex",
3131
"Exists",
32-
"GroupByRaw",
3332
"Insert",
3433
"Max",
3534
"Min",

piccolo/query/methods/objects.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
LockStrength,
2828
OffsetDelegate,
2929
OrderByDelegate,
30-
OrderByRaw,
3130
OutputDelegate,
3231
PrefetchDelegate,
3332
WhereDelegate,
@@ -375,9 +374,9 @@ def offset(self: Self, number: int) -> Self:
375374
return self
376375

377376
def order_by(
378-
self: Self, *columns: Union[Column, str, OrderByRaw], ascending=True
377+
self: Self, *columns: Union[Column, str, QueryString], ascending=True
379378
) -> Self:
380-
_columns: list[Union[Column, OrderByRaw]] = []
379+
_columns: list[Union[Column, QueryString]] = []
381380
for column in columns:
382381
if isinstance(column, str):
383382
_columns.append(self.table._meta.get_column_by_name(column))

piccolo/query/methods/select.py

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,11 @@
2727
ColumnsDelegate,
2828
DistinctDelegate,
2929
GroupByDelegate,
30-
GroupByRaw,
3130
LimitDelegate,
3231
LockRowsDelegate,
3332
LockStrength,
3433
OffsetDelegate,
3534
OrderByDelegate,
36-
OrderByRaw,
3735
OutputDelegate,
3836
WhereDelegate,
3937
)
@@ -57,26 +55,24 @@
5755
)
5856

5957

60-
class SelectRaw(Selectable):
61-
def __init__(self, sql: str, *args: Any) -> None:
62-
"""
63-
Execute raw SQL in your select query.
58+
class SelectRaw(QueryString):
59+
"""
60+
Here for backwards compatibility - just use
61+
:class:`piccolo.querystring.QueryString` directly.
6462
65-
.. code-block:: python
63+
Execute raw SQL in your select query.
6664
67-
>>> await Band.select(
68-
... Band.name,
69-
... SelectRaw("log(popularity) AS log_popularity")
70-
... )
71-
[{'name': 'Pythonistas', 'log_popularity': 3.0}]
65+
.. code-block:: python
7266
73-
"""
74-
self.querystring = QueryString(sql, *args)
67+
>>> await Band.select(
68+
... Band.name,
69+
... SelectRaw("log(popularity) AS log_popularity")
70+
... )
71+
[{'name': 'Pythonistas', 'log_popularity': 3.0}]
7572
76-
def get_select_string(
77-
self, engine_type: str, with_alias: bool = True
78-
) -> QueryString:
79-
return self.querystring
73+
"""
74+
75+
pass
8076

8177

8278
OptionalDict = Optional[dict[str, Any]]
@@ -205,14 +201,17 @@ def distinct(self: Self, *, on: Optional[Sequence[Column]] = None) -> Self:
205201
self.distinct_delegate.distinct(enabled=True, on=on)
206202
return self
207203

208-
def group_by(self: Self, *columns: Union[Column, str, GroupByRaw]) -> Self:
204+
def group_by(
205+
self: Self, *columns: Union[Column, str, QueryString]
206+
) -> Self:
209207
"""
210208
:param columns:
211209
Either a :class:`piccolo.columns.base.Column` instance, a string
212-
representing a column name, or :class:`piccolo.query.GroupByRaw`
213-
for grouping by a raw SQL expression or select alias.
210+
representing a column name, or
211+
:class:`piccolo.querystring.QueryString` for grouping by a raw SQL
212+
expression or select alias.
214213
"""
215-
_columns: list[Union[Column, GroupByRaw]] = []
214+
_columns: list[Union[Column, QueryString]] = []
216215
for column in columns:
217216
if isinstance(column, str):
218217
_columns.append(self.table._meta.get_column_by_name(column))
@@ -413,16 +412,16 @@ async def response_handler(self, response):
413412
return response
414413

415414
def order_by(
416-
self: Self, *columns: Union[Column, str, OrderByRaw], ascending=True
415+
self: Self, *columns: Union[Column, str, QueryString], ascending=True
417416
) -> Self:
418417
"""
419418
:param columns:
420419
Either a :class:`piccolo.columns.base.Column` instance, a string
421-
representing a column name, or :class:`piccolo.query.OrderByRaw`
422-
which allows you for complex use cases like
423-
``OrderByRaw('random()')``.
420+
representing a column name, or
421+
:class:`piccolo.querystring.QueryString` which allows you for
422+
complex use cases like ``QueryString('random()')``.
424423
"""
425-
_columns: list[Union[Column, OrderByRaw]] = []
424+
_columns: list[Union[Column, QueryString]] = []
426425
for column in columns:
427426
if isinstance(column, str):
428427
_columns.append(self.table._meta.get_column_by_name(column))

piccolo/query/mixins.py

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -142,18 +142,20 @@ def __str__(self) -> str:
142142
return self.querystring.__str__()
143143

144144

145-
@dataclass
146-
class OrderByRaw:
147-
__slots__ = ("sql",)
145+
class OrderByRaw(QueryString):
146+
"""
147+
Here for backwards compatibility - just use
148+
:class:`piccolo.querystring.QueryString` directly.
149+
"""
148150

149-
sql: str
151+
pass
150152

151153

152154
@dataclass
153155
class OrderByItem:
154156
__slots__ = ("columns", "ascending")
155157

156-
columns: Sequence[Union[Column, OrderByRaw]]
158+
columns: Sequence[Union[Column, QueryString]]
157159
ascending: bool
158160

159161

@@ -164,19 +166,24 @@ class OrderBy:
164166
@property
165167
def querystring(self) -> QueryString:
166168
order_by_strings: list[str] = []
169+
querystring_args = []
167170
for order_by_item in self.order_by_items:
168171
order = "ASC" if order_by_item.ascending else "DESC"
169172
for column in order_by_item.columns:
170173
if isinstance(column, Column):
171174
expression = column._meta.get_full_name(with_alias=False)
172-
elif isinstance(column, OrderByRaw):
173-
expression = column.sql
175+
elif isinstance(column, QueryString):
176+
expression = "{}"
177+
querystring_args.append(column)
174178
else:
175179
raise ValueError("Unrecognised order_by")
176180

177181
order_by_strings.append(f"{expression} {order}")
178182

179-
return QueryString(f" ORDER BY {', '.join(order_by_strings)}")
183+
return QueryString(
184+
f" ORDER BY {', '.join(order_by_strings)}",
185+
*querystring_args,
186+
)
180187

181188
def __str__(self):
182189
return self.querystring.__str__()
@@ -291,7 +298,7 @@ def get_order_by_columns(self) -> list[Column]:
291298
if isinstance(i, Column)
292299
]
293300

294-
def order_by(self, *columns: Union[Column, OrderByRaw], ascending=True):
301+
def order_by(self, *columns: Union[Column, QueryString], ascending=True):
295302
if len(columns) < 1:
296303
raise ValueError("At least one column must be passed to order_by.")
297304

@@ -592,33 +599,31 @@ def offset(self, number: int = 0):
592599
self._offset = Offset(number)
593600

594601

595-
@dataclass
596-
class GroupByRaw:
597-
__slots__ = ("sql",)
598-
599-
sql: str
600-
601-
602602
@dataclass
603603
class GroupBy:
604604
__slots__ = ("columns",)
605605

606-
columns: Sequence[Union[Column, GroupByRaw]]
606+
columns: Sequence[Union[Column, QueryString]]
607607

608608
@property
609609
def querystring(self) -> QueryString:
610610
column_names: list[str] = []
611+
querystring_args = []
611612
for column in self.columns:
612613
if isinstance(column, Column):
613614
column_names.append(
614615
column._meta.get_full_name(with_alias=False)
615616
)
616-
elif isinstance(column, GroupByRaw):
617-
column_names.append(column.sql)
617+
elif isinstance(column, QueryString):
618+
column_names.append("{}")
619+
querystring_args.append(column)
618620
else: # pragma: no cover
619621
raise ValueError("Unrecognised group_by")
620622

621-
return QueryString(f" GROUP BY {', '.join(column_names)}")
623+
return QueryString(
624+
f" GROUP BY {', '.join(column_names)}",
625+
*querystring_args,
626+
)
622627

623628
def __str__(self):
624629
return self.querystring.__str__()
@@ -635,7 +640,7 @@ class GroupByDelegate:
635640

636641
_group_by: Optional[GroupBy] = None
637642

638-
def group_by(self, *columns: Union[Column, GroupByRaw]):
643+
def group_by(self, *columns: Union[Column, QueryString]):
639644
self._group_by = GroupBy(columns=columns)
640645

641646

0 commit comments

Comments
 (0)