Keep all SQL and DB-specific logic in a single dbops layer and expose a small, consistent API that handles common patterns: insert/update (use REPLACE/UPSERT), delete, queries, and serialization of complex fields. Motivation: reduces duplicated SQL across packages, avoids mismatch between INSERT vs UPDATE code paths, and centralizes serialization/transaction handling for sqlite or other stores.

How to apply (practical steps):

Example (replace separate insert/update with REPLACE): query := REPLACE INTO block_file VALUES (?, ?, ?, ?, ?, ?, ?, ?) // tx.Exec(query, fileInfo.BlockId, fileInfo.Name, fileInfo.Opts.MaxSize, fileInfo.Opts.Circular, fileInfo.Size, fileInfo.CreatedTs, fileInfo.ModTs, metaJson)

metaJson, err := quickJson(fileInfo.Meta) if err != nil { return fmt.Errorf(“error serializing meta for %s: %w”, fileInfo.Name, err) } // then use metaJson in the REPLACE/UPSERT

Checklist for changes:

Benefit: clearer separation of concerns, fewer duplicated SQL code paths, consistent serialization, and easier maintenance and optimization of queries.