axiom-optimizer 0.1.0

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 (345) hide show
  1. checksums.yaml +7 -0
  2. data/.gemtest +0 -0
  3. data/.gitignore +37 -0
  4. data/.rspec +4 -0
  5. data/.rvmrc +1 -0
  6. data/.travis.yml +35 -0
  7. data/CONTRIBUTING.md +11 -0
  8. data/Gemfile +10 -0
  9. data/Gemfile.devtools +57 -0
  10. data/Guardfile +23 -0
  11. data/LICENSE +20 -0
  12. data/README.md +111 -0
  13. data/Rakefile +5 -0
  14. data/TODO +144 -0
  15. data/axiom-optimizer.gemspec +25 -0
  16. data/config/flay.yml +3 -0
  17. data/config/flog.yml +2 -0
  18. data/config/mutant.yml +3 -0
  19. data/config/reek.yml +162 -0
  20. data/config/roodi.yml +16 -0
  21. data/config/yardstick.yml +2 -0
  22. data/lib/axiom-optimizer.rb +3 -0
  23. data/lib/axiom/optimizer.rb +168 -0
  24. data/lib/axiom/optimizer/aggregate.rb +16 -0
  25. data/lib/axiom/optimizer/aggregate/count.rb +17 -0
  26. data/lib/axiom/optimizer/aggregate/maximum.rb +17 -0
  27. data/lib/axiom/optimizer/aggregate/mean.rb +17 -0
  28. data/lib/axiom/optimizer/aggregate/minimum.rb +17 -0
  29. data/lib/axiom/optimizer/aggregate/standard_deviation.rb +17 -0
  30. data/lib/axiom/optimizer/aggregate/sum.rb +17 -0
  31. data/lib/axiom/optimizer/aggregate/variance.rb +17 -0
  32. data/lib/axiom/optimizer/algebra/difference.rb +68 -0
  33. data/lib/axiom/optimizer/algebra/extension.rb +97 -0
  34. data/lib/axiom/optimizer/algebra/intersection.rb +68 -0
  35. data/lib/axiom/optimizer/algebra/join.rb +184 -0
  36. data/lib/axiom/optimizer/algebra/product.rb +70 -0
  37. data/lib/axiom/optimizer/algebra/projection.rb +212 -0
  38. data/lib/axiom/optimizer/algebra/rename.rb +381 -0
  39. data/lib/axiom/optimizer/algebra/restriction.rb +373 -0
  40. data/lib/axiom/optimizer/algebra/summarization.rb +200 -0
  41. data/lib/axiom/optimizer/algebra/union.rb +68 -0
  42. data/lib/axiom/optimizer/function.rb +87 -0
  43. data/lib/axiom/optimizer/function/binary.rb +124 -0
  44. data/lib/axiom/optimizer/function/connective/binary.rb +245 -0
  45. data/lib/axiom/optimizer/function/connective/conjunction.rb +122 -0
  46. data/lib/axiom/optimizer/function/connective/disjunction.rb +122 -0
  47. data/lib/axiom/optimizer/function/connective/negation.rb +65 -0
  48. data/lib/axiom/optimizer/function/numeric.rb +34 -0
  49. data/lib/axiom/optimizer/function/numeric/absolute.rb +20 -0
  50. data/lib/axiom/optimizer/function/numeric/addition.rb +20 -0
  51. data/lib/axiom/optimizer/function/numeric/division.rb +20 -0
  52. data/lib/axiom/optimizer/function/numeric/exponentiation.rb +20 -0
  53. data/lib/axiom/optimizer/function/numeric/modulo.rb +20 -0
  54. data/lib/axiom/optimizer/function/numeric/multiplication.rb +20 -0
  55. data/lib/axiom/optimizer/function/numeric/square_root.rb +20 -0
  56. data/lib/axiom/optimizer/function/numeric/subtraction.rb +20 -0
  57. data/lib/axiom/optimizer/function/numeric/unary_minus.rb +20 -0
  58. data/lib/axiom/optimizer/function/numeric/unary_plus.rb +20 -0
  59. data/lib/axiom/optimizer/function/predicate.rb +61 -0
  60. data/lib/axiom/optimizer/function/predicate/comparable.rb +144 -0
  61. data/lib/axiom/optimizer/function/predicate/enumerable.rb +138 -0
  62. data/lib/axiom/optimizer/function/predicate/equality.rb +44 -0
  63. data/lib/axiom/optimizer/function/predicate/exclusion.rb +43 -0
  64. data/lib/axiom/optimizer/function/predicate/greater_than.rb +55 -0
  65. data/lib/axiom/optimizer/function/predicate/greater_than_or_equal_to.rb +55 -0
  66. data/lib/axiom/optimizer/function/predicate/inclusion.rb +43 -0
  67. data/lib/axiom/optimizer/function/predicate/inequality.rb +44 -0
  68. data/lib/axiom/optimizer/function/predicate/less_than.rb +55 -0
  69. data/lib/axiom/optimizer/function/predicate/less_than_or_equal_to.rb +55 -0
  70. data/lib/axiom/optimizer/function/predicate/match.rb +20 -0
  71. data/lib/axiom/optimizer/function/predicate/no_match.rb +20 -0
  72. data/lib/axiom/optimizer/function/string/length.rb +31 -0
  73. data/lib/axiom/optimizer/function/unary.rb +86 -0
  74. data/lib/axiom/optimizer/optimizable.rb +60 -0
  75. data/lib/axiom/optimizer/relation/materialized.rb +40 -0
  76. data/lib/axiom/optimizer/relation/operation/binary.rb +134 -0
  77. data/lib/axiom/optimizer/relation/operation/combination.rb +33 -0
  78. data/lib/axiom/optimizer/relation/operation/deletion.rb +20 -0
  79. data/lib/axiom/optimizer/relation/operation/insertion.rb +20 -0
  80. data/lib/axiom/optimizer/relation/operation/limit.rb +141 -0
  81. data/lib/axiom/optimizer/relation/operation/offset.rb +106 -0
  82. data/lib/axiom/optimizer/relation/operation/order.rb +85 -0
  83. data/lib/axiom/optimizer/relation/operation/reverse.rb +85 -0
  84. data/lib/axiom/optimizer/relation/operation/unary.rb +124 -0
  85. data/lib/axiom/optimizer/support/predicate_partition.rb +184 -0
  86. data/lib/axiom/optimizer/version.rb +10 -0
  87. data/spec/integration/axiom/algebra/difference/optimize_spec.rb +160 -0
  88. data/spec/integration/axiom/algebra/intersection/optimize_spec.rb +160 -0
  89. data/spec/integration/axiom/algebra/join/optimize_spec.rb +112 -0
  90. data/spec/integration/axiom/algebra/product/optimize_spec.rb +178 -0
  91. data/spec/integration/axiom/algebra/projection/optimize_spec.rb +250 -0
  92. data/spec/integration/axiom/algebra/rename/optimize_spec.rb +442 -0
  93. data/spec/integration/axiom/algebra/restriction/optimize_spec.rb +218 -0
  94. data/spec/integration/axiom/algebra/summarization/optimize_spec.rb +49 -0
  95. data/spec/integration/axiom/algebra/union/optimize_spec.rb +200 -0
  96. data/spec/integration/axiom/function/connective/conjunction/optimize_spec.rb +236 -0
  97. data/spec/integration/axiom/function/connective/disjunction/optimize_spec.rb +237 -0
  98. data/spec/integration/axiom/function/connective/negation/optimize_spec.rb +43 -0
  99. data/spec/integration/axiom/function/optimize_spec.rb +30 -0
  100. data/spec/integration/axiom/function/predicate/equality/optimize_spec.rb +92 -0
  101. data/spec/integration/axiom/function/predicate/exclusion/optimize_spec.rb +133 -0
  102. data/spec/integration/axiom/function/predicate/greater_than/optimize_spec.rb +102 -0
  103. data/spec/integration/axiom/function/predicate/greater_than_or_equal_to/optimize_spec.rb +102 -0
  104. data/spec/integration/axiom/function/predicate/inclusion/optimize_spec.rb +133 -0
  105. data/spec/integration/axiom/function/predicate/inequality/optimize_spec.rb +92 -0
  106. data/spec/integration/axiom/function/predicate/less_than/optimize_spec.rb +102 -0
  107. data/spec/integration/axiom/function/predicate/less_than_or_equal_to/optimize_spec.rb +102 -0
  108. data/spec/integration/axiom/relation/empty/optimize_spec.rb +13 -0
  109. data/spec/integration/axiom/relation/materialized/optimize_spec.rb +29 -0
  110. data/spec/integration/axiom/relation/operation/limit/optimize_spec.rb +142 -0
  111. data/spec/integration/axiom/relation/operation/offset/optimize_spec.rb +100 -0
  112. data/spec/integration/axiom/relation/operation/order/optimize_spec.rb +105 -0
  113. data/spec/integration/axiom/relation/operation/reverse/optimize_spec.rb +115 -0
  114. data/spec/integration/axiom/relation/optimize_spec.rb +23 -0
  115. data/spec/rcov.opts +7 -0
  116. data/spec/shared/function_connective_binary_optimize_behavior.rb +102 -0
  117. data/spec/shared/optimize_method_behavior.rb +16 -0
  118. data/spec/spec_helper.rb +38 -0
  119. data/spec/support/add_method_missing.rb +15 -0
  120. data/spec/support/config_alias.rb +3 -0
  121. data/spec/support/ice_nine_config.rb +6 -0
  122. data/spec/support/lazy_enumerable.rb +18 -0
  123. data/spec/unit/axiom/optimizer/algebra/difference/empty_left/optimize_spec.rb +19 -0
  124. data/spec/unit/axiom/optimizer/algebra/difference/empty_right/optimize_spec.rb +19 -0
  125. data/spec/unit/axiom/optimizer/algebra/difference/equal_operands/optimize_spec.rb +23 -0
  126. data/spec/unit/axiom/optimizer/algebra/extension/extensions_spec.rb +31 -0
  127. data/spec/unit/axiom/optimizer/algebra/extension/order_operand/optimizable_predicate_spec.rb +23 -0
  128. data/spec/unit/axiom/optimizer/algebra/extension/order_operand/optimize_spec.rb +22 -0
  129. data/spec/unit/axiom/optimizer/algebra/extension/unoptimized_operand/optimizable_predicate_spec.rb +37 -0
  130. data/spec/unit/axiom/optimizer/algebra/extension/unoptimized_operand/optimize_spec.rb +27 -0
  131. data/spec/unit/axiom/optimizer/algebra/intersection/empty_left/optimize_spec.rb +19 -0
  132. data/spec/unit/axiom/optimizer/algebra/intersection/empty_right/optimize_spec.rb +19 -0
  133. data/spec/unit/axiom/optimizer/algebra/intersection/equal_operands/optimize_spec.rb +19 -0
  134. data/spec/unit/axiom/optimizer/algebra/join/disjoint_headers/optimizable_predicate_spec.rb +29 -0
  135. data/spec/unit/axiom/optimizer/algebra/join/disjoint_headers/optimize_spec.rb +22 -0
  136. data/spec/unit/axiom/optimizer/algebra/join/equal_headers/optimizable_predicate_spec.rb +29 -0
  137. data/spec/unit/axiom/optimizer/algebra/join/equal_headers/optimize_spec.rb +23 -0
  138. data/spec/unit/axiom/optimizer/algebra/join/materialized_left/optimizable_predicate_spec.rb +42 -0
  139. data/spec/unit/axiom/optimizer/algebra/join/materialized_left/optimize_spec.rb +55 -0
  140. data/spec/unit/axiom/optimizer/algebra/join/materialized_right/optimizable_predicate_spec.rb +42 -0
  141. data/spec/unit/axiom/optimizer/algebra/join/materialized_right/optimize_spec.rb +55 -0
  142. data/spec/unit/axiom/optimizer/algebra/product/table_dee_left/optimizable_predicate_spec.rb +27 -0
  143. data/spec/unit/axiom/optimizer/algebra/product/table_dee_left/optimize_spec.rb +18 -0
  144. data/spec/unit/axiom/optimizer/algebra/product/table_dee_right/optimizable_predicate_spec.rb +27 -0
  145. data/spec/unit/axiom/optimizer/algebra/product/table_dee_right/optimize_spec.rb +18 -0
  146. data/spec/unit/axiom/optimizer/algebra/projection/empty_operand/optimizable_predicate_spec.rb +27 -0
  147. data/spec/unit/axiom/optimizer/algebra/projection/empty_operand/optimize_spec.rb +22 -0
  148. data/spec/unit/axiom/optimizer/algebra/projection/extension_operand/optimizable_predicate_spec.rb +35 -0
  149. data/spec/unit/axiom/optimizer/algebra/projection/extension_operand/optimize_spec.rb +22 -0
  150. data/spec/unit/axiom/optimizer/algebra/projection/projection_operand/optimizable_predicate_spec.rb +28 -0
  151. data/spec/unit/axiom/optimizer/algebra/projection/projection_operand/optimize_spec.rb +22 -0
  152. data/spec/unit/axiom/optimizer/algebra/projection/union_operand/optimizable_predicate_spec.rb +29 -0
  153. data/spec/unit/axiom/optimizer/algebra/projection/union_operand/optimize_spec.rb +25 -0
  154. data/spec/unit/axiom/optimizer/algebra/projection/unoptimized_operand/optimizable_predicate_spec.rb +28 -0
  155. data/spec/unit/axiom/optimizer/algebra/projection/unoptimized_operand/optimize_spec.rb +22 -0
  156. data/spec/unit/axiom/optimizer/algebra/rename/aliases_spec.rb +23 -0
  157. data/spec/unit/axiom/optimizer/algebra/rename/empty_operand/optimizable_predicate_spec.rb +27 -0
  158. data/spec/unit/axiom/optimizer/algebra/rename/empty_operand/optimize_spec.rb +21 -0
  159. data/spec/unit/axiom/optimizer/algebra/rename/limit_operand/optimizable_predicate_spec.rb +28 -0
  160. data/spec/unit/axiom/optimizer/algebra/rename/limit_operand/optimize_spec.rb +23 -0
  161. data/spec/unit/axiom/optimizer/algebra/rename/offset_operand/optimizable_predicate_spec.rb +28 -0
  162. data/spec/unit/axiom/optimizer/algebra/rename/offset_operand/optimize_spec.rb +23 -0
  163. data/spec/unit/axiom/optimizer/algebra/rename/order_operand/optimizable_predicate_spec.rb +28 -0
  164. data/spec/unit/axiom/optimizer/algebra/rename/order_operand/optimize_spec.rb +22 -0
  165. data/spec/unit/axiom/optimizer/algebra/rename/projection_operand/optimizable_predicate_spec.rb +43 -0
  166. data/spec/unit/axiom/optimizer/algebra/rename/projection_operand/optimize_spec.rb +22 -0
  167. data/spec/unit/axiom/optimizer/algebra/rename/rename_operand/optimizable_predicate_spec.rb +30 -0
  168. data/spec/unit/axiom/optimizer/algebra/rename/rename_operand/optimize_spec.rb +22 -0
  169. data/spec/unit/axiom/optimizer/algebra/rename/rename_operand_and_empty_aliases/optimizable_predicate_spec.rb +37 -0
  170. data/spec/unit/axiom/optimizer/algebra/rename/rename_operand_and_empty_aliases/optimize_spec.rb +18 -0
  171. data/spec/unit/axiom/optimizer/algebra/rename/restriction_operand/optimizable_predicate_spec.rb +29 -0
  172. data/spec/unit/axiom/optimizer/algebra/rename/restriction_operand/optimize_spec.rb +23 -0
  173. data/spec/unit/axiom/optimizer/algebra/rename/reverse_operand/optimizable_predicate_spec.rb +27 -0
  174. data/spec/unit/axiom/optimizer/algebra/rename/reverse_operand/optimize_spec.rb +23 -0
  175. data/spec/unit/axiom/optimizer/algebra/rename/set_operand/optimizable_predicate_spec.rb +29 -0
  176. data/spec/unit/axiom/optimizer/algebra/rename/set_operand/optimize_spec.rb +23 -0
  177. data/spec/unit/axiom/optimizer/algebra/rename/unoptimized_operand/optimizable_predicate_spec.rb +29 -0
  178. data/spec/unit/axiom/optimizer/algebra/rename/unoptimized_operand/optimize_spec.rb +23 -0
  179. data/spec/unit/axiom/optimizer/algebra/restriction/combination_operand/optimizable_predicate_spec.rb +41 -0
  180. data/spec/unit/axiom/optimizer/algebra/restriction/combination_operand/optimize_spec.rb +35 -0
  181. data/spec/unit/axiom/optimizer/algebra/restriction/contradiction/optimizable_predicate_spec.rb +46 -0
  182. data/spec/unit/axiom/optimizer/algebra/restriction/contradiction/optimize_spec.rb +23 -0
  183. data/spec/unit/axiom/optimizer/algebra/restriction/join_operand/optimizable_predicate_spec.rb +51 -0
  184. data/spec/unit/axiom/optimizer/algebra/restriction/join_operand/optimize_spec.rb +48 -0
  185. data/spec/unit/axiom/optimizer/algebra/restriction/order_operand/optimizable_predicate_spec.rb +28 -0
  186. data/spec/unit/axiom/optimizer/algebra/restriction/order_operand/optimize_spec.rb +22 -0
  187. data/spec/unit/axiom/optimizer/algebra/restriction/predicate_spec.rb +18 -0
  188. data/spec/unit/axiom/optimizer/algebra/restriction/product_operand/optimizable_predicate_spec.rb +44 -0
  189. data/spec/unit/axiom/optimizer/algebra/restriction/product_operand/optimize_spec.rb +48 -0
  190. data/spec/unit/axiom/optimizer/algebra/restriction/restriction_operand/optimizable_predicate_spec.rb +30 -0
  191. data/spec/unit/axiom/optimizer/algebra/restriction/restriction_operand/optimize_spec.rb +24 -0
  192. data/spec/unit/axiom/optimizer/algebra/restriction/set_operand/optimizable_predicate_spec.rb +30 -0
  193. data/spec/unit/axiom/optimizer/algebra/restriction/set_operand/optimize_spec.rb +24 -0
  194. data/spec/unit/axiom/optimizer/algebra/restriction/tautology/optimizable_predicate_spec.rb +33 -0
  195. data/spec/unit/axiom/optimizer/algebra/restriction/tautology/optimize_spec.rb +19 -0
  196. data/spec/unit/axiom/optimizer/algebra/restriction/unoptimized_operand/optimizable_predicate_spec.rb +44 -0
  197. data/spec/unit/axiom/optimizer/algebra/restriction/unoptimized_operand/optimize_spec.rb +24 -0
  198. data/spec/unit/axiom/optimizer/algebra/summarization/empty_operand/class_methods/extension_default_spec.rb +22 -0
  199. data/spec/unit/axiom/optimizer/algebra/summarization/empty_operand/optimizable_predicate_spec.rb +29 -0
  200. data/spec/unit/axiom/optimizer/algebra/summarization/empty_operand/optimize_spec.rb +47 -0
  201. data/spec/unit/axiom/optimizer/algebra/summarization/empty_summarize_per/optimizable_predicate_spec.rb +29 -0
  202. data/spec/unit/axiom/optimizer/algebra/summarization/empty_summarize_per/optimize_spec.rb +25 -0
  203. data/spec/unit/axiom/optimizer/algebra/summarization/order_operand/optimizable_predicate_spec.rb +23 -0
  204. data/spec/unit/axiom/optimizer/algebra/summarization/order_operand/optimize_spec.rb +22 -0
  205. data/spec/unit/axiom/optimizer/algebra/summarization/summarize_per_spec.rb +29 -0
  206. data/spec/unit/axiom/optimizer/algebra/summarization/summarizers_spec.rb +31 -0
  207. data/spec/unit/axiom/optimizer/algebra/summarization/unoptimized_operand/optimizable_predicate_spec.rb +49 -0
  208. data/spec/unit/axiom/optimizer/algebra/summarization/unoptimized_operand/optimize_spec.rb +30 -0
  209. data/spec/unit/axiom/optimizer/algebra/union/empty_left/optimize_spec.rb +19 -0
  210. data/spec/unit/axiom/optimizer/algebra/union/empty_right/optimize_spec.rb +19 -0
  211. data/spec/unit/axiom/optimizer/algebra/union/equal_operands/optimize_spec.rb +19 -0
  212. data/spec/unit/axiom/optimizer/class_methods/chain_spec.rb +56 -0
  213. data/spec/unit/axiom/optimizer/function/binary/constant_operands/optimizable_predicate_spec.rb +36 -0
  214. data/spec/unit/axiom/optimizer/function/binary/constant_operands/optimize_spec.rb +18 -0
  215. data/spec/unit/axiom/optimizer/function/binary/left_spec.rb +28 -0
  216. data/spec/unit/axiom/optimizer/function/binary/right_spec.rb +28 -0
  217. data/spec/unit/axiom/optimizer/function/binary/unoptimized_operands/optimizable_predicate_spec.rb +37 -0
  218. data/spec/unit/axiom/optimizer/function/binary/unoptimized_operands/optimize_spec.rb +23 -0
  219. data/spec/unit/axiom/optimizer/function/class_methods/optimize_functions_spec.rb +26 -0
  220. data/spec/unit/axiom/optimizer/function/class_methods/optimize_operand_spec.rb +22 -0
  221. data/spec/unit/axiom/optimizer/function/connective/binary/constant_operands/optimize_spec.rb +16 -0
  222. data/spec/unit/axiom/optimizer/function/connective/binary/equal_operands/optimizable_predicate_spec.rb +29 -0
  223. data/spec/unit/axiom/optimizer/function/connective/binary/equal_operands/optimize_spec.rb +19 -0
  224. data/spec/unit/axiom/optimizer/function/connective/binary/left_spec.rb +16 -0
  225. data/spec/unit/axiom/optimizer/function/connective/binary/redundant_left/optimizable_predicate_spec.rb +28 -0
  226. data/spec/unit/axiom/optimizer/function/connective/binary/redundant_left/optimize_spec.rb +23 -0
  227. data/spec/unit/axiom/optimizer/function/connective/binary/redundant_right/optimizable_predicate_spec.rb +28 -0
  228. data/spec/unit/axiom/optimizer/function/connective/binary/redundant_right/optimize_spec.rb +23 -0
  229. data/spec/unit/axiom/optimizer/function/connective/binary/right_spec.rb +16 -0
  230. data/spec/unit/axiom/optimizer/function/connective/conjunction/contradiction/optimizable_predicate_spec.rb +64 -0
  231. data/spec/unit/axiom/optimizer/function/connective/conjunction/contradiction/optimize_spec.rb +19 -0
  232. data/spec/unit/axiom/optimizer/function/connective/conjunction/optimizable_to_exclusion/optimizable_predicate_spec.rb +61 -0
  233. data/spec/unit/axiom/optimizer/function/connective/conjunction/optimizable_to_exclusion/optimize_spec.rb +76 -0
  234. data/spec/unit/axiom/optimizer/function/connective/conjunction/tautology_left/optimizable_predicate_spec.rb +29 -0
  235. data/spec/unit/axiom/optimizer/function/connective/conjunction/tautology_left/optimize_spec.rb +19 -0
  236. data/spec/unit/axiom/optimizer/function/connective/conjunction/tautology_right/optimizable_predicate_spec.rb +29 -0
  237. data/spec/unit/axiom/optimizer/function/connective/conjunction/tautology_right/optimize_spec.rb +19 -0
  238. data/spec/unit/axiom/optimizer/function/connective/disjunction/contradiction_left/optimizable_predicate_spec.rb +29 -0
  239. data/spec/unit/axiom/optimizer/function/connective/disjunction/contradiction_left/optimize_spec.rb +19 -0
  240. data/spec/unit/axiom/optimizer/function/connective/disjunction/contradiction_right/optimizable_predicate_spec.rb +29 -0
  241. data/spec/unit/axiom/optimizer/function/connective/disjunction/contradiction_right/optimize_spec.rb +19 -0
  242. data/spec/unit/axiom/optimizer/function/connective/disjunction/optimizable_to_inclusion/optimizable_predicate_spec.rb +61 -0
  243. data/spec/unit/axiom/optimizer/function/connective/disjunction/optimizable_to_inclusion/optimize_spec.rb +76 -0
  244. data/spec/unit/axiom/optimizer/function/connective/disjunction/tautology/optimizable_predicate_spec.rb +64 -0
  245. data/spec/unit/axiom/optimizer/function/connective/disjunction/tautology/optimize_spec.rb +19 -0
  246. data/spec/unit/axiom/optimizer/function/connective/negation/constant_operand/optimize_spec.rb +16 -0
  247. data/spec/unit/axiom/optimizer/function/connective/negation/invertible_operand/optimizable_predicate_spec.rb +28 -0
  248. data/spec/unit/axiom/optimizer/function/connective/negation/invertible_operand/optimize_spec.rb +22 -0
  249. data/spec/unit/axiom/optimizer/function/connective/negation/operand_spec.rb +14 -0
  250. data/spec/unit/axiom/optimizer/function/predicate/comparable/never_comparable/optimizable_predicate_spec.rb +74 -0
  251. data/spec/unit/axiom/optimizer/function/predicate/comparable/never_equivalent/optimizable_predicate_spec.rb +74 -0
  252. data/spec/unit/axiom/optimizer/function/predicate/comparable/normalizable_operands/optimizable_predicate_spec.rb +43 -0
  253. data/spec/unit/axiom/optimizer/function/predicate/comparable/normalizable_operands/optimize_spec.rb +21 -0
  254. data/spec/unit/axiom/optimizer/function/predicate/constant_operands/optimize_spec.rb +16 -0
  255. data/spec/unit/axiom/optimizer/function/predicate/contradiction/optimize_spec.rb +18 -0
  256. data/spec/unit/axiom/optimizer/function/predicate/enumerable/class_methods/sort_by_value_spec.rb +27 -0
  257. data/spec/unit/axiom/optimizer/function/predicate/enumerable/empty_right/optimizable_predicate_spec.rb +78 -0
  258. data/spec/unit/axiom/optimizer/function/predicate/enumerable/one_right/optimizable_predicate_spec.rb +78 -0
  259. data/spec/unit/axiom/optimizer/function/predicate/enumerable/unoptimized_operands/optimizable_predicate_spec.rb +51 -0
  260. data/spec/unit/axiom/optimizer/function/predicate/enumerable/unoptimized_operands/optimize_spec.rb +66 -0
  261. data/spec/unit/axiom/optimizer/function/predicate/equality/tautology/optimizable_predicate_spec.rb +29 -0
  262. data/spec/unit/axiom/optimizer/function/predicate/exclusion/empty_right/optimize_spec.rb +45 -0
  263. data/spec/unit/axiom/optimizer/function/predicate/exclusion/one_right/optimize_spec.rb +65 -0
  264. data/spec/unit/axiom/optimizer/function/predicate/greater_than/contradiction/optimizable_predicate_spec.rb +43 -0
  265. data/spec/unit/axiom/optimizer/function/predicate/greater_than/tautology/optimizable_predicate_spec.rb +28 -0
  266. data/spec/unit/axiom/optimizer/function/predicate/greater_than_or_equal_to/contradiction/optimizable_predicate_spec.rb +43 -0
  267. data/spec/unit/axiom/optimizer/function/predicate/greater_than_or_equal_to/tautology/optimizable_predicate_spec.rb +43 -0
  268. data/spec/unit/axiom/optimizer/function/predicate/inclusion/empty_right/optimize_spec.rb +45 -0
  269. data/spec/unit/axiom/optimizer/function/predicate/inclusion/one_right/optimize_spec.rb +66 -0
  270. data/spec/unit/axiom/optimizer/function/predicate/inequality/contradiction/optimizable_predicate_spec.rb +29 -0
  271. data/spec/unit/axiom/optimizer/function/predicate/less_than/contradiction/optimizable_predicate_spec.rb +43 -0
  272. data/spec/unit/axiom/optimizer/function/predicate/less_than/tautology/optimizable_predicate_spec.rb +28 -0
  273. data/spec/unit/axiom/optimizer/function/predicate/less_than_or_equal_to/contradiction/optimizable_predicate_spec.rb +43 -0
  274. data/spec/unit/axiom/optimizer/function/predicate/less_than_or_equal_to/tautology/optimizable_predicate_spec.rb +43 -0
  275. data/spec/unit/axiom/optimizer/function/predicate/tautology/optimize_spec.rb +18 -0
  276. data/spec/unit/axiom/optimizer/function/unary/constant_operand/optimizable_predicate_spec.rb +27 -0
  277. data/spec/unit/axiom/optimizer/function/unary/constant_operand/optimize_spec.rb +18 -0
  278. data/spec/unit/axiom/optimizer/function/unary/operand_spec.rb +27 -0
  279. data/spec/unit/axiom/optimizer/function/unary/unoptimized_operand/optimizable_predicate_spec.rb +27 -0
  280. data/spec/unit/axiom/optimizer/function/unary/unoptimized_operand/optimize_spec.rb +18 -0
  281. data/spec/unit/axiom/optimizer/function/util/class_methods/attribute_spec.rb +21 -0
  282. data/spec/unit/axiom/optimizer/function/util/class_methods/constant_spec.rb +27 -0
  283. data/spec/unit/axiom/optimizer/function/util/class_methods/max_spec.rb +27 -0
  284. data/spec/unit/axiom/optimizer/function/util/class_methods/min_spec.rb +27 -0
  285. data/spec/unit/axiom/optimizer/operation_spec.rb +13 -0
  286. data/spec/unit/axiom/optimizer/optimizable/class_methods/optimizer_spec.rb +34 -0
  287. data/spec/unit/axiom/optimizer/optimizable/optimize_spec.rb +38 -0
  288. data/spec/unit/axiom/optimizer/optimizable_predicate_spec.rb +17 -0
  289. data/spec/unit/axiom/optimizer/optimize_spec.rb +17 -0
  290. data/spec/unit/axiom/optimizer/predicate_partition/left_spec.rb +149 -0
  291. data/spec/unit/axiom/optimizer/predicate_partition/remainder_spec.rb +149 -0
  292. data/spec/unit/axiom/optimizer/predicate_partition/right_spec.rb +149 -0
  293. data/spec/unit/axiom/optimizer/relation/materialized/empty_operand/optimizable_predicate_spec.rb +22 -0
  294. data/spec/unit/axiom/optimizer/relation/materialized/empty_operand/optimize_spec.rb +21 -0
  295. data/spec/unit/axiom/optimizer/relation/operation/binary/empty_left/optimizable_predicate_spec.rb +28 -0
  296. data/spec/unit/axiom/optimizer/relation/operation/binary/empty_right/optimizable_predicate_spec.rb +28 -0
  297. data/spec/unit/axiom/optimizer/relation/operation/binary/equal_operands/optimizable_predicate_spec.rb +31 -0
  298. data/spec/unit/axiom/optimizer/relation/operation/binary/left_spec.rb +15 -0
  299. data/spec/unit/axiom/optimizer/relation/operation/binary/materialized_operands/optimizable_predicate_spec.rb +37 -0
  300. data/spec/unit/axiom/optimizer/relation/operation/binary/materialized_operands/optimize_spec.rb +22 -0
  301. data/spec/unit/axiom/optimizer/relation/operation/binary/order_left/optimizable_predicate_spec.rb +23 -0
  302. data/spec/unit/axiom/optimizer/relation/operation/binary/order_left/optimize_spec.rb +23 -0
  303. data/spec/unit/axiom/optimizer/relation/operation/binary/order_right/optimizable_predicate_spec.rb +23 -0
  304. data/spec/unit/axiom/optimizer/relation/operation/binary/order_right/optimize_spec.rb +23 -0
  305. data/spec/unit/axiom/optimizer/relation/operation/binary/right_spec.rb +15 -0
  306. data/spec/unit/axiom/optimizer/relation/operation/binary/unoptimized_operands/optimizable_predicate_spec.rb +40 -0
  307. data/spec/unit/axiom/optimizer/relation/operation/binary/unoptimized_operands/optimize_spec.rb +24 -0
  308. data/spec/unit/axiom/optimizer/relation/operation/combination/optimize_spec.rb +18 -0
  309. data/spec/unit/axiom/optimizer/relation/operation/limit/equal_limit_operand/optimizable_predicate_spec.rb +33 -0
  310. data/spec/unit/axiom/optimizer/relation/operation/limit/equal_limit_operand/optimize_spec.rb +18 -0
  311. data/spec/unit/axiom/optimizer/relation/operation/limit/limit_operand/optimizable_predicate_spec.rb +27 -0
  312. data/spec/unit/axiom/optimizer/relation/operation/limit/limit_operand/optimize_spec.rb +35 -0
  313. data/spec/unit/axiom/optimizer/relation/operation/limit/unoptimized_operand/optimizable_predicate_spec.rb +28 -0
  314. data/spec/unit/axiom/optimizer/relation/operation/limit/unoptimized_operand/optimize_spec.rb +22 -0
  315. data/spec/unit/axiom/optimizer/relation/operation/limit/zero_limit/optimizable_predicate_spec.rb +27 -0
  316. data/spec/unit/axiom/optimizer/relation/operation/limit/zero_limit/optimize_spec.rb +22 -0
  317. data/spec/unit/axiom/optimizer/relation/operation/offset/offset_operand/optimizable_predicate_spec.rb +27 -0
  318. data/spec/unit/axiom/optimizer/relation/operation/offset/offset_operand/optimize_spec.rb +21 -0
  319. data/spec/unit/axiom/optimizer/relation/operation/offset/unoptimized_operand/optimizable_predicate_spec.rb +28 -0
  320. data/spec/unit/axiom/optimizer/relation/operation/offset/unoptimized_operand/optimize_spec.rb +22 -0
  321. data/spec/unit/axiom/optimizer/relation/operation/offset/zero_offset/optimizable_predicate_spec.rb +27 -0
  322. data/spec/unit/axiom/optimizer/relation/operation/offset/zero_offset/optimize_spec.rb +17 -0
  323. data/spec/unit/axiom/optimizer/relation/operation/order/one_limit_operand/optimizable_predicate_spec.rb +33 -0
  324. data/spec/unit/axiom/optimizer/relation/operation/order/one_limit_operand/optimize_spec.rb +18 -0
  325. data/spec/unit/axiom/optimizer/relation/operation/order/order_operand/optimizable_predicate_spec.rb +27 -0
  326. data/spec/unit/axiom/optimizer/relation/operation/order/order_operand/optimize_spec.rb +22 -0
  327. data/spec/unit/axiom/optimizer/relation/operation/order/unoptimized_operand/optimizable_predicate_spec.rb +28 -0
  328. data/spec/unit/axiom/optimizer/relation/operation/order/unoptimized_operand/optimize_spec.rb +23 -0
  329. data/spec/unit/axiom/optimizer/relation/operation/reverse/order_operand/optimizable_predicate_spec.rb +27 -0
  330. data/spec/unit/axiom/optimizer/relation/operation/reverse/order_operand/optimize_spec.rb +22 -0
  331. data/spec/unit/axiom/optimizer/relation/operation/reverse/reverse_operand/optimizable_predicate_spec.rb +27 -0
  332. data/spec/unit/axiom/optimizer/relation/operation/reverse/reverse_operand/optimize_spec.rb +19 -0
  333. data/spec/unit/axiom/optimizer/relation/operation/reverse/unoptimized_operand/optimizable_predicate_spec.rb +27 -0
  334. data/spec/unit/axiom/optimizer/relation/operation/reverse/unoptimized_operand/optimize_spec.rb +24 -0
  335. data/spec/unit/axiom/optimizer/relation/operation/unary/empty_operand/optimizable_predicate_spec.rb +23 -0
  336. data/spec/unit/axiom/optimizer/relation/operation/unary/empty_operand/optimize_spec.rb +17 -0
  337. data/spec/unit/axiom/optimizer/relation/operation/unary/header_spec.rb +15 -0
  338. data/spec/unit/axiom/optimizer/relation/operation/unary/materialized_operand/optimizable_predicate_spec.rb +23 -0
  339. data/spec/unit/axiom/optimizer/relation/operation/unary/materialized_operand/optimize_spec.rb +20 -0
  340. data/spec/unit/axiom/optimizer/relation/operation/unary/operand_spec.rb +16 -0
  341. data/spec/unit/axiom/optimizer/relation/operation/unary/order_operand/optimizable_predicate_spec.rb +28 -0
  342. data/spec/unit/axiom/optimizer/relation/operation/unary/order_operand/optimize_spec.rb +27 -0
  343. data/spec/unit/axiom/optimizer/relation/operation/unary/unchanged_header/optimizable_predicate_spec.rb +24 -0
  344. data/spec/unit/axiom/optimizer/relation/operation/unary/unchanged_header/optimize_spec.rb +14 -0
  345. metadata +697 -0
@@ -0,0 +1,250 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Algebra::Projection, '#optimize' do
6
+ subject { object.optimize }
7
+
8
+ let(:header) { [ [ :id, Integer ], [ :name, String ], [ :age, Integer ] ] }
9
+ let(:body) { LazyEnumerable.new([ [ 1, 'Dan Kubb', 35 ] ]) }
10
+ let(:relation) { Relation.new(header, body) }
11
+ let(:operand) { relation }
12
+ let(:object) { described_class.new(operand, attributes) }
13
+
14
+ before do
15
+ # skip dup of the body to avoid clearing the method stubs
16
+ body.stub!(:frozen?).and_return(true)
17
+ end
18
+
19
+ context 'when the attributes are equivalent to the relation headers, and in the same order' do
20
+ let(:attributes) { header }
21
+
22
+ it { should equal(operand) }
23
+
24
+ it 'returns an equivalent relation to the unoptimized operation' do
25
+ should == object
26
+ end
27
+
28
+ it 'does not execute body#each' do
29
+ body.should_not_receive(:each)
30
+ subject
31
+ end
32
+
33
+ it_should_behave_like 'an optimize method'
34
+ end
35
+
36
+ context 'when the attributes are equivalent to the relation headers, and not in the same order' do
37
+ let(:attributes) { [ :name, :id ] }
38
+
39
+ it 'does not factor out the object, because tuple order is currently significant' do
40
+ should equal(object)
41
+ end
42
+
43
+ it 'does not execute body#each' do
44
+ body.should_not_receive(:each)
45
+ subject
46
+ end
47
+
48
+ it_should_behave_like 'an optimize method'
49
+ end
50
+
51
+ context 'when the attributes are different from the relation headers' do
52
+ let(:attributes) { [ :id ] }
53
+
54
+ it { should equal(object) }
55
+
56
+ it 'does not execute body#each' do
57
+ body.should_not_receive(:each)
58
+ subject
59
+ end
60
+
61
+ it_should_behave_like 'an optimize method'
62
+ end
63
+
64
+ context 'containing an empty relation' do
65
+ let(:operand) { Relation::Empty.new(header) }
66
+ let(:attributes) { [ :id ] }
67
+
68
+ it { should eql(Relation::Empty.new(object.header)) }
69
+
70
+ it 'returns an equivalent relation to the unoptimized operation' do
71
+ should == object
72
+ end
73
+
74
+ it_should_behave_like 'an optimize method'
75
+ end
76
+
77
+ context 'containing an empty relation when optimized' do
78
+ let(:operand) { Algebra::Restriction.new(relation, Function::Proposition::Contradiction.instance) }
79
+ let(:attributes) { [ :id ] }
80
+
81
+ it { should eql(Relation::Empty.new(object.header)) }
82
+
83
+ it 'returns an equivalent relation to the unoptimized operation' do
84
+ should == object
85
+ end
86
+
87
+ it 'does not execute body#each' do
88
+ body.should_not_receive(:each)
89
+ subject
90
+ end
91
+
92
+ it_should_behave_like 'an optimize method'
93
+ end
94
+
95
+ context 'containing an optimizable relation' do
96
+ let(:operand) { Algebra::Restriction.new(relation, Function::Proposition::Tautology.instance) }
97
+ let(:attributes) { [ :id ] }
98
+
99
+ it { should_not equal(object) }
100
+
101
+ it { should be_kind_of(described_class) }
102
+
103
+ its(:operand) { should equal(relation) }
104
+
105
+ its(:header) { should == object.header }
106
+
107
+ it 'returns an equivalent relation to the unoptimized operation' do
108
+ should == object
109
+ end
110
+
111
+ it 'does not execute body#each' do
112
+ body.should_not_receive(:each)
113
+ subject
114
+ end
115
+
116
+ it_should_behave_like 'an optimize method'
117
+ end
118
+
119
+ context 'containing a projection' do
120
+ let(:operand) { relation.project([ :id, :name ]) }
121
+ let(:attributes) { [ :id ] }
122
+
123
+ it { should_not equal(object) }
124
+
125
+ it { should be_kind_of(described_class) }
126
+
127
+ its(:operand) { should equal(relation) }
128
+
129
+ its(:header) { should == object.header }
130
+
131
+ it 'returns an equivalent relation to the unoptimized operation' do
132
+ should == object
133
+ end
134
+
135
+ it 'does not execute body#each' do
136
+ body.should_not_receive(:each)
137
+ subject
138
+ end
139
+
140
+ it_should_behave_like 'an optimize method'
141
+ end
142
+
143
+ context 'containing a set operation' do
144
+ let(:left) { Relation.new([ [ :id, Integer ], [ :name, String ] ], LazyEnumerable.new([ [ 1, 'Dan Kubb' ] ])) }
145
+ let(:right) { Relation.new([ [ :id, Integer ], [ :name, String ] ], LazyEnumerable.new([ [ 2, 'Dan Kubb' ] ])) }
146
+ let(:operand) { left.union(right) }
147
+ let(:attributes) { [ :name ] }
148
+
149
+ it 'pushes the object to each relation' do
150
+ should eql(Algebra::Union.new(
151
+ described_class.new(left, object.header),
152
+ described_class.new(right, object.header)
153
+ ))
154
+ end
155
+
156
+ it 'returns an equivalent relation to the unoptimized operation' do
157
+ should == object
158
+ end
159
+
160
+ it 'does not execute body#each' do
161
+ body.should_not_receive(:each)
162
+ subject
163
+ end
164
+
165
+ it_should_behave_like 'an optimize method'
166
+ end
167
+
168
+ context 'containing a set operation containing a projection of relations' do
169
+ let(:left_body) { LazyEnumerable.new([ [ 1, 'Dan Kubb', 35 ] ]) }
170
+ let(:right_body) { LazyEnumerable.new([ [ 2, 'Dan Kubb', 35 ] ]) }
171
+ let(:left) { Relation.new(header, left_body) }
172
+ let(:right) { Relation.new(header, right_body) }
173
+ let(:operand) { left.project([ :id, :name ]).union(right.project([ :id, :name ])) }
174
+ let(:attributes) { [ :name ] }
175
+
176
+ before do
177
+ # skip dup of the left and right body to avoid clearing the method stubs
178
+ left_body.stub!(:frozen?).and_return(true)
179
+ right_body.stub!(:frozen?).and_return(true)
180
+ end
181
+
182
+ it 'pushes the object to each relation, and combine the nested objects' do
183
+ should eql(left.project([ :name ]).union(right.project([ :name ])))
184
+ end
185
+
186
+ it 'returns an equivalent relation to the unoptimized operation' do
187
+ should == object
188
+ end
189
+
190
+ it 'does not execute left_body#each' do
191
+ pending 'TODO: should only compare left and right with #eql? if they are materialized' do
192
+ left_body.should_not_receive(:each)
193
+ subject
194
+ end
195
+ end
196
+
197
+ it 'does not execute right_body#each' do
198
+ pending 'TODO: should only compare left and right with #eql? if they are materialized' do
199
+ right_body.should_not_receive(:each)
200
+ subject
201
+ end
202
+ end
203
+
204
+ it_should_behave_like 'an optimize method'
205
+ end
206
+
207
+ context 'containing a set operation containing a projection of materialized relations' do
208
+ let(:left_body) { [ [ 1, 'Dan Kubb', 35 ] ] }
209
+ let(:right_body) { [ [ 2, 'Dan Kubb', 35 ] ] }
210
+ let(:left) { Relation.new(header, left_body) }
211
+ let(:right) { Relation.new(header, right_body) }
212
+ let(:operand) { left.project([ :id, :name ]).union(right.project([ :id, :name ])) }
213
+ let(:attributes) { [ :name ] }
214
+
215
+ it 'pushes the object to each relation, and combine the nested objects, then materializes' do
216
+ should eql(Relation.new([ [ :name, String ] ], [ [ 'Dan Kubb' ] ]))
217
+ end
218
+
219
+ it 'returns an equivalent relation to the unoptimized operation' do
220
+ should == object
221
+ end
222
+
223
+ it 'executes left_body#each' do
224
+ pending 'TODO: make sure this is only received once'
225
+ left_body.should_receive(:each)
226
+ subject
227
+ end
228
+
229
+ it 'executes right_body#each' do
230
+ pending 'TODO: make sure this is only received once'
231
+ right_body.should_receive(:each)
232
+ subject
233
+ end
234
+
235
+ it_should_behave_like 'an optimize method'
236
+ end
237
+
238
+ context 'containing a materialized relation' do
239
+ let(:operand) { Relation.new(header, [ [ 1, 'Dan Kubb', 35 ] ]) }
240
+ let(:attributes) { [ :id ] }
241
+
242
+ it { should eql(Relation::Materialized.new([ [ :id, Integer ] ], [ [ 1 ] ])) }
243
+
244
+ it 'returns an equivalent relation to the unoptimized operation' do
245
+ should == object
246
+ end
247
+
248
+ it_should_behave_like 'an optimize method'
249
+ end
250
+ end
@@ -0,0 +1,442 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Algebra::Rename, '#optimize' do
6
+ subject { object.optimize }
7
+
8
+ let(:body) { LazyEnumerable.new([ [ 1, 'Dan Kubb' ] ]) }
9
+ let(:relation) { Relation.new([ [ :id, Integer ], [ :name, String ] ], body) }
10
+ let(:operand) { relation }
11
+ let(:aliases) { { :id => :other_id } }
12
+ let(:object) { described_class.new(operand, aliases) }
13
+
14
+ context 'containing a relation' do
15
+ it { should equal(object) }
16
+
17
+ it 'does not execute body#each' do
18
+ body.should_not_receive(:each)
19
+ subject
20
+ end
21
+
22
+ it_should_behave_like 'an optimize method'
23
+ end
24
+
25
+ context 'containing an empty relation' do
26
+ let(:operand) { Relation::Empty.new(relation.header) }
27
+
28
+ it { should eql(Relation::Empty.new(object.header)) }
29
+
30
+ it 'returns an equivalent relation to the unoptimized operation' do
31
+ should == object
32
+ end
33
+
34
+ it 'does not execute body#each' do
35
+ body.should_not_receive(:each)
36
+ subject
37
+ end
38
+
39
+ it_should_behave_like 'an optimize method'
40
+ end
41
+
42
+ context 'containing an optimizable relation' do
43
+ let(:operand) { relation.project(relation.header) }
44
+
45
+ it { should_not equal(object) }
46
+
47
+ it { should be_kind_of(described_class) }
48
+
49
+ it 'sets aliases the same as the original object' do
50
+ subject.aliases.should == object.aliases
51
+ end
52
+
53
+ its(:operand) { should equal(relation) }
54
+
55
+ it 'returns an equivalent relation to the unoptimized operation' do
56
+ should == object
57
+ end
58
+
59
+ it 'does not execute body#each' do
60
+ body.should_not_receive(:each)
61
+ subject
62
+ end
63
+
64
+ it_should_behave_like 'an optimize method'
65
+ end
66
+
67
+ context 'containing a object operation' do
68
+ let(:operand) { described_class.new(relation, :id => :other_id) }
69
+ let(:aliases) { { :name => :other_name } }
70
+
71
+ it { should_not equal(object) }
72
+
73
+ it { should be_kind_of(described_class) }
74
+
75
+ it 'sets aliases as a union of both aliases' do
76
+ subject.aliases.should == described_class::Aliases.coerce(
77
+ relation.header,
78
+ :id => :other_id,
79
+ :name => :other_name
80
+ )
81
+ end
82
+
83
+ its(:operand) { should equal(relation) }
84
+
85
+ it 'returns an equivalent relation to the unoptimized operation' do
86
+ should == object
87
+ end
88
+
89
+ it 'does not execute body#each' do
90
+ body.should_not_receive(:each)
91
+ subject
92
+ end
93
+
94
+ it_should_behave_like 'an optimize method'
95
+ end
96
+
97
+ context 'containing a object operation with overlapping aliases' do
98
+ let(:operand) { described_class.new(relation, :id => :other_id) }
99
+ let(:aliases) { { :other_id => :another_id } }
100
+
101
+ it { should_not equal(object) }
102
+
103
+ it { should be_kind_of(described_class) }
104
+
105
+ it 'sets aliases as a union of both aliases' do
106
+ subject.aliases.should == described_class::Aliases.coerce(
107
+ relation.header,
108
+ :id => :another_id
109
+ )
110
+ end
111
+
112
+ its(:operand) { should equal(relation) }
113
+
114
+ it 'returns an equivalent relation to the unoptimized operation' do
115
+ should == object
116
+ end
117
+
118
+ it 'does not execute body#each' do
119
+ body.should_not_receive(:each)
120
+ subject
121
+ end
122
+
123
+ it_should_behave_like 'an optimize method'
124
+ end
125
+
126
+ context 'containing an inverse object operation' do
127
+ let(:operand) { described_class.new(relation, :id => :other_id) }
128
+ let(:aliases) { { :other_id => :id } }
129
+
130
+ it { should equal(relation) }
131
+
132
+ it 'returns an equivalent relation to the unoptimized operation' do
133
+ should == object
134
+ end
135
+
136
+ it 'does not execute body#each' do
137
+ body.should_not_receive(:each)
138
+ subject
139
+ end
140
+
141
+ it_should_behave_like 'an optimize method'
142
+ end
143
+
144
+ context 'containing a projection' do
145
+ let(:operand) { relation.project([ :id ]) }
146
+
147
+ it { should be_kind_of(Algebra::Projection) }
148
+
149
+ its(:operand) { should eql(described_class.new(relation, aliases)) }
150
+
151
+ its(:header) { should == [ [ :other_id, Integer ] ] }
152
+
153
+ it 'returns an equivalent relation to the unoptimized operation' do
154
+ should == object
155
+ end
156
+
157
+ it 'does not execute body#each' do
158
+ body.should_not_receive(:each)
159
+ subject
160
+ end
161
+
162
+ it_should_behave_like 'an optimize method'
163
+ end
164
+
165
+ context 'containing a projection, containing a object that cancels out' do
166
+ let(:operand) { relation.rename(:id => :other_id).project([ :other_id ]) }
167
+ let(:aliases) { { :other_id => :id } }
168
+
169
+ it 'pushes the object before the projection, and then cancel it out' do
170
+ should eql(relation.project([ :id ]))
171
+ end
172
+
173
+ it 'returns an equivalent relation to the unoptimized operation' do
174
+ should == object
175
+ end
176
+
177
+ it 'does not execute body#each' do
178
+ body.should_not_receive(:each)
179
+ subject
180
+ end
181
+
182
+ it_should_behave_like 'an optimize method'
183
+ end
184
+
185
+ context 'containing a restriction' do
186
+ let(:operand) { relation.restrict { |r| r.id.eq(1) } }
187
+
188
+ it { should be_kind_of(Algebra::Restriction) }
189
+
190
+ its(:operand) { should eql(described_class.new(relation, aliases)) }
191
+
192
+ its(:header) { should == [ [ :other_id, Integer ], [ :name, String ] ] }
193
+
194
+ it 'returns an equivalent relation to the unoptimized operation' do
195
+ should == object
196
+ end
197
+
198
+ it 'does not execute body#each' do
199
+ body.should_not_receive(:each)
200
+ subject
201
+ end
202
+
203
+ it_should_behave_like 'an optimize method'
204
+ end
205
+
206
+ context 'containing a restriction, containing a object that cancels out' do
207
+ let(:operand) { relation.rename(:id => :other_id).restrict { |r| r.other_id.eq(1) } }
208
+ let(:aliases) { { :other_id => :id } }
209
+
210
+ it 'pushes the object before the restriction, and then cancel it out' do
211
+ should eql(relation.restrict { |r| r.id.eq(1) })
212
+ end
213
+
214
+ it 'returns an equivalent relation to the unoptimized operation' do
215
+ should == object
216
+ end
217
+
218
+ it 'does not execute body#each' do
219
+ body.should_not_receive(:each)
220
+ subject
221
+ end
222
+
223
+ it_should_behave_like 'an optimize method'
224
+ end
225
+
226
+ context 'containing a set operation' do
227
+ let(:left) { Relation.new([ [ :id, Integer ], [ :name, String ] ], LazyEnumerable.new([ [ 1, 'Dan Kubb' ] ])) }
228
+ let(:right) { Relation.new([ [ :id, Integer ], [ :name, String ] ], LazyEnumerable.new([ [ 2, 'Dan Kubb' ] ])) }
229
+ let(:operand) { left.union(right) }
230
+
231
+ it 'pushes the object to each relation' do
232
+ should eql(left.rename(aliases).union(right.rename(aliases)))
233
+ end
234
+
235
+ it 'returns an equivalent relation to the unoptimized operation' do
236
+ should == object
237
+ end
238
+
239
+ it 'does not execute body#each' do
240
+ body.should_not_receive(:each)
241
+ subject
242
+ end
243
+
244
+ it_should_behave_like 'an optimize method'
245
+ end
246
+
247
+ context 'containing a set operation, containing a object that cancels out' do
248
+ let(:left) { Relation.new([ [ :id, Integer ], [ :name, String ] ], LazyEnumerable.new([ [ 1, 'Dan Kubb' ] ])) }
249
+ let(:right) { Relation.new([ [ :id, Integer ], [ :name, String ] ], LazyEnumerable.new([ [ 2, 'Dan Kubb' ] ])) }
250
+ let(:operand) { left.rename(:id => :other_id).union(right.rename(:id => :other_id)) }
251
+ let(:aliases) { { :other_id => :id } }
252
+
253
+ it 'pushes the object to each relation, then cancel it out' do
254
+ should eql(left.union(right))
255
+ end
256
+
257
+ it 'returns an equivalent relation to the unoptimized operation' do
258
+ should == object
259
+ end
260
+
261
+ it 'does not execute body#each' do
262
+ body.should_not_receive(:each)
263
+ subject
264
+ end
265
+
266
+ it_should_behave_like 'an optimize method'
267
+ end
268
+
269
+ context 'containing a reverse operation' do
270
+ let(:limit) { relation.sort_by { |r| [ r.id, r.name ] }.take(2) }
271
+ let(:operand) { limit.reverse }
272
+
273
+ it 'pushes the object under the order, limit and reverse' do
274
+ should eql(relation.rename(aliases).sort_by { |r| [ r.other_id, r.name ] }.take(2).reverse)
275
+ end
276
+
277
+ it 'returns an equivalent relation to the unoptimized operation' do
278
+ should == object
279
+ end
280
+
281
+ it 'does not execute body#each' do
282
+ body.should_not_receive(:each)
283
+ subject
284
+ end
285
+
286
+ it_should_behave_like 'an optimize method'
287
+ end
288
+
289
+ context 'containing a reverse operation, containing a object that cancels out' do
290
+ let(:limit) { relation.sort_by { |r| [ r.id, r.name ] }.take(2) }
291
+ let(:operand) { limit.rename(:id => :other_id).reverse }
292
+ let(:aliases) { { :other_id => :id } }
293
+
294
+ it 'pushes the object under the order, limit and reverse, and then cancel it out' do
295
+ should eql(relation.sort_by { |r| [ r.id, r.name ] }.take(2).reverse)
296
+ end
297
+
298
+ it 'returns an equivalent relation to the unoptimized operation' do
299
+ should == object
300
+ end
301
+
302
+ it 'does not execute body#each' do
303
+ body.should_not_receive(:each)
304
+ subject
305
+ end
306
+
307
+ it_should_behave_like 'an optimize method'
308
+ end
309
+
310
+ context 'containing an order operation' do
311
+ let(:operand) { relation.sort_by { |r| [ r.id, r.name ] } }
312
+
313
+ it 'pushes the object under the order' do
314
+ should eql(relation.rename(aliases).sort_by { |r| [ r.other_id, r.name ] })
315
+ end
316
+
317
+ it 'returns an equivalent relation to the unoptimized operation' do
318
+ should == object
319
+ end
320
+
321
+ it 'does not execute body#each' do
322
+ body.should_not_receive(:each)
323
+ subject
324
+ end
325
+
326
+ it_should_behave_like 'an optimize method'
327
+ end
328
+
329
+ context 'containing an order operation, containing a object that cancels out' do
330
+ let(:operand) { relation.rename(:id => :other_id).sort_by { |r| [ r.other_id, r.name ] } }
331
+ let(:aliases) { { :other_id => :id } }
332
+
333
+ it 'pushes the object under the order, and then cancel it out' do
334
+ should eql(relation.sort_by { |r| [ r.id, r.name ] })
335
+ end
336
+
337
+ it 'returns an equivalent relation to the unoptimized operation' do
338
+ should == object
339
+ end
340
+
341
+ it 'does not execute body#each' do
342
+ body.should_not_receive(:each)
343
+ subject
344
+ end
345
+
346
+ it_should_behave_like 'an optimize method'
347
+ end
348
+
349
+ context 'containing a limit operation' do
350
+ let(:order) { relation.sort_by { |r| [ r.id, r.name ] } }
351
+ let(:operand) { order.take(2) }
352
+
353
+ it 'pushes the object under the limit and order' do
354
+ should eql(relation.rename(aliases).sort_by { |r| [ r.other_id, r.name ] }.take(2))
355
+ end
356
+
357
+ it 'returns an equivalent relation to the unoptimized operation' do
358
+ should == object
359
+ end
360
+
361
+ it 'does not execute body#each' do
362
+ body.should_not_receive(:each)
363
+ subject
364
+ end
365
+
366
+ it_should_behave_like 'an optimize method'
367
+ end
368
+
369
+ context 'containing a limit operation, containing a object that cancels out' do
370
+ let(:order) { relation.sort_by { |r| [ r.id, r.name ] } }
371
+ let(:operand) { order.rename(:id => :other_id).take(2) }
372
+ let(:aliases) { { :other_id => :id } }
373
+
374
+ it 'pushes the object under the limit and order, and then cancel it out' do
375
+ should eql(relation.sort_by { |r| [ r.id, r.name ] }.take(2))
376
+ end
377
+
378
+ it 'returns an equivalent relation to the unoptimized operation' do
379
+ should == object
380
+ end
381
+
382
+ it 'does not execute body#each' do
383
+ body.should_not_receive(:each)
384
+ subject
385
+ end
386
+
387
+ it_should_behave_like 'an optimize method'
388
+ end
389
+
390
+ context 'containing an offset operation' do
391
+ let(:order) { relation.sort_by { |r| [ r.id, r.name ] } }
392
+ let(:operand) { order.drop(1) }
393
+
394
+ it 'pushes the object under the offset and order' do
395
+ should eql(relation.rename(aliases).sort_by { |r| [ r.other_id, r.name ] }.drop(1))
396
+ end
397
+
398
+ it 'returns an equivalent relation to the unoptimized operation' do
399
+ should == object
400
+ end
401
+
402
+ it 'does not execute body#each' do
403
+ body.should_not_receive(:each)
404
+ subject
405
+ end
406
+
407
+ it_should_behave_like 'an optimize method'
408
+ end
409
+
410
+ context 'containing an offset operation, containing a object that cancels out' do
411
+ let(:order) { relation.sort_by { |r| [ r.id, r.name ] } }
412
+ let(:operand) { order.rename(:id => :other_id).drop(1) }
413
+ let(:aliases) { { :other_id => :id } }
414
+
415
+ it 'pushes the object under the offset and order, and then cancel it out' do
416
+ should eql(relation.sort_by { |r| [ r.id, r.name ] }.drop(1))
417
+ end
418
+
419
+ it 'returns an equivalent relation to the unoptimized operation' do
420
+ should == object
421
+ end
422
+
423
+ it 'does not execute body#each' do
424
+ body.should_not_receive(:each)
425
+ subject
426
+ end
427
+
428
+ it_should_behave_like 'an optimize method'
429
+ end
430
+
431
+ context 'containing a materialized relation' do
432
+ let(:operand) { Relation.new([ [ :id, Integer ], [ :name, String ] ], [ [ 1, 'Dan Kubb' ] ]) }
433
+
434
+ it { should eql(Relation::Materialized.new([ [ :other_id, Integer ], [ :name, String ] ], [ [ 1, 'Dan Kubb' ] ])) }
435
+
436
+ it 'returns an equivalent relation to the unoptimized operation' do
437
+ should == object
438
+ end
439
+
440
+ it_should_behave_like 'an optimize method'
441
+ end
442
+ end