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}