activerecord-jdbc-alt-adapter 61.2.0-java → 70.0.0.rc2-java

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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +118 -0
  3. data/.github/workflows/ruby.yml +273 -0
  4. data/.gitignore +1 -0
  5. data/.travis.yml +3 -4
  6. data/Gemfile +9 -7
  7. data/README.md +5 -1
  8. data/Rakefile +1 -1
  9. data/activerecord-jdbc-adapter.gemspec +2 -2
  10. data/activerecord-jdbc-alt-adapter.gemspec +2 -2
  11. data/lib/arel/visitors/compat.rb +5 -33
  12. data/lib/arel/visitors/h2.rb +1 -13
  13. data/lib/arel/visitors/hsqldb.rb +1 -21
  14. data/lib/arel/visitors/sql_server.rb +2 -103
  15. data/lib/arjdbc/abstract/core.rb +8 -9
  16. data/lib/arjdbc/abstract/database_statements.rb +4 -4
  17. data/lib/arjdbc/discover.rb +0 -67
  18. data/lib/arjdbc/hsqldb/adapter.rb +2 -2
  19. data/lib/arjdbc/jdbc/adapter.rb +3 -3
  20. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  21. data/lib/arjdbc/jdbc/adapter_require.rb +3 -1
  22. data/lib/arjdbc/jdbc/column.rb +1 -26
  23. data/lib/arjdbc/jdbc/type_cast.rb +2 -2
  24. data/lib/arjdbc/jdbc.rb +0 -7
  25. data/lib/arjdbc/mssql/adapter.rb +138 -108
  26. data/lib/arjdbc/mssql/quoting.rb +26 -27
  27. data/lib/arjdbc/mssql/schema_creation.rb +1 -1
  28. data/lib/arjdbc/mssql/schema_definitions.rb +32 -17
  29. data/lib/arjdbc/mssql/schema_dumper.rb +13 -1
  30. data/lib/arjdbc/mssql/schema_statements.rb +61 -36
  31. data/lib/arjdbc/mssql/transaction.rb +2 -2
  32. data/lib/arjdbc/mssql/types/date_and_time_types.rb +6 -6
  33. data/lib/arjdbc/mssql/types/numeric_types.rb +2 -2
  34. data/lib/arjdbc/mssql.rb +1 -1
  35. data/lib/arjdbc/mysql/adapter.rb +2 -1
  36. data/lib/arjdbc/oracle/adapter.rb +4 -23
  37. data/lib/arjdbc/postgresql/adapter.rb +152 -4
  38. data/lib/arjdbc/postgresql/oid_types.rb +142 -106
  39. data/lib/arjdbc/sqlite3/adapter.rb +132 -88
  40. data/lib/arjdbc/tasks/database_tasks.rb +0 -12
  41. data/lib/arjdbc/util/serialized_attributes.rb +0 -22
  42. data/lib/arjdbc/util/table_copier.rb +2 -1
  43. data/lib/arjdbc/version.rb +1 -1
  44. data/rakelib/02-test.rake +3 -18
  45. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +17 -2
  46. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +5 -0
  47. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +33 -0
  48. metadata +9 -40
  49. data/lib/active_record/connection_adapters/as400_adapter.rb +0 -2
  50. data/lib/active_record/connection_adapters/db2_adapter.rb +0 -1
  51. data/lib/active_record/connection_adapters/derby_adapter.rb +0 -1
  52. data/lib/active_record/connection_adapters/informix_adapter.rb +0 -1
  53. data/lib/arel/visitors/db2.rb +0 -137
  54. data/lib/arel/visitors/derby.rb +0 -112
  55. data/lib/arel/visitors/firebird.rb +0 -79
  56. data/lib/arjdbc/db2/adapter.rb +0 -808
  57. data/lib/arjdbc/db2/as400.rb +0 -142
  58. data/lib/arjdbc/db2/column.rb +0 -131
  59. data/lib/arjdbc/db2/connection_methods.rb +0 -48
  60. data/lib/arjdbc/db2.rb +0 -4
  61. data/lib/arjdbc/derby/active_record_patch.rb +0 -13
  62. data/lib/arjdbc/derby/adapter.rb +0 -521
  63. data/lib/arjdbc/derby/connection_methods.rb +0 -20
  64. data/lib/arjdbc/derby/schema_creation.rb +0 -15
  65. data/lib/arjdbc/derby.rb +0 -3
  66. data/lib/arjdbc/firebird/adapter.rb +0 -413
  67. data/lib/arjdbc/firebird/connection_methods.rb +0 -23
  68. data/lib/arjdbc/firebird.rb +0 -4
  69. data/lib/arjdbc/informix/adapter.rb +0 -139
  70. data/lib/arjdbc/informix/connection_methods.rb +0 -9
  71. data/lib/arjdbc/sybase/adapter.rb +0 -47
  72. data/lib/arjdbc/sybase.rb +0 -2
  73. data/lib/arjdbc/tasks/db2_database_tasks.rb +0 -104
  74. data/lib/arjdbc/tasks/derby_database_tasks.rb +0 -95
  75. data/src/java/arjdbc/derby/DerbyModule.java +0 -178
  76. data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +0 -152
  77. data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +0 -174
  78. 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 /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::Base.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::Base.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