sql_query_executor 0.2.0 → 0.3.0

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 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