alter=True/--alter option to automatically add missing columns

Closes #18
This commit is contained in:
Simon Willison 2019-05-24 17:41:04 -07:00
commit eff52023c6
6 changed files with 204 additions and 9 deletions

View file

@ -383,6 +383,37 @@ def test_upsert(db_path, tmpdir):
)
def test_insert_alter(db_path, tmpdir):
result = CliRunner().invoke(
cli.cli,
["insert", db_path, "from_json_nl", "-", "--nl"],
input='{"foo": "bar", "n": 1}\n{"foo": "baz", "n": 2}',
)
assert 0 == result.exit_code, result.output
# Should get an error with incorrect shaped additional data
result = CliRunner().invoke(
cli.cli,
["insert", db_path, "from_json_nl", "-", "--nl"],
input='{"foo": "bar", "baz": 5}',
)
assert 0 != result.exit_code, result.output
# If we run it again with --alter it should work correctly
result = CliRunner().invoke(
cli.cli,
["insert", db_path, "from_json_nl", "-", "--nl", "--alter"],
input='{"foo": "bar", "baz": 5}',
)
assert 0 == result.exit_code, result.output
# Sanity check the database itself
db = Database(db_path)
assert {"foo": str, "n": int, "baz": int} == db["from_json_nl"].columns_dict
assert [
{"foo": "bar", "n": 1, "baz": None},
{"foo": "baz", "n": 2, "baz": None},
{"foo": "bar", "baz": 5, "n": None},
] == db.execute_returning_dicts("select foo, n, baz from from_json_nl")
def test_query_csv(db_path):
db = Database(db_path)
with db.conn:

View file

@ -195,6 +195,89 @@ def test_add_foreign_key_error_if_already_exists(fresh_db):
assert "Foreign key already exists for author_id => authors.id" == ex.value.args[0]
@pytest.mark.parametrize(
"extra_data,expected_new_columns",
[
({"species": "squirrels"}, [{"name": "species", "type": "TEXT"}]),
(
{"species": "squirrels", "hats": 5},
[{"name": "species", "type": "TEXT"}, {"name": "hats", "type": "INTEGER"}],
),
(
{"hats": 5, "rating": 3.5},
[{"name": "hats", "type": "INTEGER"}, {"name": "rating", "type": "FLOAT"}],
),
],
)
def test_insert_row_alter_table(fresh_db, extra_data, expected_new_columns):
table = fresh_db["books"]
table.insert({"title": "Hedgehogs of the world", "author_id": 1})
assert [
{"name": "title", "type": "TEXT"},
{"name": "author_id", "type": "INTEGER"},
] == [{"name": col.name, "type": col.type} for col in table.columns]
record = {"title": "Squirrels of the world", "author_id": 2}
record.update(extra_data)
fresh_db["books"].insert(record, alter=True)
assert [
{"name": "title", "type": "TEXT"},
{"name": "author_id", "type": "INTEGER"},
] + expected_new_columns == [
{"name": col.name, "type": col.type} for col in table.columns
]
def test_upsert_rows_alter_table(fresh_db):
table = fresh_db["books"]
table.insert({"id": 1, "title": "Hedgehogs of the world", "author_id": 1}, pk="id")
table.upsert_all(
[
{"id": 1, "title": "Hedgedogs of the World", "species": "hedgehogs"},
{"id": 2, "title": "Squirrels of the World", "num_species": 200},
{
"id": 3,
"title": "Badgers of the World",
"significant_continents": ["Europe", "North America"],
},
],
alter=True,
)
assert {
"author_id": int,
"id": int,
"num_species": int,
"significant_continents": str,
"species": str,
"title": str,
} == table.columns_dict
assert [
{
"author_id": None,
"id": 1,
"num_species": None,
"significant_continents": None,
"species": "hedgehogs",
"title": "Hedgedogs of the World",
},
{
"author_id": None,
"id": 2,
"num_species": 200,
"significant_continents": None,
"species": None,
"title": "Squirrels of the World",
},
{
"author_id": None,
"id": 3,
"num_species": None,
"significant_continents": '["Europe", "North America"]',
"species": None,
"title": "Badgers of the World",
},
] == list(table.rows)
@pytest.mark.parametrize(
"columns,index_name,expected_index",
(