Desired schema and schema sources
Everything in Ptah starts from one declarative idea: you describe the schema a database should have — the desired schema — and Ptah computes what separates any concrete database from it. Migration files, direct applies, drift checks, and tests are all different ways of consuming that same computed difference.
How Ptah models it
Section titled “How Ptah models it”A schema source is anything that can declare part of the desired schema:
- annotated Go structs (
--root-dir), - YAML, HCL, SQL, or DBML schema files (
--schema-file), - an external loader — any program that emits SQL, HCL, or YAML, such as an
ORM exporter (
--schema-cmd), - a canonical HCL desired-schema artifact pulled from an OCI registry,
- a live database, turned into annotated Go models by
ptah introspect.
Every source parses into the same internal schema representation before any planning or rendering happens. The source format is therefore independent of both the target dialect and the workflow: a YAML file can produce PostgreSQL migrations, and the same Go annotations can drive versioned files or a direct apply without remodeling.
Sources compose. --root-dir and --schema-file repeat and mix freely, and
the merged result is the composite desired schema. Objects are matched by
their database identity, identical definitions are deduplicated, and
conflicting definitions stop the command before it renders SQL or connects to
a database — the merge rules live on
Composite desired schema.
Consequences
Section titled “Consequences”- The desired schema is the review surface. Changing a database starts with changing a source file that lives in version control, whichever workflow applies the change.
- Sources converge on one IR.
ptah schema exportconverts Go annotations to HCL, and a brownfield database can be introspected into source at any time. Canonical HCL preserves the currently modeled API names, contract type overrides, and exposure declarations. Export still reports opaque SQL bodies, byte-level normalization, and any other value it cannot prove lossless before destructive cleanup; HCL may additionally express semantics with no Go annotation spelling. - A transport is not an expressiveness promise. YAML, HCL, and Go can author Ptah API export metadata. SQL and DBML can still feed contract exports, but they have no lossless spelling for that metadata, so names and contract types are derived from storage. An external program has exactly the expressiveness of its declared SQL, YAML, or HCL payload, and an OCI artifact carries canonical HCL. Accepted input does not mean that every format can declare every Ptah object or attribute.
- Declaring is not supporting. What a concrete target accepts is decided later, by capability-aware planning — see Dialects and capabilities.
Where it appears
Section titled “Where it appears”- The operations every source shares: Work with a desired schema.
- Each source format then has its own page for its syntax and limits: SQL, YAML, HCL, Go annotations, ORM and external loaders.
- The versioned/direct decision that consumes the desired schema: Choose a workflow.
- Turning an existing database into sources: Adopt an existing database.