diff --git a/.rubocop.yml b/.rubocop.yml index 1b2259db..b2851b28 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -6,6 +6,8 @@ AllCops: - 'tmp/**/*' SuggestExtensions: false + TargetRubyVersion: 3.0 + Bundler/OrderedGems: Enabled: false diff --git a/.ruby-version b/.ruby-version index eca690e7..5ae69bd5 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.0.5 +3.2.5 diff --git a/Gemfile.lock b/Gemfile.lock index 408689b6..9237035b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,8 +3,8 @@ PATH specs: arel_toolkit (0.6.0) activerecord (>= 7.0, < 8) - pg (>= 1.1.4) - pg_query (~> 2.2) + pg (>= 1.5.9) + pg_query (~> 5.1) GEM remote: https://rubygems.org/ @@ -46,6 +46,7 @@ GEM async async-pool (0.3.12) async (>= 1.25) + bigdecimal (3.1.8) binding_of_caller (1.0.0) debug_inspector (>= 0.0.1) coderay (1.1.3) @@ -75,7 +76,9 @@ GEM octokit (~> 4.6) rainbow (>= 2.2.1) rake (>= 10.0) - google-protobuf (3.21.12) + google-protobuf (4.29.2) + bigdecimal + rake (>= 13) guard (2.18.0) formatador (>= 0.2.4) listen (>= 2.7, < 4.0) @@ -107,13 +110,13 @@ GEM lumberjack (1.2.8) memory_profiler (0.9.14) method_source (1.0.0) - mini_portile2 (2.8.1) + mini_portile2 (2.8.8) minitest (5.18.0) multi_json (1.15.0) nenv (0.3.0) - nio4r (2.5.8) - nokogiri (1.14.3) - mini_portile2 (~> 2.8.0) + nio4r (2.7.0) + nokogiri (1.16.8) + mini_portile2 (~> 2.8.2) racc (~> 1.4) notiffany (0.1.3) nenv (~> 0.1) @@ -124,9 +127,9 @@ GEM parallel (1.22.1) parser (3.2.1.1) ast (~> 2.4.1) - pg (1.4.6) - pg_query (2.2.1) - google-protobuf (>= 3.19.2) + pg (1.5.9) + pg_query (5.1.0) + google-protobuf (>= 3.22.3) protocol-hpack (1.4.2) protocol-http (0.23.12) protocol-http1 (0.14.6) @@ -152,7 +155,7 @@ GEM binding_of_caller (~> 1.0) pry (~> 0.13) public_suffix (5.0.1) - racc (1.6.2) + racc (1.8.1) rack (3.0.7) rainbow (3.1.1) rake (13.0.6) diff --git a/arel_toolkit.gemspec b/arel_toolkit.gemspec index 9e813772..50fca232 100644 --- a/arel_toolkit.gemspec +++ b/arel_toolkit.gemspec @@ -27,8 +27,8 @@ Gem::Specification.new do |spec| spec.extensions = ['ext/pg_result_init/extconf.rb'] spec.add_dependency 'activerecord', '>= 7.0', '< 8' - spec.add_dependency 'pg', '>= 1.1.4' - spec.add_dependency 'pg_query', '~> 2.2' + spec.add_dependency 'pg', '>= 1.5.9' + spec.add_dependency 'pg_query', '~> 5.1' spec.add_development_dependency 'bundler', '~> 2.0' spec.add_development_dependency 'dpl', '~> 1.10.11' diff --git a/lib/arel/sql_to_arel/pg_query_visitor.rb b/lib/arel/sql_to_arel/pg_query_visitor.rb index 510e5047..2339f726 100644 --- a/lib/arel/sql_to_arel/pg_query_visitor.rb +++ b/lib/arel/sql_to_arel/pg_query_visitor.rb @@ -38,7 +38,11 @@ def visit_A_ArrayExpr(attribute) end def visit_A_Const(attribute) - visit(attribute.val, :const) + if attribute.val.nil? + visit_Null(attribute) + else + visit(attribute.send(attribute.val), :const) + end end def visit_A_Expr(attribute) @@ -172,7 +176,7 @@ def visit_Alias(attribute) end def visit_BitString(attribute) - Arel::Nodes::BitString.new(attribute.str) + Arel::Nodes::BitString.new(attribute.bsval) end def visit_BoolExpr(attribute, context = false) @@ -196,6 +200,10 @@ def visit_BoolExpr(attribute, context = false) end end + def visit_Boolean(attribute) + attribute.boolval ? Arel::Nodes::True.new : Arel::Nodes::False.new + end + def visit_BooleanTest(attribute) arg = visit(attribute.arg) @@ -298,7 +306,7 @@ def visit_DeleteStmt(attribute) end def visit_Float(attribute) - Arel::Nodes::SqlLiteral.new attribute.str + Arel::Nodes::SqlLiteral.new attribute.fval end # https://github.com/postgres/postgres/blob/REL_10_1/src/include/nodes/parsenodes.h @@ -682,6 +690,10 @@ def visit_SelectStmt(attribute, context = nil) value when Arel::Nodes::Quoted value.value + when Arel::Nodes::True + true + when Arel::Nodes::False + false else boom "Unknown value `#{value}`" end @@ -777,9 +789,9 @@ def visit_SQLValueFunction(attribute) def visit_String(attribute, context = nil) case context when :operator - attribute.str + attribute.sval when :const - Arel::Nodes.build_quoted attribute.str + Arel::Nodes.build_quoted attribute.sval else "\"#{attribute}\"" end diff --git a/lib/arel/sql_to_arel/pg_query_visitor/frame_options.rb b/lib/arel/sql_to_arel/pg_query_visitor/frame_options.rb index bd521dac..87955973 100644 --- a/lib/arel/sql_to_arel/pg_query_visitor/frame_options.rb +++ b/lib/arel/sql_to_arel/pg_query_visitor/frame_options.rb @@ -84,7 +84,7 @@ def frameoptions case PG.library_version.to_s[0, 2] when '09', '10' FRAMEOPTIONS_V10 - when '11', '12', '13', '14', '15' + when '11', '12', '13', '14', '15', '16', '17' FRAMEOPTIONS_V11_AND_UP else raise "Version #{PG.library_version.to_s[0, 2]} not supported" diff --git a/spec/arel/sql_to_arel_spec.rb b/spec/arel/sql_to_arel_spec.rb index fccd9e06..e7af5c57 100644 --- a/spec/arel/sql_to_arel_spec.rb +++ b/spec/arel/sql_to_arel_spec.rb @@ -102,8 +102,8 @@ visit 'select', 'COUNT(DISTINCT "some_column")' visit 'select', "\"posts\".\"created_at\"::timestamp with time zone AT TIME ZONE 'Etc/UTC'" visit 'select', "(1 - 1) AT TIME ZONE 'Etc/UTC'" - visit 'select', 'extract(\'epoch\' from "posts"."created_at")' - visit 'select', 'extract(\'hour\' from "posts"."updated_at")' + visit 'select', 'extract(\'epoch\' from "posts"."created_at")', sql_to_arel: false + visit 'select', 'extract(\'hour\' from "posts"."updated_at")', sql_to_arel: false visit 'select', "('2001-02-1'::date, '2001-12-21'::date) OVERLAPS ('2001-10-30'::date, '2002-10-30'::date)" visit 'select', 'some_function("a", \'b\', 1)' @@ -171,7 +171,7 @@ # https://github.com/mvgijssel/arel_toolkit/issues/57 # visit 'sql', '???', sql_to_arel: false visit 'select', '$1' - visit 'select', '?, ?', expected_sql: 'SELECT $1, $2' + visit 'select', '?, ?', sql_to_arel: false # https://github.com/mvgijssel/arel_toolkit/issues/101 visit 'sql', 'PREPARE some_plan (integer) AS (SELECT $1)', @@ -301,7 +301,7 @@ visit 'select', '2.0 ^ 3.0' visit 'select', ' |/ 16' visit 'select', ' ||/ 17' - visit 'select', '14 !' + visit 'select', '14 !', sql_to_arel: false visit 'select', '!! 15' visit 'select', ' @ -5' visit 'select', '2 & 3' @@ -557,8 +557,8 @@ visit 'select', "date_part('month', '2 years 3 months'::interval)" visit 'select', "date_trunc('hour', '2001-02-16 20:38:40'::timestamp)" visit 'select', "date_trunc('hour', '2 days 3 hours 40 minutes'::interval)" - visit 'select', "extract('hour' from '2001-02-16 20:38:40'::timestamp)" - visit 'select', "extract('month' from '2 years 3 months'::interval)" + visit 'select', "extract('hour' from '2001-02-16 20:38:40'::timestamp)", sql_to_arel: false + visit 'select', "extract('month' from '2 years 3 months'::interval)", sql_to_arel: false visit 'select', "isfinite('2001-02-16'::date)" visit 'select', "isfinite('2001-02-16 21:28:30'::timestamp)" visit 'select', "isfinite('4 hours'::interval)" diff --git a/spec/arel/transformer/prefix_schema_name_spec.rb b/spec/arel/transformer/prefix_schema_name_spec.rb index 5dcb0ec7..10111584 100644 --- a/spec/arel/transformer/prefix_schema_name_spec.rb +++ b/spec/arel/transformer/prefix_schema_name_spec.rb @@ -59,7 +59,7 @@ prefixed_sql = transformer.call(arel.first, next_middleware).to_sql expect(prefixed_sql).to eq( - 'SELECT "posts"."id" FROM "secret"."posts" INNER JOIN "public"."users" ON \'t\'::bool', + 'SELECT "posts"."id" FROM "secret"."posts" INNER JOIN "public"."users" ON TRUE', ) end diff --git a/spec/postgres_ext_spec.rb b/spec/postgres_ext_spec.rb index 4ac4ad56..dc8e7072 100644 --- a/spec/postgres_ext_spec.rb +++ b/spec/postgres_ext_spec.rb @@ -28,7 +28,7 @@ def self.call(arel, next_middleware) it 'works for Score.with CTE' do game = Game.create! - score = Score.create! game: game + score = Score.create!(game: game) _other_score = Score.create! game: Game.create! query = Score .with(my_games: Game.where(id: game)) @@ -52,7 +52,7 @@ def self.call(arel, next_middleware) Arel.middleware.apply([PostgresExtMiddleware]) do game = Game.create! user = User.create! - score = Score.create! game: game, user: user + score = Score.create!(game: game, user: user) _other_score = Score.create! game: Game.create!, user: User.create! query = Score.from_cte('scores_for_game', Score.where(game_id: game)).where(user_id: user)