activerecord-jdbc-adapter 70.1-java → 71.0-java
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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +18 -18
- data/.gitignore +8 -0
- data/Gemfile +17 -4
- data/README.md +8 -3
- data/RUNNING_TESTS.md +36 -0
- data/activerecord-jdbc-adapter.gemspec +2 -2
- data/lib/arjdbc/abstract/connection_management.rb +25 -10
- data/lib/arjdbc/abstract/core.rb +5 -12
- data/lib/arjdbc/abstract/database_statements.rb +35 -35
- data/lib/arjdbc/abstract/relation_query_attribute_monkey_patch.rb +24 -0
- data/lib/arjdbc/abstract/statement_cache.rb +2 -7
- data/lib/arjdbc/abstract/transaction_support.rb +37 -22
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/column.rb +0 -34
- data/lib/arjdbc/jdbc/connection_methods.rb +1 -1
- data/lib/arjdbc/mysql/adapter.rb +106 -27
- data/lib/arjdbc/mysql/connection_methods.rb +43 -42
- data/lib/arjdbc/postgresql/adapter.rb +252 -105
- data/lib/arjdbc/postgresql/database_statements.rb +20 -0
- data/lib/arjdbc/postgresql/oid_types.rb +8 -27
- data/lib/arjdbc/postgresql/schema_statements.rb +57 -0
- data/lib/arjdbc/sqlite3/adapter.rb +213 -145
- data/lib/arjdbc/sqlite3/column.rb +103 -0
- data/lib/arjdbc/sqlite3/connection_methods.rb +7 -2
- data/lib/arjdbc/version.rb +1 -1
- data/rakelib/02-test.rake +1 -1
- data/rakelib/rails.rake +2 -0
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +4 -2
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +11 -0
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +2 -1
- metadata +12 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4450a117ffce0ffee520932ab4872346aa4c7192f36ebea911db380b9d5cca89
|
4
|
+
data.tar.gz: ec27e839eee02e6c3cbaba4d2a48fc46375c11b7de2f1a420d89ea4574152ef4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bc36b55927d27830d0ae0e6c424e799ccb4f34c44765fbc42b90ba49071b080ebf025adfa3568d254e75e8b137f5fc7c00b2d9004bcd0d412831eb5eebfb03ca
|
7
|
+
data.tar.gz: fdcac70debef8aba9131e875d05578d3308a34222d06738e7eca008ea51f7b89b0ee05a360f7273d9ebc2a70a62d3b753e70ad0c99e5707fb97ae81dffb2529e
|
data/.github/workflows/ruby.yml
CHANGED
@@ -27,7 +27,7 @@ jobs:
|
|
27
27
|
ruby-version: ['jruby-head']
|
28
28
|
db: ['mysql2']
|
29
29
|
test_targets: ["rails:test_mysql2"]
|
30
|
-
ar_version: ["7-
|
30
|
+
ar_version: ["7-1-stable"]
|
31
31
|
prepared_statements: ['false', 'true']
|
32
32
|
driver: ['MySQL']
|
33
33
|
|
@@ -42,10 +42,10 @@ jobs:
|
|
42
42
|
AR_VERSION: ${{ matrix.ar_version }}
|
43
43
|
PREPARED_STATEMENTS: ${{ matrix.prepared_statements }}
|
44
44
|
DRIVER: ${{ matrix.driver }}
|
45
|
-
JRUBY_OPTS: "-J-Xms64M -J-Xmx1024M"
|
45
|
+
JRUBY_OPTS: "-J-Xms64M -J-Xmx1024M --dev"
|
46
46
|
|
47
47
|
steps:
|
48
|
-
- uses: actions/checkout@
|
48
|
+
- uses: actions/checkout@v4
|
49
49
|
- name: Set up Ruby
|
50
50
|
uses: ruby/setup-ruby@v1
|
51
51
|
with:
|
@@ -79,12 +79,12 @@ jobs:
|
|
79
79
|
ruby-version: [ 'jruby-head' ]
|
80
80
|
db: [ 'postgresql' ]
|
81
81
|
test_targets: [ "rails:test_postgresql" ]
|
82
|
-
ar_version: ["7-
|
82
|
+
ar_version: ["7-1-stable"]
|
83
83
|
prepared_statements: [ 'false', 'true' ]
|
84
84
|
|
85
85
|
services:
|
86
86
|
postgres:
|
87
|
-
image: postgres:
|
87
|
+
image: postgres:11
|
88
88
|
env:
|
89
89
|
POSTGRES_PASSWORD: postgres
|
90
90
|
POSTGRES_HOST_AUTH_METHOD: trust
|
@@ -95,14 +95,14 @@ jobs:
|
|
95
95
|
env:
|
96
96
|
DB: ${{ matrix.db }}
|
97
97
|
AR_VERSION: ${{ matrix.ar_version }}
|
98
|
-
JRUBY_OPTS: "-J-Xms64M -J-Xmx1024M"
|
98
|
+
JRUBY_OPTS: "-J-Xms64M -J-Xmx1024M --dev"
|
99
99
|
PREPARED_STATEMENTS: ${{ matrix.prepared_statements }}
|
100
100
|
PGHOST: localhost
|
101
101
|
PGPORT: 5432
|
102
102
|
PGUSER: postgres
|
103
103
|
|
104
104
|
steps:
|
105
|
-
- uses: actions/checkout@
|
105
|
+
- uses: actions/checkout@v4
|
106
106
|
- name: Set up Ruby
|
107
107
|
uses: ruby/setup-ruby@v1
|
108
108
|
with:
|
@@ -129,15 +129,15 @@ jobs:
|
|
129
129
|
ruby-version: ['jruby-head']
|
130
130
|
db: ['sqlite3']
|
131
131
|
test_targets: ["rails:test_sqlite3"]
|
132
|
-
ar_version: ["7-
|
132
|
+
ar_version: ["7-1-stable"]
|
133
133
|
|
134
134
|
env:
|
135
135
|
DB: ${{ matrix.db }}
|
136
136
|
AR_VERSION: ${{ matrix.ar_version }}
|
137
|
-
JRUBY_OPTS: "-J-Xms64M -J-Xmx1024M"
|
137
|
+
JRUBY_OPTS: "-J-Xms64M -J-Xmx1024M --dev"
|
138
138
|
|
139
139
|
steps:
|
140
|
-
- uses: actions/checkout@
|
140
|
+
- uses: actions/checkout@v4
|
141
141
|
- name: Set up Ruby
|
142
142
|
uses: ruby/setup-ruby@v1
|
143
143
|
with:
|
@@ -149,7 +149,7 @@ jobs:
|
|
149
149
|
rake jar # compiles ext generates: lib/arjdbc/jdbc/adapter_java.jar
|
150
150
|
- name: Run tests
|
151
151
|
run: |
|
152
|
-
bundle exec rake ${{ matrix.test_targets }}
|
152
|
+
bundle exec rake ${{ matrix.test_targets }} --trace
|
153
153
|
|
154
154
|
test-arjdbc-mysql:
|
155
155
|
|
@@ -173,13 +173,13 @@ jobs:
|
|
173
173
|
env:
|
174
174
|
DB: ${{ matrix.db }}
|
175
175
|
DRIVER: ${{ matrix.driver }}
|
176
|
-
JRUBY_OPTS: "-J-Xms64M -J-Xmx1024M"
|
176
|
+
JRUBY_OPTS: "-J-Xms64M -J-Xmx1024M --dev"
|
177
177
|
MY_USER: root
|
178
178
|
MY_PASSWORD: root
|
179
179
|
PREPARED_STATEMENTS: ${{ matrix.prepared_statements }}
|
180
180
|
|
181
181
|
steps:
|
182
|
-
- uses: actions/checkout@
|
182
|
+
- uses: actions/checkout@v4
|
183
183
|
- name: Set up Ruby
|
184
184
|
uses: ruby/setup-ruby@v1
|
185
185
|
with:
|
@@ -211,7 +211,7 @@ jobs:
|
|
211
211
|
|
212
212
|
services:
|
213
213
|
postgres:
|
214
|
-
image: postgres:
|
214
|
+
image: postgres:11
|
215
215
|
env:
|
216
216
|
POSTGRES_PASSWORD: postgres
|
217
217
|
POSTGRES_HOST_AUTH_METHOD: trust
|
@@ -222,7 +222,7 @@ jobs:
|
|
222
222
|
env:
|
223
223
|
DB: ${{ matrix.db }}
|
224
224
|
DRIVER: ${{ matrix.driver }}
|
225
|
-
JRUBY_OPTS: "-J-Xms64M -J-Xmx1024M"
|
225
|
+
JRUBY_OPTS: "-J-Xms64M -J-Xmx1024M --dev"
|
226
226
|
PREPARED_STATEMENTS: ${{ matrix.prepared_statements }}
|
227
227
|
INSERT_RETURNING: ${{ matrix.insert_returning }}
|
228
228
|
PGHOST: localhost
|
@@ -230,7 +230,7 @@ jobs:
|
|
230
230
|
PGUSER: postgres
|
231
231
|
|
232
232
|
steps:
|
233
|
-
- uses: actions/checkout@
|
233
|
+
- uses: actions/checkout@v4
|
234
234
|
- name: Set up Ruby
|
235
235
|
uses: ruby/setup-ruby@v1
|
236
236
|
with:
|
@@ -256,10 +256,10 @@ jobs:
|
|
256
256
|
|
257
257
|
env:
|
258
258
|
DB: ${{ matrix.db }}
|
259
|
-
JRUBY_OPTS: "-J-Xms64M -J-Xmx1024M"
|
259
|
+
JRUBY_OPTS: "-J-Xms64M -J-Xmx1024M --dev"
|
260
260
|
|
261
261
|
steps:
|
262
|
-
- uses: actions/checkout@
|
262
|
+
- uses: actions/checkout@v4
|
263
263
|
- name: Set up Ruby
|
264
264
|
uses: ruby/setup-ruby@v1
|
265
265
|
with:
|
data/.gitignore
CHANGED
@@ -15,9 +15,12 @@ coverage
|
|
15
15
|
build.xml
|
16
16
|
nbproject
|
17
17
|
.classpath
|
18
|
+
.ruby-version
|
18
19
|
.project
|
19
20
|
*.sqlite
|
20
21
|
*.sqlite3
|
22
|
+
*.sqlite3-shm
|
23
|
+
*.sqlite3-wal
|
21
24
|
*.derby
|
22
25
|
derby.log
|
23
26
|
test.hsqldb*
|
@@ -32,3 +35,8 @@ Gemfile.lock
|
|
32
35
|
.settings
|
33
36
|
activerecord-jdbc.iml
|
34
37
|
lib/arjdbc/jdbc/adapter_java.jar
|
38
|
+
.jrubyrc
|
39
|
+
.rubocop.yml
|
40
|
+
.solargraph.yml
|
41
|
+
pik.sh
|
42
|
+
.tool-versions
|
data/Gemfile
CHANGED
@@ -41,10 +41,17 @@ elsif ENV['AR_VERSION'] # Use specific version of AR and not .gemspec version
|
|
41
41
|
gem 'actionpack', require: false
|
42
42
|
gem 'actionview', require: false
|
43
43
|
end
|
44
|
+
|
44
45
|
end
|
45
46
|
end
|
46
47
|
else
|
47
|
-
|
48
|
+
if defined? JRUBY_VERSION
|
49
|
+
gemspec name: 'activerecord-jdbc-adapter' # Use versiom from .gemspec
|
50
|
+
else # read add_dependency 'activerecord', '~> 7.0' and use the same requirement on MRI
|
51
|
+
ar_req = File.read('activerecord-jdbc-adapter.gemspec').match(/add_dependency.*?activerecord.*['"](.*?)['"]/)[1]
|
52
|
+
raise "add_dependency 'activerecord', ... line not detected in gemspec" unless ar_req
|
53
|
+
gem 'activerecord', ar_req
|
54
|
+
end
|
48
55
|
end
|
49
56
|
|
50
57
|
gem 'rake', require: nil
|
@@ -59,7 +66,7 @@ end
|
|
59
66
|
|
60
67
|
group :rails do
|
61
68
|
group :test do
|
62
|
-
gem 'minitest', require: nil
|
69
|
+
gem 'minitest', '~> 5.24.0', require: nil
|
63
70
|
gem 'minitest-excludes', require: nil
|
64
71
|
gem 'minitest-rg', require: nil
|
65
72
|
|
@@ -70,6 +77,10 @@ group :rails do
|
|
70
77
|
gem 'builder', require: nil
|
71
78
|
|
72
79
|
gem 'erubis', require: nil # "~> 2.7.0"
|
80
|
+
|
81
|
+
# Due to rails/activesupport/lib/active_support/message_pack.rb
|
82
|
+
gem 'msgpack', '>= 1.7.0', require: false
|
83
|
+
|
73
84
|
# NOTE: due rails/activerecord/test/cases/connection_management_test.rb
|
74
85
|
gem 'rack', require: nil
|
75
86
|
|
@@ -77,7 +88,7 @@ group :rails do
|
|
77
88
|
end
|
78
89
|
|
79
90
|
group :development do
|
80
|
-
gem 'ruby-debug', require: nil # if ENV['DEBUG']
|
91
|
+
#gem 'ruby-debug', require: nil # if ENV['DEBUG']
|
81
92
|
group :doc do
|
82
93
|
gem 'yard', require: nil
|
83
94
|
gem 'kramdown', require: nil
|
@@ -92,10 +103,12 @@ group :test do
|
|
92
103
|
|
93
104
|
gem 'mysql2', '>= 0.4.4', require: nil, platform: :mri
|
94
105
|
gem 'pg', '>= 0.18.0', require: nil, platform: :mri
|
95
|
-
gem 'sqlite3', '~> 1.
|
106
|
+
gem 'sqlite3', '~> 1.4', require: nil, platform: :mri
|
96
107
|
|
97
108
|
# group :mssql do
|
98
109
|
# gem 'tiny_tds', require: nil, platform: :mri
|
99
110
|
# gem 'activerecord-sqlserver-adapter', require: nil, platform: :mri
|
100
111
|
# end
|
101
112
|
end
|
113
|
+
|
114
|
+
gem 'pry-nav'
|
data/README.md
CHANGED
@@ -24,10 +24,15 @@ Versions are targeted at certain versions of Rails and live on their own branche
|
|
24
24
|
| 51.x | 5.1.x | 51-stable | 9.1.x | 7 |
|
25
25
|
| 52.x | 5.2.x | 52-stable | 9.1.x | 7 |
|
26
26
|
| 60.x | 6.0.x | 60-stable | 9.2.7 | 8 |
|
27
|
-
| 61.x | 6.1.x |
|
27
|
+
| 61.x | 6.1.x | 61-stable | 9.2.7 | 8 |
|
28
|
+
| 70.x | 7.0.x | 70-stable | 9.3.0 | 8 |
|
29
|
+
| 71.x | 7.1.x | 71-stable | 9.4.3 | 8 |
|
30
|
+
| 72.x | 7.2.x | master | 9.4.3 | 8 |
|
28
31
|
|
29
|
-
Note
|
30
|
-
|
32
|
+
Note: 72.x is still under development and not supported yet.
|
33
|
+
|
34
|
+
Note that JRuby 9.1.x and JRuby 9.2.x are at end-of-life. We recommend Java 8
|
35
|
+
at a minimum for all versions.
|
31
36
|
|
32
37
|
## Using ActiveRecord JDBC
|
33
38
|
|
data/RUNNING_TESTS.md
CHANGED
@@ -16,6 +16,8 @@ Rake tasks are loaded from **rakelib/02-test-rake**, most adapters have a
|
|
16
16
|
corresponding test_[adapter] task e.g. `rake test_sqlite3` that run against DB.
|
17
17
|
To check all available (test related) tasks simply `rake -T | grep test`.
|
18
18
|
|
19
|
+
### Database Setup
|
20
|
+
|
19
21
|
If the adapter supports creating a database it will try to do so automatically
|
20
22
|
(most embed databases such as SQLite3) for some adapters (MySQL, PostgreSQL) we
|
21
23
|
do this auto-magically (see the `rake db:create` tasks), but otherwise you'll
|
@@ -48,6 +50,40 @@ but one can easily run tests with prepared statements disabled using env vars :
|
|
48
50
|
|
49
51
|
rake test_derby PREPARED_STATEMENTS=false
|
50
52
|
|
53
|
+
#### MySQL with Docker
|
54
|
+
|
55
|
+
The standard Docker MySQL image can be used for testing and development. Depending on your environment these commands
|
56
|
+
may need to be run as root.
|
57
|
+
|
58
|
+
Pull the image:
|
59
|
+
|
60
|
+
```
|
61
|
+
sudo docker pull mysql
|
62
|
+
```
|
63
|
+
|
64
|
+
Start up the database with a root password (we show a simple one here but pick one no one else knows):
|
65
|
+
|
66
|
+
```
|
67
|
+
docker run -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=testtest9 -d mysql
|
68
|
+
```
|
69
|
+
|
70
|
+
The `mysql` client can be run through Docker as well:
|
71
|
+
|
72
|
+
```sh
|
73
|
+
docker run -it --link mysql:mysql --rm mysql sh -c 'exec mysql -h"$MYSQL_PORT_3306_TCP_ADDR" -P"$MYSQL_PORT_3306_TCP_PORT" -uroot -p"$MYSQL_ENV_MYSQL_ROOT_PASSWORD"'
|
74
|
+
```
|
75
|
+
|
76
|
+
Set up the database for the unit tests (you may need to replace 'localhost' with your container's IP):
|
77
|
+
|
78
|
+
```sql
|
79
|
+
CREATE USER 'rails'@'localhost' IDENTIFIED BY 'testtest9';
|
80
|
+
CREATE DATABASE activerecord_unittest;
|
81
|
+
GRANT ALL PRIVILEGES ON activerecord_unittest.* TO 'rails'@'localhost';
|
82
|
+
CREATE DATABASE activerecord_unittest2;
|
83
|
+
GRANT ALL PRIVILEGES ON activerecord_unittest2.* TO 'rails'@'localhost';
|
84
|
+
```
|
85
|
+
|
86
|
+
Then edit test/rails/config.yml for the appropriate configuration credentials.
|
51
87
|
|
52
88
|
### ActiveRecord (Rails) Tests
|
53
89
|
|
@@ -14,7 +14,7 @@ Gem::Specification.new do |gem|
|
|
14
14
|
"AR-JDBC is a database adapter for Rails' ActiveRecord component " <<
|
15
15
|
"designed to be used with JRuby built upon Java's JDBC API for " <<
|
16
16
|
"database access. Provides (ActiveRecord) built-in adapters: MySQL, " <<
|
17
|
-
"PostgreSQL,
|
17
|
+
"PostgreSQL, and SQLite3."
|
18
18
|
|
19
19
|
gem.require_paths = ["lib"]
|
20
20
|
|
@@ -41,7 +41,7 @@ Gem::Specification.new do |gem|
|
|
41
41
|
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
42
42
|
gem.test_files = gem.files.grep(%r{^test/})
|
43
43
|
|
44
|
-
gem.add_dependency 'activerecord', '~> 7.
|
44
|
+
gem.add_dependency 'activerecord', '~> 7.1.3'
|
45
45
|
|
46
46
|
#gem.add_development_dependency 'test-unit', '2.5.4'
|
47
47
|
#gem.add_development_dependency 'test-unit-context', '>= 0.3.0'
|
@@ -6,29 +6,28 @@ module ArJdbc
|
|
6
6
|
|
7
7
|
# @override
|
8
8
|
def active?
|
9
|
-
|
10
|
-
@connection.active?
|
9
|
+
@raw_connection&.active?
|
11
10
|
end
|
12
11
|
|
13
12
|
def really_valid?
|
14
|
-
|
15
|
-
@connection.really_valid?
|
13
|
+
@raw_connection&.really_valid?
|
16
14
|
end
|
17
15
|
|
18
16
|
# @override
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
17
|
+
# Removed to fix sqlite adapter, may be needed for others
|
18
|
+
# def reconnect!
|
19
|
+
# super # clear_cache! && reset_transaction
|
20
|
+
# @connection.reconnect! # handles adapter.configure_connection
|
21
|
+
# end
|
23
22
|
|
24
23
|
# @override
|
25
24
|
def disconnect!
|
26
25
|
super # clear_cache! && reset_transaction
|
27
|
-
|
28
|
-
@connection.disconnect!
|
26
|
+
@raw_connection&.disconnect!
|
29
27
|
end
|
30
28
|
|
31
29
|
# @override
|
30
|
+
# Removed to fix sqlite adapter, may be needed for others
|
32
31
|
# def verify!(*ignored)
|
33
32
|
# if @connection && @connection.jndi?
|
34
33
|
# # checkout call-back does #reconnect!
|
@@ -37,6 +36,22 @@ module ArJdbc
|
|
37
36
|
# end
|
38
37
|
# end
|
39
38
|
|
39
|
+
private
|
40
|
+
|
41
|
+
# DIFFERENCE: we delve into jdbc shared code and this does self.class.new_client.
|
42
|
+
def connect
|
43
|
+
@raw_connection = self.class.new_client(@connection_parameters, self)
|
44
|
+
rescue ActiveRecord::ConnectionNotEstablished => ex
|
45
|
+
raise ex.set_pool(@pool)
|
46
|
+
end
|
47
|
+
|
48
|
+
def reconnect
|
49
|
+
@raw_connection&.close
|
50
|
+
|
51
|
+
@raw_connection = nil
|
52
|
+
|
53
|
+
connect
|
54
|
+
end
|
40
55
|
end
|
41
56
|
end
|
42
57
|
end
|
data/lib/arjdbc/abstract/core.rb
CHANGED
@@ -2,27 +2,17 @@
|
|
2
2
|
|
3
3
|
module ArJdbc
|
4
4
|
module Abstract
|
5
|
-
|
6
5
|
# This is minimum amount of code needed from base JDBC Adapter class to make common adapters
|
7
6
|
# work. This replaces using jdbc/adapter as a base class for all adapters.
|
8
7
|
module Core
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
def initialize(connection, logger = nil, config = {})
|
13
|
-
@config = config
|
8
|
+
def initialize(...)
|
9
|
+
super
|
14
10
|
|
15
11
|
if self.class.equal? ActiveRecord::ConnectionAdapters::JdbcAdapter
|
16
12
|
spec = @config.key?(:adapter_spec) ? @config[:adapter_spec] :
|
17
13
|
( @config[:adapter_spec] = adapter_spec(@config) ) # due resolving visitor
|
18
14
|
extend spec if spec
|
19
15
|
end
|
20
|
-
|
21
|
-
connection ||= jdbc_connection_class(config[:adapter_spec]).new(config, self)
|
22
|
-
|
23
|
-
super(connection, logger, config) # AbstractAdapter
|
24
|
-
|
25
|
-
connection.configure_connection # will call us (maybe)
|
26
16
|
end
|
27
17
|
|
28
18
|
# Retrieve the raw `java.sql.Connection` object.
|
@@ -56,6 +46,9 @@ module ArJdbc
|
|
56
46
|
# swallow an ArJdbc / driver bug into an AR::StatementInvalid !
|
57
47
|
return exception if exception.is_a?(Throwable)
|
58
48
|
|
49
|
+
# We create this exception in Java where we do not have access to the pool
|
50
|
+
exception.instance_variable_set(:@connection_pool, @pool) if exception.kind_of?(::ActiveRecord::JDBCError)
|
51
|
+
|
59
52
|
case exception
|
60
53
|
when SystemExit, SignalException, NoMemoryError then exception
|
61
54
|
when ActiveModel::RangeError, TypeError, RuntimeError then exception
|
@@ -9,85 +9,75 @@ module ArJdbc
|
|
9
9
|
|
10
10
|
NO_BINDS = [].freeze
|
11
11
|
|
12
|
-
def exec_insert(sql, name = nil, binds = NO_BINDS, pk = nil, sequence_name = nil)
|
12
|
+
def exec_insert(sql, name = nil, binds = NO_BINDS, pk = nil, sequence_name = nil, returning: nil)
|
13
13
|
sql = transform_query(sql)
|
14
14
|
|
15
15
|
if preventing_writes?
|
16
16
|
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
17
17
|
end
|
18
18
|
|
19
|
-
materialize_transactions
|
20
19
|
mark_transaction_written_if_write(sql)
|
21
20
|
|
22
21
|
binds = convert_legacy_binds_to_attributes(binds) if binds.first.is_a?(Array)
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
23
|
+
with_raw_connection do |conn|
|
24
|
+
if without_prepared_statement?(binds)
|
25
|
+
log(sql, name) { conn.execute_insert_pk(sql, pk) }
|
26
|
+
else
|
27
|
+
log(sql, name, binds) do
|
28
|
+
conn.execute_insert_pk(sql, binds, pk)
|
29
|
+
end
|
29
30
|
end
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
33
34
|
# It appears that at this point (AR 5.0) "prepare" should only ever be true
|
34
35
|
# if prepared statements are enabled
|
35
|
-
def
|
36
|
+
def internal_exec_query(sql, name = nil, binds = NO_BINDS, prepare: false, async: false, allow_retry: false, materialize_transactions: true)
|
36
37
|
sql = transform_query(sql)
|
37
38
|
|
38
39
|
if preventing_writes? && write_query?(sql)
|
39
40
|
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
40
41
|
end
|
41
42
|
|
42
|
-
materialize_transactions
|
43
43
|
mark_transaction_written_if_write(sql)
|
44
44
|
|
45
45
|
binds = convert_legacy_binds_to_attributes(binds) if binds.first.is_a?(Array)
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
47
|
+
with_raw_connection do |conn|
|
48
|
+
if without_prepared_statement?(binds)
|
49
|
+
log(sql, name, async: async) { conn.execute_query(sql) }
|
50
|
+
else
|
51
|
+
log(sql, name, binds, async: async) do
|
52
|
+
# this is different from normal AR that always caches
|
53
|
+
cached_statement = fetch_cached_statement(sql) if prepare && @jdbc_statement_cache_enabled
|
54
|
+
conn.execute_prepared_query(sql, binds, cached_statement)
|
55
|
+
end
|
54
56
|
end
|
55
57
|
end
|
56
58
|
end
|
57
59
|
|
58
|
-
def exec_update(sql, name =
|
60
|
+
def exec_update(sql, name = 'SQL', binds = NO_BINDS)
|
59
61
|
sql = transform_query(sql)
|
60
62
|
|
61
63
|
if preventing_writes?
|
62
64
|
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
63
65
|
end
|
64
66
|
|
65
|
-
materialize_transactions
|
66
67
|
mark_transaction_written_if_write(sql)
|
67
68
|
|
68
69
|
binds = convert_legacy_binds_to_attributes(binds) if binds.first.is_a?(Array)
|
69
70
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
71
|
+
with_raw_connection do |conn|
|
72
|
+
if without_prepared_statement?(binds)
|
73
|
+
log(sql, name) { conn.execute_update(sql) }
|
74
|
+
else
|
75
|
+
log(sql, name, binds) { conn.execute_prepared_update(sql, binds) }
|
76
|
+
end
|
74
77
|
end
|
75
78
|
end
|
76
79
|
alias :exec_delete :exec_update
|
77
80
|
|
78
|
-
def execute(sql, name = nil, async: false)
|
79
|
-
sql = transform_query(sql)
|
80
|
-
|
81
|
-
if preventing_writes? && write_query?(sql)
|
82
|
-
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
83
|
-
end
|
84
|
-
|
85
|
-
materialize_transactions
|
86
|
-
mark_transaction_written_if_write(sql)
|
87
|
-
|
88
|
-
log(sql, name, async: async) { @connection.execute(sql) }
|
89
|
-
end
|
90
|
-
|
91
81
|
# overridden to support legacy binds
|
92
82
|
def select_all(arel, name = nil, binds = NO_BINDS, preparable: nil, async: false)
|
93
83
|
binds = convert_legacy_binds_to_attributes(binds) if binds.first.is_a?(Array)
|
@@ -102,6 +92,16 @@ module ArJdbc
|
|
102
92
|
end
|
103
93
|
end
|
104
94
|
|
95
|
+
def raw_execute(sql, name, async: false, allow_retry: false, materialize_transactions: true)
|
96
|
+
log(sql, name, async: async) do
|
97
|
+
with_raw_connection(allow_retry: allow_retry, materialize_transactions: materialize_transactions) do |conn|
|
98
|
+
result = conn.execute(sql)
|
99
|
+
verified!
|
100
|
+
result
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
105
|
end
|
106
106
|
end
|
107
107
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_model/attribute"
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
# NOTE: improved implementation for hash methods that is used to
|
7
|
+
# compare objects. AR and arel commonly use `[a, b] - [b]` operations and
|
8
|
+
# JRuby internally uses the hash method to implement that operation,
|
9
|
+
# on the other hand, CRuby does not use the hash method
|
10
|
+
# for small arrays (length <= 16).
|
11
|
+
class Relation
|
12
|
+
# monkey patch
|
13
|
+
module RelationQueryAttributeMonkeyPatch
|
14
|
+
def hash
|
15
|
+
# [self.class, name, value_for_database, type].hash
|
16
|
+
[self.class, name, value_before_type_cast, type].hash
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class QueryAttribute
|
21
|
+
prepend RelationQueryAttributeMonkeyPatch
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -24,23 +24,18 @@ module ArJdbc
|
|
24
24
|
|
25
25
|
# Only say we support the statement cache if we are using prepared statements
|
26
26
|
# and have a max number of statements defined
|
27
|
-
statement_limit = self.class.type_cast_config_to_integer(config[:statement_limit])
|
27
|
+
statement_limit = self.class.type_cast_config_to_integer(@config[:statement_limit])
|
28
28
|
@jdbc_statement_cache_enabled = prepared_statements && (statement_limit.nil? || statement_limit > 0)
|
29
29
|
|
30
30
|
@statements = StatementPool.new(statement_limit) # AR (5.0) expects this to be stored as @statements
|
31
31
|
end
|
32
32
|
|
33
|
-
# Clears the prepared statements cache.
|
34
|
-
def clear_cache!
|
35
|
-
@statements.clear
|
36
|
-
end
|
37
|
-
|
38
33
|
def delete_cached_statement(sql)
|
39
34
|
@statements.delete(sql_key(sql))
|
40
35
|
end
|
41
36
|
|
42
37
|
def fetch_cached_statement(sql)
|
43
|
-
@statements[sql_key(sql)] ||= @
|
38
|
+
@statements[sql_key(sql)] ||= @raw_connection.prepare_statement(sql)
|
44
39
|
end
|
45
40
|
|
46
41
|
private
|