prepare/exec a statement

dummy driver that parses the query
initial type support for result_sets
This commit is contained in:
Brian J. Cardiff 2016-01-28 20:31:35 -03:00
parent cc1545a58e
commit 4dd0312934
7 changed files with 145 additions and 5 deletions

View File

@ -1,10 +1,6 @@
require "spec"
require "db"
class DummyDriver < DB::Driver
end
DB.register_driver "dummy", DummyDriver
require "./dummy_driver"
describe DB::Driver do
it "should get driver class by name" do

View File

@ -0,0 +1,43 @@
class DummyDriver < DB::Driver
def prepare(query)
DummyStatement.new(self, query.split.map { |r| r.split ',' })
end
class DummyStatement < DB::Statement
def initialize(driver, @items)
super(driver)
end
def exec(*args)
DummyResultSet.new self, @items.each
end
end
class DummyResultSet < DB::ResultSet
def initialize(statement, @iterator)
super(statement)
end
def has_next
@iterator.next.tap do |n|
return false if n.is_a?(Iterator::Stop)
@values = n.each
return true
end
end
def read_string
@values.not_nil!.next as String
end
def read_u_int64
read_string.to_u64
end
end
end
DB.register_driver "dummy", DummyDriver
def get_dummy
DB.driver "dummy", {} of String => String
end

View File

@ -0,0 +1,58 @@
require "spec"
require "db"
require "./dummy_driver"
describe DummyDriver do
it "should return statements" do
get_dummy.prepare("the query").should be_a(DB::Statement)
end
describe DummyDriver::DummyStatement do
it "exec should return a result_set" do
statement = get_dummy.prepare("a,b 1,2")
result_set = statement.exec
result_set.should be_a(DB::ResultSet)
result_set.statement.should be(statement)
end
it "should enumerate records by spaces" do
result_set = get_dummy.prepare("").exec
result_set.has_next.should be_false
result_set = get_dummy.prepare("a,b").exec
result_set.has_next.should be_true
result_set.has_next.should be_false
result_set = get_dummy.prepare("a,b 1,2").exec
result_set.has_next.should be_true
result_set.has_next.should be_true
result_set.has_next.should be_false
result_set = get_dummy.prepare("a,b 1,2 c,d").exec
result_set.has_next.should be_true
result_set.has_next.should be_true
result_set.has_next.should be_true
result_set.has_next.should be_false
end
it "should enumerate string fields" do
result_set = get_dummy.prepare("a,b 1,2").exec
result_set.has_next
result_set.read(String).should eq("a")
result_set.read(String).should eq("b")
result_set.has_next
result_set.read(String).should eq("1")
result_set.read(String).should eq("2")
end
it "should enumerate uint64 fields" do
result_set = get_dummy.prepare("3,4 1,2").exec
result_set.has_next
result_set.read(UInt64).should eq(3)
result_set.read(UInt64).should eq(4)
result_set.has_next
result_set.read(UInt64).should eq(1)
result_set.read(UInt64).should eq(2)
end
end
end

View File

@ -14,3 +14,5 @@ module DB
end
require "./driver"
require "./statement"
require "./result_set"

View File

@ -4,5 +4,7 @@ module DB
def initialize(@options)
end
abstract def prepare(query) : Statement
end
end

31
src/db/result_set.cr Normal file
View File

@ -0,0 +1,31 @@
module DB
abstract class ResultSet
getter statement
def initialize(@statement : Statement)
end
abstract def has_next : Bool
# def read(t : T.class) : T
# end
# list datatypes that must be supported form the driver
# implementors will override read_string
# users will call read(String) due to overloads read(T) will be a T
# TODO: unable to write unions (nillables)
{% for t in [String, UInt64] %}
def read(t : {{t}}.class) : {{t}}
read_{{t.name.underscore}}
end
protected abstract def read_{{t.name.underscore}} : {{t}}
{% end %}
# def read(t : String.class) : String
# read_string
# end
#
# protected abstract def read_string : String
end
end

8
src/db/statement.cr Normal file
View File

@ -0,0 +1,8 @@
module DB
abstract class Statement
def initialize(@driver)
end
abstract def exec(*args) : ResultSet
end
end