allVariantKeys and allSourceContentHashes were byte-for-byte the same
query-scan-collect loop over a single string column, differing only in
the SQL, the result type and the noun in their error messages. Both now
delegate to a generic queryStringColumn helper.
Extracted rather than suppressed with a nolint: the duplication was
real, and the two call sites are the only places this shape appears.
Every error message is preserved verbatim, which is why the helper takes
both a plural and a singular noun.