2016-07-07 18:50:09 +00:00
|
|
|
require "http/params"
|
|
|
|
|
2016-01-29 19:13:01 +00:00
|
|
|
module DB
|
|
|
|
# Acts as an entry point for database access.
|
2016-07-07 18:50:09 +00:00
|
|
|
# Connections are managed by a pool.
|
|
|
|
# The connection pool can be configured from URI parameters:
|
|
|
|
#
|
|
|
|
# - initial_pool_size (default 1)
|
|
|
|
# - max_pool_size (default 1)
|
|
|
|
# - max_idle_pool_size (default 1)
|
|
|
|
# - checkout_timeout (default 5.0)
|
2016-01-30 22:46:43 +00:00
|
|
|
#
|
2016-01-31 22:40:02 +00:00
|
|
|
# It should be created from DB module. See `DB#open`.
|
|
|
|
#
|
|
|
|
# Refer to `QueryMethods` for documentation about querying the database.
|
2016-01-29 19:13:01 +00:00
|
|
|
class Database
|
2016-01-31 22:40:02 +00:00
|
|
|
# :nodoc:
|
2016-02-03 22:30:51 +00:00
|
|
|
getter driver
|
2016-08-29 16:14:47 +00:00
|
|
|
# :nodoc:
|
|
|
|
getter pool
|
2016-01-31 22:40:02 +00:00
|
|
|
|
2016-02-03 22:30:51 +00:00
|
|
|
# Returns the uri with the connection settings to the database
|
2016-02-03 21:29:09 +00:00
|
|
|
getter uri
|
2016-01-29 19:13:01 +00:00
|
|
|
|
2016-07-07 18:50:09 +00:00
|
|
|
@pool : Pool(Connection)
|
2016-08-18 03:55:43 +00:00
|
|
|
@setup_connection : Connection -> Nil
|
2016-06-16 15:14:57 +00:00
|
|
|
|
2016-01-31 22:40:02 +00:00
|
|
|
# :nodoc:
|
2016-06-16 15:14:57 +00:00
|
|
|
def initialize(@driver : Driver, @uri : URI)
|
2016-07-07 18:50:09 +00:00
|
|
|
# TODO: PR HTTP::Params.new -> HTTP::Params.new(Hash(String, Array(String)).new)
|
|
|
|
params = (query = uri.query) ? HTTP::Params.parse(query) : HTTP::Params.new(Hash(String, Array(String)).new)
|
|
|
|
pool_options = @driver.connection_pool_options(params)
|
|
|
|
|
2016-08-18 03:55:43 +00:00
|
|
|
@setup_connection = ->(conn : Connection) {}
|
2016-07-07 18:50:09 +00:00
|
|
|
@pool = uninitialized Pool(Connection) # in order to use self in the factory proc
|
2016-08-18 03:55:43 +00:00
|
|
|
@pool = Pool.new(**pool_options) {
|
|
|
|
conn = @driver.build_connection(self).as(Connection)
|
|
|
|
@setup_connection.call conn
|
|
|
|
conn
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
def setup_connection(&proc : Connection -> Nil)
|
|
|
|
@setup_connection = proc
|
|
|
|
@pool.each_resource do |conn|
|
|
|
|
@setup_connection.call conn
|
|
|
|
end
|
2016-01-29 19:13:01 +00:00
|
|
|
end
|
|
|
|
|
2016-01-31 22:40:02 +00:00
|
|
|
# Closes all connection to the database.
|
2016-01-30 22:46:43 +00:00
|
|
|
def close
|
2016-07-07 18:50:09 +00:00
|
|
|
@pool.close
|
2016-01-30 22:46:43 +00:00
|
|
|
end
|
|
|
|
|
2016-02-02 00:55:30 +00:00
|
|
|
# :nodoc:
|
2016-02-03 22:30:51 +00:00
|
|
|
def prepare(query)
|
2016-06-29 18:01:26 +00:00
|
|
|
conn = get_from_pool
|
|
|
|
begin
|
|
|
|
conn.prepare(query)
|
|
|
|
rescue ex
|
|
|
|
return_to_pool(conn)
|
|
|
|
raise ex
|
|
|
|
end
|
2016-01-30 22:46:43 +00:00
|
|
|
end
|
|
|
|
|
2016-02-03 19:57:54 +00:00
|
|
|
# :nodoc:
|
2016-02-03 22:30:51 +00:00
|
|
|
def get_from_pool
|
2016-07-07 18:50:09 +00:00
|
|
|
@pool.checkout
|
2016-02-03 22:30:51 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# :nodoc:
|
|
|
|
def return_to_pool(connection)
|
2016-07-07 18:50:09 +00:00
|
|
|
@pool.release connection
|
2016-01-30 22:46:43 +00:00
|
|
|
end
|
|
|
|
|
2016-06-23 20:27:30 +00:00
|
|
|
# yields a connection from the pool
|
|
|
|
# the connection is returned to the pool after
|
|
|
|
# when the block ends
|
|
|
|
def using_connection
|
|
|
|
connection = get_from_pool
|
2016-07-11 15:56:40 +00:00
|
|
|
begin
|
|
|
|
yield connection
|
|
|
|
ensure
|
|
|
|
return_to_pool connection
|
|
|
|
end
|
2016-06-23 20:27:30 +00:00
|
|
|
end
|
|
|
|
|
2016-01-31 17:01:52 +00:00
|
|
|
include QueryMethods
|
2016-01-29 19:13:01 +00:00
|
|
|
end
|
|
|
|
end
|