MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / plan_upsert

Function plan_upsert

nodedb-sql/src/planner/dml.rs:171–233  ·  view source on GitHub ↗

Plan an UPSERT statement (pre-processed from `UPSERT INTO` to `INSERT INTO`). Same parsing as INSERT but routes through `engine_rules.plan_upsert()`.

(ins: &ast::Insert, catalog: &dyn SqlCatalog)

Source from the content-addressed store, hash-verified

169///
170/// Same parsing as INSERT but routes through `engine_rules.plan_upsert()`.
171pub fn plan_upsert(ins: &ast::Insert, catalog: &dyn SqlCatalog) -> Result<Vec<SqlPlan>> {
172 let table_name = match &ins.table {
173 ast::TableObject::TableName(name) => normalize_object_name_checked(name)?,
174 ast::TableObject::TableFunction(_) => {
175 return Err(SqlError::Unsupported {
176 detail: "UPSERT INTO table function not supported".into(),
177 });
178 }
179 };
180 let info = catalog
181 .get_collection(DatabaseId::DEFAULT, &table_name)?
182 .ok_or_else(|| SqlError::UnknownTable {
183 name: table_name.clone(),
184 })?;
185
186 let columns: Vec<String> = ins.columns.iter().map(normalize_ident).collect();
187
188 let source = ins.source.as_ref().ok_or_else(|| SqlError::Parse {
189 detail: "UPSERT requires VALUES".into(),
190 })?;
191
192 let rows_ast = match &*source.body {
193 ast::SetExpr::Values(values) => &values.rows,
194 _ => {
195 return Err(SqlError::Unsupported {
196 detail: "UPSERT source must be VALUES".into(),
197 });
198 }
199 };
200
201 // KV: upsert is just a PUT (natural overwrite).
202 if info.engine == EngineType::KeyValue {
203 return build_kv_insert_plan(
204 table_name,
205 &columns,
206 rows_ast,
207 KvInsertIntent::Put,
208 Vec::new(),
209 info.primary_key.as_deref(),
210 );
211 }
212
213 let rows = convert_value_rows(&columns, rows_ast)?;
214 let column_defaults: Vec<(String, String)> = info
215 .columns
216 .iter()
217 .filter_map(|c| c.default.as_ref().map(|d| (c.name.clone(), d.clone())))
218 .collect();
219 let column_schema: Vec<(String, String)> = info
220 .columns
221 .iter()
222 .filter_map(|c| c.raw_type.as_ref().map(|t| (c.name.clone(), t.clone())))
223 .collect();
224 let rules = engine_rules::resolve_engine_rules(info.engine);
225 rules.plan_upsert(engine_rules::UpsertParams {
226 collection: table_name,
227 columns,
228 rows,

Callers 1

plan_statementsFunction · 0.85

Calls 10

build_kv_insert_planFunction · 0.85
convert_value_rowsFunction · 0.85
resolve_engine_rulesFunction · 0.85
collectMethod · 0.80
get_collectionMethod · 0.45
cloneMethod · 0.45
iterMethod · 0.45
as_refMethod · 0.45
plan_upsertMethod · 0.45

Tested by

no test coverage detected