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,30 @@
1
+ class ThinkingSphinx::ActiveRecord::Column
2
+ def initialize(*stack)
3
+ @stack = stack
4
+ @name = stack.pop
5
+ end
6
+
7
+ def __name
8
+ @name
9
+ end
10
+
11
+ def __stack
12
+ @stack
13
+ end
14
+
15
+ def string?
16
+ __name.is_a?(String)
17
+ end
18
+
19
+ def to_ary
20
+ [self]
21
+ end
22
+
23
+ private
24
+
25
+ def method_missing(method, *args, &block)
26
+ @stack << @name
27
+ @name = method
28
+ self
29
+ end
30
+ end
@@ -0,0 +1,51 @@
1
+ module ThinkingSphinx::ActiveRecord::DatabaseAdapters
2
+ def self.adapter_for(model)
3
+ return default.new(model) unless default.nil?
4
+
5
+ adapter = adapter_type_for(model)
6
+ klass = case adapter
7
+ when :mysql
8
+ ThinkingSphinx::ActiveRecord::DatabaseAdapters::MySQLAdapter
9
+ when :postgresql
10
+ ThinkingSphinx::ActiveRecord::DatabaseAdapters::PostgreSQLAdapter
11
+ else
12
+ raise "Invalid Database Adapter '#{adapter}': Thinking Sphinx only supports MySQL and PostgreSQL."
13
+ end
14
+
15
+ klass.new model
16
+ end
17
+
18
+ def self.adapter_type_for(model)
19
+ case model.connection.class.name
20
+ when "ActiveRecord::ConnectionAdapters::MysqlAdapter",
21
+ "ActiveRecord::ConnectionAdapters::Mysql2Adapter"
22
+ :mysql
23
+ when "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter"
24
+ :postgresql
25
+ when "ActiveRecord::ConnectionAdapters::JdbcAdapter"
26
+ case model.connection.config[:adapter]
27
+ when "jdbcmysql"
28
+ :mysql
29
+ when "jdbcpostgresql"
30
+ :postgresql
31
+ else
32
+ model.connection.config[:adapter]
33
+ end
34
+ else
35
+ model.connection.class.name
36
+ end
37
+ end
38
+
39
+ @default = nil
40
+ def self.default
41
+ @default
42
+ end
43
+
44
+ def self.default=(default)
45
+ @default = default
46
+ end
47
+ end
48
+
49
+ require 'thinking_sphinx/active_record/database_adapters/abstract_adapter'
50
+ require 'thinking_sphinx/active_record/database_adapters/mysql_adapter'
51
+ require 'thinking_sphinx/active_record/database_adapters/postgresql_adapter'
@@ -0,0 +1,13 @@
1
+ class ThinkingSphinx::ActiveRecord::DatabaseAdapters::AbstractAdapter
2
+ def initialize(model)
3
+ @model = model
4
+ end
5
+
6
+ def quote(column)
7
+ @model.connection.quote_column_name(column)
8
+ end
9
+
10
+ def quoted_table_name
11
+ @model.quoted_table_name
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ class ThinkingSphinx::ActiveRecord::DatabaseAdapters::MySQLAdapter <
2
+ ThinkingSphinx::ActiveRecord::DatabaseAdapters::AbstractAdapter
3
+
4
+ def boolean_value(value)
5
+ value ? 1 : 0
6
+ end
7
+
8
+ def cast_to_timestamp(clause)
9
+ "UNIX_TIMESTAMP(#{clause})"
10
+ end
11
+
12
+ def concatenate(clause, separator = ' ')
13
+ "CONCAT_WS('#{separator}', #{clause})"
14
+ end
15
+
16
+ def convert_nulls(clause, default = '')
17
+ "IFNULL(#{clause}, #{default})"
18
+ end
19
+
20
+ def group_concatenate(clause, separator = ' ')
21
+ "GROUP_CONCAT(#{clause} SEPARATOR '#{separator}')"
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ class ThinkingSphinx::ActiveRecord::DatabaseAdapters::PostgreSQLAdapter <
2
+ ThinkingSphinx::ActiveRecord::DatabaseAdapters::AbstractAdapter
3
+
4
+ def boolean_value(value)
5
+ value ? 'TRUE' : 'FALSE'
6
+ end
7
+
8
+ def cast_to_timestamp(clause)
9
+ "extract(epoch from #{clause})::int"
10
+ end
11
+
12
+ def concatenate(clause, separator = ' ')
13
+ clause.split(', ').collect { |part|
14
+ convert_nulls(part, "''")
15
+ }.join(" || '#{separator}' || ")
16
+ end
17
+
18
+ def convert_nulls(clause, default = '')
19
+ "COALESCE(#{clause}, #{default})"
20
+ end
21
+
22
+ def group_concatenate(clause, separator = ' ')
23
+ "array_to_string(array_agg(#{clause}), '#{separator}')"
24
+ end
25
+ end
@@ -0,0 +1,11 @@
1
+ class ThinkingSphinx::ActiveRecord::Field <
2
+ ThinkingSphinx::ActiveRecord::Property
3
+
4
+ def file?
5
+ options[:file]
6
+ end
7
+
8
+ def with_attribute?
9
+ options[:sortable] || options[:facet]
10
+ end
11
+ end
@@ -0,0 +1,55 @@
1
+ class ThinkingSphinx::ActiveRecord::Index < Riddle::Configuration::Index
2
+ include ThinkingSphinx::Core::Index
3
+
4
+ attr_reader :reference
5
+ attr_writer :definition_block
6
+
7
+ def append_source
8
+ ThinkingSphinx::ActiveRecord::SQLSource.new(
9
+ model, source_options
10
+ ).tap do |source|
11
+ sources << source
12
+ end
13
+ end
14
+
15
+ def delta?
16
+ @options[:delta?]
17
+ end
18
+
19
+ def delta_processor
20
+ @options[:delta_processor].try(:new, adapter)
21
+ end
22
+
23
+ def facets
24
+ @facets ||= sources.collect(&:facets).flatten
25
+ end
26
+
27
+ def unique_attribute_names
28
+ sources.collect(&:attributes).flatten.collect(&:name)
29
+ end
30
+
31
+ private
32
+
33
+ def adapter
34
+ @adapter ||= ThinkingSphinx::ActiveRecord::DatabaseAdapters.
35
+ adapter_for(model)
36
+ end
37
+
38
+ def interpreter
39
+ ThinkingSphinx::ActiveRecord::Interpreter
40
+ end
41
+
42
+ def name_suffix
43
+ @options[:delta?] ? 'delta' : 'core'
44
+ end
45
+
46
+ def source_options
47
+ {
48
+ :name => name,
49
+ :offset => offset,
50
+ :delta? => @options[:delta?],
51
+ :delta_processor => @options[:delta_processor],
52
+ :primary_key => @options[:primary_key] || model.primary_key || :id
53
+ }
54
+ end
55
+ end
@@ -0,0 +1,47 @@
1
+ class ThinkingSphinx::ActiveRecord::Interpreter <
2
+ ::ThinkingSphinx::Core::Interpreter
3
+
4
+ def group_by(*columns)
5
+ __source.groupings += columns
6
+ end
7
+
8
+ def has(*columns)
9
+ __source.attributes += build_properties(
10
+ ::ThinkingSphinx::ActiveRecord::Attribute, columns
11
+ )
12
+ end
13
+
14
+ def indexes(*columns)
15
+ __source.fields += build_properties(
16
+ ::ThinkingSphinx::ActiveRecord::Field, columns
17
+ )
18
+ end
19
+
20
+ def join(*columns)
21
+ __source.associations += columns.collect { |column|
22
+ ::ThinkingSphinx::ActiveRecord::Association.new column
23
+ }
24
+ end
25
+
26
+ def set_property(properties)
27
+ properties.each do |key, value|
28
+ @index.send("#{key}=", value) if @index.class.settings.include?(key)
29
+ __source.send("#{key}=", value) if __source.class.settings.include?(key)
30
+ end
31
+ end
32
+
33
+ def where(*conditions)
34
+ __source.conditions += conditions
35
+ end
36
+
37
+ private
38
+
39
+ def __source
40
+ @source ||= @index.append_source
41
+ end
42
+
43
+ def build_properties(klass, columns)
44
+ options = columns.extract_options!
45
+ columns.collect { |column| klass.new(__source.model, column, options) }
46
+ end
47
+ end
@@ -1,61 +1,13 @@
1
- require 'active_support/log_subscriber'
2
-
3
- module ThinkingSphinx
4
- module ActiveRecord
5
- class LogSubscriber < ActiveSupport::LogSubscriber
6
- def self.runtime=(value)
7
- Thread.current['thinking_sphinx_query_runtime'] = value
8
- end
9
-
10
- def self.runtime
11
- Thread.current['thinking_sphinx_query_runtime'] ||= 0
12
- end
13
-
14
- def self.reset_runtime
15
- rt, self.runtime = runtime, 0
16
- rt
17
- end
18
-
19
- def initialize
20
- super
21
- @odd_or_even = false
22
- end
23
-
24
- def query(event)
25
- self.class.runtime += event.duration
26
- return unless logger.debug?
27
-
28
- identifier = color('Sphinx Query (%.1fms)' % event.duration, GREEN, true)
29
- query = event.payload[:query]
30
- query = color query, nil, true if odd?
31
-
32
- debug " #{identifier} #{query}"
33
- end
34
-
35
- def message(event)
36
- return unless logger.debug?
37
-
38
- identifier = color 'Sphinx', GREEN, true
39
- message = event.payload[:message]
40
- message = color message, nil, true if odd?
41
-
42
- debug " #{identifier} #{message}"
43
- end
44
-
45
- def odd?
46
- @odd_or_even = !@odd_or_even
47
- end
48
-
49
- def logger
50
- return @logger if defined? @logger
51
- self.logger = ::ActiveRecord::Base.logger
52
- end
53
-
54
- def logger=(logger)
55
- @logger = logger
56
- end
1
+ class ThinkingSphinx::ActiveRecord::LogSubscriber < ActiveSupport::LogSubscriber
2
+ def query(event)
3
+ identifier = color('Sphinx Query (%.1fms)' % event.duration, GREEN, true)
4
+ debug " #{identifier} #{event.payload[:query]}"
5
+ end
57
6
 
58
- attach_to :thinking_sphinx
59
- end
7
+ def message(event)
8
+ identifier = color 'Sphinx', GREEN, true
9
+ debug " #{identifier} #{event.payload[:message]}"
60
10
  end
61
11
  end
12
+
13
+ ThinkingSphinx::ActiveRecord::LogSubscriber.attach_to :thinking_sphinx
@@ -0,0 +1,28 @@
1
+ class ThinkingSphinx::ActiveRecord::Property
2
+ attr_reader :columns, :options
3
+
4
+ def initialize(model, columns, options = {})
5
+ @model, @options = model, options
6
+
7
+ @columns = Array(columns).collect { |column|
8
+ column.respond_to?(:__name) ? column :
9
+ ThinkingSphinx::ActiveRecord::Column.new(column)
10
+ }
11
+ end
12
+
13
+ def facet?
14
+ options[:facet]
15
+ end
16
+
17
+ def multi?
18
+ false
19
+ end
20
+
21
+ def name
22
+ (options[:as] || columns.first.__name).to_s
23
+ end
24
+
25
+ def type
26
+ nil
27
+ end
28
+ end
@@ -0,0 +1,60 @@
1
+ class ThinkingSphinx::ActiveRecord::PropertySQLPresenter
2
+ attr_reader :property, :adapter, :associations
3
+
4
+ def initialize(property, adapter, associations)
5
+ @property, @adapter, @associations = property, adapter, associations
6
+ end
7
+
8
+ def to_group
9
+ return nil unless group?
10
+
11
+ columns_with_table
12
+ end
13
+
14
+ def to_select
15
+ "#{casted_column_with_table} AS #{adapter.quote property.name}"
16
+ end
17
+
18
+ private
19
+
20
+ def aggregate?
21
+ property.columns.any? { |column|
22
+ associations.aggregate_for?(column.__stack)
23
+ }
24
+ end
25
+
26
+ def aggregate_separator
27
+ (property.multi?) ? ',' : ' '
28
+ end
29
+
30
+ def casted_column_with_table
31
+ clause = columns_with_table
32
+ clause = adapter.cast_to_timestamp(clause) if property.type == :timestamp
33
+ clause = adapter.concatenate(clause, ' ') if concatenating?
34
+ if aggregate?
35
+ clause = adapter.group_concatenate(clause, aggregate_separator)
36
+ end
37
+
38
+ clause
39
+ end
40
+
41
+ def column_with_table(column)
42
+ return column.__name if column.string?
43
+
44
+ "#{associations.alias_for(column.__stack)}.#{adapter.quote column.__name}"
45
+ end
46
+
47
+ def columns_with_table
48
+ property.columns.collect { |column|
49
+ column_with_table(column)
50
+ }.join(', ')
51
+ end
52
+
53
+ def concatenating?
54
+ property.columns.length > 1
55
+ end
56
+
57
+ def group?
58
+ !(aggregate? || property.columns.any?(&:string?))
59
+ end
60
+ end
@@ -0,0 +1,159 @@
1
+ class ThinkingSphinx::ActiveRecord::SQLBuilder
2
+ attr_reader :source
3
+
4
+ def initialize(source)
5
+ @source = source
6
+ end
7
+
8
+ def sql_query
9
+ relation = model.unscoped
10
+ relation = relation.select pre_select + select_clause
11
+ relation = relation.where where_clause
12
+ relation = relation.group group_clause
13
+ relation = relation.order('NULL') if source.type == 'mysql'
14
+ relation = relation.joins associations.join_values
15
+
16
+ relation.to_sql
17
+ end
18
+
19
+ def sql_query_range
20
+ return nil if source.disable_range?
21
+
22
+ minimum = source.adapter.convert_nulls "MIN(#{quoted_primary_key})", 1
23
+ maximum = source.adapter.convert_nulls "MAX(#{quoted_primary_key})", 1
24
+
25
+ relation = source.model.unscoped
26
+ relation = relation.select "#{minimum}, #{maximum}"
27
+ relation = relation.where where_clause(true)
28
+
29
+ relation.to_sql
30
+ end
31
+
32
+ def sql_query_info
33
+ relation = source.model.unscoped
34
+ relation.where("#{quoted_primary_key} = #{reversed_document_id}").to_sql
35
+ end
36
+
37
+ def sql_query_pre
38
+ queries = []
39
+
40
+ reset_delta = delta_processor && !source.delta?
41
+ max_len = source.options[:group_concat_max_len]
42
+
43
+ queries << delta_processor.reset_query if reset_delta
44
+ queries << "SET SESSION group_concat_max_len = #{max_len}" if max_len
45
+ queries << source.adapter.utf8_query_pre if source.options[:utf8?]
46
+
47
+ queries.compact
48
+ end
49
+
50
+ private
51
+
52
+ def config
53
+ ThinkingSphinx::Configuration.instance
54
+ end
55
+
56
+ def model
57
+ source.model
58
+ end
59
+
60
+ def base_join
61
+ @base_join ||= join_dependency_class.new model, [], initial_joins
62
+ end
63
+
64
+ def delta_processor
65
+ source.delta_processor
66
+ end
67
+
68
+ def associations
69
+ @associations ||= ThinkingSphinx::ActiveRecord::Associations.new(model).tap do |assocs|
70
+ source.associations.each do |association|
71
+ assocs.add_join_to association.stack
72
+ end
73
+ end
74
+ end
75
+
76
+ def quote_column(column)
77
+ model.connection.quote_column_name(column)
78
+ end
79
+
80
+ def quoted_primary_key
81
+ "#{model.quoted_table_name}.#{quote_column(source.primary_key)}"
82
+ end
83
+
84
+ def quoted_inheritance_column
85
+ "#{model.quoted_table_name}.#{quote_column model.inheritance_column}"
86
+ end
87
+
88
+ def pre_select
89
+ source.type == 'mysql' ? 'SQL_NO_CACHE ' : ''
90
+ end
91
+
92
+ def document_id
93
+ quoted_alias = quote_column source.primary_key
94
+ "#{quoted_primary_key} * #{config.indices.count} + #{source.offset} AS #{quoted_alias}"
95
+ end
96
+
97
+ def reversed_document_id
98
+ "($id - #{source.offset}) / #{config.indices.count}"
99
+ end
100
+
101
+ def attribute_presenters
102
+ @attribute_presenters ||= begin
103
+ source.attributes.collect { |attribute|
104
+ ThinkingSphinx::ActiveRecord::PropertySQLPresenter.new(
105
+ attribute, source.adapter, associations
106
+ )
107
+ }
108
+ end
109
+ end
110
+
111
+ def field_presenters
112
+ @field_presenters ||= source.fields.collect { |field|
113
+ ThinkingSphinx::ActiveRecord::PropertySQLPresenter.new(
114
+ field, source.adapter, associations
115
+ )
116
+ }
117
+ end
118
+
119
+ def select_clause
120
+ (
121
+ [document_id] +
122
+ field_presenters.collect(&:to_select) +
123
+ attribute_presenters.collect(&:to_select)
124
+ ).compact.join(', ')
125
+ end
126
+
127
+ def where_clause(without_range = false)
128
+ logic = []
129
+
130
+ unless without_range || source.disable_range?
131
+ logic << "#{quoted_primary_key} >= $start"
132
+ logic << "#{quoted_primary_key} <= $end"
133
+ end
134
+
135
+ unless model.descends_from_active_record?
136
+ klass = model.store_full_sti_class ? model.name : model.name.demodulize
137
+ logic << "#{quoted_inheritance_column} = '#{klass}'"
138
+ end
139
+
140
+ logic << delta_processor.clause(source.delta?) if delta_processor
141
+ logic += source.conditions
142
+
143
+ logic.compact.join(' AND ')
144
+ end
145
+
146
+ def group_clause
147
+ internal_groupings = []
148
+ if model.column_names.include?(model.inheritance_column)
149
+ internal_groupings << quoted_inheritance_column
150
+ end
151
+
152
+ (
153
+ [quoted_primary_key] +
154
+ field_presenters.collect(&:to_group).compact +
155
+ attribute_presenters.collect(&:to_group).compact +
156
+ source.groupings + internal_groupings
157
+ ).join(', ')
158
+ end
159
+ end