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.



22
23
24
25
26
27
28
29
30
# File 'lib/hotdog/expression/semantics.rb', line 22

def initialize(op, expression)
  case (op || "not").to_s
  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.



20
21
22
# File 'lib/hotdog/expression/semantics.rb', line 20

def expression
  @expression
end

#opObject (readonly)

Returns the value of attribute op.



20
21
22
# File 'lib/hotdog/expression/semantics.rb', line 20

def op
  @op
end

Instance Method Details

#==(other) ⇒ Object



77
78
79
# File 'lib/hotdog/expression/semantics.rb', line 77

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

#dump(options = {}) ⇒ Object



81
82
83
# File 'lib/hotdog/expression/semantics.rb', line 81

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

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



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

def evaluate(environment, options={})
  case @op
  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
      (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



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/hotdog/expression/semantics.rb', line 60

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