Skip to main content

MutationSyntax

Struct MutationSyntax 

Source
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: bool

Accept the post-verb INSERT IGNORE modifier.

§insert_overwrite: bool

Accept the post-verb INSERT OVERWRITE modifier.

§returning: bool

Accept a RETURNING <output> [, ...] clause on INSERT/UPDATE/DELETE (PostgreSQL; also Oracle/MariaDB/SQLite).

§on_conflict: bool

Accept an INSERT ... ON CONFLICT [<target>] DO {NOTHING | UPDATE ...} upsert clause (PostgreSQL; also SQLite).

§on_duplicate_key_update: bool

Accept 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: bool

Accept UPDATE ... SET ( col, ... ) = <source> multiple-column assignment (PostgreSQL; SQL feature T641). Also reached through ON CONFLICT DO UPDATE.

§update_tuple_value_row_arity: bool

Reject 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: bool

Accept WHERE CURRENT OF <cursor> positioned UPDATE/DELETE (PostgreSQL; SQL feature F831).

§merge: bool

Accept 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: bool

Accept 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: bool

Accept 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: bool

Accept 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: bool

Accept joins in the target position of UPDATE/DELETE and comma-separated DELETE FROM targets.

§or_conflict_action: bool

Accept 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: bool

Accept 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: bool

Accept 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: bool

Accept 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: bool

Accept 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: bool

Accept 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: bool

Accept 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: bool

Accept 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: bool

Accept 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: bool

Accept 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: bool

Accept 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: bool

Accept additional comma-separated value rows in a MERGE ... THEN INSERT action.

§merge_update_set_star: bool

Accept DuckDB UPDATE SET * in a MERGE WHEN MATCHED arm (column-wise copy from the source). Off in ANSI/PostgreSQL.

§merge_insert_star_by_name: bool

Accept DuckDB INSERT * / INSERT BY NAME [*] merge insert spellings. Off in ANSI/PostgreSQL (only the standard column-list / VALUES form).

§merge_error_action: bool

Accept DuckDB THEN ERROR as a MERGE action (runtime raises when the arm fires). Off in ANSI/PostgreSQL.

§update_set_qualified_column: bool

Accept 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§

Source§

impl MutationSyntax

Source

pub const ANSI: Self

The ANSI predefined value.

Source§

impl MutationSyntax

Source

pub const LENIENT: Self

Available on crate feature lenient only.

The LENIENT preset for mutation syntax.

Source§

impl MutationSyntax

Source

pub const MYSQL: Self

Available on crate feature mysql only.

The MYSQL preset for mutation syntax.

Source§

impl MutationSyntax

Source

pub const POSTGRES: Self

Available on crate feature postgres only.

The POSTGRES preset for mutation syntax.

Source§

impl MutationSyntax

Source

pub const QUILTDB: Self

Available on crate feature quiltdb only.

Mutation syntax enabled by this preset.

Source§

impl MutationSyntax

Source

pub const SQLITE: Self

Available on crate feature sqlite only.

The SQLITE preset for mutation syntax.

Trait Implementations§

Source§

impl Clone for MutationSyntax

Source§

fn clone(&self) -> MutationSyntax

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for MutationSyntax

Source§

impl Debug for MutationSyntax

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for MutationSyntax

Source§

impl PartialEq for MutationSyntax

Source§

fn eq(&self, other: &MutationSyntax) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for MutationSyntax

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.