insert-files: support fixed value columns via -c colname:text:value

Extends the -c/--column spec so a column can be populated with a
literal value for every inserted file, e.g. -c file_type:text:gif,
without a separate update pass. Existing colname:coldef shorthands
and compound --pk behavior are unchanged.

Closes #140
This commit is contained in:
Parker Gurney 2026-08-05 14:06:58 -07:00
commit 71664b8fcf
3 changed files with 74 additions and 2 deletions

View file

@ -1747,6 +1747,13 @@ You can change the name of one of these columns using a ``-c colname:coldef`` pa
sqlite-utils insert-files gifs.db images *.gif \
-c path -c md5 -c last_modified:mtime --pk=path
You can also populate a column with a fixed value for every file using a ``-c colname:text:value`` parameter. This is useful for tagging every row from a given import with the same value, without a separate update pass:
.. code-block:: bash
sqlite-utils insert-files gifs.db images *.gif \
-c path -c content -c file_type:text:gif --pk=path
You can pass ``--replace`` or ``--upsert`` to indicate what should happen if you try to insert a file with an existing primary key. Pass ``--alter`` to cause any missing columns to be added to the table.
The full list of column definitions you can use is as follows:

View file

@ -2978,8 +2978,19 @@ def insert_files(
"size": lambda p, data=stdin_data: len(data),
}
for coldef in column:
if ":" in coldef:
colname, coltype = coldef.rsplit(":", 1)
parts = coldef.split(":", 2)
if len(parts) == 3:
# Fixed value, e.g. -c file_type:text:gif
colname, coltype, fixed_value = parts
if coltype != "text":
raise click.ClickException(
"Fixed value column definitions must use "
"'colname:text:value', not '{}'".format(coldef)
)
row[colname] = fixed_value
continue
elif len(parts) == 2:
colname, coltype = parts
else:
colname, coltype = coldef, coldef
try:

View file

@ -117,6 +117,60 @@ def test_insert_files(silent, pk_args, expected_pks):
assert set(db["files"].pks) == set(expected_pks)
def test_insert_files_fixed_value_column():
runner = CliRunner()
with runner.isolated_filesystem():
tmpdir = pathlib.Path(".")
db_path = str(tmpdir / "files.db")
(tmpdir / "one.gif").write_text("gif content", "utf-8")
result = runner.invoke(
cli.cli,
[
"insert-files",
db_path,
"files",
str(tmpdir / "one.gif"),
"-c",
"path",
"-c",
"content",
"-c",
"file_type:text:gif",
"--pk",
"path",
"--pk",
"file_type",
],
catch_exceptions=False,
)
assert result.exit_code == 0, result.output
db = Database(db_path)
row = next(iter(db["files"].rows))
assert row["file_type"] == "gif"
assert set(db["files"].pks) == {"path", "file_type"}
def test_insert_files_fixed_value_column_bad_type():
runner = CliRunner()
with runner.isolated_filesystem():
tmpdir = pathlib.Path(".")
db_path = str(tmpdir / "files.db")
(tmpdir / "one.gif").write_text("gif content", "utf-8")
result = runner.invoke(
cli.cli,
[
"insert-files",
db_path,
"files",
str(tmpdir / "one.gif"),
"-c",
"file_type:mtime:gif",
],
)
assert result.exit_code == 1
assert "colname:text:value" in result.output
@pytest.mark.parametrize(
"use_text,encoding,input,expected",
(