activerecord-jdbc-alt-adapter 51.3.2-java → 51.7.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/.gitignore +3 -0
- data/.travis.yml +22 -18
- data/Gemfile +1 -1
- data/README.md +11 -9
- data/Rakefile +30 -4
- data/activerecord-jdbc-adapter.gemspec +1 -1
- data/activerecord-jdbc-alt-adapter.gemspec +2 -2
- data/lib/activerecord-jdbc-alt-adapter.rb +1 -0
- data/lib/arjdbc/abstract/core.rb +2 -2
- data/lib/arjdbc/abstract/database_statements.rb +8 -2
- data/lib/arjdbc/jdbc.rb +0 -4
- data/lib/arjdbc/jdbc/column.rb +5 -11
- data/lib/arjdbc/mssql/adapter.rb +24 -11
- data/lib/arjdbc/mssql/connection_methods.rb +5 -0
- data/lib/arjdbc/mssql/database_statements.rb +1 -1
- data/lib/arjdbc/mssql/schema_statements.rb +1 -1
- data/lib/arjdbc/mysql/connection_methods.rb +13 -7
- data/lib/arjdbc/postgresql/column.rb +6 -3
- data/lib/arjdbc/postgresql/connection_methods.rb +3 -1
- data/lib/arjdbc/sqlite3/connection_methods.rb +1 -0
- data/lib/arjdbc/version.rb +1 -1
- data/rakelib/01-tomcat.rake +2 -2
- data/rakelib/02-test.rake +0 -2
- data/rakelib/rails.rake +1 -1
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +62 -8
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +282 -38
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +3 -2
- data/src/java/arjdbc/util/DateTimeUtils.java +22 -5
- metadata +7 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9bac3f491bd6e25ce779db381c70f8de2bcfc566f7d7add71c73453d4b9d96da
|
|
4
|
+
data.tar.gz: 5e3cdf41dde39ac86a39d6d21057ede60c0fa321aa9e1164cc5c13c1b6584800
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 28c69d682d31b0c159bf4fbc309699c0c362696e7edff789e1a51304284407dd09f4f63bf0d97bd460616378b3456cad4535c7fef4c19d607a92ccb962c8d80d
|
|
7
|
+
data.tar.gz: d83167a275cc51a6715f9a019d8df7519c6bb35d531466fe2e0c61191150238f20c70f9ae233a85e5ad31f89ae61b2f28d9c1fb2b7a17e2591c2ca2ccf529b1b
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
|
@@ -1,18 +1,27 @@
|
|
|
1
|
-
language: ruby
|
|
2
1
|
sudo: false
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
bundler_args: --without development
|
|
11
|
-
script: bundle exec rake ${TEST_PREFIX}test_$DB
|
|
2
|
+
dist: xenial
|
|
3
|
+
|
|
4
|
+
services:
|
|
5
|
+
- mysql
|
|
6
|
+
addons:
|
|
7
|
+
postgresql: 9.4
|
|
8
|
+
|
|
12
9
|
before_install:
|
|
13
10
|
- unset _JAVA_OPTIONS
|
|
14
11
|
- rvm @default,@global do gem uninstall bundler -a -x -I || true
|
|
15
12
|
- gem install bundler -v "~>1.17.3"
|
|
13
|
+
install:
|
|
14
|
+
- bundle install --retry 3 --without development
|
|
15
|
+
# to fix this issue: https://travis-ci.community/t/mariadb-10-1-fails-to-install-on-xenial/3151/3
|
|
16
|
+
- mysql -u root -e 'CREATE USER IF NOT EXISTS travis@localhost; GRANT ALL ON *.* TO travis@localhost;' || true
|
|
17
|
+
|
|
18
|
+
language: ruby
|
|
19
|
+
rvm:
|
|
20
|
+
- jruby-9.1.16.0
|
|
21
|
+
jdk:
|
|
22
|
+
- openjdk8
|
|
23
|
+
|
|
24
|
+
script: bundle exec rake ${TEST_PREFIX}test_$DB
|
|
16
25
|
before_script:
|
|
17
26
|
- echo "JAVA_OPTS=$JAVA_OPTS"
|
|
18
27
|
- export JRUBY_OPTS="-J-Xms64M -J-Xmx1024M"
|
|
@@ -38,12 +47,7 @@ before_script:
|
|
|
38
47
|
psql -c "create database activerecord_unittest;" -U postgres && \
|
|
39
48
|
psql -c "create database activerecord_unittest2;" -U postgres \
|
|
40
49
|
|| true
|
|
41
|
-
|
|
42
|
-
- jruby-9.1.16.0
|
|
43
|
-
jdk:
|
|
44
|
-
- openjdk8
|
|
45
|
-
addons:
|
|
46
|
-
postgresql: "9.4"
|
|
50
|
+
|
|
47
51
|
env:
|
|
48
52
|
- DB=mysql2 PREPARED_STATEMENTS=false
|
|
49
53
|
- DB=mysql2 PREPARED_STATEMENTS=true
|
|
@@ -86,10 +90,10 @@ matrix:
|
|
|
86
90
|
env: DB=sqlite3
|
|
87
91
|
# testing against MariaDB
|
|
88
92
|
- addons:
|
|
89
|
-
mariadb:
|
|
93
|
+
mariadb: 10.2
|
|
90
94
|
env: DB=mariadb PREPARED_STATEMENTS=false
|
|
91
95
|
- addons:
|
|
92
|
-
mariadb:
|
|
96
|
+
mariadb: 10.3
|
|
93
97
|
env: DB=mariadb PREPARED_STATEMENTS=true
|
|
94
98
|
# Rails test-suite :
|
|
95
99
|
- env: DB=mysql2 TEST_PREFIX="rails:" AR_VERSION="v5.1.7" # PS off by default
|
data/Gemfile
CHANGED
|
@@ -48,7 +48,7 @@ group :test do
|
|
|
48
48
|
gem 'mocha', '~> 1.2', require: false # Rails has '~> 0.14'
|
|
49
49
|
|
|
50
50
|
gem 'bcrypt', '~> 3.1.11', require: false
|
|
51
|
-
gem 'jdbc-mssql', '~> 0.
|
|
51
|
+
gem 'jdbc-mssql', '~> 0.7.0', require: nil
|
|
52
52
|
# gem 'pry-debugger-jruby', platform: :jruby
|
|
53
53
|
end
|
|
54
54
|
|
data/README.md
CHANGED
|
@@ -114,15 +114,16 @@ this adapter should just work.
|
|
|
114
114
|
ActiveRecord-JDBC-Adapter (AR-JDBC) is the main database adapter for Rails'
|
|
115
115
|
*ActiveRecord* component that can be used with [JRuby][0].
|
|
116
116
|
ActiveRecord-JDBC-Adapter provides full or nearly full support for:
|
|
117
|
-
**MySQL**, **PostgreSQL**, **SQLite3
|
|
118
|
-
add support **MSSQL**. Unless we get more contributions we will not be going
|
|
119
|
-
beyond these four adapters. Note that the amount of work needed to get
|
|
120
|
-
another adapter is not huge but the amount of testing required to make sure
|
|
121
|
-
that adapter continues to work is not something we can do with the resources
|
|
122
|
-
we currently have.
|
|
117
|
+
**MySQL**, **PostgreSQL**, **SQLite3** and **MSSQL*** (SQLServer).
|
|
123
118
|
|
|
124
|
-
|
|
125
|
-
|
|
119
|
+
Unless we get more contributions we will not be supporting more adapters.
|
|
120
|
+
Note that the amount of work needed to get another adapter is not huge but
|
|
121
|
+
the amount of testing required to make sure that adapter continues to work
|
|
122
|
+
is not something we can do with the resources we currently have.
|
|
123
|
+
|
|
124
|
+
- for **Oracle** database users you are encouraged to use
|
|
125
|
+
https://github.com/rsim/oracle-enhanced
|
|
126
|
+
- **MSSQL** adapter's gem parts reside in a [separate repository][8]
|
|
126
127
|
|
|
127
128
|
Version **50.x** supports Rails version 5.0.x and it lives on branch 50-stable.
|
|
128
129
|
Version **51.x** supports Rails version 5.1.x and is currently on master until
|
|
@@ -141,6 +142,7 @@ adapters are available:
|
|
|
141
142
|
- MySQL (`activerecord-jdbcmysql-adapter`)
|
|
142
143
|
- PostgreSQL (`activerecord-jdbcpostgresql-adapter`)
|
|
143
144
|
- SQLite3 (`activerecord-jdbcsqlite3-adapter`)
|
|
145
|
+
- MSSQL (`activerecord-jdbcsqlserver-adapter`)
|
|
144
146
|
|
|
145
147
|
2. If you're generating a new Rails application, use the following command:
|
|
146
148
|
|
|
@@ -275,4 +277,4 @@ license the database's drivers are licensed. See each driver gem's LICENSE.txt.
|
|
|
275
277
|
[5]: https://github.com/jruby/activerecord-jdbc-adapter/wiki
|
|
276
278
|
[6]: https://webchat.freenode.net/?channels=#jruby
|
|
277
279
|
[7]: http://badge.fury.io/rb/activerecord-jdbc-adapter
|
|
278
|
-
[8]: https://github.com/jruby/activerecord-
|
|
280
|
+
[8]: https://github.com/jruby/activerecord-jdbcsqlserver-adapter
|
data/Rakefile
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
# Common usage
|
|
2
|
+
#
|
|
3
|
+
# rake build:adapters - to build all specific adapter gems and the base gem
|
|
4
|
+
# rake release:do - build:adapters + git tag + push gems
|
|
5
|
+
#
|
|
6
|
+
# Environment variables used by this Rakefile:
|
|
7
|
+
#
|
|
8
|
+
# INCLUDE_JAR_IN_GEM [default task - false, other taks - true]:
|
|
9
|
+
# Note: This is something you should not normally have to set.
|
|
10
|
+
# For local development we always will end up including the jar file
|
|
11
|
+
# in any task which generates our main gem. The wrinkle to this
|
|
12
|
+
# is when we do a custom github link in bundler:
|
|
13
|
+
#
|
|
14
|
+
# gem 'ar-jdbc', github: '...'
|
|
15
|
+
#
|
|
16
|
+
# Because we stopped committing a .jar file for every change and so when
|
|
17
|
+
# we include a gem like this it clones the repository and does a default
|
|
18
|
+
# build in rake. This in turn will end up forcing a compile to generate
|
|
19
|
+
# that jar (similar to how c-extensions compile at the time of install).
|
|
20
|
+
# For shipped gems we do include the jar so that people do not require
|
|
21
|
+
# this compile step.
|
|
22
|
+
#
|
|
23
|
+
# NOOP [release:do - false]
|
|
24
|
+
#
|
|
25
|
+
# No commands or gem pushing during a release.
|
|
26
|
+
|
|
1
27
|
require 'rake/clean'
|
|
2
28
|
|
|
3
29
|
CLEAN.include 'derby*', 'test.db.*', '*test.sqlite3', 'test/reports'
|
|
@@ -38,7 +64,8 @@ rake = lambda { |task| ruby "-S", "rake", task }
|
|
|
38
64
|
|
|
39
65
|
desc "Build #{gem_name} gem into the pkg directory."
|
|
40
66
|
task :build => :jar do
|
|
41
|
-
|
|
67
|
+
include_jar = ENV['INCLUDE_JAR_IN_GEM'] || 'true'
|
|
68
|
+
sh("INCLUDE_JAR_IN_GEM=#{include_jar} gem build -V '#{gemspec_path}'") do
|
|
42
69
|
gem_path = built_gem_path.call
|
|
43
70
|
file_name = File.basename(gem_path)
|
|
44
71
|
FileUtils.mkdir_p(File.join(base_dir, 'pkg'))
|
|
@@ -58,7 +85,6 @@ end
|
|
|
58
85
|
|
|
59
86
|
desc "Releasing AR-JDBC gems (use NOOP=true to disable gem pushing)"
|
|
60
87
|
task 'release:do' do
|
|
61
|
-
ENV['RELEASE'] = 'true' # so that .gemspec is built with adapter_java.jar
|
|
62
88
|
Rake::Task['build'].invoke
|
|
63
89
|
# Rake::Task['build:adapters'].invoke
|
|
64
90
|
|
|
@@ -257,7 +283,7 @@ if defined? JRUBY_VERSION
|
|
|
257
283
|
begin
|
|
258
284
|
require 'arjdbc/version'
|
|
259
285
|
rescue LoadError
|
|
260
|
-
path = File.expand_path('
|
|
286
|
+
path = File.expand_path('lib', File.dirname(__FILE__))
|
|
261
287
|
unless $LOAD_PATH.include?(path)
|
|
262
288
|
$LOAD_PATH << path; retry
|
|
263
289
|
end
|
|
@@ -297,7 +323,7 @@ if defined? JRUBY_VERSION
|
|
|
297
323
|
# class_files.gsub!('$', '\$') unless windows?
|
|
298
324
|
# args = class_files.map { |path| [ "-C #{classes_dir}", path ] }.flatten
|
|
299
325
|
|
|
300
|
-
if ENV['
|
|
326
|
+
if ENV['INCLUDE_JAR_IN_GEM'] == 'true'; require 'tempfile'
|
|
301
327
|
manifest = "Built-Time: #{Time.now.utc.strftime('%Y-%m-%d %H:%M:%S')}\n"
|
|
302
328
|
manifest += "Built-JRuby: #{JRUBY_VERSION}\n"
|
|
303
329
|
manifest += "Specification-Title: ActiveRecord-JDBC\n"
|
|
@@ -27,7 +27,7 @@ Gem::Specification.new do |gem|
|
|
|
27
27
|
reject { |f| f =~ /^(gemfiles)/ } # no tests - no Gemfile_s appraised ...
|
|
28
28
|
gem.files += ['lib/arjdbc/jdbc/adapter_java.jar'] #if ENV['RELEASE'].eql?('true')
|
|
29
29
|
|
|
30
|
-
if ENV['
|
|
30
|
+
if ENV['INCLUDE_JAR_IN_GEM'] != 'true' # @see Rakefile
|
|
31
31
|
gem.extensions << 'Rakefile' # to support auto-building .jar with :git paths
|
|
32
32
|
|
|
33
33
|
#gem.add_runtime_dependency 'jar-dependencies', '~> 0.1' # development not enough!
|
|
@@ -11,7 +11,7 @@ Gem::Specification.new do |gem|
|
|
|
11
11
|
gem.license = 'BSD-2-Clause'
|
|
12
12
|
gem.summary = 'ActiveRecord JDBC adapter, for use within JRuby on Rails and SQL Server'
|
|
13
13
|
gem.description = "" <<
|
|
14
|
-
"Fork of the ActiveRecord JDBC adapter with support for SQL Server
|
|
14
|
+
"Fork of the ActiveRecord JDBC adapter with support for SQL Server and Azure SQL, " <<
|
|
15
15
|
"for more information and help look at the README file in the github repository. " <<
|
|
16
16
|
"AR-JDBC is a database adapter for Rails' ActiveRecord component designed " <<
|
|
17
17
|
"to be used with JRuby built upon Java's JDBC API for database access. " <<
|
|
@@ -29,7 +29,7 @@ Gem::Specification.new do |gem|
|
|
|
29
29
|
reject { |f| f =~ /^(gemfiles)/ } # no tests - no Gemfile_s appraised ...
|
|
30
30
|
gem.files += ['lib/arjdbc/jdbc/adapter_java.jar'] #if ENV['RELEASE'].eql?('true')
|
|
31
31
|
|
|
32
|
-
if ENV['
|
|
32
|
+
if ENV['INCLUDE_JAR_IN_GEM'] != 'true' # @see Rakefile
|
|
33
33
|
gem.extensions << 'Rakefile' # to support auto-building .jar with :git paths
|
|
34
34
|
|
|
35
35
|
#gem.add_runtime_dependency 'jar-dependencies', '~> 0.1' # development not enough!
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'arjdbc'
|
data/lib/arjdbc/abstract/core.rb
CHANGED
|
@@ -22,7 +22,7 @@ module ArJdbc
|
|
|
22
22
|
|
|
23
23
|
connection.configure_connection # will call us (maybe)
|
|
24
24
|
end
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
# Retrieve the raw `java.sql.Connection` object.
|
|
27
27
|
# The unwrap parameter is useful if an attempt to unwrap a pooled (JNDI)
|
|
28
28
|
# connection should be made - to really return the 'native' JDBC object.
|
|
@@ -56,7 +56,7 @@ module ArJdbc
|
|
|
56
56
|
case e
|
|
57
57
|
when SystemExit, SignalException, NoMemoryError then e
|
|
58
58
|
when ActiveModel::RangeError, TypeError, RuntimeError then e
|
|
59
|
-
else
|
|
59
|
+
else super
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
|
|
@@ -10,11 +10,13 @@ module ArJdbc
|
|
|
10
10
|
NO_BINDS = [].freeze
|
|
11
11
|
|
|
12
12
|
def exec_insert(sql, name = nil, binds = NO_BINDS, pk = nil, sequence_name = nil)
|
|
13
|
+
binds = convert_legacy_binds_to_attributes(binds) if binds.first.is_a?(Array)
|
|
14
|
+
|
|
13
15
|
if without_prepared_statement?(binds)
|
|
14
|
-
log(sql, name) { @connection.
|
|
16
|
+
log(sql, name) { @connection.execute_insert_pk(sql, pk) }
|
|
15
17
|
else
|
|
16
18
|
log(sql, name, binds) do
|
|
17
|
-
@connection.
|
|
19
|
+
@connection.execute_insert_pk(sql, binds, pk)
|
|
18
20
|
end
|
|
19
21
|
end
|
|
20
22
|
end
|
|
@@ -22,6 +24,8 @@ module ArJdbc
|
|
|
22
24
|
# It appears that at this point (AR 5.0) "prepare" should only ever be true
|
|
23
25
|
# if prepared statements are enabled
|
|
24
26
|
def exec_query(sql, name = nil, binds = NO_BINDS, prepare: false)
|
|
27
|
+
binds = convert_legacy_binds_to_attributes(binds) if binds.first.is_a?(Array)
|
|
28
|
+
|
|
25
29
|
if without_prepared_statement?(binds)
|
|
26
30
|
log(sql, name) { @connection.execute_query(sql) }
|
|
27
31
|
else
|
|
@@ -34,6 +38,8 @@ module ArJdbc
|
|
|
34
38
|
end
|
|
35
39
|
|
|
36
40
|
def exec_update(sql, name = nil, binds = NO_BINDS)
|
|
41
|
+
binds = convert_legacy_binds_to_attributes(binds) if binds.first.is_a?(Array)
|
|
42
|
+
|
|
37
43
|
if without_prepared_statement?(binds)
|
|
38
44
|
log(sql, name) { @connection.execute_update(sql) }
|
|
39
45
|
else
|
data/lib/arjdbc/jdbc.rb
CHANGED
data/lib/arjdbc/jdbc/column.rb
CHANGED
|
@@ -26,23 +26,17 @@ module ActiveRecord
|
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
default = args[0].cast(default)
|
|
29
|
+
default = args[0].cast(default)
|
|
31
30
|
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
sql_type = args.delete_at(1)
|
|
32
|
+
type = args.delete_at(0)
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
elsif ArJdbc::AR42
|
|
37
|
-
default = args[0].type_cast_from_database(default)
|
|
38
|
-
else
|
|
39
|
-
default = default_value(default)
|
|
40
|
-
end
|
|
34
|
+
args.unshift(SqlTypeMetadata.new(:sql_type => sql_type, :type => type))
|
|
41
35
|
|
|
42
36
|
# super <= 4.1: (name, default, sql_type = nil, null = true)
|
|
43
37
|
# super >= 4.2: (name, default, cast_type, sql_type = nil, null = true)
|
|
44
38
|
# super >= 5.0: (name, default, sql_type_metadata = nil, null = true)
|
|
45
|
-
|
|
39
|
+
|
|
46
40
|
super(name, default, *args)
|
|
47
41
|
init_column(name, default, *args)
|
|
48
42
|
end
|
data/lib/arjdbc/mssql/adapter.rb
CHANGED
|
@@ -85,6 +85,12 @@ module ActiveRecord
|
|
|
85
85
|
::ActiveRecord::ConnectionAdapters::MSSQLColumn
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
+
# Does this adapter support DDL rollbacks in transactions? That is, would
|
|
89
|
+
# CREATE TABLE or ALTER TABLE get rolled back by a transaction?
|
|
90
|
+
def supports_ddl_transactions?
|
|
91
|
+
true
|
|
92
|
+
end
|
|
93
|
+
|
|
88
94
|
# Does this adapter support creating foreign key constraints?
|
|
89
95
|
def supports_foreign_keys?
|
|
90
96
|
true
|
|
@@ -100,6 +106,16 @@ module ActiveRecord
|
|
|
100
106
|
true
|
|
101
107
|
end
|
|
102
108
|
|
|
109
|
+
# Does this adapter support index sort order?
|
|
110
|
+
def supports_index_sort_order?
|
|
111
|
+
true
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Also known as filtered index
|
|
115
|
+
def supports_partial_index?
|
|
116
|
+
true
|
|
117
|
+
end
|
|
118
|
+
|
|
103
119
|
# Does this adapter support views?
|
|
104
120
|
def supports_views?
|
|
105
121
|
true
|
|
@@ -116,6 +132,13 @@ module ActiveRecord
|
|
|
116
132
|
super
|
|
117
133
|
end
|
|
118
134
|
|
|
135
|
+
def reset!
|
|
136
|
+
# execute 'IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION'
|
|
137
|
+
# NOTE: it seems the above line interferes with the jdbc driver
|
|
138
|
+
# and ending up in connection closed, issue seen in rails 5.2 and 6.0
|
|
139
|
+
reconnect!
|
|
140
|
+
end
|
|
141
|
+
|
|
119
142
|
def disable_referential_integrity
|
|
120
143
|
tables = tables_with_referential_integrity
|
|
121
144
|
|
|
@@ -202,21 +225,11 @@ module ActiveRecord
|
|
|
202
225
|
end
|
|
203
226
|
|
|
204
227
|
def configure_connection
|
|
205
|
-
|
|
228
|
+
# Here goes initial settings per connection
|
|
206
229
|
|
|
207
230
|
set_session_transaction_isolation
|
|
208
231
|
end
|
|
209
232
|
|
|
210
|
-
def lock_timeout
|
|
211
|
-
timeout = config[:lock_timeout].to_i
|
|
212
|
-
|
|
213
|
-
if timeout.positive?
|
|
214
|
-
timeout
|
|
215
|
-
else
|
|
216
|
-
5_000
|
|
217
|
-
end
|
|
218
|
-
end
|
|
219
|
-
|
|
220
233
|
def set_session_transaction_isolation
|
|
221
234
|
isolation_level = config[:transaction_isolation]
|
|
222
235
|
|
|
@@ -52,6 +52,8 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
|
52
52
|
|
|
53
53
|
# @note Assumes SQLServer SQL-JDBC driver on the class-path.
|
|
54
54
|
def sqlserver_connection(config)
|
|
55
|
+
config = config.deep_dup
|
|
56
|
+
|
|
55
57
|
config[:adapter_spec] ||= ::ArJdbc::MSSQL
|
|
56
58
|
config[:adapter_class] = ActiveRecord::ConnectionAdapters::MSSQLAdapter unless config.key?(:adapter_class)
|
|
57
59
|
|
|
@@ -60,12 +62,15 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
|
60
62
|
config[:host] ||= 'localhost'
|
|
61
63
|
config[:driver] ||= 'com.microsoft.sqlserver.jdbc.SQLServerDriver'
|
|
62
64
|
config[:connection_alive_sql] ||= 'SELECT 1'
|
|
65
|
+
config[:lock_timeout] ||= 5000
|
|
63
66
|
|
|
64
67
|
config[:url] ||= begin
|
|
65
68
|
url = "jdbc:sqlserver://#{config[:host]}"
|
|
66
69
|
url << ( config[:port] ? ":#{config[:port]};" : ';' )
|
|
67
70
|
url << "databaseName=#{config[:database]};" if config[:database]
|
|
68
71
|
url << "instanceName=#{config[:instance]};" if config[:instance]
|
|
72
|
+
url << "loginTimeout=#{config[:login_timeout].to_i};" if config[:login_timeout]
|
|
73
|
+
url << "lockTimeout=#{config[:lock_timeout].to_i};"
|
|
69
74
|
app = config[:appname] || config[:application]
|
|
70
75
|
url << "applicationName=#{app};" if app
|
|
71
76
|
isc = config[:integrated_security] # Win only - needs sqljdbc_auth.dll
|
|
@@ -46,7 +46,7 @@ module ActiveRecord
|
|
|
46
46
|
# NOTE: This is ready, all implemented in the java part of adapter,
|
|
47
47
|
# it uses MSSQLColumn, SqlTypeMetadata, etc.
|
|
48
48
|
def columns(table_name)
|
|
49
|
-
@connection.columns(table_name)
|
|
49
|
+
log('JDBC: GETCOLUMNS', 'SCHEMA') { @connection.columns(table_name) }
|
|
50
50
|
rescue => e
|
|
51
51
|
raise translate_exception_class(e, nil)
|
|
52
52
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
ArJdbc::ConnectionMethods.module_eval do
|
|
3
3
|
def mysql_connection(config)
|
|
4
|
+
config = config.deep_dup
|
|
4
5
|
# NOTE: this isn't "really" necessary but Rails (in tests) assumes being able to :
|
|
5
6
|
# ActiveRecord::Base.mysql2_connection ActiveRecord::Base.configurations['arunit'].merge(database: ...)
|
|
6
7
|
config = symbolize_keys_if_necessary(config)
|
|
@@ -10,11 +11,9 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
|
10
11
|
|
|
11
12
|
return jndi_connection(config) if jndi_config?(config)
|
|
12
13
|
|
|
13
|
-
driver = config[:driver]
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
mysql_driver = driver.start_with?('com.mysql.')
|
|
17
|
-
mariadb_driver = ! mysql_driver && driver.start_with?('org.mariadb.')
|
|
14
|
+
driver = config[:driver]
|
|
15
|
+
mysql_driver = driver.nil? || driver.to_s.start_with?('com.mysql.')
|
|
16
|
+
mariadb_driver = ! mysql_driver && driver.to_s.start_with?('org.mariadb.')
|
|
18
17
|
|
|
19
18
|
begin
|
|
20
19
|
require 'jdbc/mysql'
|
|
@@ -22,6 +21,11 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
|
22
21
|
rescue LoadError # assuming driver.jar is on the class-path
|
|
23
22
|
end if mysql_driver
|
|
24
23
|
|
|
24
|
+
if driver.nil?
|
|
25
|
+
config[:driver] ||=
|
|
26
|
+
defined?(::Jdbc::MySQL.driver_name) ? ::Jdbc::MySQL.driver_name : 'com.mysql.jdbc.Driver'
|
|
27
|
+
end
|
|
28
|
+
|
|
25
29
|
config[:username] = 'root' unless config.key?(:username)
|
|
26
30
|
# jdbc:mysql://[host][,failoverhost...][:port]/[database]
|
|
27
31
|
# - if the host name is not specified, it defaults to 127.0.0.1
|
|
@@ -36,7 +40,8 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
|
36
40
|
|
|
37
41
|
properties = ( config[:properties] ||= {} )
|
|
38
42
|
if mysql_driver
|
|
39
|
-
properties['zeroDateTimeBehavior'] ||=
|
|
43
|
+
properties['zeroDateTimeBehavior'] ||=
|
|
44
|
+
config[:driver].to_s.start_with?('com.mysql.cj.') ? 'CONVERT_TO_NULL' : 'convertToNull'
|
|
40
45
|
properties['jdbcCompliantTruncation'] ||= false
|
|
41
46
|
# NOTE: this is "better" than passing what users are used to set on MRI
|
|
42
47
|
# e.g. 'utf8mb4' will fail cause the driver will check for a Java charset
|
|
@@ -108,7 +113,8 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
|
108
113
|
rescue LoadError # assuming driver.jar is on the class-path
|
|
109
114
|
end
|
|
110
115
|
|
|
111
|
-
config[:driver] ||=
|
|
116
|
+
config[:driver] ||=
|
|
117
|
+
defined?(::Jdbc::MariaDB.driver_name) ? ::Jdbc::MariaDB.driver_name : 'org.mariadb.jdbc.Driver'
|
|
112
118
|
|
|
113
119
|
mysql_connection(config)
|
|
114
120
|
end
|
|
@@ -15,7 +15,7 @@ module ArJdbc
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
# Extracts the value from a PostgreSQL column default definition.
|
|
18
|
-
def extract_value_from_default(default)
|
|
18
|
+
def extract_value_from_default(default)
|
|
19
19
|
case default
|
|
20
20
|
# Quoted types
|
|
21
21
|
when /\A[\(B]?'(.*)'.*::"?([\w. ]+)"?(?:\[\])?\z/m
|
|
@@ -41,10 +41,13 @@ module ArJdbc
|
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
def extract_default_function(default_value, default)
|
|
45
|
-
default if
|
|
44
|
+
def extract_default_function(default_value, default)
|
|
45
|
+
default if has_default_function?(default_value, default)
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
+
def has_default_function?(default_value, default)
|
|
49
|
+
!default_value && %r{\w+\(.*\)|\(.*\)::\w+|CURRENT_DATE|CURRENT_TIMESTAMP} === default
|
|
50
|
+
end
|
|
48
51
|
end
|
|
49
52
|
|
|
50
53
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
ArJdbc::ConnectionMethods.module_eval do
|
|
3
3
|
def postgresql_connection(config)
|
|
4
|
+
config = config.deep_dup
|
|
4
5
|
# NOTE: this isn't "really" necessary but Rails (in tests) assumes being able to :
|
|
5
6
|
# ActiveRecord::Base.postgresql_connection ActiveRecord::Base.configurations['arunit'].merge(:insert_returning => false)
|
|
6
7
|
# ... while using symbols by default but than configurations returning string keys ;(
|
|
@@ -16,7 +17,8 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
|
16
17
|
::Jdbc::Postgres.load_driver(:require) if defined?(::Jdbc::Postgres.load_driver)
|
|
17
18
|
rescue LoadError # assuming driver.jar is on the class-path
|
|
18
19
|
end
|
|
19
|
-
driver = config[:driver] ||=
|
|
20
|
+
driver = (config[:driver] ||=
|
|
21
|
+
defined?(::Jdbc::Postgres.driver_name) ? ::Jdbc::Postgres.driver_name : 'org.postgresql.Driver')
|
|
20
22
|
|
|
21
23
|
host = config[:host] ||= ( config[:hostaddr] || ENV['PGHOST'] || 'localhost' )
|
|
22
24
|
port = config[:port] ||= ( ENV['PGPORT'] || 5432 )
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
ArJdbc::ConnectionMethods.module_eval do
|
|
3
3
|
def sqlite3_connection(config)
|
|
4
|
+
config = config.deep_dup
|
|
4
5
|
config[:adapter_spec] ||= ::ArJdbc::SQLite3
|
|
5
6
|
config[:adapter_class] = ActiveRecord::ConnectionAdapters::SQLite3Adapter unless config.key?(:adapter_class)
|
|
6
7
|
|
data/lib/arjdbc/version.rb
CHANGED
data/rakelib/01-tomcat.rake
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
namespace :'tomcat-jndi' do # contains a FS JNDI impl (for tests)
|
|
2
2
|
|
|
3
|
-
TOMCAT_MAVEN_REPO = '
|
|
3
|
+
TOMCAT_MAVEN_REPO = 'https://repo1.maven.org/maven2/org/apache/tomcat'
|
|
4
4
|
TOMCAT_VERSION = '7.0.54'
|
|
5
5
|
|
|
6
6
|
DOWNLOAD_DIR = File.expand_path('../test/jars', File.dirname(__FILE__))
|
|
@@ -48,4 +48,4 @@ namespace :'tomcat-jndi' do # contains a FS JNDI impl (for tests)
|
|
|
48
48
|
rm jar_path if File.exist?(jar_path)
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
-
end
|
|
51
|
+
end
|
data/rakelib/02-test.rake
CHANGED
|
@@ -76,8 +76,6 @@ end
|
|
|
76
76
|
test_task_for adapter, :desc => "Run tests against #{adapter} (ensure driver is on class-path)"
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
-
#test_task_for :MSSQL, :name => 'test_sqlserver', :driver => nil, :database_name => 'MS-SQL using SQLJDBC'
|
|
80
|
-
|
|
81
79
|
test_task_for :AS400, :desc => "Run tests against AS400 (DB2) (ensure driver is on class-path)",
|
|
82
80
|
:files => FileList["test/db2*_test.rb"] + FileList["test/db/db2/*_test.rb"]
|
|
83
81
|
|
data/rakelib/rails.rake
CHANGED
|
@@ -57,7 +57,7 @@ namespace :rails do
|
|
|
57
57
|
ruby_opts_string += " -C \"#{ar_path}\""
|
|
58
58
|
ruby_opts_string += " -rbundler/setup"
|
|
59
59
|
ruby_opts_string += " -rminitest -rminitest/excludes" unless ENV['NO_EXCLUDES'].eql?('true')
|
|
60
|
-
file_list = ENV["TEST"] ? FileList[ ENV["TEST"] ] : test_files_finder.call
|
|
60
|
+
file_list = ENV["TEST"] ? FileList[ ENV["TEST"].split(',') ] : test_files_finder.call
|
|
61
61
|
file_list_string = file_list.map { |fn| "\"#{fn}\"" }.join(' ')
|
|
62
62
|
# test_loader_code = "-e \"ARGV.each{|f| require f}\"" # :direct
|
|
63
63
|
option_list = ( ENV["TESTOPTS"] || ENV["TESTOPT"] || ENV["TEST_OPTS"] || '' )
|
|
@@ -487,7 +487,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
487
487
|
savepoint = ((IRubyObject) savepoint).toJava(Savepoint.class);
|
|
488
488
|
}
|
|
489
489
|
|
|
490
|
-
|
|
490
|
+
releaseSavepoint(connection, (Savepoint) savepoint);
|
|
491
491
|
return context.nil;
|
|
492
492
|
}
|
|
493
493
|
catch (SQLException e) {
|
|
@@ -495,6 +495,11 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
495
495
|
}
|
|
496
496
|
}
|
|
497
497
|
|
|
498
|
+
// MSSQL doesn't support releasing savepoints so we make it possible to override the actual release action
|
|
499
|
+
protected void releaseSavepoint(final Connection connection, final Savepoint savepoint) throws SQLException {
|
|
500
|
+
connection.releaseSavepoint(savepoint);
|
|
501
|
+
}
|
|
502
|
+
|
|
498
503
|
protected static RuntimeException newSavepointNotSetError(final ThreadContext context, final IRubyObject name, final String op) {
|
|
499
504
|
RubyClass StatementInvalid = ActiveRecord(context).getClass("StatementInvalid");
|
|
500
505
|
return context.runtime.newRaiseException(StatementInvalid, "could not " + op + " savepoint: '" + name + "' (not set)");
|
|
@@ -722,7 +727,10 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
722
727
|
|
|
723
728
|
private void connectImpl(final boolean forceConnection) throws SQLException {
|
|
724
729
|
setConnection( forceConnection ? newConnection() : null );
|
|
725
|
-
if (
|
|
730
|
+
if (forceConnection) {
|
|
731
|
+
if (getConnectionImpl() == null) throw new SQLException("Didn't get a connection. Wrong URL?");
|
|
732
|
+
configureConnection();
|
|
733
|
+
}
|
|
726
734
|
}
|
|
727
735
|
|
|
728
736
|
@JRubyMethod(name = "read_only?")
|
|
@@ -880,15 +888,31 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
880
888
|
return mapQueryResult(context, connection, resultSet);
|
|
881
889
|
}
|
|
882
890
|
|
|
891
|
+
private static String[] createStatementPk(IRubyObject pk) {
|
|
892
|
+
String[] statementPk;
|
|
893
|
+
if (pk instanceof RubyArray) {
|
|
894
|
+
RubyArray ary = (RubyArray) pk;
|
|
895
|
+
int size = ary.size();
|
|
896
|
+
statementPk = new String[size];
|
|
897
|
+
for (int i = 0; i < size; i++) {
|
|
898
|
+
statementPk[i] = sqlString(ary.eltInternal(i));
|
|
899
|
+
}
|
|
900
|
+
} else {
|
|
901
|
+
statementPk = new String[] { sqlString(pk) };
|
|
902
|
+
}
|
|
903
|
+
return statementPk;
|
|
904
|
+
}
|
|
905
|
+
|
|
883
906
|
/**
|
|
884
907
|
* Executes an INSERT SQL statement
|
|
885
908
|
* @param context
|
|
886
909
|
* @param sql
|
|
910
|
+
* @param pk Rails PK
|
|
887
911
|
* @return ActiveRecord::Result
|
|
888
912
|
* @throws SQLException
|
|
889
913
|
*/
|
|
890
|
-
@JRubyMethod(name = "
|
|
891
|
-
public IRubyObject
|
|
914
|
+
@JRubyMethod(name = "execute_insert_pk", required = 2)
|
|
915
|
+
public IRubyObject execute_insert_pk(final ThreadContext context, final IRubyObject sql, final IRubyObject pk) {
|
|
892
916
|
return withConnection(context, new Callable<IRubyObject>() {
|
|
893
917
|
public IRubyObject call(final Connection connection) throws SQLException {
|
|
894
918
|
Statement statement = null;
|
|
@@ -896,7 +920,13 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
896
920
|
try {
|
|
897
921
|
|
|
898
922
|
statement = createStatement(context, connection);
|
|
899
|
-
|
|
923
|
+
|
|
924
|
+
if (pk == context.nil || pk == context.fals || !supportsGeneratedKeys(connection)) {
|
|
925
|
+
statement.executeUpdate(query, Statement.RETURN_GENERATED_KEYS);
|
|
926
|
+
} else {
|
|
927
|
+
statement.executeUpdate(query, createStatementPk(pk));
|
|
928
|
+
}
|
|
929
|
+
|
|
900
930
|
return mapGeneratedKeys(context, connection, statement);
|
|
901
931
|
|
|
902
932
|
} catch (final SQLException e) {
|
|
@@ -909,23 +939,35 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
909
939
|
});
|
|
910
940
|
}
|
|
911
941
|
|
|
942
|
+
@Deprecated
|
|
943
|
+
@JRubyMethod(name = "execute_insert", required = 1)
|
|
944
|
+
public IRubyObject execute_insert(final ThreadContext context, final IRubyObject sql) {
|
|
945
|
+
return execute_insert_pk(context, sql, context.nil);
|
|
946
|
+
}
|
|
947
|
+
|
|
912
948
|
/**
|
|
913
949
|
* Executes an INSERT SQL statement using a prepared statement
|
|
914
950
|
* @param context
|
|
915
951
|
* @param sql
|
|
916
952
|
* @param binds RubyArray of values to be bound to the query
|
|
953
|
+
* @param pk Rails PK
|
|
917
954
|
* @return ActiveRecord::Result
|
|
918
955
|
* @throws SQLException
|
|
919
956
|
*/
|
|
920
|
-
@JRubyMethod(name = "
|
|
921
|
-
public IRubyObject
|
|
957
|
+
@JRubyMethod(name = "execute_insert_pk", required = 3)
|
|
958
|
+
public IRubyObject execute_insert_pk(final ThreadContext context, final IRubyObject sql, final IRubyObject binds,
|
|
959
|
+
final IRubyObject pk) {
|
|
922
960
|
return withConnection(context, new Callable<IRubyObject>() {
|
|
923
961
|
public IRubyObject call(final Connection connection) throws SQLException {
|
|
924
962
|
PreparedStatement statement = null;
|
|
925
963
|
final String query = sqlString(sql);
|
|
926
964
|
try {
|
|
965
|
+
if (pk == context.nil || pk == context.fals || !supportsGeneratedKeys(connection)) {
|
|
966
|
+
statement = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
|
|
967
|
+
} else {
|
|
968
|
+
statement = connection.prepareStatement(query, createStatementPk(pk));
|
|
969
|
+
}
|
|
927
970
|
|
|
928
|
-
statement = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
|
|
929
971
|
setStatementParameters(context, connection, statement, (RubyArray) binds);
|
|
930
972
|
statement.executeUpdate();
|
|
931
973
|
return mapGeneratedKeys(context, connection, statement);
|
|
@@ -940,6 +982,12 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
940
982
|
});
|
|
941
983
|
}
|
|
942
984
|
|
|
985
|
+
@Deprecated
|
|
986
|
+
@JRubyMethod(name = "execute_insert", required = 2)
|
|
987
|
+
public IRubyObject execute_insert(final ThreadContext context, final IRubyObject binds, final IRubyObject sql) {
|
|
988
|
+
return execute_insert_pk(context, sql, binds, context.nil);
|
|
989
|
+
}
|
|
990
|
+
|
|
943
991
|
/**
|
|
944
992
|
* Executes an UPDATE (DELETE) SQL statement
|
|
945
993
|
* @param context
|
|
@@ -3928,6 +3976,12 @@ public class RubyJdbcConnection extends RubyObject {
|
|
|
3928
3976
|
}
|
|
3929
3977
|
}
|
|
3930
3978
|
|
|
3979
|
+
public static void debugMessage(final ThreadContext context, final IRubyObject obj) {
|
|
3980
|
+
if ( isDebug(context.runtime) ) {
|
|
3981
|
+
debugMessage(context.runtime, obj.callMethod(context, "inspect"));
|
|
3982
|
+
}
|
|
3983
|
+
}
|
|
3984
|
+
|
|
3931
3985
|
public static void debugMessage(final Ruby runtime, final String msg, final Object e) {
|
|
3932
3986
|
if ( isDebug(runtime) ) {
|
|
3933
3987
|
final PrintStream out = runtime != null ? runtime.getOut() : System.out;
|
|
@@ -29,22 +29,33 @@ import arjdbc.jdbc.Callable;
|
|
|
29
29
|
import arjdbc.jdbc.RubyJdbcConnection;
|
|
30
30
|
import arjdbc.util.DateTimeUtils;
|
|
31
31
|
|
|
32
|
+
import java.lang.reflect.InvocationTargetException;
|
|
33
|
+
import java.lang.reflect.Method;
|
|
32
34
|
import java.sql.Connection;
|
|
33
35
|
import java.sql.DatabaseMetaData;
|
|
36
|
+
import java.sql.Date;
|
|
34
37
|
import java.sql.PreparedStatement;
|
|
35
38
|
import java.sql.ResultSet;
|
|
36
39
|
import java.sql.Savepoint;
|
|
40
|
+
import java.sql.Statement;
|
|
37
41
|
import java.sql.SQLException;
|
|
38
|
-
import java.sql.Types;
|
|
39
42
|
import java.sql.Timestamp;
|
|
43
|
+
import java.sql.Types;
|
|
40
44
|
import java.util.Locale;
|
|
45
|
+
import java.util.ArrayList;
|
|
46
|
+
import java.util.HashMap;
|
|
47
|
+
import java.util.List;
|
|
48
|
+
import java.util.Map;
|
|
41
49
|
|
|
50
|
+
import org.joda.time.DateTime;
|
|
51
|
+
import org.joda.time.DateTimeZone;
|
|
42
52
|
import org.jruby.Ruby;
|
|
43
53
|
import org.jruby.RubyArray;
|
|
44
54
|
import org.jruby.RubyBoolean;
|
|
45
55
|
import org.jruby.RubyClass;
|
|
46
56
|
import org.jruby.RubyString;
|
|
47
57
|
import org.jruby.RubySymbol;
|
|
58
|
+
import org.jruby.RubyTime;
|
|
48
59
|
import org.jruby.anno.JRubyMethod;
|
|
49
60
|
import org.jruby.runtime.ObjectAllocator;
|
|
50
61
|
import org.jruby.runtime.ThreadContext;
|
|
@@ -58,6 +69,54 @@ import org.jruby.util.ByteList;
|
|
|
58
69
|
public class MSSQLRubyJdbcConnection extends RubyJdbcConnection {
|
|
59
70
|
private static final long serialVersionUID = -745716565005219263L;
|
|
60
71
|
|
|
72
|
+
private static final int DATETIMEOFFSET_TYPE;
|
|
73
|
+
private static final Method DateTimeOffsetGetMinutesOffsetMethod;
|
|
74
|
+
private static final Method DateTimeOffsetGetTimestampMethod;
|
|
75
|
+
private static final Method DateTimeOffsetValueOfMethod;
|
|
76
|
+
private static final Method PreparedStatementSetDateTimeOffsetMethod;
|
|
77
|
+
|
|
78
|
+
private static final Map<String, Integer> MSSQL_JDBC_TYPE_FOR = new HashMap<String, Integer>(32, 1);
|
|
79
|
+
static {
|
|
80
|
+
|
|
81
|
+
Class<?> DateTimeOffset;
|
|
82
|
+
Class<?> MssqlPreparedStatement;
|
|
83
|
+
Class<?> MssqlTypes;
|
|
84
|
+
try {
|
|
85
|
+
DateTimeOffset = Class.forName("microsoft.sql.DateTimeOffset");
|
|
86
|
+
MssqlPreparedStatement = Class.forName("com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement");
|
|
87
|
+
MssqlTypes = Class.forName("microsoft.sql.Types");
|
|
88
|
+
} catch (ClassNotFoundException e) {
|
|
89
|
+
System.err.println("You must require the Microsoft JDBC driver to use this gem"); // The exception doesn't bubble when ruby is initializing
|
|
90
|
+
throw new RuntimeException("You must require the Microsoft JDBC driver to use this gem");
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
DATETIMEOFFSET_TYPE = MssqlTypes.getField("DATETIMEOFFSET").getInt(null);
|
|
95
|
+
DateTimeOffsetGetMinutesOffsetMethod = DateTimeOffset.getDeclaredMethod("getMinutesOffset");
|
|
96
|
+
DateTimeOffsetGetTimestampMethod = DateTimeOffset.getDeclaredMethod("getTimestamp");
|
|
97
|
+
|
|
98
|
+
Class<?>[] valueOfArgTypes = { Timestamp.class, int.class };
|
|
99
|
+
DateTimeOffsetValueOfMethod = DateTimeOffset.getDeclaredMethod("valueOf", valueOfArgTypes);
|
|
100
|
+
|
|
101
|
+
Class<?>[] setOffsetArgTypes = { int.class, DateTimeOffset };
|
|
102
|
+
PreparedStatementSetDateTimeOffsetMethod = MssqlPreparedStatement.getDeclaredMethod("setDateTimeOffset", setOffsetArgTypes);
|
|
103
|
+
} catch (Exception e) {
|
|
104
|
+
System.err.println("You must require the Microsoft JDBC driver to use this gem"); // The exception doesn't bubble when ruby is initializing
|
|
105
|
+
throw new RuntimeException("Please make sure you are using the latest version of the Microsoft JDBC driver");
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
MSSQL_JDBC_TYPE_FOR.put("binary_basic", Types.BINARY);
|
|
109
|
+
MSSQL_JDBC_TYPE_FOR.put("image", Types.BINARY);
|
|
110
|
+
MSSQL_JDBC_TYPE_FOR.put("datetimeoffset", DATETIMEOFFSET_TYPE);
|
|
111
|
+
MSSQL_JDBC_TYPE_FOR.put("money", Types.DECIMAL);
|
|
112
|
+
MSSQL_JDBC_TYPE_FOR.put("smalldatetime", Types.TIMESTAMP);
|
|
113
|
+
MSSQL_JDBC_TYPE_FOR.put("smallmoney", Types.DECIMAL);
|
|
114
|
+
MSSQL_JDBC_TYPE_FOR.put("ss_timestamp", Types.BINARY);
|
|
115
|
+
MSSQL_JDBC_TYPE_FOR.put("text_basic", Types.LONGVARCHAR);
|
|
116
|
+
MSSQL_JDBC_TYPE_FOR.put("uuid", Types.CHAR);
|
|
117
|
+
MSSQL_JDBC_TYPE_FOR.put("varchar_max", Types.VARCHAR);
|
|
118
|
+
}
|
|
119
|
+
|
|
61
120
|
public MSSQLRubyJdbcConnection(Ruby runtime, RubyClass metaClass) {
|
|
62
121
|
super(runtime, metaClass);
|
|
63
122
|
}
|
|
@@ -89,6 +148,176 @@ public class MSSQLRubyJdbcConnection extends RubyJdbcConnection {
|
|
|
89
148
|
return context.runtime.newBoolean( startsWithIgnoreCase(sqlBytes, EXEC) );
|
|
90
149
|
}
|
|
91
150
|
|
|
151
|
+
// Support multiple result sets for mssql
|
|
152
|
+
@Override
|
|
153
|
+
@JRubyMethod(name = "execute", required = 1)
|
|
154
|
+
public IRubyObject execute(final ThreadContext context, final IRubyObject sql) {
|
|
155
|
+
final String query = sqlString(sql);
|
|
156
|
+
return withConnection(context, new Callable<IRubyObject>() {
|
|
157
|
+
public IRubyObject call(final Connection connection) throws SQLException {
|
|
158
|
+
Statement statement = null;
|
|
159
|
+
try {
|
|
160
|
+
statement = createStatement(context, connection);
|
|
161
|
+
|
|
162
|
+
// For DBs that do support multiple statements, lets return the last result set
|
|
163
|
+
// to be consistent with AR
|
|
164
|
+
boolean hasResultSet = doExecute(statement, query);
|
|
165
|
+
int updateCount = statement.getUpdateCount();
|
|
166
|
+
|
|
167
|
+
final List<IRubyObject> results = new ArrayList<IRubyObject>();
|
|
168
|
+
ResultSet resultSet;
|
|
169
|
+
|
|
170
|
+
while (hasResultSet || updateCount != -1) {
|
|
171
|
+
|
|
172
|
+
if (hasResultSet) {
|
|
173
|
+
resultSet = statement.getResultSet();
|
|
174
|
+
|
|
175
|
+
// Unfortunately the result set gets closed when getMoreResults()
|
|
176
|
+
// is called, so we have to process the result sets as we get them
|
|
177
|
+
// this shouldn't be an issue in most cases since we're only getting 1 result set anyways
|
|
178
|
+
results.add(mapExecuteResult(context, connection, resultSet));
|
|
179
|
+
} else {
|
|
180
|
+
results.add(context.runtime.newFixnum(updateCount));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Check to see if there is another result set
|
|
184
|
+
hasResultSet = statement.getMoreResults();
|
|
185
|
+
updateCount = statement.getUpdateCount();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (results.size() == 0) {
|
|
189
|
+
return context.nil; // If no results, return nil
|
|
190
|
+
} else if (results.size() == 1) {
|
|
191
|
+
return results.get(0);
|
|
192
|
+
} else {
|
|
193
|
+
return context.runtime.newArray(results);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
} catch (final SQLException e) {
|
|
197
|
+
debugErrorSQL(context, query);
|
|
198
|
+
throw e;
|
|
199
|
+
} finally {
|
|
200
|
+
close(statement);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Executes an INSERT SQL statement
|
|
208
|
+
* @param context
|
|
209
|
+
* @param sql
|
|
210
|
+
* @param pk Rails PK
|
|
211
|
+
* @return ActiveRecord::Result
|
|
212
|
+
* @throws SQLException
|
|
213
|
+
*/
|
|
214
|
+
@Override
|
|
215
|
+
@JRubyMethod(name = "execute_insert_pk", required = 2)
|
|
216
|
+
public IRubyObject execute_insert_pk(final ThreadContext context, final IRubyObject sql, final IRubyObject pk) {
|
|
217
|
+
|
|
218
|
+
// MSSQL does not like composite primary keys here so chop it if there is more than one column
|
|
219
|
+
IRubyObject modifiedPk = pk;
|
|
220
|
+
|
|
221
|
+
if (pk instanceof RubyArray) {
|
|
222
|
+
RubyArray ary = (RubyArray) pk;
|
|
223
|
+
if (ary.size() > 0) {
|
|
224
|
+
modifiedPk = ary.eltInternal(0);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return super.execute_insert_pk(context, sql, modifiedPk);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Executes an INSERT SQL statement using a prepared statement
|
|
233
|
+
* @param context
|
|
234
|
+
* @param sql
|
|
235
|
+
* @param binds RubyArray of values to be bound to the query
|
|
236
|
+
* @param pk Rails PK
|
|
237
|
+
* @return ActiveRecord::Result
|
|
238
|
+
* @throws SQLException
|
|
239
|
+
*/
|
|
240
|
+
@Override
|
|
241
|
+
@JRubyMethod(name = "execute_insert_pk", required = 3)
|
|
242
|
+
public IRubyObject execute_insert_pk(final ThreadContext context, final IRubyObject sql, final IRubyObject binds,
|
|
243
|
+
final IRubyObject pk) {
|
|
244
|
+
// MSSQL does not like composite primary keys here so chop it if there is more than one column
|
|
245
|
+
IRubyObject modifiedPk = pk;
|
|
246
|
+
|
|
247
|
+
if (pk instanceof RubyArray) {
|
|
248
|
+
RubyArray ary = (RubyArray) pk;
|
|
249
|
+
if (ary.size() > 0) {
|
|
250
|
+
modifiedPk = ary.eltInternal(0);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return super.execute_insert_pk(context, sql, binds, modifiedPk);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
@Override
|
|
258
|
+
protected Integer jdbcTypeFor(final String type) {
|
|
259
|
+
|
|
260
|
+
Integer typeValue = MSSQL_JDBC_TYPE_FOR.get(type);
|
|
261
|
+
|
|
262
|
+
if ( typeValue != null ) {
|
|
263
|
+
return typeValue;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return super.jdbcTypeFor(type);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Datetimeoffset values also make it into here
|
|
270
|
+
@Override
|
|
271
|
+
protected void setStringParameter(final ThreadContext context, final Connection connection,
|
|
272
|
+
final PreparedStatement statement, final int index, final IRubyObject value,
|
|
273
|
+
final IRubyObject attribute, final int type) throws SQLException {
|
|
274
|
+
|
|
275
|
+
// datetimeoffset values also make it in here
|
|
276
|
+
if (type == DATETIMEOFFSET_TYPE) {
|
|
277
|
+
|
|
278
|
+
Object dto = convertToDateTimeOffset(context, value);
|
|
279
|
+
|
|
280
|
+
try {
|
|
281
|
+
|
|
282
|
+
Object[] setStatementArgs = { index, dto };
|
|
283
|
+
PreparedStatementSetDateTimeOffsetMethod.invoke(statement, setStatementArgs);
|
|
284
|
+
|
|
285
|
+
} catch (IllegalAccessException e) {
|
|
286
|
+
debugMessage(context.runtime, e.getMessage());
|
|
287
|
+
throw new RuntimeException("Please make sure you are using the latest version of the Microsoft JDBC driver");
|
|
288
|
+
} catch (InvocationTargetException e) {
|
|
289
|
+
debugMessage(context.runtime, e.getMessage());
|
|
290
|
+
throw new RuntimeException("Please make sure you are using the latest version of the Microsoft JDBC driver");
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
super.setStringParameter(context, connection, statement, index, value, attribute, type);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
private Object convertToDateTimeOffset(final ThreadContext context, final IRubyObject value) {
|
|
299
|
+
|
|
300
|
+
RubyTime time = (RubyTime) value;
|
|
301
|
+
DateTime dt = time.getDateTime();
|
|
302
|
+
Timestamp timestamp = new Timestamp(dt.getMillis());
|
|
303
|
+
timestamp.setNanos(timestamp.getNanos() + (int) time.getNSec());
|
|
304
|
+
int offsetMinutes = dt.getZone().getOffset(dt.getMillis()) / 60000;
|
|
305
|
+
|
|
306
|
+
try {
|
|
307
|
+
|
|
308
|
+
Object[] dtoArgs = { timestamp, offsetMinutes };
|
|
309
|
+
return DateTimeOffsetValueOfMethod.invoke(null, dtoArgs);
|
|
310
|
+
|
|
311
|
+
} catch (IllegalAccessException e) {
|
|
312
|
+
debugMessage(context.runtime, e.getMessage());
|
|
313
|
+
throw new RuntimeException("Please make sure you are using the latest version of the Microsoft JDBC driver");
|
|
314
|
+
} catch (InvocationTargetException e) {
|
|
315
|
+
debugMessage(context.runtime, e.getMessage());
|
|
316
|
+
throw new RuntimeException("Please make sure you are using the latest version of the Microsoft JDBC driver");
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
|
|
92
321
|
@Override
|
|
93
322
|
protected RubyArray mapTables(final ThreadContext context, final Connection connection,
|
|
94
323
|
final String catalog, final String schemaPattern, final String tablePattern,
|
|
@@ -305,29 +534,6 @@ public class MSSQLRubyJdbcConnection extends RubyJdbcConnection {
|
|
|
305
534
|
statement.setObject(index, timeStr, Types.NVARCHAR);
|
|
306
535
|
}
|
|
307
536
|
|
|
308
|
-
// Overrides the method in parent, we only remove the savepoint
|
|
309
|
-
// from the getSavepoints Map
|
|
310
|
-
@JRubyMethod(name = "release_savepoint", required = 1)
|
|
311
|
-
public IRubyObject release_savepoint(final ThreadContext context, final IRubyObject name) {
|
|
312
|
-
if (name == context.nil) throw context.runtime.newArgumentError("nil savepoint name given");
|
|
313
|
-
|
|
314
|
-
final Connection connection = getConnection(true);
|
|
315
|
-
|
|
316
|
-
Object savepoint = getSavepoints(context).remove(name);
|
|
317
|
-
|
|
318
|
-
if (savepoint == null) throw newSavepointNotSetError(context, name, "release");
|
|
319
|
-
|
|
320
|
-
// NOTE: RubyHash.remove does not convert to Java as get does :
|
|
321
|
-
if (!(savepoint instanceof Savepoint)) {
|
|
322
|
-
savepoint = ((IRubyObject) savepoint).toJava(Savepoint.class);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// The 'releaseSavepoint' method is not currently supported
|
|
326
|
-
// by the Microsoft SQL Server JDBC Driver
|
|
327
|
-
// connection.releaseSavepoint((Savepoint) savepoint);
|
|
328
|
-
return context.nil;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
537
|
//----------------------------------------------------------------
|
|
332
538
|
// read_uncommitted: "READ UNCOMMITTED",
|
|
333
539
|
// read_committed: "READ COMMITTED",
|
|
@@ -453,16 +659,64 @@ public class MSSQLRubyJdbcConnection extends RubyJdbcConnection {
|
|
|
453
659
|
|
|
454
660
|
/**
|
|
455
661
|
* Treat LONGVARCHAR as CLOB on MSSQL for purposes of converting a JDBC value to Ruby.
|
|
662
|
+
* Also handle datetimeoffset values here
|
|
456
663
|
*/
|
|
457
664
|
@Override
|
|
458
665
|
protected IRubyObject jdbcToRuby(
|
|
459
666
|
final ThreadContext context, final Ruby runtime,
|
|
460
667
|
final int column, int type, final ResultSet resultSet)
|
|
461
668
|
throws SQLException {
|
|
462
|
-
|
|
669
|
+
|
|
670
|
+
if (type == DATETIMEOFFSET_TYPE) {
|
|
671
|
+
|
|
672
|
+
Object dto = resultSet.getObject(column); // Returns a microsoft.sql.DateTimeOffset
|
|
673
|
+
|
|
674
|
+
if (dto == null) return context.nil;
|
|
675
|
+
|
|
676
|
+
try {
|
|
677
|
+
|
|
678
|
+
int minutes = (int) DateTimeOffsetGetMinutesOffsetMethod.invoke(dto);
|
|
679
|
+
DateTimeZone zone = DateTimeZone.forOffsetHoursMinutes(minutes / 60, minutes % 60);
|
|
680
|
+
Timestamp ts = (Timestamp) DateTimeOffsetGetTimestampMethod.invoke(dto);
|
|
681
|
+
|
|
682
|
+
int nanos = ts.getNanos(); // max 999-999-999
|
|
683
|
+
nanos = nanos % 1000000;
|
|
684
|
+
|
|
685
|
+
// We have to do this differently than the newTime helper because the Timestamp loses its zone information when passed around
|
|
686
|
+
DateTime dateTime = new DateTime(ts.getTime(), zone);
|
|
687
|
+
return RubyTime.newTime(context.runtime, dateTime, nanos);
|
|
688
|
+
|
|
689
|
+
} catch (IllegalAccessException e) {
|
|
690
|
+
debugMessage(runtime, e.getMessage());
|
|
691
|
+
return context.nil;
|
|
692
|
+
} catch (InvocationTargetException e) {
|
|
693
|
+
debugMessage(runtime, e.getMessage());
|
|
694
|
+
return context.nil;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
if (type == Types.LONGVARCHAR || type == Types.LONGNVARCHAR) type = Types.CLOB;
|
|
463
699
|
return super.jdbcToRuby(context, runtime, column, type, resultSet);
|
|
464
700
|
}
|
|
465
701
|
|
|
702
|
+
/**
|
|
703
|
+
* Converts a JDBC date object to a Ruby date by referencing Date#civil
|
|
704
|
+
* @param context current thread context
|
|
705
|
+
* @param resultSet the jdbc result set to pull the value from
|
|
706
|
+
* @param index the index of the column to convert
|
|
707
|
+
* @return RubyNil if NULL or RubyDate if there is a value
|
|
708
|
+
* @throws SQLException if it fails to retrieve the value from the result set
|
|
709
|
+
*/
|
|
710
|
+
@Override
|
|
711
|
+
protected IRubyObject dateToRuby(ThreadContext context, Ruby runtime, ResultSet resultSet, int index) throws SQLException {
|
|
712
|
+
|
|
713
|
+
final Date value = resultSet.getDate(index);
|
|
714
|
+
|
|
715
|
+
if (value == null) return context.nil;
|
|
716
|
+
|
|
717
|
+
return DateTimeUtils.newDate(context, value);
|
|
718
|
+
}
|
|
719
|
+
|
|
466
720
|
@Override
|
|
467
721
|
protected ColumnData[] extractColumns(final ThreadContext context,
|
|
468
722
|
final Connection connection, final ResultSet resultSet,
|
|
@@ -492,19 +746,9 @@ public class MSSQLRubyJdbcConnection extends RubyJdbcConnection {
|
|
|
492
746
|
return columns;
|
|
493
747
|
}
|
|
494
748
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
// "jTDS Type 4 JDBC Driver for MS SQL Server and Sybase"
|
|
499
|
-
// SQLJDBC: "Microsoft JDBC Driver 4.0 for SQL Server"
|
|
500
|
-
return withConnection(context, new Callable<RubyBoolean>() {
|
|
501
|
-
// NOTE: only used in one place for now (on release_savepoint) ...
|
|
502
|
-
// might get optimized to only happen once since driver won't change
|
|
503
|
-
public RubyBoolean call(final Connection connection) throws SQLException {
|
|
504
|
-
final String driver = connection.getMetaData().getDriverName();
|
|
505
|
-
return context.getRuntime().newBoolean( driver.indexOf("jTDS") >= 0 );
|
|
506
|
-
}
|
|
507
|
-
});
|
|
749
|
+
@Override
|
|
750
|
+
protected void releaseSavepoint(final Connection connection, final Savepoint savepoint) throws SQLException {
|
|
751
|
+
// MSSQL doesn't support releasing savepoints
|
|
508
752
|
}
|
|
509
753
|
|
|
510
754
|
}
|
|
@@ -367,8 +367,9 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
|
367
367
|
value = value.callMethod(context, "to_date");
|
|
368
368
|
}
|
|
369
369
|
|
|
370
|
-
// NOTE:
|
|
371
|
-
|
|
370
|
+
// NOTE: Here we rely in ActiveRecord (ActiveSupport) to get
|
|
371
|
+
// the date as a string in the database format.
|
|
372
|
+
statement.setDate(index, Date.valueOf(value.callMethod(context, "to_s", context.runtime.newSymbol("db")).toString()));
|
|
372
373
|
}
|
|
373
374
|
|
|
374
375
|
@Override
|
|
@@ -31,6 +31,7 @@ import java.util.TimeZone;
|
|
|
31
31
|
import org.joda.time.Chronology;
|
|
32
32
|
import org.joda.time.DateTime;
|
|
33
33
|
import org.joda.time.DateTimeZone;
|
|
34
|
+
import org.joda.time.chrono.GJChronology;
|
|
34
35
|
import org.joda.time.chrono.ISOChronology;
|
|
35
36
|
import org.jruby.Ruby;
|
|
36
37
|
import org.jruby.RubyFloat;
|
|
@@ -50,6 +51,9 @@ import static arjdbc.util.StringHelper.decByte;
|
|
|
50
51
|
* @author kares
|
|
51
52
|
*/
|
|
52
53
|
public abstract class DateTimeUtils {
|
|
54
|
+
|
|
55
|
+
private static final GJChronology CHRONO_ITALY_UTC = GJChronology.getInstance(DateTimeZone.UTC);
|
|
56
|
+
|
|
53
57
|
public static RubyTime toTime(final ThreadContext context, final IRubyObject value) {
|
|
54
58
|
if (!(value instanceof RubyTime)) { // unlikely
|
|
55
59
|
return (RubyTime) TypeConverter.convertToTypeWithCheck(value, context.runtime.getTime(), "to_time");
|
|
@@ -217,9 +221,11 @@ public abstract class DateTimeUtils {
|
|
|
217
221
|
final int hours = time.getHours();
|
|
218
222
|
final int minutes = time.getMinutes();
|
|
219
223
|
final int seconds = time.getSeconds();
|
|
220
|
-
|
|
224
|
+
int nanos = time.getNanos(); // max 999-999-999
|
|
225
|
+
final int millis = nanos / 1000000;
|
|
226
|
+
nanos = nanos % 1000000;
|
|
221
227
|
|
|
222
|
-
DateTime dateTime = new DateTime(2000, 1, 1, hours, minutes, seconds, defaultZone);
|
|
228
|
+
DateTime dateTime = new DateTime(2000, 1, 1, hours, minutes, seconds, millis, defaultZone);
|
|
223
229
|
return RubyTime.newTime(context.runtime, dateTime, nanos);
|
|
224
230
|
}
|
|
225
231
|
|
|
@@ -232,9 +238,11 @@ public abstract class DateTimeUtils {
|
|
|
232
238
|
final int hours = timestamp.getHours();
|
|
233
239
|
final int minutes = timestamp.getMinutes();
|
|
234
240
|
final int seconds = timestamp.getSeconds();
|
|
235
|
-
|
|
241
|
+
int nanos = timestamp.getNanos(); // max 999-999-999
|
|
242
|
+
final int millis = nanos / 1000000;
|
|
243
|
+
nanos = nanos % 1000000;
|
|
236
244
|
|
|
237
|
-
DateTime dateTime = new DateTime(year, month, day, hours, minutes, seconds,
|
|
245
|
+
DateTime dateTime = new DateTime(year, month, day, hours, minutes, seconds, millis, defaultZone);
|
|
238
246
|
return RubyTime.newTime(context.runtime, dateTime, nanos);
|
|
239
247
|
}
|
|
240
248
|
|
|
@@ -259,6 +267,15 @@ public abstract class DateTimeUtils {
|
|
|
259
267
|
return newDate(context, year, month, day, ISOChronology.getInstance(zone));
|
|
260
268
|
}
|
|
261
269
|
|
|
270
|
+
@SuppressWarnings("deprecation")
|
|
271
|
+
public static IRubyObject newDate(final ThreadContext context, final Date date) {
|
|
272
|
+
final int year = date.getYear() + 1900;
|
|
273
|
+
final int month = date.getMonth() + 1;
|
|
274
|
+
final int day = date.getDate();
|
|
275
|
+
|
|
276
|
+
return newDate(context, year, month, day, CHRONO_ITALY_UTC);
|
|
277
|
+
}
|
|
278
|
+
|
|
262
279
|
// @Deprecated
|
|
263
280
|
public static Timestamp convertToTimestamp(final RubyFloat value) {
|
|
264
281
|
final Timestamp timestamp = new Timestamp(value.getLongValue() * 1000); // millis
|
|
@@ -553,7 +570,7 @@ public abstract class DateTimeUtils {
|
|
|
553
570
|
}
|
|
554
571
|
|
|
555
572
|
private static IRubyObject newDate(final ThreadContext context, final int year, final int month, final int day,
|
|
556
|
-
final
|
|
573
|
+
final Chronology chronology) {
|
|
557
574
|
// NOTE: JRuby really needs a native date.rb until than its a bit costly going from ...
|
|
558
575
|
// java.sql.Date -> allocating a DateTime proxy, help a bit by shooting at the internals
|
|
559
576
|
//
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activerecord-jdbc-alt-adapter
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 51.
|
|
4
|
+
version: 51.7.0
|
|
5
5
|
platform: java
|
|
6
6
|
authors:
|
|
7
7
|
- Nick Sieger, Ola Bini, Karol Bucek and JRuby contributors
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-01-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -20,8 +20,8 @@ dependencies:
|
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
21
|
version: 5.1.7
|
|
22
22
|
name: activerecord
|
|
23
|
-
prerelease: false
|
|
24
23
|
type: :runtime
|
|
24
|
+
prerelease: false
|
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
|
26
26
|
requirements:
|
|
27
27
|
- - "~>"
|
|
@@ -30,8 +30,8 @@ dependencies:
|
|
|
30
30
|
- - ">="
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
32
|
version: 5.1.7
|
|
33
|
-
description: 'Fork of the ActiveRecord JDBC adapter with support for SQL Server
|
|
34
|
-
SQL, for more information and help look at the README file in the github repository.
|
|
33
|
+
description: 'Fork of the ActiveRecord JDBC adapter with support for SQL Server and
|
|
34
|
+
Azure SQL, for more information and help look at the README file in the github repository.
|
|
35
35
|
AR-JDBC is a database adapter for Rails'' ActiveRecord component designed to be
|
|
36
36
|
used with JRuby built upon Java''s JDBC API for database access. Provides (ActiveRecord)
|
|
37
37
|
built-in adapters: MySQL, PostgreSQL and SQLite3 as well as adapters for popular
|
|
@@ -76,6 +76,7 @@ files:
|
|
|
76
76
|
- lib/active_record/connection_adapters/sqlite3_adapter.rb
|
|
77
77
|
- lib/active_record/connection_adapters/sqlserver_adapter.rb
|
|
78
78
|
- lib/activerecord-jdbc-adapter.rb
|
|
79
|
+
- lib/activerecord-jdbc-alt-adapter.rb
|
|
79
80
|
- lib/arel/visitors/compat.rb
|
|
80
81
|
- lib/arel/visitors/db2.rb
|
|
81
82
|
- lib/arel/visitors/derby.rb
|
|
@@ -269,8 +270,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
269
270
|
- !ruby/object:Gem::Version
|
|
270
271
|
version: '0'
|
|
271
272
|
requirements: []
|
|
272
|
-
|
|
273
|
-
rubygems_version: 2.7.6
|
|
273
|
+
rubygems_version: 3.0.6
|
|
274
274
|
signing_key:
|
|
275
275
|
specification_version: 4
|
|
276
276
|
summary: ActiveRecord JDBC adapter, for use within JRuby on Rails and SQL Server
|