sql_query_executor 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c42f0a76b148c57bbe10c04654bbd6380cab657b
4
- data.tar.gz: c653b58ffc9a847922c2b8b1e3d88463b9b46e84
3
+ metadata.gz: 1ff8930d2561d2c1093c10f8027ac682025034ae
4
+ data.tar.gz: 9045d8b249a633ae530be73a3dc2b7ba29effac3
5
5
  SHA512:
6
- metadata.gz: 48ef44419b5509ff76af6e617370350dbb7167892f0f85283d1cbd465b8349bff384319aced176870d8fbc4e42fa38ca83e8a5dc2568e2739d9170e150cd218a
7
- data.tar.gz: 2000259b6d0931d496a8757c0f4619f185609f64d741a99d44d7451cc4a41f094a06bd2fe81334bf5cc73ec807ce79d1aedfc51e0fa07f15bb032f1ac5165089
6
+ metadata.gz: aa8d67868b67353de090839b61c5b8c847cbc4d28ec552b3b11ca85378cf49f2666002013cd7cd0a121d0f0e6d595448f699f3fe5fcfade389e9be9334a9a77c
7
+ data.tar.gz: 03413bc22a1e936bec0eac260f8e0ba7d39f0decce5f0442f535204b3509a3587834feb04a015622f6192b9eef28df13c76be9bbc097f38cf4f1c035608a669b
@@ -1,34 +1,54 @@
1
1
  require 'ostruct'
2
- require 'sql_query_executor/query/base'
2
+ require 'sql_query_executor/query/query_normalizer'
3
3
  require 'sql_query_executor/query/sub_query'
4
4
 
5
5
  # Simulates a SQL where clause to filter objects from the database
6
6
  module SqlQueryExecutor #:nodoc:
7
7
  class Base #:nodoc:
8
- def initialize(collection=[])
9
- @collection = []
10
-
11
- if collection.any? && collection.first.is_a?(Hash)
12
- convert_collection(collection)
13
- else
14
- @collection = conforming_collection?(collection) ? collection : []
15
- end
16
- end
8
+ STRING_SPACE = "$SS$"
9
+ QUERY_SPACE = "$QS$"
10
+ TEMP_SPACE = "$TS$"
17
11
 
18
- # Recursive method that divides the query in sub queries, executes each part individually
19
- # and finally relates its results as specified in the query.
20
- def where(*query)
21
- query = query.first if query.respond_to?(:size) && query.size == 1
12
+ def initialize(collection, query)
13
+ query = query.first if query.respond_to?(:size) && query.size == 1 && !query.is_a?(Hash)
22
14
 
23
15
  message = check_query(query)
24
16
  raise ArgumentError.new(message) if message
25
17
 
26
- query = SqlQueryExecutor::Query::Base.new(query, @collection)
27
- query.execute!
18
+ get_collection(collection)
19
+ query = Query::QueryNormalizer.execute(query)
20
+ @query = SqlQueryExecutor::Query::SubQuery.new query, @collection
21
+ end
22
+
23
+ def execute!
24
+ @query.execute!
25
+ end
26
+
27
+ def to_sql
28
+ @query.to_sql
29
+ end
30
+
31
+ def selector
32
+ @query.selector
33
+ end
34
+
35
+ # Recursive method that divides the query in sub queries, executes each part individually
36
+ # and finally relates its results as specified in the query.
37
+ def self.where(collection, *query)
38
+ self.new(collection, query).execute!
28
39
  end
29
40
 
30
41
  private
42
+ def get_collection(collection)
43
+ if collection.any? && collection.first.is_a?(Hash)
44
+ convert_collection(collection)
45
+ else
46
+ @collection = conforming_collection?(collection) ? collection : []
47
+ end
48
+ end
49
+
31
50
  def convert_collection(collection)
51
+ @collection = []
32
52
  collection.each do |object|
33
53
  attributes = object.is_a?(Hash) ? object : object.attributes
34
54
  register = OpenStruct.new(attributes)
@@ -1,10 +1,12 @@
1
+ require 'sql_query_executor/base'
2
+
1
3
  module SqlQueryExecutor
2
4
  module Operators
3
5
  class Base
4
6
  def initialize(query, collection)
5
- @query = sanitize_query(query)
7
+ @query = SqlQueryExecutor::Query::QueryNormalizer.execute(query).gsub(SqlQueryExecutor::Base::QUERY_SPACE, ' ')
6
8
  @collection = collection
7
- @array = query.split(' ')
9
+ @array = @query.split(' ')
8
10
  @operator = @query.split(' ')[1]
9
11
  @field = get_field
10
12
  @value = get_value
@@ -20,7 +22,7 @@ module SqlQueryExecutor
20
22
  end
21
23
 
22
24
  def get_value
23
- value = @array.last.gsub(SqlQueryExecutor::Query::Base::STRING_SPACE, ' ')
25
+ value = @array.last.gsub(SqlQueryExecutor::Base::STRING_SPACE, ' ')
24
26
 
25
27
  convert_value(value)
26
28
  end
@@ -32,21 +34,13 @@ module SqlQueryExecutor
32
34
  methods = {3 => "convert_date", 7 => "convert_time"}
33
35
 
34
36
  array = split(value)
35
-
37
+
36
38
  value = (send(methods[array.size], array) || value) if methods.keys.include?(array.size)
37
39
 
38
40
  value
39
41
  end
40
42
 
41
43
  private
42
- def sanitize_query(query)
43
- params = query.scan(/(\(.*?\))/).flatten.compact
44
-
45
- params.each { |param| query.gsub!(param, param.gsub(" ", "")) }
46
-
47
- query
48
- end
49
-
50
44
  def is_a_number?(value)
51
45
  value.to_s == value.to_i.to_s
52
46
  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!(result)
6
+ def execute!
7
7
  @collection.select do |record|
8
8
  value = convert_value(record.send(@field).to_s)
9
9
 
@@ -26,8 +26,8 @@ module SqlQueryExecutor
26
26
  def get_value
27
27
  value = []
28
28
 
29
- value << convert_value(@array[2].gsub(SqlQueryExecutor::Query::Base::STRING_SPACE, ' '))
30
- value << convert_value(@array[4].gsub(SqlQueryExecutor::Query::Base::STRING_SPACE, ' '))
29
+ value << convert_value(@array[2].gsub(SqlQueryExecutor::Base::STRING_SPACE, ' '))
30
+ value << convert_value(@array[4].gsub(SqlQueryExecutor::Base::STRING_SPACE, ' '))
31
31
  end
32
32
  end
33
33
  end
@@ -17,7 +17,7 @@ module SqlQueryExecutor
17
17
  convert_operator
18
18
  end
19
19
 
20
- def execute!(result)
20
+ def execute!
21
21
  @collection.select do |record|
22
22
  value = record.send(@field.to_s)
23
23
 
@@ -28,7 +28,7 @@ module SqlQueryExecutor
28
28
  def selector
29
29
  operator = SELECTORS[@operator]
30
30
 
31
- { @field.to_sym => operator ? {operator => @value} : @value}
31
+ { @field => operator ? {operator => @value} : @value}
32
32
  end
33
33
 
34
34
  private
@@ -3,7 +3,7 @@ require 'sql_query_executor/operators/base'
3
3
  module SqlQueryExecutor
4
4
  module Operators
5
5
  class In < SqlQueryExecutor::Operators::Base
6
- def execute!(result)
6
+ def execute!
7
7
  result = @collection.select do |record|
8
8
  value = record.send(@field)
9
9
 
@@ -19,7 +19,7 @@ module SqlQueryExecutor
19
19
  def get_value
20
20
  value = super
21
21
 
22
- value.gsub(SqlQueryExecutor::Query::Base::STRING_SPACE, '').split(',').map &:strip
22
+ value.gsub(SqlQueryExecutor::Base::STRING_SPACE, '').split(',').map{ |v| convert_value(v) }
23
23
  end
24
24
  end
25
25
  end
@@ -8,17 +8,21 @@ module SqlQueryExecutor
8
8
  convert_operator
9
9
  end
10
10
 
11
- def execute!(result)
11
+ def execute!
12
12
  @collection.select do |record|
13
13
  value = record.send(@field)
14
14
 
15
- value.send(@operator, nil)
15
+ value.send(@operator, @value)
16
16
  end
17
17
  end
18
18
 
19
+ def selector
20
+ @operator == '==' ? { @field => @value } : { @field => {'$ne' => @value} }
21
+ end
22
+
19
23
  private
20
24
  def get_value
21
- @array.include?('null') ? 'nil' : @array.last
25
+ @array.include?('null') ? nil : convert_value(@array.last)
22
26
  end
23
27
 
24
28
  def convert_operator
@@ -4,19 +4,17 @@ module SqlQueryExecutor
4
4
  module Query
5
5
  class QueryNormalizer
6
6
  class << self
7
- CONVERT_METHODS = {"String" => ["get_query", ""], "Array" => ["interpolate_query", "query.flatten"], "Hash" => ["concatenate_hash", "query"]}
7
+ CONVERT_METHODS = {"String" => "get_query", "Array" => "interpolate_query", "Hash" => "concatenate_hash"}
8
8
 
9
9
  def execute(query)
10
10
  query = clean_query_attribute(query)
11
- array = CONVERT_METHODS[query.class.name]
11
+ method = CONVERT_METHODS[query.class.name]
12
12
 
13
- query = sanitize(send(array.first, query))
13
+ query = sanitize(send(method, query))
14
14
  end
15
15
 
16
16
  def clean_query(query)
17
- query = execute(query)
18
-
19
- remove_placeholders(query)
17
+ remove_placeholders execute(query)
20
18
  end
21
19
 
22
20
  private
@@ -84,6 +82,7 @@ module SqlQueryExecutor
84
82
  end
85
83
 
86
84
  def remove_spaces(query)
85
+ query.gsub!(",#{Base::QUERY_SPACE}", ',')
87
86
  query.gsub!(/\[.*?\]/) { |substr| substr.gsub(' ', '') }
88
87
  query
89
88
  end
@@ -91,14 +90,16 @@ module SqlQueryExecutor
91
90
  # Returns converted #param based on its Class, so it can be used on the query
92
91
  def convert_param(param)
93
92
  case param.class.name
93
+ when "NilClass"
94
+ nil
94
95
  when "String"
95
- param = "'#{param}'".gsub("''", "'").gsub('""', '"')
96
+ "'#{param}'".gsub("''", "'").gsub('""', '"')
96
97
  when "Date"
97
- param = "'#{param.strftime("%Y-%m-%d")}'"
98
+ "'#{param.strftime("%Y-%m-%d")}'"
98
99
  when "Time"
99
- param = "'#{param.strftime("%Y-%m-%d %H:%M:%S %z")}'"
100
+ "'#{param.strftime("%Y-%m-%d %H:%M:%S %z")}'"
100
101
  else
101
- param = param.to_s
102
+ param.to_s
102
103
  end
103
104
  end
104
105
 
@@ -109,14 +110,15 @@ module SqlQueryExecutor
109
110
 
110
111
  query.each do |key, value|
111
112
  if value.is_a?(Array)
112
- if [:and, :or].include?(key)
113
+ if ['$and', '$or'].include?(key)
114
+ key = key.gsub('$', '')
113
115
  queries = []
114
116
 
115
117
  value.each do |hash|
116
118
  queries << concatenate_hash(hash)
117
119
  end
118
120
 
119
- query_array << queries.join(" #{key.to_s} ")
121
+ query_array << "(#{queries.join(" #{key.to_s} ")})"
120
122
  else
121
123
  value = value.first.is_a?(Numeric) ? value : value.map{ |v| "'#{v}'" }
122
124
  query_array << "#{key} in (#{value.join(',')})"
@@ -130,11 +132,12 @@ module SqlQueryExecutor
130
132
  value = convert_param(value.values.first)
131
133
  end
132
134
 
133
- value = "#{convert_param(value)}"
134
- query_array << "#{key} #{operator} #{value}"
135
+ value = convert_param(value)
136
+ query_array << (value.nil? ? "#{key} is null" : "#{key} #{operator} #{value}")
135
137
  end
136
138
  end
137
139
 
140
+
138
141
  query_array.join(" and ")
139
142
  end
140
143
  end
@@ -6,7 +6,7 @@ require 'sql_query_executor/operators/in'
6
6
  module SqlQueryExecutor
7
7
  module Query
8
8
  class Sentence
9
- attr_reader :query, :operator
9
+ attr_reader :query
10
10
 
11
11
  OPERATORS = {
12
12
  "between" => SqlQueryExecutor::Operators::Between,
@@ -31,10 +31,11 @@ module SqlQueryExecutor
31
31
  set_operator
32
32
  end
33
33
 
34
- def execute!(data)
34
+ # The data parameter is only declared for SubQuery compatibility purposes
35
+ def execute!(data=[])
35
36
  return [] unless @operator
36
37
 
37
- @operator.execute!(data)
38
+ @operator.execute!
38
39
  end
39
40
 
40
41
  def selector
@@ -1,3 +1,3 @@
1
1
  module SqlQueryExecutor
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -1,527 +1,91 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  require 'sql_query_executor'
4
+ require 'sql_query_executor/base'
4
5
 
5
- describe SqlQueryExecutor, "Base" do
6
- before do
7
- @data = []
8
-
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
- end
15
-
16
- subject { SqlQueryExecutor::Base.new(@data) }
17
-
18
- describe "initialize" do
19
- before do
20
- class Model
21
- attr_reader :attributes
22
-
23
- def initialize(attributes)
24
- @attributes = attributes
25
- end
26
-
27
- def id
28
- @attributes[:id]
29
- end
30
- end
31
-
32
- class Collection
33
- def initialize(collection)
34
- @collection = []
35
-
36
- collection.each do |hash|
37
- @collection << Model.new(hash)
38
- end
39
- end
40
-
41
- def all
42
- @collection
43
- end
44
- end
45
- end
46
-
47
- subject { SqlQueryExecutor::Base.new(Collection.new(@data).all) }
48
-
49
- it 'initializes with a conforming collection' do
50
- expect(subject.where(id: 1).first.attributes).to eq (@data.first)
51
- end
52
- end
53
-
6
+ describe SqlQueryExecutor::Base do
54
7
  describe ".where" do
55
- context "when invalid query is passed" do
56
- it "raises an ArgumentError" do
57
- query = [{name: "John"}]
58
-
59
- expect { subject.where(query) }.to raise_error(ArgumentError, "First element from array must be a String. eg: [\"name = ?\", \"John\"]")
60
- end
61
- end
62
-
63
- describe "=" do
64
- context "when attribute is string" do
65
- it "matches a record" do
66
- record = subject.where("name = 'US'")
67
- record.size.should == 1
68
- record.first.id.should == 1
69
- record.first.name.should == 'US'
70
- end
71
-
72
- it "doesn't match any record" do
73
- record = subject.where("name = 'Argentina'")
74
- record.count.should == 0
75
- record.should == []
76
- end
77
- end
78
-
79
- context "when attribute is integer" do
80
- it "matches a record" do
81
- record = subject.where("id = 1")
82
- record.count.should == 1
83
- record.first.id.should == 1
84
- record.first.name.should == 'US'
85
- end
86
-
87
- it "doesn't match any record" do
88
- record = subject.where("id = 43")
89
- record.count.should == 0
90
- record.should == []
91
- end
92
- end
93
-
94
- context "when attribute is datetime" do
95
- it "matches a record" do
96
- record = subject.where("founded_at = ?", Time.parse('1500-04-22 13:34:25'))
97
- record.count.should == 1
98
- record.first.id.should == 5
99
- record.first.name.should == 'Brazil'
100
- end
101
-
102
- it "doesn't match any record" do
103
- record = subject.where("id = ?", Time.parse('1500-09-07 13:34:25'))
104
- record.count.should == 0
105
- record.should == []
106
- end
107
- end
8
+ let(:data) do
9
+ [
10
+ {id: 1, name: "US", language: 'English'},
11
+ {id: 2, name: "Canada", language: 'English', monarch: "The Crown of England"},
12
+ {id: 3, name: "Mexico", language: 'Spanish'},
13
+ {id: 4, name: "UK", language: 'English', monarch: "The Crown of England"},
14
+ {id: 5, name: "Brazil", founded_at: Time.parse('1500-04-22 13:34:25')}
15
+ ]
108
16
  end
109
17
 
110
- describe ">" do
111
- context "when attribute is a string" do
112
- it "matches a record" do
113
- records = subject.where("name > 'T'")
114
- records.count.should == 2
115
- records.first.id.should == 1
18
+ context 'conforming collection' do
19
+ before do
20
+ class Model
21
+ attr_reader :attributes
116
22
 
117
- records.map! do |record|
118
- record.to_h
23
+ def initialize(attributes)
24
+ @attributes = attributes
119
25
  end
120
26
 
121
- records.should == [@data[0], @data[3]]
122
- end
123
-
124
- it "doesn't match any record" do
125
- record = subject.where("name > 'Z'")
126
- record.count.should == 0
127
- record.should == []
128
- end
129
- end
130
-
131
- context "when attribute is integer" do
132
- it "matches a record" do
133
- records = subject.where("id > 3")
134
- records.count.should == 2
135
- records.first.id.should == 4
136
-
137
- records.map! do |record|
138
- record.to_h
27
+ def id
28
+ @attributes[:id]
139
29
  end
140
-
141
- records.should == [@data[3], @data[4]]
142
30
  end
143
31
 
144
- it "doesn't match any record" do
145
- record = subject.where("id > 5")
146
- record.count.should == 0
147
- record.should == []
148
- end
149
- end
150
-
151
- context "when attribute is datetime" do
152
- it "matches a record" do
153
- record = subject.where("founded_at > ?", Time.parse('1500-04-20 13:34:25'))
154
- record.count.should == 1
155
- record.first.id.should == 5
156
- record.first.name.should == 'Brazil'
157
- end
158
-
159
- it "doesn't match any record" do
160
- record = subject.where("founded_at > ?", Time.parse('1500-04-23 13:34:25'))
161
- record.count.should == 0
162
- record.should == []
163
- end
164
- end
165
- end
166
-
167
- describe ">=" do
168
- context "when attribute is a string" do
169
- it "matches a record" do
170
- records = subject.where("name >= 'U'")
171
- records.count.should == 2
172
- records.first.id.should == 1
32
+ class Collection
33
+ def initialize(collection)
34
+ @collection = []
173
35
 
174
- records.map! do |record|
175
- record.to_h
36
+ collection.each do |hash|
37
+ @collection << Model.new(hash)
38
+ end
176
39
  end
177
40
 
178
- records.should == [@data[0], @data[3]]
179
- end
180
-
181
- it "doesn't match any record" do
182
- record = subject.where("name >= 'Z'")
183
- record.count.should == 0
184
- record.should == []
185
- end
186
- end
187
-
188
- context "when attribute is integer" do
189
- it "matches a record" do
190
- records = subject.where("id >= 4")
191
- records.count.should == 2
192
- records.first.id.should == 4
193
-
194
- records.map! do |record|
195
- record.to_h
41
+ def all
42
+ @collection
196
43
  end
197
-
198
- records.should == [@data[3], @data[4]]
199
- end
200
-
201
- it "doesn't match any record" do
202
- record = subject.where("id >= 6")
203
- record.count.should == 0
204
- record.should == []
205
44
  end
206
45
  end
207
46
 
208
- context "when attribute is datetime" do
209
- it "matches a record" do
210
- record = subject.where("founded_at >= ?", Time.parse('1500-04-22 13:34:25'))
211
- record.count.should == 1
212
- record.first.id.should == 5
213
- record.first.name.should == 'Brazil'
214
- end
215
-
216
- it "doesn't match any record" do
217
- record = subject.where("founded_at >= ?", Time.parse('1500-04-23 13:34:25'))
218
- record.count.should == 0
219
- record.should == []
220
- end
221
- end
222
- end
223
-
224
- describe "<" do
225
- context "when attribute is a string" do
226
- it "matches a record" do
227
- records = subject.where("name < 'C'")
228
- records.count.should == 1
229
- records.first.id.should == 5
230
-
231
- records.map! do |record|
232
- record.to_h
233
- end
234
-
235
- records.should == [@data[4]]
236
- end
237
-
238
- it "doesn't match any record" do
239
- record = subject.where("name < 'B'")
240
- record.count.should == 0
241
- record.should == []
242
- end
47
+ it 'initializes with a conforming collection' do
48
+ expect(described_class.where(Collection.new(data).all, id: 1).first.attributes).to eq (data.first)
243
49
  end
50
+
51
+ context "when invalid query is passed" do
52
+ it "raises an ArgumentError" do
53
+ query = [{name: "John"}]
244
54
 
245
- context "when attribute is integer" do
246
- it "matches a record" do
247
- records = subject.where("id < 3")
248
- records.count.should == 2
249
- records.first.id.should == 1
250
-
251
- records.map! do |record|
252
- record.to_h
253
- end
254
-
255
- records.should == [@data[0], @data[1]]
256
- end
257
-
258
- it "doesn't match any record" do
259
- record = subject.where("id < 1")
260
- record.count.should == 0
261
- record.should == []
262
- end
263
- end
264
-
265
- context "when attribute is datetime" do
266
- it "matches a record" do
267
- record = subject.where("founded_at < ?", Time.parse('1500-04-22 13:34:26'))
268
- record.count.should == 1
269
- record.first.id.should == 5
270
- record.first.name.should == 'Brazil'
271
- end
272
-
273
- it "doesn't match any record" do
274
- record = subject.where("founded_at < ?", Time.parse('1500-04-22 13:34:25'))
275
- record.count.should == 0
276
- record.should == []
55
+ expect { described_class.where(Collection.new(data).all, query) }.to raise_error(ArgumentError, "First element from array must be a String. eg: [\"name = ?\", \"John\"]")
277
56
  end
278
57
  end
279
58
  end
280
59
 
281
- describe "<=" do
282
- context "when attribute is a string" do
283
- it "matches a record" do
284
- records = subject.where("name <= 'Brb'")
285
- records.count.should == 1
286
- records.first.id.should == 5
287
-
288
- records.map! do |record|
289
- record.to_h
290
- end
291
-
292
- records.should == [@data[4]]
293
- end
294
-
295
- it "doesn't match any record" do
296
- record = subject.where("name <= 'A'")
297
- record.count.should == 0
298
- record.should == []
299
- end
300
- end
301
-
302
- context "when attribute is integer" do
303
- it "matches a record" do
304
- records = subject.where("id <= 2")
305
- records.count.should == 2
306
- records.first.id.should == 1
307
-
308
- records.map! do |record|
309
- record.to_h
310
- end
311
-
312
- records.should == [@data[0], @data[1]]
313
- end
314
-
315
- it "doesn't match any record" do
316
- record = subject.where("id <= 0")
317
- record.count.should == 0
318
- record.should == []
319
- end
320
- end
321
-
322
- context "when attribute is datetime" do
323
- it "matches a record" do
324
- record = subject.where("founded_at <= ?", Time.parse('1500-04-22 13:34:25'))
325
- record.count.should == 1
326
- record.first.id.should == 5
327
- record.first.name.should == 'Brazil'
328
- end
329
-
330
- it "doesn't match any record" do
331
- record = subject.where("founded_at <= ?", Time.parse('1500-04-22 13:34:24'))
332
- record.count.should == 0
333
- record.should == []
334
- end
335
- end
336
- end
337
-
338
- describe "between" do
339
- context "when attribute is a string" do
340
- it "matches a record" do
341
- records = subject.where("name between 'A' and 'C'")
342
- records.count.should == 1
343
- records.first.id.should == 5
344
-
345
- records.map! do |record|
346
- record.to_h
347
- end
348
-
349
- records.should == [@data[4]]
350
- end
351
-
352
- it "doesn't match any record" do
353
- record = subject.where("name between 'K' and 'M'")
354
- record.count.should == 0
355
- record.should == []
356
- end
357
- end
358
-
359
- context "when attribute is integer" do
360
- it "matches a record" do
361
- records = subject.where("id between 1 and 2")
362
- records.count.should == 2
363
- records.first.id.should == 1
364
-
365
- records.map! do |record|
366
- record.to_h
367
- end
368
-
369
- records.should == [@data[0], @data[1]]
370
- end
371
-
372
- it "doesn't match any record" do
373
- record = subject.where("id between 6 and 10")
374
- record.count.should == 0
375
- record.should == []
376
- end
377
- end
378
-
379
- context "when attribute is datetime" do
380
- it "matches a record" do
381
- record = subject.where("founded_at between ? and ?", Time.parse('1500-04-22 13:34:24'), Time.parse('1500-04-22 13:34:26'))
382
- record.count.should == 1
383
- record.first.id.should == 5
384
- record.first.name.should == 'Brazil'
385
- end
386
-
387
- it "doesn't match any record" do
388
- record = subject.where("founded_at between ? and ?", Time.parse('1500-04-22 13:34:26'), Time.parse('1500-09-22 13:34:25'))
389
- record.count.should == 0
390
- record.should == []
391
- end
392
- end
393
- end
394
-
395
- describe "is" do
396
- it "attribute is condition" do
397
- records = subject.where("founded_at is null")
398
- records.count.should == 4
399
- records.first.id.should == 1
400
-
401
- records.map! do |record|
402
- record.to_h
403
- end
404
-
405
- records.should == [@data[0], @data[1], @data[2], @data[3]]
60
+ context 'not conforming collection' do
61
+ it 'initializes with a conforming collection' do
62
+ expect(described_class.where(data, id: 1)).to eq([OpenStruct.new(data.first)])
406
63
  end
64
+
65
+ context "when invalid query is passed" do
66
+ it "raises an ArgumentError" do
67
+ query = [{name: "John"}]
407
68
 
408
- it "attribute is not condition" do
409
- id = @data.last[:id]
410
- records = subject.where("founded_at is not null")
411
- records.count.should == 1
412
- records.first.id.should == id
413
-
414
- records.map! do |record|
415
- record.to_h
69
+ expect { described_class.where(data, query) }.to raise_error(ArgumentError, "First element from array must be a String. eg: [\"name = ?\", \"John\"]")
416
70
  end
417
-
418
- records.should == [@data[id-1]]
419
71
  end
420
72
  end
421
73
 
422
- describe "and" do
423
- it "attribute and condition" do
424
- records = subject.where("language = 'English' and monarch = 'The Crown of England'")
425
- records.count.should == 2
426
- records.first.id.should == 2
427
-
428
- records.map! do |record|
429
- record.to_h
430
- end
431
-
432
- records.should == [@data[1], @data[3]]
433
- end
434
-
435
- it "integer attribute and condition" do
436
- records = subject.where("id = 2 and language = 'English'")
437
- records.count.should == 1
438
- records.first.id.should == 2
74
+ context 'selector' do
75
+ let(:query) { 'id > 3' }
76
+ let(:selector) { {'id' => {'$gt' => 3}} }
439
77
 
440
- records.map! do |record|
441
- record.to_h
442
- end
443
-
444
- records.should == [@data[1]]
78
+ it 'converts query' do
79
+ expect(described_class.new([], query).selector).to eq selector
445
80
  end
446
81
  end
447
82
 
448
- describe "or" do
449
- it "attribute or condition" do
450
- records = subject.where("language = 'English' or language = 'Spanish'")
451
- records.count.should == 4
452
- records.first.id.should == 1
453
-
454
- records.map! do |record|
455
- record.to_h
456
- end
457
-
458
- records.should == [@data[0], @data[1], @data[2], @data[3]]
459
- end
460
-
461
- context "nested queries" do
462
- it "respects priority" do
463
- records = subject.where("(language = 'English' and name = 'US') or (language is null)")
464
- records.count.should == 2
465
- records.first.id.should == 1
466
-
467
- records.map! do |record|
468
- record.to_h
469
- end
470
-
471
- records.should == [@data[0], @data[4]]
472
- end
473
-
474
- it "respects priority" do
475
- records = subject.where("(language is null) or (language = 'English' and name = 'US')")
476
- records.count.should == 2
477
- records.first.id.should == 1
478
-
479
- records.map! do |record|
480
- record.to_h
481
- end
482
-
483
- records.should == [@data[0], @data[4]]
484
- end
485
- end
486
- end
487
-
488
- describe "in" do
489
- it "attribute in condition" do
490
- records = subject.where("language in ('English', 'Spanish')")
491
- records.count.should == 4
492
- records.first.id.should == 1
493
-
494
- records.map! do |record|
495
- record.to_h
496
- end
497
-
498
- records.should == [@data[0], @data[1], @data[2], @data[3]]
499
- end
500
-
501
- xit "attribute not in condition" do
502
- records = subject.where("language not in ('English', 'Spanish')")
503
- records.count.should == 1
504
- records.first.id.should == 5
505
-
506
- records.map! do |record|
507
- record.to_h
508
- end
509
-
510
- records.should == [@data[4]]
511
- end
512
- end
513
-
514
- describe "not" do
515
- xit "attribute not condition" do
516
- records = subject.where("not language = 'English'")
517
- records.count.should == 1
518
- records.first.id.should == 5
519
-
520
- records.map! do |record|
521
- record.to_h
522
- end
83
+ context 'to_sql' do
84
+ let(:query) { "name = 'Brazil'" }
85
+ let(:selector) { {name: 'Brazil'} }
523
86
 
524
- records.should == [@data[4]]
87
+ it 'converts selector' do
88
+ expect(described_class.new([], selector).to_sql).to eq query
525
89
  end
526
90
  end
527
91
  end
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.2.0
4
+ version: 0.3.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-03-05 00:00:00.000000000 Z
11
+ date: 2014-03-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -68,7 +68,6 @@ files:
68
68
  - lib/sql_query_executor/operators/default.rb
69
69
  - lib/sql_query_executor/operators/in.rb
70
70
  - lib/sql_query_executor/operators/is.rb
71
- - lib/sql_query_executor/query/base.rb
72
71
  - lib/sql_query_executor/query/query_normalizer.rb
73
72
  - lib/sql_query_executor/query/sentence.rb
74
73
  - lib/sql_query_executor/query/sub_query.rb
@@ -1,28 +0,0 @@
1
- require 'sql_query_executor/query/query_normalizer'
2
-
3
- module SqlQueryExecutor
4
- module Query
5
- class Base
6
- STRING_SPACE = "$SS$"
7
- QUERY_SPACE = "$QS$"
8
- TEMP_SPACE = "$TS$"
9
-
10
- def initialize(query, collection)
11
- query = QueryNormalizer.execute(query)
12
- @query = SqlQueryExecutor::Query::SubQuery.new query, collection
13
- end
14
-
15
- def execute!
16
- @query.execute!
17
- end
18
-
19
- def to_sql
20
- @query.to_sql
21
- end
22
-
23
- def selector
24
- @query.selector
25
- end
26
- end
27
- end
28
- end