Class: NoSE::Plans::UpdatePlan

Inherits:
AbstractPlan show all
Includes:
Comparable
Defined in:
lib/nose/plans/update_planner.rb

Overview

A plan for executing an update

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from AbstractPlan

#select_fields

Constructor Details

#initialize(statement, index, trees, update_steps, cost_model) ⇒ UpdatePlan

Returns a new instance of UpdatePlan.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/nose/plans/update_planner.rb', line 29

def initialize(statement, index, trees, update_steps, cost_model)
  @statement = statement
  @index = index
  @trees = trees
  @query_plans = nil # these will be set later when we pick indexes
  update_steps.each { |step| step.calculate_cost cost_model }
  @update_steps = update_steps
  @cost_model = cost_model

  # Update with fields specified in the settings and conditions
  # (rewrite from foreign keys to IDs if needed)
  @update_fields = if statement.is_a?(Connection) ||
                      statement.is_a?(Delete)
                     []
                   else
                     statement.settings.map(&:field)
                   end
  @update_fields += statement.conditions.each_value.map(&:field)
  @update_fields.map! do |field|
    field.is_a?(Fields::ForeignKeyField) ? field.entity.id_field : field
  end
end

Instance Attribute Details

#cost_modelObject (readonly)

Returns the value of attribute cost_model.



24
25
26
# File 'lib/nose/plans/update_planner.rb', line 24

def cost_model
  @cost_model
end

#indexObject (readonly)

Returns the value of attribute index.



24
25
26
# File 'lib/nose/plans/update_planner.rb', line 24

def index
  @index
end

#query_plansObject (readonly)

Returns the value of attribute query_plans.



24
25
26
# File 'lib/nose/plans/update_planner.rb', line 24

def query_plans
  @query_plans
end

#statementObject (readonly)

Returns the value of attribute statement.



24
25
26
# File 'lib/nose/plans/update_planner.rb', line 24

def statement
  @statement
end

#update_fieldsObject (readonly)

Returns the value of attribute update_fields.



24
25
26
# File 'lib/nose/plans/update_planner.rb', line 24

def update_fields
  @update_fields
end

#update_stepsObject (readonly)

Returns the value of attribute update_steps.



24
25
26
# File 'lib/nose/plans/update_planner.rb', line 24

def update_steps
  @update_steps
end

Instance Method Details

#<=>(other) ⇒ Boolean

Two plans are compared by their execution cost

Returns:

  • (Boolean)


143
144
145
# File 'lib/nose/plans/update_planner.rb', line 143

def <=>(other)
  cost <=> other.cost
end

#costFixnum

The cost is the sum of all the query costs plus the update costs

Returns:

  • (Fixnum)


155
156
157
# File 'lib/nose/plans/update_planner.rb', line 155

def cost
  @query_plans.sum_by(&:cost) + update_cost
end

#eql?(other) ⇒ Boolean

Compare all the fields for the plan for equality

Returns:

  • (Boolean)


119
120
121
122
123
124
125
126
127
128
129
# File 'lib/nose/plans/update_planner.rb', line 119

def eql?(other)
  return false unless other.is_a? UpdatePlan
  fail 'plans must be resolved before checking equality' \
    if @query_plans.nil? || other.query_plans.nil?

  @statement == other.statement &&
    @index == other.index &&
    @query_plans == other.query_plans &&
    @update_steps == other.update_steps &&
    @cost_model == other.cost_model
end

#groupString

The group of the associated statement

Returns:

  • (String)


62
63
64
# File 'lib/nose/plans/update_planner.rb', line 62

def group
  @statement.group
end

#nameString

Name the plan by the statement

Returns:

  • (String)


68
69
70
# File 'lib/nose/plans/update_planner.rb', line 68

def name
  "#{@statement.text} for #{@index.key}"
end

#paramsHash

Parameters to this update plan

Returns:

  • (Hash)


80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/nose/plans/update_planner.rb', line 80

def params
  conditions = if @statement.respond_to?(:conditions)
                 @statement.conditions
               else
                 {}
               end
  settings = if @statement.respond_to?(:settings)
               @statement.settings
             else
               []
             end

  params = conditions.merge Hash[settings.map do |setting|
    [setting.field.id, Condition.new(setting.field, :'=', setting.value)]
  end]

  convert_param_keys params
end

#select_query_plans(indexes = nil, &block) ⇒ void

This method returns an undefined value.

Select query plans to actually use here



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/nose/plans/update_planner.rb', line 101

def select_query_plans(indexes = nil, &block)
  if block_given?
    @query_plans = @trees.map(&block)
  else
    @query_plans = @trees.map do |tree|
      plan = tree.select_using_indexes(indexes).min_by(&:cost)
      fail if plan.nil?
      plan
    end
  end

  update_support_fields

  @trees = nil
end

#stepsArray<UpdatePlanStep>

The steps for this plan are the update steps

Returns:



74
75
76
# File 'lib/nose/plans/update_planner.rb', line 74

def steps
  @update_steps
end

#to_colorObject

:nocov:



132
133
134
135
136
137
138
# File 'lib/nose/plans/update_planner.rb', line 132

def to_color
  "\n   statement: " + @statement.to_color +
    "\n       index: " + @index.to_color +
    "\n query_plans: " + @query_plans.to_color +
    "\nupdate_steps: " + @update_steps.to_color +
    "\n  cost_model: " + @cost_model.to_color
end

#update_costFixnum

The cost of performing the update on this index

Returns:

  • (Fixnum)


149
150
151
# File 'lib/nose/plans/update_planner.rb', line 149

def update_cost
  @update_steps.sum_by(&:cost)
end

#weightFixnum

The weight of this query for a given workload

Returns:

  • (Fixnum)


54
55
56
57
58
# File 'lib/nose/plans/update_planner.rb', line 54

def weight
  return 1 if @workload.nil?

  @workload.statement_weights[@statement]
end