Skip to main content

reinhardt_db/orm/
reflection.rs

1//! Runtime reflection for ORM models
2//!
3//! This module provides functionality to inspect and manipulate model instances
4//! at runtime, allowing dynamic access to fields, relationships, and metadata.
5//!
6//! # Examples
7//!
8//! ```rust
9//! use reinhardt_db::orm::reflection::{ModelReflector, FieldInfo, FieldValue};
10//! use reinhardt_db::orm::Model;
11//! use serde::{Deserialize, Serialize};
12//!
13//! #[derive(Debug, Clone, Serialize, Deserialize)]
14//! struct User {
15//!     id: Option<i64>,
16//!     name: String,
17//!     age: i32,
18//! }
19//!
20//! # #[derive(Clone)]
21//! # struct UserFields;
22//! # impl reinhardt_db::orm::model::FieldSelector for UserFields {
23//! #     fn with_alias(self, _alias: &str) -> Self { self }
24//! # }
25//! #
26//! impl Model for User {
27//!     type PrimaryKey = i64;
28//!     type Fields = UserFields;
29//!     type Objects = reinhardt_db::orm::Manager<Self>;
30//!
31//!     fn table_name() -> &'static str {
32//!         "users"
33//!     }
34//!
35//!     fn new_fields() -> Self::Fields {
36//!         UserFields
37//!     }
38//!
39//!     fn primary_key(&self) -> Option<Self::PrimaryKey> {
40//!         self.id
41//!     }
42//!
43//!     fn set_primary_key(&mut self, value: Self::PrimaryKey) {
44//!         self.id = Some(value);
45//!     }
46//! }
47//!
48//! // Create a reflector for the User type
49//! let reflector = ModelReflector::for_model::<User>();
50//! assert_eq!(reflector.table_name(), "users");
51//!
52//! // Serialize a user instance to inspect field values
53//! let user = User {
54//!     id: Some(1),
55//!     name: "Alice".to_string(),
56//!     age: 30,
57//! };
58//! let name_value = reflector.get_field_value(&user, "name").unwrap();
59//! assert_eq!(name_value.as_str(), Some("Alice"));
60//! ```
61
62use crate::orm::model::Model;
63use crate::orm::registry::registry;
64use serde::{Deserialize, Serialize};
65use std::any::TypeId;
66use std::collections::HashMap;
67use std::fmt;
68
69/// Error types for reflection operations
70#[non_exhaustive]
71#[derive(Debug, Clone, PartialEq)]
72pub enum ReflectionError {
73	/// Model not found in registry
74	ModelNotFound(String),
75	/// Field not found in model
76	FieldNotFound(String),
77	/// Type mismatch when accessing field
78	TypeMismatch {
79		/// The expected type name.
80		expected: String,
81		/// The actual type name.
82		actual: String,
83	},
84	/// Invalid operation
85	InvalidOperation(String),
86	/// Serialization/deserialization error
87	SerializationError(String),
88}
89
90impl fmt::Display for ReflectionError {
91	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92		match self {
93			ReflectionError::ModelNotFound(name) => write!(f, "Model not found: {}", name),
94			ReflectionError::FieldNotFound(name) => write!(f, "Field not found: {}", name),
95			ReflectionError::TypeMismatch { expected, actual } => {
96				write!(f, "Type mismatch: expected {}, got {}", expected, actual)
97			}
98			ReflectionError::InvalidOperation(msg) => write!(f, "Invalid operation: {}", msg),
99			ReflectionError::SerializationError(msg) => {
100				write!(f, "Serialization error: {}", msg)
101			}
102		}
103	}
104}
105
106impl std::error::Error for ReflectionError {}
107
108/// Field value wrapper that can hold different types
109#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
110#[serde(untagged)]
111pub enum FieldValue {
112	/// Null value
113	Null,
114	/// Boolean value
115	Bool(bool),
116	/// Integer value
117	Int(i64),
118	/// Floating point value
119	Float(f64),
120	/// String value
121	String(String),
122	/// Bytes value
123	Bytes(Vec<u8>),
124	/// Array of values
125	Array(Vec<FieldValue>),
126	/// Object (map of field name to value)
127	Object(HashMap<String, FieldValue>),
128}
129
130impl FieldValue {
131	/// Check if the value is null
132	///
133	/// # Examples
134	///
135	/// ```
136	/// use reinhardt_db::orm::reflection::FieldValue;
137	///
138	/// let value = FieldValue::Null;
139	/// assert!(value.is_null());
140	///
141	/// let value = FieldValue::Int(42);
142	/// assert!(!value.is_null());
143	/// ```
144	pub fn is_null(&self) -> bool {
145		matches!(self, FieldValue::Null)
146	}
147
148	/// Try to convert to i64
149	///
150	/// # Examples
151	///
152	/// ```
153	/// use reinhardt_db::orm::reflection::FieldValue;
154	///
155	/// let value = FieldValue::Int(42);
156	/// assert_eq!(value.as_i64(), Some(42));
157	///
158	/// let value = FieldValue::String("hello".to_string());
159	/// assert_eq!(value.as_i64(), None);
160	/// ```
161	pub fn as_i64(&self) -> Option<i64> {
162		match self {
163			FieldValue::Int(v) => Some(*v),
164			_ => None,
165		}
166	}
167
168	/// Try to convert to f64
169	pub fn as_f64(&self) -> Option<f64> {
170		match self {
171			FieldValue::Float(v) => Some(*v),
172			FieldValue::Int(v) => Some(*v as f64),
173			_ => None,
174		}
175	}
176
177	/// Try to convert to string
178	pub fn as_str(&self) -> Option<&str> {
179		match self {
180			FieldValue::String(s) => Some(s),
181			_ => None,
182		}
183	}
184
185	/// Try to convert to bool
186	pub fn as_bool(&self) -> Option<bool> {
187		match self {
188			FieldValue::Bool(b) => Some(*b),
189			_ => None,
190		}
191	}
192}
193
194impl From<i64> for FieldValue {
195	fn from(value: i64) -> Self {
196		FieldValue::Int(value)
197	}
198}
199
200impl From<i32> for FieldValue {
201	fn from(value: i32) -> Self {
202		FieldValue::Int(value as i64)
203	}
204}
205
206impl From<f64> for FieldValue {
207	fn from(value: f64) -> Self {
208		FieldValue::Float(value)
209	}
210}
211
212impl From<bool> for FieldValue {
213	fn from(value: bool) -> Self {
214		FieldValue::Bool(value)
215	}
216}
217
218impl From<String> for FieldValue {
219	fn from(value: String) -> Self {
220		FieldValue::String(value)
221	}
222}
223
224impl From<&str> for FieldValue {
225	fn from(value: &str) -> Self {
226		FieldValue::String(value.to_owned())
227	}
228}
229
230/// Information about a field in a model
231#[derive(Debug, Clone, PartialEq)]
232pub struct FieldInfo {
233	/// Field name in the model
234	pub name: String,
235	/// Column name in the database
236	pub column_name: String,
237	/// SQL type of the field
238	pub field_type: String,
239	/// Whether the field can be null
240	pub nullable: bool,
241}
242
243impl FieldInfo {
244	/// Create a new FieldInfo
245	pub fn new(
246		name: impl Into<String>,
247		column_name: impl Into<String>,
248		field_type: impl Into<String>,
249		nullable: bool,
250	) -> Self {
251		Self {
252			name: name.into(),
253			column_name: column_name.into(),
254			field_type: field_type.into(),
255			nullable,
256		}
257	}
258}
259
260/// Reflector for a specific model type
261///
262/// Provides runtime introspection capabilities for model instances.
263///
264/// # Examples
265///
266/// ```rust
267/// use reinhardt_db::orm::reflection::ModelReflector;
268/// use reinhardt_db::orm::Model;
269/// use serde::{Deserialize, Serialize};
270///
271/// #[derive(Debug, Clone, Serialize, Deserialize)]
272/// struct Article {
273///     id: Option<i64>,
274///     title: String,
275///     content: String,
276/// }
277///
278/// # #[derive(Clone)]
279/// # struct ArticleFields;
280/// # impl reinhardt_db::orm::model::FieldSelector for ArticleFields {
281/// #     fn with_alias(self, _alias: &str) -> Self { self }
282/// # }
283/// #
284/// impl Model for Article {
285///     type PrimaryKey = i64;
286///     type Fields = ArticleFields;
287///     type Objects = reinhardt_db::orm::Manager<Self>;
288///
289///     fn table_name() -> &'static str {
290///         "articles"
291///     }
292///
293///     fn new_fields() -> Self::Fields {
294///         ArticleFields
295///     }
296///
297///     fn primary_key(&self) -> Option<Self::PrimaryKey> {
298///         self.id
299///     }
300///
301///     fn set_primary_key(&mut self, value: Self::PrimaryKey) {
302///         self.id = Some(value);
303///     }
304/// }
305///
306/// let reflector = ModelReflector::for_model::<Article>();
307/// let table_name = reflector.table_name();
308/// assert_eq!(table_name, "articles");
309/// ```
310#[derive(Clone)]
311pub struct ModelReflector {
312	/// Model name
313	model_name: String,
314	/// Table name
315	table_name: String,
316	/// Type ID for runtime type checking
317	// Allow dead_code: stored for future runtime type-safe downcasting in reflection API
318	#[allow(dead_code)]
319	type_id: TypeId,
320}
321
322impl ModelReflector {
323	/// Create a reflector for a specific model type
324	///
325	/// # Examples
326	///
327	/// ```rust
328	/// use reinhardt_db::orm::reflection::ModelReflector;
329	/// use reinhardt_db::orm::Model;
330	/// use serde::{Deserialize, Serialize};
331	///
332	/// #[derive(Debug, Clone, Serialize, Deserialize)]
333	/// struct Product {
334	///     id: Option<i64>,
335	///     name: String,
336	/// }
337	///
338	/// # #[derive(Clone)]
339	/// # struct ProductFields;
340	/// # impl reinhardt_db::orm::model::FieldSelector for ProductFields {
341	/// #     fn with_alias(self, _alias: &str) -> Self { self }
342	/// # }
343	/// #
344	/// impl Model for Product {
345	///     type PrimaryKey = i64;
346	///     type Fields = ProductFields;
347	///     type Objects = reinhardt_db::orm::Manager<Self>;
348	///
349	///     fn table_name() -> &'static str {
350	///         "products"
351	///     }
352	///
353	///     fn new_fields() -> Self::Fields {
354	///         ProductFields
355	///     }
356	///
357	///     fn primary_key(&self) -> Option<Self::PrimaryKey> {
358	///         self.id
359	///     }
360	///
361	///     fn set_primary_key(&mut self, value: Self::PrimaryKey) {
362	///         self.id = Some(value);
363	///     }
364	/// }
365	///
366	/// let reflector = ModelReflector::for_model::<Product>();
367	/// assert_eq!(reflector.model_name(), "Product");
368	/// ```
369	pub fn for_model<M: Model + 'static>() -> Self {
370		Self {
371			model_name: std::any::type_name::<M>()
372				.split("::")
373				.last()
374				.unwrap_or("Unknown")
375				.to_owned(),
376			table_name: M::table_name().to_owned(),
377			type_id: TypeId::of::<M>(),
378		}
379	}
380
381	/// Create a reflector by model name
382	///
383	/// This looks up the model in the registry.
384	pub fn new(model_name: impl Into<String>) -> Result<Self, ReflectionError> {
385		let model_name = model_name.into();
386		let mapper = registry()
387			.get(&model_name)
388			.ok_or_else(|| ReflectionError::ModelNotFound(model_name.clone()))?;
389
390		Ok(Self {
391			table_name: mapper.table_name,
392			model_name,
393			type_id: TypeId::of::<()>(), // Default type ID when created from string
394		})
395	}
396
397	/// Get the model name
398	pub fn model_name(&self) -> &str {
399		&self.model_name
400	}
401
402	/// Get the table name
403	pub fn table_name(&self) -> &str {
404		&self.table_name
405	}
406
407	/// Get field names
408	///
409	/// # Examples
410	///
411	/// ```rust
412	/// use reinhardt_db::orm::reflection::ModelReflector;
413	/// use reinhardt_db::orm::registry::{registry, EntityMapper, ColumnMapping};
414	///
415	/// // Register a model in the registry
416	/// let mut mapper = EntityMapper::new("users");
417	/// mapper.add_column(ColumnMapping::new("id", "id", "INTEGER"));
418	/// mapper.add_column(ColumnMapping::new("name", "name", "VARCHAR"));
419	/// registry().register("User", mapper);
420	///
421	/// let reflector = ModelReflector::new("User").unwrap();
422	/// let field_names = reflector.field_names();
423	/// assert_eq!(field_names.len(), 2);
424	/// assert!(field_names.contains(&"id".to_string()));
425	/// assert!(field_names.contains(&"name".to_string()));
426	///
427	/// // Cleanup
428	/// registry().clear();
429	/// ```
430	pub fn field_names(&self) -> Vec<String> {
431		registry()
432			.get(&self.model_name)
433			.map(|mapper| {
434				mapper
435					.columns
436					.iter()
437					.map(|col| col.property_name.clone())
438					.collect()
439			})
440			.unwrap_or_default()
441	}
442
443	/// Get field information
444	pub fn fields(&self) -> Vec<FieldInfo> {
445		registry()
446			.get(&self.model_name)
447			.map(|mapper| {
448				mapper
449					.columns
450					.iter()
451					.map(|col| {
452						FieldInfo::new(
453							&col.property_name,
454							&col.column_name,
455							&col.column_type,
456							col.nullable,
457						)
458					})
459					.collect()
460			})
461			.unwrap_or_default()
462	}
463
464	/// Get information about a specific field
465	pub fn field_info(&self, field_name: &str) -> Option<FieldInfo> {
466		registry().get(&self.model_name).and_then(|mapper| {
467			mapper
468				.columns
469				.iter()
470				.find(|col| col.property_name == field_name)
471				.map(|col| {
472					FieldInfo::new(
473						&col.property_name,
474						&col.column_name,
475						&col.column_type,
476						col.nullable,
477					)
478				})
479		})
480	}
481
482	/// Get primary key field names
483	pub fn primary_key_fields(&self) -> Vec<String> {
484		registry()
485			.get(&self.model_name)
486			.map(|mapper| mapper.primary_key.clone())
487			.unwrap_or_default()
488	}
489
490	/// Serialize a model instance to a map of field values
491	pub fn serialize_to_map<M: Model + Serialize>(
492		&self,
493		instance: &M,
494	) -> Result<HashMap<String, FieldValue>, ReflectionError> {
495		let json_value = serde_json::to_value(instance)
496			.map_err(|e| ReflectionError::SerializationError(e.to_string()))?;
497
498		match json_value {
499			serde_json::Value::Object(map) => {
500				let mut result = HashMap::new();
501				for (key, value) in map {
502					result.insert(key, json_value_to_field_value(value));
503				}
504				Ok(result)
505			}
506			_ => Err(ReflectionError::SerializationError(
507				"Expected object".to_owned(),
508			)),
509		}
510	}
511
512	/// Get field value from a serializable model
513	pub fn get_field_value<M: Model + Serialize>(
514		&self,
515		instance: &M,
516		field_name: &str,
517	) -> Result<FieldValue, ReflectionError> {
518		let map = self.serialize_to_map(instance)?;
519		map.get(field_name)
520			.cloned()
521			.ok_or_else(|| ReflectionError::FieldNotFound(field_name.to_owned()))
522	}
523}
524
525impl fmt::Debug for ModelReflector {
526	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
527		f.debug_struct("ModelReflector")
528			.field("model_name", &self.model_name)
529			.field("table_name", &self.table_name)
530			.finish()
531	}
532}
533
534/// Convert serde_json::Value to FieldValue
535fn json_value_to_field_value(value: serde_json::Value) -> FieldValue {
536	match value {
537		serde_json::Value::Null => FieldValue::Null,
538		serde_json::Value::Bool(b) => FieldValue::Bool(b),
539		serde_json::Value::Number(n) => {
540			if let Some(i) = n.as_i64() {
541				FieldValue::Int(i)
542			} else if let Some(f) = n.as_f64() {
543				FieldValue::Float(f)
544			} else {
545				FieldValue::Null
546			}
547		}
548		serde_json::Value::String(s) => FieldValue::String(s),
549		serde_json::Value::Array(arr) => {
550			FieldValue::Array(arr.into_iter().map(json_value_to_field_value).collect())
551		}
552		serde_json::Value::Object(obj) => FieldValue::Object(
553			obj.into_iter()
554				.map(|(k, v)| (k, json_value_to_field_value(v)))
555				.collect(),
556		),
557	}
558}
559
560#[cfg(test)]
561mod tests {
562	use super::*;
563	use crate::orm::Manager;
564	use crate::orm::model::Model;
565	use crate::orm::registry::{ColumnMapping, EntityMapper, registry};
566	use serial_test::serial;
567
568	#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
569	struct TestUser {
570		id: Option<i64>,
571		name: String,
572		age: i32,
573		email: Option<String>,
574	}
575
576	#[derive(Debug, Clone)]
577	struct TestUserFields;
578
579	impl crate::orm::model::FieldSelector for TestUserFields {
580		fn with_alias(self, _alias: &str) -> Self {
581			self
582		}
583	}
584
585	impl Model for TestUser {
586		type PrimaryKey = i64;
587		type Fields = TestUserFields;
588		type Objects = Manager<Self>;
589
590		fn table_name() -> &'static str {
591			"test_users"
592		}
593
594		fn primary_key(&self) -> Option<Self::PrimaryKey> {
595			self.id
596		}
597
598		fn set_primary_key(&mut self, value: Self::PrimaryKey) {
599			self.id = Some(value);
600		}
601
602		fn primary_key_field() -> &'static str {
603			"id"
604		}
605
606		fn new_fields() -> Self::Fields {
607			TestUserFields
608		}
609	}
610
611	fn setup_test_registry() {
612		registry().clear();
613		let mut mapper = EntityMapper::new("test_users");
614		mapper.add_column(ColumnMapping::new("id", "id", "INTEGER").not_null());
615		mapper.add_column(ColumnMapping::new("name", "name", "VARCHAR").not_null());
616		mapper.add_column(ColumnMapping::new("age", "age", "INTEGER").not_null());
617		mapper.add_column(ColumnMapping::new("email", "email", "VARCHAR"));
618		mapper.set_primary_key(vec!["id".to_owned()]);
619		registry().register("TestUser", mapper);
620	}
621
622	#[test]
623	fn test_model_reflector_for_model() {
624		let reflector = ModelReflector::for_model::<TestUser>();
625		assert_eq!(reflector.table_name(), "test_users");
626		assert!(reflector.model_name().contains("TestUser"));
627	}
628
629	#[test]
630	#[serial]
631	fn test_model_reflector_new() {
632		setup_test_registry();
633		let reflector = ModelReflector::new("TestUser").unwrap();
634		assert_eq!(reflector.model_name(), "TestUser");
635		assert_eq!(reflector.table_name(), "test_users");
636	}
637
638	#[test]
639	#[serial]
640	fn test_model_reflector_new_not_found() {
641		registry().clear();
642		let result = ModelReflector::new("NonExistent");
643		assert!(result.is_err());
644		assert!(matches!(
645			result.unwrap_err(),
646			ReflectionError::ModelNotFound(_)
647		));
648	}
649
650	#[test]
651	#[serial]
652	fn test_model_reflector_field_names() {
653		setup_test_registry();
654		let reflector = ModelReflector::new("TestUser").unwrap();
655		let field_names = reflector.field_names();
656		assert_eq!(field_names.len(), 4);
657		assert!(field_names.contains(&"id".to_owned()));
658		assert!(field_names.contains(&"name".to_owned()));
659		assert!(field_names.contains(&"age".to_owned()));
660		assert!(field_names.contains(&"email".to_owned()));
661	}
662
663	#[test]
664	#[serial]
665	fn test_model_reflector_fields() {
666		setup_test_registry();
667		let reflector = ModelReflector::new("TestUser").unwrap();
668		let fields = reflector.fields();
669		assert_eq!(fields.len(), 4);
670
671		let id_field = fields.iter().find(|f| f.name == "id").unwrap();
672		assert_eq!(id_field.column_name, "id");
673		assert_eq!(id_field.field_type, "INTEGER");
674		assert!(!id_field.nullable);
675	}
676
677	#[test]
678	#[serial]
679	fn test_model_reflector_field_info() {
680		setup_test_registry();
681		let reflector = ModelReflector::new("TestUser").unwrap();
682
683		let name_field = reflector.field_info("name").unwrap();
684		assert_eq!(name_field.name, "name");
685		assert_eq!(name_field.column_name, "name");
686		assert_eq!(name_field.field_type, "VARCHAR");
687		assert!(!name_field.nullable);
688
689		let email_field = reflector.field_info("email").unwrap();
690		assert!(email_field.nullable);
691
692		let nonexistent = reflector.field_info("nonexistent");
693		assert!(nonexistent.is_none());
694	}
695
696	#[test]
697	#[serial]
698	fn test_model_reflector_primary_key_fields() {
699		setup_test_registry();
700		let reflector = ModelReflector::new("TestUser").unwrap();
701		let pk_fields = reflector.primary_key_fields();
702		assert_eq!(pk_fields.len(), 1);
703		assert_eq!(pk_fields[0], "id");
704	}
705
706	#[test]
707	fn test_serialize_to_map() {
708		let reflector = ModelReflector::for_model::<TestUser>();
709		let user = TestUser {
710			id: Some(1),
711			name: "Alice".to_owned(),
712			age: 30,
713			email: Some("alice@example.com".to_owned()),
714		};
715
716		let map = reflector.serialize_to_map(&user).unwrap();
717		assert_eq!(map.get("id").unwrap().as_i64(), Some(1));
718		assert_eq!(map.get("name").unwrap().as_str(), Some("Alice"));
719		assert_eq!(map.get("age").unwrap().as_i64(), Some(30));
720		assert_eq!(
721			map.get("email").unwrap().as_str(),
722			Some("alice@example.com")
723		);
724	}
725
726	#[test]
727	fn test_get_field_value() {
728		let reflector = ModelReflector::for_model::<TestUser>();
729		let user = TestUser {
730			id: Some(42),
731			name: "Bob".to_owned(),
732			age: 25,
733			email: None,
734		};
735
736		let id_value = reflector.get_field_value(&user, "id").unwrap();
737		assert_eq!(id_value.as_i64(), Some(42));
738
739		let name_value = reflector.get_field_value(&user, "name").unwrap();
740		assert_eq!(name_value.as_str(), Some("Bob"));
741
742		let age_value = reflector.get_field_value(&user, "age").unwrap();
743		assert_eq!(age_value.as_i64(), Some(25));
744
745		let email_value = reflector.get_field_value(&user, "email").unwrap();
746		assert!(email_value.is_null());
747	}
748
749	#[test]
750	fn test_field_value_conversions() {
751		let int_value = FieldValue::Int(42);
752		assert_eq!(int_value.as_i64(), Some(42));
753		assert_eq!(int_value.as_f64(), Some(42.0));
754		assert_eq!(int_value.as_str(), None);
755		assert_eq!(int_value.as_bool(), None);
756
757		let float_value = FieldValue::Float(3.15);
758		assert_eq!(float_value.as_i64(), None);
759		assert_eq!(float_value.as_f64(), Some(3.15));
760
761		let string_value = FieldValue::String("hello".to_owned());
762		assert_eq!(string_value.as_str(), Some("hello"));
763		assert_eq!(string_value.as_i64(), None);
764
765		let bool_value = FieldValue::Bool(true);
766		assert_eq!(bool_value.as_bool(), Some(true));
767
768		let null_value = FieldValue::Null;
769		assert!(null_value.is_null());
770	}
771
772	#[test]
773	fn test_field_value_from_conversions() {
774		let int_value: FieldValue = 42i32.into();
775		assert_eq!(int_value.as_i64(), Some(42));
776
777		let i64_value: FieldValue = 100i64.into();
778		assert_eq!(i64_value.as_i64(), Some(100));
779
780		let float_value: FieldValue = 3.15f64.into();
781		assert_eq!(float_value.as_f64(), Some(3.15));
782
783		let bool_value: FieldValue = true.into();
784		assert_eq!(bool_value.as_bool(), Some(true));
785
786		let string_value: FieldValue = "test".into();
787		assert_eq!(string_value.as_str(), Some("test"));
788
789		let owned_string_value: FieldValue = "test".to_owned().into();
790		assert_eq!(owned_string_value.as_str(), Some("test"));
791	}
792
793	#[test]
794	fn test_field_info_new() {
795		let field = FieldInfo::new("username", "user_name", "VARCHAR", false);
796		assert_eq!(field.name, "username");
797		assert_eq!(field.column_name, "user_name");
798		assert_eq!(field.field_type, "VARCHAR");
799		assert!(!field.nullable);
800	}
801
802	#[test]
803	fn test_reflection_error_display() {
804		let err1 = ReflectionError::ModelNotFound("User".to_owned());
805		assert_eq!(err1.to_string(), "Model not found: User");
806
807		let err2 = ReflectionError::FieldNotFound("name".to_owned());
808		assert_eq!(err2.to_string(), "Field not found: name");
809
810		let err3 = ReflectionError::TypeMismatch {
811			expected: "String".to_owned(),
812			actual: "Int".to_owned(),
813		};
814		assert_eq!(err3.to_string(), "Type mismatch: expected String, got Int");
815
816		let err4 = ReflectionError::InvalidOperation("test".to_owned());
817		assert_eq!(err4.to_string(), "Invalid operation: test");
818
819		let err5 = ReflectionError::SerializationError("test".to_owned());
820		assert_eq!(err5.to_string(), "Serialization error: test");
821	}
822}