Skip to main content

sz_orm_core/
result_map.rs

1//! ResultMap 高级映射 + Native Query + ResultSetMapping
2//!
3//! 对应文档 6.8 节改进项 30(ResultMap 高级映射)+ 42(Native Query + ResultSetMapping)。
4//!
5//! # 核心概念
6//!
7//! - **ResultMap**:声明式结果映射规则(id property + result property + association + collection + discriminator)
8//! - **ResultSetMapping**:Hibernate `@SqlResultSetMapping` 风格,原生 SQL 的结果映射
9//! - **NativeQuery**:原生 SQL + ResultSetMapping 引用
10//! - **ResultMapRegistry**:注册中心,按 id 索引
11//! - **RowData**:行数据(列名 -> Value)
12//!
13//! # 设计灵感
14//!
15//! - MyBatis `resultMap`(最强大的 resultMap 模型,支持 discriminator 多态、association/collection 嵌套)
16//! - Hibernate `@SqlResultSetMapping`(JPA 标准)
17//! - Doctrine `ResultSetMappingBuilder`
18//!
19//! # 优势
20//!
21//! 1. **多态鉴别器**:通过 discriminator 按列值分派到不同 ResultMap
22//! 2. **嵌套映射**:association(一对一)+ collection(一对多)支持嵌套
23//! 3. **列前缀**:JOIN 查询结果通过列前缀隔离不同实体的列
24//! 4. **原生 SQL**:NativeQuery 可执行任意 SQL 并通过 ResultSetMapping 映射
25//!
26//! # 使用示例
27//!
28//! ```
29//! use sz_orm_core::result_map::{
30//!     ResultMap, Mapping, NestedAssociation, ResultMapRegistry, RowData, apply_result_map,
31//! };
32//! use sz_orm_core::Value;
33//! use std::collections::HashMap;
34//!
35//! // 1. 注册 ResultMap
36//! let mut registry = ResultMapRegistry::new();
37//!
38//! let mut dept_map = ResultMap::new("deptMap", "Dept");
39//! dept_map.add_id_mapping(Mapping::new("id", "dept_id"));
40//! dept_map.add_result_mapping(Mapping::new("name", "dept_name"));
41//! registry.register(dept_map);
42//!
43//! let mut user_map = ResultMap::new("userMap", "User");
44//! user_map.add_id_mapping(Mapping::new("id", "user_id"));
45//! user_map.add_result_mapping(Mapping::new("name", "user_name"));
46//! user_map.add_association(NestedAssociation::new("dept", "deptMap"));
47//! registry.register(user_map);
48//!
49//! // 2. 构造 JOIN 查询结果行
50//! let mut columns = HashMap::new();
51//! columns.insert("user_id".to_string(), Value::I64(1));
52//! columns.insert("user_name".to_string(), Value::String("Alice".to_string()));
53//! columns.insert("dept_id".to_string(), Value::I64(10));
54//! columns.insert("dept_name".to_string(), Value::String("Engineering".to_string()));
55//! let row = RowData::new(columns);
56//!
57//! // 3. 应用 ResultMap 映射
58//! let result = apply_result_map(&registry, "userMap", &row).unwrap();
59//! assert_eq!(result.get("id"), Some(&Value::I64(1)));
60//! assert_eq!(result.get("name"), Some(&Value::String("Alice".to_string())));
61//! ```
62
63use crate::value::Value;
64use parking_lot::RwLock;
65use std::collections::HashMap;
66
67// ============================================================================
68// Mapping — 单字段映射规则
69// ============================================================================
70
71/// 单字段映射规则(property <-> column)
72#[derive(Debug, Clone, PartialEq, Eq)]
73pub struct Mapping {
74    /// 目标属性名(Rust 字段名)
75    pub property: String,
76    /// 数据库列名
77    pub column: String,
78    /// 可选 TypeHandler 名称(用于自定义类型转换)
79    pub type_handler: Option<String>,
80}
81
82impl Mapping {
83    /// 创建字段映射
84    pub fn new(property: impl Into<String>, column: impl Into<String>) -> Self {
85        Self {
86            property: property.into(),
87            column: column.into(),
88            type_handler: None,
89        }
90    }
91
92    /// 创建带 TypeHandler 的字段映射
93    pub fn with_handler(
94        property: impl Into<String>,
95        column: impl Into<String>,
96        handler: impl Into<String>,
97    ) -> Self {
98        Self {
99            property: property.into(),
100            column: column.into(),
101            type_handler: Some(handler.into()),
102        }
103    }
104}
105
106// ============================================================================
107// NestedAssociation — 一对一嵌套映射
108// ============================================================================
109
110/// 一对一嵌套映射(association)
111#[derive(Debug, Clone, PartialEq, Eq)]
112pub struct NestedAssociation {
113    /// 目标属性名
114    pub property: String,
115    /// 引用的 ResultMap id
116    pub result_map: String,
117    /// 列前缀(用于 JOIN 场景隔离不同实体列)
118    pub column_prefix: Option<String>,
119    /// notNullColumn:仅当该列非 NULL 时才填充(避免 LEFT JOIN NULL 行被填充)
120    pub not_null_column: Option<String>,
121}
122
123impl NestedAssociation {
124    /// 创建嵌套 association
125    pub fn new(property: impl Into<String>, result_map: impl Into<String>) -> Self {
126        Self {
127            property: property.into(),
128            result_map: result_map.into(),
129            column_prefix: None,
130            not_null_column: None,
131        }
132    }
133
134    /// 设置列前缀
135    pub fn with_prefix(mut self, prefix: impl Into<String>) -> Self {
136        self.column_prefix = Some(prefix.into());
137        self
138    }
139
140    /// 设置 notNullColumn
141    pub fn with_not_null_column(mut self, column: impl Into<String>) -> Self {
142        self.not_null_column = Some(column.into());
143        self
144    }
145}
146
147// ============================================================================
148// NestedCollection — 一对多嵌套映射
149// ============================================================================
150
151/// 一对多嵌套映射(collection)
152#[derive(Debug, Clone, PartialEq, Eq)]
153pub struct NestedCollection {
154    /// 目标属性名
155    pub property: String,
156    /// 引用的 ResultMap id
157    pub result_map: String,
158    /// 列前缀
159    pub column_prefix: Option<String>,
160    /// notNullColumn
161    pub not_null_column: Option<String>,
162}
163
164impl NestedCollection {
165    /// 创建嵌套 collection
166    pub fn new(property: impl Into<String>, result_map: impl Into<String>) -> Self {
167        Self {
168            property: property.into(),
169            result_map: result_map.into(),
170            column_prefix: None,
171            not_null_column: None,
172        }
173    }
174
175    /// 设置列前缀
176    pub fn with_prefix(mut self, prefix: impl Into<String>) -> Self {
177        self.column_prefix = Some(prefix.into());
178        self
179    }
180
181    /// 设置 notNullColumn
182    pub fn with_not_null_column(mut self, column: impl Into<String>) -> Self {
183        self.not_null_column = Some(column.into());
184        self
185    }
186}
187
188// ============================================================================
189// Discriminator — 多态鉴别器
190// ============================================================================
191
192/// 多态鉴别器 case
193#[derive(Debug, Clone, PartialEq)]
194pub struct DiscriminatorCase {
195    /// 触发值
196    pub value: Value,
197    /// 该 case 使用的 ResultMap id
198    pub result_map: String,
199}
200
201impl DiscriminatorCase {
202    /// 创建 case
203    pub fn new(value: Value, result_map: impl Into<String>) -> Self {
204        Self {
205            value,
206            result_map: result_map.into(),
207        }
208    }
209}
210
211/// 多态鉴别器
212#[derive(Debug, Clone, PartialEq)]
213pub struct Discriminator {
214    /// 鉴别列
215    pub column: String,
216    /// case 列表
217    pub cases: Vec<DiscriminatorCase>,
218}
219
220impl Discriminator {
221    /// 创建鉴别器
222    pub fn new(column: impl Into<String>) -> Self {
223        Self {
224            column: column.into(),
225            cases: Vec::new(),
226        }
227    }
228
229    /// 添加 case
230    pub fn add_case(&mut self, case: DiscriminatorCase) -> &mut Self {
231        self.cases.push(case);
232        self
233    }
234
235    /// 根据值查找对应 ResultMap id
236    pub fn resolve(&self, value: &Value) -> Option<&str> {
237        for case in &self.cases {
238            if case.value == *value {
239                return Some(&case.result_map);
240            }
241        }
242        None
243    }
244}
245
246// ============================================================================
247// ResultMap — 完整结果映射规则
248// ============================================================================
249
250/// 完整结果映射规则
251#[derive(Debug, Clone, PartialEq)]
252pub struct ResultMap {
253    /// 唯一 id
254    pub id: String,
255    /// 目标类型名(如 "User")
256    pub type_name: String,
257    /// 主键字段映射(用于唯一性判断、collection 聚合)
258    pub id_mappings: Vec<Mapping>,
259    /// 普通字段映射
260    pub result_mappings: Vec<Mapping>,
261    /// 一对一嵌套映射
262    pub associations: Vec<NestedAssociation>,
263    /// 一对多嵌套映射
264    pub collections: Vec<NestedCollection>,
265    /// 多态鉴别器
266    pub discriminator: Option<Discriminator>,
267}
268
269impl ResultMap {
270    /// 创建 ResultMap
271    pub fn new(id: impl Into<String>, type_name: impl Into<String>) -> Self {
272        Self {
273            id: id.into(),
274            type_name: type_name.into(),
275            id_mappings: Vec::new(),
276            result_mappings: Vec::new(),
277            associations: Vec::new(),
278            collections: Vec::new(),
279            discriminator: None,
280        }
281    }
282
283    /// 添加主键映射
284    pub fn add_id_mapping(&mut self, mapping: Mapping) -> &mut Self {
285        self.id_mappings.push(mapping);
286        self
287    }
288
289    /// 添加普通字段映射
290    pub fn add_result_mapping(&mut self, mapping: Mapping) -> &mut Self {
291        self.result_mappings.push(mapping);
292        self
293    }
294
295    /// 添加 association 嵌套
296    pub fn add_association(&mut self, assoc: NestedAssociation) -> &mut Self {
297        self.associations.push(assoc);
298        self
299    }
300
301    /// 添加 collection 嵌套
302    pub fn add_collection(&mut self, coll: NestedCollection) -> &mut Self {
303        self.collections.push(coll);
304        self
305    }
306
307    /// 设置 discriminator
308    pub fn set_discriminator(&mut self, disc: Discriminator) -> &mut Self {
309        self.discriminator = Some(disc);
310        self
311    }
312
313    /// 收集本 ResultMap 直接引用的所有 sub-ResultMap id
314    pub fn sub_map_ids(&self) -> Vec<String> {
315        let mut ids = Vec::new();
316        for a in &self.associations {
317            ids.push(a.result_map.clone());
318        }
319        for c in &self.collections {
320            ids.push(c.result_map.clone());
321        }
322        if let Some(d) = &self.discriminator {
323            for case in &d.cases {
324                ids.push(case.result_map.clone());
325            }
326        }
327        ids
328    }
329}
330
331// ============================================================================
332// ResultMapRegistry — 注册中心
333// ============================================================================
334
335/// ResultMap 注册中心(线程安全)
336#[derive(Debug, Default)]
337pub struct ResultMapRegistry {
338    maps: RwLock<HashMap<String, ResultMap>>,
339}
340
341impl ResultMapRegistry {
342    /// 创建空注册中心
343    pub fn new() -> Self {
344        Self {
345            maps: RwLock::new(HashMap::new()),
346        }
347    }
348
349    /// 注册 ResultMap(同名覆盖)
350    pub fn register(&self, map: ResultMap) {
351        let mut maps = self.maps.write();
352        maps.insert(map.id.clone(), map);
353    }
354
355    /// 按 id 查找 ResultMap
356    pub fn get(&self, id: &str) -> Option<ResultMap> {
357        let maps = self.maps.read();
358        maps.get(id).cloned()
359    }
360
361    /// 是否包含指定 id
362    pub fn contains(&self, id: &str) -> bool {
363        let maps = self.maps.read();
364        maps.contains_key(id)
365    }
366
367    /// 已注册的 ResultMap 数量
368    pub fn len(&self) -> usize {
369        let maps = self.maps.read();
370        maps.len()
371    }
372
373    /// 是否为空
374    pub fn is_empty(&self) -> bool {
375        self.len() == 0
376    }
377
378    /// 列出所有已注册的 id
379    pub fn list_ids(&self) -> Vec<String> {
380        let maps = self.maps.read();
381        maps.keys().cloned().collect()
382    }
383
384    /// 清空注册中心
385    pub fn clear(&self) {
386        let mut maps = self.maps.write();
387        maps.clear();
388    }
389}
390
391// ============================================================================
392// RowData — 行数据
393// ============================================================================
394
395/// 行数据(列名 -> Value)
396#[derive(Debug, Clone, Default)]
397pub struct RowData {
398    columns: HashMap<String, Value>,
399}
400
401impl RowData {
402    /// 创建空行
403    pub fn new(columns: HashMap<String, Value>) -> Self {
404        Self { columns }
405    }
406
407    /// 创建空行
408    pub fn empty() -> Self {
409        Self {
410            columns: HashMap::new(),
411        }
412    }
413
414    /// 插入/更新列
415    pub fn set(&mut self, column: impl Into<String>, value: Value) {
416        self.columns.insert(column.into(), value);
417    }
418
419    /// 按列名取值
420    pub fn get(&self, column: &str) -> Option<&Value> {
421        self.columns.get(column)
422    }
423
424    /// 按前缀 + 列名取值(用于 JOIN 列前缀隔离)
425    ///
426    /// 例如:prefix="dept_", column="id" 将查找 "dept_id"
427    pub fn get_with_prefix(&self, prefix: &str, column: &str) -> Option<&Value> {
428        let full = format!("{}{}", prefix, column);
429        self.columns.get(&full)
430    }
431
432    /// 判断列是否存在且非 NULL
433    pub fn is_not_null(&self, column: &str) -> bool {
434        match self.columns.get(column) {
435            Some(Value::Null) | None => false,
436            Some(_) => true,
437        }
438    }
439
440    /// 列数
441    pub fn len(&self) -> usize {
442        self.columns.len()
443    }
444
445    /// 是否为空
446    pub fn is_empty(&self) -> bool {
447        self.columns.is_empty()
448    }
449
450    /// 所有列名
451    pub fn column_names(&self) -> Vec<String> {
452        self.columns.keys().cloned().collect()
453    }
454
455    /// 获取所有列的引用(按列名排序)
456    pub fn sorted_columns(&self) -> Vec<(&String, &Value)> {
457        let mut entries: Vec<(&String, &Value)> = self.columns.iter().collect();
458        entries.sort_by(|a, b| a.0.cmp(b.0));
459        entries
460    }
461
462    /// 获取所有列的迭代器
463    pub fn iter(&self) -> impl Iterator<Item = (&String, &Value)> {
464        self.columns.iter()
465    }
466}
467
468// ============================================================================
469// ResultMapError — 错误类型
470// ============================================================================
471
472/// ResultMap 错误
473#[derive(Debug, Clone, PartialEq)]
474pub enum ResultMapError {
475    /// ResultMap 未注册
476    MapNotFound {
477        /// 未找到的 ResultMap ID
478        id: String,
479    },
480    /// 必需列缺失
481    RequiredColumnMissing {
482        /// 缺失的列名
483        column: String,
484    },
485    /// 嵌套映射失败
486    NestedMappingFailed {
487        /// 嵌套属性名
488        property: String,
489        /// 失败原因
490        reason: String,
491    },
492}
493
494impl std::fmt::Display for ResultMapError {
495    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
496        match self {
497            ResultMapError::MapNotFound { id } => {
498                write!(f, "ResultMap '{}' not registered", id)
499            }
500            ResultMapError::RequiredColumnMissing { column } => {
501                write!(f, "Required column '{}' missing in row", column)
502            }
503            ResultMapError::NestedMappingFailed { property, reason } => {
504                write!(f, "Nested mapping failed for '{}': {}", property, reason)
505            }
506        }
507    }
508}
509
510impl std::error::Error for ResultMapError {}
511
512// ============================================================================
513// 映射函数
514// ============================================================================
515
516/// 应用 ResultMap 规则到单行,返回属性 HashMap
517///
518/// # 行为
519///
520/// 1. 检查 discriminator,若命中 case 则改用 case 指定的 ResultMap
521/// 2. 应用 id_mappings 和 result_mappings,将列值填入属性
522/// 3. 递归处理 associations(一对一)
523/// 4. 单行模式下 collections 仅返回当前行解析出的单个子实体(多次行合并需用 `apply_result_map_many`)
524#[tracing::instrument(skip(registry, row), fields(map_id = map_id))]
525pub fn apply_result_map(
526    registry: &ResultMapRegistry,
527    map_id: &str,
528    row: &RowData,
529) -> Result<HashMap<String, Value>, ResultMapError> {
530    let map = registry
531        .get(map_id)
532        .ok_or_else(|| ResultMapError::MapNotFound {
533            id: map_id.to_string(),
534        })?;
535
536    // 1. discriminator 多态分派
537    let effective_map = if let Some(disc) = &map.discriminator {
538        if let Some(disc_value) = row.get(&disc.column) {
539            if let Some(case_map_id) = disc.resolve(disc_value) {
540                registry.get(case_map_id).unwrap_or(map)
541            } else {
542                map
543            }
544        } else {
545            map
546        }
547    } else {
548        map
549    };
550
551    let mut attrs: HashMap<String, Value> = HashMap::new();
552
553    // 2. id + result 映射
554    for m in &effective_map.id_mappings {
555        if let Some(v) = row.get(&m.column) {
556            attrs.insert(m.property.clone(), v.clone());
557        }
558    }
559    for m in &effective_map.result_mappings {
560        if let Some(v) = row.get(&m.column) {
561            attrs.insert(m.property.clone(), v.clone());
562        }
563    }
564
565    // 3. associations(一对一,递归)
566    for assoc in &effective_map.associations {
567        // notNullColumn 检查
568        if let Some(not_null_col) = &assoc.not_null_column {
569            if !row.is_not_null(not_null_col) {
570                continue; // 跳过,不填充该 association
571            }
572        }
573
574        // 根据 column_prefix 决定传入的 RowData(只调用一次 apply_result_map)
575        let nested_value = if let Some(prefix) = &assoc.column_prefix {
576            // prefix 模式:构造去除前缀的 RowData 后递归
577            let mut prefixed_row = RowData::empty();
578            for (col, v) in &row.columns {
579                if let Some(stripped) = col.strip_prefix(prefix) {
580                    prefixed_row.set(stripped.to_string(), v.clone());
581                }
582            }
583            apply_result_map(registry, &assoc.result_map, &prefixed_row).map_err(|e| {
584                ResultMapError::NestedMappingFailed {
585                    property: assoc.property.clone(),
586                    reason: e.to_string(),
587                }
588            })?
589        } else {
590            // 无 prefix:直接用原始 row 递归
591            apply_result_map(registry, &assoc.result_map, row).map_err(|e| {
592                ResultMapError::NestedMappingFailed {
593                    property: assoc.property.clone(),
594                    reason: e.to_string(),
595                }
596            })?
597        };
598
599        // 将嵌套 HashMap 转为 Value::Object 存储
600        attrs.insert(assoc.property.clone(), Value::Object(nested_value));
601    }
602
603    // 4. collections(一对多,单行模式下仅返回当前行解析的单个元素)
604    for coll in &effective_map.collections {
605        if let Some(not_null_col) = &coll.not_null_column {
606            if !row.is_not_null(not_null_col) {
607                continue;
608            }
609        }
610
611        let nested = if let Some(prefix) = &coll.column_prefix {
612            let mut prefixed_row = RowData::empty();
613            for (col, v) in &row.columns {
614                if let Some(stripped) = col.strip_prefix(prefix) {
615                    prefixed_row.set(stripped.to_string(), v.clone());
616                }
617            }
618            apply_result_map(registry, &coll.result_map, &prefixed_row).map_err(|e| {
619                ResultMapError::NestedMappingFailed {
620                    property: coll.property.clone(),
621                    reason: e.to_string(),
622                }
623            })?
624        } else {
625            apply_result_map(registry, &coll.result_map, row).map_err(|e| {
626                ResultMapError::NestedMappingFailed {
627                    property: coll.property.clone(),
628                    reason: e.to_string(),
629                }
630            })?
631        };
632
633        // collection 在单行模式下以单元素 Array 形式返回
634        // 完整合并需调用 apply_result_map_many
635        attrs.insert(
636            coll.property.clone(),
637            Value::Array(vec![Value::Object(nested)]),
638        );
639    }
640
641    Ok(attrs)
642}
643
644/// 应用 ResultMap 到多行,处理 collection 聚合
645///
646/// # 行为
647///
648/// 1. 按主键(id_mappings 的属性值)分组:同一主键的多行合并为一个实体
649/// 2. associations 取第一行解析结果
650/// 3. collections 跨行聚合:每行解析出的子实体追加到数组
651#[tracing::instrument(skip(registry, rows), fields(map_id = map_id, row_count = rows.len()))]
652pub fn apply_result_map_many(
653    registry: &ResultMapRegistry,
654    map_id: &str,
655    rows: &[RowData],
656) -> Result<Vec<HashMap<String, Value>>, ResultMapError> {
657    if rows.is_empty() {
658        return Ok(Vec::new());
659    }
660
661    let map = registry
662        .get(map_id)
663        .ok_or_else(|| ResultMapError::MapNotFound {
664            id: map_id.to_string(),
665        })?;
666
667    // 用主键属性值的字符串形式作为分组的 key
668    fn pk_key(attrs: &HashMap<String, Value>, id_mappings: &[Mapping]) -> String {
669        if id_mappings.is_empty() {
670            // 无主键映射时,按行号分组(每行独立)
671            // 这里返回空字符串,调用方需另行处理
672            return String::new();
673        }
674        let mut parts = Vec::new();
675        for m in id_mappings {
676            if let Some(v) = attrs.get(&m.property) {
677                parts.push(format!("{:?}", v));
678            } else {
679                parts.push("null".to_string());
680            }
681        }
682        parts.join("|")
683    }
684
685    // 保持插入顺序
686    let mut ordered_keys: Vec<String> = Vec::new();
687    let mut groups: HashMap<String, HashMap<String, Value>> = HashMap::new();
688    let mut collection_acc: HashMap<String, HashMap<String, Vec<Value>>> = HashMap::new();
689
690    for row in rows {
691        let attrs = apply_result_map(registry, map_id, row)?;
692        let key = pk_key(&attrs, &map.id_mappings);
693
694        if !groups.contains_key(&key) {
695            ordered_keys.push(key.clone());
696            groups.insert(key.clone(), attrs.clone());
697            collection_acc.insert(key.clone(), HashMap::new());
698        }
699
700        // 聚合 collections
701        for coll in &map.collections {
702            if let Some(Value::Array(items)) = attrs.get(&coll.property) {
703                if !items.is_empty() {
704                    let acc = collection_acc.get_mut(&key).ok_or_else(|| {
705                        ResultMapError::NestedMappingFailed {
706                            property: "collection_acc".to_string(),
707                            reason: format!("key '{}' not found in collection_acc", key),
708                        }
709                    })?;
710                    let entry = acc.entry(coll.property.clone()).or_default();
711                    for item in items {
712                        entry.push(item.clone());
713                    }
714                }
715            }
716        }
717    }
718
719    // 合并 collection 聚合结果到主属性
720    let mut result = Vec::new();
721    for key in ordered_keys {
722        let mut attrs = groups
723            .remove(&key)
724            .ok_or_else(|| ResultMapError::NestedMappingFailed {
725                property: "groups".to_string(),
726                reason: format!("key '{}' not found in groups", key),
727            })?;
728        if let Some(coll_acc) = collection_acc.remove(&key) {
729            for (prop, items) in coll_acc {
730                attrs.insert(prop, Value::Array(items));
731            }
732        }
733        result.push(attrs);
734    }
735
736    Ok(result)
737}
738
739// ============================================================================
740// 零拷贝反序列化路径(zero-copy feature)
741// ============================================================================
742
743#[cfg(feature = "zero-copy")]
744mod borrowed {
745    use super::*;
746    use crate::value_borrowed::{BorrowedRowData, BorrowedValue};
747
748    /// 零拷贝版 `apply_result_map`
749    ///
750    /// 与 `apply_result_map` 行为完全一致,但返回 `BorrowedValue`(字符串/字节借用引用),
751    /// 消除 `v.clone()` 的深拷贝。
752    #[tracing::instrument(skip(registry, row), fields(map_id = map_id))]
753    pub fn apply_result_map_borrowed<'a>(
754        registry: &ResultMapRegistry,
755        map_id: &str,
756        row: &BorrowedRowData<'a>,
757    ) -> Result<HashMap<String, BorrowedValue<'a>>, ResultMapError> {
758        let map = registry
759            .get(map_id)
760            .ok_or_else(|| ResultMapError::MapNotFound {
761                id: map_id.to_string(),
762            })?;
763
764        let effective_map = if let Some(disc) = &map.discriminator {
765            if let Some(disc_value) = row.get(&disc.column) {
766                let owned_disc = disc_value.to_owned_value();
767                if let Some(case_map_id) = disc.resolve(&owned_disc) {
768                    registry.get(case_map_id).unwrap_or(map)
769                } else {
770                    map
771                }
772            } else {
773                map
774            }
775        } else {
776            map
777        };
778
779        let mut attrs: HashMap<String, BorrowedValue<'a>> = HashMap::new();
780
781        for m in &effective_map.id_mappings {
782            if let Some(v) = row.get(&m.column) {
783                attrs.insert(m.property.clone(), v.clone());
784            }
785        }
786        for m in &effective_map.result_mappings {
787            if let Some(v) = row.get(&m.column) {
788                attrs.insert(m.property.clone(), v.clone());
789            }
790        }
791
792        for assoc in &effective_map.associations {
793            if let Some(not_null_col) = &assoc.not_null_column {
794                if !row.is_not_null(not_null_col) {
795                    continue;
796                }
797            }
798
799            let nested_value = if let Some(prefix) = &assoc.column_prefix {
800                let mut prefixed_row = BorrowedRowData::new();
801                for (col, v) in row.iter() {
802                    if let Some(stripped) = col.strip_prefix(prefix) {
803                        prefixed_row.set(stripped.to_string(), v.clone());
804                    }
805                }
806                apply_result_map_borrowed(registry, &assoc.result_map, &prefixed_row).map_err(
807                    |e| ResultMapError::NestedMappingFailed {
808                        property: assoc.property.clone(),
809                        reason: e.to_string(),
810                    },
811                )?
812            } else {
813                apply_result_map_borrowed(registry, &assoc.result_map, row).map_err(|e| {
814                    ResultMapError::NestedMappingFailed {
815                        property: assoc.property.clone(),
816                        reason: e.to_string(),
817                    }
818                })?
819            };
820
821            attrs.insert(assoc.property.clone(), BorrowedValue::Object(nested_value));
822        }
823
824        for coll in &effective_map.collections {
825            if let Some(not_null_col) = &coll.not_null_column {
826                if !row.is_not_null(not_null_col) {
827                    continue;
828                }
829            }
830
831            let nested = if let Some(prefix) = &coll.column_prefix {
832                let mut prefixed_row = BorrowedRowData::new();
833                for (col, v) in row.iter() {
834                    if let Some(stripped) = col.strip_prefix(prefix) {
835                        prefixed_row.set(stripped.to_string(), v.clone());
836                    }
837                }
838                apply_result_map_borrowed(registry, &coll.result_map, &prefixed_row).map_err(
839                    |e| ResultMapError::NestedMappingFailed {
840                        property: coll.property.clone(),
841                        reason: e.to_string(),
842                    },
843                )?
844            } else {
845                apply_result_map_borrowed(registry, &coll.result_map, row).map_err(|e| {
846                    ResultMapError::NestedMappingFailed {
847                        property: coll.property.clone(),
848                        reason: e.to_string(),
849                    }
850                })?
851            };
852
853            attrs.insert(
854                coll.property.clone(),
855                BorrowedValue::Array(vec![BorrowedValue::Object(nested)]),
856            );
857        }
858
859        Ok(attrs)
860    }
861
862    /// 零拷贝版 `apply_result_map_many`
863    ///
864    /// 与 `apply_result_map_many` 行为完全一致,但返回 `BorrowedValue`。
865    #[tracing::instrument(skip(registry, rows), fields(map_id = map_id, row_count = rows.len()))]
866    pub fn apply_result_map_many_borrowed<'a>(
867        registry: &ResultMapRegistry,
868        map_id: &str,
869        rows: &[BorrowedRowData<'a>],
870    ) -> Result<Vec<HashMap<String, BorrowedValue<'a>>>, ResultMapError> {
871        if rows.is_empty() {
872            return Ok(Vec::new());
873        }
874
875        let map = registry
876            .get(map_id)
877            .ok_or_else(|| ResultMapError::MapNotFound {
878                id: map_id.to_string(),
879            })?;
880
881        fn pk_key_borrowed(
882            attrs: &HashMap<String, BorrowedValue<'_>>,
883            id_mappings: &[Mapping],
884        ) -> String {
885            if id_mappings.is_empty() {
886                return String::new();
887            }
888            let mut parts = Vec::new();
889            for m in id_mappings {
890                if let Some(v) = attrs.get(&m.property) {
891                    parts.push(format!("{:?}", v));
892                } else {
893                    parts.push("null".to_string());
894                }
895            }
896            parts.join("|")
897        }
898
899        let mut ordered_keys: Vec<String> = Vec::new();
900        let mut groups: HashMap<String, HashMap<String, BorrowedValue<'a>>> = HashMap::new();
901        let mut collection_acc: HashMap<String, HashMap<String, Vec<BorrowedValue<'a>>>> =
902            HashMap::new();
903
904        for row in rows {
905            let attrs = apply_result_map_borrowed(registry, map_id, row)?;
906            let key = pk_key_borrowed(&attrs, &map.id_mappings);
907
908            if !groups.contains_key(&key) {
909                ordered_keys.push(key.clone());
910                groups.insert(key.clone(), attrs.clone());
911                collection_acc.insert(key.clone(), HashMap::new());
912            }
913
914            for coll in &map.collections {
915                if let Some(BorrowedValue::Array(items)) = attrs.get(&coll.property) {
916                    if !items.is_empty() {
917                        let acc = collection_acc.get_mut(&key).ok_or_else(|| {
918                            ResultMapError::NestedMappingFailed {
919                                property: "collection_acc".to_string(),
920                                reason: format!("key '{}' not found in collection_acc", key),
921                            }
922                        })?;
923                        let entry = acc.entry(coll.property.clone()).or_default();
924                        for item in items {
925                            entry.push(item.clone());
926                        }
927                    }
928                }
929            }
930        }
931
932        let mut result = Vec::new();
933        for key in ordered_keys {
934            let mut attrs =
935                groups
936                    .remove(&key)
937                    .ok_or_else(|| ResultMapError::NestedMappingFailed {
938                        property: "groups".to_string(),
939                        reason: format!("key '{}' not found in groups", key),
940                    })?;
941            if let Some(coll_acc) = collection_acc.remove(&key) {
942                for (prop, items) in coll_acc {
943                    attrs.insert(prop, BorrowedValue::Array(items));
944                }
945            }
946            result.push(attrs);
947        }
948
949        Ok(result)
950    }
951}
952
953#[cfg(feature = "zero-copy")]
954pub use borrowed::{apply_result_map_borrowed, apply_result_map_many_borrowed};
955
956/// 标量结果列
957#[derive(Debug, Clone, PartialEq, Eq)]
958pub struct ScalarResult {
959    /// 列名
960    pub column: String,
961    /// 类型名(如 "i64"、"string")
962    pub type_name: String,
963}
964
965impl ScalarResult {
966    /// 创建标量结果,指定列名和类型名
967    pub fn new(column: impl Into<String>, type_name: impl Into<String>) -> Self {
968        Self {
969            column: column.into(),
970            type_name: type_name.into(),
971        }
972    }
973}
974
975/// 实体字段结果
976#[derive(Debug, Clone, PartialEq, Eq)]
977pub struct FieldResult {
978    /// 字段名(实体属性名)
979    pub name: String,
980    /// 对应的数据库列名
981    pub column: String,
982}
983
984impl FieldResult {
985    /// 创建字段结果,指定实体属性名和数据库列名
986    pub fn new(name: impl Into<String>, column: impl Into<String>) -> Self {
987        Self {
988            name: name.into(),
989            column: column.into(),
990        }
991    }
992}
993
994/// Entity 结果(用于 ResultSetMapping)
995#[derive(Debug, Clone, PartialEq, Eq)]
996pub struct EntityResult {
997    /// 实体类名
998    pub entity_class: String,
999    /// 字段映射列表
1000    pub fields: Vec<FieldResult>,
1001    /// 鉴别器列名(用于多态映射)
1002    pub discriminator_column: Option<String>,
1003}
1004
1005impl EntityResult {
1006    /// 创建实体结果,指定类名
1007    pub fn new(entity_class: impl Into<String>) -> Self {
1008        Self {
1009            entity_class: entity_class.into(),
1010            fields: Vec::new(),
1011            discriminator_column: None,
1012        }
1013    }
1014
1015    /// 添加一个字段映射
1016    pub fn add_field(&mut self, field: FieldResult) -> &mut Self {
1017        self.fields.push(field);
1018        self
1019    }
1020
1021    /// 设置鉴别器列名
1022    pub fn with_discriminator_column(mut self, col: impl Into<String>) -> Self {
1023        self.discriminator_column = Some(col.into());
1024        self
1025    }
1026}
1027
1028/// Hibernate `@SqlResultSetMapping` 风格的结果集映射
1029#[derive(Debug, Clone, PartialEq)]
1030pub struct ResultSetMapping {
1031    /// 映射名称
1032    pub name: String,
1033    /// 实体结果列表
1034    pub entities: Vec<EntityResult>,
1035    /// 标量结果列表
1036    pub scalars: Vec<ScalarResult>,
1037}
1038
1039impl ResultSetMapping {
1040    /// 创建结果集映射,指定名称
1041    pub fn new(name: impl Into<String>) -> Self {
1042        Self {
1043            name: name.into(),
1044            entities: Vec::new(),
1045            scalars: Vec::new(),
1046        }
1047    }
1048
1049    /// 添加一个实体结果
1050    pub fn add_entity(&mut self, entity: EntityResult) -> &mut Self {
1051        self.entities.push(entity);
1052        self
1053    }
1054
1055    /// 添加一个标量结果
1056    pub fn add_scalar(&mut self, scalar: ScalarResult) -> &mut Self {
1057        self.scalars.push(scalar);
1058        self
1059    }
1060}
1061
1062/// ResultSetMapping 注册中心
1063#[derive(Debug, Default)]
1064pub struct ResultSetMappingRegistry {
1065    mappings: RwLock<HashMap<String, ResultSetMapping>>,
1066}
1067
1068impl ResultSetMappingRegistry {
1069    /// 创建空的注册中心
1070    pub fn new() -> Self {
1071        Self {
1072            mappings: RwLock::new(HashMap::new()),
1073        }
1074    }
1075
1076    /// 注册一个结果集映射
1077    pub fn register(&self, mapping: ResultSetMapping) {
1078        let mut m = self.mappings.write();
1079        m.insert(mapping.name.clone(), mapping);
1080    }
1081
1082    /// 按名称查找结果集映射
1083    pub fn get(&self, name: &str) -> Option<ResultSetMapping> {
1084        let m = self.mappings.read();
1085        m.get(name).cloned()
1086    }
1087
1088    /// 判断指定名称的映射是否已注册
1089    pub fn contains(&self, name: &str) -> bool {
1090        let m = self.mappings.read();
1091        m.contains_key(name)
1092    }
1093
1094    /// 返回已注册的映射数量
1095    pub fn len(&self) -> usize {
1096        let m = self.mappings.read();
1097        m.len()
1098    }
1099
1100    /// 判断注册中心是否为空
1101    pub fn is_empty(&self) -> bool {
1102        self.len() == 0
1103    }
1104}
1105
1106// ============================================================================
1107// NativeQuery + ResultSetMapping
1108// ============================================================================
1109
1110/// NativeQuery — 原生 SQL + ResultSetMapping
1111#[derive(Debug, Clone)]
1112pub struct NativeQuery {
1113    /// SQL 语句(可含 `?` 占位符)
1114    pub sql: String,
1115    /// ResultSetMapping 名称
1116    pub result_set_mapping: String,
1117    /// 绑定参数
1118    pub parameters: Vec<Value>,
1119}
1120
1121impl NativeQuery {
1122    /// 创建原生查询,指定 SQL 和 ResultSetMapping 名称
1123    pub fn new(sql: impl Into<String>, mapping_name: impl Into<String>) -> Self {
1124        Self {
1125            sql: sql.into(),
1126            result_set_mapping: mapping_name.into(),
1127            parameters: Vec::new(),
1128        }
1129    }
1130
1131    /// 绑定单个参数
1132    pub fn bind(&mut self, value: Value) -> &mut Self {
1133        self.parameters.push(value);
1134        self
1135    }
1136
1137    /// 绑定多个参数
1138    pub fn bind_many(&mut self, values: Vec<Value>) -> &mut Self {
1139        self.parameters.extend(values);
1140        self
1141    }
1142}
1143
1144/// 应用 ResultSetMapping 到单行,返回 (entity_attrs_vec, scalar_values_vec)
1145///
1146/// 返回:
1147/// - 第一个 Vec:每个 EntityResult 对应一个 HashMap<String, Value>
1148/// - 第二个 Vec:每个 ScalarResult 对应一个 Value
1149pub fn apply_result_set_mapping(
1150    mapping: &ResultSetMapping,
1151    row: &RowData,
1152) -> ResultSetMappingResult {
1153    let mut entities = Vec::new();
1154    for ent in &mapping.entities {
1155        let mut attrs = HashMap::new();
1156        for f in &ent.fields {
1157            if let Some(v) = row.get(&f.column) {
1158                attrs.insert(f.name.clone(), v.clone());
1159            }
1160        }
1161        entities.push(attrs);
1162    }
1163
1164    let mut scalars = Vec::new();
1165    for s in &mapping.scalars {
1166        if let Some(v) = row.get(&s.column) {
1167            scalars.push(v.clone());
1168        } else {
1169            scalars.push(Value::Null);
1170        }
1171    }
1172
1173    (entities, scalars)
1174}
1175
1176/// ResultSetMapping 应用结果类型(entities + scalars)
1177pub type ResultSetMappingResult = (Vec<HashMap<String, Value>>, Vec<Value>);
1178
1179/// 应用 ResultSetMapping 到多行
1180pub fn apply_result_set_mapping_many(
1181    mapping: &ResultSetMapping,
1182    rows: &[RowData],
1183) -> Vec<ResultSetMappingResult> {
1184    rows.iter()
1185        .map(|row| apply_result_set_mapping(mapping, row))
1186        .collect()
1187}
1188
1189// ============================================================================
1190// 单元测试
1191// ============================================================================
1192
1193#[cfg(test)]
1194mod tests {
1195    use super::*;
1196
1197    // ===== Mapping =====
1198
1199    #[test]
1200    fn test_mapping_new() {
1201        let m = Mapping::new("id", "user_id");
1202        assert_eq!(m.property, "id");
1203        assert_eq!(m.column, "user_id");
1204        assert_eq!(m.type_handler, None);
1205    }
1206
1207    #[test]
1208    fn test_mapping_with_handler() {
1209        let m = Mapping::with_handler("amount", "amount", "money_handler");
1210        assert_eq!(m.property, "amount");
1211        assert_eq!(m.column, "amount");
1212        assert_eq!(m.type_handler.as_deref(), Some("money_handler"));
1213    }
1214
1215    // ===== NestedAssociation =====
1216
1217    #[test]
1218    fn test_association_new() {
1219        let a = NestedAssociation::new("dept", "deptMap");
1220        assert_eq!(a.property, "dept");
1221        assert_eq!(a.result_map, "deptMap");
1222        assert_eq!(a.column_prefix, None);
1223        assert_eq!(a.not_null_column, None);
1224    }
1225
1226    #[test]
1227    fn test_association_with_prefix() {
1228        let a = NestedAssociation::new("dept", "deptMap").with_prefix("d_");
1229        assert_eq!(a.column_prefix.as_deref(), Some("d_"));
1230    }
1231
1232    #[test]
1233    fn test_association_with_not_null_column() {
1234        let a = NestedAssociation::new("dept", "deptMap").with_not_null_column("dept_id");
1235        assert_eq!(a.not_null_column.as_deref(), Some("dept_id"));
1236    }
1237
1238    // ===== NestedCollection =====
1239
1240    #[test]
1241    fn test_collection_new() {
1242        let c = NestedCollection::new("roles", "roleMap");
1243        assert_eq!(c.property, "roles");
1244        assert_eq!(c.result_map, "roleMap");
1245        assert_eq!(c.column_prefix, None);
1246    }
1247
1248    #[test]
1249    fn test_collection_with_prefix() {
1250        let c = NestedCollection::new("roles", "roleMap").with_prefix("r_");
1251        assert_eq!(c.column_prefix.as_deref(), Some("r_"));
1252    }
1253
1254    // ===== Discriminator =====
1255
1256    #[test]
1257    fn test_discriminator_new() {
1258        let d = Discriminator::new("user_type");
1259        assert_eq!(d.column, "user_type");
1260        assert!(d.cases.is_empty());
1261    }
1262
1263    #[test]
1264    fn test_discriminator_add_case() {
1265        let mut d = Discriminator::new("user_type");
1266        d.add_case(DiscriminatorCase::new(Value::I64(1), "adminMap"))
1267            .add_case(DiscriminatorCase::new(Value::I64(2), "userMap"));
1268        assert_eq!(d.cases.len(), 2);
1269    }
1270
1271    #[test]
1272    fn test_discriminator_resolve_hit() {
1273        let mut d = Discriminator::new("user_type");
1274        d.add_case(DiscriminatorCase::new(Value::I64(1), "adminMap"))
1275            .add_case(DiscriminatorCase::new(Value::I64(2), "userMap"));
1276
1277        assert_eq!(d.resolve(&Value::I64(1)), Some("adminMap"));
1278        assert_eq!(d.resolve(&Value::I64(2)), Some("userMap"));
1279    }
1280
1281    #[test]
1282    fn test_discriminator_resolve_miss() {
1283        let mut d = Discriminator::new("user_type");
1284        d.add_case(DiscriminatorCase::new(Value::I64(1), "adminMap"));
1285
1286        assert_eq!(d.resolve(&Value::I64(99)), None);
1287    }
1288
1289    // ===== ResultMap =====
1290
1291    #[test]
1292    fn test_result_map_new() {
1293        let rm = ResultMap::new("userMap", "User");
1294        assert_eq!(rm.id, "userMap");
1295        assert_eq!(rm.type_name, "User");
1296        assert!(rm.id_mappings.is_empty());
1297        assert!(rm.result_mappings.is_empty());
1298        assert!(rm.associations.is_empty());
1299        assert!(rm.collections.is_empty());
1300        assert!(rm.discriminator.is_none());
1301    }
1302
1303    #[test]
1304    fn test_result_map_add_mappings() {
1305        let mut rm = ResultMap::new("userMap", "User");
1306        rm.add_id_mapping(Mapping::new("id", "user_id"))
1307            .add_result_mapping(Mapping::new("name", "user_name"))
1308            .add_association(NestedAssociation::new("dept", "deptMap"))
1309            .add_collection(NestedCollection::new("roles", "roleMap"));
1310
1311        assert_eq!(rm.id_mappings.len(), 1);
1312        assert_eq!(rm.result_mappings.len(), 1);
1313        assert_eq!(rm.associations.len(), 1);
1314        assert_eq!(rm.collections.len(), 1);
1315    }
1316
1317    #[test]
1318    fn test_result_map_set_discriminator() {
1319        let mut rm = ResultMap::new("userMap", "User");
1320        rm.set_discriminator(Discriminator::new("user_type"));
1321        assert!(rm.discriminator.is_some());
1322        assert_eq!(rm.discriminator.as_ref().unwrap().column, "user_type");
1323    }
1324
1325    #[test]
1326    fn test_sub_map_ids() {
1327        let mut rm = ResultMap::new("userMap", "User");
1328        rm.add_association(NestedAssociation::new("dept", "deptMap"))
1329            .add_collection(NestedCollection::new("roles", "roleMap"))
1330            .set_discriminator({
1331                let mut d = Discriminator::new("type");
1332                d.add_case(DiscriminatorCase::new(Value::I64(1), "adminMap"));
1333                d
1334            });
1335
1336        let ids = rm.sub_map_ids();
1337        assert!(ids.contains(&"deptMap".to_string()));
1338        assert!(ids.contains(&"roleMap".to_string()));
1339        assert!(ids.contains(&"adminMap".to_string()));
1340    }
1341
1342    // ===== ResultMapRegistry =====
1343
1344    #[test]
1345    fn test_registry_register_and_get() {
1346        let registry = ResultMapRegistry::new();
1347        let rm = ResultMap::new("userMap", "User");
1348        registry.register(rm);
1349
1350        assert!(registry.contains("userMap"));
1351        assert!(!registry.contains("missing"));
1352        assert_eq!(registry.len(), 1);
1353        assert!(registry.get("userMap").is_some());
1354        assert!(registry.get("missing").is_none());
1355    }
1356
1357    #[test]
1358    fn test_registry_list_ids() {
1359        let registry = ResultMapRegistry::new();
1360        registry.register(ResultMap::new("userMap", "User"));
1361        registry.register(ResultMap::new("deptMap", "Dept"));
1362
1363        let ids = registry.list_ids();
1364        assert_eq!(ids.len(), 2);
1365        assert!(ids.contains(&"userMap".to_string()));
1366        assert!(ids.contains(&"deptMap".to_string()));
1367    }
1368
1369    #[test]
1370    fn test_registry_clear() {
1371        let registry = ResultMapRegistry::new();
1372        registry.register(ResultMap::new("userMap", "User"));
1373        assert_eq!(registry.len(), 1);
1374        registry.clear();
1375        assert_eq!(registry.len(), 0);
1376    }
1377
1378    #[test]
1379    fn test_registry_overwrite() {
1380        let registry = ResultMapRegistry::new();
1381        registry.register(ResultMap::new("userMap", "User"));
1382        registry.register(ResultMap::new("userMap", "AdminUser"));
1383
1384        let rm = registry.get("userMap").unwrap();
1385        assert_eq!(rm.type_name, "AdminUser");
1386    }
1387
1388    // ===== RowData =====
1389
1390    #[test]
1391    fn test_row_data_new() {
1392        let mut cols = HashMap::new();
1393        cols.insert("id".to_string(), Value::I64(1));
1394        let row = RowData::new(cols);
1395
1396        assert_eq!(row.get("id"), Some(&Value::I64(1)));
1397        assert_eq!(row.get("missing"), None);
1398        assert_eq!(row.len(), 1);
1399    }
1400
1401    #[test]
1402    fn test_row_data_set_and_get() {
1403        let mut row = RowData::empty();
1404        row.set("name", Value::String("Alice".to_string()));
1405
1406        assert_eq!(row.get("name"), Some(&Value::String("Alice".to_string())));
1407    }
1408
1409    #[test]
1410    fn test_row_data_get_with_prefix() {
1411        let mut row = RowData::empty();
1412        row.set("dept_id", Value::I64(10));
1413        row.set("dept_name", Value::String("Engineering".to_string()));
1414
1415        assert_eq!(row.get_with_prefix("dept_", "id"), Some(&Value::I64(10)));
1416        assert_eq!(
1417            row.get_with_prefix("dept_", "name"),
1418            Some(&Value::String("Engineering".to_string()))
1419        );
1420        assert_eq!(row.get_with_prefix("dept_", "missing"), None);
1421    }
1422
1423    #[test]
1424    fn test_row_data_is_not_null() {
1425        let mut row = RowData::empty();
1426        row.set("a", Value::I64(1));
1427        row.set("b", Value::Null);
1428
1429        assert!(row.is_not_null("a"));
1430        assert!(!row.is_not_null("b"));
1431        assert!(!row.is_not_null("missing"));
1432    }
1433
1434    #[test]
1435    fn test_row_data_column_names() {
1436        let mut row = RowData::empty();
1437        row.set("id", Value::I64(1));
1438        row.set("name", Value::String("Alice".to_string()));
1439
1440        let names = row.column_names();
1441        assert_eq!(names.len(), 2);
1442        assert!(names.contains(&"id".to_string()));
1443        assert!(names.contains(&"name".to_string()));
1444    }
1445
1446    // ===== apply_result_map 基础 =====
1447
1448    #[test]
1449    fn test_apply_result_map_basic() {
1450        let registry = ResultMapRegistry::new();
1451        let mut rm = ResultMap::new("userMap", "User");
1452        rm.add_id_mapping(Mapping::new("id", "user_id"))
1453            .add_result_mapping(Mapping::new("name", "user_name"));
1454        registry.register(rm);
1455
1456        let mut row = RowData::empty();
1457        row.set("user_id", Value::I64(1));
1458        row.set("user_name", Value::String("Alice".to_string()));
1459
1460        let attrs = apply_result_map(&registry, "userMap", &row).unwrap();
1461        assert_eq!(attrs.get("id"), Some(&Value::I64(1)));
1462        assert_eq!(attrs.get("name"), Some(&Value::String("Alice".to_string())));
1463    }
1464
1465    #[test]
1466    fn test_apply_result_map_missing_column() {
1467        let registry = ResultMapRegistry::new();
1468        let mut rm = ResultMap::new("userMap", "User");
1469        rm.add_id_mapping(Mapping::new("id", "user_id"))
1470            .add_result_mapping(Mapping::new("name", "user_name"));
1471        registry.register(rm);
1472
1473        let row = RowData::empty();
1474        let attrs = apply_result_map(&registry, "userMap", &row).unwrap();
1475        // 缺失列不报错,对应属性不出现
1476        assert!(!attrs.contains_key("id"));
1477        assert!(!attrs.contains_key("name"));
1478    }
1479
1480    #[test]
1481    fn test_apply_result_map_not_found() {
1482        let registry = ResultMapRegistry::new();
1483        let row = RowData::empty();
1484        let err = apply_result_map(&registry, "missingMap", &row).unwrap_err();
1485        match err {
1486            ResultMapError::MapNotFound { id } => assert_eq!(id, "missingMap"),
1487            _ => panic!("expected MapNotFound"),
1488        }
1489    }
1490
1491    // ===== apply_result_map association =====
1492
1493    #[test]
1494    fn test_apply_result_map_with_association() {
1495        let registry = ResultMapRegistry::new();
1496
1497        let mut dept_map = ResultMap::new("deptMap", "Dept");
1498        dept_map
1499            .add_id_mapping(Mapping::new("id", "dept_id"))
1500            .add_result_mapping(Mapping::new("name", "dept_name"));
1501        registry.register(dept_map);
1502
1503        let mut user_map = ResultMap::new("userMap", "User");
1504        user_map
1505            .add_id_mapping(Mapping::new("id", "user_id"))
1506            .add_result_mapping(Mapping::new("name", "user_name"))
1507            .add_association(NestedAssociation::new("dept", "deptMap"));
1508        registry.register(user_map);
1509
1510        let mut row = RowData::empty();
1511        row.set("user_id", Value::I64(1));
1512        row.set("user_name", Value::String("Alice".to_string()));
1513        row.set("dept_id", Value::I64(10));
1514        row.set("dept_name", Value::String("Engineering".to_string()));
1515
1516        let attrs = apply_result_map(&registry, "userMap", &row).unwrap();
1517        assert_eq!(attrs.get("id"), Some(&Value::I64(1)));
1518        let dept = attrs.get("dept");
1519        assert!(dept.is_some());
1520        if let Some(Value::Object(dept_attrs)) = dept {
1521            assert_eq!(dept_attrs.get("id"), Some(&Value::I64(10)));
1522            assert_eq!(
1523                dept_attrs.get("name"),
1524                Some(&Value::String("Engineering".to_string()))
1525            );
1526        }
1527    }
1528
1529    #[test]
1530    fn test_apply_result_map_association_not_null_column_skip() {
1531        let registry = ResultMapRegistry::new();
1532
1533        let mut dept_map = ResultMap::new("deptMap", "Dept");
1534        dept_map
1535            .add_id_mapping(Mapping::new("id", "dept_id"))
1536            .add_result_mapping(Mapping::new("name", "dept_name"));
1537        registry.register(dept_map);
1538
1539        let mut user_map = ResultMap::new("userMap", "User");
1540        user_map
1541            .add_id_mapping(Mapping::new("id", "user_id"))
1542            .add_result_mapping(Mapping::new("name", "user_name"))
1543            .add_association(
1544                NestedAssociation::new("dept", "deptMap").with_not_null_column("dept_id"),
1545            );
1546        registry.register(user_map);
1547
1548        // dept_id 为 NULL(LEFT JOIN 缺失行)
1549        let mut row = RowData::empty();
1550        row.set("user_id", Value::I64(1));
1551        row.set("user_name", Value::String("Alice".to_string()));
1552        row.set("dept_id", Value::Null);
1553
1554        let attrs = apply_result_map(&registry, "userMap", &row).unwrap();
1555        // dept 应该被跳过(不出现)
1556        assert!(!attrs.contains_key("dept"));
1557    }
1558
1559    #[test]
1560    fn test_apply_result_map_association_with_prefix() {
1561        let registry = ResultMapRegistry::new();
1562
1563        let mut dept_map = ResultMap::new("deptMap", "Dept");
1564        dept_map
1565            .add_id_mapping(Mapping::new("id", "id"))
1566            .add_result_mapping(Mapping::new("name", "name"));
1567        registry.register(dept_map);
1568
1569        let mut user_map = ResultMap::new("userMap", "User");
1570        user_map
1571            .add_id_mapping(Mapping::new("id", "id"))
1572            .add_result_mapping(Mapping::new("name", "name"))
1573            .add_association(NestedAssociation::new("dept", "deptMap").with_prefix("d_"));
1574        registry.register(user_map);
1575
1576        // 列名带 d_ 前缀
1577        let mut row = RowData::empty();
1578        row.set("id", Value::I64(1));
1579        row.set("name", Value::String("Alice".to_string()));
1580        row.set("d_id", Value::I64(10));
1581        row.set("d_name", Value::String("Engineering".to_string()));
1582
1583        let attrs = apply_result_map(&registry, "userMap", &row).unwrap();
1584        assert_eq!(attrs.get("id"), Some(&Value::I64(1)));
1585        assert_eq!(attrs.get("name"), Some(&Value::String("Alice".to_string())));
1586
1587        if let Some(Value::Object(dept_attrs)) = attrs.get("dept") {
1588            assert_eq!(dept_attrs.get("id"), Some(&Value::I64(10)));
1589            assert_eq!(
1590                dept_attrs.get("name"),
1591                Some(&Value::String("Engineering".to_string()))
1592            );
1593        } else {
1594            panic!("dept should be an Object");
1595        }
1596    }
1597
1598    // ===== apply_result_map discriminator =====
1599
1600    #[test]
1601    fn test_apply_result_map_discriminator() {
1602        let registry = ResultMapRegistry::new();
1603
1604        // adminMap
1605        let mut admin_map = ResultMap::new("adminMap", "AdminUser");
1606        admin_map
1607            .add_id_mapping(Mapping::new("id", "user_id"))
1608            .add_result_mapping(Mapping::new("name", "user_name"))
1609            .add_result_mapping(Mapping::new("admin_level", "extra_level"));
1610        registry.register(admin_map);
1611
1612        // normalMap
1613        let mut normal_map = ResultMap::new("normalMap", "NormalUser");
1614        normal_map
1615            .add_id_mapping(Mapping::new("id", "user_id"))
1616            .add_result_mapping(Mapping::new("name", "user_name"));
1617        registry.register(normal_map);
1618
1619        // baseMap with discriminator
1620        let mut base_map = ResultMap::new("baseMap", "User");
1621        base_map
1622            .add_id_mapping(Mapping::new("id", "user_id"))
1623            .add_result_mapping(Mapping::new("name", "user_name"))
1624            .set_discriminator({
1625                let mut d = Discriminator::new("user_type");
1626                d.add_case(DiscriminatorCase::new(Value::I64(1), "adminMap"));
1627                d.add_case(DiscriminatorCase::new(Value::I64(2), "normalMap"));
1628                d
1629            });
1630        registry.register(base_map);
1631
1632        // user_type=1 → adminMap
1633        let mut row = RowData::empty();
1634        row.set("user_id", Value::I64(1));
1635        row.set("user_name", Value::String("Alice".to_string()));
1636        row.set("user_type", Value::I64(1));
1637        row.set("extra_level", Value::I64(5));
1638
1639        let attrs = apply_result_map(&registry, "baseMap", &row).unwrap();
1640        assert_eq!(attrs.get("id"), Some(&Value::I64(1)));
1641        assert_eq!(attrs.get("admin_level"), Some(&Value::I64(5)));
1642
1643        // user_type=2 → normalMap
1644        let mut row2 = RowData::empty();
1645        row2.set("user_id", Value::I64(2));
1646        row2.set("user_name", Value::String("Bob".to_string()));
1647        row2.set("user_type", Value::I64(2));
1648
1649        let attrs2 = apply_result_map(&registry, "baseMap", &row2).unwrap();
1650        assert_eq!(attrs2.get("id"), Some(&Value::I64(2)));
1651        assert!(!attrs2.contains_key("admin_level")); // normalMap 没有 admin_level
1652    }
1653
1654    #[test]
1655    fn test_apply_result_map_discriminator_no_match_falls_back_to_base() {
1656        let registry = ResultMapRegistry::new();
1657
1658        let mut base_map = ResultMap::new("baseMap", "User");
1659        base_map
1660            .add_id_mapping(Mapping::new("id", "user_id"))
1661            .set_discriminator({
1662                let mut d = Discriminator::new("user_type");
1663                d.add_case(DiscriminatorCase::new(Value::I64(1), "adminMap"));
1664                d
1665            });
1666        registry.register(base_map);
1667
1668        // user_type=99 → 无匹配,使用 baseMap
1669        let mut row = RowData::empty();
1670        row.set("user_id", Value::I64(1));
1671        row.set("user_type", Value::I64(99));
1672
1673        let attrs = apply_result_map(&registry, "baseMap", &row).unwrap();
1674        assert_eq!(attrs.get("id"), Some(&Value::I64(1)));
1675    }
1676
1677    // ===== apply_result_map_many collection 聚合 =====
1678
1679    #[test]
1680    fn test_apply_result_map_many_collection_aggregation() {
1681        let registry = ResultMapRegistry::new();
1682
1683        let mut role_map = ResultMap::new("roleMap", "Role");
1684        role_map
1685            .add_id_mapping(Mapping::new("id", "role_id"))
1686            .add_result_mapping(Mapping::new("name", "role_name"));
1687        registry.register(role_map);
1688
1689        let mut user_map = ResultMap::new("userMap", "User");
1690        user_map
1691            .add_id_mapping(Mapping::new("id", "user_id"))
1692            .add_result_mapping(Mapping::new("name", "user_name"))
1693            .add_collection(NestedCollection::new("roles", "roleMap"));
1694        registry.register(user_map);
1695
1696        // 用户 1 有 2 个角色
1697        let rows = vec![
1698            {
1699                let mut r = RowData::empty();
1700                r.set("user_id", Value::I64(1));
1701                r.set("user_name", Value::String("Alice".to_string()));
1702                r.set("role_id", Value::I64(100));
1703                r.set("role_name", Value::String("admin".to_string()));
1704                r
1705            },
1706            {
1707                let mut r = RowData::empty();
1708                r.set("user_id", Value::I64(1));
1709                r.set("user_name", Value::String("Alice".to_string()));
1710                r.set("role_id", Value::I64(101));
1711                r.set("role_name", Value::String("editor".to_string()));
1712                r
1713            },
1714        ];
1715
1716        let result = apply_result_map_many(&registry, "userMap", &rows).unwrap();
1717        assert_eq!(result.len(), 1); // 合并为 1 个用户
1718        let user = &result[0];
1719        assert_eq!(user.get("id"), Some(&Value::I64(1)));
1720        let roles = user.get("roles");
1721        assert!(roles.is_some());
1722        if let Some(Value::Array(items)) = roles {
1723            assert_eq!(items.len(), 2);
1724        }
1725    }
1726
1727    #[test]
1728    fn test_apply_result_map_many_multi_users() {
1729        let registry = ResultMapRegistry::new();
1730
1731        let mut role_map = ResultMap::new("roleMap", "Role");
1732        role_map
1733            .add_id_mapping(Mapping::new("id", "role_id"))
1734            .add_result_mapping(Mapping::new("name", "role_name"));
1735        registry.register(role_map);
1736
1737        let mut user_map = ResultMap::new("userMap", "User");
1738        user_map
1739            .add_id_mapping(Mapping::new("id", "user_id"))
1740            .add_result_mapping(Mapping::new("name", "user_name"))
1741            .add_collection(NestedCollection::new("roles", "roleMap"));
1742        registry.register(user_map);
1743
1744        let rows = vec![
1745            {
1746                let mut r = RowData::empty();
1747                r.set("user_id", Value::I64(1));
1748                r.set("user_name", Value::String("Alice".to_string()));
1749                r.set("role_id", Value::I64(100));
1750                r.set("role_name", Value::String("admin".to_string()));
1751                r
1752            },
1753            {
1754                let mut r = RowData::empty();
1755                r.set("user_id", Value::I64(2));
1756                r.set("user_name", Value::String("Bob".to_string()));
1757                r.set("role_id", Value::I64(101));
1758                r.set("role_name", Value::String("editor".to_string()));
1759                r
1760            },
1761        ];
1762
1763        let result = apply_result_map_many(&registry, "userMap", &rows).unwrap();
1764        assert_eq!(result.len(), 2);
1765        // 保持插入顺序
1766        assert_eq!(result[0].get("id"), Some(&Value::I64(1)));
1767        assert_eq!(result[1].get("id"), Some(&Value::I64(2)));
1768    }
1769
1770    #[test]
1771    fn test_apply_result_map_many_empty() {
1772        let registry = ResultMapRegistry::new();
1773        registry.register(ResultMap::new("userMap", "User"));
1774
1775        let result = apply_result_map_many(&registry, "userMap", &[]).unwrap();
1776        assert!(result.is_empty());
1777    }
1778
1779    // ===== ResultSetMapping =====
1780
1781    #[test]
1782    fn test_entity_result_new() {
1783        let er = EntityResult::new("User");
1784        assert_eq!(er.entity_class, "User");
1785        assert!(er.fields.is_empty());
1786        assert_eq!(er.discriminator_column, None);
1787    }
1788
1789    #[test]
1790    fn test_entity_result_add_field() {
1791        let mut er = EntityResult::new("User");
1792        er.add_field(FieldResult::new("id", "user_id"))
1793            .add_field(FieldResult::new("name", "user_name"));
1794        assert_eq!(er.fields.len(), 2);
1795    }
1796
1797    #[test]
1798    fn test_entity_result_with_discriminator() {
1799        let er = EntityResult::new("User").with_discriminator_column("user_type");
1800        assert_eq!(er.discriminator_column.as_deref(), Some("user_type"));
1801    }
1802
1803    #[test]
1804    fn test_scalar_result_new() {
1805        let s = ScalarResult::new("count", "i64");
1806        assert_eq!(s.column, "count");
1807        assert_eq!(s.type_name, "i64");
1808    }
1809
1810    #[test]
1811    fn test_result_set_mapping_new() {
1812        let rsm = ResultSetMapping::new("userCount");
1813        assert_eq!(rsm.name, "userCount");
1814        assert!(rsm.entities.is_empty());
1815        assert!(rsm.scalars.is_empty());
1816    }
1817
1818    #[test]
1819    fn test_result_set_mapping_add() {
1820        let mut rsm = ResultSetMapping::new("userWithCount");
1821        rsm.add_entity(EntityResult::new("User"))
1822            .add_scalar(ScalarResult::new("total", "i64"));
1823        assert_eq!(rsm.entities.len(), 1);
1824        assert_eq!(rsm.scalars.len(), 1);
1825    }
1826
1827    // ===== ResultSetMappingRegistry =====
1828
1829    #[test]
1830    fn test_rsm_registry() {
1831        let reg = ResultSetMappingRegistry::new();
1832        reg.register(ResultSetMapping::new("mapping1"));
1833        assert!(reg.contains("mapping1"));
1834        assert!(!reg.contains("missing"));
1835        assert_eq!(reg.len(), 1);
1836        assert!(reg.get("mapping1").is_some());
1837        assert!(reg.get("missing").is_none());
1838    }
1839
1840    // ===== NativeQuery =====
1841
1842    #[test]
1843    fn test_native_query_new() {
1844        let nq = NativeQuery::new("SELECT * FROM users WHERE id = ?", "userMapping");
1845        assert_eq!(nq.sql, "SELECT * FROM users WHERE id = ?");
1846        assert_eq!(nq.result_set_mapping, "userMapping");
1847        assert!(nq.parameters.is_empty());
1848    }
1849
1850    #[test]
1851    fn test_native_query_bind() {
1852        let mut nq = NativeQuery::new("SELECT * FROM users WHERE id = ?", "userMapping");
1853        nq.bind(Value::I64(1));
1854        assert_eq!(nq.parameters.len(), 1);
1855        assert_eq!(nq.parameters[0], Value::I64(1));
1856    }
1857
1858    #[test]
1859    fn test_native_query_bind_many() {
1860        let mut nq = NativeQuery::new("SELECT * FROM users WHERE id IN (?, ?)", "userMapping");
1861        nq.bind_many(vec![Value::I64(1), Value::I64(2)]);
1862        assert_eq!(nq.parameters.len(), 2);
1863    }
1864
1865    // ===== apply_result_set_mapping =====
1866
1867    #[test]
1868    fn test_apply_result_set_mapping_entities_only() {
1869        let mut rsm = ResultSetMapping::new("userMapping");
1870        let mut er = EntityResult::new("User");
1871        er.add_field(FieldResult::new("id", "user_id"))
1872            .add_field(FieldResult::new("name", "user_name"));
1873        rsm.add_entity(er);
1874
1875        let mut row = RowData::empty();
1876        row.set("user_id", Value::I64(1));
1877        row.set("user_name", Value::String("Alice".to_string()));
1878
1879        let (entities, scalars) = apply_result_set_mapping(&rsm, &row);
1880        assert_eq!(entities.len(), 1);
1881        assert_eq!(entities[0].get("id"), Some(&Value::I64(1)));
1882        assert_eq!(
1883            entities[0].get("name"),
1884            Some(&Value::String("Alice".to_string()))
1885        );
1886        assert!(scalars.is_empty());
1887    }
1888
1889    #[test]
1890    fn test_apply_result_set_mapping_scalars_only() {
1891        let mut rsm = ResultSetMapping::new("countMapping");
1892        rsm.add_scalar(ScalarResult::new("total", "i64"))
1893            .add_scalar(ScalarResult::new("avg_age", "f64"));
1894
1895        let mut row = RowData::empty();
1896        row.set("total", Value::I64(100));
1897        row.set("avg_age", Value::F64(25.5));
1898
1899        let (entities, scalars) = apply_result_set_mapping(&rsm, &row);
1900        assert!(entities.is_empty());
1901        assert_eq!(scalars.len(), 2);
1902        assert_eq!(scalars[0], Value::I64(100));
1903        assert_eq!(scalars[1], Value::F64(25.5));
1904    }
1905
1906    #[test]
1907    fn test_apply_result_set_mapping_mixed() {
1908        let mut rsm = ResultSetMapping::new("userWithCount");
1909        let mut er = EntityResult::new("User");
1910        er.add_field(FieldResult::new("id", "user_id"))
1911            .add_field(FieldResult::new("name", "user_name"));
1912        rsm.add_entity(er);
1913        rsm.add_scalar(ScalarResult::new("total_orders", "i64"));
1914
1915        let mut row = RowData::empty();
1916        row.set("user_id", Value::I64(1));
1917        row.set("user_name", Value::String("Alice".to_string()));
1918        row.set("total_orders", Value::I64(42));
1919
1920        let (entities, scalars) = apply_result_set_mapping(&rsm, &row);
1921        assert_eq!(entities.len(), 1);
1922        assert_eq!(scalars.len(), 1);
1923        assert_eq!(entities[0].get("id"), Some(&Value::I64(1)));
1924        assert_eq!(scalars[0], Value::I64(42));
1925    }
1926
1927    #[test]
1928    fn test_apply_result_set_mapping_many() {
1929        let mut rsm = ResultSetMapping::new("userMapping");
1930        let mut er = EntityResult::new("User");
1931        er.add_field(FieldResult::new("id", "user_id"));
1932        rsm.add_entity(er);
1933
1934        let rows = vec![
1935            {
1936                let mut r = RowData::empty();
1937                r.set("user_id", Value::I64(1));
1938                r
1939            },
1940            {
1941                let mut r = RowData::empty();
1942                r.set("user_id", Value::I64(2));
1943                r
1944            },
1945        ];
1946
1947        let results = apply_result_set_mapping_many(&rsm, &rows);
1948        assert_eq!(results.len(), 2);
1949        assert_eq!(results[0].0[0].get("id"), Some(&Value::I64(1)));
1950        assert_eq!(results[1].0[0].get("id"), Some(&Value::I64(2)));
1951    }
1952
1953    // ===== 端到端场景 =====
1954
1955    #[test]
1956    fn test_e2e_user_with_dept_and_roles() {
1957        let registry = ResultMapRegistry::new();
1958
1959        // roleMap
1960        let mut role_map = ResultMap::new("roleMap", "Role");
1961        role_map
1962            .add_id_mapping(Mapping::new("id", "role_id"))
1963            .add_result_mapping(Mapping::new("name", "role_name"));
1964        registry.register(role_map);
1965
1966        // deptMap
1967        let mut dept_map = ResultMap::new("deptMap", "Dept");
1968        dept_map
1969            .add_id_mapping(Mapping::new("id", "dept_id"))
1970            .add_result_mapping(Mapping::new("name", "dept_name"));
1971        registry.register(dept_map);
1972
1973        // userMap
1974        let mut user_map = ResultMap::new("userMap", "User");
1975        user_map
1976            .add_id_mapping(Mapping::new("id", "user_id"))
1977            .add_result_mapping(Mapping::new("name", "user_name"))
1978            .add_association(NestedAssociation::new("dept", "deptMap"))
1979            .add_collection(NestedCollection::new("roles", "roleMap"));
1980        registry.register(user_map);
1981
1982        // 模拟 JOIN 查询结果:1 个用户 + 1 个部门 + 2 个角色 = 2 行
1983        let rows = vec![
1984            {
1985                let mut r = RowData::empty();
1986                r.set("user_id", Value::I64(1));
1987                r.set("user_name", Value::String("Alice".to_string()));
1988                r.set("dept_id", Value::I64(10));
1989                r.set("dept_name", Value::String("Engineering".to_string()));
1990                r.set("role_id", Value::I64(100));
1991                r.set("role_name", Value::String("admin".to_string()));
1992                r
1993            },
1994            {
1995                let mut r = RowData::empty();
1996                r.set("user_id", Value::I64(1));
1997                r.set("user_name", Value::String("Alice".to_string()));
1998                r.set("dept_id", Value::I64(10));
1999                r.set("dept_name", Value::String("Engineering".to_string()));
2000                r.set("role_id", Value::I64(101));
2001                r.set("role_name", Value::String("editor".to_string()));
2002                r
2003            },
2004        ];
2005
2006        let result = apply_result_map_many(&registry, "userMap", &rows).unwrap();
2007        assert_eq!(result.len(), 1);
2008        let user = &result[0];
2009        assert_eq!(user.get("id"), Some(&Value::I64(1)));
2010        assert_eq!(user.get("name"), Some(&Value::String("Alice".to_string())));
2011
2012        // dept association
2013        if let Some(Value::Object(dept_attrs)) = user.get("dept") {
2014            assert_eq!(dept_attrs.get("id"), Some(&Value::I64(10)));
2015            assert_eq!(
2016                dept_attrs.get("name"),
2017                Some(&Value::String("Engineering".to_string()))
2018            );
2019        } else {
2020            panic!("dept should be an Object");
2021        }
2022
2023        // roles collection
2024        if let Some(Value::Array(roles)) = user.get("roles") {
2025            assert_eq!(roles.len(), 2);
2026        } else {
2027            panic!("roles should be an Array");
2028        }
2029    }
2030
2031    #[test]
2032    fn test_e2e_native_query_with_rsm() {
2033        // 模拟:SELECT u.id AS user_id, u.name AS user_name, COUNT(o.id) AS order_count
2034        // FROM users u LEFT JOIN orders o ON o.user_id = u.id
2035        // GROUP BY u.id
2036        let mut rsm = ResultSetMapping::new("userOrderCount");
2037        let mut er = EntityResult::new("User");
2038        er.add_field(FieldResult::new("id", "user_id"))
2039            .add_field(FieldResult::new("name", "user_name"));
2040        rsm.add_entity(er);
2041        rsm.add_scalar(ScalarResult::new("order_count", "i64"));
2042
2043        let mut nq = NativeQuery::new(
2044            "SELECT u.id AS user_id, u.name AS user_name, COUNT(o.id) AS order_count FROM users u LEFT JOIN orders o ON o.user_id = u.id GROUP BY u.id",
2045            "userOrderCount",
2046        );
2047        nq.bind(Value::Null); // 仅示意绑定参数
2048
2049        // 模拟 ResultSet
2050        let rows = vec![
2051            {
2052                let mut r = RowData::empty();
2053                r.set("user_id", Value::I64(1));
2054                r.set("user_name", Value::String("Alice".to_string()));
2055                r.set("order_count", Value::I64(5));
2056                r
2057            },
2058            {
2059                let mut r = RowData::empty();
2060                r.set("user_id", Value::I64(2));
2061                r.set("user_name", Value::String("Bob".to_string()));
2062                r.set("order_count", Value::I64(3));
2063                r
2064            },
2065        ];
2066
2067        let reg = ResultSetMappingRegistry::new();
2068        reg.register(rsm.clone());
2069        assert!(reg.contains("userOrderCount"));
2070
2071        let results = apply_result_set_mapping_many(&rsm, &rows);
2072        assert_eq!(results.len(), 2);
2073        assert_eq!(results[0].0[0].get("id"), Some(&Value::I64(1)));
2074        assert_eq!(results[0].1[0], Value::I64(5));
2075        assert_eq!(results[1].0[0].get("id"), Some(&Value::I64(2)));
2076        assert_eq!(results[1].1[0], Value::I64(3));
2077
2078        // 验证 NativeQuery 字段
2079        assert_eq!(nq.result_set_mapping, "userOrderCount");
2080        assert_eq!(nq.parameters.len(), 1);
2081    }
2082
2083    // ===== 零拷贝等价性测试 =====
2084
2085    #[cfg(feature = "zero-copy")]
2086    #[test]
2087    fn test_apply_result_map_borrowed_basic_equivalence() {
2088        use crate::value_borrowed::{BorrowedRowData, BorrowedValue};
2089
2090        let registry = ResultMapRegistry::new();
2091        let mut rm = ResultMap::new("userMap", "User");
2092        rm.add_id_mapping(Mapping::new("id", "user_id"))
2093            .add_result_mapping(Mapping::new("name", "user_name"));
2094        registry.register(rm);
2095
2096        let mut row = RowData::empty();
2097        row.set("user_id", Value::I64(42));
2098        row.set("user_name", Value::String("Alice".into()));
2099
2100        let v_id = Value::I64(42);
2101        let v_name = Value::String("Alice".into());
2102        let mut borrowed_row = BorrowedRowData::new();
2103        borrowed_row.set("user_id", BorrowedValue::from_value(&v_id));
2104        borrowed_row.set("user_name", BorrowedValue::from_value(&v_name));
2105
2106        let owned_result = apply_result_map(&registry, "userMap", &row).unwrap();
2107        let borrowed_result =
2108            apply_result_map_borrowed(&registry, "userMap", &borrowed_row).unwrap();
2109
2110        assert_eq!(owned_result.len(), borrowed_result.len());
2111        assert_eq!(owned_result.get("id"), Some(&Value::I64(42)));
2112        assert_eq!(
2113            borrowed_result.get("id").map(|v| v.to_owned_value()),
2114            Some(Value::I64(42))
2115        );
2116        assert_eq!(
2117            owned_result.get("name"),
2118            Some(&Value::String("Alice".into()))
2119        );
2120        assert_eq!(
2121            borrowed_result.get("name").map(|v| v.to_owned_value()),
2122            Some(Value::String("Alice".into()))
2123        );
2124    }
2125
2126    #[cfg(feature = "zero-copy")]
2127    #[test]
2128    fn test_apply_result_map_borrowed_association_equivalence() {
2129        use crate::value_borrowed::{BorrowedRowData, BorrowedValue};
2130
2131        let registry = ResultMapRegistry::new();
2132
2133        let mut dept_map = ResultMap::new("deptMap", "Dept");
2134        dept_map
2135            .add_id_mapping(Mapping::new("id", "id"))
2136            .add_result_mapping(Mapping::new("name", "name"));
2137        registry.register(dept_map);
2138
2139        let mut user_map = ResultMap::new("userMap", "User");
2140        user_map
2141            .add_id_mapping(Mapping::new("id", "user_id"))
2142            .add_result_mapping(Mapping::new("name", "user_name"))
2143            .add_association(NestedAssociation::new("dept", "deptMap").with_prefix("dept_"));
2144        registry.register(user_map);
2145
2146        let mut row = RowData::empty();
2147        row.set("user_id", Value::I64(1));
2148        row.set("user_name", Value::String("Alice".into()));
2149        row.set("dept_id", Value::I64(10));
2150        row.set("dept_name", Value::String("Engineering".into()));
2151
2152        let mut borrowed_row = BorrowedRowData::new();
2153        for (k, v) in &row.columns {
2154            borrowed_row.set(k.clone(), BorrowedValue::from_value(v));
2155        }
2156
2157        let owned_result = apply_result_map(&registry, "userMap", &row).unwrap();
2158        let borrowed_result =
2159            apply_result_map_borrowed(&registry, "userMap", &borrowed_row).unwrap();
2160
2161        assert_eq!(owned_result.get("id"), Some(&Value::I64(1)));
2162        assert_eq!(
2163            borrowed_result.get("id").map(|v| v.to_owned_value()),
2164            Some(Value::I64(1))
2165        );
2166
2167        let owned_dept = owned_result.get("dept").and_then(|v| match v {
2168            Value::Object(m) => Some(m),
2169            _ => None,
2170        });
2171        let borrowed_dept = borrowed_result.get("dept").and_then(|v| match v {
2172            BorrowedValue::Object(m) => Some(m),
2173            _ => None,
2174        });
2175        assert!(owned_dept.is_some() && borrowed_dept.is_some());
2176        let owned_dept = owned_dept.unwrap();
2177        let borrowed_dept = borrowed_dept.unwrap();
2178        assert_eq!(owned_dept.get("id"), Some(&Value::I64(10)));
2179        assert_eq!(
2180            borrowed_dept.get("id").map(|v| v.to_owned_value()),
2181            Some(Value::I64(10))
2182        );
2183    }
2184
2185    #[cfg(feature = "zero-copy")]
2186    #[test]
2187    fn test_apply_result_map_borrowed_many_equivalence() {
2188        use crate::value_borrowed::{BorrowedRowData, BorrowedValue};
2189
2190        let registry = ResultMapRegistry::new();
2191
2192        let mut order_map = ResultMap::new("orderMap", "Order");
2193        order_map
2194            .add_id_mapping(Mapping::new("id", "order_id"))
2195            .add_result_mapping(Mapping::new("amount", "order_amount"));
2196        registry.register(order_map);
2197
2198        let mut user_map = ResultMap::new("userMap", "User");
2199        user_map
2200            .add_id_mapping(Mapping::new("id", "user_id"))
2201            .add_result_mapping(Mapping::new("name", "user_name"))
2202            .add_collection(NestedCollection::new("orders", "orderMap"));
2203        registry.register(user_map);
2204
2205        let rows: Vec<RowData> = vec![
2206            {
2207                let mut r = RowData::empty();
2208                r.set("user_id", Value::I64(1));
2209                r.set("user_name", Value::String("Alice".into()));
2210                r.set("order_id", Value::I64(100));
2211                r.set("order_amount", Value::F64(50.0));
2212                r
2213            },
2214            {
2215                let mut r = RowData::empty();
2216                r.set("user_id", Value::I64(1));
2217                r.set("user_name", Value::String("Alice".into()));
2218                r.set("order_id", Value::I64(101));
2219                r.set("order_amount", Value::F64(75.0));
2220                r
2221            },
2222        ];
2223
2224        let borrowed_rows: Vec<BorrowedRowData> = rows
2225            .iter()
2226            .map(|r| {
2227                let mut br = BorrowedRowData::new();
2228                for (k, v) in &r.columns {
2229                    br.set(k.clone(), BorrowedValue::from_value(v));
2230                }
2231                br
2232            })
2233            .collect();
2234
2235        let owned_result = apply_result_map_many(&registry, "userMap", &rows).unwrap();
2236        let borrowed_result =
2237            apply_result_map_many_borrowed(&registry, "userMap", &borrowed_rows).unwrap();
2238
2239        assert_eq!(owned_result.len(), borrowed_result.len());
2240        assert_eq!(owned_result.len(), 1);
2241
2242        let owned_orders = owned_result[0].get("orders").and_then(|v| match v {
2243            Value::Array(a) => Some(a),
2244            _ => None,
2245        });
2246        let borrowed_orders = borrowed_result[0].get("orders").and_then(|v| match v {
2247            BorrowedValue::Array(a) => Some(a),
2248            _ => None,
2249        });
2250        assert!(owned_orders.is_some() && borrowed_orders.is_some());
2251        assert_eq!(owned_orders.unwrap().len(), 2);
2252        assert_eq!(borrowed_orders.unwrap().len(), 2);
2253    }
2254
2255    #[cfg(feature = "zero-copy")]
2256    #[test]
2257    fn test_apply_result_map_borrowed_discriminator_equivalence() {
2258        use crate::value_borrowed::{BorrowedRowData, BorrowedValue};
2259
2260        let registry = ResultMapRegistry::new();
2261
2262        let mut admin_map = ResultMap::new("adminMap", "Admin");
2263        admin_map
2264            .add_id_mapping(Mapping::new("id", "id"))
2265            .add_result_mapping(Mapping::new("level", "admin_level"));
2266        registry.register(admin_map);
2267
2268        let mut user_map = ResultMap::new("userMap", "User");
2269        user_map
2270            .add_id_mapping(Mapping::new("id", "id"))
2271            .add_result_mapping(Mapping::new("name", "user_name"));
2272        registry.register(user_map);
2273
2274        let mut base_map = ResultMap::new("personMap", "Person");
2275        base_map
2276            .add_id_mapping(Mapping::new("id", "id"))
2277            .set_discriminator({
2278                let mut disc = Discriminator::new("type");
2279                disc.add_case(DiscriminatorCase::new(
2280                    Value::String("admin".into()),
2281                    "adminMap",
2282                ));
2283                disc.add_case(DiscriminatorCase::new(
2284                    Value::String("user".into()),
2285                    "userMap",
2286                ));
2287                disc
2288            });
2289        registry.register(base_map);
2290
2291        let mut row = RowData::empty();
2292        row.set("id", Value::I64(1));
2293        row.set("type", Value::String("admin".into()));
2294        row.set("admin_level", Value::I64(5));
2295
2296        let mut borrowed_row = BorrowedRowData::new();
2297        for (k, v) in &row.columns {
2298            borrowed_row.set(k.clone(), BorrowedValue::from_value(v));
2299        }
2300
2301        let owned_result = apply_result_map(&registry, "personMap", &row).unwrap();
2302        let borrowed_result =
2303            apply_result_map_borrowed(&registry, "personMap", &borrowed_row).unwrap();
2304
2305        assert_eq!(owned_result.get("level"), Some(&Value::I64(5)));
2306        assert_eq!(
2307            borrowed_result.get("level").map(|v| v.to_owned_value()),
2308            Some(Value::I64(5))
2309        );
2310    }
2311}