pub trait ReplicationRenderer: SqlRenderer {
Show 18 methods
// Provided methods
fn session_prerequisites(&self) -> Vec<String> { ... }
fn session_prerequisites_for(&self, computes_key: bool) -> Vec<String> { ... }
fn sid_external_artifact(&self) -> Option<SidExternalArtifact> { ... }
fn sid_library_source(&self) -> Option<SidLibrarySource> { ... }
fn sid_prerequisites(&self) -> String { ... }
fn sid_prerequisite_statements(&self) -> Vec<String> { ... }
fn sid_pure_sql_fallback(&self) -> Option<String> { ... }
fn sid_pure_sql_fallback_in(&self, schemas: &[&str]) -> Option<String> { ... }
fn sid_prerequisite_kind(&self) -> SidPrerequisiteKind { ... }
fn sid_prerequisite_home(&self) -> SidPrerequisiteHome { ... }
fn sid_validation_query(
&self,
schema: Option<&str>,
null_sid: i64,
) -> String { ... }
fn render_data_extract(
&self,
qualified: &str,
columns: &str,
file_path: &str,
format: &str,
where_clause: &str,
_batch_size: Option<usize>,
) -> String { ... }
fn render_data_load(
&self,
qualified: &str,
file_path: &str,
_format: &str,
) -> String { ... }
fn render_checksum_query(&self, qualified: &str) -> String { ... }
fn parquet_export_warning(&self) -> Option<&str> { ... }
fn sid_deployment_warning(&self) -> Option<&str> { ... }
fn replication_target_warnings(&self) -> Vec<String> { ... }
fn truncate_caveat(&self) -> Option<&str> { ... }
}Expand description
Rendering methods for replication operations: SID generation, data extraction, data loading, and checksum validation.
Defaults produce ANSI-safe SQL so extension dialects (e.g., SQLite) work
without implementing every method.
Provided Methods§
Sourcefn session_prerequisites(&self) -> Vec<String>
fn session_prerequisites(&self) -> Vec<String>
Statements every generated script runs before its first real statement, in this order, in the same session.
Some engines decide how a literal is read from session settings rather than from the statement. Where that is true, a cast that is ordinary everywhere else fails on the first row of the first load until the session has been told how to read it — a date literal parsed by a session-wide format is the measured case. There is nowhere else to put such a statement: it belongs to the connection, not to any object.
§What belongs here
Settings that change how the engine reads what follows and are lost when the session ends: how literals parse, how identifiers fold, which time zone a timestamp is stamped in, how strings compare.
§What does not
Anything that creates something. A function, an extension, an
assembly, a table — none of those is a session setting, and putting one
here means running it again on every connection. Those are
Self::sid_prerequisites where they install the key function, and
ordinary DDL otherwise.
Each string is one statement without its terminator; the script that emits them adds whatever this engine ends a statement with. Every statement must be safe to run again — a script that runs twice runs these twice.
The default is empty, and an engine that reads nothing off the session leaves it that way: nothing is emitted, and its scripts are byte for byte what they were.
Sourcefn session_prerequisites_for(&self, computes_key: bool) -> Vec<String>
fn session_prerequisites_for(&self, computes_key: bool) -> Vec<String>
The session’s settings for one design, which may need fewer than
Self::session_prerequisites names.
A setting that only a key needs — loading the extension that computes
it — is wasted on a design that computes no key, and on a machine that
never installed the extension it is a stop. computes_key says whether
the design’s schema calls the key function; the prerequisites step
installs the key’s function under the same condition, so the two agree.
The default hands back Self::session_prerequisites whole, which is
right for an engine whose settings never depend on the key.
Sourcefn sid_external_artifact(&self) -> Option<SidExternalArtifact>
fn sid_external_artifact(&self) -> Option<SidExternalArtifact>
Does an external artifact already carry the name generate_sid on
this platform, and what is it?
None — the default, and the honest answer for most engines — means
razeri itself defines the key function here: the body is Razeri’s one
surrogate-key derivation with the platform’s own hash inlined, composed
from the platform name alone, so there is nothing for a dialect to
spell.
Some(…) names what the bundle’s prerequisites step installs: SQL
Server’s CLR assembly, MySQL/MariaDB’s C UDF, Snowflake’s emitted
JavaScript UDF, Databricks’ emitted Python UDF. The derivation is inside
the artifact rather than in any SQL razeri emits, so what a dialect
states is the artifact’s identity, matched against the very
prerequisites text that installs it. This is an identity, not a
body — see SidExternalArtifact.
A platform that can be given no function at all answers None here too
and says so through Self::sid_prerequisite_kind
(SidPrerequisiteKind::Refused). Razeri’s conformance checks require
that refusal to be said out loud: where no artifact is declared and
razeri emits no helper either, a dialect that has simply declared
nothing is reported, which is the distinction
SidPrerequisiteKind::Undeclared exists to keep.
Sourcefn sid_library_source(&self) -> Option<SidLibrarySource>
fn sid_library_source(&self) -> Option<SidLibrarySource>
The source of a library the operator compiles, where the key function arrives that way — shipped in the deploy bundle as a file of its own, so the build is one line.
SQLite answers it: its SQL has no CREATE FUNCTION, and its client
loads a compiled extension into each connection it opens. MySQL and
MariaDB answer it too: their server loads a compiled function from
its plugin directory. The default is None: nothing ships as a
separate source file.
Sourcefn sid_prerequisites(&self) -> String
fn sid_prerequisites(&self) -> String
Returns prerequisite SQL/instructions for SID deployment.
For platforms that require extensions or external libraries (PostgreSQL
pg_xxhash, SQL Server CLR, MariaDB C UDF), this returns the deployment
script. Default: empty (no prerequisites needed).
Sourcefn sid_prerequisite_statements(&self) -> Vec<String>
fn sid_prerequisite_statements(&self) -> Vec<String>
The executable statements inside Self::sid_prerequisites, in
order — razeri’s own text, split on razeri’s own declared boundary.
This exists so a deploy path or a test harness can install what razeri emits rather than a transcription of it — a hand-written copy is a second implementation that drifts, and a second splitter would be a second definition of the boundary.
A dialect that does not write
SID_PREREQUISITE_STATEMENT_DELIMITER declares no executable
statements, and gets an empty vector. That is the honest answer for
every arm whose prerequisite is an operator’s compile step (MariaDB’s
and MySQL’s .so) and for the platforms with
no prerequisite at all — it is not a promise that a caller can run the
prose.
Leading comment and blank lines are dropped from each segment, so the prose that explains a statement travels with it in the script and does not travel to the engine. Comments inside a statement survive: they are part of the statement the operator would paste.
The trailing terminator is dropped here, once. A ; is how the
script reads to a human pasting the whole file, and is not part of a
single statement over a REST statement API — Snowflake’s and Databricks’
both take exactly one. Stripping it in each consumer instead would put
the same rule in the cloud arms and in the bundle executor, which
is the shape this method exists to prevent. sid_prerequisites()’ text
is unchanged and keeps its semicolons.
Sourcefn sid_pure_sql_fallback(&self) -> Option<String>
fn sid_pure_sql_fallback(&self) -> Option<String>
A prerequisite script that installs the same key function without
compiling anything — where the platform has one, and None where it
does not.
The default is None: most platforms have exactly one prerequisite and
Self::sid_prerequisites is it. A dialect answers Some only where
two honest routes to the same number exist and the choice belongs to
whoever deploys rather than to whoever designed — the case being a
managed PostgreSQL service (RDS, Aurora, Cloud SQL), where nobody has
a shell on the server host and so the compiled extension the ordinary
step names can never be built.
§What answering Some promises
The same number, byte for byte. Not a near-enough hash and not a
different algorithm: the surrogate-key rule is one hash and one
derivation everywhere, so a key minted through this route and a key
minted through the compiled one are the same BIGINT and a warehouse can
be moved between them without re-keying a row. A dialect that cannot
promise that answers None and lets the ordinary step refuse.
It is a deploy-time choice and nothing about it reaches a design: the
text swaps into prerequisites.sql alone, schema.sql is unchanged, and
every call site still calls the one public name.
Sourcefn sid_pure_sql_fallback_in(&self, schemas: &[&str]) -> Option<String>
fn sid_pure_sql_fallback_in(&self, schemas: &[&str]) -> Option<String>
Self::sid_pure_sql_fallback, installed in every schema a
design writes into.
schemas names them, in the order the design first writes to each,
spelled as the rendered SQL spells them. A deploy bundle asks this
rather than the plain method, because it knows the schemas and the
plain method does not.
The default ignores the list and answers the plain method. That is right wherever an installed function is visible from every schema: a function on the session’s search path, or one with a schema of its own that every call names.
Override it where a routine resolves a bare function name in the
schema that owns the routine, and a key function created by plain SQL
has to live in that same schema. There one definition is not enough:
the answer installs the function once in each schema on the list, and
makes each schema first if it is not there yet, because this step runs
before schema.sql does. An empty list means the session’s current
schema, which is what the plain method answers.
Sourcefn sid_prerequisite_kind(&self) -> SidPrerequisiteKind
fn sid_prerequisite_kind(&self) -> SidPrerequisiteKind
Which of SidPrerequisiteKind’s shapes this platform’s prerequisite
is.
Derived from what the dialect already says, so the classification cannot drift from the text it classifies:
sid_prerequisites | sid_prerequisite_statements | kind |
|---|---|---|
| empty | — | Undeclared |
| prose and statements | non-empty | SqlInstallable |
| prose only | empty | OperatorArtifact |
§Silence is Undeclared, never None
The two answers the derivation cannot reach are the two that are positive claims about an engine:
Nonesays the platform’s own builtin returns the canonical number. That is a measurement, not an absence, and a dialect claiming it overrides this method and cites the arm that measured it;Refusedsays no SQL can ever install the function here, which a platform with a native hash and a lazy dialect author would also spell as silence.
It is the same asymmetry DdlRenderer::representable_timestamp_ceiling
documents on its own None: not measured and nothing to worry about
are opposite facts that read identically when a default supplies them.
Sourcefn sid_prerequisite_home(&self) -> SidPrerequisiteHome
fn sid_prerequisite_home(&self) -> SidPrerequisiteHome
Where Self::sid_prerequisites puts what it installs, so that a
key function created in some other schema can call it by name.
The default is SidPrerequisiteHome::Ambient: whatever the
prerequisite creates, it creates wherever the deploy runs, and every
call site names it bare. That is the right answer on every engine whose
prerequisite installs nothing with a schema — a session load, a
server-wide library, a function whose name has no qualifier — and it
leaves those dialects’ scripts exactly as they were.
Answer SidPrerequisiteHome::Schema where a routine on this engine
resolves an unqualified name in the schema that OWNS it. There, the one
hash a whole warehouse shares needs a fixed address, because every layer
schema holds its own copy of the key function, each calls the one hash,
and at most one of those schemas is the one the deploy signed in as.
See SidPrerequisiteHome::Schema for what answering it obliges the
dialect’s own prerequisite text to do.
Sourcefn sid_validation_query(&self, schema: Option<&str>, null_sid: i64) -> String
fn sid_validation_query(&self, schema: Option<&str>, null_sid: i64) -> String
Returns a validation query to verify the SID function is operational.
Default: schema-qualified SELECT generate_sid('test').
Sourcefn render_data_extract(
&self,
qualified: &str,
columns: &str,
file_path: &str,
format: &str,
where_clause: &str,
_batch_size: Option<usize>,
) -> String
fn render_data_extract( &self, qualified: &str, columns: &str, file_path: &str, format: &str, where_clause: &str, _batch_size: Option<usize>, ) -> String
Renders an extract/export SQL statement for the given table.
The format parameter is one of: "csv", "parquet", "json_lines", "native".
Default: ANSI SELECT ... FROM ... WHERE ... (no COPY).
Sourcefn render_data_load(
&self,
qualified: &str,
file_path: &str,
_format: &str,
) -> String
fn render_data_load( &self, qualified: &str, file_path: &str, _format: &str, ) -> String
Renders a load/import SQL statement for the given table.
The format parameter is one of: "csv", "parquet", "json_lines", "native".
Default: ANSI comment placeholder.
Sourcefn render_checksum_query(&self, qualified: &str) -> String
fn render_checksum_query(&self, qualified: &str) -> String
Renders a checksum validation query for data comparison.
Default: SELECT COUNT(*) AS cnt FROM <table> (no checksum).
Sourcefn parquet_export_warning(&self) -> Option<&str>
fn parquet_export_warning(&self) -> Option<&str>
Warning about Parquet export limitations on this platform.
Default: None (no warning needed).
Sourcefn sid_deployment_warning(&self) -> Option<&str>
fn sid_deployment_warning(&self) -> Option<&str>
Warning about SID function deployment requirements on this platform.
Default: None (no special deployment needed).
Sourcefn replication_target_warnings(&self) -> Vec<String>
fn replication_target_warnings(&self) -> Vec<String>
General replication caveats for this platform as a target.
Default: empty (no platform-specific caveats).
Sourcefn truncate_caveat(&self) -> Option<&str>
fn truncate_caveat(&self) -> Option<&str>
Warning about TRUNCATE behavior on this platform.
Default: None (TRUNCATE works normally).
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".