Store each hash as its raw 32 bytes in a BLOB column (closes #134) #138

Merged
clawbot merged 1 commits from issue-134-raw-hash-blobs into next 2026-10-26 03:15:39 +01:00
Collaborator

The head, tail and content columns of files become BLOB NOT NULL, each holding the raw 32-byte SHA-256 instead of its 64-character hex text. That halves what each hash costs in the table and in the files_signature index, as decided in #134 (comment).

In Go each hash is a [sha256.Size]byte from the hash phase through the database to report and trees, compared with ==. Nothing is hex-encoded, since no command prints a hash, and info reads none.

Worth knowing:

  • No query tested for a missing hash on next after #132, so there was none to rewrite.
  • The schema is edited in place at version 1, per the pre-1.0 rule in REPO_POLICIES.md.
  • File entries in the trees digest now hold raw hash bytes, which may include NUL. Each hash is 32 bytes, so the entries stay unambiguous; the comment on computeDigest says so.
  • In the tests, testHash is a stand-in, not a SHA-256: a string's bytes padded with zeros. Fixtures therefore sort as their strings do, which the report ordering tests rely on.
  • New tests check that a scanned file's three columns are BLOBs equal to its digests, and that a hash of the wrong length is refused.

Judgement call: reading a record whose hash column is not 32 bytes fails with an error naming its path, rather than copying the bytes silently.

Model: opus-5-5

The `head`, `tail` and `content` columns of `files` become `BLOB NOT NULL`, each holding the raw 32-byte SHA-256 instead of its 64-character hex text. That halves what each hash costs in the table and in the `files_signature` index, as decided in https://git.eeqj.de/sneak/sfdupes/issues/134#issuecomment-154200. In Go each hash is a `[sha256.Size]byte` from the hash phase through the database to `report` and `trees`, compared with `==`. Nothing is hex-encoded, since no command prints a hash, and `info` reads none. Worth knowing: - No query tested for a missing hash on `next` after https://git.eeqj.de/sneak/sfdupes/issues/132, so there was none to rewrite. - The schema is edited in place at version 1, per the pre-1.0 rule in `REPO_POLICIES.md`. - File entries in the `trees` digest now hold raw hash bytes, which may include NUL. Each hash is 32 bytes, so the entries stay unambiguous; the comment on `computeDigest` says so. - In the tests, `testHash` is a stand-in, not a SHA-256: a string's bytes padded with zeros. Fixtures therefore sort as their strings do, which the report ordering tests rely on. - New tests check that a scanned file's three columns are BLOBs equal to its digests, and that a hash of the wrong length is refused. Judgement call: reading a record whose hash column is not 32 bytes fails with an error naming its path, rather than copying the bytes silently. Model: opus-5-5
clawbot added the needs-review label 2026-10-26 02:15:45 +01:00
clawbot self-assigned this 2026-10-26 02:15:45 +01:00
Author
Collaborator

FAIL (needs-rework)

  • db_test.go:489: the test of the length check on reading a record stores only a one-byte head. If setHashes (db.go:609) refused only values shorter than 32 bytes, or checked only head, every test would still pass. Yet a 64-byte value, such as a hash stored as hex text, would then be read silently as its first 32 bytes, and a short tail or content would crash report and trees instead of returning the error. Acceptable: the test also stores a value longer than 32 bytes (64 bytes of hex text, say) and a wrong-length tail and content, and expects the error naming the path for each.

Model: opus-5-5

FAIL (needs-rework) - `db_test.go:489`: the test of the length check on reading a record stores only a one-byte `head`. If `setHashes` (`db.go:609`) refused only values shorter than 32 bytes, or checked only `head`, every test would still pass. Yet a 64-byte value, such as a hash stored as hex text, would then be read silently as its first 32 bytes, and a short `tail` or `content` would crash `report` and `trees` instead of returning the error. Acceptable: the test also stores a value longer than 32 bytes (64 bytes of hex text, say) and a wrong-length `tail` and `content`, and expects the error naming the path for each. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-26 02:49:33 +01:00
clawbot added 1 commit 2026-10-26 02:53:33 +01:00
The head, tail and content columns of the files table are BLOB NOT
NULL and hold the raw 32-byte SHA-256, half the size of the hex text,
in the table and in the files_signature index. The hash phase, the
records, report and trees carry each hash as a [sha256.Size]byte and
compare it with ==; nothing is hex-encoded. Reading a record whose
hash column is not 32 bytes is an error naming its path.

In the tests, testHash is a stand-in hash: a string's bytes padded
with zeros, so fixtures keep the sort order their strings give.

Judgement call: a hash of the wrong length is refused on reading,
not copied silently.

Model: opus-5-5
clawbot force-pushed issue-134-raw-hash-blobs from 894603059b to a77f07249e 2026-10-26 02:53:33 +01:00 Compare
Author
Collaborator

TestLoadRowsRefuseShortHash is now the table test TestLoadRowsRefuseWrongSizeHash: it stores a one-byte value and a 64-byte hex text in each of head, tail and content, and expects the error naming the path for each.
setHashes already refused all six, so it is unchanged.

Model: opus-5-5

`TestLoadRowsRefuseShortHash` is now the table test `TestLoadRowsRefuseWrongSizeHash`: it stores a one-byte value and a 64-byte hex text in each of `head`, `tail` and `content`, and expects the error naming the path for each. `setHashes` already refused all six, so it is unchanged. Model: opus-5-5
clawbot added needs-review and removed needs-rework labels 2026-10-26 02:54:43 +01:00
Author
Collaborator

PASS: each hash is stored in its own BLOB column and carried through report and trees as its raw 32 bytes, and the change is ready to merge into next.

Model: opus-5-5

PASS: each hash is stored in its own BLOB column and carried through `report` and `trees` as its raw 32 bytes, and the change is ready to merge into `next`. Model: opus-5-5
clawbot merged commit 68881f04f2 into next 2026-10-26 03:15:39 +01:00
clawbot deleted branch issue-134-raw-hash-blobs 2026-10-26 03:15:39 +01:00
Sign in to join this conversation.