Class: Hotdog::Expression::UnaryExpressionNode

Inherits:
ExpressionNode show all
Defined in:
lib/hotdog/expression/semantics.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(op, expression, options = {}) ⇒ UnaryExpressionNode

Returns a new instance of UnaryExpressionNode.



30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/hotdog/expression/semantics.rb', line 30

def initialize(op, expression, options={})
  case (op || "not").to_s
  when "NOOP", "noop"
    @op = :NOOP
  when "!", "~", "NOT", "not"
    @op = :NOT
  else
    raise(SyntaxError.new("unknown unary operator: #{op.inspect}"))
  end
  @expression = expression
  @options = {}
end

Instance Attribute Details

#expressionObject (readonly)

Returns the value of attribute expression.



28
29
30
# File 'lib/hotdog/expression/semantics.rb', line 28

def expression
  @expression
end

#opObject (readonly)

Returns the value of attribute op.



28
29
30
# File 'lib/hotdog/expression/semantics.rb', line 28

def op
  @op
end

Instance Method Details

#==(other) ⇒ Object



111
112
113
# File 'lib/hotdog/expression/semantics.rb', line 111

def ==(other)
  self.class === other and @op == other.op and @expression == other.expression
end

#compact(options = {}) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
# File 'lib/hotdog/expression/semantics.rb', line 99

def compact(options={})
  case op
  when :NOOP
    expression.compact(options)
  else
    UnaryExpressionNode.new(
      op,
      expression.compact(options),
    )
  end
end

#dump(options = {}) ⇒ Object



115
116
117
# File 'lib/hotdog/expression/semantics.rb', line 115

def dump(options={})
  {unary_op: @op.to_s, expression: @expression.dump(options)}
end

#evaluate(environment, options = {}) ⇒ Object



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
# File 'lib/hotdog/expression/semantics.rb', line 43

def evaluate(environment, options={})
  case @op
  when :NOOP
    @expression.evaluate(environment, options)
  when :NOT
    values = @expression.evaluate(environment, options).tap do |values|
      environment.logger.debug("expr: #{values.length} value(s)")
    end
    if values.empty?
      EverythingNode.new().evaluate(environment, options).tap do |values|
        environment.logger.debug("NOT expr: #{values.length} value(s)")
      end
    else
      # workaround for "too many terms in compound SELECT"
      min, max = environment.execute("SELECT MIN(id), MAX(id) FROM hosts LIMIT 1;").first.to_a
      sqlite_limit_compound_select = options[:sqlite_limit_compound_select] || SQLITE_LIMIT_COMPOUND_SELECT
      (min / (sqlite_limit_compound_select - 2)).upto(max / (sqlite_limit_compound_select - 2)).flat_map { |i|
        range = ((sqlite_limit_compound_select - 2) * i)...((sqlite_limit_compound_select - 2) * (i + 1))
        selected = values.select { |n| range === n }
        if 0 < selected.length
          q = "SELECT id FROM hosts " \
                "WHERE ? <= id AND id < ? AND id NOT IN (%s);"
          environment.execute(q % selected.map { "?" }.join(", "), [range.first, range.last] + selected).map { |row| row.first }
        else
          []
        end
      }.tap do |values|
        environment.logger.debug("NOT expr: #{values.length} value(s)")
      end
    end
  else
    []
  end
end

#optimize(options = {}) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/hotdog/expression/semantics.rb', line 78

def optimize(options={})
  o_self = compact(options)
  if UnaryExpressionNode === o_self
    case o_self.op
    when :NOT
      case o_self.expression
      when EverythingNode
        NothingNode.new(options)
      when NothingNode
        EverythingNode.new(options)
      else
        o_self.optimize1(options)
      end
    else
      o_self.optimize1(options)
    end
  else
    o_self.optimize(options)
  end
end