use crate::DbElement;
use crate::DbError;
use crate::DbId;
use crate::DbImpl;
use crate::QueryId;
use crate::QueryIds;
use crate::QueryMut;
use crate::QueryResult;
use crate::StorageData;
use crate::query::query_values::QueryValues;
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
#[cfg_attr(feature = "derive", derive(agdb::DbSerialize))]
#[cfg_attr(feature = "api", derive(agdb::TypeDefImpl))]
#[derive(Clone, Debug, PartialEq)]
pub struct InsertNodesQuery {
pub count: u64,
pub values: QueryValues,
pub aliases: Vec<String>,
pub ids: QueryIds,
}
impl QueryMut for InsertNodesQuery {
fn process<Store: StorageData>(&self, db: &mut DbImpl<Store>) -> Result<QueryResult, DbError> {
let mut result = QueryResult::default();
let mut ids = vec![];
let count = std::cmp::max(self.count, self.aliases.len() as u64);
let query_ids = match &self.ids {
QueryIds::Ids(ids) => ids
.iter()
.map(|query_id| db.db_id(query_id))
.collect::<Result<Vec<DbId>, DbError>>()?,
QueryIds::Search(search_query) => search_query.search(db)?,
};
let values = match &self.values {
QueryValues::Single(v) => vec![v; std::cmp::max(query_ids.len(), count as usize)],
QueryValues::Multi(v) => v.iter().collect(),
};
if values.len() < self.aliases.len() {
return Err(DbError::from(format!(
"Aliases ({}) and values ({}) must have compatible lenghts ({} <= {})",
self.aliases.len(),
values.len(),
self.aliases.len(),
values.len(),
)));
}
if !query_ids.is_empty() {
query_ids.iter().try_for_each(|db_id| {
if db_id.0 < 0 {
Err(DbError::from(format!(
"The ids for insert or update must all refer to nodes - edge id '{}' found",
db_id.0
)))
} else {
Ok(())
}
})?;
if values.len() != query_ids.len() {
return Err(DbError::from(format!(
"Values ({}) and ids ({}) must have the same length",
values.len(),
query_ids.len()
)));
}
for ((index, db_id), key_values) in query_ids.iter().enumerate().zip(values) {
db.reserve_key_value_capacity(*db_id, key_values.len() as u64)?;
for key_value in key_values {
db.insert_or_replace_key_value(*db_id, key_value)?;
}
if let Some(alias) = self.aliases.get(index) {
db.insert_new_alias(*db_id, alias)?;
}
ids.push(*db_id);
}
} else {
for (index, key_values) in values.iter().enumerate() {
if let Some(alias) = self.aliases.get(index)
&& let Ok(db_id) = db.db_id(&QueryId::Alias(alias.to_string()))
{
ids.push(db_id);
db.reserve_key_value_capacity(db_id, key_values.len() as u64)?;
for key_value in *key_values {
db.insert_or_replace_key_value(db_id, key_value)?;
}
continue;
}
let db_id = db.insert_node()?;
ids.push(db_id);
if let Some(alias) = self.aliases.get(index) {
db.insert_new_alias(db_id, alias)?;
}
db.reserve_key_value_capacity(db_id, key_values.len() as u64)?;
for key_value in *key_values {
db.insert_key_value(db_id, key_value)?;
}
}
}
result.result = ids.len() as i64;
result.elements = ids
.into_iter()
.map(|id| DbElement {
id,
from: None,
to: None,
values: vec![],
})
.collect();
Ok(result)
}
}
impl QueryMut for &InsertNodesQuery {
fn process<Store: StorageData>(&self, db: &mut DbImpl<Store>) -> Result<QueryResult, DbError> {
(*self).process(db)
}
}