activerecord-jdbc-adapter 0.8.2 → 0.9
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 +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.
|