activerecord-jdbc-adapter 0.8.2 → 0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +22 -1
- data/Manifest.txt +5 -0
- data/README.txt +45 -16
- data/Rakefile +8 -2
- data/lib/active_record/connection_adapters/informix_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/jdbc_adapter.rb +59 -15
- data/lib/active_record/connection_adapters/jdbc_adapter_spec.rb +1 -0
- data/lib/jdbc_adapter/jdbc.rake +16 -3
- data/lib/jdbc_adapter/jdbc_adapter_internal.jar +0 -0
- data/lib/jdbc_adapter/jdbc_cachedb.rb +0 -0
- data/lib/jdbc_adapter/jdbc_hsqldb.rb +11 -6
- data/lib/jdbc_adapter/jdbc_informix.rb +148 -0
- data/lib/jdbc_adapter/jdbc_oracle.rb +44 -15
- data/lib/jdbc_adapter/jdbc_postgre.rb +56 -41
- data/lib/jdbc_adapter/version.rb +2 -2
- data/src/java/jdbc_adapter/JdbcAdapterInternalService.java +15 -7
- data/test/db/cachedb.rb +0 -0
- data/test/db/h2.rb +3 -0
- data/test/db/informix.rb +11 -0
- data/test/informix_simple_test.rb +48 -0
- data/test/jdbc_common.rb +4 -2
- data/test/jndi_callbacks_test.rb +38 -0
- data/test/manualTestDatabase.rb +0 -0
- data/test/simple.rb +2 -0
- metadata +9 -4
data/History.txt
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
== 0.9
|
2
|
+
|
3
|
+
- Now updated to support ActiveRecord 2.2. JNDI-based connections will
|
4
|
+
automatically connect/disconnect for every AR connection pool
|
5
|
+
checkout/checkin. For best results, set your pool: parameter >= the
|
6
|
+
actual maximum size of the JNDI connection pool. (We'll look at how
|
7
|
+
to eliminate the need to configure AR's pool in the future.)
|
8
|
+
- NEW! Informix support courtesy of Javier Fernandez-Ivern.
|
9
|
+
- Backport another Oracle CLOB issue, thanks Edson C�sar.
|
10
|
+
- Rubyforge #22018: chomp final trailing semicolon for oracle
|
11
|
+
- JRUBY-2848: Fix NPE error in set_native_database_types
|
12
|
+
- Rework oracle lob saving callback to be Rails 2.1 friendly (assist
|
13
|
+
from court3nay)
|
14
|
+
- JRUBY-2715: Add create/drop database methods to Postgres (Peter Williams)
|
15
|
+
- JRUBY-3183: Fix structure dump for Postgres (Ryan Bell)
|
16
|
+
- JRUBY-3184: recreate_database for test database working for PG (Ryan Bell)
|
17
|
+
- JRUBY-3186: disable referential integrity for PG (Ryan Bell)
|
18
|
+
- Authoritative repository now hosted at
|
19
|
+
git://github.com/nicksieger/activerecord-jdbc-adapter.git; rubyforge
|
20
|
+
svn trunk cleaned out.
|
21
|
+
|
1
22
|
== 0.8.2
|
2
23
|
|
3
24
|
- Added an optional config key called :dialect. Using :dialect allows you to
|
@@ -145,4 +166,4 @@
|
|
145
166
|
|
146
167
|
== 0.0.1
|
147
168
|
|
148
|
-
- Initial, very alpha release
|
169
|
+
- Initial, very alpha release
|
data/Manifest.txt
CHANGED
@@ -7,6 +7,7 @@ lib/active_record/connection_adapters/cachedb_adapter.rb
|
|
7
7
|
lib/active_record/connection_adapters/derby_adapter.rb
|
8
8
|
lib/active_record/connection_adapters/h2_adapter.rb
|
9
9
|
lib/active_record/connection_adapters/hsqldb_adapter.rb
|
10
|
+
lib/active_record/connection_adapters/informix_adapter.rb
|
10
11
|
lib/active_record/connection_adapters/jdbc_adapter.rb
|
11
12
|
lib/active_record/connection_adapters/jdbc_adapter_spec.rb
|
12
13
|
lib/active_record/connection_adapters/jndi_adapter.rb
|
@@ -19,6 +20,7 @@ lib/jdbc_adapter/jdbc_db2.rb
|
|
19
20
|
lib/jdbc_adapter/jdbc_derby.rb
|
20
21
|
lib/jdbc_adapter/jdbc_firebird.rb
|
21
22
|
lib/jdbc_adapter/jdbc_hsqldb.rb
|
23
|
+
lib/jdbc_adapter/jdbc_informix.rb
|
22
24
|
lib/jdbc_adapter/jdbc_mimer.rb
|
23
25
|
lib/jdbc_adapter/jdbc_mssql.rb
|
24
26
|
lib/jdbc_adapter/jdbc_mysql.rb
|
@@ -40,6 +42,7 @@ test/db/db2.rb
|
|
40
42
|
test/db/derby.rb
|
41
43
|
test/db/h2.rb
|
42
44
|
test/db/hsqldb.rb
|
45
|
+
test/db/informix.rb
|
43
46
|
test/db/jdbc.rb
|
44
47
|
test/db/jndi_config.rb
|
45
48
|
test/db/logger.rb
|
@@ -55,9 +58,11 @@ test/generic_jdbc_connection_test.rb
|
|
55
58
|
test/h2_simple_test.rb
|
56
59
|
test/has_many_through.rb
|
57
60
|
test/hsqldb_simple_test.rb
|
61
|
+
test/informix_simple_test.rb
|
58
62
|
test/jdbc_adapter/jdbc_db2_test.rb
|
59
63
|
test/jdbc_adapter/jdbc_sybase_test.rb
|
60
64
|
test/jdbc_common.rb
|
65
|
+
test/jndi_callbacks_test.rb
|
61
66
|
test/jndi_test.rb
|
62
67
|
test/manualTestDatabase.rb
|
63
68
|
test/minirunit/testConnect.rb
|
data/README.txt
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
activerecord-jdbc-adapter is a database adapter for Rails' ActiveRecord
|
2
|
+
component that can be used with JRuby[http://www.jruby.org/]. It allows use of
|
3
|
+
virtually any JDBC-compliant database with your JRuby on Rails application.
|
4
4
|
|
5
5
|
== Databases
|
6
6
|
|
@@ -27,16 +27,21 @@ What's there, and what is not there:
|
|
27
27
|
* HSQLDB - Complete
|
28
28
|
* H2 - Complete
|
29
29
|
* SQLite3 - work in progress
|
30
|
+
* Informix - Fairly complete support, all tests pass and migrations appear to work. Comments welcome.
|
30
31
|
|
31
|
-
Other databases will require testing and likely a custom configuration module.
|
32
|
+
Other databases will require testing and likely a custom configuration module.
|
33
|
+
Please join the jruby-extras
|
34
|
+
mailing-list[http://rubyforge.org/mail/?group_id=2014] to help us discover
|
35
|
+
support for more databases.
|
32
36
|
|
33
37
|
== Using ActiveRecord JDBC
|
34
38
|
|
35
39
|
=== Inside Rails
|
36
40
|
|
37
|
-
To use
|
41
|
+
To use activerecord-jdbc-adapter with JRuby on Rails:
|
38
42
|
|
39
|
-
1. Choose the adapter you wish to gem install.
|
43
|
+
1. Choose the adapter you wish to gem install. The following pre-packaged
|
44
|
+
adapters are available:
|
40
45
|
|
41
46
|
* 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.
|
42
47
|
* mysql (<tt>activerecord-jdbcmysql-adapter</tt>)
|
@@ -45,7 +50,12 @@ To use ActiveRecord-JDBC with JRuby on Rails:
|
|
45
50
|
* hsqldb (<tt>activerecord-jdbchsqldb-adapter</tt>)
|
46
51
|
* h2 (<tt>activerecord-jdbch2-adapter</tt>)
|
47
52
|
|
48
|
-
2. If you're using Rails 2.0, you may skip to the next step. For Rails prior to
|
53
|
+
2. If you're using Rails 2.0, you may skip to the next step. For Rails prior to
|
54
|
+
version 2.0, you'll need to add one-time setup to your config/environment.rb
|
55
|
+
file in your Rails application. Add the following lines just before the
|
56
|
+
<code>Rails::Initializer</code>. (If you're using activerecord-jdbc-adapter
|
57
|
+
under the old gem name used in versions 0.5 and earlier (ActiveRecord-JDBC),
|
58
|
+
replace 'activerecord-jdbc-adapter' with 'ActiveRecord-JDBC' below.)
|
49
59
|
|
50
60
|
if RUBY_PLATFORM =~ /java/
|
51
61
|
require 'rubygems'
|
@@ -53,8 +63,11 @@ To use ActiveRecord-JDBC with JRuby on Rails:
|
|
53
63
|
require 'jdbc_adapter'
|
54
64
|
end
|
55
65
|
|
56
|
-
3. Configure your database.yml to use the <code>jdbc</code> adapter.
|
57
|
-
|
66
|
+
3. Configure your database.yml to use the <code>jdbc</code> adapter. For mysql,
|
67
|
+
postgres, derby, oracle, hsqldb, h2, and informix you can simply configure
|
68
|
+
the database in the normal Rails style. If you use one of the convenience
|
69
|
+
'activerecord-jdbcXXX-adapter' adapters, be sure and put a 'jdbc' prefix in
|
70
|
+
front of the databas adapter name as below.
|
58
71
|
|
59
72
|
development:
|
60
73
|
adapter: jdbcmysql
|
@@ -63,7 +76,8 @@ For mysql, postgres, derby, oracle, hsqldb and h2 you can simply configure the d
|
|
63
76
|
hostname: localhost
|
64
77
|
database: weblog_development
|
65
78
|
|
66
|
-
For other databases, you'll need to know the database driver class and URL.
|
79
|
+
For other databases, you'll need to know the database driver class and URL.
|
80
|
+
Example:
|
67
81
|
|
68
82
|
development:
|
69
83
|
adapter: jdbc
|
@@ -78,11 +92,13 @@ For other databases, you'll need to know the database driver class and URL. Exa
|
|
78
92
|
|
79
93
|
jruby -S gem install activerecord-jdbc-adapter
|
80
94
|
|
81
|
-
If you wish to use the adapter for a specific database, you can install it
|
95
|
+
If you wish to use the adapter for a specific database, you can install it
|
96
|
+
directly and a driver gem will be installed as well:
|
82
97
|
|
83
98
|
jruby -S gem install activerecord-jdbcderby-adapter
|
84
99
|
|
85
|
-
2. If using ActiveRecord 2.0 (Rails 2.0) or greater, you can skip to the next
|
100
|
+
2. If using ActiveRecord 2.0 (Rails 2.0) or greater, you can skip to the next
|
101
|
+
step. Otherwise, ensure the following code gets executed in your script:
|
86
102
|
|
87
103
|
require 'rubygems'
|
88
104
|
gem 'activerecord-jdbc-adapter'
|
@@ -104,16 +120,29 @@ For other databases, you'll need to know the database driver class and URL. Exa
|
|
104
120
|
:url => 'jdbc:derby:test_ar;create=true'
|
105
121
|
)
|
106
122
|
|
123
|
+
== Getting the source
|
124
|
+
|
125
|
+
The source for activerecord-jdbc-adapter is available using git.
|
126
|
+
|
127
|
+
git clone git://github.com/nicksieger/activerecord-jdbc-adapter.git
|
128
|
+
|
107
129
|
== Running AR-JDBC's Tests
|
108
130
|
|
109
|
-
Drivers for 4 open-source databases are included.
|
131
|
+
Drivers for 4 open-source databases are included. Provided you have MySQL
|
132
|
+
installed, you can simply type <tt>jruby -S rake</tt> to run the tests. A
|
133
|
+
database named <tt>weblog_development</tt> is needed beforehand with a
|
134
|
+
connection user of "blog" and password empty.
|
110
135
|
|
111
136
|
== Authors
|
112
137
|
|
113
|
-
This project was written by Nick Sieger <nick@nicksieger.com> and Ola Bini
|
138
|
+
This project was written by Nick Sieger <nick@nicksieger.com> and Ola Bini
|
139
|
+
<olabini@gmail.com> with lots of help from the JRuby community.
|
114
140
|
|
115
141
|
== License
|
116
142
|
|
117
|
-
|
143
|
+
activerecord-jdbc-adapter is released under a BSD license. See the LICENSE file
|
144
|
+
included with the distribution for details.
|
118
145
|
|
119
|
-
Open-source driver gems for
|
146
|
+
Open-source driver gems for activerecord-jdbc-adapter are licensed under the
|
147
|
+
same license the database's drivers are licensed. See each driver gem's
|
148
|
+
LICENSE.txt file for details.
|
data/Rakefile
CHANGED
@@ -53,7 +53,7 @@ FileList['drivers/*'].each do |d|
|
|
53
53
|
end
|
54
54
|
|
55
55
|
Rake::TestTask.new(:test_jdbc) do |t|
|
56
|
-
t.test_files = FileList['test/generic_jdbc_connection_test.rb']
|
56
|
+
t.test_files = FileList['test/generic_jdbc_connection_test.rb', 'test/jndi_callbacks_test.rb']
|
57
57
|
t.libs << 'test' << 'drivers/mysql/lib'
|
58
58
|
end
|
59
59
|
|
@@ -89,6 +89,12 @@ Rake::TestTask.new(:test_mssql) do | t |
|
|
89
89
|
t.libs << 'test'
|
90
90
|
end
|
91
91
|
|
92
|
+
# Ensure that the Informix driver is on your classpath before launching rake
|
93
|
+
Rake::TestTask.new(:test_informix) do |t|
|
94
|
+
t.test_files = FileList[ 'test/informix_simple_test.rb' ]
|
95
|
+
t.libs << 'test'
|
96
|
+
end
|
97
|
+
|
92
98
|
# Tests for JDBC adapters that don't require a database.
|
93
99
|
Rake::TestTask.new(:test_jdbc_adapters) do | t |
|
94
100
|
t.test_files = FileList[ 'test/jdbc_adapter/jdbc_sybase_test.rb' ]
|
@@ -170,4 +176,4 @@ end
|
|
170
176
|
end
|
171
177
|
|
172
178
|
require 'rake/clean'
|
173
|
-
CLEAN.include 'derby*', 'test.db.*','test/reports', 'test.sqlite3','lib/**/*.jar','manifest.mf'
|
179
|
+
CLEAN.include 'derby*', 'test.db.*','test/reports', 'test.sqlite3','lib/**/*.jar','manifest.mf', '*.log'
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'active_record/connection_adapters/jdbc_adapter'
|
@@ -124,6 +124,7 @@ module ActiveRecord
|
|
124
124
|
lambda {|r| r['type_name'] =~ /^varchar$/i},
|
125
125
|
lambda {|r| r['type_name'] =~ /varying/i}],
|
126
126
|
:text => [ lambda {|r| [Jdbc::Types::LONGVARCHAR, Jdbc::Types::CLOB].include?(r['data_type'].to_i)},
|
127
|
+
lambda {|r| r['type_name'] =~ /^text$/i}, # For Informix
|
127
128
|
lambda {|r| r['type_name'] =~ /^(text|clob)$/i},
|
128
129
|
lambda {|r| r['type_name'] =~ /^character large object$/i},
|
129
130
|
lambda {|r| r['sql_data_type'] == 2005}],
|
@@ -156,6 +157,7 @@ module ActiveRecord
|
|
156
157
|
lambda {|r| r['type_name'] =~ /^integer/i}], #Num of milliseconds for SQLite3 JDBC Driver
|
157
158
|
:time => [ lambda {|r| Jdbc::Types::TIME == r['data_type'].to_i},
|
158
159
|
lambda {|r| r['type_name'] =~ /^time$/i},
|
160
|
+
lambda {|r| r['type_name'] =~ /^datetime/i}, # For Informix
|
159
161
|
lambda {|r| r['type_name'] =~ /^date/i},
|
160
162
|
lambda {|r| r['type_name'] =~ /^integer/i}], #Num of milliseconds for SQLite3 JDBC Driver
|
161
163
|
:date => [ lambda {|r| Jdbc::Types::DATE == r['data_type'].to_i},
|
@@ -372,6 +374,10 @@ module ActiveRecord
|
|
372
374
|
end
|
373
375
|
end
|
374
376
|
|
377
|
+
def jndi_connection?
|
378
|
+
@jndi_connection
|
379
|
+
end
|
380
|
+
|
375
381
|
private
|
376
382
|
def configure_jndi
|
377
383
|
jndi = @config[:jndi].to_s
|
@@ -383,6 +389,7 @@ module ActiveRecord
|
|
383
389
|
unless @config[:driver]
|
384
390
|
@config[:driver] = connection.meta_data.connection.java_class.name
|
385
391
|
end
|
392
|
+
@jndi_connection = true
|
386
393
|
end
|
387
394
|
|
388
395
|
def configure_jdbc
|
@@ -407,32 +414,68 @@ module ActiveRecord
|
|
407
414
|
jdbc_driver.connection(url, user, pass)
|
408
415
|
end
|
409
416
|
end
|
410
|
-
|
411
417
|
end
|
412
418
|
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
+
class JdbcAdapter < AbstractAdapter
|
420
|
+
module ShadowCoreMethods
|
421
|
+
def alias_chained_method(meth, feature, target)
|
422
|
+
if instance_methods.include?("#{meth}_without_#{feature}")
|
423
|
+
alias_method "#{meth}_without_#{feature}".to_sym, target
|
424
|
+
else
|
425
|
+
alias_method meth, target
|
426
|
+
end
|
419
427
|
end
|
420
428
|
end
|
421
|
-
end
|
422
429
|
|
423
|
-
|
424
|
-
|
425
|
-
|
430
|
+
module CompatibilityMethods
|
431
|
+
def self.needed?(base)
|
432
|
+
!base.instance_methods.include?("quote_table_name")
|
433
|
+
end
|
434
|
+
|
435
|
+
def quote_table_name(name)
|
436
|
+
quote_column_name(name)
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
module ConnectionPoolCallbacks
|
441
|
+
def self.included(base)
|
442
|
+
base.checkin :on_checkin
|
443
|
+
base.checkout :on_checkout
|
444
|
+
end
|
445
|
+
|
446
|
+
def self.needed?
|
447
|
+
ActiveRecord::Base.respond_to?(:connection_pool)
|
448
|
+
end
|
449
|
+
|
450
|
+
def on_checkin
|
451
|
+
# default implementation does nothing
|
452
|
+
end
|
453
|
+
|
454
|
+
def on_checkout
|
455
|
+
# default implementation does nothing
|
456
|
+
end
|
426
457
|
end
|
427
458
|
|
428
|
-
|
429
|
-
|
459
|
+
module JndiConnectionPoolCallbacks
|
460
|
+
def self.prepare(adapter, conn)
|
461
|
+
if ActiveRecord::Base.respond_to?(:connection_pool) && conn.jndi_connection?
|
462
|
+
adapter.extend self
|
463
|
+
conn.disconnect! # disconnect initial connection in JdbcConnection#initialize
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
def on_checkin
|
468
|
+
disconnect!
|
469
|
+
end
|
470
|
+
|
471
|
+
def on_checkout
|
472
|
+
reconnect!
|
473
|
+
end
|
430
474
|
end
|
431
|
-
end
|
432
475
|
|
433
|
-
class JdbcAdapter < AbstractAdapter
|
434
476
|
extend ShadowCoreMethods
|
435
477
|
include CompatibilityMethods if CompatibilityMethods.needed?(self)
|
478
|
+
include ConnectionPoolCallbacks if ConnectionPoolCallbacks.needed?
|
436
479
|
|
437
480
|
attr_reader :config
|
438
481
|
|
@@ -452,6 +495,7 @@ module ActiveRecord
|
|
452
495
|
end
|
453
496
|
end
|
454
497
|
connection.adapter = self
|
498
|
+
JndiConnectionPoolCallbacks.prepare(self, connection)
|
455
499
|
end
|
456
500
|
|
457
501
|
def modify_types(tp)
|
data/lib/jdbc_adapter/jdbc.rake
CHANGED
@@ -64,17 +64,30 @@ namespace :db do
|
|
64
64
|
namespace :test do
|
65
65
|
redefine_task :clone_structure => [ "db:structure:dump", "db:test:purge" ] do
|
66
66
|
abcs = ActiveRecord::Base.configurations
|
67
|
+
abcs['test']['pg_params'] = '?allowEncodingChanges=true' if abcs['test']['adapter'] =~ /postgresql/i
|
67
68
|
ActiveRecord::Base.establish_connection(abcs["test"])
|
68
69
|
ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0') if abcs["test"]["adapter"] =~ /mysql/i
|
69
70
|
IO.readlines("db/#{RAILS_ENV}_structure.sql").join.split(";\n\n").each do |ddl|
|
70
|
-
ActiveRecord::Base.connection.execute(ddl)
|
71
|
+
ActiveRecord::Base.connection.execute(ddl.chomp(';'))
|
71
72
|
end
|
72
73
|
end
|
73
74
|
|
74
75
|
redefine_task :purge => :environment do
|
75
76
|
abcs = ActiveRecord::Base.configurations
|
76
|
-
|
77
|
-
|
77
|
+
config = abcs['test'].dup
|
78
|
+
if config['adapter'] =~ /postgresql/i
|
79
|
+
if config['url']
|
80
|
+
db = config['url'][/\/([^\/]*)$/, 1]
|
81
|
+
config['url'][/\/([^\/]*)$/, 1] if db_name
|
82
|
+
else
|
83
|
+
db = config['database']
|
84
|
+
config['database'] = 'postgres'
|
85
|
+
end
|
86
|
+
ActiveRecord::Base.establish_connection(config)
|
87
|
+
else
|
88
|
+
ActiveRecord::Base.establish_connection(config)
|
89
|
+
db = ActiveRecord::Base.connection.database_name
|
90
|
+
end
|
78
91
|
ActiveRecord::Base.connection.recreate_database(db)
|
79
92
|
end
|
80
93
|
end
|
Binary file
|
File without changes
|
@@ -5,23 +5,26 @@ module ::JdbcSpec
|
|
5
5
|
config[:driver] ||= "org.hsqldb.jdbcDriver"
|
6
6
|
embedded_driver(config)
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
def h2_connection(config)
|
10
10
|
config[:url] ||= "jdbc:h2:#{config[:database]}"
|
11
11
|
config[:driver] ||= "org.h2.Driver"
|
12
12
|
embedded_driver(config)
|
13
13
|
end
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
module HSQLDB
|
17
17
|
def self.column_selector
|
18
18
|
[/hsqldb|\.h2\./i, lambda {|cfg,col| col.extend(::JdbcSpec::HSQLDB::Column)}]
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.adapter_selector
|
22
|
-
[/hsqldb|\.h2\./i, lambda
|
22
|
+
[/hsqldb|\.h2\./i, lambda do |cfg,adapt|
|
23
|
+
adapt.extend(::JdbcSpec::HSQLDB)
|
24
|
+
def adapt.h2_adapter; true; end if cfg[:driver] =~ /\.h2\./
|
25
|
+
end]
|
23
26
|
end
|
24
|
-
|
27
|
+
|
25
28
|
module Column
|
26
29
|
def type_cast(value)
|
27
30
|
return nil if value.nil? || value =~ /^\s*null\s*$/i
|
@@ -93,10 +96,12 @@ module ::JdbcSpec
|
|
93
96
|
|
94
97
|
def quote(value, column = nil) # :nodoc:
|
95
98
|
return value.quoted_id if value.respond_to?(:quoted_id)
|
96
|
-
|
99
|
+
|
97
100
|
case value
|
98
101
|
when String
|
99
|
-
if
|
102
|
+
if respond_to?(:h2_adapter) && value.empty?
|
103
|
+
"NULL"
|
104
|
+
elsif column && column.type == :binary
|
100
105
|
"'#{quote_string(value).unpack("C*").collect {|v| v.to_s(16)}.join}'"
|
101
106
|
else
|
102
107
|
"'#{quote_string(value)}'"
|
@@ -0,0 +1,148 @@
|
|
1
|
+
module ::ActiveRecord
|
2
|
+
class Base
|
3
|
+
after_save :write_lobs
|
4
|
+
|
5
|
+
private
|
6
|
+
def write_lobs
|
7
|
+
if connection.is_a?(JdbcSpec::Informix)
|
8
|
+
self.class.columns.each do |c|
|
9
|
+
if [:text, :binary].include? c.type
|
10
|
+
value = self[c.name]
|
11
|
+
value = value.to_yaml if unserializable_attribute?(c.name, c)
|
12
|
+
|
13
|
+
unless value.nil? || (value == '')
|
14
|
+
connection.write_large_object(c.type == :binary,
|
15
|
+
c.name,
|
16
|
+
self.class.table_name,
|
17
|
+
self.class.primary_key,
|
18
|
+
quote_value(id),
|
19
|
+
value)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module ::JdbcSpec
|
29
|
+
module ActiveRecordExtensions
|
30
|
+
def informix_connection(config)
|
31
|
+
config[:port] ||= 9088
|
32
|
+
config[:url] ||= "jdbc:informix-sqli://#{config[:host]}:#{config[:port]}/#{config[:database]}:INFORMIXSERVER=#{config[:servername]}"
|
33
|
+
config[:driver] = 'com.informix.jdbc.IfxDriver'
|
34
|
+
jdbc_connection(config)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
module Informix
|
39
|
+
def self.extended(base)
|
40
|
+
@@db_major_version = base.select_one("SELECT dbinfo('version', 'major') version FROM systables WHERE tabid = 1")['version'].to_i
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.column_selector
|
44
|
+
[ /informix/i,
|
45
|
+
lambda { |cfg, column| column.extend(::JdbcSpec::Informix::Column) } ]
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.adapter_selector
|
49
|
+
[ /informix/i,
|
50
|
+
lambda { |cfg, adapter| adapter.extend(::JdbcSpec::Informix) } ]
|
51
|
+
end
|
52
|
+
|
53
|
+
module Column
|
54
|
+
private
|
55
|
+
# TODO: Test all Informix column types.
|
56
|
+
def simplified_type(field_type)
|
57
|
+
if field_type =~ /serial/i
|
58
|
+
:primary_key
|
59
|
+
else
|
60
|
+
super
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def modify_types(tp)
|
66
|
+
tp[:primary_key] = "SERIAL PRIMARY KEY"
|
67
|
+
tp[:string] = { :name => "VARCHAR", :limit => 255 }
|
68
|
+
tp[:integer] = { :name => "INTEGER" }
|
69
|
+
tp[:float] = { :name => "FLOAT" }
|
70
|
+
tp[:decimal] = { :name => "DECIMAL" }
|
71
|
+
tp[:datetime] = { :name => "DATETIME YEAR TO FRACTION(5)" }
|
72
|
+
tp[:timestamp] = { :name => "DATETIME YEAR TO FRACTION(5)" }
|
73
|
+
tp[:time] = { :name => "DATETIME HOUR TO FRACTION(5)" }
|
74
|
+
tp[:date] = { :name => "DATE" }
|
75
|
+
tp[:binary] = { :name => "BYTE" }
|
76
|
+
tp[:boolean] = { :name => "BOOLEAN" }
|
77
|
+
tp
|
78
|
+
end
|
79
|
+
|
80
|
+
def prefetch_primary_key?(table_name = nil)
|
81
|
+
true
|
82
|
+
end
|
83
|
+
|
84
|
+
def supports_migrations?
|
85
|
+
true
|
86
|
+
end
|
87
|
+
|
88
|
+
def default_sequence_name(table, column)
|
89
|
+
"#{table}_seq"
|
90
|
+
end
|
91
|
+
|
92
|
+
def add_limit_offset!(sql, options)
|
93
|
+
if options[:limit]
|
94
|
+
limit = "FIRST #{options[:limit]}"
|
95
|
+
# SKIP available only in IDS >= 10
|
96
|
+
offset = (@@db_major_version >= 10 && options[:offset]?
|
97
|
+
"SKIP #{options[:offset]}" : "")
|
98
|
+
sql.sub!(/^select /i, "SELECT #{offset} #{limit} ")
|
99
|
+
end
|
100
|
+
sql
|
101
|
+
end
|
102
|
+
|
103
|
+
def next_sequence_value(sequence_name)
|
104
|
+
select_one("SELECT #{sequence_name}.nextval id FROM systables WHERE tabid=1")['id']
|
105
|
+
end
|
106
|
+
|
107
|
+
# TODO: Add some smart quoting for newlines in string and text fields.
|
108
|
+
def quote_string(string)
|
109
|
+
string.gsub(/\'/, "''")
|
110
|
+
end
|
111
|
+
|
112
|
+
def quote(value, column = nil)
|
113
|
+
if column && [:binary, :text].include?(column.type)
|
114
|
+
# LOBs are updated separately by an after_save trigger.
|
115
|
+
"NULL"
|
116
|
+
elsif column && column.type == :date
|
117
|
+
"'#{value.mon}/#{value.day}/#{value.year}'"
|
118
|
+
else
|
119
|
+
super
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def create_table(name, options = {})
|
124
|
+
super(name, options)
|
125
|
+
execute("CREATE SEQUENCE #{name}_seq")
|
126
|
+
end
|
127
|
+
|
128
|
+
def rename_table(name, new_name)
|
129
|
+
execute("RENAME TABLE #{name} TO #{new_name}")
|
130
|
+
execute("RENAME SEQUENCE #{name}_seq TO #{new_name}_seq")
|
131
|
+
end
|
132
|
+
|
133
|
+
def drop_table(name)
|
134
|
+
super(name)
|
135
|
+
execute("DROP SEQUENCE #{name}_seq")
|
136
|
+
end
|
137
|
+
|
138
|
+
def remove_index(table_name, options = {})
|
139
|
+
@connection.execute_update("DROP INDEX #{index_name(table_name, options)}")
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
def select(sql, name = nil)
|
144
|
+
# Informix does not like "= NULL", "!= NULL", or "<> NULL".
|
145
|
+
execute(sql.gsub(/(!=|<>)\s*null/i, "IS NOT NULL").gsub(/=\s*null/i, "IS NULL"), name)
|
146
|
+
end
|
147
|
+
end # module Informix
|
148
|
+
end # module ::JdbcSpec
|
@@ -1,8 +1,5 @@
|
|
1
1
|
module ::ActiveRecord
|
2
2
|
class Base
|
3
|
-
# After setting large objects to empty, write data back with a helper method
|
4
|
-
alias after_save_without_oracle_lob after_save
|
5
|
-
|
6
3
|
def after_save_with_oracle_lob() #:nodoc:
|
7
4
|
if connection.is_a?(JdbcSpec::Oracle)
|
8
5
|
self.class.columns.select { |c| c.sql_type =~ /LOB\(|LOB$/i }.each { |c|
|
@@ -13,10 +10,7 @@ module ::ActiveRecord
|
|
13
10
|
connection.write_large_object(c.type == :binary, c.name, self.class.table_name, self.class.primary_key, quote_value(id), value)
|
14
11
|
}
|
15
12
|
end
|
16
|
-
after_save_without_oracle_lob
|
17
13
|
end
|
18
|
-
|
19
|
-
alias after_save after_save_with_oracle_lob
|
20
14
|
end
|
21
15
|
end
|
22
16
|
|
@@ -29,8 +23,13 @@ module ::JdbcSpec
|
|
29
23
|
jdbc_connection(config)
|
30
24
|
end
|
31
25
|
end
|
32
|
-
|
26
|
+
|
33
27
|
module Oracle
|
28
|
+
def self.extended(mod)
|
29
|
+
ActiveRecord::Base.after_save :after_save_with_oracle_lob unless @lob_callback_added
|
30
|
+
@lob_callback_added = true
|
31
|
+
end
|
32
|
+
|
34
33
|
def self.column_selector
|
35
34
|
[/oracle/i, lambda {|cfg,col| col.extend(::JdbcSpec::Oracle::Column)}]
|
36
35
|
end
|
@@ -54,17 +53,31 @@ module ::JdbcSpec
|
|
54
53
|
def type_cast(value)
|
55
54
|
return nil if value.nil?
|
56
55
|
case type
|
57
|
-
when :string
|
58
|
-
when :integer
|
56
|
+
when :string then value
|
57
|
+
when :integer then defined?(value.to_i) ? value.to_i : (value ? 1 : 0)
|
59
58
|
when :primary_key then defined?(value.to_i) ? value.to_i : (value ? 1 : 0)
|
60
|
-
when :float
|
61
|
-
when :datetime
|
62
|
-
when :time
|
63
|
-
when :decimal
|
64
|
-
when :boolean
|
59
|
+
when :float then value.to_f
|
60
|
+
when :datetime then JdbcSpec::Oracle::Column.cast_to_date_or_time(value)
|
61
|
+
when :time then JdbcSpec::Oracle::Column.cast_to_time(value)
|
62
|
+
when :decimal then self.class.value_to_decimal(value)
|
63
|
+
when :boolean then self.class.value_to_boolean(value)
|
65
64
|
else value
|
66
65
|
end
|
67
66
|
end
|
67
|
+
|
68
|
+
def type_cast_code(var_name)
|
69
|
+
case type
|
70
|
+
when :string then nil
|
71
|
+
when :integer then "(#{var_name}.to_i rescue #{var_name} ? 1 : 0)"
|
72
|
+
when :primary_key then "(#{var_name}.to_i rescue #{var_name} ? 1 : 0)"
|
73
|
+
when :float then "#{var_name}.to_f"
|
74
|
+
when :datetime then "JdbcSpec::Oracle::Column.cast_to_date_or_time(#{var_name})"
|
75
|
+
when :time then "JdbcSpec::Oracle::Column.cast_to_time(#{var_name})"
|
76
|
+
when :decimal then "#{self.class.name}.value_to_decimal(#{var_name})"
|
77
|
+
when :boolean then "#{self.class.name}.value_to_boolean(#{var_name})"
|
78
|
+
else nil
|
79
|
+
end
|
80
|
+
end
|
68
81
|
|
69
82
|
private
|
70
83
|
def simplified_type(field_type)
|
@@ -188,12 +201,20 @@ module ::JdbcSpec
|
|
188
201
|
execute "ALTER TABLE #{table_name} MODIFY #{column_name} DEFAULT #{quote(default)}"
|
189
202
|
end
|
190
203
|
|
204
|
+
def add_column_options!(sql, options) #:nodoc:
|
205
|
+
# handle case of defaults for CLOB columns, which would otherwise get "quoted" incorrectly
|
206
|
+
if options_include_default?(options) && (column = options[:column]) && column.type == :text
|
207
|
+
sql << " DEFAULT #{quote(options.delete(:default))}"
|
208
|
+
end
|
209
|
+
super
|
210
|
+
end
|
211
|
+
|
191
212
|
def change_column(table_name, column_name, type, options = {}) #:nodoc:
|
192
213
|
change_column_sql = "ALTER TABLE #{table_name} MODIFY #{column_name} #{type_to_sql(type, options[:limit])}"
|
193
214
|
add_column_options!(change_column_sql, options)
|
194
215
|
execute(change_column_sql)
|
195
216
|
end
|
196
|
-
|
217
|
+
|
197
218
|
def rename_column(table_name, column_name, new_column_name) #:nodoc:
|
198
219
|
execute "ALTER TABLE #{table_name} RENAME COLUMN #{column_name} to #{new_column_name}"
|
199
220
|
end
|
@@ -328,6 +349,14 @@ module ::JdbcSpec
|
|
328
349
|
end
|
329
350
|
end
|
330
351
|
|
352
|
+
def quoted_true #:nodoc:
|
353
|
+
'1'
|
354
|
+
end
|
355
|
+
|
356
|
+
def quoted_false #:nodoc:
|
357
|
+
'0'
|
358
|
+
end
|
359
|
+
|
331
360
|
private
|
332
361
|
def select(sql, name=nil)
|
333
362
|
records = execute(sql,name)
|
@@ -7,6 +7,7 @@ module ::JdbcSpec
|
|
7
7
|
config[:host] ||= "localhost"
|
8
8
|
config[:port] ||= 5432
|
9
9
|
config[:url] ||= "jdbc:postgresql://#{config[:host]}:#{config[:port]}/#{config[:database]}"
|
10
|
+
config[:url] << config[:pg_params] if config[:pg_params]
|
10
11
|
config[:driver] ||= "org.postgresql.Driver"
|
11
12
|
jdbc_connection(config)
|
12
13
|
end
|
@@ -20,7 +21,7 @@ module ::JdbcSpec
|
|
20
21
|
def self.adapter_selector
|
21
22
|
[/postgre/i, lambda {|cfg,adapt| adapt.extend(::JdbcSpec::PostgreSQL)}]
|
22
23
|
end
|
23
|
-
|
24
|
+
|
24
25
|
module Column
|
25
26
|
def type_cast(value)
|
26
27
|
case type
|
@@ -30,7 +31,7 @@ module ::JdbcSpec
|
|
30
31
|
end
|
31
32
|
|
32
33
|
def simplified_type(field_type)
|
33
|
-
return :integer if field_type =~ /^serial/i
|
34
|
+
return :integer if field_type =~ /^serial/i
|
34
35
|
return :string if field_type =~ /\[\]$/i || field_type =~ /^interval/i
|
35
36
|
return :string if field_type =~ /^(?:point|lseg|box|"?path"?|polygon|circle)/i
|
36
37
|
return :datetime if field_type =~ /^timestamp/i
|
@@ -39,7 +40,7 @@ module ::JdbcSpec
|
|
39
40
|
return :boolean if field_type =~ /^bool/i
|
40
41
|
super
|
41
42
|
end
|
42
|
-
|
43
|
+
|
43
44
|
def cast_to_boolean(value)
|
44
45
|
if value == true || value == false
|
45
46
|
value
|
@@ -70,16 +71,16 @@ module ::JdbcSpec
|
|
70
71
|
# Boolean types
|
71
72
|
return "t" if value =~ /true/i
|
72
73
|
return "f" if value =~ /false/i
|
73
|
-
|
74
|
+
|
74
75
|
# Char/String/Bytea type values
|
75
76
|
return $1 if value =~ /^'(.*)'::(bpchar|text|character varying|bytea)$/
|
76
|
-
|
77
|
+
|
77
78
|
# Numeric values
|
78
79
|
return value if value =~ /^-?[0-9]+(\.[0-9]*)?/
|
79
|
-
|
80
|
+
|
80
81
|
# Fixed dates / timestamp
|
81
82
|
return $1 if value =~ /^'(.+)'::(date|timestamp)/
|
82
|
-
|
83
|
+
|
83
84
|
# Anything else is blank, some user type, or some function
|
84
85
|
# and we can't know the value of that, so return nil.
|
85
86
|
return nil
|
@@ -93,7 +94,7 @@ module ::JdbcSpec
|
|
93
94
|
tp[:boolean][:limit] = nil
|
94
95
|
tp
|
95
96
|
end
|
96
|
-
|
97
|
+
|
97
98
|
def default_sequence_name(table_name, pk = nil)
|
98
99
|
default_pk, default_seq = pk_and_sequence_for(table_name)
|
99
100
|
default_seq || "#{table_name}_#{pk || default_pk || 'id'}_seq"
|
@@ -216,34 +217,41 @@ module ::JdbcSpec
|
|
216
217
|
Integer(select_value("SELECT currval('#{sequence_name}')"))
|
217
218
|
end
|
218
219
|
|
219
|
-
# the point here is really just to empty the database, not recreate it
|
220
|
-
# so we delete all tables
|
221
220
|
def recreate_database(name)
|
222
|
-
|
221
|
+
drop_database(name)
|
222
|
+
create_database(name)
|
223
223
|
end
|
224
|
-
|
225
|
-
def structure_dump
|
226
|
-
abcs = ActiveRecord::Base.configurations
|
227
224
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
225
|
+
def create_database(name, options = {})
|
226
|
+
execute "CREATE DATABASE \"#{name}\" ENCODING='#{options[:encoding] || 'utf8'}'"
|
227
|
+
end
|
228
|
+
|
229
|
+
def drop_database(name)
|
230
|
+
execute "DROP DATABASE \"#{name}\""
|
231
|
+
end
|
232
|
+
|
233
|
+
def structure_dump
|
234
|
+
database = @config[:database]
|
235
|
+
if database.nil?
|
236
|
+
if @config[:url] =~ /\/([^\/]*)$/
|
237
|
+
database = $1
|
238
|
+
else
|
239
|
+
raise "Could not figure out what database this url is for #{@config["url"]}"
|
240
|
+
end
|
233
241
|
end
|
234
|
-
|
235
|
-
ENV['PGHOST'] =
|
236
|
-
ENV['PGPORT'] =
|
237
|
-
ENV['PGPASSWORD'] =
|
238
|
-
search_path =
|
242
|
+
|
243
|
+
ENV['PGHOST'] = @config[:host] if @config[:host]
|
244
|
+
ENV['PGPORT'] = @config[:port].to_s if @config[:port]
|
245
|
+
ENV['PGPASSWORD'] = @config[:password].to_s if @config[:password]
|
246
|
+
search_path = @config[:schema_search_path]
|
239
247
|
search_path = "--schema=#{search_path}" if search_path
|
240
248
|
|
241
249
|
@connection.connection.close
|
242
250
|
begin
|
243
251
|
file = "db/#{RAILS_ENV}_structure.sql"
|
244
|
-
`pg_dump -i -U "#{
|
252
|
+
`pg_dump -i -U "#{@config[:username]}" -s -x -O -f #{file} #{search_path} #{database}`
|
245
253
|
raise "Error dumping database" if $?.exitstatus == 1
|
246
|
-
|
254
|
+
|
247
255
|
# need to patch away any references to SQL_ASCII as it breaks the JDBC driver
|
248
256
|
lines = File.readlines(file)
|
249
257
|
File.open(file, "w") do |io|
|
@@ -254,9 +262,9 @@ module ::JdbcSpec
|
|
254
262
|
end
|
255
263
|
ensure
|
256
264
|
reconnect!
|
257
|
-
end
|
265
|
+
end
|
258
266
|
end
|
259
|
-
|
267
|
+
|
260
268
|
def _execute(sql, name = nil)
|
261
269
|
case sql.strip
|
262
270
|
when /\A\(?\s*(select|show)/i:
|
@@ -265,7 +273,7 @@ module ::JdbcSpec
|
|
265
273
|
@connection.execute_update(sql)
|
266
274
|
end
|
267
275
|
end
|
268
|
-
|
276
|
+
|
269
277
|
# SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.
|
270
278
|
#
|
271
279
|
# PostgreSQL requires the ORDER BY columns in the select list for distinct queries, and
|
@@ -288,22 +296,22 @@ module ::JdbcSpec
|
|
288
296
|
end
|
289
297
|
|
290
298
|
# ORDER BY clause for the passed order option.
|
291
|
-
#
|
299
|
+
#
|
292
300
|
# PostgreSQL does not allow arbitrary ordering when using DISTINCT ON, so we work around this
|
293
301
|
# by wrapping the sql as a sub-select and ordering in that query.
|
294
302
|
def add_order_by_for_association_limiting!(sql, options)
|
295
303
|
return sql if options[:order].blank?
|
296
|
-
|
304
|
+
|
297
305
|
order = options[:order].split(',').collect { |s| s.strip }.reject(&:blank?)
|
298
306
|
order.map! { |s| 'DESC' if s =~ /\bdesc$/i }
|
299
307
|
order = order.zip((0...order.size).to_a).map { |s,i| "id_list.alias_#{i} #{s}" }.join(', ')
|
300
|
-
|
308
|
+
|
301
309
|
sql.replace "SELECT * FROM (#{sql}) AS id_list ORDER BY #{order}"
|
302
310
|
end
|
303
311
|
|
304
312
|
def quote(value, column = nil)
|
305
313
|
return value.quoted_id if value.respond_to?(:quoted_id)
|
306
|
-
|
314
|
+
|
307
315
|
if value.kind_of?(String) && column && column.type == :binary
|
308
316
|
"'#{escape_bytea(value)}'"
|
309
317
|
elsif column && column.type == :primary_key
|
@@ -320,7 +328,7 @@ module ::JdbcSpec
|
|
320
328
|
result
|
321
329
|
end
|
322
330
|
end
|
323
|
-
|
331
|
+
|
324
332
|
def quote_column_name(name)
|
325
333
|
%("#{name}")
|
326
334
|
end
|
@@ -329,10 +337,17 @@ module ::JdbcSpec
|
|
329
337
|
value.strftime("%Y-%m-%d %H:%M:%S")
|
330
338
|
end
|
331
339
|
|
340
|
+
def disable_referential_integrity(&block) #:nodoc:
|
341
|
+
execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} DISABLE TRIGGER ALL" }.join(";"))
|
342
|
+
yield
|
343
|
+
ensure
|
344
|
+
execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} ENABLE TRIGGER ALL" }.join(";"))
|
345
|
+
end
|
346
|
+
|
332
347
|
def rename_table(name, new_name)
|
333
348
|
execute "ALTER TABLE #{name} RENAME TO #{new_name}"
|
334
349
|
end
|
335
|
-
|
350
|
+
|
336
351
|
def add_column(table_name, column_name, type, options = {})
|
337
352
|
execute("ALTER TABLE #{table_name} ADD #{column_name} #{type_to_sql(type, options[:limit])}")
|
338
353
|
change_column_default(table_name, column_name, options[:default]) unless options[:default].nil?
|
@@ -355,23 +370,23 @@ module ::JdbcSpec
|
|
355
370
|
commit_db_transaction
|
356
371
|
end
|
357
372
|
change_column_default(table_name, column_name, options[:default]) unless options[:default].nil?
|
358
|
-
end
|
359
|
-
|
373
|
+
end
|
374
|
+
|
360
375
|
def change_column_default(table_name, column_name, default) #:nodoc:
|
361
376
|
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET DEFAULT '#{default}'"
|
362
377
|
end
|
363
|
-
|
378
|
+
|
364
379
|
def rename_column(table_name, column_name, new_column_name) #:nodoc:
|
365
380
|
execute "ALTER TABLE #{table_name} RENAME COLUMN #{column_name} TO #{new_column_name}"
|
366
381
|
end
|
367
|
-
|
382
|
+
|
368
383
|
def remove_index(table_name, options) #:nodoc:
|
369
384
|
execute "DROP INDEX #{index_name(table_name, options)}"
|
370
385
|
end
|
371
386
|
|
372
387
|
def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc:
|
373
388
|
return super unless type.to_s == 'integer'
|
374
|
-
|
389
|
+
|
375
390
|
if limit.nil? || limit == 4
|
376
391
|
'integer'
|
377
392
|
elsif limit < 4
|
@@ -384,5 +399,5 @@ module ::JdbcSpec
|
|
384
399
|
def tables
|
385
400
|
@connection.tables(database_name, nil, nil, ["TABLE"])
|
386
401
|
end
|
387
|
-
end
|
402
|
+
end
|
388
403
|
end
|
data/lib/jdbc_adapter/version.rb
CHANGED
@@ -235,7 +235,7 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
|
|
235
235
|
Throwable toWrap = null;
|
236
236
|
boolean autoCommit = false;
|
237
237
|
while (i < tries) {
|
238
|
-
Connection c = getConnection(recv);
|
238
|
+
Connection c = getConnection(recv, true);
|
239
239
|
try {
|
240
240
|
autoCommit = c.getAutoCommit();
|
241
241
|
return block.call(c);
|
@@ -370,7 +370,7 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
|
|
370
370
|
@JRubyMethod(name = "set_native_database_types")
|
371
371
|
public static IRubyObject set_native_database_types(IRubyObject recv) throws SQLException, IOException {
|
372
372
|
Ruby runtime = recv.getRuntime();
|
373
|
-
IRubyObject types = unmarshal_result_downcase(recv, getConnection(recv).getMetaData().getTypeInfo());
|
373
|
+
IRubyObject types = unmarshal_result_downcase(recv, getConnection(recv, true).getMetaData().getTypeInfo());
|
374
374
|
IRubyObject typeConverter = ((RubyModule) (runtime.getModule("ActiveRecord").getConstant("ConnectionAdapters"))).getConstant("JdbcTypeConverter");
|
375
375
|
IRubyObject value = rubyApi.callMethod(rubyApi.callMethod(typeConverter, "new", types), "choose_best_types");
|
376
376
|
rubyApi.setInstanceVariable(recv, "@native_types", value);
|
@@ -379,9 +379,9 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
|
|
379
379
|
|
380
380
|
@JRubyMethod(name = "database_name")
|
381
381
|
public static IRubyObject database_name(IRubyObject recv) throws SQLException {
|
382
|
-
String name = getConnection(recv).getCatalog();
|
382
|
+
String name = getConnection(recv, true).getCatalog();
|
383
383
|
if(null == name) {
|
384
|
-
name = getConnection(recv).getMetaData().getUserName();
|
384
|
+
name = getConnection(recv, true).getMetaData().getUserName();
|
385
385
|
if(null == name) {
|
386
386
|
name = "db1";
|
387
387
|
}
|
@@ -391,13 +391,13 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
|
|
391
391
|
|
392
392
|
@JRubyMethod(name = "begin")
|
393
393
|
public static IRubyObject begin(IRubyObject recv) throws SQLException {
|
394
|
-
getConnection(recv).setAutoCommit(false);
|
394
|
+
getConnection(recv, true).setAutoCommit(false);
|
395
395
|
return recv.getRuntime().getNil();
|
396
396
|
}
|
397
397
|
|
398
398
|
@JRubyMethod(name = "commit")
|
399
399
|
public static IRubyObject commit(IRubyObject recv) throws SQLException {
|
400
|
-
Connection c = getConnection(recv);
|
400
|
+
Connection c = getConnection(recv, true);
|
401
401
|
if (!c.getAutoCommit()) {
|
402
402
|
try {
|
403
403
|
c.commit();
|
@@ -410,7 +410,7 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
|
|
410
410
|
|
411
411
|
@JRubyMethod(name = "rollback")
|
412
412
|
public static IRubyObject rollback(IRubyObject recv) throws SQLException {
|
413
|
-
Connection c = getConnection(recv);
|
413
|
+
Connection c = getConnection(recv, true);
|
414
414
|
if (!c.getAutoCommit()) {
|
415
415
|
try {
|
416
416
|
c.rollback();
|
@@ -1057,7 +1057,15 @@ public class JdbcAdapterInternalService implements BasicLibraryService {
|
|
1057
1057
|
}
|
1058
1058
|
|
1059
1059
|
private static Connection getConnection(IRubyObject recv) {
|
1060
|
+
return getConnection(recv, false);
|
1061
|
+
}
|
1062
|
+
|
1063
|
+
private static Connection getConnection(IRubyObject recv, boolean error) {
|
1060
1064
|
Connection conn = (Connection) recv.dataGetStruct();
|
1065
|
+
if(error && conn == null) {
|
1066
|
+
RubyClass err = recv.getRuntime().getModule("ActiveRecord").getClass("ConnectionNotEstablished");
|
1067
|
+
throw new RaiseException(recv.getRuntime(), err, "no connection available", false);
|
1068
|
+
}
|
1061
1069
|
return conn;
|
1062
1070
|
}
|
1063
1071
|
|
data/test/db/cachedb.rb
CHANGED
File without changes
|
data/test/db/h2.rb
CHANGED
data/test/db/informix.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# To run this script, run the following:
|
4
|
+
#
|
5
|
+
# CREATE DATABASE weblog_development;
|
6
|
+
#
|
7
|
+
# TODO: Finish the explanation.
|
8
|
+
|
9
|
+
require 'jdbc_common'
|
10
|
+
require 'db/informix'
|
11
|
+
|
12
|
+
class InformixSimpleTest < Test::Unit::TestCase
|
13
|
+
include SimpleTestMethods
|
14
|
+
|
15
|
+
# Informix does not like "= NULL".
|
16
|
+
def test_equals_null
|
17
|
+
Entry.create!(:title => "Foo")
|
18
|
+
entry = Entry.find(:first, :conditions => ["content = NULL"])
|
19
|
+
assert_equal "Foo", entry.title
|
20
|
+
end
|
21
|
+
|
22
|
+
# Informix does not like "!= NULL" or "<> NULL".
|
23
|
+
def test_not_equals_null
|
24
|
+
Entry.create!(:title => "Foo", :content => "Bar")
|
25
|
+
entry = Entry.find_by_title("Foo", :conditions => ["content != NULL"])
|
26
|
+
assert_equal "Foo", entry.title
|
27
|
+
entry = Entry.find_by_title("Foo", :conditions => ["content <> NULL"])
|
28
|
+
assert_equal "Foo", entry.title
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class InformixMultibyteTest < Test::Unit::TestCase
|
33
|
+
include MultibyteTestMethods
|
34
|
+
|
35
|
+
# Overriding the included test since we can't create text fields via a
|
36
|
+
# simple insert in Informix.
|
37
|
+
def test_select_multibyte_string
|
38
|
+
Entry.create!(:title => 'テスト', :content => '本文')
|
39
|
+
entry = Entry.find(:first)
|
40
|
+
assert_equal "テスト", entry.title
|
41
|
+
assert_equal "本文", entry.content
|
42
|
+
assert_equal entry, Entry.find_by_title("テスト")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class InformixHasManyThroughTest < Test::Unit::TestCase
|
47
|
+
include HasManyThroughMethods
|
48
|
+
end
|
data/test/jdbc_common.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
# Specify version of activerecord
|
3
|
-
|
2
|
+
# Specify version of activerecord with ENV['AR_VERSION'] if desired
|
3
|
+
gem 'activerecord', ENV['AR_VERSION'] if ENV['AR_VERSION']
|
4
4
|
require 'jdbc_adapter'
|
5
|
+
puts "Using activerecord version #{ActiveRecord::VERSION::STRING}"
|
6
|
+
puts "Specify version with AR_VERSION=={version} or RUBYLIB={path}"
|
5
7
|
require 'models/auto_id'
|
6
8
|
require 'models/entry'
|
7
9
|
require 'models/add_not_null_column_to_table'
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'jdbc_common'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'mocha'
|
5
|
+
|
6
|
+
class JndiConnectionPoolCallbacksTest < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
@connection = mock "JdbcConnection"
|
9
|
+
@connection.stubs(:jndi_connection?).returns(true)
|
10
|
+
@connection.stubs(:adapter=)
|
11
|
+
@logger = mock "logger"
|
12
|
+
@config = { :jndi => "jdbc/some_pool", :adapter => "mysql" }
|
13
|
+
Entry.connection_pool.disconnect!
|
14
|
+
assert !Entry.connection_pool.connected?
|
15
|
+
class << Entry.connection_pool; public :instance_variable_set; end
|
16
|
+
end
|
17
|
+
|
18
|
+
def teardown
|
19
|
+
@connection.stubs(:disconnect!)
|
20
|
+
Entry.connection_pool.disconnect!
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_should_call_hooks_on_checkout_and_checkin
|
24
|
+
@connection.expects(:disconnect!)
|
25
|
+
@adapter = ActiveRecord::ConnectionAdapters::JdbcAdapter.new @connection, @logger, @config
|
26
|
+
Entry.connection_pool.instance_variable_set "@connections", [@adapter]
|
27
|
+
|
28
|
+
@connection.expects(:reconnect!)
|
29
|
+
Entry.connection_pool.checkout
|
30
|
+
|
31
|
+
@connection.expects(:disconnect!)
|
32
|
+
Entry.connection_pool.checkin @adapter
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
rescue LoadError
|
37
|
+
warn "mocha not found, disabling mocha-based tests"
|
38
|
+
end if ActiveRecord::Base.respond_to?(:connection_pool)
|
data/test/manualTestDatabase.rb
CHANGED
File without changes
|
data/test/simple.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
1
2
|
ActiveRecord::Schema.verbose = false
|
2
3
|
|
3
4
|
module MigrationSetup
|
@@ -138,6 +139,7 @@ module SimpleTestMethods
|
|
138
139
|
def test_disconnect
|
139
140
|
assert_equal 1, Entry.count
|
140
141
|
ActiveRecord::Base.clear_active_connections!
|
142
|
+
ActiveRecord::Base.connection_pool.disconnect! if ActiveRecord::Base.respond_to?(:connection_pool)
|
141
143
|
assert !ActiveRecord::Base.connected?
|
142
144
|
assert_equal 1, Entry.count
|
143
145
|
assert ActiveRecord::Base.connected?
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-jdbc-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: "0.9"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Sieger, Ola Bini and JRuby contributors
|
@@ -9,11 +9,11 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-11-26 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
16
|
-
description:
|
16
|
+
description: activerecord-jdbc-adapter is a database adapter for Rails' ActiveRecord component that can be used with JRuby[http://www.jruby.org/]. It allows use of virtually any JDBC-compliant database with your JRuby on Rails application.
|
17
17
|
email: nick@nicksieger.com, ola.bini@gmail.com
|
18
18
|
executables: []
|
19
19
|
|
@@ -34,6 +34,7 @@ files:
|
|
34
34
|
- lib/active_record/connection_adapters/derby_adapter.rb
|
35
35
|
- lib/active_record/connection_adapters/h2_adapter.rb
|
36
36
|
- lib/active_record/connection_adapters/hsqldb_adapter.rb
|
37
|
+
- lib/active_record/connection_adapters/informix_adapter.rb
|
37
38
|
- lib/active_record/connection_adapters/jdbc_adapter.rb
|
38
39
|
- lib/active_record/connection_adapters/jdbc_adapter_spec.rb
|
39
40
|
- lib/active_record/connection_adapters/jndi_adapter.rb
|
@@ -46,6 +47,7 @@ files:
|
|
46
47
|
- lib/jdbc_adapter/jdbc_derby.rb
|
47
48
|
- lib/jdbc_adapter/jdbc_firebird.rb
|
48
49
|
- lib/jdbc_adapter/jdbc_hsqldb.rb
|
50
|
+
- lib/jdbc_adapter/jdbc_informix.rb
|
49
51
|
- lib/jdbc_adapter/jdbc_mimer.rb
|
50
52
|
- lib/jdbc_adapter/jdbc_mssql.rb
|
51
53
|
- lib/jdbc_adapter/jdbc_mysql.rb
|
@@ -67,6 +69,7 @@ files:
|
|
67
69
|
- test/db/derby.rb
|
68
70
|
- test/db/h2.rb
|
69
71
|
- test/db/hsqldb.rb
|
72
|
+
- test/db/informix.rb
|
70
73
|
- test/db/jdbc.rb
|
71
74
|
- test/db/jndi_config.rb
|
72
75
|
- test/db/logger.rb
|
@@ -82,9 +85,11 @@ files:
|
|
82
85
|
- test/h2_simple_test.rb
|
83
86
|
- test/has_many_through.rb
|
84
87
|
- test/hsqldb_simple_test.rb
|
88
|
+
- test/informix_simple_test.rb
|
85
89
|
- test/jdbc_adapter/jdbc_db2_test.rb
|
86
90
|
- test/jdbc_adapter/jdbc_sybase_test.rb
|
87
91
|
- test/jdbc_common.rb
|
92
|
+
- test/jndi_callbacks_test.rb
|
88
93
|
- test/jndi_test.rb
|
89
94
|
- test/manualTestDatabase.rb
|
90
95
|
- test/minirunit/testConnect.rb
|
@@ -136,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
136
141
|
requirements: []
|
137
142
|
|
138
143
|
rubyforge_project: jruby-extras
|
139
|
-
rubygems_version: 1.
|
144
|
+
rubygems_version: 1.3.1
|
140
145
|
signing_key:
|
141
146
|
specification_version: 2
|
142
147
|
summary: JDBC adapter for ActiveRecord, for use within JRuby on Rails.
|