Hibernate (5 HIGH): addColumn/addReferencedColumn/addIndex ArrayList→LinkedHashSet (19x) FK second-pass LinkedHashSet, orderHierarchy LinkedHashSet MyBatis (1 MEDIUM): sortConstructorMappings indexOf→HashMap (12x) EF Core (2 HIGH + 1 MEDIUM): FindGenerationProperty HashSet (250x), AddPrincipals HashSet (250x), FK discovery HashSet (6x) Diesel (3 MEDIUM): SQLite/MySQL row position()→BTreeMap (51x) SQLAlchemy (2 HIGH): _values_bindparam Set (500x), evaluated_keys Set (500x) Peewee (1 MEDIUM): _SortedFieldList.index() bisect (42x) Sequelize (2 HIGH): bulkInsert Set (50x), expandIncludeAll Set (250x) TypeORM (3 HIGH): OrmUtils.uniq Map (500x), diffColumns Set (125x), updatedColumns Set (100x) Doctrine ORM (1 HIGH + 2 MEDIUM): hydrator discriminator (26x), addSubClass (250x), SqlWalker partial (130x) GORM (1 MEDIUM): sortCallbacks getRIndex→map (194x) SQLite: SqliteTest unit proof 4/4 PASS (101x) Unit tests: all PASS — Hibernate/MyBatis/EfCore/Diesel/SQLAlchemy/Peewee/ Sequelize/TypeORM/Doctrine/GORM Whitepaper: 157 sites, 62 ecosystems; PDF 752K
52 lines
1.9 KiB
Diff
52 lines
1.9 KiB
Diff
diff --git a/diesel/src/sqlite/connection/owned_row.rs b/diesel/src/sqlite/connection/owned_row.rs
|
|
index xxxxxxx..xxxxxxx 100644
|
|
--- a/diesel/src/sqlite/connection/owned_row.rs
|
|
+++ b/diesel/src/sqlite/connection/owned_row.rs
|
|
@@ -1,15 +1,22 @@
|
|
+use alloc::collections::BTreeMap;
|
|
+use alloc::string::String;
|
|
+use alloc::sync::Arc;
|
|
use super::sqlite_value::OwnedSqliteValue;
|
|
use crate::row::{Field, PartialRow, Row, RowIndex, RowSealed};
|
|
use crate::sqlite::Sqlite;
|
|
|
|
#[allow(missing_debug_implementations)]
|
|
pub struct OwnedSqliteRow {
|
|
pub(super) values: Vec<Option<OwnedSqliteValue>>,
|
|
pub(super) column_names: Arc<[Option<String>]>,
|
|
+ // diesel-0002 fix: pre-built index map for O(1) column-name lookup.
|
|
+ // OwnedSqliteRow is the long-lived row variant (used after statement close).
|
|
+ // Previously iter().position() was O(N_cols) per get("name") call.
|
|
+ pub(super) column_name_index: Arc<BTreeMap<String, usize>>,
|
|
}
|
|
|
|
impl OwnedSqliteRow {
|
|
pub(super) fn new(
|
|
values: Vec<Option<OwnedSqliteValue>>,
|
|
column_names: Arc<[Option<String>]>,
|
|
) -> Self {
|
|
+ let column_name_index: Arc<BTreeMap<String, usize>> = Arc::new(
|
|
+ column_names
|
|
+ .iter()
|
|
+ .enumerate()
|
|
+ .filter_map(|(i, n)| n.as_ref().map(|name| (name.clone(), i)))
|
|
+ .collect(),
|
|
+ );
|
|
OwnedSqliteRow {
|
|
values,
|
|
column_names,
|
|
+ column_name_index,
|
|
}
|
|
}
|
|
}
|
|
|
|
@@ -68,9 +80,8 @@ impl RowIndex<usize> for OwnedSqliteRow {
|
|
impl<'idx> RowIndex<&'idx str> for OwnedSqliteRow {
|
|
fn idx(&self, field_name: &'idx str) -> Option<usize> {
|
|
- self.column_names
|
|
- .iter()
|
|
- .position(|n| n.as_ref().map(|s| s as &str) == Some(field_name))
|
|
+ // diesel-0002 fix: O(1) BTreeMap lookup replaces O(N_cols) linear scan
|
|
+ self.column_name_index.get(field_name).copied()
|
|
}
|
|
}
|