2016-01-28 23:31:35 +00:00
|
|
|
module DB
|
2016-08-29 19:56:34 +00:00
|
|
|
# Common interface for connection based statements
|
|
|
|
# and for connection pool statements.
|
|
|
|
module StatementMethods
|
|
|
|
include Disposable
|
|
|
|
|
|
|
|
protected def do_close
|
|
|
|
end
|
|
|
|
|
|
|
|
# See `QueryMethods#scalar`
|
|
|
|
def scalar(*args)
|
|
|
|
query(*args) do |rs|
|
|
|
|
rs.each do
|
|
|
|
return rs.read
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
raise "no results"
|
|
|
|
end
|
|
|
|
|
|
|
|
# See `QueryMethods#query`
|
|
|
|
def query(*args)
|
|
|
|
rs = query(*args)
|
|
|
|
yield rs ensure rs.close
|
|
|
|
end
|
|
|
|
|
|
|
|
# See `QueryMethods#exec`
|
|
|
|
abstract def exec : ExecResult
|
|
|
|
# See `QueryMethods#exec`
|
|
|
|
abstract def exec(*args) : ExecResult
|
|
|
|
# See `QueryMethods#exec`
|
|
|
|
abstract def exec(args : Array) : ExecResult
|
|
|
|
|
|
|
|
# See `QueryMethods#query`
|
|
|
|
abstract def query : ResultSet
|
|
|
|
# See `QueryMethods#query`
|
|
|
|
abstract def query(*args) : ResultSet
|
|
|
|
# See `QueryMethods#query`
|
|
|
|
abstract def query(args : Array) : ResultSet
|
|
|
|
end
|
|
|
|
|
2016-12-04 18:14:43 +00:00
|
|
|
# Represents a query in a `Connection`.
|
2016-01-31 22:40:02 +00:00
|
|
|
# It should be created by `QueryMethods`.
|
|
|
|
#
|
|
|
|
# ### Note to implementors
|
|
|
|
#
|
|
|
|
# 1. Subclass `Statements`
|
|
|
|
# 2. `Statements` are created from a custom driver `Connection#prepare` method.
|
2016-02-02 02:02:04 +00:00
|
|
|
# 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.
|
2016-01-28 23:31:35 +00:00
|
|
|
abstract class Statement
|
2016-08-29 19:56:34 +00:00
|
|
|
include StatementMethods
|
2016-02-03 20:10:03 +00:00
|
|
|
|
2016-02-03 21:46:37 +00:00
|
|
|
# :nodoc:
|
2016-01-30 22:46:43 +00:00
|
|
|
getter connection
|
2016-01-29 19:13:01 +00:00
|
|
|
|
2016-06-16 15:14:57 +00:00
|
|
|
def initialize(@connection : Connection)
|
2016-01-28 23:31:35 +00:00
|
|
|
end
|
|
|
|
|
2016-02-04 00:28:53 +00:00
|
|
|
def release_connection
|
2016-11-16 02:46:11 +00:00
|
|
|
@connection.release_from_statement
|
2016-02-04 00:28:53 +00:00
|
|
|
end
|
|
|
|
|
2016-02-02 02:02:04 +00:00
|
|
|
# See `QueryMethods#exec`
|
|
|
|
def exec
|
2016-12-07 02:27:15 +00:00
|
|
|
perform_exec_and_release(Slice(Any).empty)
|
2016-02-04 00:28:53 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# See `QueryMethods#exec`
|
2016-04-15 04:40:27 +00:00
|
|
|
def exec(args : Array)
|
|
|
|
perform_exec_and_release(args)
|
2016-02-02 02:02:04 +00:00
|
|
|
end
|
|
|
|
|
2016-01-31 22:40:02 +00:00
|
|
|
# See `QueryMethods#exec`
|
2016-01-30 22:46:43 +00:00
|
|
|
def exec(*args)
|
2016-02-02 02:02:04 +00:00
|
|
|
# TODO better way to do it
|
2016-04-15 04:40:27 +00:00
|
|
|
perform_exec_and_release(args)
|
2016-01-29 20:13:05 +00:00
|
|
|
end
|
|
|
|
|
2016-01-31 22:40:02 +00:00
|
|
|
# See `QueryMethods#query`
|
2016-04-14 20:33:39 +00:00
|
|
|
def query
|
2016-09-28 19:45:38 +00:00
|
|
|
perform_query_with_rescue Tuple.new
|
2016-01-30 22:46:43 +00:00
|
|
|
end
|
|
|
|
|
2016-04-14 20:33:39 +00:00
|
|
|
# See `QueryMethods#query`
|
|
|
|
def query(args : Array)
|
2016-09-28 19:45:38 +00:00
|
|
|
perform_query_with_rescue args
|
2016-01-29 22:21:48 +00:00
|
|
|
end
|
|
|
|
|
2016-04-14 20:33:39 +00:00
|
|
|
# See `QueryMethods#query`
|
|
|
|
def query(*args)
|
2016-09-28 19:45:38 +00:00
|
|
|
perform_query_with_rescue args
|
2016-04-14 20:33:39 +00:00
|
|
|
end
|
|
|
|
|
2016-04-15 04:40:27 +00:00
|
|
|
private def perform_exec_and_release(args : Enumerable) : ExecResult
|
2016-08-29 04:23:20 +00:00
|
|
|
return perform_exec(args)
|
|
|
|
ensure
|
2016-06-29 19:54:16 +00:00
|
|
|
release_connection
|
2016-02-04 00:28:53 +00:00
|
|
|
end
|
|
|
|
|
2016-09-28 19:45:38 +00:00
|
|
|
private def perform_query_with_rescue(args : Enumerable) : ResultSet
|
|
|
|
return perform_query(args)
|
|
|
|
rescue e : Exception
|
|
|
|
# Release connection only when an exception occurs during the query
|
|
|
|
# execution since we need the connection open while the ResultSet is open
|
|
|
|
release_connection
|
|
|
|
raise e
|
|
|
|
end
|
|
|
|
|
2016-04-14 20:33:39 +00:00
|
|
|
protected abstract def perform_query(args : Enumerable) : ResultSet
|
2016-04-15 04:40:27 +00:00
|
|
|
protected abstract def perform_exec(args : Enumerable) : ExecResult
|
2016-01-28 23:31:35 +00:00
|
|
|
end
|
|
|
|
end
|