Class: Volt::Sql::WhereCall

Inherits:
Object
  • Object
show all
Defined in:
app/sql/lib/where_call.rb

Constant Summary collapse

VALID_METHODS =
['&', '|', '~', '>', '<', '>=', '<=' , '=~', '!~']

Instance Method Summary collapse

Constructor Details

#initialize(ident) ⇒ WhereCall

Returns a new instance of WhereCall.



12
13
14
# File 'app/sql/lib/where_call.rb', line 12

def initialize(ident)
  @ident = ident
end

Instance Method Details

#call(ast) ⇒ Object



16
17
18
# File 'app/sql/lib/where_call.rb', line 16

def call(ast)
  walk(ast)
end

#op_call(self_obj, method_name, *args) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'app/sql/lib/where_call.rb', line 39

def op_call(self_obj, method_name, *args)
  if self_obj == 'ident'
    self_obj = @ident
  end

  # walk on the self obj
  self_obj = walk(self_obj)

  # Method name security checks
  case method_name
  when 'send'
    raise "Send is not supported in queries"
  end

  if method_name !~ /^[a-zA-Z0-9_]+$/ && !VALID_METHODS.include?(method_name)
    raise "Only method names matching /[a-zA-Z0-9_]/ are allowed from client side queries (called `#{method_name}`)"
  end

  walked_args = args.map {|arg| walk(arg) }

  # We have to use __send__ because send is handled differently
  self_obj.__send__(method_name, *walked_args)
end

#walk(ast) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'app/sql/lib/where_call.rb', line 20

def walk(ast)
  if ast.is_a?(Array) && !ast.is_a?(Sequel::SQL::Identifier)
    op = ast.shift

    case op
    when 'c'
      return op_call(*ast)
    when 'a'
      # We popped off the 'a', so we just return the array
      return ast
    else
      raise "invalid op: #{op.inspect} - #{ast.inspect} - #{ast.is_a?(Array).inspect}"
    end
  else
    # Not an operation, return
    return ast
  end
end