use sqlparser::ast;
use super::super::dml_helpers::{
KvInsertParams, VectorPrimaryInsertParams, build_kv_insert_plan,
build_vector_primary_insert_plan, check_declared_float_ranges_in_assignments,
check_declared_int_ranges_in_assignments, is_vector_primary, resolve_insert_columns,
};
use super::target::{
column_schema, insert_columns, resolve_target, target_scope, typed_rows, values_rows,
};
use crate::engine_rules::{self, UpsertParams};
use crate::error::Result;
use crate::planner::declared_type_coerce::coerce_assignments_to_declared_types;
use crate::types::*;
pub fn plan_upsert(ins: &ast::Insert, catalog: &dyn SqlCatalog) -> Result<Vec<SqlPlan>> {
plan_upsert_rows(ins, catalog, "UPSERT", Vec::new())
}
pub(super) fn plan_upsert_with_on_conflict(
ins: &ast::Insert,
catalog: &dyn SqlCatalog,
on_conflict_updates: Vec<(String, SqlExpr)>,
) -> Result<Vec<SqlPlan>> {
plan_upsert_rows(ins, catalog, "INSERT ... ON CONFLICT", on_conflict_updates)
}
fn plan_upsert_rows(
ins: &ast::Insert,
catalog: &dyn SqlCatalog,
verb: &str,
mut on_conflict_updates: Vec<(String, SqlExpr)>,
) -> Result<Vec<SqlPlan>> {
let (table_name, info) = resolve_target(ins, verb, catalog)?;
let columns = insert_columns(&ins.columns, &target_scope(&table_name, &info)?)?;
let rows_ast = values_rows(ins, verb)?;
if info.engine == EngineType::KeyValue {
return build_kv_insert_plan(KvInsertParams {
collection: table_name,
columns: &columns,
rows_ast,
intent: KvInsertIntent::Put,
on_conflict_updates,
pk_col: info.primary_key.as_deref(),
declared_columns: &info.columns,
catalog,
});
}
let columns = resolve_insert_columns(columns, &info, rows_ast)?;
let typed = typed_rows(&info, &columns, rows_ast, catalog)?;
coerce_assignments_to_declared_types(
&info.columns,
&mut on_conflict_updates,
info.primary_key.as_deref(),
)?;
check_declared_int_ranges_in_assignments(&info.columns, &on_conflict_updates)?;
check_declared_float_ranges_in_assignments(&info.columns, &on_conflict_updates)?;
if is_vector_primary(&info)
&& let Some(ref vpc) = info.vector_primary
{
return build_vector_primary_insert_plan(VectorPrimaryInsertParams {
collection: &table_name,
vpc,
rows: typed.rows,
volatile_defaults: typed.volatile_defaults,
intent: VectorPrimaryInsertIntent::Upsert,
on_conflict_updates,
primary_key: info.primary_key.clone(),
});
}
let column_schema = column_schema(&info);
let rules = engine_rules::resolve_engine_rules(info.engine);
rules.plan_upsert(UpsertParams {
collection: table_name,
columns,
rows: typed.rows,
volatile_defaults: typed.volatile_defaults,
on_conflict_updates,
column_schema,
primary_key: info.primary_key.clone(),
})
}