Automate issuer overlay creation from ticker searches

This commit is contained in:
2026-03-19 20:44:58 -04:00
parent 17de3dd72d
commit 391d6d34ce
79 changed files with 4746 additions and 695 deletions

View File

@@ -35,12 +35,12 @@ export function hasColumn(
return rows.some((row) => row.name === columnName);
}
export function applySqlFile(client: Database, fileName: string) {
function applySqlFile(client: Database, fileName: string) {
const sql = readFileSync(join(process.cwd(), "drizzle", fileName), "utf8");
client.exec(sql);
}
export function applyBaseSchemaCompat(client: Database) {
function applyBaseSchemaCompat(client: Database) {
const sql = readFileSync(
join(process.cwd(), "drizzle", "0000_cold_silver_centurion.sql"),
"utf8",
@@ -340,6 +340,7 @@ const TAXONOMY_SNAPSHOT_REQUIRED_COLUMNS = [
"kpi_rows",
"computed_definitions",
"normalization_summary",
"issuer_overlay_revision_id",
] as const;
function ensureTaxonomySnapshotCompat(client: Database) {
@@ -388,6 +389,10 @@ function ensureTaxonomySnapshotCompat(client: Database) {
name: "normalization_summary",
sql: "ALTER TABLE `filing_taxonomy_snapshot` ADD `normalization_summary` text;",
},
{
name: "issuer_overlay_revision_id",
sql: "ALTER TABLE `filing_taxonomy_snapshot` ADD `issuer_overlay_revision_id` integer REFERENCES `issuer_overlay_revision`(`id`) ON UPDATE no action ON DELETE set null;",
},
]);
for (const columnName of TAXONOMY_SNAPSHOT_REQUIRED_COLUMNS) {
@@ -527,6 +532,52 @@ function ensureTaxonomyCompat(client: Database) {
ensureTaxonomyFactCompat(client);
}
function ensureIssuerOverlaySchema(client: Database) {
if (!hasTable(client, "issuer_overlay_revision")) {
client.exec(`
CREATE TABLE IF NOT EXISTS \`issuer_overlay_revision\` (
\`id\` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
\`ticker\` text NOT NULL,
\`revision_number\` integer NOT NULL,
\`definition_hash\` text NOT NULL,
\`definition_json\` text NOT NULL,
\`diagnostics_json\` text,
\`source_snapshot_ids\` text NOT NULL DEFAULT '[]',
\`created_at\` text NOT NULL
);
`);
}
if (!hasTable(client, "issuer_overlay")) {
client.exec(`
CREATE TABLE IF NOT EXISTS \`issuer_overlay\` (
\`ticker\` text PRIMARY KEY NOT NULL,
\`status\` text NOT NULL DEFAULT 'empty',
\`active_revision_id\` integer,
\`last_built_at\` text,
\`last_error\` text,
\`stats_json\` text,
\`created_at\` text NOT NULL,
\`updated_at\` text NOT NULL,
FOREIGN KEY (\`active_revision_id\`) REFERENCES \`issuer_overlay_revision\`(\`id\`) ON UPDATE no action ON DELETE set null
);
`);
}
client.exec(
"CREATE UNIQUE INDEX IF NOT EXISTS `issuer_overlay_revision_ticker_revision_uidx` ON `issuer_overlay_revision` (`ticker`, `revision_number`);",
);
client.exec(
"CREATE UNIQUE INDEX IF NOT EXISTS `issuer_overlay_revision_ticker_hash_uidx` ON `issuer_overlay_revision` (`ticker`, `definition_hash`);",
);
client.exec(
"CREATE INDEX IF NOT EXISTS `issuer_overlay_revision_ticker_created_idx` ON `issuer_overlay_revision` (`ticker`, `created_at`);",
);
client.exec(
"CREATE INDEX IF NOT EXISTS `issuer_overlay_status_idx` ON `issuer_overlay` (`status`, `updated_at`);",
);
}
export function ensureLocalSqliteSchema(client: Database) {
const missingBaseSchema = [
"filing",
@@ -684,6 +735,7 @@ WHERE resource_key IS NOT NULL AND status IN ('queued', 'running');`);
if (!hasTable(client, "filing_taxonomy_snapshot")) {
applySqlFile(client, "0005_financial_taxonomy_v3.sql");
}
ensureIssuerOverlaySchema(client);
ensureTaxonomyCompat(client);
if (!hasTable(client, "company_financial_bundle")) {
@@ -725,7 +777,7 @@ WHERE resource_key IS NOT NULL AND status IN ('queued', 'running');`);
ensureResearchWorkspaceSchema(client);
}
export const __sqliteSchemaCompatInternals = {
const __sqliteSchemaCompatInternals = {
applyBaseSchemaCompat,
applySqlFile,
hasColumn,