agdb/query/
insert_edges_query.rs1use crate::DbElement;
2use crate::DbError;
3use crate::DbId;
4use crate::DbImpl;
5use crate::DbKeyValue;
6use crate::QueryIds;
7use crate::QueryMut;
8use crate::QueryResult;
9use crate::StorageData;
10use crate::query::query_values::QueryValues;
11
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
30#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
31#[cfg_attr(feature = "derive", derive(agdb::DbSerialize))]
32#[cfg_attr(feature = "api", derive(agdb::TypeDefImpl))]
33#[derive(Clone, Debug, PartialEq)]
34pub struct InsertEdgesQuery {
35 pub from: QueryIds,
37
38 pub to: QueryIds,
40
41 pub ids: QueryIds,
44
45 pub values: QueryValues,
48
49 pub each: bool,
52}
53
54impl QueryMut for InsertEdgesQuery {
55 fn process<Store: StorageData>(&self, db: &mut DbImpl<Store>) -> Result<QueryResult, DbError> {
56 let mut result = QueryResult::default();
57
58 let query_ids = match &self.ids {
59 QueryIds::Ids(ids) => ids
60 .iter()
61 .map(|query_id| db.db_id(query_id))
62 .collect::<Result<Vec<DbId>, DbError>>()?,
63 QueryIds::Search(search_query) => search_query.search(db)?,
64 };
65
66 let ids = if !query_ids.is_empty() {
67 query_ids.iter().try_for_each(|db_id| {
68 if db_id.0 > 0 {
69 Err(DbError::from(format!(
70 "The ids for insert or update must all refer to edges - node id '{}' found",
71 db_id.0
72 )))
73 } else {
74 Ok(())
75 }
76 })?;
77
78 let mut ids = vec![];
79
80 for (db_id, key_values) in query_ids.iter().zip(self.values(query_ids.len())?) {
81 db.reserve_key_value_capacity(*db_id, key_values.len() as u64)?;
82 for key_value in key_values {
83 db.insert_or_replace_key_value(*db_id, key_value)?;
84 }
85
86 ids.push(*db_id);
87 }
88
89 ids
90 } else {
91 let from = Self::db_ids(&self.from, db)?;
92 let to: Vec<DbId> = Self::db_ids(&self.to, db)?;
93
94 if self.each || from.len() != to.len() {
95 self.many_to_many_each(db, &from, &to)?
96 } else {
97 self.many_to_many(db, &from, &to)?
98 }
99 };
100
101 result.result = ids.len() as i64;
102 result.elements = ids
103 .into_iter()
104 .map(|id| DbElement {
105 id,
106 from: db.from_id(id),
107 to: db.to_id(id),
108 values: vec![],
109 })
110 .collect();
111
112 Ok(result)
113 }
114}
115
116impl QueryMut for &InsertEdgesQuery {
117 fn process<Store: StorageData>(&self, db: &mut DbImpl<Store>) -> Result<QueryResult, DbError> {
118 (*self).process(db)
119 }
120}
121
122impl InsertEdgesQuery {
123 fn db_ids<Store: StorageData>(
124 query_ids: &QueryIds,
125 db: &DbImpl<Store>,
126 ) -> Result<Vec<DbId>, DbError> {
127 Ok(match &query_ids {
128 QueryIds::Ids(query_ids) => {
129 let mut ids = Vec::with_capacity(query_ids.len());
130
131 for query_id in query_ids {
132 ids.push(db.db_id(query_id)?);
133 }
134
135 ids
136 }
137 QueryIds::Search(search_query) => search_query
138 .search(db)?
139 .into_iter()
140 .filter(|id| id.0 > 0)
141 .collect(),
142 })
143 }
144
145 fn many_to_many<Store: StorageData>(
146 &self,
147 db: &mut DbImpl<Store>,
148 from: &[DbId],
149 to: &[DbId],
150 ) -> Result<Vec<DbId>, DbError> {
151 let mut ids = Vec::with_capacity(from.len());
152 let values = self.values(from.len())?;
153
154 for ((from, to), key_values) in from.iter().zip(to).zip(values) {
155 let db_id = db.insert_edge(*from, *to)?;
156 ids.push(db_id);
157
158 db.reserve_key_value_capacity(db_id, key_values.len() as u64)?;
159
160 for key_value in key_values {
161 db.insert_key_value(db_id, key_value)?;
162 }
163 }
164
165 Ok(ids)
166 }
167
168 fn many_to_many_each<Store: StorageData>(
169 &self,
170 db: &mut DbImpl<Store>,
171 from: &[DbId],
172 to: &[DbId],
173 ) -> Result<Vec<DbId>, DbError> {
174 let count = from.len() * to.len();
175 let mut ids = Vec::with_capacity(count);
176 let values = self.values(count)?;
177 let mut index = 0;
178
179 for from in from {
180 for to in to {
181 let db_id = db.insert_edge(*from, *to)?;
182 ids.push(db_id);
183
184 db.reserve_key_value_capacity(db_id, values[index].len() as u64)?;
185
186 for key_value in values[index] {
187 db.insert_key_value(db_id, key_value)?;
188 }
189
190 index += 1;
191 }
192 }
193
194 Ok(ids)
195 }
196
197 fn values(&self, count: usize) -> Result<Vec<&Vec<DbKeyValue>>, DbError> {
198 let values = match &self.values {
199 QueryValues::Single(v) => vec![v; std::cmp::max(1, count)],
200 QueryValues::Multi(v) => v.iter().collect(),
201 };
202
203 if values.len() != count {
204 return Err(DbError::from(format!(
205 "Values len '{}' do not match the insert count '{count}'",
206 values.len()
207 )));
208 }
209
210 Ok(values)
211 }
212}