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.
- checksums.yaml +7 -0
- data/.rspec +2 -1
- data/.rubocop.yml +7 -0
- data/.travis.yml +10 -7
- data/Gemfile +4 -0
- data/Gemfile.devtools +27 -13
- data/Guardfile +2 -2
- data/README.md +36 -30
- data/TODO +22 -24
- data/axiom.gemspec +9 -9
- data/benchmarks/memory.rb +1 -2
- data/benchmarks/speed.rb +7 -8
- data/config/flay.yml +1 -1
- data/config/reek.yml +19 -7
- data/config/rubocop.yml +6 -9
- data/lib/axiom.rb +28 -13
- data/lib/axiom/aggregate/mean.rb +4 -3
- data/lib/axiom/aggregate/sum.rb +1 -1
- data/lib/axiom/algebra/extension.rb +1 -1
- data/lib/axiom/algebra/join.rb +4 -27
- data/lib/axiom/algebra/product.rb +3 -3
- data/lib/axiom/algebra/projection.rb +2 -2
- data/lib/axiom/algebra/rename.rb +2 -2
- data/lib/axiom/algebra/rename/aliases.rb +3 -3
- data/lib/axiom/algebra/summarization.rb +3 -3
- data/lib/axiom/attribute.rb +5 -4
- data/lib/axiom/attribute/comparable.rb +15 -11
- data/lib/axiom/attribute/date.rb +1 -1
- data/lib/axiom/attribute/date_time.rb +1 -1
- data/lib/axiom/attribute/length_comparable.rb +39 -0
- data/lib/axiom/attribute/numeric.rb +1 -26
- data/lib/axiom/attribute/relation.rb +64 -0
- data/lib/axiom/attribute/string.rb +1 -28
- data/lib/axiom/attribute/time.rb +1 -1
- data/lib/axiom/attribute/tuple.rb +50 -0
- data/lib/axiom/attribute/value_comparable.rb +42 -0
- data/lib/axiom/function.rb +1 -1
- data/lib/axiom/function/binary.rb +4 -16
- data/lib/axiom/function/comparable.rb +1 -1
- data/lib/axiom/function/connective/conjunction.rb +1 -1
- data/lib/axiom/function/connective/disjunction.rb +1 -1
- data/lib/axiom/function/connective/negation.rb +1 -1
- data/lib/axiom/function/numeric/exponentiation.rb +1 -1
- data/lib/axiom/function/numeric/square_root.rb +1 -1
- data/lib/axiom/function/predicate/enumerable.rb +0 -14
- data/lib/axiom/function/predicate/exclusion.rb +1 -1
- data/lib/axiom/function/predicate/inclusion.rb +1 -1
- data/lib/axiom/function/proposition.rb +12 -25
- data/lib/axiom/function/unary.rb +92 -106
- data/lib/axiom/relation.rb +3 -3
- data/lib/axiom/relation/base.rb +15 -0
- data/lib/axiom/relation/header.rb +25 -22
- data/lib/axiom/relation/index.rb +91 -0
- data/lib/axiom/relation/keys.rb +3 -3
- data/lib/axiom/relation/materialized.rb +48 -4
- data/lib/axiom/relation/operation/binary.rb +5 -5
- data/lib/axiom/relation/operation/group.rb +95 -0
- data/lib/axiom/relation/operation/limit.rb +15 -15
- data/lib/axiom/relation/operation/offset.rb +12 -12
- data/lib/axiom/relation/operation/reverse.rb +9 -9
- data/lib/axiom/relation/operation/set.rb +1 -1
- data/lib/axiom/relation/operation/{order.rb → sorted.rb} +29 -28
- data/lib/axiom/relation/operation/{order → sorted}/direction.rb +4 -4
- data/lib/axiom/relation/operation/{order → sorted}/direction_set.rb +3 -3
- data/lib/axiom/relation/operation/ungroup.rb +82 -0
- data/lib/axiom/relation/operation/unwrap.rb +80 -0
- data/lib/axiom/relation/operation/wrap.rb +85 -0
- data/lib/axiom/relation/proxy.rb +5 -6
- data/lib/axiom/relation/variable.rb +1 -2
- data/lib/axiom/support/aliasable.rb +3 -5
- data/lib/axiom/support/equalizer.rb +10 -12
- data/lib/axiom/support/operation/binary.rb +3 -2
- data/lib/axiom/support/operation/unary.rb +1 -1
- data/lib/axiom/tuple.rb +76 -26
- data/lib/axiom/types/relation.rb +13 -0
- data/lib/axiom/types/tuple.rb +13 -0
- data/lib/axiom/version.rb +1 -1
- data/spec/integration/axiom/relation/efficient_enumerable_spec.rb +9 -9
- data/spec/integration/axiom/relation/writable_relations_spec.rb +12 -12
- data/spec/shared/invertible_method_behaviour.rb +1 -1
- data/spec/spec_helper.rb +8 -6
- data/spec/unit/axiom/aggregate/call_spec.rb +7 -12
- data/spec/unit/axiom/aggregate/class_methods/default_spec.rb +7 -2
- data/spec/unit/axiom/aggregate/default_spec.rb +1 -1
- data/spec/unit/axiom/aggregate/finalize_spec.rb +1 -1
- data/spec/unit/axiom/aggregate/maximum/type_spec.rb +2 -6
- data/spec/unit/axiom/aggregate/mean/class_methods/call_spec.rb +2 -2
- data/spec/unit/axiom/aggregate/mean/class_methods/finalize_spec.rb +10 -3
- data/spec/unit/axiom/aggregate/minimum/type_spec.rb +2 -6
- data/spec/unit/axiom/aggregate/sum/default_spec.rb +32 -6
- data/spec/unit/axiom/aggregate/sum/type_spec.rb +2 -6
- data/spec/unit/axiom/aggregate/variance/class_methods/call_spec.rb +6 -6
- data/spec/unit/axiom/algebra/difference/each_spec.rb +3 -3
- data/spec/unit/axiom/algebra/extension/class_methods/new_spec.rb +1 -1
- data/spec/unit/axiom/algebra/extension/each_spec.rb +2 -2
- data/spec/unit/axiom/algebra/intersection/each_spec.rb +3 -3
- data/spec/unit/axiom/algebra/join/each_spec.rb +6 -6
- data/spec/unit/axiom/algebra/product/each_spec.rb +2 -2
- data/spec/unit/axiom/algebra/projection/each_spec.rb +2 -2
- data/spec/unit/axiom/algebra/rename/directions_spec.rb +3 -3
- data/spec/unit/axiom/algebra/rename/each_spec.rb +2 -2
- data/spec/unit/axiom/algebra/restriction/delete_spec.rb +3 -3
- data/spec/unit/axiom/algebra/restriction/each_spec.rb +12 -11
- data/spec/unit/axiom/algebra/restriction/insert_spec.rb +3 -3
- data/spec/unit/axiom/algebra/restriction/methods/restrict_spec.rb +4 -4
- data/spec/unit/axiom/algebra/summarization/each_spec.rb +2 -2
- data/spec/unit/axiom/algebra/summarization/eql_spec.rb +1 -1
- data/spec/unit/axiom/algebra/summarization/summaries/summarize_by_spec.rb +4 -4
- data/spec/unit/axiom/algebra/summarization/summaries/to_hash_spec.rb +2 -2
- data/spec/unit/axiom/algebra/summarization/summary/summarize_by_spec.rb +1 -1
- data/spec/unit/axiom/algebra/union/each_spec.rb +4 -4
- data/spec/unit/axiom/aliasable/fixtures/classes.rb +3 -1
- data/spec/unit/axiom/aliasable/inheritable_alias_spec.rb +18 -27
- data/spec/unit/axiom/attribute/call_spec.rb +1 -1
- data/spec/unit/axiom/attribute/class_methods/coerce_spec.rb +57 -51
- data/spec/unit/axiom/attribute/class_methods/new_spec.rb +1 -1
- data/spec/unit/axiom/attribute/comparable/asc_spec.rb +4 -2
- data/spec/unit/axiom/attribute/comparable/desc_spec.rb +4 -2
- data/spec/unit/axiom/attribute/comparable/range_spec.rb +20 -0
- data/spec/unit/axiom/attribute/eql_spec.rb +1 -1
- data/spec/unit/axiom/attribute/equality_operator_spec.rb +1 -1
- data/spec/unit/axiom/attribute/include_predicate_spec.rb +1 -1
- data/spec/unit/axiom/attribute/name_spec.rb +1 -1
- data/spec/unit/axiom/attribute/optional_predicate_spec.rb +1 -1
- data/spec/unit/axiom/attribute/relation/class_methods/new_spec.rb +56 -0
- data/spec/unit/axiom/attribute/relation/class_methods/type_spec.rb +13 -0
- data/spec/unit/axiom/attribute/relation/header_spec.rb +13 -0
- data/spec/unit/axiom/attribute/relation/new_relation_spec.rb +15 -0
- data/spec/unit/axiom/attribute/rename_spec.rb +1 -1
- data/spec/unit/axiom/attribute/required_predicate_spec.rb +1 -1
- data/spec/unit/axiom/attribute/tuple/class_methods/new_spec.rb +56 -0
- data/spec/unit/axiom/attribute/tuple/class_methods/type_spec.rb +13 -0
- data/spec/unit/axiom/attribute/tuple/header_spec.rb +13 -0
- data/spec/unit/axiom/equalizer/class_method/new_spec.rb +24 -54
- data/spec/unit/axiom/evaluator/context/add_spec.rb +7 -7
- data/spec/unit/axiom/evaluator/context/element_reader_spec.rb +4 -4
- data/spec/unit/axiom/evaluator/context/functions_spec.rb +1 -1
- data/spec/unit/axiom/evaluator/context/method_missing_spec.rb +3 -3
- data/spec/unit/axiom/evaluator/context/respond_to_predicate_spec.rb +3 -3
- data/spec/unit/axiom/evaluator/context/send_spec.rb +8 -8
- data/spec/unit/axiom/function/binary/call_spec.rb +1 -1
- data/spec/unit/axiom/function/binary/type_spec.rb +12 -10
- data/spec/unit/axiom/function/comparable/class_methods/included_spec.rb +2 -2
- data/spec/unit/axiom/function/connective/negation/inverse_spec.rb +1 -1
- data/spec/unit/axiom/function/predicate/call_spec.rb +5 -4
- data/spec/unit/axiom/function/predicate/enumerable/call_spec.rb +12 -2
- data/spec/unit/axiom/function/predicate/eql_spec.rb +4 -3
- data/spec/unit/axiom/function/predicate/equality/methods/eq_spec.rb +5 -1
- data/spec/unit/axiom/function/predicate/exclusion/class_methods/call_spec.rb +37 -8
- data/spec/unit/axiom/function/predicate/exclusion/methods/exclude_spec.rb +6 -2
- data/spec/unit/axiom/function/predicate/greater_than/methods/gt_spec.rb +5 -1
- data/spec/unit/axiom/function/predicate/greater_than_or_equal_to/methods/gte_spec.rb +5 -1
- data/spec/unit/axiom/function/predicate/inclusion/class_methods/call_spec.rb +37 -8
- data/spec/unit/axiom/function/predicate/inclusion/methods/include_spec.rb +6 -2
- data/spec/unit/axiom/function/predicate/inequality/methods/ne_spec.rb +5 -1
- data/spec/unit/axiom/function/predicate/less_than/methods/lt_spec.rb +5 -1
- data/spec/unit/axiom/function/predicate/less_than_or_equal_to/methods/lte_spec.rb +5 -1
- data/spec/unit/axiom/function/predicate/match/methods/match_spec.rb +7 -3
- data/spec/unit/axiom/function/predicate/no_match/methods/no_match_spec.rb +6 -2
- data/spec/unit/axiom/function/proposition/call_spec.rb +6 -4
- data/spec/unit/axiom/function/proposition/class_methods/{new_spec.rb → coerce_spec.rb} +17 -17
- data/spec/unit/axiom/function/proposition/eql_spec.rb +4 -4
- data/spec/unit/axiom/function/proposition/equality_operator_spec.rb +3 -3
- data/spec/unit/axiom/function/proposition/inverse_spec.rb +4 -4
- data/spec/unit/axiom/function/proposition/rename_spec.rb +1 -1
- data/spec/unit/axiom/function/type_spec.rb +1 -1
- data/spec/unit/axiom/function/unary/call_spec.rb +1 -1
- data/spec/unit/axiom/function/unary/callable/call_spec.rb +3 -13
- data/spec/unit/axiom/function/unary/callable/included_spec.rb +2 -2
- data/spec/unit/axiom/function/unary/type_spec.rb +11 -1
- data/spec/unit/axiom/relation/base/eql_spec.rb +1 -1
- data/spec/unit/axiom/relation/base/equality_operator_spec.rb +138 -0
- data/spec/unit/axiom/relation/class_methods/new_spec.rb +7 -7
- data/spec/unit/axiom/relation/directions_spec.rb +2 -2
- data/spec/unit/axiom/relation/each_spec.rb +5 -5
- data/spec/unit/axiom/relation/element_reader_spec.rb +1 -1
- data/spec/unit/axiom/relation/empty/each_spec.rb +1 -1
- data/spec/unit/axiom/relation/empty_predicate_spec.rb +1 -1
- data/spec/unit/axiom/relation/eql_spec.rb +1 -1
- data/spec/unit/axiom/relation/equality_operator_spec.rb +1 -1
- data/spec/unit/axiom/relation/header/class_methods/coerce_spec.rb +2 -2
- data/spec/unit/axiom/relation/header/class_methods/new_spec.rb +3 -3
- data/spec/unit/axiom/relation/header/context_spec.rb +2 -2
- data/spec/unit/axiom/relation/header/each_spec.rb +2 -2
- data/spec/unit/axiom/relation/header/extend_spec.rb +1 -1
- data/spec/unit/axiom/relation/header/{call_spec.rb → fetch_spec.rb} +1 -1
- data/spec/unit/axiom/relation/header/project_spec.rb +1 -1
- data/spec/unit/axiom/relation/header/rename_spec.rb +19 -5
- data/spec/unit/axiom/relation/header/size_spec.rb +14 -0
- data/spec/unit/axiom/relation/header_spec.rb +1 -1
- data/spec/unit/axiom/relation/index/each_spec.rb +33 -0
- data/spec/unit/axiom/relation/index/element_reader_spec.rb +17 -0
- data/spec/unit/axiom/relation/index/left_shift_operator_spec.rb +23 -0
- data/spec/unit/axiom/relation/index/merge_spec.rb +19 -0
- data/spec/unit/axiom/relation/keys/class_methods/coerce_spec.rb +19 -2
- data/spec/unit/axiom/relation/keys/class_methods/new_spec.rb +1 -1
- data/spec/unit/axiom/relation/keys/each_spec.rb +2 -2
- data/spec/unit/axiom/relation/materialize_spec.rb +1 -1
- data/spec/unit/axiom/relation/materialized/class_methods/new_spec.rb +30 -4
- data/spec/unit/axiom/relation/materialized/directions_spec.rb +1 -1
- data/spec/unit/axiom/relation/materialized/materialized_predicate_spec.rb +1 -1
- data/spec/unit/axiom/relation/materialized_predicate_spec.rb +1 -1
- data/spec/unit/axiom/relation/operation/binary/class_methods/included_spec.rb +2 -2
- data/spec/unit/axiom/relation/operation/binary/class_methods/new_spec.rb +6 -6
- data/spec/unit/axiom/relation/operation/combination/class_methods/combine_tuples_spec.rb +4 -4
- data/spec/unit/axiom/relation/operation/group/each_spec.rb +33 -0
- data/spec/unit/axiom/relation/operation/group/header_spec.rb +22 -0
- data/spec/unit/axiom/relation/operation/group/methods/group_spec.rb +25 -0
- data/spec/unit/axiom/relation/operation/limit/class_methods/new_spec.rb +4 -4
- data/spec/unit/axiom/relation/operation/limit/directions_spec.rb +3 -3
- data/spec/unit/axiom/relation/operation/limit/each_spec.rb +4 -4
- data/spec/unit/axiom/relation/operation/limit/limit_spec.rb +2 -2
- data/spec/unit/axiom/relation/operation/offset/class_methods/new_spec.rb +4 -4
- data/spec/unit/axiom/relation/operation/offset/directions_spec.rb +3 -3
- data/spec/unit/axiom/relation/operation/offset/each_spec.rb +4 -4
- data/spec/unit/axiom/relation/operation/offset/offset_spec.rb +2 -2
- data/spec/unit/axiom/relation/operation/reverse/class_methods/new_spec.rb +6 -6
- data/spec/unit/axiom/relation/operation/reverse/directions_spec.rb +3 -3
- data/spec/unit/axiom/relation/operation/reverse/each_spec.rb +4 -4
- data/spec/unit/axiom/relation/operation/set/class_methods/included_spec.rb +2 -2
- data/spec/unit/axiom/relation/operation/{order → sorted}/ascending/class_methods/call_spec.rb +22 -1
- data/spec/unit/axiom/relation/operation/sorted/ascending/class_methods/reverse_spec.rb +11 -0
- data/spec/unit/axiom/relation/operation/{order/descending → sorted/ascending}/reverse_spec.rb +2 -2
- data/spec/unit/axiom/relation/operation/{order → sorted}/class_methods/new_spec.rb +4 -4
- data/spec/unit/axiom/relation/operation/{order → sorted}/delete_spec.rb +12 -6
- data/spec/unit/axiom/relation/operation/{order → sorted}/descending/class_methods/call_spec.rb +22 -1
- data/spec/unit/axiom/relation/operation/sorted/descending/class_methods/reverse_spec.rb +11 -0
- data/spec/unit/axiom/relation/operation/{order/ascending → sorted/descending}/reverse_spec.rb +2 -2
- data/spec/unit/axiom/relation/operation/{order → sorted}/direction/attribute_spec.rb +4 -4
- data/spec/unit/axiom/relation/operation/{order → sorted}/direction/call_spec.rb +7 -7
- data/spec/unit/axiom/relation/operation/{order → sorted}/direction/class_methods/coerce_spec.rb +2 -2
- data/spec/unit/axiom/relation/operation/{order → sorted}/direction/eql_predicate_spec.rb +4 -4
- data/spec/unit/axiom/relation/operation/{order → sorted}/direction/name_spec.rb +4 -4
- data/spec/unit/axiom/relation/operation/{order → sorted}/direction/rename_spec.rb +5 -5
- data/spec/unit/axiom/relation/operation/{order → sorted}/direction/reverse_spec.rb +9 -9
- data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/attributes_spec.rb +1 -1
- data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/class_methods/coerce_spec.rb +3 -3
- data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/class_methods/new_spec.rb +1 -1
- data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/eql_spec.rb +1 -1
- data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/equality_operator_spec.rb +1 -1
- data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/project_spec.rb +1 -1
- data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/rename_spec.rb +1 -1
- data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/reverse_spec.rb +2 -2
- data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/sort_tuples_spec.rb +1 -1
- data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/to_ary_spec.rb +1 -1
- data/spec/unit/axiom/relation/operation/{order → sorted}/directions_spec.rb +1 -1
- data/spec/unit/axiom/relation/operation/{order → sorted}/each_spec.rb +3 -3
- data/spec/unit/axiom/relation/operation/{order → sorted}/eql_spec.rb +1 -1
- data/spec/unit/axiom/relation/operation/{order → sorted}/header_spec.rb +1 -1
- data/spec/unit/axiom/relation/operation/{order → sorted}/insert_spec.rb +12 -6
- data/spec/unit/axiom/relation/operation/{order → sorted}/methods/sort_by_spec.rb +24 -24
- data/spec/unit/axiom/relation/operation/sorted/methods/sort_spec.rb +19 -0
- data/spec/unit/axiom/relation/operation/ungroup/each_spec.rb +33 -0
- data/spec/unit/axiom/relation/operation/ungroup/header_spec.rb +19 -0
- data/spec/unit/axiom/relation/operation/ungroup/methods/ungroup_spec.rb +21 -0
- data/spec/unit/axiom/relation/operation/unwrap/each_spec.rb +33 -0
- data/spec/unit/axiom/relation/operation/unwrap/header_spec.rb +19 -0
- data/spec/unit/axiom/relation/operation/unwrap/methods/unwrap_spec.rb +21 -0
- data/spec/unit/axiom/relation/operation/wrap/each_spec.rb +33 -0
- data/spec/unit/axiom/relation/operation/wrap/header_spec.rb +22 -0
- data/spec/unit/axiom/relation/operation/wrap/methods/wrap_spec.rb +25 -0
- data/spec/unit/axiom/relation/proxy/each_spec.rb +2 -2
- data/spec/unit/axiom/relation/proxy/respond_to_predicate_spec.rb +48 -12
- data/spec/unit/axiom/relation/replace_spec.rb +8 -8
- data/spec/unit/axiom/tuple/class_methods/coerce_spec.rb +7 -1
- data/spec/unit/axiom/tuple/{call_spec.rb → fetch_spec.rb} +1 -1
- data/spec/unit/axiom/tuple/inspect_spec.rb +14 -0
- data/spec/unit/axiom/tuple/rename_spec.rb +17 -0
- data/spec/unit/axiom/tuple/size_spec.rb +14 -0
- data/spec/unit/axiom/tuple/to_ary_spec.rb +22 -5
- data/spec/unit/axiom/tuple/to_hash_spec.rb +14 -0
- data/spec/unit/axiom/types/relation/class_methods/primitive_spec.rb +13 -0
- data/spec/unit/axiom/types/tuple/class_methods/primitive_spec.rb +13 -0
- data/spec/unit/axiom/visitable/accept_spec.rb +1 -1
- data/spec/unit/date/pred_spec.rb +1 -1
- data/spec/unit/time/pred_spec.rb +1 -1
- metadata +631 -107
- data/spec/unit/axiom/aggregate/hash_spec.rb +0 -15
- data/spec/unit/axiom/algebra/extension/hash_spec.rb +0 -15
- data/spec/unit/axiom/algebra/projection/hash_spec.rb +0 -16
- data/spec/unit/axiom/algebra/rename/aliases/hash_spec.rb +0 -15
- data/spec/unit/axiom/algebra/rename/hash_spec.rb +0 -15
- data/spec/unit/axiom/algebra/restriction/hash_spec.rb +0 -15
- data/spec/unit/axiom/algebra/summarization/hash_spec.rb +0 -16
- data/spec/unit/axiom/attribute/hash_spec.rb +0 -21
- data/spec/unit/axiom/attribute/numeric/hash_spec.rb +0 -17
- data/spec/unit/axiom/attribute/string/hash_spec.rb +0 -25
- data/spec/unit/axiom/equalizer/methods/eql_spec.rb +0 -49
- data/spec/unit/axiom/equalizer/methods/equality_operator_spec.rb +0 -85
- data/spec/unit/axiom/function/binary/invertible/class_methods/included_spec.rb +0 -29
- data/spec/unit/axiom/function/predicate/hash_spec.rb +0 -16
- data/spec/unit/axiom/function/predicate/inverse_spec.rb +0 -17
- data/spec/unit/axiom/function/proposition/hash_spec.rb +0 -14
- data/spec/unit/axiom/function/unary/hash_spec.rb +0 -18
- data/spec/unit/axiom/function/unary/invertible/class_methods/included_spec.rb +0 -29
- data/spec/unit/axiom/operation/binary/hash_spec.rb +0 -16
- data/spec/unit/axiom/operation/unary/hash_spec.rb +0 -15
- data/spec/unit/axiom/relation/base/hash_spec.rb +0 -16
- data/spec/unit/axiom/relation/hash_spec.rb +0 -19
- data/spec/unit/axiom/relation/header/hash_spec.rb +0 -15
- data/spec/unit/axiom/relation/operation/limit/hash_spec.rb +0 -16
- data/spec/unit/axiom/relation/operation/offset/hash_spec.rb +0 -16
- data/spec/unit/axiom/relation/operation/order/ascending/class_methods/reverse_spec.rb +0 -11
- data/spec/unit/axiom/relation/operation/order/descending/class_methods/reverse_spec.rb +0 -11
- data/spec/unit/axiom/relation/operation/order/direction/hash_spec.rb +0 -15
- data/spec/unit/axiom/relation/operation/order/direction_set/hash_spec.rb +0 -15
- data/spec/unit/axiom/relation/operation/order/hash_spec.rb +0 -15
- data/spec/unit/axiom/relation/operation/order/methods/sort_spec.rb +0 -19
- data/spec/unit/axiom/relation/proxy/hash_spec.rb +0 -26
- data/spec/unit/axiom/relation/proxy/method_missing_spec.rb +0 -24
- 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
|
data/lib/axiom/relation/keys.rb
CHANGED
@@ -31,7 +31,7 @@ module Axiom
|
|
31
31
|
if object.kind_of?(self)
|
32
32
|
object
|
33
33
|
else
|
34
|
-
block ||=
|
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
|
-
|
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 =
|
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::
|
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::
|
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
|
73
|
+
def initialize(header, tuples, directions = Operation::Sorted::DirectionSet::EMPTY)
|
30
74
|
super(header, tuples)
|
31
|
-
@directions = Operation::
|
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
|
-
|
50
|
+
assert_sorted_match(left, right)
|
51
51
|
super
|
52
52
|
end
|
53
53
|
|
54
54
|
private
|
55
55
|
|
56
|
-
# Assert that
|
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
|
64
|
+
# raised if one relation is sorted and the other is not
|
65
65
|
#
|
66
66
|
# @api private
|
67
|
-
def
|
67
|
+
def assert_sorted_match(left, right)
|
68
68
|
if left.directions.empty? != right.directions.empty?
|
69
|
-
|
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::
|
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
|
-
|
43
|
+
assert_sorted_operand(operand)
|
44
44
|
assert_valid_limit(limit)
|
45
45
|
super
|
46
46
|
end
|
47
47
|
|
48
|
-
# Assert the operand is
|
48
|
+
# Assert the operand is sorted
|
49
49
|
#
|
50
50
|
# @param [Relation] operand
|
51
51
|
#
|
52
52
|
# @return [undefined]
|
53
53
|
#
|
54
|
-
# @raise [
|
55
|
-
# raised if the operand is
|
54
|
+
# @raise [SortededRelationRequiredError]
|
55
|
+
# raised if the operand is unsorted
|
56
56
|
#
|
57
57
|
# @api private
|
58
|
-
def self.
|
59
|
-
if operand.header.
|
60
|
-
|
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
|
-
|
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 :
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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::
|
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
|
-
|
43
|
+
assert_sorted_operand(operand)
|
44
44
|
assert_valid_offset(offset)
|
45
45
|
super
|
46
46
|
end
|
47
47
|
|
48
|
-
# Assert the operand is
|
48
|
+
# Assert the operand is sorted
|
49
49
|
#
|
50
50
|
# @param [Relation] operand
|
51
51
|
#
|
52
52
|
# @return [undefined]
|
53
53
|
#
|
54
|
-
# @raise [
|
55
|
-
# raised if the operand is
|
54
|
+
# @raise [SortededRelationRequiredError]
|
55
|
+
# raised if the operand is unsorted
|
56
56
|
#
|
57
57
|
# @api private
|
58
|
-
def self.
|
59
|
-
if operand.header.
|
60
|
-
|
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
|
-
|
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 :
|
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
|
-
|
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
|
-
|
147
|
+
fail ImmutableRelationError, 'deleting from an offset is impossible'
|
148
148
|
end
|
149
149
|
|
150
150
|
module Methods
|