Class: Redis::Bitops::Queries::BinaryOperator

Inherits:
Object
  • Object
show all
Includes:
LazyEvaluation, MaterializationHelpers, TreeBuildingHelpers
Defined in:
lib/redis/bitops/queries/binary_operator.rb

Overview

Binary bitwise operator.

Instance Method Summary collapse

Methods included from LazyEvaluation

#dest, #evaluate

Methods included from TreeBuildingHelpers

#&, #^, #|, #~

Methods included from MaterializationHelpers

#resolve_operand, #temp_bitmap, #unique_key

Constructor Details

#initialize(op, lhs, rhs) ⇒ BinaryOperator

Creates a bitwise operator ‘op’ with left-hand operand, ‘lhs’, and right-hand operand, ‘rhs’.



16
17
18
19
# File 'lib/redis/bitops/queries/binary_operator.rb', line 16

def initialize(op, lhs, rhs)
  @args = [lhs, rhs]
  @op = op
end

Instance Method Details

#bitmap_factoryObject

Finds the first bitmap factory in the expression tree. Required by LazyEvaluation and MaterializationHelpers.



64
65
66
67
# File 'lib/redis/bitops/queries/binary_operator.rb', line 64

def bitmap_factory
  arg = @args.find { |arg| arg.bitmap_factory } or raise "Internal error. Cannot find a bitmap factory."
  arg.bitmap_factory
end

#materialize(dest) ⇒ Object

Runs the expression tree against the redis database, saving the results in bitmap ‘dest’.



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/redis/bitops/queries/binary_operator.rb', line 24

def materialize(dest)
  # Resolve lhs and rhs operand, using 'dest' to store intermediate result so
  # a maximum of one temporary Bitmap has to be created.
  # Then apply the bitwise operator storing the final result in 'dest'.

  intermediate = dest

  lhs, *other_args = @args
  temp_intermediates = []

  # Side-effects: if a temp intermediate bitmap is created, it's added to 'temp_intermediates' 
  # to be deleted in the "ensure" block. Marked with "<- SE".
  
  lhs_operand, intermediate = resolve_operand(lhs, intermediate, temp_intermediates) # <- SE
  other_operands, *_ = other_args.inject([[], intermediate]) do |(operands, intermediate), arg|
    operand, intermediate = resolve_operand(arg, intermediate, temp_intermediates) # <- SE
    [operands << operand, intermediate]
  end

  lhs_operand.bitop(@op, *other_operands, dest)
ensure
  temp_intermediates.each(&:delete!)
end

#optimize!(parent_op = nil) ⇒ Object

Recursively optimizes the expression tree by combining operands for neighboring identical operators, so for instance a & b & c ultimately becomes BITOP :and dest a b c as opposed to running two separate BITOP commands.



52
53
54
55
56
57
58
59
# File 'lib/redis/bitops/queries/binary_operator.rb', line 52

def optimize!(parent_op = nil)
  @args.map! { |arg| arg.respond_to?(:optimize!) ? arg.optimize!(@op) : arg }.flatten!
  if parent_op == @op
    @args
  else
    self
  end
end