add cache of pool statements per query

refactor/reuse connection statement cache
This commit is contained in:
Brian J. Cardiff 2016-08-30 16:20:18 -03:00
parent 09b3b4bc01
commit f568e4506d
5 changed files with 46 additions and 11 deletions

View file

@ -47,4 +47,20 @@ describe DB::Database do
db.prepare("query3").should be_a(DB::PoolStatement) db.prepare("query3").should be_a(DB::PoolStatement)
end end
end end
it "should return same statement in pool per query" do
with_dummy do |db|
stmt = db.prepare("query1")
db.prepare("query2").should_not eq(stmt)
db.prepare("query1").should eq(stmt)
end
end
it "should close pool statements when closing db" do
stmt = uninitialized DB::PoolStatement
with_dummy do |db|
stmt = db.prepare("query1")
end
stmt.closed?.should be_true
end
end end

View file

@ -119,6 +119,7 @@ module DB
end end
require "./db/pool" require "./db/pool"
require "./db/string_key_cache"
require "./db/query_methods" require "./db/query_methods"
require "./db/disposable" require "./db/disposable"
require "./db/database" require "./db/database"

View file

@ -20,25 +20,20 @@ module DB
# :nodoc: # :nodoc:
getter database getter database
@statements_cache = {} of String => Statement @statements_cache = StringKeyCache(Statement).new
def initialize(@database : Database) def initialize(@database : Database)
end end
# :nodoc: # :nodoc:
def prepare(query) : Statement def prepare(query) : Statement
stmt = @statements_cache.fetch(query, nil) @statements_cache.fetch(query) { build_statement(query) }
stmt = @statements_cache[query] = build_statement(query) unless stmt
stmt
end end
abstract def build_statement(query) : Statement abstract def build_statement(query) : Statement
protected def do_close protected def do_close
@statements_cache.each do |_, stmt| @statements_cache.each_value &.close
stmt.close
end
@statements_cache.clear @statements_cache.clear
end end
end end

View file

@ -24,6 +24,7 @@ module DB
@pool : Pool(Connection) @pool : Pool(Connection)
@setup_connection : Connection -> Nil @setup_connection : Connection -> Nil
@statements_cache = StringKeyCache(PoolStatement).new
# :nodoc: # :nodoc:
def initialize(@driver : Driver, @uri : URI) def initialize(@driver : Driver, @uri : URI)
@ -48,14 +49,15 @@ module DB
# Closes all connection to the database. # Closes all connection to the database.
def close def close
@statements_cache.each_value &.close
@statements_cache.clear
@pool.close @pool.close
end end
# :nodoc: # :nodoc:
def prepare(query) def prepare(query)
# TODO query based cache for pool statement @statements_cache.fetch(query) { PoolStatement.new(self, query) }
# TODO clear PoolStatements when closing the DB
PoolStatement.new self, query
end end
# :nodoc: # :nodoc:

View file

@ -0,0 +1,21 @@
module DB
class StringKeyCache(T)
@cache = {} of String => T
def fetch(key : String) : T
value = @cache.fetch(key, nil)
value = @cache[key] = yield unless value
value
end
def each_value
@cache.each do |_, value|
yield value
end
end
def clear
@cache.clear
end
end
end