Better validation for upsert --pk, closes #390

This commit is contained in:
Simon Willison 2022-01-25 19:19:39 -08:00
commit 2b20957b18
3 changed files with 79 additions and 59 deletions

View file

@ -253,8 +253,6 @@ 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.
The --pk option is required.
Example: Example:
echo '[ echo '[
@ -264,6 +262,7 @@ 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

View file

@ -813,7 +813,8 @@ def import_options(fn):
return fn return fn
def insert_upsert_options(fn): def insert_upsert_options(*, require_pk=False):
def inner(fn):
for decorator in reversed( for decorator in reversed(
( (
click.argument( click.argument(
@ -824,7 +825,10 @@ def insert_upsert_options(fn):
click.argument("table"), click.argument("table"),
click.argument("file", type=click.File("rb"), required=True), click.argument("file", type=click.File("rb"), required=True),
click.option( click.option(
"--pk", help="Columns to use as the primary key, e.g. id", multiple=True "--pk",
help="Columns to use as the primary key, e.g. id",
multiple=True,
required=require_pk,
), ),
) )
+ _import_options + _import_options
@ -867,6 +871,8 @@ def insert_upsert_options(fn):
fn = decorator(fn) fn = decorator(fn)
return fn return fn
return inner
def insert_upsert_implementation( def insert_upsert_implementation(
path, path,
@ -1060,7 +1066,7 @@ def _find_variables(tb, vars):
@cli.command() @cli.command()
@insert_upsert_options @insert_upsert_options()
@click.option( @click.option(
"--ignore", is_flag=True, default=False, help="Ignore records if pk already exists" "--ignore", is_flag=True, default=False, help="Ignore records if pk already exists"
) )
@ -1168,7 +1174,7 @@ def insert(
@cli.command() @cli.command()
@insert_upsert_options @insert_upsert_options(require_pk=True)
def upsert( def upsert(
path, path,
table, table,
@ -1201,8 +1207,6 @@ 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.
The --pk option is required.
Example: Example:
\b \b

View file

@ -922,6 +922,23 @@ def test_upsert(db_path, tmpdir):
] ]
def test_upsert_pk_required(db_path, tmpdir):
json_path = str(tmpdir / "dogs.json")
db = Database(db_path)
insert_dogs = [
{"id": 1, "name": "Cleo", "age": 4},
{"id": 2, "name": "Nixie", "age": 4},
]
open(json_path, "w").write(json.dumps(insert_dogs))
result = CliRunner().invoke(
cli.cli,
["upsert", db_path, "dogs", json_path],
catch_exceptions=False,
)
assert result.exit_code == 2
assert "Error: Missing option '--pk'" in result.output
def test_upsert_analyze(db_path, tmpdir): def test_upsert_analyze(db_path, tmpdir):
db = Database(db_path) db = Database(db_path)
db["rows"].insert({"id": 1, "foo": "x", "n": 3}, pk="id") db["rows"].insert({"id": 1, "foo": "x", "n": 3}, pk="id")