@@ -820,6 +820,77 @@ mod test {
820820        Ok ( ( ) ) 
821821    } 
822822
823+     // When using RETURNING clauses, DuckDB core treats the statement as a query result instead of a modification 
824+     // statement. This causes execute() to return 0 changed rows and insert() to fail with an error. 
825+     // This test demonstrates current behavior and proper usage patterns for RETURNING clauses. 
826+     #[ test]  
827+     fn  test_insert_with_returning_clause ( )  -> Result < ( ) >  { 
828+         let  db = Connection :: open_in_memory ( ) ?; 
829+         db. execute_batch ( 
830+             "CREATE SEQUENCE location_id_seq START WITH 1 INCREMENT BY 1; 
831+              CREATE TABLE location ( 
832+                  id INTEGER PRIMARY KEY DEFAULT nextval('location_id_seq'), 
833+                  name TEXT NOT NULL 
834+              )" , 
835+         ) ?; 
836+ 
837+         // INSERT without RETURNING using execute 
838+         let  changes = db. execute ( "INSERT INTO location (name) VALUES (?)" ,  [ "test1" ] ) ?; 
839+         assert_eq ! ( changes,  1 ) ; 
840+ 
841+         // INSERT with RETURNING using execute - returns 0 (known limitation) 
842+         let  changes = db. execute ( "INSERT INTO location (name) VALUES (?) RETURNING id" ,  [ "test2" ] ) ?; 
843+         assert_eq ! ( changes,  0 ) ; 
844+ 
845+         // Verify the row was actually inserted despite returning 0 
846+         let  count:  i64  = db. query_row ( "SELECT COUNT(*) FROM location" ,  [ ] ,  |r| r. get ( 0 ) ) ?; 
847+         assert_eq ! ( count,  2 ) ; 
848+ 
849+         // INSERT without RETURNING using insert 
850+         let  mut  stmt = db. prepare ( "INSERT INTO location (name) VALUES (?)" ) ?; 
851+         stmt. insert ( [ "test3" ] ) ?; 
852+ 
853+         // INSERT with RETURNING using insert - fails (known limitation) 
854+         let  mut  stmt = db. prepare ( "INSERT INTO location (name) VALUES (?) RETURNING id" ) ?; 
855+         let  result = stmt. insert ( [ "test4" ] ) ; 
856+         assert ! ( matches!( result,  Err ( Error :: StatementChangedRows ( 0 ) ) ) ) ; 
857+ 
858+         // Verify the row was still inserted despite the error 
859+         let  count:  i64  = db. query_row ( "SELECT COUNT(*) FROM location" ,  [ ] ,  |r| r. get ( 0 ) ) ?; 
860+         assert_eq ! ( count,  4 ) ; 
861+ 
862+         // Proper way to use RETURNING - with query_row 
863+         let  id:  i64  = db. query_row ( "INSERT INTO location (name) VALUES (?) RETURNING id" ,  [ "test5" ] ,  |r| { 
864+             r. get ( 0 ) 
865+         } ) ?; 
866+         assert_eq ! ( id,  5 ) ; 
867+ 
868+         // Proper way to use RETURNING - with query_map 
869+         let  mut  stmt = db. prepare ( "INSERT INTO location (name) VALUES (?) RETURNING id" ) ?; 
870+         let  ids:  Vec < i64 >  = stmt
871+             . query_map ( [ "test6" ] ,  |row| row. get ( 0 ) ) ?
872+             . collect :: < Result < Vec < _ > > > ( ) ?; 
873+         assert_eq ! ( ids. len( ) ,  1 ) ; 
874+         assert_eq ! ( ids[ 0 ] ,  6 ) ; 
875+ 
876+         // Proper way to use RETURNING - with query_one 
877+         let  id:  i64  = db
878+             . prepare ( "INSERT INTO location (name) VALUES (?) RETURNING id" ) ?
879+             . query_one ( [ "test7" ] ,  |r| r. get ( 0 ) ) ?; 
880+         assert_eq ! ( id,  7 ) ; 
881+ 
882+         // Multiple RETURNING columns 
883+         let  ( id,  name) :  ( i64 ,  String )  = db. query_row ( 
884+             "INSERT INTO location (name) VALUES (?) RETURNING id, name" , 
885+             [ "test8" ] , 
886+             |r| Ok ( ( r. get ( 0 ) ?,  r. get ( 1 ) ?) ) , 
887+         ) ?; 
888+         assert_eq ! ( id,  8 ) ; 
889+         assert_eq ! ( name,  "test8" ) ; 
890+ 
891+         Ok ( ( ) ) 
892+     } 
893+ 
823894    #[ test]  
824895    fn  test_exists ( )  -> Result < ( ) >  { 
825896        let  db = Connection :: open_in_memory ( ) ?; 
0 commit comments