Class: Hotdog::Expression::MultinaryExpressionNode

Inherits:
ExpressionNode show all
Defined in:
lib/hotdog/expression/semantics.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from ExpressionNode

#==, #compact, #optimize

Constructor Details

#initialize(op, expressions, options = {}) ⇒ MultinaryExpressionNode

Returns a new instance of MultinaryExpressionNode.



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

def initialize(op, expressions, options={})
  case (op || "or").to_s
  when ",", "||", "|", "OR", "or"
    @op = :OR
  else
    raise(SyntaxError.new("unknown multinary operator: #{op.inspect}"))
  end
  sqlite_limit_compound_select = options[:sqlite_limit_compound_select] || SQLITE_LIMIT_COMPOUND_SELECT
  if sqlite_limit_compound_select < expressions.length
    raise(ArgumentError.new("expressions limit exceeded: #{expressions.length} for #{sqlite_limit_compound_select}"))
  end
  @expressions = expressions
  @options = options
end

Instance Attribute Details

#expressionsObject (readonly)

Returns the value of attribute expressions.



406
407
408
# File 'lib/hotdog/expression/semantics.rb', line 406

def expressions
  @expressions
end

#opObject (readonly)

Returns the value of attribute op.



406
407
408
# File 'lib/hotdog/expression/semantics.rb', line 406

def op
  @op
end

Instance Method Details

#dump(options = {}) ⇒ Object



465
466
467
# File 'lib/hotdog/expression/semantics.rb', line 465

def dump(options={})
  {multinary_op: @op.to_s, expressions: expressions.map { |expression| expression.dump(options) }}
end

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



431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
# File 'lib/hotdog/expression/semantics.rb', line 431

def evaluate(environment, options={})
  case @op
  when :OR
    if expressions.all? { |expression| TagExpressionNode === expression }
      values = expressions.group_by { |expression| expression.class }.values.flat_map { |expressions|
        query_without_condition = expressions.first.maybe_query_without_condition(options)
        if query_without_condition
          condition_length = expressions.map { |expression| expression.condition_values(options).length }.max
          sqlite_limit_compound_select = options[:sqlite_limit_compound_select] || SQLITE_LIMIT_COMPOUND_SELECT
          expressions.each_slice(sqlite_limit_compound_select / condition_length).flat_map { |expressions|
            q = query_without_condition.sub(/\s*;\s*\z/, " WHERE #{expressions.map { |expression| "( %s )" % expression.condition(options) }.join(" OR ")};")
            environment.execute(q, expressions.flat_map { |expression| expression.condition_values(options) }).map { |row| row.first }
          }
        else
          []
        end
      }
    else
      values = []
    end
  else
    values = []
  end
  if values.empty?
    if @options[:fallback]
      @options[:fallback].evaluate(environment, options={})
    else
      []
    end
  else
    values
  end
end

#merge(other, options = {}) ⇒ Object



423
424
425
426
427
428
429
# File 'lib/hotdog/expression/semantics.rb', line 423

def merge(other, options={})
  if MultinaryExpressionNode === other and op == other.op
    MultinaryExpressionNode.new(op, expressions + other.expressions, options)
  else
    MultinaryExpressionNode.new(op, expressions + [other], options)
  end
end