Skip to main content

razeri_plugin_contract/
lib.rs

1// Copyright (C) 2026 Gabriel Shea
2// Licensed under either of the Apache License, Version 2.0 or the MIT
3// license, at your option.
4
5#![warn(missing_docs)]
6
7//! # razeri-plugin-contract
8//!
9//! **The contract a Razeri dialect plugin is written against.**
10//!
11//! This crate and `razeri-plugin-api` are the two open crates in Razeri's
12//! workspace. Everything a plugin author needs in order to *describe* and
13//! *render* a database platform lives here; nothing else does. It depends on
14//! `serde` and on nothing else at all, which is what lets a plugin be built,
15//! published and consumed outside this repository.
16//!
17//! ## What is in here
18//!
19//! **The rendering hierarchy** — ten traits, layered so that a new dialect
20//! implements four required methods and inherits ANSI-standard behaviour for
21//! the rest:
22//!
23//! 1. [`SqlRenderer`] — core SQL rendering (the four required methods)
24//! 2. [`ExpressionRenderer`] — expressions, with ANSI defaults
25//! 3. [`DdlRenderer`] — DDL, with ANSI defaults
26//! 4. [`DmlRenderer`] — DML, with ANSI defaults
27//! 5. [`ProcedureRenderer`] — stored procedures and functions
28//! 6. [`FormulaRenderer`] — formulas, with ANSI defaults
29//! 7. [`TaskRenderer`] — scheduled tasks
30//! 8. [`ReplicationRenderer`] — data extraction, loading and key-function deployment
31//! 9. [`StorageRenderer`] — partitioning, compression and index strategy
32//! 10. [`DialectCapabilities`] — what the platform's SQL can and cannot do
33//!
34//! **The vocabulary those traits speak**: [`DataType`] and [`DataTypeRef`], the
35//! [`storage_strategy::StoragePlan`] a [`StorageRenderer`] translates, the
36//! [`StoragePlatform`] a storage plugin names, and [`DialectFamily`], the
37//! platform's own identity.
38//!
39//! **The fan-out an engine states** — [`flatten`]. One row holding an array
40//! becomes one row per element, and every engine spells that differently, so
41//! the dialect answers with the whole shape rather than filling in a template.
42//!
43//! **The decisions a dialect states rather than a core crate deciding for it**,
44//! starting with [`SidSpelling`] — how this engine spells a surrogate key —
45//! and continuing with [`ProcedureForm`] and [`ScalarFunctionForm`], the
46//! routine grammars it speaks, [`MergeShape`], how it upserts, and
47//! [`EvolutionAnswers`], what it keeps when a table that already holds rows
48//! changes shape.
49//!
50//! **The surrogate key's composition** — [`sid`] turns a [`SidSpelling`] into
51//! the key expression an engine runs. It is here rather than in the product
52//! because a dialect author who cannot render their own key expression cannot
53//! run it either, and *"the same key on every engine"* is then a claim nobody
54//! outside this repository can check.
55//!
56//! **The named routine grammars, spelled** — [`routine_render`]. A dialect
57//! whose engine has stored procedures in a grammar of its own renders the whole
58//! `CREATE` itself, and *"PL/pgSQL with one tweak"* used to mean writing the
59//! whole thing from nothing. These three functions write out the grammar a
60//! dialect is nearly the same as, so it can start there and say what differs.
61//!
62//! ## What is deliberately not in here
63//!
64//! Razeri's design model, and the renderers that turn it into Razeri's own
65//! output. A plugin says what its engine spells; Razeri composes. That division
66//! is why one contract crate can be open while the product is not.
67//!
68//! The routine grammars are the one thing on both sides of that line, and they
69//! are here because they belong to the engines rather than to Razeri's design: a
70//! plugin author who cannot read the grammar next to theirs has to guess at it.
71//!
72//! ## How this crate is versioned
73//!
74//! While the major version is zero:
75//!
76//! - **a change to a trait's method set bumps the minor version** — a method
77//!   added, removed or renamed, whether or not it carries a default body;
78//! - **documentation and fixes bump the patch version.**
79//!
80//! The rule is about who decides when a plugin's behaviour changes. Cargo
81//! flows a patch release to every plugin pinned at the minor the next time it
82//! builds, and flows a minor release to nobody. A defaulted method costs an
83//! existing plugin no line of code, and it still changes what that plugin
84//! *says*: an engine that has not implemented the new method now answers the
85//! default, and its users meet whatever Razeri does with that answer — a
86//! refusal they had never seen, arriving because somebody else released. So a
87//! new method is opted into, and the plugin author chooses the day.
88//!
89//! This is stricter than semantic versioning requires of a zero-major crate,
90//! deliberately: the looser reading saves a version number and spends a
91//! plugin author's afternoon.
92
93pub mod agnostic;
94pub mod capabilities;
95pub mod constraint_enforcement;
96pub mod data_type;
97pub mod dialect_family;
98pub mod evolution;
99pub mod flatten;
100pub mod formula_renderer;
101pub mod merge_shape;
102pub mod procedure_log_level;
103pub mod renderer;
104pub mod replication;
105pub mod routine_form;
106pub mod routine_render;
107pub mod routine_spec;
108pub mod sid;
109pub mod sid_spelling;
110pub mod storage_platform;
111pub mod storage_renderer;
112pub mod storage_strategy;
113pub mod task_renderer;
114
115pub use agnostic::*;
116pub use capabilities::*;
117pub use constraint_enforcement::*;
118pub use data_type::{DataType, DataTypeRef};
119pub use dialect_family::DialectFamily;
120pub use evolution::*;
121pub use flatten::{Flatten, FlattenField, FlattenRequest};
122pub use formula_renderer::*;
123pub use merge_shape::*;
124pub use procedure_log_level::ProcedureLogLevel;
125pub use renderer::*;
126pub use replication::*;
127pub use routine_form::*;
128pub use routine_render::{
129    render_procedure_as, render_scalar_function_as, render_table_function_as,
130};
131pub use routine_spec::*;
132pub use sid::sid_expression;
133pub use sid_spelling::*;
134pub use storage_platform::StoragePlatform;
135pub use storage_renderer::*;
136pub use task_renderer::*;