From d478b0f9071506e911d1beb32f5aa3d0ef16364f Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Sun, 2 May 2021 16:20:07 -0400 Subject: [PATCH] Arel::Visitors::Dot renders all attributes of some AST node types These node types were missing some properties: - SelectCore - SelectStatement - InsertStatement - UpdateStatement - DeleteStatement Fixes #42026 --- activerecord/CHANGELOG.md | 6 ++ activerecord/lib/arel/visitors/dot.rb | 26 +++++-- .../test/cases/arel/visitors/dot_test.rb | 77 ++++++++++++++++++- 3 files changed, 103 insertions(+), 6 deletions(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 0355ae58d1..0c3f7b9e3f 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,9 @@ +* `Arel::Visitors::Dot` now renders a complete set of properties when visiting + `Arel::Nodes::SelectCore`, `SelectStatement`, `InsertStatement`, `UpdateStatement`, and + `DeleteStatement`, which fixes #42026. Previously, some properties were omitted. + + *Mike Dalessio* + * `Arel::Visitors::Dot` now supports `Arel::Nodes::Bin`, `Case`, `CurrentRow`, `Distinct`, `DistinctOn`, `Else`, `Except`, `InfixOperation`, `Intersect`, `Lock`, `NotRegexp`, `Quoted`, `Regexp`, `UnaryOperation`, `Union`, `UnionAll`, `When`, and `With`. Previously, these node diff --git a/activerecord/lib/arel/visitors/dot.rb b/activerecord/lib/arel/visitors/dot.rb index b5b3cee217..2999aef92a 100644 --- a/activerecord/lib/arel/visitors/dot.rb +++ b/activerecord/lib/arel/visitors/dot.rb @@ -87,11 +87,6 @@ def visit_Arel_Nodes_StringJoin(o) visit_edge o, "left" end - def visit_Arel_Nodes_DeleteStatement(o) - visit_edge o, "relation" - visit_edge o, "wheres" - end - def visit_Arel_Nodes_Window(o) visit_edge o, "partitions" visit_edge o, "orders" @@ -127,6 +122,7 @@ def visit_Arel_Nodes_InsertStatement(o) visit_edge o, "relation" visit_edge o, "columns" visit_edge o, "values" + visit_edge o, "select" end def visit_Arel_Nodes_SelectCore(o) @@ -134,6 +130,11 @@ def visit_Arel_Nodes_SelectCore(o) visit_edge o, "projections" visit_edge o, "wheres" visit_edge o, "windows" + visit_edge o, "groups" + visit_edge o, "comment" + visit_edge o, "havings" + visit_edge o, "set_quantifier" + visit_edge o, "optimizer_hints" end def visit_Arel_Nodes_SelectStatement(o) @@ -141,12 +142,27 @@ def visit_Arel_Nodes_SelectStatement(o) visit_edge o, "limit" visit_edge o, "orders" visit_edge o, "offset" + visit_edge o, "lock" + visit_edge o, "with" end def visit_Arel_Nodes_UpdateStatement(o) visit_edge o, "relation" visit_edge o, "wheres" visit_edge o, "values" + visit_edge o, "orders" + visit_edge o, "limit" + visit_edge o, "offset" + visit_edge o, "key" + end + + def visit_Arel_Nodes_DeleteStatement(o) + visit_edge o, "relation" + visit_edge o, "wheres" + visit_edge o, "orders" + visit_edge o, "limit" + visit_edge o, "offset" + visit_edge o, "key" end def visit_Arel_Table(o) diff --git a/activerecord/test/cases/arel/visitors/dot_test.rb b/activerecord/test/cases/arel/visitors/dot_test.rb index 98d3743dee..f10a1e7a64 100644 --- a/activerecord/test/cases/arel/visitors/dot_test.rb +++ b/activerecord/test/cases/arel/visitors/dot_test.rb @@ -10,6 +10,10 @@ def setup @visitor = Visitors::Dot.new end + def assert_edge(edge_name, dot_string) + assert_match(/->.*label="#{edge_name}"/, dot_string) + end + # functions [ Nodes::Sum, @@ -64,7 +68,6 @@ def test_named_function Arel::Nodes::Or, Arel::Nodes::TableAlias, Arel::Nodes::As, - Arel::Nodes::DeleteStatement, Arel::Nodes::JoinSource, Arel::Nodes::Casted, ].each do |klass| @@ -170,6 +173,78 @@ def test_Arel_Nodes_With assert_edge("1", dot) assert_edge("2", dot) end + + def test_Arel_Nodes_SelectCore + node = Arel::Nodes::SelectCore.new + + dot = @visitor.accept(node, Arel::Collectors::PlainString.new).value + + assert_match '[label="Arel::Nodes::SelectCore"]', dot + assert_edge("source", dot) + assert_edge("projections", dot) + assert_edge("wheres", dot) + assert_edge("windows", dot) + assert_edge("groups", dot) + assert_edge("comment", dot) + assert_edge("havings", dot) + assert_edge("set_quantifier", dot) + assert_edge("optimizer_hints", dot) + end + + def test_Arel_Nodes_SelectStatement + node = Arel::Nodes::SelectStatement.new + + dot = @visitor.accept(node, Arel::Collectors::PlainString.new).value + + assert_match '[label="Arel::Nodes::SelectStatement"]', dot + assert_edge("cores", dot) + assert_edge("limit", dot) + assert_edge("orders", dot) + assert_edge("offset", dot) + assert_edge("lock", dot) + assert_edge("with", dot) + end + + def test_Arel_Nodes_InsertStatement + node = Arel::Nodes::InsertStatement.new + + dot = @visitor.accept(node, Arel::Collectors::PlainString.new).value + + assert_match '[label="Arel::Nodes::InsertStatement"]', dot + assert_edge("relation", dot) + assert_edge("columns", dot) + assert_edge("values", dot) + assert_edge("select", dot) + end + + def test_Arel_Nodes_UpdateStatement + node = Arel::Nodes::UpdateStatement.new + + dot = @visitor.accept(node, Arel::Collectors::PlainString.new).value + + assert_match '[label="Arel::Nodes::UpdateStatement"]', dot + assert_edge("relation", dot) + assert_edge("wheres", dot) + assert_edge("values", dot) + assert_edge("orders", dot) + assert_edge("limit", dot) + assert_edge("offset", dot) + assert_edge("key", dot) + end + + def test_Arel_Nodes_DeleteStatement + node = Arel::Nodes::DeleteStatement.new + + dot = @visitor.accept(node, Arel::Collectors::PlainString.new).value + + assert_match '[label="Arel::Nodes::DeleteStatement"]', dot + assert_edge("relation", dot) + assert_edge("wheres", dot) + assert_edge("orders", dot) + assert_edge("limit", dot) + assert_edge("offset", dot) + assert_edge("key", dot) + end end end end