/
inline_param_encoder.rb
70 lines (61 loc) · 1.58 KB
/
inline_param_encoder.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# frozen_string_literal: true
module MiniSql
class InlineParamEncoder
attr_reader :conn
def initialize(conn)
@conn = conn
end
def encode(sql, *params)
return sql unless params && params.length > 0
if Hash === (hash = params[0])
raise ArgumentError, "Only one hash param is allowed, multiple were sent" if params.length > 1
encode_hash(sql, hash)
else
encode_array(sql, params)
end
end
def encode_hash(sql, hash)
sql = sql.dup
hash.each do |k, v|
sql.gsub!(":#{k}") do
# ignore ::int and stuff like that
# $` is previous to match
if $` && $`[-1] != ":"
quote_val(v)
else
":#{k}"
end
end
end
sql
end
def encode_array(sql, array)
i = -1
sql.gsub("?") do |p|
i += 1
quote_val(array[i])
end
end
def quoted_date(value)
value.utc.iso8601
end
def quote_val(value)
case value
when String then "'#{conn.escape_string(value.to_s)}'"
when Numeric then value.to_s
when BigDecimal then value.to_s("F")
when Date, Time then "'#{quoted_date(value)}'"
when Symbol then "'#{conn.escape_string(value.to_s)}'"
when true then "true"
when false then "false"
when nil then "NULL"
when [] then "NULL"
when Array
value.map do |v|
quote_val(v)
end.join(', ')
else raise TypeError, "can't quote #{value.class.name}"
end
end
end
end