sphinx 0.9.9.2117 → 0.9.10
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -3
- data/README.rdoc +18 -213
- data/Rakefile +15 -24
- data/VERSION.yml +1 -2
- data/install.rb +5 -0
- data/lib/sphinx/client.rb +893 -2089
- data/lib/sphinx/request.rb +11 -82
- data/lib/sphinx/response.rb +0 -2
- data/lib/sphinx.rb +5 -50
- data/spec/client_response_spec.rb +40 -33
- data/spec/client_spec.rb +471 -669
- data/spec/fixtures/ranking_sph04.php +9 -0
- data/spec/fixtures/sphinxapi.php +69 -54
- data/spec/sphinx/sphinx-id64.conf +1 -1
- data/spec/sphinx/sphinx.conf +1 -1
- data/spec/sphinx/sphinx_test.sql +2 -4
- data/sphinx.gemspec +8 -13
- data/sphinx.yml.tpl +3 -0
- data/tasks/sphinx.rake +75 -0
- metadata +6 -11
- data/lib/sphinx/buffered_io.rb +0 -26
- data/lib/sphinx/constants.rb +0 -179
- data/lib/sphinx/indifferent_access.rb +0 -152
- data/lib/sphinx/server.rb +0 -170
- data/lib/sphinx/timeout.rb +0 -31
- data/spec/client_validations_spec.rb +0 -859
- data/spec/spec_helper.rb +0 -24
data/lib/sphinx/request.rb
CHANGED
@@ -1,121 +1,50 @@
|
|
1
1
|
module Sphinx
|
2
2
|
# Pack ints, floats, strings, and arrays to internal representation
|
3
3
|
# needed by Sphinx search engine.
|
4
|
-
#
|
5
4
|
class Request
|
6
|
-
# Initialize new
|
7
|
-
#
|
5
|
+
# Initialize new request.
|
8
6
|
def initialize
|
9
7
|
@request = ''
|
10
8
|
end
|
11
|
-
|
9
|
+
|
12
10
|
# Put int(s) to request.
|
13
|
-
#
|
14
|
-
# @param [Integer] ints one or more integers to put to the request.
|
15
|
-
# @return [Request] self.
|
16
|
-
#
|
17
|
-
# @example
|
18
|
-
# request.put_int 10
|
19
|
-
# request.put_int 10, 20, 30
|
20
|
-
# request.put_int *[10, 20, 30]
|
21
|
-
#
|
22
11
|
def put_int(*ints)
|
23
12
|
ints.each { |i| @request << [i].pack('N') }
|
24
|
-
self
|
25
13
|
end
|
26
14
|
|
27
15
|
# Put 64-bit int(s) to request.
|
28
|
-
#
|
29
|
-
# @param [Integer] ints one or more 64-bit integers to put to the request.
|
30
|
-
# @return [Request] self.
|
31
|
-
#
|
32
|
-
# @example
|
33
|
-
# request.put_int64 10
|
34
|
-
# request.put_int64 10, 20, 30
|
35
|
-
# request.put_int64 *[10, 20, 30]
|
36
|
-
#
|
37
16
|
def put_int64(*ints)
|
38
17
|
ints.each { |i| @request << [i].pack('q').reverse }#[i >> 32, i & ((1 << 32) - 1)].pack('NN') }
|
39
|
-
self
|
40
18
|
end
|
41
19
|
|
42
|
-
# Put
|
43
|
-
#
|
44
|
-
# @param [String] strings one or more strings to put to the request.
|
45
|
-
# @return [Request] self.
|
46
|
-
#
|
47
|
-
# @example
|
48
|
-
# request.put_string 'str1'
|
49
|
-
# request.put_string 'str1', 'str2', 'str3'
|
50
|
-
# request.put_string *['str1', 'str2', 'str3']
|
51
|
-
#
|
20
|
+
# Put string(s) to request (first length, then the string itself).
|
52
21
|
def put_string(*strings)
|
53
22
|
strings.each { |s| @request << [s.length].pack('N') + s }
|
54
|
-
self
|
55
23
|
end
|
56
|
-
|
24
|
+
|
57
25
|
# Put float(s) to request.
|
58
|
-
#
|
59
|
-
# @param [Integer, Float] floats one or more floats to put to the request.
|
60
|
-
# @return [Request] self.
|
61
|
-
#
|
62
|
-
# @example
|
63
|
-
# request.put_float 10
|
64
|
-
# request.put_float 10, 20, 30
|
65
|
-
# request.put_float *[10, 20, 30]
|
66
|
-
#
|
67
26
|
def put_float(*floats)
|
68
27
|
floats.each do |f|
|
69
|
-
t1 = [f
|
28
|
+
t1 = [f].pack('f') # machine order
|
70
29
|
t2 = t1.unpack('L*').first # int in machine order
|
71
30
|
@request << [t2].pack('N')
|
72
31
|
end
|
73
|
-
self
|
74
32
|
end
|
75
|
-
|
76
|
-
# Put array of ints to request
|
77
|
-
#
|
78
|
-
# @param [Array<Integer>] arr an array of integers to put to the request.
|
79
|
-
# @return [Request] self.
|
80
|
-
#
|
81
|
-
# @example
|
82
|
-
# request.put_int_array [10]
|
83
|
-
# request.put_int_array [10, 20, 30]
|
84
|
-
#
|
33
|
+
|
34
|
+
# Put array of ints to request (first length, then the array itself)
|
85
35
|
def put_int_array(arr)
|
86
36
|
put_int arr.length, *arr
|
87
|
-
self
|
88
37
|
end
|
89
38
|
|
90
|
-
# Put array of 64-bit ints to request
|
91
|
-
#
|
92
|
-
# @param [Array<Integer>] arr an array of integers to put to the request.
|
93
|
-
# @return [Request] self.
|
94
|
-
#
|
95
|
-
# @example
|
96
|
-
# request.put_int64_array [10]
|
97
|
-
# request.put_int64_array [10, 20, 30]
|
98
|
-
#
|
39
|
+
# Put array of 64-bit ints to request (first length, then the array itself)
|
99
40
|
def put_int64_array(arr)
|
100
|
-
put_int
|
41
|
+
put_int arr.length
|
101
42
|
put_int64(*arr)
|
102
|
-
self
|
103
43
|
end
|
104
|
-
|
105
|
-
# Returns the
|
106
|
-
#
|
107
|
-
# @return [String] serialized request.
|
108
|
-
#
|
44
|
+
|
45
|
+
# Returns the entire message
|
109
46
|
def to_s
|
110
47
|
@request
|
111
48
|
end
|
112
|
-
|
113
|
-
# Returns CRC32 of the serialized request.
|
114
|
-
#
|
115
|
-
# @return [Integer] CRC32 of the serialized request.
|
116
|
-
#
|
117
|
-
def crc32
|
118
|
-
Zlib.crc32(@request)
|
119
|
-
end
|
120
49
|
end
|
121
50
|
end
|
data/lib/sphinx/response.rb
CHANGED
data/lib/sphinx.rb
CHANGED
@@ -1,51 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
# Copyright:: Copyright (c) 2006 — 2009 Dmytro Shteflyuk
|
5
|
-
# License:: Distributes under the same terms as Ruby
|
6
|
-
# Version:: 0.9.9-r2117
|
7
|
-
# Website:: http://kpumuk.info/projects/ror-plugins/sphinx
|
8
|
-
# Sources:: http://github.com/kpumuk/sphinx
|
9
|
-
#
|
10
|
-
# This library is distributed under the terms of the Ruby license.
|
11
|
-
# You can freely distribute/modify this library.
|
12
|
-
#
|
13
|
-
module Sphinx
|
14
|
-
VERSION = begin
|
15
|
-
require 'yaml'
|
16
|
-
config = YAML.load(File.read(File.dirname(__FILE__) + '/../VERSION.yml'))
|
17
|
-
"#{config[:major]}.#{config[:minor]}.#{config[:patch]}.#{config[:build]}"
|
18
|
-
end
|
19
|
-
|
20
|
-
# Base class for all Sphinx errors
|
21
|
-
class SphinxError < StandardError; end
|
22
|
-
|
23
|
-
# Connect error occurred on the API side.
|
24
|
-
class SphinxConnectError < SphinxError; end
|
25
|
-
|
26
|
-
# Request error occurred on the API side.
|
27
|
-
class SphinxResponseError < SphinxError; end
|
28
|
-
|
29
|
-
# Internal error occurred inside searchd.
|
30
|
-
class SphinxInternalError < SphinxError; end
|
1
|
+
require File.dirname(__FILE__) + '/sphinx/request'
|
2
|
+
require File.dirname(__FILE__) + '/sphinx/response'
|
3
|
+
require File.dirname(__FILE__) + '/sphinx/client'
|
31
4
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
# Unknown error occurred inside searchd.
|
36
|
-
class SphinxUnknownError < SphinxError; end
|
37
|
-
end
|
38
|
-
|
39
|
-
require 'net/protocol'
|
40
|
-
require 'socket'
|
41
|
-
require 'zlib'
|
42
|
-
|
43
|
-
path = File.dirname(__FILE__)
|
44
|
-
require "#{path}/sphinx/constants"
|
45
|
-
require "#{path}/sphinx/indifferent_access"
|
46
|
-
require "#{path}/sphinx/request"
|
47
|
-
require "#{path}/sphinx/response"
|
48
|
-
require "#{path}/sphinx/timeout"
|
49
|
-
require "#{path}/sphinx/buffered_io"
|
50
|
-
require "#{path}/sphinx/server"
|
51
|
-
require "#{path}/sphinx/client"
|
5
|
+
module Sphinx
|
6
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.dirname(__FILE__) + '
|
1
|
+
require File.dirname(__FILE__) + '/../init'
|
2
2
|
|
3
3
|
# To execute these tests you need to execute sphinx_test.sql and configure sphinx using sphinx.conf
|
4
4
|
# (both files are placed under sphinx directory)
|
@@ -24,7 +24,7 @@ describe Sphinx::Client, 'connected' do
|
|
24
24
|
|
25
25
|
it 'should process errors in Query method' do
|
26
26
|
@sphinx.Query('wifi', 'fakeindex').should be_false
|
27
|
-
@sphinx.GetLastError.should_not
|
27
|
+
@sphinx.GetLastError.length.should_not == 0
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
@@ -34,14 +34,14 @@ describe Sphinx::Client, 'connected' do
|
|
34
34
|
@sphinx.AddQuery('gprs', 'test1')
|
35
35
|
results = @sphinx.RunQueries
|
36
36
|
results.should be_an_instance_of(Array)
|
37
|
-
results.should
|
37
|
+
results.length.should == 2
|
38
38
|
validate_results_wifi(results[0])
|
39
39
|
end
|
40
40
|
|
41
41
|
it 'should process errors in RunQueries method' do
|
42
42
|
@sphinx.AddQuery('wifi', 'fakeindex')
|
43
43
|
r = @sphinx.RunQueries
|
44
|
-
r[0]['error'].should_not
|
44
|
+
r[0]['error'].length.should_not == 0
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
@@ -62,6 +62,25 @@ describe Sphinx::Client, 'connected' do
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
+
context 'in Open method' do
|
66
|
+
it 'should open socket' do
|
67
|
+
@sphinx.Open.should be_true
|
68
|
+
socket = @sphinx.instance_variable_get(:@socket)
|
69
|
+
socket.should be_kind_of(TCPSocket)
|
70
|
+
socket.close
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should produce an error when opened twice' do
|
74
|
+
@sphinx.Open.should be_true
|
75
|
+
@sphinx.Open.should be_false
|
76
|
+
@sphinx.GetLastError.should == 'already connected'
|
77
|
+
|
78
|
+
socket = @sphinx.instance_variable_get(:@socket)
|
79
|
+
socket.should be_kind_of(TCPSocket)
|
80
|
+
socket.close
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
65
84
|
context 'in UpdateAttributes method' do
|
66
85
|
it 'should parse response' do
|
67
86
|
@sphinx.UpdateAttributes('test1', ['group_id'], { 2 => [1] }).should == 1
|
@@ -82,43 +101,23 @@ describe Sphinx::Client, 'connected' do
|
|
82
101
|
end
|
83
102
|
end
|
84
103
|
|
85
|
-
context 'in Open method' do
|
86
|
-
it 'should open socket' do
|
87
|
-
@sphinx.Open.should be_true
|
88
|
-
socket = @sphinx.servers.first.instance_variable_get(:@socket)
|
89
|
-
socket.should_not be_nil
|
90
|
-
socket.should be_kind_of(Sphinx::BufferedIO)
|
91
|
-
socket.close
|
92
|
-
end
|
93
|
-
|
94
|
-
it 'should produce an error when opened twice' do
|
95
|
-
@sphinx.Open.should be_true
|
96
|
-
@sphinx.Open.should be_false
|
97
|
-
@sphinx.GetLastError.should == 'already connected'
|
98
|
-
|
99
|
-
socket = @sphinx.servers.first.instance_variable_get(:@socket)
|
100
|
-
socket.should be_kind_of(Sphinx::BufferedIO)
|
101
|
-
socket.close
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
104
|
context 'in Close method' do
|
106
105
|
it 'should open socket' do
|
107
106
|
@sphinx.Open.should be_true
|
108
107
|
@sphinx.Close.should be_true
|
109
|
-
@sphinx.
|
108
|
+
@sphinx.instance_variable_get(:@socket).should be_false
|
110
109
|
end
|
111
|
-
|
110
|
+
|
112
111
|
it 'should produce socket is closed' do
|
113
112
|
@sphinx.Close.should be_false
|
114
113
|
@sphinx.GetLastError.should == 'not connected'
|
115
|
-
@sphinx.
|
116
|
-
|
114
|
+
@sphinx.instance_variable_get(:@socket).should be_false
|
115
|
+
|
117
116
|
@sphinx.Open.should be_true
|
118
117
|
@sphinx.Close.should be_true
|
119
118
|
@sphinx.Close.should be_false
|
120
119
|
@sphinx.GetLastError.should == 'not connected'
|
121
|
-
@sphinx.
|
120
|
+
@sphinx.instance_variable_get(:@socket).should be_false
|
122
121
|
end
|
123
122
|
end
|
124
123
|
|
@@ -130,15 +129,23 @@ describe Sphinx::Client, 'connected' do
|
|
130
129
|
end
|
131
130
|
end
|
132
131
|
|
132
|
+
context 'in FlushAttrs method' do
|
133
|
+
it 'should not raise an error' do
|
134
|
+
expect {
|
135
|
+
@sphinx.FlushAttrs
|
136
|
+
}.to_not raise_error
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
133
140
|
def validate_results_wifi(result)
|
134
141
|
result['total_found'].should == 3
|
135
142
|
result['matches'].length.should == 3
|
136
143
|
result['time'].should_not be_nil
|
137
144
|
result['attrs'].should == {
|
138
|
-
'group_id' => Sphinx::SPH_ATTR_INTEGER,
|
139
|
-
'created_at' => Sphinx::SPH_ATTR_TIMESTAMP,
|
140
|
-
'rating' => Sphinx::SPH_ATTR_FLOAT,
|
141
|
-
'tags' => Sphinx::SPH_ATTR_MULTI | Sphinx::SPH_ATTR_INTEGER
|
145
|
+
'group_id' => Sphinx::Client::SPH_ATTR_INTEGER,
|
146
|
+
'created_at' => Sphinx::Client::SPH_ATTR_TIMESTAMP,
|
147
|
+
'rating' => Sphinx::Client::SPH_ATTR_FLOAT,
|
148
|
+
'tags' => Sphinx::Client::SPH_ATTR_MULTI | Sphinx::Client::SPH_ATTR_INTEGER
|
142
149
|
}
|
143
150
|
result['fields'].should == [ 'name', 'description' ]
|
144
151
|
result['total'].should == 3
|