thinking-sphinx 2.1.0 → 3.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
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'