duckdb 1.5.3.0 → 1.5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +47 -0
- data/CLAUDE.md +4 -0
- data/README.md +52 -0
- data/duckdb.gemspec +1 -1
- data/ext/duckdb/aggregate_function.c +0 -1
- data/ext/duckdb/appender.c +17 -0
- data/ext/duckdb/arrow_array_stream.c +226 -0
- data/ext/duckdb/arrow_array_stream.h +61 -0
- data/ext/duckdb/arrow_import.c +165 -0
- data/ext/duckdb/arrow_import.h +6 -0
- data/ext/duckdb/blob.c +1 -1
- data/ext/duckdb/blob.h +1 -2
- data/ext/duckdb/config.c +1 -1
- data/ext/duckdb/config.h +1 -1
- data/ext/duckdb/connection.c +26 -4
- data/ext/duckdb/converter.h +1 -0
- data/ext/duckdb/conveter.c +39 -9
- data/ext/duckdb/data_chunk.c +10 -0
- data/ext/duckdb/data_chunk.h +1 -0
- data/ext/duckdb/duckdb.c +13 -11
- data/ext/duckdb/error.c +13 -1
- data/ext/duckdb/error.h +2 -3
- data/ext/duckdb/function_executor.c +308 -2
- data/ext/duckdb/function_executor.h +44 -0
- data/ext/duckdb/function_vector.c +14 -0
- data/ext/duckdb/prepared_statement.c +141 -5
- data/ext/duckdb/result.c +49 -3
- data/ext/duckdb/result.h +11 -0
- data/ext/duckdb/ruby-duckdb.h +3 -0
- data/ext/duckdb/scalar_function.c +97 -29
- data/ext/duckdb/scalar_function.h +2 -4
- data/ext/duckdb/scalar_function_bind_info.c +13 -13
- data/ext/duckdb/scalar_function_bind_info.h +1 -1
- data/ext/duckdb/scalar_function_set.c +9 -9
- data/ext/duckdb/scalar_function_set.h +2 -2
- data/ext/duckdb/table_description.c +19 -19
- data/ext/duckdb/table_description.h +1 -1
- data/ext/duckdb/table_function.c +94 -28
- data/ext/duckdb/table_function.h +2 -2
- data/ext/duckdb/table_function_bind_info.c +20 -20
- data/ext/duckdb/table_function_bind_info.h +2 -2
- data/ext/duckdb/table_function_function_info.c +5 -5
- data/ext/duckdb/table_function_function_info.h +2 -2
- data/ext/duckdb/table_function_init_info.c +70 -5
- data/ext/duckdb/table_function_init_info.h +2 -2
- data/ext/duckdb/util.c +8 -0
- data/ext/duckdb/util.h +1 -0
- data/ext/duckdb/value.c +526 -1
- data/lib/duckdb/appender.rb +23 -0
- data/lib/duckdb/arrow_array_stream.rb +33 -0
- data/lib/duckdb/connection.rb +73 -0
- data/lib/duckdb/converter/int_to_sym.rb +54 -1
- data/lib/duckdb/converter.rb +7 -7
- data/lib/duckdb/error.rb +26 -0
- data/lib/duckdb/function_type_validation.rb +1 -0
- data/lib/duckdb/logical_type.rb +6 -3
- data/lib/duckdb/prepared_statement.rb +32 -0
- data/lib/duckdb/scalar_function.rb +6 -6
- data/lib/duckdb/value.rb +400 -0
- data/lib/duckdb/version.rb +1 -1
- data/lib/duckdb.rb +2 -0
- metadata +10 -3
|
@@ -5,10 +5,10 @@ VALUE cDuckDBScalarFunctionBindInfo;
|
|
|
5
5
|
static void deallocate(void *ctx);
|
|
6
6
|
static VALUE allocate(VALUE klass);
|
|
7
7
|
static size_t memsize(const void *p);
|
|
8
|
-
static VALUE
|
|
9
|
-
static VALUE
|
|
10
|
-
static VALUE
|
|
11
|
-
static VALUE
|
|
8
|
+
static VALUE scalar_function_bind_info_argument_count(VALUE self);
|
|
9
|
+
static VALUE scalar_function_bind_info_set_error(VALUE self, VALUE error);
|
|
10
|
+
static VALUE scalar_function_bind_info__get_argument(VALUE self, VALUE index);
|
|
11
|
+
static VALUE scalar_function_bind_info_client_context(VALUE self);
|
|
12
12
|
|
|
13
13
|
static const rb_data_type_t scalar_function_bind_info_data_type = {
|
|
14
14
|
"DuckDB/ScalarFunction/BindInfo",
|
|
@@ -46,7 +46,7 @@ VALUE rbduckdb_scalar_function_bind_info_new(duckdb_bind_info bind_info) {
|
|
|
46
46
|
*
|
|
47
47
|
* bind_info.argument_count # => 2
|
|
48
48
|
*/
|
|
49
|
-
static VALUE
|
|
49
|
+
static VALUE scalar_function_bind_info_argument_count(VALUE self) {
|
|
50
50
|
rubyDuckDBScalarFunctionBindInfo *ctx;
|
|
51
51
|
TypedData_Get_Struct(self, rubyDuckDBScalarFunctionBindInfo, &scalar_function_bind_info_data_type, ctx);
|
|
52
52
|
return ULL2NUM(duckdb_scalar_function_bind_get_argument_count(ctx->bind_info));
|
|
@@ -61,7 +61,7 @@ static VALUE rbduckdb_scalar_function_bind_info_argument_count(VALUE self) {
|
|
|
61
61
|
*
|
|
62
62
|
* bind_info.set_error('invalid argument')
|
|
63
63
|
*/
|
|
64
|
-
static VALUE
|
|
64
|
+
static VALUE scalar_function_bind_info_set_error(VALUE self, VALUE error) {
|
|
65
65
|
rubyDuckDBScalarFunctionBindInfo *ctx;
|
|
66
66
|
TypedData_Get_Struct(self, rubyDuckDBScalarFunctionBindInfo, &scalar_function_bind_info_data_type, ctx);
|
|
67
67
|
duckdb_scalar_function_bind_set_error(ctx->bind_info, StringValueCStr(error));
|
|
@@ -75,7 +75,7 @@ static VALUE rbduckdb_scalar_function_bind_info_set_error(VALUE self, VALUE erro
|
|
|
75
75
|
* Returns the expression at the given argument index.
|
|
76
76
|
* Called internally by +get_argument+ after index validation.
|
|
77
77
|
*/
|
|
78
|
-
static VALUE
|
|
78
|
+
static VALUE scalar_function_bind_info__get_argument(VALUE self, VALUE index) {
|
|
79
79
|
rubyDuckDBScalarFunctionBindInfo *ctx;
|
|
80
80
|
TypedData_Get_Struct(self, rubyDuckDBScalarFunctionBindInfo, &scalar_function_bind_info_data_type, ctx);
|
|
81
81
|
duckdb_expression expr = duckdb_scalar_function_bind_get_argument(ctx->bind_info, (idx_t)NUM2ULL(index));
|
|
@@ -88,7 +88,7 @@ static VALUE rbduckdb_scalar_function_bind_info_get_argument(VALUE self, VALUE i
|
|
|
88
88
|
*
|
|
89
89
|
* Returns the client context associated with the bind phase of the scalar function.
|
|
90
90
|
*/
|
|
91
|
-
static VALUE
|
|
91
|
+
static VALUE scalar_function_bind_info_client_context(VALUE self) {
|
|
92
92
|
rubyDuckDBScalarFunctionBindInfo *ctx;
|
|
93
93
|
duckdb_client_context client_context;
|
|
94
94
|
TypedData_Get_Struct(self, rubyDuckDBScalarFunctionBindInfo, &scalar_function_bind_info_data_type, ctx);
|
|
@@ -96,14 +96,14 @@ static VALUE rbduckdb_scalar_function_bind_info_client_context(VALUE self) {
|
|
|
96
96
|
return rbduckdb_client_context_new(client_context);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
void
|
|
99
|
+
void rbduckdb_init_scalar_function_bind_info(void) {
|
|
100
100
|
#if 0
|
|
101
101
|
VALUE mDuckDB = rb_define_module("DuckDB");
|
|
102
102
|
#endif
|
|
103
103
|
cDuckDBScalarFunctionBindInfo = rb_define_class_under(cDuckDBScalarFunction, "BindInfo", rb_cObject);
|
|
104
104
|
rb_define_alloc_func(cDuckDBScalarFunctionBindInfo, allocate);
|
|
105
|
-
rb_define_method(cDuckDBScalarFunctionBindInfo, "argument_count",
|
|
106
|
-
rb_define_method(cDuckDBScalarFunctionBindInfo, "set_error",
|
|
107
|
-
rb_define_private_method(cDuckDBScalarFunctionBindInfo, "_get_argument",
|
|
108
|
-
rb_define_method(cDuckDBScalarFunctionBindInfo, "client_context",
|
|
105
|
+
rb_define_method(cDuckDBScalarFunctionBindInfo, "argument_count", scalar_function_bind_info_argument_count, 0);
|
|
106
|
+
rb_define_method(cDuckDBScalarFunctionBindInfo, "set_error", scalar_function_bind_info_set_error, 1);
|
|
107
|
+
rb_define_private_method(cDuckDBScalarFunctionBindInfo, "_get_argument", scalar_function_bind_info__get_argument, 1);
|
|
108
|
+
rb_define_method(cDuckDBScalarFunctionBindInfo, "client_context", scalar_function_bind_info_client_context, 0);
|
|
109
109
|
}
|
|
@@ -7,7 +7,7 @@ struct _rubyDuckDBScalarFunctionBindInfo {
|
|
|
7
7
|
|
|
8
8
|
typedef struct _rubyDuckDBScalarFunctionBindInfo rubyDuckDBScalarFunctionBindInfo;
|
|
9
9
|
|
|
10
|
-
void
|
|
10
|
+
void rbduckdb_init_scalar_function_bind_info(void);
|
|
11
11
|
VALUE rbduckdb_scalar_function_bind_info_new(duckdb_bind_info bind_info);
|
|
12
12
|
|
|
13
13
|
#endif
|
|
@@ -7,8 +7,8 @@ static void deallocate(void *);
|
|
|
7
7
|
static VALUE allocate(VALUE klass);
|
|
8
8
|
static size_t memsize(const void *p);
|
|
9
9
|
static void compact(void *);
|
|
10
|
-
static VALUE
|
|
11
|
-
static VALUE
|
|
10
|
+
static VALUE scalar_function_set__initialize(VALUE self, VALUE name);
|
|
11
|
+
static VALUE scalar_function_set__add(VALUE self, VALUE scalar_function);
|
|
12
12
|
|
|
13
13
|
static const rb_data_type_t scalar_function_set_data_type = {
|
|
14
14
|
"DuckDB/ScalarFunctionSet",
|
|
@@ -44,14 +44,14 @@ static size_t memsize(const void *p) {
|
|
|
44
44
|
return sizeof(rubyDuckDBScalarFunctionSet);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
rubyDuckDBScalarFunctionSet *
|
|
47
|
+
rubyDuckDBScalarFunctionSet *rbduckdb_get_struct_scalar_function_set(VALUE obj) {
|
|
48
48
|
rubyDuckDBScalarFunctionSet *ctx;
|
|
49
49
|
TypedData_Get_Struct(obj, rubyDuckDBScalarFunctionSet, &scalar_function_set_data_type, ctx);
|
|
50
50
|
return ctx;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
/* :nodoc: */
|
|
54
|
-
static VALUE
|
|
54
|
+
static VALUE scalar_function_set__initialize(VALUE self, VALUE name) {
|
|
55
55
|
rubyDuckDBScalarFunctionSet *p;
|
|
56
56
|
|
|
57
57
|
TypedData_Get_Struct(self, rubyDuckDBScalarFunctionSet, &scalar_function_set_data_type, p);
|
|
@@ -60,12 +60,12 @@ static VALUE rbduckdb_scalar_function_set__initialize(VALUE self, VALUE name) {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
/* :nodoc: */
|
|
63
|
-
static VALUE
|
|
63
|
+
static VALUE scalar_function_set__add(VALUE self, VALUE scalar_function) {
|
|
64
64
|
rubyDuckDBScalarFunctionSet *p;
|
|
65
65
|
rubyDuckDBScalarFunction *sf;
|
|
66
66
|
|
|
67
67
|
TypedData_Get_Struct(self, rubyDuckDBScalarFunctionSet, &scalar_function_set_data_type, p);
|
|
68
|
-
sf =
|
|
68
|
+
sf = rbduckdb_get_struct_scalar_function(scalar_function);
|
|
69
69
|
|
|
70
70
|
if (duckdb_add_scalar_function_to_set(p->scalar_function_set, sf->scalar_function) == DuckDBError) {
|
|
71
71
|
rb_raise(eDuckDBError, "failed to add scalar function to set (duplicate overload?)");
|
|
@@ -75,12 +75,12 @@ static VALUE rbduckdb_scalar_function_set__add(VALUE self, VALUE scalar_function
|
|
|
75
75
|
return self;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
void
|
|
78
|
+
void rbduckdb_init_scalar_function_set(void) {
|
|
79
79
|
#if 0
|
|
80
80
|
VALUE mDuckDB = rb_define_module("DuckDB");
|
|
81
81
|
#endif
|
|
82
82
|
cDuckDBScalarFunctionSet = rb_define_class_under(mDuckDB, "ScalarFunctionSet", rb_cObject);
|
|
83
83
|
rb_define_alloc_func(cDuckDBScalarFunctionSet, allocate);
|
|
84
|
-
rb_define_private_method(cDuckDBScalarFunctionSet, "_initialize",
|
|
85
|
-
rb_define_private_method(cDuckDBScalarFunctionSet, "_add",
|
|
84
|
+
rb_define_private_method(cDuckDBScalarFunctionSet, "_initialize", scalar_function_set__initialize, 1);
|
|
85
|
+
rb_define_private_method(cDuckDBScalarFunctionSet, "_add", scalar_function_set__add, 1);
|
|
86
86
|
}
|
|
@@ -8,7 +8,7 @@ struct _rubyDuckDBScalarFunctionSet {
|
|
|
8
8
|
|
|
9
9
|
typedef struct _rubyDuckDBScalarFunctionSet rubyDuckDBScalarFunctionSet;
|
|
10
10
|
|
|
11
|
-
void
|
|
12
|
-
rubyDuckDBScalarFunctionSet *
|
|
11
|
+
void rbduckdb_init_scalar_function_set(void);
|
|
12
|
+
rubyDuckDBScalarFunctionSet *rbduckdb_get_struct_scalar_function_set(VALUE obj);
|
|
13
13
|
|
|
14
14
|
#endif
|
|
@@ -8,13 +8,13 @@ static void deallocate(void *ctx);
|
|
|
8
8
|
static VALUE allocate(VALUE klass);
|
|
9
9
|
static size_t memsize(const void *p);
|
|
10
10
|
static rubyDuckDBTableDescription *get_struct_table_description(VALUE obj);
|
|
11
|
-
static VALUE
|
|
12
|
-
static VALUE
|
|
11
|
+
static VALUE table_description_error_message(VALUE self);
|
|
12
|
+
static VALUE table_description__initialize(VALUE self, VALUE conn, VALUE catalog, VALUE schema, VALUE table);
|
|
13
13
|
|
|
14
|
-
static VALUE
|
|
15
|
-
static VALUE
|
|
16
|
-
static VALUE
|
|
17
|
-
static VALUE
|
|
14
|
+
static VALUE table_description__column_count(VALUE self);
|
|
15
|
+
static VALUE table_description__column_name(VALUE self, VALUE idx);
|
|
16
|
+
static VALUE table_description__column_logical_type(VALUE self, VALUE idx);
|
|
17
|
+
static VALUE table_description__column_has_default(VALUE self, VALUE idx);
|
|
18
18
|
|
|
19
19
|
static const rb_data_type_t table_description_data_type = {
|
|
20
20
|
"DuckDB/TableDescription",
|
|
@@ -46,14 +46,14 @@ static rubyDuckDBTableDescription *get_struct_table_description(VALUE obj) {
|
|
|
46
46
|
return ctx;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
static VALUE
|
|
49
|
+
static VALUE table_description_error_message(VALUE self) {
|
|
50
50
|
rubyDuckDBTableDescription *ctx = get_struct_table_description(self);
|
|
51
51
|
const char *p = duckdb_table_description_error(ctx->table_description);
|
|
52
52
|
return p ? rb_str_new2(p) : Qnil;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
/* nodoc */
|
|
56
|
-
static VALUE
|
|
56
|
+
static VALUE table_description__initialize(VALUE self, VALUE con, VALUE catalog, VALUE schema, VALUE table) {
|
|
57
57
|
char *pcatalog = NULL;
|
|
58
58
|
char *pschema = NULL;
|
|
59
59
|
char *ptable = NULL;
|
|
@@ -89,14 +89,14 @@ static VALUE duckdb_table_description__initialize(VALUE self, VALUE con, VALUE c
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
/* nodoc */
|
|
92
|
-
static VALUE
|
|
92
|
+
static VALUE table_description__column_count(VALUE self) {
|
|
93
93
|
rubyDuckDBTableDescription *ctx;
|
|
94
94
|
ctx = get_struct_table_description(self);
|
|
95
95
|
return ULL2NUM(duckdb_table_description_get_column_count(ctx->table_description));
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
/* nodoc */
|
|
99
|
-
static VALUE
|
|
99
|
+
static VALUE table_description__column_name(VALUE self, VALUE idx) {
|
|
100
100
|
VALUE name = Qnil;
|
|
101
101
|
rubyDuckDBTableDescription *ctx;
|
|
102
102
|
ctx = get_struct_table_description(self);
|
|
@@ -109,7 +109,7 @@ static VALUE duckdb_table_description__column_name(VALUE self, VALUE idx) {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
/* nodoc */
|
|
112
|
-
static VALUE
|
|
112
|
+
static VALUE table_description__column_logical_type(VALUE self, VALUE idx) {
|
|
113
113
|
rubyDuckDBTableDescription *ctx;
|
|
114
114
|
duckdb_logical_type lt;
|
|
115
115
|
ctx = get_struct_table_description(self);
|
|
@@ -117,7 +117,7 @@ static VALUE duckdb_table_description__column_logical_type(VALUE self, VALUE idx
|
|
|
117
117
|
return rbduckdb_create_logical_type(lt);
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
static VALUE
|
|
120
|
+
static VALUE table_description__column_has_default(VALUE self, VALUE idx) {
|
|
121
121
|
rubyDuckDBTableDescription *ctx;
|
|
122
122
|
bool has_default;
|
|
123
123
|
ctx = get_struct_table_description(self);
|
|
@@ -128,17 +128,17 @@ static VALUE duckdb_table_description__column_has_default(VALUE self, VALUE idx)
|
|
|
128
128
|
return has_default ? Qtrue : Qfalse;
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
void
|
|
131
|
+
void rbduckdb_init_table_description(void) {
|
|
132
132
|
#if 0
|
|
133
133
|
VALUE mDuckDB = rb_define_module("DuckDB");
|
|
134
134
|
#endif
|
|
135
135
|
cDuckDBTableDescription = rb_define_class_under(mDuckDB, "TableDescription", rb_cObject);
|
|
136
136
|
rb_define_alloc_func(cDuckDBTableDescription, allocate);
|
|
137
|
-
rb_define_method(cDuckDBTableDescription, "error_message",
|
|
138
|
-
rb_define_private_method(cDuckDBTableDescription, "_initialize",
|
|
139
|
-
rb_define_private_method(cDuckDBTableDescription, "_column_count",
|
|
140
|
-
rb_define_private_method(cDuckDBTableDescription, "_column_name",
|
|
141
|
-
rb_define_private_method(cDuckDBTableDescription, "_column_logical_type",
|
|
142
|
-
rb_define_private_method(cDuckDBTableDescription, "_column_has_default",
|
|
137
|
+
rb_define_method(cDuckDBTableDescription, "error_message", table_description_error_message, 0);
|
|
138
|
+
rb_define_private_method(cDuckDBTableDescription, "_initialize", table_description__initialize, 4);
|
|
139
|
+
rb_define_private_method(cDuckDBTableDescription, "_column_count", table_description__column_count, 0);
|
|
140
|
+
rb_define_private_method(cDuckDBTableDescription, "_column_name", table_description__column_name, 1);
|
|
141
|
+
rb_define_private_method(cDuckDBTableDescription, "_column_logical_type", table_description__column_logical_type, 1);
|
|
142
|
+
rb_define_private_method(cDuckDBTableDescription, "_column_has_default", table_description__column_has_default, 1);
|
|
143
143
|
}
|
|
144
144
|
#endif
|
data/ext/duckdb/table_function.c
CHANGED
|
@@ -11,16 +11,21 @@ static void deallocate(void *ctx);
|
|
|
11
11
|
static VALUE allocate(VALUE klass);
|
|
12
12
|
static size_t memsize(const void *p);
|
|
13
13
|
static void compact(void *ctx);
|
|
14
|
-
static VALUE
|
|
15
|
-
static VALUE
|
|
16
|
-
static VALUE
|
|
17
|
-
static VALUE
|
|
18
|
-
static VALUE
|
|
14
|
+
static VALUE table_function_initialize(VALUE self);
|
|
15
|
+
static VALUE table_function_set_name(VALUE self, VALUE name);
|
|
16
|
+
static VALUE table_function_add_parameter(VALUE self, VALUE logical_type);
|
|
17
|
+
static VALUE table_function_add_named_parameter(VALUE self, VALUE name, VALUE logical_type);
|
|
18
|
+
static VALUE table_function_bind(VALUE self);
|
|
19
19
|
static void table_function_bind_callback(duckdb_bind_info info);
|
|
20
|
-
static VALUE
|
|
20
|
+
static VALUE table_function_init(VALUE self);
|
|
21
21
|
static void table_function_init_callback(duckdb_init_info info);
|
|
22
|
-
static VALUE
|
|
22
|
+
static VALUE table_function_execute(VALUE self);
|
|
23
23
|
static void table_function_execute_callback(duckdb_function_info info, duckdb_data_chunk output);
|
|
24
|
+
#ifdef HAVE_DUCKDB_H_GE_V1_5_0
|
|
25
|
+
/* Thread detection (declared in function_executor.c); used to skip the proxy on Ruby threads. */
|
|
26
|
+
extern int ruby_native_thread_p(void);
|
|
27
|
+
static void table_function_local_init_callback(duckdb_init_info info);
|
|
28
|
+
#endif
|
|
24
29
|
|
|
25
30
|
static const rb_data_type_t table_function_data_type = {
|
|
26
31
|
"DuckDB/TableFunction",
|
|
@@ -84,7 +89,7 @@ static size_t memsize(const void *p) {
|
|
|
84
89
|
* tf.name = "my_function"
|
|
85
90
|
* # ... configure tf ...
|
|
86
91
|
*/
|
|
87
|
-
static VALUE
|
|
92
|
+
static VALUE table_function_initialize(VALUE self) {
|
|
88
93
|
rubyDuckDBTableFunction *ctx;
|
|
89
94
|
|
|
90
95
|
TypedData_Get_Struct(self, rubyDuckDBTableFunction, &table_function_data_type, ctx);
|
|
@@ -113,7 +118,7 @@ static VALUE duckdb_table_function_initialize(VALUE self) {
|
|
|
113
118
|
*
|
|
114
119
|
* tf.name = "my_function"
|
|
115
120
|
*/
|
|
116
|
-
static VALUE
|
|
121
|
+
static VALUE table_function_set_name(VALUE self, VALUE name) {
|
|
117
122
|
rubyDuckDBTableFunction *ctx;
|
|
118
123
|
const char *func_name;
|
|
119
124
|
|
|
@@ -138,7 +143,7 @@ static VALUE rbduckdb_table_function_set_name(VALUE self, VALUE name) {
|
|
|
138
143
|
* tf.add_parameter(DuckDB::LogicalType::BIGINT)
|
|
139
144
|
* tf.add_parameter(DuckDB::LogicalType::VARCHAR)
|
|
140
145
|
*/
|
|
141
|
-
static VALUE
|
|
146
|
+
static VALUE table_function_add_parameter(VALUE self, VALUE logical_type) {
|
|
142
147
|
rubyDuckDBTableFunction *ctx;
|
|
143
148
|
rubyDuckDBLogicalType *ctx_logical_type;
|
|
144
149
|
|
|
@@ -162,7 +167,7 @@ static VALUE rbduckdb_table_function_add_parameter(VALUE self, VALUE logical_typ
|
|
|
162
167
|
*
|
|
163
168
|
* tf.add_named_parameter("limit", DuckDB::LogicalType::BIGINT)
|
|
164
169
|
*/
|
|
165
|
-
static VALUE
|
|
170
|
+
static VALUE table_function_add_named_parameter(VALUE self, VALUE name, VALUE logical_type) {
|
|
166
171
|
rubyDuckDBTableFunction *ctx;
|
|
167
172
|
rubyDuckDBLogicalType *ctx_logical_type;
|
|
168
173
|
const char *param_name;
|
|
@@ -192,7 +197,7 @@ static VALUE rbduckdb_table_function_add_named_parameter(VALUE self, VALUE name,
|
|
|
192
197
|
* bind_info.add_result_column('name', DuckDB::LogicalType::VARCHAR)
|
|
193
198
|
* end
|
|
194
199
|
*/
|
|
195
|
-
static VALUE
|
|
200
|
+
static VALUE table_function_bind(VALUE self) {
|
|
196
201
|
rubyDuckDBTableFunction *ctx;
|
|
197
202
|
|
|
198
203
|
if (!rb_block_given_p()) {
|
|
@@ -231,7 +236,7 @@ static void execute_bind_callback_protected(void *user_data) {
|
|
|
231
236
|
int state = 0;
|
|
232
237
|
|
|
233
238
|
bind_info_obj = rb_class_new_instance(0, NULL, cDuckDBTableFunctionBindInfo);
|
|
234
|
-
bind_info_ctx =
|
|
239
|
+
bind_info_ctx = rbduckdb_get_struct_bind_info(bind_info_obj);
|
|
235
240
|
bind_info_ctx->bind_info = darg->info;
|
|
236
241
|
|
|
237
242
|
VALUE call_args[2] = { darg->ctx->bind_proc, bind_info_obj };
|
|
@@ -269,7 +274,7 @@ static void table_function_bind_callback(duckdb_bind_info info) {
|
|
|
269
274
|
* # Initialize execution state
|
|
270
275
|
* end
|
|
271
276
|
*/
|
|
272
|
-
static VALUE
|
|
277
|
+
static VALUE table_function_init(VALUE self) {
|
|
273
278
|
rubyDuckDBTableFunction *ctx;
|
|
274
279
|
|
|
275
280
|
if (!rb_block_given_p()) {
|
|
@@ -307,7 +312,7 @@ static void execute_init_callback_protected(void *user_data) {
|
|
|
307
312
|
int state = 0;
|
|
308
313
|
|
|
309
314
|
init_info_obj = rb_class_new_instance(0, NULL, cDuckDBTableFunctionInitInfo);
|
|
310
|
-
init_info_ctx =
|
|
315
|
+
init_info_ctx = rbduckdb_get_struct_init_info(init_info_obj);
|
|
311
316
|
init_info_ctx->info = darg->info;
|
|
312
317
|
|
|
313
318
|
VALUE call_args[2] = { darg->ctx->init_proc, init_info_obj };
|
|
@@ -347,7 +352,7 @@ static void table_function_init_callback(duckdb_init_info info) {
|
|
|
347
352
|
* # Write data...
|
|
348
353
|
* end
|
|
349
354
|
*/
|
|
350
|
-
static VALUE
|
|
355
|
+
static VALUE table_function_execute(VALUE self) {
|
|
351
356
|
rubyDuckDBTableFunction *ctx;
|
|
352
357
|
|
|
353
358
|
if (!rb_block_given_p()) {
|
|
@@ -358,6 +363,10 @@ static VALUE rbduckdb_table_function_set_execute(VALUE self) {
|
|
|
358
363
|
|
|
359
364
|
ctx->execute_proc = rb_block_proc();
|
|
360
365
|
duckdb_table_function_set_function(ctx->table_function, table_function_execute_callback);
|
|
366
|
+
#ifdef HAVE_DUCKDB_H_GE_V1_5_0
|
|
367
|
+
/* Per-worker proxy threads for the execute path (DuckDB >= 1.5.0). */
|
|
368
|
+
duckdb_table_function_set_local_init(ctx->table_function, table_function_local_init_callback);
|
|
369
|
+
#endif
|
|
361
370
|
|
|
362
371
|
rbduckdb_function_executor_ensure_started();
|
|
363
372
|
|
|
@@ -384,7 +393,7 @@ static void execute_execute_callback_protected(void *user_data) {
|
|
|
384
393
|
int state = 0;
|
|
385
394
|
|
|
386
395
|
func_info_obj = rb_class_new_instance(0, NULL, cDuckDBTableFunctionFunctionInfo);
|
|
387
|
-
func_info_ctx =
|
|
396
|
+
func_info_ctx = rbduckdb_get_struct_function_info(func_info_obj);
|
|
388
397
|
func_info_ctx->info = darg->info;
|
|
389
398
|
|
|
390
399
|
data_chunk_obj = rb_class_new_instance(0, NULL, cDuckDBDataChunk);
|
|
@@ -405,6 +414,7 @@ static void execute_execute_callback_protected(void *user_data) {
|
|
|
405
414
|
static void table_function_execute_callback(duckdb_function_info info, duckdb_data_chunk output) {
|
|
406
415
|
rubyDuckDBTableFunction *ctx;
|
|
407
416
|
struct execute_dispatch_arg darg;
|
|
417
|
+
struct worker_proxy *proxy = NULL;
|
|
408
418
|
|
|
409
419
|
ctx = (rubyDuckDBTableFunction *)duckdb_function_get_extra_info(info);
|
|
410
420
|
if (!ctx || ctx->execute_proc == Qnil) return;
|
|
@@ -413,28 +423,84 @@ static void table_function_execute_callback(duckdb_function_info info, duckdb_da
|
|
|
413
423
|
darg.info = info;
|
|
414
424
|
darg.output = output;
|
|
415
425
|
|
|
416
|
-
|
|
426
|
+
#ifdef HAVE_DUCKDB_H_GE_V1_5_0
|
|
427
|
+
/* On DuckDB >= 1.5.0 each worker thread carries its own proxy (see local_init). */
|
|
428
|
+
proxy = (struct worker_proxy *)duckdb_function_get_local_init_data(info);
|
|
429
|
+
#endif
|
|
430
|
+
rbduckdb_function_executor_dispatch_via_proxy(execute_execute_callback_protected, &darg, proxy);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
#ifdef HAVE_DUCKDB_H_GE_V1_5_0
|
|
434
|
+
/*
|
|
435
|
+
* Per-worker init for the execute path (DuckDB >= 1.5.0).
|
|
436
|
+
*
|
|
437
|
+
* DuckDB calls this once on each worker thread that will run the execute
|
|
438
|
+
* callback. We create a per-worker proxy (allocating its Ruby thread under the
|
|
439
|
+
* GVL via the global executor, since this runs on a non-Ruby thread) and store
|
|
440
|
+
* it as thread-local init data. The execute callback then dispatches through it
|
|
441
|
+
* instead of the shared global executor, so workers run callbacks concurrently.
|
|
442
|
+
* DuckDB invokes rbduckdb_worker_proxy_destroy when the local state is freed.
|
|
443
|
+
*/
|
|
444
|
+
struct create_proxy_callback_arg {
|
|
445
|
+
struct worker_proxy *proxy;
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
static VALUE create_proxy_callback(VALUE varg) {
|
|
449
|
+
struct create_proxy_callback_arg *arg = (struct create_proxy_callback_arg *)varg;
|
|
450
|
+
arg->proxy = rbduckdb_worker_proxy_create();
|
|
451
|
+
return Qnil;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/*
|
|
455
|
+
* rbduckdb_worker_proxy_create may raise (NoMemError, Thread.new failure),
|
|
456
|
+
* and the executor runs callbacks unprotected — a raise would longjmp past
|
|
457
|
+
* its done-signaling and block the waiting DuckDB worker forever. Swallow
|
|
458
|
+
* the exception instead: the proxy stays NULL, local_init sets no state, and
|
|
459
|
+
* the execute callback falls back to the global executor.
|
|
460
|
+
*/
|
|
461
|
+
static void create_proxy_callback_protected(void *user_data) {
|
|
462
|
+
int exception_state;
|
|
463
|
+
|
|
464
|
+
rb_protect(create_proxy_callback, (VALUE)user_data, &exception_state);
|
|
465
|
+
if (exception_state) {
|
|
466
|
+
rb_set_errinfo(Qnil);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
static void table_function_local_init_callback(duckdb_init_info info) {
|
|
471
|
+
struct create_proxy_callback_arg arg;
|
|
472
|
+
|
|
473
|
+
/* A Ruby calling thread runs the callback inline (Case 1/2); no proxy needed. */
|
|
474
|
+
if (ruby_native_thread_p()) return;
|
|
475
|
+
|
|
476
|
+
arg.proxy = NULL;
|
|
477
|
+
rbduckdb_function_executor_dispatch(create_proxy_callback_protected, &arg);
|
|
478
|
+
|
|
479
|
+
if (arg.proxy != NULL) {
|
|
480
|
+
duckdb_init_set_init_data(info, arg.proxy, rbduckdb_worker_proxy_destroy);
|
|
481
|
+
}
|
|
417
482
|
}
|
|
483
|
+
#endif
|
|
418
484
|
|
|
419
|
-
rubyDuckDBTableFunction *
|
|
485
|
+
rubyDuckDBTableFunction *rbduckdb_get_struct_table_function(VALUE self) {
|
|
420
486
|
rubyDuckDBTableFunction *ctx;
|
|
421
487
|
TypedData_Get_Struct(self, rubyDuckDBTableFunction, &table_function_data_type, ctx);
|
|
422
488
|
return ctx;
|
|
423
489
|
}
|
|
424
490
|
|
|
425
|
-
void
|
|
491
|
+
void rbduckdb_init_table_function(void) {
|
|
426
492
|
#if 0
|
|
427
493
|
VALUE mDuckDB = rb_define_module("DuckDB");
|
|
428
494
|
#endif
|
|
429
495
|
cDuckDBTableFunction = rb_define_class_under(mDuckDB, "TableFunction", rb_cObject);
|
|
430
496
|
rb_define_alloc_func(cDuckDBTableFunction, allocate);
|
|
431
497
|
|
|
432
|
-
rb_define_method(cDuckDBTableFunction, "initialize",
|
|
433
|
-
rb_define_method(cDuckDBTableFunction, "set_name",
|
|
434
|
-
rb_define_method(cDuckDBTableFunction, "name=",
|
|
435
|
-
rb_define_method(cDuckDBTableFunction, "add_parameter",
|
|
436
|
-
rb_define_method(cDuckDBTableFunction, "add_named_parameter",
|
|
437
|
-
rb_define_method(cDuckDBTableFunction, "bind",
|
|
438
|
-
rb_define_method(cDuckDBTableFunction, "init",
|
|
439
|
-
rb_define_method(cDuckDBTableFunction, "execute",
|
|
498
|
+
rb_define_method(cDuckDBTableFunction, "initialize", table_function_initialize, 0);
|
|
499
|
+
rb_define_method(cDuckDBTableFunction, "set_name", table_function_set_name, 1);
|
|
500
|
+
rb_define_method(cDuckDBTableFunction, "name=", table_function_set_name, 1);
|
|
501
|
+
rb_define_method(cDuckDBTableFunction, "add_parameter", table_function_add_parameter, 1);
|
|
502
|
+
rb_define_method(cDuckDBTableFunction, "add_named_parameter", table_function_add_named_parameter, 2);
|
|
503
|
+
rb_define_method(cDuckDBTableFunction, "bind", table_function_bind, 0);
|
|
504
|
+
rb_define_method(cDuckDBTableFunction, "init", table_function_init, 0);
|
|
505
|
+
rb_define_method(cDuckDBTableFunction, "execute", table_function_execute, 0);
|
|
440
506
|
}
|
data/ext/duckdb/table_function.h
CHANGED
|
@@ -11,7 +11,7 @@ struct _rubyDuckDBTableFunction {
|
|
|
11
11
|
typedef struct _rubyDuckDBTableFunction rubyDuckDBTableFunction;
|
|
12
12
|
|
|
13
13
|
extern VALUE cDuckDBTableFunction;
|
|
14
|
-
rubyDuckDBTableFunction *
|
|
15
|
-
void
|
|
14
|
+
rubyDuckDBTableFunction *rbduckdb_get_struct_table_function(VALUE self);
|
|
15
|
+
void rbduckdb_init_table_function(void);
|
|
16
16
|
|
|
17
17
|
#endif
|
|
@@ -5,12 +5,12 @@ VALUE cDuckDBTableFunctionBindInfo;
|
|
|
5
5
|
static void deallocate(void *ctx);
|
|
6
6
|
static VALUE allocate(VALUE klass);
|
|
7
7
|
static size_t memsize(const void *p);
|
|
8
|
-
static VALUE
|
|
9
|
-
static VALUE
|
|
10
|
-
static VALUE
|
|
11
|
-
static VALUE
|
|
12
|
-
static VALUE
|
|
13
|
-
static VALUE
|
|
8
|
+
static VALUE table_function_bind_info_parameter_count(VALUE self);
|
|
9
|
+
static VALUE table_function_bind_info_get_parameter(VALUE self, VALUE index);
|
|
10
|
+
static VALUE table_function_bind_info_get_named_parameter(VALUE self, VALUE name);
|
|
11
|
+
static VALUE table_function_bind_info__add_result_column(VALUE self, VALUE column_name, VALUE logical_type);
|
|
12
|
+
static VALUE table_function_bind_info_set_cardinality(VALUE self, VALUE cardinality, VALUE is_exact);
|
|
13
|
+
static VALUE table_function_bind_info_set_error(VALUE self, VALUE error);
|
|
14
14
|
|
|
15
15
|
static const rb_data_type_t bind_info_data_type = {
|
|
16
16
|
"DuckDB/TableFunctionBindInfo",
|
|
@@ -32,7 +32,7 @@ static size_t memsize(const void *p) {
|
|
|
32
32
|
return sizeof(rubyDuckDBBindInfo);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
rubyDuckDBBindInfo *
|
|
35
|
+
rubyDuckDBBindInfo *rbduckdb_get_struct_bind_info(VALUE obj) {
|
|
36
36
|
rubyDuckDBBindInfo *ctx;
|
|
37
37
|
TypedData_Get_Struct(obj, rubyDuckDBBindInfo, &bind_info_data_type, ctx);
|
|
38
38
|
return ctx;
|
|
@@ -52,7 +52,7 @@ rubyDuckDBBindInfo *get_struct_bind_info(VALUE obj) {
|
|
|
52
52
|
*
|
|
53
53
|
* bind_info.parameter_count # => 2
|
|
54
54
|
*/
|
|
55
|
-
static VALUE
|
|
55
|
+
static VALUE table_function_bind_info_parameter_count(VALUE self) {
|
|
56
56
|
rubyDuckDBBindInfo *ctx;
|
|
57
57
|
idx_t count;
|
|
58
58
|
|
|
@@ -71,7 +71,7 @@ static VALUE rbduckdb_bind_info_parameter_count(VALUE self) {
|
|
|
71
71
|
*
|
|
72
72
|
* param = bind_info.get_parameter(0)
|
|
73
73
|
*/
|
|
74
|
-
static VALUE
|
|
74
|
+
static VALUE table_function_bind_info_get_parameter(VALUE self, VALUE index) {
|
|
75
75
|
rubyDuckDBBindInfo *ctx;
|
|
76
76
|
idx_t idx;
|
|
77
77
|
duckdb_value param_value;
|
|
@@ -97,7 +97,7 @@ static VALUE rbduckdb_bind_info_get_parameter(VALUE self, VALUE index) {
|
|
|
97
97
|
*
|
|
98
98
|
* param = bind_info.get_named_parameter('limit')
|
|
99
99
|
*/
|
|
100
|
-
static VALUE
|
|
100
|
+
static VALUE table_function_bind_info_get_named_parameter(VALUE self, VALUE name) {
|
|
101
101
|
rubyDuckDBBindInfo *ctx;
|
|
102
102
|
const char *param_name;
|
|
103
103
|
duckdb_value param_value;
|
|
@@ -129,7 +129,7 @@ static VALUE rbduckdb_bind_info_get_named_parameter(VALUE self, VALUE name) {
|
|
|
129
129
|
* bind_info.add_result_column('id', DuckDB::LogicalType::BIGINT)
|
|
130
130
|
* bind_info.add_result_column('name', DuckDB::LogicalType::VARCHAR)
|
|
131
131
|
*/
|
|
132
|
-
static VALUE
|
|
132
|
+
static VALUE table_function_bind_info__add_result_column(VALUE self, VALUE column_name, VALUE logical_type) {
|
|
133
133
|
rubyDuckDBBindInfo *ctx;
|
|
134
134
|
rubyDuckDBLogicalType *ctx_logical_type;
|
|
135
135
|
const char *col_name;
|
|
@@ -152,7 +152,7 @@ static VALUE rbduckdb_bind_info__add_result_column(VALUE self, VALUE column_name
|
|
|
152
152
|
* bind_info.set_cardinality(100, true) # Exactly 100 rows
|
|
153
153
|
* bind_info.set_cardinality(1000, false) # Approximately 1000 rows
|
|
154
154
|
*/
|
|
155
|
-
static VALUE
|
|
155
|
+
static VALUE table_function_bind_info_set_cardinality(VALUE self, VALUE cardinality, VALUE is_exact) {
|
|
156
156
|
rubyDuckDBBindInfo *ctx;
|
|
157
157
|
idx_t card;
|
|
158
158
|
bool exact;
|
|
@@ -175,7 +175,7 @@ static VALUE rbduckdb_bind_info_set_cardinality(VALUE self, VALUE cardinality, V
|
|
|
175
175
|
*
|
|
176
176
|
* bind_info.set_error('Invalid parameter value')
|
|
177
177
|
*/
|
|
178
|
-
static VALUE
|
|
178
|
+
static VALUE table_function_bind_info_set_error(VALUE self, VALUE error) {
|
|
179
179
|
rubyDuckDBBindInfo *ctx;
|
|
180
180
|
const char *error_msg;
|
|
181
181
|
|
|
@@ -187,18 +187,18 @@ static VALUE rbduckdb_bind_info_set_error(VALUE self, VALUE error) {
|
|
|
187
187
|
return self;
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
-
void
|
|
190
|
+
void rbduckdb_init_table_function_bind_info(void) {
|
|
191
191
|
#if 0
|
|
192
192
|
VALUE mDuckDB = rb_define_module("DuckDB");
|
|
193
193
|
#endif
|
|
194
194
|
cDuckDBTableFunctionBindInfo = rb_define_class_under(cDuckDBTableFunction, "BindInfo", rb_cObject);
|
|
195
195
|
rb_define_alloc_func(cDuckDBTableFunctionBindInfo, allocate);
|
|
196
196
|
|
|
197
|
-
rb_define_method(cDuckDBTableFunctionBindInfo, "parameter_count",
|
|
198
|
-
rb_define_method(cDuckDBTableFunctionBindInfo, "get_parameter",
|
|
199
|
-
rb_define_method(cDuckDBTableFunctionBindInfo, "get_named_parameter",
|
|
200
|
-
rb_define_method(cDuckDBTableFunctionBindInfo, "set_cardinality",
|
|
201
|
-
rb_define_method(cDuckDBTableFunctionBindInfo, "set_error",
|
|
197
|
+
rb_define_method(cDuckDBTableFunctionBindInfo, "parameter_count", table_function_bind_info_parameter_count, 0);
|
|
198
|
+
rb_define_method(cDuckDBTableFunctionBindInfo, "get_parameter", table_function_bind_info_get_parameter, 1);
|
|
199
|
+
rb_define_method(cDuckDBTableFunctionBindInfo, "get_named_parameter", table_function_bind_info_get_named_parameter, 1);
|
|
200
|
+
rb_define_method(cDuckDBTableFunctionBindInfo, "set_cardinality", table_function_bind_info_set_cardinality, 2);
|
|
201
|
+
rb_define_method(cDuckDBTableFunctionBindInfo, "set_error", table_function_bind_info_set_error, 1);
|
|
202
202
|
|
|
203
|
-
rb_define_private_method(cDuckDBTableFunctionBindInfo, "_add_result_column",
|
|
203
|
+
rb_define_private_method(cDuckDBTableFunctionBindInfo, "_add_result_column", table_function_bind_info__add_result_column, 2);
|
|
204
204
|
}
|
|
@@ -8,7 +8,7 @@ struct _rubyDuckDBBindInfo {
|
|
|
8
8
|
typedef struct _rubyDuckDBBindInfo rubyDuckDBBindInfo;
|
|
9
9
|
|
|
10
10
|
extern VALUE cDuckDBTableFunctionBindInfo;
|
|
11
|
-
rubyDuckDBBindInfo *
|
|
12
|
-
void
|
|
11
|
+
rubyDuckDBBindInfo *rbduckdb_get_struct_bind_info(VALUE obj);
|
|
12
|
+
void rbduckdb_init_table_function_bind_info(void);
|
|
13
13
|
|
|
14
14
|
#endif
|
|
@@ -5,7 +5,7 @@ VALUE cDuckDBTableFunctionFunctionInfo;
|
|
|
5
5
|
static void deallocate(void *ctx);
|
|
6
6
|
static VALUE allocate(VALUE klass);
|
|
7
7
|
static size_t memsize(const void *p);
|
|
8
|
-
static VALUE
|
|
8
|
+
static VALUE table_function_function_info_set_error(VALUE self, VALUE error);
|
|
9
9
|
|
|
10
10
|
static const rb_data_type_t function_info_data_type = {
|
|
11
11
|
"DuckDB/TableFunctionFunctionInfo",
|
|
@@ -27,7 +27,7 @@ static size_t memsize(const void *p) {
|
|
|
27
27
|
return sizeof(rubyDuckDBFunctionInfo);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
rubyDuckDBFunctionInfo *
|
|
30
|
+
rubyDuckDBFunctionInfo *rbduckdb_get_struct_function_info(VALUE obj) {
|
|
31
31
|
rubyDuckDBFunctionInfo *ctx;
|
|
32
32
|
TypedData_Get_Struct(obj, rubyDuckDBFunctionInfo, &function_info_data_type, ctx);
|
|
33
33
|
return ctx;
|
|
@@ -42,7 +42,7 @@ rubyDuckDBFunctionInfo *get_struct_function_info(VALUE obj) {
|
|
|
42
42
|
*
|
|
43
43
|
* function_info.set_error('Invalid parameter value')
|
|
44
44
|
*/
|
|
45
|
-
static VALUE
|
|
45
|
+
static VALUE table_function_function_info_set_error(VALUE self, VALUE error) {
|
|
46
46
|
rubyDuckDBFunctionInfo *ctx;
|
|
47
47
|
const char *error_msg;
|
|
48
48
|
|
|
@@ -54,12 +54,12 @@ static VALUE rbduckdb_function_info_set_error(VALUE self, VALUE error) {
|
|
|
54
54
|
return self;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
void
|
|
57
|
+
void rbduckdb_init_table_function_function_info(void) {
|
|
58
58
|
#if 0
|
|
59
59
|
VALUE mDuckDB = rb_define_module("DuckDB");
|
|
60
60
|
#endif
|
|
61
61
|
cDuckDBTableFunctionFunctionInfo = rb_define_class_under(cDuckDBTableFunction, "FunctionInfo", rb_cObject);
|
|
62
62
|
rb_define_alloc_func(cDuckDBTableFunctionFunctionInfo, allocate);
|
|
63
63
|
|
|
64
|
-
rb_define_method(cDuckDBTableFunctionFunctionInfo, "set_error",
|
|
64
|
+
rb_define_method(cDuckDBTableFunctionFunctionInfo, "set_error", table_function_function_info_set_error, 1);
|
|
65
65
|
}
|