activerecord-jdbc-adapter 1.2.5 → 1.2.8
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.travis.yml +5 -1
- data/Appraisals +5 -5
- data/Gemfile +9 -1
- data/Gemfile.lock +44 -10
- data/History.txt +126 -2
- data/README.md +246 -0
- data/Rakefile +34 -25
- data/activerecord-jdbc-adapter.gemspec +1 -1
- data/gemfiles/rails23.gemfile +5 -3
- data/gemfiles/rails23.gemfile.lock +26 -18
- data/gemfiles/rails30.gemfile +4 -2
- data/gemfiles/rails30.gemfile.lock +16 -8
- data/gemfiles/rails31.gemfile +4 -2
- data/gemfiles/rails31.gemfile.lock +16 -9
- data/gemfiles/rails32.gemfile +4 -2
- data/gemfiles/rails32.gemfile.lock +15 -8
- data/lib/active_record/connection_adapters/db2_adapter.rb +1 -0
- data/lib/arel/visitors/sql_server.rb +3 -0
- data/lib/arjdbc.rb +3 -5
- data/lib/arjdbc/db2.rb +1 -0
- data/lib/arjdbc/db2/adapter.rb +302 -196
- data/lib/arjdbc/db2/connection_methods.rb +18 -0
- data/lib/arjdbc/derby/active_record_patch.rb +12 -0
- data/lib/arjdbc/derby/adapter.rb +180 -158
- data/lib/arjdbc/derby/connection_methods.rb +5 -1
- data/lib/arjdbc/firebird/adapter.rb +27 -19
- data/lib/arjdbc/h2/adapter.rb +162 -7
- data/lib/arjdbc/h2/connection_methods.rb +5 -1
- data/lib/arjdbc/hsqldb.rb +1 -1
- data/lib/arjdbc/hsqldb/adapter.rb +96 -61
- data/lib/arjdbc/hsqldb/connection_methods.rb +5 -1
- data/lib/arjdbc/hsqldb/explain_support.rb +35 -0
- data/lib/arjdbc/informix/adapter.rb +56 -55
- data/lib/arjdbc/jdbc/adapter.rb +173 -86
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/column.rb +28 -23
- data/lib/arjdbc/jdbc/connection.rb +10 -6
- data/lib/arjdbc/jdbc/driver.rb +13 -5
- data/lib/arjdbc/jdbc/serialized_attributes_helper.rb +21 -0
- data/lib/arjdbc/mssql.rb +1 -1
- data/lib/arjdbc/mssql/adapter.rb +51 -53
- data/lib/arjdbc/mssql/connection_methods.rb +8 -1
- data/lib/arjdbc/mysql.rb +1 -1
- data/lib/arjdbc/mysql/adapter.rb +186 -150
- data/lib/arjdbc/mysql/connection_methods.rb +9 -9
- data/lib/arjdbc/mysql/explain_support.rb +85 -0
- data/lib/arjdbc/oracle.rb +1 -1
- data/lib/arjdbc/oracle/adapter.rb +232 -125
- data/lib/arjdbc/oracle/connection_methods.rb +2 -2
- data/lib/arjdbc/postgresql.rb +1 -1
- data/lib/arjdbc/postgresql/adapter.rb +134 -86
- data/lib/arjdbc/postgresql/connection_methods.rb +6 -4
- data/lib/arjdbc/postgresql/explain_support.rb +55 -0
- data/lib/arjdbc/sqlite3.rb +1 -1
- data/lib/arjdbc/sqlite3/adapter.rb +176 -108
- data/lib/arjdbc/sqlite3/connection_methods.rb +5 -5
- data/lib/arjdbc/sqlite3/explain_support.rb +32 -0
- data/lib/arjdbc/sybase/adapter.rb +7 -6
- data/lib/arjdbc/version.rb +1 -1
- data/pom.xml +1 -1
- data/rakelib/02-test.rake +9 -11
- data/rakelib/rails.rake +18 -10
- data/src/java/arjdbc/db2/DB2Module.java +70 -0
- data/src/java/arjdbc/derby/DerbyModule.java +24 -5
- data/src/java/arjdbc/hsqldb/HSQLDBModule.java +66 -0
- data/src/java/arjdbc/jdbc/AdapterJavaService.java +14 -7
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +111 -89
- data/src/java/arjdbc/mysql/MySQLModule.java +79 -70
- data/src/java/arjdbc/oracle/OracleModule.java +74 -0
- data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +5 -10
- data/src/java/arjdbc/sqlite3/SQLite3Module.java +77 -0
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +127 -0
- data/src/java/arjdbc/sqlite3/Sqlite3RubyJdbcConnection.java +25 -111
- data/src/java/arjdbc/util/QuotingUtils.java +104 -0
- data/test/abstract_db_create.rb +6 -6
- data/test/activerecord/connection_adapters/type_conversion_test.rb +2 -2
- data/test/assets/flowers.jpg +0 -0
- data/test/binary.rb +67 -0
- data/test/db/db2.rb +30 -7
- data/test/db/jdbc.rb +4 -2
- data/test/db/oracle.rb +18 -27
- data/test/db2_binary_test.rb +6 -0
- data/test/db2_serialize_test.rb +6 -0
- data/test/db2_simple_test.rb +20 -25
- data/test/db2_test.rb +71 -0
- data/test/derby_binary_test.rb +6 -0
- data/test/derby_migration_test.rb +42 -35
- data/test/derby_reset_column_information_test.rb +1 -0
- data/test/derby_row_locking_test.rb +17 -0
- data/test/derby_schema_dump_test.rb +9 -0
- data/test/derby_serialize_test.rb +6 -0
- data/test/derby_simple_test.rb +59 -17
- data/test/generic_jdbc_connection_test.rb +112 -5
- data/test/h2_binary_test.rb +6 -0
- data/test/h2_change_column_test.rb +1 -1
- data/test/h2_schema_dump_test.rb +25 -0
- data/test/h2_serialize_test.rb +6 -0
- data/test/h2_simple_test.rb +23 -9
- data/test/has_many_through.rb +18 -4
- data/test/hsqldb_binary_test.rb +6 -0
- data/test/hsqldb_schema_dump_test.rb +15 -0
- data/test/hsqldb_serialize_test.rb +6 -0
- data/test/hsqldb_simple_test.rb +1 -0
- data/test/informix_simple_test.rb +1 -1
- data/test/jdbc/db2.rb +23 -0
- data/test/jdbc/oracle.rb +23 -0
- data/test/jdbc_common.rb +3 -110
- data/test/jndi_callbacks_test.rb +0 -2
- data/test/jndi_test.rb +2 -0
- data/test/models/binary.rb +18 -0
- data/test/models/custom_pk_name.rb +1 -0
- data/test/models/data_types.rb +11 -2
- data/test/models/entry.rb +1 -1
- data/test/models/string_id.rb +2 -2
- data/test/models/thing.rb +1 -1
- data/test/models/topic.rb +32 -0
- data/test/mssql_legacy_types_test.rb +1 -1
- data/test/mssql_limit_offset_test.rb +13 -3
- data/test/mssql_serialize_test.rb +6 -0
- data/test/mysql_binary_test.rb +6 -0
- data/test/mysql_schema_dump_test.rb +220 -0
- data/test/mysql_serialize_test.rb +6 -0
- data/test/mysql_simple_test.rb +22 -2
- data/test/mysql_test.rb +93 -0
- data/test/oracle_binary_test.rb +6 -0
- data/test/oracle_limit_test.rb +2 -1
- data/test/oracle_serialize_test.rb +6 -0
- data/test/oracle_simple_test.rb +61 -0
- data/test/oracle_specific_test.rb +77 -26
- data/test/postgres_binary_test.rb +6 -0
- data/test/postgres_native_type_mapping_test.rb +12 -11
- data/test/postgres_nonseq_pkey_test.rb +1 -0
- data/test/postgres_reserved_test.rb +1 -0
- data/test/postgres_reset_column_information_test.rb +1 -0
- data/test/postgres_row_locking_test.rb +21 -0
- data/test/postgres_schema_dump_test.rb +88 -0
- data/test/postgres_schema_search_path_test.rb +1 -0
- data/test/postgres_simple_test.rb +62 -89
- data/test/postgres_table_alias_length_test.rb +1 -0
- data/test/postgres_test.rb +31 -0
- data/test/postgres_type_conversion_test.rb +16 -16
- data/test/row_locking.rb +69 -64
- data/test/schema_dump.rb +168 -0
- data/test/serialize.rb +277 -0
- data/test/simple.rb +326 -122
- data/test/sqlite3_serialize_test.rb +6 -0
- data/test/sqlite3_simple_test.rb +51 -84
- data/test/sqlite3_type_conversion_test.rb +101 -0
- data/test/test_helper.rb +224 -0
- metadata +325 -366
- data/README.rdoc +0 -214
- data/test/db/logger.rb +0 -3
- data/test/derby_multibyte_test.rb +0 -11
- data/test/mysql_info_test.rb +0 -123
data/Rakefile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'rake/testtask'
|
2
2
|
require 'rake/clean'
|
3
|
-
CLEAN.include 'derby*', 'test.db.*','test/reports', 'test.sqlite3','lib/**/*.jar','manifest.mf', '*.log'
|
3
|
+
CLEAN.include 'derby*', 'test.db.*','test/reports', 'test.sqlite3','lib/**/*.jar','manifest.mf', '*.log', 'target/*'
|
4
4
|
|
5
5
|
require 'bundler/gem_helper'
|
6
6
|
Bundler::GemHelper.install_tasks
|
@@ -14,46 +14,55 @@ task :default => [:jar, :test]
|
|
14
14
|
task :build => :jar
|
15
15
|
task :install => :jar
|
16
16
|
|
17
|
-
ADAPTERS = %w[derby h2 hsqldb mssql mysql postgresql sqlite3].map {|a| "activerecord-jdbc#{a}-adapter" }
|
18
|
-
DRIVERS = %w[derby h2 hsqldb jtds mysql postgres sqlite3].map {|a| "jdbc-#{a}" }
|
17
|
+
ADAPTERS = %w[derby h2 hsqldb mssql mysql postgresql sqlite3].map { |a| "activerecord-jdbc#{a}-adapter" }
|
18
|
+
DRIVERS = %w[derby h2 hsqldb jtds mysql postgres sqlite3].map { |a| "jdbc-#{a}" }
|
19
|
+
TARGETS = ( ADAPTERS + DRIVERS )
|
19
20
|
|
20
21
|
def rake(*args)
|
21
22
|
ruby "-S", "rake", *args
|
22
23
|
end
|
23
24
|
|
24
|
-
|
25
|
-
namespace
|
26
|
-
|
25
|
+
TARGETS.each do |target|
|
26
|
+
namespace target do
|
27
27
|
task :build do
|
28
|
-
Dir.chdir(
|
29
|
-
|
30
|
-
end
|
31
|
-
cp FileList["#{adapter}/pkg/#{adapter}-*.gem"], "pkg"
|
28
|
+
Dir.chdir(target) { rake "build" }
|
29
|
+
cp FileList["#{target}/pkg/#{target}-*.gem"], "pkg"
|
32
30
|
end
|
33
|
-
|
34
|
-
# bundler handles install => build itself
|
35
31
|
task :install do
|
36
|
-
Dir.chdir(
|
37
|
-
rake "install"
|
38
|
-
end
|
32
|
+
Dir.chdir(target) { rake "install" }
|
39
33
|
end
|
40
|
-
|
41
34
|
task :release do
|
42
|
-
Dir.chdir(
|
43
|
-
rake "release"
|
44
|
-
end
|
35
|
+
Dir.chdir(target) { rake "release" }
|
45
36
|
end
|
46
37
|
end
|
47
38
|
end
|
48
39
|
|
49
|
-
|
50
|
-
|
40
|
+
# DRIVERS
|
41
|
+
|
42
|
+
desc "Build drivers"
|
43
|
+
task "drivers:build" => DRIVERS.map { |name| "#{name}:build" }
|
44
|
+
|
45
|
+
desc "Install drivers"
|
46
|
+
task "drivers:install" => DRIVERS.map { |name| "#{name}:install" }
|
47
|
+
|
48
|
+
desc "Release drivers"
|
49
|
+
task "drivers:release" => DRIVERS.map { |name| "#{name}:release" }
|
50
|
+
|
51
|
+
# ADAPTERS
|
52
|
+
|
53
|
+
desc "Build adapters"
|
54
|
+
task "adapters:build" => [ 'build' ] + ADAPTERS.map { |name| "#{name}:build" }
|
55
|
+
|
56
|
+
desc "Install adapters"
|
57
|
+
task "adapters:install" => [ 'install' ] + ADAPTERS.map { |name| "#{name}:install" }
|
58
|
+
|
59
|
+
desc "Release adapters"
|
60
|
+
task "adapters:release" => [ 'release' ] + ADAPTERS.map { |name| "#{name}:release" }
|
51
61
|
|
52
|
-
|
53
|
-
task "all:install" => ["install", *ADAPTERS.map { |f| "#{f}:install" }]
|
62
|
+
# ALL
|
54
63
|
|
55
|
-
|
56
|
-
task "all:
|
64
|
+
task "all:build" => [ 'build' ] + TARGETS.map { |name| "#{name}:build" }
|
65
|
+
task "all:install" => [ 'install' ] + TARGETS.map { |name| "#{name}:install" }
|
57
66
|
|
58
67
|
task :filelist do
|
59
68
|
puts FileList['pkg/**/*'].inspect
|
@@ -18,7 +18,7 @@ virtually any JDBC-compliant database with your JRuby on Rails application.}
|
|
18
18
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f) }
|
20
20
|
s.require_paths = ["lib"]
|
21
|
-
s.rdoc_options = ["--main", "README.
|
21
|
+
s.rdoc_options = ["--main", "README.md", "-SHN", "-f", "darkfish"]
|
22
22
|
s.rubyforge_project = %q{jruby-extras}
|
23
23
|
end
|
24
24
|
|
data/gemfiles/rails23.gemfile
CHANGED
@@ -6,7 +6,9 @@ gem "jruby-openssl", :platform=>:jruby
|
|
6
6
|
gem "appraisal"
|
7
7
|
gem "rake", :require=>nil
|
8
8
|
gem "test-unit", :group=>:test
|
9
|
-
gem "mocha", :group=>:test
|
10
|
-
gem "
|
11
|
-
gem "
|
9
|
+
gem "mocha", :require=>nil, :group=>:test
|
10
|
+
gem "simplecov", :require=>nil, :group=>:test
|
11
|
+
gem "bcrypt-ruby", "~> 3.0.0", :require=>nil, :group=>:test
|
12
|
+
gem "activerecord", "~> 2.3.16"
|
13
|
+
gem "rails", "~> 2.3.16"
|
12
14
|
|
@@ -1,44 +1,52 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
-
actionmailer (2.3.
|
5
|
-
actionpack (= 2.3.
|
6
|
-
actionpack (2.3.
|
7
|
-
activesupport (= 2.3.
|
4
|
+
actionmailer (2.3.16)
|
5
|
+
actionpack (= 2.3.16)
|
6
|
+
actionpack (2.3.16)
|
7
|
+
activesupport (= 2.3.16)
|
8
8
|
rack (~> 1.1.0)
|
9
|
-
activerecord (2.3.
|
10
|
-
activesupport (= 2.3.
|
11
|
-
activeresource (2.3.
|
12
|
-
activesupport (= 2.3.
|
13
|
-
activesupport (2.3.
|
9
|
+
activerecord (2.3.16)
|
10
|
+
activesupport (= 2.3.16)
|
11
|
+
activeresource (2.3.16)
|
12
|
+
activesupport (= 2.3.16)
|
13
|
+
activesupport (2.3.16)
|
14
14
|
appraisal (0.5.1)
|
15
15
|
bundler
|
16
16
|
rake
|
17
|
+
bcrypt-ruby (3.0.1-java)
|
17
18
|
bouncy-castle-java (1.5.0146.1)
|
18
19
|
jruby-openssl (0.7.7)
|
19
20
|
bouncy-castle-java (>= 1.5.0146.1)
|
20
21
|
metaclass (0.0.1)
|
21
22
|
mocha (0.11.4)
|
22
23
|
metaclass (~> 0.0.1)
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
24
|
+
multi_json (1.5.0)
|
25
|
+
rack (1.1.5)
|
26
|
+
rails (2.3.16)
|
27
|
+
actionmailer (= 2.3.16)
|
28
|
+
actionpack (= 2.3.16)
|
29
|
+
activerecord (= 2.3.16)
|
30
|
+
activeresource (= 2.3.16)
|
31
|
+
activesupport (= 2.3.16)
|
30
32
|
rake (>= 0.8.3)
|
31
33
|
rake (0.9.2.2)
|
34
|
+
simplecov (0.7.1)
|
35
|
+
multi_json (~> 1.0)
|
36
|
+
simplecov-html (~> 0.7.1)
|
37
|
+
simplecov-html (0.7.1)
|
32
38
|
test-unit (2.5.3)
|
33
39
|
|
34
40
|
PLATFORMS
|
35
41
|
java
|
36
42
|
|
37
43
|
DEPENDENCIES
|
38
|
-
activerecord (~> 2.3.
|
44
|
+
activerecord (~> 2.3.16)
|
39
45
|
appraisal
|
46
|
+
bcrypt-ruby (~> 3.0.0)
|
40
47
|
jruby-openssl
|
41
48
|
mocha
|
42
|
-
rails (~> 2.3.
|
49
|
+
rails (~> 2.3.16)
|
43
50
|
rake
|
51
|
+
simplecov
|
44
52
|
test-unit
|
data/gemfiles/rails30.gemfile
CHANGED
@@ -6,6 +6,8 @@ gem "jruby-openssl", :platform=>:jruby
|
|
6
6
|
gem "appraisal"
|
7
7
|
gem "rake", :require=>nil
|
8
8
|
gem "test-unit", :group=>:test
|
9
|
-
gem "mocha", :group=>:test
|
10
|
-
gem "
|
9
|
+
gem "mocha", :require=>nil, :group=>:test
|
10
|
+
gem "simplecov", :require=>nil, :group=>:test
|
11
|
+
gem "bcrypt-ruby", "~> 3.0.0", :require=>nil, :group=>:test
|
12
|
+
gem "activerecord", "~> 3.0.20"
|
11
13
|
|
@@ -1,20 +1,21 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
-
activemodel (3.0.
|
5
|
-
activesupport (= 3.0.
|
4
|
+
activemodel (3.0.20)
|
5
|
+
activesupport (= 3.0.20)
|
6
6
|
builder (~> 2.1.2)
|
7
7
|
i18n (~> 0.5.0)
|
8
|
-
activerecord (3.0.
|
9
|
-
activemodel (= 3.0.
|
10
|
-
activesupport (= 3.0.
|
8
|
+
activerecord (3.0.20)
|
9
|
+
activemodel (= 3.0.20)
|
10
|
+
activesupport (= 3.0.20)
|
11
11
|
arel (~> 2.0.10)
|
12
12
|
tzinfo (~> 0.3.23)
|
13
|
-
activesupport (3.0.
|
13
|
+
activesupport (3.0.20)
|
14
14
|
appraisal (0.5.1)
|
15
15
|
bundler
|
16
16
|
rake
|
17
17
|
arel (2.0.10)
|
18
|
+
bcrypt-ruby (3.0.1-java)
|
18
19
|
bouncy-castle-java (1.5.0146.1)
|
19
20
|
builder (2.1.2)
|
20
21
|
i18n (0.5.0)
|
@@ -23,17 +24,24 @@ GEM
|
|
23
24
|
metaclass (0.0.1)
|
24
25
|
mocha (0.11.4)
|
25
26
|
metaclass (~> 0.0.1)
|
27
|
+
multi_json (1.5.0)
|
26
28
|
rake (10.0.3)
|
29
|
+
simplecov (0.7.1)
|
30
|
+
multi_json (~> 1.0)
|
31
|
+
simplecov-html (~> 0.7.1)
|
32
|
+
simplecov-html (0.7.1)
|
27
33
|
test-unit (2.5.3)
|
28
|
-
tzinfo (0.3.
|
34
|
+
tzinfo (0.3.35)
|
29
35
|
|
30
36
|
PLATFORMS
|
31
37
|
java
|
32
38
|
|
33
39
|
DEPENDENCIES
|
34
|
-
activerecord (~> 3.0.
|
40
|
+
activerecord (~> 3.0.20)
|
35
41
|
appraisal
|
42
|
+
bcrypt-ruby (~> 3.0.0)
|
36
43
|
jruby-openssl
|
37
44
|
mocha
|
38
45
|
rake
|
46
|
+
simplecov
|
39
47
|
test-unit
|
data/gemfiles/rails31.gemfile
CHANGED
@@ -6,6 +6,8 @@ gem "jruby-openssl", :platform=>:jruby
|
|
6
6
|
gem "appraisal"
|
7
7
|
gem "rake", :require=>nil
|
8
8
|
gem "test-unit", :group=>:test
|
9
|
-
gem "mocha", :group=>:test
|
10
|
-
gem "
|
9
|
+
gem "mocha", :require=>nil, :group=>:test
|
10
|
+
gem "simplecov", :require=>nil, :group=>:test
|
11
|
+
gem "bcrypt-ruby", "~> 3.0.0", :require=>nil, :group=>:test
|
12
|
+
gem "activerecord", "~> 3.1.10"
|
11
13
|
|
@@ -1,23 +1,24 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
-
activemodel (3.1.
|
5
|
-
activesupport (= 3.1.
|
4
|
+
activemodel (3.1.10)
|
5
|
+
activesupport (= 3.1.10)
|
6
6
|
builder (~> 3.0.0)
|
7
7
|
i18n (~> 0.6)
|
8
|
-
activerecord (3.1.
|
9
|
-
activemodel (= 3.1.
|
10
|
-
activesupport (= 3.1.
|
8
|
+
activerecord (3.1.10)
|
9
|
+
activemodel (= 3.1.10)
|
10
|
+
activesupport (= 3.1.10)
|
11
11
|
arel (~> 2.2.3)
|
12
12
|
tzinfo (~> 0.3.29)
|
13
|
-
activesupport (3.1.
|
13
|
+
activesupport (3.1.10)
|
14
14
|
multi_json (>= 1.0, < 1.3)
|
15
15
|
appraisal (0.5.1)
|
16
16
|
bundler
|
17
17
|
rake
|
18
18
|
arel (2.2.3)
|
19
|
+
bcrypt-ruby (3.0.1-java)
|
19
20
|
bouncy-castle-java (1.5.0146.1)
|
20
|
-
builder (3.0.
|
21
|
+
builder (3.0.4)
|
21
22
|
i18n (0.6.1)
|
22
23
|
jruby-openssl (0.7.7)
|
23
24
|
bouncy-castle-java (>= 1.5.0146.1)
|
@@ -26,16 +27,22 @@ GEM
|
|
26
27
|
metaclass (~> 0.0.1)
|
27
28
|
multi_json (1.2.0)
|
28
29
|
rake (10.0.3)
|
30
|
+
simplecov (0.7.1)
|
31
|
+
multi_json (~> 1.0)
|
32
|
+
simplecov-html (~> 0.7.1)
|
33
|
+
simplecov-html (0.7.1)
|
29
34
|
test-unit (2.5.3)
|
30
|
-
tzinfo (0.3.
|
35
|
+
tzinfo (0.3.35)
|
31
36
|
|
32
37
|
PLATFORMS
|
33
38
|
java
|
34
39
|
|
35
40
|
DEPENDENCIES
|
36
|
-
activerecord (~> 3.1.
|
41
|
+
activerecord (~> 3.1.10)
|
37
42
|
appraisal
|
43
|
+
bcrypt-ruby (~> 3.0.0)
|
38
44
|
jruby-openssl
|
39
45
|
mocha
|
40
46
|
rake
|
47
|
+
simplecov
|
41
48
|
test-unit
|
data/gemfiles/rails32.gemfile
CHANGED
@@ -6,6 +6,8 @@ gem "jruby-openssl", :platform=>:jruby
|
|
6
6
|
gem "appraisal"
|
7
7
|
gem "rake", :require=>nil
|
8
8
|
gem "test-unit", :group=>:test
|
9
|
-
gem "mocha", :group=>:test
|
10
|
-
gem "
|
9
|
+
gem "mocha", :require=>nil, :group=>:test
|
10
|
+
gem "simplecov", :require=>nil, :group=>:test
|
11
|
+
gem "bcrypt-ruby", "~> 3.0.0", :require=>nil, :group=>:test
|
12
|
+
gem "activerecord", "~> 3.2.11"
|
11
13
|
|
@@ -1,21 +1,22 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
-
activemodel (3.2.
|
5
|
-
activesupport (= 3.2.
|
4
|
+
activemodel (3.2.11)
|
5
|
+
activesupport (= 3.2.11)
|
6
6
|
builder (~> 3.0.0)
|
7
|
-
activerecord (3.2.
|
8
|
-
activemodel (= 3.2.
|
9
|
-
activesupport (= 3.2.
|
7
|
+
activerecord (3.2.11)
|
8
|
+
activemodel (= 3.2.11)
|
9
|
+
activesupport (= 3.2.11)
|
10
10
|
arel (~> 3.0.2)
|
11
11
|
tzinfo (~> 0.3.29)
|
12
|
-
activesupport (3.2.
|
12
|
+
activesupport (3.2.11)
|
13
13
|
i18n (~> 0.6)
|
14
14
|
multi_json (~> 1.0)
|
15
15
|
appraisal (0.5.1)
|
16
16
|
bundler
|
17
17
|
rake
|
18
18
|
arel (3.0.2)
|
19
|
+
bcrypt-ruby (3.0.1-java)
|
19
20
|
bouncy-castle-java (1.5.0146.1)
|
20
21
|
builder (3.0.4)
|
21
22
|
i18n (0.6.1)
|
@@ -24,8 +25,12 @@ GEM
|
|
24
25
|
metaclass (0.0.1)
|
25
26
|
mocha (0.11.4)
|
26
27
|
metaclass (~> 0.0.1)
|
27
|
-
multi_json (1.
|
28
|
+
multi_json (1.5.0)
|
28
29
|
rake (10.0.3)
|
30
|
+
simplecov (0.7.1)
|
31
|
+
multi_json (~> 1.0)
|
32
|
+
simplecov-html (~> 0.7.1)
|
33
|
+
simplecov-html (0.7.1)
|
29
34
|
test-unit (2.5.3)
|
30
35
|
tzinfo (0.3.35)
|
31
36
|
|
@@ -33,9 +38,11 @@ PLATFORMS
|
|
33
38
|
java
|
34
39
|
|
35
40
|
DEPENDENCIES
|
36
|
-
activerecord (~> 3.2.
|
41
|
+
activerecord (~> 3.2.11)
|
37
42
|
appraisal
|
43
|
+
bcrypt-ruby (~> 3.0.0)
|
38
44
|
jruby-openssl
|
39
45
|
mocha
|
40
46
|
rake
|
47
|
+
simplecov
|
41
48
|
test-unit
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'arjdbc/db2'
|
@@ -15,6 +15,9 @@ module Arel
|
|
15
15
|
# Need to mimic the subquery logic in ARel 1.x for select count with limit
|
16
16
|
# See arel/engines/sql/compilers/mssql_compiler.rb for details
|
17
17
|
def visit_Arel_Nodes_SelectStatement o
|
18
|
+
if !o.limit && o.offset
|
19
|
+
raise ActiveRecord::ActiveRecordError, "You must specify :limit with :offset."
|
20
|
+
end
|
18
21
|
order = "ORDER BY #{o.orders.map { |x| visit x }.join(', ')}" unless o.orders.empty?
|
19
22
|
if o.limit
|
20
23
|
if select_count?(o)
|
data/lib/arjdbc.rb
CHANGED
@@ -7,16 +7,14 @@ if defined?(JRUBY_VERSION)
|
|
7
7
|
else
|
8
8
|
RAILS_CONNECTION_ADAPTERS = %w(jdbc)
|
9
9
|
end
|
10
|
-
if ActiveRecord::VERSION::MAJOR == 1 && ActiveRecord::VERSION::MINOR == 14
|
11
|
-
require 'arjdbc/jdbc'
|
12
|
-
end
|
13
10
|
else
|
14
11
|
require 'active_record'
|
15
|
-
require 'arjdbc/jdbc'
|
16
12
|
end
|
17
|
-
rescue LoadError
|
13
|
+
rescue LoadError => e
|
18
14
|
warn "activerecord-jdbc-adapter requires ActiveRecord at runtime"
|
15
|
+
raise e
|
19
16
|
end
|
17
|
+
require 'arjdbc/jdbc'
|
20
18
|
else
|
21
19
|
warn "activerecord-jdbc-adapter is for use with JRuby only"
|
22
20
|
end
|
data/lib/arjdbc/db2.rb
CHANGED
data/lib/arjdbc/db2/adapter.rb
CHANGED
@@ -1,69 +1,87 @@
|
|
1
|
+
require 'arjdbc/jdbc/serialized_attributes_helper'
|
2
|
+
|
1
3
|
module ArJdbc
|
2
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
|
+
|
9
|
+
@@_lob_callback_added = nil
|
10
|
+
def self.lob_callback_added? # :nodoc
|
11
|
+
@@_lob_callback_added
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.lob_callback_added! # :nodoc
|
15
|
+
@@_lob_callback_added = true
|
16
|
+
end
|
17
|
+
|
3
18
|
def self.extended(base)
|
4
|
-
if
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
19
|
+
if ADD_LOB_CALLBACK && ! lob_callback_added?
|
20
|
+
ActiveRecord::Base.class_eval do
|
21
|
+
def after_save_with_db2_lob
|
22
|
+
lob_columns = self.class.columns.select { |c| c.sql_type =~ /blob|clob/i }
|
23
|
+
lob_columns.each do |column|
|
24
|
+
value = ::ArJdbc::SerializedAttributesHelper.dump_column_value(self, column)
|
25
|
+
next if value.nil? # already set NULL
|
26
|
+
|
27
|
+
connection.write_large_object(
|
28
|
+
column.type == :binary, column.name,
|
29
|
+
self.class.table_name,
|
30
|
+
self.class.primary_key,
|
31
|
+
quote_value(id), value
|
32
|
+
)
|
19
33
|
end
|
20
34
|
end
|
21
|
-
|
22
|
-
ActiveRecord::Base.after_save :after_save_with_db2zos_blob
|
23
|
-
|
24
|
-
@lob_callback_added = true
|
35
|
+
alias after_save_with_db2zos_blob after_save_with_db2_lob # <-compat
|
25
36
|
end
|
37
|
+
# TODO this should be changed to :after_save_with_db2_lob :
|
38
|
+
ActiveRecord::Base.after_save :after_save_with_db2zos_blob # <-compat
|
39
|
+
lob_callback_added!
|
26
40
|
end
|
27
41
|
end
|
28
|
-
|
42
|
+
|
29
43
|
def self.column_selector
|
30
|
-
[ /(db2|as400|zos)/i,
|
31
|
-
lambda { |cfg, column| column.extend(::ArJdbc::DB2::Column) } ]
|
44
|
+
[ /(db2|as400|zos)/i, lambda { |cfg, column| column.extend(::ArJdbc::DB2::Column) } ]
|
32
45
|
end
|
33
46
|
|
34
47
|
def self.jdbc_connection_class
|
35
48
|
::ActiveRecord::ConnectionAdapters::DB2JdbcConnection
|
36
49
|
end
|
37
50
|
|
51
|
+
def self.arel2_visitors(config)
|
52
|
+
require 'arel/visitors/db2'
|
53
|
+
{ 'db2' => ::Arel::Visitors::DB2, 'as400' => ::Arel::Visitors::DB2 }
|
54
|
+
end
|
55
|
+
|
56
|
+
def adapter_name
|
57
|
+
'DB2'
|
58
|
+
end
|
59
|
+
|
38
60
|
NATIVE_DATABASE_TYPES = {
|
39
|
-
:double
|
40
|
-
:bigint
|
61
|
+
:double => { :name => "double" },
|
62
|
+
:bigint => { :name => "bigint" },
|
63
|
+
:string => { :name => "varchar", :limit => 255 },
|
64
|
+
:text => { :name => "clob" },
|
65
|
+
:date => { :name => "date" },
|
66
|
+
:binary => { :name => "blob" },
|
67
|
+
:boolean => { :name => "smallint" }, # no native boolean type
|
68
|
+
:xml => { :name => "xml" },
|
69
|
+
:decimal => { :name => "decimal" },
|
70
|
+
:char => { :name => "char" },
|
71
|
+
:decfloat => { :name => "decfloat" },
|
72
|
+
#:rowid => { :name => "rowid" }, # supported datatype on z/OS and i/5
|
73
|
+
#:graphic => { :name => "graphic", :limit => 1 },
|
74
|
+
#:vargraphic => { :name => "vargraphic", :limit => 1 },
|
75
|
+
# TODO datetime / timestamp / time mapping
|
41
76
|
}
|
42
77
|
|
43
78
|
def native_database_types
|
44
79
|
super.merge(NATIVE_DATABASE_TYPES)
|
45
80
|
end
|
46
81
|
|
47
|
-
def explain(query, *binds)
|
48
|
-
# TODO: Explain this!
|
49
|
-
end
|
50
|
-
|
51
|
-
def prefetch_primary_key?(table_name = nil)
|
52
|
-
# TRUE if the table has no identity column
|
53
|
-
names = table_name.upcase.split(".")
|
54
|
-
sql = "SELECT 1 FROM SYSCAT.COLUMNS WHERE IDENTITY = 'Y' "
|
55
|
-
sql += "AND TABSCHEMA = '#{names.first}' " if names.size == 2
|
56
|
-
sql += "AND TABNAME = '#{names.last}'"
|
57
|
-
select_one(sql).nil?
|
58
|
-
end
|
59
|
-
|
60
|
-
def next_sequence_value(sequence_name)
|
61
|
-
select_value("select next value for #{sequence_name} from sysibm.sysdummy1")
|
62
|
-
end
|
63
|
-
|
64
82
|
module Column
|
65
83
|
def type_cast(value)
|
66
|
-
return nil if value.nil? || value =~ /^\s*
|
84
|
+
return nil if value.nil? || value == 'NULL' || value =~ /^\s*NULL\s*$/i
|
67
85
|
case type
|
68
86
|
when :string then value
|
69
87
|
when :integer then defined?(value.to_i) ? value.to_i : (value ? 1 : 0)
|
@@ -93,6 +111,7 @@ module ArJdbc
|
|
93
111
|
def self.cast_to_date_or_time(value)
|
94
112
|
return value if value.is_a? Date
|
95
113
|
return nil if value.blank?
|
114
|
+
# https://github.com/jruby/activerecord-jdbc-adapter/commit/c225126e025df2e98ba3386c67e2a5bc5e5a73e6
|
96
115
|
return Time.now if value =~ /^CURRENT/
|
97
116
|
guess_date_or_time((value.is_a? Time) ? value : cast_to_time(value))
|
98
117
|
rescue
|
@@ -110,17 +129,30 @@ module ArJdbc
|
|
110
129
|
end
|
111
130
|
|
112
131
|
def self.guess_date_or_time(value)
|
113
|
-
|
114
|
-
|
132
|
+
return value if value.is_a? Date
|
133
|
+
( value && value.hour == 0 && value.min == 0 && value.sec == 0 ) ?
|
134
|
+
Date.new(value.year, value.month, value.day) : value
|
115
135
|
end
|
116
136
|
|
117
137
|
private
|
118
138
|
# http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.java.doc/doc/rjvjdata.html
|
119
139
|
def simplified_type(field_type)
|
120
140
|
case field_type
|
121
|
-
when /^decimal\(1\)$/i
|
122
|
-
when
|
123
|
-
when /^
|
141
|
+
when /^decimal\(1\)$/i then :boolean
|
142
|
+
when /smallint|boolean/i then :boolean
|
143
|
+
when /^real|double/i then :float
|
144
|
+
when /int|serial/i then :integer
|
145
|
+
when /numeric|decfloat/i then :decimal
|
146
|
+
when /timestamp/i then :timestamp
|
147
|
+
when /datetime/i then :datetime
|
148
|
+
when /time/i then :time
|
149
|
+
when /date/i then :date
|
150
|
+
when /clob/i then :text
|
151
|
+
when /for bit data/i then :binary
|
152
|
+
when /xml/i then :xml
|
153
|
+
#when /vargraphic/i then :vargraphic
|
154
|
+
#when /graphic/i then :graphic
|
155
|
+
#when /rowid/i then :rowid # rowid is a supported datatype on z/OS and i/5
|
124
156
|
else
|
125
157
|
super
|
126
158
|
end
|
@@ -137,15 +169,18 @@ module ArJdbc
|
|
137
169
|
value
|
138
170
|
end
|
139
171
|
end
|
172
|
+
|
173
|
+
def prefetch_primary_key?(table_name = nil)
|
174
|
+
# TRUE if the table has no identity column
|
175
|
+
names = table_name.upcase.split(".")
|
176
|
+
sql = "SELECT 1 FROM SYSCAT.COLUMNS WHERE IDENTITY = 'Y' "
|
177
|
+
sql += "AND TABSCHEMA = '#{names.first}' " if names.size == 2
|
178
|
+
sql += "AND TABNAME = '#{names.last}'"
|
179
|
+
select_one(sql).nil?
|
180
|
+
end
|
140
181
|
|
141
|
-
def
|
142
|
-
|
143
|
-
@connection.execute_query(sql)
|
144
|
-
elsif ActiveRecord::ConnectionAdapters::JdbcConnection::insert?(sql)
|
145
|
-
(@connection.execute_insert(sql) or last_insert_id(sql)).to_i
|
146
|
-
else
|
147
|
-
@connection.execute_update(sql)
|
148
|
-
end
|
182
|
+
def next_sequence_value(sequence_name)
|
183
|
+
select_value("SELECT NEXT VALUE FOR #{sequence_name} FROM sysibm.sysdummy1")
|
149
184
|
end
|
150
185
|
|
151
186
|
# holy moly batman! all this to tell AS400 "yes i am sure"
|
@@ -155,108 +190,93 @@ module ArJdbc
|
|
155
190
|
@connection.execute_update "call qsys.qcmdexc('ADDRPYLE SEQNBR(9876) MSGID(CPA32B2) RPY(''I'')',0000000045.00000)"
|
156
191
|
rescue Exception => e
|
157
192
|
raise "Could not call CHGJOB INQMSGRPY(*SYSRPYL) and ADDRPYLE SEQNBR(9876) MSGID(CPA32B2) RPY('I').\n" +
|
158
|
-
|
193
|
+
"Do you have authority to do this?\n\n" + e.to_s
|
159
194
|
end
|
160
195
|
|
161
|
-
|
196
|
+
result = execute sql
|
162
197
|
|
163
198
|
begin
|
164
199
|
@connection.execute_update "call qsys.qcmdexc('QSYS/CHGJOB INQMSGRPY(*DFT)',0000000027.00000)"
|
165
200
|
@connection.execute_update "call qsys.qcmdexc('RMVRPYLE SEQNBR(9876)',0000000021.00000)"
|
166
201
|
rescue Exception => e
|
167
202
|
raise "Could not call CHGJOB INQMSGRPY(*DFT) and RMVRPYLE SEQNBR(9876).\n" +
|
168
|
-
|
203
|
+
"Do you have authority to do this?\n\n" + e.to_s
|
169
204
|
end
|
170
|
-
|
205
|
+
result
|
171
206
|
end
|
172
207
|
|
208
|
+
def _execute(sql, name = nil)
|
209
|
+
if self.class.select?(sql)
|
210
|
+
@connection.execute_query(sql)
|
211
|
+
elsif self.class.insert?(sql)
|
212
|
+
(@connection.execute_insert(sql) or last_insert_id(sql)).to_i
|
213
|
+
else
|
214
|
+
@connection.execute_update(sql)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
173
218
|
def last_insert_id(sql)
|
174
219
|
table_name = sql.split(/\s/)[2]
|
175
|
-
result = select(ActiveRecord::Base.send(:sanitize_sql, %[
|
220
|
+
result = select(ActiveRecord::Base.send(:sanitize_sql, %[SELECT IDENTITY_VAL_LOCAL() AS last_insert_id FROM #{table_name}], nil))
|
176
221
|
result.last['last_insert_id']
|
177
222
|
end
|
178
|
-
|
179
|
-
def modify_types(tp)
|
180
|
-
tp[:primary_key] = 'int not null generated by default as identity (start with 1) primary key'
|
181
|
-
tp[:string][:limit] = 255
|
182
|
-
tp[:integer][:limit] = nil
|
183
|
-
tp[:boolean] = {:name => "decimal(1)"}
|
184
|
-
tp
|
185
|
-
end
|
186
|
-
|
187
|
-
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
|
188
|
-
limit = nil if type.to_sym == :integer
|
189
|
-
super(type, limit, precision, scale)
|
190
|
-
end
|
191
|
-
|
192
|
-
def adapter_name
|
193
|
-
'DB2'
|
194
|
-
end
|
195
|
-
|
196
|
-
def self.arel2_visitors(config)
|
197
|
-
require 'arel/visitors/db2'
|
198
|
-
{}.tap {|v| %w(db2 as400).each {|a| v[a] = ::Arel::Visitors::DB2 } }
|
199
|
-
end
|
200
|
-
|
201
|
-
def add_limit_offset!(sql, options)
|
202
|
-
replace_limit_offset!(sql, options[:limit], options[:offset])
|
203
|
-
end
|
204
|
-
|
205
|
-
|
223
|
+
|
206
224
|
def create_table(name, options = {}) #:nodoc:
|
207
225
|
if zos?
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
# Second: and delete them from the original Colums-Array
|
219
|
-
table_definition.columns.delete_if { |x| x.type=="text" }
|
226
|
+
zos_create_table(name, options)
|
227
|
+
else
|
228
|
+
super(name, options)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def zos_create_table(name, options = {}) #:nodoc:
|
233
|
+
table_definition = ActiveRecord::ConnectionAdapters::TableDefinition.new(self)
|
234
|
+
table_definition.primary_key(options[:primary_key] || ActiveRecord::Base.get_primary_key(name)) unless options[:id] == false
|
220
235
|
|
221
|
-
|
222
|
-
super.drop_table(name, options)
|
223
|
-
end
|
236
|
+
yield table_definition
|
224
237
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
238
|
+
# Clobs in DB2 Host have to be created after the Table with an auxiliary Table.
|
239
|
+
# First: Save them for later in Array "clobs"
|
240
|
+
clobs = table_definition.columns.select { |x| x.type.to_s == "text" }
|
241
|
+
# Second: and delete them from the original Colums-Array
|
242
|
+
table_definition.columns.delete_if { |x| x.type.to_s == "text" }
|
230
243
|
|
231
|
-
|
244
|
+
drop_table(name, options) if options[:force] && table_exists?(name)
|
232
245
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
246
|
+
create_sql = "CREATE#{' TEMPORARY' if options[:temporary]} TABLE "
|
247
|
+
create_sql << "#{quote_table_name(name)} ("
|
248
|
+
create_sql << table_definition.to_sql
|
249
|
+
create_sql << ") #{options[:options]}"
|
250
|
+
if @config[:database] && @config[:tablespace]
|
251
|
+
in_db_table_space = " IN #{@config[:database]}.#{@config[:tablespace]}"
|
238
252
|
else
|
239
|
-
|
253
|
+
in_db_table_space = ''
|
240
254
|
end
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
255
|
+
create_sql << in_db_table_space
|
256
|
+
|
257
|
+
execute create_sql
|
258
|
+
|
259
|
+
# Table definition is complete only when a unique index is created on the primary_key column for DB2 V8 on zOS
|
260
|
+
# create index on id column if options[:id] is nil or id ==true
|
261
|
+
# else check if options[:primary_key]is not nil then create an unique index on that column
|
262
|
+
# TODO someone on Z/OS should test this out - also not needed for V9 ?
|
263
|
+
#primary_column = options[:id] == true ? 'id' : options[:primary_key]
|
264
|
+
#add_index(name, (primary_column || 'id').to_s, :unique => true)
|
265
|
+
|
266
|
+
clobs.each do |clob_column|
|
267
|
+
column_name = clob_column.name.to_s
|
268
|
+
execute "ALTER TABLE #{name + ' ADD COLUMN ' + column_name + ' clob'}"
|
269
|
+
clob_table_name = name + '_' + column_name + '_CD_'
|
270
|
+
if @config[:database] && @config[:lob_tablespaces]
|
271
|
+
in_lob_table_space = " IN #{@config[:database]}.#{@config[:lob_tablespaces][name.split(".")[1]]}"
|
252
272
|
else
|
253
|
-
|
254
|
-
sql.sub!(/SELECT/i, 'SELECT B.* FROM (SELECT A.*, row_number() over () AS internal$rownum FROM (SELECT')
|
255
|
-
sql << ") A ) B WHERE B.internal$rownum > #{offset} AND B.internal$rownum <= #{limit + offset}"
|
273
|
+
in_lob_table_space = ''
|
256
274
|
end
|
275
|
+
execute "CREATE AUXILIARY TABLE #{clob_table_name} #{in_lob_table_space} STORES #{name} COLUMN #{column_name}"
|
276
|
+
execute "CREATE UNIQUE INDEX #{clob_table_name} ON #{clob_table_name};"
|
257
277
|
end
|
258
|
-
sql
|
259
278
|
end
|
279
|
+
private :zos_create_table
|
260
280
|
|
261
281
|
def pk_and_sequence_for(table)
|
262
282
|
# In JDBC/DB2 side, only upcase names of table and column are handled.
|
@@ -268,74 +288,147 @@ module ArJdbc
|
|
268
288
|
keys
|
269
289
|
end
|
270
290
|
|
271
|
-
|
272
|
-
|
273
|
-
end
|
274
|
-
|
291
|
+
# Properly quotes the various data types.
|
292
|
+
# +value+ contains the data, +column+ is optional and contains info on the field
|
275
293
|
def quote(value, column = nil) # :nodoc:
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
294
|
+
return value.quoted_id if value.respond_to?(:quoted_id)
|
295
|
+
|
296
|
+
if column
|
297
|
+
if column.respond_to?(:primary) && column.primary && column.klass != String
|
298
|
+
return value.to_i.to_s
|
299
|
+
end
|
300
|
+
if value && (column.type.to_sym == :decimal || column.type.to_sym == :integer)
|
301
|
+
return value.to_s
|
302
|
+
end
|
281
303
|
end
|
304
|
+
|
305
|
+
column_type = column && column.type.to_sym
|
306
|
+
|
282
307
|
case value
|
283
|
-
when
|
284
|
-
|
285
|
-
|
308
|
+
when nil then "NULL"
|
309
|
+
when Numeric # IBM_DB doesn't accept quotes on numeric types
|
310
|
+
# if the column type is text or string, return the quote value
|
311
|
+
if column_type == :text || column_type == :string
|
312
|
+
"'#{value}'"
|
286
313
|
else
|
287
|
-
|
288
|
-
|
314
|
+
value.to_s
|
315
|
+
end
|
316
|
+
when String, ActiveSupport::Multibyte::Chars
|
317
|
+
if column_type == :binary && !(column.sql_type =~ /for bit data/i)
|
318
|
+
if ArJdbc::DB2.lob_callback_added?
|
319
|
+
"NULL" # '@@@IBMBINARY@@@'"
|
320
|
+
else
|
321
|
+
"BLOB('#{quote_string(value)}')"
|
322
|
+
end
|
323
|
+
elsif column && column.sql_type =~ /clob/ # :text
|
324
|
+
if ArJdbc::DB2.lob_callback_added?
|
325
|
+
"NULL" # "'@@@IBMTEXT@@@'"
|
289
326
|
else
|
290
327
|
"'#{quote_string(value)}'"
|
291
328
|
end
|
329
|
+
elsif column_type == :xml
|
330
|
+
"#{value}" # "'<ibm>@@@IBMXML@@@</ibm>'"
|
331
|
+
else
|
332
|
+
"'#{quote_string(value)}'"
|
292
333
|
end
|
334
|
+
when Symbol then "'#{quote_string(value.to_s)}'"
|
293
335
|
else super
|
294
336
|
end
|
295
337
|
end
|
296
338
|
|
297
|
-
def
|
298
|
-
|
339
|
+
def quote_column_name(column_name)
|
340
|
+
column_name.to_s
|
299
341
|
end
|
300
|
-
|
301
|
-
def
|
302
|
-
|
342
|
+
|
343
|
+
def modify_types(types)
|
344
|
+
super(types)
|
345
|
+
types[:primary_key] = 'int not null generated by default as identity (start with 1) primary key'
|
346
|
+
types[:string][:limit] = 255
|
347
|
+
types[:integer][:limit] = nil
|
348
|
+
types[:boolean] = {:name => "decimal(1)"}
|
349
|
+
types
|
303
350
|
end
|
304
351
|
|
305
|
-
def
|
306
|
-
|
352
|
+
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
|
353
|
+
limit = nil if type.to_sym == :integer
|
354
|
+
super(type, limit, precision, scale)
|
307
355
|
end
|
308
356
|
|
357
|
+
def add_limit_offset!(sql, options)
|
358
|
+
replace_limit_offset!(sql, options[:limit], options[:offset])
|
359
|
+
end
|
360
|
+
|
361
|
+
def add_column_options!(sql, options) # :nodoc:
|
362
|
+
# handle case of defaults for CLOB columns,
|
363
|
+
# which might get incorrect if we write LOBs in the after_save callback
|
364
|
+
if options_include_default?(options)
|
365
|
+
column = options[:column]
|
366
|
+
if column && column.type == :text
|
367
|
+
sql << " DEFAULT #{quote(options.delete(:default))}"
|
368
|
+
end
|
369
|
+
if column && column.type == :binary
|
370
|
+
# quoting required for the default value of a column :
|
371
|
+
value = options.delete(:default)
|
372
|
+
# DB2 z/OS only allows NULL or "" (empty) string as DEFAULT value
|
373
|
+
# for a BLOB column. non-empty string and non-NULL, return error!
|
374
|
+
if value.nil?
|
375
|
+
sql_value = "NULL"
|
376
|
+
else
|
377
|
+
sql_value = zos? ? "#{value}" : "BLOB('#{quote_string(value)}'"
|
378
|
+
end
|
379
|
+
sql << " DEFAULT #{sql_value}"
|
380
|
+
end
|
381
|
+
end
|
382
|
+
super
|
383
|
+
end
|
384
|
+
|
385
|
+
def replace_limit_offset!(sql, limit, offset)
|
386
|
+
if limit
|
387
|
+
limit = limit.to_i
|
388
|
+
if !offset
|
389
|
+
if limit == 1
|
390
|
+
sql << " FETCH FIRST ROW ONLY"
|
391
|
+
else
|
392
|
+
sql << " FETCH FIRST #{limit} ROWS ONLY"
|
393
|
+
end
|
394
|
+
else
|
395
|
+
offset = offset.to_i
|
396
|
+
sql.sub!(/SELECT/i, 'SELECT B.* FROM (SELECT A.*, row_number() over () AS internal$rownum FROM (SELECT')
|
397
|
+
sql << ") A ) B WHERE B.internal$rownum > #{offset} AND B.internal$rownum <= #{limit + offset}"
|
398
|
+
end
|
399
|
+
end
|
400
|
+
sql
|
401
|
+
end
|
402
|
+
|
309
403
|
def reorg_table(table_name)
|
310
404
|
unless as400?
|
311
405
|
@connection.execute_update "call sysproc.admin_cmd ('REORG TABLE #{table_name}')"
|
312
406
|
end
|
313
407
|
end
|
408
|
+
private :reorg_table
|
314
409
|
|
315
410
|
def runstats_for_table(tablename, priority=10)
|
316
411
|
@connection.execute_update "call sysproc.admin_cmd('RUNSTATS ON TABLE #{tablename} WITH DISTRIBUTION AND DETAILED INDEXES ALL UTIL_IMPACT_PRIORITY #{priority}')"
|
317
412
|
end
|
318
413
|
|
319
414
|
def recreate_database(name, options = {})
|
320
|
-
tables.each {|table| drop_table("#{db2_schema}.#{table}")}
|
415
|
+
tables.each { |table| drop_table("#{db2_schema}.#{table}") }
|
321
416
|
end
|
322
417
|
|
323
418
|
def add_index(table_name, column_name, options = {})
|
324
|
-
if
|
419
|
+
if ! zos? || ( table_name.to_s == ActiveRecord::Migrator.schema_migrations_table_name.to_s )
|
325
420
|
column_name = column_name.to_s if column_name.is_a?(Symbol)
|
326
421
|
super
|
327
422
|
else
|
328
|
-
statement =
|
329
|
-
statement <<
|
330
|
-
statement << " INDEX
|
331
|
-
|
423
|
+
statement = 'CREATE'
|
424
|
+
statement << ' UNIQUE ' if options[:unique]
|
425
|
+
statement << " INDEX #{ActiveRecord::Base.table_name_prefix}#{options[:name]} "
|
332
426
|
statement << " ON #{table_name}(#{column_name})"
|
333
|
-
|
427
|
+
|
334
428
|
execute statement
|
335
429
|
end
|
336
430
|
end
|
337
431
|
|
338
|
-
|
339
432
|
def remove_index(table_name, options = { })
|
340
433
|
execute "DROP INDEX #{quote_column_name(index_name(table_name, options))}"
|
341
434
|
end
|
@@ -392,12 +485,13 @@ module ArJdbc
|
|
392
485
|
change_column_null(table_name, column_name, options[:null])
|
393
486
|
end
|
394
487
|
end
|
395
|
-
|
488
|
+
|
396
489
|
# http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.admin.dbobj.doc/doc/t0020132.html
|
397
|
-
def remove_column(table_name,
|
398
|
-
|
399
|
-
|
400
|
-
|
490
|
+
def remove_column(table_name, *column_names) #:nodoc:
|
491
|
+
for column_name in column_names.flatten
|
492
|
+
sql = "ALTER TABLE #{table_name} DROP COLUMN #{column_name}"
|
493
|
+
as400? ? execute_and_auto_confirm(sql) : execute(sql)
|
494
|
+
end
|
401
495
|
reorg_table(table_name)
|
402
496
|
end
|
403
497
|
|
@@ -406,35 +500,34 @@ module ArJdbc
|
|
406
500
|
execute "RENAME TABLE #{name} TO #{new_name}"
|
407
501
|
reorg_table(new_name)
|
408
502
|
end
|
409
|
-
|
503
|
+
|
410
504
|
def tables
|
411
505
|
@connection.tables(nil, db2_schema, nil, ["TABLE"])
|
412
506
|
end
|
413
507
|
|
414
|
-
# only record precision and scale for types that can set
|
415
|
-
# them via CREATE TABLE:
|
508
|
+
# only record precision and scale for types that can set them via CREATE TABLE:
|
416
509
|
# http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.ref.doc/doc/r0000927.html
|
417
510
|
HAVE_LIMIT = %w(FLOAT DECFLOAT CHAR VARCHAR CLOB BLOB NCHAR NCLOB DBCLOB GRAPHIC VARGRAPHIC) #TIMESTAMP
|
418
511
|
HAVE_PRECISION = %w(DECIMAL NUMERIC)
|
419
512
|
HAVE_SCALE = %w(DECIMAL NUMERIC)
|
420
513
|
|
421
514
|
def columns(table_name, name = nil)
|
422
|
-
|
515
|
+
columns = @connection.columns(table_name.to_s, name, db2_schema)
|
423
516
|
|
424
517
|
if zos?
|
425
518
|
# Remove the mighty db2_generated_rowid_for_lobs from the list of columns
|
426
|
-
|
519
|
+
columns = columns.reject { |col| "db2_generated_rowid_for_lobs" == col.name }
|
427
520
|
end
|
428
521
|
# scrub out sizing info when CREATE TABLE doesn't support it
|
429
522
|
# but JDBC reports it (doh!)
|
430
|
-
for
|
431
|
-
base_sql_type =
|
432
|
-
|
433
|
-
|
434
|
-
#
|
523
|
+
for column in columns
|
524
|
+
base_sql_type = column.sql_type.sub(/\(.*/, "").upcase
|
525
|
+
column.limit = nil unless HAVE_LIMIT.include?(base_sql_type)
|
526
|
+
column.precision = nil unless HAVE_PRECISION.include?(base_sql_type)
|
527
|
+
#column.scale = nil unless HAVE_SCALE.include?(base_sql_type)
|
435
528
|
end
|
436
529
|
|
437
|
-
|
530
|
+
columns
|
438
531
|
end
|
439
532
|
|
440
533
|
def jdbc_columns(table_name, name = nil)
|
@@ -462,9 +555,9 @@ module ArJdbc
|
|
462
555
|
end
|
463
556
|
|
464
557
|
def structure_dump #:nodoc:
|
465
|
-
definition=""
|
466
558
|
schema_name = db2_schema.upcase if db2_schema.present?
|
467
|
-
rs = @connection.connection.meta_data.getTables(nil,schema_name,nil,["TABLE"].to_java(:string))
|
559
|
+
rs = @connection.connection.meta_data.getTables(nil, schema_name, nil, ["TABLE"].to_java(:string))
|
560
|
+
definition = ''
|
468
561
|
while rs.next
|
469
562
|
tname = rs.getString(3)
|
470
563
|
definition << "CREATE TABLE #{tname} (\n"
|
@@ -527,34 +620,47 @@ module ArJdbc
|
|
527
620
|
end
|
528
621
|
definition
|
529
622
|
end
|
530
|
-
|
623
|
+
|
624
|
+
DRIVER_NAME = 'com.ibm.db2.jcc.DB2Driver'.freeze
|
625
|
+
|
531
626
|
def zos?
|
532
|
-
@
|
627
|
+
return @zos unless @zos.nil?
|
628
|
+
@zos =
|
629
|
+
if url = @config[:url]
|
630
|
+
!!( url =~ /^jdbc:db2j:net:/ && @config[:driver] == DRIVER_NAME )
|
631
|
+
else
|
632
|
+
nil
|
633
|
+
end
|
533
634
|
end
|
534
|
-
|
535
|
-
private
|
635
|
+
|
536
636
|
def as400?
|
537
|
-
@
|
637
|
+
return @as400 unless @as400.nil?
|
638
|
+
@as400 =
|
639
|
+
if url = @config[:url]
|
640
|
+
!!( url =~ /^jdbc:as400:/ )
|
641
|
+
else
|
642
|
+
nil
|
643
|
+
end
|
538
644
|
end
|
539
645
|
|
646
|
+
private
|
647
|
+
|
540
648
|
def db2_schema
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
(schema[-1..-1] == ";") ? schema.chop : schema
|
546
|
-
elsif @config[:username].present?
|
547
|
-
# LUW implementation uses schema name of username by default
|
548
|
-
@config[:username]
|
649
|
+
return @db2_schema unless @db2_schema.nil?
|
650
|
+
@db2_schema =
|
651
|
+
if @config[:schema].present?
|
652
|
+
@config[:schema]
|
549
653
|
elsif @config[:jndi].present?
|
550
|
-
# let
|
551
|
-
|
654
|
+
nil # let JNDI worry about schema
|
655
|
+
elsif as400?
|
656
|
+
# AS400 implementation takes schema from library name (last part of URL)
|
657
|
+
# jdbc:as400://localhost/schema;naming=system;libraries=lib1,lib2
|
658
|
+
@config[:url].split('/').last.split(';').first.strip
|
552
659
|
else
|
553
|
-
|
660
|
+
# LUW implementation uses schema name of username by default
|
661
|
+
@config[:username].presence || ENV['USER']
|
554
662
|
end
|
555
|
-
else
|
556
|
-
@config[:schema]
|
557
|
-
end
|
558
663
|
end
|
664
|
+
|
559
665
|
end
|
560
666
|
end
|