Skip to content

Commit b722b89

Browse files
committed
refactoring update command
1 parent 0ef521e commit b722b89

File tree

4 files changed

+69
-31
lines changed

4 files changed

+69
-31
lines changed

piccolo/commands/playground.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from piccolo import table
1010
from piccolo import columns
11-
from piccolo.engine import SQLiteEngine
11+
from piccolo.engine import SQLiteEngine, PostgresEngine
1212

1313

1414
# DB = PostgresEngine({})

piccolo/query/methods/update.py

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,48 @@
11
from __future__ import annotations
22

33
from piccolo.query.base import Query
4-
from piccolo.query.mixins import WhereMixin
4+
from piccolo.query.mixins import ValuesMixin, WhereMixin
55
from piccolo.querystring import QueryString
66

77

8-
class Update(Query, WhereMixin):
8+
class Update(Query, ValuesMixin, WhereMixin):
99

1010
@property
11-
def querystring(self) -> QueryString:
12-
querystring = self.base
11+
def sqlite_querystring(self) -> QueryString:
12+
raise NotImplementedError()
13+
14+
def validate(self):
15+
if len(self._values) == 0:
16+
raise ValueError(
17+
"No values were specified to update - please use .values"
18+
)
19+
20+
for column, value in self._values.items():
21+
if len(column.call_chain) > 0:
22+
raise ValueError(
23+
"Related values can't be updated via an update"
24+
)
25+
26+
@property
27+
def postgres_querystring(self) -> QueryString:
28+
self.validate()
29+
30+
columns_str = ', '.join([
31+
f'{column_name} = {{}}' for column_name, _ in self._values.items()
32+
])
33+
34+
query = f'UPDATE {self.table.Meta.tablename} SET ' + columns_str
35+
36+
querystring = QueryString(
37+
query,
38+
self._values.values()
39+
)
40+
41+
# TODO - need to support joins
42+
# UPDATE band SET name='bob' FROM manager WHERE band.manager = manager.id AND manager.name = 'Guido';
43+
# I think the joins should work differently from select i.e. no need
44+
# to shared underlying code.
45+
1346
if self._where:
1447
where_querystring = QueryString(
1548
'{} WHERE {}',
@@ -20,5 +53,3 @@ def querystring(self) -> QueryString:
2053
else:
2154
return querystring
2255

23-
def __str__(self) -> str:
24-
return self.querystring.__str__()

piccolo/query/mixins.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,3 +198,21 @@ def __init__(self):
198198
def columns(self, *columns: Column):
199199
self.selected_columns += columns
200200
return self
201+
202+
203+
class ValuesMixin():
204+
"""
205+
Used to specify new column values - primarily used in update queries.
206+
207+
Example usage:
208+
209+
.values({MyTable.column_a: 1})
210+
"""
211+
212+
def __init__(self):
213+
super().__init__()
214+
self._values: t.Dict[Column, t.Any] = {}
215+
216+
def values(self, values: t.Dict[Column, t.Any]):
217+
self._values.update(values)
218+
return self

piccolo/table.py

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,19 @@ def select(cls) -> Select:
177177
table=cls,
178178
)
179179

180+
@property
181+
def update(cls) -> Update:
182+
"""
183+
Update rows.
184+
185+
await Band.update.values(
186+
{Band.name: "Spamalot"}
187+
).where(Band.name=="Pythonistas")
188+
"""
189+
return Update(
190+
table=cls,
191+
)
192+
180193

181194
class Table(metaclass=TableMeta):
182195

@@ -355,30 +368,6 @@ def insert(cls, *rows: 'Table') -> Insert:
355368
query.add(*rows)
356369
return query
357370

358-
# TODO - needs refactoring into Band.update.columns()
359-
@classmethod
360-
def update(cls, **columns) -> Update:
361-
"""
362-
await Band.update(name='Spamalot').where(
363-
Band.name='Pythonistas'
364-
).run()
365-
"""
366-
columns_str = ', '.join([
367-
f'{column_name} = {{}}' for column_name in columns.keys()
368-
])
369-
370-
query = f'UPDATE {cls.Meta.tablename} SET ' + columns_str
371-
372-
querystring = QueryString(
373-
query,
374-
*columns.values()
375-
)
376-
377-
return Update(
378-
table=cls,
379-
base=querystring
380-
)
381-
382371
@classmethod
383372
def raw(cls, sql: str) -> Raw:
384373
"""

0 commit comments

Comments
 (0)