Schema 1.2.0: meta.series_schemas registry; lower-case name checks
- meta.series_schemas (name, description, created_at, created_by), seeded with 'series'. FK series_db_schema_fkey from meta.series.db_schema: a series may only live in a registered schema, for every client. Unregistered schemas belong to the user and are never touched. - CHECK series_schemas_name_check and series_table_name_check enforce the shared lower-case identifier rule in the database. - meta.find_schema_problems() covers the registry and reports a registered schema that no longer exists; user schemas are not examined. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
155fc7c3dd
commit
4c067bc4b9
7 changed files with 59 additions and 5 deletions
|
|
@ -9,7 +9,7 @@ timeseries database. Both client libraries target the schema defined here:
|
|||
Neither project should keep its own copy of the DDL. When the schema changes,
|
||||
it changes **here**, and both projects re-provision / re-test against it.
|
||||
|
||||
Current schema version: **1.1.0** (see [`VERSION`](VERSION); recorded at runtime
|
||||
Current schema version: **1.2.0** (see [`VERSION`](VERSION); recorded at runtime
|
||||
in the `meta.schema_version` table).
|
||||
|
||||
---
|
||||
|
|
|
|||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
1.1.0
|
||||
1.2.0
|
||||
|
|
|
|||
|
|
@ -135,6 +135,16 @@ CREATE TABLE meta.sessions (
|
|||
exchange_id character varying(12) NOT NULL
|
||||
);
|
||||
|
||||
-- Registry of series schemas. A series may only live in a registered schema
|
||||
-- (FK from meta.series.db_schema, 04_indexes.sql). Every other schema in the
|
||||
-- database belongs to the user and is never touched by the clients.
|
||||
CREATE TABLE meta.series_schemas (
|
||||
name text NOT NULL,
|
||||
description text,
|
||||
created_at timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
created_by text NOT NULL DEFAULT CURRENT_USER
|
||||
);
|
||||
|
||||
CREATE TABLE meta.timezones (
|
||||
iana_name character varying(50) NOT NULL,
|
||||
display_name character varying(100) NOT NULL,
|
||||
|
|
|
|||
|
|
@ -21,6 +21,23 @@ ALTER TABLE meta.currencies ADD CONSTRAINT currencies_pkey PRIMARY KEY (code);
|
|||
ALTER TABLE meta.security_types ADD CONSTRAINT security_types_pkey PRIMARY KEY (code);
|
||||
ALTER TABLE meta.timezones ADD CONSTRAINT timezones_pkey PRIMARY KEY (iana_name);
|
||||
|
||||
-- Series schema registry. Names follow the table-name rule shared by both
|
||||
-- clients: lower case, [a-z_][a-z0-9_]*, at most 63 bytes, never quoted.
|
||||
ALTER TABLE meta.series_schemas ADD CONSTRAINT series_schemas_pkey PRIMARY KEY (name);
|
||||
ALTER TABLE meta.series_schemas ADD CONSTRAINT series_schemas_name_check
|
||||
CHECK (name ~ '^[a-z_][a-z0-9_]*$' AND octet_length(name) <= 63);
|
||||
|
||||
-- A series may only live in a registered schema -- enforced here, so no
|
||||
-- client can bypass it. RESTRICT: a schema cannot be unregistered while it
|
||||
-- still holds series.
|
||||
ALTER TABLE meta.series ADD CONSTRAINT series_db_schema_fkey
|
||||
FOREIGN KEY (db_schema) REFERENCES meta.series_schemas (name)
|
||||
ON UPDATE RESTRICT ON DELETE RESTRICT;
|
||||
|
||||
-- Table names follow the same rule (Core contract 6 in both clients).
|
||||
ALTER TABLE meta.series ADD CONSTRAINT series_table_name_check
|
||||
CHECK (table_name ~ '^[a-z_][a-z0-9_]*$' AND octet_length(table_name) <= 63);
|
||||
|
||||
CREATE INDEX idx_event_log_series_timestamp ON log.event_log USING btree (series_name, "timestamp" DESC);
|
||||
|
||||
CREATE INDEX idx_event_log_timestamp ON log.event_log USING btree ("timestamp" DESC);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
-- Reference data (timezones and currencies)
|
||||
-- Reference data (series schema registry, timezones, currencies, security types)
|
||||
-- Generated: 2025-10-15T12:24:56.582392
|
||||
|
||||
-- Timezones
|
||||
|
|
@ -767,3 +767,7 @@ VALUES
|
|||
('OPT', 'Option', 'Equity and index options', NULL),
|
||||
('STK', 'Stock', 'Common and preferred equities', NULL),
|
||||
('WAR', 'Warrant', 'Equity warrants', NULL);
|
||||
|
||||
-- Series schema registry: the default schema, created in 01_schemas.sql
|
||||
INSERT INTO meta.series_schemas (name, description)
|
||||
VALUES ('series', 'Default series schema');
|
||||
|
|
|
|||
|
|
@ -114,6 +114,10 @@ BEGIN
|
|||
('meta.instruments', 'asset_class', 'character varying(30)', false),
|
||||
('meta.instruments', 'geography', 'character varying(30)', false),
|
||||
('meta.instruments', 'underlying', 'character varying(30)', false),
|
||||
('meta.series_schemas', 'name', 'text', true),
|
||||
('meta.series_schemas', 'description', 'text', false),
|
||||
('meta.series_schemas', 'created_at', 'timestamp with time zone', true),
|
||||
('meta.series_schemas', 'created_by', 'text', true),
|
||||
('meta.security_types', 'code', 'character varying(10)', true),
|
||||
('meta.security_types', 'name', 'character varying(50)', true),
|
||||
('meta.security_types', 'description', 'text', false),
|
||||
|
|
@ -211,6 +215,10 @@ BEGIN
|
|||
('meta.sessions', 'sessions_pkey'),
|
||||
('meta.series', 'series_pkey'),
|
||||
('meta.series', 'series_schema_table_key'),
|
||||
('meta.series', 'series_db_schema_fkey'),
|
||||
('meta.series', 'series_table_name_check'),
|
||||
('meta.series_schemas', 'series_schemas_pkey'),
|
||||
('meta.series_schemas', 'series_schemas_name_check'),
|
||||
('meta.currencies', 'currencies_pkey'),
|
||||
('meta.security_types', 'security_types_pkey'),
|
||||
('meta.timezones', 'timezones_pkey')
|
||||
|
|
@ -301,12 +309,27 @@ BEGIN
|
|||
FROM (VALUES
|
||||
('meta.timezones', 563),
|
||||
('meta.currencies', 179),
|
||||
('meta.security_types', 13)
|
||||
('meta.security_types', 13),
|
||||
('meta.series_schemas', 1)
|
||||
) AS e(tbl, expected)
|
||||
WHERE to_regclass(e.tbl) IS NOT NULL
|
||||
) AS r
|
||||
WHERE r.actual < r.expected;
|
||||
|
||||
-- Series schema registry ------------------------------------------------
|
||||
-- Only REGISTERED schemas are examined; user schemas are never looked at.
|
||||
IF to_regclass('meta.series_schemas') IS NOT NULL THEN
|
||||
RETURN QUERY
|
||||
SELECT 'series schema series', 'not registered in meta.series_schemas'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM meta.series_schemas WHERE name = 'series');
|
||||
|
||||
RETURN QUERY
|
||||
SELECT 'series schema ' || r.name, 'registered but the schema does not exist'
|
||||
FROM meta.series_schemas r
|
||||
WHERE NOT EXISTS (SELECT 1 FROM pg_namespace WHERE nspname = r.name)
|
||||
ORDER BY r.name;
|
||||
END IF;
|
||||
|
||||
IF to_regclass('meta.schema_version') IS NOT NULL THEN
|
||||
RETURN QUERY
|
||||
SELECT 'schema version', 'not recorded in meta.schema_version'
|
||||
|
|
|
|||
|
|
@ -5,4 +5,4 @@
|
|||
-- they were built for (Python: DB_SCHEMA_VERSION in tsapi_pgdb/_version.py).
|
||||
|
||||
INSERT INTO meta.schema_version (version, description)
|
||||
VALUES ('1.1.0', 'meta.find_schema_problems(); every install runs 00-10');
|
||||
VALUES ('1.2.0', 'meta.series_schemas registry; lower-case table name check');
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue