vibesql_ast/
dml.rs

1//! Data Manipulation Language (DML) statements
2//!
3//! This module contains INSERT, UPDATE, and DELETE statement types.
4
5use crate::{CommonTableExpr, Expression, FromClause, OrderByItem, SelectStmt};
6
7// ============================================================================
8// INSERT Statement
9// ============================================================================
10
11/// Source of data for INSERT statement
12#[derive(Debug, Clone, PartialEq)]
13pub enum InsertSource {
14    /// INSERT ... VALUES (...)
15    Values(Vec<Vec<Expression>>),
16    /// INSERT ... SELECT ...
17    Select(Box<SelectStmt>),
18    /// INSERT ... DEFAULT VALUES
19    /// Inserts a single row using default values for all columns.
20    DefaultValues,
21}
22
23/// Conflict resolution strategy for INSERT and UPDATE statements (SQLite extension)
24///
25/// SQLite supports conflict resolution clauses in both INSERT and UPDATE statements:
26/// - `INSERT OR REPLACE INTO ...`
27/// - `UPDATE OR REPLACE ... SET ...`
28///
29/// See: <https://www.sqlite.org/lang_conflict.html>
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub enum ConflictClause {
32    /// ABORT - Abort current statement, rollback changes from this statement (default)
33    /// When a constraint violation occurs, the statement is aborted and all changes
34    /// made by the statement are rolled back, but changes from prior statements
35    /// in the same transaction are preserved.
36    Abort,
37    /// FAIL - Abort statement but keep prior changes within the statement
38    /// When a constraint violation occurs, the statement is aborted but changes
39    /// made by the statement prior to the violation are preserved.
40    Fail,
41    /// IGNORE - Skip the row causing violation, continue with next row
42    /// When a constraint violation occurs, the row is simply skipped and processing
43    /// continues with the next row.
44    Ignore,
45    /// REPLACE - Delete conflicting rows, then insert/update the new row
46    /// When a UNIQUE or PRIMARY KEY constraint violation occurs, the conflicting
47    /// row is deleted before inserting/updating the new row.
48    Replace,
49    /// ROLLBACK - Abort and rollback entire transaction
50    /// When a constraint violation occurs, the entire transaction is rolled back
51    /// and the statement returns an error.
52    Rollback,
53}
54
55// ============================================================================
56// ON CONFLICT (Upsert) Clause
57// ============================================================================
58
59/// Action to take when a conflict occurs (SQLite upsert clause)
60///
61/// Part of the `ON CONFLICT` clause syntax:
62/// ```sql
63/// INSERT INTO t VALUES (...) ON CONFLICT (cols) DO NOTHING;
64/// INSERT INTO t VALUES (...) ON CONFLICT (cols) DO UPDATE SET col = val WHERE ...;
65/// ```
66///
67/// See: <https://www.sqlite.org/lang_upsert.html>
68#[derive(Debug, Clone, PartialEq)]
69pub enum OnConflictAction {
70    /// DO NOTHING - Skip the conflicting row
71    DoNothing,
72    /// DO UPDATE SET ... [WHERE ...] - Update the conflicting row
73    DoUpdate {
74        /// Assignments for the update (SET col = val, ...)
75        assignments: Vec<Assignment>,
76        /// Optional WHERE clause for the update
77        where_clause: Option<Expression>,
78    },
79}
80
81/// ON CONFLICT clause for INSERT statements (SQLite upsert)
82///
83/// Syntax:
84/// ```sql
85/// INSERT INTO t VALUES (...) ON CONFLICT [(column_list)] DO {NOTHING | UPDATE SET ...};
86/// ```
87///
88/// The conflict target (column list) is optional. When omitted, the conflict
89/// clause applies to any unique constraint violation.
90///
91/// See: <https://www.sqlite.org/lang_upsert.html>
92#[derive(Debug, Clone, PartialEq)]
93pub struct OnConflictClause {
94    /// Optional list of indexed columns to match for conflict detection.
95    /// When None, matches any unique constraint violation.
96    pub conflict_target: Option<Vec<String>>,
97    /// The action to take when a conflict occurs.
98    pub action: OnConflictAction,
99}
100
101/// INSERT statement
102#[derive(Debug, Clone, PartialEq)]
103pub struct InsertStmt {
104    /// Optional WITH clause (CTEs) for INSERT statements
105    /// SQLite supports: WITH cte AS (...) INSERT INTO table SELECT * FROM cte
106    pub with_clause: Option<Vec<CommonTableExpr>>,
107    /// Optional schema name for schema-qualified table references (e.g., schema.table)
108    pub schema_name: Option<String>,
109    /// Whether the schema name was quoted (delimited) in the original SQL.
110    /// Per SQL:1999, quoted identifiers are case-sensitive.
111    pub schema_quoted: bool,
112    pub table_name: String,
113    /// Whether the table name was quoted (delimited) in the original SQL.
114    /// Per SQL:1999, quoted identifiers are case-sensitive.
115    pub table_quoted: bool,
116    pub columns: Vec<String>,
117    pub source: InsertSource,
118    /// Conflict resolution strategy (None = fail on conflict)
119    /// Used for INSERT OR REPLACE/IGNORE/etc. syntax
120    pub conflict_clause: Option<ConflictClause>,
121    /// ON CONFLICT clause (SQLite upsert)
122    /// Used for INSERT ... ON CONFLICT (cols) DO NOTHING/UPDATE syntax
123    pub on_conflict: Option<OnConflictClause>,
124    /// ON DUPLICATE KEY UPDATE clause (MySQL-style upsert)
125    pub on_duplicate_key_update: Option<Vec<Assignment>>,
126}
127
128// ============================================================================
129// UPDATE Statement
130// ============================================================================
131
132/// WHERE clause for positioned UPDATE/DELETE
133#[derive(Debug, Clone, PartialEq)]
134pub enum WhereClause {
135    /// Normal WHERE condition
136    Condition(Expression),
137    /// WHERE CURRENT OF cursor_name (positioned update/delete)
138    CurrentOf(String),
139}
140
141/// UPDATE statement
142#[derive(Debug, Clone, PartialEq)]
143pub struct UpdateStmt {
144    /// Optional WITH clause (CTEs) for UPDATE statements
145    /// SQLite supports: WITH cte AS (...) UPDATE table SET ... WHERE ...
146    pub with_clause: Option<Vec<CommonTableExpr>>,
147    pub table_name: String,
148    /// Whether the table name was quoted (delimited) in the original SQL.
149    /// Per SQL:1999, quoted identifiers are case-sensitive.
150    pub quoted: bool,
151    /// Optional table alias (SQLite extension: UPDATE t1 AS xyz SET ...)
152    pub alias: Option<String>,
153    pub assignments: Vec<Assignment>,
154    /// Optional FROM clause for multi-table UPDATE (SQLite 3.33.0+ / SQL:1999)
155    /// Syntax: UPDATE t1 SET col = t2.val FROM t2 WHERE t1.id = t2.id
156    /// See: <https://www.sqlite.org/lang_update.html#update_from>
157    pub from_clause: Option<Vec<FromClause>>,
158    pub where_clause: Option<WhereClause>,
159    /// Optional conflict resolution clause (SQLite extension)
160    /// Syntax: UPDATE OR REPLACE|IGNORE|ABORT|ROLLBACK|FAIL table SET ...
161    pub conflict_clause: Option<ConflictClause>,
162}
163
164/// Column assignment (column = value)
165#[derive(Debug, Clone, PartialEq)]
166pub struct Assignment {
167    pub column: String,
168    pub value: Expression,
169}
170
171// ============================================================================
172// DELETE Statement
173// ============================================================================
174
175/// DELETE statement
176#[derive(Debug, Clone, PartialEq)]
177pub struct DeleteStmt {
178    /// Optional WITH clause (CTEs) for DELETE statements
179    /// SQLite supports: WITH cte AS (...) DELETE FROM table WHERE ...
180    pub with_clause: Option<Vec<CommonTableExpr>>,
181    /// If true, DELETE FROM ONLY (excludes derived tables in table inheritance)
182    pub only: bool,
183    pub table_name: String,
184    /// Whether the table name was quoted (delimited) in the original SQL.
185    /// Per SQL:1999, quoted identifiers are case-sensitive.
186    pub quoted: bool,
187    pub where_clause: Option<WhereClause>,
188    /// Optional ORDER BY clause (SQLite extension for DELETE)
189    /// When present with LIMIT, deletes rows in the specified order
190    pub order_by: Option<Vec<OrderByItem>>,
191    /// Optional LIMIT clause (SQLite extension for DELETE)
192    /// When used with ORDER BY, limits the number of rows deleted
193    pub limit: Option<Expression>,
194    /// Optional OFFSET clause (SQLite extension for DELETE)
195    /// When used with ORDER BY and LIMIT, skips rows before deleting
196    pub offset: Option<Expression>,
197}