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,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::Outside do
|
13
|
+
context "with an inclusive range" do
|
14
|
+
let(:comparison) { Oedipus::Comparison::Outside.new(42..100) }
|
15
|
+
|
16
|
+
it "draws as NOT BETWEEN x AND y" do
|
17
|
+
comparison.to_s.should == "NOT BETWEEN 42 AND 100"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "inverses as BETWEEN x AND y" do
|
21
|
+
comparison.inverse.to_s.should == "BETWEEN 42 AND 100"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "with an exclusive range" do
|
26
|
+
let(:comparison) { Oedipus::Comparison::Outside.new(42...100) }
|
27
|
+
|
28
|
+
it "draws as NOT BETWEEN x AND y-1" do
|
29
|
+
comparison.to_s.should == "NOT BETWEEN 42 AND 99"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "inverses as BETWEEN x AND y-1" do
|
33
|
+
comparison.inverse.to_s.should == "BETWEEN 42 AND 99"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,125 @@
|
|
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::Shortcuts do
|
13
|
+
let(:s) { Object.new.tap { |o| o.extend subject } }
|
14
|
+
|
15
|
+
describe "#eq" do
|
16
|
+
it "returns the = comparison for v" do
|
17
|
+
s.eq(7).should == Oedipus::Comparison::Equal.new(7)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#neq" do
|
22
|
+
it "returns the != comparison for v" do
|
23
|
+
s.neq(7).should == Oedipus::Comparison::NotEqual.new(7)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
describe "#not" do
|
29
|
+
it "returns the NOT comparison for v" do
|
30
|
+
s.not(7).should == Oedipus::Comparison::Not.new(7)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#gt" do
|
35
|
+
it "returns the > comparison for v" do
|
36
|
+
s.gt(7).should == Oedipus::Comparison::GT.new(7)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#lt" do
|
41
|
+
it "returns the < comparison for v" do
|
42
|
+
s.lt(7).should == Oedipus::Comparison::LT.new(7)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#gte" do
|
47
|
+
it "returns the >= comparison for v" do
|
48
|
+
s.gte(7).should == Oedipus::Comparison::GTE.new(7)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#lte" do
|
53
|
+
it "returns the <= comparison for v" do
|
54
|
+
s.lte(7).should == Oedipus::Comparison::LTE.new(7)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#between" do
|
59
|
+
context "with a range" do
|
60
|
+
it "returns the BETWEEN comparison for v" do
|
61
|
+
s.between(7..11).should == Oedipus::Comparison::Between.new(7..11)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "with two bounds" do
|
66
|
+
it "returns the BETWEEN comparison for x and y" do
|
67
|
+
s.between(7, 11).should == Oedipus::Comparison::Between.new(7..11)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "#outside" do
|
73
|
+
context "with a range" do
|
74
|
+
it "returns the NOT BETWEEN comparison for v" do
|
75
|
+
s.outside(7..11).should == Oedipus::Comparison::Outside.new(7..11)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "with two bounds" do
|
80
|
+
it "returns the NOT BETWEEN comparison for x and y" do
|
81
|
+
s.outside(7, 11).should == Oedipus::Comparison::Outside.new(7..11)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "#in" do
|
87
|
+
context "with an array" do
|
88
|
+
it "returns the IN comparison for v" do
|
89
|
+
s.in([1, 2, 3]).should == Oedipus::Comparison::In.new([1, 2, 3])
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "with a range" do
|
94
|
+
it "returns the IN comparison for v" do
|
95
|
+
s.in(1..3).should == Oedipus::Comparison::In.new([1, 2, 3])
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context "with a variable arguments" do
|
100
|
+
it "returns the IN comparison for x, y, z" do
|
101
|
+
s.in(1, 2, 3).should == Oedipus::Comparison::In.new([1, 2, 3])
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "#not_in" do
|
107
|
+
context "with an array" do
|
108
|
+
it "returns the NOT IN comparison for v" do
|
109
|
+
s.not_in([1, 2, 3]).should == Oedipus::Comparison::NotIn.new([1, 2, 3])
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context "with a range" do
|
114
|
+
it "returns the NOT IN comparison for v" do
|
115
|
+
s.not_in(1..3).should == Oedipus::Comparison::NotIn.new([1, 2, 3])
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context "with a variable arguments" do
|
120
|
+
it "returns the NOT IN comparison for x, y, z" do
|
121
|
+
s.not_in(1, 2, 3).should == Oedipus::Comparison::NotIn.new([1, 2, 3])
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,109 @@
|
|
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 do
|
13
|
+
subject { Oedipus::Comparison }
|
14
|
+
|
15
|
+
describe "#of" do
|
16
|
+
context "with a comparison" do
|
17
|
+
it "returns the comparison" do
|
18
|
+
subject.of(
|
19
|
+
Oedipus::Comparison::Equal.new(7)
|
20
|
+
).should == Oedipus::Comparison::Equal.new(7)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "with a Fixnum" do
|
25
|
+
it "returns an Equal comparison" do
|
26
|
+
subject.of(7).should == Oedipus::Comparison::Equal.new(7)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "with a Float" do
|
31
|
+
it "returns an Equal comparison" do
|
32
|
+
subject.of(7.2).should == Oedipus::Comparison::Equal.new(7.2)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "with a BigDecimal" do
|
37
|
+
it "returns an Equal comparison" do
|
38
|
+
subject.of(BigDecimal("7.2")).should == Oedipus::Comparison::Equal.new(7.2)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "with a Rational" do
|
43
|
+
it "returns an Equal comparison" do
|
44
|
+
subject.of(Rational("1/3")).should == Oedipus::Comparison::Equal.new(Rational("1/3").to_f)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "with a String" do
|
49
|
+
it "returns an Equal comparison" do
|
50
|
+
subject.of("test").should == Oedipus::Comparison::Equal.new("test")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "with a Symbol" do
|
55
|
+
it "returns an Equal comparison" do
|
56
|
+
subject.of(:test).should == Oedipus::Comparison::Equal.new(:test)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "with a range" do
|
61
|
+
context "starting at -Infinity" do
|
62
|
+
context "inclusive" do
|
63
|
+
it "returns a LTE comparison" do
|
64
|
+
subject.of(-Float::INFINITY..10).should == Oedipus::Comparison::LTE.new(10)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "exclusive" do
|
69
|
+
it "returns a LT comparison" do
|
70
|
+
subject.of(-Float::INFINITY...10).should == Oedipus::Comparison::LT.new(10)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context "ending at -Infinity" do
|
76
|
+
context "inclusive" do
|
77
|
+
it "returns a GTE comparison" do
|
78
|
+
subject.of(10..Float::INFINITY).should == Oedipus::Comparison::GTE.new(10)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "exclusive" do
|
83
|
+
it "returns a GT comparison" do
|
84
|
+
subject.of(10...Float::INFINITY).should == Oedipus::Comparison::GT.new(10)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "of real numbers" do
|
90
|
+
it "returns a BETWEEN comparison" do
|
91
|
+
subject.of(10..20).should == Oedipus::Comparison::Between.new(10..20)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "with an array" do
|
97
|
+
it "returns an IN comparison" do
|
98
|
+
subject.of([1, 2, 3]).should == Oedipus::Comparison::In.new([1, 2, 3])
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context "with an Enumerable type" do
|
103
|
+
it "returns an IN comparison" do
|
104
|
+
require 'set'
|
105
|
+
subject.of(Set[1, 2, 3]).should == Oedipus::Comparison::In.new([1, 2, 3])
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,150 @@
|
|
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::QueryBuilder do
|
13
|
+
let(:builder) { Oedipus::QueryBuilder.new(:posts) }
|
14
|
+
|
15
|
+
describe "#select" do
|
16
|
+
context "with a fulltext search" do
|
17
|
+
it "uses MATCH()" do
|
18
|
+
builder.select("dogs AND cats", {}).should =~ /SELECT .* FROM posts WHERE MATCH\('dogs AND cats'\)/
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "without conditions" do
|
23
|
+
it "does not add a where clause" do
|
24
|
+
builder.select("", {}).should_not =~ /WHERE/
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "with equal attribute filters" do
|
29
|
+
it "uses the '=' operator" do
|
30
|
+
builder.select("dogs", author_id: 7).should =~ /SELECT .* FROM posts WHERE .* author_id = 7/
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "with not equal attribute filters" do
|
35
|
+
it "uses the '!=' operator" do
|
36
|
+
builder.select("dogs", author_id: Oedipus.not(7)).should =~ /SELECT .* FROM posts WHERE .* author_id != 7/
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "with inclusive range-filtered attribute filters" do
|
41
|
+
it "uses the BETWEEN operator" do
|
42
|
+
builder.select("cats", views: 10..20).should =~ /SELECT .* FROM posts WHERE .* views BETWEEN 10 AND 20/
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "with exclusive range-filtered attribute filters" do
|
47
|
+
it "uses the BETWEEN operator" do
|
48
|
+
builder.select("cats", views: 10...20).should =~ /SELECT .* FROM posts WHERE .* views BETWEEN 10 AND 19/
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "with a greater than or equal comparison" do
|
53
|
+
it "uses the >= operator" do
|
54
|
+
builder.select("cats", views: 50..(1/0.0)).should =~ /SELECT .* FROM posts WHERE .* views >= 50/
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "with a greater than comparison" do
|
59
|
+
it "uses the > operator" do
|
60
|
+
builder.select("cats", views: 50...(1/0.0)).should =~ /SELECT .* FROM posts WHERE .* views > 50/
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "with a less than or equal comparison" do
|
65
|
+
it "uses the <= operator" do
|
66
|
+
builder.select("cats", views: -(1/0.0)..50).should =~ /SELECT .* FROM posts WHERE .* views <= 50/
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "with a less than comparison" do
|
71
|
+
it "uses the < operator" do
|
72
|
+
builder.select("cats", views: -(1/0.0)...50).should =~ /SELECT .* FROM posts WHERE .* views < 50/
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "with a negated range comparison" do
|
77
|
+
it "uses the NOT BETWEEN operator" do
|
78
|
+
builder.select("cats", views: Oedipus.not(50..100)).should =~ /SELECT .* FROM posts WHERE .* views NOT BETWEEN 50 AND 100/
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "with an attributed filtered by collection" do
|
83
|
+
it "uses the IN operator" do
|
84
|
+
builder.select("cats", author_id: [7, 11]).should =~ /SELECT .* FROM posts WHERE .* author_id IN \(7, 11\)/
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context "with an attributed filtered by negated collection" do
|
89
|
+
it "uses the NOT IN operator" do
|
90
|
+
builder.select("cats", author_id: Oedipus.not([7, 11])).should =~ /SELECT .* FROM posts WHERE .* author_id NOT IN \(7, 11\)/
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context "with a limit" do
|
95
|
+
it "applies a LIMIT with an offset of 0" do
|
96
|
+
builder.select("dogs", limit: 50).should =~ /SELECT .* FROM posts WHERE .* LIMIT 0, 50/
|
97
|
+
end
|
98
|
+
|
99
|
+
it "is not considered an attribute" do
|
100
|
+
builder.select("dogs", limit: 50).should_not =~ /limit = 50/
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context "with an offset" do
|
105
|
+
it "applies a LIMIT with an offset" do
|
106
|
+
builder.select("dogs", limit: 50, offset: 200).should =~ /SELECT .* FROM posts WHERE .* LIMIT 200, 50/
|
107
|
+
end
|
108
|
+
|
109
|
+
it "is not considered an attribute" do
|
110
|
+
builder.select("dogs", limit: 50, offset: 200).should_not =~ /offset = 200/
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context "with an order clause" do
|
115
|
+
it "applies an ORDER BY" do
|
116
|
+
builder.select("cats", order: {views: :desc}).should =~ /SELECT .* FROM posts WHERE .* ORDER BY views DESC/
|
117
|
+
end
|
118
|
+
|
119
|
+
it "defaults to ASC" do
|
120
|
+
builder.select("cats", order: :views).should =~ /SELECT .* FROM posts WHERE .* ORDER BY views ASC/
|
121
|
+
end
|
122
|
+
|
123
|
+
it "supports multiple orders" do
|
124
|
+
builder.select("cats", order: {views: :asc, author_id: :desc}).should =~ /SELECT .* FROM posts WHERE .* ORDER BY views ASC, author_id DESC/
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe "#insert" do
|
130
|
+
it "includes the ID and the attributes" do
|
131
|
+
builder.insert(3, title: "example", views: 9).should == "INSERT INTO posts (id, title, views) VALUES (3, 'example', 9)"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe "#update" do
|
136
|
+
it "includes the ID in the WHERE clause" do
|
137
|
+
builder.update(3, title: "example", views: 9).should =~ /UPDATE posts SET .* WHERE id = 3/
|
138
|
+
end
|
139
|
+
|
140
|
+
it "includes the changed attributes" do
|
141
|
+
builder.update(3, title: "example", views: 9).should =~ /UPDATE posts SET title = 'example', views = 9/
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe "#replace" do
|
146
|
+
it "includes the ID and the attributes" do
|
147
|
+
builder.replace(3, title: "example", views: 9).should == "REPLACE INTO posts (id, title, views) VALUES (3, 'example', 9)"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oedipus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1.
|
4
|
+
version: 0.0.1.pre2
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,22 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-04-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
16
|
-
requirement: &
|
15
|
+
name: rspec
|
16
|
+
requirement: &22480320 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
21
|
version: '0'
|
22
|
-
type: :
|
22
|
+
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *22480320
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
|
-
name:
|
27
|
-
requirement: &
|
26
|
+
name: rake-compiler
|
27
|
+
requirement: &22479900 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,16 +32,16 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
36
|
-
description: ! "Oedipus brings full support for Sphinx 2 to Ruby:\n\n
|
37
|
-
indexes\n
|
38
|
-
|
39
|
-
|
40
|
-
interface."
|
35
|
+
version_requirements: *22479900
|
36
|
+
description: ! "Oedipus brings full support for Sphinx 2 to Ruby:\n\n * real-time
|
37
|
+
indexes\n * faceted search\n * multi-queries\n * full attribute support\n *
|
38
|
+
optional model-style interaction\n\nIt works with 'stable' versions of Sphinx 2
|
39
|
+
(>= 2.0.2). All\nfeatures are implemented entirely through the SphinxQL interface.\n"
|
41
40
|
email:
|
42
41
|
- chris@w3style.co.uk
|
43
42
|
executables: []
|
44
|
-
extensions:
|
43
|
+
extensions:
|
44
|
+
- ext/oedipus/extconf.rb
|
45
45
|
extra_rdoc_files: []
|
46
46
|
files:
|
47
47
|
- .gitignore
|
@@ -50,18 +50,48 @@ files:
|
|
50
50
|
- LICENSE
|
51
51
|
- README.md
|
52
52
|
- Rakefile
|
53
|
+
- ext/oedipus/extconf.rb
|
54
|
+
- ext/oedipus/oedipus.c
|
55
|
+
- ext/oedipus/oedipus.h
|
53
56
|
- lib/oedipus.rb
|
57
|
+
- lib/oedipus/comparison.rb
|
58
|
+
- lib/oedipus/comparison/between.rb
|
59
|
+
- lib/oedipus/comparison/equal.rb
|
60
|
+
- lib/oedipus/comparison/gt.rb
|
61
|
+
- lib/oedipus/comparison/gte.rb
|
62
|
+
- lib/oedipus/comparison/in.rb
|
63
|
+
- lib/oedipus/comparison/lt.rb
|
64
|
+
- lib/oedipus/comparison/lte.rb
|
65
|
+
- lib/oedipus/comparison/not.rb
|
66
|
+
- lib/oedipus/comparison/not_equal.rb
|
67
|
+
- lib/oedipus/comparison/not_in.rb
|
68
|
+
- lib/oedipus/comparison/outside.rb
|
69
|
+
- lib/oedipus/comparison/shortcuts.rb
|
54
70
|
- lib/oedipus/connection.rb
|
71
|
+
- lib/oedipus/connection_error.rb
|
55
72
|
- lib/oedipus/index.rb
|
56
|
-
- lib/oedipus/mysql/client.rb
|
57
73
|
- lib/oedipus/query_builder.rb
|
58
74
|
- lib/oedipus/version.rb
|
59
75
|
- oedipus.gemspec
|
60
76
|
- spec/data/.gitkeep
|
77
|
+
- spec/integration/connection_spec.rb
|
78
|
+
- spec/integration/index_spec.rb
|
61
79
|
- spec/spec_helper.rb
|
62
80
|
- spec/support/test_harness.rb
|
63
|
-
- spec/unit/
|
64
|
-
- spec/unit/
|
81
|
+
- spec/unit/comparison/between_spec.rb
|
82
|
+
- spec/unit/comparison/equal_spec.rb
|
83
|
+
- spec/unit/comparison/gt_spec.rb
|
84
|
+
- spec/unit/comparison/gte_spec.rb
|
85
|
+
- spec/unit/comparison/in_spec.rb
|
86
|
+
- spec/unit/comparison/lt_spec.rb
|
87
|
+
- spec/unit/comparison/lte_spec.rb
|
88
|
+
- spec/unit/comparison/not_equal_spec.rb
|
89
|
+
- spec/unit/comparison/not_in_spec.rb
|
90
|
+
- spec/unit/comparison/not_spec.rb
|
91
|
+
- spec/unit/comparison/outside_spec.rb
|
92
|
+
- spec/unit/comparison/shortcuts_spec.rb
|
93
|
+
- spec/unit/comparison_spec.rb
|
94
|
+
- spec/unit/query_builder_spec.rb
|
65
95
|
homepage: https://github.com/d11wtq/oedipus
|
66
96
|
licenses: []
|
67
97
|
post_install_message:
|
@@ -86,4 +116,23 @@ rubygems_version: 1.8.11
|
|
86
116
|
signing_key:
|
87
117
|
specification_version: 3
|
88
118
|
summary: Sphinx 2 Search Client for Ruby
|
89
|
-
test_files:
|
119
|
+
test_files:
|
120
|
+
- spec/data/.gitkeep
|
121
|
+
- spec/integration/connection_spec.rb
|
122
|
+
- spec/integration/index_spec.rb
|
123
|
+
- spec/spec_helper.rb
|
124
|
+
- spec/support/test_harness.rb
|
125
|
+
- spec/unit/comparison/between_spec.rb
|
126
|
+
- spec/unit/comparison/equal_spec.rb
|
127
|
+
- spec/unit/comparison/gt_spec.rb
|
128
|
+
- spec/unit/comparison/gte_spec.rb
|
129
|
+
- spec/unit/comparison/in_spec.rb
|
130
|
+
- spec/unit/comparison/lt_spec.rb
|
131
|
+
- spec/unit/comparison/lte_spec.rb
|
132
|
+
- spec/unit/comparison/not_equal_spec.rb
|
133
|
+
- spec/unit/comparison/not_in_spec.rb
|
134
|
+
- spec/unit/comparison/not_spec.rb
|
135
|
+
- spec/unit/comparison/outside_spec.rb
|
136
|
+
- spec/unit/comparison/shortcuts_spec.rb
|
137
|
+
- spec/unit/comparison_spec.rb
|
138
|
+
- spec/unit/query_builder_spec.rb
|
data/lib/oedipus/mysql/client.rb
DELETED
@@ -1,136 +0,0 @@
|
|
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 "socket"
|
11
|
-
require "net/protocol"
|
12
|
-
|
13
|
-
module Oedipus
|
14
|
-
module Mysql
|
15
|
-
# Limited subset of MySQL protocol for communication with SphinxQL.
|
16
|
-
#
|
17
|
-
# This needs to exist since other ruby MySQL clients do not provide the relevant features.
|
18
|
-
class Client
|
19
|
-
# Connect to the SphinxQL server.
|
20
|
-
#
|
21
|
-
# @param [Hash]
|
22
|
-
# a Hash containing :host and :port
|
23
|
-
def initialize(options)
|
24
|
-
@sock = TCPSocket.new(options[:host], options[:port])
|
25
|
-
@seq = 0
|
26
|
-
perform_handshake
|
27
|
-
end
|
28
|
-
|
29
|
-
def execute(sql)
|
30
|
-
p send_packet(query_packet(sql))
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def perform_handshake
|
36
|
-
auth_pkt = clnt_authentication_packet(serv_initialization_packet)
|
37
|
-
raise "Some sort of error" unless send_packet(auth_pkt)[:type] == :ok
|
38
|
-
end
|
39
|
-
|
40
|
-
def incr_seq(seq)
|
41
|
-
raise ProtocolError, "Invalid packet sequence value #{seq} != #{@seq}" unless seq == @seq
|
42
|
-
@seq = (seq + 1) % 256
|
43
|
-
end
|
44
|
-
|
45
|
-
def recv_packet
|
46
|
-
a, b, seq = @sock.read(4).unpack("CvC")
|
47
|
-
incr_seq(seq)
|
48
|
-
@sock.read(a | (b << 8))
|
49
|
-
end
|
50
|
-
|
51
|
-
def send_packet(pkt)
|
52
|
-
while chunk = pkt.read(2**24 - 1)
|
53
|
-
@sock.write([chunk.length % 256, chunk.length / 256, @seq, chunk].pack("CvCZ*"))
|
54
|
-
incr_seq(@seq)
|
55
|
-
end
|
56
|
-
|
57
|
-
serv_result_packet
|
58
|
-
end
|
59
|
-
|
60
|
-
def serv_result_packet
|
61
|
-
pkt = recv_packet
|
62
|
-
case pkt[0]
|
63
|
-
when "\x00" then ok_packet(pkt)
|
64
|
-
else raise ProtocolError, "Unknown packet type #{pkt[0]}"
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def scan_lcb(str)
|
69
|
-
case v = str.slice!(0)
|
70
|
-
when "\xFB" then nil
|
71
|
-
when "\xFC" then str.slice!(0, 2).unpack("v").first
|
72
|
-
when "\xFD"
|
73
|
-
a, b = str.slice!(0, 3).unpack("Cv")
|
74
|
-
a | (b << 8)
|
75
|
-
when "\xFE"
|
76
|
-
a, b = str.slice!(0, 8).unpack("VV")
|
77
|
-
a | (b << 32)
|
78
|
-
else v.ord
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def ok_packet(str)
|
83
|
-
Hash[
|
84
|
-
[
|
85
|
-
:field_count,
|
86
|
-
:affected_rows,
|
87
|
-
:insert_id,
|
88
|
-
:serv_stat,
|
89
|
-
:warning_count,
|
90
|
-
:message
|
91
|
-
].zip([scan_lcb(str), scan_lcb(str), scan_lcb(str)] + str.unpack("vva*"))
|
92
|
-
].tap { |pkt| pkt[:type] = :ok }
|
93
|
-
end
|
94
|
-
|
95
|
-
def serv_initialization_packet
|
96
|
-
Hash[
|
97
|
-
[
|
98
|
-
:prot_ver,
|
99
|
-
:serv_ver,
|
100
|
-
:thread_id,
|
101
|
-
:scramble_buf_a,
|
102
|
-
:filler_a,
|
103
|
-
:serv_cap_a,
|
104
|
-
:serv_enc,
|
105
|
-
:serv_stat,
|
106
|
-
:serv_cap_b,
|
107
|
-
:scramble_len,
|
108
|
-
:filler_b,
|
109
|
-
:scramble_buf_b
|
110
|
-
].zip(recv_packet.unpack("CZ*Va8CvCvvCa10Z*"))
|
111
|
-
].tap do |pkt|
|
112
|
-
raise ProtocolError, "Unsupported MySQL protocol version #{pkt[:prot_ver]}" unless pkt[:prot_ver] == 0x0A
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def clnt_authentication_packet(init_pkt)
|
117
|
-
StringIO.new [
|
118
|
-
197120, # clnt_cap (prot 4.1, multi-stmt, multi-rs)
|
119
|
-
1024**3, # max pkt size
|
120
|
-
0, # charset not used
|
121
|
-
'', # filler 23 bytes
|
122
|
-
'', # username not used
|
123
|
-
'', # scramble buf (no password)
|
124
|
-
'' # dbname not used
|
125
|
-
].pack("VVCa23Z*A*Z*")
|
126
|
-
end
|
127
|
-
|
128
|
-
def query_packet(sql)
|
129
|
-
StringIO.new [
|
130
|
-
0x03, # COM_QUERY type
|
131
|
-
sql
|
132
|
-
].pack("Ca*")
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|