Module: PgInsights::ApplicationHelper
- Defined in:
- app/helpers/pg_insights/application_helper.rb
Instance Method Summary collapse
Instance Method Details
#render_plan_node(node, level = 0) ⇒ Object
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'app/helpers/pg_insights/application_helper.rb', line 3 def render_plan_node(node, level = 0) return "".html_safe unless node # Build the node display text node_text = [] node_text << "#{node['Node Type']}" node_text << "on #{node['Relation Name']}" if node["Relation Name"] # Cost information cost_info = [] if node["Startup Cost"] && node["Total Cost"] cost_info << "cost=#{node['Startup Cost']}..#{node['Total Cost']}" elsif node["Total Cost"] cost_info << "cost=#{node['Total Cost']}" end if node["Plan Rows"] cost_info << "rows=#{node['Plan Rows']}" end if node["Plan Width"] cost_info << "width=#{node['Plan Width']}" end node_text << "(#{cost_info.join(' ')})" if cost_info.any? # Actual execution stats actual_info = [] if node["Actual Total Time"] actual_info << "actual time=#{node['Actual Total Time']}ms" end if node["Actual Rows"] actual_info << "rows=#{node['Actual Rows']}" end if node["Actual Loops"] actual_info << "loops=#{node['Actual Loops']}" end node_text << "[#{actual_info.join(' ')}]" if actual_info.any? # Build the HTML for this node indent = " " * level prefix = level == 0 ? "" : "├─ " result = content_tag(:div, class: "plan-node level-#{level}") do content = content_tag(:span, "#{indent}#{prefix}", class: "plan-indent") content += content_tag(:span, node_text.join(" "), class: "plan-node-text") # Add filter information if present if node["Filter"] content += content_tag(:div, class: "plan-filter") do content_tag(:span, "#{indent} Filter: #{node['Filter']}", class: "filter-text") end end # Add index condition if present if node["Index Cond"] content += content_tag(:div, class: "plan-condition") do content_tag(:span, "#{indent} Index Cond: #{node['Index Cond']}", class: "condition-text") end end # Add other important fields %w[Sort Key Hash Cond Join Filter].each do |field| if node[field] content += content_tag(:div, class: "plan-detail") do content_tag(:span, "#{indent} #{field}: #{node[field]}", class: "detail-text") end end end content end # Recursively render child nodes if node["Plans"] && node["Plans"].any? node["Plans"].each do |child_plan| result += render_plan_node(child_plan, level + 1) end end result end |
#render_plan_node_modern(node, level = 0) ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'app/helpers/pg_insights/application_helper.rb', line 87 def render_plan_node_modern(node, level = 0) return "".html_safe unless node # Get node type and determine color/icon node_type = node["Node Type"] || "Unknown" operation_class = get_operation_class(node_type) operation_icon = get_operation_icon(node_type) # Build timing info timing_info = [] if node["Actual Total Time"] timing_info << "#{node['Actual Total Time']}ms" end if node["Actual Rows"] timing_info << "#{node['Actual Rows']} rows" end # Build cost info cost_info = node["Total Cost"] ? node["Total Cost"].round(2) : nil result = content_tag(:div, class: "plan-node-modern level-#{level} #{operation_class}") do content = "" # Tree connector if level > 0 content += content_tag(:div, class: "tree-connector") do "├─".html_safe end end # Node card content += content_tag(:div, class: "node-card") do card_content = "" # Header row card_content += content_tag(:div, class: "node-header") do header_content = content_tag(:span, operation_icon, class: "node-icon") header_content += content_tag(:span, node_type, class: "node-type") if node["Relation Name"] header_content += content_tag(:span, "#{node['Relation Name']}", class: "relation-name") end if timing_info.any? header_content += content_tag(:div, timing_info.join(" • "), class: "timing-badge") end header_content end # Details row (if present) details = [] if cost_info details << "Cost: #{cost_info}" end if node["Filter"] details << "Filter: #{truncate_filter(node['Filter'])}" end if node["Sort Key"] details << "Sort: #{node['Sort Key']}" end if node["Hash Cond"] details << "Join: #{truncate_filter(node['Hash Cond'])}" end if details.any? card_content += content_tag(:div, class: "node-details") do details.map { |detail| content_tag(:span, detail, class: "detail-item") }.join(" • ").html_safe end end card_content.html_safe end content.html_safe end # Recursively render child nodes if node["Plans"] && node["Plans"].any? node["Plans"].each do |child_plan| result += render_plan_node_modern(child_plan, level + 1) end end result end |