diff --git a/Gemfile b/Gemfile index 68e53281..b828c5f1 100644 --- a/Gemfile +++ b/Gemfile @@ -3,7 +3,7 @@ source "https://rubygems.org" # Specify your gem's dependencies in activerecord-spanner.gemspec gemspec -gem "activerecord", ENV.fetch("AR_VERSION", "~> 7.1.0") +gem "activerecord", ENV.fetch("AR_VERSION", "~> 8.0.0") gem "ostruct" gem "minitest", "~> 5.25.0" gem "minitest-rg", "~> 5.3.0" @@ -13,7 +13,7 @@ gem "pry-byebug", "~> 3.9.0" gem 'sqlite3', '~> 1.4' # Required for samples and testing. -install_if -> { ENV.fetch("AR_VERSION", "~> 7.1.0").dup.to_s.sub("~>", "").strip < "7.1.0" && !ENV["SKIP_COMPOSITE_PK"] } do +install_if -> { ENV.fetch("AR_VERSION", "~> 8.0.0").dup.to_s.sub("~>", "").strip < "7.1.0" && !ENV["SKIP_COMPOSITE_PK"] } do gem "composite_primary_keys" end diff --git a/activerecord-spanner-adapter.gemspec b/activerecord-spanner-adapter.gemspec index 5f7e40b0..ef129e97 100644 --- a/activerecord-spanner-adapter.gemspec +++ b/activerecord-spanner-adapter.gemspec @@ -22,12 +22,12 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename f } spec.require_paths = ["lib"] - spec.required_ruby_version = ">= 2.7" + spec.required_ruby_version = ">= 3.2" spec.add_dependency "google-cloud-spanner", "~> 2.18" # Pin gRPC to 1.64.3, as 1.65 and 1.66 cause test runs to hang randomly. spec.add_dependency "grpc", "1.64.3" - spec.add_runtime_dependency "activerecord", [">= 6.1", "< 7.3"] + spec.add_runtime_dependency "activerecord", [">= 6.1", "< 9"] spec.add_development_dependency "autotest-suffix", "~> 1.1" spec.add_development_dependency "bundler", "~> 2.0" diff --git a/lib/active_record/connection_adapters/spanner/quoting.rb b/lib/active_record/connection_adapters/spanner/quoting.rb index e4e18123..7e67d8b1 100644 --- a/lib/active_record/connection_adapters/spanner/quoting.rb +++ b/lib/active_record/connection_adapters/spanner/quoting.rb @@ -30,10 +30,24 @@ module ActiveRecord module ConnectionAdapters + QUOTED_COLUMN_NAMES = Concurrent::Map.new # :nodoc: + QUOTED_TABLE_NAMES = Concurrent::Map.new # :nodoc: + + module Quoting + module ClassMethods + # This is used for ActiveRecord v8 and higher. + def quote_column_name name + QUOTED_COLUMN_NAMES[name] ||= "`#{name.to_s.gsub '`', '``'}`".freeze + end + + def quote_table_name name + QUOTED_TABLE_NAMES[name] ||= "`#{name.to_s.gsub '.', '`.`'}`".freeze + end + end + end + module Spanner module Quoting - QUOTED_COLUMN_NAMES = Concurrent::Map.new # :nodoc: - QUOTED_TABLE_NAMES = Concurrent::Map.new # :nodoc: def quote_column_name name QUOTED_COLUMN_NAMES[name] ||= "`#{name.to_s.gsub '`', '``'}`".freeze diff --git a/lib/active_record/connection_adapters/spanner_adapter.rb b/lib/active_record/connection_adapters/spanner_adapter.rb index 2fe571e4..dce5317e 100644 --- a/lib/active_record/connection_adapters/spanner_adapter.rb +++ b/lib/active_record/connection_adapters/spanner_adapter.rb @@ -274,7 +274,9 @@ def type_map end def transform sql - if ActiveRecord::VERSION::MAJOR >= 7 + if ActiveRecord::VERSION::MAJOR >= 8 + preprocess_query sql + elsif ActiveRecord::VERSION::MAJOR == 7 transform_query sql else sql @@ -282,12 +284,23 @@ def transform sql end # Overwrite the standard log method to be able to translate exceptions. - def log sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil, *args - super - rescue ActiveRecord::StatementInvalid - raise - rescue StandardError => e - raise translate_exception_class(e, sql, binds) + # sql, name = "SQL", binds = [], type_casted_binds = [], async: false, &block + if ActiveRecord::VERSION::MAJOR >= 8 + def log(sql, name = "SQL", binds = [], type_casted_binds = [], async: false, &block) + super + rescue ActiveRecord::StatementInvalid + raise + rescue StandardError => e + raise translate_exception_class(e, sql, binds) + end + else + def log sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil, *args + super + rescue ActiveRecord::StatementInvalid + raise + rescue StandardError => e + raise translate_exception_class(e, sql, binds) + end end def translate_exception exception, message:, sql:, binds: diff --git a/test/activerecord_spanner_mock_server/base_spanner_mock_server_test.rb b/test/activerecord_spanner_mock_server/base_spanner_mock_server_test.rb index 31be7138..e4f23b95 100644 --- a/test/activerecord_spanner_mock_server/base_spanner_mock_server_test.rb +++ b/test/activerecord_spanner_mock_server/base_spanner_mock_server_test.rb @@ -22,6 +22,8 @@ module MockServerTests class BaseSpannerMockServerTest < Minitest::Test def setup super + ActiveRecord::ConnectionAdapters.register("spanner", "ActiveRecord::ConnectionAdapters::SpannerAdapter") + @server = GRPC::RpcServer.new @port = @server.add_http2_port "localhost:0", :this_port_is_insecure @mock = SpannerMockServer.new