ruby-duckdb is Ruby binding for DuckDB database engine
You must have DuckDB engine installed in order to build/use this module.
gem install duckdb
or you must specify the location of the C header and library files:
gem install duckdb -- --with-duckdb-include=/duckdb_header_directory --with-duckdb-lib=/duckdb_library_directory
require 'duckdb'
db = DuckDB::Database.open # database in memory
con = db.connect
con.query('CREATE TABLE users (id INTEGER, name VARCHAR(30))')
con.query("INSERT into users VALUES(1, 'Alice')")
con.query("INSERT into users VALUES(2, 'Bob')")
con.query("INSERT into users VALUES(3, 'Cathy')")
result = con.query('SELECT * from users')
result.each do |row|
p row
end
Or, you can use block.
require 'duckdb'
DuckDB::Database.open do |db|
db.connect do |con|
con.query('CREATE TABLE users (id INTEGER, name VARCHAR(30))')
con.query("INSERT into users VALUES(1, 'Alice')")
con.query("INSERT into users VALUES(2, 'Bob')")
con.query("INSERT into users VALUES(3, 'Cathy')")
result = con.query('SELECT * from users')
result.each do |row|
p row
end
end
end
BLOB is available with DuckDB v0.2.5 or later.
Use DuckDB::Blob.new
or use sting#force_encoding(Encoding::BINARY)
require 'duckdb'
DuckDB::Database.open do |db|
db.connect do |con|
con.query('CREATE TABLE blob_table (binary_data BLOB)')
stmt = DuckDB::PreparedStatement.new(con, 'INSERT INTO blob_table VALUES ($1)')
stmt.bind(1, DuckDB::Blob.new("\0\1\2\3\4\5"))
# stmt.bind(1, "\0\1\2\3\4\5".force_encoding(Encoding::BINARY))
stmt.execute
result = con.query('SELECT binary_data FROM blob_table')
p result.first.first
end
end
Appender class provides Ruby interface of DuckDB Appender
require 'duckdb'
require 'benchmark'
def insert
DuckDB::Database.open do |db|
db.connect do |con|
con.query('CREATE TABLE users (id INTEGER, name VARCHAR(30))')
10000.times do
con.query("INSERT into users VALUES(1, 'Alice')")
end
end
end
end
def prepare
DuckDB::Database.open do |db|
db.connect do |con|
con.query('CREATE TABLE users (id INTEGER, name VARCHAR(30))')
stmt = con.prepared_statement('INSERT INTO users VALUES($1, $2)')
10000.times do
stmt.bind(1, 1)
stmt.bind(2, 'Alice')
stmt.execute
end
end
end
end
def append
DuckDB::Database.open do |db|
db.connect do |con|
con.query('CREATE TABLE users (id INTEGER, name VARCHAR(30))')
appender = con.appender('users')
10000.times do
appender.begin_row
appender.append(1)
appender.append('Alice')
appender.end_row
end
appender.flush
end
end
end
Benchmark.bm(8) do |x|
x.report('insert') { insert }
x.report('prepare') { prepare }
x.report('append') { append }
end
# =>
# user system total real
# insert 0.637439 0.000000 0.637439 ( 0.637486 )
# prepare 0.230457 0.000000 0.230457 ( 0.230460 )
# append 0.012666 0.000000 0.012666 ( 0.012670 )
Config class provides Ruby interface of DuckDB configuration.
require 'duckdb'
config = DuckDB::Config.new
config['default_order'] = 'DESC'
db = DuckDB::Database.open(nil, config)
con = db.connect
con.query('CREATE TABLE numbers (number INTEGER)')
con.query('INSERT INTO numbers VALUES (2), (1), (4), (3)')
# number is ordered by descending.
r = con.query('SELECT number FROM numbers ORDER BY number')
r.first.first # => 4