Skip to content

Commit

Permalink
1079 Add batch to raw queries (#1080)
Browse files Browse the repository at this point in the history
* add `batch` to `raw` queries

* link to `batch` clause from `Raw` docs page
  • Loading branch information
dantownsend authored Sep 16, 2024
1 parent 89f1adb commit df86c2e
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 2 deletions.
1 change: 1 addition & 0 deletions docs/src/piccolo/query_clauses/batch.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ batch
You can use ``batch`` clauses with the following queries:

* :ref:`Objects`
* :ref:`Raw`
* :ref:`Select`

Example
Expand Down
15 changes: 13 additions & 2 deletions docs/src/piccolo/query_types/raw.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,26 @@ Should you need to, you can execute raw SQL.

.. code-block:: python
>>> await Band.raw('select name from band')
>>> await Band.raw('SELECT name FROM band')
[{'name': 'Pythonistas'}]
It's recommended that you parameterise any values. Use curly braces ``{}`` as
placeholders:

.. code-block:: python
>>> await Band.raw('select * from band where name = {}', 'Pythonistas')
>>> await Band.raw('SELECT * FROM band WHERE name = {}', 'Pythonistas')
[{'name': 'Pythonistas', 'manager': 1, 'popularity': 1000, 'id': 1}]
.. warning:: Be careful to avoid SQL injection attacks. Don't add any user submitted data into your SQL strings, unless it's parameterised.


-------------------------------------------------------------------------------

Query clauses
-------------

batch
~~~~~

See :ref:`batch`.
13 changes: 13 additions & 0 deletions piccolo/query/methods/raw.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import typing as t

from piccolo.engine.base import BaseBatch
from piccolo.query.base import Query
from piccolo.querystring import QueryString

Expand All @@ -21,6 +22,18 @@ def __init__(
super().__init__(table, **kwargs)
self.querystring = querystring

async def batch(
self,
batch_size: t.Optional[int] = None,
node: t.Optional[str] = None,
**kwargs,
) -> BaseBatch:
if batch_size:
kwargs.update(batch_size=batch_size)
if node:
kwargs.update(node=node)
return await self.table._meta.db.batch(self, **kwargs)

@property
def default_querystrings(self) -> t.Sequence[QueryString]:
return [self.querystring]
41 changes: 41 additions & 0 deletions tests/table/test_batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,47 @@ def test_batch(self):
self.assertEqual(iterations, _iterations)


class TestBatchRaw(DBTestCase):
def _check_results(self, batch):
"""
Make sure the data is returned in the correct format.
"""
self.assertEqual(type(batch), list)
if len(batch) > 0:
row = batch[0]
self.assertIsInstance(row, Manager)

async def run_batch(self, batch_size):
row_count = 0
iterations = 0

async with await Manager.raw("SELECT * FROM manager").batch(
batch_size=batch_size
) as batch:
async for _batch in batch:
self._check_results(_batch)
_row_count = len(_batch)
row_count += _row_count
iterations += 1

return row_count, iterations

async def test_batch(self):
row_count = 1000
self.insert_many_rows(row_count)

batch_size = 10

_row_count, iterations = asyncio.run(
self.run_batch(batch_size=batch_size), debug=True
)

_iterations = math.ceil(row_count / batch_size)

self.assertEqual(_row_count, row_count)
self.assertEqual(iterations, _iterations)


@engines_only("postgres", "cockroach")
class TestBatchNodeArg(TestCase):
def test_batch_extra_node(self):
Expand Down

0 comments on commit df86c2e

Please sign in to comment.