axiom 0.1.1 → 0.2.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 (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