Skip to content

Instantly share code, notes, and snippets.

@hassox
Created June 28, 2013 23:04
Show Gist options
  • Save hassox/fb5f76d079bca27a4308 to your computer and use it in GitHub Desktop.
Save hassox/fb5f76d079bca27a4308 to your computer and use it in GitHub Desktop.
Sequel Hibernate integration.
require 'sequel'
require 'sequel/adapters/jdbc'
require 'sequel/adapters/jdbc/mysql'
Sequel.ts_require 'adapters/jdbc/mysql'
# A dataset implementation that only uses the generic `Connection` interface,
# rather than the postgres specific `Jdbc4Connection` one.
module Sequel
class MinecartMysqlDataset < Sequel::JDBC::Dataset
# We don't have access to escape_string method on the underlying connection
# object because it is wrapped in a c3p0 proxy, so have to override this
# method to supply our own implementation.
def literal_string_append(sql, v)
sql << APOS << escape_string(v) << APOS
end
# Pretty much a copy/paste of the real method, except with our own
# `standard_conforming_strings` check patched in.
def escape_string(v)
org.mysql.core.Utils.appendEscapedLiteral(
nil, v, standard_conforming_strings?
).to_string
end
# This is technically incorrect, but fine in practice. Prior to 8.2, this
# value was always false. Now it is a server side setting that is
# communicated to the driver on connect. We don't have access to the
# underlying driver, but all of our servers have this set to `true`, and
# there is no reason why we would ever set it to `false`.
#
# A correct implementation should run `SHOW standard_conforming_strings`
# against the server and cache the result. YAGNI for now.
def standard_conforming_strings?
true
end
end
class MinecartMysqlAdapter < Sequel::JDBC::Database
include ::Sequel::JDBC::MySQL::DatabaseMethods
def initialize(opts)
opts[:pool_class] = Sequel::MinecartConnectionPool
super
Sequel::JDBC::DATABASE_SETUP[:mysql].call self
self.dataset_class = Sequel::MinecartMysqlDataset
end
end
end
# encoding: UTF-8
require 'sequel'
module Sequel
class MinecartConnectionPool
##
# Initialize using the passed Sequel::Database object and options hash.
#
# :call-seq:
# initialize(Database, Hash)
def initialize(db, opts={})
@db = db
@session_factory = opts.fetch(:session_factory)
@key = "minecart-connection-pool-#{object_id}-connection".freeze
end
##
# Yield a connection object to the current block. For sharded connection
# pools, the Symbol passed is the shard/server to use.
#
# :call-seq:
# hold(Symbol, &block)
def hold(name) # :yields: connection
if connection
yield connection
else
connect do
yield connection
end
end
end
##
# Disconnect the connection object. For sharded connection pools, the
# Symbol passed is the shard/server to use.
#
# :call-seq:
# disconnect(Symbol)
def disconnect(name)
end
##
# An array of shard/server symbols for all shards/servers that this
# connection pool recognizes.
#
# :call-seq:
# servers
def servers
[]
end
##
# An integer representing the total number of connections in the pool, or
# for the given shard/server if sharding is supported.
#
# :call-seq:
# size
def size
0 # TODO(matthewtodd): Can we answer anything meaningful here?
end
def connection
Thread.current[@key]
end
def connection=(connection)
Thread.current[@key] = connection
end
private
def connect(&block)
session = @session_factory.open_session
begin
session.doWork(CallInUnitOfWork.new(self, block))
ensure
session.close
end
end
class CallInUnitOfWork
include org.hibernate.jdbc.Work
def initialize(pool, block)
@pool = pool
@block = block
end
def execute(connection)
@pool.connection = connection
@block.call
ensure
@pool.connection = nil
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment