oedipus 0.0.1.pre1 → 0.0.1.pre2
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.
- data/.gitignore +2 -0
- data/README.md +235 -44
- data/Rakefile +25 -0
- data/ext/oedipus/extconf.rb +72 -0
- data/ext/oedipus/oedipus.c +239 -0
- data/ext/oedipus/oedipus.h +50 -0
- data/lib/oedipus/comparison/between.rb +26 -0
- data/lib/oedipus/comparison/equal.rb +21 -0
- data/lib/oedipus/comparison/gt.rb +21 -0
- data/lib/oedipus/comparison/gte.rb +21 -0
- data/lib/oedipus/comparison/in.rb +21 -0
- data/lib/oedipus/comparison/lt.rb +21 -0
- data/lib/oedipus/comparison/lte.rb +21 -0
- data/lib/oedipus/comparison/not.rb +25 -0
- data/lib/oedipus/comparison/not_equal.rb +21 -0
- data/lib/oedipus/comparison/not_in.rb +21 -0
- data/lib/oedipus/comparison/outside.rb +26 -0
- data/lib/oedipus/comparison/shortcuts.rb +144 -0
- data/lib/oedipus/comparison.rb +88 -0
- data/lib/oedipus/connection.rb +91 -13
- data/lib/oedipus/connection_error.rb +14 -0
- data/lib/oedipus/index.rb +189 -46
- data/lib/oedipus/query_builder.rb +97 -4
- data/lib/oedipus/version.rb +1 -1
- data/lib/oedipus.rb +24 -7
- data/oedipus.gemspec +4 -5
- data/spec/integration/connection_spec.rb +58 -0
- data/spec/integration/index_spec.rb +353 -0
- data/spec/spec_helper.rb +2 -23
- data/spec/support/test_harness.rb +30 -9
- data/spec/unit/comparison/between_spec.rb +36 -0
- data/spec/unit/comparison/equal_spec.rb +22 -0
- data/spec/unit/comparison/gt_spec.rb +22 -0
- data/spec/unit/comparison/gte_spec.rb +22 -0
- data/spec/unit/comparison/in_spec.rb +22 -0
- data/spec/unit/comparison/lt_spec.rb +22 -0
- data/spec/unit/comparison/lte_spec.rb +22 -0
- data/spec/unit/comparison/not_equal_spec.rb +22 -0
- data/spec/unit/comparison/not_in_spec.rb +22 -0
- data/spec/unit/comparison/not_spec.rb +37 -0
- data/spec/unit/comparison/outside_spec.rb +36 -0
- data/spec/unit/comparison/shortcuts_spec.rb +125 -0
- data/spec/unit/comparison_spec.rb +109 -0
- data/spec/unit/query_builder_spec.rb +150 -0
- metadata +68 -19
- data/lib/oedipus/mysql/client.rb +0 -136
- data/spec/unit/connection_spec.rb +0 -36
- data/spec/unit/index_spec.rb +0 -85
@@ -0,0 +1,353 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
##
|
4
|
+
# Oedipus Sphinx 2 Search.
|
5
|
+
# Copyright © 2012 Chris Corbyn.
|
6
|
+
#
|
7
|
+
# See LICENSE file for details.
|
8
|
+
##
|
9
|
+
|
10
|
+
require "spec_helper"
|
11
|
+
|
12
|
+
describe Oedipus::Index do
|
13
|
+
include Oedipus::TestHarness
|
14
|
+
|
15
|
+
let(:conn) { Oedipus::Connection.new(searchd_host) }
|
16
|
+
let(:index) { Oedipus::Index.new(:posts_rt, conn) }
|
17
|
+
|
18
|
+
describe "#insert" do
|
19
|
+
context "with valid data" do
|
20
|
+
it "returns the number of rows inserted" do
|
21
|
+
index.insert(
|
22
|
+
10,
|
23
|
+
title: "Badgers",
|
24
|
+
body: "They live in setts, do badgers.",
|
25
|
+
views: 721,
|
26
|
+
user_id: 7
|
27
|
+
).should == 1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "with invalid data" do
|
32
|
+
it "raises an error" do
|
33
|
+
expect {
|
34
|
+
index.insert(
|
35
|
+
10,
|
36
|
+
bad_field: "Invalid",
|
37
|
+
body: "They live in setts, do badgers.",
|
38
|
+
views: 721,
|
39
|
+
user_id: 7
|
40
|
+
)
|
41
|
+
}.to raise_error(Oedipus::ConnectionError)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#fetch" do
|
47
|
+
before(:each) do
|
48
|
+
index.insert(1, title: "Badgers and foxes", views: 150)
|
49
|
+
index.insert(2, title: "Rabbits and hares", views: 73)
|
50
|
+
index.insert(3, title: "Clowns and cannon girls", views: 1)
|
51
|
+
end
|
52
|
+
|
53
|
+
context "with a valid document ID" do
|
54
|
+
it "returns the matched document" do
|
55
|
+
index.fetch(2).should == { id: 2, views: 73, user_id: 0, status: "" }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "with a bad document ID" do
|
60
|
+
it "returns nil" do
|
61
|
+
index.fetch(7).should be_nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#update" do
|
67
|
+
before(:each) do
|
68
|
+
index.insert(1, title: "Badgers and foxes", views: 150, user_id: 7)
|
69
|
+
end
|
70
|
+
|
71
|
+
context "with valid data" do
|
72
|
+
it "returns the number of rows modified" do
|
73
|
+
index.update(1, views: 721).should == 1
|
74
|
+
end
|
75
|
+
|
76
|
+
it "modifies the data" do
|
77
|
+
index.update(1, views: 721)
|
78
|
+
index.fetch(1).should == { id: 1, views: 721, user_id: 7, status: "" }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "with unmatched data" do
|
83
|
+
it "returns 0" do
|
84
|
+
index.update(3, views: 721).should == 0
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context "with invalid data" do
|
89
|
+
it "raises an error" do
|
90
|
+
expect {
|
91
|
+
index.update(1, bad_field: "Invalid", views: 721)
|
92
|
+
}.to raise_error(Oedipus::ConnectionError)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "#replace" do
|
98
|
+
before(:each) do
|
99
|
+
index.insert(
|
100
|
+
1,
|
101
|
+
title: "Badgers",
|
102
|
+
body: "They live in setts, do badgers.",
|
103
|
+
views: 721,
|
104
|
+
user_id: 7
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
context "with valid existing data" do
|
109
|
+
it "returns the number of rows inserted" do
|
110
|
+
index.replace(1, title: "Badgers and foxes", views: 150).should == 1
|
111
|
+
end
|
112
|
+
|
113
|
+
it "entirely replaces the record" do
|
114
|
+
index.replace(1, title: "Badgers and foxes", views: 150)
|
115
|
+
index.fetch(1).should == { id: 1, views: 150, user_id: 0, status: "" }
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context "with valid new data" do
|
120
|
+
it "returns the number of rows inserted" do
|
121
|
+
index.replace(2, title: "Beer and wine", views: 15).should == 1
|
122
|
+
end
|
123
|
+
|
124
|
+
it "entirely replaces the record" do
|
125
|
+
index.replace(2, title: "Beer and wine", views: 15)
|
126
|
+
index.fetch(2).should == { id: 2, views: 15, user_id: 0, status: "" }
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context "with invalid data" do
|
131
|
+
it "raises an error" do
|
132
|
+
expect {
|
133
|
+
index.replace(1, bad_field: "Badgers and foxes", views: 150)
|
134
|
+
}.to raise_error(Oedipus::ConnectionError)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "#search" do
|
140
|
+
before(:each) do
|
141
|
+
index.insert(1, title: "Badgers and foxes", views: 150)
|
142
|
+
index.insert(2, title: "Rabbits and hares", views: 87)
|
143
|
+
index.insert(3, title: "Badgers in the wild", views: 41)
|
144
|
+
index.insert(4, title: "Badgers for all!", views: 3003)
|
145
|
+
end
|
146
|
+
|
147
|
+
context "by fulltext matching" do
|
148
|
+
it "indicates the number of records found" do
|
149
|
+
index.search("badgers")[:total_found].should == 3
|
150
|
+
end
|
151
|
+
|
152
|
+
it "includes the matches records" do
|
153
|
+
index.search("badgers")[:records].should == [
|
154
|
+
{ id: 1, views: 150, user_id: 0, status: "" },
|
155
|
+
{ id: 3, views: 41, user_id: 0, status: "" },
|
156
|
+
{ id: 4, views: 3003, user_id: 0, status: "" }
|
157
|
+
]
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
context "by attribute filtering" do
|
162
|
+
it "indicates the number of records found" do
|
163
|
+
index.search(views: 40..90)[:total_found].should == 2
|
164
|
+
end
|
165
|
+
|
166
|
+
it "includes the matches records" do
|
167
|
+
index.search(views: 40..90)[:records].should == [
|
168
|
+
{ id: 2, views: 87, user_id: 0, status: "" },
|
169
|
+
{ id: 3, views: 41, user_id: 0, status: "" }
|
170
|
+
]
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
context "by fulltext with attribute filtering" do
|
175
|
+
it "indicates the number of records found" do
|
176
|
+
index.search("badgers", views: Oedipus.gt(100))[:total_found].should == 2
|
177
|
+
end
|
178
|
+
|
179
|
+
it "includes the matches records" do
|
180
|
+
index.search("badgers", views: Oedipus.gt(100))[:records].should == [
|
181
|
+
{ id: 1, views: 150, user_id: 0, status: "" },
|
182
|
+
{ id: 4, views: 3003, user_id: 0, status: "" }
|
183
|
+
]
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
context "with limits" do
|
188
|
+
it "still indicates the number of records found" do
|
189
|
+
index.search("badgers", limit: 2)[:total_found].should == 3
|
190
|
+
end
|
191
|
+
|
192
|
+
it "returns the limited subset of the results" do
|
193
|
+
index.search("badgers", limit: 2)[:records].should == [
|
194
|
+
{ id: 1, views: 150, user_id: 0, status: "" },
|
195
|
+
{ id: 3, views: 41, user_id: 0, status: "" }
|
196
|
+
]
|
197
|
+
end
|
198
|
+
|
199
|
+
it "can use an offset" do
|
200
|
+
index.search("badgers", limit: 1, offset: 1)[:records].should == [
|
201
|
+
{ id: 3, views: 41, user_id: 0, status: "" }
|
202
|
+
]
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
context "with ordering" do
|
207
|
+
it "returns the results ordered accordingly" do
|
208
|
+
index.search("badgers", order: {views: :desc})[:records].should == [
|
209
|
+
{ id: 4, views: 3003, user_id: 0, status: "" },
|
210
|
+
{ id: 1, views: 150, user_id: 0, status: "" },
|
211
|
+
{ id: 3, views: 41, user_id: 0, status: "" },
|
212
|
+
]
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
describe "#multi_search" do
|
218
|
+
before(:each) do
|
219
|
+
index.insert(1, title: "Badgers and foxes", views: 150, user_id: 1)
|
220
|
+
index.insert(2, title: "Rabbits and hares", views: 87, user_id: 1)
|
221
|
+
index.insert(3, title: "Badgers in the wild", views: 41, user_id: 2)
|
222
|
+
index.insert(4, title: "Badgers for all!", views: 3003, user_id: 1)
|
223
|
+
end
|
224
|
+
|
225
|
+
context "by fulltext querying" do
|
226
|
+
it "indicates the number of results for each query" do
|
227
|
+
results = index.multi_search(
|
228
|
+
badgers: "badgers",
|
229
|
+
rabbits: "rabbits"
|
230
|
+
)
|
231
|
+
results[:badgers][:total_found].should == 3
|
232
|
+
results[:rabbits][:total_found].should == 1
|
233
|
+
end
|
234
|
+
|
235
|
+
it "returns the records for each search" do
|
236
|
+
results = index.multi_search(
|
237
|
+
badgers: "badgers",
|
238
|
+
rabbits: "rabbits"
|
239
|
+
)
|
240
|
+
results[:badgers][:records].should == [
|
241
|
+
{ id: 1, views: 150, user_id: 1, status: "" },
|
242
|
+
{ id: 3, views: 41, user_id: 2, status: "" },
|
243
|
+
{ id: 4, views: 3003, user_id: 1, status: "" }
|
244
|
+
]
|
245
|
+
results[:rabbits][:records].should == [
|
246
|
+
{ id: 2, views: 87, user_id: 1, status: "" }
|
247
|
+
]
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
context "by attribute filtering" do
|
252
|
+
it "indicates the number of results for each query" do
|
253
|
+
results = index.multi_search(
|
254
|
+
shiela: {user_id: 1},
|
255
|
+
barry: {user_id: 2}
|
256
|
+
)
|
257
|
+
results[:shiela][:total_found].should == 3
|
258
|
+
results[:barry][:total_found].should == 1
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
describe "#faceted_search" do
|
264
|
+
before(:each) do
|
265
|
+
index.insert(1, title: "Badgers and foxes", body: "Badgers", views: 150, user_id: 1)
|
266
|
+
index.insert(2, title: "Rabbits and hares", body: "Rabbits", views: 87, user_id: 1)
|
267
|
+
index.insert(3, title: "Badgers in the wild", body: "Test", views: 41, user_id: 2)
|
268
|
+
index.insert(4, title: "Badgers for all!", body: "For all", views: 3003, user_id: 1)
|
269
|
+
end
|
270
|
+
|
271
|
+
context "with additional attribute filters" do
|
272
|
+
let(:results) do
|
273
|
+
index.faceted_search(
|
274
|
+
"badgers",
|
275
|
+
facets: {
|
276
|
+
popular: {views: Oedipus.gte(50)},
|
277
|
+
di_carla: {user_id: 2}
|
278
|
+
}
|
279
|
+
)
|
280
|
+
end
|
281
|
+
|
282
|
+
it "returns the main results in the top-level" do
|
283
|
+
results[:records].should == [
|
284
|
+
{ id: 1, views: 150, user_id: 1, status: "" },
|
285
|
+
{ id: 3, views: 41, user_id: 2, status: "" },
|
286
|
+
{ id: 4, views: 3003, user_id: 1, status: "" }
|
287
|
+
]
|
288
|
+
end
|
289
|
+
|
290
|
+
it "applies the filters on top of the base query" do
|
291
|
+
results[:facets][:popular][:records].should == [
|
292
|
+
{ id: 1, views: 150, user_id: 1, status: "" },
|
293
|
+
{ id: 4, views: 3003, user_id: 1, status: "" }
|
294
|
+
]
|
295
|
+
results[:facets][:di_carla][:records].should == [
|
296
|
+
{ id: 3, views: 41, user_id: 2, status: "" }
|
297
|
+
]
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
context "with overriding attribute filters" do
|
302
|
+
let(:results) do
|
303
|
+
index.faceted_search(
|
304
|
+
"badgers",
|
305
|
+
user_id: 1,
|
306
|
+
facets: {
|
307
|
+
di_carla: {user_id: 2}
|
308
|
+
}
|
309
|
+
)
|
310
|
+
end
|
311
|
+
|
312
|
+
it "applies the filters on top of the base query" do
|
313
|
+
results[:facets][:di_carla][:records].should == [
|
314
|
+
{ id: 3, views: 41, user_id: 2, status: "" }
|
315
|
+
]
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
context "with overriding overriding fulltext queries" do
|
320
|
+
let(:results) do
|
321
|
+
index.faceted_search(
|
322
|
+
"badgers",
|
323
|
+
facets: {
|
324
|
+
rabbits: "rabbits"
|
325
|
+
}
|
326
|
+
)
|
327
|
+
end
|
328
|
+
|
329
|
+
it "entirely replaces the base query" do
|
330
|
+
results[:facets][:rabbits][:records].should == [
|
331
|
+
{ id: 2, views: 87, user_id: 1, status: "" }
|
332
|
+
]
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
context "with overriding refined fulltext queries" do
|
337
|
+
let(:results) do
|
338
|
+
index.faceted_search(
|
339
|
+
"badgers",
|
340
|
+
facets: {
|
341
|
+
in_body: "@body (%{query})"
|
342
|
+
}
|
343
|
+
)
|
344
|
+
end
|
345
|
+
|
346
|
+
it "merges the queries" do
|
347
|
+
results[:facets][:in_body][:records].should == [
|
348
|
+
{ id: 1, views: 150, user_id: 1, status: "" },
|
349
|
+
]
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -7,33 +7,12 @@
|
|
7
7
|
# See LICENSE file for details.
|
8
8
|
##
|
9
9
|
|
10
|
-
require "rspec"
|
11
10
|
require "bundler/setup"
|
11
|
+
|
12
|
+
require "rspec"
|
12
13
|
require "oedipus"
|
13
14
|
|
14
15
|
Dir[File.expand_path("../support/**/*rb", __FILE__)].each { |f| require f }
|
15
16
|
|
16
17
|
RSpec.configure do |config|
|
17
|
-
include Oedipus::TestHarness
|
18
|
-
|
19
|
-
config.before(:suite) do
|
20
|
-
unless ENV.key?("SEARCHD")
|
21
|
-
raise "You must specify a path to the Sphinx 'searchd' executable (>= 2.0.2)"
|
22
|
-
end
|
23
|
-
|
24
|
-
set_data_dir File.expand_path("../data", __FILE__)
|
25
|
-
set_searchd ENV["SEARCHD"]
|
26
|
-
|
27
|
-
prepare_data_dirs
|
28
|
-
write_sphinx_conf
|
29
|
-
start_searchd
|
30
|
-
end
|
31
|
-
|
32
|
-
config.before(:each) do
|
33
|
-
empty_indexes
|
34
|
-
end
|
35
|
-
|
36
|
-
config.after(:suite) do
|
37
|
-
stop_searchd
|
38
|
-
end
|
39
18
|
end
|
@@ -8,8 +8,33 @@
|
|
8
8
|
##
|
9
9
|
|
10
10
|
module Oedipus
|
11
|
-
# Mixed into RSpec suites to manage starting/stopping Sphinx.
|
11
|
+
# Mixed into RSpec suites to manage starting/stopping Sphinx and writing indexes.
|
12
12
|
module TestHarness
|
13
|
+
class << self
|
14
|
+
def included(base)
|
15
|
+
base.before(:all) do
|
16
|
+
unless ENV.key?("SEARCHD")
|
17
|
+
raise "You must specify a path to the Sphinx 'searchd' executable (>= 2.0.2)"
|
18
|
+
end
|
19
|
+
|
20
|
+
set_data_dir File.expand_path("../../data", __FILE__)
|
21
|
+
set_searchd ENV["SEARCHD"]
|
22
|
+
|
23
|
+
prepare_data_dirs
|
24
|
+
write_sphinx_conf
|
25
|
+
start_searchd
|
26
|
+
end
|
27
|
+
|
28
|
+
base.before(:each) do
|
29
|
+
empty_indexes
|
30
|
+
end
|
31
|
+
|
32
|
+
base.after(:all) do
|
33
|
+
stop_searchd
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
13
38
|
# Set the path to the searchd executable.
|
14
39
|
#
|
15
40
|
# The version of Sphinx must be >= 2.0.2.
|
@@ -37,15 +62,11 @@ module Oedipus
|
|
37
62
|
end
|
38
63
|
|
39
64
|
def empty_indexes
|
40
|
-
|
41
|
-
@conn ||= ::Mysql.new(searchd_host[:host], nil, nil, nil, searchd_host[:port])
|
42
|
-
|
43
|
-
idxs = @conn.query("SHOW TABLES")
|
65
|
+
@conn ||= Oedipus::Connection.new(host: searchd_host[:host], port: searchd_host[:port])
|
44
66
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
@conn.query("DELETE FROM #{idx['Index']} WHERE id = #{hash['id']}")
|
67
|
+
@conn.query("SHOW TABLES").each do |idx|
|
68
|
+
@conn.query("SELECT id FROM #{idx['Index']}").each do |hash|
|
69
|
+
@conn.execute("DELETE FROM #{idx['Index']} WHERE id = #{hash['id']}")
|
49
70
|
end
|
50
71
|
end
|
51
72
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
##
|
4
|
+
# Oedipus Sphinx 2 Search.
|
5
|
+
# Copyright © 2012 Chris Corbyn.
|
6
|
+
#
|
7
|
+
# See LICENSE file for details.
|
8
|
+
##
|
9
|
+
|
10
|
+
require "spec_helper"
|
11
|
+
|
12
|
+
describe Oedipus::Comparison::Between do
|
13
|
+
context "with an inclusive range" do
|
14
|
+
let(:comparison) { Oedipus::Comparison::Between.new(42..100) }
|
15
|
+
|
16
|
+
it "draws as BETWEEN x AND y" do
|
17
|
+
comparison.to_s.should == "BETWEEN 42 AND 100"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "inverses as NOT BETWEEN x AND y" do
|
21
|
+
comparison.inverse.to_s.should == "NOT BETWEEN 42 AND 100"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "with an exclusive range" do
|
26
|
+
let(:comparison) { Oedipus::Comparison::Between.new(42...100) }
|
27
|
+
|
28
|
+
it "draws as BETWEEN x AND y-1" do
|
29
|
+
comparison.to_s.should == "BETWEEN 42 AND 99"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "inverses as NOT BETWEEN x AND y-1" do
|
33
|
+
comparison.inverse.to_s.should == "NOT BETWEEN 42 AND 99"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
##
|
4
|
+
# Oedipus Sphinx 2 Search.
|
5
|
+
# Copyright © 2012 Chris Corbyn.
|
6
|
+
#
|
7
|
+
# See LICENSE file for details.
|
8
|
+
##
|
9
|
+
|
10
|
+
require "spec_helper"
|
11
|
+
|
12
|
+
describe Oedipus::Comparison::Equal do
|
13
|
+
let(:comparison) { Oedipus::Comparison::Equal.new('test') }
|
14
|
+
|
15
|
+
it "draws as = v" do
|
16
|
+
comparison.to_s.should == "= 'test'"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "inverses as != v" do
|
20
|
+
comparison.inverse.to_s.should == "!= 'test'"
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
##
|
4
|
+
# Oedipus Sphinx 2 Search.
|
5
|
+
# Copyright © 2012 Chris Corbyn.
|
6
|
+
#
|
7
|
+
# See LICENSE file for details.
|
8
|
+
##
|
9
|
+
|
10
|
+
require "spec_helper"
|
11
|
+
|
12
|
+
describe Oedipus::Comparison::GT do
|
13
|
+
let(:comparison) { Oedipus::Comparison::GT.new(42) }
|
14
|
+
|
15
|
+
it "draws as > v" do
|
16
|
+
comparison.to_s.should == "> 42"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "inverses as <= v" do
|
20
|
+
comparison.inverse.to_s.should == "<= 42"
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
##
|
4
|
+
# Oedipus Sphinx 2 Search.
|
5
|
+
# Copyright © 2012 Chris Corbyn.
|
6
|
+
#
|
7
|
+
# See LICENSE file for details.
|
8
|
+
##
|
9
|
+
|
10
|
+
require "spec_helper"
|
11
|
+
|
12
|
+
describe Oedipus::Comparison::GTE do
|
13
|
+
let(:comparison) { Oedipus::Comparison::GTE.new(42) }
|
14
|
+
|
15
|
+
it "draws as >= v" do
|
16
|
+
comparison.to_s.should == ">= 42"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "inverses as < v" do
|
20
|
+
comparison.inverse.to_s.should == "< 42"
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
##
|
4
|
+
# Oedipus Sphinx 2 Search.
|
5
|
+
# Copyright © 2012 Chris Corbyn.
|
6
|
+
#
|
7
|
+
# See LICENSE file for details.
|
8
|
+
##
|
9
|
+
|
10
|
+
require "spec_helper"
|
11
|
+
|
12
|
+
describe Oedipus::Comparison::In do
|
13
|
+
let(:comparison) { Oedipus::Comparison::In.new([1, 2, 3]) }
|
14
|
+
|
15
|
+
it "draws as IN (x, y, z)" do
|
16
|
+
comparison.to_s.should == "IN (1, 2, 3)"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "inverses as NOT IN (x, y, z)" do
|
20
|
+
comparison.inverse.to_s.should == "NOT IN (1, 2, 3)"
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
##
|
4
|
+
# Oedipus Sphinx 2 Search.
|
5
|
+
# Copyright © 2012 Chris Corbyn.
|
6
|
+
#
|
7
|
+
# See LICENSE file for details.
|
8
|
+
##
|
9
|
+
|
10
|
+
require "spec_helper"
|
11
|
+
|
12
|
+
describe Oedipus::Comparison::LT do
|
13
|
+
let(:comparison) { Oedipus::Comparison::LT.new(42) }
|
14
|
+
|
15
|
+
it "draws as < v" do
|
16
|
+
comparison.to_s.should == "< 42"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "inverses as >= v" do
|
20
|
+
comparison.inverse.to_s.should == ">= 42"
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
##
|
4
|
+
# Oedipus Sphinx 2 Search.
|
5
|
+
# Copyright © 2012 Chris Corbyn.
|
6
|
+
#
|
7
|
+
# See LICENSE file for details.
|
8
|
+
##
|
9
|
+
|
10
|
+
require "spec_helper"
|
11
|
+
|
12
|
+
describe Oedipus::Comparison::LTE do
|
13
|
+
let(:comparison) { Oedipus::Comparison::LTE.new(42) }
|
14
|
+
|
15
|
+
it "draws as <= v" do
|
16
|
+
comparison.to_s.should == "<= 42"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "inverses as > v" do
|
20
|
+
comparison.inverse.to_s.should == "> 42"
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
##
|
4
|
+
# Oedipus Sphinx 2 Search.
|
5
|
+
# Copyright © 2012 Chris Corbyn.
|
6
|
+
#
|
7
|
+
# See LICENSE file for details.
|
8
|
+
##
|
9
|
+
|
10
|
+
require "spec_helper"
|
11
|
+
|
12
|
+
describe Oedipus::Comparison::NotEqual do
|
13
|
+
let(:comparison) { Oedipus::Comparison::NotEqual.new('test') }
|
14
|
+
|
15
|
+
it "draws as != v" do
|
16
|
+
comparison.to_s.should == "!= 'test'"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "inverses as = v" do
|
20
|
+
comparison.inverse.to_s.should == "= 'test'"
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
##
|
4
|
+
# Oedipus Sphinx 2 Search.
|
5
|
+
# Copyright © 2012 Chris Corbyn.
|
6
|
+
#
|
7
|
+
# See LICENSE file for details.
|
8
|
+
##
|
9
|
+
|
10
|
+
require "spec_helper"
|
11
|
+
|
12
|
+
describe Oedipus::Comparison::NotIn do
|
13
|
+
let(:comparison) { Oedipus::Comparison::NotIn.new([1, 2, 3]) }
|
14
|
+
|
15
|
+
it "draws as NOT IN (x, y, z)" do
|
16
|
+
comparison.to_s.should == "NOT IN (1, 2, 3)"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "inverses as IN (x, y, z)" do
|
20
|
+
comparison.inverse.to_s.should == "IN (1, 2, 3)"
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
##
|
4
|
+
# Oedipus Sphinx 2 Search.
|
5
|
+
# Copyright © 2012 Chris Corbyn.
|
6
|
+
#
|
7
|
+
# See LICENSE file for details.
|
8
|
+
##
|
9
|
+
|
10
|
+
require "spec_helper"
|
11
|
+
|
12
|
+
describe Oedipus::Comparison::In do
|
13
|
+
context "with a non-comparison" do
|
14
|
+
let(:comparison) { Oedipus::Comparison::Not.new(0..10) }
|
15
|
+
|
16
|
+
it "converts to a comparison" do
|
17
|
+
comparison.v.should be_a_kind_of(Oedipus::Comparison)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "returns the comparison as its inverse" do
|
21
|
+
comparison.inverse.should == comparison.v
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "with a comparison" do
|
26
|
+
let(:original) { Oedipus::Comparison::GTE.new(7) }
|
27
|
+
let(:comparison) { Oedipus::Comparison::Not.new(original) }
|
28
|
+
|
29
|
+
it "draws as the inverse of the comparison" do
|
30
|
+
comparison.to_s.should == original.inverse.to_s
|
31
|
+
end
|
32
|
+
|
33
|
+
it "inverses as the original" do
|
34
|
+
comparison.inverse.to_s == original.to_s
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|