Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save mattyoho/456cdd5668c30020933b1a55bc991443 to your computer and use it in GitHub Desktop.
Save mattyoho/456cdd5668c30020933b1a55bc991443 to your computer and use it in GitHub Desktop.
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 2955ead3bb..01467628d8 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -348,7 +348,7 @@ def reorder!(*args) # :nodoc:
self
end
- VALID_UNSCOPING_VALUES = Set.new([:where, :select, :group, :order, :lock,
+ VALID_UNSCOPING_VALUES = Set.new([:where, :select, :group, :order, :lock, :optimizer_hints,
:limit, :offset, :joins, :left_outer_joins,
:includes, :from, :readonly, :having, :annotate])
diff --git a/activerecord/lib/arel/nodes.rb b/activerecord/lib/arel/nodes.rb
index 76b51812ed..1e475ac819 100644
--- a/activerecord/lib/arel/nodes.rb
+++ b/activerecord/lib/arel/nodes.rb
@@ -66,6 +66,7 @@
require "arel/nodes/string_join"
require "arel/nodes/annotation"
+require "arel/nodes/optimizer_hints"
require "arel/nodes/sql_literal"
diff --git a/activerecord/lib/arel/nodes/optimizer_hints.rb b/activerecord/lib/arel/nodes/optimizer_hints.rb
new file mode 100644
index 0000000000..d1048ccf74
--- /dev/null
+++ b/activerecord/lib/arel/nodes/optimizer_hints.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+module Arel # :nodoc: all
+ module Nodes
+ class OptimizerHints < Arel::Nodes::Annotation
+ end
+ end
+end
diff --git a/activerecord/lib/arel/nodes/unary.rb b/activerecord/lib/arel/nodes/unary.rb
index 6d1ac36b0e..00639304e4 100644
--- a/activerecord/lib/arel/nodes/unary.rb
+++ b/activerecord/lib/arel/nodes/unary.rb
@@ -35,7 +35,6 @@ def eql?(other)
Not
Offset
On
- OptimizerHints
Ordering
RollUp
}.each do |name|
diff --git a/activerecord/lib/arel/select_manager.rb b/activerecord/lib/arel/select_manager.rb
index 2bd7cf8a97..96b1b46452 100644
--- a/activerecord/lib/arel/select_manager.rb
+++ b/activerecord/lib/arel/select_manager.rb
@@ -148,7 +148,7 @@ def projections=(projections)
def optimizer_hints(*hints)
unless hints.empty?
- @ctx.optimizer_hints = Arel::Nodes::OptimizerHints.new(hints)
+ @ctx.optimizer_hints = Arel::Nodes::OptimizerHints.new(*hints)
end
self
end
diff --git a/activerecord/lib/arel/visitors/depth_first.rb b/activerecord/lib/arel/visitors/depth_first.rb
index bfb5684203..e11f53a24a 100644
--- a/activerecord/lib/arel/visitors/depth_first.rb
+++ b/activerecord/lib/arel/visitors/depth_first.rb
@@ -35,7 +35,6 @@ def unary(o)
alias :visit_Arel_Nodes_Ascending :unary
alias :visit_Arel_Nodes_Descending :unary
alias :visit_Arel_Nodes_UnqualifiedColumn :unary
- alias :visit_Arel_Nodes_OptimizerHints :unary
def function(o)
visit o.expressions
@@ -184,6 +183,7 @@ def visit_Arel_Nodes_UpdateStatement(o)
def visit_Arel_Nodes_Annotation(o)
visit o.values
end
+ alias :visit_Arel_Nodes_OptimizerHints :visit_Arel_Nodes_Annotation
def visit_Array(o)
o.each { |i| visit i }
diff --git a/activerecord/lib/arel/visitors/dot.rb b/activerecord/lib/arel/visitors/dot.rb
index 157150c16c..c59163d4dd 100644
--- a/activerecord/lib/arel/visitors/dot.rb
+++ b/activerecord/lib/arel/visitors/dot.rb
@@ -82,7 +82,6 @@ def unary(o)
alias :visit_Arel_Nodes_Offset :unary
alias :visit_Arel_Nodes_On :unary
alias :visit_Arel_Nodes_UnqualifiedColumn :unary
- alias :visit_Arel_Nodes_OptimizerHints :unary
alias :visit_Arel_Nodes_Preceding :unary
alias :visit_Arel_Nodes_Following :unary
alias :visit_Arel_Nodes_Rows :unary
@@ -237,6 +236,7 @@ def visit_Array(o)
def visit_Arel_Nodes_Annotation(o)
visit_edge(o, "values")
end
+ alias :visit_Arel_Nodes_OptimizerHints :visit_Arel_Nodes_Annotation
def visit_edge(o, method)
edge(method) { visit o.send(method) }
diff --git a/activerecord/lib/arel/visitors/ibm_db.rb b/activerecord/lib/arel/visitors/ibm_db.rb
index 0ffc0725f7..4ca6f27af9 100644
--- a/activerecord/lib/arel/visitors/ibm_db.rb
+++ b/activerecord/lib/arel/visitors/ibm_db.rb
@@ -10,7 +10,7 @@ def visit_Arel_Nodes_SelectCore(o, collector)
end
def visit_Arel_Nodes_OptimizerHints(o, collector)
- collector << "/* <OPTGUIDELINES>#{sanitize_as_sql_comment(o).join}</OPTGUIDELINES> */"
+ collector << "/* <OPTGUIDELINES>#{o.values.join}</OPTGUIDELINES> */"
end
def visit_Arel_Nodes_Limit(o, collector)
diff --git a/activerecord/lib/arel/visitors/informix.rb b/activerecord/lib/arel/visitors/informix.rb
index cd43be8858..63c2a671a9 100644
--- a/activerecord/lib/arel/visitors/informix.rb
+++ b/activerecord/lib/arel/visitors/informix.rb
@@ -43,7 +43,7 @@ def visit_Arel_Nodes_SelectCore(o, collector)
end
def visit_Arel_Nodes_OptimizerHints(o, collector)
- collector << "/*+ #{sanitize_as_sql_comment(o).join(", ")} */"
+ collector << "/*+ #{o.values.join(", ")} */"
end
def visit_Arel_Nodes_Offset(o, collector)
diff --git a/activerecord/lib/arel/visitors/mssql.rb b/activerecord/lib/arel/visitors/mssql.rb
index 85815baca2..cc916f5bee 100644
--- a/activerecord/lib/arel/visitors/mssql.rb
+++ b/activerecord/lib/arel/visitors/mssql.rb
@@ -82,7 +82,7 @@ def visit_Arel_Nodes_SelectCore(o, collector)
end
def visit_Arel_Nodes_OptimizerHints(o, collector)
- collector << "OPTION (#{sanitize_as_sql_comment(o).join(", ")})"
+ collector << "OPTION (#{o.values.join(", ")})"
end
def get_offset_limit_clause(o)
diff --git a/activerecord/lib/arel/visitors/to_sql.rb b/activerecord/lib/arel/visitors/to_sql.rb
index 0a6d090a82..f31a4aadfb 100644
--- a/activerecord/lib/arel/visitors/to_sql.rb
+++ b/activerecord/lib/arel/visitors/to_sql.rb
@@ -240,7 +240,7 @@ def visit_Arel_Nodes_SelectCore(o, collector)
end
def visit_Arel_Nodes_OptimizerHints(o, collector)
- collector << "/*+ #{sanitize_as_sql_comment(o).join(" ")} */"
+ collector << "/*+ #{o.values.join(SPACE)} */"
end
def collect_nodes_for(nodes, collector, spacer, connector = COMMA)
@@ -810,10 +810,6 @@ def quote_column_name(name)
@connection.quote_column_name(name)
end
- def sanitize_as_sql_comment(o)
- o.expr.map { |v| v.gsub(%r{ /\*\+?\s* | \s*\*/ }x, "") }
- end
-
def collect_optimizer_hints(o, collector)
maybe_visit o.optimizer_hints, collector
end
diff --git a/activerecord/test/cases/adapters/mysql2/optimizer_hints_test.rb b/activerecord/test/cases/adapters/mysql2/optimizer_hints_test.rb
index 349de49b36..17579e6389 100644
--- a/activerecord/test/cases/adapters/mysql2/optimizer_hints_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/optimizer_hints_test.rb
@@ -13,12 +13,6 @@ def test_optimizer_hints
posts = posts.select(:id).where(author_id: [0, 1])
assert_includes posts.explain, "| index | index_posts_on_author_id | index_posts_on_author_id |"
end
-
- assert_sql(%r{\ASELECT /\*\+ NO_RANGE_OPTIMIZATION\(posts index_posts_on_author_id\) \*/}) do
- posts = Post.optimizer_hints("/*+ NO_RANGE_OPTIMIZATION(posts index_posts_on_author_id) */")
- posts = posts.select(:id).where(author_id: [0, 1])
- assert_includes posts.explain, "| index | index_posts_on_author_id | index_posts_on_author_id |"
- end
end
end
end
diff --git a/activerecord/test/cases/adapters/postgresql/optimizer_hints_test.rb b/activerecord/test/cases/adapters/postgresql/optimizer_hints_test.rb
index 1bfa815cac..206096e0ff 100644
--- a/activerecord/test/cases/adapters/postgresql/optimizer_hints_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/optimizer_hints_test.rb
@@ -17,12 +17,6 @@ def test_optimizer_hints
posts = posts.select(:id).where(author_id: [0, 1])
assert_includes posts.explain, "Seq Scan on posts"
end
-
- assert_sql(%r{\ASELECT /\*\+ SeqScan\(posts\) \*/}) do
- posts = Post.optimizer_hints("/*+ SeqScan(posts) */")
- posts = posts.select(:id).where(author_id: [0, 1])
- assert_includes posts.explain, "Seq Scan on posts"
- end
end
end
end
diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb
index 061328df5f..29bfcabbd7 100644
--- a/activerecord/test/cases/relation_test.rb
+++ b/activerecord/test/cases/relation_test.rb
@@ -355,6 +355,15 @@ def test_relation_without_annotation_does_not_include_an_empty_comment
assert_predicate log.select { |query| query.match?(%r{/\*}) }, :empty?
end
+ def test_relation_with_optimizer_hints_filters_sql_comment_delimiters
+ post_with_hint = Post.where(id: 1).optimizer_hints("**//BADHINT//**")
+ assert_match %r{BADHINT}, post_with_hint.to_sql
+ assert_no_match %r{\*/BADHINT}, post_with_hint.to_sql
+ assert_no_match %r{\*//BADHINT}, post_with_hint.to_sql
+ assert_no_match %r{BADHINT/\*}, post_with_hint.to_sql
+ assert_no_match %r{BADHINT//\*}, post_with_hint.to_sql
+ end
+
class EnsureRoundTripTypeCasting < ActiveRecord::Type::Value
def type
:string
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment