Skip to content

Instantly share code, notes, and snippets.

@taku0
Created September 17, 2011 03:43
Show Gist options
  • Save taku0/1223605 to your computer and use it in GitHub Desktop.
Save taku0/1223605 to your computer and use it in GitHub Desktop.
オレオレJDBCラッパのプロトタイプ Ruby版
# -*- coding: utf-8 -*-
class RowParser
end
class BlockParser < RowParser
def initialize(*parsers, &block)
@block = block
@parsers = parsers
end
def arity
@parsers.map(&:arity).inject(0) do |left, right| left + right end
end
def parse(resultSet, index)
elements = @parsers.map do |parser|
element = parser.parse(resultSet, index)
index += parser.arity
element
end
@block.call(*elements)
end
end
class ParameterSetter
def to_setter
self
end
end
class TupleSetter < ParameterSetter
def initialize(*setters)
@setters = setters
end
def arity
@setters.map(&:arity).inject(0) do |left, right| left + right end
end
def set_to(index, statement)
@setters.each do |setter|
setter.set_to(index, statement)
index += setter.arity
end
end
def set_null(index, statement)
@setters.each do |setter|
setter.set_null(index, statement)
index += setter.arity
end
end
end
class RichConnection
def initialize(connection)
@connection = connection
end
def query_array(sql, parser, *setters)
if not parser.kind_of?(RowParser)
parser = parser::ROW_PARSER
end
statement = @connection.prepareStatement(sql)
begin
set_parameters(statement, setters)
result_set = statement.executeQuery()
array = []
while result_set.next()
array.push(parser.parse(result_set, 1))
end
array
ensure
statement.close()
end
end
def execute_update(sql, *setters)
statement = @connection.prepareStatement(sql)
begin
set_parameters(statement, setters)
statement.executeUpdate()
rescue
statement.close()
end
end
protected
def set_parameters(statement, setters)
index = 1
setters.each do |setter|
setter = setter.to_setter
setter.set_to(index, statement)
index += setter.arity
end
end
end
class Int
ROW_PARSER = RowParser.new
class << ROW_PARSER
def arity
1
end
def parse(resultSet, index)
resultSet.getInt(index)
end
end
class Setter < ParameterSetter
def initialize(value)
@value = value
end
def arity
1
end
def set_to(index, statement)
if @value.nil?
set_null(index, statement)
else
statement.setInt(index, @value)
end
end
def set_null(index, statement)
statement.setNull(index, Types::INTEGER)
end
end
def self.to_setter(value)
Setter.new(value)
end
end
class Module
def case_class(*parameters)
parameter_names = parameters.map do |parameter|
("@" + parameter[0].to_s).to_sym
end
define_method(:initialize) do |*args|
args.zip(parameter_names).each do |arg, parameter_name|
instance_variable_set(parameter_name, arg)
end
end
define_method(:to_a) do
parameter_names.map do |parameter_name|
instance_variable_get(parameter_name)
end
end
parameter_types = parameters.map do |parameter|
parameter[1]
end
const_set(:ROW_PARSER, BlockParser.new(*(parameter_types.map do |type| type::ROW_PARSER end), &method(:new)))
define_singleton_method(:to_setter) do |value|
tuple = value.to_a
setters = parameter_types.map.with_index do |type, index|
type.to_setter(tuple[index])
end
TupleSetter.new(*setters)
end
mod = self
define_method(:to_setter) do
mod.to_setter(self)
end
class_name = name
define_method(:to_s) do
"#{class_name}(#{to_a.join(', ')})"
end
end
end
class Foo
case_class([:a, Int],
[:b, Int])
end
class Bar
case_class([:a, Foo],
[:b, Int])
end
class Buz
case_class([:a, Int],
[:b, Bar])
end
# java.sql以下のクラスのデモ用実装
class NullConnection
def prepareStatement(sql)
puts("prepareStatement(#{sql.inspect})")
NullPreparedStatement.new
end
end
class NullPreparedStatement
def executeQuery
puts("executeQuery()")
NullResultSet.new
end
def executeUpdate
puts("executeUpdate()")
1
end
def setInt(index, value)
puts("setInt(#{index}, #{value})")
end
def setNull(index, type)
puts("setNull(#{index}, #{type})")
end
def close
puts("close()")
end
end
class NullResultSet
def next
puts("next()")
@x ||= 0
@x += 1
@x < 3
end
def getInt(index)
puts("getInt(#{index})")
@v ||= 0
@v += 1
@v
end
end
class Types
INTEGER = :INTEGER
end
puts("Buz::ROW_PARSER.arity = #{Buz::ROW_PARSER.arity}")
puts("Buz.to_setter(nil).arity = #{Buz.to_setter(nil).arity}")
puts
connection = NullConnection.new
buz_array = RichConnection.new(connection).query_array("SELECT a, b, c, d FROM t WHERE x = ? AND y = ?", Buz, Int.to_setter(1), Int.to_setter(2))
puts
puts(buz_array)
puts
RichConnection.new(connection).execute_update("INSERT INTO s (a, b, c, d) VALUES (?, ?, ?, ?)", buz_array[1])
puts
RichConnection.new(connection).execute_update("INSERT INTO s (a, b, c, d) VALUES (?, ?, ?, ?)", Buz.to_setter(nil))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment