22
33static VALUE cDuckDBTableFunction ;
44extern VALUE cDuckDBBindInfo ;
5+ extern VALUE cDuckDBInitInfo ;
56extern VALUE cDuckDBFunctionInfo ;
67extern VALUE cDuckDBDataChunk ;
78
@@ -15,6 +16,8 @@ static VALUE rbduckdb_table_function_add_parameter(VALUE self, VALUE logical_typ
1516static VALUE rbduckdb_table_function_add_named_parameter (VALUE self , VALUE name , VALUE logical_type );
1617static VALUE rbduckdb_table_function_set_bind (VALUE self );
1718static void table_function_bind_callback (duckdb_bind_info info );
19+ static VALUE rbduckdb_table_function_set_init (VALUE self );
20+ static void table_function_init_callback (duckdb_init_info info );
1821static VALUE rbduckdb_table_function_set_execute (VALUE self );
1922static void table_function_execute_callback (duckdb_function_info info , duckdb_data_chunk output );
2023
@@ -27,6 +30,7 @@ static const rb_data_type_t table_function_data_type = {
2730static void mark (void * ctx ) {
2831 rubyDuckDBTableFunction * p = (rubyDuckDBTableFunction * )ctx ;
2932 rb_gc_mark (p -> bind_proc );
33+ rb_gc_mark (p -> init_proc );
3034 rb_gc_mark (p -> execute_proc );
3135}
3236
@@ -218,6 +222,68 @@ static void table_function_bind_callback(duckdb_bind_info info) {
218222 }
219223}
220224
225+ /*
226+ * call-seq:
227+ * table_function.init { |init_info| ... } -> table_function
228+ *
229+ * Sets the init callback for the table function.
230+ * The callback is invoked once during query initialization to set up execution state.
231+ *
232+ * table_function.init do |init_info|
233+ * # Initialize execution state
234+ * end
235+ */
236+ static VALUE rbduckdb_table_function_set_init (VALUE self ) {
237+ rubyDuckDBTableFunction * ctx ;
238+
239+ if (!rb_block_given_p ()) {
240+ rb_raise (rb_eArgError , "block is required for init" );
241+ }
242+
243+ TypedData_Get_Struct (self , rubyDuckDBTableFunction , & table_function_data_type , ctx );
244+
245+ if (!ctx -> table_function ) {
246+ rb_raise (eDuckDBError , "Table function is destroyed" );
247+ }
248+
249+ ctx -> init_proc = rb_block_proc ();
250+ duckdb_table_function_set_init (ctx -> table_function , table_function_init_callback );
251+ duckdb_table_function_set_extra_info (ctx -> table_function , (void * )self , NULL );
252+
253+ return self ;
254+ }
255+
256+ static VALUE call_init_proc (VALUE args_val ) {
257+ VALUE * args = (VALUE * )args_val ;
258+ return rb_funcall (args [0 ], rb_intern ("call" ), 1 , args [1 ]);
259+ }
260+
261+ static void table_function_init_callback (duckdb_init_info info ) {
262+ VALUE self = (VALUE )duckdb_init_get_extra_info (info );
263+ rubyDuckDBTableFunction * ctx ;
264+ VALUE init_info_obj ;
265+ rubyDuckDBInitInfo * init_info_ctx ;
266+ int state = 0 ;
267+
268+ TypedData_Get_Struct (self , rubyDuckDBTableFunction , & table_function_data_type , ctx );
269+
270+ // Create InitInfo wrapper
271+ init_info_obj = rb_funcall (cDuckDBInitInfo , rb_intern ("allocate" ), 0 );
272+ init_info_ctx = get_struct_init_info (init_info_obj );
273+ init_info_ctx -> info = info ;
274+
275+ // Call Ruby block with exception protection
276+ VALUE call_args [2 ] = { ctx -> init_proc , init_info_obj };
277+ rb_protect (call_init_proc , (VALUE )call_args , & state );
278+
279+ if (state ) {
280+ VALUE err = rb_errinfo ();
281+ VALUE msg = rb_funcall (err , rb_intern ("message" ), 0 );
282+ duckdb_init_set_error (info , StringValueCStr (msg ));
283+ rb_set_errinfo (Qnil ); // Clear the error
284+ }
285+ }
286+
221287/*
222288 * call-seq:
223289 * table_function.execute { |function_info, output| ... } -> table_function
@@ -304,5 +370,6 @@ void rbduckdb_init_duckdb_table_function(void) {
304370 rb_define_method (cDuckDBTableFunction , "add_parameter" , rbduckdb_table_function_add_parameter , 1 );
305371 rb_define_method (cDuckDBTableFunction , "add_named_parameter" , rbduckdb_table_function_add_named_parameter , 2 );
306372 rb_define_method (cDuckDBTableFunction , "bind" , rbduckdb_table_function_set_bind , 0 );
373+ rb_define_method (cDuckDBTableFunction , "init" , rbduckdb_table_function_set_init , 0 );
307374 rb_define_method (cDuckDBTableFunction , "execute" , rbduckdb_table_function_set_execute , 0 );
308375}
0 commit comments