Skip to main content

ReplicationRenderer

Trait ReplicationRenderer 

Source
pub trait ReplicationRenderer: SqlRenderer {
Show 14 methods // Provided methods fn session_prerequisites(&self) -> Vec<String> { ... } fn sid_external_artifact(&self) -> Option<SidExternalArtifact> { ... } fn sid_prerequisites(&self) -> String { ... } fn sid_prerequisite_statements(&self) -> Vec<String> { ... } fn sid_pure_sql_fallback(&self) -> Option<String> { ... } fn sid_prerequisite_kind(&self) -> SidPrerequisiteKind { ... } 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§

Source

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.

Source

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 — SQLite, which has no CREATE FUNCTION in its SQL surface — 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.

Source

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).

Source

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 (SQL Server’s CLR assembly, 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.

Source

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.

Source

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_prerequisitessid_prerequisite_statementskind
empty—Undeclared
prose and statementsnon-emptySqlInstallable
prose onlyemptyOperatorArtifact
§Silence is Undeclared, never None

The two answers the derivation cannot reach are the two that are positive claims about an engine:

  • None says 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;
  • Refused says 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.

Source

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').

Source

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).

Source

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.

Source

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).

Source

fn parquet_export_warning(&self) -> Option<&str>

Warning about Parquet export limitations on this platform.

Default: None (no warning needed).

Source

fn sid_deployment_warning(&self) -> Option<&str>

Warning about SID function deployment requirements on this platform.

Default: None (no special deployment needed).

Source

fn replication_target_warnings(&self) -> Vec<String>

General replication caveats for this platform as a target.

Default: empty (no platform-specific caveats).

Source

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".

Implementors§