@@ -118,6 +118,16 @@ impl Appender<'_> {
118118 result_from_duckdb_appender ( rc, & mut self . app )
119119 }
120120
121+ /// Append a DEFAULT value to the current row
122+ #[ inline]
123+ fn append_default ( & mut self ) -> Result < ( ) > {
124+ let rc = unsafe { ffi:: duckdb_append_default ( self . app ) } ;
125+ if rc != 0 {
126+ return Err ( Error :: AppendError ) ;
127+ }
128+ Ok ( ( ) )
129+ }
130+
121131 #[ inline]
122132 pub ( crate ) fn bind_parameters < P > ( & mut self , params : P ) -> Result < ( ) >
123133 where
@@ -130,13 +140,14 @@ impl Appender<'_> {
130140 Ok ( ( ) )
131141 }
132142
133- fn bind_parameter < P : ?Sized + ToSql > ( & self , param : & P ) -> Result < ( ) > {
143+ fn bind_parameter < P : ?Sized + ToSql > ( & mut self , param : & P ) -> Result < ( ) > {
134144 let value = param. to_sql ( ) ?;
135145
136146 let ptr = self . app ;
137147 let value = match value {
138148 ToSqlOutput :: Borrowed ( v) => v,
139149 ToSqlOutput :: Owned ( ref v) => ValueRef :: from ( v) ,
150+ ToSqlOutput :: AppendDefault => return self . append_default ( ) ,
140151 } ;
141152 // NOTE: we ignore the return value here
142153 // because if anything failed, end_row will fail
@@ -224,7 +235,7 @@ impl fmt::Debug for Appender<'_> {
224235
225236#[ cfg( test) ]
226237mod test {
227- use crate :: { params, Connection , Error , Result } ;
238+ use crate :: { params, types :: AppendDefault , Connection , Error , Result } ;
228239
229240 #[ test]
230241 fn test_append_one_row ( ) -> Result < ( ) > {
@@ -424,4 +435,50 @@ mod test {
424435
425436 Ok ( ( ) )
426437 }
438+
439+ #[ test]
440+ fn test_append_default ( ) -> Result < ( ) > {
441+ let db = Connection :: open_in_memory ( ) ?;
442+ db. execute_batch (
443+ "CREATE TABLE test (
444+ id INTEGER,
445+ name VARCHAR,
446+ status VARCHAR DEFAULT 'active'
447+ )" ,
448+ ) ?;
449+
450+ {
451+ let mut app = db. appender ( "test" ) ?;
452+ app. append_row ( params ! [ 1 , "Alice" , AppendDefault ] ) ?;
453+ app. append_row ( params ! [ 2 , "Bob" , AppendDefault ] ) ?;
454+ app. append_row ( params ! [ 3 , AppendDefault , AppendDefault ] ) ?;
455+ app. append_row ( params ! [ 4 , None :: <String >, "inactive" ] ) ?;
456+ }
457+
458+ let rows: Vec < ( i32 , Option < String > , String ) > = db
459+ . prepare ( "SELECT id, name, status FROM test ORDER BY id" ) ?
460+ . query_map ( [ ] , |row| Ok ( ( row. get ( 0 ) ?, row. get ( 1 ) ?, row. get ( 2 ) ?) ) ) ?
461+ . collect :: < Result < Vec < _ > > > ( ) ?;
462+
463+ assert_eq ! ( rows. len( ) , 4 ) ;
464+ assert_eq ! ( rows[ 0 ] , ( 1 , Some ( "Alice" . to_string( ) ) , "active" . to_string( ) ) ) ;
465+ assert_eq ! ( rows[ 1 ] , ( 2 , Some ( "Bob" . to_string( ) ) , "active" . to_string( ) ) ) ;
466+ assert_eq ! ( rows[ 2 ] , ( 3 , None , "active" . to_string( ) ) ) ;
467+ assert_eq ! ( rows[ 3 ] , ( 4 , None , "inactive" . to_string( ) ) ) ;
468+
469+ Ok ( ( ) )
470+ }
471+
472+ #[ test]
473+ fn test_append_default_in_prepared_statement_fails ( ) -> Result < ( ) > {
474+ let db = Connection :: open_in_memory ( ) ?;
475+ db. execute_batch ( "CREATE TABLE test (id INTEGER, name VARCHAR DEFAULT 'test')" ) ?;
476+
477+ let mut stmt = db. prepare ( "INSERT INTO test VALUES (?, ?)" ) ?;
478+ let result = stmt. execute ( params ! [ 1 , AppendDefault ] ) ;
479+
480+ assert ! ( matches!( result, Err ( Error :: ToSqlConversionFailure ( _) ) ) ) ;
481+
482+ Ok ( ( ) )
483+ }
427484}
0 commit comments