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

Function build_kv_insert_plan

nodedb-sql/src/planner/dml_helpers.rs:308–371  ·  view source on GitHub ↗

Build a `SqlPlan::KvInsert` from a VALUES clause. Shared by plain INSERT, UPSERT, and `INSERT ... ON CONFLICT (key) DO UPDATE` — the three paths differ only in `intent` and `on_conflict_updates`, never in how entries are extracted from the row exprs. `pk_col` is the schema-defined primary-key column name from `CollectionInfo::primary_key`. When supplied, that column is used as the KV key regardl

(
    table_name: String,
    columns: &[String],
    rows_ast: &[Vec<ast::Expr>],
    intent: KvInsertIntent,
    on_conflict_updates: Vec<(String, SqlExpr)>,
    pk_col: Option<&str>,
)

Source from the content-addressed store, hash-verified

306/// the literal name `"key"` when `pk_col` is `None` (legacy / generic
307/// KV collections that use the built-in key/value column convention).
308pub(super) fn build_kv_insert_plan(
309 table_name: String,
310 columns: &[String],
311 rows_ast: &[Vec<ast::Expr>],
312 intent: KvInsertIntent,
313 on_conflict_updates: Vec<(String, SqlExpr)>,
314 pk_col: Option<&str>,
315) -> Result<Vec<SqlPlan>> {
316 let key_col_name = pk_col.unwrap_or("key");
317 let key_idx = columns.iter().position(|c| c == key_col_name);
318 let ttl_idx = columns.iter().position(|c| c == "ttl");
319 // When using a named primary-key column (e.g. `k STRING PRIMARY KEY`), we
320 // store the key bytes in the KV key slot AND also keep the column in the
321 // value map. This allows scan filters on the primary-key column (e.g.
322 // `WHERE k = 'x'`) and projection (e.g. `SELECT k FROM ...`) to work
323 // without teaching the KV scan handler to inspect the raw key bytes.
324 // The only column we exclude from the value map is the built-in `"key"`
325 // sentinel (used by raw key/value KV collections) and `"ttl"`.
326 let exclude_from_value: std::collections::HashSet<usize> = {
327 let mut s = std::collections::HashSet::new();
328 // Exclude the raw "key" sentinel column (not a named PK column).
329 if key_col_name == "key"
330 && let Some(idx) = key_idx
331 {
332 s.insert(idx);
333 }
334 if let Some(idx) = ttl_idx {
335 s.insert(idx);
336 }
337 s
338 };
339 let mut entries = Vec::with_capacity(rows_ast.len());
340 let mut ttl_secs: u64 = 0;
341 for row_exprs in rows_ast {
342 let key_val = match key_idx {
343 Some(idx) => expr_to_sql_value(&row_exprs[idx])?,
344 None => SqlValue::String(String::new()),
345 };
346 if let Some(idx) = ttl_idx {
347 match expr_to_sql_value(&row_exprs[idx]) {
348 Ok(SqlValue::Int(n)) => ttl_secs = n.max(0) as u64,
349 Ok(SqlValue::Float(f)) => ttl_secs = f.max(0.0) as u64,
350 _ => {}
351 }
352 }
353 let value_cols: Vec<(String, SqlValue)> = columns
354 .iter()
355 .enumerate()
356 .filter(|(i, _)| !exclude_from_value.contains(i))
357 .map(|(i, col)| {
358 let val = expr_to_sql_value(&row_exprs[i])?;
359 Ok((col.clone(), val))
360 })
361 .collect::<Result<Vec<_>>>()?;
362 entries.push((key_val, value_cols));
363 }
364 Ok(vec![SqlPlan::KvInsert {
365 collection: table_name,

Callers 3

plan_insertFunction · 0.85
plan_upsertFunction · 0.85

Calls 7

expr_to_sql_valueFunction · 0.85
iterMethod · 0.45
insertMethod · 0.45
lenMethod · 0.45
containsMethod · 0.45
cloneMethod · 0.45
pushMethod · 0.45

Tested by

no test coverage detected