Refactor Database and Connection dsl methods. Update docs.

This commit is contained in:
Brian J. Cardiff 2016-12-04 15:14:43 -03:00
parent 543592a337
commit d55b088216
5 changed files with 88 additions and 112 deletions

View file

@ -134,12 +134,13 @@ end
require "./db/pool" require "./db/pool"
require "./db/string_key_cache" require "./db/string_key_cache"
require "./db/query_methods" require "./db/query_methods"
require "./db/session_methods"
require "./db/disposable" require "./db/disposable"
require "./db/database"
require "./db/driver" require "./db/driver"
require "./db/connection"
require "./db/statement" require "./db/statement"
require "./db/connection"
require "./db/pool_statement" require "./db/pool_statement"
require "./db/database"
require "./db/pool_prepared_statement" require "./db/pool_prepared_statement"
require "./db/pool_unprepared_statement" require "./db/pool_unprepared_statement"
require "./db/result_set" require "./db/result_set"

View file

@ -12,6 +12,7 @@ module DB
# The connection must be initialized in `#initialize` and closed in `#do_close`. # The connection must be initialized in `#initialize` and closed in `#do_close`.
# #
# Override `#build_prepared_statement` method in order to return a prepared `Statement` to allow querying. # Override `#build_prepared_statement` method in order to return a prepared `Statement` to allow querying.
# Override `#build_unprepared_statement` method in order to return a unprepared `Statement` to allow querying.
# See also `Statement` to define how the statements are executed. # See also `Statement` to define how the statements are executed.
# #
# If at any give moment the connection is lost a DB::ConnectionLost should be raised. This will # If at any give moment the connection is lost a DB::ConnectionLost should be raised. This will
@ -19,7 +20,7 @@ module DB
# #
abstract class Connection abstract class Connection
include Disposable include Disposable
include QueryMethods include SessionMethods(Connection, Statement)
# :nodoc: # :nodoc:
getter database getter database
@ -30,22 +31,15 @@ module DB
@prepared_statements = @database.prepared_statements? @prepared_statements = @database.prepared_statements?
end end
# :nodoc:
def build(query) : Statement
if prepared_statements?
fetch_or_build_prepared_statement(query)
else
build_unprepared_statement(query)
end
end
# :nodoc: # :nodoc:
def fetch_or_build_prepared_statement(query) def fetch_or_build_prepared_statement(query)
@statements_cache.fetch(query) { build_prepared_statement(query) } @statements_cache.fetch(query) { build_prepared_statement(query) }
end end
# :nodoc:
abstract def build_prepared_statement(query) : Statement abstract def build_prepared_statement(query) : Statement
# :nodoc:
abstract def build_unprepared_statement(query) : Statement abstract def build_unprepared_statement(query) : Statement
protected def do_close protected def do_close
@ -53,49 +47,5 @@ module DB
@statements_cache.clear @statements_cache.clear
@database.pool.delete self @database.pool.delete self
end end
# dsl helper to build prepared statements
# returns a value that includes `QueryMethods`
def prepared
PreparedQuery.new(self)
end
# Returns a prepared `Statement` that has not been executed yet.
def prepared(query)
prepared.build(query)
end
# dsl helper to build unprepared statements
# returns a value that includes `QueryMethods`
def unprepared
UnpreparedQuery.new(self)
end
# Returns an unprepared `Statement` that has not been executed yet.
def unprepared(query)
unprepared.build(query)
end
struct PreparedQuery
include QueryMethods
def initialize(@connection : Connection)
end
def build(query)
@connection.fetch_or_build_prepared_statement(query)
end
end
struct UnpreparedQuery
include QueryMethods
def initialize(@connection : Connection)
end
def build(query)
@connection.build_unprepared_statement(query)
end
end
end end
end end

View file

@ -13,11 +13,16 @@ module DB
# - retry_attempts (default 1) # - retry_attempts (default 1)
# - retry_delay (in seconds, default 1.0) # - retry_delay (in seconds, default 1.0)
# #
# When querying a database prepared statements are used by default.
# This can be changed from the `prepared_statements` URI parameter:
#
# - prepared_statements = `true`|`false` (default `true`)
#
# It should be created from DB module. See `DB#open`. # It should be created from DB module. See `DB#open`.
# #
# Refer to `QueryMethods` for documentation about querying the database. # Refer to `QueryMethods` and `SessionMethods` for documentation about querying the database.
class Database class Database
include QueryMethods include SessionMethods(Database, PoolStatement)
# :nodoc: # :nodoc:
getter driver getter driver
@ -63,15 +68,6 @@ module DB
@pool.close @pool.close
end end
# :nodoc:
def build(query) : PoolStatement
if prepared_statements?
fetch_or_build_prepared_statement(query)
else
build_unprepared_statement(query)
end
end
# :nodoc: # :nodoc:
def fetch_or_build_prepared_statement(query) def fetch_or_build_prepared_statement(query)
@statements_cache.fetch(query) { build_prepared_statement(query) } @statements_cache.fetch(query) { build_prepared_statement(query) }
@ -115,49 +111,5 @@ module DB
yield yield
end end
end end
# dsl helper to build prepared statements
# returns a value that includes `QueryMethods`
def prepared
PreparedQuery.new(self)
end
# Returns a prepared `Statement` that has not been executed yet.
def prepared(query)
prepared.build(query)
end
# dsl helper to build unprepared statements
# returns a value that includes `QueryMethods`
def unprepared
UnpreparedQuery.new(self)
end
# Returns an unprepared `Statement` that has not been executed yet.
def unprepared(query)
unprepared.build(query)
end
struct PreparedQuery
include QueryMethods
def initialize(@db : Database)
end
def build(query)
@db.fetch_or_build_prepared_statement(query)
end
end
struct UnpreparedQuery
include QueryMethods
def initialize(@db : Database)
end
def build(query)
@db.build_unprepared_statement(query)
end
end
end end
end end

73
src/db/session_methods.cr Normal file
View file

@ -0,0 +1,73 @@
module DB
# Methods that are shared accross session like objects:
# - Database
# - Connection
#
# Classes that includes this module are able to execute
# queries and statements in both prepared and unprepared fashion.
#
# This module serves for dsl reuse over session like objects.
module SessionMethods(Session, Stmt)
include QueryMethods
# Returns whether by default the statements should
# be prepared or not.
abstract def prepared_statements? : Bool
abstract def fetch_or_build_prepared_statement(query) : Stmt
abstract def build_unprepared_statement(query) : Stmt
def build(query) : Stmt
if prepared_statements?
fetch_or_build_prepared_statement(query)
else
build_unprepared_statement(query)
end
end
# dsl helper to build prepared statements
# returns a value that includes `QueryMethods`
def prepared
PreparedQuery(Session, Stmt).new(self)
end
# Returns a prepared `Statement` that has not been executed yet.
def prepared(query)
prepared.build(query)
end
# dsl helper to build unprepared statements
# returns a value that includes `QueryMethods`
def unprepared
UnpreparedQuery(Session, Stmt).new(self)
end
# Returns an unprepared `Statement` that has not been executed yet.
def unprepared(query)
unprepared.build(query)
end
struct PreparedQuery(Session, Stmt)
include QueryMethods
def initialize(@session : Session)
end
def build(query) : Stmt
@session.fetch_or_build_prepared_statement(query)
end
end
struct UnpreparedQuery(Session, Stmt)
include QueryMethods
def initialize(@session : Session)
end
def build(query) : Stmt
@session.build_unprepared_statement(query)
end
end
end
end

View file

@ -39,7 +39,7 @@ module DB
abstract def query(args : Array) : ResultSet abstract def query(args : Array) : ResultSet
end end
# Represents a prepared query in a `Connection`. # Represents a query in a `Connection`.
# It should be created by `QueryMethods`. # It should be created by `QueryMethods`.
# #
# ### Note to implementors # ### Note to implementors