From d55b088216ed47cee9c06d7153273dcad29ac677 Mon Sep 17 00:00:00 2001 From: "Brian J. Cardiff" Date: Sun, 4 Dec 2016 15:14:43 -0300 Subject: [PATCH] Refactor Database and Connection dsl methods. Update docs. --- src/db.cr | 5 +-- src/db/connection.cr | 58 +++---------------------------- src/db/database.cr | 62 ++++----------------------------- src/db/session_methods.cr | 73 +++++++++++++++++++++++++++++++++++++++ src/db/statement.cr | 2 +- 5 files changed, 88 insertions(+), 112 deletions(-) create mode 100644 src/db/session_methods.cr diff --git a/src/db.cr b/src/db.cr index 71d64c6..43a90f4 100644 --- a/src/db.cr +++ b/src/db.cr @@ -134,12 +134,13 @@ end require "./db/pool" require "./db/string_key_cache" require "./db/query_methods" +require "./db/session_methods" require "./db/disposable" -require "./db/database" require "./db/driver" -require "./db/connection" require "./db/statement" +require "./db/connection" require "./db/pool_statement" +require "./db/database" require "./db/pool_prepared_statement" require "./db/pool_unprepared_statement" require "./db/result_set" diff --git a/src/db/connection.cr b/src/db/connection.cr index 1b1aeb2..74ac257 100644 --- a/src/db/connection.cr +++ b/src/db/connection.cr @@ -12,6 +12,7 @@ module DB # 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_unprepared_statement` method in order to return a unprepared `Statement` to allow querying. # 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 @@ -19,7 +20,7 @@ module DB # abstract class Connection include Disposable - include QueryMethods + include SessionMethods(Connection, Statement) # :nodoc: getter database @@ -30,22 +31,15 @@ module DB @prepared_statements = @database.prepared_statements? end - # :nodoc: - def build(query) : Statement - if prepared_statements? - fetch_or_build_prepared_statement(query) - else - build_unprepared_statement(query) - end - end - # :nodoc: def fetch_or_build_prepared_statement(query) @statements_cache.fetch(query) { build_prepared_statement(query) } end + # :nodoc: abstract def build_prepared_statement(query) : Statement + # :nodoc: abstract def build_unprepared_statement(query) : Statement protected def do_close @@ -53,49 +47,5 @@ module DB @statements_cache.clear @database.pool.delete self 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 diff --git a/src/db/database.cr b/src/db/database.cr index 95d2ecd..f80e6b8 100644 --- a/src/db/database.cr +++ b/src/db/database.cr @@ -13,11 +13,16 @@ module DB # - retry_attempts (default 1) # - 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`. # - # Refer to `QueryMethods` for documentation about querying the database. + # Refer to `QueryMethods` and `SessionMethods` for documentation about querying the database. class Database - include QueryMethods + include SessionMethods(Database, PoolStatement) # :nodoc: getter driver @@ -63,15 +68,6 @@ module DB @pool.close end - # :nodoc: - def build(query) : PoolStatement - if prepared_statements? - fetch_or_build_prepared_statement(query) - else - build_unprepared_statement(query) - end - end - # :nodoc: def fetch_or_build_prepared_statement(query) @statements_cache.fetch(query) { build_prepared_statement(query) } @@ -115,49 +111,5 @@ module DB yield 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 diff --git a/src/db/session_methods.cr b/src/db/session_methods.cr new file mode 100644 index 0000000..1bc189c --- /dev/null +++ b/src/db/session_methods.cr @@ -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 diff --git a/src/db/statement.cr b/src/db/statement.cr index 3f8058b..01eba35 100644 --- a/src/db/statement.cr +++ b/src/db/statement.cr @@ -39,7 +39,7 @@ module DB abstract def query(args : Array) : ResultSet end - # Represents a prepared query in a `Connection`. + # Represents a query in a `Connection`. # It should be created by `QueryMethods`. # # ### Note to implementors