Commit graph

10 commits

Author SHA1 Message Date
85679b5e78 Schema 1.5.0: holiday calendar registry, citext names; drop num_records
For the coverage-aware holiday-calendar API in TSAPI core (db_base
holiday_calendar__get / __set_coverage / __set_metadata / __upsert).

- meta.holiday_calendars (name, description, covered_from, covered_to,
  source, updated_at): a calendar exists when it has a row here, not
  when it has holidays (retires the 9999-12-31 sentinel row).
  covered_from/to: the range over which the closure list is complete;
  both set or both NULL, from <= to (holiday_calendars_coverage_check).
- Calendar names are citext in every table (registry, holidays.calendar_name,
  exchanges.default_holiday_calendar, instruments.holiday_calendar):
  stored as given, unique and matched case-insensitively -- also in the
  foreign keys -- as the native TSAPI backend does with COLLATE NOCASE.
  New extension citext (00_extensions.sql). Name check: non-empty,
  trimmed, <= 50 characters.
- FKs: holidays -> registry ON DELETE CASCADE; exchanges/instruments ->
  registry ON DELETE RESTRICT (a calendar in use cannot be dropped);
  ON UPDATE CASCADE everywhere.
- meta.series.num_records dropped. Only some write paths maintained it
  (never C++), it sometimes held an estimate, and it was NULL for a series
  never written to. Clients ask the table: count(*), or
  SELECT EXISTS (SELECT 1 FROM <table>) for "is it empty?".
- find_schema_problems() covers the new table, columns, constraints and
  extension, and runs with search_path = pg_catalog so format_type()
  reports 'public.citext' whatever the caller's search_path.

Verified on a fresh database (PG 17): run_setup.py installs it and
find_schema_problems() returns zero rows, also for a caller without
public on the search_path; constraint behaviour checked by hand
(case-insensitive duplicate refused, FK matches any spelling, RESTRICT
and CASCADE, coverage and name checks).

Re-provision databases (no migration).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 17:56:04 +01:00
cddaec5730 Schema 1.4.0: drop meta.sessions.json
The definition string is the only stored schedule. The "json" column held a
parsed copy that the Python client wrote, the C++ client never wrote, and
neither client read -- and a raw UPDATE of one field silently left two
different schedules. Clients derive the parsed form from the definition.
09_schema_check.sql no longer expects the column; VERSION and
10_schema_version.sql at 1.4.0. Re-provision databases (no migrations).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 22:42:39 +01:00
738fe0fe2d find_schema_problems(): report problems in a stable order
Several sections had no ORDER BY, so when one section found more than one
problem PostgreSQL could return them in any order (found by new
break-one-thing tests). Every section is now sorted. Output is otherwise
unchanged; no version bump.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 12:18:54 +01:00
9032fd3a45 run_setup: refuse an existing installation; remove --clean-slate
- Removed --clean-slate: it dropped every schema in the database,
  including user data. Nothing used it.
- Pre-check (same rule as the Python client's init_postgres_db()): refuse
  if meta or log exists, series is not empty, or the prevent_series_drops
  trigger exists, naming the installed version. User schemas and tables
  are allowed and never touched; an empty series schema is reused.
- --drop-existing drops every registered series schema plus meta and log,
  and refuses if a series schema holds non-series objects.
- All files run in one transaction: a failure leaves nothing behind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 11:58:46 +01:00
eb0f93e032 Schema 1.3.0: meta.find_series_registry_mismatches()
An occasional consistency check (not for connect time) comparing
meta.series with the registered series schemas: non-series tables, views,
sequences and functions inside a series schema; registered series whose
table is missing; series tables without a timestamp column or its BRIN
index. Report only; user schemas are never examined. find_schema_problems()
fingerprints its body like every other procedure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 11:48:26 +01:00
4c067bc4b9 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>
2026-10-06 11:42:10 +01:00
155fc7c3dd Schema version 1.1.0
meta.find_schema_problems() (09), the version row in the DDL (10), every
install running 00-10, and the removal of sql/migrate/ changed what a
complete database is. Databases from 1.0.0 are re-provisioned.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 11:20:51 +01:00
1f5cfeceeb Add meta.find_schema_problems(); every install runs 00-10; drop migrations
09_schema_check.sql adds meta.find_schema_problems(), a read-only check
any client (Python, C++, psql) can call:

    SELECT * FROM meta.find_schema_problems();   -- zero rows = usable

One row per problem (object, problem): missing schemas, extension,
sequences, tables, columns, wrong column type or NOT NULL, missing
constraints, indexes, views, stored-function bodies that differ from the
DDL (whitespace-insensitive md5 fingerprint), a missing/disabled/
misdirected event trigger, short reference data, no version row. It
mirrors 00-08 and must change in the same commit as they do; the
release test (a fresh install returns zero rows) enforces that.

10_schema_version.sql records VERSION in meta.schema_version. Before,
only the Python client wrote that row, so databases provisioned by
run_setup.py recorded no version at all.

run_setup.py now runs 00-10. It skipped 08_script_log.sql, so its
databases lacked a table the Python client uses; every fresh install is
now identical regardless of provisioner.

sql/migrate/ is removed: databases are re-provisioned, not migrated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 11:01:28 +01:00
6dde987cfb run_setup: defer psycopg2 import so --help works without it
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 17:29:18 +01:00
eed06559c0 Canonical TSAPI series DB schema v1.0.0
Single source of truth for the timeseries PostgreSQL schema shared by the
Python (TSAPI_SERIESDB_PG_PY) and C++ (TSAPI_POSTGRES_CPP) libraries. SQL
seeded byte-for-byte from TSAPI_SERIESDB_PG_PY/tsapi_pgdb/sql on 2026-09-02.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 17:27:26 +01:00