insert-files: add --sqlar flag and content_sqlar column for sqlar-compatible compressed payloads

Adds a --sqlar option that defaults insert-files to the name/mode/mtime/sz/data
schema used by SQLite's own sqlar archive format, plus a content_sqlar column
type that zlib-compresses content the same way sqlar_compress() does (only
when compression actually shrinks the data). Reuses the existing -c coldef
parsing added for fixed-literal metadata columns, no changes needed there.
Existing BLOB/TEXT content/content_text imports are untouched.

Closes #141
This commit is contained in:
Parker Gurney 2026-08-05 14:11:30 -07:00
commit daf2ebbbaf
3 changed files with 91 additions and 2 deletions

View file

@ -1,6 +1,7 @@
import os
import pathlib
import sys
import zlib
import pytest
from click.testing import CliRunner
@ -171,6 +172,55 @@ def test_insert_files_fixed_value_column_bad_type():
assert "colname:text:value" in result.output
def test_insert_files_sqlar():
runner = CliRunner()
with runner.isolated_filesystem():
tmpdir = pathlib.Path(".")
db_path = str(tmpdir / "files.db")
# Compresses well - lots of repetition
compressible = b"abcdefgh" * 1000
# Does not compress smaller than the original
incompressible = os.urandom(20)
(tmpdir / "one.txt").write_bytes(compressible)
(tmpdir / "two.bin").write_bytes(incompressible)
result = runner.invoke(
cli.cli,
["insert-files", db_path, "sqlar", str(tmpdir), "--sqlar"],
catch_exceptions=False,
)
assert result.exit_code == 0, result.output
db = Database(db_path)
assert db["sqlar"].columns_dict == {
"name": str,
"mode": int,
"mtime": int,
"sz": int,
"data": bytes,
}
assert db["sqlar"].pks == ["name"]
rows_by_name = {r["name"]: r for r in db["sqlar"].rows}
one, two = rows_by_name["one.txt"], rows_by_name["two.bin"]
assert one["sz"] == len(compressible)
assert len(one["data"]) < len(compressible)
assert zlib.decompress(one["data"]) == compressible
assert two["sz"] == len(incompressible)
assert two["data"] == incompressible
def test_insert_files_sqlar_and_text_conflict():
runner = CliRunner()
with runner.isolated_filesystem():
tmpdir = pathlib.Path(".")
db_path = str(tmpdir / "files.db")
(tmpdir / "one.txt").write_text("hello", "utf-8")
result = runner.invoke(
cli.cli,
["insert-files", db_path, "files", str(tmpdir), "--text", "--sqlar"],
)
assert result.exit_code == 1
assert "Cannot use --text and --sqlar together" in result.output
@pytest.mark.parametrize(
"use_text,encoding,input,expected",
(