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

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 (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