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.



345
346
347
348
349
350
351
352
353
# File 'lib/hotdog/commands/search.rb', line 345

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



343
344
345
# File 'lib/hotdog/commands/search.rb', line 343

def expression
  @expression
end

#opObject (readonly)

Returns the value of attribute op.



343
344
345
# File 'lib/hotdog/commands/search.rb', line 343

def op
  @op
end

Instance Method Details

#==(other) ⇒ Object



400
401
402
# File 'lib/hotdog/commands/search.rb', line 400

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

#dump(options = {}) ⇒ Object



404
405
406
# File 'lib/hotdog/commands/search.rb', line 404

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

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



355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
# File 'lib/hotdog/commands/search.rb', line 355

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?
      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 - 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



408
409
410
# File 'lib/hotdog/commands/search.rb', line 408

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

#leafsObject



412
413
414
# File 'lib/hotdog/commands/search.rb', line 412

def leafs()
  @expression.leafs
end

#optimize(options = {}) ⇒ Object



383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
# File 'lib/hotdog/commands/search.rb', line 383

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