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) ⇒ UnaryExpressionNode

Returns a new instance of UnaryExpressionNode.



26
27
28
29
30
31
32
33
34
35
36
# File 'lib/hotdog/expression/semantics.rb', line 26

def initialize(op, expression)
  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
end

Instance Attribute Details

#expressionObject (readonly)

Returns the value of attribute expression.



24
25
26
# File 'lib/hotdog/expression/semantics.rb', line 24

def expression
  @expression
end

#opObject (readonly)

Returns the value of attribute op.



24
25
26
# File 'lib/hotdog/expression/semantics.rb', line 24

def op
  @op
end

Instance Method Details

#==(other) ⇒ Object



88
89
90
# File 'lib/hotdog/expression/semantics.rb', line 88

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

#dump(options = {}) ⇒ Object



92
93
94
# File 'lib/hotdog/expression/semantics.rb', line 92

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

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



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

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 }
        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 }
      }.tap do |values|
        environment.logger.debug("NOT expr: #{values.length} value(s)")
      end
    end
  else
    []
  end
end

#optimize(options = {}) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/hotdog/expression/semantics.rb', line 69

def optimize(options={})
  case op
  when :NOOP
    optimize1(options)
  when :NOT
    case expression
    when EverythingNode
      NothingNode.new(options)
    when NothingNode
      EverythingNode.new(options)
    else
      optimize1(options)
    end
  else
    @expression = expression.optimize(options)
    self
  end
end