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,162 @@
1
+ require 'spec_helper'
2
+
3
+ describe ThinkingSphinx::ActiveRecord::PropertySQLPresenter do
4
+ let(:adapter) { double('adapter') }
5
+ let(:associations) {
6
+ double('associations', :alias_for => 'articles', :aggregate_for? => false)
7
+ }
8
+
9
+ before :each do
10
+ adapter.stub(:quote) { |column| column }
11
+ end
12
+
13
+ context 'with a field' do
14
+ let(:presenter) {
15
+ ThinkingSphinx::ActiveRecord::PropertySQLPresenter.new(
16
+ field, adapter, associations
17
+ )
18
+ }
19
+ let(:field) { double('field', :name => 'title', :columns => [column],
20
+ :type => nil, :multi? => false) }
21
+ let(:column) { double('column', :string? => false, :__stack => [],
22
+ :__name => 'title') }
23
+
24
+ describe '#to_group' do
25
+ it "returns the column name as a string" do
26
+ presenter.to_group.should == 'articles.title'
27
+ end
28
+
29
+ it "gets the column's table alias from the associations object" do
30
+ column.stub!(:__stack => [:users, :posts])
31
+
32
+ associations.should_receive(:alias_for).with([:users, :posts]).
33
+ and_return('posts')
34
+
35
+ presenter.to_group
36
+ end
37
+
38
+ it "returns nil if the property is an aggregate" do
39
+ associations.stub! :aggregate_for? => true
40
+
41
+ presenter.to_group.should be_nil
42
+ end
43
+ end
44
+
45
+ describe '#to_select' do
46
+ it "returns the column name as a string" do
47
+ presenter.to_select.should == 'articles.title AS title'
48
+ end
49
+
50
+ it "gets the column's table alias from the associations object" do
51
+ column.stub!(:__stack => [:users, :posts])
52
+
53
+ associations.should_receive(:alias_for).with([:users, :posts]).
54
+ and_return('posts')
55
+
56
+ presenter.to_select
57
+ end
58
+
59
+ it "returns the column name with an alias when provided" do
60
+ field.stub!(:name => :subject)
61
+
62
+ presenter.to_select.should == 'articles.title AS subject'
63
+ end
64
+
65
+ it "groups and concatenates aggregated columns" do
66
+ adapter.stub :group_concatenate do |clause, separator|
67
+ "GROUP_CONCAT(#{clause} SEPARATOR '#{separator}')"
68
+ end
69
+
70
+ associations.stub! :aggregate_for? => true
71
+
72
+ presenter.to_select.
73
+ should == "GROUP_CONCAT(articles.title SEPARATOR ' ') AS title"
74
+ end
75
+
76
+ it "concatenates multiple columns" do
77
+ adapter.stub :concatenate do |clause, separator|
78
+ "CONCAT_WS('#{separator}', #{clause})"
79
+ end
80
+
81
+ field.stub!(:columns => [column, column])
82
+
83
+ presenter.to_select.
84
+ should == "CONCAT_WS(' ', articles.title, articles.title) AS title"
85
+ end
86
+ end
87
+ end
88
+
89
+ context 'with an attribute' do
90
+ let(:presenter) {
91
+ ThinkingSphinx::ActiveRecord::PropertySQLPresenter.new(
92
+ attribute, adapter, associations
93
+ )
94
+ }
95
+ let(:attribute) { double('attribute', :name => 'created_at',
96
+ :columns => [column], :type => :integer, :multi? => false) }
97
+ let(:column) { double('column', :string? => false, :__stack => [],
98
+ :__name => 'created_at') }
99
+
100
+ before :each do
101
+ adapter.stub :cast_to_timestamp do |clause|
102
+ "UNIX_TIMESTAMP(#{clause})"
103
+ end
104
+ end
105
+
106
+ describe '#to_group' do
107
+ it "returns the column name as a string" do
108
+ presenter.to_group.should == 'articles.created_at'
109
+ end
110
+
111
+ it "gets the column's table alias from the associations object" do
112
+ column.stub!(:__stack => [:users, :posts])
113
+
114
+ associations.should_receive(:alias_for).with([:users, :posts]).
115
+ and_return('posts')
116
+
117
+ presenter.to_group
118
+ end
119
+
120
+ it "returns nil if the column is a string" do
121
+ column.stub!(:string? => true)
122
+
123
+ presenter.to_group.should be_nil
124
+ end
125
+
126
+ it "returns nil if the property is an aggregate" do
127
+ associations.stub! :aggregate_for? => true
128
+
129
+ presenter.to_group.should be_nil
130
+ end
131
+ end
132
+
133
+ describe '#to_select' do
134
+ it "returns the column name as a string" do
135
+ presenter.to_select.should == 'articles.created_at AS created_at'
136
+ end
137
+
138
+ it "gets the column's table alias from the associations object" do
139
+ column.stub!(:__stack => [:users, :posts])
140
+
141
+ associations.should_receive(:alias_for).with([:users, :posts]).
142
+ and_return('posts')
143
+
144
+ presenter.to_select
145
+ end
146
+
147
+ it "returns the column name with an alias when provided" do
148
+ attribute.stub!(:name => :creation_timestamp)
149
+
150
+ presenter.to_select.
151
+ should == 'articles.created_at AS creation_timestamp'
152
+ end
153
+
154
+ it "ensures datetime attributes are converted to timestamps" do
155
+ attribute.stub :type => :timestamp
156
+
157
+ presenter.to_select.
158
+ should == 'UNIX_TIMESTAMP(articles.created_at) AS created_at'
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,666 @@
1
+ require 'spec_helper'
2
+
3
+ describe ThinkingSphinx::ActiveRecord::SQLBuilder do
4
+ let(:source) { double('source', :model => model, :offset => 3,
5
+ :fields => [], :attributes => [], :disable_range? => false,
6
+ :delta_processor => nil, :conditions => [], :groupings => [],
7
+ :adapter => adapter, :associations => [], :primary_key => :id) }
8
+ let(:model) { double('model', :connection => connection,
9
+ :descends_from_active_record? => true, :column_names => [],
10
+ :inheritance_column => 'type', :unscoped => relation,
11
+ :quoted_table_name => '`users`', :name => 'User') }
12
+ let(:connection) { double('connection') }
13
+ let(:relation) { double('relation') }
14
+ let(:config) { double('config', :indices => indices) }
15
+ let(:indices) { double('indices', :count => 5) }
16
+ let(:presenter) { double('presenter', :to_select => '`name` AS `name`',
17
+ :to_group => '`name`') }
18
+ let(:adapter) { double('adapter') }
19
+ let(:associations) { double('associations', :join_values => []) }
20
+ let(:builder) { ThinkingSphinx::ActiveRecord::SQLBuilder.new source }
21
+
22
+ before :each do
23
+ ThinkingSphinx::Configuration.stub! :instance => config
24
+ ThinkingSphinx::ActiveRecord::PropertySQLPresenter.stub! :new => presenter
25
+ ThinkingSphinx::ActiveRecord::Associations.stub! :new => associations
26
+ relation.stub! :select => relation, :where => relation, :group => relation,
27
+ :order => relation, :joins => relation, :to_sql => ''
28
+ connection.stub!(:quote_column_name) { |column| "`#{column}`"}
29
+ end
30
+
31
+ describe 'sql_query' do
32
+ before :each do
33
+ source.stub! :type => 'mysql'
34
+ end
35
+
36
+ it "adds source associations to the joins of the query" do
37
+ source.associations << double('association', :stack => [:user, :posts])
38
+
39
+ associations.should_receive(:add_join_to).with([:user, :posts])
40
+
41
+ builder.sql_query
42
+ end
43
+
44
+ context 'MySQL adapter' do
45
+ before :each do
46
+ source.stub! :type => 'mysql'
47
+ end
48
+
49
+ it "returns the relation's query" do
50
+ relation.stub! :to_sql => 'SELECT * FROM people'
51
+
52
+ builder.sql_query.should == 'SELECT * FROM people'
53
+ end
54
+
55
+ it "ensures results aren't from cache" do
56
+ relation.should_receive(:select) do |string|
57
+ string.should match(/^SQL_NO_CACHE /)
58
+ relation
59
+ end
60
+
61
+ builder.sql_query
62
+ end
63
+
64
+ it "adds the document id using the offset and index count" do
65
+ relation.should_receive(:select) do |string|
66
+ string.should match(/`users`.`id` \* 5 \+ 3 AS `id`/)
67
+ relation
68
+ end
69
+
70
+ builder.sql_query
71
+ end
72
+
73
+ it "adds each field to the SELECT clause" do
74
+ source.fields << double('field')
75
+
76
+ relation.should_receive(:select) do |string|
77
+ string.should match(/`name` AS `name`/)
78
+ relation
79
+ end
80
+
81
+ builder.sql_query
82
+ end
83
+
84
+ it "adds each attribute to the SELECT clause" do
85
+ source.attributes << double('attribute')
86
+ presenter.stub!(:to_select => '`created_at` AS `created_at`')
87
+
88
+ relation.should_receive(:select) do |string|
89
+ string.should match(/`created_at` AS `created_at`/)
90
+ relation
91
+ end
92
+
93
+ builder.sql_query
94
+ end
95
+
96
+ it "limits results to a set range" do
97
+ relation.should_receive(:where) do |string|
98
+ string.should match(/`users`.`id` >= \$start/)
99
+ string.should match(/`users`.`id` <= \$end/)
100
+ relation
101
+ end
102
+
103
+ builder.sql_query
104
+ end
105
+
106
+ it "shouldn't limit results to a range if ranges are disabled" do
107
+ source.stub! :disable_range? => true
108
+
109
+ relation.should_receive(:where) do |string|
110
+ string.should_not match(/`users`.`id` >= \$start/)
111
+ string.should_not match(/`users`.`id` <= \$end/)
112
+ relation
113
+ end
114
+
115
+ builder.sql_query
116
+ end
117
+
118
+ it "adds source conditions" do
119
+ source.conditions << 'created_at > NOW()'
120
+
121
+ relation.should_receive(:where) do |string|
122
+ string.should match(/created_at > NOW()/)
123
+ relation
124
+ end
125
+
126
+ builder.sql_query
127
+ end
128
+
129
+ it "groups by the primary key" do
130
+ relation.should_receive(:group) do |string|
131
+ string.should match(/`users`.`id`/)
132
+ relation
133
+ end
134
+
135
+ builder.sql_query
136
+ end
137
+
138
+ it "groups each field" do
139
+ source.fields << double('field')
140
+
141
+ relation.should_receive(:group) do |string|
142
+ string.should match(/`name`/)
143
+ relation
144
+ end
145
+
146
+ builder.sql_query
147
+ end
148
+
149
+ it "groups each attribute" do
150
+ source.attributes << double('attribute')
151
+ presenter.stub!(:to_group => '`created_at`')
152
+
153
+ relation.should_receive(:group) do |string|
154
+ string.should match(/`created_at`/)
155
+ relation
156
+ end
157
+
158
+ builder.sql_query
159
+ end
160
+
161
+ it "groups by source groupings" do
162
+ source.groupings << '`latitude`'
163
+
164
+ relation.should_receive(:group) do |string|
165
+ string.should match(/`latitude`/)
166
+ relation
167
+ end
168
+
169
+ builder.sql_query
170
+ end
171
+
172
+ it "orders by NULL" do
173
+ relation.should_receive(:order).with('NULL').and_return(relation)
174
+
175
+ builder.sql_query
176
+ end
177
+
178
+ context 'STI model' do
179
+ before :each do
180
+ model.column_names << 'type'
181
+ model.stub! :descends_from_active_record? => false
182
+ model.stub! :store_full_sti_class => true
183
+ end
184
+
185
+ it "limits results to just the model" do
186
+ relation.should_receive(:where) do |string|
187
+ string.should match(/`users`.`type` = 'User'/)
188
+ relation
189
+ end
190
+
191
+ builder.sql_query
192
+ end
193
+
194
+ it "uses the demodulised name if that's what is stored" do
195
+ model.stub! :store_full_sti_class => false
196
+ model.name.stub! :demodulize => 'U'
197
+
198
+ relation.should_receive(:where) do |string|
199
+ string.should match(/`users`.`type` = 'U'/)
200
+ relation
201
+ end
202
+
203
+ builder.sql_query
204
+ end
205
+
206
+ it "groups by the inheritance column" do
207
+ relation.should_receive(:group) do |string|
208
+ string.should match(/`users`.`type`/)
209
+ relation
210
+ end
211
+
212
+ builder.sql_query
213
+ end
214
+
215
+ context 'with a custom inheritance column' do
216
+ before :each do
217
+ model.column_names << 'custom_type'
218
+ model.stub :inheritance_column => 'custom_type'
219
+ end
220
+
221
+ it "limits results on the right column" do
222
+ relation.should_receive(:where) do |string|
223
+ string.should match(/`users`.`custom_type` = 'User'/)
224
+ relation
225
+ end
226
+
227
+ builder.sql_query
228
+ end
229
+
230
+ it "groups by the right column" do
231
+ relation.should_receive(:group) do |string|
232
+ string.should match(/`users`.`custom_type`/)
233
+ relation
234
+ end
235
+
236
+ builder.sql_query
237
+ end
238
+ end
239
+ end
240
+
241
+ context 'with a delta processor' do
242
+ let(:processor) { double('processor') }
243
+
244
+ before :each do
245
+ source.stub! :delta_processor => processor
246
+ source.stub! :delta? => true
247
+ end
248
+
249
+ it "filters by the provided clause" do
250
+ processor.should_receive(:clause).with(true).and_return('`delta` = 1')
251
+ relation.should_receive(:where) do |string|
252
+ string.should match(/`delta` = 1/)
253
+ relation
254
+ end
255
+
256
+ builder.sql_query
257
+ end
258
+ end
259
+ end
260
+
261
+ context 'PostgreSQL adapter' do
262
+ let(:presenter) { double('presenter', :to_select => '"name" AS "name"',
263
+ :to_group => '"name"') }
264
+
265
+ before :each do
266
+ source.stub! :type => 'pgsql'
267
+ model.stub! :quoted_table_name => '"users"'
268
+ connection.stub!(:quote_column_name) { |column| "\"#{column}\""}
269
+ end
270
+
271
+ it "returns the relation's query" do
272
+ relation.stub! :to_sql => 'SELECT * FROM people'
273
+
274
+ builder.sql_query.should == 'SELECT * FROM people'
275
+ end
276
+
277
+ it "adds the document id using the offset and index count" do
278
+ relation.should_receive(:select) do |string|
279
+ string.should match(/"users"."id" \* 5 \+ 3 AS "id"/)
280
+ relation
281
+ end
282
+
283
+ builder.sql_query
284
+ end
285
+
286
+ it "adds each field to the SELECT clause" do
287
+ source.fields << double('field')
288
+
289
+ relation.should_receive(:select) do |string|
290
+ string.should match(/"name" AS "name"/)
291
+ relation
292
+ end
293
+
294
+ builder.sql_query
295
+ end
296
+
297
+ it "adds each attribute to the SELECT clause" do
298
+ source.attributes << double('attribute')
299
+ presenter.stub!(:to_select => '"created_at" AS "created_at"')
300
+
301
+ relation.should_receive(:select) do |string|
302
+ string.should match(/"created_at" AS "created_at"/)
303
+ relation
304
+ end
305
+
306
+ builder.sql_query
307
+ end
308
+
309
+ it "limits results to a set range" do
310
+ relation.should_receive(:where) do |string|
311
+ string.should match(/"users"."id" >= \$start/)
312
+ string.should match(/"users"."id" <= \$end/)
313
+ relation
314
+ end
315
+
316
+ builder.sql_query
317
+ end
318
+
319
+ it "shouldn't limit results to a range if ranges are disabled" do
320
+ source.stub! :disable_range? => true
321
+
322
+ relation.should_receive(:where) do |string|
323
+ string.should_not match(/"users"."id" >= \$start/)
324
+ string.should_not match(/"users"."id" <= \$end/)
325
+ relation
326
+ end
327
+
328
+ builder.sql_query
329
+ end
330
+
331
+ it "adds source conditions" do
332
+ source.conditions << 'created_at > NOW()'
333
+
334
+ relation.should_receive(:where) do |string|
335
+ string.should match(/created_at > NOW()/)
336
+ relation
337
+ end
338
+
339
+ builder.sql_query
340
+ end
341
+
342
+ it "groups by the primary key" do
343
+ relation.should_receive(:group) do |string|
344
+ string.should match(/"users"."id"/)
345
+ relation
346
+ end
347
+
348
+ builder.sql_query
349
+ end
350
+
351
+ it "groups each field" do
352
+ source.fields << double('field')
353
+
354
+ relation.should_receive(:group) do |string|
355
+ string.should match(/"name"/)
356
+ relation
357
+ end
358
+
359
+ builder.sql_query
360
+ end
361
+
362
+ it "groups each attribute" do
363
+ source.attributes << double('attribute')
364
+ presenter.stub!(:to_group => '"created_at"')
365
+
366
+ relation.should_receive(:group) do |string|
367
+ string.should match(/"created_at"/)
368
+ relation
369
+ end
370
+
371
+ builder.sql_query
372
+ end
373
+
374
+ it "groups by source groupings" do
375
+ source.groupings << '"latitude"'
376
+
377
+ relation.should_receive(:group) do |string|
378
+ string.should match(/"latitude"/)
379
+ relation
380
+ end
381
+
382
+ builder.sql_query
383
+ end
384
+
385
+ it "has no ORDER clause" do
386
+ relation.should_not_receive(:order)
387
+
388
+ builder.sql_query
389
+ end
390
+
391
+ context 'STI model' do
392
+ before :each do
393
+ model.column_names << 'type'
394
+ model.stub! :descends_from_active_record? => false
395
+ model.stub! :store_full_sti_class => true
396
+ end
397
+
398
+ it "limits results to just the model" do
399
+ relation.should_receive(:where) do |string|
400
+ string.should match(/"users"."type" = 'User'/)
401
+ relation
402
+ end
403
+
404
+ builder.sql_query
405
+ end
406
+
407
+ it "uses the demodulised name if that's what is stored" do
408
+ model.stub! :store_full_sti_class => false
409
+ model.name.stub! :demodulize => 'U'
410
+
411
+ relation.should_receive(:where) do |string|
412
+ string.should match(/"users"."type" = 'U'/)
413
+ relation
414
+ end
415
+
416
+ builder.sql_query
417
+ end
418
+
419
+ it "groups by the inheritance column" do
420
+ relation.should_receive(:group) do |string|
421
+ string.should match(/"users"."type"/)
422
+ relation
423
+ end
424
+
425
+ builder.sql_query
426
+ end
427
+
428
+ context 'with a custom inheritance column' do
429
+ before :each do
430
+ model.column_names << 'custom_type'
431
+ model.stub :inheritance_column => 'custom_type'
432
+ end
433
+
434
+ it "limits results on the right column" do
435
+ relation.should_receive(:where) do |string|
436
+ string.should match(/"users"."custom_type" = 'User'/)
437
+ relation
438
+ end
439
+
440
+ builder.sql_query
441
+ end
442
+
443
+ it "groups by the right column" do
444
+ relation.should_receive(:group) do |string|
445
+ string.should match(/"users"."custom_type"/)
446
+ relation
447
+ end
448
+
449
+ builder.sql_query
450
+ end
451
+ end
452
+ end
453
+
454
+ context 'with a delta processor' do
455
+ let(:processor) { double('processor') }
456
+
457
+ before :each do
458
+ source.stub! :delta_processor => processor
459
+ source.stub! :delta? => true
460
+ end
461
+
462
+ it "filters by the provided clause" do
463
+ processor.should_receive(:clause).with(true).and_return('"delta" = 1')
464
+ relation.should_receive(:where) do |string|
465
+ string.should match(/"delta" = 1/)
466
+ relation
467
+ end
468
+
469
+ builder.sql_query
470
+ end
471
+ end
472
+ end
473
+ end
474
+
475
+ describe 'sql_query_info' do
476
+ it "filters on the reversed document id" do
477
+ relation.should_receive(:where).
478
+ with("`users`.`id` = ($id - #{source.offset}) / #{indices.count}").
479
+ and_return(relation)
480
+
481
+ builder.sql_query_info
482
+ end
483
+
484
+ it "returns the generated SQL query" do
485
+ relation.stub(:to_sql).and_return('SELECT * FROM people WHERE id = $id')
486
+
487
+ builder.sql_query_info.should == 'SELECT * FROM people WHERE id = $id'
488
+ end
489
+ end
490
+
491
+ describe 'sql_query_pre' do
492
+ let(:processor) { double('processor', :reset_query => 'RESET DELTAS') }
493
+
494
+ before :each do
495
+ source.stub :options => {}, :delta_processor => nil, :delta? => false
496
+ adapter.stub :utf8_query_pre => 'SET UTF8'
497
+ end
498
+
499
+ it "adds a reset delta query if there is a delta processor and this is the core source" do
500
+ source.stub :delta_processor => processor
501
+
502
+ builder.sql_query_pre.should include('RESET DELTAS')
503
+ end
504
+
505
+ it "does not add a reset query if there is no delta processor" do
506
+ builder.sql_query_pre.should_not include('RESET DELTAS')
507
+ end
508
+
509
+ it "does not add a reset query if this is a delta source" do
510
+ source.stub :delta_processor => processor
511
+ source.stub :delta? => true
512
+
513
+ builder.sql_query_pre.should_not include('RESET DELTAS')
514
+ end
515
+
516
+ it "sets the group_concat_max_len value if set" do
517
+ source.options[:group_concat_max_len] = 123
518
+
519
+ builder.sql_query_pre.
520
+ should include('SET SESSION group_concat_max_len = 123')
521
+ end
522
+
523
+ it "does not set the group_concat_max_len if not provided" do
524
+ source.options[:group_concat_max_len] = nil
525
+
526
+ builder.sql_query_pre.select { |sql|
527
+ sql[/SET SESSION group_concat_max_len/]
528
+ }.should be_empty
529
+ end
530
+
531
+ it "sets the connection to use UTF-8 if required" do
532
+ source.options[:utf8?] = true
533
+
534
+ builder.sql_query_pre.should include('SET UTF8')
535
+ end
536
+
537
+ it "does not set the connection to use UTF-8 if not required" do
538
+ source.options[:utf8?] = false
539
+
540
+ builder.sql_query_pre.should_not include('SET UTF8')
541
+ end
542
+ end
543
+
544
+ describe 'sql_query_range' do
545
+ before :each do
546
+ adapter.stub!(:convert_nulls) { |string, default|
547
+ "ISNULL(#{string}, #{default})"
548
+ }
549
+ end
550
+
551
+ it "returns the relation's query" do
552
+ relation.stub! :to_sql => 'SELECT * FROM people'
553
+
554
+ builder.sql_query_range.should == 'SELECT * FROM people'
555
+ end
556
+
557
+ it "returns nil if ranges are disabled" do
558
+ source.stub! :disable_range? => true
559
+
560
+ builder.sql_query_range.should be_nil
561
+ end
562
+
563
+ it "selects the minimum primary key value, allowing for nulls" do
564
+ relation.should_receive(:select) do |string|
565
+ string.should match(/ISNULL\(MIN\(`users`.`id`\), 1\)/)
566
+ relation
567
+ end
568
+
569
+ builder.sql_query_range
570
+ end
571
+
572
+ it "selects the maximum primary key value, allowing for nulls" do
573
+ relation.should_receive(:select) do |string|
574
+ string.should match(/ISNULL\(MAX\(`users`.`id`\), 1\)/)
575
+ relation
576
+ end
577
+
578
+ builder.sql_query_range
579
+ end
580
+
581
+ it "shouldn't limit results to a range" do
582
+ relation.should_receive(:where) do |string|
583
+ string.should_not match(/`users`.`id` >= \$start/)
584
+ string.should_not match(/`users`.`id` <= \$end/)
585
+ relation
586
+ end
587
+
588
+ builder.sql_query_range
589
+ end
590
+
591
+ it "adds source conditions" do
592
+ source.conditions << 'created_at > NOW()'
593
+
594
+ relation.should_receive(:where) do |string|
595
+ string.should match(/created_at > NOW()/)
596
+ relation
597
+ end
598
+
599
+ builder.sql_query_range
600
+ end
601
+
602
+ context 'STI model' do
603
+ before :each do
604
+ model.column_names << 'type'
605
+ model.stub! :descends_from_active_record? => false
606
+ model.stub! :store_full_sti_class => true
607
+ end
608
+
609
+ it "limits results to just the model" do
610
+ relation.should_receive(:where) do |string|
611
+ string.should match(/`users`.`type` = 'User'/)
612
+ relation
613
+ end
614
+
615
+ builder.sql_query_range
616
+ end
617
+
618
+ it "uses the demodulised name if that's what is stored" do
619
+ model.stub! :store_full_sti_class => false
620
+ model.name.stub! :demodulize => 'U'
621
+
622
+ relation.should_receive(:where) do |string|
623
+ string.should match(/`users`.`type` = 'U'/)
624
+ relation
625
+ end
626
+
627
+ builder.sql_query_range
628
+ end
629
+
630
+ context 'with a custom inheritance column' do
631
+ before :each do
632
+ model.column_names << 'custom_type'
633
+ model.stub :inheritance_column => 'custom_type'
634
+ end
635
+
636
+ it "limits results on the right column" do
637
+ relation.should_receive(:where) do |string|
638
+ string.should match(/`users`.`custom_type` = 'User'/)
639
+ relation
640
+ end
641
+
642
+ builder.sql_query_range
643
+ end
644
+ end
645
+ end
646
+
647
+ context 'with a delta processor' do
648
+ let(:processor) { double('processor') }
649
+
650
+ before :each do
651
+ source.stub! :delta_processor => processor
652
+ source.stub! :delta? => true
653
+ end
654
+
655
+ it "filters by the provided clause" do
656
+ processor.should_receive(:clause).with(true).and_return('`delta` = 1')
657
+ relation.should_receive(:where) do |string|
658
+ string.should match(/`delta` = 1/)
659
+ relation
660
+ end
661
+
662
+ builder.sql_query_range
663
+ end
664
+ end
665
+ end
666
+ end