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.
Files changed (68) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -2
  3. data/.travis.yml +15 -416
  4. data/Gemfile +35 -37
  5. data/README.md +23 -118
  6. data/RUNNING_TESTS.md +31 -26
  7. data/Rakefile +2 -3
  8. data/activerecord-jdbc-adapter.gemspec +1 -2
  9. data/lib/arjdbc/abstract/connection_management.rb +21 -0
  10. data/lib/arjdbc/abstract/core.rb +62 -0
  11. data/lib/arjdbc/abstract/database_statements.rb +46 -0
  12. data/lib/arjdbc/abstract/statement_cache.rb +58 -0
  13. data/lib/arjdbc/abstract/transaction_support.rb +86 -0
  14. data/lib/arjdbc/derby/adapter.rb +6 -1
  15. data/lib/arjdbc/discover.rb +0 -7
  16. data/lib/arjdbc/firebird/adapter.rb +2 -2
  17. data/lib/arjdbc/jdbc/adapter.rb +10 -252
  18. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  19. data/lib/arjdbc/jdbc/connection.rb +6 -0
  20. data/lib/arjdbc/jdbc.rb +2 -2
  21. data/lib/arjdbc/mysql/adapter.rb +87 -944
  22. data/lib/arjdbc/mysql/connection_methods.rb +4 -2
  23. data/lib/arjdbc/postgresql/adapter.rb +288 -1023
  24. data/lib/arjdbc/postgresql/base/array_decoder.rb +26 -0
  25. data/lib/arjdbc/postgresql/base/array_encoder.rb +25 -0
  26. data/lib/arjdbc/postgresql/base/pgconn.rb +8 -5
  27. data/lib/arjdbc/postgresql/column.rb +10 -599
  28. data/lib/arjdbc/postgresql/connection_methods.rb +9 -0
  29. data/lib/arjdbc/postgresql/name.rb +24 -0
  30. data/lib/arjdbc/postgresql/oid_types.rb +25 -110
  31. data/lib/arjdbc/sqlite3/adapter.rb +171 -170
  32. data/lib/arjdbc/tasks/database_tasks.rb +1 -3
  33. data/lib/arjdbc/tasks/db2_database_tasks.rb +2 -2
  34. data/lib/arjdbc/version.rb +1 -1
  35. data/pom.xml +3 -3
  36. data/rakelib/02-test.rake +0 -12
  37. data/rakelib/compile.rake +1 -1
  38. data/rakelib/db.rake +7 -5
  39. data/rakelib/rails.rake +63 -64
  40. data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +1 -17
  41. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +518 -1260
  42. data/src/java/arjdbc/mysql/MySQLModule.java +3 -3
  43. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +53 -134
  44. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +214 -240
  45. data/src/java/arjdbc/sqlite3/SQLite3Module.java +0 -20
  46. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +85 -10
  47. metadata +20 -34
  48. data/Appraisals +0 -41
  49. data/lib/active_record/connection_adapters/oracle_adapter.rb +0 -1
  50. data/lib/arjdbc/common_jdbc_methods.rb +0 -89
  51. data/lib/arjdbc/mysql/bulk_change_table.rb +0 -150
  52. data/lib/arjdbc/mysql/column.rb +0 -162
  53. data/lib/arjdbc/mysql/explain_support.rb +0 -82
  54. data/lib/arjdbc/mysql/schema_creation.rb +0 -58
  55. data/lib/arjdbc/oracle/adapter.rb +0 -952
  56. data/lib/arjdbc/oracle/column.rb +0 -126
  57. data/lib/arjdbc/oracle/connection_methods.rb +0 -21
  58. data/lib/arjdbc/oracle.rb +0 -4
  59. data/lib/arjdbc/postgresql/_bc_time_cast_patch.rb +0 -21
  60. data/lib/arjdbc/postgresql/base/oid.rb +0 -412
  61. data/lib/arjdbc/postgresql/base/schema_definitions.rb +0 -131
  62. data/lib/arjdbc/postgresql/explain_support.rb +0 -53
  63. data/lib/arjdbc/postgresql/oid/bytea.rb +0 -2
  64. data/lib/arjdbc/postgresql/schema_creation.rb +0 -60
  65. data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +0 -297
  66. data/lib/arjdbc/tasks/oracle_database_tasks.rb +0 -65
  67. data/src/java/arjdbc/oracle/OracleModule.java +0 -75
  68. 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.png)][7]
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**, **Oracle**, *MS-SQL** (SQL Server),
24
- **DB2**, **Firebird**, **Derby**, **HSQLDB**, **H2**, and **Informix**.
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
- Other databases will require testing and likely a custom configuration module.
27
- Please join the JRuby [mailing list][1] to help us discover support for more
28
- databases.
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
- 2a. If you're generating a new Rails application, use the following command:
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: 'derby',
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', '~> 3.2.14'
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 "~> 3.2.10"
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-jdbcderby-adapter
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-jdbcderby-adapter' if defined? JRUBY_VERSION
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 default run against the "current" ActiveRecord version locked down
33
- by Bundler, however since we usually do support more versions from a single code
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 appraisal:rails31 test_mysql TEST=test/db/mysql/rake_test.rb
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 appraisal:rails40 test_postgres TESTOPTS="--name=/integer/"
40
+ rake test_postgres TESTOPTS="--name=/integer/"
42
41
 
43
- This of course also works when running the "plain" test (no appraisal:xxx) task.
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
- Since 1.3.0 we also support prepared statements, these are off by default (AR)
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
- It's very desirable to pass all unit tests from ActiveRecord's own test suite.
54
- Unfortunately it's been a while since we have accomplished that, luckily a lot
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
- To run the AR-JDBC's sources agains AR tests, use the **rails:test** task, be
63
- sure to specify a **DRIVER** and the **RAILS** sources path on the file system :
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 RAILS=path/to/rails_source_dir
69
+ jruby -S rake rails:test:all DRIVER=derby
66
70
 
67
- There's even tasks for Rails built-in adapters e.g. `rake rails:test_mysql`
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
- You will likely only be able to run the Rails suite against the latest (stable)
70
- ActiveRecord ~> version we support (check the *Gemfile.lock*) e.g. for
71
- **activerecord (3.2.13)** you want to **git checkout 3-2-stable** branch.
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
- We strive to not stub and include native (MRI) test required artefacts into
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[derby h2 hsqldb mssql mysql postgresql sqlite3].map { |a| "activerecord-jdbc#{a}-adapter" }
19
- DRIVERS = %w[derby h2 hsqldb jtds mysql postgres sqlite3].map { |a| "jdbc-#{a}" }
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
- # NOTE: 1.3.0 only supports >= 2.3 but users report it works with 2.2 :
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
@@ -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 @connection.marked_savepoint_names.include?(name)
186
+ release_savepoint(name) if existing_savepoint_name?(name)
182
187
  super(name)
183
188
  end
184
189
 
@@ -75,13 +75,6 @@ module ArJdbc
75
75
  end
76
76
  end
77
77
 
78
- extension :Oracle do |name|
79
- if name =~ /oracle/i
80
- require 'arjdbc/oracle'
81
- true
82
- end
83
- end
84
-
85
78
  # NOTE: following ones are likely getting deprecated :
86
79
 
87
80
  extension :FireBird do |name|
@@ -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 # oracle-enhanced
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