insert --alter support, closes #23

This commit is contained in:
Simon Willison 2024-02-27 20:49:54 -08:00
commit adfa6cce14
3 changed files with 32 additions and 1 deletions

View file

@ -108,6 +108,7 @@ def query(url_or_alias, sql, token):
)
@click.option("--ignore", is_flag=True, help="Ignore rows with a matching primary key")
@click.option("--create", is_flag=True, help="Create table if it does not exist")
@click.option("--alter", is_flag=True, help="Alter table to add any missing columns")
@click.option(
"pks",
"--pk",
@ -135,6 +136,7 @@ def insert(
replace,
ignore,
create,
alter,
pks,
batch_size,
interval,
@ -240,6 +242,7 @@ def insert(
batch=batch,
token=token,
create=create,
alter=alter,
pks=pks,
replace=replace,
ignore=ignore,
@ -422,7 +425,7 @@ def _batches(iterable, size, interval=None):
last_yield_time = time.time()
def _insert_batch(*, url, table, batch, token, create, pks, replace, ignore):
def _insert_batch(*, url, table, batch, token, create, alter, pks, replace, ignore):
if create:
data = {
"table": table,
@ -432,6 +435,8 @@ def _insert_batch(*, url, table, batch, token, create, pks, replace, ignore):
data["replace"] = True
if ignore:
data["ignore"] = True
if alter:
data["alter"] = True
if pks:
if len(pks) == 1:
data["pk"] = pks[0]
@ -446,6 +451,8 @@ def _insert_batch(*, url, table, batch, token, create, pks, replace, ignore):
data["replace"] = True
if ignore:
data["ignore"] = True
if alter:
data["alter"] = True
url = "{}/{}/-/insert".format(url, table)
response = httpx.post(
url,

View file

@ -88,6 +88,7 @@ You can disable this and have every value treated as a string using `--no-detect
- `--create` - create the table if it doesn't already exist
- `--replace` - replace any rows with a matching primary key
- `--ignore` - ignore any rows with a matching existing primary key
- `--alter` - alter table to add any columns that are missing
- `--pk id` - set a primary key (for if the table is being created)
If you use `--create` a table will be created with rows to match the columns in your uploaded data - using the correctly detected types, unless you use `--no-detect-types` in which case every column will be of type `text`.
@ -125,6 +126,7 @@ Options:
--replace Replace rows with a matching primary key
--ignore Ignore rows with a matching primary key
--create Create table if it does not exist
--alter Alter table to add any missing columns
--pk TEXT Columns to use as the primary key when creating the
table
--batch-size INTEGER Send rows in batches of this size

View file

@ -206,6 +206,27 @@ def make_format_test(content, arg):
should_error=False,
expected_table_json=[{"a": 1, "b": 2, "c": 3}, {"a": 4, "b": 5, "c": 6}],
),
# Existing table without alter should fail
InsertTest(
input_data="a,b,c,d\n1,2,4,5\n",
cmd_args=["--ignore"],
table_exists=True,
expected_output="Inserting rows\nError: Row 0 has invalid columns: d\n",
should_error=True,
expected_table_json=[{"a": 1, "b": 2, "c": 3}, {"a": 4, "b": 5, "c": 6}],
),
# Existing table with --alter should work
InsertTest(
input_data="a,b,c,d\n1,2,4,5\n",
cmd_args=["--replace", "--alter"],
table_exists=True,
expected_output="Inserting rows\n",
should_error=False,
expected_table_json=[
{"a": 1, "b": 2, "c": 4, "d": 5},
{"a": 4, "b": 5, "c": 6, "d": None},
],
),
),
)
def test_insert_against_datasette(
@ -224,6 +245,7 @@ def test_insert_against_datasette(
"create-table": {"id": "*"},
"insert-row": {"id": "*"},
"update-row": {"id": "*"},
"alter-table": {"id": "*"},
}
}
)