mirror of
https://gitea.invidious.io/iv-org/shard-crystal-sqlite3.git
synced 2024-08-15 00:53:26 +00:00
migrate to crystal std db. keeping old code side by side
This commit is contained in:
parent
67ef13caed
commit
efa010e2ad
7 changed files with 188 additions and 13 deletions
|
@ -1,8 +1,6 @@
|
|||
require "./spec_helper"
|
||||
|
||||
DB_FILENAME = "./test.db"
|
||||
|
||||
private def with_db
|
||||
private def with_db_old
|
||||
yield Database.new DB_FILENAME
|
||||
ensure
|
||||
File.delete(DB_FILENAME)
|
||||
|
@ -10,43 +8,43 @@ end
|
|||
|
||||
describe Database do
|
||||
it "opens a database" do
|
||||
with_db do |db|
|
||||
with_db_old do |db|
|
||||
File.exists?(DB_FILENAME).should be_true
|
||||
end
|
||||
end
|
||||
|
||||
[nil, 1, 1_i64, "hello", 1.5, 1.5_f32].each do |value|
|
||||
it "executes and select #{value}" do
|
||||
with_db(&.execute("select #{value ? value.inspect : "null"}")).should eq([[value]])
|
||||
with_db_old(&.execute("select #{value ? value.inspect : "null"}")).should eq([[value]])
|
||||
end
|
||||
|
||||
it "executes with bind #{value}" do
|
||||
with_db(&.execute(%(select ?), value)).should eq([[value]])
|
||||
with_db_old(&.execute(%(select ?), value)).should eq([[value]])
|
||||
end
|
||||
|
||||
it "executes with bind #{value} as array" do
|
||||
with_db(&.execute(%(select ?), [value])).should eq([[value]])
|
||||
with_db_old(&.execute(%(select ?), [value])).should eq([[value]])
|
||||
end
|
||||
end
|
||||
|
||||
it "executes and selects blob" do
|
||||
rows = with_db(&.execute(%(select X'53514C697465')))
|
||||
rows = with_db_old(&.execute(%(select X'53514C697465')))
|
||||
row = rows[0]
|
||||
cell = row[0] as Slice(UInt8)
|
||||
cell.to_a.should eq([0x53, 0x51, 0x4C, 0x69, 0x74, 0x65])
|
||||
end
|
||||
|
||||
it "executes with named bind using symbol" do
|
||||
with_db(&.execute(%(select :value), {value: "hello"})).should eq([["hello"]])
|
||||
with_db_old(&.execute(%(select :value), {value: "hello"})).should eq([["hello"]])
|
||||
end
|
||||
|
||||
it "executes with named bind using string" do
|
||||
with_db(&.execute(%(select :value), {"value": "hello"})).should eq([["hello"]])
|
||||
with_db_old(&.execute(%(select :value), {"value": "hello"})).should eq([["hello"]])
|
||||
end
|
||||
|
||||
it "executes with bind blob" do
|
||||
ary = UInt8[0x53, 0x51, 0x4C, 0x69, 0x74, 0x65]
|
||||
rows = with_db(&.execute(%(select cast(? as BLOB)), Slice.new(ary.to_unsafe, ary.size)))
|
||||
rows = with_db_old(&.execute(%(select cast(? as BLOB)), Slice.new(ary.to_unsafe, ary.size)))
|
||||
row = rows[0]
|
||||
cell = row[0] as Slice(UInt8)
|
||||
cell.to_a.should eq(ary)
|
||||
|
@ -102,11 +100,11 @@ describe Database do
|
|||
end
|
||||
|
||||
it "gets first row" do
|
||||
with_db(&.get_first_row(%(select 1))).should eq([1])
|
||||
with_db_old(&.get_first_row(%(select 1))).should eq([1])
|
||||
end
|
||||
|
||||
it "gets first value" do
|
||||
with_db(&.get_first_value(%(select 1))).should eq(1)
|
||||
with_db_old(&.get_first_value(%(select 1))).should eq(1)
|
||||
end
|
||||
|
||||
it "ensures statements are closed" do
|
||||
|
|
65
spec/driver_spec.cr
Normal file
65
spec/driver_spec.cr
Normal file
|
@ -0,0 +1,65 @@
|
|||
require "./spec_helper"
|
||||
|
||||
def with_db
|
||||
yield DB.open "sqlite3", {"database": DB_FILENAME}
|
||||
ensure
|
||||
File.delete(DB_FILENAME)
|
||||
end
|
||||
|
||||
def sql(s : String)
|
||||
"#{s.inspect}"
|
||||
end
|
||||
|
||||
def sql(s)
|
||||
"#{s}"
|
||||
end
|
||||
|
||||
describe Driver do
|
||||
it "should register sqlite3 name" do
|
||||
DB.driver_class("sqlite3").should eq(SQLite3::Driver)
|
||||
end
|
||||
|
||||
it "should use database option as file to open" do
|
||||
with_db do |db|
|
||||
db.driver_class.should eq(SQLite3::Driver)
|
||||
File.exists?(DB_FILENAME).should be_true
|
||||
end
|
||||
end
|
||||
|
||||
{% for value in [1, 1_i64, "hello", 1.5, 1.5_f32] %}
|
||||
it "executes and select {{value.id}}" do
|
||||
with_db do |db|
|
||||
result_set = db.exec("select #{sql({{value}})}")
|
||||
result_set.move_next.should be_true
|
||||
result_set.read(typeof({{value}})).should eq({{value}})
|
||||
result_set.move_next.should be_false
|
||||
end
|
||||
end
|
||||
|
||||
it "executes and select {{value.id}} as nillable" do
|
||||
with_db do |db|
|
||||
result_set = db.exec("select #{sql({{value}})}")
|
||||
result_set.move_next.should be_true
|
||||
result_set.read?(typeof({{value}})).should eq({{value}})
|
||||
result_set.move_next.should be_false
|
||||
end
|
||||
end
|
||||
|
||||
it "executes and select nil as type of {{value.id}}" do
|
||||
with_db do |db|
|
||||
result_set = db.exec("select null")
|
||||
result_set.move_next.should be_true
|
||||
result_set.read?(typeof({{value}})).should be_nil
|
||||
result_set.move_next.should be_false
|
||||
end
|
||||
end
|
||||
|
||||
# it "executes with bind #{value}" do
|
||||
# with_db(&.execute(%(select ?), value)).should eq([[value]])
|
||||
# end
|
||||
|
||||
# it "executes with bind #{value} as array" do
|
||||
# with_db(&.execute(%(select ?), [value])).should eq([[value]])
|
||||
# end
|
||||
{% end %}
|
||||
end
|
|
@ -2,3 +2,5 @@ require "spec"
|
|||
require "../src/sqlite3"
|
||||
|
||||
include SQLite3
|
||||
|
||||
DB_FILENAME = "./test.db"
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
require "db"
|
||||
require "./sqlite3/**"
|
||||
|
|
22
src/sqlite3/driver.cr
Normal file
22
src/sqlite3/driver.cr
Normal file
|
@ -0,0 +1,22 @@
|
|||
class SQLite3::Driver < DB::Driver
|
||||
def initialize(options)
|
||||
super
|
||||
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
|
||||
|
||||
DB.register_driver "sqlite3", SQLite3::Driver
|
68
src/sqlite3/result_set2.cr
Normal file
68
src/sqlite3/result_set2.cr
Normal file
|
@ -0,0 +1,68 @@
|
|||
class SQLite3::ResultSet2 < DB::ResultSet
|
||||
@column_index = 0
|
||||
|
||||
# Advances to the next row. Returns `true` if there's a next row,
|
||||
# `false` otherwise. Must be called at least once to advance to the first
|
||||
# row.
|
||||
def move_next
|
||||
@column_index = 0
|
||||
|
||||
case step
|
||||
when LibSQLite3::Code::ROW
|
||||
true
|
||||
when LibSQLite3::Code::DONE
|
||||
false
|
||||
else
|
||||
raise Exception.new(@statement.driver)
|
||||
end
|
||||
end
|
||||
|
||||
{% for t in DB::TYPES %}
|
||||
def read?(t : {{t}}.class) : {{t}}?
|
||||
if read_nil?
|
||||
moving_column { nil }
|
||||
else
|
||||
read(t)
|
||||
end
|
||||
end
|
||||
{% end %}
|
||||
|
||||
def read(t : String.class) : String
|
||||
moving_column { |col| String.new(LibSQLite3.column_text(self, col)) }
|
||||
end
|
||||
|
||||
def read(t : Int32.class) : Int32
|
||||
read(Int64).to_i32
|
||||
end
|
||||
|
||||
def read(t : Int64.class) : Int64
|
||||
moving_column { |col| LibSQLite3.column_int64(self, col) }
|
||||
end
|
||||
|
||||
def read(t : Float32.class) : Float32
|
||||
read(Float64).to_f32
|
||||
end
|
||||
|
||||
def read(t : Float64.class) : Float64
|
||||
moving_column { LibSQLite3.column_double(self, @column_index) }
|
||||
end
|
||||
|
||||
def to_unsafe
|
||||
@statement.to_unsafe
|
||||
end
|
||||
|
||||
private def read_nil?
|
||||
LibSQLite3.column_type(self, @column_index) == Type::NULL
|
||||
end
|
||||
|
||||
# :nodoc:
|
||||
private def step
|
||||
LibSQLite3::Code.new LibSQLite3.step(@statement)
|
||||
end
|
||||
|
||||
private def moving_column
|
||||
res = yield @column_index
|
||||
@column_index += 1
|
||||
res
|
||||
end
|
||||
end
|
19
src/sqlite3/statement2.cr
Normal file
19
src/sqlite3/statement2.cr
Normal file
|
@ -0,0 +1,19 @@
|
|||
class SQLite3::Statement2 < DB::Statement
|
||||
def initialize(@driver, sql)
|
||||
check LibSQLite3.prepare_v2(@driver, sql, sql.bytesize + 1, out @stmt, nil)
|
||||
# @closed = false
|
||||
end
|
||||
|
||||
def exec(*args)
|
||||
LibSQLite3.reset(self)
|
||||
ResultSet2.new(self)
|
||||
end
|
||||
|
||||
private def check(code)
|
||||
raise Exception.new(@driver) unless code == 0
|
||||
end
|
||||
|
||||
def to_unsafe
|
||||
@stmt
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue