sequel 3.27.0 → 3.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +96 -0
- data/README.rdoc +2 -2
- data/Rakefile +1 -1
- data/doc/association_basics.rdoc +48 -0
- data/doc/opening_databases.rdoc +29 -5
- data/doc/prepared_statements.rdoc +1 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/testing.rdoc +42 -0
- data/doc/transactions.rdoc +97 -0
- data/lib/sequel/adapters/db2.rb +95 -65
- data/lib/sequel/adapters/firebird.rb +25 -219
- data/lib/sequel/adapters/ibmdb.rb +440 -0
- data/lib/sequel/adapters/jdbc.rb +12 -0
- data/lib/sequel/adapters/jdbc/as400.rb +0 -7
- data/lib/sequel/adapters/jdbc/db2.rb +49 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +34 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +2 -27
- data/lib/sequel/adapters/jdbc/transactions.rb +34 -0
- data/lib/sequel/adapters/mysql.rb +10 -15
- data/lib/sequel/adapters/odbc.rb +1 -2
- data/lib/sequel/adapters/odbc/db2.rb +5 -5
- data/lib/sequel/adapters/postgres.rb +71 -11
- data/lib/sequel/adapters/shared/db2.rb +290 -0
- data/lib/sequel/adapters/shared/firebird.rb +214 -0
- data/lib/sequel/adapters/shared/mssql.rb +18 -75
- data/lib/sequel/adapters/shared/mysql.rb +13 -0
- data/lib/sequel/adapters/shared/postgres.rb +52 -36
- data/lib/sequel/adapters/shared/sqlite.rb +32 -36
- data/lib/sequel/adapters/sqlite.rb +4 -8
- data/lib/sequel/adapters/tinytds.rb +7 -3
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +55 -0
- data/lib/sequel/core.rb +1 -1
- data/lib/sequel/database/connecting.rb +1 -1
- data/lib/sequel/database/misc.rb +6 -5
- data/lib/sequel/database/query.rb +1 -1
- data/lib/sequel/database/schema_generator.rb +2 -1
- data/lib/sequel/dataset/actions.rb +149 -33
- data/lib/sequel/dataset/features.rb +44 -7
- data/lib/sequel/dataset/misc.rb +9 -1
- data/lib/sequel/dataset/prepared_statements.rb +2 -2
- data/lib/sequel/dataset/query.rb +63 -10
- data/lib/sequel/dataset/sql.rb +22 -5
- data/lib/sequel/model.rb +3 -3
- data/lib/sequel/model/associations.rb +250 -27
- data/lib/sequel/model/base.rb +10 -16
- data/lib/sequel/plugins/many_through_many.rb +34 -2
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +1 -1
- data/lib/sequel/sql.rb +94 -51
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/postgres_spec.rb +74 -6
- data/spec/adapters/spec_helper.rb +1 -0
- data/spec/adapters/sqlite_spec.rb +11 -0
- data/spec/core/database_spec.rb +7 -0
- data/spec/core/dataset_spec.rb +180 -17
- data/spec/core/expression_filters_spec.rb +107 -41
- data/spec/core/spec_helper.rb +11 -0
- data/spec/extensions/many_through_many_spec.rb +115 -1
- data/spec/extensions/prepared_statements_with_pk_spec.rb +3 -3
- data/spec/integration/associations_test.rb +193 -15
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +215 -19
- data/spec/integration/plugin_test.rb +8 -5
- data/spec/integration/prepared_statement_test.rb +91 -98
- data/spec/integration/schema_test.rb +27 -11
- data/spec/integration/spec_helper.rb +10 -0
- data/spec/integration/type_test.rb +2 -2
- data/spec/model/association_reflection_spec.rb +91 -0
- data/spec/model/associations_spec.rb +13 -0
- data/spec/model/base_spec.rb +8 -21
- data/spec/model/eager_loading_spec.rb +243 -9
- data/spec/model/model_spec.rb +15 -2
- metadata +16 -4
@@ -0,0 +1,440 @@
|
|
1
|
+
require 'ibm_db'
|
2
|
+
Sequel.require 'adapters/shared/db2'
|
3
|
+
|
4
|
+
module Sequel
|
5
|
+
|
6
|
+
module IBMDB
|
7
|
+
@convert_smallint_to_bool = true
|
8
|
+
|
9
|
+
class << self
|
10
|
+
# Whether to convert smallint values to bool, true by default.
|
11
|
+
# Can also be overridden per dataset.
|
12
|
+
attr_accessor :convert_smallint_to_bool
|
13
|
+
end
|
14
|
+
|
15
|
+
tt = Class.new do
|
16
|
+
def boolean(s) !s.to_i.zero? end
|
17
|
+
def int(s) s.to_i end
|
18
|
+
end.new
|
19
|
+
|
20
|
+
# Hash holding type translation methods, used by Dataset#fetch_rows.
|
21
|
+
DB2_TYPES = {
|
22
|
+
:boolean => tt.method(:boolean),
|
23
|
+
:int => tt.method(:int),
|
24
|
+
:blob => ::Sequel::SQL::Blob.method(:new),
|
25
|
+
:time => ::Sequel.method(:string_to_time),
|
26
|
+
:date => ::Sequel.method(:string_to_date),
|
27
|
+
:timestamp => ::Sequel.method(:database_to_application_timestamp)
|
28
|
+
}
|
29
|
+
DB2_TYPES[:clob] = DB2_TYPES[:blob]
|
30
|
+
|
31
|
+
# Wraps an underlying connection to DB2 using IBM_DB.
|
32
|
+
class Connection
|
33
|
+
# A hash with prepared statement name symbol keys, where each value is
|
34
|
+
# a two element array with an sql string and cached Statement value.
|
35
|
+
attr_accessor :prepared_statements
|
36
|
+
|
37
|
+
# Error class for exceptions raised by the connection.
|
38
|
+
class Error < StandardError
|
39
|
+
end
|
40
|
+
|
41
|
+
# Create the underlying IBM_DB connection.
|
42
|
+
def initialize(connection_string)
|
43
|
+
@conn = IBM_DB.connect(connection_string, '', '')
|
44
|
+
self.autocommit = true
|
45
|
+
@prepared_statements = {}
|
46
|
+
end
|
47
|
+
|
48
|
+
# Check whether the connection is in autocommit state or not.
|
49
|
+
def autocommit
|
50
|
+
IBM_DB.autocommit(@conn) == 1
|
51
|
+
end
|
52
|
+
|
53
|
+
# Turn autocommit on or off for the connection.
|
54
|
+
def autocommit=(value)
|
55
|
+
IBM_DB.autocommit(@conn, value ? IBM_DB::SQL_AUTOCOMMIT_ON : IBM_DB::SQL_AUTOCOMMIT_OFF)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Close the connection, disconnecting from DB2.
|
59
|
+
def close
|
60
|
+
IBM_DB.close(@conn)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Commit the currently outstanding transaction on this connection.
|
64
|
+
def commit
|
65
|
+
IBM_DB.commit(@conn)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Return the related error message for the connection.
|
69
|
+
def error_msg
|
70
|
+
IBM_DB.getErrormsg(@conn, IBM_DB::DB_CONN)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Execute the given SQL on the database, and return a Statement instance
|
74
|
+
# holding the results.
|
75
|
+
def execute(sql)
|
76
|
+
stmt = IBM_DB.exec(@conn, sql)
|
77
|
+
raise Error, error_msg unless stmt
|
78
|
+
Statement.new(stmt)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Execute the related prepared statement on the database with the given
|
82
|
+
# arguments.
|
83
|
+
def execute_prepared(ps_name, *values)
|
84
|
+
stmt = @prepared_statements[ps_name].last
|
85
|
+
res = stmt.execute(*values)
|
86
|
+
unless res
|
87
|
+
raise Error, "Error executing statement #{ps_name}: #{error_msg}"
|
88
|
+
end
|
89
|
+
stmt
|
90
|
+
end
|
91
|
+
|
92
|
+
# Prepare a statement with the given +sql+ on the database, and
|
93
|
+
# cache the prepared statement value by name.
|
94
|
+
def prepare(sql, ps_name)
|
95
|
+
if stmt = IBM_DB.prepare(@conn, sql)
|
96
|
+
ps_name = ps_name.to_sym
|
97
|
+
stmt = Statement.new(stmt)
|
98
|
+
@prepared_statements[ps_name] = [sql, stmt]
|
99
|
+
else
|
100
|
+
err = error_msg
|
101
|
+
err = "Error preparing #{ps_name} with SQL: #{sql}" if error_msg.nil? || error_msg.empty?
|
102
|
+
raise Error, err
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Rollback the currently outstanding transaction on this connection.
|
107
|
+
def rollback
|
108
|
+
IBM_DB.rollback(@conn)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Wraps results returned by queries on IBM_DB.
|
113
|
+
class Statement
|
114
|
+
# Hold the given statement.
|
115
|
+
def initialize(stmt)
|
116
|
+
@stmt = stmt
|
117
|
+
end
|
118
|
+
|
119
|
+
# Return the number of rows affected.
|
120
|
+
def affected
|
121
|
+
IBM_DB.num_rows(@stmt)
|
122
|
+
end
|
123
|
+
|
124
|
+
# If this statement is a prepared statement, execute it on the database
|
125
|
+
# with the given values.
|
126
|
+
def execute(*values)
|
127
|
+
IBM_DB.execute(@stmt, values)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Return the results of a query as an array of values.
|
131
|
+
def fetch_array
|
132
|
+
IBM_DB.fetch_array(@stmt) if @stmt
|
133
|
+
end
|
134
|
+
|
135
|
+
# Return the field name at the given column in the result set.
|
136
|
+
def field_name(ind)
|
137
|
+
IBM_DB.field_name(@stmt, ind)
|
138
|
+
end
|
139
|
+
|
140
|
+
# Return the field type for the given field name in the result set.
|
141
|
+
def field_type(key)
|
142
|
+
IBM_DB.field_type(@stmt, key)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Return the field precision for the given field name in the result set.
|
146
|
+
def field_precision(key)
|
147
|
+
IBM_DB.field_precision(@stmt, key)
|
148
|
+
end
|
149
|
+
|
150
|
+
# Free the memory related to this result set.
|
151
|
+
def free
|
152
|
+
IBM_DB.free_result(@stmt)
|
153
|
+
end
|
154
|
+
|
155
|
+
# Return the number of fields in the result set.
|
156
|
+
def num_fields
|
157
|
+
IBM_DB.num_fields(@stmt)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
class Database < Sequel::Database
|
162
|
+
include Sequel::DB2::DatabaseMethods
|
163
|
+
|
164
|
+
set_adapter_scheme :ibmdb
|
165
|
+
|
166
|
+
# REORG the related table whenever it is altered. This is not always
|
167
|
+
# required, but it is necessary for compatibilty with other Sequel
|
168
|
+
# code in many cases.
|
169
|
+
def alter_table(name, generator=nil, &block)
|
170
|
+
res = super
|
171
|
+
reorg(name)
|
172
|
+
res
|
173
|
+
end
|
174
|
+
|
175
|
+
# Create a new connection object for the given server.
|
176
|
+
def connect(server)
|
177
|
+
opts = server_opts(server)
|
178
|
+
|
179
|
+
# use uncataloged connection so that host and port can be supported
|
180
|
+
connection_string = ( \
|
181
|
+
'Driver={IBM DB2 ODBC DRIVER};' \
|
182
|
+
"Database=#{opts[:database]};" \
|
183
|
+
"Hostname=#{opts[:host]};" \
|
184
|
+
"Port=#{opts[:port] || 50000};" \
|
185
|
+
'Protocol=TCPIP;' \
|
186
|
+
"Uid=#{opts[:user]};" \
|
187
|
+
"Pwd=#{opts[:password]};" \
|
188
|
+
)
|
189
|
+
|
190
|
+
Connection.new(connection_string)
|
191
|
+
end
|
192
|
+
|
193
|
+
# Return a related IBMDB::Dataset instance with the given options.
|
194
|
+
def dataset(opts = nil)
|
195
|
+
IBMDB::Dataset.new(self, opts)
|
196
|
+
end
|
197
|
+
|
198
|
+
# Execute the given SQL on the database.
|
199
|
+
def execute(sql, opts={}, &block)
|
200
|
+
if sql.is_a?(Symbol)
|
201
|
+
execute_prepared_statement(sql, opts, &block)
|
202
|
+
else
|
203
|
+
synchronize(opts[:server]){|c| _execute(c, sql, opts, &block)}
|
204
|
+
end
|
205
|
+
rescue Connection::Error => e
|
206
|
+
raise_error(e)
|
207
|
+
end
|
208
|
+
|
209
|
+
# Execute the given SQL on the database, returning the last inserted
|
210
|
+
# identity value.
|
211
|
+
def execute_insert(sql, opts={})
|
212
|
+
synchronize(opts[:server]) do |c|
|
213
|
+
if sql.is_a?(Symbol)
|
214
|
+
execute_prepared_statement(sql, opts)
|
215
|
+
else
|
216
|
+
_execute(c, sql, opts)
|
217
|
+
end
|
218
|
+
_execute(c, "SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1", opts){|stmt| i = stmt.fetch_array.first.to_i; stmt.free; i}
|
219
|
+
end
|
220
|
+
rescue Connection::Error => e
|
221
|
+
raise_error(e)
|
222
|
+
end
|
223
|
+
|
224
|
+
# Execute a prepared statement named by name on the database.
|
225
|
+
def execute_prepared_statement(ps_name, opts)
|
226
|
+
args = opts[:arguments]
|
227
|
+
ps = prepared_statements[ps_name]
|
228
|
+
sql = ps.prepared_sql
|
229
|
+
synchronize(opts[:server]) do |conn|
|
230
|
+
unless conn.prepared_statements.fetch(ps_name, []).first == sql
|
231
|
+
log_yield("Preparing #{ps_name}: #{sql}"){conn.prepare(sql, ps_name)}
|
232
|
+
end
|
233
|
+
args = args.map{|v| v.nil? ? nil : prepared_statement_arg(v)}
|
234
|
+
stmt = log_yield("Executing #{ps_name}: #{args.inspect}"){conn.execute_prepared(ps_name, *args)}
|
235
|
+
|
236
|
+
if block_given?
|
237
|
+
begin
|
238
|
+
yield(stmt)
|
239
|
+
ensure
|
240
|
+
stmt.free
|
241
|
+
end
|
242
|
+
else
|
243
|
+
stmt.affected
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
# Convert smallint type to boolean if convert_smallint_to_bool is true
|
249
|
+
def schema_column_type(db_type)
|
250
|
+
if Sequel::IBMDB.convert_smallint_to_bool && db_type =~ /smallint/i
|
251
|
+
:boolean
|
252
|
+
else
|
253
|
+
db_type =~ /[bc]lob/i ? :blob : super
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
# On DB2, a table might need to be REORGed if you are testing existence
|
258
|
+
# of it. This REORGs automatically if the database raises a specific
|
259
|
+
# error that indicates it should be REORGed.
|
260
|
+
def table_exists?(name)
|
261
|
+
v ||= false # only retry once
|
262
|
+
sch, table_name = schema_and_table(name)
|
263
|
+
name = SQL::QualifiedIdentifier.new(sch, table_name) if sch
|
264
|
+
from(name).first
|
265
|
+
true
|
266
|
+
rescue DatabaseError => e
|
267
|
+
if e.to_s =~ /Operation not allowed for reason code "7" on table/ && v == false
|
268
|
+
# table probably needs reorg
|
269
|
+
reorg(name)
|
270
|
+
v = true
|
271
|
+
retry
|
272
|
+
end
|
273
|
+
false
|
274
|
+
end
|
275
|
+
|
276
|
+
private
|
277
|
+
|
278
|
+
# Execute the given SQL on the database.
|
279
|
+
def _execute(conn, sql, opts)
|
280
|
+
stmt = log_yield(sql){conn.execute(sql)}
|
281
|
+
if block_given?
|
282
|
+
begin
|
283
|
+
yield(stmt)
|
284
|
+
ensure
|
285
|
+
stmt.free
|
286
|
+
end
|
287
|
+
else
|
288
|
+
stmt.affected
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
# IBM_DB uses an autocommit setting instead of sending SQL queries.
|
293
|
+
# So starting a transaction just turns autocommit off.
|
294
|
+
def begin_transaction(conn, opts={})
|
295
|
+
log_yield(TRANSACTION_BEGIN){conn.autocommit = false}
|
296
|
+
conn
|
297
|
+
end
|
298
|
+
|
299
|
+
# This commits transaction in progress on the
|
300
|
+
# connection and sets autocommit back on.
|
301
|
+
def commit_transaction(conn, opts={})
|
302
|
+
log_yield(TRANSACTION_COMMIT){conn.commit} if conn
|
303
|
+
ensure
|
304
|
+
conn.autocommit = true if conn
|
305
|
+
end
|
306
|
+
|
307
|
+
# Close the given connection.
|
308
|
+
def disconnect_connection(conn)
|
309
|
+
conn.close
|
310
|
+
end
|
311
|
+
|
312
|
+
# Don't convert smallint to boolean for the metadata
|
313
|
+
# dataset, since the DB2 metadata does not use
|
314
|
+
# boolean columns, and some smallint columns are
|
315
|
+
# accidently treated as booleans.
|
316
|
+
def metadata_dataset
|
317
|
+
ds = super
|
318
|
+
ds.convert_smallint_to_bool = false
|
319
|
+
ds
|
320
|
+
end
|
321
|
+
|
322
|
+
# Format Numeric, Date, and Time types specially for use
|
323
|
+
# as IBM_DB prepared statements argument vlaues.
|
324
|
+
def prepared_statement_arg(v)
|
325
|
+
case v
|
326
|
+
when Numeric
|
327
|
+
v.to_s
|
328
|
+
when Date, Time
|
329
|
+
literal(v).gsub("'", '')
|
330
|
+
else
|
331
|
+
v
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
# This rolls back the transaction in progress on the
|
336
|
+
# connection and sets autocommit back on.
|
337
|
+
def rollback_transaction(conn, opts={})
|
338
|
+
log_yield(TRANSACTION_ROLLBACK){conn.rollback} if conn
|
339
|
+
ensure
|
340
|
+
conn.autocommit = true if conn
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
class Dataset < Sequel::Dataset
|
345
|
+
include Sequel::DB2::DatasetMethods
|
346
|
+
|
347
|
+
module CallableStatementMethods
|
348
|
+
# Extend given dataset with this module so subselects inside subselects in
|
349
|
+
# prepared statements work.
|
350
|
+
def subselect_sql(ds)
|
351
|
+
ps = ds.to_prepared_statement(:select)
|
352
|
+
ps.extend(CallableStatementMethods)
|
353
|
+
ps = ps.bind(@opts[:bind_vars]) if @opts[:bind_vars]
|
354
|
+
ps.prepared_args = prepared_args
|
355
|
+
ps.prepared_sql
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
# Methods for DB2 prepared statements using the native driver.
|
360
|
+
module PreparedStatementMethods
|
361
|
+
include Sequel::Dataset::UnnumberedArgumentMapper
|
362
|
+
|
363
|
+
private
|
364
|
+
# Execute the prepared statement with arguments instead of the given SQL.
|
365
|
+
def execute(sql, opts={}, &block)
|
366
|
+
super(prepared_statement_name, {:arguments=>bind_arguments}.merge(opts), &block)
|
367
|
+
end
|
368
|
+
|
369
|
+
# Execute the prepared statment with arguments instead of the given SQL.
|
370
|
+
def execute_dui(sql, opts={}, &block)
|
371
|
+
super(prepared_statement_name, {:arguments=>bind_arguments}.merge(opts), &block)
|
372
|
+
end
|
373
|
+
|
374
|
+
# Execute the prepared statement with arguments instead of the given SQL.
|
375
|
+
def execute_insert(sql, opts={}, &block)
|
376
|
+
super(prepared_statement_name, {:arguments=>bind_arguments}.merge(opts), &block)
|
377
|
+
end
|
378
|
+
|
379
|
+
end
|
380
|
+
|
381
|
+
# Emulate support of bind arguments in called statements.
|
382
|
+
def call(type, bind_arguments={}, *values, &block)
|
383
|
+
ps = to_prepared_statement(type, values)
|
384
|
+
ps.extend(CallableStatementMethods)
|
385
|
+
ps.call(bind_arguments, &block)
|
386
|
+
end
|
387
|
+
|
388
|
+
# Whether to convert smallint to boolean arguments for this dataset.
|
389
|
+
# Defaults to the IBMDB module setting.
|
390
|
+
def convert_smallint_to_bool
|
391
|
+
defined?(@convert_smallint_to_bool) ? @convert_smallint_to_bool : (@convert_smallint_to_bool = IBMDB.convert_smallint_to_bool)
|
392
|
+
end
|
393
|
+
|
394
|
+
# Override the default IBMDB.convert_smallint_to_bool setting for this dataset.
|
395
|
+
attr_writer :convert_smallint_to_bool
|
396
|
+
|
397
|
+
# Fetch the rows from the database and yield plain hashes.
|
398
|
+
def fetch_rows(sql)
|
399
|
+
execute(sql) do |stmt|
|
400
|
+
offset = @opts[:offset]
|
401
|
+
columns = []
|
402
|
+
convert = convert_smallint_to_bool
|
403
|
+
stmt.num_fields.times do |i|
|
404
|
+
k = stmt.field_name i
|
405
|
+
key = output_identifier(k)
|
406
|
+
type = stmt.field_type(k).downcase.to_sym
|
407
|
+
# decide if it is a smallint from precision
|
408
|
+
type = :boolean if type ==:int && convert && stmt.field_precision(k) < 8
|
409
|
+
columns << [key, DB2_TYPES[type]]
|
410
|
+
end
|
411
|
+
cols = columns.map{|c| c.at(0)}
|
412
|
+
cols.delete(row_number_column) if offset
|
413
|
+
@columns = cols
|
414
|
+
|
415
|
+
while res = stmt.fetch_array
|
416
|
+
row = {}
|
417
|
+
res.zip(columns).each do |v, (k, pr)|
|
418
|
+
row[k] = ((pr ? pr.call(v) : v) if v)
|
419
|
+
end
|
420
|
+
row.delete(row_number_column) if offset
|
421
|
+
yield row
|
422
|
+
end
|
423
|
+
end
|
424
|
+
self
|
425
|
+
end
|
426
|
+
|
427
|
+
# Store the given type of prepared statement in the associated database
|
428
|
+
# with the given name.
|
429
|
+
def prepare(type, name=nil, *values)
|
430
|
+
ps = to_prepared_statement(type, values)
|
431
|
+
ps.extend(PreparedStatementMethods)
|
432
|
+
if name
|
433
|
+
ps.prepared_statement_name = name
|
434
|
+
db.prepared_statements[name] = ps
|
435
|
+
end
|
436
|
+
ps
|
437
|
+
end
|
438
|
+
end
|
439
|
+
end
|
440
|
+
end
|
data/lib/sequel/adapters/jdbc.rb
CHANGED
@@ -80,6 +80,16 @@ module Sequel
|
|
80
80
|
Sequel.ts_require 'adapters/jdbc/informix'
|
81
81
|
db.extend(Sequel::JDBC::Informix::DatabaseMethods)
|
82
82
|
com.informix.jdbc.IfxDriver
|
83
|
+
end,
|
84
|
+
:db2=>proc do |db|
|
85
|
+
Sequel.ts_require 'adapters/jdbc/db2'
|
86
|
+
db.extend(Sequel::JDBC::DB2::DatabaseMethods)
|
87
|
+
com.ibm.db2.jcc.DB2Driver
|
88
|
+
end,
|
89
|
+
:firebirdsql=>proc do |db|
|
90
|
+
Sequel.ts_require 'adapters/jdbc/firebird'
|
91
|
+
db.extend(Sequel::JDBC::Firebird::DatabaseMethods)
|
92
|
+
org.firebirdsql.jdbc.FBDriver
|
83
93
|
end
|
84
94
|
}
|
85
95
|
|
@@ -595,6 +605,8 @@ module Sequel
|
|
595
605
|
Sequel::SQL::Blob.new(String.from_java_bytes(v))
|
596
606
|
when Java::JavaSQL::Blob
|
597
607
|
convert_type(v.getBytes(1, v.length))
|
608
|
+
when Java::JavaSQL::Clob
|
609
|
+
Sequel::SQL::Blob.new(v.getSubString(1, v.length))
|
598
610
|
else
|
599
611
|
v
|
600
612
|
end
|