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.



368
369
370
371
372
373
374
375
376
# File 'lib/hotdog/commands/search.rb', line 368

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.



366
367
368
# File 'lib/hotdog/commands/search.rb', line 366

def expression
  @expression
end

#opObject (readonly)

Returns the value of attribute op.



366
367
368
# File 'lib/hotdog/commands/search.rb', line 366

def op
  @op
end

Instance Method Details

#==(other) ⇒ Object



423
424
425
# File 'lib/hotdog/commands/search.rb', line 423

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

#dump(options = {}) ⇒ Object



427
428
429
# File 'lib/hotdog/commands/search.rb', line 427

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

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



378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
# File 'lib/hotdog/commands/search.rb', line 378

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 ORDER BY id 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

#intermediatesObject



431
432
433
# File 'lib/hotdog/commands/search.rb', line 431

def intermediates()
  [self] + @expression.intermediates
end

#leafsObject



435
436
437
# File 'lib/hotdog/commands/search.rb', line 435

def leafs()
  @expression.leafs
end

#optimize(options = {}) ⇒ Object



406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
# File 'lib/hotdog/commands/search.rb', line 406

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