skalee-thinking-sphinx 1.3.14.1
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/LICENCE +20 -0
- data/README.textile +201 -0
- data/Rakefile +3 -0
- data/VERSION +1 -0
- data/contribute.rb +385 -0
- data/cucumber.yml +1 -0
- data/features/abstract_inheritance.feature +10 -0
- data/features/alternate_primary_key.feature +27 -0
- data/features/attribute_transformation.feature +22 -0
- data/features/attribute_updates.feature +51 -0
- data/features/deleting_instances.feature +67 -0
- data/features/direct_attributes.feature +11 -0
- data/features/excerpts.feature +13 -0
- data/features/extensible_delta_indexing.feature +9 -0
- data/features/facets.feature +82 -0
- data/features/facets_across_model.feature +29 -0
- data/features/handling_edits.feature +92 -0
- data/features/retry_stale_indexes.feature +24 -0
- data/features/searching_across_models.feature +20 -0
- data/features/searching_by_index.feature +40 -0
- data/features/searching_by_model.feature +175 -0
- data/features/searching_with_find_arguments.feature +56 -0
- data/features/sphinx_detection.feature +25 -0
- data/features/sphinx_scopes.feature +42 -0
- data/features/step_definitions/alpha_steps.rb +16 -0
- data/features/step_definitions/beta_steps.rb +7 -0
- data/features/step_definitions/common_steps.rb +188 -0
- data/features/step_definitions/extensible_delta_indexing_steps.rb +7 -0
- data/features/step_definitions/facet_steps.rb +96 -0
- data/features/step_definitions/find_arguments_steps.rb +36 -0
- data/features/step_definitions/gamma_steps.rb +15 -0
- data/features/step_definitions/scope_steps.rb +15 -0
- data/features/step_definitions/search_steps.rb +89 -0
- data/features/step_definitions/sphinx_steps.rb +35 -0
- data/features/sti_searching.feature +19 -0
- data/features/support/database.example.yml +3 -0
- data/features/support/db/.gitignore +1 -0
- data/features/support/db/fixtures/alphas.rb +10 -0
- data/features/support/db/fixtures/authors.rb +1 -0
- data/features/support/db/fixtures/betas.rb +10 -0
- data/features/support/db/fixtures/boxes.rb +9 -0
- data/features/support/db/fixtures/categories.rb +1 -0
- data/features/support/db/fixtures/cats.rb +3 -0
- data/features/support/db/fixtures/comments.rb +24 -0
- data/features/support/db/fixtures/developers.rb +29 -0
- data/features/support/db/fixtures/dogs.rb +3 -0
- data/features/support/db/fixtures/extensible_betas.rb +10 -0
- data/features/support/db/fixtures/foxes.rb +3 -0
- data/features/support/db/fixtures/gammas.rb +10 -0
- data/features/support/db/fixtures/music.rb +4 -0
- data/features/support/db/fixtures/people.rb +1001 -0
- data/features/support/db/fixtures/posts.rb +6 -0
- data/features/support/db/fixtures/robots.rb +14 -0
- data/features/support/db/fixtures/tags.rb +27 -0
- data/features/support/db/migrations/create_alphas.rb +8 -0
- data/features/support/db/migrations/create_animals.rb +5 -0
- data/features/support/db/migrations/create_authors.rb +3 -0
- data/features/support/db/migrations/create_authors_posts.rb +6 -0
- data/features/support/db/migrations/create_betas.rb +5 -0
- data/features/support/db/migrations/create_boxes.rb +5 -0
- data/features/support/db/migrations/create_categories.rb +3 -0
- data/features/support/db/migrations/create_comments.rb +10 -0
- data/features/support/db/migrations/create_developers.rb +9 -0
- data/features/support/db/migrations/create_extensible_betas.rb +5 -0
- data/features/support/db/migrations/create_gammas.rb +3 -0
- data/features/support/db/migrations/create_genres.rb +3 -0
- data/features/support/db/migrations/create_music.rb +6 -0
- data/features/support/db/migrations/create_people.rb +13 -0
- data/features/support/db/migrations/create_posts.rb +5 -0
- data/features/support/db/migrations/create_robots.rb +4 -0
- data/features/support/db/migrations/create_taggings.rb +5 -0
- data/features/support/db/migrations/create_tags.rb +4 -0
- data/features/support/env.rb +21 -0
- data/features/support/lib/generic_delta_handler.rb +8 -0
- data/features/support/models/alpha.rb +22 -0
- data/features/support/models/animal.rb +5 -0
- data/features/support/models/author.rb +3 -0
- data/features/support/models/beta.rb +8 -0
- data/features/support/models/box.rb +8 -0
- data/features/support/models/cat.rb +3 -0
- data/features/support/models/category.rb +4 -0
- data/features/support/models/comment.rb +10 -0
- data/features/support/models/developer.rb +16 -0
- data/features/support/models/dog.rb +3 -0
- data/features/support/models/extensible_beta.rb +9 -0
- data/features/support/models/fox.rb +5 -0
- data/features/support/models/gamma.rb +5 -0
- data/features/support/models/genre.rb +3 -0
- data/features/support/models/medium.rb +5 -0
- data/features/support/models/music.rb +8 -0
- data/features/support/models/person.rb +23 -0
- data/features/support/models/post.rb +21 -0
- data/features/support/models/robot.rb +12 -0
- data/features/support/models/tag.rb +3 -0
- data/features/support/models/tagging.rb +4 -0
- data/ginger_scenarios.rb +28 -0
- data/init.rb +5 -0
- data/install.rb +5 -0
- data/lib/cucumber/thinking_sphinx/external_world.rb +8 -0
- data/lib/cucumber/thinking_sphinx/internal_world.rb +126 -0
- data/lib/cucumber/thinking_sphinx/sql_logger.rb +20 -0
- data/lib/thinking_sphinx/active_record/attribute_updates.rb +19 -0
- data/lib/thinking_sphinx/active_record/delta.rb +47 -0
- data/lib/thinking_sphinx/active_record/has_many_association.rb +29 -0
- data/lib/thinking_sphinx/active_record/scopes.rb +75 -0
- data/lib/thinking_sphinx/active_record.rb +348 -0
- data/lib/thinking_sphinx/adapters/abstract_adapter.rb +42 -0
- data/lib/thinking_sphinx/adapters/mysql_adapter.rb +54 -0
- data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +143 -0
- data/lib/thinking_sphinx/association.rb +164 -0
- data/lib/thinking_sphinx/attribute.rb +362 -0
- data/lib/thinking_sphinx/auto_version.rb +22 -0
- data/lib/thinking_sphinx/class_facet.rb +15 -0
- data/lib/thinking_sphinx/configuration.rb +300 -0
- data/lib/thinking_sphinx/context.rb +68 -0
- data/lib/thinking_sphinx/core/array.rb +7 -0
- data/lib/thinking_sphinx/core/string.rb +15 -0
- data/lib/thinking_sphinx/deltas/default_delta.rb +62 -0
- data/lib/thinking_sphinx/deltas.rb +28 -0
- data/lib/thinking_sphinx/deploy/capistrano.rb +100 -0
- data/lib/thinking_sphinx/excerpter.rb +22 -0
- data/lib/thinking_sphinx/facet.rb +125 -0
- data/lib/thinking_sphinx/facet_search.rb +136 -0
- data/lib/thinking_sphinx/field.rb +82 -0
- data/lib/thinking_sphinx/index/builder.rb +296 -0
- data/lib/thinking_sphinx/index/faux_column.rb +110 -0
- data/lib/thinking_sphinx/index.rb +157 -0
- data/lib/thinking_sphinx/property.rb +162 -0
- data/lib/thinking_sphinx/rails_additions.rb +150 -0
- data/lib/thinking_sphinx/search.rb +769 -0
- data/lib/thinking_sphinx/search_methods.rb +439 -0
- data/lib/thinking_sphinx/source/internal_properties.rb +46 -0
- data/lib/thinking_sphinx/source/sql.rb +130 -0
- data/lib/thinking_sphinx/source.rb +153 -0
- data/lib/thinking_sphinx/tasks.rb +131 -0
- data/lib/thinking_sphinx/test.rb +52 -0
- data/lib/thinking_sphinx.rb +225 -0
- data/rails/init.rb +16 -0
- data/recipes/thinking_sphinx.rb +3 -0
- data/spec/fixtures/data.sql +32 -0
- data/spec/fixtures/database.yml.default +3 -0
- data/spec/fixtures/models.rb +145 -0
- data/spec/fixtures/structure.sql +125 -0
- data/spec/spec_helper.rb +60 -0
- data/spec/sphinx_helper.rb +81 -0
- data/spec/thinking_sphinx/active_record/delta_spec.rb +128 -0
- data/spec/thinking_sphinx/active_record/has_many_association_spec.rb +55 -0
- data/spec/thinking_sphinx/active_record/scopes_spec.rb +177 -0
- data/spec/thinking_sphinx/active_record_spec.rb +622 -0
- data/spec/thinking_sphinx/association_spec.rb +239 -0
- data/spec/thinking_sphinx/attribute_spec.rb +570 -0
- data/spec/thinking_sphinx/auto_version_spec.rb +39 -0
- data/spec/thinking_sphinx/configuration_spec.rb +234 -0
- data/spec/thinking_sphinx/context_spec.rb +119 -0
- data/spec/thinking_sphinx/core/array_spec.rb +9 -0
- data/spec/thinking_sphinx/core/string_spec.rb +9 -0
- data/spec/thinking_sphinx/excerpter_spec.rb +57 -0
- data/spec/thinking_sphinx/facet_search_spec.rb +176 -0
- data/spec/thinking_sphinx/facet_spec.rb +333 -0
- data/spec/thinking_sphinx/field_spec.rb +154 -0
- data/spec/thinking_sphinx/index/builder_spec.rb +479 -0
- data/spec/thinking_sphinx/index/faux_column_spec.rb +30 -0
- data/spec/thinking_sphinx/index_spec.rb +183 -0
- data/spec/thinking_sphinx/rails_additions_spec.rb +203 -0
- data/spec/thinking_sphinx/search_methods_spec.rb +152 -0
- data/spec/thinking_sphinx/search_spec.rb +1181 -0
- data/spec/thinking_sphinx/source_spec.rb +235 -0
- data/spec/thinking_sphinx_spec.rb +204 -0
- data/tasks/distribution.rb +41 -0
- data/tasks/rails.rake +1 -0
- data/tasks/testing.rb +72 -0
- data/vendor/after_commit/.gitignore +1 -0
- data/vendor/after_commit/lib/after_commit/active_record.rb +122 -0
- data/vendor/after_commit/lib/after_commit/connection_adapters.rb +168 -0
- data/vendor/after_commit/lib/after_commit/test_bypass.rb +30 -0
- data/vendor/after_commit/lib/after_commit.rb +70 -0
- data/vendor/riddle/lib/riddle/0.9.8.rb +1 -0
- data/vendor/riddle/lib/riddle/0.9.9/client/filter.rb +22 -0
- data/vendor/riddle/lib/riddle/0.9.9/client.rb +49 -0
- data/vendor/riddle/lib/riddle/0.9.9/configuration/searchd.rb +28 -0
- data/vendor/riddle/lib/riddle/0.9.9.rb +7 -0
- data/vendor/riddle/lib/riddle/auto_version.rb +11 -0
- data/vendor/riddle/lib/riddle/client/filter.rb +62 -0
- data/vendor/riddle/lib/riddle/client/message.rb +70 -0
- data/vendor/riddle/lib/riddle/client/response.rb +94 -0
- data/vendor/riddle/lib/riddle/client.rb +745 -0
- data/vendor/riddle/lib/riddle/configuration/distributed_index.rb +49 -0
- data/vendor/riddle/lib/riddle/configuration/index.rb +149 -0
- data/vendor/riddle/lib/riddle/configuration/indexer.rb +20 -0
- data/vendor/riddle/lib/riddle/configuration/remote_index.rb +17 -0
- data/vendor/riddle/lib/riddle/configuration/searchd.rb +28 -0
- data/vendor/riddle/lib/riddle/configuration/section.rb +43 -0
- data/vendor/riddle/lib/riddle/configuration/source.rb +23 -0
- data/vendor/riddle/lib/riddle/configuration/sql_source.rb +53 -0
- data/vendor/riddle/lib/riddle/configuration/xml_source.rb +29 -0
- data/vendor/riddle/lib/riddle/configuration.rb +33 -0
- data/vendor/riddle/lib/riddle/controller.rb +78 -0
- data/vendor/riddle/lib/riddle.rb +51 -0
- metadata +312 -0
@@ -0,0 +1,168 @@
|
|
1
|
+
module AfterCommit
|
2
|
+
module ConnectionAdapters
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
# The commit_db_transaction method gets called when the outermost
|
6
|
+
# transaction finishes and everything inside commits. We want to
|
7
|
+
# override it so that after this happens, any records that were saved
|
8
|
+
# or destroyed within this transaction now get their after_commit
|
9
|
+
# callback fired.
|
10
|
+
def commit_db_transaction_with_callback
|
11
|
+
increment_transaction_pointer
|
12
|
+
committed = false
|
13
|
+
begin
|
14
|
+
trigger_before_commit_callbacks
|
15
|
+
trigger_before_commit_on_create_callbacks
|
16
|
+
trigger_before_commit_on_update_callbacks
|
17
|
+
trigger_before_commit_on_destroy_callbacks
|
18
|
+
|
19
|
+
commit_db_transaction_without_callback
|
20
|
+
committed = true
|
21
|
+
|
22
|
+
trigger_after_commit_callbacks
|
23
|
+
trigger_after_commit_on_create_callbacks
|
24
|
+
trigger_after_commit_on_update_callbacks
|
25
|
+
trigger_after_commit_on_destroy_callbacks
|
26
|
+
rescue
|
27
|
+
rollback_db_transaction unless committed
|
28
|
+
ensure
|
29
|
+
AfterCommit.cleanup(self)
|
30
|
+
decrement_transaction_pointer
|
31
|
+
end
|
32
|
+
end
|
33
|
+
alias_method_chain :commit_db_transaction, :callback
|
34
|
+
|
35
|
+
# In the event the transaction fails and rolls back, nothing inside
|
36
|
+
# should recieve the after_commit callback, but do fire the after_rollback
|
37
|
+
# callback for each record that failed to be committed.
|
38
|
+
def rollback_db_transaction_with_callback
|
39
|
+
begin
|
40
|
+
trigger_before_rollback_callbacks
|
41
|
+
rollback_db_transaction_without_callback
|
42
|
+
trigger_after_rollback_callbacks
|
43
|
+
ensure
|
44
|
+
AfterCommit.cleanup(self)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
alias_method_chain :rollback_db_transaction, :callback
|
48
|
+
|
49
|
+
def unique_transaction_key
|
50
|
+
[object_id, transaction_pointer]
|
51
|
+
end
|
52
|
+
|
53
|
+
def old_transaction_key
|
54
|
+
[object_id, transaction_pointer - 1]
|
55
|
+
end
|
56
|
+
|
57
|
+
protected
|
58
|
+
|
59
|
+
def trigger_before_commit_callbacks
|
60
|
+
AfterCommit.records(self).each do |record|
|
61
|
+
record.send :callback, :before_commit
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def trigger_before_commit_on_create_callbacks
|
66
|
+
AfterCommit.created_records(self).each do |record|
|
67
|
+
record.send :callback, :before_commit_on_create
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def trigger_before_commit_on_update_callbacks
|
72
|
+
AfterCommit.updated_records(self).each do |record|
|
73
|
+
record.send :callback, :before_commit_on_update
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def trigger_before_commit_on_destroy_callbacks
|
78
|
+
AfterCommit.destroyed_records(self).each do |record|
|
79
|
+
record.send :callback, :before_commit_on_destroy
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def trigger_before_rollback_callbacks
|
84
|
+
AfterCommit.records(self).each do |record|
|
85
|
+
begin
|
86
|
+
record.send :callback, :before_rollback
|
87
|
+
rescue
|
88
|
+
#
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def trigger_after_commit_callbacks
|
94
|
+
# Trigger the after_commit callback for each of the committed
|
95
|
+
# records.
|
96
|
+
AfterCommit.records(self).each do |record|
|
97
|
+
begin
|
98
|
+
record.send :callback, :after_commit
|
99
|
+
rescue
|
100
|
+
#
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def trigger_after_commit_on_create_callbacks
|
106
|
+
# Trigger the after_commit_on_create callback for each of the committed
|
107
|
+
# records.
|
108
|
+
AfterCommit.created_records(self).each do |record|
|
109
|
+
begin
|
110
|
+
record.send :callback, :after_commit_on_create
|
111
|
+
rescue
|
112
|
+
#
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def trigger_after_commit_on_update_callbacks
|
118
|
+
# Trigger the after_commit_on_update callback for each of the committed
|
119
|
+
# records.
|
120
|
+
AfterCommit.updated_records(self).each do |record|
|
121
|
+
begin
|
122
|
+
record.send :callback, :after_commit_on_update
|
123
|
+
rescue
|
124
|
+
#
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def trigger_after_commit_on_destroy_callbacks
|
130
|
+
# Trigger the after_commit_on_destroy callback for each of the committed
|
131
|
+
# records.
|
132
|
+
AfterCommit.destroyed_records(self).each do |record|
|
133
|
+
begin
|
134
|
+
record.send :callback, :after_commit_on_destroy
|
135
|
+
rescue
|
136
|
+
#
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def trigger_after_rollback_callbacks
|
142
|
+
# Trigger the after_rollback callback for each of the committed
|
143
|
+
# records.
|
144
|
+
AfterCommit.records(self).each do |record|
|
145
|
+
begin
|
146
|
+
record.send :callback, :after_rollback
|
147
|
+
rescue
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def transaction_pointer
|
153
|
+
Thread.current[:after_commit_pointer] ||= 0
|
154
|
+
end
|
155
|
+
|
156
|
+
def increment_transaction_pointer
|
157
|
+
Thread.current[:after_commit_pointer] ||= 0
|
158
|
+
Thread.current[:after_commit_pointer] += 1
|
159
|
+
end
|
160
|
+
|
161
|
+
def decrement_transaction_pointer
|
162
|
+
Thread.current[:after_commit_pointer] ||= 0
|
163
|
+
Thread.current[:after_commit_pointer] -= 1
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Fix problems caused because tests all run in a single transaction.
|
2
|
+
|
3
|
+
# The single transaction means that after_commit callback never happens in tests. Each of these method definitions
|
4
|
+
# overwrites the method in the after_commit plugin that stores the callback for after the commit. In each case here
|
5
|
+
# we simply call the callback rather than waiting for a commit that will never come.
|
6
|
+
|
7
|
+
module AfterCommit::TestBypass
|
8
|
+
def self.included(klass)
|
9
|
+
klass.class_eval do
|
10
|
+
[:add_committed_record_on_create, :add_committed_record_on_update, :add_committed_record_on_destroy].each do |method|
|
11
|
+
remove_method(method)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_committed_record_on_create
|
17
|
+
callback :after_commit
|
18
|
+
callback :after_commit_on_create
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_committed_record_on_update
|
22
|
+
callback :after_commit
|
23
|
+
callback :after_commit_on_update
|
24
|
+
end
|
25
|
+
|
26
|
+
def add_committed_record_on_destroy
|
27
|
+
callback :after_commit
|
28
|
+
callback :after_commit_on_destroy
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module AfterCommit
|
2
|
+
def self.record(connection, record)
|
3
|
+
prepare_collection :committed_records, connection
|
4
|
+
add_to_collection :committed_records, connection, record
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.record_created(connection, record)
|
8
|
+
prepare_collection :committed_records_on_create, connection
|
9
|
+
add_to_collection :committed_records_on_create, connection, record
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.record_updated(connection, record)
|
13
|
+
prepare_collection :committed_records_on_update, connection
|
14
|
+
add_to_collection :committed_records_on_update, connection, record
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.record_destroyed(connection, record)
|
18
|
+
prepare_collection :committed_records_on_destroy, connection
|
19
|
+
add_to_collection :committed_records_on_destroy, connection, record
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.records(connection)
|
23
|
+
collection :committed_records, connection
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.created_records(connection)
|
27
|
+
collection :committed_records_on_create, connection
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.updated_records(connection)
|
31
|
+
collection :committed_records_on_update, connection
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.destroyed_records(connection)
|
35
|
+
collection :committed_records_on_destroy, connection
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.cleanup(connection)
|
39
|
+
[
|
40
|
+
:committed_records,
|
41
|
+
:committed_records_on_create,
|
42
|
+
:committed_records_on_update,
|
43
|
+
:committed_records_on_destroy
|
44
|
+
].each do |collection|
|
45
|
+
Thread.current[collection] ||= {}
|
46
|
+
Thread.current[collection][connection.old_transaction_key] = []
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.prepare_collection(collection, connection)
|
51
|
+
Thread.current[collection] ||= {}
|
52
|
+
Thread.current[collection][connection.unique_transaction_key] ||= []
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.add_to_collection(collection, connection, record)
|
56
|
+
Thread.current[collection][connection.unique_transaction_key] << record
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.collection(collection, connection)
|
60
|
+
Thread.current[collection] ||= {}
|
61
|
+
Thread.current[collection][connection.old_transaction_key] ||= []
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
require 'after_commit/active_record'
|
66
|
+
require 'after_commit/connection_adapters'
|
67
|
+
require 'after_commit/test_bypass'
|
68
|
+
|
69
|
+
ActiveRecord::Base.send(:include, AfterCommit::ActiveRecord)
|
70
|
+
ActiveRecord::Base.include_after_commit_extensions
|
@@ -0,0 +1 @@
|
|
1
|
+
Riddle.loaded_version = '0.9.8'
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Riddle::Client::Filter
|
2
|
+
#
|
3
|
+
|
4
|
+
private
|
5
|
+
|
6
|
+
def append_integer_range(message, range)
|
7
|
+
message.append_64bit_ints self.values.first, self.values.last
|
8
|
+
end
|
9
|
+
|
10
|
+
def append_array(message, array)
|
11
|
+
message.append_64bit_ints *array.collect { |val|
|
12
|
+
case val
|
13
|
+
when TrueClass
|
14
|
+
1
|
15
|
+
when FalseClass
|
16
|
+
0
|
17
|
+
else
|
18
|
+
val
|
19
|
+
end
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
Riddle::Client::Versions[:search] = 0x116
|
2
|
+
Riddle::Client::Versions[:update] = 0x102
|
3
|
+
|
4
|
+
class Riddle::Client
|
5
|
+
private
|
6
|
+
|
7
|
+
def initialise_connection
|
8
|
+
socket = initialise_socket
|
9
|
+
|
10
|
+
# Send version
|
11
|
+
socket.send [1].pack('N'), 0
|
12
|
+
|
13
|
+
# Checking version
|
14
|
+
version = socket.recv(4).unpack('N*').first
|
15
|
+
if version < 1
|
16
|
+
socket.close
|
17
|
+
raise VersionError, "Can only connect to searchd version 1.0 or better, not version #{version}"
|
18
|
+
end
|
19
|
+
|
20
|
+
socket
|
21
|
+
end
|
22
|
+
|
23
|
+
def update_message(index, attributes, values_by_doc)
|
24
|
+
message = Message.new
|
25
|
+
|
26
|
+
message.append_string index
|
27
|
+
message.append_int attributes.length
|
28
|
+
attributes.each_with_index do |attribute, index|
|
29
|
+
message.append_string attribute
|
30
|
+
message.append_boolean values_by_doc.values.first[index].is_a?(Array)
|
31
|
+
end
|
32
|
+
|
33
|
+
message.append_int values_by_doc.length
|
34
|
+
values_by_doc.each do |key,values|
|
35
|
+
message.append_64bit_int key # document ID
|
36
|
+
values.each do |value|
|
37
|
+
case value
|
38
|
+
when Array
|
39
|
+
message.append_int value.length
|
40
|
+
message.append_ints *value
|
41
|
+
else
|
42
|
+
message.append_int value
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
message.to_s
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Riddle
|
2
|
+
class Configuration
|
3
|
+
class Searchd
|
4
|
+
def valid?
|
5
|
+
set_listen
|
6
|
+
clear_deprecated
|
7
|
+
|
8
|
+
!( @listen.nil? || @pid_file.nil? )
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def set_listen
|
14
|
+
return unless @listen.nil?
|
15
|
+
|
16
|
+
@listen = @port.to_s if @port && @address.nil?
|
17
|
+
@listen = "#{@address}:#{@port}" if @address && @port
|
18
|
+
end
|
19
|
+
|
20
|
+
def clear_deprecated
|
21
|
+
return if @listen.nil?
|
22
|
+
|
23
|
+
@address = nil
|
24
|
+
@port = nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Riddle
|
2
|
+
class Client
|
3
|
+
class Filter
|
4
|
+
attr_accessor :attribute, :values, :exclude
|
5
|
+
|
6
|
+
# Attribute name, values (which can be an array or a range), and whether
|
7
|
+
# the filter should be exclusive.
|
8
|
+
def initialize(attribute, values, exclude=false)
|
9
|
+
@attribute, @values, @exclude = attribute, values, exclude
|
10
|
+
end
|
11
|
+
|
12
|
+
def exclude?
|
13
|
+
self.exclude
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns the message for this filter to send to the Sphinx service
|
17
|
+
def query_message
|
18
|
+
message = Message.new
|
19
|
+
|
20
|
+
message.append_string self.attribute.to_s
|
21
|
+
case self.values
|
22
|
+
when Range
|
23
|
+
if self.values.first.is_a?(Float) && self.values.last.is_a?(Float)
|
24
|
+
message.append_int FilterTypes[:float_range]
|
25
|
+
message.append_floats self.values.first, self.values.last
|
26
|
+
else
|
27
|
+
message.append_int FilterTypes[:range]
|
28
|
+
append_integer_range message, self.values
|
29
|
+
end
|
30
|
+
when Array
|
31
|
+
message.append_int FilterTypes[:values]
|
32
|
+
message.append_int self.values.length
|
33
|
+
append_array message, self.values
|
34
|
+
end
|
35
|
+
message.append_int self.exclude? ? 1 : 0
|
36
|
+
|
37
|
+
message.to_s
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def append_integer_range(message, range)
|
43
|
+
message.append_ints self.values.first, self.values.last
|
44
|
+
end
|
45
|
+
|
46
|
+
# Using to_f is a hack from the PHP client - to workaround 32bit signed
|
47
|
+
# ints on x32 platforms
|
48
|
+
def append_array(message, array)
|
49
|
+
message.append_ints *array.collect { |val|
|
50
|
+
case val
|
51
|
+
when TrueClass
|
52
|
+
1.0
|
53
|
+
when FalseClass
|
54
|
+
0.0
|
55
|
+
else
|
56
|
+
val.to_f
|
57
|
+
end
|
58
|
+
}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Riddle
|
2
|
+
class Client
|
3
|
+
# This class takes care of the translation of ints, strings and arrays to
|
4
|
+
# the format required by the Sphinx service.
|
5
|
+
class Message
|
6
|
+
def initialize
|
7
|
+
@message = ""
|
8
|
+
@size_method = @message.respond_to?(:bytesize) ? :bytesize : :length
|
9
|
+
end
|
10
|
+
|
11
|
+
# Append raw data (only use if you know what you're doing)
|
12
|
+
def append(*args)
|
13
|
+
args.each { |arg| @message << arg }
|
14
|
+
end
|
15
|
+
|
16
|
+
# Append a string's length, then the string itself
|
17
|
+
def append_string(str)
|
18
|
+
string = str.respond_to?(:force_encoding) ?
|
19
|
+
str.dup.force_encoding('ASCII-8BIT') : str
|
20
|
+
|
21
|
+
@message << [string.send(@size_method)].pack('N') + string
|
22
|
+
end
|
23
|
+
|
24
|
+
# Append an integer
|
25
|
+
def append_int(int)
|
26
|
+
@message << [int].pack('N')
|
27
|
+
end
|
28
|
+
|
29
|
+
def append_64bit_int(int)
|
30
|
+
@message << [int >> 32, int & 0xFFFFFFFF].pack('NN')
|
31
|
+
end
|
32
|
+
|
33
|
+
# Append a float
|
34
|
+
def append_float(float)
|
35
|
+
@message << [float].pack('f').unpack('L*').pack("N")
|
36
|
+
end
|
37
|
+
|
38
|
+
def append_boolean(bool)
|
39
|
+
append_int(bool ? 1 : 0)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Append multiple integers
|
43
|
+
def append_ints(*ints)
|
44
|
+
ints.each { |int| append_int(int) }
|
45
|
+
end
|
46
|
+
|
47
|
+
def append_64bit_ints(*ints)
|
48
|
+
ints.each { |int| append_64bit_int(int) }
|
49
|
+
end
|
50
|
+
|
51
|
+
# Append multiple floats
|
52
|
+
def append_floats(*floats)
|
53
|
+
floats.each { |float| append_float(float) }
|
54
|
+
end
|
55
|
+
|
56
|
+
# Append an array of strings - first appends the length of the array,
|
57
|
+
# then each item's length and value.
|
58
|
+
def append_array(array)
|
59
|
+
append_int(array.length)
|
60
|
+
|
61
|
+
array.each { |item| append_string(item) }
|
62
|
+
end
|
63
|
+
|
64
|
+
# Returns the entire message
|
65
|
+
def to_s
|
66
|
+
@message
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Riddle
|
2
|
+
class Client
|
3
|
+
# Used to interrogate responses from the Sphinx daemon. Keep in mind none
|
4
|
+
# of the methods here check whether the data they're grabbing are what the
|
5
|
+
# user expects - it just assumes the user knows what the data stream is
|
6
|
+
# made up of.
|
7
|
+
class Response
|
8
|
+
# Create with the data to interpret
|
9
|
+
def initialize(str)
|
10
|
+
@str = str
|
11
|
+
@marker = 0
|
12
|
+
end
|
13
|
+
|
14
|
+
# Return the next string value in the stream
|
15
|
+
def next
|
16
|
+
len = next_int
|
17
|
+
result = @str[@marker, len]
|
18
|
+
@marker += len
|
19
|
+
|
20
|
+
return result
|
21
|
+
end
|
22
|
+
|
23
|
+
# Return the next integer value from the stream
|
24
|
+
def next_int
|
25
|
+
int = @str[@marker, 4].unpack('N*').first
|
26
|
+
@marker += 4
|
27
|
+
|
28
|
+
return int
|
29
|
+
end
|
30
|
+
|
31
|
+
def next_64bit_int
|
32
|
+
high, low = @str[@marker, 8].unpack('N*N*')[0..1]
|
33
|
+
@marker += 8
|
34
|
+
|
35
|
+
return (high << 32) + low
|
36
|
+
end
|
37
|
+
|
38
|
+
# Return the next float value from the stream
|
39
|
+
def next_float
|
40
|
+
float = @str[@marker, 4].unpack('N*').pack('L').unpack('f*').first
|
41
|
+
@marker += 4
|
42
|
+
|
43
|
+
return float
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns an array of string items
|
47
|
+
def next_array
|
48
|
+
count = next_int
|
49
|
+
items = []
|
50
|
+
for i in 0...count
|
51
|
+
items << self.next
|
52
|
+
end
|
53
|
+
|
54
|
+
return items
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns an array of int items
|
58
|
+
def next_int_array
|
59
|
+
count = next_int
|
60
|
+
items = []
|
61
|
+
for i in 0...count
|
62
|
+
items << self.next_int
|
63
|
+
end
|
64
|
+
|
65
|
+
return items
|
66
|
+
end
|
67
|
+
|
68
|
+
def next_float_array
|
69
|
+
count = next_int
|
70
|
+
items = []
|
71
|
+
for i in 0...count
|
72
|
+
items << self.next_float
|
73
|
+
end
|
74
|
+
|
75
|
+
return items
|
76
|
+
end
|
77
|
+
|
78
|
+
def next_64bit_int_array
|
79
|
+
count = next_int
|
80
|
+
items = []
|
81
|
+
for i in 0...count
|
82
|
+
items << self.next_64bit_int
|
83
|
+
end
|
84
|
+
|
85
|
+
return items
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns the length of the streamed data
|
89
|
+
def length
|
90
|
+
@str.length
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|