activerecord-jdbc-adapter 1.0.0.beta1-java → 1.0.0.beta2-java
Sign up to get free protection for your applications and to get access to all the features.
- 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
|