axiom 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (311) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +2 -1
  3. data/.rubocop.yml +7 -0
  4. data/.travis.yml +10 -7
  5. data/Gemfile +4 -0
  6. data/Gemfile.devtools +27 -13
  7. data/Guardfile +2 -2
  8. data/README.md +36 -30
  9. data/TODO +22 -24
  10. data/axiom.gemspec +9 -9
  11. data/benchmarks/memory.rb +1 -2
  12. data/benchmarks/speed.rb +7 -8
  13. data/config/flay.yml +1 -1
  14. data/config/reek.yml +19 -7
  15. data/config/rubocop.yml +6 -9
  16. data/lib/axiom.rb +28 -13
  17. data/lib/axiom/aggregate/mean.rb +4 -3
  18. data/lib/axiom/aggregate/sum.rb +1 -1
  19. data/lib/axiom/algebra/extension.rb +1 -1
  20. data/lib/axiom/algebra/join.rb +4 -27
  21. data/lib/axiom/algebra/product.rb +3 -3
  22. data/lib/axiom/algebra/projection.rb +2 -2
  23. data/lib/axiom/algebra/rename.rb +2 -2
  24. data/lib/axiom/algebra/rename/aliases.rb +3 -3
  25. data/lib/axiom/algebra/summarization.rb +3 -3
  26. data/lib/axiom/attribute.rb +5 -4
  27. data/lib/axiom/attribute/comparable.rb +15 -11
  28. data/lib/axiom/attribute/date.rb +1 -1
  29. data/lib/axiom/attribute/date_time.rb +1 -1
  30. data/lib/axiom/attribute/length_comparable.rb +39 -0
  31. data/lib/axiom/attribute/numeric.rb +1 -26
  32. data/lib/axiom/attribute/relation.rb +64 -0
  33. data/lib/axiom/attribute/string.rb +1 -28
  34. data/lib/axiom/attribute/time.rb +1 -1
  35. data/lib/axiom/attribute/tuple.rb +50 -0
  36. data/lib/axiom/attribute/value_comparable.rb +42 -0
  37. data/lib/axiom/function.rb +1 -1
  38. data/lib/axiom/function/binary.rb +4 -16
  39. data/lib/axiom/function/comparable.rb +1 -1
  40. data/lib/axiom/function/connective/conjunction.rb +1 -1
  41. data/lib/axiom/function/connective/disjunction.rb +1 -1
  42. data/lib/axiom/function/connective/negation.rb +1 -1
  43. data/lib/axiom/function/numeric/exponentiation.rb +1 -1
  44. data/lib/axiom/function/numeric/square_root.rb +1 -1
  45. data/lib/axiom/function/predicate/enumerable.rb +0 -14
  46. data/lib/axiom/function/predicate/exclusion.rb +1 -1
  47. data/lib/axiom/function/predicate/inclusion.rb +1 -1
  48. data/lib/axiom/function/proposition.rb +12 -25
  49. data/lib/axiom/function/unary.rb +92 -106
  50. data/lib/axiom/relation.rb +3 -3
  51. data/lib/axiom/relation/base.rb +15 -0
  52. data/lib/axiom/relation/header.rb +25 -22
  53. data/lib/axiom/relation/index.rb +91 -0
  54. data/lib/axiom/relation/keys.rb +3 -3
  55. data/lib/axiom/relation/materialized.rb +48 -4
  56. data/lib/axiom/relation/operation/binary.rb +5 -5
  57. data/lib/axiom/relation/operation/group.rb +95 -0
  58. data/lib/axiom/relation/operation/limit.rb +15 -15
  59. data/lib/axiom/relation/operation/offset.rb +12 -12
  60. data/lib/axiom/relation/operation/reverse.rb +9 -9
  61. data/lib/axiom/relation/operation/set.rb +1 -1
  62. data/lib/axiom/relation/operation/{order.rb → sorted.rb} +29 -28
  63. data/lib/axiom/relation/operation/{order → sorted}/direction.rb +4 -4
  64. data/lib/axiom/relation/operation/{order → sorted}/direction_set.rb +3 -3
  65. data/lib/axiom/relation/operation/ungroup.rb +82 -0
  66. data/lib/axiom/relation/operation/unwrap.rb +80 -0
  67. data/lib/axiom/relation/operation/wrap.rb +85 -0
  68. data/lib/axiom/relation/proxy.rb +5 -6
  69. data/lib/axiom/relation/variable.rb +1 -2
  70. data/lib/axiom/support/aliasable.rb +3 -5
  71. data/lib/axiom/support/equalizer.rb +10 -12
  72. data/lib/axiom/support/operation/binary.rb +3 -2
  73. data/lib/axiom/support/operation/unary.rb +1 -1
  74. data/lib/axiom/tuple.rb +76 -26
  75. data/lib/axiom/types/relation.rb +13 -0
  76. data/lib/axiom/types/tuple.rb +13 -0
  77. data/lib/axiom/version.rb +1 -1
  78. data/spec/integration/axiom/relation/efficient_enumerable_spec.rb +9 -9
  79. data/spec/integration/axiom/relation/writable_relations_spec.rb +12 -12
  80. data/spec/shared/invertible_method_behaviour.rb +1 -1
  81. data/spec/spec_helper.rb +8 -6
  82. data/spec/unit/axiom/aggregate/call_spec.rb +7 -12
  83. data/spec/unit/axiom/aggregate/class_methods/default_spec.rb +7 -2
  84. data/spec/unit/axiom/aggregate/default_spec.rb +1 -1
  85. data/spec/unit/axiom/aggregate/finalize_spec.rb +1 -1
  86. data/spec/unit/axiom/aggregate/maximum/type_spec.rb +2 -6
  87. data/spec/unit/axiom/aggregate/mean/class_methods/call_spec.rb +2 -2
  88. data/spec/unit/axiom/aggregate/mean/class_methods/finalize_spec.rb +10 -3
  89. data/spec/unit/axiom/aggregate/minimum/type_spec.rb +2 -6
  90. data/spec/unit/axiom/aggregate/sum/default_spec.rb +32 -6
  91. data/spec/unit/axiom/aggregate/sum/type_spec.rb +2 -6
  92. data/spec/unit/axiom/aggregate/variance/class_methods/call_spec.rb +6 -6
  93. data/spec/unit/axiom/algebra/difference/each_spec.rb +3 -3
  94. data/spec/unit/axiom/algebra/extension/class_methods/new_spec.rb +1 -1
  95. data/spec/unit/axiom/algebra/extension/each_spec.rb +2 -2
  96. data/spec/unit/axiom/algebra/intersection/each_spec.rb +3 -3
  97. data/spec/unit/axiom/algebra/join/each_spec.rb +6 -6
  98. data/spec/unit/axiom/algebra/product/each_spec.rb +2 -2
  99. data/spec/unit/axiom/algebra/projection/each_spec.rb +2 -2
  100. data/spec/unit/axiom/algebra/rename/directions_spec.rb +3 -3
  101. data/spec/unit/axiom/algebra/rename/each_spec.rb +2 -2
  102. data/spec/unit/axiom/algebra/restriction/delete_spec.rb +3 -3
  103. data/spec/unit/axiom/algebra/restriction/each_spec.rb +12 -11
  104. data/spec/unit/axiom/algebra/restriction/insert_spec.rb +3 -3
  105. data/spec/unit/axiom/algebra/restriction/methods/restrict_spec.rb +4 -4
  106. data/spec/unit/axiom/algebra/summarization/each_spec.rb +2 -2
  107. data/spec/unit/axiom/algebra/summarization/eql_spec.rb +1 -1
  108. data/spec/unit/axiom/algebra/summarization/summaries/summarize_by_spec.rb +4 -4
  109. data/spec/unit/axiom/algebra/summarization/summaries/to_hash_spec.rb +2 -2
  110. data/spec/unit/axiom/algebra/summarization/summary/summarize_by_spec.rb +1 -1
  111. data/spec/unit/axiom/algebra/union/each_spec.rb +4 -4
  112. data/spec/unit/axiom/aliasable/fixtures/classes.rb +3 -1
  113. data/spec/unit/axiom/aliasable/inheritable_alias_spec.rb +18 -27
  114. data/spec/unit/axiom/attribute/call_spec.rb +1 -1
  115. data/spec/unit/axiom/attribute/class_methods/coerce_spec.rb +57 -51
  116. data/spec/unit/axiom/attribute/class_methods/new_spec.rb +1 -1
  117. data/spec/unit/axiom/attribute/comparable/asc_spec.rb +4 -2
  118. data/spec/unit/axiom/attribute/comparable/desc_spec.rb +4 -2
  119. data/spec/unit/axiom/attribute/comparable/range_spec.rb +20 -0
  120. data/spec/unit/axiom/attribute/eql_spec.rb +1 -1
  121. data/spec/unit/axiom/attribute/equality_operator_spec.rb +1 -1
  122. data/spec/unit/axiom/attribute/include_predicate_spec.rb +1 -1
  123. data/spec/unit/axiom/attribute/name_spec.rb +1 -1
  124. data/spec/unit/axiom/attribute/optional_predicate_spec.rb +1 -1
  125. data/spec/unit/axiom/attribute/relation/class_methods/new_spec.rb +56 -0
  126. data/spec/unit/axiom/attribute/relation/class_methods/type_spec.rb +13 -0
  127. data/spec/unit/axiom/attribute/relation/header_spec.rb +13 -0
  128. data/spec/unit/axiom/attribute/relation/new_relation_spec.rb +15 -0
  129. data/spec/unit/axiom/attribute/rename_spec.rb +1 -1
  130. data/spec/unit/axiom/attribute/required_predicate_spec.rb +1 -1
  131. data/spec/unit/axiom/attribute/tuple/class_methods/new_spec.rb +56 -0
  132. data/spec/unit/axiom/attribute/tuple/class_methods/type_spec.rb +13 -0
  133. data/spec/unit/axiom/attribute/tuple/header_spec.rb +13 -0
  134. data/spec/unit/axiom/equalizer/class_method/new_spec.rb +24 -54
  135. data/spec/unit/axiom/evaluator/context/add_spec.rb +7 -7
  136. data/spec/unit/axiom/evaluator/context/element_reader_spec.rb +4 -4
  137. data/spec/unit/axiom/evaluator/context/functions_spec.rb +1 -1
  138. data/spec/unit/axiom/evaluator/context/method_missing_spec.rb +3 -3
  139. data/spec/unit/axiom/evaluator/context/respond_to_predicate_spec.rb +3 -3
  140. data/spec/unit/axiom/evaluator/context/send_spec.rb +8 -8
  141. data/spec/unit/axiom/function/binary/call_spec.rb +1 -1
  142. data/spec/unit/axiom/function/binary/type_spec.rb +12 -10
  143. data/spec/unit/axiom/function/comparable/class_methods/included_spec.rb +2 -2
  144. data/spec/unit/axiom/function/connective/negation/inverse_spec.rb +1 -1
  145. data/spec/unit/axiom/function/predicate/call_spec.rb +5 -4
  146. data/spec/unit/axiom/function/predicate/enumerable/call_spec.rb +12 -2
  147. data/spec/unit/axiom/function/predicate/eql_spec.rb +4 -3
  148. data/spec/unit/axiom/function/predicate/equality/methods/eq_spec.rb +5 -1
  149. data/spec/unit/axiom/function/predicate/exclusion/class_methods/call_spec.rb +37 -8
  150. data/spec/unit/axiom/function/predicate/exclusion/methods/exclude_spec.rb +6 -2
  151. data/spec/unit/axiom/function/predicate/greater_than/methods/gt_spec.rb +5 -1
  152. data/spec/unit/axiom/function/predicate/greater_than_or_equal_to/methods/gte_spec.rb +5 -1
  153. data/spec/unit/axiom/function/predicate/inclusion/class_methods/call_spec.rb +37 -8
  154. data/spec/unit/axiom/function/predicate/inclusion/methods/include_spec.rb +6 -2
  155. data/spec/unit/axiom/function/predicate/inequality/methods/ne_spec.rb +5 -1
  156. data/spec/unit/axiom/function/predicate/less_than/methods/lt_spec.rb +5 -1
  157. data/spec/unit/axiom/function/predicate/less_than_or_equal_to/methods/lte_spec.rb +5 -1
  158. data/spec/unit/axiom/function/predicate/match/methods/match_spec.rb +7 -3
  159. data/spec/unit/axiom/function/predicate/no_match/methods/no_match_spec.rb +6 -2
  160. data/spec/unit/axiom/function/proposition/call_spec.rb +6 -4
  161. data/spec/unit/axiom/function/proposition/class_methods/{new_spec.rb → coerce_spec.rb} +17 -17
  162. data/spec/unit/axiom/function/proposition/eql_spec.rb +4 -4
  163. data/spec/unit/axiom/function/proposition/equality_operator_spec.rb +3 -3
  164. data/spec/unit/axiom/function/proposition/inverse_spec.rb +4 -4
  165. data/spec/unit/axiom/function/proposition/rename_spec.rb +1 -1
  166. data/spec/unit/axiom/function/type_spec.rb +1 -1
  167. data/spec/unit/axiom/function/unary/call_spec.rb +1 -1
  168. data/spec/unit/axiom/function/unary/callable/call_spec.rb +3 -13
  169. data/spec/unit/axiom/function/unary/callable/included_spec.rb +2 -2
  170. data/spec/unit/axiom/function/unary/type_spec.rb +11 -1
  171. data/spec/unit/axiom/relation/base/eql_spec.rb +1 -1
  172. data/spec/unit/axiom/relation/base/equality_operator_spec.rb +138 -0
  173. data/spec/unit/axiom/relation/class_methods/new_spec.rb +7 -7
  174. data/spec/unit/axiom/relation/directions_spec.rb +2 -2
  175. data/spec/unit/axiom/relation/each_spec.rb +5 -5
  176. data/spec/unit/axiom/relation/element_reader_spec.rb +1 -1
  177. data/spec/unit/axiom/relation/empty/each_spec.rb +1 -1
  178. data/spec/unit/axiom/relation/empty_predicate_spec.rb +1 -1
  179. data/spec/unit/axiom/relation/eql_spec.rb +1 -1
  180. data/spec/unit/axiom/relation/equality_operator_spec.rb +1 -1
  181. data/spec/unit/axiom/relation/header/class_methods/coerce_spec.rb +2 -2
  182. data/spec/unit/axiom/relation/header/class_methods/new_spec.rb +3 -3
  183. data/spec/unit/axiom/relation/header/context_spec.rb +2 -2
  184. data/spec/unit/axiom/relation/header/each_spec.rb +2 -2
  185. data/spec/unit/axiom/relation/header/extend_spec.rb +1 -1
  186. data/spec/unit/axiom/relation/header/{call_spec.rb → fetch_spec.rb} +1 -1
  187. data/spec/unit/axiom/relation/header/project_spec.rb +1 -1
  188. data/spec/unit/axiom/relation/header/rename_spec.rb +19 -5
  189. data/spec/unit/axiom/relation/header/size_spec.rb +14 -0
  190. data/spec/unit/axiom/relation/header_spec.rb +1 -1
  191. data/spec/unit/axiom/relation/index/each_spec.rb +33 -0
  192. data/spec/unit/axiom/relation/index/element_reader_spec.rb +17 -0
  193. data/spec/unit/axiom/relation/index/left_shift_operator_spec.rb +23 -0
  194. data/spec/unit/axiom/relation/index/merge_spec.rb +19 -0
  195. data/spec/unit/axiom/relation/keys/class_methods/coerce_spec.rb +19 -2
  196. data/spec/unit/axiom/relation/keys/class_methods/new_spec.rb +1 -1
  197. data/spec/unit/axiom/relation/keys/each_spec.rb +2 -2
  198. data/spec/unit/axiom/relation/materialize_spec.rb +1 -1
  199. data/spec/unit/axiom/relation/materialized/class_methods/new_spec.rb +30 -4
  200. data/spec/unit/axiom/relation/materialized/directions_spec.rb +1 -1
  201. data/spec/unit/axiom/relation/materialized/materialized_predicate_spec.rb +1 -1
  202. data/spec/unit/axiom/relation/materialized_predicate_spec.rb +1 -1
  203. data/spec/unit/axiom/relation/operation/binary/class_methods/included_spec.rb +2 -2
  204. data/spec/unit/axiom/relation/operation/binary/class_methods/new_spec.rb +6 -6
  205. data/spec/unit/axiom/relation/operation/combination/class_methods/combine_tuples_spec.rb +4 -4
  206. data/spec/unit/axiom/relation/operation/group/each_spec.rb +33 -0
  207. data/spec/unit/axiom/relation/operation/group/header_spec.rb +22 -0
  208. data/spec/unit/axiom/relation/operation/group/methods/group_spec.rb +25 -0
  209. data/spec/unit/axiom/relation/operation/limit/class_methods/new_spec.rb +4 -4
  210. data/spec/unit/axiom/relation/operation/limit/directions_spec.rb +3 -3
  211. data/spec/unit/axiom/relation/operation/limit/each_spec.rb +4 -4
  212. data/spec/unit/axiom/relation/operation/limit/limit_spec.rb +2 -2
  213. data/spec/unit/axiom/relation/operation/offset/class_methods/new_spec.rb +4 -4
  214. data/spec/unit/axiom/relation/operation/offset/directions_spec.rb +3 -3
  215. data/spec/unit/axiom/relation/operation/offset/each_spec.rb +4 -4
  216. data/spec/unit/axiom/relation/operation/offset/offset_spec.rb +2 -2
  217. data/spec/unit/axiom/relation/operation/reverse/class_methods/new_spec.rb +6 -6
  218. data/spec/unit/axiom/relation/operation/reverse/directions_spec.rb +3 -3
  219. data/spec/unit/axiom/relation/operation/reverse/each_spec.rb +4 -4
  220. data/spec/unit/axiom/relation/operation/set/class_methods/included_spec.rb +2 -2
  221. data/spec/unit/axiom/relation/operation/{order → sorted}/ascending/class_methods/call_spec.rb +22 -1
  222. data/spec/unit/axiom/relation/operation/sorted/ascending/class_methods/reverse_spec.rb +11 -0
  223. data/spec/unit/axiom/relation/operation/{order/descending → sorted/ascending}/reverse_spec.rb +2 -2
  224. data/spec/unit/axiom/relation/operation/{order → sorted}/class_methods/new_spec.rb +4 -4
  225. data/spec/unit/axiom/relation/operation/{order → sorted}/delete_spec.rb +12 -6
  226. data/spec/unit/axiom/relation/operation/{order → sorted}/descending/class_methods/call_spec.rb +22 -1
  227. data/spec/unit/axiom/relation/operation/sorted/descending/class_methods/reverse_spec.rb +11 -0
  228. data/spec/unit/axiom/relation/operation/{order/ascending → sorted/descending}/reverse_spec.rb +2 -2
  229. data/spec/unit/axiom/relation/operation/{order → sorted}/direction/attribute_spec.rb +4 -4
  230. data/spec/unit/axiom/relation/operation/{order → sorted}/direction/call_spec.rb +7 -7
  231. data/spec/unit/axiom/relation/operation/{order → sorted}/direction/class_methods/coerce_spec.rb +2 -2
  232. data/spec/unit/axiom/relation/operation/{order → sorted}/direction/eql_predicate_spec.rb +4 -4
  233. data/spec/unit/axiom/relation/operation/{order → sorted}/direction/name_spec.rb +4 -4
  234. data/spec/unit/axiom/relation/operation/{order → sorted}/direction/rename_spec.rb +5 -5
  235. data/spec/unit/axiom/relation/operation/{order → sorted}/direction/reverse_spec.rb +9 -9
  236. data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/attributes_spec.rb +1 -1
  237. data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/class_methods/coerce_spec.rb +3 -3
  238. data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/class_methods/new_spec.rb +1 -1
  239. data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/eql_spec.rb +1 -1
  240. data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/equality_operator_spec.rb +1 -1
  241. data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/project_spec.rb +1 -1
  242. data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/rename_spec.rb +1 -1
  243. data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/reverse_spec.rb +2 -2
  244. data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/sort_tuples_spec.rb +1 -1
  245. data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/to_ary_spec.rb +1 -1
  246. data/spec/unit/axiom/relation/operation/{order → sorted}/directions_spec.rb +1 -1
  247. data/spec/unit/axiom/relation/operation/{order → sorted}/each_spec.rb +3 -3
  248. data/spec/unit/axiom/relation/operation/{order → sorted}/eql_spec.rb +1 -1
  249. data/spec/unit/axiom/relation/operation/{order → sorted}/header_spec.rb +1 -1
  250. data/spec/unit/axiom/relation/operation/{order → sorted}/insert_spec.rb +12 -6
  251. data/spec/unit/axiom/relation/operation/{order → sorted}/methods/sort_by_spec.rb +24 -24
  252. data/spec/unit/axiom/relation/operation/sorted/methods/sort_spec.rb +19 -0
  253. data/spec/unit/axiom/relation/operation/ungroup/each_spec.rb +33 -0
  254. data/spec/unit/axiom/relation/operation/ungroup/header_spec.rb +19 -0
  255. data/spec/unit/axiom/relation/operation/ungroup/methods/ungroup_spec.rb +21 -0
  256. data/spec/unit/axiom/relation/operation/unwrap/each_spec.rb +33 -0
  257. data/spec/unit/axiom/relation/operation/unwrap/header_spec.rb +19 -0
  258. data/spec/unit/axiom/relation/operation/unwrap/methods/unwrap_spec.rb +21 -0
  259. data/spec/unit/axiom/relation/operation/wrap/each_spec.rb +33 -0
  260. data/spec/unit/axiom/relation/operation/wrap/header_spec.rb +22 -0
  261. data/spec/unit/axiom/relation/operation/wrap/methods/wrap_spec.rb +25 -0
  262. data/spec/unit/axiom/relation/proxy/each_spec.rb +2 -2
  263. data/spec/unit/axiom/relation/proxy/respond_to_predicate_spec.rb +48 -12
  264. data/spec/unit/axiom/relation/replace_spec.rb +8 -8
  265. data/spec/unit/axiom/tuple/class_methods/coerce_spec.rb +7 -1
  266. data/spec/unit/axiom/tuple/{call_spec.rb → fetch_spec.rb} +1 -1
  267. data/spec/unit/axiom/tuple/inspect_spec.rb +14 -0
  268. data/spec/unit/axiom/tuple/rename_spec.rb +17 -0
  269. data/spec/unit/axiom/tuple/size_spec.rb +14 -0
  270. data/spec/unit/axiom/tuple/to_ary_spec.rb +22 -5
  271. data/spec/unit/axiom/tuple/to_hash_spec.rb +14 -0
  272. data/spec/unit/axiom/types/relation/class_methods/primitive_spec.rb +13 -0
  273. data/spec/unit/axiom/types/tuple/class_methods/primitive_spec.rb +13 -0
  274. data/spec/unit/axiom/visitable/accept_spec.rb +1 -1
  275. data/spec/unit/date/pred_spec.rb +1 -1
  276. data/spec/unit/time/pred_spec.rb +1 -1
  277. metadata +631 -107
  278. data/spec/unit/axiom/aggregate/hash_spec.rb +0 -15
  279. data/spec/unit/axiom/algebra/extension/hash_spec.rb +0 -15
  280. data/spec/unit/axiom/algebra/projection/hash_spec.rb +0 -16
  281. data/spec/unit/axiom/algebra/rename/aliases/hash_spec.rb +0 -15
  282. data/spec/unit/axiom/algebra/rename/hash_spec.rb +0 -15
  283. data/spec/unit/axiom/algebra/restriction/hash_spec.rb +0 -15
  284. data/spec/unit/axiom/algebra/summarization/hash_spec.rb +0 -16
  285. data/spec/unit/axiom/attribute/hash_spec.rb +0 -21
  286. data/spec/unit/axiom/attribute/numeric/hash_spec.rb +0 -17
  287. data/spec/unit/axiom/attribute/string/hash_spec.rb +0 -25
  288. data/spec/unit/axiom/equalizer/methods/eql_spec.rb +0 -49
  289. data/spec/unit/axiom/equalizer/methods/equality_operator_spec.rb +0 -85
  290. data/spec/unit/axiom/function/binary/invertible/class_methods/included_spec.rb +0 -29
  291. data/spec/unit/axiom/function/predicate/hash_spec.rb +0 -16
  292. data/spec/unit/axiom/function/predicate/inverse_spec.rb +0 -17
  293. data/spec/unit/axiom/function/proposition/hash_spec.rb +0 -14
  294. data/spec/unit/axiom/function/unary/hash_spec.rb +0 -18
  295. data/spec/unit/axiom/function/unary/invertible/class_methods/included_spec.rb +0 -29
  296. data/spec/unit/axiom/operation/binary/hash_spec.rb +0 -16
  297. data/spec/unit/axiom/operation/unary/hash_spec.rb +0 -15
  298. data/spec/unit/axiom/relation/base/hash_spec.rb +0 -16
  299. data/spec/unit/axiom/relation/hash_spec.rb +0 -19
  300. data/spec/unit/axiom/relation/header/hash_spec.rb +0 -15
  301. data/spec/unit/axiom/relation/operation/limit/hash_spec.rb +0 -16
  302. data/spec/unit/axiom/relation/operation/offset/hash_spec.rb +0 -16
  303. data/spec/unit/axiom/relation/operation/order/ascending/class_methods/reverse_spec.rb +0 -11
  304. data/spec/unit/axiom/relation/operation/order/descending/class_methods/reverse_spec.rb +0 -11
  305. data/spec/unit/axiom/relation/operation/order/direction/hash_spec.rb +0 -15
  306. data/spec/unit/axiom/relation/operation/order/direction_set/hash_spec.rb +0 -15
  307. data/spec/unit/axiom/relation/operation/order/hash_spec.rb +0 -15
  308. data/spec/unit/axiom/relation/operation/order/methods/sort_spec.rb +0 -19
  309. data/spec/unit/axiom/relation/proxy/hash_spec.rb +0 -26
  310. data/spec/unit/axiom/relation/proxy/method_missing_spec.rb +0 -24
  311. data/spec/unit/axiom/tuple/hash_spec.rb +0 -15
@@ -0,0 +1,91 @@
1
+ # encoding: utf-8
2
+
3
+ module Axiom
4
+ class Relation
5
+
6
+ # Tuples keyed by a tuple
7
+ class Index
8
+
9
+ # Initialize an index
10
+ #
11
+ # @param [Header] key
12
+ # @param [Header] header
13
+ #
14
+ # @return [undefined]
15
+ #
16
+ # @api private
17
+ def initialize(key, header)
18
+ @key = key
19
+ @header = header
20
+ @index = Hash.new { |hash, tuple| hash[tuple] = Set.new }
21
+ end
22
+
23
+ # Add a set of tuples to the index
24
+ #
25
+ # @example
26
+ # index.merge(tuples)
27
+ #
28
+ # @param [Enumerable<Tuple>] tuples
29
+ #
30
+ # @return [Index]
31
+ #
32
+ # @api public
33
+ def merge(tuples)
34
+ tuples.each(&method(:<<))
35
+ self
36
+ end
37
+
38
+ # Add a tuple to the index
39
+ #
40
+ # @example
41
+ # index << tuple
42
+ #
43
+ # @param [Tuple]
44
+ #
45
+ # @return [Index]
46
+ #
47
+ # @api public
48
+ def <<(tuple)
49
+ self[tuple] << tuple.project(@header)
50
+ self
51
+ end
52
+
53
+ # Iterate over each entry in the index
54
+ #
55
+ # @example
56
+ # index = Index.new(key_header, tuple_header)
57
+ # index.each { |key, tuples| ... }
58
+ #
59
+ # @yield [key, tuples]
60
+ #
61
+ # @yieldparam [Tuple] key
62
+ # the key for the tuples
63
+ # @yieldparam [Set<Tuple>] tuples
64
+ # the indexed tuples
65
+ #
66
+ # @return [Index]
67
+ #
68
+ # @api public
69
+ def each(&block)
70
+ return to_enum unless block_given?
71
+ @index.each(&block)
72
+ self
73
+ end
74
+
75
+ # Return the tuples in the index based on the tuple key
76
+ #
77
+ # @example
78
+ # index[tuple] # => tuples
79
+ #
80
+ # @param [Tuple] tuple
81
+ #
82
+ # @return [Set<Tuple>]
83
+ #
84
+ # @api public
85
+ def [](tuple)
86
+ @index[tuple.project(@key)]
87
+ end
88
+
89
+ end # class Index
90
+ end # class Relation
91
+ end # module Axiom
@@ -31,7 +31,7 @@ module Axiom
31
31
  if object.kind_of?(self)
32
32
  object
33
33
  else
34
- block ||= ->(attributes) { coerce_attributes(attributes) }
34
+ block ||= method(:coerce_attributes)
35
35
  new(object.map(&block))
36
36
  end
37
37
  end
@@ -80,7 +80,7 @@ module Axiom
80
80
  def self.assert_irreducible_keys(keys)
81
81
  reducible_keys = reducible_keys(keys)
82
82
  if reducible_keys
83
- raise ReducibleKeyError, "reducible keys: #{reducible_keys.inspect}"
83
+ fail ReducibleKeyError, "reducible keys: #{reducible_keys}"
84
84
  end
85
85
  end
86
86
 
@@ -109,7 +109,7 @@ module Axiom
109
109
  #
110
110
  # @api public
111
111
  def initialize(keys)
112
- @keys = freeze_object(keys)
112
+ @keys = self.class.freezer.call(keys)
113
113
  end
114
114
 
115
115
  # Iterate over each key in the Keys
@@ -9,26 +9,70 @@ module Axiom
9
9
 
10
10
  # The relation sort order
11
11
  #
12
- # @return [Operation::Order::DirectionSet]
12
+ # @return [Operation::Sorted::DirectionSet]
13
13
  #
14
14
  # @api private
15
15
  attr_reader :directions
16
16
 
17
+ # Instantiate a materialized Relation
18
+ #
19
+ # @example of a materialized Array based relation
20
+ # array = [[1], [2], [3]]
21
+ # relation = Relation::Materialized.new([[:id, Integer]], array)
22
+ #
23
+ # @example of a materialized Set based relation
24
+ # set = Set[[1], [2], [3]]
25
+ # relation = Relation::Materialized.new([[:id, Integer]], set)
26
+ #
27
+ # @example of a materialized empty relation
28
+ # relation = Relation::Materialized.new([[:id, Integer]])
29
+ #
30
+ # @param [Array(Header, Enumerable)] args
31
+ #
32
+ # @return [Relation]
33
+ #
34
+ # @api public
35
+ def self.new(*args)
36
+ if equal?(Materialized) && empty?(args[1])
37
+ Empty.new(args.first)
38
+ else
39
+ super
40
+ end
41
+ end
42
+
43
+ # Test if the tuples are empty
44
+ #
45
+ # When tuples are nil, it means there are no tuples so it is the equivalent
46
+ # of specifying [] for the tuples.
47
+ #
48
+ # @param [nil, #size] tuples
49
+ #
50
+ # @return [Boolean]
51
+ #
52
+ # @api private
53
+ def self.empty?(tuples)
54
+ tuples.nil? || begin
55
+ size = tuples.size
56
+ size && size.zero?
57
+ end
58
+ end
59
+ private_class_method :empty?
60
+
17
61
  # Initialize a materialized Relation
18
62
  #
19
63
  # @param [Header, #to_ary] header
20
64
  # the relation header
21
65
  # @param [Enumerable] tuples
22
66
  # the relation tuples
23
- # @param [Operation::Order::DirectionSet] directions
67
+ # @param [Operation::Sorted::DirectionSet] directions
24
68
  # optional directions to sort the relation by
25
69
  #
26
70
  # @return [undefined]
27
71
  #
28
72
  # @api private
29
- def initialize(header, tuples = ZERO_TUPLE, directions = Operation::Order::DirectionSet::EMPTY)
73
+ def initialize(header, tuples, directions = Operation::Sorted::DirectionSet::EMPTY)
30
74
  super(header, tuples)
31
- @directions = Operation::Order::DirectionSet.coerce(directions)
75
+ @directions = Operation::Sorted::DirectionSet.coerce(directions)
32
76
  end
33
77
 
34
78
  # A noop for Materialized relations
@@ -47,13 +47,13 @@ module Axiom
47
47
  #
48
48
  # @api public
49
49
  def new(left, right)
50
- assert_ordered_match(left, right)
50
+ assert_sorted_match(left, right)
51
51
  super
52
52
  end
53
53
 
54
54
  private
55
55
 
56
- # Assert that ordered and unordered relations are not mixed
56
+ # Assert that sorted and unsorted relations are not mixed
57
57
  #
58
58
  # @param [Relation] left
59
59
  # @param [Relation] right
@@ -61,12 +61,12 @@ module Axiom
61
61
  # @return [undefined]
62
62
  #
63
63
  # @raise [RelationMismatchError]
64
- # raised if one relation is ordered and the other is not
64
+ # raised if one relation is sorted and the other is not
65
65
  #
66
66
  # @api private
67
- def assert_ordered_match(left, right)
67
+ def assert_sorted_match(left, right)
68
68
  if left.directions.empty? != right.directions.empty?
69
- raise RelationMismatchError, 'both relations must be ordered or neither may be ordered'
69
+ fail RelationMismatchError, 'both relations must be sorted or neither may be sorted'
70
70
  end
71
71
  end
72
72
 
@@ -0,0 +1,95 @@
1
+ # encoding: utf-8
2
+
3
+ module Axiom
4
+ class Relation
5
+ module Operation
6
+
7
+ # A class representing a grouped relation
8
+ class Group < Relation
9
+ include Unary
10
+ include Equalizer.new(:operand, :attribute)
11
+
12
+ # The grouped attribute
13
+ #
14
+ # @return [Attribute::Relation]
15
+ #
16
+ # @api private
17
+ attr_reader :attribute
18
+
19
+ # Initialize a grouped relation
20
+ #
21
+ # @param [Relation] operand
22
+ # @param [#to_sym] name
23
+ # @param [Enumerable<Axiom::Attribute>] attributes
24
+ #
25
+ # @return [undefined]
26
+ #
27
+ # @api private
28
+ def initialize(operand, name, attributes)
29
+ super(operand)
30
+ inner = header.project(attributes)
31
+ @outer = header - inner
32
+ @attribute = Attribute::Relation.new(name, header: inner)
33
+ @header = @outer.extend(attribute)
34
+ end
35
+
36
+ # Iterate over each tuple in the set
37
+ #
38
+ # @example
39
+ # grouped = Group.new(operand, name, attributes)
40
+ # grouped.each { |tuple| ... }
41
+ #
42
+ # @yield [tuple]
43
+ #
44
+ # @yieldparam [Tuple] tuple
45
+ # each tuple in the set
46
+ #
47
+ # @return [self]
48
+ #
49
+ # @api public
50
+ def each
51
+ return to_enum unless block_given?
52
+ build_index.each do |outer_tuple, inner_tuples|
53
+ inner_relation = attribute.new_relation(inner_tuples)
54
+ yield outer_tuple.extend(header, [inner_relation])
55
+ end
56
+ self
57
+ end
58
+
59
+ private
60
+
61
+ # Build an index using every tuple in the operand
62
+ #
63
+ # @return [Index]
64
+ #
65
+ # @api private
66
+ def build_index
67
+ Index.new(@outer, @attribute.header).merge(operand)
68
+ end
69
+
70
+ module Methods
71
+
72
+ # Return a grouped relation
73
+ #
74
+ # @example
75
+ # grouped = relation.group(location: [:latitude, :longitude])
76
+ #
77
+ # @param [Hash{#to_sym => Enumerable<Axiom::Attribute>] grouping
78
+ #
79
+ # @return [Group]
80
+ #
81
+ # @api public
82
+ def group(grouping)
83
+ grouping.reduce(self) do |operation, pair|
84
+ Group.new(operation, *pair)
85
+ end
86
+ end
87
+
88
+ end # module Methods
89
+
90
+ Relation.class_eval { include Methods }
91
+
92
+ end # class Group
93
+ end # module Operation
94
+ end # class Relation
95
+ end # module Axiom
@@ -21,7 +21,7 @@ module Axiom
21
21
 
22
22
  # The relation sort order
23
23
  #
24
- # @return [Operation::Order::DirectionSet]
24
+ # @return [Operation::Sorted::DirectionSet]
25
25
  #
26
26
  # @api private
27
27
  attr_reader :directions
@@ -40,24 +40,24 @@ module Axiom
40
40
  #
41
41
  # @api public
42
42
  def self.new(operand, limit)
43
- assert_ordered_operand(operand)
43
+ assert_sorted_operand(operand)
44
44
  assert_valid_limit(limit)
45
45
  super
46
46
  end
47
47
 
48
- # Assert the operand is ordered
48
+ # Assert the operand is sorted
49
49
  #
50
50
  # @param [Relation] operand
51
51
  #
52
52
  # @return [undefined]
53
53
  #
54
- # @raise [OrderedRelationRequiredError]
55
- # raised if the operand is unordered
54
+ # @raise [SortededRelationRequiredError]
55
+ # raised if the operand is unsorted
56
56
  #
57
57
  # @api private
58
- def self.assert_ordered_operand(operand)
59
- if operand.header.to_ary.size != operand.directions.to_ary.size
60
- raise OrderedRelationRequiredError, 'can only limit an ordered operand'
58
+ def self.assert_sorted_operand(operand)
59
+ if operand.header.size != operand.directions.size
60
+ fail SortededRelationRequiredError, 'can only limit a sorted operand'
61
61
  end
62
62
  end
63
63
 
@@ -73,11 +73,11 @@ module Axiom
73
73
  # @api private
74
74
  def self.assert_valid_limit(limit)
75
75
  if limit.nil? || limit < 0
76
- raise InvalidLimitError, "limit must be greater than or equal to 0, but was #{limit.inspect}"
76
+ fail InvalidLimitError, "limit must be greater than or equal to 0, but was #{limit.inspect}"
77
77
  end
78
78
  end
79
79
 
80
- private_class_method :assert_ordered_operand, :assert_valid_limit
80
+ private_class_method :assert_sorted_operand, :assert_valid_limit
81
81
 
82
82
  # Initialize a Limit
83
83
  #
@@ -130,7 +130,7 @@ module Axiom
130
130
  #
131
131
  # @api public
132
132
  def insert(*)
133
- raise ImmutableRelationError, 'inserting into a limit is impossible'
133
+ fail ImmutableRelationError, 'inserting into a limit is impossible'
134
134
  end
135
135
 
136
136
  # Raise an exception when deleting from the Limit
@@ -145,13 +145,13 @@ module Axiom
145
145
  #
146
146
  # @api public
147
147
  def delete(*)
148
- raise ImmutableRelationError, 'deleting from a limit is impossible'
148
+ fail ImmutableRelationError, 'deleting from a limit is impossible'
149
149
  end
150
150
 
151
151
  module Methods
152
152
 
153
153
  # Default block used in #one
154
- DEFAULT_ONE_BLOCK = -> { }
154
+ DEFAULT_ONE_BLOCK = -> {}
155
155
 
156
156
  # Maximum number of tuples to take in #one
157
157
  ONE_LIMIT = 2
@@ -230,7 +230,7 @@ module Axiom
230
230
  tuples = take(ONE_LIMIT).to_a
231
231
  assert_no_more_than_one_tuple(tuples.size)
232
232
  tuples.first or block.yield or
233
- raise NoTuplesError, 'one tuple expected, but was an empty set'
233
+ fail NoTuplesError, 'one tuple expected, but was an empty set'
234
234
  end
235
235
 
236
236
  private
@@ -245,7 +245,7 @@ module Axiom
245
245
  # @api private
246
246
  def assert_no_more_than_one_tuple(size)
247
247
  if size > 1
248
- raise(
248
+ fail(
249
249
  ManyTuplesError,
250
250
  "one tuple expected, but set contained #{count} tuples"
251
251
  )
@@ -21,7 +21,7 @@ module Axiom
21
21
 
22
22
  # The relation sort order
23
23
  #
24
- # @return [Operation::Order::DirectionSet]
24
+ # @return [Operation::Sorted::DirectionSet]
25
25
  #
26
26
  # @api private
27
27
  attr_reader :directions
@@ -40,24 +40,24 @@ module Axiom
40
40
  #
41
41
  # @api public
42
42
  def self.new(operand, offset)
43
- assert_ordered_operand(operand)
43
+ assert_sorted_operand(operand)
44
44
  assert_valid_offset(offset)
45
45
  super
46
46
  end
47
47
 
48
- # Assert the operand is ordered
48
+ # Assert the operand is sorted
49
49
  #
50
50
  # @param [Relation] operand
51
51
  #
52
52
  # @return [undefined]
53
53
  #
54
- # @raise [OrderedRelationRequiredError]
55
- # raised if the operand is unordered
54
+ # @raise [SortededRelationRequiredError]
55
+ # raised if the operand is unsorted
56
56
  #
57
57
  # @api private
58
- def self.assert_ordered_operand(operand)
59
- if operand.header.to_ary.size != operand.directions.to_ary.size
60
- raise OrderedRelationRequiredError, 'can only offset an ordered operand'
58
+ def self.assert_sorted_operand(operand)
59
+ if operand.header.size != operand.directions.size
60
+ fail SortededRelationRequiredError, 'can only offset a sorted operand'
61
61
  end
62
62
  end
63
63
 
@@ -73,11 +73,11 @@ module Axiom
73
73
  # @api private
74
74
  def self.assert_valid_offset(offset)
75
75
  if offset.nil? || offset < 0
76
- raise InvalidOffsetError, "offset must be greater than or equal to 0, but was #{offset.inspect}"
76
+ fail InvalidOffsetError, "offset must be greater than or equal to 0, but was #{offset.inspect}"
77
77
  end
78
78
  end
79
79
 
80
- private_class_method :assert_ordered_operand, :assert_valid_offset
80
+ private_class_method :assert_sorted_operand, :assert_valid_offset
81
81
 
82
82
  # Initialize an Offset
83
83
  #
@@ -129,7 +129,7 @@ module Axiom
129
129
  #
130
130
  # @api public
131
131
  def insert(*)
132
- raise ImmutableRelationError, 'inserting into an offset is impossible'
132
+ fail ImmutableRelationError, 'inserting into an offset is impossible'
133
133
  end
134
134
 
135
135
  # Raise an exception when deleting from the Offset
@@ -144,7 +144,7 @@ module Axiom
144
144
  #
145
145
  # @api public
146
146
  def delete(*)
147
- raise ImmutableRelationError, 'deleting from an offset is impossible'
147
+ fail ImmutableRelationError, 'deleting from an offset is impossible'
148
148
  end
149
149
 
150
150
  module Methods