activerecord-jdbc-adapter 5.0.pre1 → 51.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +1 -2
- data/.travis.yml +15 -416
- data/Gemfile +35 -37
- data/README.md +23 -118
- data/RUNNING_TESTS.md +31 -26
- data/Rakefile +2 -3
- data/activerecord-jdbc-adapter.gemspec +1 -2
- data/lib/arjdbc/abstract/connection_management.rb +21 -0
- data/lib/arjdbc/abstract/core.rb +62 -0
- data/lib/arjdbc/abstract/database_statements.rb +46 -0
- data/lib/arjdbc/abstract/statement_cache.rb +58 -0
- data/lib/arjdbc/abstract/transaction_support.rb +86 -0
- data/lib/arjdbc/derby/adapter.rb +6 -1
- data/lib/arjdbc/discover.rb +0 -7
- data/lib/arjdbc/firebird/adapter.rb +2 -2
- data/lib/arjdbc/jdbc/adapter.rb +10 -252
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/connection.rb +6 -0
- data/lib/arjdbc/jdbc.rb +2 -2
- data/lib/arjdbc/mysql/adapter.rb +87 -944
- data/lib/arjdbc/mysql/connection_methods.rb +4 -2
- data/lib/arjdbc/postgresql/adapter.rb +288 -1023
- data/lib/arjdbc/postgresql/base/array_decoder.rb +26 -0
- data/lib/arjdbc/postgresql/base/array_encoder.rb +25 -0
- data/lib/arjdbc/postgresql/base/pgconn.rb +8 -5
- data/lib/arjdbc/postgresql/column.rb +10 -599
- data/lib/arjdbc/postgresql/connection_methods.rb +9 -0
- data/lib/arjdbc/postgresql/name.rb +24 -0
- data/lib/arjdbc/postgresql/oid_types.rb +25 -110
- data/lib/arjdbc/sqlite3/adapter.rb +171 -170
- data/lib/arjdbc/tasks/database_tasks.rb +1 -3
- data/lib/arjdbc/tasks/db2_database_tasks.rb +2 -2
- data/lib/arjdbc/version.rb +1 -1
- data/pom.xml +3 -3
- data/rakelib/02-test.rake +0 -12
- data/rakelib/compile.rake +1 -1
- data/rakelib/db.rake +7 -5
- data/rakelib/rails.rake +63 -64
- data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +1 -17
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +518 -1260
- data/src/java/arjdbc/mysql/MySQLModule.java +3 -3
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +53 -134
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +214 -240
- data/src/java/arjdbc/sqlite3/SQLite3Module.java +0 -20
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +85 -10
- metadata +20 -34
- data/Appraisals +0 -41
- data/lib/active_record/connection_adapters/oracle_adapter.rb +0 -1
- data/lib/arjdbc/common_jdbc_methods.rb +0 -89
- data/lib/arjdbc/mysql/bulk_change_table.rb +0 -150
- data/lib/arjdbc/mysql/column.rb +0 -162
- data/lib/arjdbc/mysql/explain_support.rb +0 -82
- data/lib/arjdbc/mysql/schema_creation.rb +0 -58
- data/lib/arjdbc/oracle/adapter.rb +0 -952
- data/lib/arjdbc/oracle/column.rb +0 -126
- data/lib/arjdbc/oracle/connection_methods.rb +0 -21
- data/lib/arjdbc/oracle.rb +0 -4
- data/lib/arjdbc/postgresql/_bc_time_cast_patch.rb +0 -21
- data/lib/arjdbc/postgresql/base/oid.rb +0 -412
- data/lib/arjdbc/postgresql/base/schema_definitions.rb +0 -131
- data/lib/arjdbc/postgresql/explain_support.rb +0 -53
- data/lib/arjdbc/postgresql/oid/bytea.rb +0 -2
- data/lib/arjdbc/postgresql/schema_creation.rb +0 -60
- data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +0 -297
- data/lib/arjdbc/tasks/oracle_database_tasks.rb +0 -65
- data/src/java/arjdbc/oracle/OracleModule.java +0 -75
- data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +0 -465
data/README.md
CHANGED
@@ -1,31 +1,24 @@
|
|
1
1
|
# ActiveRecord JDBC Adapter
|
2
2
|
|
3
|
-
[![Gem Version](https://badge.fury.io/rb/activerecord-jdbc-adapter.
|
4
|
-
|
5
|
-
ActiveRecord-JDBC-Adapter (AR-JDBC) is a database adapter for Rails'
|
6
|
-
*ActiveRecord* component that can be used with [JRuby][0]. It allows use of
|
7
|
-
virtually any JDBC-compliant database with your JRuby on Rails application.
|
8
|
-
|
9
|
-
We supports *ActiveRecord* **2.3**, **3.x** and **4.x** from a single code base.
|
10
|
-
You'll need JRuby >= **1.6.8** (we recommend using the latest and greatest of
|
11
|
-
JRubies) thus Java >= **1.6** is mandatory.
|
12
|
-
|
13
|
-
#### AR-JDBC **1.3.x** is a recommended update for all **1.2.x** users.
|
14
|
-
|
15
|
-
Our latest major version **1.3.x** represents a few months of refactoring and
|
16
|
-
updates covering (not just) new/old *ActiveRecord* features. It tries to stay
|
17
|
-
compatible with 1.2.9 as much as possible but please be aware that it's not always
|
18
|
-
possible(mostly for the best), please read our [migration guide][8] for details.
|
19
|
-
|
20
|
-
## Databases
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/activerecord-jdbc-adapter.svg)][7]
|
21
4
|
|
5
|
+
ActiveRecord-JDBC-Adapter (AR-JDBC) is the main database adapter for Rails'
|
6
|
+
*ActiveRecord* component that can be used with [JRuby][0].
|
22
7
|
ActiveRecord-JDBC-Adapter provides full or nearly full support for:
|
23
|
-
**MySQL**, **PostgreSQL**, **SQLite3
|
24
|
-
|
8
|
+
**MySQL**, **PostgreSQL**, **SQLite3**. In the near future there are plans to
|
9
|
+
add support **MSSQL**. Unless we get more contributions we will not be going
|
10
|
+
beyond these four adapters. Note that the amount of work needed to get
|
11
|
+
another adapter is not huge but the amount of testing required to make sure
|
12
|
+
that adapter continues to work is not something we can do with the resources
|
13
|
+
we currently have.
|
25
14
|
|
26
|
-
|
27
|
-
|
28
|
-
|
15
|
+
For Oracle database users you are encouraged to use
|
16
|
+
https://github.com/rsim/oracle-enhanced.
|
17
|
+
|
18
|
+
Version 50.x supports Rails version 5.0.x and it lives on branch 50-stable.
|
19
|
+
Version 51.x supports Rails version 5.1.x and is currently on master until
|
20
|
+
its first release. The minimum version of JRuby for 50+ is JRuby 9.1.x and
|
21
|
+
JRuby 9.1+ requires Java 7 or newer.
|
29
22
|
|
30
23
|
## Using ActiveRecord JDBC
|
31
24
|
|
@@ -36,39 +29,14 @@ To use AR-JDBC with JRuby on Rails:
|
|
36
29
|
1. Choose the adapter you wish to gem install. The following pre-packaged
|
37
30
|
adapters are available:
|
38
31
|
|
39
|
-
- Base JDBC (`activerecord-jdbc-adapter`) - supports all available databases
|
40
|
-
via JDBC, but requires you to download and manually setup a JDBC driver for
|
41
|
-
the database you're using
|
42
32
|
- MySQL (`activerecord-jdbcmysql-adapter`)
|
43
33
|
- PostgreSQL (`activerecord-jdbcpostgresql-adapter`)
|
44
34
|
- SQLite3 (`activerecord-jdbcsqlite3-adapter`)
|
45
|
-
- Derby (`activerecord-jdbcderby-adapter`)
|
46
|
-
- HSQLDB (`activerecord-jdbchsqldb-adapter`)
|
47
|
-
- H2 (`activerecord-jdbch2-adapter`)
|
48
|
-
- MSSQL (`activerecord-jdbcmssql-adapter`) - uses the OSS jTDS driver by default
|
49
|
-
which might have issues with the latest SQLServer (but should work using the
|
50
|
-
Microsoft JDBC Driver for SQL Server - we recommend using 4.0)
|
51
35
|
|
52
|
-
|
36
|
+
2. If you're generating a new Rails application, use the following command:
|
53
37
|
|
54
38
|
jruby -S rails new sweetapp
|
55
39
|
|
56
|
-
2b. Otherwise, you might need to perform some extra configuration steps
|
57
|
-
to prepare your Rails application for JDBC.
|
58
|
-
|
59
|
-
You'll need to modify your *Gemfile* to use the *activerecord-jdbc-adapter* gem
|
60
|
-
(or one of the helper gems) under JRuby. Change your *Gemfile* to look something
|
61
|
-
like the following:
|
62
|
-
|
63
|
-
```ruby
|
64
|
-
gem 'mysql2', platform: :ruby
|
65
|
-
gem 'activerecord-jdbcmysql-adapter', platform: :jruby
|
66
|
-
```
|
67
|
-
|
68
|
-
If you're (stuck) using Rails 2.3, you might need to:
|
69
|
-
|
70
|
-
jruby script/generate jdbc
|
71
|
-
|
72
40
|
3. Configure your *database.yml* in the normal Rails style:
|
73
41
|
|
74
42
|
```yml
|
@@ -79,22 +47,6 @@ development:
|
|
79
47
|
password: 1234
|
80
48
|
```
|
81
49
|
|
82
|
-
**Legacy Configuration:** If you use one of the *activerecord-jdbcxxx-adapter*
|
83
|
-
gems, you can still put a 'jdbc' prefix in front of the database adapter name,
|
84
|
-
e.g. `adapter: jdbcmysql`.
|
85
|
-
|
86
|
-
For plain JDBC database configurations, you'll need to know the database driver
|
87
|
-
class and URL (do not forget to put the driver .jar(s) on the class-path) e.g.:
|
88
|
-
|
89
|
-
```yml
|
90
|
-
development:
|
91
|
-
adapter: jdbc
|
92
|
-
username: blog
|
93
|
-
password: 1234
|
94
|
-
driver: com.mysql.jdbc.Driver
|
95
|
-
url: jdbc:mysql://localhost:3306/blog_development
|
96
|
-
```
|
97
|
-
|
98
50
|
For JNDI data sources, you may simply specify the JNDI location as follows, it's
|
99
51
|
recommended to use the same adapter: setting as one would configure when using
|
100
52
|
"bare" (JDBC) connections e.g. :
|
@@ -122,27 +74,6 @@ production:
|
|
122
74
|
connectTimeout: 60000
|
123
75
|
```
|
124
76
|
|
125
|
-
If you're really old school you might want to use AR-JDBC with a DB2 on z/OS:
|
126
|
-
|
127
|
-
```yml
|
128
|
-
development:
|
129
|
-
adapter: jdbc
|
130
|
-
url: jdbc:db2j:net://mightyzoshost:446/RAILS_DBT1
|
131
|
-
driver: com.ibm.db2.jcc.DB2Driver
|
132
|
-
schema: DB2XB12
|
133
|
-
database: RAILS_DB1
|
134
|
-
tablespace: TSDE911
|
135
|
-
lob_tablespaces:
|
136
|
-
first_table: TSDE912
|
137
|
-
username: business
|
138
|
-
password: machines
|
139
|
-
encoding: unicode
|
140
|
-
# you can force a (DB2) dialect using:
|
141
|
-
#dialect: as400
|
142
|
-
```
|
143
|
-
|
144
|
-
More information on (configuring) AR-JDBC might be found on our [wiki][5].
|
145
|
-
|
146
77
|
### Standalone with ActiveRecord
|
147
78
|
|
148
79
|
Once the setup is made (see below) you can establish a JDBC connection like this
|
@@ -150,53 +81,34 @@ Once the setup is made (see below) you can establish a JDBC connection like this
|
|
150
81
|
|
151
82
|
```ruby
|
152
83
|
ActiveRecord::Base.establish_connection(
|
153
|
-
adapter: '
|
84
|
+
adapter: 'sqlite3',
|
154
85
|
database: 'db/my-database'
|
155
86
|
)
|
156
87
|
```
|
157
88
|
|
158
|
-
or using (requires that you manually put the driver jar on the class-path):
|
159
|
-
|
160
|
-
```ruby
|
161
|
-
ActiveRecord::Base.establish_connection(
|
162
|
-
:adapter => 'jdbc',
|
163
|
-
:driver => 'org.apache.derby.jdbc.EmbeddedDriver',
|
164
|
-
:url => 'jdbc:derby:sample_db;create=true'
|
165
|
-
)
|
166
|
-
```
|
167
|
-
|
168
89
|
#### Using Bundler
|
169
90
|
|
170
91
|
Proceed as with Rails; specify `ActiveRecord` in your Bundle along with the
|
171
92
|
chosen JDBC adapter(s), this time sample *Gemfile* for MySQL:
|
172
93
|
|
173
94
|
```ruby
|
174
|
-
gem 'activerecord', '~>
|
95
|
+
gem 'activerecord', '~> 5.0.6'
|
175
96
|
gem 'activerecord-jdbcmysql-adapter', :platform => :jruby
|
176
97
|
```
|
177
98
|
|
178
99
|
When you `require 'bundler/setup'` everything will be set up for you as expected.
|
179
100
|
|
180
|
-
You do not need to use the 'helper' *activerecord-jdbcxxx-adapter* gem we provide
|
181
|
-
but than should make sure an appropriate JDBC driver is available at runtime, in
|
182
|
-
that case simply setup your *Gemfile* as:
|
183
|
-
|
184
|
-
```ruby
|
185
|
-
gem 'activerecord', '~> 4.0.0'
|
186
|
-
gem 'activerecord-jdbc-adapter', '~> 1.3.2', platform: :jruby
|
187
|
-
```
|
188
|
-
|
189
101
|
#### Without Bundler
|
190
102
|
|
191
103
|
Install the needed gems with JRuby, for example:
|
192
104
|
|
193
|
-
gem install activerecord -v "~>
|
105
|
+
gem install activerecord -v "~> 5.0.6"
|
194
106
|
gem install activerecord-jdbc-adapter --ignore-dependencies
|
195
107
|
|
196
108
|
If you wish to use the adapter for a specific database, you can install it
|
197
109
|
directly and the (jdbc-) driver gem (dependency) will be installed as well:
|
198
110
|
|
199
|
-
jruby -S gem install activerecord-
|
111
|
+
jruby -S gem install activerecord-jdbcmysql-adapter
|
200
112
|
|
201
113
|
Your program should include:
|
202
114
|
|
@@ -204,16 +116,9 @@ Your program should include:
|
|
204
116
|
require 'active_record'
|
205
117
|
require 'activerecord-jdbc-adapter' if defined? JRUBY_VERSION
|
206
118
|
# or in case you're using the pre-packaged adapter gem :
|
207
|
-
require 'activerecord-
|
119
|
+
require 'activerecord-jdbcmysql-adapter' if defined? JRUBY_VERSION
|
208
120
|
```
|
209
121
|
|
210
|
-
## Extending AR-JDBC
|
211
|
-
|
212
|
-
You can create your own extension to AR-JDBC for a JDBC-based database that core
|
213
|
-
AR-JDBC does not support. We've created an example project for the Intersystems
|
214
|
-
Cache database that you can examine as a template.
|
215
|
-
See the [cachedb-adapter project][4] for more information.
|
216
|
-
|
217
122
|
## Source
|
218
123
|
|
219
124
|
The source for activerecord-jdbc-adapter is available using git:
|
@@ -263,4 +168,4 @@ license the database's drivers are licensed. See each driver gem's LICENSE.txt.
|
|
263
168
|
[5]: https://github.com/jruby/activerecord-jdbc-adapter/wiki
|
264
169
|
[6]: https://webchat.freenode.net/?channels=#jruby
|
265
170
|
[7]: http://badge.fury.io/rb/activerecord-jdbc-adapter
|
266
|
-
[8]: https://github.com/jruby/activerecord-jdbc-adapter/wiki/Migrating-from-1.2.x-to-1.3.0
|
171
|
+
[8]: https://github.com/jruby/activerecord-jdbc-adapter/wiki/Migrating-from-1.2.x-to-1.3.0
|
data/RUNNING_TESTS.md
CHANGED
@@ -29,52 +29,57 @@ export ORACLE_PASS=sample
|
|
29
29
|
export ORACLE_SID=MAIN
|
30
30
|
```
|
31
31
|
|
32
|
-
Tests are by
|
33
|
-
|
34
|
-
base run those with the (appraisal) provided task e.g. for MySQL :
|
32
|
+
Tests are run by calling the rake task corresponding the database adapter being
|
33
|
+
tested, e.g. for MySQL :
|
35
34
|
|
36
|
-
rake
|
35
|
+
rake test_mysql TEST=test/db/mysql/rake_test.rb
|
37
36
|
|
38
37
|
Observe the **TEST** variable used to specify a single file to be used to resolve
|
39
38
|
test cases, you pick tests by matching their names as well using **TESTOPTS** :
|
40
39
|
|
41
|
-
rake
|
40
|
+
rake test_postgres TESTOPTS="--name=/integer/"
|
42
41
|
|
43
|
-
|
42
|
+
Since 1.3.0 we also support prepared statements, these are enabled by default (AR)
|
43
|
+
but one can easily run tests with prepared statements disabled using env vars :
|
44
44
|
|
45
|
-
|
46
|
-
but one can easily run tests with prepared statements enabled using env vars :
|
47
|
-
|
48
|
-
rake test_derby PS=true # or PREPARED_STATEMENTS=true
|
45
|
+
rake test_derby PREPARED_STATEMENTS=false
|
49
46
|
|
50
47
|
|
51
48
|
### ActiveRecord (Rails) Tests
|
52
49
|
|
53
|
-
|
54
|
-
|
55
|
-
of failures are artificial (and would require tweaks at the Rails repo itself),
|
56
|
-
others simply need quality time spent to get them in shape and address issues.
|
57
|
-
|
58
|
-
First make sure you have the ActiveRecord (Rails) sources cloned locally :
|
50
|
+
We also have the ability to run our adapters against Rails ActiveRecord
|
51
|
+
tests as well. First, make sure you have the Rails repository cloned locally:
|
59
52
|
|
60
53
|
git clone git://github.com/rails/rails.git
|
61
54
|
|
62
|
-
|
63
|
-
|
55
|
+
If you clone Rails to the same parent directory this project is cloned to
|
56
|
+
then you may do either:
|
57
|
+
|
58
|
+
jruby -S rake rails:test:sqlite
|
59
|
+
jruby -S rake rails:test:postgres
|
60
|
+
jruby -S rake rails:test:mysql
|
61
|
+
|
62
|
+
If you have your rails source in another directory then you can pass
|
63
|
+
in **RAILS**:
|
64
|
+
|
65
|
+
jruby -S rake rails:test:sqlite RAILS=../../somewhere/rails
|
66
|
+
|
67
|
+
If you are working on a more exotic adapter you can also pass in **DRIVER**:
|
64
68
|
|
65
|
-
jruby -S rake rails:test DRIVER=derby
|
69
|
+
jruby -S rake rails:test:all DRIVER=derby
|
66
70
|
|
67
|
-
|
71
|
+
Note, that if you want to test against particular version of Rails you need
|
72
|
+
to check out the proper branch in Rails source (e.g. v5.0.2). If you are
|
73
|
+
just starting to debug an adapter then running:
|
68
74
|
|
69
|
-
|
70
|
-
|
71
|
-
|
75
|
+
jruby -S rake rails:test:sqlite:basic_test
|
76
|
+
jruby -S rake rails:test:postgres:basic_test
|
77
|
+
jruby -S rake rails:test:mysql:basic_test
|
72
78
|
|
73
|
-
|
74
|
-
(non-test) code e.g. the `Mysql` module, instead put that into **test/rails**.
|
79
|
+
is helpful since basic_test in active-record hits that 80% sweet spot.
|
75
80
|
|
76
81
|
[![Build Status][0]](http://travis-ci.org/#!/jruby/activerecord-jdbc-adapter)
|
77
82
|
|
78
83
|
Happy Testing!
|
79
84
|
|
80
|
-
[0]: https://secure.travis-ci.org/jruby/activerecord-jdbc-adapter.png
|
85
|
+
[0]: https://secure.travis-ci.org/jruby/activerecord-jdbc-adapter.png
|
data/Rakefile
CHANGED
@@ -8,15 +8,14 @@ require 'bundler/gem_helper'
|
|
8
8
|
Bundler::GemHelper.install_tasks
|
9
9
|
|
10
10
|
require 'bundler/setup'
|
11
|
-
require 'appraisal'
|
12
11
|
|
13
12
|
task :default => [:jar, :test]
|
14
13
|
|
15
14
|
task :build => :jar
|
16
15
|
task :install => :jar
|
17
16
|
|
18
|
-
ADAPTERS = %w[
|
19
|
-
DRIVERS = %w[
|
17
|
+
ADAPTERS = %w[mysql postgresql sqlite3].map { |a| "activerecord-jdbc#{a}-adapter" }
|
18
|
+
DRIVERS = %w[mysql postgres sqlite3].map { |a| "jdbc-#{a}" }
|
20
19
|
TARGETS = ( ADAPTERS + DRIVERS )
|
21
20
|
|
22
21
|
rake = lambda { |task| ruby "-S", "rake", task }
|
@@ -29,8 +29,7 @@ Gem::Specification.new do |gem|
|
|
29
29
|
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
30
30
|
gem.test_files = gem.files.grep(%r{^test/})
|
31
31
|
|
32
|
-
|
33
|
-
gem.add_dependency 'activerecord', '>= 2.2'
|
32
|
+
gem.add_dependency 'activerecord', '~> 5.1.0'
|
34
33
|
|
35
34
|
#gem.add_development_dependency 'test-unit', '2.5.4'
|
36
35
|
#gem.add_development_dependency 'test-unit-context', '>= 0.3.0'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ArJdbc
|
2
|
+
module Abstract
|
3
|
+
module ConnectionManagement
|
4
|
+
|
5
|
+
def active?
|
6
|
+
@connection.active?
|
7
|
+
end
|
8
|
+
|
9
|
+
def disconnect!
|
10
|
+
super
|
11
|
+
@connection.disconnect!
|
12
|
+
end
|
13
|
+
|
14
|
+
def reconnect!
|
15
|
+
super
|
16
|
+
@connection.reconnect! # handles adapter.configure_connection
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module ArJdbc
|
2
|
+
module Abstract
|
3
|
+
|
4
|
+
# This is minimum amount of code needed from base JDBC Adapter class to make common adapters
|
5
|
+
# work. This replaces using jdbc/adapter as a base class for all adapters.
|
6
|
+
module Core
|
7
|
+
|
8
|
+
attr_reader :config
|
9
|
+
|
10
|
+
def initialize(connection, logger = nil, config = {})
|
11
|
+
@config = config
|
12
|
+
|
13
|
+
connection ||= jdbc_connection_class(config[:adapter_spec]).new(config, self)
|
14
|
+
|
15
|
+
super(connection, logger, config)
|
16
|
+
|
17
|
+
# NOTE: should not be necessary for JNDI due reconnect! on checkout :
|
18
|
+
configure_connection if respond_to?(:configure_connection)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Retrieve the raw `java.sql.Connection` object.
|
22
|
+
# The unwrap parameter is useful if an attempt to unwrap a pooled (JNDI)
|
23
|
+
# connection should be made - to really return the 'native' JDBC object.
|
24
|
+
# @param unwrap [true, false] whether to unwrap the connection object
|
25
|
+
# @return [Java::JavaSql::Connection] the JDBC connection
|
26
|
+
def jdbc_connection(unwrap = false)
|
27
|
+
java_connection = raw_connection.connection
|
28
|
+
return java_connection unless unwrap
|
29
|
+
|
30
|
+
connection_class = java.sql.Connection.java_class
|
31
|
+
begin
|
32
|
+
if java_connection.wrapper_for?(connection_class)
|
33
|
+
return java_connection.unwrap(connection_class) # java.sql.Wrapper.unwrap
|
34
|
+
end
|
35
|
+
rescue Java::JavaLang::AbstractMethodError => e
|
36
|
+
ArJdbc.warn("driver/pool connection impl does not support unwrapping (#{e})")
|
37
|
+
end
|
38
|
+
|
39
|
+
if java_connection.respond_to?(:connection)
|
40
|
+
# e.g. org.apache.tomcat.jdbc.pool.PooledConnection
|
41
|
+
java_connection.connection # getConnection
|
42
|
+
else
|
43
|
+
java_connection
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
def translate_exception(e, message)
|
49
|
+
# we shall not translate native "Java" exceptions as they might
|
50
|
+
# swallow an ArJdbc / driver bug into a AR::StatementInvalid ...
|
51
|
+
return e if e.is_a?(Java::JavaLang::Throwable)
|
52
|
+
|
53
|
+
case e
|
54
|
+
when ActiveModel::RangeError, TypeError, SystemExit, SignalException, NoMemoryError then e
|
55
|
+
# NOTE: wraps AR::JDBCError into AR::StatementInvalid, desired ?!
|
56
|
+
else super
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module ArJdbc
|
2
|
+
module Abstract
|
3
|
+
|
4
|
+
# This provides the basic interface for interacting with the
|
5
|
+
# database for JDBC based adapters
|
6
|
+
module DatabaseStatements
|
7
|
+
|
8
|
+
# It appears that at this point (AR 5.0) "prepare" should only ever be true
|
9
|
+
# if prepared statements are enabled
|
10
|
+
def exec_query(sql, name = nil, binds = [], prepare: false)
|
11
|
+
if without_prepared_statement?(binds)
|
12
|
+
execute(sql, name)
|
13
|
+
else
|
14
|
+
binds = convert_legacy_binds_to_attributes(binds) if binds.first.is_a?(Array)
|
15
|
+
log(sql, name, binds) do
|
16
|
+
# It seems that #supports_statement_cache? is defined but isn't checked before setting "prepare" (AR 5.0)
|
17
|
+
cached_statement = fetch_cached_statement(sql) if prepare && supports_statement_cache?
|
18
|
+
@connection.execute_prepared(sql, binds, cached_statement)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def exec_update(sql, name = nil, binds = [])
|
24
|
+
if without_prepared_statement?(binds)
|
25
|
+
log(sql, name) { @connection.execute_update(sql, nil) }
|
26
|
+
else
|
27
|
+
log(sql, name, binds) { @connection.execute_prepared_update(sql, binds) }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
alias :exec_delete :exec_update
|
31
|
+
|
32
|
+
def execute(sql, name = nil)
|
33
|
+
log(sql, name) { @connection.execute(sql) }
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def convert_legacy_binds_to_attributes(binds)
|
39
|
+
binds.map do |column, value|
|
40
|
+
ActiveRecord::Relation::QueryAttribute.new(nil, type_cast(value, column), ActiveModel::Type::Value.new)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'active_record/connection_adapters/statement_pool'
|
2
|
+
|
3
|
+
module ArJdbc
|
4
|
+
module Abstract
|
5
|
+
module StatementCache
|
6
|
+
|
7
|
+
# This works a little differently than the AR implementation in that
|
8
|
+
# we are storing an actual PreparedStatement object instead of just
|
9
|
+
# the name of the prepared statement
|
10
|
+
class StatementPool < ActiveRecord::ConnectionAdapters::StatementPool
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def dealloc(statement)
|
15
|
+
statement.close
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(connection, logger, config)
|
21
|
+
super
|
22
|
+
|
23
|
+
# Only say we support the statement cache if we are using prepared statements
|
24
|
+
# and have a max number of statements defined
|
25
|
+
statement_limit = self.class.type_cast_config_to_integer(config[:statement_limit])
|
26
|
+
@jdbc_statement_cache_enabled = config[:prepared_statements] && (statement_limit.nil? || statement_limit > 0)
|
27
|
+
|
28
|
+
@statements = StatementPool.new(statement_limit) # AR (5.0) expects this to be stored as @statements
|
29
|
+
end
|
30
|
+
|
31
|
+
# Clears the prepared statements cache.
|
32
|
+
def clear_cache!
|
33
|
+
@statements.clear
|
34
|
+
end
|
35
|
+
|
36
|
+
def delete_cached_statement(sql)
|
37
|
+
@statements.delete(cached_statement_key(sql))
|
38
|
+
end
|
39
|
+
|
40
|
+
def fetch_cached_statement(sql)
|
41
|
+
@statements[cached_statement_key(sql)] ||= @connection.connection.prepare_statement(sql)
|
42
|
+
end
|
43
|
+
|
44
|
+
def supports_statement_cache?
|
45
|
+
@jdbc_statement_cache_enabled
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# This should be overridden by the adapter if the sql itself
|
51
|
+
# is not enough to make the key unique
|
52
|
+
def cached_statement_key(sql)
|
53
|
+
sql
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module ArJdbc
|
2
|
+
module Abstract
|
3
|
+
|
4
|
+
# Provides the basic interface needed to support transactions for JDBC based adapters
|
5
|
+
module TransactionSupport
|
6
|
+
|
7
|
+
########################## Support Checks #################################
|
8
|
+
|
9
|
+
# Does our database (+ its JDBC driver) support save-points?
|
10
|
+
# @since 1.3.0
|
11
|
+
# @override
|
12
|
+
def supports_savepoints?
|
13
|
+
@connection.supports_savepoints?
|
14
|
+
end
|
15
|
+
|
16
|
+
# Does this adapter support setting the isolation level for a transaction?
|
17
|
+
# Unlike 'plain' `ActiveRecord` we allow checking for concrete transaction
|
18
|
+
# isolation level support by the database.
|
19
|
+
# @param level optional to check if we support a specific isolation level
|
20
|
+
# @since 1.3.0
|
21
|
+
# @extension added optional level parameter
|
22
|
+
def supports_transaction_isolation?(level = nil)
|
23
|
+
return false unless level
|
24
|
+
@connection.supports_transaction_isolation?(level)
|
25
|
+
end
|
26
|
+
|
27
|
+
########################## Transaction Interface ##########################
|
28
|
+
|
29
|
+
# Starts a database transaction.
|
30
|
+
# @override
|
31
|
+
def begin_db_transaction
|
32
|
+
log('BEGIN TRANSACTION'.freeze, nil) { @connection.begin }
|
33
|
+
end
|
34
|
+
|
35
|
+
# Starts a database transaction.
|
36
|
+
# @param isolation the transaction isolation to use
|
37
|
+
def begin_isolated_db_transaction(isolation)
|
38
|
+
log("BEGIN ISOLATED TRANSACTION - #{isolation}", nil) { @connection.begin(isolation) }
|
39
|
+
end
|
40
|
+
|
41
|
+
# Commits the current database transaction.
|
42
|
+
# @override
|
43
|
+
def commit_db_transaction
|
44
|
+
log('COMMIT TRANSACTION'.freeze, nil) { @connection.commit }
|
45
|
+
end
|
46
|
+
|
47
|
+
# Rolls back the current database transaction.
|
48
|
+
# Called from 'rollback_db_transaction' in the AbstractAdapter
|
49
|
+
# @override
|
50
|
+
def exec_rollback_db_transaction
|
51
|
+
log('ROLLBACK TRANSACTION'.freeze, nil) { @connection.rollback }
|
52
|
+
end
|
53
|
+
|
54
|
+
########################## Savepoint Interface ############################
|
55
|
+
|
56
|
+
# Creates a (transactional) save-point one can rollback to.
|
57
|
+
# Unlike 'plain' `ActiveRecord` it is allowed to pass a save-point name.
|
58
|
+
# @param name the save-point name
|
59
|
+
# @return save-point name (even if nil passed will be generated)
|
60
|
+
# @since 1.3.0
|
61
|
+
# @extension added optional name parameter
|
62
|
+
def create_savepoint(name = current_savepoint_name)
|
63
|
+
log("SAVEPOINT #{name}", 'Savepoint') { @connection.create_savepoint(name) }
|
64
|
+
end
|
65
|
+
|
66
|
+
# Transaction rollback to a given (previously created) save-point.
|
67
|
+
# If no save-point name given rollback to the last created one.
|
68
|
+
# Called from 'rollback_to_savepoint' in AbstractAdapter
|
69
|
+
# @param name the save-point name
|
70
|
+
# @extension added optional name parameter
|
71
|
+
def exec_rollback_to_savepoint(name = current_savepoint_name)
|
72
|
+
log("ROLLBACK TO SAVEPOINT #{name}", 'Savepoint') { @connection.rollback_savepoint(name) }
|
73
|
+
end
|
74
|
+
|
75
|
+
# Release a previously created save-point.
|
76
|
+
# @note Save-points are auto-released with the transaction they're created
|
77
|
+
# in (on transaction commit or roll-back).
|
78
|
+
# @param name the save-point name
|
79
|
+
# @extension added optional name parameter
|
80
|
+
def release_savepoint(name = current_savepoint_name)
|
81
|
+
log("RELEASE SAVEPOINT #{name}", 'Savepoint') { @connection.release_savepoint(name) }
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/arjdbc/derby/adapter.rb
CHANGED
@@ -175,10 +175,15 @@ module ArJdbc
|
|
175
175
|
NATIVE_DATABASE_TYPES
|
176
176
|
end
|
177
177
|
|
178
|
+
# UNTESTED
|
179
|
+
def existing_savepoint_name?(name)
|
180
|
+
(@connection.instance_variable_get('@savepoints') || {}).key? name
|
181
|
+
end
|
182
|
+
|
178
183
|
# Ensure the savepoint name is unused before creating it.
|
179
184
|
# @override
|
180
185
|
def create_savepoint(name = current_savepoint_name(true))
|
181
|
-
release_savepoint(name) if
|
186
|
+
release_savepoint(name) if existing_savepoint_name?(name)
|
182
187
|
super(name)
|
183
188
|
end
|
184
189
|
|
data/lib/arjdbc/discover.rb
CHANGED
@@ -413,7 +413,7 @@ module ActiveRecord::ConnectionAdapters
|
|
413
413
|
# ActiveRecord::ConnectionAdapters::FirebirdAdapter.emulate_booleans = false
|
414
414
|
#
|
415
415
|
def self.emulate_booleans?; ::ArJdbc::Firebird.emulate_booleans?; end
|
416
|
-
def self.emulate_booleans; ::ArJdbc::Firebird.emulate_booleans?; end
|
416
|
+
def self.emulate_booleans; ::ArJdbc::Firebird.emulate_booleans?; end
|
417
417
|
def self.emulate_booleans=(emulate); ::ArJdbc::Firebird.emulate_booleans = emulate; end
|
418
418
|
|
419
419
|
def initialize(*args)
|
@@ -431,4 +431,4 @@ module ActiveRecord::ConnectionAdapters
|
|
431
431
|
include ::ArJdbc::Firebird::Column
|
432
432
|
end
|
433
433
|
|
434
|
-
end
|
434
|
+
end
|