activerecord-jdbc-adapter 1.3.0.beta1 → 1.3.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (161) hide show
  1. data/.gitignore +12 -11
  2. data/.travis.yml +36 -7
  3. data/Appraisals +3 -3
  4. data/Gemfile +1 -1
  5. data/Gemfile.lock +13 -6
  6. data/History.txt +64 -0
  7. data/README.md +8 -1
  8. data/Rakefile +3 -1
  9. data/gemfiles/rails23.gemfile +1 -1
  10. data/gemfiles/rails23.gemfile.lock +6 -5
  11. data/gemfiles/rails30.gemfile +1 -1
  12. data/gemfiles/rails30.gemfile.lock +7 -6
  13. data/gemfiles/rails31.gemfile +1 -1
  14. data/gemfiles/rails31.gemfile.lock +6 -5
  15. data/gemfiles/rails32.gemfile +1 -1
  16. data/gemfiles/rails32.gemfile.lock +6 -5
  17. data/gemfiles/rails40.gemfile +2 -4
  18. data/gemfiles/rails40.gemfile.lock +37 -51
  19. data/lib/active_record/connection_adapters/as400_adapter.rb +2 -0
  20. data/lib/active_record/connection_adapters/db2_adapter.rb +1 -1
  21. data/lib/arel/visitors/db2.rb +5 -1
  22. data/lib/arel/visitors/hsqldb.rb +1 -0
  23. data/lib/arel/visitors/sql_server.rb +55 -13
  24. data/lib/arjdbc/db2/adapter.rb +197 -227
  25. data/lib/arjdbc/db2/as400.rb +124 -0
  26. data/lib/arjdbc/db2/connection_methods.rb +20 -1
  27. data/lib/arjdbc/derby/adapter.rb +17 -85
  28. data/lib/arjdbc/derby/connection_methods.rb +2 -1
  29. data/lib/arjdbc/discover.rb +55 -47
  30. data/lib/arjdbc/h2/adapter.rb +52 -18
  31. data/lib/arjdbc/h2/connection_methods.rb +10 -2
  32. data/lib/arjdbc/hsqldb/adapter.rb +33 -9
  33. data/lib/arjdbc/hsqldb/connection_methods.rb +10 -2
  34. data/lib/arjdbc/informix.rb +2 -1
  35. data/lib/arjdbc/jdbc.rb +5 -1
  36. data/lib/arjdbc/jdbc/adapter.rb +167 -89
  37. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  38. data/lib/arjdbc/jdbc/adapter_require.rb +46 -0
  39. data/lib/arjdbc/jdbc/base_ext.rb +25 -3
  40. data/lib/arjdbc/jdbc/callbacks.rb +9 -8
  41. data/lib/arjdbc/jdbc/column.rb +8 -20
  42. data/lib/arjdbc/jdbc/connection.rb +69 -80
  43. data/lib/arjdbc/jdbc/extension.rb +6 -8
  44. data/lib/arjdbc/jdbc/jdbc.rake +3 -141
  45. data/lib/arjdbc/jdbc/rake_tasks.rb +3 -10
  46. data/lib/arjdbc/mssql/adapter.rb +108 -34
  47. data/lib/arjdbc/mssql/connection_methods.rb +3 -1
  48. data/lib/arjdbc/mssql/limit_helpers.rb +3 -2
  49. data/lib/arjdbc/mssql/lock_helpers.rb +5 -1
  50. data/lib/arjdbc/mysql/adapter.rb +127 -70
  51. data/lib/arjdbc/mysql/connection_methods.rb +5 -2
  52. data/lib/arjdbc/oracle/adapter.rb +124 -94
  53. data/lib/arjdbc/oracle/connection_methods.rb +2 -1
  54. data/lib/arjdbc/postgresql/adapter.rb +99 -67
  55. data/lib/arjdbc/postgresql/column_cast.rb +3 -5
  56. data/lib/arjdbc/postgresql/connection_methods.rb +6 -6
  57. data/lib/arjdbc/railtie.rb +3 -1
  58. data/lib/arjdbc/sqlite3/adapter.rb +60 -43
  59. data/lib/arjdbc/sqlite3/connection_methods.rb +9 -9
  60. data/lib/arjdbc/sybase.rb +1 -1
  61. data/lib/arjdbc/tasks.rb +13 -0
  62. data/lib/arjdbc/tasks/database_tasks.rb +50 -0
  63. data/lib/arjdbc/tasks/databases.rake +89 -0
  64. data/lib/arjdbc/tasks/databases3.rake +203 -0
  65. data/lib/arjdbc/tasks/databases4.rake +39 -0
  66. data/lib/arjdbc/tasks/db2_database_tasks.rb +104 -0
  67. data/lib/arjdbc/tasks/derby_database_tasks.rb +95 -0
  68. data/lib/arjdbc/tasks/h2_database_tasks.rb +29 -0
  69. data/lib/arjdbc/tasks/hsqldb_database_tasks.rb +70 -0
  70. data/lib/arjdbc/tasks/jdbc_database_tasks.rb +122 -0
  71. data/lib/arjdbc/tasks/mssql_database_tasks.rb +36 -0
  72. data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +297 -0
  73. data/lib/arjdbc/tasks/oracle_database_tasks.rb +62 -0
  74. data/lib/arjdbc/version.rb +1 -1
  75. data/pom.xml +11 -12
  76. data/rails_generators/jdbc_generator.rb +1 -1
  77. data/rails_generators/templates/config/initializers/jdbc.rb +8 -5
  78. data/rails_generators/templates/lib/tasks/jdbc.rake +7 -4
  79. data/rakelib/02-test.rake +42 -15
  80. data/rakelib/compile.rake +29 -2
  81. data/rakelib/db.rake +2 -1
  82. data/rakelib/rails.rake +23 -6
  83. data/src/java/arjdbc/ArJdbcModule.java +175 -0
  84. data/src/java/arjdbc/db2/DB2Module.java +2 -1
  85. data/src/java/arjdbc/derby/DerbyModule.java +5 -24
  86. data/src/java/arjdbc/hsqldb/HSQLDBModule.java +3 -2
  87. data/src/java/arjdbc/jdbc/AdapterJavaService.java +3 -46
  88. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +1001 -259
  89. data/src/java/arjdbc/mssql/MSSQLModule.java +2 -1
  90. data/src/java/arjdbc/mysql/MySQLModule.java +4 -3
  91. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +12 -7
  92. data/src/java/arjdbc/oracle/OracleModule.java +2 -1
  93. data/src/java/arjdbc/sqlite3/SQLite3Module.java +2 -1
  94. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +12 -0
  95. data/test/db/db2.rb +14 -7
  96. data/test/db/db2/rake_test.rb +82 -0
  97. data/test/db/db2/rake_test_data.sql +35 -0
  98. data/test/db/db2/simple_test.rb +20 -0
  99. data/test/db/db2/unit_test.rb +3 -1
  100. data/test/db/derby.rb +7 -5
  101. data/test/db/derby/rake_test.rb +96 -0
  102. data/test/db/derby/simple_test.rb +10 -2
  103. data/test/db/h2.rb +6 -8
  104. data/test/db/h2/identity_column_test.rb +35 -0
  105. data/test/db/h2/offset_test.rb +49 -0
  106. data/test/db/h2/rake_test.rb +98 -0
  107. data/test/db/h2/schema_dump_test.rb +5 -1
  108. data/test/db/hsqldb.rb +6 -10
  109. data/test/db/hsqldb/rake_test.rb +101 -0
  110. data/test/db/hsqldb/schema_dump_test.rb +5 -1
  111. data/test/db/hsqldb/simple_test.rb +8 -0
  112. data/test/db/jndi_config.rb +1 -3
  113. data/test/db/jndi_pooled_config.rb +1 -3
  114. data/test/db/mssql/limit_offset_test.rb +23 -14
  115. data/test/db/mssql/rake_test.rb +143 -0
  116. data/test/db/mysql/_rails_test_mysql.32.out +1069 -1252
  117. data/test/db/mysql/nonstandard_primary_key_test.rb +21 -24
  118. data/test/db/mysql/rake_test.rb +97 -0
  119. data/test/db/mysql/schema_dump_test.rb +11 -11
  120. data/test/db/mysql/simple_test.rb +52 -3
  121. data/test/db/mysql/statement_escaping_test.rb +46 -0
  122. data/test/db/oracle/rake_test.rb +100 -0
  123. data/test/db/oracle/simple_test.rb +48 -0
  124. data/test/db/postgres/_rails_test_postgres.32.out +998 -1370
  125. data/test/db/postgres/active_schema_unit_test.rb +68 -0
  126. data/test/db/postgres/connection_test.rb +10 -2
  127. data/test/db/postgres/data_types_test.rb +2 -2
  128. data/test/db/postgres/ltree_test.rb +6 -5
  129. data/test/db/postgres/native_types_test.rb +1 -5
  130. data/test/db/postgres/rake_test.rb +117 -0
  131. data/test/db/postgres/schema_dump_test.rb +9 -2
  132. data/test/db/postgres/schema_test.rb +4 -2
  133. data/test/db/postgres/simple_test.rb +57 -16
  134. data/test/db/sqlite3.rb +3 -10
  135. data/test/db/sqlite3/_rails_test_sqlite3.32.out +1070 -1298
  136. data/test/db/sqlite3/rake_test.rb +71 -0
  137. data/test/db/sqlite3/simple_test.rb +9 -9
  138. data/test/has_many_through.rb +4 -1
  139. data/test/jdbc/db2.rb +14 -1
  140. data/test/jdbc_column_test.rb +23 -0
  141. data/test/{generic_jdbc_connection_test.rb → jdbc_connection_test.rb} +22 -17
  142. data/test/jndi_callbacks_test.rb +26 -28
  143. data/test/jndi_test.rb +7 -16
  144. data/test/models/data_types.rb +2 -1
  145. data/test/models/thing.rb +1 -0
  146. data/test/rails/mysql.rb +13 -0
  147. data/test/rails/sqlite3/version.rb +6 -0
  148. data/test/rails_stub.rb +31 -0
  149. data/test/rake_test_support.rb +298 -0
  150. data/test/serialize.rb +2 -4
  151. data/test/{helper.rb → shared_helper.rb} +0 -0
  152. data/test/simple.rb +167 -93
  153. data/test/test_helper.rb +52 -16
  154. metadata +388 -354
  155. data/lib/pg.rb +0 -26
  156. data/test/abstract_db_create.rb +0 -139
  157. data/test/activerecord/connection_adapters/type_conversion_test.rb +0 -36
  158. data/test/db/mssql/db_create_test.rb +0 -29
  159. data/test/db/mysql/db_create_test.rb +0 -33
  160. data/test/db/postgres/db_create_test.rb +0 -44
  161. data/test/db/postgres/db_drop_test.rb +0 -17
@@ -4,14 +4,12 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "activerecord"
6
6
  gem "jruby-openssl", :platform=>:jruby
7
- gem "appraisal"
7
+ gem "appraisal", :require=>nil
8
8
  gem "rake", :require=>nil
9
9
  gem "test-unit", "2.5.4", :group=>:test
10
10
  gem "test-unit-context", :group=>:test
11
11
  gem "mocha", ">= 0.13.0", :require=>nil, :group=>:test
12
12
  gem "simplecov", :require=>nil, :group=>:test
13
13
  gem "bcrypt-ruby", "~> 3.0.0", :require=>nil, :group=>:test
14
- gem "rails", :github=>"rails/rails"
15
- gem "journey", :github=>"rails/journey"
16
- gem "activerecord-deprecated_finders", :github=>"rails/activerecord-deprecated_finders", :require=>nil
14
+ gem "rails", :github=>"rails/rails", :branch=>"4-0-stable"
17
15
 
@@ -1,83 +1,71 @@
1
- GIT
2
- remote: git://github.com/rails/activerecord-deprecated_finders.git
3
- revision: 46aa99efc9c3c1db1d4f2e55373481212e6b2e26
4
- specs:
5
- activerecord-deprecated_finders (0.0.3)
6
-
7
- GIT
8
- remote: git://github.com/rails/journey.git
9
- revision: f0938d664286dc0b47f13092fa5d04a9225038d4
10
- specs:
11
- journey (2.0.0.20120723141804)
12
-
13
1
  GIT
14
2
  remote: git://github.com/rails/rails.git
15
- revision: 817e8fad5a84569729ae65fbd713274678c68d8f
3
+ revision: b83a7203b85df83026af2b1d8a9135c4d068d807
4
+ branch: 4-0-stable
16
5
  specs:
17
- actionmailer (4.0.0.beta1)
18
- actionpack (= 4.0.0.beta1)
19
- mail (~> 2.5.3)
20
- actionpack (4.0.0.beta1)
21
- activesupport (= 4.0.0.beta1)
6
+ actionmailer (4.0.0.rc1)
7
+ actionpack (= 4.0.0.rc1)
8
+ mail (~> 2.5.4)
9
+ actionpack (4.0.0.rc1)
10
+ activesupport (= 4.0.0.rc1)
22
11
  builder (~> 3.1.0)
23
12
  erubis (~> 2.7.0)
24
13
  rack (~> 1.5.2)
25
14
  rack-test (~> 0.6.2)
26
- activemodel (4.0.0.beta1)
27
- activesupport (= 4.0.0.beta1)
15
+ activemodel (4.0.0.rc1)
16
+ activesupport (= 4.0.0.rc1)
28
17
  builder (~> 3.1.0)
29
- activerecord (4.0.0.beta1)
30
- activemodel (= 4.0.0.beta1)
31
- activerecord-deprecated_finders (~> 0.0.3)
32
- activesupport (= 4.0.0.beta1)
33
- arel (~> 4.0.0.beta2)
34
- activesupport (4.0.0.beta1)
18
+ activerecord (4.0.0.rc1)
19
+ activemodel (= 4.0.0.rc1)
20
+ activerecord-deprecated_finders (~> 1.0.2)
21
+ activesupport (= 4.0.0.rc1)
22
+ arel (~> 4.0.0)
23
+ activesupport (4.0.0.rc1)
35
24
  i18n (~> 0.6, >= 0.6.4)
36
25
  minitest (~> 4.2)
37
26
  multi_json (~> 1.3)
38
27
  thread_safe (~> 0.1)
39
28
  tzinfo (~> 0.3.37)
40
- rails (4.0.0.beta1)
41
- actionmailer (= 4.0.0.beta1)
42
- actionpack (= 4.0.0.beta1)
43
- activerecord (= 4.0.0.beta1)
44
- activesupport (= 4.0.0.beta1)
29
+ rails (4.0.0.rc1)
30
+ actionmailer (= 4.0.0.rc1)
31
+ actionpack (= 4.0.0.rc1)
32
+ activerecord (= 4.0.0.rc1)
33
+ activesupport (= 4.0.0.rc1)
45
34
  bundler (>= 1.3.0, < 2.0)
46
- railties (= 4.0.0.beta1)
47
- sprockets-rails (~> 2.0.0.rc3)
48
- railties (4.0.0.beta1)
49
- actionpack (= 4.0.0.beta1)
50
- activesupport (= 4.0.0.beta1)
35
+ railties (= 4.0.0.rc1)
36
+ sprockets-rails (~> 2.0.0.rc4)
37
+ railties (4.0.0.rc1)
38
+ actionpack (= 4.0.0.rc1)
39
+ activesupport (= 4.0.0.rc1)
51
40
  rake (>= 0.8.7)
52
41
  thor (>= 0.18.1, < 2.0)
53
42
 
54
43
  GEM
55
44
  remote: https://rubygems.org/
56
45
  specs:
46
+ activerecord-deprecated_finders (1.0.2)
57
47
  appraisal (0.5.2)
58
48
  bundler
59
49
  rake
60
- arel (4.0.0.beta2)
61
- atomic (1.1.6-java)
62
- bcrypt-ruby (3.0.1)
50
+ arel (4.0.0)
51
+ atomic (1.1.9-java)
63
52
  bcrypt-ruby (3.0.1-java)
64
53
  bouncy-castle-java (1.5.0147)
65
54
  builder (3.1.4)
66
55
  erubis (2.7.0)
67
56
  hike (1.2.2)
68
57
  i18n (0.6.4)
69
- jruby-openssl (0.8.7)
58
+ jruby-openssl (0.8.8)
70
59
  bouncy-castle-java (>= 1.5.0147)
71
- mail (2.5.3)
72
- i18n (>= 0.4.0)
60
+ mail (2.5.4)
73
61
  mime-types (~> 1.16)
74
62
  treetop (~> 1.4.8)
75
63
  metaclass (0.0.1)
76
- mime-types (1.22)
77
- minitest (4.7.0)
64
+ mime-types (1.23)
65
+ minitest (4.7.4)
78
66
  mocha (0.13.3)
79
67
  metaclass (~> 0.0.1)
80
- multi_json (1.7.2)
68
+ multi_json (1.7.3)
81
69
  polyglot (0.3.3)
82
70
  rack (1.5.2)
83
71
  rack-test (0.6.2)
@@ -87,22 +75,22 @@ GEM
87
75
  multi_json (~> 1.0)
88
76
  simplecov-html (~> 0.7.1)
89
77
  simplecov-html (0.7.1)
90
- sprockets (2.9.2)
78
+ sprockets (2.9.3)
91
79
  hike (~> 1.2)
92
80
  multi_json (~> 1.0)
93
81
  rack (~> 1.0)
94
82
  tilt (~> 1.1, != 1.3.0)
95
- sprockets-rails (2.0.0.rc3)
83
+ sprockets-rails (2.0.0.rc4)
96
84
  actionpack (>= 3.0)
97
85
  activesupport (>= 3.0)
98
86
  sprockets (~> 2.8)
99
87
  test-unit (2.5.4)
100
- test-unit-context (0.3.0)
88
+ test-unit-context (0.3.1)
101
89
  test-unit (>= 2.4.0)
102
90
  thor (0.18.1)
103
91
  thread_safe (0.1.0)
104
92
  atomic
105
- tilt (1.3.6)
93
+ tilt (1.4.1)
106
94
  treetop (1.4.12)
107
95
  polyglot
108
96
  polyglot (>= 0.3.1)
@@ -113,10 +101,8 @@ PLATFORMS
113
101
 
114
102
  DEPENDENCIES
115
103
  activerecord
116
- activerecord-deprecated_finders!
117
104
  appraisal
118
105
  bcrypt-ruby (~> 3.0.0)
119
- journey!
120
106
  jruby-openssl
121
107
  mocha (>= 0.13.0)
122
108
  rails!
@@ -0,0 +1,2 @@
1
+ require 'arjdbc/db2'
2
+ require 'arjdbc/db2/as400'
@@ -1 +1 @@
1
- require 'arjdbc/db2'
1
+ require 'arjdbc/db2'
@@ -10,7 +10,11 @@ module Arel
10
10
  end
11
11
 
12
12
  def add_limit_offset(sql, o)
13
- @connection.replace_limit_offset! sql, limit_for(o.limit), o.offset && o.offset.value
13
+ if o.offset && o.offset.value && o.limit && o.limit.value
14
+ @connection.replace_limit_offset_for_arel! o, sql
15
+ else
16
+ @connection.replace_limit_offset! sql, limit_for(o.limit), o.offset && o.offset.value
17
+ end
14
18
  end
15
19
  end
16
20
  end
@@ -12,6 +12,7 @@ module Arel
12
12
 
13
13
  def limit_offset sql, o
14
14
  offset = o.offset || 0
15
+ offset = offset.expr unless(offset.nil? or offset == 0)
15
16
  bef = sql[7..-1]
16
17
  if limit = o.limit
17
18
  "SELECT LIMIT #{offset} #{limit_for(limit)} #{bef}"
@@ -3,21 +3,16 @@ require 'arel/visitors/compat'
3
3
  module Arel
4
4
  module Visitors
5
5
  class SQLServer < ToSql
6
- include ArJdbc::MSSQL::LimitHelpers::SqlServerReplaceLimitOffset
7
- include ArJdbc::MSSQL::LockHelpers::SqlServerAddLock
8
-
9
- def select_count? o
10
- sel = o.cores.length == 1 && o.cores.first
11
- projections = sel && sel.projections.length == 1 && sel.projections
12
- projections && Arel::Nodes::Count === projections.first
13
- end
14
6
 
15
7
  # Need to mimic the subquery logic in ARel 1.x for select count with limit
16
8
  # See arel/engines/sql/compilers/mssql_compiler.rb for details
17
- def visit_Arel_Nodes_SelectStatement o
18
- if !o.limit && o.offset
9
+ def visit_Arel_Nodes_SelectStatement(*args) # [o] AR <= 4.0 [o, a] on 4.1
10
+ o, a = args.first, args.last
11
+
12
+ if ! o.limit && o.offset
19
13
  raise ActiveRecord::ActiveRecordError, "You must specify :limit with :offset."
20
14
  end
15
+
21
16
  order = "ORDER BY #{o.orders.map { |x| visit x }.join(', ')}" unless o.orders.empty?
22
17
  if o.limit
23
18
  if select_count?(o)
@@ -25,10 +20,10 @@ module Arel
25
20
  sql = o.cores.map do |x|
26
21
  x = x.dup
27
22
  x.projections = [Arel::Nodes::SqlLiteral.new("*")]
28
- visit_Arel_Nodes_SelectCore x
23
+ do_visit_select_core(x, a)
29
24
  end.join
30
25
  else
31
- sql = o.cores.map { |x| visit_Arel_Nodes_SelectCore x }.join
26
+ sql = o.cores.map { |x| do_visit_select_core(x, a) }.join
32
27
  end
33
28
 
34
29
  order ||= "ORDER BY #{@connection.determine_order_clause(sql)}"
@@ -40,13 +35,60 @@ module Arel
40
35
  add_lock!(sql, :lock => o.lock && true)
41
36
  sql
42
37
  end
43
-
38
+
44
39
  # MS-SQL doesn't support "SELECT...FOR UPDATE". Instead, it needs
45
40
  # WITH(ROWLOCK,UPDLOCK) specified after each table in the FROM clause.
46
41
  #
47
42
  # So, we return nothing here and add the appropriate stuff using add_lock! above.
48
43
  def visit_Arel_Nodes_Lock o
44
+ # visit o.expr
45
+ end
46
+
47
+ def visit_Arel_Nodes_UpdateStatement o
48
+ if o.orders.any? && o.limit.nil?
49
+ o.limit = Nodes::Limit.new(9223372036854775807)
50
+ end
51
+ super
52
+ end
53
+
54
+ def visit_Arel_Nodes_Limit(o)
55
+ "TOP (#{visit o.expr})"
49
56
  end
57
+
58
+ def visit_Arel_Nodes_Ordering(o)
59
+ if o.respond_to?(:direction)
60
+ "#{visit o.expr} #{o.ascending? ? 'ASC' : 'DESC'}"
61
+ else
62
+ visit o.expr
63
+ end
64
+ end
65
+
66
+ def visit_Arel_Nodes_Bin(o)
67
+ "#{visit o.expr} COLLATE Latin1_General_CS_AS_WS"
68
+ end
69
+
70
+ private
71
+
72
+ def select_count? o
73
+ sel = o.cores.length == 1 && o.cores.first
74
+ projections = sel && sel.projections.length == 1 && sel.projections
75
+ projections && Arel::Nodes::Count === projections.first
76
+ end
77
+
78
+ if instance_method('visit_Arel_Nodes_SelectCore').arity == 1
79
+ def do_visit_select_core(x, a) # a = nil
80
+ visit_Arel_Nodes_SelectCore(x)
81
+ end
82
+ else # > AREL 4.0
83
+ def do_visit_select_core(x, a)
84
+ visit_Arel_Nodes_SelectCore(x, a)
85
+ end
86
+ end
87
+
88
+ include ArJdbc::MSSQL::LockHelpers::SqlServerAddLock
89
+
90
+ include ArJdbc::MSSQL::LimitHelpers::SqlServerReplaceLimitOffset
91
+
50
92
  end
51
93
 
52
94
  class SQLServer2000 < SQLServer
@@ -1,51 +1,40 @@
1
- require 'arjdbc/jdbc/serialized_attributes_helper'
1
+ ArJdbc.load_java_part :DB2
2
2
 
3
3
  module ArJdbc
4
4
  module DB2
5
-
6
- # TODO kind of standard AR configuration option for this would be nice :
7
- ADD_LOB_CALLBACK = true unless const_defined?(:ADD_LOB_CALLBACK) # :nodoc
8
5
 
9
- @@_lob_callback_added = nil
10
- def self.lob_callback_added? # :nodoc
11
- @@_lob_callback_added
12
- end
6
+ # This adapter doesn't support explain
7
+ # config.active_record.auto_explain_threshold_in_seconds should be commented before rails 4.0
13
8
 
14
- def self.lob_callback_added! # :nodoc
15
- @@_lob_callback_added = true
16
- end
17
-
18
- def explain(query, *binds)
19
- # TODO: Explain this! Do not remove !
20
- end
9
+ def self.extended(adapter); initialize!; end
21
10
 
22
- def self.extended(base)
23
- if ADD_LOB_CALLBACK && ! lob_callback_added?
24
- ActiveRecord::Base.class_eval do
25
- def after_save_with_db2_lob
26
- lob_columns = self.class.columns.select { |c| c.sql_type =~ /blob|clob/i }
27
- lob_columns.each do |column|
28
- value = ::ArJdbc::SerializedAttributesHelper.dump_column_value(self, column)
29
- next if value.nil? # already set NULL
30
-
31
- connection.write_large_object(
32
- column.type == :binary, column.name,
33
- self.class.table_name,
34
- self.class.primary_key,
35
- quote_value(id), value
36
- )
37
- end
11
+ @@_initialized = nil
12
+
13
+ def self.initialize!
14
+ return if @@_initialized; @@_initialized = true
15
+
16
+ require 'arjdbc/jdbc/serialized_attributes_helper'
17
+ ActiveRecord::Base.class_eval do
18
+ def after_save_with_db2_lob
19
+ lob_columns = self.class.columns.select { |c| c.sql_type =~ /blob|clob/i }
20
+ lob_columns.each do |column|
21
+ value = ::ArJdbc::SerializedAttributesHelper.dump_column_value(self, column)
22
+ next if value.nil? # already set NULL
23
+
24
+ self.class.connection.write_large_object(
25
+ column.type == :binary, column.name,
26
+ self.class.table_name,
27
+ self.class.primary_key,
28
+ self.class.connection.quote(id), value
29
+ )
38
30
  end
39
- alias after_save_with_db2zos_blob after_save_with_db2_lob # <-compat
40
31
  end
41
- # TODO this should be changed to :after_save_with_db2_lob :
42
- ActiveRecord::Base.after_save :after_save_with_db2zos_blob # <-compat
43
- lob_callback_added!
44
32
  end
33
+ ActiveRecord::Base.after_save :after_save_with_db2_lob
45
34
  end
46
35
 
47
36
  def self.column_selector
48
- [ /(db2|as400|zos)/i, lambda { |cfg, column| column.extend(::ArJdbc::DB2::Column) } ]
37
+ [ /(db2|zos)/i, lambda { |cfg, column| column.extend(::ArJdbc::DB2::Column) } ]
49
38
  end
50
39
 
51
40
  def self.jdbc_connection_class
@@ -54,10 +43,17 @@ module ArJdbc
54
43
 
55
44
  def self.arel2_visitors(config)
56
45
  require 'arel/visitors/db2'
57
- { 'db2' => ::Arel::Visitors::DB2, 'as400' => ::Arel::Visitors::DB2 }
46
+ { 'db2' => ::Arel::Visitors::DB2 }
47
+ end
48
+
49
+ def self.handle_lobs?; true; end
50
+
51
+ def configure_connection
52
+ schema = self.schema
53
+ set_schema(schema) if schema && schema != config[:username]
58
54
  end
59
55
 
60
- ADAPTER_NAME = 'DB2'
56
+ ADAPTER_NAME = 'DB2'.freeze
61
57
 
62
58
  def adapter_name
63
59
  ADAPTER_NAME
@@ -75,9 +71,10 @@ module ArJdbc
75
71
  :decimal => { :name => "decimal" },
76
72
  :char => { :name => "char" },
77
73
  :decfloat => { :name => "decfloat" },
78
- #:rowid => { :name => "rowid" }, # supported datatype on z/OS and i/5
79
- #:graphic => { :name => "graphic", :limit => 1 },
80
- #:vargraphic => { :name => "vargraphic", :limit => 1 },
74
+ :rowid => { :name => "rowid" }, # rowid is a supported datatype on z/OS and i/5
75
+ :serial => { :name => "serial" }, # supported datatype on Informix Dynamic Server
76
+ :graphic => { :name => "graphic", :limit => 1 },
77
+ :vargraphic => { :name => "vargraphic", :limit => 1 },
81
78
  :datetime => { :name => "timestamp" },
82
79
  :timestamp => { :name => "timestamp" },
83
80
  :time => { :name => "time" }
@@ -87,7 +84,17 @@ module ArJdbc
87
84
  super.merge(NATIVE_DATABASE_TYPES)
88
85
  end
89
86
 
87
+ @@emulate_booleans = true
88
+
89
+ # Boolean emulation can be disabled using :
90
+ #
91
+ # ArJdbc::DB2.emulate_booleans = false
92
+ #
93
+ def self.emulate_booleans; @@emulate_booleans; end
94
+ def self.emulate_booleans=(emulate); @@emulate_booleans = emulate; end
95
+
90
96
  module Column
97
+
91
98
  def type_cast(value)
92
99
  return nil if value.nil? || value == 'NULL' || value =~ /^\s*NULL\s*$/i
93
100
  case type
@@ -95,10 +102,10 @@ module ArJdbc
95
102
  when :integer then value.respond_to?(:to_i) ? value.to_i : (value ? 1 : 0)
96
103
  when :primary_key then value.respond_to?(:to_i) ? value.to_i : (value ? 1 : 0)
97
104
  when :float then value.to_f
98
- when :datetime then ArJdbc::DB2::Column.cast_to_date_or_time(value)
99
- when :date then ArJdbc::DB2::Column.cast_to_date_or_time(value)
100
- when :timestamp then ArJdbc::DB2::Column.cast_to_time(value)
101
- when :time then ArJdbc::DB2::Column.cast_to_time(value)
105
+ when :datetime then Column.cast_to_date_or_time(value)
106
+ when :date then Column.cast_to_date_or_time(value)
107
+ when :timestamp then Column.cast_to_time(value)
108
+ when :time then Column.cast_to_time(value)
102
109
  # TODO AS400 stores binary strings in EBCDIC (CCSID 65535), need to convert back to ASCII
103
110
  else
104
111
  super
@@ -146,21 +153,26 @@ module ArJdbc
146
153
  # http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.java.doc/doc/rjvjdata.html
147
154
  def simplified_type(field_type)
148
155
  case field_type
149
- when /^decimal\(1\)$/i then :boolean
150
- when /smallint|boolean/i then :boolean
156
+ when /^decimal\(1\)$/i then DB2.emulate_booleans ? :boolean : :integer
157
+ when /smallint/i then DB2.emulate_booleans ? :boolean : :integer
158
+ when /boolean/i then :boolean
151
159
  when /^real|double/i then :float
152
160
  when /int|serial/i then :integer
153
- when /numeric|decfloat/i then :decimal
161
+ # if a numeric column has no scale, lets treat it as an integer.
162
+ # The AS400 rpg guys do this ALOT since they have no integer datatype ...
163
+ when /decimal|numeric|decfloat/i
164
+ extract_scale(field_type) == 0 ? :integer : :decimal
154
165
  when /timestamp/i then :timestamp
155
166
  when /datetime/i then :datetime
156
167
  when /time/i then :time
157
168
  when /date/i then :date
158
- when /clob/i then :text
169
+ when /clob|text/i then :text
170
+ when /blob|binary/i then :binary
159
171
  when /for bit data/i then :binary
160
172
  when /xml/i then :xml
161
- #when /vargraphic/i then :vargraphic
162
- #when /graphic/i then :graphic
163
- #when /rowid/i then :rowid # rowid is a supported datatype on z/OS and i/5
173
+ when /^vargraphic/i then :vargraphic
174
+ when /^graphic/i then :graphic
175
+ when /rowid/i then :rowid # rowid is a supported datatype on z/OS and i/5
164
176
  else
165
177
  super
166
178
  end
@@ -179,10 +191,45 @@ module ArJdbc
179
191
  end
180
192
 
181
193
  class TableDefinition < ::ActiveRecord::ConnectionAdapters::TableDefinition # :nodoc:
194
+
182
195
  def xml(*args)
183
196
  options = args.extract_options!
184
197
  column(args[0], 'xml', options)
185
198
  end
199
+
200
+ # IBM DB adapter (MRI) compatibility :
201
+
202
+ def double(*args)
203
+ options = args.extract_options!
204
+ column(args[0], 'double', options)
205
+ end
206
+
207
+ def decfloat(*args)
208
+ options = args.extract_options!
209
+ column(args[0], 'decfloat', options)
210
+ end
211
+
212
+ def graphic(*args)
213
+ options = args.extract_options!
214
+ column(args[0], 'graphic', options)
215
+ end
216
+
217
+ def vargraphic(*args)
218
+ options = args.extract_options!
219
+ column(args[0], 'vargraphic', options)
220
+ end
221
+
222
+ def bigint(*args)
223
+ options = args.extract_options!
224
+ column(args[0], 'bigint', options)
225
+ end
226
+
227
+ def char(*args)
228
+ options = args.extract_options!
229
+ column(args[0], 'char', options)
230
+ end
231
+ # alias_method :character, :char
232
+
186
233
  end
187
234
 
188
235
  def table_definition(*args)
@@ -192,54 +239,15 @@ module ArJdbc
192
239
  def prefetch_primary_key?(table_name = nil)
193
240
  # TRUE if the table has no identity column
194
241
  names = table_name.upcase.split(".")
195
- if as400?
196
- sql = "SELECT 1 FROM SYSIBM.SQLPRIMARYKEYS WHERE "
197
- sql << "TABLE_SCHEM = '#{names.first}' AND " if names.size == 2
198
- sql << "TABLE_NAME = '#{names.last}'"
199
- else
200
- sql = "SELECT 1 FROM SYSCAT.COLUMNS WHERE IDENTITY = 'Y' "
201
- sql << "AND TABSCHEMA = '#{names.first}' " if names.size == 2
202
- sql << "AND TABNAME = '#{names.last}'"
203
- end
242
+ sql = "SELECT 1 FROM SYSCAT.COLUMNS WHERE IDENTITY = 'Y' "
243
+ sql << "AND TABSCHEMA = '#{names.first}' " if names.size == 2
244
+ sql << "AND TABNAME = '#{names.last}'"
204
245
  select_one(sql).nil?
205
246
  end
206
247
 
207
248
  def next_sequence_value(sequence_name)
208
249
  select_value("SELECT NEXT VALUE FOR #{sequence_name} FROM sysibm.sysdummy1")
209
250
  end
210
-
211
- # holy moly batman! all this to tell AS400 "yes i am sure"
212
- def execute_and_auto_confirm(sql)
213
- begin
214
- @connection.execute_update "call qsys.qcmdexc('QSYS/CHGJOB INQMSGRPY(*SYSRPYL)',0000000031.00000)"
215
- @connection.execute_update "call qsys.qcmdexc('ADDRPYLE SEQNBR(9876) MSGID(CPA32B2) RPY(''I'')',0000000045.00000)"
216
- rescue Exception => e
217
- raise "Could not call CHGJOB INQMSGRPY(*SYSRPYL) and ADDRPYLE SEQNBR(9876) MSGID(CPA32B2) RPY('I').\n" +
218
- "Do you have authority to do this?\n\n#{e.inspect}"
219
- end
220
-
221
- result = execute sql
222
-
223
- begin
224
- @connection.execute_update "call qsys.qcmdexc('QSYS/CHGJOB INQMSGRPY(*DFT)',0000000027.00000)"
225
- @connection.execute_update "call qsys.qcmdexc('RMVRPYLE SEQNBR(9876)',0000000021.00000)"
226
- rescue Exception => e
227
- raise "Could not call CHGJOB INQMSGRPY(*DFT) and RMVRPYLE SEQNBR(9876).\n" +
228
- "Do you have authority to do this?\n\n#{e.inspect}"
229
- end
230
- result
231
- end
232
-
233
- def _execute(sql, name = nil)
234
- if self.class.select?(sql)
235
- @connection.execute_query_raw(sql)
236
- elsif self.class.insert?(sql)
237
- (@connection.execute_insert(sql) || last_insert_id(sql)).to_i
238
- else
239
- @connection.execute_update(sql)
240
- end
241
- end
242
- private :_execute
243
251
 
244
252
  def last_insert_id(sql)
245
253
  table_name = sql.split(/\s/)[2]
@@ -344,13 +352,13 @@ module ArJdbc
344
352
  end
345
353
  when String, ActiveSupport::Multibyte::Chars
346
354
  if column_type == :binary && !(column.sql_type =~ /for bit data/i)
347
- if ArJdbc::DB2.lob_callback_added?
355
+ if ArJdbc::DB2.handle_lobs?
348
356
  "NULL" # '@@@IBMBINARY@@@'"
349
357
  else
350
358
  "BLOB('#{quote_string(value)}')"
351
359
  end
352
360
  elsif column && column.sql_type =~ /clob/ # :text
353
- if ArJdbc::DB2.lob_callback_added?
361
+ if ArJdbc::DB2.handle_lobs?
354
362
  "NULL" # "'@@@IBMTEXT@@@'"
355
363
  else
356
364
  "'#{quote_string(value)}'"
@@ -417,10 +425,11 @@ module ArJdbc
417
425
  end
418
426
  super
419
427
  end
420
-
428
+
421
429
  def replace_limit_offset!(sql, limit, offset)
422
430
  if limit
423
431
  limit = limit.to_i
432
+
424
433
  if !offset
425
434
  if limit == 1
426
435
  sql << " FETCH FIRST ROW ONLY"
@@ -428,27 +437,43 @@ module ArJdbc
428
437
  sql << " FETCH FIRST #{limit} ROWS ONLY"
429
438
  end
430
439
  else
431
- offset = offset.to_i
432
- sql.sub!(/SELECT/i, 'SELECT B.* FROM (SELECT A.*, row_number() over () AS internal$rownum FROM (SELECT')
433
- sql << ") A ) B WHERE B.internal$rownum > #{offset} AND B.internal$rownum <= #{limit + offset}"
440
+ replace_limit_offset_with_ordering( sql, limit, offset )
434
441
  end
442
+
435
443
  end
436
444
  sql
437
445
  end
446
+
447
+ def replace_limit_offset_for_arel!( query, sql )
448
+ replace_limit_offset_with_ordering sql, query.limit.value, query.offset && query.offset.value, query.orders
449
+ end
450
+
451
+ def replace_limit_offset_with_ordering( sql, limit, offset, orders=[] )
452
+ sql.sub!(/SELECT/i, "SELECT B.* FROM (SELECT A.*, row_number() over (#{build_ordering(orders)}) AS internal$rownum FROM (SELECT")
453
+ sql << ") A ) B WHERE B.internal$rownum > #{offset} AND B.internal$rownum <= #{limit + offset}"
454
+ sql
455
+ end
456
+ private :replace_limit_offset_with_ordering
438
457
 
439
- def reorg_table(table_name, name = nil)
440
- exec_update "call sysproc.admin_cmd ('REORG TABLE #{table_name}')", name, [] unless as400?
458
+ def build_ordering( orders )
459
+ return '' unless orders.size > 0
460
+ # need to remove the library/table names from the orderings because we are not really ordering by them anymore
461
+ # we are actually ordering by the results of a query where the result set has the same column names
462
+ orders = orders.map do |o|
463
+ # need to keep in mind that the order clause could be wrapped in a function
464
+ matches = /(?:\w+\(|\s)*(\S+)(?:\)|\s)*/.match(o)
465
+ o = o.gsub( matches[1], matches[1].split('.').last ) if matches
466
+ o
467
+ end
468
+ "ORDER BY " + orders.join( ', ')
441
469
  end
442
- private :reorg_table
470
+ private :build_ordering
443
471
 
472
+ # @deprecated seems not sued nor tested ?!
444
473
  def runstats_for_table(tablename, priority = 10)
445
474
  @connection.execute_update "call sysproc.admin_cmd('RUNSTATS ON TABLE #{tablename} WITH DISTRIBUTION AND DETAILED INDEXES ALL UTIL_IMPACT_PRIORITY #{priority}')"
446
475
  end
447
476
 
448
- def recreate_database(name, options = {})
449
- tables.each { |table| drop_table("#{db2_schema}.#{table}") }
450
- end
451
-
452
477
  def add_index(table_name, column_name, options = {})
453
478
  if ! zos? || ( table_name.to_s == ActiveRecord::Migrator.schema_migrations_table_name.to_s )
454
479
  column_name = column_name.to_s if column_name.is_a?(Symbol)
@@ -470,12 +495,8 @@ module ArJdbc
470
495
  # http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.admin.dbobj.doc/doc/t0020130.html
471
496
  # ...not supported on IBM i, so we raise in this case
472
497
  def rename_column(table_name, column_name, new_column_name) #:nodoc:
473
- if as400?
474
- raise NotImplementedError, "rename_column is not supported on IBM i"
475
- else
476
- execute "ALTER TABLE #{table_name} RENAME COLUMN #{column_name} TO #{new_column_name}"
477
- reorg_table(table_name, 'Rename Column')
478
- end
498
+ sql = "ALTER TABLE #{table_name} RENAME COLUMN #{column_name} TO #{new_column_name}"
499
+ execute_table_change(sql, table_name, 'Rename Column')
479
500
  end
480
501
 
481
502
  def change_column_null(table_name, column_name, null)
@@ -484,8 +505,7 @@ module ArJdbc
484
505
  else
485
506
  sql = "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET NOT NULL"
486
507
  end
487
- as400? ? execute_and_auto_confirm(sql) : execute(sql)
488
- reorg_table(table_name, 'Change Column')
508
+ execute_table_change(sql, table_name, 'Change Column')
489
509
  end
490
510
 
491
511
  def change_column_default(table_name, column_name, default)
@@ -494,15 +514,13 @@ module ArJdbc
494
514
  else
495
515
  sql = "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET WITH DEFAULT #{quote(default)}"
496
516
  end
497
- as400? ? execute_and_auto_confirm(sql) : execute(sql)
498
- reorg_table(table_name, 'Change Column')
517
+ execute_table_change(sql, table_name, 'Change Column')
499
518
  end
500
519
 
501
520
  def change_column(table_name, column_name, type, options = {})
502
521
  data_type = type_to_sql(type, options[:limit], options[:precision], options[:scale])
503
522
  sql = "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET DATA TYPE #{data_type}"
504
- as400? ? execute_and_auto_confirm(sql) : execute(sql)
505
- reorg_table(table_name, 'Change Column')
523
+ execute_table_change(sql, table_name, 'Change Column')
506
524
 
507
525
  if options.include?(:default) and options.include?(:null)
508
526
  # which to run first?
@@ -521,22 +539,23 @@ module ArJdbc
521
539
  end
522
540
 
523
541
  # http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.admin.dbobj.doc/doc/t0020132.html
524
- def remove_column(table_name, *column_names) #:nodoc:
525
- for column_name in column_names.flatten
542
+ def remove_column(table_name, *column_names) # :nodoc:
543
+ outcome = nil
544
+ column_names = column_names.flatten
545
+ for column_name in column_names
526
546
  sql = "ALTER TABLE #{table_name} DROP COLUMN #{column_name}"
527
- as400? ? execute_and_auto_confirm(sql) : execute(sql)
547
+ outcome = execute_table_change(sql, table_name, 'Remove Column')
528
548
  end
529
- reorg_table(table_name, 'Remove Column')
549
+ column_names.size == 1 ? outcome : nil
530
550
  end
531
551
 
532
552
  # http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.ref.doc/doc/r0000980.html
533
- def rename_table(name, new_name) #:nodoc:
534
- execute "RENAME TABLE #{name} TO #{new_name}"
535
- reorg_table(new_name, 'Rename Table')
553
+ def rename_table(name, new_name) # :nodoc:
554
+ execute_table_change("RENAME TABLE #{name} TO #{new_name}", new_name, 'Rename Table')
536
555
  end
537
556
 
538
557
  def tables
539
- @connection.tables(nil, db2_schema, nil, ["TABLE"])
558
+ @connection.tables(nil, schema)
540
559
  end
541
560
 
542
561
  # only record precision and scale for types that can set them via CREATE TABLE:
@@ -546,7 +565,7 @@ module ArJdbc
546
565
  HAVE_SCALE = %w(DECIMAL NUMERIC)
547
566
 
548
567
  def columns(table_name, name = nil)
549
- columns = @connection.columns_internal(table_name.to_s, nil, db2_schema)
568
+ columns = @connection.columns_internal(table_name.to_s, nil, schema) # catalog == nil
550
569
 
551
570
  if zos?
552
571
  # Remove the mighty db2_generated_rowid_for_lobs from the list of columns
@@ -564,135 +583,86 @@ module ArJdbc
564
583
  columns
565
584
  end
566
585
 
567
- def jdbc_columns(table_name, name = nil)
568
- columns(table_name, name)
569
- end
570
-
571
586
  def indexes(table_name, name = nil)
572
- @connection.indexes(table_name, name, db2_schema)
587
+ @connection.indexes(table_name, name, schema)
573
588
  end
574
589
 
575
- def add_quotes(name)
576
- return name unless name
577
- %Q{"#{name}"}
590
+ def recreate_database(name = nil, options = {})
591
+ drop_database(name)
578
592
  end
579
-
580
- def strip_quotes(str)
581
- return str unless str
582
- return str unless /^(["']).*\1$/ =~ str
583
- str[1..-2]
593
+
594
+ def drop_database(name = nil)
595
+ tables.each { |table| drop_table("#{table}") }
584
596
  end
585
-
586
- def expand_double_quotes(name)
587
- return name unless name && name['"']
588
- name.gsub(/"/,'""')
597
+
598
+ def execute_table_change(sql, table_name, name = nil)
599
+ outcome = execute(sql, name)
600
+ reorg_table(table_name, name)
601
+ outcome
589
602
  end
603
+ protected :execute_table_change
604
+
605
+ def reorg_table(table_name, name = nil)
606
+ exec_update "call sysproc.admin_cmd ('REORG TABLE #{table_name}')", name, []
607
+ end
608
+ private :reorg_table
609
+
610
+ # alias_method :execute_and_auto_confirm, :execute
590
611
 
591
- def structure_dump #:nodoc:
592
- schema_name = db2_schema.upcase if db2_schema.present?
593
- rs = @connection.connection.meta_data.getTables(nil, schema_name, nil, ["TABLE"].to_java(:string))
594
- definition = ''
595
- while rs.next
596
- tname = rs.getString(3)
597
- definition << "CREATE TABLE #{tname} (\n"
598
- rs2 = @connection.connection.meta_data.getColumns(nil,schema_name,tname,nil)
599
- first_col = true
600
- while rs2.next
601
- col_name = add_quotes(rs2.getString(4));
602
- default = ""
603
- d1 = rs2.getString(13)
604
- # IBM i (as400 toolbox driver) will return an empty string if there is no default
605
- if @config[:url] =~ /^jdbc:as400:/
606
- default = !d1.blank? ? " DEFAULT #{d1}" : ""
607
- else
608
- default = d1 ? " DEFAULT #{d1}" : ""
609
- end
610
-
611
- type = rs2.getString(6)
612
- col_precision = rs2.getString(7)
613
- col_scale = rs2.getString(9)
614
- col_size = ""
615
- if HAVE_SCALE.include?(type) and col_scale
616
- col_size = "(#{col_precision},#{col_scale})"
617
- elsif (HAVE_LIMIT + HAVE_PRECISION).include?(type) and col_precision
618
- col_size = "(#{col_precision})"
619
- end
620
- nulling = (rs2.getString(18) == 'NO' ? " NOT NULL" : "")
621
- autoincrement = (rs2.getString(23) == 'YES' ? " GENERATED ALWAYS AS IDENTITY" : "")
622
- create_col_string = add_quotes(expand_double_quotes(strip_quotes(col_name))) +
623
- " " +
624
- type +
625
- col_size +
626
- "" +
627
- nulling +
628
- default +
629
- autoincrement
630
- if !first_col
631
- create_col_string = ",\n #{create_col_string}"
632
- else
633
- create_col_string = " #{create_col_string}"
634
- end
635
-
636
- definition << create_col_string
637
-
638
- first_col = false
639
- end
640
- definition << ");\n\n"
641
-
642
- pkrs = @connection.connection.meta_data.getPrimaryKeys(nil,schema_name,tname)
643
- primary_key = {}
644
- while pkrs.next
645
- name = pkrs.getString(6)
646
- primary_key[name] = [] unless primary_key[name]
647
- primary_key[name] << pkrs.getString(4)
648
- end
649
- primary_key.each do |name, cols|
650
- definition << "ALTER TABLE #{tname}\n"
651
- definition << " ADD CONSTRAINT #{name}\n"
652
- definition << " PRIMARY KEY (#{cols.join(', ')});\n\n"
653
- end
612
+ def _execute(sql, name = nil)
613
+ if self.class.select?(sql)
614
+ @connection.execute_query_raw(sql)
615
+ elsif self.class.insert?(sql)
616
+ (@connection.execute_insert(sql) || last_insert_id(sql)).to_i
617
+ else
618
+ @connection.execute_update(sql)
654
619
  end
655
- definition
656
620
  end
621
+ private :_execute
657
622
 
658
623
  DRIVER_NAME = 'com.ibm.db2.jcc.DB2Driver'.freeze
659
624
 
660
625
  def zos?
626
+ @zos = nil unless defined? @zos
661
627
  return @zos unless @zos.nil?
662
628
  @zos =
663
- if url = @config[:url]
664
- !!( url =~ /^jdbc:db2j:net:/ && @config[:driver] == DRIVER_NAME )
629
+ if url = config[:url]
630
+ !!( url =~ /^jdbc:db2j:net:/ && config[:driver] == DRIVER_NAME )
665
631
  else
666
632
  nil
667
633
  end
668
634
  end
669
635
 
636
+ # @deprecated no longer used
670
637
  def as400?
671
- return @as400 unless @as400.nil?
672
- @as400 =
673
- if url = @config[:url]
674
- !!( url =~ /^jdbc:as400:/ )
675
- else
676
- nil
677
- end
638
+ false
678
639
  end
679
640
 
641
+ def schema
642
+ db2_schema
643
+ end
644
+
645
+ def schema=(schema)
646
+ set_schema(@db2_schema = schema) if db2_schema != schema
647
+ end
648
+
680
649
  private
681
650
 
651
+ def set_schema(schema)
652
+ execute("SET SCHEMA #{schema}")
653
+ end
654
+
682
655
  def db2_schema
683
- return @db2_schema unless @db2_schema.nil?
656
+ @db2_schema = false unless defined? @db2_schema
657
+ return @db2_schema if @db2_schema != false
684
658
  @db2_schema =
685
- if @config[:schema].present?
686
- @config[:schema]
687
- elsif @config[:jndi].present?
659
+ if config[:schema].present?
660
+ config[:schema]
661
+ elsif config[:jndi].present?
688
662
  nil # let JNDI worry about schema
689
- elsif as400?
690
- # AS400 implementation takes schema from library name (last part of URL)
691
- # jdbc:as400://localhost/schema;naming=system;libraries=lib1,lib2
692
- @config[:url].split('/').last.split(';').first.strip
693
663
  else
694
664
  # LUW implementation uses schema name of username by default
695
- @config[:username].presence || ENV['USER']
665
+ config[:username].presence || ENV['USER']
696
666
  end
697
667
  end
698
668