@@ -115,6 +115,18 @@ pub struct TestSoftDelete {
115115 pub deleted_at : Option < chrono:: DateTime < chrono:: Utc > > ,
116116}
117117
118+ #[ derive( Model , PartialEq ) ]
119+ #[ tideorm( table = "timestamp_users" ) ]
120+ pub struct TimestampUser {
121+ #[ tideorm( primary_key, auto_increment) ]
122+ pub id : i64 ,
123+ pub email : String ,
124+ pub name : String ,
125+ pub login_count : i32 ,
126+ pub created_at : chrono:: DateTime < chrono:: Utc > ,
127+ pub updated_at : chrono:: DateTime < chrono:: Utc > ,
128+ }
129+
118130// =============================================================================
119131// SINGLE INTEGRATION TEST - Runs all scenarios sequentially
120132// =============================================================================
@@ -138,6 +150,7 @@ async fn postgres_integration_tests() {
138150 let _ = Database :: execute ( "DROP TABLE IF EXISTS test_soft_deletes CASCADE" ) . await ;
139151 let _ = Database :: execute ( "DROP TABLE IF EXISTS test_posts CASCADE" ) . await ;
140152 let _ = Database :: execute ( "DROP TABLE IF EXISTS test_users CASCADE" ) . await ;
153+ let _ = Database :: execute ( "DROP TABLE IF EXISTS timestamp_users CASCADE" ) . await ;
141154 let _ = Database :: execute ( "DROP TABLE IF EXISTS callback_users CASCADE" ) . await ;
142155
143156 Database :: execute (
@@ -180,6 +193,21 @@ async fn postgres_integration_tests() {
180193 . await
181194 . expect ( "Failed to create test_soft_deletes table" ) ;
182195
196+ Database :: execute (
197+ r#"
198+ CREATE TABLE timestamp_users (
199+ id BIGSERIAL PRIMARY KEY,
200+ email VARCHAR(255) NOT NULL UNIQUE,
201+ name VARCHAR(255) NOT NULL,
202+ login_count INTEGER NOT NULL DEFAULT 0,
203+ created_at TIMESTAMPTZ NOT NULL,
204+ updated_at TIMESTAMPTZ NOT NULL
205+ )
206+ "# ,
207+ )
208+ . await
209+ . expect ( "Failed to create timestamp_users table" ) ;
210+
183211 Database :: execute (
184212 r#"
185213 CREATE TABLE callback_users (
@@ -952,6 +980,57 @@ async fn postgres_integration_tests() {
952980 }
953981 println ! ( ) ;
954982
983+ println ! ( "🕒 Testing: Upsert With Timestamp Columns" ) ;
984+ {
985+ let _ = Database :: execute ( "TRUNCATE TABLE timestamp_users RESTART IDENTITY CASCADE" ) . await ;
986+
987+ let created_at = chrono:: Utc :: now ( ) ;
988+ let updated_at = created_at + chrono:: TimeDelta :: minutes ( 15 ) ;
989+
990+ let inserted = TimestampUser :: insert_or_update (
991+ TimestampUser {
992+ id : 0 ,
993+ email : "typed-upsert@example.com" . into ( ) ,
994+ name : "Initial Timestamp User" . into ( ) ,
995+ login_count : 1 ,
996+ created_at,
997+ updated_at,
998+ } ,
999+ vec ! [ "email" ] ,
1000+ )
1001+ . await
1002+ . expect ( "insert_or_update should preserve timestamp parameter types on insert" ) ;
1003+
1004+ assert_eq ! ( inserted. email, "typed-upsert@example.com" ) ;
1005+ assert_eq ! ( inserted. login_count, 1 ) ;
1006+ assert_eq ! ( inserted. created_at, created_at) ;
1007+ assert_eq ! ( inserted. updated_at, updated_at) ;
1008+
1009+ let next_updated_at = updated_at + chrono:: TimeDelta :: minutes ( 30 ) ;
1010+ let updated = TimestampUser :: insert_or_update (
1011+ TimestampUser {
1012+ id : inserted. id ,
1013+ email : "typed-upsert@example.com" . into ( ) ,
1014+ name : "Updated Timestamp User" . into ( ) ,
1015+ login_count : 2 ,
1016+ created_at,
1017+ updated_at : next_updated_at,
1018+ } ,
1019+ vec ! [ "email" ] ,
1020+ )
1021+ . await
1022+ . expect ( "insert_or_update should preserve timestamp parameter types on conflict update" ) ;
1023+
1024+ assert_eq ! ( updated. id, inserted. id) ;
1025+ assert_eq ! ( updated. name, "Updated Timestamp User" ) ;
1026+ assert_eq ! ( updated. login_count, 2 ) ;
1027+ assert_eq ! ( updated. created_at, created_at) ;
1028+ assert_eq ! ( updated. updated_at, next_updated_at) ;
1029+
1030+ println ! ( " ✓ insert_or_update preserves timestamp column types" ) ;
1031+ }
1032+ println ! ( ) ;
1033+
9551034 // =========================================================================
9561035 // BATCH UPDATE TESTS
9571036 // =========================================================================
0 commit comments