activerecord-jdbc-adapter 70.0-java → 70.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -1
  3. data/activerecord-jdbc-adapter.gemspec +1 -1
  4. data/lib/arel/visitors/compat.rb +5 -33
  5. data/lib/arel/visitors/h2.rb +1 -13
  6. data/lib/arel/visitors/hsqldb.rb +1 -21
  7. data/lib/arel/visitors/sql_server.rb +2 -103
  8. data/lib/arjdbc/abstract/database_statements.rb +8 -0
  9. data/lib/arjdbc/discover.rb +0 -67
  10. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  11. data/lib/arjdbc/jdbc/column.rb +1 -26
  12. data/lib/arjdbc/jdbc.rb +0 -7
  13. data/lib/arjdbc/oracle/adapter.rb +3 -22
  14. data/lib/arjdbc/postgresql/adapter.rb +152 -3
  15. data/lib/arjdbc/postgresql/oid_types.rb +155 -108
  16. data/lib/arjdbc/sqlite3/adapter.rb +27 -18
  17. data/lib/arjdbc/tasks/database_tasks.rb +0 -15
  18. data/lib/arjdbc/util/serialized_attributes.rb +0 -22
  19. data/lib/arjdbc/version.rb +1 -1
  20. data/rakelib/02-test.rake +3 -18
  21. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +5 -0
  22. metadata +2 -35
  23. data/lib/active_record/connection_adapters/as400_adapter.rb +0 -2
  24. data/lib/active_record/connection_adapters/db2_adapter.rb +0 -1
  25. data/lib/active_record/connection_adapters/derby_adapter.rb +0 -1
  26. data/lib/active_record/connection_adapters/informix_adapter.rb +0 -1
  27. data/lib/arel/visitors/db2.rb +0 -137
  28. data/lib/arel/visitors/derby.rb +0 -112
  29. data/lib/arel/visitors/firebird.rb +0 -79
  30. data/lib/arjdbc/db2/adapter.rb +0 -808
  31. data/lib/arjdbc/db2/as400.rb +0 -142
  32. data/lib/arjdbc/db2/column.rb +0 -131
  33. data/lib/arjdbc/db2/connection_methods.rb +0 -48
  34. data/lib/arjdbc/db2.rb +0 -4
  35. data/lib/arjdbc/derby/active_record_patch.rb +0 -13
  36. data/lib/arjdbc/derby/adapter.rb +0 -521
  37. data/lib/arjdbc/derby/connection_methods.rb +0 -20
  38. data/lib/arjdbc/derby/schema_creation.rb +0 -15
  39. data/lib/arjdbc/derby.rb +0 -3
  40. data/lib/arjdbc/firebird/adapter.rb +0 -413
  41. data/lib/arjdbc/firebird/connection_methods.rb +0 -23
  42. data/lib/arjdbc/firebird.rb +0 -4
  43. data/lib/arjdbc/informix/adapter.rb +0 -139
  44. data/lib/arjdbc/informix/connection_methods.rb +0 -9
  45. data/lib/arjdbc/sybase/adapter.rb +0 -47
  46. data/lib/arjdbc/sybase.rb +0 -2
  47. data/lib/arjdbc/tasks/db2_database_tasks.rb +0 -104
  48. data/lib/arjdbc/tasks/derby_database_tasks.rb +0 -95
  49. data/src/java/arjdbc/derby/DerbyModule.java +0 -178
  50. data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +0 -152
  51. data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +0 -174
  52. data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +0 -75
@@ -1,808 +0,0 @@
1
- # NOTE: file contains code adapted from **ruby-ibmdb** adapter, license follows
2
- =begin
3
- Copyright (c) 2006 - 2015 IBM Corporation
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
- =end
24
-
25
- ArJdbc.load_java_part :DB2
26
-
27
- require 'arjdbc/db2/column'
28
-
29
- module ArJdbc
30
- # @note This adapter doesn't support explain `config.active_record.auto_explain_threshold_in_seconds` should be commented (Rails < 4.0)
31
- module DB2
32
-
33
-
34
- module ActiveRecord::ConnectionAdapters
35
-
36
- remove_const(:DB2Adapter) if const_defined?(:DB2Adapter)
37
-
38
- class DB2Adapter < JdbcAdapter
39
-
40
- include ArJdbc::DB2
41
- include ArJdbc::DB2::Column
42
-
43
- # AR 5.2 Fix
44
- def initialize(connection, logger = nil, connection_parameters = nil, config = {})
45
- super(connection, logger, config) # configure_connection happens in super
46
- end
47
-
48
- def jdbc_connection_class(spec)
49
- ArJdbc::DB2.jdbc_connection_class
50
- end
51
-
52
- def data_source_sql(name = nil, type: nil)
53
- scope = quoted_scope(name, type: type)
54
-
55
- sql = if scope[:type] == "'T'"
56
- "select table_name from sysibm.tables".dup
57
- else
58
- "select table_name from sysibm.views".dup
59
- end
60
-
61
- wheres = []
62
-
63
- wheres << " table_type = #{scope[:type]}" if scope[:type]
64
- wheres << " table_schema = #{scope[:schema]}" if scope[:schema]
65
- wheres << " UPPER(table_name) = UPPER(#{scope[:name]})" if scope[:name]
66
-
67
- if wheres.present?
68
- sql << ' WHERE '
69
- sql << wheres.join(' AND ')
70
- end
71
- sql
72
- end
73
-
74
- def quoted_scope(name = nil, type: nil)
75
- type = \
76
- case type
77
- when "BASE TABLE"
78
- "'T'"
79
- when "VIEW"
80
- "'V'"
81
- end
82
- scope = {}
83
- scope[:name] = quote(name) if name
84
- scope[:type] = type if type
85
- scope[:schema] = quote(scope[:schema] || schema)
86
- scope
87
- end
88
-
89
- end
90
- end
91
-
92
- # @private
93
- def self.extended(adapter); initialize!; end
94
-
95
- # @private
96
- @@_initialized = nil
97
-
98
- # @private
99
- def self.initialize!
100
- return if @@_initialized; @@_initialized = true
101
-
102
- require 'arjdbc/util/serialized_attributes'
103
- Util::SerializedAttributes.setup %r{blob|clob}i, 'after_save_with_db2_lob'
104
- end
105
-
106
- # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_connection_class
107
- def self.jdbc_connection_class
108
- ::ActiveRecord::ConnectionAdapters::DB2JdbcConnection
109
- end
110
-
111
- # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_column_class
112
- def jdbc_column_class
113
- ::ActiveRecord::ConnectionAdapters::DB2Column
114
- end
115
-
116
- # @private
117
- @@emulate_booleans = true
118
-
119
- # Boolean emulation can be disabled using :
120
- #
121
- # ArJdbc::DB2.emulate_booleans = false
122
- #
123
- def self.emulate_booleans?; @@emulate_booleans; end
124
- # @deprecated Use {#emulate_booleans?} instead.
125
- def self.emulate_booleans; @@emulate_booleans; end
126
- # @see #emulate_booleans?
127
- def self.emulate_booleans=(emulate); @@emulate_booleans = emulate; end
128
-
129
- # @private
130
- @@update_lob_values = true
131
-
132
- # Updating records with LOB values (binary/text columns) in a separate
133
- # statement can be disabled using :
134
- #
135
- # ArJdbc::DB2.update_lob_values = false
136
- #
137
- # @note This only applies when prepared statements are not used.
138
- def self.update_lob_values?; @@update_lob_values; end
139
- # @see #update_lob_values?
140
- def self.update_lob_values=(update); @@update_lob_values = update; end
141
-
142
- # @see #update_lob_values?
143
- # @see ArJdbc::Util::SerializedAttributes#update_lob_columns
144
- def update_lob_value?(value, column = nil)
145
- DB2.update_lob_values? && ! prepared_statements? # && value
146
- end
147
-
148
- # @see #quote
149
- # @private
150
- BLOB_VALUE_MARKER = "BLOB('')"
151
- # @see #quote
152
- # @private
153
- CLOB_VALUE_MARKER = "''"
154
-
155
- def configure_connection
156
- schema = self.schema
157
- set_schema(schema) if schema && schema != config[:username]
158
- end
159
-
160
- ADAPTER_NAME = 'DB2'.freeze
161
-
162
- def adapter_name
163
- ADAPTER_NAME
164
- end
165
-
166
- NATIVE_DATABASE_TYPES = {
167
- :string => { :name => "varchar", :limit => 255 },
168
- :integer => { :name => "integer" },
169
- :bigint => { :name => 'bigint' },
170
- :float => { :name => "real" }, # :limit => 24
171
- :double => { :name => "double" }, # :limit => 53
172
- :text => { :name => "clob" },
173
- :binary => { :name => "blob" },
174
- :xml => { :name => "xml" },
175
- :decimal => { :name => "decimal" }, # :limit => 31
176
- :char => { :name => "char" }, # :limit => 254
177
- :date => { :name => "date" },
178
- :datetime => { :name => "timestamp" },
179
- :timestamp => { :name => "timestamp" },
180
- :time => { :name => "time" },
181
- :boolean => { :name => "smallint" }, # no native boolean type
182
- #:rowid => { :name => "rowid" }, # rowid is a supported datatype on z/OS and i/5
183
- #:serial => { :name => "serial" }, # supported datatype on Informix Dynamic Server
184
- #:graphic => { :name => "graphic", :limit => 1 }, # :limit => 127
185
- }
186
-
187
- # @override
188
- def initialize_type_map(m)
189
- register_class_with_limit m, %r(boolean)i, ActiveRecord::Type::Boolean
190
- register_class_with_limit m, %r(char)i, ActiveRecord::Type::String
191
- register_class_with_limit m, %r(binary)i, ActiveRecord::Type::Binary
192
- register_class_with_limit m, %r(text)i, ActiveRecord::Type::Text
193
- register_class_with_limit m, %r(date)i, ActiveRecord::Type::Date
194
- register_class_with_limit m, %r(time)i, ActiveRecord::Type::Time
195
- register_class_with_limit m, %r(datetime)i, ActiveRecord::Type::DateTime
196
- register_class_with_limit m, %r(float)i, ActiveRecord::Type::Float
197
- register_class_with_limit m, %r(int)i, ActiveRecord::Type::Integer
198
-
199
- m.alias_type %r(blob)i, 'binary'
200
- m.alias_type %r(clob)i, 'text'
201
- m.alias_type %r(timestamp)i, 'datetime'
202
- m.alias_type %r(numeric)i, 'decimal'
203
- m.alias_type %r(number)i, 'decimal'
204
- m.alias_type %r(double)i, 'float'
205
- m.alias_type %r(real)i, 'float'
206
-
207
- m.register_type(%r(decimal)i) do |sql_type|
208
- scale = extract_scale(sql_type)
209
- precision = extract_precision(sql_type)
210
- limit = extract_limit(sql_type)
211
- if scale == 0
212
- ActiveRecord::Type::BigInteger.new(:precision => precision, :limit => limit)
213
- else
214
- ActiveRecord::Type::Decimal.new(:precision => precision, :scale => scale)
215
- end
216
- end
217
-
218
- m.alias_type %r(for bit data)i, 'binary'
219
- m.alias_type %r(smallint)i, 'boolean'
220
- m.alias_type %r(serial)i, 'int'
221
- m.alias_type %r(decfloat)i, 'decimal'
222
- #m.alias_type %r(real)i, 'decimal'
223
- m.alias_type %r(graphic)i, 'binary'
224
- m.alias_type %r(rowid)i, 'int'
225
-
226
- m.register_type(%r(smallint)i) do
227
- if DB2.emulate_booleans?
228
- ActiveRecord::Type::Boolean.new
229
- else
230
- ActiveRecord::Type::Integer.new(:limit => 1)
231
- end
232
- end
233
-
234
- m.register_type %r(xml)i, XmlType.new
235
- end if AR42
236
-
237
- # @private
238
- class XmlType < ActiveRecord::Type::String
239
- def type; :xml end
240
-
241
- def type_cast_for_database(value)
242
- return unless value
243
- Data.new(super)
244
- end
245
-
246
- class Data
247
- def initialize(value)
248
- @value = value
249
- end
250
- def to_s; @value end
251
- end
252
- end if AR42
253
-
254
- # @override
255
- def reset_column_information
256
- initialize_type_map(type_map)
257
- end if AR42
258
-
259
- # @override
260
- def native_database_types
261
- # NOTE: currently merging with what JDBC gives us since there's a lot
262
- # of DB2-like stuff we could be connecting e.g. "classic", Z/OS etc.
263
- # types = super
264
- types = super.merge(NATIVE_DATABASE_TYPES)
265
- types
266
- end
267
-
268
- # @private
269
- class TableDefinition < ::ActiveRecord::ConnectionAdapters::TableDefinition
270
-
271
- def xml(*args)
272
- options = args.extract_options!
273
- column(args[0], 'xml', options)
274
- end
275
-
276
- # IBM DB adapter (MRI) compatibility :
277
-
278
- # @private
279
- # @deprecated
280
- def double(*args)
281
- options = args.extract_options!
282
- column(args[0], 'double', options)
283
- end
284
-
285
- # @private
286
- def decfloat(*args)
287
- options = args.extract_options!
288
- column(args[0], 'decfloat', options)
289
- end
290
-
291
- def graphic(*args)
292
- options = args.extract_options!
293
- column(args[0], 'graphic', options)
294
- end
295
-
296
- # @private
297
- # @deprecated
298
- def vargraphic(*args)
299
- options = args.extract_options!
300
- column(args[0], 'vargraphic', options)
301
- end
302
-
303
- # @private
304
- # @deprecated
305
- def bigint(*args)
306
- options = args.extract_options!
307
- column(args[0], 'bigint', options)
308
- end
309
-
310
- def char(*args)
311
- options = args.extract_options!
312
- column(args[0], 'char', options)
313
- end
314
- # alias_method :character, :char
315
-
316
- end
317
-
318
- def table_definition(*args)
319
- new_table_definition(TableDefinition, *args)
320
- end
321
-
322
- def prefetch_primary_key?(table_name = nil)
323
- # TRUE if the table has no identity column
324
- names = table_name.upcase.split(".")
325
- sql = "SELECT 1 FROM SYSCAT.COLUMNS WHERE IDENTITY = 'Y' "
326
- sql << "AND TABSCHEMA = '#{names.first}' " if names.size == 2
327
- sql << "AND TABNAME = '#{names.last}'"
328
- select_one(sql).nil?
329
- end
330
-
331
- # @override
332
- def primary_keys(table)
333
- # If no schema in table name is given but present in URL parameter. Use the URL parameter one
334
- # This avoids issues if the table is present in multiple schemas
335
- if table.split(".").size == 1 && schema
336
- table = "#{schema}.#{table}"
337
- end
338
-
339
- super
340
- end
341
-
342
- def next_sequence_value(sequence_name)
343
- select_value("SELECT NEXT VALUE FOR #{sequence_name} FROM sysibm.sysdummy1")
344
- end
345
-
346
- def create_table(name, options = {}, &block)
347
- if zos?
348
- zos_create_table(name, options, &block)
349
- else
350
- super
351
- end
352
- end
353
-
354
- def zos_create_table(name, options = {})
355
- table_definition = new_table_definition TableDefinition, name, options[:temporary], options[:options], options[:as]
356
-
357
- unless options[:id] == false
358
- table_definition.primary_key(options[:primary_key] || primary_key(name))
359
- end
360
-
361
- yield table_definition if block_given?
362
-
363
- # Clobs in DB2 Host have to be created after the Table with an auxiliary Table.
364
- clob_columns = []
365
- table_definition.columns.delete_if do |column|
366
- if column.type && column.type.to_sym == :text
367
- clob_columns << column; true
368
- end
369
- end
370
-
371
- drop_table(name, options) if options[:force] && table_exists?(name)
372
-
373
- create_sql = "CREATE#{' TEMPORARY' if options[:temporary]} TABLE "
374
- create_sql << "#{quote_table_name(name)} ("
375
- create_sql << table_definition.to_sql
376
- create_sql << ") #{options[:options]}"
377
- if @config[:database] && @config[:tablespace]
378
- create_sql << " IN #{@config[:database]}.#{@config[:tablespace]}"
379
- end
380
-
381
- execute create_sql
382
-
383
- # Table definition is complete only when a unique index is created on the primary_key column for DB2 V8 on zOS
384
- # create index on id column if options[:id] is nil or id ==true
385
- # else check if options[:primary_key]is not nil then create an unique index on that column
386
- # TODO someone on Z/OS should test this out - also not needed for V9 ?
387
- #primary_column = options[:id] == true ? 'id' : options[:primary_key]
388
- #add_index(name, (primary_column || 'id').to_s, :unique => true)
389
-
390
- clob_columns.each do |clob_column|
391
- column_name = clob_column.name.to_s
392
- execute "ALTER TABLE #{name} ADD COLUMN #{column_name} clob"
393
- clob_table_name = "#{name}_#{column_name}_CD_"
394
- if @config[:database] && @config[:lob_tablespaces]
395
- in_lob_table_space = " IN #{@config[:database]}.#{@config[:lob_tablespaces][name.split(".")[1]]}"
396
- end
397
- execute "CREATE AUXILIARY TABLE #{clob_table_name} #{in_lob_table_space} STORES #{name} COLUMN #{column_name}"
398
- execute "CREATE UNIQUE INDEX #{clob_table_name} ON #{clob_table_name};"
399
- end
400
- end
401
- private :zos_create_table
402
-
403
- def pk_and_sequence_for(table)
404
- # In JDBC/DB2 side, only upcase names of table and column are handled.
405
- keys = super(table.upcase)
406
- if keys && keys[0]
407
- # In ActiveRecord side, only downcase names of table and column are handled.
408
- keys[0] = keys[0].downcase
409
- end
410
- keys
411
- end
412
-
413
- # Properly quotes the various data types.
414
- # @param value contains the data
415
- # @override
416
- def quote(value)
417
- return value if sql_literal?(value)
418
- super
419
- end
420
-
421
- # @override
422
- def quoted_date(value)
423
- if value.acts_like?(:time) && value.respond_to?(:usec)
424
- usec = sprintf("%06d", value.usec)
425
- value = ::ActiveRecord.default_timezone == :utc ? value.getutc : value.getlocal
426
- "#{value.strftime("%Y-%m-%d %H:%M:%S")}.#{usec}"
427
- else
428
- super
429
- end
430
- end if ::ActiveRecord::VERSION::MAJOR >= 3
431
-
432
- def quote_time(value)
433
- value = ::ActiveRecord.default_timezone == :utc ? value.getutc : value.getlocal
434
- # AS400 doesn't support date in time column
435
- "'#{value.strftime("%H:%M:%S")}'"
436
- end
437
-
438
- def quote_column_name(column_name)
439
- column_name.to_s
440
- end
441
-
442
- def modify_types(types)
443
- super(types)
444
- types[:primary_key] = 'int not null generated by default as identity (start with 1) primary key'
445
- types[:string][:limit] = 255
446
- types[:integer][:limit] = nil
447
- types[:boolean] = {:name => "decimal(1)"}
448
- types
449
- end
450
-
451
- def type_to_sql(type, limit: nil, precision: nil, scale: nil, **)
452
- limit = nil if type.to_sym == :integer
453
- super
454
- end
455
-
456
- # @private
457
- VALUES_DEFAULT = 'VALUES ( DEFAULT )' # NOTE: Arel::Visitors::DB2 uses this
458
-
459
- # @override
460
- def empty_insert_statement_value
461
- VALUES_DEFAULT # won't work as DB2 needs to know the column count
462
- end
463
-
464
- def add_column(table_name, column_name, type, options = {})
465
- # The keyword COLUMN allows to use reserved names for columns (ex: date)
466
- add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD COLUMN #{quote_column_name(column_name)} #{type_to_sql(type, options)}"
467
- add_column_options!(add_column_sql, options)
468
- execute(add_column_sql)
469
- end
470
-
471
- def add_column_options!(sql, options)
472
- # handle case of defaults for CLOB columns,
473
- # which might get incorrect if we write LOBs in the after_save callback
474
- if options_include_default?(options)
475
- column = options[:column]
476
- if column && column.type == :text
477
- sql << " DEFAULT #{quote(options.delete(:default))}"
478
- end
479
- if column && column.type == :binary
480
- # quoting required for the default value of a column :
481
- value = options.delete(:default)
482
- # DB2 z/OS only allows NULL or "" (empty) string as DEFAULT value
483
- # for a BLOB column. non-empty string and non-NULL, return error!
484
- if value.nil?
485
- sql_value = "NULL"
486
- else
487
- sql_value = zos? ? "#{value}" : "BLOB('#{quote_string(value)}'"
488
- end
489
- sql << " DEFAULT #{sql_value}"
490
- end
491
- end
492
- super
493
- end
494
-
495
- # @note Only used with (non-AREL) ActiveRecord **2.3**.
496
- # @see Arel::Visitors::DB2
497
- def add_limit_offset!(sql, options)
498
- limit = options[:limit]
499
- replace_limit_offset!(sql, limit, options[:offset]) if limit
500
- end if ::ActiveRecord::VERSION::MAJOR < 3
501
-
502
- # @private shared with {Arel::Visitors::DB2}
503
- def replace_limit_offset!(sql, limit, offset, orders = nil)
504
- limit = limit.to_i
505
-
506
- if offset # && limit
507
- over_order_by = nil # NOTE: orders matching got reverted as it was not complete and there were no case covering it ...
508
-
509
- start_sql = "SELECT B.* FROM (SELECT A.*, row_number() OVER (#{over_order_by}) AS internal$rownum FROM (SELECT"
510
- end_sql = ") A ) B WHERE B.internal$rownum > #{offset} AND B.internal$rownum <= #{limit + offset.to_i}"
511
-
512
- if sql.is_a?(String)
513
- sql.sub!(/SELECT/i, start_sql)
514
- sql << end_sql
515
- else # AR 4.2 sql.class ... Arel::Collectors::Bind
516
- sql.parts[0] = start_sql # sql.sub! /SELECT/i
517
- sql.parts[ sql.parts.length ] = end_sql
518
- end
519
- else
520
- limit_sql = limit == 1 ? " FETCH FIRST ROW ONLY" : " FETCH FIRST #{limit} ROWS ONLY"
521
- if sql.is_a?(String)
522
- sql << limit_sql
523
- else # AR 4.2 sql.class ... Arel::Collectors::Bind
524
- sql.parts[ sql.parts.length ] = limit_sql
525
- end
526
- end
527
- sql
528
- end
529
-
530
- # @deprecated seems not sued nor tested ?!
531
- def runstats_for_table(tablename, priority = 10)
532
- @connection.execute_update "call sysproc.admin_cmd('RUNSTATS ON TABLE #{tablename} WITH DISTRIBUTION AND DETAILED INDEXES ALL UTIL_IMPACT_PRIORITY #{priority}')"
533
- end
534
-
535
- if ::ActiveRecord::VERSION::MAJOR >= 4
536
-
537
- def select(sql, name = nil, binds = [])
538
- exec_query(to_sql(suble_null_test(sql), binds), name, binds)
539
- end
540
-
541
- else
542
-
543
- def select(sql, name = nil, binds = [])
544
- exec_query_raw(to_sql(suble_null_test(sql), binds), name, binds)
545
- end
546
-
547
- end
548
-
549
- # @private
550
- IS_NOT_NULL = /(!=|<>)\s*NULL/i
551
- # @private
552
- IS_NULL = /=\s*NULL/i
553
-
554
- def suble_null_test(sql)
555
- return sql unless sql.is_a?(String)
556
- # DB2 does not like "= NULL", "!= NULL", or "<> NULL" :
557
- sql = sql.dup
558
- sql.gsub! IS_NOT_NULL, 'IS NOT NULL'
559
- sql.gsub! IS_NULL, 'IS NULL'
560
- sql
561
- end
562
- private :suble_null_test
563
-
564
- def add_index(table_name, column_name, options = {})
565
- if ! zos? || ( table_name.to_s == ActiveRecord::Migrator.schema_migrations_table_name.to_s )
566
- column_name = column_name.to_s if column_name.is_a?(Symbol)
567
- super
568
- else
569
- statement = 'CREATE'
570
- statement << ' UNIQUE ' if options[:unique]
571
- statement << " INDEX #{ActiveRecord::Base.table_name_prefix}#{options[:name]} "
572
- statement << " ON #{table_name}(#{column_name})"
573
-
574
- execute statement
575
- end
576
- end
577
-
578
- # @override
579
- def remove_index!(table_name, index_name)
580
- execute "DROP INDEX #{quote_column_name(index_name)}"
581
- end
582
-
583
- # http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.admin.dbobj.doc/doc/t0020130.html
584
- # ...not supported on IBM i, so we raise in this case
585
- def rename_column(table_name, column_name, new_column_name) #:nodoc:
586
- sql = "ALTER TABLE #{table_name} RENAME COLUMN #{column_name} TO #{new_column_name}"
587
- execute_table_change(sql, table_name, 'Rename Column')
588
- end
589
-
590
- def change_column_null(table_name, column_name, null)
591
- if null
592
- sql = "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} DROP NOT NULL"
593
- else
594
- sql = "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET NOT NULL"
595
- end
596
- execute_table_change(sql, table_name, 'Change Column')
597
- end
598
-
599
- def change_column_default(table_name, column_name, default)
600
- if default.nil?
601
- sql = "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} DROP DEFAULT"
602
- else
603
- sql = "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET WITH DEFAULT #{quote(default)}"
604
- end
605
- execute_table_change(sql, table_name, 'Change Column')
606
- end
607
-
608
- def change_column(table_name, column_name, type, options = {})
609
- data_type = type_to_sql(type, options)
610
- sql = "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET DATA TYPE #{data_type}"
611
- execute_table_change(sql, table_name, 'Change Column')
612
-
613
- if options.include?(:default) and options.include?(:null)
614
- # which to run first?
615
- if options[:null] or options[:default].nil?
616
- change_column_null(table_name, column_name, options[:null])
617
- change_column_default(table_name, column_name, options[:default])
618
- else
619
- change_column_default(table_name, column_name, options[:default])
620
- change_column_null(table_name, column_name, options[:null])
621
- end
622
- elsif options.include?(:default)
623
- change_column_default(table_name, column_name, options[:default])
624
- elsif options.include?(:null)
625
- change_column_null(table_name, column_name, options[:null])
626
- end
627
- end
628
-
629
- if ActiveRecord::VERSION::MAJOR >= 4
630
-
631
- def remove_column(table_name, column_name, type = nil, options = {})
632
- db2_remove_column(table_name, column_name)
633
- end
634
-
635
- else
636
-
637
- def remove_column(table_name, *column_names)
638
- # http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.admin.dbobj.doc/doc/t0020132.html
639
- outcome = nil
640
- column_names = column_names.flatten
641
- for column_name in column_names
642
- outcome = db2_remove_column(table_name, column_name)
643
- end
644
- column_names.size == 1 ? outcome : nil
645
- end
646
-
647
- end
648
-
649
- def rename_table(name, new_name)
650
- # http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.ref.doc/doc/r0000980.html
651
- execute_table_change("RENAME TABLE #{name} TO #{new_name}", new_name, 'Rename Table')
652
- end
653
-
654
- def tables
655
- @connection.tables(nil, schema)
656
- end
657
-
658
- # only record precision and scale for types that can set them via CREATE TABLE:
659
- # http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.ref.doc/doc/r0000927.html
660
-
661
- HAVE_LIMIT = %w(FLOAT DECFLOAT CHAR VARCHAR CLOB BLOB NCHAR NCLOB DBCLOB GRAPHIC VARGRAPHIC) # TIMESTAMP
662
- HAVE_PRECISION = %w(DECIMAL NUMERIC)
663
- HAVE_SCALE = %w(DECIMAL NUMERIC)
664
-
665
- def columns(table_name, name = nil)
666
- columns = @connection.columns_internal(table_name.to_s, nil, schema) # catalog == nil
667
-
668
- if zos?
669
- # Remove the mighty db2_generated_rowid_for_lobs from the list of columns
670
- columns = columns.reject { |col| "db2_generated_rowid_for_lobs" == col.name }
671
- end
672
- # scrub out sizing info when CREATE TABLE doesn't support it
673
- # but JDBC reports it (doh!)
674
- for column in columns
675
- base_sql_type = column.sql_type.sub(/\(.*/, "").upcase
676
- column.limit = nil unless HAVE_LIMIT.include?(base_sql_type)
677
- column.precision = nil unless HAVE_PRECISION.include?(base_sql_type)
678
- #column.scale = nil unless HAVE_SCALE.include?(base_sql_type)
679
- end
680
-
681
- columns
682
- end
683
-
684
- def indexes(table_name, name = nil)
685
- @connection.indexes(table_name, name, schema)
686
- end
687
-
688
- def recreate_database(name = nil, options = {})
689
- drop_database(name)
690
- end
691
-
692
- def drop_database(name = nil)
693
- tables.each { |table| drop_table("#{table}") }
694
- end
695
-
696
- def truncate(table_name, name = nil)
697
- execute "TRUNCATE TABLE #{quote_table_name(table_name)} IMMEDIATE", name
698
- end
699
-
700
- # @override
701
- def supports_views?; true end
702
-
703
- def execute_table_change(sql, table_name, name = nil)
704
- outcome = execute(sql, name)
705
- reorg_table(table_name, name)
706
- outcome
707
- end
708
- protected :execute_table_change
709
-
710
- def reorg_table(table_name, name = nil)
711
- exec_update "call sysproc.admin_cmd ('REORG TABLE #{table_name}')", name, []
712
- end
713
- private :reorg_table
714
-
715
- # alias_method :execute_and_auto_confirm, :execute
716
-
717
- # Returns the value of an identity column of the last *INSERT* statement made over this connection.
718
- # @note Check the *IDENTITY_VAL_LOCAL* function for documentation.
719
- # @return [Integer, NilClass]
720
- def last_inserted_id(result)
721
- @connection.identity_val_local
722
- end
723
-
724
- # NOTE: only setup query analysis on AR <= 3.0 since on 3.1 {#exec_query},
725
- # {#exec_insert} will be used for AR generated queries/inserts etc.
726
- # Also there's prepared statement support and {#execute} is meant to stay
727
- # as a way of running non-prepared SQL statements (returning raw results).
728
- if ActiveRecord::VERSION::MAJOR < 3 ||
729
- ( ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR < 1 )
730
-
731
- def _execute(sql, name = nil)
732
- if self.class.select?(sql)
733
- @connection.execute_query_raw(sql)
734
- elsif self.class.insert?(sql)
735
- @connection.execute_insert(sql) || last_insert_id
736
- else
737
- @connection.execute_update(sql)
738
- end
739
- end
740
- private :_execute
741
-
742
- end
743
-
744
- DRIVER_NAME = 'com.ibm.db2.jcc.DB2Driver'.freeze
745
-
746
- # @private
747
- def zos?
748
- @zos = nil unless defined? @zos
749
- return @zos unless @zos.nil?
750
- @zos =
751
- if url = config[:url]
752
- !!( url =~ /^jdbc:db2j:net:/ && config[:driver] == DRIVER_NAME )
753
- else
754
- nil
755
- end
756
- end
757
-
758
- # @private
759
- # @deprecated no longer used
760
- def as400?
761
- false
762
- end
763
-
764
- def schema
765
- db2_schema
766
- end
767
-
768
- def schema=(schema)
769
- set_schema(@db2_schema = schema) if db2_schema != schema
770
- end
771
-
772
- private
773
-
774
- def set_schema(schema)
775
- execute("SET SCHEMA #{schema}")
776
- end
777
-
778
- def db2_schema
779
- @db2_schema = false unless defined? @db2_schema
780
- return @db2_schema if @db2_schema != false
781
- schema = config[:schema]
782
- @db2_schema =
783
- if schema then schema
784
- elsif config[:jndi] || config[:data_source]
785
- nil # let JNDI worry about schema
786
- else
787
- # LUW implementation uses schema name of username by default
788
- config[:username] || ENV['USER']
789
- end
790
- end
791
-
792
- def db2_remove_column(table_name, column_name)
793
- sql = "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)}"
794
- execute_table_change(sql, table_name, 'Remove Column')
795
- end
796
-
797
- end
798
- end
799
-
800
- module ActiveRecord::ConnectionAdapters
801
-
802
- remove_const(:DB2Column) if const_defined?(:DB2Column)
803
-
804
- class DB2Column < JdbcColumn
805
- include ::ArJdbc::DB2::Column
806
- end
807
-
808
- end