-- FROZEN FIXTURE. querylog.db schema version 1: byte-for-byte the `ddl` text of -- `src/storage/querylog_schema.zig`, which is the schema the 0.0.12 and 0.0.13 -- binaries created and the one version 1 names. -- -- IMMUTABLE once released. The release gate byte-compares this file against the -- previous tag and fails the cut on any edit, because it is the starting point -- every future migration is proved against: editing it would prove a migration -- against a file no operator ever had. A new schema version ships a NEW pair. -- -- The `PRAGMA user_version` stamp is deliberately NOT part of this file. The -- loader applies it, which is what lets one fixture serve both the version-1 -- stamp and the 0.0.12/0.0.13 legacy fingerprint. CREATE TABLE domains ( id INTEGER PRIMARY KEY, domain TEXT NOT NULL UNIQUE ); CREATE TABLE query_log ( id INTEGER PRIMARY KEY, timestamp INTEGER NOT NULL, domain_id INTEGER NOT NULL REFERENCES domains(id), client_ip TEXT NOT NULL, -- text, not a FK: log rows are immutable facts qtype INTEGER, blocked INTEGER NOT NULL, response_time_us INTEGER, cache_hit INTEGER, upstream TEXT, qclass INTEGER NOT NULL, rcode INTEGER NOT NULL, group_id INTEGER, -- text/id pairs, not FKs: a renamed group_name TEXT, -- group must not rewrite history policy_action TEXT NOT NULL, policy_reason TEXT NOT NULL, matched TEXT, source_id INTEGER, source_name TEXT, cname_target TEXT, safe_search_target TEXT, route_kind TEXT NOT NULL, forward_zone TEXT, CHECK (rcode BETWEEN 0 AND 4095) -- twelve bits (RFC 6891 6.1.3) ); CREATE INDEX idx_query_log_ts ON query_log(timestamp); CREATE INDEX idx_query_log_client ON query_log(client_ip); CREATE INDEX idx_query_log_domain ON query_log(domain_id); CREATE TABLE querylog_meta ( id INTEGER PRIMARY KEY CHECK (id = 1), -- one row, enforced by the schema created_at INTEGER NOT NULL, available_since INTEGER NOT NULL ); INSERT INTO querylog_meta (id, created_at, available_since) VALUES (1, unixepoch(), unixepoch() + 1); CREATE TABLE bucket_totals ( bucket INTEGER PRIMARY KEY, queries INTEGER NOT NULL, blocked INTEGER NOT NULL, cached INTEGER NOT NULL, rt_sum INTEGER NOT NULL, -- sum(response_time_us) over timed rows rt_count INTEGER NOT NULL -- count(response_time_us) ) WITHOUT ROWID; CREATE TABLE bucket_clients ( bucket INTEGER NOT NULL, client_ip TEXT NOT NULL, queries INTEGER NOT NULL, PRIMARY KEY (bucket, client_ip) ) WITHOUT ROWID; CREATE TABLE bucket_types ( bucket INTEGER NOT NULL, qtype INTEGER NOT NULL, -- -1 encodes a NULL qtype, losslessly count INTEGER NOT NULL, PRIMARY KEY (bucket, qtype) ) WITHOUT ROWID; CREATE TABLE bucket_routes ( bucket INTEGER NOT NULL, route_kind TEXT NOT NULL, source_present INTEGER NOT NULL, -- 0: source NULL; 1: source = source_text source_text TEXT NOT NULL, -- '' when source_present = 0 count INTEGER NOT NULL, PRIMARY KEY (bucket, route_kind, source_present, source_text), CHECK (source_present IN (0, 1)), CHECK (source_present = 1 OR source_text = '') ) WITHOUT ROWID;