sql_query_executor 0.3.2 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/sql_query_executor/base.rb +1 -1
- data/lib/sql_query_executor/operators/base.rb +1 -1
- data/lib/sql_query_executor/query/normalizers/base_normalizer.rb +47 -15
- data/lib/sql_query_executor/query/normalizers/origin_normalizer.rb +45 -43
- data/lib/sql_query_executor/query/normalizers/query_normalizer.rb +68 -60
- data/lib/sql_query_executor/query/sub_query.rb +2 -2
- data/lib/sql_query_executor/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 885c973bd56f42cacc7f5a2ec53399c6004aa487
|
4
|
+
data.tar.gz: a5591b1baddeb58afd77ac9279f82b8eca4f3213
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59120a2dc4c1468f86b4bef599daf7b2601c8e30164cfb427397559656320163a1bc80a0b29c3e6d96f4649047e3e4823c5c49d2b356a2304c322f45484acb3f
|
7
|
+
data.tar.gz: 32a3793e8c462c62719c37ebf5900ecae59130831f33216c36bc8e4165a5e45439c146c2569181febcac63c7afcce50d5b90ed6ac115a15c631d2d318c34b22a
|
@@ -16,7 +16,7 @@ module SqlQueryExecutor #:nodoc:
|
|
16
16
|
raise ArgumentError.new(message) if message
|
17
17
|
|
18
18
|
get_collection(collection)
|
19
|
-
query = Query::QueryNormalizer.execute(query)
|
19
|
+
query = Query::Normalizers::QueryNormalizer.execute(query)
|
20
20
|
@query = SqlQueryExecutor::Query::SubQuery.new query, @collection
|
21
21
|
end
|
22
22
|
|
@@ -4,7 +4,7 @@ module SqlQueryExecutor
|
|
4
4
|
module Operators
|
5
5
|
class Base
|
6
6
|
def initialize(query, collection)
|
7
|
-
@query = SqlQueryExecutor::Query::QueryNormalizer.execute(query).gsub(SqlQueryExecutor::Base::QUERY_SPACE, ' ')
|
7
|
+
@query = SqlQueryExecutor::Query::Normalizers::QueryNormalizer.execute(query).gsub(SqlQueryExecutor::Base::QUERY_SPACE, ' ')
|
8
8
|
@collection = collection
|
9
9
|
@array = @query.split(' ')
|
10
10
|
@operator = @query.split(' ')[1]
|
@@ -2,21 +2,53 @@ require 'sql_query_executor'
|
|
2
2
|
|
3
3
|
module SqlQueryExecutor
|
4
4
|
module Query
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
"
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
5
|
+
module Normalizers
|
6
|
+
class BaseNormalizer
|
7
|
+
private
|
8
|
+
# Returns converted #param based on its Class, so it can be used on the query
|
9
|
+
def self.convert_param(param)
|
10
|
+
case param.class.name
|
11
|
+
when "NilClass"
|
12
|
+
nil
|
13
|
+
when "String"
|
14
|
+
"'#{param}'".gsub("''", "'").gsub('""', '"')
|
15
|
+
when "Date"
|
16
|
+
"'#{param.strftime("%Y-%m-%d")}'"
|
17
|
+
when "Time"
|
18
|
+
"'#{param.strftime("%Y-%m-%d %H:%M:%S %z")}'"
|
19
|
+
else
|
20
|
+
param.to_s
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.attributes_from_query(selector)
|
25
|
+
return {} if selector.empty?
|
26
|
+
|
27
|
+
attributes = {}
|
28
|
+
|
29
|
+
selector.each do |key, value|
|
30
|
+
case value.class.name
|
31
|
+
when 'Array'
|
32
|
+
attributes.merge!(attributes_from_array(value)) if key == '$and'
|
33
|
+
when 'Hash'
|
34
|
+
attributes.merge!(attributes_from_query(value))
|
35
|
+
else
|
36
|
+
attributes[key.to_sym] = value unless key.to_s.include?('$')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
attributes
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
def self.attributes_from_array(array)
|
45
|
+
attributes = {}
|
46
|
+
|
47
|
+
array.each do |hash|
|
48
|
+
attributes.merge!(attributes_from_query(hash))
|
49
|
+
end
|
50
|
+
|
51
|
+
attributes
|
20
52
|
end
|
21
53
|
end
|
22
54
|
end
|
@@ -3,60 +3,62 @@ require 'sql_query_executor/query/normalizers/base_normalizer'
|
|
3
3
|
|
4
4
|
module SqlQueryExecutor
|
5
5
|
module Query
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
6
|
+
module Normalizers
|
7
|
+
class OriginNormalizer < BaseNormalizer
|
8
|
+
BINDING_OPERATORS = ['$and', '$or']
|
9
|
+
OPERATORS = {
|
10
|
+
"$gt" => '>',
|
11
|
+
"$lt" => '<',
|
12
|
+
"$gte" => '>=',
|
13
|
+
"$lte" => '<=',
|
14
|
+
"$ne" => '!=',
|
15
|
+
"$in" => 'in'
|
16
|
+
}
|
17
|
+
|
18
|
+
def self.execute(query)
|
19
|
+
query_array = []
|
20
|
+
|
21
|
+
query.each do |key, value|
|
22
|
+
if value.is_a?(Array)
|
23
|
+
query_array << hash_with_array_value(key, value)
|
24
|
+
else
|
25
|
+
query_array << normal_hash(key, value)
|
26
|
+
end
|
25
27
|
end
|
26
|
-
end
|
27
28
|
|
28
29
|
|
29
|
-
|
30
|
-
|
30
|
+
query_array.join(" and ").gsub('!=', '<>')
|
31
|
+
end
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
private
|
34
|
+
def self.hash_with_array_value(key, value)
|
35
|
+
if BINDING_OPERATORS.include?(key)
|
36
|
+
key = key.gsub('$', '')
|
37
|
+
queries = []
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
39
|
+
value.each do |hash|
|
40
|
+
queries << execute(hash)
|
41
|
+
end
|
41
42
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
"(#{queries.join(" #{key.to_s} ")})"
|
44
|
+
else
|
45
|
+
value = value.first.is_a?(Numeric) ? value : value.map{ |v| "'#{v}'" }
|
46
|
+
"#{key} in (#{value.join(',')})"
|
47
|
+
end
|
46
48
|
end
|
47
|
-
end
|
48
49
|
|
49
|
-
|
50
|
-
|
50
|
+
def self.normal_hash(key, value)
|
51
|
+
operator = '='
|
51
52
|
|
52
|
-
|
53
|
-
|
53
|
+
if value.is_a?(Hash)
|
54
|
+
operator = OPERATORS[value.keys.first] || operator
|
54
55
|
|
55
|
-
|
56
|
-
|
56
|
+
value = convert_param(value.values.first)
|
57
|
+
end
|
57
58
|
|
58
|
-
|
59
|
-
|
59
|
+
value = convert_param(value)
|
60
|
+
value.nil? ? "#{key} is null" : "#{key} #{operator} #{value}"
|
61
|
+
end
|
60
62
|
end
|
61
63
|
end
|
62
64
|
end
|
@@ -4,92 +4,100 @@ require 'sql_query_executor/query/normalizers/origin_normalizer'
|
|
4
4
|
|
5
5
|
module SqlQueryExecutor
|
6
6
|
module Query
|
7
|
-
|
8
|
-
|
7
|
+
module Normalizers
|
8
|
+
class QueryNormalizer < BaseNormalizer
|
9
|
+
CONVERT_METHODS = {"String" => "get_query", "Array" => "interpolate_query", "Hash" => "convert_hash"}
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
def self.execute(query)
|
12
|
+
query = clean_query_attribute(query)
|
13
|
+
method = CONVERT_METHODS[query.class.name]
|
13
14
|
|
14
|
-
|
15
|
-
|
15
|
+
query = sanitize(send(method, query))
|
16
|
+
end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
def self.clean_query(query)
|
19
|
+
remove_placeholders execute(query).gsub('!=', '<>')
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
def self.attributes_from_query(query)
|
23
|
+
return {} if query.empty?
|
24
|
+
selector = query.class == Hash ? query : Base.new([], query).selector
|
25
|
+
super(selector)
|
26
|
+
end
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
28
|
+
private
|
29
|
+
def self.convert_hash(query)
|
30
|
+
OriginNormalizer.execute(query)
|
31
|
+
end
|
29
32
|
|
30
|
-
|
31
|
-
|
33
|
+
def self.remove_placeholders(query)
|
34
|
+
query.gsub(Base::QUERY_SPACE, ' ').gsub(Base::STRING_SPACE, ' ').gsub(Base::TEMP_SPACE, ' ')
|
35
|
+
end
|
32
36
|
|
33
|
-
|
37
|
+
def self.clean_query_attribute(query)
|
38
|
+
return query unless query.is_a?(Array)
|
34
39
|
|
35
|
-
|
36
|
-
end
|
40
|
+
query = query.flatten
|
37
41
|
|
38
|
-
|
39
|
-
|
40
|
-
end
|
42
|
+
(query.size == 1 ? query.first : query)
|
43
|
+
end
|
41
44
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
return args.first if args.size == 1 && args.first.is_a?(String)
|
45
|
+
def self.get_query(query)
|
46
|
+
query
|
47
|
+
end
|
46
48
|
|
47
|
-
query
|
48
|
-
|
49
|
+
# Prepares query by replacing all ? by it's real values in #args
|
50
|
+
def self.interpolate_query(args)
|
51
|
+
args.flatten!
|
52
|
+
return args.first if args.size == 1 && args.first.is_a?(String)
|
49
53
|
|
50
|
-
|
54
|
+
query = args.first
|
55
|
+
param = args.delete_at(1)
|
51
56
|
|
52
|
-
|
57
|
+
param = convert_param(param)
|
53
58
|
|
54
|
-
|
55
|
-
end
|
59
|
+
args[0] = query.sub("?", param.is_a?(Numeric) ? param : "#{param}")
|
56
60
|
|
57
|
-
|
58
|
-
|
59
|
-
new_query = replace_on_query(query, /(["|'].*?["|'])/, " ", Base::STRING_SPACE)
|
60
|
-
new_query = replace_on_query(new_query, /(\(.*?\))/, " ", Base::QUERY_SPACE)
|
61
|
+
interpolate_query(args)
|
62
|
+
end
|
61
63
|
|
62
|
-
|
63
|
-
|
64
|
+
# Removes all accents and other non default characters
|
65
|
+
def self.sanitize(query)
|
66
|
+
new_query = replace_on_query(query, /(["|'].*?["|'])/, " ", Base::STRING_SPACE)
|
67
|
+
new_query = replace_on_query(new_query, /(\(.*?\))/, " ", Base::QUERY_SPACE)
|
64
68
|
|
65
|
-
|
66
|
-
|
69
|
+
remove_spaces(prepare_query(new_query))
|
70
|
+
end
|
67
71
|
|
68
|
-
|
72
|
+
def self.replace_on_query(query, regexp, pattern, replacement)
|
73
|
+
new_query = query ? query.dup : query
|
69
74
|
|
70
|
-
|
71
|
-
new_param = param.dup
|
75
|
+
params = new_query.scan(regexp).flatten.compact
|
72
76
|
|
73
|
-
|
77
|
+
params.each do |param|
|
78
|
+
new_param = param.dup
|
74
79
|
|
75
|
-
|
76
|
-
end
|
80
|
+
new_param = new_param.gsub(pattern, replacement)
|
77
81
|
|
78
|
-
|
79
|
-
|
82
|
+
new_query = new_query.gsub(param, new_param)
|
83
|
+
end
|
80
84
|
|
81
|
-
|
82
|
-
SubQuery::BINDING_OPERATORS.keys.each do |operator|
|
83
|
-
query.gsub!(" #{operator} ", "#{Base::TEMP_SPACE}#{operator}#{Base::QUERY_SPACE}")
|
85
|
+
new_query
|
84
86
|
end
|
85
87
|
|
86
|
-
|
87
|
-
|
88
|
+
def self.prepare_query(query)
|
89
|
+
SubQuery::BINDING_OPERATORS.keys.each do |operator|
|
90
|
+
query.gsub!(" #{operator} ", "#{Base::TEMP_SPACE}#{operator}#{Base::QUERY_SPACE}")
|
91
|
+
end
|
88
92
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
query
|
93
|
+
query.gsub(" ", Base::QUERY_SPACE).gsub(Base::TEMP_SPACE, " ")
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.remove_spaces(query)
|
97
|
+
query.gsub!(",#{Base::QUERY_SPACE}", ',')
|
98
|
+
query.gsub!(/\[.*?\]/) { |substr| substr.gsub(' ', '') }
|
99
|
+
query
|
100
|
+
end
|
93
101
|
end
|
94
102
|
end
|
95
103
|
end
|
@@ -35,7 +35,7 @@ module SqlQueryExecutor
|
|
35
35
|
@children.each do |child|
|
36
36
|
if child.respond_to?(:binding_operator) && child.binding_operator
|
37
37
|
operator = BINDING_OPERATORS.invert[child.binding_operator]
|
38
|
-
hash = {operator
|
38
|
+
hash = {"$#{operator}" => [hash,child.selector]}
|
39
39
|
else
|
40
40
|
hash.merge!(child.selector)
|
41
41
|
end
|
@@ -45,7 +45,7 @@ module SqlQueryExecutor
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def to_sql
|
48
|
-
QueryNormalizer.clean_query(@query)
|
48
|
+
SqlQueryExecutor::Query::Normalizers::QueryNormalizer.clean_query(@query)
|
49
49
|
end
|
50
50
|
|
51
51
|
private
|