Class: Shiba::Explain::PostgresExplain
- Inherits:
-
Object
- Object
- Shiba::Explain::PostgresExplain
- Defined in:
- lib/shiba/explain/postgres_explain.rb
Instance Method Summary collapse
- #extract_join_key_parts(cond) ⇒ Object
- #extract_used_key_parts(cond) ⇒ Object
-
#initialize(json) ⇒ PostgresExplain
constructor
A new instance of PostgresExplain.
- #recurse_plans(node, array) ⇒ Object
- #transform ⇒ Object
- #transform_node(node, array) ⇒ Object
- #with_state(hash) ⇒ Object
Constructor Details
#initialize(json) ⇒ PostgresExplain
Returns a new instance of PostgresExplain.
6 7 8 9 |
# File 'lib/shiba/explain/postgres_explain.rb', line 6 def initialize(json) @json = json @state = {} end |
Instance Method Details
#extract_join_key_parts(cond) ⇒ Object
90 91 92 93 94 95 96 97 98 |
# File 'lib/shiba/explain/postgres_explain.rb', line 90 def extract_join_key_parts(cond) begin conds = Parsers::PostgresExplainIndexConditions.new(cond) conds.join_fields rescue Parsers::BadParse => e debugger {} end end |
#extract_used_key_parts(cond) ⇒ Object
80 81 82 83 84 85 86 87 88 |
# File 'lib/shiba/explain/postgres_explain.rb', line 80 def extract_used_key_parts(cond) begin conds = Parsers::PostgresExplainIndexConditions.new(cond) conds.fields rescue Parsers::BadParse => e debugger {} end end |
#recurse_plans(node, array) ⇒ Object
100 101 102 103 104 |
# File 'lib/shiba/explain/postgres_explain.rb', line 100 def recurse_plans(node, array) node['Plans'].each do |n| transform_node(n, array) end end |
#transform ⇒ Object
106 107 108 109 |
# File 'lib/shiba/explain/postgres_explain.rb', line 106 def transform plan = @json.first['Plan'] transform_node(plan, []) end |
#transform_node(node, array) ⇒ Object
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 |
# File 'lib/shiba/explain/postgres_explain.rb', line 18 def transform_node(node, array) case node['Node Type'] when "Limit", "LockRows", "Aggregate", "Unique", "Sort", "Hash", "ProjectSet", "Materialize" recurse_plans(node, array) when "Hash Join", "Merge Join", "Nested Loop", "BitmapOr" with_state(join_type: node['Node Type']) do recurse_plans(node, array) end when "Bitmap Heap Scan" with_state(table: node['Relation Name']) do recurse_plans(node, array) end when "Subquery Scan" with_state(subquery: true) do recurse_plans(node, array) end when "Seq Scan" array << { "table" => node["Relation Name"], "access_type" => "ALL", "key" => nil, "filter" => node["Filter"] } when "Index Scan", "Bitmap Index Scan", "Index Only Scan" table = node["Relation Name"] || @state[:table] if node['Index Cond'] used_key_parts = extract_used_key_parts(node['Index Cond']) else used_key_parts = [] end if @state[:join_type] == 'BitmapOr' access_type = "intersect" else access_type = "ref" end h = { "table" => node["Relation Name"] || @state[:table], "access_type" => access_type, "key" => node["Index Name"], "used_key_parts" => used_key_parts } if node['Node Type'] == "Index Only Scan" h['using_index'] = true end array << h when "Result" # TBD: What the hell is here? seems like queries that short-circuit end up here? array << { "extra" => "No tables used" } else debugger raise "unhandled node: #{node}" end array end |
#with_state(hash) ⇒ Object
11 12 13 14 15 16 |
# File 'lib/shiba/explain/postgres_explain.rb', line 11 def with_state(hash) old_state = @state @state = @state.merge(hash) yield @state = old_state end |