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

#==, #optimize

Constructor Details

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

Returns a new instance of MultinaryExpressionNode.



357
358
359
360
361
362
363
364
365
366
367
368
369
370
# File 'lib/hotdog/expression/semantics.rb', line 357

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
  @fallback = options[:fallback]
end

Instance Attribute Details

#expressionsObject (readonly)

Returns the value of attribute expressions.



355
356
357
# File 'lib/hotdog/expression/semantics.rb', line 355

def expressions
  @expressions
end

#opObject (readonly)

Returns the value of attribute op.



355
356
357
# File 'lib/hotdog/expression/semantics.rb', line 355

def op
  @op
end

Instance Method Details

#dump(options = {}) ⇒ Object



414
415
416
# File 'lib/hotdog/expression/semantics.rb', line 414

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

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



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
405
406
407
408
409
410
411
412
# File 'lib/hotdog/expression/semantics.rb', line 380

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 @fallback
      @fallback.evaluate(environment, options={})
    else
      []
    end
  else
    values
  end
end

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



372
373
374
375
376
377
378
# File 'lib/hotdog/expression/semantics.rb', line 372

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