Class: Hotdog::Commands::Search::UnaryExpressionNode

Inherits:
ExpressionNode show all
Defined in:
lib/hotdog/commands/search.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(op, expression) ⇒ UnaryExpressionNode

Returns a new instance of UnaryExpressionNode.



297
298
299
300
301
302
303
304
305
# File 'lib/hotdog/commands/search.rb', line 297

def initialize(op, expression)
  case op
  when "!", "~", /\Anot\z/i
    @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.



295
296
297
# File 'lib/hotdog/commands/search.rb', line 295

def expression
  @expression
end

#opObject (readonly)

Returns the value of attribute op.



295
296
297
# File 'lib/hotdog/commands/search.rb', line 295

def op
  @op
end

Instance Method Details

#==(other) ⇒ Object



347
348
349
# File 'lib/hotdog/commands/search.rb', line 347

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

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



307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
# File 'lib/hotdog/commands/search.rb', line 307

def evaluate(environment, options={})
  case @op
  when :NOT
    values = @expression.evaluate(environment).sort
    environment.logger.debug("expr: #{values.length} value(s)")
    if values.empty?
      environment.execute("SELECT id FROM hosts").map { |row| row.first }.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 ORDER BY id LIMIT 1").first.to_a
      (min / SQLITE_LIMIT_COMPOUND_SELECT).upto(max / SQLITE_LIMIT_COMPOUND_SELECT).flat_map { |i|
        range = (SQLITE_LIMIT_COMPOUND_SELECT*i)...(SQLITE_LIMIT_COMPOUND_SELECT*(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



334
335
336
337
338
339
340
341
342
343
344
345
# File 'lib/hotdog/commands/search.rb', line 334

def optimize(options={})
  @expression = @expression.optimize(options)
  if UnaryExpressionNode === @expression
    if @op == :NOT and @expression.op == :NOT
      @expression.expression
    else
      self
    end
  else
    self
  end
end