mirror of
https://gitea.invidious.io/iv-org/shard-crystal-sqlite3.git
synced 2024-08-15 00:53:26 +00:00
update to refactored api
refactor specs
This commit is contained in:
parent
5266a7e7b3
commit
add75d86bf
6 changed files with 131 additions and 73 deletions
|
@ -27,7 +27,6 @@ describe Database do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# pending
|
|
||||||
it "executes and selects blob" do
|
it "executes and selects blob" do
|
||||||
rows = with_db_old(&.execute(%(select X'53514C697465')))
|
rows = with_db_old(&.execute(%(select X'53514C697465')))
|
||||||
row = rows[0]
|
row = rows[0]
|
||||||
|
@ -60,6 +59,7 @@ describe Database do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# pending
|
||||||
it "gets column types" do
|
it "gets column types" do
|
||||||
Database.new(":memory:") do |db|
|
Database.new(":memory:") do |db|
|
||||||
db.execute "create table person (name string, age integer)"
|
db.execute "create table person (name string, age integer)"
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
require "./spec_helper"
|
require "./spec_helper"
|
||||||
|
|
||||||
def with_db
|
def with_db(&block : DB::Database ->)
|
||||||
yield DB.open "sqlite3", {"database": DB_FILENAME}
|
DB.open "sqlite3", {"database": DB_FILENAME}, &block
|
||||||
ensure
|
ensure
|
||||||
File.delete(DB_FILENAME)
|
File.delete(DB_FILENAME)
|
||||||
end
|
end
|
||||||
|
|
||||||
def with_mem_db
|
def with_mem_db(&block : DB::Database ->)
|
||||||
yield DB.open "sqlite3", {"database": ":memory:"}
|
DB.open "sqlite3", {"database": ":memory:"}, &block
|
||||||
end
|
end
|
||||||
|
|
||||||
def sql(s : String)
|
def sql(s : String)
|
||||||
|
@ -18,16 +18,16 @@ def sql(s)
|
||||||
"#{s}"
|
"#{s}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def assert_single_read(result_set, value_type, value)
|
def assert_single_read(rs, value_type, value)
|
||||||
result_set.move_next.should be_true
|
rs.move_next.should be_true
|
||||||
result_set.read(value_type).should eq(value)
|
rs.read(value_type).should eq(value)
|
||||||
result_set.move_next.should be_false
|
rs.move_next.should be_false
|
||||||
end
|
end
|
||||||
|
|
||||||
def assert_single_read?(result_set, value_type, value)
|
def assert_single_read?(rs, value_type, value)
|
||||||
result_set.move_next.should be_true
|
rs.move_next.should be_true
|
||||||
result_set.read?(value_type).should eq(value)
|
rs.read?(value_type).should eq(value)
|
||||||
result_set.move_next.should be_false
|
rs.move_next.should be_false
|
||||||
end
|
end
|
||||||
|
|
||||||
describe Driver do
|
describe Driver do
|
||||||
|
@ -45,108 +45,154 @@ describe Driver do
|
||||||
{% for value in [1, 1_i64, "hello", 1.5, 1.5_f32] %}
|
{% for value in [1, 1_i64, "hello", 1.5, 1.5_f32] %}
|
||||||
it "executes and select {{value.id}}" do
|
it "executes and select {{value.id}}" do
|
||||||
with_db do |db|
|
with_db do |db|
|
||||||
result_set = db.exec("select #{sql({{value}})}")
|
db.scalar(typeof({{value}}), "select #{sql({{value}})}").should eq({{value}})
|
||||||
assert_single_read result_set, typeof({{value}}), {{value}}
|
|
||||||
|
db.query "select #{sql({{value}})}" do |rs|
|
||||||
|
assert_single_read rs, typeof({{value}}), {{value}}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "executes and select {{value.id}} as nillable" do
|
it "executes and select {{value.id}} as nillable" do
|
||||||
with_db do |db|
|
with_db do |db|
|
||||||
result_set = db.exec("select #{sql({{value}})}")
|
db.scalar?(typeof({{value}}), "select #{sql({{value}})}").should eq({{value}})
|
||||||
assert_single_read? result_set, typeof({{value}}), {{value}}
|
|
||||||
|
db.query "select #{sql({{value}})}" do |rs|
|
||||||
|
assert_single_read? rs, typeof({{value}}), {{value}}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "executes and select nil as type of {{value.id}}" do
|
it "executes and select nil as type of {{value.id}}" do
|
||||||
with_db do |db|
|
with_db do |db|
|
||||||
result_set = db.exec("select null")
|
db.scalar?(typeof({{value}}), "select null").should be_nil
|
||||||
assert_single_read? result_set, typeof({{value}}), nil
|
|
||||||
|
db.query "select null" do |rs|
|
||||||
|
assert_single_read? rs, typeof({{value}}), nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "executes with bind {{value.id}}" do
|
it "executes with bind {{value.id}}" do
|
||||||
with_db do |db|
|
with_db do |db|
|
||||||
result_set = db.exec(%(select ?), {{value}})
|
db.scalar(typeof({{value}}), %(select ?), {{value}}).should eq({{value}})
|
||||||
assert_single_read result_set, typeof({{value}}), {{value}}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "executes with bind {{value.id}} read as nillable" do
|
it "executes with bind {{value.id}} read as nillable" do
|
||||||
with_db do |db|
|
with_db do |db|
|
||||||
result_set = db.exec(%(select ?), {{value}})
|
db.scalar?(typeof({{value}}), %(select ?), {{value}}).should eq({{value}})
|
||||||
assert_single_read? result_set, typeof({{value}}), {{value}}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "executes with bind nil as typeof {{value.id}}" do
|
it "executes with bind nil as typeof {{value.id}}" do
|
||||||
with_db do |db|
|
with_db do |db|
|
||||||
result_set = db.exec(%(select ?), nil)
|
db.scalar?(typeof({{value}}), %(select ?), nil).should be_nil
|
||||||
assert_single_read? result_set, typeof({{value}}), nil
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "executes with bind {{value.id}} as array" do
|
it "executes with bind {{value.id}} as array" do
|
||||||
with_db do |db|
|
with_db do |db|
|
||||||
result_set = db.exec(%(select ?), [{{value}}])
|
db.scalar?(typeof({{value}}), %(select ?), [{{value}}]).should eq({{value}})
|
||||||
assert_single_read result_set, typeof({{value}}), {{value}}
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
{% end %}
|
{% end %}
|
||||||
|
|
||||||
it "executes and selects blob" do
|
it "executes and selects blob" do
|
||||||
with_db do |db|
|
with_db do |db|
|
||||||
result_set = db.exec %(select X'53514C697465')
|
slice = db.scalar(Slice(UInt8), %(select X'53514C697465'))
|
||||||
result_set.move_next
|
slice.to_a.should eq([0x53, 0x51, 0x4C, 0x69, 0x74, 0x65])
|
||||||
result_set.read(Slice(UInt8)).to_a.should eq([0x53, 0x51, 0x4C, 0x69, 0x74, 0x65])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "executes with bind blob" do
|
it "executes with bind blob" do
|
||||||
with_db do |db|
|
with_db do |db|
|
||||||
ary = UInt8[0x53, 0x51, 0x4C, 0x69, 0x74, 0x65]
|
ary = UInt8[0x53, 0x51, 0x4C, 0x69, 0x74, 0x65]
|
||||||
result_set = db.exec %(select cast(? as BLOB)), Slice.new(ary.to_unsafe, ary.size)
|
slice = db.scalar Slice(UInt8), %(select cast(? as BLOB)), Slice.new(ary.to_unsafe, ary.size)
|
||||||
result_set.move_next
|
slice.to_a.should eq(ary)
|
||||||
result_set.read(Slice(UInt8)).to_a.should eq(ary)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "executes with named bind using symbol" do
|
it "executes with named bind using symbol" do
|
||||||
with_db do |db|
|
with_db do |db|
|
||||||
result_set = db.exec(%(select :value), {value: "hello"})
|
db.scalar(String, %(select :value), {value: "hello"}).should eq("hello")
|
||||||
assert_single_read result_set, String, "hello"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "executes with named bind using string" do
|
it "executes with named bind using string" do
|
||||||
with_db do |db|
|
with_db do |db|
|
||||||
result_set = db.exec(%(select :value), {"value": "hello"})
|
db.scalar(String, %(select :value), {"value": "hello"}).should eq("hello")
|
||||||
assert_single_read result_set, String, "hello"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "gets column count" do
|
it "gets column count" do
|
||||||
with_mem_db do |db|
|
with_mem_db do |db|
|
||||||
db.exec_non_query "create table person (name string, age integer)"
|
db.exec "create table person (name string, age integer)"
|
||||||
db.exec_non_query %(insert into person values ("foo", 10))
|
|
||||||
|
|
||||||
run = false
|
db.query "select * from person" do |rs|
|
||||||
db.exec_query_each "select * from person" do |result_set|
|
rs.column_count.should eq(2)
|
||||||
run = true
|
|
||||||
result_set.column_count.should eq(2)
|
|
||||||
end
|
end
|
||||||
run.should be_true
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "gets column name" do
|
it "gets column name" do
|
||||||
with_mem_db do |db|
|
with_mem_db do |db|
|
||||||
db.exec_non_query "create table person (name string, age integer)"
|
db.exec "create table person (name string, age integer)"
|
||||||
db.exec_non_query %(insert into person values ("foo", 10))
|
|
||||||
|
|
||||||
db.exec_query_each("select * from person") do |result_set|
|
db.query "select * from person" do |rs|
|
||||||
result_set.column_name(0).should eq("name")
|
rs.column_name(0).should eq("name")
|
||||||
result_set.column_name(1).should eq("age")
|
rs.column_name(1).should eq("age")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# TODO get other value types from table
|
||||||
|
# TODO get many rows from table
|
||||||
|
# TODO get_last_row_id
|
||||||
|
# TODO gets column types
|
||||||
|
# TODO migrate quotes to std
|
||||||
|
|
||||||
|
it "gets values from table" do
|
||||||
|
with_mem_db do |db|
|
||||||
|
db.exec "create table person (name string, age integer)"
|
||||||
|
db.exec %(insert into person values ("foo", 10))
|
||||||
|
|
||||||
|
db.query "select * from person" do |rs|
|
||||||
|
rs.move_next.should be_true
|
||||||
|
rs.read(String).should eq("foo")
|
||||||
|
rs.read(Int32).should eq(10)
|
||||||
|
rs.move_next.should be_false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "ensures statements are closed" do
|
||||||
|
begin
|
||||||
|
DB.open "sqlite3", {"database": DB_FILENAME} do |db|
|
||||||
|
db.exec %(create table if not exists a (i int not null, str text not null);)
|
||||||
|
db.exec %(insert into a (i, str) values (23, "bai bai");)
|
||||||
|
end
|
||||||
|
|
||||||
|
2.times do |i|
|
||||||
|
DB.open "sqlite3", {"database": DB_FILENAME} do |db|
|
||||||
|
begin
|
||||||
|
db.query("SELECT i, str FROM a WHERE i = ?", 23) do |rs|
|
||||||
|
rs.move_next
|
||||||
|
break
|
||||||
|
end
|
||||||
|
rescue e : SQLite3::Exception
|
||||||
|
fail("Expected no exception, but got \"#{e.message}\"")
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
db.exec("UPDATE a SET i = ? WHERE i = ?", 23, 23)
|
||||||
|
rescue e : SQLite3::Exception
|
||||||
|
fail("Expected no exception, but got \"#{e.message}\"")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ensure
|
||||||
|
File.delete(DB_FILENAME)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
23
src/sqlite3/connection.cr
Normal file
23
src/sqlite3/connection.cr
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
class SQLite3::Connection < DB::Connection
|
||||||
|
def initialize(options)
|
||||||
|
super
|
||||||
|
filename = options["database"]
|
||||||
|
check LibSQLite3.open_v2(filename, out @db, (LibSQLite3::Flag::READWRITE | LibSQLite3::Flag::CREATE), nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
def prepare(query)
|
||||||
|
Statement2.new(self, query)
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform_close
|
||||||
|
LibSQLite3.close_v2(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_unsafe
|
||||||
|
@db
|
||||||
|
end
|
||||||
|
|
||||||
|
private def check(code)
|
||||||
|
raise Exception.new(self) unless code == 0
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,21 +1,6 @@
|
||||||
class SQLite3::Driver < DB::Driver
|
class SQLite3::Driver < DB::Driver
|
||||||
def initialize(options)
|
def build_connection
|
||||||
super
|
SQLite3::Connection.new(options)
|
||||||
filename = options["database"]
|
|
||||||
check LibSQLite3.open_v2(filename, out @db, (LibSQLite3::Flag::READWRITE | LibSQLite3::Flag::CREATE), nil)
|
|
||||||
# @closed = false
|
|
||||||
end
|
|
||||||
|
|
||||||
def prepare(query)
|
|
||||||
Statement2.new(self, query)
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_unsafe
|
|
||||||
@db
|
|
||||||
end
|
|
||||||
|
|
||||||
private def check(code)
|
|
||||||
raise Exception.new(@db) unless code == 0
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ class SQLite3::ResultSet2 < DB::ResultSet
|
||||||
when LibSQLite3::Code::DONE
|
when LibSQLite3::Code::DONE
|
||||||
false
|
false
|
||||||
else
|
else
|
||||||
raise Exception.new(@statement.driver)
|
raise Exception.new(@statement.connection)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -65,6 +65,10 @@ class SQLite3::ResultSet2 < DB::ResultSet
|
||||||
String.new LibSQLite3.column_name(self, index)
|
String.new LibSQLite3.column_name(self, index)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def column_type(index : Int32)
|
||||||
|
raise "not implemented"
|
||||||
|
end
|
||||||
|
|
||||||
def to_unsafe
|
def to_unsafe
|
||||||
@statement.to_unsafe
|
@statement.to_unsafe
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
class SQLite3::Statement2 < DB::Statement
|
class SQLite3::Statement2 < DB::Statement
|
||||||
def initialize(@driver, sql)
|
def initialize(connection, sql)
|
||||||
check LibSQLite3.prepare_v2(@driver, sql, sql.bytesize + 1, out @stmt, nil)
|
super(connection)
|
||||||
# @closed = false
|
check LibSQLite3.prepare_v2(@connection, sql, sql.bytesize + 1, out @stmt, nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
protected def before_execute
|
protected def begin_parameters
|
||||||
LibSQLite3.reset(self)
|
LibSQLite3.reset(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ class SQLite3::Statement2 < DB::Statement
|
||||||
bind_arg(index, value)
|
bind_arg(index, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
protected def execute
|
protected def perform
|
||||||
ResultSet2.new(self)
|
ResultSet2.new(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ class SQLite3::Statement2 < DB::Statement
|
||||||
end
|
end
|
||||||
|
|
||||||
private def check(code)
|
private def check(code)
|
||||||
raise Exception.new(@driver) unless code == 0
|
raise Exception.new(@connection) unless code == 0
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_unsafe
|
def to_unsafe
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue