Skip to content
Merged
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
84 changes: 30 additions & 54 deletions sample/issue922.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,73 +3,49 @@
require 'duckdb'
require 'polars-df'

df = Polars::DataFrame.new(
{
a: [1, 2, 3],
b: %w[one two three]
}
)

module DuckDB
class TableFunction
@table_adapters = {}
class << self
def add_table_adapter(klass, adapter)
@table_adapters[klass] = adapter
end

def table_adapter_for(klass)
@table_adapters[klass]
end
end
class PolarsDataFrameTableAdapter
def call(data_frame, name, columns: nil)
columns ||= infer_columns(data_frame)
DuckDB::TableFunction.create(name:, columns:, &execute_block(data_frame))
end

class Connection
def create_table_function(object, name)
adapter = TableFunction.table_adapter_for(object.class)
raise ArgumentError, "No table adapter registered for #{object.class}" if adapter.nil?
private

tf = adapter.call(object, name)
register_table_function(tf)
def execute_block(data_frame)
counter = 0
height = data_frame.height
width = data_frame.width
proc do |_func_info, output|
next counter = 0 if counter >= height

write_row(data_frame, output, counter, width)
counter += 1
1
end
end

module Polars
module DataFrame
class TableAdapter
def call(df, name) # rubocop:disable Metrics/MethodLength, Naming/MethodParameterName
columns = df.columns.to_h { |header| [header, LogicalType::VARCHAR] }
counter = 0
height = df.height
width = df.columns.length
def write_row(data_frame, output, counter, width)
width.times { |index| output.set_value(index, 0, data_frame[counter, index]) }
end

DuckDB::TableFunction.create(
name:,
columns:
) do |_func_info, output|
if counter < height
width.times do |index|
output.set_value(index, 0, df[counter, index])
end
counter += 1
1
else
counter = 0
0
end
end
end
end
end
def infer_columns(data_frame)
data_frame.columns.to_h { |header| [header, DuckDB::LogicalType::VARCHAR] }
end
TableFunction.add_table_adapter(::Polars::DataFrame, DuckDB::Polars::DataFrame::TableAdapter.new)
end

db = DuckDB::Database.open
DuckDB::TableFunction.add_table_adapter(Polars::DataFrame, PolarsDataFrameTableAdapter.new)

df = Polars::DataFrame.new(
{
a: [1, 2, 3],
b: %w[one two three]
}
)

db = DuckDB::Database.open
con = db.connect
con.query('SET threads=1')
con.create_table_function(df, 'polars_df')
con.expose_as_table(df, 'polars_df')
result = con.query('SELECT * FROM polars_df()').to_a
p result
puts result.first.first == '1'
Expand Down
Loading