pub enum Statement {
Show 107 variants
AlterSystem {
parameter: Option<String>,
},
DropDatabase {
name: String,
if_exists: bool,
},
NoOpPreventedInTransaction {
what: String,
},
DropAggregate {
if_exists: bool,
items: Vec<(String, Option<Vec<String>>)>,
},
AlterRolePassword {
name: String,
password: Option<String>,
},
ValidateOnly {
kind: ValidateOnlyKind,
names: Vec<String>,
},
SetDbRoleSetting(Box<SetDbRoleSettingStatement>),
SetConstraints {
names: Vec<String>,
deferred: bool,
},
DropTable {
names: Vec<String>,
if_exists: bool,
},
DropIndex {
name: String,
if_exists: bool,
},
Prepare {
name: String,
param_types: Vec<String>,
body: Box<Statement>,
source: String,
},
Execute {
name: String,
args: Vec<Expr>,
},
Deallocate(Option<String>),
CreateStatistics {
name: String,
if_not_exists: bool,
kinds: Vec<String>,
columns: Vec<String>,
table: String,
},
DropStatistics {
name: String,
if_exists: bool,
},
Call(String),
PrepareTransaction(String),
Empty,
DeclareCursor {
name: String,
scroll: Option<bool>,
hold: bool,
query: Box<Statement>,
},
FetchCursor {
name: String,
direction: CursorDirection,
},
MoveCursor {
name: String,
direction: CursorDirection,
},
CloseCursor {
name: Option<String>,
},
Listen(String),
Notify {
channel: String,
payload: Option<String>,
},
Unlisten(Option<String>),
CopyTo {
table: String,
columns: Option<Vec<String>>,
query: Option<Box<Statement>>,
options: CopyOptions,
},
CopyFromFile {
table: String,
columns: Option<Vec<String>>,
path: String,
options: CopyOptions,
},
CopyToFile {
table: String,
columns: Option<Vec<String>>,
query: Option<Box<Statement>>,
path: String,
options: CopyOptions,
},
Select(SelectStatement),
CreateTable(CreateTableStatement),
CreateExtension(String),
DoBlock(PlPgSqlBlock),
CreateIndex(CreateIndexStatement),
Insert(InsertStatement),
Update(UpdateStatement),
Delete(DeleteStatement),
Merge(MergeStatement),
Vacuum {
table: Option<String>,
analyze: bool,
},
Begin(Option<IsolationLevel>),
Commit,
Rollback,
Savepoint(String),
RollbackToSavepoint(String),
ReleaseSavepoint(String),
ShowTables,
ShowDatabases,
ShowCreateTable(String),
ShowIndexes(String),
ShowStatus,
ShowVariables,
ShowProcesslist,
Discard(DiscardTarget),
Kill {
query_only: bool,
id: Box<Expr>,
},
ShowColumns(String),
CreateUser(CreateUserStatement),
DropUser {
name: String,
if_exists: bool,
},
SetRole(Option<String>),
Grant(GrantStatement),
Revoke(GrantStatement),
CreatePolicy(CreatePolicyStatement),
AlterPolicy(AlterPolicyStatement),
DropPolicy(DropPolicyStatement),
ShowUsers,
Explain(ExplainStatement),
AlterIndex(AlterIndexStatement),
AlterTable(AlterTableStatement),
CreatePublication(CreatePublicationStatement),
DropPublication {
name: String,
if_exists: bool,
},
ShowPublications,
CreateSubscription(CreateSubscriptionStatement),
DropSubscription {
name: String,
if_exists: bool,
},
ShowSubscriptions,
WaitForWalPosition {
pos: u64,
timeout_ms: Option<u64>,
},
Analyze(Option<String>),
Maintain {
kind: MaintainKind,
concurrently: bool,
target: Option<String>,
},
Truncate {
tables: Vec<String>,
restart_identity: bool,
cascade: bool,
only: bool,
},
CompactColdSegments,
SetParameter {
name: String,
value: SetValue,
local: bool,
},
SetParameterList(Vec<(String, SetValue)>),
SetUserVars(Vec<(String, Expr)>, Vec<(String, Expr)>),
SetTransaction {
isolation: IsolationLevel,
},
ShowParameter(String),
ResetParameter(Option<String>),
CreateFunction(CreateFunctionStatement),
CreateTrigger(CreateTriggerStatement),
CreateRule(CreateRuleStatement),
DropRule {
name: String,
table: String,
if_exists: bool,
},
DropTrigger {
name: String,
table: String,
if_exists: bool,
},
DropFunction {
name: String,
args: Option<Vec<String>>,
if_exists: bool,
},
CreateSequence(CreateSequenceStatement),
AlterSequence(AlterSequenceStatement),
DropSequence {
names: Vec<String>,
if_exists: bool,
},
CreateView(CreateViewStatement),
DropView {
names: Vec<String>,
if_exists: bool,
},
CreateMaterializedView(CreateMaterializedViewStatement),
RefreshMaterializedView {
name: String,
with_data: bool,
},
DropMaterializedView {
names: Vec<String>,
if_exists: bool,
},
CreateType(CreateTypeStatement),
CommentOn {
kind: String,
name: String,
comment: Option<String>,
},
AlterTypeRenameValue {
type_name: String,
old: String,
new: String,
},
AlterTypeAddValue {
type_name: String,
label: String,
if_not_exists: bool,
position: Option<(bool, String)>,
},
DropType {
names: Vec<String>,
if_exists: bool,
},
CreateDomain(CreateDomainStatement),
AlterDomain {
name: String,
action: AlterDomainAction,
},
DropDomain {
names: Vec<String>,
if_exists: bool,
},
CreateSchema {
name: String,
if_not_exists: bool,
},
DropSchema {
names: Vec<String>,
if_exists: bool,
},
}Variants§
AlterSystem
v7.39 (round 695) — ALTER SYSTEM SET <name> = … / RESET <name>.
It used to be swallowed with the rest of the ALTER no-ops, which meant
ALTER SYSTEM SET nosuch_guc = 1 was ACCEPTED where PG18 answers
unrecognized configuration parameter. SPG still applies nothing —
there is no postgresql.auto.conf to write — but a name it does not
know is now refused rather than swallowed.
None is RESET ALL, which names no parameter.
DropDatabase
DROP DATABASE [IF EXISTS] <name>. SPG is single-database, so
this never succeeds; the name and the flag are carried so the
engine can answer with PG’s wording for the two cases PG itself
has — an unknown name, or the database you are connected to.
NoOpPreventedInTransaction
A statement SPG accepts as a no-op but PG refuses inside a
transaction block — today CREATE DATABASE / DROP DATABASE,
which are no-ops here because SPG is single-database.
The no-op path they used to share (Statement::Empty) also
carries CREATE ROLE, CREATE CAST and a dozen others that PG is
happy to run inside a transaction, so the object has to be named
to refuse the right ones.
DropAggregate
v7.39 (round 696) — statements SPG performs nothing for, but whose OPERAND PG validates before performing nothing either.
All four used to be consumed whole by is_dump_noise_statement,
which meant LOCK TABLE nosuch and DROP OWNED BY nosuchrole were
ACCEPTED where PG18 errors. Accepting a statement that names
something that does not exist is the F29 shape: the caller is told
their intent was understood when the object it referred to is not
there.
They share one variant because they share one rule — resolve the
name, refuse if absent, otherwise no-op — and four variants would be
four places for that rule to drift.
v7.39 (round 707) — DROP AGGREGATE [IF EXISTS] name(argtypes)[, …].
Consumed whole by the dump-noise list before, so DROP AGGREGATE nosuch(int) reported success. PG validates every named aggregate’s
EXISTENCE first (measured: a list with one unknown fails on the
unknown even when an earlier entry exists), renders the signature
with canonical type names (int → integer), and refuses to drop a
built-in (cannot drop function sum(integer) because it is required by the database system). Every SPG aggregate is a built-in, so the
outcome is one of those two errors — or the IF EXISTS no-op.
args holds the argument type names as written; None is the
(*) spelling.
AlterRolePassword
v7.39 (round 750) — ALTER ROLE|USER <name> … PASSWORD 'x' | PASSWORD NULL. The one attribute of the no-op family with a
SECURITY consequence: it was silently dropped (ledgered r710),
so a rotated credential never rotated. None = PASSWORD NULL
(the role keeps existing but can no longer password-auth).
ValidateOnly
Fields
kind: ValidateOnlyKindSetDbRoleSetting(Box<SetDbRoleSettingStatement>)
v7.39 (round 547) — ALTER ROLE … SET/RESET and
ALTER DATABASE … SET/RESET: the GUC defaults a session picks up
when it starts. Both used to land in the pg_dump no-op tail, so
the statement reported success and changed nothing.
database / role are None for PG’s oid 0 — ALTER ROLE ALL
sets both to None. param is None for RESET ALL. value is
None for RESET of one parameter.
SetConstraints
v7.39 (round 288) — SET CONSTRAINTS { ALL | <name>… } { DEFERRED | IMMEDIATE }. deferred carries the timing; the
name list is not yet honoured (ALL is what pg_dump emits and
what a circular-FK restore needs), so a named form applies to
all deferrable constraints too rather than silently doing
nothing.
v7.39 (round 308) — SET CONSTRAINTS { ALL | name [, …] } { DEFERRED | IMMEDIATE }. An empty names is the ALL form;
otherwise the timing applies only to the constraints listed.
DropTable
v7.14.0 — DROP TABLE [IF EXISTS] name [, name…] [CASCADE | RESTRICT]. Engine removes the matching tables
(each one) from the catalog; IF EXISTS makes the drop
idempotent. CASCADE / RESTRICT trailers parsed silently
(SPG always cascades index drops on table drop).
DropIndex
v7.14.0 — DROP INDEX [IF EXISTS] name. Removes the
matching index across whichever table holds it.
Prepare
v7.14.0 — empty / comment-only statement. The lexer strips
-- line comments and /* … */ block comments (including
the MySQL conditional /*!NNNNN … */ form) before the
parser ever sees them; a SQL chunk that contains nothing
else lands here. Engine returns CommandOk no-op so
pg_dump / mysqldump preambles (SET NAMES utf8mb4
wrapped in conditional comments, etc.) load cleanly.
v7.39 (round 277) — SQL-level PREPARE <name> [(type, …)] AS <stmt>. Session-scoped; the body keeps its $N placeholders
and is substituted at EXECUTE time.
Fields
Execute
v7.39 (round 277) — EXECUTE <name> [(arg, …)].
Deallocate(Option<String>)
v7.39 (round 277) — DEALLOCATE {<name> | ALL}. None = ALL.
CreateStatistics
v7.39 (round 280) — CREATE STATISTICS [IF NOT EXISTS] <name> [(kind, …)] ON <col>, … FROM <table>. SPG records the object so
dumps restore and reflection is honest; the planner does not
consult it yet.
Fields
DropStatistics
v7.39 (round 280) — DROP STATISTICS [IF EXISTS] <name>.
Call(String)
v7.39 (round 278) — CALL <proc>(…). Parses; the engine
reports that the procedure does not exist, because SPG has no
procedure catalog. Carried as a statement rather than raised at
parse time so the failure is a missing OBJECT (42883), not a
syntax error.
PrepareTransaction(String)
v7.39 (round 278) — PREPARE TRANSACTION '<gid>'. Same shape:
2PC is unavailable, which PG itself reports when
max_prepared_transactions is 0.
Empty
DeclareCursor
v7.39 (round 218) — DECLARE <name> [BINARY] [INSENSITIVE] [[NO] SCROLL] CURSOR [{WITH|WITHOUT} HOLD] FOR <select>. The
canonical driver path for streaming large result sets (psycopg2
named cursors, JDBC setFetchSize).
Fields
FetchCursor
v7.39 (round 218) — FETCH [<direction>] [FROM|IN] <name>.
MoveCursor
v7.39 (round 218) — MOVE [<direction>] [FROM|IN] <name>: FETCH
without returning rows; the command tag carries the move count.
CloseCursor
v7.39 (round 218) — CLOSE <name> / CLOSE ALL (None = ALL).
Listen(String)
v7.39 (round 222) — LISTEN <channel>: subscribe this session to
async notifications on the channel.
Notify
v7.39 (round 222) — NOTIFY <channel> [, '<payload>']. Delivered at
COMMIT (PG semantics: transactional, deduplicated within the tx);
immediately under autocommit.
Unlisten(Option<String>)
v7.39 (round 222) — UNLISTEN <channel> / UNLISTEN * (None = *).
CopyTo
COPY table [(cols)] TO STDOUT — the engine renders the
visible rows in COPY text format (tab-separated, \N
nulls, backslash escapes) as a single-text-column result
set; the wire layer streams CopyData from it.
Fields
query: Option<Box<Statement>>v7.39 (read01 round 94) — COPY (<query>) TO STDOUT: an
arbitrary SELECT/VALUES/CTE (a whole Statement, so set-ops and
VALUES ride through unchanged) whose result set is streamed in COPY
format. Some overrides table/columns (which are empty then);
None is the classic COPY <table> … shape.
options: CopyOptionsv7.37.x — WITH (FORMAT csv, HEADER, DELIMITER, NULL, QUOTE)
and the legacy WITH CSV HEADER … spelling. Default =
text format, no header (bare COPY … TO STDOUT).
CopyFromFile
v7.39 (round 249) — COPY table [(cols)] FROM '<path>' [(opts)].
The engine is no_std and cannot read the file itself: the host
(embedded / server / tooling) reads the path and hands the bytes to
Engine::copy_from_buffer. Dispatching this statement straight to
the engine reports that contract.
CopyToFile
v7.39 (round 249/252) — COPY <table> [(cols)] TO '<file>' (and
the COPY (<query>) TO '<file>' form). The engine is no_std and
cannot write the file itself: the host renders the payload via
Engine::copy_to_buffer and writes the path.
Fields
options: CopyOptionsSelect(SelectStatement)
CreateTable(CreateTableStatement)
CreateExtension(String)
v7.9.15 — CREATE EXTENSION [IF NOT EXISTS] <name> [WITH SCHEMA <s>] [VERSION <v>] [CASCADE] accepted as a
no-op so PG dumps that include extension declarations
(notably pgvector) load against SPG without splitting
init scripts. mailrs migration follow-up F3.
DoBlock(PlPgSqlBlock)
v7.9.27 → v7.16.2 — PG DO $$ … $$ [LANGUAGE plpgsql];
block. The body is now CAPTURED as a PlPgSqlBlock and
the engine executes it at top level (mailrs round-10
A.2). Pre-v7.16.2 the parser discarded the body and the
engine returned CommandOk — a SEV-1 silent no-op that
turned mailrs’s DO BEGIN IF EXISTS … THEN ALTER … END $$ idempotent migrations into invisible no-ops.
CreateIndex(CreateIndexStatement)
Insert(InsertStatement)
Update(UpdateStatement)
v4.4 — UPDATE <table> SET col=expr [, ...] [WHERE cond].
Delete(DeleteStatement)
v4.4 — DELETE FROM <table> [WHERE cond].
Merge(MergeStatement)
v7.17.0 Phase 3.P0-42 — SQL:2003 / PG 15+ MERGE statement.
MERGE INTO target [alias] USING source [alias] ON cond WHEN MATCHED [AND cond] THEN { UPDATE SET … | DELETE | DO NOTHING } WHEN NOT MATCHED [AND cond] THEN { INSERT (cols) VALUES (vals) | DO NOTHING } [WHEN …]. SPG v7.17 supports table-based source (subquery
source is a follow-up); BY SOURCE / BY TARGET and RETURNING
are also follow-ups.
Vacuum
v7.39 (round 169) — VACUUM [(opts)] [FULL|FREEZE|VERBOSE|ANALYZE] [<table>]. Was a parse-time no-op from the pre-MVCC era; with the
in-place MVCC gate ON, tombstoned versions are REAL bloat and a
customer’s manual VACUUM must actually reclaim. analyze mirrors
the VACUUM ANALYZE spelling.
Begin(Option<IsolationLevel>)
BEGIN / START TRANSACTION — with an optional explicit
ISOLATION LEVEL … mode (None = use the session default). PG
applies the level for the duration of this transaction only.
Commit
Rollback
Savepoint(String)
SAVEPOINT <name> — push a named savepoint onto the active TX’s
stack so a later ROLLBACK TO <name> can undo just the work
since this point.
RollbackToSavepoint(String)
ROLLBACK TO [SAVEPOINT] <name> — restore catalog state to the
named savepoint and discard later savepoints. Does not end the
transaction.
ReleaseSavepoint(String)
RELEASE [SAVEPOINT] <name> — discard a savepoint without
rolling back. Keeps the work done since then.
ShowTables
SHOW TABLES — return the list of tables in the catalog.
ShowDatabases
v7.17.0 Phase 3.P0-58 — MySQL SHOW DATABASES /
SHOW SCHEMAS. SPG is single-database; the executor
returns the canonical MySQL set so the mysql / MariaDB
client populates its database selector.
ShowCreateTable(String)
v7.17.0 Phase 3.P0-59 — MySQL SHOW CREATE TABLE <t>
returns a 2-column row (Table, "Create Table") carrying
the synthesized DDL. mysqldump emits this for every
table at scrape time.
ShowIndexes(String)
v7.17.0 Phase 3.P0-60 — MySQL SHOW INDEXES FROM <t>
(also SHOW INDEX, SHOW KEYS).
ShowStatus
v7.17.0 Phase 3.P0-61 — MySQL SHOW STATUS.
ShowVariables
v7.17.0 Phase 3.P0-61 — MySQL SHOW VARIABLES.
ShowProcesslist
v7.17.0 Phase 3.P0-62 — MySQL SHOW PROCESSLIST.
Discard(DiscardTarget)
v7.39 (round 320, V53) — DISCARD { ALL | PLANS | SEQUENCES | TEMP }.
pgbouncer sends DISCARD ALL between pooled client sessions to make
the connection look brand new to the next client; it used to be
swallowed as dump noise, so nothing was discarded.
Kill
v7.39 (round 318, V51) — MySQL KILL [CONNECTION | QUERY] <expr>.
The id is an expression because MariaDB accepts one
(KILL connection_id() is the documented way to drop your own
connection). query_only is the QUERY form: stop the target’s
running statement but leave it connected.
ShowColumns(String)
SHOW COLUMNS FROM <table> — return one row per column with
its declared name / type / nullability.
CreateUser(CreateUserStatement)
CREATE USER 'name' WITH PASSWORD 'pw' ROLE 'admin' (v4.1).
Role is optional; defaults to readonly when omitted.
DropUser
DROP USER 'name' (v4.1). v7.39 (read01 round 58) — IF EXISTS is
carried through: PG skips with a NOTICE rather than erroring.
SetRole(Option<String>)
v7.39 (RLS) — SET ROLE { name | NONE | DEFAULT } / RESET ROLE.
Some(name) switches the session’s effective role (drives
current_user and RLS enforcement); None resets to the login
identity (the Admin superuser).
Grant(GrantStatement)
v7.39 (read01 round 57) — GRANT <privs> ON <object> TO <roles>.
Revoke(GrantStatement)
v7.39 (read01 round 57) — REVOKE [GRANT OPTION FOR] <privs> ON <object> FROM <roles>.
CreatePolicy(CreatePolicyStatement)
v7.39 (RLS) — CREATE POLICY name ON table ….
AlterPolicy(AlterPolicyStatement)
v7.39 (RLS) — ALTER POLICY name ON table ….
DropPolicy(DropPolicyStatement)
v7.39 (RLS) — DROP POLICY [IF EXISTS] name ON table.
ShowUsers
SHOW USERS (v4.1) — admin-only listing of (name, role).
Explain(ExplainStatement)
v4.26 — EXPLAIN [ANALYZE] <select>. The engine returns a
single-column text table describing the rewritten plan tree
for inner. analyze triggers an actual exec to attach
observed row counts and elapsed micros to each node.
AlterIndex(AlterIndexStatement)
v6.0.4 — ALTER INDEX <name> REBUILD [WITH (encoding = ...)].
Synchronous rebuild of an NSW index. With the optional
encoding clause, every stored cell at the indexed column is
also re-encoded through coerce_value before the new graph
builds.
AlterTable(AlterTableStatement)
v6.7.2 — ALTER TABLE <name> SET <setting> = <value>.
The only setting in v6.7.2 is hot_tier_bytes, which
overrides the global SPG_HOT_TIER_BYTES freezer trigger
for the named table.
CreatePublication(CreatePublicationStatement)
v6.1.2 — CREATE PUBLICATION <name> [FOR ALL TABLES].
The catalog row lives in spg_publications. Publisher-side
WAL filtering arrives in v6.1.5.
DropPublication
v6.1.2 — DROP PUBLICATION <name>. PG-compatible silent
no-op when the publication does not exist.
Fields
ShowPublications
v6.1.3 — SHOW PUBLICATIONS. Returns one row per
publication ordered by name with (name, scope_summary, table_count) columns. The scope summary is the human-
readable form ALL TABLES / FOR TABLE … / FOR ALL TABLES EXCEPT …; table_count is NULL for the
AllTables scope and the table-list length otherwise.
CreateSubscription(CreateSubscriptionStatement)
v6.1.4 — CREATE SUBSCRIPTION <name> CONNECTION '<conn>' PUBLICATION <pub_name> [, <pub_name> …]. Catalog lands
in spg_subscriptions; when the subscription is
enabled = true (default) the server spawns a
background worker that connects to conn and drains the
requested publication(s) into the local engine.
DropSubscription
v6.1.4 — DROP SUBSCRIPTION <name>. Like DROP
PUBLICATION, silent no-op when absent. Stops the
associated worker thread before removing the row.
Fields
if_exists: boolv7.39 (round 754, F31-B4) — same contract as
Statement::DropPublication.
ShowSubscriptions
v6.1.4 — SHOW SUBSCRIPTIONS. Returns one row per
subscription ordered by name with (name, conn_str, publications, enabled, last_received_pos).
WaitForWalPosition
v6.1.7 — WAIT FOR WAL POSITION <pos> [WITH TIMEOUT <ms>].
Blocks until the local server’s apply position reaches
<pos> or <ms> elapses. Server-layer command: the
engine refuses it (EngineError::Unsupported) since
lag_state lives in spg-server’s ServerState.
Fields
Analyze(Option<String>)
v6.2.0 — ANALYZE [<table>]. Bare form walks every user
table; ANALYZE <name> re-stats just one. Populates
spg_statistic with per-column null_frac + n_distinct +
100-bucket equi-depth histogram.
Maintain
v7.39 (round 535) — REINDEX { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } [CONCURRENTLY] <name> and CLUSTER [VERBOSE] [<table> [USING <index>]].
SPG has neither index bloat nor a clustering order to rebuild, so
the work is a no-op — but PG VALIDATES the target, and both were
swallowed at parse time, so REINDEX TABLE typo reported success.
The name is carried now so the engine can say what PG says.
Fields
kind: MaintainKindconcurrently: boolREINDEX … CONCURRENTLY. Carried for the same reason as
CreateIndexStatement::concurrently: PG bars the
CONCURRENTLY form inside a transaction block and allows the
plain one.
Truncate
v7.37.17 (17.6 sibling) — TRUNCATE [TABLE] [ONLY] <name> [, ...] [RESTART IDENTITY | CONTINUE IDENTITY] [CASCADE | RESTRICT]. Clears every row from each named table. SPG’s
SEQUENCE identity is per-table; RESTART IDENTITY reinitializes
the associated sequence to its starting value. CASCADE
currently walks direct FK-referring tables and truncates
them too (PG’s semantics). The ONLY modifier (skip partitions)
and RESTRICT (default) are accepted with no effect since
SPG’s declarative partitions are always truncated together.
Fields
only: boolv7.39 (round 647) — TRUNCATE ONLY t. Absorbed as a no-op
since v7.14 on the reasoning that SPG’s children are separate
relations a truncate does not descend into. Same reasoning
round 621 applied to FROM ONLY, and it stopped being true
for the same reason: measured, TRUNCATE <inheritance parent>
leaves the children’s rows where PG empties them, and
TRUNCATE ONLY <partitioned parent> is silently accepted
where PG refuses it outright.
CompactColdSegments
v6.7.3 — COMPACT COLD SEGMENTS. Walks every user table’s
BTree-cold indices and merges small cold-tier segments
(size below SPG_COMPACTION_TARGET_SEGMENT_BYTES, default
4 MiB) into a single larger segment per (table, index).
WHERE predicate filtering on which tables to compact is
carved out of v6.7.3 (per V6_7_DESIGN.md STABILITY entry);
v6.7.3 only supports the bare form.
SetParameter
v7.12.1 — SET <name> [TO|=] <value>. Records a session
parameter on the engine; v7.12.1 honours
default_text_search_config (consumed by to_tsvector /
plainto_tsquery family when called without an explicit
config arg). All other names are accepted as a no-op so PG
dumps with SET client_encoding, SET search_path etc.
load cleanly.
Fields
SetParameterList(Vec<(String, SetValue)>)
v7.14.0 — SET a = 1, b = 2, … MySQL-flavoured
multi-assignment (mysqldump preamble uses
SET @OLD_FOREIGN_KEY_CHECKS = @@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0). Engine applies each pair in
source order. Pairs whose LHS is a MySQL session/user
variable (@VAR / @@VAR) are recorded with the raw
name so the engine can ignore them; pairs whose LHS is
a recognised engine parameter (e.g. FOREIGN_KEY_CHECKS)
go through the regular set_session_param path.
SetUserVars(Vec<(String, Expr)>, Vec<(String, Expr)>)
v7.39 (round 430) — MySQL’s USER-defined variables:
SET @x = 5, @s := CONCAT('a','b'). Distinct from
Self::SetParameter (a @@-style engine/session setting) in
every way that matters: the value is an arbitrary EXPRESSION, the
name lives in its own per-session namespace, and reading an unset
one answers NULL rather than raising. := and = are the same
assignment here.
Before this the parser stripped every @, so @x and @@x were
the same node: SET @x = 5 silently landed in the session-parameter
store where nothing could read it back, and SELECT @x failed with
“Unknown system variable”.
v7.39 (round 554) — SET @a = …, SETTING = ….
settings is the trailing half a mysqldump preamble writes:
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO'
saves a value and changes it in one statement. The parser used
to refuse the mixture outright, so no mysqldump could be
restored past its preamble.
SetTransaction
v7.38 轴 4 — SET [SESSION] TRANSACTION ISOLATION LEVEL …
(plus optional READ ONLY / READ WRITE / DEFERRABLE clauses
silently accepted). PG-standard surface for picking an
isolation level. Engine tracks the value on
Engine::current_isolation_level(); actual MVCC / SSI
semantics implementation lands separately. PG itself maps
READ UNCOMMITTED to READ COMMITTED; SPG mirrors that —
effectively every level reads as READ COMMITTED in v7.37.8.
Fields
isolation: IsolationLevelShowParameter(String)
v7.38 轴 4 — SHOW <param> returns a 1-column 1-row result
with the parameter’s current value as TEXT. Today the only
recognised param is transaction_isolation; further
surfaces (search_path, application_name, …) land as the
session-parameter inventory grows.
ResetParameter(Option<String>)
v7.12.1 — RESET <name> / RESET ALL. Restores parameter
to its default. No-op for parameters SPG does not track.
CreateFunction(CreateFunctionStatement)
v7.12.4 — CREATE [OR REPLACE] FUNCTION name(args) RETURNS <type> [LANGUAGE <lang>] AS $$ body $$ [LANGUAGE <lang>].
v7.12.4 ships plpgsql for RETURNS TRIGGER bodies (the
CREATE TRIGGER + AFTER/BEFORE row-level pipeline). Other
languages parse but error at exec time with a clear
unsupported message.
CreateTrigger(CreateTriggerStatement)
v7.12.4 — CREATE [OR REPLACE] TRIGGER name {BEFORE|AFTER} {INSERT|UPDATE|DELETE} [OR ...] ON tbl FOR EACH ROW EXECUTE {FUNCTION|PROCEDURE} fn_name(). STATEMENT-level
triggers and column-list / WHEN clauses are out of scope
for v7.12.4.
CreateRule(CreateRuleStatement)
v7.39 (round 139) — CREATE RULE name AS ON event TO table [WHERE cond] DO [ALSO|INSTEAD] { NOTHING | command } query-rewrite rule.
DropRule
v7.39 (round 139) — DROP RULE [IF EXISTS] name ON table.
DropTrigger
v7.12.4 — DROP TRIGGER [IF EXISTS] name ON tbl. Silent
no-op when missing if IF EXISTS is set.
DropFunction
v7.12.4 — DROP FUNCTION [IF EXISTS] name. Same shape as
DROP TRIGGER but global (no table scope).
Fields
CreateSequence(CreateSequenceStatement)
v7.17.0 — CREATE [TEMPORARY] SEQUENCE [IF NOT EXISTS] name [AS data_type] [INCREMENT [BY] n] [MINVALUE n | NO MINVALUE] [MAXVALUE n | NO MAXVALUE] [START [WITH] n] [CACHE n] [[NO] CYCLE] [OWNED BY {table.col | NONE}].
Closes the round-7+ silent-no-op SEQUENCE story so pg_dump
emits + nextval/currval/setval downstream all work.
AlterSequence(AlterSequenceStatement)
v7.17.0 — ALTER SEQUENCE [IF EXISTS] name <options> with
the same option grammar as CREATE SEQUENCE, plus
RESTART [WITH n] and OWNED BY ... re-attach.
DropSequence
v7.17.0 — DROP SEQUENCE [IF EXISTS] name [, name…] [CASCADE | RESTRICT]. CASCADE / RESTRICT trailers parsed
silently (no FK on sequences).
CreateView(CreateViewStatement)
v7.17.0 Phase 1.2 — CREATE [OR REPLACE] [TEMPORARY] VIEW [IF NOT EXISTS] name [(col, …)] AS <SELECT …>. Closes the
silent-no-op VIEW story from the v7.17 customer-readiness
audit: pre-v7.17 SPG parsed CREATE VIEW as Statement::Empty
so any downstream SELECT FROM v errored with table-not-
found. The view body is stored verbatim; SELECT FROM
DropView
v7.17.0 Phase 1.2 — DROP VIEW [IF EXISTS] name [, name…] [CASCADE | RESTRICT]. Removes the matching view from the
catalog; CASCADE/RESTRICT parsed silently.
CreateMaterializedView(CreateMaterializedViewStatement)
v7.17.0 Phase 1.3 — CREATE MATERIALIZED VIEW [IF NOT EXISTS] name [(col, …)] AS <SELECT …> [WITH [NO] DATA].
Closes the silent-no-op MATERIALIZED VIEW story. Storage
model: the materialised result lives as a regular table
with the matching name + a parallel
materialized_views registry mapping name → body source
(used by REFRESH).
RefreshMaterializedView
v7.17.0 Phase 1.3 — REFRESH MATERIALIZED VIEW name [WITH [NO] DATA]. Re-runs the stored body and replaces the
cached rows. WITH NO DATA truncates without re-running.
DropMaterializedView
v7.17.0 Phase 1.3 — DROP MATERIALIZED VIEW [IF EXISTS] name [, name…] [CASCADE | RESTRICT]. Drops both the
backing table and the source registry entry.
CreateType(CreateTypeStatement)
v7.17.0 Phase 1.4 — CREATE TYPE name AS ENUM ('a', 'b', …). Closes the silent-no-op CREATE TYPE story so PG
dumps that declare enum types load with real constraints
instead of becoming free-form TEXT. Future kinds
(composite / range / domain) extend the inner kind
enum.
CommentOn
v7.37 D.55 — ALTER TYPE name ADD VALUE [IF NOT EXISTS] 'label' [{BEFORE | AFTER} 'existing']. Extends an enum’s label list so
enum evolution stops being a silent no-op. position is
Some((is_before, anchor)).
v7.39 (read01 round 49) — ALTER TYPE t RENAME VALUE 'old' TO 'new'.
Used to be swallowed by the ALTER TYPE no-op tail, so the rename was
accepted and silently ignored.
v7.39 (read01 round 50) — COMMENT ON <kind> <name> IS { 'text' | NULL }.
Used to be swallowed as dump noise, so a comment was accepted and lost
(and obj_description / col_description always returned NULL).
kind is lowercase (“table” / “column” / “index” / …); for a column
name is the dotted table.column. comment: None = IS NULL = remove.
AlterTypeRenameValue
AlterTypeAddValue
DropType
v7.17.0 Phase 1.4 — DROP TYPE [IF EXISTS] name [, name…] [CASCADE | RESTRICT]. Removes the matching enum/domain
from the catalog.
CreateDomain(CreateDomainStatement)
v7.17.0 Phase 1.5 — CREATE DOMAIN name AS base_type [DEFAULT expr] [NOT NULL | NULL] [CHECK (expr)]*.
A DOMAIN is a named CHECK-constrained alias over a built-
in type. The CHECK + NOT NULL + DEFAULT clauses apply to
every column declared with the domain. Closes the
silent-no-op CREATE DOMAIN story so PG dumps that ship
validated identifier types (email, positive_int, …) keep
their guarantees.
AlterDomain
v7.39 (round 260) — ALTER DOMAIN name <action>. Every form was
previously swallowed by the catch-all DDL arm: the statement
reported success and did nothing, so a migration that dropped a
constraint kept rejecting the data it had just been told to
accept.
DropDomain
v7.17.0 Phase 1.5 — DROP DOMAIN [IF EXISTS] name [, name…] [CASCADE | RESTRICT]. Removes the matching
domain from the catalog.
CreateSchema
v7.17.0 Phase 1.6 — CREATE SCHEMA [IF NOT EXISTS] name [AUTHORIZATION user]. SPG is single-database;
schemas are tracked as a namespace registry so pg_dump
multi-schema declarations land cleanly and SELECT * FROM information_schema.schemata returns real entries.
Schema-qualified schema.table references still strip
the prefix at lookup time per PG (schemas are not
isolation boundaries in v7.17 — see project-next-docket
for the v7.18+ isolation tracking).
DropSchema
v7.17.0 Phase 1.6 — DROP SCHEMA [IF EXISTS] name [, name…] [CASCADE | RESTRICT]. Removes the schema
from the registry; built-in public / pg_catalog /
information_schema cannot be dropped.
Implementations§
Source§impl Statement
impl Statement
Sourcepub fn mysql_implicit_commit(&self) -> bool
pub fn mysql_implicit_commit(&self) -> bool
v7.18 — classify whether the statement is read-only at
engine level. Used by spg-sqlx’s SpgConnection to
route SELECT-shaped traffic through the fan-out
AsyncReadHandle (no writer-lock contention) while
keeping DML / DDL / TX-control on the single-writer path.
The classification matches what
Engine::execute_readonly_with_cancel accepts: anything
that does NOT mutate catalog, statistics, session state,
or transaction state. WaitForWalPosition is included
(engine returns Unsupported, but the classification is
semantically read-only — no mutation). Empty is excluded
out of an abundance of caution — the no-op routes
through the writer so any future side effect lands
uniformly.
Not connection-state aware. SET LOCAL / RESET
affect session parameters and must run on the writer
engine that owns the session state; they classify as
writer-path here. Same for BEGIN / COMMIT /
ROLLBACK / SAVEPOINT — transaction control is
always writer-path.
v7.39 (round 435) — does this statement implicitly COMMIT an open
transaction under MySQL?
PG runs DDL inside the transaction; MySQL commits before (and after)
it, so START TRANSACTION; INSERT …; CREATE TABLE …; ROLLBACK keeps
the INSERT on MySQL and loses it on PG. Measured on MariaDB 11 for
CREATE TABLE, ALTER TABLE, DROP TABLE, TRUNCATE, CREATE INDEX and a
nested START TRANSACTION; and measured NOT to fire for CREATE TEMPORARY TABLE, SET, or a SELECT.
A positive list, not “everything that is not DML”: a statement wrongly listed here commits a client’s data early, which is as bad as the divergence it fixes. SPG-only maintenance verbs (VACUUM, DISCARD, COMPACT) are left out — a MySQL session never sends them.