pub struct MutationSyntax {Show 29 fields
pub insert_ignore: bool,
pub insert_overwrite: bool,
pub returning: bool,
pub on_conflict: bool,
pub on_duplicate_key_update: bool,
pub multi_column_assignment: bool,
pub update_tuple_value_row_arity: bool,
pub where_current_of: bool,
pub merge: bool,
pub replace_into: bool,
pub insert_set: bool,
pub update_delete_tails: bool,
pub joined_update_delete: bool,
pub or_conflict_action: bool,
pub insert_column_matching: bool,
pub delete_using: bool,
pub update_from: bool,
pub delete_using_target_alias: bool,
pub cte_before_insert: bool,
pub cte_before_merge: bool,
pub data_modifying_ctes: bool,
pub merge_when_not_matched_by: bool,
pub merge_insert_default_values: bool,
pub merge_insert_overriding: bool,
pub merge_insert_multirow: bool,
pub merge_update_set_star: bool,
pub merge_insert_star_by_name: bool,
pub merge_error_action: bool,
pub update_set_qualified_column: bool,
}Expand description
Dialect-owned mutation-statement (INSERT/UPDATE/DELETE) syntax extensions.
These cover the non-ANSI tails the standard expresses differently (the standard
upsert is MERGE, and it has no RETURNING): they are explicit dialect data
so a parser gate never type-checks the dialect. Each flag is purely a
grammar gate — when off, the keyword is left unconsumed and the trailing clause
surfaces as a parse error, which is how ANSI rejects PostgreSQL upserts.
Fields§
§insert_ignore: boolAccept the post-verb INSERT IGNORE modifier.
insert_overwrite: boolAccept the post-verb INSERT OVERWRITE modifier.
returning: boolAccept a RETURNING <output> [, ...] clause on INSERT/UPDATE/DELETE
(PostgreSQL; also Oracle/MariaDB/SQLite).
on_conflict: boolAccept an INSERT ... ON CONFLICT [<target>] DO {NOTHING | UPDATE ...}
upsert clause (PostgreSQL; also SQLite).
on_duplicate_key_update: boolAccept an INSERT ... ON DUPLICATE KEY UPDATE <col> = <expr> [, ...] upsert
clause (MySQL/MariaDB). MySQL infers the conflicting unique key, so there is
no arbiter and no DO NOTHING; this also admits the VALUES(<col>) reference
to a column’s proposed insert value inside those update expressions.
multi_column_assignment: boolAccept UPDATE ... SET ( col, ... ) = <source> multiple-column assignment
(PostgreSQL; SQL feature T641). Also reached through ON CONFLICT DO UPDATE.
update_tuple_value_row_arity: boolReject explicit value-row RHS tuple assignments whose element count differs from
the target column count (UPDATE t SET (a, b) = (1)). This is a parse-time
DuckDB arity check; PostgreSQL parses the same surface and leaves arity to later
analysis, so the behavior is intentionally split from multi_column_assignment.
where_current_of: boolAccept WHERE CURRENT OF <cursor> positioned UPDATE/DELETE
(PostgreSQL; SQL feature F831).
merge: boolAccept the MERGE INTO <target> USING <source> ON <cond> WHEN [NOT] MATCHED ...
statement (SQL:2003 feature F312, the standard upsert; PostgreSQL 15+). Unlike
the other flags here this gates a leading statement keyword, not a trailing
clause: when off, MERGE is not dispatched and surfaces as an unknown
statement, which is how MySQL (no MERGE) rejects it.
replace_into: boolAccept the MySQL REPLACE [INTO] <table> ... delete-then-insert statement.
Like merge this gates a leading statement keyword: when off (ANSI /
PostgreSQL), REPLACE is not dispatched and surfaces as an unknown statement.
REPLACE reuses the INSERT tail grammar tagged
InsertVerb::Replace, so it needs no node of its own.
insert_set: boolAccept the MySQL INSERT/REPLACE ... SET <col> = <value> [, ...]
assignment-list source (InsertSource::Set). When
off (ANSI / PostgreSQL), SET after the target is left unconsumed and surfaces
as a parse error, the same reject mechanism the other trailing-clause gates use.
update_delete_tails: boolAccept the MySQL single-table UPDATE/DELETE ... [ORDER BY <keys>] [LIMIT <count>] row-limiting tails. One flag gates both clauses on both statements
because they are a single dialect unit — MySQL admits the ORDER BY only
alongside the LIMIT it orders, and on UPDATE exactly as on DELETE
(mirroring how table_options gates the trailing options and column attribute
together). The multi-table UPDATE/DELETE forms take no such tail, so this is
the single-table grammar only. Off in ANSI/PostgreSQL, which have neither tail:
there the trailing ORDER BY/LIMIT is left unconsumed and surfaces as a clean
parse error.
joined_update_delete: boolAccept joins in the target position of UPDATE/DELETE and comma-separated
DELETE FROM targets.
or_conflict_action: boolAccept the SQLite INSERT OR <action> / UPDATE OR <action> conflict-resolution
prefix on the mutation verb, where <action> is REPLACE/IGNORE/ABORT/FAIL/
ROLLBACK (ConflictResolution, the Insert::or_action
/ Update::or_action slot). SQLite only. Distinct from the
MySQL INSERT IGNORE surface (a bare post-verb IGNORE, no OR) — that is not
absorbed here. Off in ANSI/PostgreSQL/MySQL, where the OR after the verb is left
unconsumed and surfaces as a clean parse error.
insert_column_matching: boolAccept DuckDB INSERT INTO t BY NAME|BY POSITION … column-matching mode
between the target and the source. When off, BY is left unconsumed.
delete_using: boolAccept the DELETE FROM <target> USING <from-list> … multi-relation delete
(PostgreSQL; also MySQL’s multi-table delete). On for
ANSI/PostgreSQL/MySQL/DuckDB/Lenient. SQLite has no USING on DELETE
(engine-measured-rejected via rusqlite), so it is off; the USING keyword is then
left unconsumed and the trailing relation list surfaces as a clean parse error.
update_from: boolAccept a PostgreSQL/SQLite UPDATE … SET … FROM <table refs> additional-relations
clause. On for ANSI/PostgreSQL/SQLite/DuckDB/Lenient. MySQL has no UPDATE … FROM —
its multi-table update lists every table in the target position
(UPDATE t1, t2 SET …) — so UPDATE t SET … FROM u is an ER_PARSE_ERROR on
mysql:8; with the flag off the FROM keyword is left unconsumed and surfaces as a
clean parse error.
delete_using_target_alias: boolAccept an alias on the target of a DELETE FROM <target> USING <table_refs>
multi-table delete (DELETE FROM t AS e USING u …). On for ANSI/PostgreSQL/
DuckDB/Lenient. MySQL’s DELETE FROM tbl … USING … names the delete target(s) as
bare table names that must match the USING relations, so an alias there is an
ER_PARSE_ERROR on mysql:8 (DELETE FROM event AS e USING sales … rejects, while a
single-table DELETE FROM event AS e WHERE … — no USING — parses); it is off for
MySQL. Only the USING-form target is governed — the plain single-table delete’s
alias is unaffected. Independent of delete_using, which gates
whether the USING clause is admitted at all.
cte_before_insert: boolAccept a leading WITH CTE clause before an INSERT statement
(WITH a AS (…) INSERT INTO t …). On for ANSI/PostgreSQL/DuckDB/Lenient. MySQL
admits a statement-leading WITH before SELECT/UPDATE/DELETE but not before
INSERT (its CTE for an insert rides the INSERT … SELECT source instead:
INSERT INTO t WITH … SELECT …), so WITH … INSERT … is an ER_PARSE_ERROR on
mysql:8; it is off for MySQL and the INSERT after the CTE list then surfaces as a
clean parse error. The bare INSERT with no leading WITH is unaffected.
cte_before_merge: boolAccept a leading WITH CTE clause before a MERGE statement
(WITH a AS (…) MERGE INTO t USING a …; PostgreSQL 15+, DuckDB — probed on
1.5.4). Off for ANSI: SQL:2016’s <merge statement> takes no <with clause>
(unlike an INSERT, whose source query carries one), so a leading WITH
before MERGE is a dialect extension, not standard surface. The MERGE
counterpart of cte_before_insert: when off, the
MERGE after the CTE list surfaces as a clean parse error, and the bare
MERGE (no leading WITH) is unaffected. Only reachable where
merge dispatches MERGE at all (the dependency is
FeatureDependencyViolation::CteBeforeMergeWithoutMerge).
data_modifying_ctes: boolAccept a data-modifying statement — INSERT/UPDATE/DELETE/MERGE, the
MERGE arm PG 17+ — as a CTE body
(WITH t AS (DELETE FROM x RETURNING *) SELECT * FROM t;
CteBody). PostgreSQL admits the DML body at every
WITH site during raw parsing — nested subquery/scalar-subquery WITHs,
DECLARE CURSOR/CREATE TABLE AS/CREATE VIEW/EXPLAIN/COPY (…) TO
bodies (all probed on pg_query 17; misuse is rejected at analysis, past the
parse boundary this crate models) — so the gate governs the one shared CTE
grammar uniformly rather than per placement. Off everywhere else: DuckDB
parse-rejects a DML CTE body (A CTE needs a SELECT, probed on 1.5.4), MySQL
is an ER_PARSE_ERROR (probed on mysql:8), SQLite rejects, and the SQL
standard has no data-modifying WITH; there the DML keyword after AS ( is
not dispatched and surfaces as the ordinary query-body parse error.
merge_when_not_matched_by: boolAccept the WHEN NOT MATCHED BY {SOURCE | TARGET} MERGE arms (PostgreSQL 17+,
DuckDB — both probed). NOT MATCHED BY TARGET is the bare NOT MATCHED (an
unpaired source row → insert); NOT MATCHED BY SOURCE is the new arm firing on an
unpaired target row (→ update/delete, like MATCHED). Off in ANSI: SQL:2016’s
<merge when clause> is only MATCHED/NOT MATCHED, so the BY after NOT MATCHED is not standard surface — with the flag off it is left unconsumed and the
clause surfaces as a clean parse error. Only reachable where merge
dispatches MERGE at all (the dependency is
FeatureDependencyViolation::MergeWhenNotMatchedByWithoutMerge); the bare
WHEN NOT MATCHED is unaffected.
merge_insert_default_values: boolAccept the MERGE ... WHEN NOT MATCHED THEN INSERT DEFAULT VALUES action — a
column-default row taking neither a column list nor an OVERRIDING clause
(PostgreSQL, DuckDB — both probed). Off in ANSI: SQL:2016’s
<merge insert specification> is INSERT [cols] [override] VALUES (...) with no
DEFAULT VALUES alternative, so with the flag off the DEFAULT after INSERT
surfaces as a clean parse error. Distinct from the top-level INSERT ... DEFAULT VALUES source, which every dialect admits. Only reachable where
merge dispatches MERGE at all (the dependency is
FeatureDependencyViolation::MergeInsertDefaultValuesWithoutMerge).
merge_insert_overriding: boolAccept the MERGE ... WHEN NOT MATCHED THEN INSERT ... OVERRIDING {SYSTEM | USER} VALUE identity override on the merge insert action (SQL:2016
<merge insert specification>’s <override clause>; PostgreSQL). Unlike the
other two merge extensions here this is standard surface, so it is on for ANSI —
but DuckDB rejects OVERRIDING inside MERGE (syntax error at or near "OVERRIDING", probed on 1.5.4) while accepting it on a top-level INSERT, so its
preset splits from the shared top-level InsertOverriding
grammar in exactly this knob. Off for DuckDB/MySQL; with the flag off the
OVERRIDING between the column list and VALUES is left unconsumed and surfaces
as a clean parse error. Only reachable where merge dispatches
MERGE at all (the dependency is
FeatureDependencyViolation::MergeInsertOverridingWithoutMerge).
merge_insert_multirow: boolAccept additional comma-separated value rows in a MERGE ... THEN INSERT action.
merge_update_set_star: boolAccept DuckDB UPDATE SET * in a MERGE WHEN MATCHED arm (column-wise copy
from the source). Off in ANSI/PostgreSQL.
merge_insert_star_by_name: boolAccept DuckDB INSERT * / INSERT BY NAME [*] merge insert spellings.
Off in ANSI/PostgreSQL (only the standard column-list / VALUES form).
merge_error_action: boolAccept DuckDB THEN ERROR as a MERGE action (runtime raises when the arm
fires). Off in ANSI/PostgreSQL.
update_set_qualified_column: boolAccept a multi-part (qualified) column name as an UPDATE … SET assignment target
(UPDATE t SET t.i = 1 / schema.t.col = …). On for ANSI/PostgreSQL/MySQL/SQLite/Lenient.
DuckDB parse-rejects qualified SET targets (“Qualified column names in UPDATE .. SET
not supported”, probed on 1.5.4), so it is off there; with the flag off a target whose
ObjectName has more than one part surfaces as a clean parse
error. A bare single-part column remains free either way.
Implementations§
Trait Implementations§
Source§impl Clone for MutationSyntax
impl Clone for MutationSyntax
Source§fn clone(&self) -> MutationSyntax
fn clone(&self) -> MutationSyntax
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more