mirror of
https://gitea.invidious.io/iv-org/shard-crystal-db.git
synced 2024-08-15 00:53:32 +00:00
112 lines
3 KiB
Crystal
112 lines
3 KiB
Crystal
module DB
|
|
# Represents a prepared query in a `Connection`.
|
|
# It should be created by `QueryMethods`.
|
|
#
|
|
# ### Note to implementors
|
|
#
|
|
# 1. Subclass `Statements`
|
|
# 2. `Statements` are created from a custom driver `Connection#prepare` method.
|
|
# 3. `#perform_query` executes a query that is expected to return a `ResultSet`
|
|
# 4. `#perform_exec` executes a query that is expected to return an `ExecResult`
|
|
# 6. `#do_close` is called to release the statement resources.
|
|
abstract class Statement
|
|
include Disposable
|
|
|
|
# :nodoc:
|
|
getter connection
|
|
|
|
def initialize(@connection)
|
|
end
|
|
|
|
protected def do_close
|
|
end
|
|
|
|
def release_connection
|
|
@connection.database.return_to_pool(@connection)
|
|
end
|
|
|
|
# See `QueryMethods#exec`
|
|
def exec
|
|
perform_exec_and_release(Slice(Any).new(0)) # no overload matches ... with types Slice(NoReturn)
|
|
end
|
|
|
|
# See `QueryMethods#exec`
|
|
def exec(args : Enumerable(Any))
|
|
perform_exec_and_release(args.to_a.to_unsafe.to_slice(args.size))
|
|
end
|
|
|
|
# See `QueryMethods#exec`
|
|
def exec(*args)
|
|
# TODO better way to do it
|
|
perform_exec_and_release(args.to_a.to_unsafe.to_slice(args.size))
|
|
end
|
|
|
|
# See `QueryMethods#scalar`
|
|
def scalar(*args)
|
|
query(*args) do |rs|
|
|
rs.each do
|
|
# return case rs.read?(rs.column_type(0)) # :-( Some day...
|
|
t = rs.column_type(0)
|
|
if t == String
|
|
return rs.read?(String)
|
|
elsif t == Int32
|
|
return rs.read?(Int32)
|
|
elsif t == Int64
|
|
return rs.read?(Int64)
|
|
elsif t == Float32
|
|
return rs.read?(Float32)
|
|
elsif t == Float64
|
|
return rs.read?(Float64)
|
|
elsif t == Slice(UInt8)
|
|
return rs.read?(Slice(UInt8))
|
|
elsif t == Nil
|
|
return rs.read?(Int32)
|
|
else
|
|
raise "not implemented for #{t} type"
|
|
end
|
|
end
|
|
end
|
|
|
|
raise "no results"
|
|
end
|
|
|
|
# See `QueryMethods#query`
|
|
def query(*args)
|
|
perform_query *args
|
|
end
|
|
|
|
# See `QueryMethods#query`
|
|
def query(*args)
|
|
perform_query(*args).tap do |rs|
|
|
begin
|
|
yield rs
|
|
ensure
|
|
rs.close
|
|
end
|
|
end
|
|
end
|
|
|
|
private def perform_query : ResultSet
|
|
perform_query(Slice(Any).new(0)) # no overload matches ... with types Slice(NoReturn)
|
|
end
|
|
|
|
private def perform_query(args : Enumerable(Any)) : ResultSet
|
|
# TODO better way to do it
|
|
perform_query(args.to_a.to_unsafe.to_slice(args.size))
|
|
end
|
|
|
|
private def perform_query(*args) : ResultSet
|
|
# TODO better way to do it
|
|
perform_query(args.to_a.to_unsafe.to_slice(args.size))
|
|
end
|
|
|
|
private def perform_exec_and_release(args : Slice(Any)) : ExecResult
|
|
perform_exec(args).tap do
|
|
release_connection
|
|
end
|
|
end
|
|
|
|
protected abstract def perform_query(args : Slice(Any)) : ResultSet
|
|
protected abstract def perform_exec(args : Slice(Any)) : ExecResult
|
|
end
|
|
end
|