1use crate::db::internal_bytes;
26use crate::error::{KitError, Result};
27use crate::internal::{cols, iso_now, ROW_GUARDS, UNIQUE_KEYS};
28use crate::query::{project_distinct, run_aggregate, run_join, run_select, ExecCtx, JoinRow};
29use crate::schema::{core_row_to_json, json_to_core, pk_to_map, row_to_core_cells, Row};
30use mongreldb_core::memtable::{Row as CoreRow, Value as CoreValue};
31use mongreldb_core::query::Condition;
32use mongreldb_core::RowId;
33use mongreldb_core::UpsertAction;
34use mongreldb_core::{NativeAgg, NativeAggResult};
35use mongreldb_kit_core::keys::{
36 decode_pk, encode_pk, encode_row_guard_key, encode_unique_key, KeyComponent, KIT_KEY_VERSION,
37};
38use mongreldb_kit_core::planner::{plan_delete, DeletePlan};
39use mongreldb_kit_core::query::{
40 AggFunc, AggregateQuery, Cte, Expr, JoinQuery, OnConflict, Query, Select,
41};
42use mongreldb_kit_core::schema::{
43 Column, ColumnType, DefaultKind, ForeignKey, Table as KitTable, UniqueConstraint,
44};
45use serde_json::{Map, Value};
46use std::cell::RefCell;
47use std::collections::{HashMap, HashSet};
48
49pub struct Transaction<'a> {
51 db: &'a crate::db::Database,
52 core: mongreldb_core::txn::Transaction<'a>,
53 staged: Vec<StagedOp>,
54 staged_unique: Vec<StagedUnique>,
56 touched_guards: HashSet<String>,
58 next_temp_id: u64,
59}
60
61#[derive(Debug, Clone)]
62enum StagedOp {
63 Insert {
64 table: String,
65 values: Map<String, Value>,
66 },
67 Update {
68 table: String,
69 old_pk: String,
70 row_id: u64,
71 values: Map<String, Value>,
72 },
73 Delete {
76 table: String,
77 pk: String,
78 },
79 Truncate {
80 table: String,
81 },
82}
83
84#[derive(Debug, Clone)]
85struct StagedUnique {
86 encoded_key: String,
87 owner_table: String,
88 owner_pk: String,
89}
90
91impl<'a> Transaction<'a> {
92 pub(crate) fn new(
93 db: &'a crate::db::Database,
94 core: mongreldb_core::txn::Transaction<'a>,
95 ) -> Self {
96 Self {
97 db,
98 core,
99 staged: Vec::new(),
100 staged_unique: Vec::new(),
101 touched_guards: HashSet::new(),
102 next_temp_id: 1,
103 }
104 }
105
106 pub fn insert(&mut self, table: &str, row: Map<String, Value>) -> Result<Row> {
108 let t = self.require_table(table)?.clone();
109 self.do_insert(table, &t, row, None)
110 }
111
112 pub fn insert_returning(
113 &mut self,
114 table: &str,
115 row: Map<String, Value>,
116 returning: Vec<String>,
117 ) -> Result<Value> {
118 let inserted = self.insert(table, row)?;
119 project_returning(&inserted, &returning)
120 }
121
122 pub fn insert_many(&mut self, table: &str, rows: Vec<Map<String, Value>>) -> Result<Vec<Row>> {
131 let t = self.require_table(table)?.clone();
132 let mut pk_seen: Option<HashSet<String>> = if t.primary_key.len() == 1 {
135 let mut set = HashSet::new();
136 for r in self.snapshot_rows(table)? {
137 set.insert(encoded_pk_for(&t, &r.values));
138 }
139 Some(set)
140 } else {
141 None
142 };
143 let mut out = Vec::with_capacity(rows.len());
144 for row in rows {
145 out.push(self.do_insert(table, &t, row, pk_seen.as_mut())?);
146 }
147 Ok(out)
148 }
149
150 fn do_insert(
155 &mut self,
156 table: &str,
157 t: &KitTable,
158 mut row: Map<String, Value>,
159 pk_seen: Option<&mut HashSet<String>>,
160 ) -> Result<Row> {
161 let pk_explicit = pk_is_explicit(t, &row);
165
166 self.apply_defaults(&mut row, t)?;
167 for col in &t.columns {
170 row.entry(col.name.clone()).or_insert(Value::Null);
171 }
172 mongreldb_kit_core::validation::validate_row(t, &row)?;
173
174 self.check_unique_constraints(t, &row, None)?;
176 self.check_pk(t, &row, pk_explicit, pk_seen)?;
177 self.check_foreign_keys(t, &row)?;
178
179 self.reserve_unique_guards(t, &row, None)?;
181 self.reserve_pk_guard(t, &row, pk_explicit)?;
182 self.touch_foreign_key_guards(t, &row)?;
183
184 let cells = row_to_core_cells(&row, t)?;
185 self.core.put(table, cells).map_err(KitError::from)?;
186 let temp_id = self.alloc_temp_id();
187 self.staged.push(StagedOp::Insert {
188 table: table.to_string(),
189 values: row.clone(),
190 });
191 Ok(Row {
192 row_id: temp_id,
193 values: row,
194 })
195 }
196
197 pub fn update(&mut self, table: &str, pk: &Value, patch: Map<String, Value>) -> Result<Row> {
199 let t = self.require_table(table)?.clone();
200 let pk_map = pk_to_map(pk, &t)?;
201 let old_row = self
202 .get_by_pk_internal(table, &pk_map)?
203 .ok_or_else(|| KitError::Integrity(format!("row not found in {table}")))?;
204
205 let patch_keys: HashSet<String> = patch.keys().cloned().collect();
206 let mut values = old_row.values.clone();
207 for (k, v) in patch {
208 if t.column(&k).is_some() {
209 values.insert(k, v);
210 }
211 }
212 self.apply_update_defaults(&mut values, &patch_keys, &t);
213 mongreldb_kit_core::validation::validate_row(&t, &values)?;
214 self.check_unique_constraints(&t, &values, Some(&old_row.values))?;
215 self.check_foreign_keys(&t, &values)?;
216
217 self.reserve_unique_guards(&t, &values, Some(&old_row.values))?;
219 self.touch_foreign_key_guards(&t, &values)?;
220
221 let cells = row_to_core_cells(&values, &t)?;
222 self.core
223 .delete(table, RowId(old_row.row_id))
224 .map_err(KitError::from)?;
225 self.core.put(table, cells).map_err(KitError::from)?;
226 let temp_id = self.alloc_temp_id();
227 self.staged.push(StagedOp::Update {
228 table: table.to_string(),
229 old_pk: encoded_pk_for(&t, &old_row.values),
230 row_id: old_row.row_id,
231 values: values.clone(),
232 });
233 Ok(Row {
234 row_id: temp_id,
235 values,
236 })
237 }
238
239 fn delete_row(&mut self, table: &str, row: &Row) -> Result<u64> {
243 let t = self.require_table(table)?.clone();
244 let (plan, row_cache) = self.plan_delete(table, row)?;
245 if !plan.restricted.is_empty() {
246 let msg = format!(
247 "delete restricted by {}",
248 plan.restricted
249 .iter()
250 .map(|r| format!("{}.{}", r.table, r.constraint))
251 .collect::<Vec<_>>()
252 .join(", ")
253 );
254 return Err(KitError::Restrict(msg));
255 }
256
257 for set_null in &plan.set_null {
261 let key = format!("{}:{}", set_null.table, set_null.pk);
262 if let Some(child_row) = row_cache.get(&key).cloned() {
263 self.apply_set_null(set_null, &child_row)?;
264 }
265 }
266 for del in &plan.delete {
267 if del.table == table {
268 continue; }
270 let child_table = self.require_table(&del.table)?.clone();
271 let key = format!("{}:{}", del.table, del.pk);
272 if let Some(child_row) = row_cache.get(&key) {
273 let row_id = child_row.row_id;
274 let values = child_row.values.clone();
275 self.delete_guards_for(&child_table, &values)?;
276 self.core
277 .delete(&del.table, RowId(row_id))
278 .map_err(KitError::from)?;
279 self.staged.push(StagedOp::Delete {
280 table: del.table.clone(),
281 pk: del.pk.clone(),
282 });
283 }
284 }
285
286 self.delete_guards_for(&t, &row.values)?;
289 self.touch_row_guard(table, &pk_components(&t, &row.values))?;
290 self.staged.push(StagedOp::Delete {
291 table: table.to_string(),
292 pk: encoded_pk_for(&t, &row.values),
293 });
294 Ok(row.row_id)
295 }
296
297 pub fn delete(&mut self, table: &str, pk: &Value) -> Result<()> {
299 let t = self.require_table(table)?.clone();
300 let pk_map = pk_to_map(pk, &t)?;
301 let row = self
302 .get_by_pk_internal(table, &pk_map)?
303 .ok_or_else(|| KitError::Integrity(format!("row not found in {table}")))?;
304 let row_id = self.delete_row(table, &row)?;
305 self.core
306 .delete(table, RowId(row_id))
307 .map_err(KitError::from)?;
308 Ok(())
309 }
310
311 pub fn truncate(&mut self, table: &str) -> Result<()> {
312 let t = self.require_table(table)?.clone();
313 let has_data_writes = self.staged.iter().any(|op| match op {
316 StagedOp::Insert { table: t, .. }
317 | StagedOp::Update { table: t, .. }
318 | StagedOp::Delete { table: t, .. } => t == table,
319 StagedOp::Truncate { .. } => false,
320 });
321 if has_data_writes {
322 return Err(KitError::Validation(format!(
323 "truncate cannot be combined with prior writes on {table}"
324 )));
325 }
326 if self.db.schema.tables.iter().any(|other| {
327 other.name != t.name
328 && other
329 .foreign_keys
330 .iter()
331 .any(|fk| fk.references_table == t.name)
332 }) {
333 return Err(KitError::Restrict(format!(
334 "table {} is referenced by a foreign key",
335 t.name
336 )));
337 }
338 self.delete_all_guards_for_table(&t)?;
339 self.core.truncate(table).map_err(KitError::from)?;
340 self.staged.push(StagedOp::Truncate { table: t.name });
341 Ok(())
342 }
343
344 pub fn upsert(
345 &mut self,
346 table: &str,
347 row: Map<String, Value>,
348 on_conflict: OnConflict,
349 returning: Vec<String>,
350 ) -> Result<Value> {
351 let t = self.require_table(table)?.clone();
352 let mut values = row;
353 self.apply_defaults(&mut values, &t)?;
354 for col in &t.columns {
355 values.entry(col.name.clone()).or_insert(Value::Null);
356 }
357 mongreldb_kit_core::validation::validate_row(&t, &values)?;
358 let pk_map = pk_values_map(&t, &values);
359 let existing = self.get_by_pk_internal(table, &pk_map)?;
360 match (existing, on_conflict) {
361 (Some(old), OnConflict::DoNothing) => project_returning(&old, &returning),
362 (Some(old), OnConflict::DoUpdate(patch)) => {
363 let mut merged = values.clone();
364 let mut patch_keys = HashSet::new();
365 for (k, v) in patch {
366 if t.column(&k).is_some() {
367 merged.insert(k.clone(), v);
368 patch_keys.insert(k);
369 }
370 }
371 self.apply_update_defaults(&mut merged, &patch_keys, &t);
372 mongreldb_kit_core::validation::validate_row(&t, &merged)?;
373 self.check_unique_constraints(&t, &merged, Some(&old.values))?;
374 self.check_foreign_keys(&t, &merged)?;
375 self.reserve_unique_guards(&t, &merged, Some(&old.values))?;
376 self.touch_foreign_key_guards(&t, &merged)?;
377
378 let insert_cells = row_to_core_cells(&merged, &t)?;
379 let mut patch_values = Map::new();
380 for k in &patch_keys {
381 patch_values.insert(k.clone(), merged.get(k).cloned().unwrap_or(Value::Null));
382 }
383 let update_cells = patch_to_core_cells(&patch_values, &t)?;
384
385 self.core
386 .upsert(table, insert_cells, UpsertAction::DoUpdate(update_cells))
387 .map_err(KitError::from)?;
388 self.staged.push(StagedOp::Update {
389 table: table.to_string(),
390 old_pk: encoded_pk_for(&t, &old.values),
391 row_id: old.row_id,
392 values: merged.clone(),
393 });
394 project_returning(
395 &Row {
396 row_id: old.row_id,
397 values: merged,
398 },
399 &returning,
400 )
401 }
402 (None, on_conflict) => {
403 self.check_unique_constraints(&t, &values, None)?;
404 self.check_foreign_keys(&t, &values)?;
405 self.reserve_unique_guards(&t, &values, None)?;
406 let pk_explicit = pk_is_explicit(&t, &values);
407 self.reserve_pk_guard(&t, &values, pk_explicit)?;
408 self.touch_foreign_key_guards(&t, &values)?;
409 let cells = row_to_core_cells(&values, &t)?;
410 let action = match on_conflict {
411 OnConflict::DoNothing => UpsertAction::DoNothing,
412 OnConflict::DoUpdate(patch) => {
413 UpsertAction::DoUpdate(patch_to_core_cells(&patch, &t)?)
414 }
415 };
416 self.core
417 .upsert(table, cells, action)
418 .map_err(KitError::from)?;
419 self.staged.push(StagedOp::Insert {
420 table: table.to_string(),
421 values: values.clone(),
422 });
423 project_returning(&Row { row_id: 0, values }, &returning)
424 }
425 }
426 }
427
428 pub fn update_where(
429 &mut self,
430 table: &str,
431 filter: Option<Expr>,
432 patch: Map<String, Value>,
433 returning: Vec<String>,
434 ) -> Result<Vec<Value>> {
435 let t = self.require_table(table)?.clone();
436 let rows = self.select(&Query::Select(select_all(table, filter)))?;
437 let mut updates = Vec::with_capacity(rows.len());
438 let mut out = Vec::with_capacity(rows.len());
439 let patch_keys: HashSet<String> = patch.keys().cloned().collect();
440 for row in rows {
441 let mut values = row.values.clone();
442 for (k, v) in &patch {
443 if t.column(k).is_some() {
444 values.insert(k.clone(), v.clone());
445 }
446 }
447 self.apply_update_defaults(&mut values, &patch_keys, &t);
448 mongreldb_kit_core::validation::validate_row(&t, &values)?;
449 self.check_unique_constraints(&t, &values, Some(&row.values))?;
450 self.check_foreign_keys(&t, &values)?;
451 self.reserve_unique_guards(&t, &values, Some(&row.values))?;
452 self.touch_foreign_key_guards(&t, &values)?;
453
454 let cells = row_to_core_cells(&values, &t)?;
455 updates.push((RowId(row.row_id), cells));
456 self.staged.push(StagedOp::Update {
457 table: table.to_string(),
458 old_pk: encoded_pk_for(&t, &row.values),
459 row_id: row.row_id,
460 values: values.clone(),
461 });
462 out.push(project_returning(
463 &Row {
464 row_id: row.row_id,
465 values,
466 },
467 &returning,
468 )?);
469 }
470 if !updates.is_empty() {
471 self.core
472 .update_many(table, updates)
473 .map_err(KitError::from)?;
474 }
475 Ok(out)
476 }
477
478 pub fn delete_where(
479 &mut self,
480 table: &str,
481 filter: Option<Expr>,
482 returning: Vec<String>,
483 ) -> Result<Vec<Value>> {
484 self.require_table(table)?;
485 let rows = self.select(&Query::Select(select_all(table, filter)))?;
486 let mut out = Vec::with_capacity(rows.len());
487 let mut ids = Vec::with_capacity(rows.len());
488 for row in rows {
489 out.push(project_returning(&row, &returning)?);
490 ids.push(self.delete_row(table, &row)?);
491 }
492 if !ids.is_empty() {
493 self.core
494 .delete_many(table, ids.into_iter().map(RowId).collect())
495 .map_err(KitError::from)?;
496 }
497 Ok(out)
498 }
499
500 pub fn get_by_pk(&self, table: &str, pk: &Value) -> Result<Option<Row>> {
502 let t = self.require_table(table)?;
503 let pk_map = pk_to_map(pk, t)?;
504 self.get_by_pk_internal(table, &pk_map)
505 }
506
507 pub fn select(&self, query: &Query) -> Result<Vec<Row>> {
511 let select = match query {
512 Query::Select(s) => s,
513 _ => return Err(KitError::Validation("only SELECT supported".into())),
514 };
515 let ctx = self.exec_ctx();
516 run_select(&ctx, select)
517 }
518
519 pub fn select_distinct(&self, query: &Query) -> Result<Vec<Row>> {
523 let select = match query {
524 Query::Select(s) => s,
525 _ => return Err(KitError::Validation("only SELECT supported".into())),
526 };
527 let ctx = self.exec_ctx();
528 let rows = run_select(&ctx, select)?;
529 Ok(project_distinct(select, rows))
530 }
531
532 pub fn select_with(&self, ctes: &[Cte], body: &Select) -> Result<Vec<Row>> {
535 let mut ctx = self.exec_ctx();
536 for cte in ctes {
537 let rows = run_select(&ctx, &cte.query)?;
538 ctx.add_cte(cte.name.clone(), rows);
539 }
540 run_select(&ctx, body)
541 }
542
543 pub fn aggregate(&self, query: &AggregateQuery) -> Result<Vec<Row>> {
547 if let Some(rows) = self.try_native_aggregate(query)? {
548 return Ok(rows);
549 }
550 let ctx = self.exec_ctx();
551 run_aggregate(&ctx, query)
552 }
553
554 fn try_native_aggregate(&self, query: &AggregateQuery) -> Result<Option<Vec<Row>>> {
564 if !query.group_by.is_empty() || query.having.is_some() || query.aggregates.len() != 1 {
565 return Ok(None);
566 }
567 let agg = &query.aggregates[0];
568 if self.has_staged_for(&query.table) {
569 return Ok(None); }
571
572 if agg.distinct {
577 if !matches!(agg.func, AggFunc::Count) || query.filter.is_some() {
578 return Ok(None);
579 }
580 let Some(col_name) = &agg.column else {
581 return Ok(None);
582 };
583 let t = self.require_table(&query.table)?;
584 let Some(col) = t.columns.iter().find(|c| &c.name == col_name) else {
585 return Ok(None);
586 };
587 let Some(n) = self.db.count_distinct_core_at(
588 &query.table,
589 col.id as u16,
590 self.core.read_snapshot(),
591 )?
592 else {
593 return Ok(None);
594 };
595 let mut values = Map::new();
596 values.insert(agg.alias.clone(), Value::Number((n as i64).into()));
597 return Ok(Some(vec![Row { row_id: 0, values }]));
598 }
599
600 let conditions: Vec<Condition> = match &query.filter {
601 None => Vec::new(),
602 Some(filter) => {
603 let t = self.require_table(&query.table)?;
604 match crate::pushdown::translate_predicate(t, filter) {
605 Some(plan) if plan.can_push() && plan.fully_translated => plan.conditions,
607 _ => return Ok(None),
608 }
609 }
610 };
611 let snapshot = self.core.read_snapshot();
612
613 let value: Value = match (agg.func, &agg.column) {
614 (AggFunc::Count, None) => {
616 let Some(n) = self
617 .db
618 .count_core_rows_at(&query.table, &conditions, snapshot)?
619 else {
620 return Ok(None);
621 };
622 Value::Number((n as i64).into())
623 }
624 (func, Some(col_name)) => {
627 let t = self.require_table(&query.table)?;
628 let Some(col) = t.columns.iter().find(|c| &c.name == col_name) else {
629 return Ok(None);
630 };
631 let native = match func {
632 AggFunc::Count => NativeAgg::Count,
633 AggFunc::Sum => NativeAgg::Sum,
634 AggFunc::Min => NativeAgg::Min,
635 AggFunc::Max => NativeAgg::Max,
636 AggFunc::Avg => NativeAgg::Avg,
637 };
638 let Some(result) = self.db.aggregate_core_at(
639 &query.table,
640 Some(col.id as u16),
641 &conditions,
642 native,
643 snapshot,
644 )?
645 else {
646 return Ok(None);
647 };
648 match result {
651 NativeAggResult::Count(n) => Value::Number((n as i64).into()),
652 NativeAggResult::Int(x) => Value::Number(x.into()),
653 NativeAggResult::Float(f) => serde_json::Number::from_f64(f)
654 .map(Value::Number)
655 .unwrap_or(Value::Null),
656 NativeAggResult::Null => Value::Null,
657 }
658 }
659 _ => return Ok(None),
661 };
662
663 let mut values = Map::new();
664 values.insert(agg.alias.clone(), value);
665 Ok(Some(vec![Row { row_id: 0, values }]))
666 }
667
668 pub fn join(&self, query: &JoinQuery) -> Result<Vec<JoinRow>> {
671 let ctx = self.exec_ctx();
672 run_join(&ctx, query)
673 }
674
675 pub fn ann_search(
680 &self,
681 table: &str,
682 column: &str,
683 query: Vec<f32>,
684 k: usize,
685 ) -> Result<Vec<Row>> {
686 let t = self.require_table(table)?;
687 let col = t
688 .column(column)
689 .ok_or_else(|| KitError::Validation(format!("unknown column \"{column}\"")))?;
690 let cond = Condition::Ann {
691 column_id: col.id as u16,
692 query,
693 k,
694 };
695 self.snapshot_rows_pushed(table, &[cond])
696 }
697
698 pub fn sparse_match(
703 &self,
704 table: &str,
705 column: &str,
706 query: Vec<(u32, f32)>,
707 k: usize,
708 ) -> Result<Vec<Row>> {
709 let t = self.require_table(table)?;
710 let col = t
711 .column(column)
712 .ok_or_else(|| KitError::Validation(format!("unknown column \"{column}\"")))?;
713 let cond = Condition::SparseMatch {
714 column_id: col.id as u16,
715 query,
716 k,
717 };
718 self.snapshot_rows_pushed(table, &[cond])
719 }
720
721 pub fn execute(&mut self, query: &Query) -> Result<Vec<Value>> {
722 match query {
723 Query::Select(_) => Err(KitError::Validation("use select() for SELECT".into())),
724 Query::Insert(insert) => Ok(vec![self.insert_returning(
725 &insert.table,
726 insert.values.clone(),
727 insert.returning.clone(),
728 )?]),
729 Query::Upsert(upsert) => Ok(vec![self.upsert(
730 &upsert.table,
731 upsert.values.clone(),
732 upsert.on_conflict.clone(),
733 upsert.returning.clone(),
734 )?]),
735 Query::Update(update) => {
736 if update.pk.is_some() && update.filter.is_some() {
737 return Err(KitError::Validation(
738 "update cannot specify both pk and filter".into(),
739 ));
740 }
741 if let Some(pk) = &update.pk {
742 let row = self.update(&update.table, pk, update.set.clone())?;
743 Ok(vec![project_returning(&row, &update.returning)?])
744 } else if let Some(filter) = &update.filter {
745 self.update_where(
746 &update.table,
747 Some(filter.clone()),
748 update.set.clone(),
749 update.returning.clone(),
750 )
751 } else {
752 Err(KitError::Validation(
753 "update requires either a pk or a filter".into(),
754 ))
755 }
756 }
757 Query::Delete(delete) => {
758 if delete.pk.is_some() && delete.filter.is_some() {
759 return Err(KitError::Validation(
760 "delete cannot specify both pk and filter".into(),
761 ));
762 }
763 if let Some(pk) = &delete.pk {
764 let t = self.require_table(&delete.table)?;
765 let pk_map = pk_to_map(pk, t)?;
766 let projected = match self.get_by_pk_internal(&delete.table, &pk_map)? {
767 Some(row) => project_returning(&row, &delete.returning)?,
768 None => {
769 self.delete(&delete.table, pk)?;
771 unreachable!("delete returned Ok for a missing row")
772 }
773 };
774 self.delete(&delete.table, pk)?;
775 Ok(vec![projected])
776 } else if let Some(filter) = &delete.filter {
777 self.delete_where(
778 &delete.table,
779 Some(filter.clone()),
780 delete.returning.clone(),
781 )
782 } else {
783 Err(KitError::Validation(
784 "delete requires either a pk or a filter".into(),
785 ))
786 }
787 }
788 Query::Aggregate(_) | Query::Join(_) => Err(KitError::Validation(
789 "aggregate/join are not mutating statements".into(),
790 )),
791 }
792 }
793
794 fn exec_ctx(&self) -> ExecCtx<'_> {
798 ExecCtx::new(
799 Some(&self.db.schema),
800 |name: &str, conds: Option<&[Condition]>| match conds {
801 Some(c) if !c.is_empty() => self.snapshot_rows_pushed(name, c),
802 _ => self.snapshot_rows(name),
803 },
804 )
805 }
806
807 pub fn commit(self) -> Result<()> {
809 self.core.commit().map_err(KitError::from).map(|_| ())
810 }
811
812 pub fn rollback(self) {
814 self.core.rollback();
815 }
816
817 fn alloc_temp_id(&mut self) -> u64 {
820 let id = self.next_temp_id;
821 self.next_temp_id += 1;
822 id
823 }
824
825 fn require_table(&self, name: &str) -> Result<&KitTable> {
826 self.db
827 .table(name)
828 .ok_or_else(|| KitError::Integrity(format!("table {name} not found")))
829 }
830
831 pub fn all_rows(&self, table: &str) -> Result<Vec<Row>> {
833 self.snapshot_rows(table)
834 }
835
836 fn snapshot_rows(&self, table: &str) -> Result<Vec<Row>> {
837 let t = self.require_table(table)?;
838 let core_rows = self
839 .db
840 .visible_core_rows_at(table, self.core.read_snapshot())?;
841 let mut rows = core_rows
842 .into_iter()
843 .map(|r| core_row_to_json(&r, t))
844 .collect::<Result<Vec<_>>>()?;
845 self.replay_staged_rows(t, &mut rows);
846 Ok(rows)
847 }
848
849 fn snapshot_rows_pushed(&self, table: &str, conditions: &[Condition]) -> Result<Vec<Row>> {
853 let t = self.require_table(table)?;
854 if self.has_staged_for(table) {
855 return Ok(self
856 .snapshot_rows(table)?
857 .into_iter()
858 .filter(|r| row_matches_conditions(t, r, conditions))
859 .collect());
860 }
861 let core_rows = self
862 .db
863 .query_core_rows_at(table, conditions, self.core.read_snapshot())?;
864 core_rows
865 .into_iter()
866 .map(|r| core_row_to_json(&r, t))
867 .collect()
868 }
869
870 fn get_by_pk_internal(&self, table: &str, pk_map: &Map<String, Value>) -> Result<Option<Row>> {
871 let t = self.require_table(table)?;
872 if self.has_staged_for(table) {
873 let rows = self.snapshot_rows(table)?;
874 return Ok(rows.into_iter().find(|r| pk_matches(&r.values, pk_map, t)));
875 }
876 if let Some(conditions) = crate::pushdown::pk_conditions(t, pk_map) {
879 let core_rows =
880 self.db
881 .query_core_rows_at(table, &conditions, self.core.read_snapshot())?;
882 return Ok(core_rows
883 .into_iter()
884 .filter_map(|r| core_row_to_json(&r, t).ok())
885 .find(|r| pk_matches(&r.values, pk_map, t)));
886 }
887 let rows = self.snapshot_rows(table)?;
888 Ok(rows.into_iter().find(|r| pk_matches(&r.values, pk_map, t)))
889 }
890
891 fn internal_rows(&self, table: &str) -> Result<Vec<CoreRow>> {
892 self.db
893 .visible_core_rows_at(table, self.core.read_snapshot())
894 }
895
896 fn check_unique_constraints(
901 &self,
902 table: &KitTable,
903 values: &Map<String, Value>,
904 old_values: Option<&Map<String, Value>>,
905 ) -> Result<()> {
906 let owner_pk = encoded_pk_for(table, values);
907 let committed = self.internal_rows(UNIQUE_KEYS)?;
908 for uq in &table.unique_constraints {
909 let Some(key) = unique_key(table, uq, values) else {
910 continue;
911 };
912 if let Some(old) = old_values {
914 if unique_key(table, uq, old).as_deref() == Some(key.as_str()) {
915 continue;
916 }
917 }
918 self.assert_key_free(&committed, table, uq, &key, &owner_pk)?;
919 }
920 Ok(())
921 }
922
923 fn assert_key_free(
924 &self,
925 committed: &[CoreRow],
926 table: &KitTable,
927 uq: &UniqueConstraint,
928 key: &str,
929 owner_pk: &str,
930 ) -> Result<()> {
931 for guard in committed {
932 if internal_bytes(guard, cols::UQ_ENCODED).as_deref() == Some(key) {
933 let g_table = internal_bytes(guard, cols::UQ_OWNER_TABLE).unwrap_or_default();
934 let g_pk = internal_bytes(guard, cols::UQ_OWNER_PK).unwrap_or_default();
935 if g_table != table.name || g_pk != owner_pk {
936 return Err(KitError::Duplicate(format!(
937 "unique constraint {} on {}",
938 uq.name, table.name
939 )));
940 }
941 }
942 }
943 for staged in &self.staged_unique {
944 if staged.encoded_key == key
945 && (staged.owner_table != table.name || staged.owner_pk != owner_pk)
946 {
947 return Err(KitError::Duplicate(format!(
948 "unique constraint {} on {}",
949 uq.name, table.name
950 )));
951 }
952 }
953 Ok(())
954 }
955
956 fn reserve_unique_guards(
959 &mut self,
960 table: &KitTable,
961 values: &Map<String, Value>,
962 old_values: Option<&Map<String, Value>>,
963 ) -> Result<()> {
964 let owner_pk = encoded_pk_for(table, values);
965 for uq in &table.unique_constraints {
966 let new_key = unique_key(table, uq, values);
967 let old_key = old_values.and_then(|old| unique_key(table, uq, old));
968 if new_key == old_key {
969 continue;
970 }
971 if let Some(key) = &new_key {
972 self.put_unique_guard(&uq.name, key, &table.name, &owner_pk)?;
973 }
974 if let Some(key) = &old_key {
975 self.delete_unique_guard(key)?;
976 }
977 }
978 Ok(())
979 }
980
981 fn put_unique_guard(
982 &mut self,
983 constraint: &str,
984 encoded_key: &str,
985 owner_table: &str,
986 owner_pk: &str,
987 ) -> Result<()> {
988 let now = iso_now();
989 self.core
990 .put(
991 UNIQUE_KEYS,
992 vec![
993 (cols::UQ_ENCODED, CoreValue::Bytes(encoded_key.into())),
994 (cols::UQ_CONSTRAINT, CoreValue::Bytes(constraint.into())),
995 (cols::UQ_OWNER_TABLE, CoreValue::Bytes(owner_table.into())),
996 (cols::UQ_OWNER_PK, CoreValue::Bytes(owner_pk.into())),
997 (cols::UQ_CREATED, CoreValue::Bytes(now.into_bytes())),
998 ],
999 )
1000 .map_err(KitError::from)?;
1001 self.staged_unique.push(StagedUnique {
1002 encoded_key: encoded_key.to_string(),
1003 owner_table: owner_table.to_string(),
1004 owner_pk: owner_pk.to_string(),
1005 });
1006 Ok(())
1007 }
1008
1009 fn delete_unique_guard(&mut self, encoded_key: &str) -> Result<()> {
1010 let committed = self.internal_rows(UNIQUE_KEYS)?;
1011 for guard in &committed {
1012 if internal_bytes(guard, cols::UQ_ENCODED).as_deref() == Some(encoded_key) {
1013 self.core
1014 .delete(UNIQUE_KEYS, guard.row_id)
1015 .map_err(KitError::from)?;
1016 }
1017 }
1018 self.staged_unique.retain(|s| s.encoded_key != encoded_key);
1019 Ok(())
1020 }
1021
1022 fn delete_unique_guards_for_owner(&mut self, table: &KitTable, owner_pk: &str) -> Result<()> {
1024 let constraint_names: HashSet<&str> = table
1025 .unique_constraints
1026 .iter()
1027 .map(|u| u.name.as_str())
1028 .collect();
1029 let committed = self.internal_rows(UNIQUE_KEYS)?;
1030 for guard in &committed {
1031 let g_table = internal_bytes(guard, cols::UQ_OWNER_TABLE).unwrap_or_default();
1032 let g_pk = internal_bytes(guard, cols::UQ_OWNER_PK).unwrap_or_default();
1033 let g_constraint = internal_bytes(guard, cols::UQ_CONSTRAINT).unwrap_or_default();
1034 if g_table == table.name
1035 && g_pk == owner_pk
1036 && (constraint_names.contains(g_constraint.as_str())
1037 || g_constraint == pk_guard_constraint(table))
1038 {
1039 self.core
1040 .delete(UNIQUE_KEYS, guard.row_id)
1041 .map_err(KitError::from)?;
1042 }
1043 }
1044 let owner_pk = owner_pk.to_string();
1045 let name = table.name.clone();
1046 self.staged_unique
1047 .retain(|s| !(s.owner_table == name && s.owner_pk == owner_pk));
1048 Ok(())
1049 }
1050
1051 fn check_pk(
1061 &self,
1062 table: &KitTable,
1063 values: &Map<String, Value>,
1064 pk_explicit: bool,
1065 pk_seen: Option<&mut HashSet<String>>,
1066 ) -> Result<()> {
1067 if table.primary_key.is_empty() || !pk_explicit {
1069 return Ok(());
1070 }
1071
1072 if table.primary_key.len() == 1 {
1073 let duplicate = match pk_seen {
1078 Some(seen) => {
1079 let key = encoded_pk_for(table, values);
1080 if seen.contains(&key) {
1081 true
1082 } else {
1083 seen.insert(key);
1084 false
1085 }
1086 }
1087 None => {
1088 self.parent_exists(&table.name, values)?
1089 || self.staged_row_exists(table, values)
1090 }
1091 };
1092 if duplicate {
1093 return Err(KitError::Duplicate(format!(
1094 "primary key {} on {}",
1095 encoded_pk_for(table, values),
1096 table.name
1097 )));
1098 }
1099 return Ok(());
1100 }
1101
1102 let key = pk_guard_key(table, values);
1105 let owner_pk = encoded_pk_for(table, values);
1106 let committed = self.internal_rows(UNIQUE_KEYS)?;
1107 for guard in &committed {
1108 if internal_bytes(guard, cols::UQ_ENCODED).as_deref() == Some(key.as_str()) {
1109 return Err(KitError::Duplicate(format!(
1110 "primary key {} on {}",
1111 owner_pk, table.name
1112 )));
1113 }
1114 }
1115 for staged in &self.staged_unique {
1116 if staged.encoded_key == key {
1117 return Err(KitError::Duplicate(format!(
1118 "primary key {} on {}",
1119 owner_pk, table.name
1120 )));
1121 }
1122 }
1123 Ok(())
1124 }
1125
1126 fn reserve_pk_guard(
1127 &mut self,
1128 table: &KitTable,
1129 values: &Map<String, Value>,
1130 pk_explicit: bool,
1131 ) -> Result<()> {
1132 if table.primary_key.len() < 2 || !pk_explicit {
1135 return Ok(());
1136 }
1137 let key = pk_guard_key(table, values);
1138 let owner_pk = encoded_pk_for(table, values);
1139 let constraint = pk_guard_constraint(table);
1140 self.put_unique_guard(&constraint, &key, &table.name, &owner_pk)
1141 }
1142
1143 fn check_foreign_keys(&self, table: &KitTable, values: &Map<String, Value>) -> Result<()> {
1146 for fk in &table.foreign_keys {
1147 if fk_values_null(fk, values) {
1148 continue;
1149 }
1150 let parent = self.require_table(&fk.references_table)?;
1151 let parent_pk = parent_pk_value(values, fk, parent)?;
1152 let parent_pk_map = pk_to_map(&parent_pk, parent)?;
1153 if self.parent_exists(&fk.references_table, &parent_pk_map)?
1154 || self.staged_row_exists(parent, &parent_pk_map)
1155 {
1156 continue;
1157 }
1158 return Err(KitError::ForeignKey(format!(
1159 "{} references {}({})",
1160 fk.name,
1161 fk.references_table,
1162 fk.references_columns.join(",")
1163 )));
1164 }
1165 Ok(())
1166 }
1167
1168 fn touch_foreign_key_guards(
1169 &mut self,
1170 table: &KitTable,
1171 values: &Map<String, Value>,
1172 ) -> Result<()> {
1173 for fk in table.foreign_keys.clone() {
1174 if fk_values_null(&fk, values) {
1175 continue;
1176 }
1177 let parent = self.require_table(&fk.references_table)?.clone();
1178 let components = parent_pk_components(values, &fk, &parent);
1179 self.touch_row_guard(&parent.name, &components)?;
1180 }
1181 Ok(())
1182 }
1183
1184 fn parent_exists(&self, table: &str, pk_map: &Map<String, Value>) -> Result<bool> {
1185 let t = self.require_table(table)?;
1186 if self.has_staged_for(table) {
1187 let rows = self.snapshot_rows(table)?;
1188 return Ok(rows.iter().any(|r| pk_matches(&r.values, pk_map, t)));
1189 }
1190 if let Some(conditions) = crate::pushdown::pk_conditions(t, pk_map) {
1193 let core_rows =
1194 self.db
1195 .query_core_rows_at(table, &conditions, self.core.read_snapshot())?;
1196 return Ok(!core_rows.is_empty());
1197 }
1198 let rows = self.snapshot_rows(table)?;
1199 Ok(rows.iter().any(|r| pk_matches(&r.values, pk_map, t)))
1200 }
1201
1202 fn staged_row_exists(&self, table: &KitTable, pk_map: &Map<String, Value>) -> bool {
1208 let target = encode_pk(&pk_components(table, pk_map));
1209 let mut exists = false;
1210 for staged in &self.staged {
1211 match staged {
1212 StagedOp::Insert { table: t, values }
1213 | StagedOp::Update {
1214 table: t, values, ..
1215 } => {
1216 if t == &table.name && pk_matches(values, pk_map, table) {
1217 exists = true;
1218 }
1219 }
1220 StagedOp::Delete { table: t, pk } => {
1221 if t == &table.name && *pk == target {
1222 exists = false;
1223 }
1224 }
1225 StagedOp::Truncate { table: t } => {
1226 if t == &table.name {
1227 exists = false;
1228 }
1229 }
1230 }
1231 }
1232 exists
1233 }
1234
1235 fn touch_row_guard(&mut self, table: &str, pk_components: &[KeyComponent]) -> Result<()> {
1238 let encoded_pk = encode_pk(pk_components);
1239 let guard_key = encode_row_guard_key(table, &encoded_pk);
1240 if !self.touched_guards.insert(guard_key.clone()) {
1241 return Ok(());
1242 }
1243 let mut version = 1i64;
1245 let committed = self.internal_rows(ROW_GUARDS)?;
1246 for guard in &committed {
1247 if internal_bytes(guard, cols::RG_ENCODED).as_deref() == Some(guard_key.as_str()) {
1248 if let Some(CoreValue::Int64(v)) = guard.columns.get(&cols::RG_VERSION) {
1249 version = v + 1;
1250 }
1251 self.core
1252 .delete(ROW_GUARDS, guard.row_id)
1253 .map_err(KitError::from)?;
1254 }
1255 }
1256 let now = iso_now();
1257 self.core
1258 .put(
1259 ROW_GUARDS,
1260 vec![
1261 (cols::RG_ENCODED, CoreValue::Bytes(guard_key.into_bytes())),
1262 (cols::RG_TABLE, CoreValue::Bytes(table.into())),
1263 (cols::RG_PK, CoreValue::Bytes(encoded_pk.into_bytes())),
1264 (cols::RG_VERSION, CoreValue::Int64(version)),
1265 (cols::RG_UPDATED, CoreValue::Bytes(now.into_bytes())),
1266 ],
1267 )
1268 .map_err(KitError::from)?;
1269 Ok(())
1270 }
1271
1272 fn has_staged_for(&self, table: &str) -> bool {
1273 self.staged.iter().any(|op| match op {
1274 StagedOp::Insert { table: t, .. }
1275 | StagedOp::Update { table: t, .. }
1276 | StagedOp::Delete { table: t, .. }
1277 | StagedOp::Truncate { table: t } => t == table,
1278 })
1279 }
1280
1281 fn replay_staged_rows(&self, table: &KitTable, rows: &mut Vec<Row>) {
1282 for staged in &self.staged {
1283 match staged {
1284 StagedOp::Insert { table: t, values } if t == &table.name => {
1285 let pk = encoded_pk_for(table, values);
1286 rows.retain(|r| encoded_pk_for(table, &r.values) != pk);
1287 rows.push(Row {
1288 row_id: 0,
1289 values: values.clone(),
1290 });
1291 }
1292 StagedOp::Update {
1293 table: t,
1294 old_pk,
1295 row_id,
1296 values,
1297 } if t == &table.name => {
1298 let new_pk = encoded_pk_for(table, values);
1299 rows.retain(|r| {
1300 let pk = encoded_pk_for(table, &r.values);
1301 pk != *old_pk && pk != new_pk
1302 });
1303 rows.push(Row {
1304 row_id: *row_id,
1305 values: values.clone(),
1306 });
1307 }
1308 StagedOp::Delete { table: t, pk } if t == &table.name => {
1309 rows.retain(|r| encoded_pk_for(table, &r.values) != *pk);
1310 }
1311 StagedOp::Truncate { table: t } if t == &table.name => {
1312 rows.clear();
1313 }
1314 _ => {}
1315 }
1316 }
1317 }
1318
1319 fn delete_guards_for(&mut self, table: &KitTable, values: &Map<String, Value>) -> Result<()> {
1321 let owner_pk = encoded_pk_for(table, values);
1322 self.delete_unique_guards_for_owner(table, &owner_pk)
1323 }
1324
1325 fn delete_all_guards_for_table(&mut self, table: &KitTable) -> Result<()> {
1326 for guard in self.internal_rows(UNIQUE_KEYS)? {
1327 let owner_table = internal_bytes(&guard, cols::UQ_OWNER_TABLE).unwrap_or_default();
1328 if owner_table == table.name {
1329 self.core
1330 .delete(UNIQUE_KEYS, guard.row_id)
1331 .map_err(KitError::from)?;
1332 }
1333 }
1334 for guard in self.internal_rows(ROW_GUARDS)? {
1335 let owner_table = internal_bytes(&guard, cols::RG_TABLE).unwrap_or_default();
1336 if owner_table == table.name {
1337 self.core
1338 .delete(ROW_GUARDS, guard.row_id)
1339 .map_err(KitError::from)?;
1340 }
1341 }
1342 self.staged_unique.retain(|s| s.owner_table != table.name);
1343 self.touched_guards
1344 .retain(|key| !key.starts_with(&format!("{}:", table.name)));
1345 Ok(())
1346 }
1347
1348 fn plan_delete(&self, table: &str, row: &Row) -> Result<(DeletePlan, HashMap<String, Row>)> {
1351 let schema = &self.db.schema;
1352 let t = self.require_table(table)?;
1353 let pk_str = encoded_pk_for(t, &row.values);
1354 let row_cache: RefCell<HashMap<String, Row>> = RefCell::new(HashMap::new());
1359 let find_children =
1360 |child_table: &KitTable, fk: &ForeignKey, parent_pk: &str| -> Vec<(String, String)> {
1361 let parent_pk_value = match pk_string_to_value(parent_pk, t) {
1362 Ok(v) => v,
1363 Err(_) => return Vec::new(),
1364 };
1365 let parent_pk_map = match pk_to_map(&parent_pk_value, t) {
1366 Ok(m) => m,
1367 Err(_) => return Vec::new(),
1368 };
1369 let child_rows = match self.snapshot_rows(&child_table.name) {
1370 Ok(r) => r,
1371 Err(_) => return Vec::new(),
1372 };
1373 let mut out = Vec::new();
1374 for child_row in child_rows {
1375 if fk_matches(&child_row.values, fk, &parent_pk_map, t) {
1376 let child_pk = encoded_pk_for(child_table, &child_row.values);
1377 row_cache
1378 .borrow_mut()
1379 .insert(format!("{}:{}", child_table.name, child_pk), child_row);
1380 out.push((child_pk, parent_pk.to_string()));
1381 }
1382 }
1383 out
1384 };
1385 let plan = plan_delete(schema, table, &pk_str, find_children).map_err(KitError::from)?;
1386 Ok((plan, row_cache.into_inner()))
1387 }
1388
1389 fn apply_set_null(
1390 &mut self,
1391 set_null: &mongreldb_kit_core::planner::SetNullUpdate,
1392 child_row: &Row,
1393 ) -> Result<()> {
1394 let child_table = self.require_table(&set_null.table)?.clone();
1395 let mut values = child_row.values.clone();
1396 for col in &set_null.columns {
1397 let col_def = child_table
1398 .column(col)
1399 .ok_or_else(|| KitError::Integrity(format!("set-null column {col} not found")))?;
1400 if !col_def.nullable {
1401 return Err(KitError::Restrict(format!(
1402 "set-null on non-nullable column {col}"
1403 )));
1404 }
1405 values.insert(col.clone(), Value::Null);
1406 }
1407 mongreldb_kit_core::validation::validate_row(&child_table, &values)?;
1409 self.delete_guards_for(&child_table, &child_row.values)?;
1413 let cells = row_to_core_cells(&values, &child_table)?;
1414 self.core
1415 .delete(&set_null.table, RowId(child_row.row_id))
1416 .map_err(KitError::from)?;
1417 self.core
1418 .put(&set_null.table, cells)
1419 .map_err(KitError::from)?;
1420 self.reserve_unique_guards(&child_table, &values, None)?;
1421 self.reserve_pk_guard(&child_table, &values, true)?;
1425 self.staged.push(StagedOp::Update {
1426 table: set_null.table.clone(),
1427 old_pk: encoded_pk_for(&child_table, &child_row.values),
1428 row_id: child_row.row_id,
1429 values: values.clone(),
1430 });
1431 Ok(())
1432 }
1433
1434 fn apply_defaults(&self, row: &mut Map<String, Value>, table: &KitTable) -> Result<()> {
1437 for col in &table.columns {
1438 if row.contains_key(&col.name) && row.get(&col.name) != Some(&Value::Null) {
1439 continue;
1440 }
1441 let Some(default) = &col.default else {
1442 continue;
1443 };
1444 let value = match default {
1445 DefaultKind::Static(v) => v.clone(),
1446 DefaultKind::Now => {
1447 let now = iso_now();
1448 if col.storage_type == ColumnType::Date {
1449 Value::String(now[..10].to_string())
1450 } else {
1451 Value::String(now)
1452 }
1453 }
1454 DefaultKind::Uuid => Value::String(uuid::Uuid::new_v4().to_string()),
1455 DefaultKind::Sequence(name) => {
1456 let start = self.db.allocate_sequence(name, 1)?;
1457 Value::Number(start.into())
1458 }
1459 DefaultKind::CustomName(name) => {
1460 let provider = self.db.default_providers.get(name).ok_or_else(|| {
1461 KitError::Validation(format!("custom default \"{name}\" is not registered"))
1462 })?;
1463 provider()
1464 }
1465 };
1466 row.insert(col.name.clone(), value);
1467 }
1468 Ok(())
1469 }
1470
1471 fn apply_update_defaults(
1479 &self,
1480 merged: &mut Map<String, Value>,
1481 patch_keys: &HashSet<String>,
1482 table: &KitTable,
1483 ) {
1484 let mut now: Option<String> = None;
1485 for col in &table.columns {
1486 if patch_keys.contains(&col.name) {
1487 continue;
1488 }
1489 if col.generated && matches!(col.default, Some(DefaultKind::Now)) {
1490 let stamp = now.get_or_insert_with(iso_now);
1491 let value = if col.storage_type == ColumnType::Date {
1492 Value::String(stamp[..10].to_string())
1493 } else {
1494 Value::String(stamp.clone())
1495 };
1496 merged.insert(col.name.clone(), value);
1497 }
1498 }
1499 }
1500}
1501
1502fn project_returning(row: &Row, columns: &[String]) -> Result<Value> {
1505 let mut out = Map::new();
1506 for c in columns {
1507 out.insert(c.clone(), row.values.get(c).cloned().unwrap_or(Value::Null));
1508 }
1509 Ok(Value::Object(out))
1510}
1511
1512fn pk_values_map(table: &KitTable, values: &Map<String, Value>) -> Map<String, Value> {
1513 let mut out = Map::new();
1514 for name in &table.primary_key {
1515 out.insert(
1516 name.clone(),
1517 values.get(name).cloned().unwrap_or(Value::Null),
1518 );
1519 }
1520 out
1521}
1522
1523fn patch_to_core_cells(
1527 patch: &Map<String, Value>,
1528 table: &KitTable,
1529) -> Result<Vec<(u16, CoreValue)>> {
1530 let mut cells = Vec::new();
1531 for (name, value) in patch {
1532 let Some(col) = table.column(name) else {
1533 continue;
1534 };
1535 cells.push((col.id as u16, json_to_core(value, col.storage_type)?));
1536 }
1537 Ok(cells)
1538}
1539
1540fn select_all(table: &str, filter: Option<Expr>) -> Select {
1541 Select {
1542 table: table.to_string(),
1543 columns: vec![],
1544 filter,
1545 order_by: vec![],
1546 limit: None,
1547 offset: None,
1548 }
1549}
1550
1551fn pk_matches(values: &Map<String, Value>, pk_map: &Map<String, Value>, table: &KitTable) -> bool {
1552 for name in &table.primary_key {
1553 if values.get(name) != pk_map.get(name) {
1554 return false;
1555 }
1556 }
1557 true
1558}
1559
1560fn pk_is_explicit(table: &KitTable, row: &Map<String, Value>) -> bool {
1566 !table.primary_key.is_empty()
1567 && table
1568 .primary_key
1569 .iter()
1570 .all(|name| matches!(row.get(name), Some(v) if !v.is_null()))
1571}
1572
1573fn pk_guard_constraint(table: &KitTable) -> String {
1574 format!("__pk_{}", table.name)
1575}
1576
1577fn pk_guard_key(table: &KitTable, values: &Map<String, Value>) -> String {
1578 encode_unique_key(
1579 KIT_KEY_VERSION,
1580 &pk_guard_constraint(table),
1581 &pk_components(table, values),
1582 )
1583}
1584
1585pub(crate) fn key_component(col: &Column, value: Option<&Value>) -> KeyComponent {
1587 match value {
1588 None | Some(Value::Null) => KeyComponent::Null,
1589 Some(v) => match col.storage_type {
1590 ColumnType::Int8
1591 | ColumnType::Int16
1592 | ColumnType::Int32
1593 | ColumnType::Int64
1594 | ColumnType::TimestampNanos => KeyComponent::Int(v.as_i64().unwrap_or(0)),
1595 _ => KeyComponent::Text(value_to_text(v)),
1596 },
1597 }
1598}
1599
1600fn value_to_text(value: &Value) -> String {
1601 match value {
1602 Value::String(s) => s.clone(),
1603 other => other.to_string(),
1604 }
1605}
1606
1607fn pk_components(table: &KitTable, values: &Map<String, Value>) -> Vec<KeyComponent> {
1608 table
1609 .primary_key
1610 .iter()
1611 .map(|name| {
1612 let col = table.column(name);
1613 match col {
1614 Some(c) => key_component(c, values.get(name)),
1615 None => KeyComponent::Null,
1616 }
1617 })
1618 .collect()
1619}
1620
1621pub(crate) fn encoded_pk_for(table: &KitTable, values: &Map<String, Value>) -> String {
1622 encode_pk(&pk_components(table, values))
1623}
1624
1625pub(crate) fn unique_key(
1626 table: &KitTable,
1627 uq: &UniqueConstraint,
1628 values: &Map<String, Value>,
1629) -> Option<String> {
1630 let mut components = Vec::with_capacity(uq.columns.len());
1631 for name in &uq.columns {
1632 let col = table.column(name)?;
1633 let component = key_component(col, values.get(name));
1634 if component == KeyComponent::Null {
1635 return None; }
1637 components.push(component);
1638 }
1639 Some(encode_unique_key(KIT_KEY_VERSION, &uq.name, &components))
1640}
1641
1642pub(crate) fn fk_values_null(fk: &ForeignKey, values: &Map<String, Value>) -> bool {
1643 fk.columns
1644 .iter()
1645 .any(|c| values.get(c).map(|v| v.is_null()).unwrap_or(true))
1646}
1647
1648pub(crate) fn parent_pk_components(
1649 values: &Map<String, Value>,
1650 fk: &ForeignKey,
1651 parent: &KitTable,
1652) -> Vec<KeyComponent> {
1653 fk.columns
1654 .iter()
1655 .zip(&parent.primary_key)
1656 .map(|(child_col, parent_col)| {
1657 let col = parent.column(parent_col);
1658 match col {
1659 Some(c) => key_component(c, values.get(child_col)),
1660 None => KeyComponent::Null,
1661 }
1662 })
1663 .collect()
1664}
1665
1666fn parent_pk_value(
1667 values: &Map<String, Value>,
1668 fk: &ForeignKey,
1669 parent: &KitTable,
1670) -> Result<Value> {
1671 if parent.primary_key.len() == 1 {
1672 let child_col = fk
1673 .columns
1674 .first()
1675 .ok_or_else(|| KitError::Integrity("fk has no columns".into()))?;
1676 Ok(values.get(child_col).cloned().unwrap_or(Value::Null))
1677 } else {
1678 let mut obj = Map::new();
1679 for (child_col, parent_col) in fk.columns.iter().zip(&parent.primary_key) {
1680 obj.insert(
1681 parent_col.clone(),
1682 values.get(child_col).cloned().unwrap_or(Value::Null),
1683 );
1684 }
1685 Ok(Value::Object(obj))
1686 }
1687}
1688
1689fn fk_matches(
1690 child_values: &Map<String, Value>,
1691 fk: &ForeignKey,
1692 parent_pk_map: &Map<String, Value>,
1693 parent_table: &KitTable,
1694) -> bool {
1695 for (child_col, parent_col) in fk.columns.iter().zip(&parent_table.primary_key) {
1696 if child_values.get(child_col) != parent_pk_map.get(parent_col) {
1697 return false;
1698 }
1699 }
1700 true
1701}
1702
1703fn pk_string_to_value(encoded: &str, table: &KitTable) -> Result<Value> {
1708 let components = decode_pk(encoded);
1709 if components.len() != table.primary_key.len() {
1710 return Err(KitError::Validation(format!(
1711 "encoded pk \"{encoded}\" has {} components, expected {}",
1712 components.len(),
1713 table.primary_key.len()
1714 )));
1715 }
1716 if table.primary_key.len() == 1 {
1717 return Ok(component_to_value(&components[0]));
1718 }
1719 let mut obj = Map::new();
1720 for (name, component) in table.primary_key.iter().zip(&components) {
1721 obj.insert(name.clone(), component_to_value(component));
1722 }
1723 Ok(Value::Object(obj))
1724}
1725
1726fn component_to_value(component: &KeyComponent) -> Value {
1727 match component {
1728 KeyComponent::Null => Value::Null,
1729 KeyComponent::Int(i) => Value::Number((*i).into()),
1730 KeyComponent::Text(s) => Value::String(s.clone()),
1731 }
1732}
1733
1734fn row_matches_conditions(table: &KitTable, row: &Row, conditions: &[Condition]) -> bool {
1735 conditions
1736 .iter()
1737 .all(|condition| row_matches_condition(table, row, condition))
1738}
1739
1740fn row_matches_condition(table: &KitTable, row: &Row, condition: &Condition) -> bool {
1741 match condition {
1742 Condition::Pk(key) => {
1743 let Some(pk_name) = table.primary_key.first() else {
1744 return false;
1745 };
1746 let Some(col) = table.column(pk_name) else {
1747 return false;
1748 };
1749 value_index_key(col, &row.values).as_deref() == Some(key.as_slice())
1750 }
1751 Condition::BitmapEq { column_id, value } => {
1752 let Some(col) = column_by_id(table, *column_id) else {
1753 return false;
1754 };
1755 value_index_key(col, &row.values).as_deref() == Some(value.as_slice())
1756 }
1757 Condition::BitmapIn { column_id, values } => {
1758 let Some(col) = column_by_id(table, *column_id) else {
1759 return false;
1760 };
1761 let Some(key) = value_index_key(col, &row.values) else {
1762 return false;
1763 };
1764 values.iter().any(|value| value == &key)
1765 }
1766 Condition::Range { column_id, lo, hi } => {
1767 let Some(col) = column_by_id(table, *column_id) else {
1768 return false;
1769 };
1770 matches!(
1771 json_to_core(
1772 row.values.get(&col.name).unwrap_or(&Value::Null),
1773 col.storage_type
1774 ),
1775 Ok(CoreValue::Int64(v)) if v >= *lo && v <= *hi
1776 )
1777 }
1778 Condition::RangeF64 {
1779 column_id,
1780 lo,
1781 lo_inclusive,
1782 hi,
1783 hi_inclusive,
1784 } => {
1785 let Some(col) = column_by_id(table, *column_id) else {
1786 return false;
1787 };
1788 let Ok(CoreValue::Float64(v)) = json_to_core(
1789 row.values.get(&col.name).unwrap_or(&Value::Null),
1790 col.storage_type,
1791 ) else {
1792 return false;
1793 };
1794 let ge_lo = if *lo_inclusive { v >= *lo } else { v > *lo };
1795 let le_hi = if *hi_inclusive { v <= *hi } else { v < *hi };
1796 ge_lo && le_hi
1797 }
1798 Condition::FmContains { column_id, pattern } => {
1799 let Some(col) = column_by_id(table, *column_id) else {
1800 return false;
1801 };
1802 if pattern.is_empty() {
1803 return true;
1804 }
1805 match json_to_core(
1806 row.values.get(&col.name).unwrap_or(&Value::Null),
1807 col.storage_type,
1808 ) {
1809 Ok(CoreValue::Bytes(bytes)) => bytes
1810 .windows(pattern.len())
1811 .any(|window| window == pattern.as_slice()),
1812 _ => false,
1813 }
1814 }
1815 Condition::IsNull { column_id } => {
1816 let Some(col) = column_by_id(table, *column_id) else {
1817 return false;
1818 };
1819 matches!(row.values.get(&col.name), None | Some(Value::Null))
1820 }
1821 Condition::IsNotNull { column_id } => {
1822 let Some(col) = column_by_id(table, *column_id) else {
1823 return false;
1824 };
1825 !matches!(row.values.get(&col.name), None | Some(Value::Null))
1826 }
1827 _ => true,
1830 }
1831}
1832
1833fn column_by_id(table: &KitTable, column_id: u16) -> Option<&Column> {
1834 table.columns.iter().find(|col| col.id as u16 == column_id)
1835}
1836
1837fn value_index_key(col: &Column, values: &Map<String, Value>) -> Option<Vec<u8>> {
1838 let value = values.get(&col.name).unwrap_or(&Value::Null);
1839 if value.is_null() {
1840 return None;
1841 }
1842 json_to_core(value, col.storage_type)
1843 .ok()
1844 .map(|value| value.encode_key())
1845}