class NoSE::Serialize::UpdatePlanBuilder

Reconstruct the steps of an update plan

Public Instance Methods

call(_, fragment:, represented:, **) click to toggle source
# File lib/nose/serialize.rb, line 378
def call(_, fragment:, represented:, **)
  workload = represented.workload

  if fragment['statement'].nil?
    statement = OpenStruct.new group: fragment['group']
  else
    statement = Statement.parse fragment['statement'], workload.model,
                                group: fragment['group']
  end

  update_steps = fragment['update_steps'].map do |step_hash|
    step_class = Plans::PlanStep.subtype_class step_hash['type']
    index_key = step_hash['index']['key']
    step_index = represented.indexes.find { |i| i.key == index_key }

    if statement.nil?
      state = nil
    else
      state = Plans::UpdateState.new statement, step_hash['cardinality']
    end
    step = step_class.new step_index, state

    # Set the fields to be inserted
    fields = (step_hash['fields'] || []).map do |dict|
      workload.model[dict['parent']][dict['name']]
    end
    step.instance_variable_set(:@fields, fields) \
      if step.is_a?(Plans::InsertPlanStep)

    step
  end

  index_key = fragment['index']['key']
  index = represented.indexes.find { |i| i.key == index_key }
  update_plan = Plans::UpdatePlan.new statement, index, [], update_steps,
                                      represented.cost_model

  update_plan.instance_variable_set(:@group, fragment['group']) \
    unless fragment['group'].nil?
  update_plan.instance_variable_set(:@name, fragment['name']) \
    unless fragment['name'].nil?
  update_plan.instance_variable_set(:@weight, fragment['weight'])

  # Reconstruct and assign the query plans
  builder = QueryPlanBuilder.new
  query_plans = fragment['query_plans'].map do |plan|
    builder.call [], represented: represented, fragment: plan
  end
  update_plan.instance_variable_set(:@query_plans, query_plans)
  update_plan.send :update_support_fields

  update_plan
end