1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
require 'db2/db2cli'
module Sequel
module DB2
class Database < Sequel::Database
set_adapter_scheme :db2
include DB2CLI
# AUTO_INCREMENT = 'IDENTITY(1,1)'.freeze
#
# def auto_increment_sql
# AUTO_INCREMENT
# end
def check_error(rc, msg)
case rc
when SQL_SUCCESS, SQL_SUCCESS_WITH_INFO
nil
else
raise Error, msg
end
end
rc, @@env = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE)
check_error(rc, "Could not allocate DB2 environment")
def connect
rc, dbc = SQLAllocHandle(SQL_HANDLE_DBC, @@env)
check_error(rc, "Could not allocate database connection")
rc = SQLConnect(dbc, @opts[:database], @opts[:user], @opts[:password])
check_error(rc, "Could not connect to database")
dbc
end
def disconnect
@pool.disconnect do |conn|
rc = SQLDisconnect(conn)
check_error(rc, "Could not disconnect from database")
rc = SQLFreeHandle(SQL_HANDLE_DBC, conn)
check_error(rc, "Could not free Database handle")
end
end
def test_connection
@pool.hold {|conn|}
true
end
def dataset(opts = nil)
DB2::Dataset.new(self, opts)
end
def execute(sql, &block)
@logger.info(sql) if @logger
@pool.hold do |conn|
rc, sth = SQLAllocHandle(SQL_HANDLE_STMT, @handle)
check_error(rc, "Could not allocate statement")
begin
rc = SQLExecDirect(sth, sql)
check_error(rc, "Could not execute statement")
block[sth] if block
rc, rpc = SQLRowCount(sth)
check_error(rc, "Could not get RPC")
rpc
ensure
rc = SQLFreeHandle(SQL_HANDLE_STMT, sth)
check_error(rc, "Could not free statement")
end
end
end
alias_method :do, :execute
end
class Dataset < Sequel::Dataset
def literal(v)
case v
when Time
literal(v.iso8601)
else
super
end
end
def fetch_rows(sql, &block)
@db.synchronize do
@db.execute(sql) do |sth|
@column_info = get_column_info(sth)
@columns = @column_info.map {|c| c[:name]}
while (rc = SQLFetch(@handle)) != SQL_NO_DATA_FOUND
@db.check_error(rc, "Could not fetch row")
yield hash_row(sth)
end
end
end
self
end
MAX_COL_SIZE = 256
def get_column_info(sth)
rc, column_count = SQLNumResultCols(sth)
@db.check_error(rc, "Could not get number of result columns")
(1..column_count).map do |i|
rc, name, buflen, datatype, size, digits, nullable = SQLDescribeCol(sth, i, MAX_COL_SIZE)
@b.check_error(rc, "Could not describe column")
{:name => name, :db2_type => datatype, :precision => size}
end
end
def hash_row(sth)
row = {}
@column_info.each_with_index do |c, i|
rc, v = SQLGetData(sth, i+1, c[:db2_type], c[:precision])
@db.check_error(rc, "Could not get data")
@row[c[:name]] = convert_type(v)
end
row
end
def convert_type(v)
case v
when DB2CLI::Date
DBI::Date.new(v.year, v.month, v.day)
when DB2CLI::Time
DBI::Time.new(v.hour, v.minute, v.second)
when DB2CLI::Timestamp
DBI::Timestamp.new(v.year, v.month, v.day,
v.hour, v.minute, v.second, v.fraction)
when DB2CLI::Null
nil
else
v
end
end
def insert(*values)
@db.do insert_sql(*values)
end
def update(*args, &block)
@db.do update_sql(*args, &block)
end
def delete(opts = nil)
@db.do delete_sql(opts)
end
end
end
end
|