Skip to content

Commit 6d61c1f

Browse files
authored
target is required on do_update (#1322)
1 parent 53b7628 commit 6d61c1f

File tree

3 files changed

+30
-2
lines changed

3 files changed

+30
-2
lines changed

docs/src/piccolo/query_clauses/on_conflict.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ Instead, if we want to update the ``popularity``:
7878
... Band(name="Pythonistas", popularity=1200)
7979
... ).on_conflict(
8080
... action="DO UPDATE",
81+
... target=Band.name,
8182
... values=[Band.popularity]
8283
... )
8384
@@ -93,8 +94,9 @@ If we fetch the data from the database, we'll see that it was updated:
9394

9495
Using the ``target`` argument, we can specify which constraint we're concerned
9596
with. By specifying ``target=Band.name`` we're only concerned with the unique
96-
constraint for the ``band`` column. If you omit the ``target`` argument, then
97-
it works for all constraints on the table.
97+
constraint for the ``band`` column. If you omit the ``target`` argument on
98+
``DO NOTHING`` action, then it works for all constraints on the table. For
99+
``DO UPDATE`` action, ``target`` is mandatory and must be provided.
98100

99101
.. code-block:: python
100102
:emphasize-lines: 5

piccolo/query/mixins.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,11 @@ def on_conflict(
769769
else:
770770
raise ValueError("Unrecognised `on conflict` action.")
771771

772+
if target is None and action_ == OnConflictAction.do_update:
773+
raise ValueError(
774+
"The `target` option must be provided with DO UPDATE."
775+
)
776+
772777
if where and action_ == OnConflictAction.do_nothing:
773778
raise ValueError(
774779
"The `where` option can only be used with DO NOTHING."

tests/table/test_insert.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,27 @@ def test_do_update_tuple_values(self):
174174
],
175175
)
176176

177+
def test_do_update_no_target(self):
178+
"""
179+
Make sure that `DO UPDATE` with no `target` raises an exception.
180+
"""
181+
Band = self.Band
182+
183+
new_popularity = self.band.popularity + 1000
184+
185+
with self.assertRaises(ValueError) as manager:
186+
Band.insert(
187+
Band(name=self.band.name, popularity=new_popularity)
188+
).on_conflict(
189+
action="DO UPDATE",
190+
values=[(Band.popularity, new_popularity + 2000)],
191+
).run_sync()
192+
193+
self.assertEqual(
194+
manager.exception.__str__(),
195+
"The `target` option must be provided with DO UPDATE.",
196+
)
197+
177198
def test_do_update_no_values(self):
178199
"""
179200
Make sure that `DO UPDATE` with no `values` raises an exception.

0 commit comments

Comments
 (0)