@@ -83,6 +83,16 @@ impl Appender<'_> {
8383 result_from_duckdb_appender ( rc, & mut self . app )
8484 }
8585
86+ /// Append a DEFAULT value to the current row
87+ #[ inline]
88+ fn append_default ( & mut self ) -> Result < ( ) > {
89+ let rc = unsafe { ffi:: duckdb_append_default ( self . app ) } ;
90+ if rc != 0 {
91+ return Err ( Error :: AppendError ) ;
92+ }
93+ Ok ( ( ) )
94+ }
95+
8696 #[ inline]
8797 pub ( crate ) fn bind_parameters < P > ( & mut self , params : P ) -> Result < ( ) >
8898 where
@@ -95,13 +105,14 @@ impl Appender<'_> {
95105 Ok ( ( ) )
96106 }
97107
98- fn bind_parameter < P : ?Sized + ToSql > ( & self , param : & P ) -> Result < ( ) > {
108+ fn bind_parameter < P : ?Sized + ToSql > ( & mut self , param : & P ) -> Result < ( ) > {
99109 let value = param. to_sql ( ) ?;
100110
101111 let ptr = self . app ;
102112 let value = match value {
103113 ToSqlOutput :: Borrowed ( v) => v,
104114 ToSqlOutput :: Owned ( ref v) => ValueRef :: from ( v) ,
115+ ToSqlOutput :: AppendDefault => return self . append_default ( ) ,
105116 } ;
106117 // NOTE: we ignore the return value here
107118 // because if anything failed, end_row will fail
@@ -189,7 +200,7 @@ impl fmt::Debug for Appender<'_> {
189200
190201#[ cfg( test) ]
191202mod test {
192- use crate :: { params, Connection , Error , Result } ;
203+ use crate :: { params, types :: AppendDefault , Connection , Error , Result } ;
193204
194205 #[ test]
195206 fn test_append_one_row ( ) -> Result < ( ) > {
@@ -389,4 +400,50 @@ mod test {
389400
390401 Ok ( ( ) )
391402 }
403+
404+ #[ test]
405+ fn test_append_default ( ) -> Result < ( ) > {
406+ let db = Connection :: open_in_memory ( ) ?;
407+ db. execute_batch (
408+ "CREATE TABLE test (
409+ id INTEGER,
410+ name VARCHAR,
411+ status VARCHAR DEFAULT 'active'
412+ )" ,
413+ ) ?;
414+
415+ {
416+ let mut app = db. appender ( "test" ) ?;
417+ app. append_row ( params ! [ 1 , "Alice" , AppendDefault ] ) ?;
418+ app. append_row ( params ! [ 2 , "Bob" , AppendDefault ] ) ?;
419+ app. append_row ( params ! [ 3 , AppendDefault , AppendDefault ] ) ?;
420+ app. append_row ( params ! [ 4 , None :: <String >, "inactive" ] ) ?;
421+ }
422+
423+ let rows: Vec < ( i32 , Option < String > , String ) > = db
424+ . prepare ( "SELECT id, name, status FROM test ORDER BY id" ) ?
425+ . query_map ( [ ] , |row| Ok ( ( row. get ( 0 ) ?, row. get ( 1 ) ?, row. get ( 2 ) ?) ) ) ?
426+ . collect :: < Result < Vec < _ > > > ( ) ?;
427+
428+ assert_eq ! ( rows. len( ) , 4 ) ;
429+ assert_eq ! ( rows[ 0 ] , ( 1 , Some ( "Alice" . to_string( ) ) , "active" . to_string( ) ) ) ;
430+ assert_eq ! ( rows[ 1 ] , ( 2 , Some ( "Bob" . to_string( ) ) , "active" . to_string( ) ) ) ;
431+ assert_eq ! ( rows[ 2 ] , ( 3 , None , "active" . to_string( ) ) ) ;
432+ assert_eq ! ( rows[ 3 ] , ( 4 , None , "inactive" . to_string( ) ) ) ;
433+
434+ Ok ( ( ) )
435+ }
436+
437+ #[ test]
438+ fn test_append_default_in_prepared_statement_fails ( ) -> Result < ( ) > {
439+ let db = Connection :: open_in_memory ( ) ?;
440+ db. execute_batch ( "CREATE TABLE test (id INTEGER, name VARCHAR DEFAULT 'test')" ) ?;
441+
442+ let mut stmt = db. prepare ( "INSERT INTO test VALUES (?, ?)" ) ?;
443+ let result = stmt. execute ( params ! [ 1 , AppendDefault ] ) ;
444+
445+ assert ! ( matches!( result, Err ( Error :: ToSqlConversionFailure ( _) ) ) ) ;
446+
447+ Ok ( ( ) )
448+ }
392449}
0 commit comments