agdb/query/
insert_values_query.rs1use crate::DbElement;
2use crate::DbError;
3use crate::DbId;
4use crate::DbImpl;
5use crate::DbKeyValue;
6use crate::QueryId;
7use crate::QueryIds;
8use crate::QueryMut;
9use crate::QueryResult;
10use crate::SearchQuery;
11use crate::StorageData;
12use crate::query::query_values::QueryValues;
13use crate::query_builder::search::SearchQueryBuilder;
14
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
26#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
27#[cfg_attr(feature = "derive", derive(agdb::DbSerialize))]
28#[cfg_attr(feature = "api", derive(agdb::ApiDef))]
29#[derive(Clone, Debug, PartialEq)]
30pub struct InsertValuesQuery {
31 pub ids: QueryIds,
33
34 pub values: QueryValues,
36}
37
38impl QueryMut for InsertValuesQuery {
39 fn process<Store: StorageData>(&self, db: &mut DbImpl<Store>) -> Result<QueryResult, DbError> {
40 let mut result = QueryResult::default();
41
42 match &self.ids {
43 QueryIds::Ids(ids) => match &self.values {
44 QueryValues::Single(values) => {
45 for id in ids {
46 insert_values(db, id, values, &mut result)?;
47 }
48 }
49 QueryValues::Multi(values) => {
50 if ids.len() != values.len() {
51 return Err(DbError::from("Ids and values length do not match"));
52 }
53
54 for (id, values) in ids.iter().zip(values) {
55 insert_values(db, id, values, &mut result)?;
56 }
57 }
58 },
59 QueryIds::Search(search_query) => {
60 let db_ids = search_query.search(db)?;
61
62 match &self.values {
63 QueryValues::Single(values) => {
64 for db_id in db_ids {
65 insert_values_id(db, db_id, values, &mut result)?;
66 }
67 }
68 QueryValues::Multi(values) => {
69 if db_ids.len() != values.len() {
70 return Err(DbError::from("Ids and values length do not match"));
71 }
72
73 for (db_id, values) in db_ids.iter().zip(values) {
74 insert_values_id(db, *db_id, values, &mut result)?;
75 }
76 }
77 }
78 }
79 }
80
81 Ok(result)
82 }
83}
84
85impl QueryMut for &InsertValuesQuery {
86 fn process<Store: StorageData>(&self, db: &mut DbImpl<Store>) -> Result<QueryResult, DbError> {
87 (*self).process(db)
88 }
89}
90
91fn insert_values<Store: StorageData>(
92 db: &mut DbImpl<Store>,
93 id: &QueryId,
94 values: &[DbKeyValue],
95 result: &mut QueryResult,
96) -> Result<(), DbError> {
97 match db.db_id(id) {
98 Ok(db_id) => insert_values_id(db, db_id, values, result),
99 Err(e) => match id {
100 QueryId::Id(id) => {
101 if id.0 == 0 {
102 insert_values_new(db, None, values, result)
103 } else {
104 Err(e)
105 }
106 }
107 QueryId::Alias(alias) => insert_values_new(db, Some(alias), values, result),
108 },
109 }
110}
111
112fn insert_values_new<Store: StorageData>(
113 db: &mut DbImpl<Store>,
114 alias: Option<&String>,
115 values: &[DbKeyValue],
116 result: &mut QueryResult,
117) -> Result<(), DbError> {
118 let db_id = db.insert_node()?;
119
120 if let Some(alias) = alias {
121 db.insert_new_alias(db_id, alias)?;
122 }
123
124 for key_value in values {
125 db.insert_key_value(db_id, key_value)?;
126 }
127
128 result.result += values.len() as i64;
129 result.elements.push(DbElement {
130 id: db_id,
131 from: None,
132 to: None,
133 values: vec![],
134 });
135
136 Ok(())
137}
138
139fn insert_values_id<Store: StorageData>(
140 db: &mut DbImpl<Store>,
141 db_id: DbId,
142 values: &[DbKeyValue],
143 result: &mut QueryResult,
144) -> Result<(), DbError> {
145 for key_value in values {
146 db.insert_or_replace_key_value(db_id, key_value)?;
147 result.result += 1;
148 }
149 Ok(())
150}
151
152impl SearchQueryBuilder for InsertValuesQuery {
153 fn search_mut(&mut self) -> &mut SearchQuery {
154 if let QueryIds::Search(search) = &mut self.ids {
155 search
156 } else {
157 panic!("Expected search query");
158 }
159 }
160}
161
162#[cfg(test)]
163mod tests {
164 use super::*;
165
166 #[test]
167 #[should_panic]
168 fn missing_search() {
169 InsertValuesQuery {
170 values: QueryValues::Single(vec![]),
171 ids: QueryIds::Ids(vec![]),
172 }
173 .search_mut();
174 }
175}