Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for SQL Server on Rails 5.x, 6.0, 6.1, and 7.0 #1007

Open
wants to merge 163 commits into
base: 50-stable
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
163 commits
Select commit Hold shift + click to select a range
5798a00
commet out some undefined methods/constants
JesseChavez Jan 21, 2019
7162719
remane mssql adapter.rb file to old_adapter.rb
JesseChavez Jan 21, 2019
e9a6070
add basic MSSQL adapter
JesseChavez Jan 21, 2019
997b51e
Implement some required methods
JesseChavez Jan 21, 2019
0f033a1
Add new sqlserver arel visitor, code taken from the sqlserver adapter
JesseChavez Jan 21, 2019
45a6dfe
change bind param markerto be a question mark, jdbc style
JesseChavez Jan 21, 2019
3fc66d9
Fix order of offset and limit (sqlserver specific)
JesseChavez Jan 21, 2019
34886ee
add clear_cache! reload type map then clear statements cache
JesseChavez Jan 21, 2019
eb258e7
Reuse the existing MSSQL type definitions.
JesseChavez Jan 22, 2019
ce7c53b
Add initial quoting methods
JesseChavez Jan 22, 2019
b697895
enable support migrations, create/drop database, and native database …
JesseChavez Jan 24, 2019
eb07126
Add quoting for table and column names
JesseChavez Jan 26, 2019
ddf4a5b
handle migrations that specify a limit on integer columns
Jan 31, 2019
127dee2
Merge pull request #1 from chrisrobbie/50-stable-dev
JesseChavez Jan 31, 2019
0dd3ecb
handle calls to execute stored procedures
Jan 31, 2019
6d9a4e0
Add valid_type? and indexes methods
JesseChavez Jan 31, 2019
c89b9a6
remove sqlserver_2000? method call.
JesseChavez Jan 31, 2019
2fb95c7
handle identity on/off for inserts passed to execute
Jan 31, 2019
5f8fce6
Merge pull request #2 from chrisrobbie/50-stable-dev
JesseChavez Feb 1, 2019
3fe253b
CR: handle constraints with mssql during remove_column migration
Feb 3, 2019
241c5a4
CR: remove mssql2000 check from test ignore-system-views
Feb 3, 2019
2a756ed
Make sqlserver default adapter when running tests
JesseChavez Feb 4, 2019
5e6646b
remove sqlserver_2000? from rake tasks tests
JesseChavez Feb 4, 2019
7b655aa
Merge pull request #3 from chrisrobbie/50-stable-dev
JesseChavez Feb 4, 2019
ae57b9e
remove doubled up indexes method
JesseChavez Feb 5, 2019
9eb5f87
Fix some rake tasks tests, create/drop db, charset, collation
JesseChavez Feb 5, 2019
f4369df
rejig mssql multibyte test to use mssql conn rather than jdbc
Feb 5, 2019
623485b
rejig mssql multiple connections test to pass
Feb 5, 2019
f0ce25d
fix test when non-existing database
JesseChavez Feb 7, 2019
7391205
copy minimal methods from old mssql adapter for rake_test to pass
Feb 7, 2019
31e7ed4
Merge branch '50-stable-dev' into 50-stable-dev
JesseChavez Feb 8, 2019
37d8be2
Merge pull request #4 from chrisrobbie/50-stable-dev
JesseChavez Feb 8, 2019
da22032
remove unused methods and register tasks as sqlserver
JesseChavez Feb 8, 2019
c8ab3f9
clean up multibyte tests
JesseChavez Feb 8, 2019
5d2e7e6
add rename table and rename table indexes accordingly
JesseChavez Feb 10, 2019
a013616
include existing explain support to mssql adapter
JesseChavez Feb 11, 2019
6623c7f
add quote_string method
JesseChavez Feb 14, 2019
a06f5e1
move mssql column class definition in a single file
JesseChavez Feb 17, 2019
4496519
change from compact to nested modules
JesseChavez Feb 17, 2019
a977fb1
Fix some rubocop offences and add comments
JesseChavez Feb 17, 2019
656b7cd
Add mssql column class initialize and extract_default methods
JesseChavez Feb 17, 2019
2291367
Implement of the truncate method.
JesseChavez Feb 17, 2019
05e6da7
Add SQL Server specific methods, current_user and default_schema
JesseChavez Feb 17, 2019
6447bf1
Add implementation of change_column
JesseChavez Feb 17, 2019
e172e31
Fix spec when retrieving columns of non-existent table
JesseChavez Feb 17, 2019
b0fb60d
Fix ambiguous column name 'name' in test (test still fails)
JesseChavez Feb 19, 2019
e72da58
Split time type test in 3 tests to better track fractional seconds ti…
JesseChavez Feb 19, 2019
0e6f444
Add some notes related to the MS jdbc driver
JesseChavez Feb 19, 2019
feee5be
Override timeToRuby and setTimeParameter java methods for the mssql a…
JesseChavez Feb 20, 2019
6d492b2
Move get_table_name away from utils to fix specs
JesseChavez Feb 20, 2019
d3dd2e1
Fix savepoints and transactions
JesseChavez Feb 21, 2019
82d4b9f
Fix test, select distinct with joins and limit
JesseChavez Feb 22, 2019
07396c7
Fix indexes test, the java parts was not return all columns associated
JesseChavez Feb 22, 2019
235b445
add .jrubyrc to .gitignore
JesseChavez Feb 23, 2019
e88adbc
refomat initialize_type_map method
JesseChavez Feb 25, 2019
aa215f9
Fix some issues in integer type columns
JesseChavez Feb 25, 2019
835cdfd
Fix sql_type metadata for boolean type (bit in SQL Server)
JesseChavez Feb 26, 2019
3858109
Add some smoke tests for exact numerics
JesseChavez Feb 26, 2019
46838b2
Remove precision and scale from money and smallmoney sql types
JesseChavez Feb 26, 2019
2b33bef
Add some smoke test for approximate numeric types
JesseChavez Feb 26, 2019
40f9371
move numeric types to a separate file
JesseChavez Feb 26, 2019
66d6572
rearrange and fix native database types hash
JesseChavez Feb 27, 2019
e13a75a
Add some smoke test for string column types
JesseChavez Feb 27, 2019
356469c
Add some smoke tests for binary columns
JesseChavez Feb 27, 2019
bba584a
Add some smoke tests for xml and uuid columns
JesseChavez Feb 27, 2019
4108cf2
Add some smoke test for deprecated columns types
JesseChavez Feb 28, 2019
d912545
Add some initial smoke tests for date and time column types
JesseChavez Feb 28, 2019
00d7c01
Add remaining smoke tests for date and time column types
JesseChavez Mar 3, 2019
e68a3c3
Review, fix, and improve integers type mapping
JesseChavez Mar 3, 2019
3307b9f
Improve decimal type mapping and add aliases test
JesseChavez Mar 3, 2019
2446902
Improve mapping of float , real, boolean, uuid, and xml
JesseChavez Mar 3, 2019
876b02c
add some binary type aliases and tests
JesseChavez Mar 3, 2019
0069a2b
Restore the identity part of integer sql_types when is primary key
JesseChavez Mar 3, 2019
78660a1
Clean up old type definitions
JesseChavez Mar 3, 2019
207f7f1
Add some test cases for fixture inserts
JesseChavez Mar 4, 2019
7a5d7bb
Fix insert fixture issues when inserting time and binary types
JesseChavez Mar 9, 2019
5705c11
Set support transaction isolation to false to run activerecord tests …
JesseChavez Mar 9, 2019
4cf9e8a
Fix set identity insert on/off
JesseChavez Mar 9, 2019
fed50d4
Fix identity insert when insert is run with exec_insert
JesseChavez Mar 9, 2019
c54c522
Add settings to run activerecord test using the mssql adapter
JesseChavez Mar 11, 2019
d61a826
Fix change column default (migrations)
JesseChavez Mar 12, 2019
9b98c5f
Fix and add some smoke tests for rename column.
JesseChavez Mar 12, 2019
770206d
Fix issues when update identity columns
JesseChavez Mar 12, 2019
7fa1fef
Add columns_for_distinct implementation
JesseChavez Mar 13, 2019
dd615c4
Fixes index out of range issue
JesseChavez Mar 13, 2019
05d0962
fix warning due missing brackets
JesseChavez Mar 20, 2019
b3f44a0
Implement change_column_null
JesseChavez Mar 20, 2019
231759d
Rename migration test file
JesseChavez Mar 21, 2019
e8cfc65
Fix migration method add_column without limit
JesseChavez Mar 21, 2019
1413dd6
Fix migration method change_column_default with from and to
JesseChavez Mar 21, 2019
e62b3fd
Add some support_* flags relevant to the mssql adapter
JesseChavez Mar 21, 2019
9d6d9b7
Fix exception when trying to rename a not existing column
JesseChavez Mar 22, 2019
ab20154
Fix uniqueness violation translated to specific exception
JesseChavez Mar 22, 2019
5879922
add test to keep track of behaviour when removing column that is part…
JesseChavez Mar 23, 2019
901503a
Keep the default behaviour of begin_isolated_db_transaction method un…
JesseChavez Mar 23, 2019
7292cf0
Fix test according active record specs
JesseChavez Mar 24, 2019
2d5f0cc
Fix unquote issue of default values
JesseChavez Mar 24, 2019
f672ce9
Fix case sensitive uniqueness validation
JesseChavez Mar 24, 2019
0e54abe
Fix Decimal type issues according active record default behaviour
JesseChavez Mar 24, 2019
10901f3
Fix (Allow) updates on custom primary keys, column must not be identity
JesseChavez Mar 24, 2019
2737d63
Fix default value may contain newline characters
JesseChavez Mar 25, 2019
fc24c04
Use integer 1 and 0 as quoted boolean values
JesseChavez Mar 25, 2019
df3ce4e
Fix default time precision as per active record behaviour, mssql defa…
JesseChavez Mar 30, 2019
1b05fe8
Add deprecation warnings as per active record specs
JesseChavez Mar 31, 2019
0f8719d
Remove support of equality comparison for deprecated data types
JesseChavez Apr 4, 2019
608cf14
Remove support of equality comparison and special treatment for depre…
JesseChavez Apr 4, 2019
ec95650
Add smalldatetime to native database types
JesseChavez Apr 5, 2019
e4a5176
Add more serialize tests, as array field and json coder
JesseChavez Apr 7, 2019
e6f11be
Add exception class to handle lock timeouts and enable transaction is…
JesseChavez Apr 9, 2019
c2cea49
Add some transaction isolation tests
JesseChavez Apr 10, 2019
f5743fd
Fix MSSQL transactions and fix/add more tests
JesseChavez Apr 10, 2019
912d223
Clean up, delete empty lines, commented code, and unused code
JesseChavez Apr 11, 2019
00eb9b4
Fix datetime rounding issues (used some code of the old_adapter)
JesseChavez Apr 11, 2019
a40b023
Fix rounding issues in datetime data type due a bug in the mssql-jdbc…
JesseChavez Apr 12, 2019
436f07f
Enable foreign ket constraints support
JesseChavez Apr 13, 2019
6406665
Rework on exceptions test file to add more exeption tests
JesseChavez Apr 13, 2019
9424e91
Add some exceptions translations and tests
JesseChavez Apr 13, 2019
c578d73
Change the way disable_referential_integrity is implemented
JesseChavez Apr 13, 2019
87ad897
Add some test to fix issues with foreign keys
JesseChavez Apr 13, 2019
bf1fc9a
Fix foreign keys, it is requred to have newer versions of the mssql j…
JesseChavez Apr 14, 2019
dfe38b6
Fix create table from select
JesseChavez Apr 14, 2019
0017edd
Fix explain (execution plan)
JesseChavez Apr 15, 2019
d548d93
Fix warnings and run pending test, work on time presicion fixed the test
JesseChavez Apr 15, 2019
f701351
Add some relevant notes
JesseChavez Apr 16, 2019
8e3dd77
Check supported and unsupported mssql versions
JesseChavez Apr 23, 2019
d0939b9
Add support for mssql transaction isolation level snapshot
JesseChavez Apr 23, 2019
33bfec5
Split date and time tests in to separated files
JesseChavez Apr 27, 2019
22bc52a
fix datetime and smalldatetime in schema dump
JesseChavez Apr 27, 2019
583dc4e
Fix time data type in schema dump and rounding issues
JesseChavez Apr 28, 2019
af904b1
Add table definition for smalldatetime type
JesseChavez Apr 28, 2019
4e8d194
Add support for create table with force: cascade
JesseChavez Apr 29, 2019
0aff8eb
Add datetime2 support and use it as the timestamps fields
JesseChavez Apr 30, 2019
e59c367
Fix yaml dump and load for activerecord objects
JesseChavez Apr 30, 2019
edf8162
Fix time type default format in schema dump as per activerecord tests
JesseChavez May 1, 2019
b98fe57
Merge pull request #6 from jruby/50-stable
JesseChavez May 1, 2019
3cce984
Merge branch '50-stable' into 50-stable-dev
JesseChavez May 1, 2019
e46a76a
Fix timestamps precision when loading fixtures
JesseChavez May 1, 2019
485e320
Add datetime_basic to schema definition
JesseChavez May 1, 2019
2aa3f16
Add other mssql specific schema definitions
JesseChavez May 1, 2019
c83ee61
use jdbc-mssql 0.6.0 for running tests
JesseChavez May 2, 2019
147bf29
Ignore tags and .jrubyrc files
JesseChavez May 2, 2019
cbab9b8
Fix time zone offset for datetime_basic data type
JesseChavez May 7, 2019
2a7610e
[backport from 52-release] Ensure date has the format 'yyyy-[m]m-[d]d…
JesseChavez Jun 29, 2019
79b5b02
Merge remote-tracking branch 'upstream/50-stable' into 50-stable
JesseChavez Aug 6, 2019
1fbb85a
[backport from 51-release]Ensure date has the format 'yyyy-[m]m-[d]d'…
JesseChavez Aug 6, 2019
f5a2a19
[backport from 52-release] Add missing flags
JesseChavez Sep 30, 2019
cecb4b2
Merge remote-tracking branch 'upstream/50-stable' into 50-stable
JesseChavez Nov 16, 2019
f4ed1e2
Merge branch '50-stable' into 50-stable-dev
JesseChavez Nov 16, 2019
f0040d7
restore files deleted on merge
JesseChavez Nov 23, 2019
9c4149e
remove conflicting java methods
JesseChavez Nov 23, 2019
cff6ab9
restore task to run tests
JesseChavez Nov 23, 2019
b492e01
move lock_timeout to url connection string (it's not really required …
JesseChavez Nov 23, 2019
cc82c65
fix jdbc type mapping of deprecated data type image
JesseChavez Nov 24, 2019
de0609e
implement connection reset! method
JesseChavez Dec 19, 2019
c23b621
use columns from schema cache to detect identity column in inserts
JesseChavez Dec 19, 2019
baddd1b
remove line I forgot to remove
JesseChavez Dec 19, 2019
9f90425
Merge remote-tracking branch 'upstream/50-stable' into 50-stable
JesseChavez Dec 20, 2019
17605bd
Merge branch '50-stable' into 50-stable-dev
JesseChavez Dec 20, 2019
15c2a22
deep dup config as per changes in postgres and mysql adapters
JesseChavez Dec 21, 2019
c11cb87
fix recurring bub 'The connection is closed', error seen in Rails 5.2…
JesseChavez Dec 22, 2019
afd3e3a
Merge remote-tracking branch 'upstream/50-stable' into 50-stable
JesseChavez Jan 16, 2021
fdd3840
Merge branch '50-stable' into 50-stable-dev
JesseChavez Jan 16, 2021
871159a
add some files to gitignore
JesseChavez Jan 17, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,7 @@ Gemfile.lock
.settings
activerecord-jdbc.iml
lib/arjdbc/jdbc/adapter_java.jar
.jrubyrc
tags
.ruby-version
pik.sh
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ group :test do

gem 'bcrypt', '~> 3.1.11', require: false
gem 'builder', require: false
gem 'jdbc-mssql', '~> 0.7.0', require: nil
end

group :rails do
Expand Down
1 change: 1 addition & 0 deletions lib/active_record/connection_adapters/mssql_adapter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require 'arjdbc/mssql'
1 change: 1 addition & 0 deletions lib/active_record/connection_adapters/sqlserver_adapter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require 'arjdbc/mssql'
3 changes: 2 additions & 1 deletion lib/arel/visitors/sql_server/ng42.rb
Original file line number Diff line number Diff line change
Expand Up @@ -290,4 +290,5 @@ def _yield_str(str); @block ? @block.call(str) : str end
end
end

Arel::Visitors::VISITORS['mssql'] = Arel::Visitors::VISITORS['sqlserver'] = Arel::Visitors::SQLServerNG
# FIXME: Arel::Visitors::VISITORS is not defined anymore
# Arel::Visitors::VISITORS['mssql'] = Arel::Visitors::VISITORS['sqlserver'] = Arel::Visitors::SQLServerNG
214 changes: 214 additions & 0 deletions lib/arel/visitors/sqlserver.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
# NOTE: this code was take from the **sqlserver** adapter and adapted to work
# with this adapter.
#
module Arel
module Visitors
class SQLServer < Arel::Visitors::ToSql

OFFSET = " OFFSET "
ROWS = " ROWS"
FETCH = " FETCH NEXT "
FETCH0 = " FETCH FIRST (SELECT 0) "
ROWS_ONLY = " ROWS ONLY"


private

# SQLServer ToSql/Visitor (Overides)

def visit_Arel_Nodes_BindParam o, collector
# collector.add_bind(o) { |i| "@#{i-1}" }
collector.add_bind(o) { |i| '?' }
end

def visit_Arel_Nodes_Bin o, collector
visit o.expr, collector
collector << " #{ActiveRecord::ConnectionAdapters::MSSQLAdapter.cs_equality_operator} "
end

def visit_Arel_Nodes_UpdateStatement(o, a)
if o.orders.any? && o.limit.nil?
o.limit = Nodes::Limit.new(9_223_372_036_854_775_807)
end
super
end

def visit_Arel_Nodes_Lock o, collector
o.expr = Arel.sql('WITH(UPDLOCK)') if o.expr.to_s =~ /FOR UPDATE/
collector << SPACE
visit o.expr, collector
end

def visit_Arel_Nodes_Offset o, collector
collector << OFFSET
visit o.expr, collector
collector << ROWS
end

def visit_Arel_Nodes_Limit o, collector
if node_value(o) == 0
collector << FETCH0
collector << ROWS_ONLY
else
collector << FETCH
visit o.expr, collector
collector << ROWS_ONLY
end
end

def visit_Arel_Nodes_SelectStatement o, collector
@select_statement = o
distinct_One_As_One_Is_So_Not_Fetch o
if o.with
collector = visit o.with, collector
collector << SPACE
end
collector = o.cores.inject(collector) { |c,x|
visit_Arel_Nodes_SelectCore(x, c)
}
collector = visit_Orders_And_Let_Fetch_Happen o, collector
collector = visit_Make_Fetch_Happen o, collector
collector
ensure
@select_statement = nil
end

def visit_Arel_Table o, collector
# Apparently, o.engine.connection can actually be a different adapter
# than sqlserver. Can be removed if fixed in ActiveRecord. See:
# github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues/450
table_name = begin
if o.class.engine.connection.respond_to?(:sqlserver?) && o.class.engine.connection.database_prefix_remote_server?
remote_server_table_name(o)
else
quote_table_name(o.name)
end
rescue Exception => e
quote_table_name(o.name)
end
if o.table_alias
collector << "#{table_name} #{quote_table_name o.table_alias}"
else
collector << table_name
end
end

def visit_Arel_Nodes_JoinSource o, collector
if o.left
collector = visit o.left, collector
collector = visit_Arel_Nodes_SelectStatement_SQLServer_Lock collector
end
if o.right.any?
collector << " " if o.left
collector = inject_join o.right, collector, ' '
end
collector
end

def visit_Arel_Nodes_OuterJoin o, collector
collector << "LEFT OUTER JOIN "
collector = visit o.left, collector
collector = visit_Arel_Nodes_SelectStatement_SQLServer_Lock collector, space: true
collector << " "
visit o.right, collector
end

# SQLServer ToSql/Visitor (Additions)

def visit_Arel_Nodes_SelectStatement_SQLServer_Lock collector, options = {}
if select_statement_lock?
collector = visit @select_statement.lock, collector
collector << SPACE if options[:space]
end
collector
end

def visit_Orders_And_Let_Fetch_Happen o, collector
make_Fetch_Possible_And_Deterministic o
unless o.orders.empty?
collector << SPACE
collector << ORDER_BY
len = o.orders.length - 1
o.orders.each_with_index { |x, i|
collector = visit(x, collector)
collector << COMMA unless len == i
}
end
collector
end

def visit_Make_Fetch_Happen o, collector
o.offset = Nodes::Offset.new(0) if o.limit && !o.offset
collector = visit o.offset, collector if o.offset
collector = visit o.limit, collector if o.limit
collector
end

# SQLServer Helpers

def node_value(node)
return nil unless node
case node.expr
when NilClass then nil
when Numeric then node.expr
when Arel::Nodes::Unary then node.expr.expr
end
end

def select_statement_lock?
@select_statement && @select_statement.lock
end

def make_Fetch_Possible_And_Deterministic o
return if o.limit.nil? && o.offset.nil?
t = table_From_Statement o
pk = primary_Key_From_Table t
return unless pk
if o.orders.empty?
# Prefer deterministic vs a simple `(SELECT NULL)` expr.
o.orders = [pk.asc]
end
end

def distinct_One_As_One_Is_So_Not_Fetch o
core = o.cores.first
distinct = Nodes::Distinct === core.set_quantifier
oneasone = core.projections.all? { |x| x == ActiveRecord::FinderMethods::ONE_AS_ONE }
limitone = [nil, 0, 1].include? node_value(o.limit)
if distinct && oneasone && limitone && !o.offset
# NOTE: part clears the limit part of the query but the bind parameter
# is still hanging around in active record, this issue makes
# the prepared statement to fails with "index i is out of range"
# As a quick fix is just add the bind marker as parameter of TOP
# which always be one.
core.projections = [Arel.sql("TOP(?) 1 AS [one]")]
o.limit = nil
end
end

def table_From_Statement o
core = o.cores.first
if Arel::Table === core.from
core.from
elsif Arel::Nodes::SqlLiteral === core.from
Arel::Table.new(core.from)
elsif Arel::Nodes::JoinSource === core.source
Arel::Nodes::SqlLiteral === core.source.left ? Arel::Table.new(core.source.left, @engine) : core.source.left
end
end

def primary_Key_From_Table t
return unless t
column_name = schema_cache.primary_keys(t.name) || column_cache(t.name).first.try(:second).try(:name)
column_name ? t[column_name] : nil
end

def remote_server_table_name o
ActiveRecord::ConnectionAdapters::SQLServer::Utils.extract_identifiers(
"#{o.class.engine.connection.database_prefix}#{o.name}"
).quoted
end

end
end
end
7 changes: 7 additions & 0 deletions lib/arjdbc/mssql.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'arjdbc'
require 'arjdbc/mssql/adapter'
require 'arjdbc/mssql/connection_methods'
module ArJdbc
MsSQL = MSSQL # compatibility with 1.2
end
ArJdbc.warn_unsupported_adapter 'mssql', [5, 0] # warns on AR >= 4.2
Loading