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.
Files changed (199) hide show
  1. data/LICENCE +20 -0
  2. data/README.textile +201 -0
  3. data/Rakefile +3 -0
  4. data/VERSION +1 -0
  5. data/contribute.rb +385 -0
  6. data/cucumber.yml +1 -0
  7. data/features/abstract_inheritance.feature +10 -0
  8. data/features/alternate_primary_key.feature +27 -0
  9. data/features/attribute_transformation.feature +22 -0
  10. data/features/attribute_updates.feature +51 -0
  11. data/features/deleting_instances.feature +67 -0
  12. data/features/direct_attributes.feature +11 -0
  13. data/features/excerpts.feature +13 -0
  14. data/features/extensible_delta_indexing.feature +9 -0
  15. data/features/facets.feature +82 -0
  16. data/features/facets_across_model.feature +29 -0
  17. data/features/handling_edits.feature +92 -0
  18. data/features/retry_stale_indexes.feature +24 -0
  19. data/features/searching_across_models.feature +20 -0
  20. data/features/searching_by_index.feature +40 -0
  21. data/features/searching_by_model.feature +175 -0
  22. data/features/searching_with_find_arguments.feature +56 -0
  23. data/features/sphinx_detection.feature +25 -0
  24. data/features/sphinx_scopes.feature +42 -0
  25. data/features/step_definitions/alpha_steps.rb +16 -0
  26. data/features/step_definitions/beta_steps.rb +7 -0
  27. data/features/step_definitions/common_steps.rb +188 -0
  28. data/features/step_definitions/extensible_delta_indexing_steps.rb +7 -0
  29. data/features/step_definitions/facet_steps.rb +96 -0
  30. data/features/step_definitions/find_arguments_steps.rb +36 -0
  31. data/features/step_definitions/gamma_steps.rb +15 -0
  32. data/features/step_definitions/scope_steps.rb +15 -0
  33. data/features/step_definitions/search_steps.rb +89 -0
  34. data/features/step_definitions/sphinx_steps.rb +35 -0
  35. data/features/sti_searching.feature +19 -0
  36. data/features/support/database.example.yml +3 -0
  37. data/features/support/db/.gitignore +1 -0
  38. data/features/support/db/fixtures/alphas.rb +10 -0
  39. data/features/support/db/fixtures/authors.rb +1 -0
  40. data/features/support/db/fixtures/betas.rb +10 -0
  41. data/features/support/db/fixtures/boxes.rb +9 -0
  42. data/features/support/db/fixtures/categories.rb +1 -0
  43. data/features/support/db/fixtures/cats.rb +3 -0
  44. data/features/support/db/fixtures/comments.rb +24 -0
  45. data/features/support/db/fixtures/developers.rb +29 -0
  46. data/features/support/db/fixtures/dogs.rb +3 -0
  47. data/features/support/db/fixtures/extensible_betas.rb +10 -0
  48. data/features/support/db/fixtures/foxes.rb +3 -0
  49. data/features/support/db/fixtures/gammas.rb +10 -0
  50. data/features/support/db/fixtures/music.rb +4 -0
  51. data/features/support/db/fixtures/people.rb +1001 -0
  52. data/features/support/db/fixtures/posts.rb +6 -0
  53. data/features/support/db/fixtures/robots.rb +14 -0
  54. data/features/support/db/fixtures/tags.rb +27 -0
  55. data/features/support/db/migrations/create_alphas.rb +8 -0
  56. data/features/support/db/migrations/create_animals.rb +5 -0
  57. data/features/support/db/migrations/create_authors.rb +3 -0
  58. data/features/support/db/migrations/create_authors_posts.rb +6 -0
  59. data/features/support/db/migrations/create_betas.rb +5 -0
  60. data/features/support/db/migrations/create_boxes.rb +5 -0
  61. data/features/support/db/migrations/create_categories.rb +3 -0
  62. data/features/support/db/migrations/create_comments.rb +10 -0
  63. data/features/support/db/migrations/create_developers.rb +9 -0
  64. data/features/support/db/migrations/create_extensible_betas.rb +5 -0
  65. data/features/support/db/migrations/create_gammas.rb +3 -0
  66. data/features/support/db/migrations/create_genres.rb +3 -0
  67. data/features/support/db/migrations/create_music.rb +6 -0
  68. data/features/support/db/migrations/create_people.rb +13 -0
  69. data/features/support/db/migrations/create_posts.rb +5 -0
  70. data/features/support/db/migrations/create_robots.rb +4 -0
  71. data/features/support/db/migrations/create_taggings.rb +5 -0
  72. data/features/support/db/migrations/create_tags.rb +4 -0
  73. data/features/support/env.rb +21 -0
  74. data/features/support/lib/generic_delta_handler.rb +8 -0
  75. data/features/support/models/alpha.rb +22 -0
  76. data/features/support/models/animal.rb +5 -0
  77. data/features/support/models/author.rb +3 -0
  78. data/features/support/models/beta.rb +8 -0
  79. data/features/support/models/box.rb +8 -0
  80. data/features/support/models/cat.rb +3 -0
  81. data/features/support/models/category.rb +4 -0
  82. data/features/support/models/comment.rb +10 -0
  83. data/features/support/models/developer.rb +16 -0
  84. data/features/support/models/dog.rb +3 -0
  85. data/features/support/models/extensible_beta.rb +9 -0
  86. data/features/support/models/fox.rb +5 -0
  87. data/features/support/models/gamma.rb +5 -0
  88. data/features/support/models/genre.rb +3 -0
  89. data/features/support/models/medium.rb +5 -0
  90. data/features/support/models/music.rb +8 -0
  91. data/features/support/models/person.rb +23 -0
  92. data/features/support/models/post.rb +21 -0
  93. data/features/support/models/robot.rb +12 -0
  94. data/features/support/models/tag.rb +3 -0
  95. data/features/support/models/tagging.rb +4 -0
  96. data/ginger_scenarios.rb +28 -0
  97. data/init.rb +5 -0
  98. data/install.rb +5 -0
  99. data/lib/cucumber/thinking_sphinx/external_world.rb +8 -0
  100. data/lib/cucumber/thinking_sphinx/internal_world.rb +126 -0
  101. data/lib/cucumber/thinking_sphinx/sql_logger.rb +20 -0
  102. data/lib/thinking_sphinx/active_record/attribute_updates.rb +19 -0
  103. data/lib/thinking_sphinx/active_record/delta.rb +47 -0
  104. data/lib/thinking_sphinx/active_record/has_many_association.rb +29 -0
  105. data/lib/thinking_sphinx/active_record/scopes.rb +75 -0
  106. data/lib/thinking_sphinx/active_record.rb +348 -0
  107. data/lib/thinking_sphinx/adapters/abstract_adapter.rb +42 -0
  108. data/lib/thinking_sphinx/adapters/mysql_adapter.rb +54 -0
  109. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +143 -0
  110. data/lib/thinking_sphinx/association.rb +164 -0
  111. data/lib/thinking_sphinx/attribute.rb +362 -0
  112. data/lib/thinking_sphinx/auto_version.rb +22 -0
  113. data/lib/thinking_sphinx/class_facet.rb +15 -0
  114. data/lib/thinking_sphinx/configuration.rb +300 -0
  115. data/lib/thinking_sphinx/context.rb +68 -0
  116. data/lib/thinking_sphinx/core/array.rb +7 -0
  117. data/lib/thinking_sphinx/core/string.rb +15 -0
  118. data/lib/thinking_sphinx/deltas/default_delta.rb +62 -0
  119. data/lib/thinking_sphinx/deltas.rb +28 -0
  120. data/lib/thinking_sphinx/deploy/capistrano.rb +100 -0
  121. data/lib/thinking_sphinx/excerpter.rb +22 -0
  122. data/lib/thinking_sphinx/facet.rb +125 -0
  123. data/lib/thinking_sphinx/facet_search.rb +136 -0
  124. data/lib/thinking_sphinx/field.rb +82 -0
  125. data/lib/thinking_sphinx/index/builder.rb +296 -0
  126. data/lib/thinking_sphinx/index/faux_column.rb +110 -0
  127. data/lib/thinking_sphinx/index.rb +157 -0
  128. data/lib/thinking_sphinx/property.rb +162 -0
  129. data/lib/thinking_sphinx/rails_additions.rb +150 -0
  130. data/lib/thinking_sphinx/search.rb +769 -0
  131. data/lib/thinking_sphinx/search_methods.rb +439 -0
  132. data/lib/thinking_sphinx/source/internal_properties.rb +46 -0
  133. data/lib/thinking_sphinx/source/sql.rb +130 -0
  134. data/lib/thinking_sphinx/source.rb +153 -0
  135. data/lib/thinking_sphinx/tasks.rb +131 -0
  136. data/lib/thinking_sphinx/test.rb +52 -0
  137. data/lib/thinking_sphinx.rb +225 -0
  138. data/rails/init.rb +16 -0
  139. data/recipes/thinking_sphinx.rb +3 -0
  140. data/spec/fixtures/data.sql +32 -0
  141. data/spec/fixtures/database.yml.default +3 -0
  142. data/spec/fixtures/models.rb +145 -0
  143. data/spec/fixtures/structure.sql +125 -0
  144. data/spec/spec_helper.rb +60 -0
  145. data/spec/sphinx_helper.rb +81 -0
  146. data/spec/thinking_sphinx/active_record/delta_spec.rb +128 -0
  147. data/spec/thinking_sphinx/active_record/has_many_association_spec.rb +55 -0
  148. data/spec/thinking_sphinx/active_record/scopes_spec.rb +177 -0
  149. data/spec/thinking_sphinx/active_record_spec.rb +622 -0
  150. data/spec/thinking_sphinx/association_spec.rb +239 -0
  151. data/spec/thinking_sphinx/attribute_spec.rb +570 -0
  152. data/spec/thinking_sphinx/auto_version_spec.rb +39 -0
  153. data/spec/thinking_sphinx/configuration_spec.rb +234 -0
  154. data/spec/thinking_sphinx/context_spec.rb +119 -0
  155. data/spec/thinking_sphinx/core/array_spec.rb +9 -0
  156. data/spec/thinking_sphinx/core/string_spec.rb +9 -0
  157. data/spec/thinking_sphinx/excerpter_spec.rb +57 -0
  158. data/spec/thinking_sphinx/facet_search_spec.rb +176 -0
  159. data/spec/thinking_sphinx/facet_spec.rb +333 -0
  160. data/spec/thinking_sphinx/field_spec.rb +154 -0
  161. data/spec/thinking_sphinx/index/builder_spec.rb +479 -0
  162. data/spec/thinking_sphinx/index/faux_column_spec.rb +30 -0
  163. data/spec/thinking_sphinx/index_spec.rb +183 -0
  164. data/spec/thinking_sphinx/rails_additions_spec.rb +203 -0
  165. data/spec/thinking_sphinx/search_methods_spec.rb +152 -0
  166. data/spec/thinking_sphinx/search_spec.rb +1181 -0
  167. data/spec/thinking_sphinx/source_spec.rb +235 -0
  168. data/spec/thinking_sphinx_spec.rb +204 -0
  169. data/tasks/distribution.rb +41 -0
  170. data/tasks/rails.rake +1 -0
  171. data/tasks/testing.rb +72 -0
  172. data/vendor/after_commit/.gitignore +1 -0
  173. data/vendor/after_commit/lib/after_commit/active_record.rb +122 -0
  174. data/vendor/after_commit/lib/after_commit/connection_adapters.rb +168 -0
  175. data/vendor/after_commit/lib/after_commit/test_bypass.rb +30 -0
  176. data/vendor/after_commit/lib/after_commit.rb +70 -0
  177. data/vendor/riddle/lib/riddle/0.9.8.rb +1 -0
  178. data/vendor/riddle/lib/riddle/0.9.9/client/filter.rb +22 -0
  179. data/vendor/riddle/lib/riddle/0.9.9/client.rb +49 -0
  180. data/vendor/riddle/lib/riddle/0.9.9/configuration/searchd.rb +28 -0
  181. data/vendor/riddle/lib/riddle/0.9.9.rb +7 -0
  182. data/vendor/riddle/lib/riddle/auto_version.rb +11 -0
  183. data/vendor/riddle/lib/riddle/client/filter.rb +62 -0
  184. data/vendor/riddle/lib/riddle/client/message.rb +70 -0
  185. data/vendor/riddle/lib/riddle/client/response.rb +94 -0
  186. data/vendor/riddle/lib/riddle/client.rb +745 -0
  187. data/vendor/riddle/lib/riddle/configuration/distributed_index.rb +49 -0
  188. data/vendor/riddle/lib/riddle/configuration/index.rb +149 -0
  189. data/vendor/riddle/lib/riddle/configuration/indexer.rb +20 -0
  190. data/vendor/riddle/lib/riddle/configuration/remote_index.rb +17 -0
  191. data/vendor/riddle/lib/riddle/configuration/searchd.rb +28 -0
  192. data/vendor/riddle/lib/riddle/configuration/section.rb +43 -0
  193. data/vendor/riddle/lib/riddle/configuration/source.rb +23 -0
  194. data/vendor/riddle/lib/riddle/configuration/sql_source.rb +53 -0
  195. data/vendor/riddle/lib/riddle/configuration/xml_source.rb +29 -0
  196. data/vendor/riddle/lib/riddle/configuration.rb +33 -0
  197. data/vendor/riddle/lib/riddle/controller.rb +78 -0
  198. data/vendor/riddle/lib/riddle.rb +51 -0
  199. 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,7 @@
1
+ Riddle.loaded_version = '0.9.9'
2
+
3
+ require 'riddle/0.9.9/client'
4
+ require 'riddle/0.9.9/client/filter'
5
+ require 'riddle/0.9.9/configuration/searchd'
6
+
7
+ Riddle.escape_pattern = /[\(\)\|\-!@~"&\/\\\^\$=]/
@@ -0,0 +1,11 @@
1
+ class Riddle::AutoVersion
2
+ def self.configure
3
+ controller = Riddle::Controller.new nil, ''
4
+ version = controller.sphinx_version
5
+
6
+ case version
7
+ when '0.9.8', '0.9.9'
8
+ require "riddle/#{version}"
9
+ end
10
+ end
11
+ 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