razeri-plugin-contract
The contract a Razeri dialect plugin is written against.
This crate and razeri-plugin-api are the two open crates in Razeri's workspace. Everything a plugin author needs in order to describe and render a database platform lives here; nothing else does. It depends on serde and on nothing else at all, which is what lets a plugin be built, published and consumed outside Razeri's repository.
What is in here
The rendering hierarchy — ten traits, layered so that a new dialect implements four required methods and inherits ANSI-standard behaviour for the rest:
| Trait | What it renders |
|---|---|
SqlRenderer |
Core SQL — the four required methods |
ExpressionRenderer |
Expressions, with ANSI defaults |
DdlRenderer |
DDL, with ANSI defaults |
DmlRenderer |
DML, with ANSI defaults |
ProcedureRenderer |
Stored procedures and functions |
FormulaRenderer |
Formulas, with ANSI defaults |
TaskRenderer |
Scheduled tasks |
ReplicationRenderer |
Data extraction, loading and key-function deployment |
StorageRenderer |
Partitioning, compression and index strategy |
DialectCapabilities |
What the platform's SQL can and cannot do |
The vocabulary those traits speak: DataType and DataTypeRef, the StoragePlan a StorageRenderer translates, the StoragePlatform a storage plugin names, and DialectFamily, the platform's own identity.
The decisions a dialect states rather than a core crate deciding for it — starting with SidSpelling, how this engine spells a surrogate key, and continuing with ProcedureForm, ScalarFunctionForm and TableFunctionForm, the routine grammars it speaks. Each of the three carries a Custom arm for a grammar Razeri does not know: your dialect names it and renders the routine itself, from the RoutineSpec Razeri hands over.
The fan-out an engine states — flatten. One row holding an array becomes one row per element, and no two engine families spell that the same way, so the dialect's render_flatten answers with the whole shape — the FROM item, the ordinal and one expression per field — rather than filling in a template. The ordinal it returns counts from one on every engine, because the element's surrogate key is derived from its position.
The surrogate key's composition — sid::sid_expression turns a SidSpelling into the key expression an engine runs. It is here because a dialect author who cannot render their own key expression cannot run it either, and "the same key on every engine" is then a claim nobody outside Razeri's repository can check.
AnsiDialect is a complete worked implementation of the required methods, and render_data_type_ansi is the ANSI type mapping to start from.
How this crate is versioned
While the major version is zero:
- a change to a trait's method set bumps the minor version — a method added, removed or renamed, whether or not it carries a default body;
- documentation and fixes bump the patch version.
The rule is about who decides when a plugin's behaviour changes. Cargo flows a patch release to every plugin pinned at the minor the next time it builds, and flows a minor release to nobody. A defaulted method costs an existing plugin no line of code, and it still changes what that plugin says: an engine that has not implemented the new method now answers the default, and its users meet whatever Razeri does with that answer — a refusal they had never seen, arriving because somebody else released. So a new method is opted into, and the plugin author chooses the day.
This is stricter than semantic versioning requires of a zero-major crate, deliberately: the looser reading saves a version number and spends a plugin author's afternoon.
What is deliberately not in here
Razeri's design model and every renderer that produces Razeri's own output. A plugin says what its engine spells; Razeri composes.
License
Dual-licensed under MIT or Apache 2.0, at your option. Plugins belong to their authors.
Security
Report a vulnerability through GitHub's private vulnerability reporting on the Razeri repository — see its security policy.