thinking-sphinx 2.1.0 → 3.0.0.pre

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 (352) hide show
  1. data/.gitignore +8 -0
  2. data/.travis.yml +13 -0
  3. data/Appraisals +7 -0
  4. data/Gemfile +10 -0
  5. data/HISTORY +2 -267
  6. data/LICENCE +1 -1
  7. data/README.textile +194 -226
  8. data/Rakefile +24 -0
  9. data/gemfiles/.gitignore +1 -0
  10. data/gemfiles/rails_3_1.gemfile +11 -0
  11. data/gemfiles/rails_3_2.gemfile +11 -0
  12. data/lib/thinking-sphinx.rb +1 -1
  13. data/lib/thinking_sphinx.rb +34 -292
  14. data/lib/thinking_sphinx/active_record.rb +22 -383
  15. data/lib/thinking_sphinx/active_record/association.rb +9 -0
  16. data/lib/thinking_sphinx/active_record/association_proxy.rb +68 -0
  17. data/lib/thinking_sphinx/active_record/associations.rb +68 -0
  18. data/lib/thinking_sphinx/active_record/attribute.rb +20 -0
  19. data/lib/thinking_sphinx/active_record/attribute/sphinx_presenter.rb +32 -0
  20. data/lib/thinking_sphinx/active_record/attribute/type.rb +79 -0
  21. data/lib/thinking_sphinx/active_record/attribute/values.rb +18 -0
  22. data/lib/thinking_sphinx/active_record/base.rb +36 -0
  23. data/lib/thinking_sphinx/active_record/callbacks/delete_callbacks.rb +31 -0
  24. data/lib/thinking_sphinx/active_record/callbacks/delta_callbacks.rb +55 -0
  25. data/lib/thinking_sphinx/active_record/callbacks/update_callbacks.rb +59 -0
  26. data/lib/thinking_sphinx/active_record/column.rb +30 -0
  27. data/lib/thinking_sphinx/active_record/database_adapters.rb +51 -0
  28. data/lib/thinking_sphinx/active_record/database_adapters/abstract_adapter.rb +13 -0
  29. data/lib/thinking_sphinx/active_record/database_adapters/mysql_adapter.rb +23 -0
  30. data/lib/thinking_sphinx/active_record/database_adapters/postgresql_adapter.rb +25 -0
  31. data/lib/thinking_sphinx/active_record/field.rb +11 -0
  32. data/lib/thinking_sphinx/active_record/index.rb +55 -0
  33. data/lib/thinking_sphinx/active_record/interpreter.rb +47 -0
  34. data/lib/thinking_sphinx/active_record/log_subscriber.rb +10 -58
  35. data/lib/thinking_sphinx/active_record/property.rb +28 -0
  36. data/lib/thinking_sphinx/active_record/property_sql_presenter.rb +60 -0
  37. data/lib/thinking_sphinx/active_record/sql_builder.rb +159 -0
  38. data/lib/thinking_sphinx/active_record/sql_source.rb +138 -0
  39. data/lib/thinking_sphinx/active_record/sql_source/template.rb +46 -0
  40. data/lib/thinking_sphinx/batched_search.rb +26 -0
  41. data/lib/thinking_sphinx/callbacks.rb +15 -0
  42. data/lib/thinking_sphinx/configuration.rb +80 -331
  43. data/lib/thinking_sphinx/configuration/consistent_ids.rb +31 -0
  44. data/lib/thinking_sphinx/configuration/defaults.rb +5 -0
  45. data/lib/thinking_sphinx/core.rb +6 -0
  46. data/lib/thinking_sphinx/core/index.rb +68 -0
  47. data/lib/thinking_sphinx/core/interpreter.rb +19 -0
  48. data/lib/thinking_sphinx/deltas.rb +35 -26
  49. data/lib/thinking_sphinx/deltas/default_delta.rb +56 -56
  50. data/lib/thinking_sphinx/excerpter.rb +23 -21
  51. data/lib/thinking_sphinx/facet.rb +22 -127
  52. data/lib/thinking_sphinx/facet_search.rb +95 -162
  53. data/lib/thinking_sphinx/index.rb +39 -143
  54. data/lib/thinking_sphinx/index_set.rb +51 -0
  55. data/lib/thinking_sphinx/masks.rb +8 -0
  56. data/lib/thinking_sphinx/masks/group_enumerators_mask.rb +23 -0
  57. data/lib/thinking_sphinx/masks/pagination_mask.rb +60 -0
  58. data/lib/thinking_sphinx/masks/scopes_mask.rb +35 -0
  59. data/lib/thinking_sphinx/masks/weight_enumerator_mask.rb +11 -0
  60. data/lib/thinking_sphinx/middlewares.rb +36 -0
  61. data/lib/thinking_sphinx/middlewares/active_record_translator.rb +73 -0
  62. data/lib/thinking_sphinx/middlewares/geographer.rb +53 -0
  63. data/lib/thinking_sphinx/middlewares/glazier.rb +39 -0
  64. data/lib/thinking_sphinx/middlewares/ids_only.rb +13 -0
  65. data/lib/thinking_sphinx/middlewares/inquirer.rb +62 -0
  66. data/lib/thinking_sphinx/middlewares/middleware.rb +9 -0
  67. data/lib/thinking_sphinx/middlewares/sphinxql.rb +149 -0
  68. data/lib/thinking_sphinx/middlewares/stale_id_checker.rb +45 -0
  69. data/lib/thinking_sphinx/middlewares/stale_id_filter.rb +46 -0
  70. data/lib/thinking_sphinx/panes.rb +8 -0
  71. data/lib/thinking_sphinx/panes/attributes_pane.rb +9 -0
  72. data/lib/thinking_sphinx/panes/distance_pane.rb +13 -0
  73. data/lib/thinking_sphinx/panes/excerpts_pane.rb +37 -0
  74. data/lib/thinking_sphinx/panes/weight_pane.rb +9 -0
  75. data/lib/thinking_sphinx/railtie.rb +6 -40
  76. data/lib/thinking_sphinx/rake_interface.rb +47 -0
  77. data/lib/thinking_sphinx/real_time.rb +11 -0
  78. data/lib/thinking_sphinx/real_time/attribute.rb +5 -0
  79. data/lib/thinking_sphinx/real_time/callbacks/real_time_callbacks.rb +48 -0
  80. data/lib/thinking_sphinx/real_time/field.rb +3 -0
  81. data/lib/thinking_sphinx/real_time/index.rb +47 -0
  82. data/lib/thinking_sphinx/real_time/index/template.rb +33 -0
  83. data/lib/thinking_sphinx/real_time/interpreter.rb +23 -0
  84. data/lib/thinking_sphinx/real_time/property.rb +16 -0
  85. data/lib/thinking_sphinx/scopes.rb +22 -0
  86. data/lib/thinking_sphinx/search.rb +90 -1028
  87. data/lib/thinking_sphinx/search/batch_inquirer.rb +27 -0
  88. data/lib/thinking_sphinx/search/context.rb +26 -0
  89. data/lib/thinking_sphinx/search/glaze.rb +32 -0
  90. data/lib/thinking_sphinx/search/merger.rb +24 -0
  91. data/lib/thinking_sphinx/search/query.rb +43 -0
  92. data/lib/thinking_sphinx/search/stale_ids_exception.rb +11 -0
  93. data/lib/thinking_sphinx/search/translator.rb +50 -0
  94. data/lib/thinking_sphinx/tasks.rb +22 -125
  95. data/lib/thinking_sphinx/test.rb +9 -19
  96. data/sketchpad.rb +58 -0
  97. data/spec/acceptance/association_scoping_spec.rb +23 -0
  98. data/spec/acceptance/attribute_access_spec.rb +39 -0
  99. data/spec/acceptance/attribute_updates_spec.rb +16 -0
  100. data/spec/acceptance/batch_searching_spec.rb +21 -0
  101. data/spec/acceptance/big_integers_spec.rb +27 -0
  102. data/spec/acceptance/excerpts_spec.rb +14 -0
  103. data/spec/acceptance/facets_spec.rb +122 -0
  104. data/spec/acceptance/geosearching_spec.rb +39 -0
  105. data/spec/acceptance/grouping_by_attributes_spec.rb +77 -0
  106. data/spec/acceptance/paginating_search_results_spec.rb +24 -0
  107. data/spec/acceptance/remove_deleted_records_spec.rb +23 -0
  108. data/spec/acceptance/search_counts_spec.rb +18 -0
  109. data/spec/acceptance/search_for_just_ids_spec.rb +19 -0
  110. data/spec/acceptance/searching_across_models_spec.rb +28 -0
  111. data/spec/acceptance/searching_on_fields_spec.rb +56 -0
  112. data/spec/acceptance/searching_with_filters_spec.rb +109 -0
  113. data/spec/acceptance/searching_with_sti_spec.rb +55 -0
  114. data/spec/acceptance/searching_within_a_model_spec.rb +52 -0
  115. data/spec/acceptance/sorting_search_results_spec.rb +41 -0
  116. data/spec/acceptance/spec_helper.rb +4 -0
  117. data/spec/acceptance/specifying_sql_spec.rb +62 -0
  118. data/spec/acceptance/sphinx_scopes_spec.rb +49 -0
  119. data/spec/acceptance/sql_deltas_spec.rb +43 -0
  120. data/spec/acceptance/support/database_cleaner.rb +11 -0
  121. data/spec/acceptance/support/sphinx_controller.rb +39 -0
  122. data/spec/acceptance/support/sphinx_helpers.rb +24 -0
  123. data/spec/acceptance/suspended_deltas_spec.rb +20 -0
  124. data/spec/internal/.gitignore +1 -0
  125. data/spec/internal/app/indices/animal_index.rb +3 -0
  126. data/spec/internal/app/indices/article_index.rb +24 -0
  127. data/spec/internal/app/indices/book_index.rb +8 -0
  128. data/spec/internal/app/indices/city_index.rb +6 -0
  129. data/spec/internal/app/indices/product_index.rb +3 -0
  130. data/spec/internal/app/indices/tee_index.rb +4 -0
  131. data/spec/internal/app/indices/user_index.rb +5 -0
  132. data/spec/internal/app/models/animal.rb +2 -0
  133. data/spec/internal/app/models/article.rb +5 -0
  134. data/spec/internal/app/models/bird.rb +2 -0
  135. data/spec/internal/app/models/book.rb +11 -0
  136. data/spec/internal/app/models/city.rb +2 -0
  137. data/spec/internal/app/models/colour.rb +3 -0
  138. data/spec/internal/app/models/flightless_bird.rb +2 -0
  139. data/spec/internal/app/models/mammal.rb +2 -0
  140. data/spec/internal/app/models/product.rb +3 -0
  141. data/spec/internal/app/models/tag.rb +4 -0
  142. data/{features/thinking_sphinx → spec/internal/app}/models/tagging.rb +1 -1
  143. data/spec/internal/app/models/tee.rb +3 -0
  144. data/spec/internal/app/models/tweet.rb +3 -0
  145. data/spec/internal/app/models/user.rb +3 -0
  146. data/spec/internal/config/database.yml +5 -0
  147. data/spec/internal/db/schema.rb +65 -0
  148. data/spec/internal/log/.gitignore +1 -0
  149. data/spec/spec_helper.rb +8 -49
  150. data/spec/support/sphinx_yaml_helpers.rb +9 -0
  151. data/spec/thinking_sphinx/active_record/association_spec.rb +12 -0
  152. data/spec/thinking_sphinx/active_record/associations_spec.rb +184 -0
  153. data/spec/thinking_sphinx/active_record/attribute/type_spec.rb +147 -0
  154. data/spec/thinking_sphinx/active_record/base_spec.rb +61 -0
  155. data/spec/thinking_sphinx/active_record/callbacks/delete_callbacks_spec.rb +80 -0
  156. data/spec/thinking_sphinx/active_record/callbacks/delta_callbacks_spec.rb +147 -0
  157. data/spec/thinking_sphinx/active_record/callbacks/update_callbacks_spec.rb +69 -0
  158. data/spec/thinking_sphinx/active_record/column_spec.rb +47 -0
  159. data/spec/thinking_sphinx/active_record/database_adapters/abstract_adapter_spec.rb +31 -0
  160. data/spec/thinking_sphinx/active_record/database_adapters/mysql_adapter_spec.rb +43 -0
  161. data/spec/thinking_sphinx/active_record/database_adapters/postgresql_adapter_spec.rb +45 -0
  162. data/spec/thinking_sphinx/active_record/database_adapters_spec.rb +108 -0
  163. data/spec/thinking_sphinx/active_record/field_spec.rb +36 -0
  164. data/spec/thinking_sphinx/active_record/index_spec.rb +208 -0
  165. data/spec/thinking_sphinx/active_record/interpreter_spec.rb +293 -0
  166. data/spec/thinking_sphinx/active_record/property_sql_presenter_spec.rb +162 -0
  167. data/spec/thinking_sphinx/active_record/sql_builder_spec.rb +666 -0
  168. data/spec/thinking_sphinx/active_record/sql_source_spec.rb +401 -0
  169. data/spec/thinking_sphinx/configuration_spec.rb +264 -171
  170. data/spec/thinking_sphinx/deltas/default_delta_spec.rb +116 -0
  171. data/spec/thinking_sphinx/deltas_spec.rb +58 -0
  172. data/spec/thinking_sphinx/excerpter_spec.rb +40 -38
  173. data/spec/thinking_sphinx/facet_search_spec.rb +49 -151
  174. data/spec/thinking_sphinx/index_set_spec.rb +68 -0
  175. data/spec/thinking_sphinx/index_spec.rb +91 -155
  176. data/spec/thinking_sphinx/masks/pagination_mask_spec.rb +121 -0
  177. data/spec/thinking_sphinx/masks/scopes_mask_spec.rb +68 -0
  178. data/spec/thinking_sphinx/middlewares/active_record_translator_spec.rb +132 -0
  179. data/spec/thinking_sphinx/middlewares/geographer_spec.rb +89 -0
  180. data/spec/thinking_sphinx/middlewares/glazier_spec.rb +62 -0
  181. data/spec/thinking_sphinx/middlewares/inquirer_spec.rb +55 -0
  182. data/spec/thinking_sphinx/middlewares/sphinxql_spec.rb +271 -0
  183. data/spec/thinking_sphinx/middlewares/stale_id_checker_spec.rb +47 -0
  184. data/spec/thinking_sphinx/middlewares/stale_id_filter_spec.rb +91 -0
  185. data/spec/thinking_sphinx/panes/attributes_pane_spec.rb +21 -0
  186. data/spec/thinking_sphinx/panes/distance_pane_spec.rb +41 -0
  187. data/spec/thinking_sphinx/panes/excerpts_pane_spec.rb +53 -0
  188. data/spec/thinking_sphinx/panes/weight_pane_spec.rb +20 -0
  189. data/spec/thinking_sphinx/rake_interface_spec.rb +147 -0
  190. data/spec/thinking_sphinx/real_time/attribute_spec.rb +62 -0
  191. data/spec/thinking_sphinx/real_time/callbacks/real_time_callbacks_spec.rb +76 -0
  192. data/spec/thinking_sphinx/real_time/field_spec.rb +54 -0
  193. data/spec/thinking_sphinx/real_time/index_spec.rb +154 -0
  194. data/spec/thinking_sphinx/real_time/interpreter_spec.rb +147 -0
  195. data/spec/thinking_sphinx/scopes_spec.rb +38 -0
  196. data/spec/thinking_sphinx/search/glaze_spec.rb +55 -0
  197. data/spec/thinking_sphinx/search/query_spec.rb +46 -0
  198. data/spec/thinking_sphinx/search_spec.rb +65 -1357
  199. data/spec/thinking_sphinx_spec.rb +19 -182
  200. data/thinking-sphinx.gemspec +33 -0
  201. metadata +318 -431
  202. data/features/abstract_inheritance.feature +0 -10
  203. data/features/alternate_primary_key.feature +0 -27
  204. data/features/attribute_transformation.feature +0 -22
  205. data/features/attribute_updates.feature +0 -79
  206. data/features/deleting_instances.feature +0 -70
  207. data/features/direct_attributes.feature +0 -11
  208. data/features/excerpts.feature +0 -21
  209. data/features/extensible_delta_indexing.feature +0 -9
  210. data/features/facets.feature +0 -88
  211. data/features/facets_across_model.feature +0 -29
  212. data/features/field_sorting.feature +0 -18
  213. data/features/handling_edits.feature +0 -97
  214. data/features/retry_stale_indexes.feature +0 -24
  215. data/features/searching_across_models.feature +0 -20
  216. data/features/searching_by_index.feature +0 -41
  217. data/features/searching_by_model.feature +0 -175
  218. data/features/searching_with_find_arguments.feature +0 -56
  219. data/features/sphinx_detection.feature +0 -25
  220. data/features/sphinx_scopes.feature +0 -68
  221. data/features/step_definitions/alpha_steps.rb +0 -16
  222. data/features/step_definitions/beta_steps.rb +0 -7
  223. data/features/step_definitions/common_steps.rb +0 -205
  224. data/features/step_definitions/extensible_delta_indexing_steps.rb +0 -7
  225. data/features/step_definitions/facet_steps.rb +0 -96
  226. data/features/step_definitions/find_arguments_steps.rb +0 -36
  227. data/features/step_definitions/gamma_steps.rb +0 -15
  228. data/features/step_definitions/scope_steps.rb +0 -19
  229. data/features/step_definitions/search_steps.rb +0 -94
  230. data/features/step_definitions/sphinx_steps.rb +0 -35
  231. data/features/sti_searching.feature +0 -19
  232. data/features/support/env.rb +0 -24
  233. data/features/support/lib/generic_delta_handler.rb +0 -8
  234. data/features/thinking_sphinx/database.example.yml +0 -3
  235. data/features/thinking_sphinx/db/.gitignore +0 -1
  236. data/features/thinking_sphinx/db/fixtures/alphas.rb +0 -8
  237. data/features/thinking_sphinx/db/fixtures/authors.rb +0 -1
  238. data/features/thinking_sphinx/db/fixtures/betas.rb +0 -11
  239. data/features/thinking_sphinx/db/fixtures/boxes.rb +0 -9
  240. data/features/thinking_sphinx/db/fixtures/categories.rb +0 -1
  241. data/features/thinking_sphinx/db/fixtures/cats.rb +0 -3
  242. data/features/thinking_sphinx/db/fixtures/comments.rb +0 -24
  243. data/features/thinking_sphinx/db/fixtures/developers.rb +0 -31
  244. data/features/thinking_sphinx/db/fixtures/dogs.rb +0 -3
  245. data/features/thinking_sphinx/db/fixtures/extensible_betas.rb +0 -10
  246. data/features/thinking_sphinx/db/fixtures/foxes.rb +0 -3
  247. data/features/thinking_sphinx/db/fixtures/gammas.rb +0 -10
  248. data/features/thinking_sphinx/db/fixtures/music.rb +0 -4
  249. data/features/thinking_sphinx/db/fixtures/people.rb +0 -1001
  250. data/features/thinking_sphinx/db/fixtures/post_keywords.txt +0 -1
  251. data/features/thinking_sphinx/db/fixtures/posts.rb +0 -10
  252. data/features/thinking_sphinx/db/fixtures/robots.rb +0 -8
  253. data/features/thinking_sphinx/db/fixtures/tags.rb +0 -27
  254. data/features/thinking_sphinx/db/migrations/create_alphas.rb +0 -8
  255. data/features/thinking_sphinx/db/migrations/create_animals.rb +0 -5
  256. data/features/thinking_sphinx/db/migrations/create_authors.rb +0 -3
  257. data/features/thinking_sphinx/db/migrations/create_authors_posts.rb +0 -6
  258. data/features/thinking_sphinx/db/migrations/create_betas.rb +0 -5
  259. data/features/thinking_sphinx/db/migrations/create_boxes.rb +0 -5
  260. data/features/thinking_sphinx/db/migrations/create_categories.rb +0 -3
  261. data/features/thinking_sphinx/db/migrations/create_comments.rb +0 -10
  262. data/features/thinking_sphinx/db/migrations/create_developers.rb +0 -7
  263. data/features/thinking_sphinx/db/migrations/create_extensible_betas.rb +0 -5
  264. data/features/thinking_sphinx/db/migrations/create_gammas.rb +0 -3
  265. data/features/thinking_sphinx/db/migrations/create_genres.rb +0 -3
  266. data/features/thinking_sphinx/db/migrations/create_music.rb +0 -6
  267. data/features/thinking_sphinx/db/migrations/create_people.rb +0 -13
  268. data/features/thinking_sphinx/db/migrations/create_posts.rb +0 -6
  269. data/features/thinking_sphinx/db/migrations/create_robots.rb +0 -4
  270. data/features/thinking_sphinx/db/migrations/create_taggings.rb +0 -5
  271. data/features/thinking_sphinx/db/migrations/create_tags.rb +0 -4
  272. data/features/thinking_sphinx/models/alpha.rb +0 -23
  273. data/features/thinking_sphinx/models/andrew.rb +0 -17
  274. data/features/thinking_sphinx/models/animal.rb +0 -5
  275. data/features/thinking_sphinx/models/author.rb +0 -3
  276. data/features/thinking_sphinx/models/beta.rb +0 -13
  277. data/features/thinking_sphinx/models/box.rb +0 -8
  278. data/features/thinking_sphinx/models/cat.rb +0 -3
  279. data/features/thinking_sphinx/models/category.rb +0 -4
  280. data/features/thinking_sphinx/models/comment.rb +0 -10
  281. data/features/thinking_sphinx/models/developer.rb +0 -21
  282. data/features/thinking_sphinx/models/dog.rb +0 -3
  283. data/features/thinking_sphinx/models/extensible_beta.rb +0 -9
  284. data/features/thinking_sphinx/models/fox.rb +0 -5
  285. data/features/thinking_sphinx/models/gamma.rb +0 -5
  286. data/features/thinking_sphinx/models/genre.rb +0 -3
  287. data/features/thinking_sphinx/models/medium.rb +0 -5
  288. data/features/thinking_sphinx/models/music.rb +0 -10
  289. data/features/thinking_sphinx/models/person.rb +0 -24
  290. data/features/thinking_sphinx/models/post.rb +0 -22
  291. data/features/thinking_sphinx/models/robot.rb +0 -12
  292. data/features/thinking_sphinx/models/tag.rb +0 -3
  293. data/lib/cucumber/thinking_sphinx/external_world.rb +0 -12
  294. data/lib/cucumber/thinking_sphinx/internal_world.rb +0 -137
  295. data/lib/cucumber/thinking_sphinx/sql_logger.rb +0 -28
  296. data/lib/thinking_sphinx/action_controller.rb +0 -31
  297. data/lib/thinking_sphinx/active_record/attribute_updates.rb +0 -54
  298. data/lib/thinking_sphinx/active_record/collection_proxy.rb +0 -47
  299. data/lib/thinking_sphinx/active_record/collection_proxy_with_scopes.rb +0 -27
  300. data/lib/thinking_sphinx/active_record/delta.rb +0 -67
  301. data/lib/thinking_sphinx/active_record/has_many_association.rb +0 -44
  302. data/lib/thinking_sphinx/active_record/has_many_association_with_scopes.rb +0 -21
  303. data/lib/thinking_sphinx/active_record/scopes.rb +0 -110
  304. data/lib/thinking_sphinx/adapters/abstract_adapter.rb +0 -94
  305. data/lib/thinking_sphinx/adapters/mysql_adapter.rb +0 -62
  306. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +0 -188
  307. data/lib/thinking_sphinx/association.rb +0 -230
  308. data/lib/thinking_sphinx/attribute.rb +0 -405
  309. data/lib/thinking_sphinx/auto_version.rb +0 -40
  310. data/lib/thinking_sphinx/bundled_search.rb +0 -40
  311. data/lib/thinking_sphinx/class_facet.rb +0 -20
  312. data/lib/thinking_sphinx/connection.rb +0 -71
  313. data/lib/thinking_sphinx/context.rb +0 -81
  314. data/lib/thinking_sphinx/core/string.rb +0 -15
  315. data/lib/thinking_sphinx/deltas/delete_job.rb +0 -16
  316. data/lib/thinking_sphinx/deltas/index_job.rb +0 -17
  317. data/lib/thinking_sphinx/deploy/capistrano.rb +0 -99
  318. data/lib/thinking_sphinx/field.rb +0 -98
  319. data/lib/thinking_sphinx/index/builder.rb +0 -315
  320. data/lib/thinking_sphinx/index/faux_column.rb +0 -118
  321. data/lib/thinking_sphinx/join.rb +0 -37
  322. data/lib/thinking_sphinx/property.rb +0 -187
  323. data/lib/thinking_sphinx/search_methods.rb +0 -439
  324. data/lib/thinking_sphinx/sinatra.rb +0 -7
  325. data/lib/thinking_sphinx/source.rb +0 -194
  326. data/lib/thinking_sphinx/source/internal_properties.rb +0 -51
  327. data/lib/thinking_sphinx/source/sql.rb +0 -174
  328. data/spec/fixtures/data.sql +0 -32
  329. data/spec/fixtures/database.yml.default +0 -3
  330. data/spec/fixtures/models.rb +0 -164
  331. data/spec/fixtures/structure.sql +0 -146
  332. data/spec/sphinx_helper.rb +0 -60
  333. data/spec/support/rails.rb +0 -25
  334. data/spec/thinking_sphinx/active_record/delta_spec.rb +0 -123
  335. data/spec/thinking_sphinx/active_record/has_many_association_spec.rb +0 -173
  336. data/spec/thinking_sphinx/active_record/scopes_spec.rb +0 -177
  337. data/spec/thinking_sphinx/active_record_spec.rb +0 -573
  338. data/spec/thinking_sphinx/adapters/abstract_adapter_spec.rb +0 -163
  339. data/spec/thinking_sphinx/association_spec.rb +0 -250
  340. data/spec/thinking_sphinx/attribute_spec.rb +0 -552
  341. data/spec/thinking_sphinx/auto_version_spec.rb +0 -103
  342. data/spec/thinking_sphinx/connection_spec.rb +0 -77
  343. data/spec/thinking_sphinx/context_spec.rb +0 -127
  344. data/spec/thinking_sphinx/core/array_spec.rb +0 -9
  345. data/spec/thinking_sphinx/core/string_spec.rb +0 -9
  346. data/spec/thinking_sphinx/facet_spec.rb +0 -359
  347. data/spec/thinking_sphinx/field_spec.rb +0 -127
  348. data/spec/thinking_sphinx/index/builder_spec.rb +0 -532
  349. data/spec/thinking_sphinx/index/faux_column_spec.rb +0 -36
  350. data/spec/thinking_sphinx/search_methods_spec.rb +0 -156
  351. data/spec/thinking_sphinx/source_spec.rb +0 -267
  352. data/spec/thinking_sphinx/test_spec.rb +0 -20
@@ -0,0 +1,138 @@
1
+ class ThinkingSphinx::ActiveRecord::SQLSource < Riddle::Configuration::SQLSource
2
+ attr_reader :model, :database_settings, :options
3
+ attr_accessor :fields, :attributes, :associations, :conditions, :groupings
4
+
5
+ # Options:
6
+ # - :name
7
+ # - :offset
8
+ # - :delta_processor
9
+ # - :delta?
10
+ # - :disable_range?
11
+ # - :group_concat_max_len
12
+ # - :utf8?
13
+ #
14
+ def initialize(model, options = {})
15
+ @model = model
16
+ @database_settings = model.connection.instance_variable_get(:@config).clone
17
+ @options = options
18
+
19
+ @fields = []
20
+ @attributes = []
21
+ @associations = []
22
+ @conditions = []
23
+ @groupings = []
24
+
25
+ Template.new(self).apply
26
+
27
+ name = "#{options[:name] || model.name.downcase}_#{name_suffix}"
28
+
29
+ super name, type
30
+ end
31
+
32
+ def adapter
33
+ @adapter ||= ThinkingSphinx::ActiveRecord::DatabaseAdapters.
34
+ adapter_for(@model)
35
+ end
36
+
37
+ def delta_processor
38
+ options[:delta_processor].try(:new, adapter)
39
+ end
40
+
41
+ def delta?
42
+ options[:delta?]
43
+ end
44
+
45
+ def disable_range?
46
+ options[:disable_range?]
47
+ end
48
+
49
+ def facets
50
+ properties.select(&:facet?)
51
+ end
52
+
53
+ def offset
54
+ options[:offset]
55
+ end
56
+
57
+ def primary_key
58
+ options[:primary_key]
59
+ end
60
+
61
+ def render
62
+ self.class.settings.each do |setting|
63
+ value = config.settings[setting.to_s]
64
+ send("#{setting}=", value) unless value.nil?
65
+ end
66
+
67
+ prepare_for_render unless @prepared
68
+
69
+ super
70
+ end
71
+
72
+ def type
73
+ @type ||= case adapter
74
+ when ThinkingSphinx::ActiveRecord::DatabaseAdapters::MySQLAdapter
75
+ 'mysql'
76
+ when ThinkingSphinx::ActiveRecord::DatabaseAdapters::PostgreSQLAdapter
77
+ 'pgsql'
78
+ else
79
+ raise "Unknown Adapter Type: #{adapter.class.name}"
80
+ end
81
+ end
82
+
83
+ private
84
+
85
+ def attribute_array_for(type)
86
+ instance_variable_get "@sql_attr_#{type}".to_sym
87
+ end
88
+
89
+ def builder
90
+ @builder ||= ThinkingSphinx::ActiveRecord::SQLBuilder.new self
91
+ end
92
+
93
+ def config
94
+ ThinkingSphinx::Configuration.instance
95
+ end
96
+
97
+ def name_suffix
98
+ delta? ? 'delta' : 'core'
99
+ end
100
+
101
+ def prepare_for_render
102
+ set_database_settings
103
+
104
+ fields.each do |field|
105
+ @sql_field_string << field.name if field.with_attribute?
106
+ @sql_file_field << field.name if field.file?
107
+ end
108
+
109
+ attributes.each do |attribute|
110
+ presenter = ThinkingSphinx::ActiveRecord::Attribute::SphinxPresenter.new(attribute)
111
+
112
+ attribute_array_for(presenter.collection_type) << presenter.declaration
113
+ end
114
+
115
+ @sql_query = builder.sql_query
116
+ @sql_query_range = builder.sql_query_range
117
+ @sql_query_info = builder.sql_query_info
118
+ @sql_query_pre += builder.sql_query_pre
119
+
120
+ @prepared = true
121
+ end
122
+
123
+ def properties
124
+ fields + attributes
125
+ end
126
+
127
+ def set_database_settings
128
+ @sql_host ||= database_settings[:host] || 'localhost'
129
+ @sql_user ||= database_settings[:username] || database_settings[:user] ||
130
+ ENV['USER']
131
+ @sql_pass ||= database_settings[:password].to_s.gsub('#', '\#')
132
+ @sql_db ||= database_settings[:database]
133
+ @sql_port ||= database_settings[:port]
134
+ @sql_sock ||= database_settings[:socket]
135
+ end
136
+ end
137
+
138
+ require 'thinking_sphinx/active_record/sql_source/template'
@@ -0,0 +1,46 @@
1
+ class ThinkingSphinx::ActiveRecord::SQLSource::Template
2
+ attr_reader :source
3
+
4
+ def initialize(source)
5
+ @source = source
6
+ end
7
+
8
+ def apply
9
+ add_field class_column, :sphinx_internal_class, :facet => true
10
+
11
+ add_attribute :id, :sphinx_internal_id, nil
12
+ add_attribute '0', :sphinx_deleted, :integer
13
+ end
14
+
15
+ private
16
+
17
+ def add_attribute(column, name, type, options = {})
18
+ source.attributes << ThinkingSphinx::ActiveRecord::Attribute.new(
19
+ source.model, ThinkingSphinx::ActiveRecord::Column.new(column),
20
+ options.merge(:as => name, :type => type)
21
+ )
22
+ end
23
+
24
+ def add_field(column, name, options = {})
25
+ source.fields << ThinkingSphinx::ActiveRecord::Field.new(
26
+ source.model, ThinkingSphinx::ActiveRecord::Column.new(column),
27
+ options.merge(:as => name)
28
+ )
29
+ end
30
+
31
+ def class_column
32
+ if inheriting?
33
+ source.adapter.convert_nulls model.inheritance_column, "'#{model.name}'"
34
+ else
35
+ "'#{model.name}'"
36
+ end
37
+ end
38
+
39
+ def inheriting?
40
+ model.column_names.include?(model.inheritance_column)
41
+ end
42
+
43
+ def model
44
+ source.model
45
+ end
46
+ end
@@ -0,0 +1,26 @@
1
+ class ThinkingSphinx::BatchedSearch
2
+ attr_accessor :searches
3
+
4
+ def initialize
5
+ @searches = []
6
+ end
7
+
8
+ def populate(middleware = ThinkingSphinx::Middlewares::DEFAULT)
9
+ return if populated? || searches.empty?
10
+
11
+ middleware.call contexts
12
+ searches.each &:populated!
13
+
14
+ @populated = true
15
+ end
16
+
17
+ private
18
+
19
+ def contexts
20
+ searches.collect &:context
21
+ end
22
+
23
+ def populated?
24
+ @populated
25
+ end
26
+ end
@@ -0,0 +1,15 @@
1
+ class ThinkingSphinx::Callbacks
2
+ attr_reader :instance
3
+
4
+ def self.callbacks(*methods)
5
+ mod = Module.new
6
+ methods.each do |method|
7
+ mod.send(:define_method, method) { |instance| new(instance).send(method) }
8
+ end
9
+ extend mod
10
+ end
11
+
12
+ def initialize(instance)
13
+ @instance = instance
14
+ end
15
+ end
@@ -1,361 +1,110 @@
1
- require 'erb'
2
- require 'singleton'
1
+ class ThinkingSphinx::Configuration < Riddle::Configuration
2
+ attr_accessor :configuration_file, :indices_location
3
3
 
4
- module ThinkingSphinx
5
- # This class both keeps track of the configuration settings for Sphinx and
6
- # also generates the resulting file for Sphinx to use.
7
- #
8
- # Here are the default settings, relative to Rails.root where relevant:
9
- #
10
- # config file:: config/#{environment}.sphinx.conf
11
- # searchd log file:: log/searchd.log
12
- # query log file:: log/searchd.query.log
13
- # pid file:: log/searchd.#{environment}.pid
14
- # searchd files:: db/sphinx/#{environment}/
15
- # address:: 127.0.0.1
16
- # port:: 9312
17
- # allow star:: false
18
- # stop timeout:: 5
19
- # min prefix length:: 1
20
- # min infix length:: 1
21
- # mem limit:: 64M
22
- # max matches:: 1000
23
- # morphology:: nil
24
- # charset type:: utf-8
25
- # charset table:: nil
26
- # ignore chars:: nil
27
- # html strip:: false
28
- # html remove elements:: ''
29
- # searchd_binary_name:: searchd
30
- # indexer_binary_name:: indexer
31
- # hard_retry_count:: 0
32
- #
33
- # If you want to change these settings, create a YAML file at
34
- # config/sphinx.yml with settings for each environment, in a similar
35
- # fashion to database.yml - using the following keys: config_file,
36
- # searchd_log_file, query_log_file, pid_file, searchd_file_path, port,
37
- # allow_star, enable_star, min_prefix_len, min_infix_len, mem_limit,
38
- # max_matches, morphology, charset_type, charset_table, ignore_chars,
39
- # html_strip, html_remove_elements, delayed_job_priority,
40
- # searchd_binary_name, indexer_binary_name.
41
- #
42
- # I think you've got the idea.
43
- #
44
- # Each setting in the YAML file is optional - so only put in the ones you
45
- # want to change.
46
- #
47
- # Keep in mind, if for some particular reason you're using a version of
48
- # Sphinx older than 0.9.8 r871 (that's prior to the proper 0.9.8 release),
49
- # don't set allow_star to true.
50
- #
51
- class Configuration
52
- include Singleton
4
+ attr_reader :index_paths
53
5
 
54
- SourceOptions = Riddle::Configuration::SQLSource.settings.map { |setting|
55
- setting.to_s
56
- } - %w( type sql_query sql_joined_field sql_file_field
57
- sql_query_range sql_attr_uint sql_attr_bool sql_attr_bigint sql_query_info
58
- sql_attr_timestamp sql_attr_str2ordinal sql_attr_float sql_attr_multi
59
- sql_attr_string sql_attr_str2wordcount sql_column_buffers sql_field_string
60
- sql_field_str2wordcount )
61
- IndexOptions = Riddle::Configuration::Index.settings.map { |setting|
62
- setting.to_s
63
- } - %w( source prefix_fields infix_fields )
64
- CustomOptions = %w( disable_range use_64_bit )
6
+ def initialize
7
+ super
65
8
 
66
- attr_accessor :searchd_file_path, :allow_star, :app_root,
67
- :model_directories, :delayed_job_priority, :indexed_models, :use_64_bit,
68
- :touched_reindex_file, :stop_timeout, :version, :shuffle,
69
- :hard_retry_count
9
+ @configuration_file = Rails.root.join 'config', "#{Rails.env}.sphinx.conf"
10
+ @index_paths = [Rails.root.join('app', 'indices')]
11
+ @indices_location = Rails.root.join 'db', 'sphinx', Rails.env
70
12
 
71
- attr_accessor :source_options, :index_options
72
- attr_reader :configuration
73
- attr_writer :controller
13
+ searchd.pid_file = Rails.root.join 'log', "#{Rails.env}.sphinx.pid"
14
+ searchd.log = Rails.root.join 'log', "#{Rails.env}.searchd.log"
15
+ searchd.query_log = Rails.root.join 'log', "#{Rails.env}.searchd.query.log"
16
+ searchd.binlog_path = Rails.root.join 'tmp', 'binlog', Rails.env
74
17
 
75
- @@environment = nil
18
+ searchd.address = settings['address']
19
+ searchd.address = Defaults::ADDRESS unless searchd.address.present?
20
+ searchd.mysql41 = settings['mysql41'] || settings['port'] ||
21
+ Defaults::PORT
22
+ # searchd.workers = 'threads'
76
23
 
77
- # Load in the configuration settings - this will look for config/sphinx.yml
78
- # and parse it according to the current environment.
79
- #
80
- def initialize(app_root = Dir.pwd)
81
- self.reset
82
- end
83
-
84
- def self.configure(&block)
85
- yield instance
86
- instance.reset(instance.app_root)
87
- end
88
-
89
- def reset(custom_app_root=nil)
90
- if custom_app_root
91
- self.app_root = custom_app_root
92
- else
93
- self.app_root = Merb.root if defined?(Merb)
94
- self.app_root = Sinatra::Application.root if defined?(Sinatra)
95
- self.app_root = Rails.root if defined?(Rails)
96
- self.app_root ||= app_root
97
- end
98
-
99
- @controller = nil
100
- @configuration = Riddle::Configuration.new
101
- @configuration.searchd.pid_file = "#{self.app_root}/log/searchd.#{environment}.pid"
102
- @configuration.searchd.log = "#{self.app_root}/log/searchd.log"
103
- @configuration.searchd.query_log = "#{self.app_root}/log/searchd.query.log"
104
-
105
- self.address = "127.0.0.1"
106
- self.port = 9312
107
- self.searchd_file_path = "#{self.app_root}/db/sphinx/#{environment}"
108
- self.allow_star = false
109
- self.stop_timeout = 5
110
- self.model_directories = initial_model_directories
111
- self.delayed_job_priority = 0
112
- self.indexed_models = []
113
- self.shuffle = false
114
- self.hard_retry_count = 0
115
-
116
- self.source_options = {}
117
- self.index_options = {
118
- :charset_type => "utf-8"
119
- }
120
-
121
- self.version = nil
122
- parse_config
123
- if controller.respond_to?(:sphinx_version)
124
- self.version ||= controller.sphinx_version
125
- end
126
-
127
- ThinkingSphinx::Attribute::SphinxTypeMappings.merge!(
128
- :string => :sql_attr_string
129
- ) if Riddle.loaded_version.to_i > 1
130
-
131
- self
132
- end
133
-
134
- def self.environment
135
- @@environment ||= if defined?(Merb)
136
- Merb.environment
137
- elsif defined?(Rails)
138
- Rails.env
139
- elsif defined?(Sinatra)
140
- Sinatra::Application.environment.to_s
141
- else
142
- ENV['RAILS_ENV'] || 'development'
143
- end
144
- end
145
-
146
- def self.reset_environment
147
- ThinkingSphinx.mutex.synchronize do
148
- @@environment = nil
149
- end
150
- end
151
-
152
- def environment
153
- self.class.environment
154
- end
155
-
156
- def controller
157
- @controller ||= Riddle::Controller.new @configuration,
158
- "#{self.app_root}/config/#{environment}.sphinx.conf"
159
- end
160
-
161
- def generate
162
- @configuration.indices.clear
163
-
164
- ThinkingSphinx.context.indexed_models.each do |model|
165
- model = model.constantize
166
- model.define_indexes
167
- @configuration.indices.concat model.to_riddle
168
-
169
- enforce_common_attribute_types
170
- end
171
- end
172
-
173
- # Generate the config file for Sphinx by using all the settings defined and
174
- # looping through all the models with indexes to build the relevant
175
- # indexer and searchd configuration, and sources and indexes details.
176
- #
177
- def build(file_path=nil)
178
- file_path ||= "#{self.config_file}"
179
-
180
- generate
181
-
182
- open(file_path, "w") do |file|
183
- file.write @configuration.render
184
- end
185
- end
186
-
187
- def address
188
- @address
189
- end
24
+ @offsets = {}
25
+ end
190
26
 
191
- def address=(address)
192
- @address = address
193
- @configuration.searchd.address = address
194
- end
27
+ def self.instance
28
+ @instance ||= new
29
+ end
195
30
 
196
- def port
197
- @port
198
- end
31
+ def self.reset
32
+ @instance = nil
33
+ end
199
34
 
200
- def port=(port)
201
- @port = port
202
- @configuration.searchd.port = port
203
- end
35
+ def connection
36
+ # If you use localhost, MySQL insists on a socket connection, but Sphinx
37
+ # requires a TCP connection. Using 127.0.0.1 fixes that.
38
+ address = searchd.address || '127.0.0.1'
39
+ address = '127.0.0.1' if address == 'localhost'
40
+
41
+ Mysql2::Client.new({
42
+ :host => address,
43
+ :port => searchd.mysql41,
44
+ :flags => Mysql2::Client::MULTI_STATEMENTS
45
+ }.merge(settings['connection_options'] || {}))
46
+ end
204
47
 
205
- def use_socket=(use_socket)
206
- if use_socket
207
- socket = "#{app_root}/tmp/sockets/searchd.#{self.environment}.sock"
208
- @configuration.searchd.listen = socket
209
- self.address = socket
48
+ def controller
49
+ @controller ||= begin
50
+ rc = Riddle::Controller.new self, configuration_file
51
+ if settings['bin_path'].present?
52
+ rc.bin_path = settings['bin_path'].gsub(/([^\/])$/, '\1/')
210
53
  end
54
+ rc
211
55
  end
56
+ end
212
57
 
213
- def pid_file
214
- @configuration.searchd.pid_file
215
- end
216
-
217
- def pid_file=(pid_file)
218
- @configuration.searchd.pid_file = pid_file
219
- end
220
-
221
- def searchd_log_file
222
- @configuration.searchd.log
223
- end
224
-
225
- def searchd_log_file=(file)
226
- @configuration.searchd.log = file
227
- end
228
-
229
- def query_log_file
230
- @configuration.searchd.query_log
231
- end
232
-
233
- def query_log_file=(file)
234
- @configuration.searchd.query_log = file
235
- end
236
-
237
- def config_file
238
- controller.path
239
- end
240
-
241
- def config_file=(file)
242
- controller.path = file
243
- end
244
-
245
- def bin_path
246
- controller.bin_path
247
- end
248
-
249
- def bin_path=(path)
250
- controller.bin_path = path
251
- end
252
-
253
- def searchd_binary_name
254
- controller.searchd_binary_name
255
- end
256
-
257
- def searchd_binary_name=(name)
258
- controller.searchd_binary_name = name
259
- end
260
-
261
- def indexer_binary_name
262
- controller.indexer_binary_name
263
- end
58
+ def indices_for_references(*references)
59
+ preload_indices
60
+ indices.select { |index| references.include?(index.reference) }
61
+ end
264
62
 
265
- def indexer_binary_name=(name)
266
- controller.indexer_binary_name = name
267
- end
63
+ def next_offset(reference)
64
+ @offsets[reference] ||= @offsets.keys.count
65
+ end
268
66
 
269
- attr_accessor :timeout
67
+ def preload_indices
68
+ return if @preloaded_indices
270
69
 
271
- def models_by_crc
272
- @models_by_crc ||= begin
273
- ThinkingSphinx.context.indexed_models.inject({}) do |hash, model|
274
- hash[model.constantize.to_crc32] = model
275
- model.constantize.descendants.each { |subclass|
276
- hash[subclass.to_crc32] = subclass.name
277
- }
278
- hash
279
- end
70
+ index_paths.each do |path|
71
+ Dir["#{path}/**/*.rb"].each do |file|
72
+ ActiveSupport::Dependencies.require_or_load file
280
73
  end
281
74
  end
282
75
 
283
- def touch_reindex_file(output)
284
- return FileUtils.touch(@touched_reindex_file) if @touched_reindex_file and output =~ /succesfully sent SIGHUP to searchd/
285
- false
286
- end
287
-
288
- private
289
-
290
- # Parse the config/sphinx.yml file - if it exists - then use the attribute
291
- # accessors to set the appropriate values. Nothing too clever.
292
- #
293
- def parse_config
294
- path = "#{app_root}/config/sphinx.yml"
295
- return unless File.exists?(path)
296
-
297
- conf = YAML::load(ERB.new(IO.read(path)).result)[environment]
298
-
299
- conf.each do |key,value|
300
- self.send("#{key}=", value) if self.respond_to?("#{key}=")
301
-
302
- set_sphinx_setting self.source_options, key, value, SourceOptions
303
- set_sphinx_setting self.index_options, key, value, IndexOptions
304
- set_sphinx_setting self.index_options, key, value, CustomOptions
305
- set_sphinx_setting @configuration.searchd, key, value
306
- set_sphinx_setting @configuration.indexer, key, value
307
- end unless conf.nil?
308
-
309
- self.bin_path += '/' unless self.bin_path.blank?
76
+ @preloaded_indices = true
77
+ end
310
78
 
311
- if self.allow_star
312
- self.index_options[:enable_star] = true
313
- self.index_options[:min_prefix_len] = 1
314
- end
315
- end
79
+ def render
80
+ preload_indices
316
81
 
317
- def set_sphinx_setting(object, key, value, allowed = {})
318
- if object.is_a?(Hash)
319
- object[key.to_sym] = value if allowed.include?(key.to_s)
320
- else
321
- object.send("#{key}=", value) if object.respond_to?("#{key}")
322
- send("#{key}=", value) if self.respond_to?("#{key}")
323
- end
324
- end
82
+ ThinkingSphinx::Configuration::ConsistentIds.new(indices).reconcile
325
83
 
326
- def enforce_common_attribute_types
327
- sql_indexes = configuration.indices.reject { |index|
328
- index.is_a? Riddle::Configuration::DistributedIndex
329
- }
84
+ super
85
+ end
330
86
 
331
- return unless sql_indexes.any? { |index|
332
- index.sources.any? { |source|
333
- source.sql_attr_bigint.include? :sphinx_internal_id
334
- }
335
- }
87
+ def render_to_file
88
+ FileUtils.mkdir_p searchd.binlog_path
336
89
 
337
- sql_indexes.each { |index|
338
- index.sources.each { |source|
339
- next if source.sql_attr_bigint.include? :sphinx_internal_id
90
+ open(configuration_file, 'w') { |file| file.write render }
91
+ end
340
92
 
341
- source.sql_attr_bigint << :sphinx_internal_id
342
- source.sql_attr_uint.delete :sphinx_internal_id
343
- }
344
- }
345
- end
93
+ def settings
94
+ @settings ||= File.exists?(settings_file) ? settings_to_hash : {}
95
+ end
346
96
 
347
- def initial_model_directories
348
- directories = ["#{app_root}/app/models/"] +
349
- Dir.glob("#{app_root}/vendor/plugins/*/app/models/")
97
+ private
350
98
 
351
- if defined?(Rails) && Rails.application
352
- directories += Rails.application.paths['app/models'].to_a
353
- directories += Rails.application.railties.engines.collect { |engine|
354
- engine.paths['app/models'].to_a
355
- }.flatten
356
- end
99
+ def settings_to_hash
100
+ contents = YAML.load(ERB.new(File.read(settings_file)).result)
101
+ contents && contents[Rails.env] || {}
102
+ end
357
103
 
358
- directories
359
- end
104
+ def settings_file
105
+ Rails.root.join 'config', 'thinking_sphinx.yml'
360
106
  end
361
107
  end
108
+
109
+ require 'thinking_sphinx/configuration/consistent_ids'
110
+ require 'thinking_sphinx/configuration/defaults'