diff --git a/stdlib/src/database.rs b/stdlib/src/database.rs index 236e7777..9364abf0 100644 --- a/stdlib/src/database.rs +++ b/stdlib/src/database.rs @@ -136,6 +136,12 @@ fn std_database_query( })?; let mut result_rows = Vec::new(); + let mut prototype_map = IndexMap::with_capacity(column_names.len()); + let mut col_to_map_idx = Vec::with_capacity(column_names.len()); + for name in column_names.iter() { + let (map_idx, _) = prototype_map.insert_full(name.clone(), RuntimeValue::Null); + col_to_map_idx.push(map_idx); + } while let Some(row) = rows.next().map_err(|e| { RuntimeError::new( @@ -144,8 +150,8 @@ fn std_database_query( None, ) })? { - let mut row_map = IndexMap::with_capacity(column_names.len()); - for (idx, name) in column_names.iter().enumerate() { + let mut row_map = prototype_map.clone(); + for idx in 0..column_names.len() { let value = match row.get_ref(idx).map_err(|e| { RuntimeError::new( RuntimeErrorKind::InvalidOperation(format!("Database column get error: {}", e)), @@ -165,9 +171,10 @@ fn std_database_query( RuntimeValue::Str(s) } }; - // The clone here is strictly necessary because `IndexMap` requires an owned `String` - // key, and each row constructs a fresh map containing these keys. - row_map.insert(name.clone(), value); + let map_idx = col_to_map_idx[idx]; + if let Some((_, v)) = row_map.get_index_mut(map_idx) { + *v = value; + } } result_rows.push(RuntimeValue::Map { entries: Rc::new(RefCell::new(row_map)), diff --git a/stdlib/src/sqlite.rs b/stdlib/src/sqlite.rs index 03bf6e17..9b0ea5c6 100644 --- a/stdlib/src/sqlite.rs +++ b/stdlib/src/sqlite.rs @@ -181,9 +181,16 @@ impl StdlibRegistry { .collect(); let mut rows = Vec::new(); + let mut prototype_map = IndexMap::with_capacity(col_count); + let mut col_to_map_idx = Vec::with_capacity(col_count); + for name in col_names.iter() { + let (map_idx, _) = prototype_map.insert_full(name.clone(), RuntimeValue::Null); + col_to_map_idx.push(map_idx); + } + let row_iter = stmt .query_map(rusqlite::params_from_iter(params), |row| { - let mut map = IndexMap::with_capacity(col_count); + let mut map = prototype_map.clone(); for i in 0..col_count { let val = row.get_ref_unwrap(i); let rt_val = match val { @@ -207,7 +214,10 @@ impl StdlibRegistry { ) } }; - map.insert(col_names[i].clone(), rt_val); + let map_idx = col_to_map_idx[i]; + if let Some((_, v)) = map.get_index_mut(map_idx) { + *v = rt_val; + } } Ok(map) })