shard-crystal-db/spec/dummy_driver.cr
2016-06-22 14:10:09 -03:00

196 lines
3.7 KiB
Crystal

require "spec"
require "../src/db"
class DummyDriver < DB::Driver
def build_connection(db : DB::Database) : DB::Connection
DummyConnection.new(db)
end
class DummyConnection < DB::Connection
def initialize(db)
super(db)
@@connections ||= [] of DummyConnection
@@connections.not_nil! << self
end
def self.connections
@@connections.not_nil!
end
def self.clear_connections
@@connections.try &.clear
end
def build_statement(query)
DummyStatement.new(self, query)
end
def last_insert_id : Int64
0
end
protected def do_close
super
end
end
class DummyStatement < DB::Statement
property params
def initialize(connection, @query : String)
@params = Hash(Int32 | String, DB::Any).new
super(connection)
end
protected def perform_query(args : Enumerable)
set_params args
DummyResultSet.new self, @query
end
protected def perform_exec(args : Enumerable)
set_params args
DB::ExecResult.new 0i64, 0_i64
end
private def set_params(args)
@params.clear
args.each_with_index do |arg, index|
set_param(index, arg)
end
end
private def set_param(index, value : DB::Any)
@params[index] = value
end
private def set_param(index, value)
raise "not implemented for #{value.class}"
end
protected def do_close
super
end
end
class DummyResultSet < DB::ResultSet
@@next_column_type = String
@top_values : Array(Array(String))
@values : Array(String)?
@@last_result_set : self?
@@next_column_type : Nil.class | String.class | Int32.class | Int64.class | Float32.class | Float64.class | Bytes.class
def initialize(statement, query)
super(statement)
@top_values = query.split.map { |r| r.split(',') }.to_a
@@last_result_set = self
end
protected def do_close
super
end
def self.last_result_set
@@last_result_set.not_nil!
end
def move_next
@values = @top_values.shift?
!!@values
end
def column_count
2
end
def column_name(index)
"c#{index}"
end
def column_type(index : Int32)
@@next_column_type
end
def self.next_column_type=(value)
@@next_column_type = value
end
private def read? : DB::Any?
n = @values.not_nil!.shift?
raise "end of row" if n.is_a?(Nil)
return nil if n == "NULL"
if n == "?"
return (@statement.as(DummyStatement)).params[0]
end
return n
end
def read?(t : Nil.class)
read?.as(Nil)
end
def read?(t : String.class)
read?.try &.to_s
end
def read?(t : Int32.class)
read?(String).try &.to_i32
end
def read?(t : Int64.class)
read?(String).try &.to_i64
end
def read?(t : Float32.class)
read?(String).try &.to_f32
end
def read?(t : Float64.class)
read?(String).try &.to_f64
end
def read?(t : Bytes.class)
value = read?
if value.is_a?(Nil)
value
elsif value.is_a?(String)
ary = value.bytes
Slice.new(ary.to_unsafe, ary.size)
elsif value.is_a?(Bytes)
value
else
raise "#{value} is not convertible to Bytes"
end
end
end
end
DB.register_driver "dummy", DummyDriver
class Witness
getter count
def initialize(@count = 1)
end
def check
@count -= 1
end
end
def with_witness(count = 1)
w = Witness.new(count)
yield w
w.count.should eq(0), "The expected coverage was unmet"
end
def with_dummy
DummyDriver::DummyConnection.clear_connections
DB.open "dummy://host" do |db|
yield db
end
end