sql_query_executor 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/sql_query_executor/operators/base.rb +44 -18
- data/lib/sql_query_executor/operators/between.rb +3 -3
- data/lib/sql_query_executor/operators/default.rb +1 -1
- data/lib/sql_query_executor/operators/in.rb +3 -3
- data/lib/sql_query_executor/operators/is.rb +1 -1
- data/lib/sql_query_executor/query/base.rb +29 -16
- data/lib/sql_query_executor/query/sentence.rb +70 -0
- data/lib/sql_query_executor/query/sub_query.rb +101 -42
- data/lib/sql_query_executor/{version → version.rb} +1 -1
- data/spec/sql_query_executor/base_spec.rb +43 -5
- data/sql_query_executor.gemspec +4 -4
- metadata +6 -6
- data/lib/sql_query_executor/query/divider.rb +0 -56
- data/lib/sql_query_executor/query/executor.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d35ed6525f34f2fa2b89077179627bb398e60569
|
4
|
+
data.tar.gz: d7f5b1378fe6932180ed501143f8282620b36ee1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 17f7149a30b187f41262d8dfe826cf3a100400764aea984b5783cb440f9874b356038574ee5a16e9dd0e7f87d24c40e2085dad37ead3fe0f23db9f23fe8971b5
|
7
|
+
data.tar.gz: 407df8d2c2a114b9979b17f7249bfcf9698a04b317087a59b3199e9cda64bcb2fa58e74657069c76190954bc80b6cba1cc2f97a2e6e8f9e23047629724358ece
|
@@ -2,7 +2,7 @@ module SqlQueryExecutor
|
|
2
2
|
module Operators
|
3
3
|
class Base
|
4
4
|
def initialize(query, collection)
|
5
|
-
@query = query
|
5
|
+
@query = sanitize_query(query)
|
6
6
|
@collection = collection
|
7
7
|
@array = query.split(' ')
|
8
8
|
@operator = @query.split(' ')[1]
|
@@ -16,31 +16,57 @@ module SqlQueryExecutor
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def get_value
|
19
|
-
value = @array.last.gsub(
|
19
|
+
value = @array.last.gsub(::SqlQueryExecutor::Query::Base::STRING_SPACE, ' ')
|
20
20
|
|
21
21
|
convert_value(value)
|
22
22
|
end
|
23
23
|
|
24
24
|
def convert_value(value)
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
if (value.to_i.to_s == value.to_s)
|
34
|
-
return value.to_i
|
35
|
-
elsif array.size == 3
|
36
|
-
return array.first.to_i > 1000 ? Date.new(array[0].to_i, array[1].to_i, array[2].to_i) : value
|
37
|
-
elsif array.size == 7
|
38
|
-
array[6] = array[6] == '+0000' ? '+00:00' : array[6].gsub('00', ':00')
|
39
|
-
return array.first.to_i > 1000 ? Time.new(*array) : value
|
40
|
-
end
|
25
|
+
value.gsub!(/[\(\)\'\"]/, "")
|
26
|
+
return value.to_i if is_a_number?(value)
|
27
|
+
|
28
|
+
methods = {3 => "convert_date", 7 => "convert_time"}
|
29
|
+
|
30
|
+
array = split(value)
|
31
|
+
|
32
|
+
value = (send(methods[array.size], array) || value) if methods.keys.include?(array.size)
|
41
33
|
|
42
34
|
value
|
43
35
|
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def sanitize_query(query)
|
39
|
+
params = query.scan(/(\(.*?\))/).flatten.compact
|
40
|
+
|
41
|
+
params.each { |param| query.gsub!(param, param.gsub(" ", "")) }
|
42
|
+
|
43
|
+
query
|
44
|
+
end
|
45
|
+
|
46
|
+
def is_a_number?(value)
|
47
|
+
value.to_s == value.to_i.to_s
|
48
|
+
end
|
49
|
+
|
50
|
+
def split(value)
|
51
|
+
return [] unless value.size >= 10
|
52
|
+
|
53
|
+
array = value.split(/[ :]/)
|
54
|
+
array[0] = array.first.split('-')
|
55
|
+
array.flatten
|
56
|
+
end
|
57
|
+
|
58
|
+
def convert_date(args)
|
59
|
+
return if args.first.to_i < 1000
|
60
|
+
|
61
|
+
Date.new(args[0].to_i, args[1].to_i, args[2].to_i)
|
62
|
+
end
|
63
|
+
|
64
|
+
def convert_time(args)
|
65
|
+
return if args.first.to_i < 1000
|
66
|
+
args[6] = args[6].gsub('00', ':00').gsub("+:", "+")
|
67
|
+
|
68
|
+
Time.new(*args)
|
69
|
+
end
|
44
70
|
end
|
45
71
|
end
|
46
72
|
end
|
@@ -3,7 +3,7 @@ require 'sql_query_executor/operators/base'
|
|
3
3
|
module SqlQueryExecutor
|
4
4
|
module Operators
|
5
5
|
class Between < SqlQueryExecutor::Operators::Base
|
6
|
-
def execute!
|
6
|
+
def execute!(result)
|
7
7
|
@collection.select do |record|
|
8
8
|
value = convert_value(record.send(@field).to_s)
|
9
9
|
|
@@ -22,8 +22,8 @@ module SqlQueryExecutor
|
|
22
22
|
def get_value
|
23
23
|
value = []
|
24
24
|
|
25
|
-
value << convert_value(@array[2].gsub(
|
26
|
-
value << convert_value(@array[4].gsub(
|
25
|
+
value << convert_value(@array[2].gsub(SqlQueryExecutor::Query::Base::STRING_SPACE, ' '))
|
26
|
+
value << convert_value(@array[4].gsub(SqlQueryExecutor::Query::Base::STRING_SPACE, ' '))
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -3,8 +3,8 @@ require 'sql_query_executor/operators/base'
|
|
3
3
|
module SqlQueryExecutor
|
4
4
|
module Operators
|
5
5
|
class In < SqlQueryExecutor::Operators::Base
|
6
|
-
def execute!
|
7
|
-
@collection.select do |record|
|
6
|
+
def execute!(result)
|
7
|
+
result = @collection.select do |record|
|
8
8
|
value = record.send(@field)
|
9
9
|
|
10
10
|
@value.send('include?', value)
|
@@ -15,7 +15,7 @@ module SqlQueryExecutor
|
|
15
15
|
def get_value
|
16
16
|
value = super
|
17
17
|
|
18
|
-
value.gsub(
|
18
|
+
value.gsub(SqlQueryExecutor::Query::Base::STRING_SPACE, '').split(',').map &:strip
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
@@ -1,23 +1,23 @@
|
|
1
|
-
require 'sql_query_executor/query/executor'
|
2
|
-
|
3
1
|
module SqlQueryExecutor
|
4
2
|
module Query
|
5
3
|
class Base
|
6
4
|
attr_reader :query
|
7
5
|
|
8
6
|
CONVERT_METHODS = {"String" => ["get_query", ""], "Array" => ["interpolate_query", "query.flatten"], "Hash" => ["concatenate_hash", "query"]}
|
7
|
+
STRING_SPACE = "$SS$"
|
8
|
+
QUERY_SPACE = "$QS$"
|
9
|
+
TEMP_SPACE = "$TS$"
|
9
10
|
|
10
11
|
def initialize(query, collection)
|
11
12
|
query = clean_query_attribute(query)
|
12
13
|
array = CONVERT_METHODS[query.class.name]
|
13
14
|
|
14
|
-
|
15
|
-
@
|
16
|
-
sanitize
|
15
|
+
query = sanitize(send(array.first, query))
|
16
|
+
@query = SqlQueryExecutor::Query::SubQuery.new query, collection
|
17
17
|
end
|
18
18
|
|
19
19
|
def execute!
|
20
|
-
|
20
|
+
@query.execute!
|
21
21
|
end
|
22
22
|
|
23
23
|
private
|
@@ -43,34 +43,45 @@ module SqlQueryExecutor
|
|
43
43
|
|
44
44
|
param = convert_param(param)
|
45
45
|
|
46
|
-
args[0] = query.sub("?", param)
|
46
|
+
args[0] = query.sub("?", param.is_a?(Numeric) ? param : "#{param}")
|
47
47
|
|
48
48
|
interpolate_query(args)
|
49
49
|
end
|
50
50
|
|
51
51
|
# Removes all accents and other non default characters
|
52
|
-
def sanitize
|
52
|
+
def sanitize(query)
|
53
53
|
cruft = /\'|\"|\(|\)/
|
54
54
|
|
55
|
-
new_query =
|
56
|
-
params = new_query.scan(/(["|'].*?["|'])
|
55
|
+
new_query = query ? query.dup : query
|
56
|
+
params = new_query.scan(/(["|'].*?["|'])/).flatten.compact
|
57
|
+
|
58
|
+
params.each do |param|
|
59
|
+
new_param = param.dup
|
60
|
+
|
61
|
+
new_param = new_param.gsub(" ", STRING_SPACE)
|
62
|
+
|
63
|
+
new_query = new_query.gsub(param, new_param)
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
params = new_query.scan(/(\(.*?\))/).flatten.compact
|
57
68
|
|
58
69
|
params.each do |param|
|
59
70
|
new_param = param.dup
|
60
71
|
|
61
|
-
new_param = new_param.gsub(
|
62
|
-
new_param = new_param.gsub(" ", "$S$")
|
72
|
+
new_param = new_param.gsub(" ", QUERY_SPACE)
|
63
73
|
|
64
74
|
new_query = new_query.gsub(param, new_param)
|
65
75
|
end
|
66
76
|
|
67
|
-
|
77
|
+
query = new_query.gsub(" and ", "#{TEMP_SPACE}and#{QUERY_SPACE}").gsub(" or ", "#{TEMP_SPACE}or#{QUERY_SPACE}").gsub(" ", QUERY_SPACE).gsub(TEMP_SPACE, " ")
|
68
78
|
|
69
|
-
remove_spaces
|
79
|
+
remove_spaces(query)
|
70
80
|
end
|
71
81
|
|
72
|
-
def remove_spaces
|
73
|
-
|
82
|
+
def remove_spaces(query)
|
83
|
+
query.gsub!(/\[.*?\]/) { |substr| substr.gsub(' ', '') }
|
84
|
+
query
|
74
85
|
end
|
75
86
|
|
76
87
|
# Returns converted #param based on its Class, so it can be used on the query
|
@@ -93,8 +104,10 @@ module SqlQueryExecutor
|
|
93
104
|
|
94
105
|
query.each do |key, value|
|
95
106
|
if value.is_a?(Array)
|
107
|
+
value = value.first.is_a?(Numeric) ? value : value.map{ |v| "'#{v}'" }
|
96
108
|
query_array << "#{key} in (#{value.join(',')})"
|
97
109
|
else
|
110
|
+
value = value.is_a?(Numeric) ? value : "'#{value}'"
|
98
111
|
query_array << "#{key} = #{value}"
|
99
112
|
end
|
100
113
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'sql_query_executor/operators/default'
|
2
|
+
require 'sql_query_executor/operators/between'
|
3
|
+
require 'sql_query_executor/operators/is'
|
4
|
+
require 'sql_query_executor/operators/in'
|
5
|
+
|
6
|
+
module SqlQueryExecutor
|
7
|
+
module Query
|
8
|
+
class Sentence
|
9
|
+
attr_reader :query, :binding_operator, :operator
|
10
|
+
|
11
|
+
OPERATORS = {
|
12
|
+
"between" => SqlQueryExecutor::Operators::Between,
|
13
|
+
"is" => SqlQueryExecutor::Operators::Is,
|
14
|
+
"in" => SqlQueryExecutor::Operators::In,
|
15
|
+
"=" => SqlQueryExecutor::Operators::Default,
|
16
|
+
">" => SqlQueryExecutor::Operators::Default,
|
17
|
+
"<" => SqlQueryExecutor::Operators::Default,
|
18
|
+
">=" => SqlQueryExecutor::Operators::Default,
|
19
|
+
"<=" => SqlQueryExecutor::Operators::Default,
|
20
|
+
"<>" => SqlQueryExecutor::Operators::Default,
|
21
|
+
"!=" => SqlQueryExecutor::Operators::Default,
|
22
|
+
"not" => SqlQueryExecutor::Operators::Default,
|
23
|
+
"exists" => SqlQueryExecutor::Operators::Default,#Exists
|
24
|
+
}
|
25
|
+
|
26
|
+
BINDING_OPERATORS = {
|
27
|
+
"and" => "&",
|
28
|
+
"or" => "+"
|
29
|
+
}
|
30
|
+
|
31
|
+
def initialize(query, collection)
|
32
|
+
@query = query
|
33
|
+
@collection = collection
|
34
|
+
@array = query.split(' ')
|
35
|
+
|
36
|
+
set_binding_operator
|
37
|
+
set_operator
|
38
|
+
end
|
39
|
+
|
40
|
+
def execute!(data)
|
41
|
+
return [] unless @operator
|
42
|
+
|
43
|
+
result = @operator.execute!(data)
|
44
|
+
|
45
|
+
result = data.send(@binding_operator, result) if @binding_operator && (data && !data.empty?)
|
46
|
+
|
47
|
+
result
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
def set_operator
|
52
|
+
operator = OPERATORS[@query.split(' ')[1]]
|
53
|
+
|
54
|
+
@operator = operator ? operator.new(@query, @collection) : nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def set_binding_operator
|
58
|
+
@binding_operator = BINDING_OPERATORS[@array.first]
|
59
|
+
|
60
|
+
fix_query if @binding_operator
|
61
|
+
end
|
62
|
+
|
63
|
+
def fix_query
|
64
|
+
@array.delete_at(0)
|
65
|
+
|
66
|
+
@query = @array.join(' ')
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -1,67 +1,126 @@
|
|
1
|
-
require 'sql_query_executor/operators/default'
|
2
|
-
require 'sql_query_executor/operators/between'
|
3
|
-
require 'sql_query_executor/operators/is'
|
4
|
-
require 'sql_query_executor/operators/in'
|
5
|
-
|
6
1
|
module SqlQueryExecutor
|
7
2
|
module Query
|
8
3
|
class SubQuery
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
"in" => SqlQueryExecutor::Operators::In,
|
13
|
-
"=" => SqlQueryExecutor::Operators::Default,
|
14
|
-
">" => SqlQueryExecutor::Operators::Default,
|
15
|
-
"<" => SqlQueryExecutor::Operators::Default,
|
16
|
-
">=" => SqlQueryExecutor::Operators::Default,
|
17
|
-
"<=" => SqlQueryExecutor::Operators::Default,
|
18
|
-
"<>" => SqlQueryExecutor::Operators::Default,
|
19
|
-
"!=" => SqlQueryExecutor::Operators::Default,
|
20
|
-
"not" => SqlQueryExecutor::Operators::Default,
|
21
|
-
"exists" => SqlQueryExecutor::Operators::Default,#Exists
|
22
|
-
}
|
23
|
-
|
24
|
-
BINDING_OPERATORS = {
|
25
|
-
"and" => "&",
|
26
|
-
"or" => "+"
|
27
|
-
}
|
28
|
-
|
4
|
+
BINDING_OPERATORS = { "or" => "+", "and" => "&" }
|
5
|
+
attr_reader :query, :children, :kind
|
6
|
+
ADD_CHILDREN_METHODS = { sentence: :add_sentence_children, sub_query: :add_sub_query_children }
|
29
7
|
def initialize(query, collection)
|
30
|
-
@query = query
|
31
8
|
@collection = collection
|
32
|
-
@
|
33
|
-
|
9
|
+
@query = query
|
10
|
+
@children = []
|
34
11
|
set_binding_operator
|
35
|
-
|
12
|
+
set_kind
|
13
|
+
set_children
|
36
14
|
end
|
37
15
|
|
38
|
-
def execute!(data)
|
39
|
-
return [] unless @
|
16
|
+
def execute!(data=[])
|
17
|
+
return [] unless @children
|
18
|
+
|
19
|
+
result = []
|
40
20
|
|
41
|
-
|
21
|
+
@children.each do |child|
|
22
|
+
result = child.execute!(result)
|
23
|
+
end
|
42
24
|
|
43
25
|
result = data.send(@binding_operator, result) if @binding_operator && (data && !data.empty?)
|
44
26
|
|
45
|
-
result
|
27
|
+
result.sort_by(&:id)
|
46
28
|
end
|
47
29
|
|
48
30
|
private
|
49
|
-
def
|
50
|
-
|
31
|
+
def set_binding_operator
|
32
|
+
@binding_operator = nil
|
33
|
+
operator = @query.split(Base::QUERY_SPACE).first
|
51
34
|
|
52
|
-
|
35
|
+
if ["and", "or"].include?(operator)
|
36
|
+
@binding_operator = BINDING_OPERATORS[operator]
|
37
|
+
@query = @query.gsub("#{operator}$QS$", "")
|
38
|
+
end
|
53
39
|
end
|
54
40
|
|
55
|
-
def
|
56
|
-
@
|
41
|
+
def set_kind
|
42
|
+
@kind = is_single_query? ? :sentence : :sub_query
|
43
|
+
end
|
44
|
+
|
45
|
+
def set_children
|
46
|
+
send(ADD_CHILDREN_METHODS[@kind])
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_sentence_children
|
50
|
+
@children << SqlQueryExecutor::Query::Sentence.new(@query.gsub(Base::QUERY_SPACE, " "), @collection)
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_sub_query_children
|
54
|
+
array = @query.split(" ")
|
55
|
+
queries = []
|
56
|
+
|
57
|
+
array.each do |query|
|
58
|
+
sanitized_query = replace_parentheses(query)
|
59
|
+
params = sanitized_query.scan(/\$op1\$(\S+)\$cp1\$/).flatten.compact
|
60
|
+
|
61
|
+
params.each do |param|
|
62
|
+
string = param.gsub("$QS$and$QS$", " and$QS$").gsub("$QS$or$QS$", " or$QS$")
|
63
|
+
query = sanitized_query.gsub(param, string)
|
64
|
+
end
|
57
65
|
|
58
|
-
|
66
|
+
query = query.gsub("\$op1\$", "").gsub("\$cp1\$", "").gsub(/\$\Sp\d\$/, "")
|
67
|
+
|
68
|
+
@children << SqlQueryExecutor::Query::SubQuery.new(query, @collection)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def is_single_query?
|
73
|
+
array = @query.gsub(Base::QUERY_SPACE, ' ').split(' ')
|
74
|
+
|
75
|
+
array.size <= 5
|
76
|
+
end
|
77
|
+
|
78
|
+
def build_sub_query(query)
|
79
|
+
array = query.split(" ")
|
80
|
+
|
81
|
+
offset = is_binding_operator?(array.first) ? 1 : 0
|
82
|
+
operator = array[1+offset]
|
83
|
+
|
84
|
+
result = case operator
|
85
|
+
when "between"
|
86
|
+
array[0..4+offset]
|
87
|
+
when "is"
|
88
|
+
size = array[2+offset] == "not" ? 3 : 2
|
89
|
+
array[0..size+offset]
|
90
|
+
when "not"
|
91
|
+
array[0..3+offset]
|
92
|
+
else
|
93
|
+
array[0..2+offset]
|
94
|
+
end
|
95
|
+
|
96
|
+
result.join(' ')
|
97
|
+
end
|
98
|
+
|
99
|
+
def is_binding_operator?(operator)
|
100
|
+
BINDING_OPERATORS.include?(operator)
|
59
101
|
end
|
60
102
|
|
61
|
-
def
|
62
|
-
|
103
|
+
def replace_parentheses(query)
|
104
|
+
count = 1
|
105
|
+
string = ""
|
106
|
+
|
107
|
+
query.each_char do |c|
|
108
|
+
char = c
|
109
|
+
|
110
|
+
if c == "("
|
111
|
+
char = "$op#{count}$"
|
112
|
+
count += 1
|
113
|
+
end
|
114
|
+
|
115
|
+
if c == ")"
|
116
|
+
count -= 1
|
117
|
+
char = "$cp#{count}$"
|
118
|
+
end
|
119
|
+
|
120
|
+
string << char
|
121
|
+
end
|
63
122
|
|
64
|
-
|
123
|
+
string
|
65
124
|
end
|
66
125
|
end
|
67
126
|
end
|
@@ -6,11 +6,11 @@ describe SqlQueryExecutor, "Base" do
|
|
6
6
|
before do
|
7
7
|
@data = []
|
8
8
|
|
9
|
-
@data << {:
|
10
|
-
@data << {:
|
11
|
-
@data << {:
|
12
|
-
@data << {:
|
13
|
-
@data << {:
|
9
|
+
@data << {id: 1, name: "US", language: 'English'}
|
10
|
+
@data << {id: 2, name: "Canada", language: 'English', monarch: "The Crown of England"}
|
11
|
+
@data << {id: 3, name: "Mexico", language: 'Spanish'}
|
12
|
+
@data << {id: 4, name: "UK", language: 'English', monarch: "The Crown of England"}
|
13
|
+
@data << {id: 5, name: "Brazil", founded_at: Time.parse('1500-04-22 13:34:25')}
|
14
14
|
end
|
15
15
|
|
16
16
|
subject { SqlQueryExecutor::Base.new(@data) }
|
@@ -413,6 +413,32 @@ describe SqlQueryExecutor, "Base" do
|
|
413
413
|
|
414
414
|
records.should == [@data[0], @data[1], @data[2], @data[3]]
|
415
415
|
end
|
416
|
+
|
417
|
+
context "nested queries" do
|
418
|
+
it "respects priority" do
|
419
|
+
records = subject.where("(language = 'English' and name = 'US') or (language is null)")
|
420
|
+
records.count.should == 2
|
421
|
+
records.first.id.should == 1
|
422
|
+
|
423
|
+
records.map! do |record|
|
424
|
+
record.to_h
|
425
|
+
end
|
426
|
+
|
427
|
+
records.should == [@data[0], @data[4]]
|
428
|
+
end
|
429
|
+
|
430
|
+
it "respects priority" do
|
431
|
+
records = subject.where("(language is null) or (language = 'English' and name = 'US')")
|
432
|
+
records.count.should == 2
|
433
|
+
records.first.id.should == 1
|
434
|
+
|
435
|
+
records.map! do |record|
|
436
|
+
record.to_h
|
437
|
+
end
|
438
|
+
|
439
|
+
records.should == [@data[0], @data[4]]
|
440
|
+
end
|
441
|
+
end
|
416
442
|
end
|
417
443
|
|
418
444
|
describe "in" do
|
@@ -427,6 +453,18 @@ describe SqlQueryExecutor, "Base" do
|
|
427
453
|
|
428
454
|
records.should == [@data[0], @data[1], @data[2], @data[3]]
|
429
455
|
end
|
456
|
+
|
457
|
+
xit "attribute not in condition" do
|
458
|
+
records = subject.where("language not in ('English', 'Spanish')")
|
459
|
+
records.count.should == 1
|
460
|
+
records.first.id.should == 5
|
461
|
+
|
462
|
+
records.map! do |record|
|
463
|
+
record.to_h
|
464
|
+
end
|
465
|
+
|
466
|
+
records.should == [@data[4]]
|
467
|
+
end
|
430
468
|
end
|
431
469
|
|
432
470
|
describe "not" do
|
data/sql_query_executor.gemspec
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
|
2
|
+
require File.expand_path('../lib/sql_query_executor/version.rb', __FILE__)
|
3
3
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
5
|
gem.authors = ["Caio Torres"]
|
6
6
|
gem.email = ["efreesen@gmail.com"]
|
7
|
-
gem.description = %q{Gem to run SQL like queries on array of hashes}
|
8
|
-
gem.summary = %q{With SqlQueryExecutor you can run SQL like queries on any array of hashes}
|
7
|
+
gem.description = %q{Gem to run SQL like queries on array of hashes or similar objects}
|
8
|
+
gem.summary = %q{With SqlQueryExecutor you can run SQL like queries on any array of hashes or similar objects}
|
9
9
|
gem.homepage = "http://github.com/efreesen/sql_query_executor"
|
10
10
|
|
11
11
|
gem.files = `git ls-files`.split($\)
|
12
12
|
gem.test_files = gem.files.grep(%r{^(spec)/})
|
13
13
|
gem.name = "sql_query_executor"
|
14
14
|
gem.require_paths = ["lib"]
|
15
|
-
gem.version =
|
15
|
+
gem.version = SqlQueryExecutor::VERSION
|
16
16
|
gem.license = "GPLv2"
|
17
17
|
gem.files = [
|
18
18
|
"LICENSE",
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sql_query_executor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Caio Torres
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-02-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -52,7 +52,7 @@ dependencies:
|
|
52
52
|
- - '>='
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
-
description: Gem to run SQL like queries on array of hashes
|
55
|
+
description: Gem to run SQL like queries on array of hashes or similar objects
|
56
56
|
email:
|
57
57
|
- efreesen@gmail.com
|
58
58
|
executables: []
|
@@ -69,10 +69,9 @@ files:
|
|
69
69
|
- lib/sql_query_executor/operators/in.rb
|
70
70
|
- lib/sql_query_executor/operators/is.rb
|
71
71
|
- lib/sql_query_executor/query/base.rb
|
72
|
-
- lib/sql_query_executor/query/
|
73
|
-
- lib/sql_query_executor/query/executor.rb
|
72
|
+
- lib/sql_query_executor/query/sentence.rb
|
74
73
|
- lib/sql_query_executor/query/sub_query.rb
|
75
|
-
- lib/sql_query_executor/version
|
74
|
+
- lib/sql_query_executor/version.rb
|
76
75
|
- lib/sql_query_executor.rb
|
77
76
|
- Gemfile
|
78
77
|
- spec/sql_query_executor/base_spec.rb
|
@@ -100,6 +99,7 @@ rubygems_version: 2.0.14
|
|
100
99
|
signing_key:
|
101
100
|
specification_version: 4
|
102
101
|
summary: With SqlQueryExecutor you can run SQL like queries on any array of hashes
|
102
|
+
or similar objects
|
103
103
|
test_files:
|
104
104
|
- Gemfile
|
105
105
|
- spec/sql_query_executor/base_spec.rb
|
@@ -1,56 +0,0 @@
|
|
1
|
-
require 'sql_query_executor/query/sub_query'
|
2
|
-
|
3
|
-
module SqlQueryExecutor
|
4
|
-
module Query
|
5
|
-
class Divider
|
6
|
-
BINDING_OPERATORS = ['and', 'or']
|
7
|
-
|
8
|
-
class << self
|
9
|
-
def divide(query, collection)
|
10
|
-
@query = query
|
11
|
-
divide_query(collection)
|
12
|
-
end
|
13
|
-
|
14
|
-
private
|
15
|
-
# Splits the first sub query from the rest of the query and returns it.
|
16
|
-
def divide_query(collection)
|
17
|
-
array = @query.split(" ")
|
18
|
-
operator = array[1].downcase
|
19
|
-
|
20
|
-
sub_query = get_sub_array(operator, array)
|
21
|
-
remaining_query = @query.gsub(sub_query, '').strip
|
22
|
-
|
23
|
-
sub_query = SqlQueryExecutor::Query::SubQuery.new(sub_query, collection)
|
24
|
-
|
25
|
-
return sub_query, remaining_query == '' ? nil : remaining_query
|
26
|
-
end
|
27
|
-
|
28
|
-
def get_sub_array(operator, array)
|
29
|
-
result = case operator
|
30
|
-
when "between"
|
31
|
-
array[0..4]
|
32
|
-
when "is"
|
33
|
-
size = array[2] == "not" ? 3 : 2
|
34
|
-
array[0..size]
|
35
|
-
when "not"
|
36
|
-
array[0..3]
|
37
|
-
else
|
38
|
-
array[0..2]
|
39
|
-
end
|
40
|
-
|
41
|
-
result = fix_array(array, result)
|
42
|
-
|
43
|
-
result.join(' ')
|
44
|
-
end
|
45
|
-
|
46
|
-
def fix_array(array, result)
|
47
|
-
if BINDING_OPERATORS.include?(result.first)
|
48
|
-
array[0..result.size]
|
49
|
-
else
|
50
|
-
result
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
require 'sql_query_executor/query/divider'
|
2
|
-
|
3
|
-
module SqlQueryExecutor
|
4
|
-
module Query
|
5
|
-
class Executor
|
6
|
-
class << self
|
7
|
-
def execute!(query, collection, data=[])
|
8
|
-
sub_query, remaining_query = SqlQueryExecutor::Query::Divider.divide(query, collection)
|
9
|
-
|
10
|
-
result = sub_query.execute!(data)
|
11
|
-
|
12
|
-
remaining_query.nil? ? result.sort_by{ |r| r.id } : execute!(remaining_query, collection, result)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|