Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
All notable changes to this project will be documented in this file.

# Unreleased
- add `DuckDB::TableFunction::BindInfo#set_bind_data` to store an arbitrary Ruby object as a custom table function's bind data.
- add `DuckDB::TableFunction::FunctionInfo#get_bind_data` to retrieve, during execution, the object stored by `BindInfo#set_bind_data`.
- add `DuckDB::TableFunction::InitInfo#bind_data` (and `#get_bind_data`) to retrieve, during the init phase, the object stored by `BindInfo#set_bind_data`.
- add `DuckDB::TableFunction::BindInfo#bind_data=` to store an arbitrary Ruby object as a custom table function's bind data.
- add `DuckDB::TableFunction::FunctionInfo#bind_data` to retrieve, during execution, the object stored by `BindInfo#bind_data=`.
- add `DuckDB::TableFunction::InitInfo#bind_data` to retrieve, during the init phase, the object stored by `BindInfo#bind_data=`.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you change these entries into Braking changes section?

- support the statement types added in DuckDB 1.5.5: `#statement_type` now returns `:copy_database`, `:update_extensions` and `:merge_into` instead of raising `DuckDB::Error: Unknown statement type`.

# 1.5.5.0 - 2026-07-27
Expand Down
6 changes: 3 additions & 3 deletions ext/duckdb/table_function_bind_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,13 +170,13 @@ static VALUE table_function_bind_info_set_cardinality(VALUE self, VALUE cardinal

/*
* call-seq:
* bind_info.set_bind_data(data) -> self
* bind_info.bind_data = data
*
* Stores an arbitrary Ruby object as the table function's bind data. The same
* object can be retrieved during init and execution, and is kept alive until
* DuckDB frees the bind data.
*
* bind_info.set_bind_data({ rows: 100 })
* bind_info.bind_data = { rows: 100 }
*/
static VALUE table_function_bind_info_set_bind_data(VALUE self, VALUE data) {
rubyDuckDBBindInfo *ctx;
Expand Down Expand Up @@ -225,7 +225,7 @@ void rbduckdb_init_table_function_bind_info(void) {
rb_define_method(cDuckDBTableFunctionBindInfo, "get_parameter", table_function_bind_info_get_parameter, 1);
rb_define_method(cDuckDBTableFunctionBindInfo, "get_named_parameter", table_function_bind_info_get_named_parameter, 1);
rb_define_method(cDuckDBTableFunctionBindInfo, "set_cardinality", table_function_bind_info_set_cardinality, 2);
rb_define_method(cDuckDBTableFunctionBindInfo, "set_bind_data", table_function_bind_info_set_bind_data, 1);
rb_define_method(cDuckDBTableFunctionBindInfo, "bind_data=", table_function_bind_info_set_bind_data, 1);
rb_define_method(cDuckDBTableFunctionBindInfo, "set_error", table_function_bind_info_set_error, 1);

rb_define_private_method(cDuckDBTableFunctionBindInfo, "_add_result_column", table_function_bind_info__add_result_column, 2);
Expand Down
12 changes: 6 additions & 6 deletions ext/duckdb/table_function_function_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ VALUE cDuckDBTableFunctionFunctionInfo;
static void deallocate(void *ctx);
static VALUE allocate(VALUE klass);
static size_t memsize(const void *p);
static VALUE table_function_function_info_get_bind_data(VALUE self);
static VALUE table_function_function_info_bind_data(VALUE self);
static VALUE table_function_function_info_set_error(VALUE self, VALUE error);

static const rb_data_type_t function_info_data_type = {
Expand Down Expand Up @@ -36,14 +36,14 @@ rubyDuckDBFunctionInfo *rbduckdb_get_struct_function_info(VALUE obj) {

/*
* call-seq:
* function_info.get_bind_data -> object or nil
* function_info.bind_data -> object or nil
*
* Returns the object stored during the bind phase with
* DuckDB::TableFunction::BindInfo#set_bind_data, or nil if none was set.
* DuckDB::TableFunction::BindInfo#bind_data=, or nil if none was set.
*
* data = function_info.get_bind_data
* data = function_info.bind_data
*/
static VALUE table_function_function_info_get_bind_data(VALUE self) {
static VALUE table_function_function_info_bind_data(VALUE self) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Prefix both renamed C helpers with rbduckdb_.

The Ruby API rename is consistent. The renamed C symbols still use table_function_*. Apply the required prefix to each declaration, definition, and registration.

  • ext/duckdb/table_function_function_info.c#L46-L46: rename the implementation to rbduckdb_table_function_function_info_bind_data.
  • ext/duckdb/table_function_function_info.c#L8-L8: update the forward declaration.
  • ext/duckdb/table_function_function_info.c#L85-L85: update the Ruby method registration.
  • ext/duckdb/table_function_init_info.c#L128-L128: rename the implementation to rbduckdb_table_function_init_info_bind_data.
  • ext/duckdb/table_function_init_info.c#L12-L12: update the forward declaration.
  • ext/duckdb/table_function_init_info.c#L148-L148: update the Ruby method registration.

As per coding guidelines, all C symbols in ext/duckdb/**/*.c must be prefixed with rbduckdb_.

📍 Affects 2 files
  • ext/duckdb/table_function_function_info.c#L46-L46 (this comment)
  • ext/duckdb/table_function_function_info.c#L8-L8
  • ext/duckdb/table_function_function_info.c#L85-L85
  • ext/duckdb/table_function_init_info.c#L128-L128
  • ext/duckdb/table_function_init_info.c#L12-L12
  • ext/duckdb/table_function_init_info.c#L148-L148
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ext/duckdb/table_function_function_info.c` at line 46, The renamed C helpers
still lack the required rbduckdb_ prefix. In
ext/duckdb/table_function_function_info.c at lines 8-8, 46-46, and 85-85, rename
the declaration, implementation, and Ruby registration to
rbduckdb_table_function_function_info_bind_data; in
ext/duckdb/table_function_init_info.c at lines 12-12, 128-128, and 148-148,
apply the corresponding rbduckdb_table_function_init_info_bind_data name
consistently.

Source: Coding guidelines

rubyDuckDBFunctionInfo *ctx;
void *bind_data;

Expand Down Expand Up @@ -82,6 +82,6 @@ void rbduckdb_init_table_function_function_info(void) {
cDuckDBTableFunctionFunctionInfo = rb_define_class_under(cDuckDBTableFunction, "FunctionInfo", rb_cObject);
rb_define_alloc_func(cDuckDBTableFunctionFunctionInfo, allocate);

rb_define_method(cDuckDBTableFunctionFunctionInfo, "get_bind_data", table_function_function_info_get_bind_data, 0);
rb_define_method(cDuckDBTableFunctionFunctionInfo, "bind_data", table_function_function_info_bind_data, 0);
rb_define_method(cDuckDBTableFunctionFunctionInfo, "set_error", table_function_function_info_set_error, 1);
}
10 changes: 4 additions & 6 deletions ext/duckdb/table_function_init_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ static VALUE table_function_init_info_set_error(VALUE self, VALUE error);
static VALUE table_function_init_info_set_max_threads(VALUE self, VALUE max_threads);
static VALUE table_function_init_info_column_count(VALUE self);
static VALUE table_function_init_info_column_index(VALUE self, VALUE index);
static VALUE table_function_init_info_get_bind_data(VALUE self);
static VALUE table_function_init_info_bind_data(VALUE self);

static const rb_data_type_t init_info_data_type = {
"DuckDB/TableFunctionInitInfo",
Expand Down Expand Up @@ -118,15 +118,14 @@ static VALUE table_function_init_info_column_index(VALUE self, VALUE index) {

/*
* call-seq:
* init_info.get_bind_data -> object or nil
* init_info.bind_data -> object or nil
*
* Returns the object stored during the bind phase with
* DuckDB::TableFunction::BindInfo#set_bind_data, or nil if none was set.
* DuckDB::TableFunction::BindInfo#bind_data=, or nil if none was set.
*
* data = init_info.bind_data
*/
static VALUE table_function_init_info_get_bind_data(VALUE self) {
static VALUE table_function_init_info_bind_data(VALUE self) {
rubyDuckDBInitInfo *ctx;

TypedData_Get_Struct(self, rubyDuckDBInitInfo, &init_info_data_type, ctx);
Expand All @@ -146,6 +145,5 @@ void rbduckdb_init_table_function_init_info(void) {
rb_define_method(cDuckDBTableFunctionInitInfo, "max_threads=", table_function_init_info_set_max_threads, 1);
rb_define_method(cDuckDBTableFunctionInitInfo, "column_count", table_function_init_info_column_count, 0);
rb_define_method(cDuckDBTableFunctionInitInfo, "column_index", table_function_init_info_column_index, 1);
rb_define_method(cDuckDBTableFunctionInitInfo, "get_bind_data", table_function_init_info_get_bind_data, 0);
rb_define_method(cDuckDBTableFunctionInitInfo, "bind_data", table_function_init_info_get_bind_data, 0);
rb_define_method(cDuckDBTableFunctionInitInfo, "bind_data", table_function_init_info_bind_data, 0);
}
14 changes: 6 additions & 8 deletions test/duckdb_test/table_function/function_info_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,24 +49,22 @@ def test_bind_data_round_trip
table_function = DuckDB::TableFunction.new
table_function.name = 'test_bind_data'

returned_bind_info = nil
table_function.bind do |bind_info|
bind_info.add_result_column('value', DuckDB::LogicalType::BIGINT)
returned_bind_info = bind_info.set_bind_data({ token: 'round-trip', n: 7 })
bind_info.bind_data = { token: 'round-trip', n: 7 }
end

table_function.init { |_init_info| GC.compact }

observed_bind_data = nil
table_function.execute do |func_info, output|
observed_bind_data = func_info.get_bind_data
observed_bind_data = func_info.bind_data
output.size = 0
end

@connection.register_table_function(table_function)
@connection.query('SELECT * FROM test_bind_data()').each.to_a

assert_instance_of DuckDB::TableFunction::BindInfo, returned_bind_info
assert_equal({ token: 'round-trip', n: 7 }, observed_bind_data)
end

Expand All @@ -78,15 +76,15 @@ def test_bind_data_last_set_wins

table_function.bind do |bind_info|
bind_info.add_result_column('value', DuckDB::LogicalType::BIGINT)
bind_info.set_bind_data({ which: 'first' })
bind_info.set_bind_data({ which: 'second' })
bind_info.bind_data = { which: 'first' }
bind_info.bind_data = { which: 'second' }
end

table_function.init { |_init_info| GC.compact }

observed_bind_data = nil
table_function.execute do |func_info, output|
observed_bind_data = func_info.get_bind_data
observed_bind_data = func_info.bind_data
output.size = 0
end

Expand All @@ -110,7 +108,7 @@ def test_bind_data_nil_when_unset

observed_bind_data = :unset
table_function.execute do |func_info, output|
observed_bind_data = func_info.get_bind_data
observed_bind_data = func_info.bind_data
output.size = 0
end

Expand Down
9 changes: 3 additions & 6 deletions test/duckdb_test/table_function/init_info_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,13 @@ def test_init_info_bind_data_round_trip

table_function.bind do |bind_info|
bind_info.add_result_column('value', DuckDB::LogicalType::BIGINT)
bind_info.set_bind_data({ token: 'init-round-trip', n: 7 })
bind_info.bind_data = { token: 'init-round-trip', n: 7 }
end

observed_bind_data = nil
observed_via_alias = nil
table_function.init do |init_info|
GC.compact
observed_bind_data = init_info.get_bind_data
observed_via_alias = init_info.bind_data
observed_bind_data = init_info.bind_data
end

table_function.execute { |_func_info, output| output.size = 0 }
Expand All @@ -165,7 +163,6 @@ def test_init_info_bind_data_round_trip
@connection.query('SELECT * FROM test_init_bind_data()').each.to_a

assert_equal({ token: 'init-round-trip', n: 7 }, observed_bind_data)
assert_same observed_bind_data, observed_via_alias
end

def test_init_info_bind_data_nil_when_unset
Expand All @@ -178,7 +175,7 @@ def test_init_info_bind_data_nil_when_unset

observed_bind_data = :unset
table_function.init do |init_info|
observed_bind_data = init_info.get_bind_data
observed_bind_data = init_info.bind_data
end

table_function.execute { |_func_info, output| output.size = 0 }
Expand Down
Loading