Skip to content

Commit

Permalink
Merge pull request #30 from AnswerDotAI/add-returning-to-update
Browse files Browse the repository at this point in the history
Add RETURNING to Table.update()
  • Loading branch information
jph00 authored Nov 6, 2024
2 parents 2b7da3c + 4530c7e commit cc82a30
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 17 deletions.
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,13 +238,36 @@ sqlite-minutils is different from sqlite-utils in that write actions
affected without relying on `last_rowid`. It does this through the
`RETURNING` SQL keyword.

Testing `INSERT`

``` python
user = users.insert(dict(name='Turkey', age=2, pwd='gravy'))
user
```

{'id': 8, 'name': 'Turkey', 'age': 2, 'pwd': 'gravy'}
{'id': 6, 'name': 'Turkey', 'age': 2, 'pwd': 'gravy'}

``` python
test(user['name'], 'Turkey', equals)
```

Testing `UPDATE`

``` python
user = users.insert(dict(name='Flamingo', age=12, pwd='pink'))
user
```

{'id': 8, 'name': 'Flamingo', 'age': 12, 'pwd': 'pink'}

``` python
user = users.update(user['id'], dict(name='Kiwi', pwd='pumpkin'))
user
```

{'id': 7, 'name': 'Kiwi', 'age': 12, 'pwd': 'pumpkin'}

``` python
test(user['name'], 'Kiwi', equals)
test(users.last_pk, user['id'], equals)
```
79 changes: 68 additions & 11 deletions nbs/index.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,7 @@
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The autoreload extension is already loaded. To reload it, use:\n",
" %reload_ext autoreload\n"
]
}
],
"outputs": [],
"source": [
"#| hide\n",
"%load_ext autoreload\n",
Expand Down Expand Up @@ -581,6 +572,13 @@
"sqlite-minutils is different from sqlite-utils in that write actions (`INSERT`, `UPDATE`, `UPSERT`) return back the record(s) they have affected without relying on `last_rowid`. It does this through the `RETURNING` SQL keyword."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Testing `INSERT`"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand All @@ -589,7 +587,7 @@
{
"data": {
"text/plain": [
"{'id': 8, 'name': 'Turkey', 'age': 2, 'pwd': 'gravy'}"
"{'id': 6, 'name': 'Turkey', 'age': 2, 'pwd': 'gravy'}"
]
},
"execution_count": null,
Expand All @@ -610,6 +608,65 @@
"source": [
"test(user['name'], 'Turkey', equals)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Testing `UPDATE`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'id': 8, 'name': 'Flamingo', 'age': 12, 'pwd': 'pink'}"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"user = users.insert(dict(name='Flamingo', age=12, pwd='pink'))\n",
"user"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'id': 7, 'name': 'Kiwi', 'age': 12, 'pwd': 'pumpkin'}"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"user = users.update(user['id'], dict(name='Kiwi', pwd='pumpkin'))\n",
"user"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"test(user['name'], 'Kiwi', equals)\n",
"test(users.last_pk, user['id'], equals)"
]
}
],
"metadata": {
Expand Down
14 changes: 9 additions & 5 deletions sqlite_minutils/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -2700,7 +2700,7 @@ def update(
updates: Optional[dict] = None,
alter: bool = False,
conversions: Optional[dict] = None,
) -> "Table":
) -> Dict:
"""
Execute a SQL ``UPDATE`` against the specified row.
Expand Down Expand Up @@ -2731,23 +2731,27 @@ def update(
args.append(jsonify_if_needed(value))
wheres = ["[{}] = ?".format(pk_name) for pk_name in pks]
args.extend(pk_values)
sql = "update [{table}] set {sets} where {wheres}".format(
sql = "update [{table}] set {sets} where {wheres} returning *".format(
table=self.name, sets=", ".join(sets), wheres=" and ".join(wheres)
)
try:
rowcount = self.db.execute(sql, args).rowcount
cursor = self.db.execute(sql, args)
cursor.rowcount
except OperationalError as e:
if alter and (" column" in e.args[0]):
# Attempt to add any missing columns, then try again
self.add_missing_columns([updates])
rowcount = self.db.execute(sql, args).rowcount
cursor = self.db.execute(sql, args)
cursor.rowcount
else:
raise

# TODO: Test this works (rolls back) - use better exception:
# assert rowcount == 1
self.last_pk = pk_values[0] if len(pks) == 1 else pk_values
return self

columns = [c[0] for c in cursor.description]
return dict(zip(columns, cursor.fetchone()))

def build_insert_queries_and_params(
self,
Expand Down

0 comments on commit cc82a30

Please sign in to comment.