Inserts nodes using a prepared statement: parse SQL once, then bind+execute+reset for each row — zero SQL parsing after the first call.
(&self, nodes: &[Node])
| 240 | /// Inserts nodes using a prepared statement: parse SQL once, then |
| 241 | /// bind+execute+reset for each row — zero SQL parsing after the first call. |
| 242 | pub async fn insert_nodes(&self, nodes: &[Node]) -> Result<()> { |
| 243 | if nodes.is_empty() { |
| 244 | return Ok(()); |
| 245 | } |
| 246 | |
| 247 | self.with_batch_transaction("insert_nodes", async { |
| 248 | let stmt = self.conn() |
| 249 | .prepare( |
| 250 | "INSERT OR REPLACE INTO nodes \ |
| 251 | (id,kind,name,qualified_name,file_path,\ |
| 252 | start_line,end_line,start_column,end_column,\ |
| 253 | docstring,signature,visibility,is_async,\ |
| 254 | branches,loops,returns,max_nesting,\ |
| 255 | unsafe_blocks,unchecked_calls,assertions,updated_at,attrs_start_line,parent_id) \ |
| 256 | VALUES (?1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12,?13,?14,?15,?16,?17,?18,?19,?20,?21,?22,?23)" |
| 257 | ) |
| 258 | .await |
| 259 | .map_err(|e| TraceDecayError::Database { |
| 260 | message: format!("failed to prepare: {e}"), |
| 261 | operation: "insert_nodes".to_string(), |
| 262 | })?; |
| 263 | |
| 264 | for node in nodes { |
| 265 | let params = params![ |
| 266 | node.id.as_str(), |
| 267 | node.kind.as_str(), |
| 268 | node.name.as_str(), |
| 269 | node.qualified_name.as_str(), |
| 270 | node.file_path.as_str(), |
| 271 | i64::from(node.start_line), |
| 272 | i64::from(node.end_line), |
| 273 | i64::from(node.start_column), |
| 274 | i64::from(node.end_column), |
| 275 | opt_str(node.docstring.as_deref()), |
| 276 | opt_str(node.signature.as_deref()), |
| 277 | node.visibility.as_str(), |
| 278 | i64::from(node.is_async), |
| 279 | i64::from(node.branches), |
| 280 | i64::from(node.loops), |
| 281 | i64::from(node.returns), |
| 282 | i64::from(node.max_nesting), |
| 283 | i64::from(node.unsafe_blocks), |
| 284 | i64::from(node.unchecked_calls), |
| 285 | i64::from(node.assertions), |
| 286 | node.updated_at as i64, |
| 287 | i64::from(node.attrs_start_line), |
| 288 | opt_str(node.parent_id.as_deref()), |
| 289 | ]; |
| 290 | let insert_result = stmt.execute(params).await; |
| 291 | if let Err(e) = insert_result { |
| 292 | stmt.reset(); |
| 293 | return Err(TraceDecayError::Database { |
| 294 | message: format!("failed to insert node: {e}"), |
| 295 | operation: "insert_nodes".to_string(), |
| 296 | }); |
| 297 | } |
| 298 | stmt.reset(); |
| 299 | } |