mirror of
https://github.com/simonw/sqlite-utils.git
synced 2026-09-09 10:04:10 +02:00
Allow sqlite-utils upsert to infer --pk from existing table
This commit is contained in:
parent
aa300942bf
commit
ebafb84c93
4 changed files with 30 additions and 6 deletions
|
|
@ -321,6 +321,8 @@ See :ref:`cli_upsert`.
|
||||||
incoming record has a primary key that matches an existing record the existing
|
incoming record has a primary key that matches an existing record the existing
|
||||||
record will be updated.
|
record will be updated.
|
||||||
|
|
||||||
|
If the table already exists and has a primary key, --pk can be omitted.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
echo '[
|
echo '[
|
||||||
|
|
@ -330,7 +332,6 @@ See :ref:`cli_upsert`.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--pk TEXT Columns to use as the primary key, e.g. id
|
--pk TEXT Columns to use as the primary key, e.g. id
|
||||||
[required]
|
|
||||||
--flatten Flatten nested JSON objects, so {"a": {"b": 1}}
|
--flatten Flatten nested JSON objects, so {"a": {"b": 1}}
|
||||||
becomes {"a_b": 1}
|
becomes {"a_b": 1}
|
||||||
--nl Expect newline-delimited JSON
|
--nl Expect newline-delimited JSON
|
||||||
|
|
|
||||||
|
|
@ -1593,6 +1593,8 @@ For example:
|
||||||
|
|
||||||
This will update the dog with an ID of 2 to have an age of 4, creating a new record (with a null name) if one does not exist. If a row DOES exist the name will be left as-is.
|
This will update the dog with an ID of 2 to have an age of 4, creating a new record (with a null name) if one does not exist. If a row DOES exist the name will be left as-is.
|
||||||
|
|
||||||
|
If the table already exists and has a primary key, you can omit the ``--pk`` option and ``sqlite-utils`` will use that existing primary key.
|
||||||
|
|
||||||
The command will fail if you reference columns that do not exist on the table. To automatically create missing columns, use the ``--alter`` option.
|
The command will fail if you reference columns that do not exist on the table. To automatically create missing columns, use the ``--alter`` option.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ from sqlite_utils.db import (
|
||||||
InvalidColumns,
|
InvalidColumns,
|
||||||
NoTable,
|
NoTable,
|
||||||
NoView,
|
NoView,
|
||||||
|
PrimaryKeyRequired,
|
||||||
quote_identifier,
|
quote_identifier,
|
||||||
)
|
)
|
||||||
from sqlite_utils.plugins import ensure_plugins_loaded, pm, get_plugins
|
from sqlite_utils.plugins import ensure_plugins_loaded, pm, get_plugins
|
||||||
|
|
@ -1184,7 +1185,7 @@ def insert_upsert_implementation(
|
||||||
db.table(table).insert_all(
|
db.table(table).insert_all(
|
||||||
docs, pk=pk, batch_size=batch_size, alter=alter, **extra_kwargs
|
docs, pk=pk, batch_size=batch_size, alter=alter, **extra_kwargs
|
||||||
)
|
)
|
||||||
except (NoTable, InvalidColumns) as e:
|
except (NoTable, InvalidColumns, PrimaryKeyRequired) as e:
|
||||||
raise click.ClickException(str(e))
|
raise click.ClickException(str(e))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if (
|
if (
|
||||||
|
|
@ -1372,7 +1373,7 @@ def insert(
|
||||||
|
|
||||||
|
|
||||||
@cli.command()
|
@cli.command()
|
||||||
@insert_upsert_options(require_pk=True)
|
@insert_upsert_options()
|
||||||
def upsert(
|
def upsert(
|
||||||
path,
|
path,
|
||||||
table,
|
table,
|
||||||
|
|
@ -1408,6 +1409,8 @@ def upsert(
|
||||||
an incoming record has a primary key that matches an existing record
|
an incoming record has a primary key that matches an existing record
|
||||||
the existing record will be updated.
|
the existing record will be updated.
|
||||||
|
|
||||||
|
If the table already exists and has a primary key, --pk can be omitted.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
\b
|
\b
|
||||||
|
|
|
||||||
|
|
@ -1235,20 +1235,38 @@ def test_upsert(db_path, tmpdir):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def test_upsert_pk_required(db_path, tmpdir):
|
def test_upsert_pk_inferred_from_existing_table(db_path, tmpdir):
|
||||||
json_path = str(tmpdir / "dogs.json")
|
json_path = str(tmpdir / "dogs.json")
|
||||||
|
db = Database(db_path)
|
||||||
insert_dogs = [
|
insert_dogs = [
|
||||||
{"id": 1, "name": "Cleo", "age": 4},
|
{"id": 1, "name": "Cleo", "age": 4},
|
||||||
{"id": 2, "name": "Nixie", "age": 4},
|
{"id": 2, "name": "Nixie", "age": 4},
|
||||||
]
|
]
|
||||||
write_json(json_path, insert_dogs)
|
write_json(json_path, insert_dogs)
|
||||||
|
result = CliRunner().invoke(
|
||||||
|
cli.cli,
|
||||||
|
["insert", db_path, "dogs", json_path, "--pk", "id"],
|
||||||
|
catch_exceptions=False,
|
||||||
|
)
|
||||||
|
assert result.exit_code == 0, result.output
|
||||||
|
|
||||||
|
write_json(
|
||||||
|
json_path,
|
||||||
|
[
|
||||||
|
{"id": 1, "age": 5},
|
||||||
|
{"id": 2, "age": 5},
|
||||||
|
],
|
||||||
|
)
|
||||||
result = CliRunner().invoke(
|
result = CliRunner().invoke(
|
||||||
cli.cli,
|
cli.cli,
|
||||||
["upsert", db_path, "dogs", json_path],
|
["upsert", db_path, "dogs", json_path],
|
||||||
catch_exceptions=False,
|
catch_exceptions=False,
|
||||||
)
|
)
|
||||||
assert result.exit_code == 2
|
assert result.exit_code == 0, result.output
|
||||||
assert "Error: Missing option '--pk'" in result.output
|
assert list(db.query("select * from dogs order by id")) == [
|
||||||
|
{"id": 1, "name": "Cleo", "age": 5},
|
||||||
|
{"id": 2, "name": "Nixie", "age": 5},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def test_upsert_analyze(db_path, tmpdir):
|
def test_upsert_analyze(db_path, tmpdir):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue