thinking-sphinx 4.3.2 → 5.2.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 +4 -4
- data/.circleci/config.yml +152 -0
- data/.travis.yml +16 -21
- data/Appraisals +11 -20
- data/CHANGELOG.markdown +79 -0
- data/README.textile +15 -17
- data/bin/loadsphinx +30 -7
- data/lib/thinking_sphinx.rb +5 -4
- data/lib/thinking_sphinx/active_record.rb +1 -0
- data/lib/thinking_sphinx/active_record/association_proxy.rb +1 -2
- data/lib/thinking_sphinx/active_record/association_proxy/attribute_finder.rb +1 -1
- data/lib/thinking_sphinx/active_record/attribute/sphinx_presenter.rb +1 -1
- data/lib/thinking_sphinx/active_record/base.rb +17 -6
- data/lib/thinking_sphinx/active_record/callbacks/association_delta_callbacks.rb +21 -0
- data/lib/thinking_sphinx/active_record/callbacks/delete_callbacks.rb +1 -1
- data/lib/thinking_sphinx/active_record/callbacks/delta_callbacks.rb +3 -2
- data/lib/thinking_sphinx/active_record/callbacks/update_callbacks.rb +1 -1
- data/lib/thinking_sphinx/active_record/interpreter.rb +4 -4
- data/lib/thinking_sphinx/active_record/sql_source.rb +12 -0
- data/lib/thinking_sphinx/active_record/sql_source/template.rb +2 -2
- data/lib/thinking_sphinx/callbacks.rb +9 -0
- data/lib/thinking_sphinx/callbacks/appender.rb +59 -0
- data/lib/thinking_sphinx/commands/index_real_time.rb +1 -3
- data/lib/thinking_sphinx/connection.rb +4 -0
- data/lib/thinking_sphinx/connection/client.rb +6 -1
- data/lib/thinking_sphinx/core/index.rb +5 -2
- data/lib/thinking_sphinx/deletion.rb +18 -17
- data/lib/thinking_sphinx/errors.rb +1 -1
- data/lib/thinking_sphinx/index_set.rb +7 -3
- data/lib/thinking_sphinx/middlewares/sphinxql.rb +1 -1
- data/lib/thinking_sphinx/railtie.rb +14 -1
- data/lib/thinking_sphinx/real_time.rb +17 -0
- data/lib/thinking_sphinx/real_time/index.rb +5 -3
- data/lib/thinking_sphinx/real_time/index/template.rb +12 -0
- data/lib/thinking_sphinx/real_time/interpreter.rb +8 -6
- data/lib/thinking_sphinx/real_time/populator.rb +5 -2
- data/lib/thinking_sphinx/real_time/processor.rb +36 -0
- data/lib/thinking_sphinx/real_time/transcriber.rb +41 -19
- data/lib/thinking_sphinx/real_time/translator.rb +1 -0
- data/lib/thinking_sphinx/settings.rb +13 -9
- data/lib/thinking_sphinx/subscribers/populator_subscriber.rb +0 -4
- data/spec/acceptance/big_integers_spec.rb +1 -1
- data/spec/acceptance/geosearching_spec.rb +13 -3
- data/spec/acceptance/merging_spec.rb +1 -1
- data/spec/acceptance/real_time_updates_spec.rb +2 -2
- data/spec/acceptance/sql_deltas_spec.rb +15 -3
- data/spec/acceptance/support/sphinx_helpers.rb +4 -4
- data/spec/acceptance/suspended_deltas_spec.rb +3 -3
- data/spec/internal/app/indices/article_index.rb +0 -1
- data/spec/internal/app/indices/colour_index.rb +7 -0
- data/spec/internal/app/models/admin/person.rb +3 -1
- data/spec/internal/app/models/album.rb +3 -1
- data/spec/internal/app/models/animal.rb +1 -0
- data/spec/internal/app/models/article.rb +2 -0
- data/spec/internal/app/models/bird.rb +1 -0
- data/spec/internal/app/models/book.rb +2 -0
- data/spec/internal/app/models/car.rb +1 -1
- data/spec/internal/app/models/city.rb +2 -0
- data/spec/internal/app/models/colour.rb +2 -0
- data/spec/internal/app/models/product.rb +1 -1
- data/spec/internal/app/models/tee.rb +5 -0
- data/spec/internal/app/models/user.rb +2 -0
- data/spec/internal/config/database.yml +6 -1
- data/spec/internal/db/schema.rb +1 -0
- data/spec/thinking_sphinx/active_record/callbacks/update_callbacks_spec.rb +2 -1
- data/spec/thinking_sphinx/active_record/index_spec.rb +0 -12
- data/spec/thinking_sphinx/active_record/interpreter_spec.rb +15 -14
- data/spec/thinking_sphinx/active_record/sql_source_spec.rb +41 -3
- data/spec/thinking_sphinx/connection/mri_spec.rb +49 -0
- data/spec/thinking_sphinx/deletion_spec.rb +5 -4
- data/spec/thinking_sphinx/index_set_spec.rb +28 -12
- data/spec/thinking_sphinx/middlewares/sphinxql_spec.rb +2 -1
- data/spec/thinking_sphinx/real_time/index_spec.rb +51 -13
- data/spec/thinking_sphinx/real_time/interpreter_spec.rb +14 -14
- data/spec/thinking_sphinx/real_time/transcriber_spec.rb +9 -1
- data/thinking-sphinx.gemspec +3 -5
- metadata +17 -11
- data/spec/acceptance/connection_spec.rb +0 -25
@@ -6,22 +6,22 @@ module SphinxHelpers
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def index(*indices)
|
9
|
-
sleep 0.5 if ENV['
|
9
|
+
sleep 0.5 if ENV['CI']
|
10
10
|
|
11
11
|
yield if block_given?
|
12
12
|
|
13
13
|
sphinx.index *indices
|
14
14
|
sleep 0.25
|
15
|
-
sleep 0.5 if ENV['
|
15
|
+
sleep 0.5 if ENV['CI']
|
16
16
|
end
|
17
17
|
|
18
18
|
def merge
|
19
|
-
sleep 0.5 if ENV['
|
19
|
+
sleep 0.5 if ENV['CI']
|
20
20
|
sleep 0.5
|
21
21
|
|
22
22
|
sphinx.merge
|
23
23
|
sleep 1.5
|
24
|
-
sleep 0.5 if ENV['
|
24
|
+
sleep 0.5 if ENV['CI']
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
@@ -10,7 +10,7 @@ describe 'Suspend deltas for a given action', :live => true do
|
|
10
10
|
expect(Book.search('Harry').to_a).to eq([book])
|
11
11
|
|
12
12
|
ThinkingSphinx::Deltas.suspend :book do
|
13
|
-
book.reload.
|
13
|
+
book.reload.update(:author => 'Terry Pratchett')
|
14
14
|
sleep 0.25
|
15
15
|
|
16
16
|
expect(Book.search('Terry').to_a).to eq([])
|
@@ -27,7 +27,7 @@ describe 'Suspend deltas for a given action', :live => true do
|
|
27
27
|
expect(Book.search('Harry').to_a).to eq([book])
|
28
28
|
|
29
29
|
ThinkingSphinx::Deltas.suspend :book do
|
30
|
-
book.reload.
|
30
|
+
book.reload.update(:author => 'Terry Pratchett')
|
31
31
|
sleep 0.25
|
32
32
|
|
33
33
|
expect(Book.search('Terry').to_a).to eq([])
|
@@ -44,7 +44,7 @@ describe 'Suspend deltas for a given action', :live => true do
|
|
44
44
|
expect(Book.search('Harry').to_a).to eq([book])
|
45
45
|
|
46
46
|
ThinkingSphinx::Deltas.suspend_and_update :book do
|
47
|
-
book.reload.
|
47
|
+
book.reload.update(:author => 'Terry Pratchett')
|
48
48
|
sleep 0.25
|
49
49
|
|
50
50
|
expect(Book.search('Terry').to_a).to eq([])
|
@@ -10,7 +10,6 @@ ThinkingSphinx::Index.define :article, :with => :active_record do
|
|
10
10
|
has taggings.created_at, :as => :taggings_at, :type => :timestamp
|
11
11
|
|
12
12
|
set_property :min_infix_len => 4
|
13
|
-
set_property :enable_star => true
|
14
13
|
end
|
15
14
|
|
16
15
|
ThinkingSphinx::Index.define :article, :with => :active_record,
|
@@ -6,7 +6,9 @@ class Album < ActiveRecord::Base
|
|
6
6
|
before_validation :set_id, :on => :create
|
7
7
|
before_validation :set_integer_id, :on => :create
|
8
8
|
|
9
|
-
|
9
|
+
ThinkingSphinx::Callbacks.append(
|
10
|
+
self, :behaviours => [:sql, :real_time, :deltas]
|
11
|
+
)
|
10
12
|
|
11
13
|
validates :id, :presence => true, :uniqueness => true
|
12
14
|
validates :integer_id, :presence => true, :uniqueness => true
|
@@ -1,6 +1,11 @@
|
|
1
1
|
test:
|
2
2
|
adapter: <%= ENV['DATABASE'] || 'mysql2' %>
|
3
3
|
database: thinking_sphinx
|
4
|
-
username: <%= ENV['DATABASE'] == 'postgresql' ?
|
4
|
+
username: <%= ENV['DATABASE'] == 'postgresql' ? 'postgres' : 'root' %>
|
5
|
+
<% if ENV["CI"] %>
|
6
|
+
password: thinking_sphinx
|
7
|
+
host: 127.0.0.1
|
8
|
+
port: <%= ENV['DATABASE'] == 'postgresql' ? 5432 : 3306 %>
|
9
|
+
<% end %>
|
5
10
|
min_messages: warning
|
6
11
|
encoding: utf8
|
data/spec/internal/db/schema.rb
CHANGED
@@ -19,12 +19,13 @@ describe ThinkingSphinx::ActiveRecord::Callbacks::UpdateCallbacks do
|
|
19
19
|
let(:klass) { double(:name => 'Article') }
|
20
20
|
let(:configuration) { double('configuration',
|
21
21
|
:settings => {'attribute_updates' => true},
|
22
|
-
:indices_for_references => [index]) }
|
22
|
+
:indices_for_references => [index], :index_set_class => set_class) }
|
23
23
|
let(:connection) { double('connection', :execute => '') }
|
24
24
|
let(:index) { double 'index', :name => 'article_core',
|
25
25
|
:sources => [source], :document_id_for_key => 3, :distributed? => false,
|
26
26
|
:type => 'plain', :primary_key => :id}
|
27
27
|
let(:source) { double('source', :attributes => []) }
|
28
|
+
let(:set_class) { double(:reference_name => :article) }
|
28
29
|
|
29
30
|
before :each do
|
30
31
|
stub_const 'ThinkingSphinx::Configuration',
|
@@ -94,18 +94,6 @@ describe ThinkingSphinx::ActiveRecord::Index do
|
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
|
-
describe '#docinfo' do
|
98
|
-
it "defaults to extern" do
|
99
|
-
expect(index.docinfo).to eq(:extern)
|
100
|
-
end
|
101
|
-
|
102
|
-
it "can be disabled" do
|
103
|
-
config.settings["skip_docinfo"] = true
|
104
|
-
|
105
|
-
expect(index.docinfo).to be_nil
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
97
|
describe '#document_id_for_key' do
|
110
98
|
it "calculates the document id based on offset and number of indices" do
|
111
99
|
allow(config).to receive_message_chain(:indices, :count).and_return(5)
|
@@ -15,8 +15,13 @@ describe ThinkingSphinx::ActiveRecord::Interpreter do
|
|
15
15
|
let(:block) { Proc.new { } }
|
16
16
|
|
17
17
|
before :each do
|
18
|
-
allow(ThinkingSphinx::ActiveRecord::SQLSource).to receive_messages
|
19
|
-
|
18
|
+
allow(ThinkingSphinx::ActiveRecord::SQLSource).to receive_messages(
|
19
|
+
:new => source
|
20
|
+
)
|
21
|
+
|
22
|
+
allow(source).to receive_messages(
|
23
|
+
:model => model, :add_attribute => nil, :add_field => nil
|
24
|
+
)
|
20
25
|
end
|
21
26
|
|
22
27
|
describe '.translate!' do
|
@@ -94,17 +99,15 @@ describe ThinkingSphinx::ActiveRecord::Interpreter do
|
|
94
99
|
end
|
95
100
|
|
96
101
|
it "adds an attribute to the source" do
|
97
|
-
|
102
|
+
expect(source).to receive(:add_attribute).with(attribute)
|
98
103
|
|
99
|
-
|
104
|
+
instance.has column
|
100
105
|
end
|
101
106
|
|
102
107
|
it "adds multiple attributes when passed multiple columns" do
|
103
|
-
|
108
|
+
expect(source).to receive(:add_attribute).with(attribute).twice
|
104
109
|
|
105
|
-
|
106
|
-
saved_attribute == attribute
|
107
|
-
}.length).to eq(2)
|
110
|
+
instance.has column, column
|
108
111
|
end
|
109
112
|
end
|
110
113
|
|
@@ -144,17 +147,15 @@ describe ThinkingSphinx::ActiveRecord::Interpreter do
|
|
144
147
|
end
|
145
148
|
|
146
149
|
it "adds a field to the source" do
|
147
|
-
|
150
|
+
expect(source).to receive(:add_field).with(field)
|
148
151
|
|
149
|
-
|
152
|
+
instance.indexes column
|
150
153
|
end
|
151
154
|
|
152
155
|
it "adds multiple fields when passed multiple columns" do
|
153
|
-
|
156
|
+
expect(source).to receive(:add_field).with(field).twice
|
154
157
|
|
155
|
-
|
156
|
-
saved_field == field
|
157
|
-
}.length).to eq(2)
|
158
|
+
instance.indexes column, column
|
158
159
|
end
|
159
160
|
end
|
160
161
|
|
@@ -30,6 +30,44 @@ describe ThinkingSphinx::ActiveRecord::SQLSource do
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
+
describe '#add_attribute' do
|
34
|
+
let(:attribute) { double('attribute', name: 'my_attribute') }
|
35
|
+
|
36
|
+
it "appends attributes to the collection" do
|
37
|
+
source.add_attribute attribute
|
38
|
+
|
39
|
+
expect(source.attributes.collect(&:name)).to include('my_attribute')
|
40
|
+
end
|
41
|
+
|
42
|
+
it "replaces attributes with the same name" do
|
43
|
+
source.add_attribute double('attribute', name: 'my_attribute')
|
44
|
+
source.add_attribute attribute
|
45
|
+
|
46
|
+
matching = source.attributes.select { |attr| attr.name == attribute.name }
|
47
|
+
|
48
|
+
expect(matching).to eq([attribute])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#add_field' do
|
53
|
+
let(:field) { double('field', name: 'my_field') }
|
54
|
+
|
55
|
+
it "appends fields to the collection" do
|
56
|
+
source.add_field field
|
57
|
+
|
58
|
+
expect(source.fields.collect(&:name)).to include('my_field')
|
59
|
+
end
|
60
|
+
|
61
|
+
it "replaces fields with the same name" do
|
62
|
+
source.add_field double('field', name: 'my_field')
|
63
|
+
source.add_field field
|
64
|
+
|
65
|
+
matching = source.fields.select { |fld| fld.name == field.name }
|
66
|
+
|
67
|
+
expect(matching).to eq([field])
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
33
71
|
describe '#attributes' do
|
34
72
|
it "has the internal id attribute by default" do
|
35
73
|
expect(source.attributes.collect(&:name)).to include('sphinx_internal_id')
|
@@ -287,14 +325,14 @@ describe ThinkingSphinx::ActiveRecord::SQLSource do
|
|
287
325
|
expect(source.sql_attr_string).to include('name')
|
288
326
|
end
|
289
327
|
|
290
|
-
it "adds timestamp attributes to
|
328
|
+
it "adds timestamp attributes to sql_attr_uint" do
|
291
329
|
source.attributes << double('attribute')
|
292
330
|
allow(presenter).to receive_messages :declaration => 'created_at',
|
293
|
-
:collection_type => :
|
331
|
+
:collection_type => :uint
|
294
332
|
|
295
333
|
source.render
|
296
334
|
|
297
|
-
expect(source.
|
335
|
+
expect(source.sql_attr_uint).to include('created_at')
|
298
336
|
end
|
299
337
|
|
300
338
|
it "adds float attributes to sql_attr_float" do
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe ThinkingSphinx::Connection::MRI do
|
4
|
+
subject { described_class.new :host => "127.0.0.1", :port => 9306 }
|
5
|
+
|
6
|
+
let(:client) { double :client, :query => "result", :next_result => false }
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
allow(Mysql2::Client).to receive(:new).and_return(client)
|
10
|
+
end
|
11
|
+
|
12
|
+
after :each do
|
13
|
+
ThinkingSphinx::Configuration.reset
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#execute" do
|
17
|
+
it "sends the query to the client" do
|
18
|
+
subject.execute "SELECT QUERY"
|
19
|
+
|
20
|
+
expect(client).to have_received(:query).with("SELECT QUERY")
|
21
|
+
end
|
22
|
+
|
23
|
+
it "returns a result" do
|
24
|
+
expect(subject.execute("SELECT QUERY")).to eq("result")
|
25
|
+
end
|
26
|
+
|
27
|
+
context "with long queries" do
|
28
|
+
let(:maximum) { (2 ** 23) - 5 }
|
29
|
+
let(:query) { String.new "SELECT * FROM book_core WHERE MATCH('')" }
|
30
|
+
let(:difference) { maximum - query.length }
|
31
|
+
|
32
|
+
it 'does not allow overly long queries' do
|
33
|
+
expect {
|
34
|
+
subject.execute(query.insert(-3, 'a' * (difference + 5)))
|
35
|
+
}.to raise_error(ThinkingSphinx::QueryLengthError)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'does not allow queries longer than specified in the settings' do
|
39
|
+
ThinkingSphinx::Configuration.reset
|
40
|
+
|
41
|
+
write_configuration('maximum_statement_length' => maximum - 5)
|
42
|
+
|
43
|
+
expect {
|
44
|
+
subject.execute(query.insert(-3, 'a' * (difference)))
|
45
|
+
}.to raise_error(ThinkingSphinx::QueryLengthError)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end if RUBY_PLATFORM != 'java'
|
@@ -6,7 +6,7 @@ describe ThinkingSphinx::Deletion do
|
|
6
6
|
describe '.perform' do
|
7
7
|
let(:connection) { double('connection', :execute => nil) }
|
8
8
|
let(:index) { double('index', :name => 'foo_core',
|
9
|
-
:
|
9
|
+
:type => 'plain', :distributed? => false) }
|
10
10
|
|
11
11
|
before :each do
|
12
12
|
allow(ThinkingSphinx::Connection).to receive(:take).and_yield(connection)
|
@@ -15,8 +15,9 @@ describe ThinkingSphinx::Deletion do
|
|
15
15
|
|
16
16
|
context 'index is SQL-backed' do
|
17
17
|
it "updates the deleted flag to false" do
|
18
|
-
expect(connection).to receive(:execute).
|
19
|
-
|
18
|
+
expect(connection).to receive(:execute).with(
|
19
|
+
'UPDATE foo_core SET sphinx_deleted = 1 WHERE sphinx_internal_id IN (7)'
|
20
|
+
)
|
20
21
|
|
21
22
|
ThinkingSphinx::Deletion.perform index, 7
|
22
23
|
end
|
@@ -38,7 +39,7 @@ describe ThinkingSphinx::Deletion do
|
|
38
39
|
|
39
40
|
it "deletes the record to false" do
|
40
41
|
expect(connection).to receive(:execute).
|
41
|
-
with('DELETE FROM foo_core WHERE
|
42
|
+
with('DELETE FROM foo_core WHERE sphinx_internal_id IN (7)')
|
42
43
|
|
43
44
|
ThinkingSphinx::Deletion.perform index, 7
|
44
45
|
end
|