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.
- data/.gitignore +12 -11
- data/.travis.yml +36 -7
- data/Appraisals +3 -3
- data/Gemfile +1 -1
- data/Gemfile.lock +13 -6
- data/History.txt +64 -0
- data/README.md +8 -1
- data/Rakefile +3 -1
- data/gemfiles/rails23.gemfile +1 -1
- data/gemfiles/rails23.gemfile.lock +6 -5
- data/gemfiles/rails30.gemfile +1 -1
- data/gemfiles/rails30.gemfile.lock +7 -6
- data/gemfiles/rails31.gemfile +1 -1
- data/gemfiles/rails31.gemfile.lock +6 -5
- data/gemfiles/rails32.gemfile +1 -1
- data/gemfiles/rails32.gemfile.lock +6 -5
- data/gemfiles/rails40.gemfile +2 -4
- data/gemfiles/rails40.gemfile.lock +37 -51
- data/lib/active_record/connection_adapters/as400_adapter.rb +2 -0
- data/lib/active_record/connection_adapters/db2_adapter.rb +1 -1
- data/lib/arel/visitors/db2.rb +5 -1
- data/lib/arel/visitors/hsqldb.rb +1 -0
- data/lib/arel/visitors/sql_server.rb +55 -13
- data/lib/arjdbc/db2/adapter.rb +197 -227
- data/lib/arjdbc/db2/as400.rb +124 -0
- data/lib/arjdbc/db2/connection_methods.rb +20 -1
- data/lib/arjdbc/derby/adapter.rb +17 -85
- data/lib/arjdbc/derby/connection_methods.rb +2 -1
- data/lib/arjdbc/discover.rb +55 -47
- data/lib/arjdbc/h2/adapter.rb +52 -18
- data/lib/arjdbc/h2/connection_methods.rb +10 -2
- data/lib/arjdbc/hsqldb/adapter.rb +33 -9
- data/lib/arjdbc/hsqldb/connection_methods.rb +10 -2
- data/lib/arjdbc/informix.rb +2 -1
- data/lib/arjdbc/jdbc.rb +5 -1
- data/lib/arjdbc/jdbc/adapter.rb +167 -89
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/adapter_require.rb +46 -0
- data/lib/arjdbc/jdbc/base_ext.rb +25 -3
- data/lib/arjdbc/jdbc/callbacks.rb +9 -8
- data/lib/arjdbc/jdbc/column.rb +8 -20
- data/lib/arjdbc/jdbc/connection.rb +69 -80
- data/lib/arjdbc/jdbc/extension.rb +6 -8
- data/lib/arjdbc/jdbc/jdbc.rake +3 -141
- data/lib/arjdbc/jdbc/rake_tasks.rb +3 -10
- data/lib/arjdbc/mssql/adapter.rb +108 -34
- data/lib/arjdbc/mssql/connection_methods.rb +3 -1
- data/lib/arjdbc/mssql/limit_helpers.rb +3 -2
- data/lib/arjdbc/mssql/lock_helpers.rb +5 -1
- data/lib/arjdbc/mysql/adapter.rb +127 -70
- data/lib/arjdbc/mysql/connection_methods.rb +5 -2
- data/lib/arjdbc/oracle/adapter.rb +124 -94
- data/lib/arjdbc/oracle/connection_methods.rb +2 -1
- data/lib/arjdbc/postgresql/adapter.rb +99 -67
- data/lib/arjdbc/postgresql/column_cast.rb +3 -5
- data/lib/arjdbc/postgresql/connection_methods.rb +6 -6
- data/lib/arjdbc/railtie.rb +3 -1
- data/lib/arjdbc/sqlite3/adapter.rb +60 -43
- data/lib/arjdbc/sqlite3/connection_methods.rb +9 -9
- data/lib/arjdbc/sybase.rb +1 -1
- data/lib/arjdbc/tasks.rb +13 -0
- data/lib/arjdbc/tasks/database_tasks.rb +50 -0
- data/lib/arjdbc/tasks/databases.rake +89 -0
- data/lib/arjdbc/tasks/databases3.rake +203 -0
- data/lib/arjdbc/tasks/databases4.rake +39 -0
- data/lib/arjdbc/tasks/db2_database_tasks.rb +104 -0
- data/lib/arjdbc/tasks/derby_database_tasks.rb +95 -0
- data/lib/arjdbc/tasks/h2_database_tasks.rb +29 -0
- data/lib/arjdbc/tasks/hsqldb_database_tasks.rb +70 -0
- data/lib/arjdbc/tasks/jdbc_database_tasks.rb +122 -0
- data/lib/arjdbc/tasks/mssql_database_tasks.rb +36 -0
- data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +297 -0
- data/lib/arjdbc/tasks/oracle_database_tasks.rb +62 -0
- data/lib/arjdbc/version.rb +1 -1
- data/pom.xml +11 -12
- data/rails_generators/jdbc_generator.rb +1 -1
- data/rails_generators/templates/config/initializers/jdbc.rb +8 -5
- data/rails_generators/templates/lib/tasks/jdbc.rake +7 -4
- data/rakelib/02-test.rake +42 -15
- data/rakelib/compile.rake +29 -2
- data/rakelib/db.rake +2 -1
- data/rakelib/rails.rake +23 -6
- data/src/java/arjdbc/ArJdbcModule.java +175 -0
- data/src/java/arjdbc/db2/DB2Module.java +2 -1
- data/src/java/arjdbc/derby/DerbyModule.java +5 -24
- data/src/java/arjdbc/hsqldb/HSQLDBModule.java +3 -2
- data/src/java/arjdbc/jdbc/AdapterJavaService.java +3 -46
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +1001 -259
- data/src/java/arjdbc/mssql/MSSQLModule.java +2 -1
- data/src/java/arjdbc/mysql/MySQLModule.java +4 -3
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +12 -7
- data/src/java/arjdbc/oracle/OracleModule.java +2 -1
- data/src/java/arjdbc/sqlite3/SQLite3Module.java +2 -1
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +12 -0
- data/test/db/db2.rb +14 -7
- data/test/db/db2/rake_test.rb +82 -0
- data/test/db/db2/rake_test_data.sql +35 -0
- data/test/db/db2/simple_test.rb +20 -0
- data/test/db/db2/unit_test.rb +3 -1
- data/test/db/derby.rb +7 -5
- data/test/db/derby/rake_test.rb +96 -0
- data/test/db/derby/simple_test.rb +10 -2
- data/test/db/h2.rb +6 -8
- data/test/db/h2/identity_column_test.rb +35 -0
- data/test/db/h2/offset_test.rb +49 -0
- data/test/db/h2/rake_test.rb +98 -0
- data/test/db/h2/schema_dump_test.rb +5 -1
- data/test/db/hsqldb.rb +6 -10
- data/test/db/hsqldb/rake_test.rb +101 -0
- data/test/db/hsqldb/schema_dump_test.rb +5 -1
- data/test/db/hsqldb/simple_test.rb +8 -0
- data/test/db/jndi_config.rb +1 -3
- data/test/db/jndi_pooled_config.rb +1 -3
- data/test/db/mssql/limit_offset_test.rb +23 -14
- data/test/db/mssql/rake_test.rb +143 -0
- data/test/db/mysql/_rails_test_mysql.32.out +1069 -1252
- data/test/db/mysql/nonstandard_primary_key_test.rb +21 -24
- data/test/db/mysql/rake_test.rb +97 -0
- data/test/db/mysql/schema_dump_test.rb +11 -11
- data/test/db/mysql/simple_test.rb +52 -3
- data/test/db/mysql/statement_escaping_test.rb +46 -0
- data/test/db/oracle/rake_test.rb +100 -0
- data/test/db/oracle/simple_test.rb +48 -0
- data/test/db/postgres/_rails_test_postgres.32.out +998 -1370
- data/test/db/postgres/active_schema_unit_test.rb +68 -0
- data/test/db/postgres/connection_test.rb +10 -2
- data/test/db/postgres/data_types_test.rb +2 -2
- data/test/db/postgres/ltree_test.rb +6 -5
- data/test/db/postgres/native_types_test.rb +1 -5
- data/test/db/postgres/rake_test.rb +117 -0
- data/test/db/postgres/schema_dump_test.rb +9 -2
- data/test/db/postgres/schema_test.rb +4 -2
- data/test/db/postgres/simple_test.rb +57 -16
- data/test/db/sqlite3.rb +3 -10
- data/test/db/sqlite3/_rails_test_sqlite3.32.out +1070 -1298
- data/test/db/sqlite3/rake_test.rb +71 -0
- data/test/db/sqlite3/simple_test.rb +9 -9
- data/test/has_many_through.rb +4 -1
- data/test/jdbc/db2.rb +14 -1
- data/test/jdbc_column_test.rb +23 -0
- data/test/{generic_jdbc_connection_test.rb → jdbc_connection_test.rb} +22 -17
- data/test/jndi_callbacks_test.rb +26 -28
- data/test/jndi_test.rb +7 -16
- data/test/models/data_types.rb +2 -1
- data/test/models/thing.rb +1 -0
- data/test/rails/mysql.rb +13 -0
- data/test/rails/sqlite3/version.rb +6 -0
- data/test/rails_stub.rb +31 -0
- data/test/rake_test_support.rb +298 -0
- data/test/serialize.rb +2 -4
- data/test/{helper.rb → shared_helper.rb} +0 -0
- data/test/simple.rb +167 -93
- data/test/test_helper.rb +52 -16
- metadata +388 -354
- data/lib/pg.rb +0 -26
- data/test/abstract_db_create.rb +0 -139
- data/test/activerecord/connection_adapters/type_conversion_test.rb +0 -36
- data/test/db/mssql/db_create_test.rb +0 -29
- data/test/db/mysql/db_create_test.rb +0 -33
- data/test/db/postgres/db_create_test.rb +0 -44
- data/test/db/postgres/db_drop_test.rb +0 -17
data/gemfiles/rails40.gemfile
CHANGED
|
@@ -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:
|
|
3
|
+
revision: b83a7203b85df83026af2b1d8a9135c4d068d807
|
|
4
|
+
branch: 4-0-stable
|
|
16
5
|
specs:
|
|
17
|
-
actionmailer (4.0.0.
|
|
18
|
-
actionpack (= 4.0.0.
|
|
19
|
-
mail (~> 2.5.
|
|
20
|
-
actionpack (4.0.0.
|
|
21
|
-
activesupport (= 4.0.0.
|
|
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.
|
|
27
|
-
activesupport (= 4.0.0.
|
|
15
|
+
activemodel (4.0.0.rc1)
|
|
16
|
+
activesupport (= 4.0.0.rc1)
|
|
28
17
|
builder (~> 3.1.0)
|
|
29
|
-
activerecord (4.0.0.
|
|
30
|
-
activemodel (= 4.0.0.
|
|
31
|
-
activerecord-deprecated_finders (~>
|
|
32
|
-
activesupport (= 4.0.0.
|
|
33
|
-
arel (~> 4.0.0
|
|
34
|
-
activesupport (4.0.0.
|
|
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.
|
|
41
|
-
actionmailer (= 4.0.0.
|
|
42
|
-
actionpack (= 4.0.0.
|
|
43
|
-
activerecord (= 4.0.0.
|
|
44
|
-
activesupport (= 4.0.0.
|
|
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.
|
|
47
|
-
sprockets-rails (~> 2.0.0.
|
|
48
|
-
railties (4.0.0.
|
|
49
|
-
actionpack (= 4.0.0.
|
|
50
|
-
activesupport (= 4.0.0.
|
|
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
|
|
61
|
-
atomic (1.1.
|
|
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.
|
|
58
|
+
jruby-openssl (0.8.8)
|
|
70
59
|
bouncy-castle-java (>= 1.5.0147)
|
|
71
|
-
mail (2.5.
|
|
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.
|
|
77
|
-
minitest (4.7.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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!
|
|
@@ -1 +1 @@
|
|
|
1
|
-
require 'arjdbc/db2'
|
|
1
|
+
require 'arjdbc/db2'
|
data/lib/arel/visitors/db2.rb
CHANGED
|
@@ -10,7 +10,11 @@ module Arel
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def add_limit_offset(sql, o)
|
|
13
|
-
|
|
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
|
data/lib/arel/visitors/hsqldb.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
23
|
+
do_visit_select_core(x, a)
|
|
29
24
|
end.join
|
|
30
25
|
else
|
|
31
|
-
sql = o.cores.map { |x|
|
|
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
|
data/lib/arjdbc/db2/adapter.rb
CHANGED
|
@@ -1,51 +1,40 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
10
|
-
|
|
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.
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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|
|
|
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'
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
|
99
|
-
when :date then
|
|
100
|
-
when :timestamp then
|
|
101
|
-
when :time then
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
|
440
|
-
|
|
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 :
|
|
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
|
-
|
|
474
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
|
525
|
-
|
|
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
|
-
|
|
547
|
+
outcome = execute_table_change(sql, table_name, 'Remove Column')
|
|
528
548
|
end
|
|
529
|
-
|
|
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)
|
|
534
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
587
|
+
@connection.indexes(table_name, name, schema)
|
|
573
588
|
end
|
|
574
589
|
|
|
575
|
-
def
|
|
576
|
-
|
|
577
|
-
%Q{"#{name}"}
|
|
590
|
+
def recreate_database(name = nil, options = {})
|
|
591
|
+
drop_database(name)
|
|
578
592
|
end
|
|
579
|
-
|
|
580
|
-
def
|
|
581
|
-
|
|
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
|
|
587
|
-
|
|
588
|
-
name
|
|
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
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
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 =
|
|
664
|
-
!!( url =~ /^jdbc:db2j:net:/ &&
|
|
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
|
-
|
|
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
|
-
|
|
656
|
+
@db2_schema = false unless defined? @db2_schema
|
|
657
|
+
return @db2_schema if @db2_schema != false
|
|
684
658
|
@db2_schema =
|
|
685
|
-
if
|
|
686
|
-
|
|
687
|
-
elsif
|
|
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
|
-
|
|
665
|
+
config[:username].presence || ENV['USER']
|
|
696
666
|
end
|
|
697
667
|
end
|
|
698
668
|
|