veritas 0.0.4 → 0.0.5

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 (244) hide show
  1. data/.travis.yml +4 -2
  2. data/Gemfile +7 -8
  3. data/README.rdoc +17 -18
  4. data/Rakefile +2 -2
  5. data/TODO +18 -14
  6. data/benchmarks/memory.rb +8 -7
  7. data/benchmarks/speed.rb +4 -3
  8. data/config/flay.yml +1 -1
  9. data/lib/veritas/aggregate.rb +3 -0
  10. data/lib/veritas/algebra/join.rb +11 -4
  11. data/lib/veritas/algebra/product.rb +2 -1
  12. data/lib/veritas/algebra/restriction.rb +3 -2
  13. data/lib/veritas/algebra/summarization.rb +8 -3
  14. data/lib/veritas/attribute/string.rb +3 -1
  15. data/lib/veritas/attribute.rb +1 -1
  16. data/lib/veritas/function/binary.rb +1 -0
  17. data/lib/veritas/function/comparable.rb +1 -0
  18. data/lib/veritas/function/connective/negation.rb +2 -0
  19. data/lib/veritas/function/proposition.rb +5 -1
  20. data/lib/veritas/function/unary.rb +1 -0
  21. data/lib/veritas/function.rb +3 -0
  22. data/lib/veritas/relation/base.rb +32 -3
  23. data/lib/veritas/relation/header.rb +2 -2
  24. data/lib/veritas/relation/materialized.rb +12 -0
  25. data/lib/veritas/relation/operation/binary.rb +1 -0
  26. data/lib/veritas/relation/operation/limit.rb +1 -1
  27. data/lib/veritas/relation/operation/offset.rb +1 -1
  28. data/lib/veritas/relation/operation/order/direction_set.rb +67 -5
  29. data/lib/veritas/relation/operation/order.rb +25 -3
  30. data/lib/veritas/relation/operation/set.rb +1 -0
  31. data/lib/veritas/relation.rb +20 -7
  32. data/lib/veritas/support/abstract_class.rb +1 -0
  33. data/lib/veritas/support/evaluator.rb +49 -3
  34. data/lib/veritas/support/immutable.rb +2 -1
  35. data/lib/veritas/tuple.rb +28 -14
  36. data/lib/veritas/version.rb +1 -1
  37. data/lib/veritas.rb +6 -3
  38. data/spec/integration/veritas/algebra/projection_spec.rb +4 -4
  39. data/spec/integration/veritas/relation/efficient_enumerable_spec.rb +1 -1
  40. data/spec/shared/each_method_behaviour.rb +2 -2
  41. data/spec/shared/hash_method_behavior.rb +2 -2
  42. data/spec/spec_helper.rb +1 -0
  43. data/spec/unit/date/pred_spec.rb +3 -3
  44. data/spec/unit/range/overlaps_spec.rb +14 -14
  45. data/spec/unit/range/to_inclusive_spec.rb +2 -2
  46. data/spec/unit/time/pred_spec.rb +3 -3
  47. data/spec/unit/veritas/abstract_class/class_methods/new_spec.rb +1 -1
  48. data/spec/unit/veritas/aggregate/count/class_methods/call_spec.rb +1 -1
  49. data/spec/unit/veritas/aggregate/count/methods/count_spec.rb +1 -1
  50. data/spec/unit/veritas/aggregate/maximum/methods/maximum_spec.rb +1 -1
  51. data/spec/unit/veritas/aggregate/mean/class_methods/call_spec.rb +1 -1
  52. data/spec/unit/veritas/aggregate/mean/methods/mean_spec.rb +1 -1
  53. data/spec/unit/veritas/aggregate/minimum/methods/minimum_spec.rb +1 -1
  54. data/spec/unit/veritas/aggregate/standard_deviation/methods/standard_deviation_spec.rb +1 -1
  55. data/spec/unit/veritas/aggregate/sum/class_methods/call_spec.rb +1 -1
  56. data/spec/unit/veritas/aggregate/sum/methods/sum_spec.rb +1 -1
  57. data/spec/unit/veritas/aggregate/variance/class_methods/call_spec.rb +1 -1
  58. data/spec/unit/veritas/aggregate/variance/methods/variance_spec.rb +1 -1
  59. data/spec/unit/veritas/algebra/difference/methods/difference_spec.rb +2 -2
  60. data/spec/unit/veritas/algebra/extension/class_methods/new_spec.rb +1 -1
  61. data/spec/unit/veritas/algebra/extension/eql_spec.rb +5 -5
  62. data/spec/unit/veritas/algebra/extension/header_spec.rb +1 -1
  63. data/spec/unit/veritas/algebra/extension/methods/extend_spec.rb +1 -1
  64. data/spec/unit/veritas/algebra/intersection/methods/intersect_spec.rb +2 -2
  65. data/spec/unit/veritas/algebra/join/class_methods/new_spec.rb +2 -2
  66. data/spec/unit/veritas/algebra/join/join_header_spec.rb +17 -0
  67. data/spec/unit/veritas/algebra/join/methods/join_spec.rb +2 -2
  68. data/spec/unit/veritas/algebra/product/class_methods/new_spec.rb +1 -1
  69. data/spec/unit/veritas/algebra/product/methods/product_spec.rb +1 -1
  70. data/spec/unit/veritas/algebra/projection/eql_spec.rb +5 -5
  71. data/spec/unit/veritas/algebra/projection/header_spec.rb +1 -1
  72. data/spec/unit/veritas/algebra/projection/methods/project_spec.rb +1 -1
  73. data/spec/unit/veritas/algebra/projection/methods/remove_spec.rb +1 -1
  74. data/spec/unit/veritas/algebra/rename/aliases/class_methods/coerce_spec.rb +4 -4
  75. data/spec/unit/veritas/algebra/rename/aliases/class_methods/new_spec.rb +1 -1
  76. data/spec/unit/veritas/algebra/rename/aliases/eql_spec.rb +4 -4
  77. data/spec/unit/veritas/algebra/rename/aliases/equal_value_spec.rb +4 -4
  78. data/spec/unit/veritas/algebra/rename/aliases/to_hash_spec.rb +1 -1
  79. data/spec/unit/veritas/algebra/rename/aliases/union_spec.rb +10 -10
  80. data/spec/unit/veritas/algebra/rename/directions_spec.rb +3 -3
  81. data/spec/unit/veritas/algebra/rename/eql_spec.rb +5 -5
  82. data/spec/unit/veritas/algebra/rename/header_spec.rb +1 -1
  83. data/spec/unit/veritas/algebra/rename/methods/rename_spec.rb +1 -1
  84. data/spec/unit/veritas/algebra/restriction/eql_spec.rb +5 -5
  85. data/spec/unit/veritas/algebra/restriction/methods/restrict_spec.rb +1 -1
  86. data/spec/unit/veritas/algebra/summarization/class_methods/new_spec.rb +1 -1
  87. data/spec/unit/veritas/algebra/summarization/eql_spec.rb +7 -7
  88. data/spec/unit/veritas/algebra/summarization/header_spec.rb +1 -1
  89. data/spec/unit/veritas/algebra/summarization/methods/summarize_spec.rb +18 -8
  90. data/spec/unit/veritas/algebra/summarization/summaries/summarize_by_spec.rb +3 -3
  91. data/spec/unit/veritas/algebra/summarization/summaries/to_hash_spec.rb +2 -2
  92. data/spec/unit/veritas/algebra/summarization/summary/summarize_by_spec.rb +1 -1
  93. data/spec/unit/veritas/algebra/union/methods/union_spec.rb +2 -2
  94. data/spec/unit/veritas/aliasable/inheritable_alias_spec.rb +2 -2
  95. data/spec/unit/veritas/attribute/class_methods/coerce_spec.rb +4 -4
  96. data/spec/unit/veritas/attribute/class_methods/descendants_spec.rb +2 -6
  97. data/spec/unit/veritas/attribute/class_methods/new_spec.rb +1 -1
  98. data/spec/unit/veritas/attribute/comparable/comparable_spec.rb +3 -3
  99. data/spec/unit/veritas/attribute/eql_spec.rb +4 -4
  100. data/spec/unit/veritas/attribute/equal_value_spec.rb +4 -4
  101. data/spec/unit/veritas/attribute/inspect_spec.rb +1 -1
  102. data/spec/unit/veritas/attribute/joinable_spec.rb +4 -4
  103. data/spec/unit/veritas/attribute/numeric/joinable_spec.rb +3 -3
  104. data/spec/unit/veritas/attribute/options_spec.rb +2 -2
  105. data/spec/unit/veritas/attribute/orderable/asc_spec.rb +1 -1
  106. data/spec/unit/veritas/attribute/orderable/desc_spec.rb +1 -1
  107. data/spec/unit/veritas/attribute/rename_spec.rb +1 -1
  108. data/spec/unit/veritas/attribute/string/joinable_spec.rb +14 -4
  109. data/spec/unit/veritas/evaluator/context/method_missing_spec.rb +29 -0
  110. data/spec/unit/veritas/evaluator/context/respond_to_spec.rb +39 -0
  111. data/spec/unit/veritas/evaluator/context/send_spec.rb +28 -0
  112. data/spec/unit/veritas/evaluator/context/yield_spec.rb +14 -0
  113. data/spec/unit/veritas/function/binary/equal_value_spec.rb +5 -5
  114. data/spec/unit/veritas/function/binary/invertible/inverse_spec.rb +1 -1
  115. data/spec/unit/veritas/function/binary/rename_spec.rb +3 -3
  116. data/spec/unit/veritas/function/connective/conjunction/inverse_spec.rb +1 -1
  117. data/spec/unit/veritas/function/connective/disjunction/inverse_spec.rb +1 -1
  118. data/spec/unit/veritas/function/connective/negation/methods/not_spec.rb +2 -2
  119. data/spec/unit/veritas/function/numeric/absolute/methods/absolute_spec.rb +1 -1
  120. data/spec/unit/veritas/function/numeric/addition/methods/add_spec.rb +1 -1
  121. data/spec/unit/veritas/function/numeric/division/methods/divide_spec.rb +1 -1
  122. data/spec/unit/veritas/function/numeric/exponentiation/inverse_spec.rb +1 -1
  123. data/spec/unit/veritas/function/numeric/exponentiation/methods/exponent_spec.rb +1 -1
  124. data/spec/unit/veritas/function/numeric/modulo/methods/modulo_spec.rb +1 -1
  125. data/spec/unit/veritas/function/numeric/multiplication/methods/multiply_spec.rb +1 -1
  126. data/spec/unit/veritas/function/numeric/square_root/methods/square_root_spec.rb +1 -1
  127. data/spec/unit/veritas/function/numeric/subtraction/methods/subtract_spec.rb +1 -1
  128. data/spec/unit/veritas/function/numeric/unary_minus/methods/unary_minus_spec.rb +1 -1
  129. data/spec/unit/veritas/function/numeric/unary_plus/methods/unary_plus_spec.rb +1 -1
  130. data/spec/unit/veritas/function/predicate/eql_spec.rb +5 -5
  131. data/spec/unit/veritas/function/predicate/equality/inverse_spec.rb +1 -1
  132. data/spec/unit/veritas/function/predicate/equality/methods/eq_spec.rb +1 -1
  133. data/spec/unit/veritas/function/predicate/exclusion/inverse_spec.rb +1 -1
  134. data/spec/unit/veritas/function/predicate/exclusion/methods/exclude_spec.rb +1 -1
  135. data/spec/unit/veritas/function/predicate/greater_than/inverse_spec.rb +1 -1
  136. data/spec/unit/veritas/function/predicate/greater_than/methods/gt_spec.rb +1 -1
  137. data/spec/unit/veritas/function/predicate/greater_than_or_equal_to/inverse_spec.rb +1 -1
  138. data/spec/unit/veritas/function/predicate/greater_than_or_equal_to/methods/gte_spec.rb +1 -1
  139. data/spec/unit/veritas/function/predicate/inclusion/inverse_spec.rb +1 -1
  140. data/spec/unit/veritas/function/predicate/inclusion/methods/include_spec.rb +1 -1
  141. data/spec/unit/veritas/function/predicate/inequality/inverse_spec.rb +1 -1
  142. data/spec/unit/veritas/function/predicate/inequality/methods/ne_spec.rb +1 -1
  143. data/spec/unit/veritas/function/predicate/inverse_spec.rb +1 -1
  144. data/spec/unit/veritas/function/predicate/less_than/inverse_spec.rb +1 -1
  145. data/spec/unit/veritas/function/predicate/less_than/methods/lt_spec.rb +1 -1
  146. data/spec/unit/veritas/function/predicate/less_than_or_equal_to/inverse_spec.rb +1 -1
  147. data/spec/unit/veritas/function/predicate/less_than_or_equal_to/methods/lte_spec.rb +1 -1
  148. data/spec/unit/veritas/function/predicate/match/inverse_spec.rb +1 -1
  149. data/spec/unit/veritas/function/predicate/match/methods/match_spec.rb +1 -1
  150. data/spec/unit/veritas/function/predicate/no_match/inverse_spec.rb +1 -1
  151. data/spec/unit/veritas/function/predicate/no_match/methods/no_match_spec.rb +1 -1
  152. data/spec/unit/veritas/function/proposition/eql_spec.rb +3 -3
  153. data/spec/unit/veritas/function/proposition/equal_value_spec.rb +3 -3
  154. data/spec/unit/veritas/function/string/length/methods/length_spec.rb +1 -1
  155. data/spec/unit/veritas/function/unary/equal_value_spec.rb +4 -4
  156. data/spec/unit/veritas/function/unary/invertible/inverse_spec.rb +1 -1
  157. data/spec/unit/veritas/function/unary/rename_spec.rb +1 -1
  158. data/spec/unit/veritas/immutable/class_methods/freeze_object_spec.rb +7 -1
  159. data/spec/unit/veritas/immutable/class_methods/new_spec.rb +1 -1
  160. data/spec/unit/veritas/immutable/freeze_spec.rb +2 -2
  161. data/spec/unit/veritas/immutable/module_methods/memoize_spec.rb +2 -2
  162. data/spec/unit/veritas/operation/binary/eql_spec.rb +5 -5
  163. data/spec/unit/veritas/operation/unary/eql_spec.rb +4 -4
  164. data/spec/unit/veritas/relation/base/class_methods/new_spec.rb +35 -0
  165. data/spec/unit/veritas/relation/base/eql_spec.rb +100 -0
  166. data/spec/unit/veritas/relation/base/hash_spec.rb +16 -0
  167. data/spec/unit/veritas/relation/class_methods/new_spec.rb +2 -2
  168. data/spec/unit/veritas/relation/directions_spec.rb +1 -1
  169. data/spec/unit/veritas/relation/eql_spec.rb +15 -15
  170. data/spec/unit/veritas/relation/equal_value_spec.rb +16 -16
  171. data/spec/unit/veritas/relation/header/class_methods/coerce_spec.rb +1 -1
  172. data/spec/unit/veritas/relation/header/class_methods/new_spec.rb +2 -2
  173. data/spec/unit/veritas/relation/header/difference_spec.rb +1 -1
  174. data/spec/unit/veritas/relation/header/eql_spec.rb +5 -5
  175. data/spec/unit/veritas/relation/header/equal_value_spec.rb +7 -7
  176. data/spec/unit/veritas/relation/header/inspect_spec.rb +1 -1
  177. data/spec/unit/veritas/relation/header/intersect_spec.rb +1 -1
  178. data/spec/unit/veritas/relation/header/project_spec.rb +1 -1
  179. data/spec/unit/veritas/relation/header/rename_spec.rb +1 -1
  180. data/spec/unit/veritas/relation/header/to_ary_spec.rb +1 -1
  181. data/spec/unit/veritas/relation/header/union_spec.rb +1 -1
  182. data/spec/unit/veritas/relation/materialize_spec.rb +3 -3
  183. data/spec/unit/veritas/relation/materialized/class_methods/new_spec.rb +2 -2
  184. data/spec/unit/veritas/relation/materialized/materialized_spec.rb +15 -0
  185. data/spec/unit/veritas/relation/materialized_spec.rb +15 -0
  186. data/spec/unit/veritas/relation/operation/binary/class_methods/new_spec.rb +6 -6
  187. data/spec/unit/veritas/relation/operation/binary/header_spec.rb +1 -1
  188. data/spec/unit/veritas/relation/operation/combination/header_spec.rb +1 -1
  189. data/spec/unit/veritas/relation/operation/limit/class_methods/new_spec.rb +12 -5
  190. data/spec/unit/veritas/relation/operation/limit/directions_spec.rb +1 -1
  191. data/spec/unit/veritas/relation/operation/limit/each_spec.rb +1 -1
  192. data/spec/unit/veritas/relation/operation/limit/eql_spec.rb +11 -11
  193. data/spec/unit/veritas/relation/operation/limit/hash_spec.rb +1 -1
  194. data/spec/unit/veritas/relation/operation/limit/limit_spec.rb +1 -1
  195. data/spec/unit/veritas/relation/operation/limit/methods/first_spec.rb +3 -3
  196. data/spec/unit/veritas/relation/operation/limit/methods/last_spec.rb +3 -3
  197. data/spec/unit/veritas/relation/operation/limit/methods/take_spec.rb +2 -2
  198. data/spec/unit/veritas/relation/operation/offset/class_methods/new_spec.rb +12 -5
  199. data/spec/unit/veritas/relation/operation/offset/directions_spec.rb +1 -1
  200. data/spec/unit/veritas/relation/operation/offset/each_spec.rb +1 -1
  201. data/spec/unit/veritas/relation/operation/offset/eql_spec.rb +11 -11
  202. data/spec/unit/veritas/relation/operation/offset/hash_spec.rb +1 -1
  203. data/spec/unit/veritas/relation/operation/offset/methods/drop_spec.rb +2 -2
  204. data/spec/unit/veritas/relation/operation/offset/offset_spec.rb +1 -1
  205. data/spec/unit/veritas/relation/operation/order/ascending/reverse_spec.rb +1 -1
  206. data/spec/unit/veritas/relation/operation/order/class_methods/new_spec.rb +3 -7
  207. data/spec/unit/veritas/relation/operation/order/descending/reverse_spec.rb +1 -1
  208. data/spec/unit/veritas/relation/operation/order/direction/class_methods/coerce_spec.rb +1 -1
  209. data/spec/unit/veritas/relation/operation/order/direction/eql_spec.rb +4 -4
  210. data/spec/unit/veritas/relation/operation/order/direction/rename_spec.rb +1 -1
  211. data/spec/unit/veritas/relation/operation/order/direction_set/attributes_spec.rb +1 -1
  212. data/spec/unit/veritas/relation/operation/order/direction_set/class_methods/coerce_spec.rb +4 -4
  213. data/spec/unit/veritas/relation/operation/order/direction_set/class_methods/new_spec.rb +32 -0
  214. data/spec/unit/veritas/relation/operation/order/direction_set/eql_spec.rb +4 -4
  215. data/spec/unit/veritas/relation/operation/order/direction_set/equal_value_spec.rb +6 -6
  216. data/spec/unit/veritas/relation/operation/order/direction_set/project_spec.rb +1 -1
  217. data/spec/unit/veritas/relation/operation/order/direction_set/rename_spec.rb +1 -1
  218. data/spec/unit/veritas/relation/operation/order/direction_set/reverse_spec.rb +2 -2
  219. data/spec/unit/veritas/relation/operation/order/direction_set/sort_tuples_spec.rb +4 -4
  220. data/spec/unit/veritas/relation/operation/order/direction_set/to_ary_spec.rb +1 -1
  221. data/spec/unit/veritas/relation/operation/order/direction_set/union_spec.rb +1 -1
  222. data/spec/unit/veritas/relation/operation/order/eql_spec.rb +5 -5
  223. data/spec/unit/veritas/relation/operation/order/methods/order_spec.rb +24 -4
  224. data/spec/unit/veritas/relation/operation/order/methods/sort_by_spec.rb +28 -0
  225. data/spec/unit/veritas/relation/operation/reverse/class_methods/new_spec.rb +6 -6
  226. data/spec/unit/veritas/relation/operation/reverse/directions_spec.rb +1 -1
  227. data/spec/unit/veritas/relation/operation/reverse/each_spec.rb +1 -1
  228. data/spec/unit/veritas/relation/operation/reverse/methods/reverse_spec.rb +2 -2
  229. data/spec/unit/veritas/relation/operation/set/class_methods/new_spec.rb +1 -1
  230. data/spec/unit/veritas/tuple/class_methods/coerce_spec.rb +1 -1
  231. data/spec/unit/veritas/tuple/data_spec.rb +16 -0
  232. data/spec/unit/veritas/tuple/element_reference_spec.rb +1 -1
  233. data/spec/unit/veritas/tuple/eql_spec.rb +5 -5
  234. data/spec/unit/veritas/tuple/equal_value_spec.rb +7 -7
  235. data/spec/unit/veritas/tuple/extend_spec.rb +3 -3
  236. data/spec/unit/veritas/tuple/hash_spec.rb +1 -1
  237. data/spec/unit/veritas/tuple/inspect_spec.rb +2 -2
  238. data/spec/unit/veritas/tuple/join_spec.rb +1 -1
  239. data/spec/unit/veritas/tuple/predicate_spec.rb +44 -0
  240. data/spec/unit/veritas/tuple/project_spec.rb +1 -1
  241. data/spec/unit/veritas/tuple/to_ary_spec.rb +3 -1
  242. data/tasks/metrics/heckle.rake +1 -0
  243. data/veritas.gemspec +28 -14
  244. metadata +31 -17
data/.travis.yml CHANGED
@@ -1,8 +1,10 @@
1
1
  bundler_args: --without guard metrics
2
2
  script: "bundle exec rake spec"
3
3
  rvm:
4
- - ree
5
4
  - 1.8.7
6
5
  - 1.9.2
7
- - ruby-head
8
6
  - rbx
7
+ # - rbx-2.0
8
+ - ree
9
+ # - jruby
10
+ - ruby-head
data/Gemfile CHANGED
@@ -3,19 +3,18 @@
3
3
  source :rubygems
4
4
 
5
5
  group :development do
6
- gem 'backports', '~> 2.2.1'
7
- gem 'jeweler', '~> 1.6.0'
8
- gem 'rake', '~> 0.9.0'
6
+ gem 'backports', '~> 2.3.0'
7
+ gem 'jeweler', '~> 1.6.4'
8
+ gem 'rake', '~> 0.9.2'
9
9
  gem 'rspec', '~> 1.3.2'
10
- gem 'yard', '~> 0.7.1'
10
+ gem 'yard', '~> 0.7.2'
11
11
  end
12
12
 
13
13
  group :guard do
14
- gem 'growl', '~> 1.0.3'
15
- gem 'guard', '~> 0.3.4'
14
+ gem 'guard', '~> 0.5.1'
16
15
  gem 'guard-bundler', '~> 0.1.3'
17
16
  gem 'guard-ego', '~> 0.0.1'
18
- gem 'guard-rspec', '~> 0.3.1'
17
+ gem 'guard-rspec', '~> 0.4.0'
19
18
  end
20
19
 
21
20
  group :benchmarks do
@@ -33,7 +32,7 @@ platforms :mri_18 do
33
32
  gem 'flay', '~> 1.4.2'
34
33
  gem 'flog', '~> 2.5.1'
35
34
  gem 'heckle', '~> 1.4.3'
36
- gem 'json', '~> 1.5.1'
35
+ gem 'json', '~> 1.5.3'
37
36
  gem 'metric_fu', '~> 2.1.1'
38
37
  gem 'mspec', '~> 1.5.17'
39
38
  gem 'rcov', '~> 0.9.9'
data/README.rdoc CHANGED
@@ -36,19 +36,19 @@ http://travis-ci.org/dkubb/veritas.png
36
36
  new_relation = relation.difference(other) # OR relation - other
37
37
 
38
38
  # restriction
39
- new_relation = relation.restrict { |r| r[:a].eq('other').and(r[:b].gte(42)) }
39
+ new_relation = relation.restrict { |r| r.a.eq('other').and(r.b.gte(42)) }
40
40
 
41
41
  # theta-join
42
- new_relation = relation.join(other) { |r| r[:a].gte(r[:b]) }
42
+ new_relation = relation.join(other) { |r| r.a.gte(r.b) }
43
43
 
44
44
  # NOTE: theta-join is effectively restricting a product of the relations
45
45
 
46
46
  # extend
47
- new_relation = relation.extend { |r| r.add(:total, r[:unit_price] * r[:quantity]) }
47
+ new_relation = relation.extend { |r| r.add(:total, r.unit_price * r.quantity) }
48
48
  new_relation = relation.extend { |r| r.add(:total) { |t| t[:unit_price] * t[:quantity] } }
49
49
 
50
50
  # summarize
51
- new_relation = relation.summarize(relation.project([ :name ])) { |r| r.add(:count, r[:name].count) }
51
+ new_relation = relation.summarize(relation.project([ :name ])) { |r| r.add(:count, r.name.count) }
52
52
  new_relation = relation.summarize(relation.project([ :name ])) { |r| r.add(:count) { |acc, t| acc.to_i + 1 } }
53
53
 
54
54
  # Non-Relational Operators
@@ -57,14 +57,11 @@ http://travis-ci.org/dkubb/veritas.png
57
57
  # returns a set that represents the relation header
58
58
  header = relation.header
59
59
 
60
- # simplifies and normalizes the relation operations
61
- optimized_relation = relation.optimize
62
-
63
60
  # a relation is Enumerable
64
61
  relation = relation.each { |tuple| ... }
65
62
 
66
63
  # order by attribute and direction
67
- new_relation = relation.order { |r| [ r[:a].desc, r[:b] ] }
64
+ new_relation = relation.sort_by { |r| [ r.a.desc, r.b ] }
68
65
 
69
66
  # reverse the relation (only allowed if ordered)
70
67
  new_relation = relation.reverse
@@ -83,14 +80,6 @@ http://travis-ci.org/dkubb/veritas.png
83
80
  new_relation = relation.last # default is 1
84
81
  new_relation = relation.last(5)
85
82
 
86
- # CRUD Operators
87
- # --------------
88
-
89
- # can only modify relations that project all candidate keys for the base relations
90
- new_relation = relation.create(a: 'test', b: 'other', c: 'yet another')
91
- new_relation = relation.update(a: 'test', b: 'other', c: 'yet another')
92
- new_relation = relation.delete
93
-
94
83
  == Goals
95
84
 
96
85
  The purpose of this project is to expand my knowledge of relational algebra by attempting to implement a simple query system using the primitive operations defined in relational algebra.
@@ -107,18 +96,28 @@ Not only does this work nicely with associations, but it will allow DataMapper t
107
96
 
108
97
  The first phase of this project will be to implement all the operations listed below using in-memory data structures. I'm focusing on the API, and making sure the specs ensure the desired results are obtained from each operation.
109
98
 
110
- This is 100% complete now.
99
+ This is 100% complete.
111
100
 
112
101
  === Phase 2: RDBMS Engines
113
102
 
114
103
  The second phase of this project will be to add a RDBMS based engine, and move the in-memory matching to it's own engine. I'll also be working on a system where if the primary engine cannot carry out some operation, that it first look at alternate forms (eg. using a join instead of an intersection), and then fall-back to in-memory matching. I also want to look at re-arranging queries so that all the operations that can be performed natively are "pushed down" the hierarchy and then the in-memory matching is performed last.
115
104
 
116
- This is 90% complete. I have finished a first pass on the veritas-sql-compiler[https://github.com/dkubb/veritas-sql-compiler] which is a visitor that walks the AST and produces SQL for every operation except extend and summarize. To finish those I will need to add function support to veritas that are introspectable (i.e. not Proc objects). Once I can introspect them, then I can serialize them to SQL and other query languages.
105
+ This is 95% complete. I have completed a first pass on veritas-sql-generator[https://github.com/dkubb/veritas-sql-generator] which is a visitor that walks the AST and produces SQL for every operatione. More work is needed to write adapters that use the veritas-sql-generator and manage database connections/execution.
117
106
 
118
107
  === Phase 3: DataMapper Integration
119
108
 
120
109
  The third phase of this project will be to add a few NoSQL engines (like MongoDB[http://www.mongodb.org/] and CouchDB[http://couchdb.org/]) and then look at writing a DataMapper adapter that translates Query objects into Veritas relations. I want to make sure all the DM specs pass with this adapter and each engine, and if everything goes well I will look at updating DM to work directly on top of Veritas.
121
110
 
111
+ == Related Projects
112
+
113
+ * veritas-optimizer[https://github.com/dkubb/veritas-optimizer]
114
+
115
+ This is an optimizer that takes a veritas relation, scalar or aggregate function and will transform it into something equivalent but simpler in structure to the original.
116
+
117
+ * veritas-sql-generator[https://github.com/dkubb/veritas-sql-generator]
118
+
119
+ This is a visitor class that takes a veritas relation and generates valid SQL from it.
120
+
122
121
  == Note on Patches/Pull Requests
123
122
 
124
123
  * If you want your code merged into the mainline, please discuss
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'rake'
5
5
  require File.expand_path('../lib/veritas/version', __FILE__)
6
6
 
7
7
  begin
8
- gem('jeweler', '~> 1.6.0') if respond_to?(:gem, true)
8
+ gem('jeweler', '~> 1.6.2') if respond_to?(:gem, true)
9
9
  require 'jeweler'
10
10
 
11
11
  Jeweler::Tasks.new do |gem|
@@ -23,5 +23,5 @@ begin
23
23
 
24
24
  FileList['tasks/**/*.rake'].each { |task| import task }
25
25
  rescue LoadError
26
- puts 'Jeweler (or a dependency) not available. Install it with: gem install jeweler -v 1.6.0'
26
+ puts 'Jeweler (or a dependency) not available. Install it with: gem install jeweler -v 1.6.2'
27
27
  end
data/TODO CHANGED
@@ -1,3 +1,8 @@
1
+ * Materialized relations need to hold a reference to the original relation.
2
+ * Especially "empty" relations should hold a reference to the original
3
+ relation so that insert/update can be performed on them if they are
4
+ empty not because they are valid, but because the source object is empty
5
+
1
6
  * Remove Order, Reverse, Limit and Offset from the Relation inheritance chain
2
7
  * Instead make it so they are proxy classes that wrap Relations, but
3
8
  proxy method calls to the Relation methods, and then wrap the return
@@ -12,7 +17,7 @@
12
17
  and instead wrap materialized relations in the Order object
13
18
  if any.
14
19
 
15
- * Add Relation#nest and Relation#unnest
20
+ * Add Relation#group and Relation#ungroup
16
21
 
17
22
  * Update Attributes so that constraints are modelled using predicates,
18
23
  so that when "join-ability" is tested, the predicates can just be
@@ -40,16 +45,15 @@
40
45
  * The #call method should propagate the Tuple down to each callable entry
41
46
  in the Enumerable.
42
47
 
43
- * Update context to return an object that allows aliasing of ruby-ish predicates
44
- to specific operations, eg:
45
- * Predicates:
46
- * Alias #== to #eq (may break alot)
47
- * Alias #!= to #ne (in 1.9 only)
48
- * Alias #>= to #gte
49
- * Alias #> to #gt
50
- * Alias #<= to #lte
51
- * Alias #< to #lt
52
- * Alias #=~ to #match
53
- * Direction:
54
- * Alias #@+ to #asc
55
- * Alias #@- to #desc
48
+ * Within the restriction context, make sure the attributes have aliases for:
49
+ * Alias #== to #eq (may break alot)
50
+ * Alias #!= to #ne (in 1.9 only)
51
+ * Alias #>= to #gte
52
+ * Alias #> to #gt
53
+ * Alias #<= to #lte
54
+ * Alias #< to #lt
55
+ * Alias #=~ to #match
56
+
57
+ * Within the sort_by context, make sure the attributes have aliases for:
58
+ * Alias #@+ to #asc
59
+ * Alias #@- to #desc
data/benchmarks/memory.rb CHANGED
@@ -7,6 +7,7 @@
7
7
  $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
8
8
 
9
9
  require 'backports'
10
+ require 'backports/basic_object'
10
11
 
11
12
  unless GC.respond_to?(:enable_stats)
12
13
  puts 'Error: benchmark works on ree, or ruby with Railsbench GC patch only'
@@ -94,7 +95,7 @@ end
94
95
 
95
96
  each_count do |array, relation, count|
96
97
  gc_statistics "restriction (#{count} tuples)" do
97
- relation.restrict { |r| r[:id].gte(1) }.each {}
98
+ relation.restrict { |r| r.id.gte(1) }.each {}
98
99
  end
99
100
  end
100
101
 
@@ -130,12 +131,12 @@ end
130
131
 
131
132
  each_count do |array, relation, count|
132
133
  gc_statistics "order (#{count} tuples)" do
133
- relation.order { |r| [ r[:id].desc, r[:name] ] }.each {}
134
+ relation.sort_by { |r| [ r.id.desc, r.name ] }.each {}
134
135
  end
135
136
  end
136
137
 
137
138
  each_count do |array, relation, count|
138
- relation = relation.order(relation.header)
139
+ relation = relation.sort_by { |r| [ r.id, r.name ] }
139
140
 
140
141
  gc_statistics "take (#{count} tuples)" do
141
142
  relation.take(count).each {}
@@ -143,7 +144,7 @@ each_count do |array, relation, count|
143
144
  end
144
145
 
145
146
  each_count do |array, relation, count|
146
- relation = relation.order(relation.header)
147
+ relation = relation.sort_by { |r| [ r.id, r.name ] }
147
148
 
148
149
  gc_statistics "drop (#{count} tuples)" do
149
150
  relation.drop(1).each {}
@@ -151,7 +152,7 @@ each_count do |array, relation, count|
151
152
  end
152
153
 
153
154
  each_count do |array, relation, count|
154
- relation = relation.order(relation.header)
155
+ relation = relation.sort_by { |r| [ r.id, r.name ] }
155
156
 
156
157
  gc_statistics "first (#{count} tuples)" do
157
158
  relation.first(count).each {}
@@ -159,7 +160,7 @@ each_count do |array, relation, count|
159
160
  end
160
161
 
161
162
  each_count do |array, relation, count|
162
- relation = relation.order(relation.header)
163
+ relation = relation.sort_by { |r| [ r.id, r.name ] }
163
164
 
164
165
  gc_statistics "last (#{count} tuples)" do
165
166
  relation.last(count).each {}
@@ -167,7 +168,7 @@ each_count do |array, relation, count|
167
168
  end
168
169
 
169
170
  each_count do |array, relation, count|
170
- relation = relation.order(relation.header)
171
+ relation = relation.sort_by { |r| [ r.id, r.name ] }
171
172
 
172
173
  gc_statistics "reverse (#{count} tuples)" do
173
174
  relation.reverse.each {}
data/benchmarks/speed.rb CHANGED
@@ -7,6 +7,7 @@
7
7
  $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
8
8
 
9
9
  require 'backports'
10
+ require 'backports/basic_object'
10
11
  require 'rbench'
11
12
  require 'veritas'
12
13
  include Veritas
@@ -18,7 +19,7 @@ array = (1..100).map { |n| Tuple.new(header, [ n, 'Dan Kubb' ]) }
18
19
  relation = Relation.new(header, array)
19
20
  join = Relation.new([ [ :id, Integer, ], [ :age, Integer ] ], [ [ 1, 35 ] ])
20
21
  product = Relation.new([ [ :age, Integer ] ], [ [ 35 ] ])
21
- ordered = relation.order(relation.header)
22
+ ordered = relation.sort_by { |r| [ r.id, r.name ] }
22
23
 
23
24
  RBench.run(TIMES) do
24
25
  column :ruby, :title => 'Ruby'
@@ -42,7 +43,7 @@ RBench.run(TIMES) do
42
43
 
43
44
  report 'restriction' do
44
45
  ruby { array.select { |tuple| tuple[:id] >= 1 }.each {} }
45
- veritas { relation.restrict { |r| r[:id].gte(1) }.each {} }
46
+ veritas { relation.restrict { |r| r.id.gte(1) }.each {} }
46
47
  end
47
48
 
48
49
  report 'join' do
@@ -71,7 +72,7 @@ RBench.run(TIMES) do
71
72
 
72
73
  report 'order' do
73
74
  ruby { array.sort_by { |tuple| [ -tuple[:id], tuple[:name] ] }.each {} }
74
- veritas { relation.order { |r| [ r[:id].desc, r[:name] ] }.each {} }
75
+ veritas { relation.sort_by { |r| [ r.id.desc, r.name ] }.each {} }
75
76
  end
76
77
 
77
78
  report 'take' do
data/config/flay.yml CHANGED
@@ -1,3 +1,3 @@
1
1
  ---
2
2
  threshold: 68
3
- total_score: 654
3
+ total_score: 738
@@ -86,6 +86,9 @@ module Veritas
86
86
 
87
87
  # Return the type returned from #call
88
88
  #
89
+ # @example
90
+ # type = aggregate.type
91
+ #
89
92
  # @return [Class<Attribute>]
90
93
  #
91
94
  # @api public
@@ -7,6 +7,13 @@ module Veritas
7
7
  class Join < Relation
8
8
  include Relation::Operation::Combination
9
9
 
10
+ # The common headers between the operands
11
+ #
12
+ # @return [Header]
13
+ #
14
+ # @api private
15
+ attr_reader :join_header
16
+
10
17
  # Instantiate a new Join
11
18
  #
12
19
  # @example
@@ -54,7 +61,7 @@ module Veritas
54
61
  super
55
62
  right_header = right.header
56
63
  @join_header = left.header & right_header
57
- @remainder_header = right_header - @join_header
64
+ @remainder_header = right_header - join_header
58
65
  end
59
66
 
60
67
  # Iterate over each tuple in the set
@@ -73,8 +80,8 @@ module Veritas
73
80
  # @api public
74
81
  def each(&block)
75
82
  return to_enum unless block_given?
76
- index = build_index
77
83
  util = Relation::Operation::Combination
84
+ index = build_index
78
85
 
79
86
  left.each do |left_tuple|
80
87
  right_tuples = index[join_tuple(left_tuple)]
@@ -109,7 +116,7 @@ module Veritas
109
116
  #
110
117
  # @api private
111
118
  def join_tuple(tuple)
112
- tuple.project(@join_header)
119
+ tuple.project(join_header)
113
120
  end
114
121
 
115
122
  # Generate a tuple with the disjoint attributes to use in the join
@@ -132,7 +139,7 @@ module Veritas
132
139
  # join = relation.join(other)
133
140
  #
134
141
  # @example theta-join using a block
135
- # join = relation.join(other) { |r| r[:a].gte(r[:b]) }
142
+ # join = relation.join(other) { |r| r.a.gte(r.b) }
136
143
  #
137
144
  # @param [Relation] other
138
145
  # the other relation to join
@@ -58,8 +58,9 @@ module Veritas
58
58
  # @api public
59
59
  def each(&block)
60
60
  return to_enum unless block_given?
61
+ right_tuples = right.to_a
61
62
  left.each do |left_tuple|
62
- Relation::Operation::Combination.combine_tuples(header, left_tuple, right, &block)
63
+ Relation::Operation::Combination.combine_tuples(header, left_tuple, right_tuples, &block)
63
64
  end
64
65
  self
65
66
  end
@@ -83,7 +83,7 @@ module Veritas
83
83
  # Return a relation with restricted tuples
84
84
  #
85
85
  # @example restriction using a block
86
- # restriction = relation.restrict { |r| r[:a].eq('other').and(r[:b].gte(42)) }
86
+ # restriction = relation.restrict { |r| r.a.eq('other').and(r.b.gte(42)) }
87
87
  #
88
88
  # @yield [relation]
89
89
  # optional block to restrict the tuples with
@@ -98,7 +98,8 @@ module Veritas
98
98
  #
99
99
  # @api public
100
100
  def restrict
101
- Restriction.new(self, yield(self))
101
+ context = Evaluator::Context.new(header) { |context| yield context }
102
+ Restriction.new(self, context.yield)
102
103
  end
103
104
 
104
105
  end # module Methods
@@ -155,14 +155,19 @@ module Veritas
155
155
 
156
156
  # Return a summarized relation
157
157
  #
158
+ # @example with no arguments
159
+ # summarization = relation.summarize do |context|
160
+ # context.add(:count, context[:id].count)
161
+ # end
162
+ #
158
163
  # @example with a relation
159
164
  # summarization = relation.summarize(relation.project([ :name ])) do |context|
160
- # context.add(:count, context[:name].count)
165
+ # context.add(:count, context[:id].count)
161
166
  # end
162
167
  #
163
168
  # @example with a header
164
169
  # summarization = relation.summarize([ :name ]) do |context|
165
- # context.add(:count, context[:name].count)
170
+ # context.add(:count, context[:id].count)
166
171
  # end
167
172
  #
168
173
  # @param [Relation, Header, #to_ary] summarize_with
@@ -176,7 +181,7 @@ module Veritas
176
181
  # @return [Summarization]
177
182
  #
178
183
  # @api public
179
- def summarize(summarize_with)
184
+ def summarize(summarize_with = TABLE_DEE)
180
185
  summarize_per = coerce_to_relation(summarize_with)
181
186
  context = Evaluator::Context.new(header - summarize_per.header) { |context| yield context }
182
187
  Summarization.new(self, summarize_per, context.functions)
@@ -93,7 +93,9 @@ module Veritas
93
93
  #
94
94
  # @api public
95
95
  def joinable?(other)
96
- super && length.eql?(other.length)
96
+ super &&
97
+ min_length.eql?(other.min_length) &&
98
+ max_length.eql?(other.max_length)
97
99
  end
98
100
 
99
101
  private
@@ -31,7 +31,7 @@ module Veritas
31
31
  # @api private
32
32
  def self.inherited(descendant)
33
33
  superclass = self.superclass
34
- superclass.inherited(descendant) unless superclass.equal?(::Object)
34
+ superclass.inherited(descendant) if superclass.respond_to?(:descendants)
35
35
  descendants.unshift(descendant)
36
36
  self
37
37
  end
@@ -85,6 +85,7 @@ module Veritas
85
85
  #
86
86
  # @api private
87
87
  def self.included(descendant)
88
+ super
88
89
  descendant.memoize :inverse
89
90
  end
90
91
 
@@ -16,6 +16,7 @@ module Veritas
16
16
  #
17
17
  # @api private
18
18
  def self.included(descendant)
19
+ super
19
20
  descendant.extend ClassMethods
20
21
  self
21
22
  end
@@ -65,6 +65,8 @@ module Veritas
65
65
  # @example with other argument
66
66
  # conjunction = expression.not(other)
67
67
  #
68
+ # @return [Connective]
69
+ #
68
70
  # @overload not
69
71
  # Negates the expression
70
72
  #
@@ -5,7 +5,11 @@ module Veritas
5
5
 
6
6
  # Abstract base class for logical propositions
7
7
  class Proposition < Function
8
- include AbstractClass, Singleton
8
+ include AbstractClass,
9
+ Singleton,
10
+ Function::Connective::Conjunction::Methods,
11
+ Function::Connective::Disjunction::Methods,
12
+ Function::Connective::Negation::Methods
9
13
 
10
14
  # Instantiate a new Proposition
11
15
  #
@@ -79,6 +79,7 @@ module Veritas
79
79
  #
80
80
  # @api private
81
81
  def self.included(descendant)
82
+ super
82
83
  descendant.memoize :inverse
83
84
  end
84
85
 
@@ -41,6 +41,9 @@ module Veritas
41
41
 
42
42
  # Evaluate the function using the operands
43
43
  #
44
+ # @example
45
+ # object = function.call(*args)
46
+ #
44
47
  # @return [Object]
45
48
  #
46
49
  # @api public
@@ -9,7 +9,7 @@ module Veritas
9
9
  # The base relation name
10
10
  #
11
11
  # @example
12
- # name = base_relation.name
12
+ # name = base.name
13
13
  #
14
14
  # @return [#to_s]
15
15
  #
@@ -28,11 +28,40 @@ module Veritas
28
28
  # @return [undefined]
29
29
  #
30
30
  # @api private
31
- def initialize(name, *args)
32
- super(*args)
31
+ def initialize(name, header, tuples = Empty::ZERO_TUPLE)
32
+ super(header, tuples)
33
33
  @name = Immutable.freeze_object(name.to_s)
34
34
  end
35
35
 
36
+ # Compare the base relation with other relation for equality
37
+ #
38
+ # @example
39
+ # base.eql?(other) # => true or false
40
+ #
41
+ # @param [Relation] other
42
+ # the other relation to compare with
43
+ #
44
+ # @return [Boolean]
45
+ #
46
+ # @api public
47
+ def eql?(other)
48
+ super && name.eql?(other.name)
49
+ end
50
+
51
+ # Return the hash of the base relation
52
+ #
53
+ # @example
54
+ # hash = base.hash
55
+ #
56
+ # @return [Fixnum]
57
+ #
58
+ # @api public
59
+ def hash
60
+ super ^ name.hash
61
+ end
62
+
63
+ memoize :hash
64
+
36
65
  end # class Base
37
66
  end # class Relation
38
67
  end # module Veritas
@@ -26,7 +26,7 @@ module Veritas
26
26
  #
27
27
  # @api public
28
28
  def self.new(attributes = [])
29
- attributes = coerce_attributes(attributes).freeze
29
+ attributes = coerce_attributes(attributes.to_ary)
30
30
  assert_unique_attributes(attributes)
31
31
  super
32
32
  end
@@ -39,7 +39,7 @@ module Veritas
39
39
  #
40
40
  # @api private
41
41
  def self.coerce_attributes(attributes)
42
- attributes.to_ary.map { |attribute| Attribute.coerce(attribute) }
42
+ attributes.map { |attribute| Attribute.coerce(attribute) }
43
43
  end
44
44
 
45
45
  # Assert the attributes are unique
@@ -42,6 +42,18 @@ module Veritas
42
42
  self
43
43
  end
44
44
 
45
+ # Return true for a Materialized relation
46
+ #
47
+ # @example
48
+ # relation.materialized? # => true
49
+ #
50
+ # @return [true]
51
+ #
52
+ # @api public
53
+ def materialized?
54
+ true
55
+ end
56
+
45
57
  # Test if there are no tuples
46
58
  #
47
59
  # @example
@@ -17,6 +17,7 @@ module Veritas
17
17
  #
18
18
  # @api private
19
19
  def self.included(descendant)
20
+ super
20
21
  descendant.extend ClassMethods
21
22
  self
22
23
  end
@@ -71,7 +71,7 @@ module Veritas
71
71
  #
72
72
  # @api private
73
73
  def self.assert_valid_limit(limit)
74
- if limit < 0
74
+ if limit.nil? || limit < 0
75
75
  raise InvalidLimitError, "limit must be greater than or equal to 0, but was #{limit.inspect}"
76
76
  end
77
77
  end
@@ -71,7 +71,7 @@ module Veritas
71
71
  #
72
72
  # @api private
73
73
  def self.assert_valid_offset(offset)
74
- if offset < 0
74
+ if offset.nil? || offset < 0
75
75
  raise InvalidOffsetError, "offset must be greater than or equal to 0, but was #{offset.inspect}"
76
76
  end
77
77
  end