Skip to content

Commit 188871d

Browse files
committed
Add BLOB support to scalar functions
- Add DUCKDB_TYPE_BLOB case to vector_set_value_at() - Uses same API as VARCHAR: duckdb_vector_assign_string_element_len() - Update type validation to allow :blob - Add test_scalar_function_blob_return_type test - Sort allowed types alphabetically in validation
1 parent 71fcf24 commit 188871d

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed

ext/duckdb/scalar_function.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,14 @@ static void vector_set_value_at(duckdb_vector vector, duckdb_logical_type elemen
251251
duckdb_vector_assign_string_element_len(vector, index, str_ptr, str_len);
252252
break;
253253
}
254+
case DUCKDB_TYPE_BLOB: {
255+
// BLOB uses same API as VARCHAR, but expects binary data
256+
VALUE str = rb_obj_as_string(value);
257+
const char *str_ptr = StringValuePtr(str);
258+
idx_t str_len = RSTRING_LEN(str);
259+
duckdb_vector_assign_string_element_len(vector, index, str_ptr, str_len);
260+
break;
261+
}
254262
default:
255263
rb_raise(rb_eArgError, "Unsupported return type for scalar function");
256264
break;

lib/duckdb/scalar_function.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module DuckDB
44
# DuckDB::ScalarFunction encapsulates DuckDB's scalar function
55
class ScalarFunction
66
# Sets the return type for the scalar function.
7-
# Currently supports BOOLEAN, INTEGER, BIGINT, FLOAT, DOUBLE, and VARCHAR types.
7+
# Currently supports BOOLEAN, INTEGER, BIGINT, FLOAT, DOUBLE, VARCHAR, and BLOB types.
88
#
99
# @param logical_type [DuckDB::LogicalType] the return type
1010
# @return [DuckDB::ScalarFunction] self
@@ -13,9 +13,9 @@ def return_type=(logical_type)
1313
raise DuckDB::Error, 'logical_type must be a DuckDB::LogicalType' unless logical_type.is_a?(DuckDB::LogicalType)
1414

1515
# Check if the type is supported
16-
unless %i[boolean integer bigint float double varchar].include?(logical_type.type)
16+
unless %i[bigint blob boolean double float integer varchar].include?(logical_type.type)
1717
raise DuckDB::Error,
18-
'Only BOOLEAN, INTEGER, BIGINT, FLOAT, DOUBLE, and VARCHAR return types are currently supported'
18+
'Only BIGINT, BLOB, BOOLEAN, DOUBLE, FLOAT, INTEGER, and VARCHAR return types are currently supported'
1919
end
2020

2121
_set_return_type(logical_type)

test/duckdb_test/scalar_function_test.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,5 +231,25 @@ def test_scalar_function_varchar_return_type # rubocop:disable Metrics/MethodLen
231231

232232
assert_equal [['Hello, Alice!'], ['Hello, Bob!']], result.to_a
233233
end
234+
235+
def test_scalar_function_blob_return_type # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
236+
@con.execute('SET threads=1')
237+
@con.execute('CREATE TABLE test_table (data BLOB)')
238+
@con.execute("INSERT INTO test_table VALUES ('\\x01\\x02\\x03'::BLOB), ('\\xAA\\xBB\\xCC'::BLOB)")
239+
240+
sf = DuckDB::ScalarFunction.new
241+
sf.name = 'add_prefix'
242+
sf.add_parameter(DuckDB::LogicalType.new(18)) # BLOB (type ID 18)
243+
sf.return_type = DuckDB::LogicalType.new(18) # BLOB
244+
sf.set_function { |data| DuckDB::Blob.new("\xFF".b + data) }
245+
246+
@con.register_scalar_function(sf)
247+
result = @con.execute('SELECT add_prefix(data) FROM test_table ORDER BY data')
248+
rows = result.to_a
249+
250+
assert_equal 2, rows.size
251+
assert_equal "\xFF\x01\x02\x03".b, rows[0][0]
252+
assert_equal "\xFF\xAA\xBB\xCC".b, rows[1][0]
253+
end
234254
end
235255
end

0 commit comments

Comments
 (0)