activerecord-jdbc-adapter 1.0.0.beta1-java → 1.0.0.beta2-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +37 -0
- data/Manifest.txt +8 -0
- data/README.txt +41 -88
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
- data/lib/arel/engines/sql/compilers/hsqldb_compiler.rb +9 -0
- data/lib/arel/engines/sql/compilers/mssql_compiler.rb +34 -0
- data/lib/arjdbc/db2/adapter.rb +232 -52
- data/lib/arjdbc/derby/adapter.rb +28 -1
- data/lib/arjdbc/derby/connection_methods.rb +1 -1
- data/lib/arjdbc/discover.rb +1 -1
- data/lib/arjdbc/firebird/adapter.rb +26 -0
- data/lib/arjdbc/h2/adapter.rb +13 -0
- data/lib/arjdbc/hsqldb/adapter.rb +8 -6
- data/lib/arjdbc/informix/adapter.rb +4 -0
- data/lib/arjdbc/jdbc/adapter.rb +27 -5
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/connection.rb +76 -45
- data/lib/arjdbc/jdbc/jdbc.rake +22 -20
- data/lib/arjdbc/jdbc/type_converter.rb +9 -2
- data/lib/arjdbc/mssql/adapter.rb +102 -24
- data/lib/arjdbc/mssql/connection_methods.rb +19 -2
- data/lib/arjdbc/mssql/tsql_helper.rb +1 -0
- data/lib/arjdbc/mysql/adapter.rb +6 -0
- data/lib/arjdbc/mysql/connection_methods.rb +8 -7
- data/lib/arjdbc/oracle/adapter.rb +8 -6
- data/lib/arjdbc/postgresql/adapter.rb +51 -19
- data/lib/arjdbc/version.rb +1 -1
- data/lib/jdbc_adapter/rake_tasks.rb +3 -0
- data/rails_generators/templates/lib/tasks/jdbc.rake +2 -2
- data/rakelib/package.rake +2 -0
- data/rakelib/test.rake +6 -3
- data/src/java/arjdbc/derby/DerbyModule.java +30 -1
- data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +74 -0
- data/src/java/arjdbc/jdbc/AdapterJavaService.java +7 -3
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +45 -30
- data/src/java/arjdbc/mssql/MssqlRubyJdbcConnection.java +54 -1
- data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +85 -0
- data/test/abstract_db_create.rb +6 -1
- data/test/db/jndi_config.rb +20 -10
- data/test/db2_simple_test.rb +34 -1
- data/test/derby_simple_test.rb +78 -0
- data/test/generic_jdbc_connection_test.rb +21 -1
- data/test/jndi_callbacks_test.rb +2 -1
- data/test/jndi_test.rb +1 -11
- data/test/models/entry.rb +20 -0
- data/test/mssql_limit_offset_test.rb +28 -0
- data/test/mssql_simple_test.rb +7 -1
- data/test/mysql_info_test.rb +49 -6
- data/test/mysql_simple_test.rb +4 -0
- data/test/oracle_simple_test.rb +3 -47
- data/test/oracle_specific_test.rb +83 -0
- data/test/postgres_db_create_test.rb +6 -0
- data/test/postgres_drop_db_test.rb +16 -0
- data/test/postgres_simple_test.rb +17 -0
- data/test/postgres_table_alias_length_test.rb +15 -0
- data/test/simple.rb +17 -4
- metadata +33 -7
data/History.txt
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
== 1.0.0
|
2
2
|
|
3
|
+
- Thanks to David Kellum, Dmitry Denisov, Dwayne Litzenberger, Gregor
|
4
|
+
Schmidt, James Walker, John Duff, Joshua Suggs, Nicholas J Kreucher,
|
5
|
+
Peter Donald, Geoff Longman, and Ryan Bell for their contributions
|
6
|
+
to this release.
|
7
|
+
- BIG set of DB2 updates (Thanks Nick Kreucher)
|
8
|
+
- Deprecate jdbc_adapter/rake_tasks
|
3
9
|
- (1.0.0.beta1)
|
4
10
|
- Make database-specific extensions only load when necessary
|
5
11
|
- Allow for discovery of database extensions outside of ar-jdbc
|
@@ -8,6 +14,37 @@
|
|
8
14
|
- Get AR's own tests running as close to 100% as possible. MySQL is
|
9
15
|
currently 100%, SQLite3 is close.
|
10
16
|
- JRUBY-4876: Bump up Derby's max index name length (Uwe Kubosch)
|
17
|
+
- (1.0.0.beta2)
|
18
|
+
- 98 commits since beta1
|
19
|
+
- MSSQL updates from dlitz and realityforge
|
20
|
+
- ACTIVERECORD_JDBC-131: Fix string slug issue for DB2 (Youhei Kondou)
|
21
|
+
- JRUBY-1642: Don't use H2 INFORMATION_SCHEMA in table or column
|
22
|
+
searches
|
23
|
+
- JRUBY-4972: Attempt to deal with type(0)/:limit => 0 by not setting
|
24
|
+
it808e213 JRUBY-5040: Fix issue with limits on timestamps in MySQL
|
25
|
+
- JRUBY-3555: Allow setting Derby schema with 'schema:' option917ebd9
|
26
|
+
ACTIVERECORD_JDBC-98: Make sure we actuall raise an error when
|
27
|
+
inappropriately configured
|
28
|
+
- ACTIVERECORD_JDBC-112: Add schema dumper tests for already-fixed
|
29
|
+
MySQL type limits
|
30
|
+
- ACTIVERECORD_JDBC-113: Fix PG float precision issue2c6b1aa No longer
|
31
|
+
need M[ys]SQL escape hatch on case-sensitive test
|
32
|
+
- ACTIVERECORD_JDBC-103: Fix decimal options for PG add/change column
|
33
|
+
(Michael Pitman)
|
34
|
+
- ACTIVERECORD_JDBC-127: Fix quoting of Date vs. Time(stamp) for
|
35
|
+
Oracle (Lenny Marks)
|
36
|
+
- Oracle: Sort out theNUMBER vs NUMBER(x) vs NUMBER(x,y) situation.
|
37
|
+
- JRUBY-3051: Think we finally got the PG mixed-case patches applied.
|
38
|
+
- JRUBY-5081: Consolidate code for dropping DB via postgres
|
39
|
+
- ACTIVERECORD_JDBC-101: Add override of LONGVARCHAR => CLOB for
|
40
|
+
informix
|
41
|
+
- ACTIVERECORD_JDBC-107: Fix MySQL update_all issue on AR 2.3
|
42
|
+
- ACTIVERECORD_JDBC-124: Filter out special _row_num column
|
43
|
+
- ACTIVERECORD_JDBC-126: Fix sql 2000 limit/offset per Michael Pitman
|
44
|
+
- ACTIVERECORD_JDBC-125: Add tweak to limit/offset code for HABTM
|
45
|
+
queries (alex b)
|
46
|
+
- ACTIVERECORD_JDBC-129: Don't have limits for text, binary or bit
|
47
|
+
fields
|
11
48
|
|
12
49
|
== 0.9.7
|
13
50
|
|
data/Manifest.txt
CHANGED
@@ -15,6 +15,7 @@ lib/active_record/connection_adapters/informix_adapter.rb
|
|
15
15
|
lib/active_record/connection_adapters/jdbc_adapter.rb
|
16
16
|
lib/active_record/connection_adapters/jndi_adapter.rb
|
17
17
|
lib/active_record/connection_adapters/mssql_adapter.rb
|
18
|
+
lib/active_record/connection_adapters/mysql2_adapter.rb
|
18
19
|
lib/active_record/connection_adapters/mysql_adapter.rb
|
19
20
|
lib/active_record/connection_adapters/oracle_adapter.rb
|
20
21
|
lib/active_record/connection_adapters/postgresql_adapter.rb
|
@@ -24,6 +25,7 @@ lib/arel/engines/sql/compilers/derby_compiler.rb
|
|
24
25
|
lib/arel/engines/sql/compilers/h2_compiler.rb
|
25
26
|
lib/arel/engines/sql/compilers/hsqldb_compiler.rb
|
26
27
|
lib/arel/engines/sql/compilers/jdbc_compiler.rb
|
28
|
+
lib/arel/engines/sql/compilers/mssql_compiler.rb
|
27
29
|
lib/arjdbc/cachedb.rb
|
28
30
|
lib/arjdbc/db2.rb
|
29
31
|
lib/arjdbc/derby.rb
|
@@ -84,6 +86,7 @@ lib/arjdbc/sqlite3/adapter.rb
|
|
84
86
|
lib/arjdbc/sqlite3/connection_methods.rb
|
85
87
|
lib/arjdbc/sybase/adapter.rb
|
86
88
|
lib/generators/jdbc/jdbc_generator.rb
|
89
|
+
lib/jdbc_adapter/rake_tasks.rb
|
87
90
|
lib/jdbc_adapter/version.rb
|
88
91
|
lib/arjdbc/jdbc/adapter_java.jar
|
89
92
|
test/abstract_db_create.rb
|
@@ -114,13 +117,16 @@ test/mysql_multibyte_test.rb
|
|
114
117
|
test/mysql_nonstandard_primary_key_test.rb
|
115
118
|
test/mysql_simple_test.rb
|
116
119
|
test/oracle_simple_test.rb
|
120
|
+
test/oracle_specific_test.rb
|
117
121
|
test/pick_rails_version.rb
|
118
122
|
test/postgres_db_create_test.rb
|
123
|
+
test/postgres_drop_db_test.rb
|
119
124
|
test/postgres_mixed_case_test.rb
|
120
125
|
test/postgres_nonseq_pkey_test.rb
|
121
126
|
test/postgres_reserved_test.rb
|
122
127
|
test/postgres_schema_search_path_test.rb
|
123
128
|
test/postgres_simple_test.rb
|
129
|
+
test/postgres_table_alias_length_test.rb
|
124
130
|
test/simple.rb
|
125
131
|
test/sqlite3_simple_test.rb
|
126
132
|
test/sybase_jtds_simple_test.rb
|
@@ -150,12 +156,14 @@ test/models/string_id.rb
|
|
150
156
|
test/models/validates_uniqueness_of_string.rb
|
151
157
|
lib/arjdbc/jdbc/jdbc.rake
|
152
158
|
src/java/arjdbc/derby/DerbyModule.java
|
159
|
+
src/java/arjdbc/informix/InformixRubyJdbcConnection.java
|
153
160
|
src/java/arjdbc/jdbc/AdapterJavaService.java
|
154
161
|
src/java/arjdbc/jdbc/JdbcConnectionFactory.java
|
155
162
|
src/java/arjdbc/jdbc/RubyJdbcConnection.java
|
156
163
|
src/java/arjdbc/jdbc/SQLBlock.java
|
157
164
|
src/java/arjdbc/mssql/MssqlRubyJdbcConnection.java
|
158
165
|
src/java/arjdbc/mysql/MySQLModule.java
|
166
|
+
src/java/arjdbc/oracle/OracleRubyJdbcConnection.java
|
159
167
|
src/java/arjdbc/postgresql/PostgresqlRubyJdbcConnection.java
|
160
168
|
src/java/arjdbc/sqlite3/Sqlite3RubyJdbcConnection.java
|
161
169
|
rakelib/compile.rake
|
data/README.txt
CHANGED
@@ -2,39 +2,11 @@ activerecord-jdbc-adapter is a database adapter for Rails' ActiveRecord
|
|
2
2
|
component that can be used with JRuby[http://www.jruby.org/]. It allows use of
|
3
3
|
virtually any JDBC-compliant database with your JRuby on Rails application.
|
4
4
|
|
5
|
-
== Project Info
|
6
|
-
|
7
|
-
* Mailing Lists: http://kenai.com/projects/activerecord-jdbc/lists
|
8
|
-
* Issues: http://kenai.com/jira/browse/ACTIVERECORD_JDBC
|
9
|
-
* Source: git://kenai.com/activerecord-jdbc~main
|
10
|
-
git://github.com/nicksieger/activerecord-jdbc-adapter.git
|
11
|
-
|
12
5
|
== Databases
|
13
6
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
* PostgreSQL - Complete support
|
18
|
-
* Oracle - Complete support
|
19
|
-
* Microsoft SQL Server - Complete support
|
20
|
-
* DB2 - Complete, except for the migrations:
|
21
|
-
* change_column
|
22
|
-
* change_column_default
|
23
|
-
* remove_column
|
24
|
-
* rename_column
|
25
|
-
* add_index
|
26
|
-
* remove_index
|
27
|
-
* rename_table
|
28
|
-
* FireBird - Complete, except for change_column_default and rename_column
|
29
|
-
* Derby - Complete, except for:
|
30
|
-
* change_column
|
31
|
-
* change_column_default
|
32
|
-
* remove_column
|
33
|
-
* rename_column
|
34
|
-
* HSQLDB - Complete
|
35
|
-
* H2 - Complete
|
36
|
-
* SQLite3 - work in progress
|
37
|
-
* Informix - Fairly complete support, all tests pass and migrations appear to work. Comments welcome.
|
7
|
+
Activerecord-jdbc-adapter provides full or nearly full support for:
|
8
|
+
MySQL, PostgreSQL, SQLite3, Oracle, Microsoft SQL Server, DB2,
|
9
|
+
FireBird, Derby, HSQLDB, H2, and Informix.
|
38
10
|
|
39
11
|
Other databases will require testing and likely a custom configuration module.
|
40
12
|
Please join the activerecord-jdbc
|
@@ -48,7 +20,7 @@ support for more databases.
|
|
48
20
|
To use activerecord-jdbc-adapter with JRuby on Rails:
|
49
21
|
|
50
22
|
1. Choose the adapter you wish to gem install. The following pre-packaged
|
51
|
-
|
23
|
+
adapters are available:
|
52
24
|
|
53
25
|
* base jdbc (<tt>activerecord-jdbc-adapter</tt>). Supports all available databases via JDBC, but requires you to download and manually install the database vendor's JDBC driver .jar file.
|
54
26
|
* mysql (<tt>activerecord-jdbcmysql-adapter</tt>)
|
@@ -60,54 +32,33 @@ To use activerecord-jdbc-adapter with JRuby on Rails:
|
|
60
32
|
* mssql (<tt>activerecord-jdbcmssql-adapter</tt>)
|
61
33
|
|
62
34
|
2a. For Rails 3, if you're generating a new application, use the
|
63
|
-
|
35
|
+
following command to generate your application:
|
64
36
|
|
65
|
-
jruby -S rails
|
37
|
+
jruby -S rails new sweetapp -m http://jruby.org/rails3.rb
|
66
38
|
|
67
|
-
2b. Otherwise, you'll need to
|
68
|
-
|
39
|
+
2b. Otherwise, you'll need to perform some extra configuration steps
|
40
|
+
to prepare your Rails application for JDBC.
|
69
41
|
|
70
|
-
|
71
|
-
|
72
|
-
|
42
|
+
If you're using Rails 3, you'll need to modify your Gemfile to use the
|
43
|
+
activerecord-jdbc-adapter gem under JRuby. Change your Gemfile to look
|
44
|
+
like the following (using sqlite3 as an example):
|
73
45
|
|
74
46
|
if defined?(JRUBY_VERSION)
|
75
|
-
gem 'activerecord-jdbc-adapter'
|
76
|
-
gem 'jdbc-sqlite3
|
47
|
+
gem 'activerecord-jdbc-adapter'
|
48
|
+
gem 'jdbc-sqlite3'
|
77
49
|
else
|
78
|
-
gem sqlite3-ruby', :require => 'sqlite3'
|
50
|
+
gem 'sqlite3-ruby', :require => 'sqlite3'
|
79
51
|
end
|
80
52
|
|
81
|
-
|
82
|
-
|
83
|
-
jruby script/rails generate jdbc
|
84
|
-
|
85
|
-
With Rails 2:
|
53
|
+
If you're using Rails 2:
|
86
54
|
|
87
55
|
jruby script/generate jdbc
|
88
|
-
|
89
|
-
The initializer and rake task files generated are guarded such that
|
90
|
-
they won't be loaded if you still run your application under C Ruby.
|
91
|
-
|
92
|
-
Legacy: If you're using Rails prior to version 2.0, you'll need to
|
93
|
-
add one-time setup to your config/environment.rb file in your Rails
|
94
|
-
application. Add the following lines just before the
|
95
|
-
<code>Rails::Initializer</code>. (If you're using
|
96
|
-
activerecord-jdbc-adapter under the old gem name used in versions
|
97
|
-
0.5 and earlier (ActiveRecord-JDBC), replace
|
98
|
-
'activerecord-jdbc-adapter' with 'ActiveRecord-JDBC' below.)
|
99
|
-
|
100
|
-
if RUBY_PLATFORM =~ /java/
|
101
|
-
require 'rubygems'
|
102
|
-
gem 'activerecord-jdbc-adapter'
|
103
|
-
require 'jdbc_adapter'
|
104
|
-
end
|
105
56
|
|
106
57
|
3. Configure your database.yml in the normal Rails style.
|
107
58
|
|
108
|
-
|
109
|
-
|
110
|
-
|
59
|
+
Legacy configuration: If you use one of the convenience
|
60
|
+
'activerecord-jdbcXXX-adapter' adapters, you can still put a 'jdbc'
|
61
|
+
prefix in front of the database adapter name as below.
|
111
62
|
|
112
63
|
development:
|
113
64
|
adapter: jdbcmysql
|
@@ -116,8 +67,8 @@ To use activerecord-jdbc-adapter with JRuby on Rails:
|
|
116
67
|
hostname: localhost
|
117
68
|
database: weblog_development
|
118
69
|
|
119
|
-
|
120
|
-
|
70
|
+
For other databases, you'll need to know the database driver class and
|
71
|
+
URL. Example:
|
121
72
|
|
122
73
|
development:
|
123
74
|
adapter: jdbc
|
@@ -126,11 +77,11 @@ To use activerecord-jdbc-adapter with JRuby on Rails:
|
|
126
77
|
driver: com.mysql.jdbc.Driver
|
127
78
|
url: jdbc:mysql://localhost:3306/weblog_development
|
128
79
|
|
129
|
-
For JNDI data sources, you may simply specify the
|
130
|
-
|
80
|
+
For JNDI data sources, you may simply specify the JNDI location as follows
|
81
|
+
(the adapter will be automatically detected):
|
131
82
|
|
132
83
|
production:
|
133
|
-
adapter:
|
84
|
+
adapter: jdbc
|
134
85
|
jndi: jdbc/mysqldb
|
135
86
|
|
136
87
|
=== Standalone, with ActiveRecord
|
@@ -139,27 +90,19 @@ To use activerecord-jdbc-adapter with JRuby on Rails:
|
|
139
90
|
|
140
91
|
jruby -S gem install activerecord-jdbc-adapter
|
141
92
|
|
142
|
-
|
143
|
-
|
93
|
+
If you wish to use the adapter for a specific database, you can
|
94
|
+
install it directly and a driver gem will be installed as well:
|
144
95
|
|
145
96
|
jruby -S gem install activerecord-jdbcderby-adapter
|
146
97
|
|
147
|
-
2.
|
148
|
-
step. Otherwise, ensure the following code gets executed in your script:
|
149
|
-
|
150
|
-
require 'rubygems'
|
151
|
-
gem 'activerecord-jdbc-adapter'
|
152
|
-
require 'jdbc_adapter'
|
153
|
-
require 'active_record'
|
154
|
-
|
155
|
-
3. After this you can establish a JDBC connection like this:
|
98
|
+
2. After this you can establish a JDBC connection like this:
|
156
99
|
|
157
100
|
ActiveRecord::Base.establish_connection(
|
158
101
|
:adapter => 'jdbcderby',
|
159
102
|
:database => "db/my-database"
|
160
103
|
)
|
161
104
|
|
162
|
-
|
105
|
+
or like this (but requires that you manually put the driver jar on the classpath):
|
163
106
|
|
164
107
|
ActiveRecord::Base.establish_connection(
|
165
108
|
:adapter => 'jdbc',
|
@@ -179,12 +122,22 @@ Please file bug reports at
|
|
179
122
|
http://kenai.com/jira/browse/ACTIVERECORD_JDBC. If you're not sure if
|
180
123
|
something's a bug, feel free to pre-report it on the mailing lists.
|
181
124
|
|
125
|
+
== Project Info
|
126
|
+
|
127
|
+
* Mailing Lists: http://kenai.com/projects/activerecord-jdbc/lists
|
128
|
+
* Issues: http://kenai.com/jira/browse/ACTIVERECORD_JDBC
|
129
|
+
* Source:
|
130
|
+
git://github.com/nicksieger/activerecord-jdbc-adapter.git
|
131
|
+
git://kenai.com/activerecord-jdbc~main
|
132
|
+
|
182
133
|
== Running AR-JDBC's Tests
|
183
134
|
|
184
|
-
Drivers for 6 open-source databases are included. Provided you have
|
185
|
-
installed, you can simply type <tt>jruby -S rake</tt> to run the
|
186
|
-
database named <tt>weblog_development</tt> is needed
|
187
|
-
connection user of "blog" and an empty password.
|
135
|
+
Drivers for 6 open-source databases are included. Provided you have
|
136
|
+
MySQL installed, you can simply type <tt>jruby -S rake</tt> to run the
|
137
|
+
tests. A database named <tt>weblog_development</tt> is needed
|
138
|
+
beforehand with a connection user of "blog" and an empty password. You
|
139
|
+
alse need to grant "blog" create privileges on
|
140
|
+
'test_rake_db_create.*'.
|
188
141
|
|
189
142
|
If you also have PostgreSQL available, those tests will be run if the
|
190
143
|
`psql' executable can be found. Also ensure you have a database named
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'arjdbc/mysql'
|
@@ -1,6 +1,15 @@
|
|
1
1
|
module Arel
|
2
2
|
module SqlCompiler
|
3
3
|
class HsqldbCompiler < GenericCompiler
|
4
|
+
def select_sql
|
5
|
+
# HSQLDB needs to add LIMIT in right after SELECT
|
6
|
+
query = super
|
7
|
+
offset = relation.skipped
|
8
|
+
limit = relation.taken
|
9
|
+
@engine.connection.add_limit_offset!(query, :limit => limit,
|
10
|
+
:offset => offset) if offset || limit
|
11
|
+
query
|
12
|
+
end
|
4
13
|
end
|
5
14
|
end
|
6
15
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Arel
|
2
|
+
module SqlCompiler
|
3
|
+
class MsSQLCompiler < GenericCompiler
|
4
|
+
def select_sql
|
5
|
+
query = super
|
6
|
+
|
7
|
+
offset = relation.skipped
|
8
|
+
limit = relation.taken
|
9
|
+
@engine.connection.add_limit_offset!(query, :limit => limit, :offset => offset) if offset || limit
|
10
|
+
|
11
|
+
query
|
12
|
+
end
|
13
|
+
|
14
|
+
def build_clauses
|
15
|
+
joins = relation.joins(self)
|
16
|
+
wheres = relation.where_clauses
|
17
|
+
groups = relation.group_clauses
|
18
|
+
havings = relation.having_clauses
|
19
|
+
orders = relation.order_clauses
|
20
|
+
|
21
|
+
clauses = [ "",
|
22
|
+
joins,
|
23
|
+
("WHERE #{wheres.join(' AND ')}" unless wheres.empty?),
|
24
|
+
("GROUP BY #{groups.join(', ')}" unless groups.empty?),
|
25
|
+
("HAVING #{havings.join(' AND ')}" unless havings.empty?),
|
26
|
+
("ORDER BY #{orders.join(', ')}" unless orders.empty?)
|
27
|
+
].compact.join ' '
|
28
|
+
|
29
|
+
clauses << " #{locked}" unless locked.blank?
|
30
|
+
clauses unless clauses.blank?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/arjdbc/db2/adapter.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module ArJdbc
|
2
2
|
module DB2
|
3
|
-
def self.
|
4
|
-
|
5
|
-
|
3
|
+
def self.column_selector
|
4
|
+
[ /(db2|as400)/i,
|
5
|
+
lambda { |cfg, column| column.extend(::ArJdbc::DB2::Column) } ]
|
6
6
|
end
|
7
7
|
|
8
8
|
module Column
|
@@ -13,48 +13,114 @@ module ArJdbc
|
|
13
13
|
when :integer then defined?(value.to_i) ? value.to_i : (value ? 1 : 0)
|
14
14
|
when :primary_key then defined?(value.to_i) ? value.to_i : (value ? 1 : 0)
|
15
15
|
when :float then value.to_f
|
16
|
-
when :datetime then cast_to_date_or_time(value)
|
17
|
-
when :
|
18
|
-
when :
|
19
|
-
|
16
|
+
when :datetime then ArJdbc::DB2::Column.cast_to_date_or_time(value)
|
17
|
+
when :date then ArJdbc::DB2::Column.cast_to_date_or_time(value)
|
18
|
+
when :timestamp then ArJdbc::DB2::Column.cast_to_time(value)
|
19
|
+
when :time then ArJdbc::DB2::Column.cast_to_time(value)
|
20
|
+
# TODO AS400 stores binary strings in EBCDIC (CCSID 65535), need to convert back to ASCII
|
21
|
+
else
|
22
|
+
super
|
20
23
|
end
|
21
24
|
end
|
22
|
-
|
25
|
+
|
26
|
+
def type_cast_code(var_name)
|
27
|
+
case type
|
28
|
+
when :datetime then "ArJdbc::DB2::Column.cast_to_date_or_time(#{var_name})"
|
29
|
+
when :date then "ArJdbc::DB2::Column.cast_to_date_or_time(#{var_name})"
|
30
|
+
when :timestamp then "ArJdbc::DB2::Column.cast_to_time(#{var_name})"
|
31
|
+
when :time then "ArJdbc::DB2::Column.cast_to_time(#{var_name})"
|
32
|
+
else
|
33
|
+
super
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.cast_to_date_or_time(value)
|
23
38
|
return value if value.is_a? Date
|
24
39
|
return nil if value.blank?
|
25
40
|
guess_date_or_time((value.is_a? Time) ? value : cast_to_time(value))
|
26
41
|
end
|
27
42
|
|
28
|
-
def cast_to_time(value)
|
43
|
+
def self.cast_to_time(value)
|
29
44
|
return value if value.is_a? Time
|
30
|
-
|
45
|
+
# AS400 returns a 2 digit year, LUW returns a 4 digit year, so comp = true to help out AS400
|
46
|
+
time_array = ParseDate.parsedate(value, true)
|
31
47
|
time_array[0] ||= 2000; time_array[1] ||= 1; time_array[2] ||= 1;
|
32
48
|
Time.send(ActiveRecord::Base.default_timezone, *time_array) rescue nil
|
33
49
|
end
|
34
50
|
|
35
|
-
def guess_date_or_time(value)
|
51
|
+
def self.guess_date_or_time(value)
|
36
52
|
(value.hour == 0 and value.min == 0 and value.sec == 0) ?
|
37
53
|
Date.new(value.year, value.month, value.day) : value
|
38
54
|
end
|
55
|
+
|
56
|
+
private
|
57
|
+
# <b>DEPRECATED:</b> SMALLINT is now used for boolean field types. Please
|
58
|
+
# convert your tables using DECIMAL(5) for boolean values to SMALLINT instead.
|
59
|
+
def use_decimal5_for_boolean
|
60
|
+
warn "[DEPRECATION] using DECIMAL(5) for boolean is deprecated. Convert your columns to SMALLINT instead."
|
61
|
+
:boolean
|
62
|
+
end
|
63
|
+
|
64
|
+
# http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.apdv.java.doc/doc/rjvjdata.html
|
65
|
+
def simplified_type(field_type)
|
66
|
+
case field_type
|
67
|
+
# old jdbc_db2.rb used decimal(5,0) as boolean
|
68
|
+
when /^smallint/i then :boolean
|
69
|
+
when /^decimal\(5\)$/i then use_decimal5_for_boolean
|
70
|
+
when /^real/i then :float
|
71
|
+
when /^timestamp/i then :datetime
|
72
|
+
else
|
73
|
+
super
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Post process default value from JDBC into a Rails-friendly format (columns{-internal})
|
78
|
+
def default_value(value)
|
79
|
+
# IBM i (AS400) will return an empty string instead of null for no default
|
80
|
+
return nil if value.blank?
|
81
|
+
|
82
|
+
# string defaults are surrounded by single quotes
|
83
|
+
return $1 if value =~ /^'(.*)'$/
|
84
|
+
|
85
|
+
value
|
86
|
+
end
|
39
87
|
end
|
40
88
|
|
41
|
-
def
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
89
|
+
def _execute(sql, name = nil)
|
90
|
+
if ActiveRecord::ConnectionAdapters::JdbcConnection::select?(sql)
|
91
|
+
@connection.execute_query(sql)
|
92
|
+
elsif ActiveRecord::ConnectionAdapters::JdbcConnection::insert?(sql)
|
93
|
+
(@connection.execute_insert(sql) or last_insert_id(sql)).to_i
|
94
|
+
else
|
95
|
+
@connection.execute_update(sql)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# holy moly batman! all this to tell AS400 "yes i am sure"
|
100
|
+
def execute_and_auto_confirm(sql)
|
101
|
+
@connection.execute_update "call qsys.qcmdexc('QSYS/CHGJOB INQMSGRPY(*SYSRPYL)',0000000031.00000)"
|
102
|
+
begin
|
103
|
+
@connection.execute_update "call qsys.qcmdexc('ADDRPYLE SEQNBR(9876) MSGID(CPA32B2) RPY(''I'')',0000000045.00000)"
|
104
|
+
execute sql
|
105
|
+
ensure
|
106
|
+
@connection.execute_update "call qsys.qcmdexc('QSYS/CHGJOB INQMSGRPY(*DFT)',0000000027.00000)"
|
107
|
+
@connection.execute_update "call qsys.qcmdexc('RMVRPYLE SEQNBR(9876)',0000000021.00000) "
|
49
108
|
end
|
50
|
-
|
109
|
+
end
|
110
|
+
|
111
|
+
def last_insert_id(sql)
|
112
|
+
table_name = sql.split(/\s/)[2]
|
113
|
+
result = select(ActiveRecord::Base.send(:sanitize_sql,
|
114
|
+
%[select IDENTITY_VAL_LOCAL() as last_insert_id from #{table_name}],
|
115
|
+
nil))
|
116
|
+
result.last['last_insert_id']
|
51
117
|
end
|
52
118
|
|
53
119
|
def modify_types(tp)
|
54
120
|
tp[:primary_key] = 'int not null generated by default as identity (start with 1) primary key'
|
55
121
|
tp[:string][:limit] = 255
|
56
|
-
tp[:integer]
|
57
|
-
tp[:boolean]
|
122
|
+
tp[:integer] = {:limit => nil}
|
123
|
+
tp[:boolean] = {:name => "smallint"}
|
58
124
|
tp
|
59
125
|
end
|
60
126
|
|
@@ -63,17 +129,24 @@ module ArJdbc
|
|
63
129
|
end
|
64
130
|
|
65
131
|
def add_limit_offset!(sql, options)
|
66
|
-
|
67
|
-
|
132
|
+
limit, offset = options[:limit], options[:offset]
|
133
|
+
if limit && !offset
|
134
|
+
if limit == 1
|
135
|
+
sql << " FETCH FIRST ROW ONLY"
|
136
|
+
else
|
137
|
+
sql << " FETCH FIRST #{sanitize_limit(limit)} ROWS ONLY"
|
138
|
+
end
|
139
|
+
elsif limit && offset
|
68
140
|
sql.gsub!(/SELECT/i, 'SELECT B.* FROM (SELECT A.*, row_number() over () AS internal$rownum FROM (SELECT')
|
69
|
-
sql << ") A ) B WHERE B.internal$rownum > #{offset} AND B.internal$
|
141
|
+
sql << ") A ) B WHERE B.internal$rownum > #{offset} AND B.internal$rown
|
142
|
+
um <= #{sanitize_limit(limit) + offset}"
|
70
143
|
end
|
71
144
|
end
|
72
145
|
|
73
146
|
def pk_and_sequence_for(table)
|
74
147
|
# In JDBC/DB2 side, only upcase names of table and column are handled.
|
75
148
|
keys = super(table.upcase)
|
76
|
-
if keys[0]
|
149
|
+
if keys && keys[0]
|
77
150
|
# In ActiveRecord side, only downcase names of table and column are handled.
|
78
151
|
keys[0] = keys[0].downcase
|
79
152
|
end
|
@@ -85,8 +158,8 @@ module ArJdbc
|
|
85
158
|
end
|
86
159
|
|
87
160
|
def quote(value, column = nil) # :nodoc:
|
88
|
-
if column && column.
|
89
|
-
return value.to_s
|
161
|
+
if column && column.respond_to?(:primary) && column.primary && column.klass != String
|
162
|
+
return value.to_i.to_s
|
90
163
|
end
|
91
164
|
if column && (column.type == :decimal || column.type == :integer) && value
|
92
165
|
return value.to_s
|
@@ -114,26 +187,113 @@ module ArJdbc
|
|
114
187
|
'0'
|
115
188
|
end
|
116
189
|
|
117
|
-
def
|
118
|
-
|
119
|
-
|
120
|
-
unless do_not_drop.include?(table)
|
121
|
-
drop_table(table)
|
122
|
-
end
|
190
|
+
def reorg_table(table_name)
|
191
|
+
unless as400?
|
192
|
+
@connection.execute_update "call sysproc.admin_cmd ('REORG TABLE #{table_name}')"
|
123
193
|
end
|
124
194
|
end
|
125
195
|
|
196
|
+
def recreate_database(name)
|
197
|
+
tables.each {|table| drop_table("#{db2_schema}.#{table}")}
|
198
|
+
end
|
199
|
+
|
126
200
|
def remove_index(table_name, options = { })
|
127
201
|
execute "DROP INDEX #{quote_column_name(index_name(table_name, options))}"
|
128
202
|
end
|
129
203
|
|
130
|
-
#
|
131
|
-
#
|
204
|
+
# http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.admin.dbobj.doc/doc/t0020130.html
|
205
|
+
# ...not supported on IBM i, so we raise in this case
|
206
|
+
def rename_column(table_name, column_name, new_column_name) #:nodoc:
|
207
|
+
if as400?
|
208
|
+
raise NotImplementedError, "rename_column is not supported on IBM i"
|
209
|
+
else
|
210
|
+
execute "ALTER TABLE #{table_name} RENAME COLUMN #{column_name} TO #{new_column_name}"
|
211
|
+
reorg_table(table_name)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def change_column_null(table_name, column_name, null)
|
216
|
+
if null
|
217
|
+
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} DROP NOT NULL"
|
218
|
+
else
|
219
|
+
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET NOT NULL"
|
220
|
+
end
|
221
|
+
reorg_table(table_name)
|
222
|
+
end
|
223
|
+
|
224
|
+
def change_column_default(table_name, column_name, default)
|
225
|
+
if default.nil?
|
226
|
+
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} DROP DEFAULT"
|
227
|
+
else
|
228
|
+
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET WITH DEFAULT #{quote(default)}"
|
229
|
+
end
|
230
|
+
reorg_table(table_name)
|
231
|
+
end
|
232
|
+
|
233
|
+
def change_column(table_name, column_name, type, options = {})
|
234
|
+
data_type = type_to_sql(type, options[:limit], options[:precision], options[:scale])
|
235
|
+
sql = "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET DATA TYPE #{data_type}"
|
236
|
+
as400? ? execute_and_auto_confirm(sql) : execute(sql)
|
237
|
+
reorg_table(table_name)
|
238
|
+
|
239
|
+
if options.include?(:default) and options.include?(:null)
|
240
|
+
# which to run first?
|
241
|
+
if options[:null] or options[:default].nil?
|
242
|
+
change_column_null(table_name, column_name, options[:null])
|
243
|
+
change_column_default(table_name, column_name, options[:default])
|
244
|
+
else
|
245
|
+
change_column_default(table_name, column_name, options[:default])
|
246
|
+
change_column_null(table_name, column_name, options[:null])
|
247
|
+
end
|
248
|
+
elsif options.include?(:default)
|
249
|
+
change_column_default(table_name, column_name, options[:default])
|
250
|
+
elsif options.include?(:null)
|
251
|
+
change_column_null(table_name, column_name, options[:null])
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
# http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.admin.dbobj.doc/doc/t0020132.html
|
256
|
+
def remove_column(table_name, column_name) #:nodoc:
|
257
|
+
sql = "ALTER TABLE #{table_name} DROP COLUMN #{column_name}"
|
258
|
+
|
259
|
+
as400? ? execute_and_auto_confirm(sql) : execute(sql)
|
260
|
+
reorg_table(table_name)
|
261
|
+
end
|
262
|
+
|
263
|
+
# http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.ref.doc/doc/r0000980.html
|
264
|
+
def rename_table(name, new_name) #:nodoc:
|
265
|
+
execute "RENAME TABLE #{name} TO #{new_name}"
|
266
|
+
reorg_table(table_name)
|
267
|
+
end
|
268
|
+
|
269
|
+
def tables
|
270
|
+
@connection.tables(nil, db2_schema, nil, ["TABLE"])
|
271
|
+
end
|
272
|
+
|
273
|
+
# only record precision and scale for types that can set
|
274
|
+
# them via CREATE TABLE:
|
275
|
+
# http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.ref.doc/doc/r0000927.html
|
276
|
+
HAVE_LIMIT = %w(FLOAT DECFLOAT CHAR VARCHAR CLOB BLOB NCHAR NCLOB DBCLOB GRAPHIC VARGRAPHIC) #TIMESTAMP
|
277
|
+
HAVE_PRECISION = %w(DECIMAL NUMERIC)
|
278
|
+
HAVE_SCALE = %w(DECIMAL NUMERIC)
|
279
|
+
|
132
280
|
def columns(table_name, name = nil)
|
133
|
-
|
134
|
-
|
135
|
-
|
281
|
+
cols = @connection.columns(table_name, name, db2_schema)
|
282
|
+
|
283
|
+
# scrub out sizing info when CREATE TABLE doesn't support it
|
284
|
+
# but JDBC reports it (doh!)
|
285
|
+
for col in cols
|
286
|
+
base_sql_type = col.sql_type.sub(/\(.*/, "").upcase
|
287
|
+
col.limit = nil unless HAVE_LIMIT.include?(base_sql_type)
|
288
|
+
col.precision = nil unless HAVE_PRECISION.include?(base_sql_type)
|
289
|
+
#col.scale = nil unless HAVE_SCALE.include?(base_sql_type)
|
136
290
|
end
|
291
|
+
|
292
|
+
cols
|
293
|
+
end
|
294
|
+
|
295
|
+
def indexes(table_name, name = nil)
|
296
|
+
@connection.indexes(table_name, name, db2_schema)
|
137
297
|
end
|
138
298
|
|
139
299
|
def add_quotes(name)
|
@@ -152,27 +312,39 @@ module ArJdbc
|
|
152
312
|
name.gsub(/"/,'""')
|
153
313
|
end
|
154
314
|
|
155
|
-
|
156
315
|
def structure_dump #:nodoc:
|
157
316
|
definition=""
|
158
|
-
rs = @connection.connection.meta_data.getTables(nil,
|
317
|
+
rs = @connection.connection.meta_data.getTables(nil,db2_schema.upcase,nil,["TABLE"].to_java(:string))
|
159
318
|
while rs.next
|
160
319
|
tname = rs.getString(3)
|
161
320
|
definition << "CREATE TABLE #{tname} (\n"
|
162
|
-
rs2 = @connection.connection.meta_data.getColumns(nil,
|
321
|
+
rs2 = @connection.connection.meta_data.getColumns(nil,db2_schema.upcase,tname,nil)
|
163
322
|
first_col = true
|
164
323
|
while rs2.next
|
165
324
|
col_name = add_quotes(rs2.getString(4));
|
166
325
|
default = ""
|
167
326
|
d1 = rs2.getString(13)
|
168
|
-
|
327
|
+
# IBM i (as400 toolbox driver) will return an empty string if there is no default
|
328
|
+
if @config[:url] =~ /^jdbc:as400:/
|
329
|
+
default = !d1.blank? ? " DEFAULT #{d1}" : ""
|
330
|
+
else
|
331
|
+
default = d1 ? " DEFAULT #{d1}" : ""
|
332
|
+
end
|
169
333
|
|
170
334
|
type = rs2.getString(6)
|
171
|
-
|
335
|
+
col_precision = rs2.getString(7)
|
336
|
+
col_scale = rs2.getString(9)
|
337
|
+
col_size = ""
|
338
|
+
if HAVE_SCALE.include?(type) and col_scale
|
339
|
+
col_size = "(#{col_precision},#{col_scale})"
|
340
|
+
elsif (HAVE_LIMIT + HAVE_PRECISION).include?(type) and col_precision
|
341
|
+
col_size = "(#{col_precision})"
|
342
|
+
end
|
172
343
|
nulling = (rs2.getString(18) == 'NO' ? " NOT NULL" : "")
|
173
344
|
create_col_string = add_quotes(expand_double_quotes(strip_quotes(col_name))) +
|
174
345
|
" " +
|
175
346
|
type +
|
347
|
+
col_size +
|
176
348
|
"" +
|
177
349
|
nulling +
|
178
350
|
default
|
@@ -191,16 +363,24 @@ module ArJdbc
|
|
191
363
|
definition
|
192
364
|
end
|
193
365
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
366
|
+
private
|
367
|
+
def as400?
|
368
|
+
@config[:url] =~ /^jdbc:as400:/
|
369
|
+
end
|
370
|
+
|
371
|
+
def db2_schema
|
372
|
+
if @config[:schema].blank?
|
373
|
+
if as400?
|
374
|
+
# AS400 implementation takes schema from library name (last part of url)
|
375
|
+
schema = @config[:url].split('/').last.strip
|
376
|
+
(schema[-1..-1] == ";") ? schema.chop : schema
|
377
|
+
else
|
378
|
+
# LUW implementation uses schema name of username by default
|
379
|
+
@config[:username] or ENV['USER']
|
199
380
|
end
|
200
|
-
|
201
|
-
|
381
|
+
else
|
382
|
+
@config[:schema]
|
202
383
|
end
|
203
384
|
end
|
204
|
-
|
205
385
|
end
|
206
386
|
end
|