Skip to content

Commit b2c501f

Browse files
committed
Merge branch 'main' into pk_autopopulated_trigger
2 parents a228501 + 20d1c84 commit b2c501f

File tree

11 files changed

+97
-56
lines changed

11 files changed

+97
-56
lines changed

.devcontainer/Dockerfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ FROM mcr.microsoft.com/devcontainers/ruby:${VARIANT}
66

77
# TinyTDS
88
RUN apt-get -y install libc6-dev \
9-
&& wget http://www.freetds.org/files/stable/freetds-1.1.32.tar.gz \
10-
&& tar -xzf freetds-1.1.32.tar.gz \
11-
&& cd freetds-1.1.32 \
9+
&& wget http://www.freetds.org/files/stable/freetds-1.4.14.tar.gz \
10+
&& tar -xzf freetds-1.4.14.tar.gz \
11+
&& cd freetds-1.4.14 \
1212
&& ./configure --prefix=/usr/local --with-tdsver=7.3 \
1313
&& make \
1414
&& make install

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ jobs:
1414
fail-fast: false
1515
matrix:
1616
ruby:
17-
- 3.1.4
18-
- 3.2.2
19-
- 3.3.0
17+
- 3.1.6
18+
- 3.2.4
19+
- 3.3.2
2020

2121
steps:
2222
- name: Checkout code

Dockerfile.ci

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ WORKDIR $WORKDIR
99

1010
COPY . $WORKDIR
1111

12-
RUN RAILS_BRANCH=7-2-stable bundle install --jobs `expr $(cat /proc/cpuinfo | grep -c "cpu cores") - 1` --retry 3
12+
RUN bundle install --jobs `expr $(cat /proc/cpuinfo | grep -c "cpu cores") - 1` --retry 3
1313

1414
CMD ["sh"]

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ gemspec
88

99
gem "bcrypt"
1010
gem "pg", ">= 0.18.0"
11-
gem "sqlite3", "~> 1.4"
11+
gem "sqlite3", ">= 1.6.6"
1212
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby]
1313
gem "benchmark-ips"
1414
gem "minitest", ">= 5.15.0"

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
7.2.0.alpha
1+
7.2.0.beta2

activerecord-sqlserver-adapter.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ Gem::Specification.new do |spec|
2727
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
2828
spec.require_paths = ["lib"]
2929

30-
spec.add_dependency "activerecord", "~> 7.2.0.alpha"
30+
spec.add_dependency "activerecord", "~> 7.2.0.beta2"
3131
spec.add_dependency "tiny_tds"
3232
end

docker-compose.ci.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ services:
55
ci:
66
environment:
77
- ACTIVERECORD_UNITTEST_HOST=sqlserver
8-
- RAILS_BRANCH=7-2-stable
98
build:
109
context: .
1110
dockerfile: Dockerfile.ci

lib/active_record/tasks/sqlserver_database_tasks.rb

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ module Tasks
1010
class SQLServerDatabaseTasks
1111
DEFAULT_COLLATION = "SQL_Latin1_General_CP1_CI_AS"
1212

13-
delegate :lease_connection, :establish_connection, to: ActiveRecord::Base
13+
delegate :with_connection, :establish_connection, to: ActiveRecord::Base
1414

1515
def self.using_database_configurations?
1616
true
@@ -23,8 +23,10 @@ def initialize(configuration)
2323

2424
def create(master_established = false)
2525
establish_master_connection unless master_established
26-
lease_connection.create_database configuration.database, configuration_hash.merge(collation: default_collation)
27-
establish_connection configuration
26+
with_connection do |connection|
27+
connection.create_database(configuration.database, configuration_hash.merge(collation: default_collation))
28+
end
29+
establish_connection(configuration)
2830
rescue ActiveRecord::StatementInvalid => e
2931
if /database .* already exists/i === e.message
3032
raise DatabaseAlreadyExists
@@ -35,15 +37,15 @@ def create(master_established = false)
3537

3638
def drop
3739
establish_master_connection
38-
lease_connection.drop_database configuration.database
40+
with_connection { |connection| connection.drop_database(configuration.database) }
3941
end
4042

4143
def charset
42-
lease_connection.charset
44+
with_connection { |connection| connection.charset }
4345
end
4446

4547
def collation
46-
lease_connection.collation
48+
with_connection { |connection| connection.collation }
4749
end
4850

4951
def purge
@@ -56,34 +58,38 @@ def clear_active_connections!
5658
ActiveRecord::Base.connection_handler.clear_active_connections!(:all)
5759
end
5860

59-
def structure_dump(filename, extra_flags)
60-
server_arg = "-S #{Shellwords.escape(configuration_hash[:host])}"
61-
server_arg += ":#{Shellwords.escape(configuration_hash[:port])}" if configuration_hash[:port]
62-
command = [
63-
"defncopy-ttds",
64-
server_arg,
65-
"-D #{Shellwords.escape(configuration_hash[:database])}",
66-
"-U #{Shellwords.escape(configuration_hash[:username])}",
67-
"-P #{Shellwords.escape(configuration_hash[:password])}",
68-
"-o #{Shellwords.escape(filename)}",
69-
]
70-
table_args = lease_connection.tables.map { |t| Shellwords.escape(t) }
71-
command.concat(table_args)
72-
view_args = lease_connection.views.map { |v| Shellwords.escape(v) }
73-
command.concat(view_args)
74-
raise "Error dumping database" unless Kernel.system(command.join(" "))
75-
76-
dump = File.read(filename)
77-
dump.gsub!(/^USE .*$\nGO\n/, "") # Strip db USE statements
78-
dump.gsub!(/^GO\n/, "") # Strip db GO statements
79-
dump.gsub!(/nvarchar\(8000\)/, "nvarchar(4000)") # Fix nvarchar(8000) column defs
80-
dump.gsub!(/nvarchar\(-1\)/, "nvarchar(max)") # Fix nvarchar(-1) column defs
81-
dump.gsub!(/text\(\d+\)/, "text") # Fix text(16) column defs
82-
File.open(filename, "w") { |file| file.puts dump }
61+
def structure_dump(filename, _extra_flags)
62+
with_connection do |connection|
63+
server_arg = "-S #{Shellwords.escape(configuration_hash[:host])}"
64+
server_arg += ":#{Shellwords.escape(configuration_hash[:port])}" if configuration_hash[:port]
65+
command = [
66+
"defncopy-ttds",
67+
server_arg,
68+
"-D #{Shellwords.escape(configuration_hash[:database])}",
69+
"-U #{Shellwords.escape(configuration_hash[:username])}",
70+
"-P #{Shellwords.escape(configuration_hash[:password])}",
71+
"-o #{Shellwords.escape(filename)}",
72+
]
73+
table_args = connection.tables.map { |t| Shellwords.escape(t) }
74+
command.concat(table_args)
75+
view_args = connection.views.map { |v| Shellwords.escape(v) }
76+
command.concat(view_args)
77+
raise "Error dumping database" unless Kernel.system(command.join(" "))
78+
79+
dump = File.read(filename)
80+
dump.gsub!(/^USE .*$\nGO\n/, "") # Strip db USE statements
81+
dump.gsub!(/^GO\n/, "") # Strip db GO statements
82+
dump.gsub!(/nvarchar\(8000\)/, "nvarchar(4000)") # Fix nvarchar(8000) column defs
83+
dump.gsub!(/nvarchar\(-1\)/, "nvarchar(max)") # Fix nvarchar(-1) column defs
84+
dump.gsub!(/text\(\d+\)/, "text") # Fix text(16) column defs
85+
File.open(filename, "w") { |file| file.puts dump }
86+
end
8387
end
8488

85-
def structure_load(filename, extra_flags)
86-
lease_connection.execute File.read(filename)
89+
def structure_load(filename, _extra_flags)
90+
with_connection do |connection|
91+
connection.execute File.read(filename)
92+
end
8793
end
8894

8995
private

lib/arel/visitors/sqlserver.rb

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,12 @@ def visit_Arel_Table(o, collector)
129129
# github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues/450
130130
table_name =
131131
begin
132-
if o.class.engine.lease_connection.respond_to?(:sqlserver?) && o.class.engine.lease_connection.database_prefix_remote_server?
133-
remote_server_table_name(o)
134-
else
135-
quote_table_name(o.name)
132+
o.class.engine.with_connection do |connection|
133+
if connection.respond_to?(:sqlserver?) && connection.database_prefix_remote_server?
134+
remote_server_table_name(o)
135+
else
136+
quote_table_name(o.name)
137+
end
136138
end
137139
rescue Exception
138140
quote_table_name(o.name)
@@ -201,6 +203,11 @@ def collect_optimizer_hints(o, collector)
201203
collector
202204
end
203205

206+
def visit_Arel_Nodes_WithRecursive(o, collector)
207+
collector << "WITH "
208+
collect_ctes(o.children, collector)
209+
end
210+
204211
# SQLServer ToSql/Visitor (Additions)
205212

206213
def visit_Arel_Nodes_SelectStatement_SQLServer_Lock(collector, options = {})
@@ -315,14 +322,16 @@ def primary_Key_From_Table(t)
315322
end
316323

317324
def remote_server_table_name(o)
318-
ActiveRecord::ConnectionAdapters::SQLServer::Utils.extract_identifiers(
319-
"#{o.class.engine.lease_connection.database_prefix}#{o.name}"
320-
).quoted
325+
o.class.engine.with_connection do |connection|
326+
ActiveRecord::ConnectionAdapters::SQLServer::Utils.extract_identifiers(
327+
"#{connection.database_prefix}#{o.name}"
328+
).quoted
329+
end
321330
end
322331

323-
# Need to remove ordering from subqueries unless TOP/OFFSET also used. Otherwise, SQLServer
332+
# Need to remove ordering from sub-queries unless TOP/OFFSET also used. Otherwise, SQLServer
324333
# returns error "The ORDER BY clause is invalid in views, inline functions, derived tables,
325-
# subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified."
334+
# sub-queries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified."
326335
def remove_invalid_ordering_from_select_statement(node)
327336
return unless Arel::Nodes::SelectStatement === node
328337

test/cases/coerced_tests.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2735,3 +2735,26 @@ def test_assert_queries_match_coerced
27352735
end
27362736
end
27372737
end
2738+
2739+
module ActiveRecord
2740+
class WithTest < ActiveRecord::TestCase
2741+
# SQL contains just 'WITH' instead of 'WITH RECURSIVE' as expected by the original test.
2742+
coerce_tests! :test_with_recursive
2743+
def test_with_recursive_coerced
2744+
top_companies = Company.where(firm_id: nil).to_a
2745+
child_companies = Company.where(firm_id: top_companies).to_a
2746+
top_companies_and_children = (top_companies.map(&:id) + child_companies.map(&:id)).sort
2747+
2748+
relation = Company.with_recursive(
2749+
top_companies_and_children: [
2750+
Company.where(firm_id: nil),
2751+
Company.joins("JOIN top_companies_and_children ON companies.firm_id = top_companies_and_children.id"),
2752+
]
2753+
).from("top_companies_and_children AS companies")
2754+
2755+
assert_equal top_companies_and_children, relation.order(:id).pluck(:id)
2756+
assert_match "WITH ", relation.to_sql
2757+
end
2758+
end
2759+
end
2760+

test/cases/rake_test_sqlserver.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,18 +138,22 @@ class SQLServerRakeStructureDumpLoadTest < SQLServerRakeTest
138138

139139
it "dumps structure and accounts for defncopy oddities" do
140140
skip "debug defncopy on windows later" if host_windows?
141+
141142
quietly { db_tasks.structure_dump configuration, filename }
143+
142144
_(filedata).wont_match %r{\AUSE.*\z}
143145
_(filedata).wont_match %r{\AGO.*\z}
144-
_(filedata).must_match %r{email\s+nvarchar\(4000\)}
145-
_(filedata).must_match %r{background1\s+nvarchar\(max\)}
146-
_(filedata).must_match %r{background2\s+text\s+}
146+
_(filedata).must_match %r{\[email\]\s+nvarchar\(4000\)}
147+
_(filedata).must_match %r{\[background1\]\s+nvarchar\(max\)}
148+
_(filedata).must_match %r{\[background2\]\s+text\s+}
147149
end
148150

149151
it "can load dumped structure" do
150152
skip "debug defncopy on windows later" if host_windows?
153+
151154
quietly { db_tasks.structure_dump configuration, filename }
152-
_(filedata).must_match %r{CREATE TABLE dbo\.users}
155+
156+
_(filedata).must_match %r{CREATE TABLE \[dbo\]\.\[users\]}
153157
db_tasks.purge(configuration)
154158
_(connection.tables).wont_include "users"
155159
db_tasks.load_schema db_config, :sql, filename

0 commit comments

Comments
 (0)