axiom-optimizer 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gemtest +0 -0
- data/.gitignore +37 -0
- data/.rspec +4 -0
- data/.rvmrc +1 -0
- data/.travis.yml +35 -0
- data/CONTRIBUTING.md +11 -0
- data/Gemfile +10 -0
- data/Gemfile.devtools +57 -0
- data/Guardfile +23 -0
- data/LICENSE +20 -0
- data/README.md +111 -0
- data/Rakefile +5 -0
- data/TODO +144 -0
- data/axiom-optimizer.gemspec +25 -0
- data/config/flay.yml +3 -0
- data/config/flog.yml +2 -0
- data/config/mutant.yml +3 -0
- data/config/reek.yml +162 -0
- data/config/roodi.yml +16 -0
- data/config/yardstick.yml +2 -0
- data/lib/axiom-optimizer.rb +3 -0
- data/lib/axiom/optimizer.rb +168 -0
- data/lib/axiom/optimizer/aggregate.rb +16 -0
- data/lib/axiom/optimizer/aggregate/count.rb +17 -0
- data/lib/axiom/optimizer/aggregate/maximum.rb +17 -0
- data/lib/axiom/optimizer/aggregate/mean.rb +17 -0
- data/lib/axiom/optimizer/aggregate/minimum.rb +17 -0
- data/lib/axiom/optimizer/aggregate/standard_deviation.rb +17 -0
- data/lib/axiom/optimizer/aggregate/sum.rb +17 -0
- data/lib/axiom/optimizer/aggregate/variance.rb +17 -0
- data/lib/axiom/optimizer/algebra/difference.rb +68 -0
- data/lib/axiom/optimizer/algebra/extension.rb +97 -0
- data/lib/axiom/optimizer/algebra/intersection.rb +68 -0
- data/lib/axiom/optimizer/algebra/join.rb +184 -0
- data/lib/axiom/optimizer/algebra/product.rb +70 -0
- data/lib/axiom/optimizer/algebra/projection.rb +212 -0
- data/lib/axiom/optimizer/algebra/rename.rb +381 -0
- data/lib/axiom/optimizer/algebra/restriction.rb +373 -0
- data/lib/axiom/optimizer/algebra/summarization.rb +200 -0
- data/lib/axiom/optimizer/algebra/union.rb +68 -0
- data/lib/axiom/optimizer/function.rb +87 -0
- data/lib/axiom/optimizer/function/binary.rb +124 -0
- data/lib/axiom/optimizer/function/connective/binary.rb +245 -0
- data/lib/axiom/optimizer/function/connective/conjunction.rb +122 -0
- data/lib/axiom/optimizer/function/connective/disjunction.rb +122 -0
- data/lib/axiom/optimizer/function/connective/negation.rb +65 -0
- data/lib/axiom/optimizer/function/numeric.rb +34 -0
- data/lib/axiom/optimizer/function/numeric/absolute.rb +20 -0
- data/lib/axiom/optimizer/function/numeric/addition.rb +20 -0
- data/lib/axiom/optimizer/function/numeric/division.rb +20 -0
- data/lib/axiom/optimizer/function/numeric/exponentiation.rb +20 -0
- data/lib/axiom/optimizer/function/numeric/modulo.rb +20 -0
- data/lib/axiom/optimizer/function/numeric/multiplication.rb +20 -0
- data/lib/axiom/optimizer/function/numeric/square_root.rb +20 -0
- data/lib/axiom/optimizer/function/numeric/subtraction.rb +20 -0
- data/lib/axiom/optimizer/function/numeric/unary_minus.rb +20 -0
- data/lib/axiom/optimizer/function/numeric/unary_plus.rb +20 -0
- data/lib/axiom/optimizer/function/predicate.rb +61 -0
- data/lib/axiom/optimizer/function/predicate/comparable.rb +144 -0
- data/lib/axiom/optimizer/function/predicate/enumerable.rb +138 -0
- data/lib/axiom/optimizer/function/predicate/equality.rb +44 -0
- data/lib/axiom/optimizer/function/predicate/exclusion.rb +43 -0
- data/lib/axiom/optimizer/function/predicate/greater_than.rb +55 -0
- data/lib/axiom/optimizer/function/predicate/greater_than_or_equal_to.rb +55 -0
- data/lib/axiom/optimizer/function/predicate/inclusion.rb +43 -0
- data/lib/axiom/optimizer/function/predicate/inequality.rb +44 -0
- data/lib/axiom/optimizer/function/predicate/less_than.rb +55 -0
- data/lib/axiom/optimizer/function/predicate/less_than_or_equal_to.rb +55 -0
- data/lib/axiom/optimizer/function/predicate/match.rb +20 -0
- data/lib/axiom/optimizer/function/predicate/no_match.rb +20 -0
- data/lib/axiom/optimizer/function/string/length.rb +31 -0
- data/lib/axiom/optimizer/function/unary.rb +86 -0
- data/lib/axiom/optimizer/optimizable.rb +60 -0
- data/lib/axiom/optimizer/relation/materialized.rb +40 -0
- data/lib/axiom/optimizer/relation/operation/binary.rb +134 -0
- data/lib/axiom/optimizer/relation/operation/combination.rb +33 -0
- data/lib/axiom/optimizer/relation/operation/deletion.rb +20 -0
- data/lib/axiom/optimizer/relation/operation/insertion.rb +20 -0
- data/lib/axiom/optimizer/relation/operation/limit.rb +141 -0
- data/lib/axiom/optimizer/relation/operation/offset.rb +106 -0
- data/lib/axiom/optimizer/relation/operation/order.rb +85 -0
- data/lib/axiom/optimizer/relation/operation/reverse.rb +85 -0
- data/lib/axiom/optimizer/relation/operation/unary.rb +124 -0
- data/lib/axiom/optimizer/support/predicate_partition.rb +184 -0
- data/lib/axiom/optimizer/version.rb +10 -0
- data/spec/integration/axiom/algebra/difference/optimize_spec.rb +160 -0
- data/spec/integration/axiom/algebra/intersection/optimize_spec.rb +160 -0
- data/spec/integration/axiom/algebra/join/optimize_spec.rb +112 -0
- data/spec/integration/axiom/algebra/product/optimize_spec.rb +178 -0
- data/spec/integration/axiom/algebra/projection/optimize_spec.rb +250 -0
- data/spec/integration/axiom/algebra/rename/optimize_spec.rb +442 -0
- data/spec/integration/axiom/algebra/restriction/optimize_spec.rb +218 -0
- data/spec/integration/axiom/algebra/summarization/optimize_spec.rb +49 -0
- data/spec/integration/axiom/algebra/union/optimize_spec.rb +200 -0
- data/spec/integration/axiom/function/connective/conjunction/optimize_spec.rb +236 -0
- data/spec/integration/axiom/function/connective/disjunction/optimize_spec.rb +237 -0
- data/spec/integration/axiom/function/connective/negation/optimize_spec.rb +43 -0
- data/spec/integration/axiom/function/optimize_spec.rb +30 -0
- data/spec/integration/axiom/function/predicate/equality/optimize_spec.rb +92 -0
- data/spec/integration/axiom/function/predicate/exclusion/optimize_spec.rb +133 -0
- data/spec/integration/axiom/function/predicate/greater_than/optimize_spec.rb +102 -0
- data/spec/integration/axiom/function/predicate/greater_than_or_equal_to/optimize_spec.rb +102 -0
- data/spec/integration/axiom/function/predicate/inclusion/optimize_spec.rb +133 -0
- data/spec/integration/axiom/function/predicate/inequality/optimize_spec.rb +92 -0
- data/spec/integration/axiom/function/predicate/less_than/optimize_spec.rb +102 -0
- data/spec/integration/axiom/function/predicate/less_than_or_equal_to/optimize_spec.rb +102 -0
- data/spec/integration/axiom/relation/empty/optimize_spec.rb +13 -0
- data/spec/integration/axiom/relation/materialized/optimize_spec.rb +29 -0
- data/spec/integration/axiom/relation/operation/limit/optimize_spec.rb +142 -0
- data/spec/integration/axiom/relation/operation/offset/optimize_spec.rb +100 -0
- data/spec/integration/axiom/relation/operation/order/optimize_spec.rb +105 -0
- data/spec/integration/axiom/relation/operation/reverse/optimize_spec.rb +115 -0
- data/spec/integration/axiom/relation/optimize_spec.rb +23 -0
- data/spec/rcov.opts +7 -0
- data/spec/shared/function_connective_binary_optimize_behavior.rb +102 -0
- data/spec/shared/optimize_method_behavior.rb +16 -0
- data/spec/spec_helper.rb +38 -0
- data/spec/support/add_method_missing.rb +15 -0
- data/spec/support/config_alias.rb +3 -0
- data/spec/support/ice_nine_config.rb +6 -0
- data/spec/support/lazy_enumerable.rb +18 -0
- data/spec/unit/axiom/optimizer/algebra/difference/empty_left/optimize_spec.rb +19 -0
- data/spec/unit/axiom/optimizer/algebra/difference/empty_right/optimize_spec.rb +19 -0
- data/spec/unit/axiom/optimizer/algebra/difference/equal_operands/optimize_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/algebra/extension/extensions_spec.rb +31 -0
- data/spec/unit/axiom/optimizer/algebra/extension/order_operand/optimizable_predicate_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/algebra/extension/order_operand/optimize_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/algebra/extension/unoptimized_operand/optimizable_predicate_spec.rb +37 -0
- data/spec/unit/axiom/optimizer/algebra/extension/unoptimized_operand/optimize_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/algebra/intersection/empty_left/optimize_spec.rb +19 -0
- data/spec/unit/axiom/optimizer/algebra/intersection/empty_right/optimize_spec.rb +19 -0
- data/spec/unit/axiom/optimizer/algebra/intersection/equal_operands/optimize_spec.rb +19 -0
- data/spec/unit/axiom/optimizer/algebra/join/disjoint_headers/optimizable_predicate_spec.rb +29 -0
- data/spec/unit/axiom/optimizer/algebra/join/disjoint_headers/optimize_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/algebra/join/equal_headers/optimizable_predicate_spec.rb +29 -0
- data/spec/unit/axiom/optimizer/algebra/join/equal_headers/optimize_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/algebra/join/materialized_left/optimizable_predicate_spec.rb +42 -0
- data/spec/unit/axiom/optimizer/algebra/join/materialized_left/optimize_spec.rb +55 -0
- data/spec/unit/axiom/optimizer/algebra/join/materialized_right/optimizable_predicate_spec.rb +42 -0
- data/spec/unit/axiom/optimizer/algebra/join/materialized_right/optimize_spec.rb +55 -0
- data/spec/unit/axiom/optimizer/algebra/product/table_dee_left/optimizable_predicate_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/algebra/product/table_dee_left/optimize_spec.rb +18 -0
- data/spec/unit/axiom/optimizer/algebra/product/table_dee_right/optimizable_predicate_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/algebra/product/table_dee_right/optimize_spec.rb +18 -0
- data/spec/unit/axiom/optimizer/algebra/projection/empty_operand/optimizable_predicate_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/algebra/projection/empty_operand/optimize_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/algebra/projection/extension_operand/optimizable_predicate_spec.rb +35 -0
- data/spec/unit/axiom/optimizer/algebra/projection/extension_operand/optimize_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/algebra/projection/projection_operand/optimizable_predicate_spec.rb +28 -0
- data/spec/unit/axiom/optimizer/algebra/projection/projection_operand/optimize_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/algebra/projection/union_operand/optimizable_predicate_spec.rb +29 -0
- data/spec/unit/axiom/optimizer/algebra/projection/union_operand/optimize_spec.rb +25 -0
- data/spec/unit/axiom/optimizer/algebra/projection/unoptimized_operand/optimizable_predicate_spec.rb +28 -0
- data/spec/unit/axiom/optimizer/algebra/projection/unoptimized_operand/optimize_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/algebra/rename/aliases_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/algebra/rename/empty_operand/optimizable_predicate_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/algebra/rename/empty_operand/optimize_spec.rb +21 -0
- data/spec/unit/axiom/optimizer/algebra/rename/limit_operand/optimizable_predicate_spec.rb +28 -0
- data/spec/unit/axiom/optimizer/algebra/rename/limit_operand/optimize_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/algebra/rename/offset_operand/optimizable_predicate_spec.rb +28 -0
- data/spec/unit/axiom/optimizer/algebra/rename/offset_operand/optimize_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/algebra/rename/order_operand/optimizable_predicate_spec.rb +28 -0
- data/spec/unit/axiom/optimizer/algebra/rename/order_operand/optimize_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/algebra/rename/projection_operand/optimizable_predicate_spec.rb +43 -0
- data/spec/unit/axiom/optimizer/algebra/rename/projection_operand/optimize_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/algebra/rename/rename_operand/optimizable_predicate_spec.rb +30 -0
- data/spec/unit/axiom/optimizer/algebra/rename/rename_operand/optimize_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/algebra/rename/rename_operand_and_empty_aliases/optimizable_predicate_spec.rb +37 -0
- data/spec/unit/axiom/optimizer/algebra/rename/rename_operand_and_empty_aliases/optimize_spec.rb +18 -0
- data/spec/unit/axiom/optimizer/algebra/rename/restriction_operand/optimizable_predicate_spec.rb +29 -0
- data/spec/unit/axiom/optimizer/algebra/rename/restriction_operand/optimize_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/algebra/rename/reverse_operand/optimizable_predicate_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/algebra/rename/reverse_operand/optimize_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/algebra/rename/set_operand/optimizable_predicate_spec.rb +29 -0
- data/spec/unit/axiom/optimizer/algebra/rename/set_operand/optimize_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/algebra/rename/unoptimized_operand/optimizable_predicate_spec.rb +29 -0
- data/spec/unit/axiom/optimizer/algebra/rename/unoptimized_operand/optimize_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/algebra/restriction/combination_operand/optimizable_predicate_spec.rb +41 -0
- data/spec/unit/axiom/optimizer/algebra/restriction/combination_operand/optimize_spec.rb +35 -0
- data/spec/unit/axiom/optimizer/algebra/restriction/contradiction/optimizable_predicate_spec.rb +46 -0
- data/spec/unit/axiom/optimizer/algebra/restriction/contradiction/optimize_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/algebra/restriction/join_operand/optimizable_predicate_spec.rb +51 -0
- data/spec/unit/axiom/optimizer/algebra/restriction/join_operand/optimize_spec.rb +48 -0
- data/spec/unit/axiom/optimizer/algebra/restriction/order_operand/optimizable_predicate_spec.rb +28 -0
- data/spec/unit/axiom/optimizer/algebra/restriction/order_operand/optimize_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/algebra/restriction/predicate_spec.rb +18 -0
- data/spec/unit/axiom/optimizer/algebra/restriction/product_operand/optimizable_predicate_spec.rb +44 -0
- data/spec/unit/axiom/optimizer/algebra/restriction/product_operand/optimize_spec.rb +48 -0
- data/spec/unit/axiom/optimizer/algebra/restriction/restriction_operand/optimizable_predicate_spec.rb +30 -0
- data/spec/unit/axiom/optimizer/algebra/restriction/restriction_operand/optimize_spec.rb +24 -0
- data/spec/unit/axiom/optimizer/algebra/restriction/set_operand/optimizable_predicate_spec.rb +30 -0
- data/spec/unit/axiom/optimizer/algebra/restriction/set_operand/optimize_spec.rb +24 -0
- data/spec/unit/axiom/optimizer/algebra/restriction/tautology/optimizable_predicate_spec.rb +33 -0
- data/spec/unit/axiom/optimizer/algebra/restriction/tautology/optimize_spec.rb +19 -0
- data/spec/unit/axiom/optimizer/algebra/restriction/unoptimized_operand/optimizable_predicate_spec.rb +44 -0
- data/spec/unit/axiom/optimizer/algebra/restriction/unoptimized_operand/optimize_spec.rb +24 -0
- data/spec/unit/axiom/optimizer/algebra/summarization/empty_operand/class_methods/extension_default_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/algebra/summarization/empty_operand/optimizable_predicate_spec.rb +29 -0
- data/spec/unit/axiom/optimizer/algebra/summarization/empty_operand/optimize_spec.rb +47 -0
- data/spec/unit/axiom/optimizer/algebra/summarization/empty_summarize_per/optimizable_predicate_spec.rb +29 -0
- data/spec/unit/axiom/optimizer/algebra/summarization/empty_summarize_per/optimize_spec.rb +25 -0
- data/spec/unit/axiom/optimizer/algebra/summarization/order_operand/optimizable_predicate_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/algebra/summarization/order_operand/optimize_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/algebra/summarization/summarize_per_spec.rb +29 -0
- data/spec/unit/axiom/optimizer/algebra/summarization/summarizers_spec.rb +31 -0
- data/spec/unit/axiom/optimizer/algebra/summarization/unoptimized_operand/optimizable_predicate_spec.rb +49 -0
- data/spec/unit/axiom/optimizer/algebra/summarization/unoptimized_operand/optimize_spec.rb +30 -0
- data/spec/unit/axiom/optimizer/algebra/union/empty_left/optimize_spec.rb +19 -0
- data/spec/unit/axiom/optimizer/algebra/union/empty_right/optimize_spec.rb +19 -0
- data/spec/unit/axiom/optimizer/algebra/union/equal_operands/optimize_spec.rb +19 -0
- data/spec/unit/axiom/optimizer/class_methods/chain_spec.rb +56 -0
- data/spec/unit/axiom/optimizer/function/binary/constant_operands/optimizable_predicate_spec.rb +36 -0
- data/spec/unit/axiom/optimizer/function/binary/constant_operands/optimize_spec.rb +18 -0
- data/spec/unit/axiom/optimizer/function/binary/left_spec.rb +28 -0
- data/spec/unit/axiom/optimizer/function/binary/right_spec.rb +28 -0
- data/spec/unit/axiom/optimizer/function/binary/unoptimized_operands/optimizable_predicate_spec.rb +37 -0
- data/spec/unit/axiom/optimizer/function/binary/unoptimized_operands/optimize_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/function/class_methods/optimize_functions_spec.rb +26 -0
- data/spec/unit/axiom/optimizer/function/class_methods/optimize_operand_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/function/connective/binary/constant_operands/optimize_spec.rb +16 -0
- data/spec/unit/axiom/optimizer/function/connective/binary/equal_operands/optimizable_predicate_spec.rb +29 -0
- data/spec/unit/axiom/optimizer/function/connective/binary/equal_operands/optimize_spec.rb +19 -0
- data/spec/unit/axiom/optimizer/function/connective/binary/left_spec.rb +16 -0
- data/spec/unit/axiom/optimizer/function/connective/binary/redundant_left/optimizable_predicate_spec.rb +28 -0
- data/spec/unit/axiom/optimizer/function/connective/binary/redundant_left/optimize_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/function/connective/binary/redundant_right/optimizable_predicate_spec.rb +28 -0
- data/spec/unit/axiom/optimizer/function/connective/binary/redundant_right/optimize_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/function/connective/binary/right_spec.rb +16 -0
- data/spec/unit/axiom/optimizer/function/connective/conjunction/contradiction/optimizable_predicate_spec.rb +64 -0
- data/spec/unit/axiom/optimizer/function/connective/conjunction/contradiction/optimize_spec.rb +19 -0
- data/spec/unit/axiom/optimizer/function/connective/conjunction/optimizable_to_exclusion/optimizable_predicate_spec.rb +61 -0
- data/spec/unit/axiom/optimizer/function/connective/conjunction/optimizable_to_exclusion/optimize_spec.rb +76 -0
- data/spec/unit/axiom/optimizer/function/connective/conjunction/tautology_left/optimizable_predicate_spec.rb +29 -0
- data/spec/unit/axiom/optimizer/function/connective/conjunction/tautology_left/optimize_spec.rb +19 -0
- data/spec/unit/axiom/optimizer/function/connective/conjunction/tautology_right/optimizable_predicate_spec.rb +29 -0
- data/spec/unit/axiom/optimizer/function/connective/conjunction/tautology_right/optimize_spec.rb +19 -0
- data/spec/unit/axiom/optimizer/function/connective/disjunction/contradiction_left/optimizable_predicate_spec.rb +29 -0
- data/spec/unit/axiom/optimizer/function/connective/disjunction/contradiction_left/optimize_spec.rb +19 -0
- data/spec/unit/axiom/optimizer/function/connective/disjunction/contradiction_right/optimizable_predicate_spec.rb +29 -0
- data/spec/unit/axiom/optimizer/function/connective/disjunction/contradiction_right/optimize_spec.rb +19 -0
- data/spec/unit/axiom/optimizer/function/connective/disjunction/optimizable_to_inclusion/optimizable_predicate_spec.rb +61 -0
- data/spec/unit/axiom/optimizer/function/connective/disjunction/optimizable_to_inclusion/optimize_spec.rb +76 -0
- data/spec/unit/axiom/optimizer/function/connective/disjunction/tautology/optimizable_predicate_spec.rb +64 -0
- data/spec/unit/axiom/optimizer/function/connective/disjunction/tautology/optimize_spec.rb +19 -0
- data/spec/unit/axiom/optimizer/function/connective/negation/constant_operand/optimize_spec.rb +16 -0
- data/spec/unit/axiom/optimizer/function/connective/negation/invertible_operand/optimizable_predicate_spec.rb +28 -0
- data/spec/unit/axiom/optimizer/function/connective/negation/invertible_operand/optimize_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/function/connective/negation/operand_spec.rb +14 -0
- data/spec/unit/axiom/optimizer/function/predicate/comparable/never_comparable/optimizable_predicate_spec.rb +74 -0
- data/spec/unit/axiom/optimizer/function/predicate/comparable/never_equivalent/optimizable_predicate_spec.rb +74 -0
- data/spec/unit/axiom/optimizer/function/predicate/comparable/normalizable_operands/optimizable_predicate_spec.rb +43 -0
- data/spec/unit/axiom/optimizer/function/predicate/comparable/normalizable_operands/optimize_spec.rb +21 -0
- data/spec/unit/axiom/optimizer/function/predicate/constant_operands/optimize_spec.rb +16 -0
- data/spec/unit/axiom/optimizer/function/predicate/contradiction/optimize_spec.rb +18 -0
- data/spec/unit/axiom/optimizer/function/predicate/enumerable/class_methods/sort_by_value_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/function/predicate/enumerable/empty_right/optimizable_predicate_spec.rb +78 -0
- data/spec/unit/axiom/optimizer/function/predicate/enumerable/one_right/optimizable_predicate_spec.rb +78 -0
- data/spec/unit/axiom/optimizer/function/predicate/enumerable/unoptimized_operands/optimizable_predicate_spec.rb +51 -0
- data/spec/unit/axiom/optimizer/function/predicate/enumerable/unoptimized_operands/optimize_spec.rb +66 -0
- data/spec/unit/axiom/optimizer/function/predicate/equality/tautology/optimizable_predicate_spec.rb +29 -0
- data/spec/unit/axiom/optimizer/function/predicate/exclusion/empty_right/optimize_spec.rb +45 -0
- data/spec/unit/axiom/optimizer/function/predicate/exclusion/one_right/optimize_spec.rb +65 -0
- data/spec/unit/axiom/optimizer/function/predicate/greater_than/contradiction/optimizable_predicate_spec.rb +43 -0
- data/spec/unit/axiom/optimizer/function/predicate/greater_than/tautology/optimizable_predicate_spec.rb +28 -0
- data/spec/unit/axiom/optimizer/function/predicate/greater_than_or_equal_to/contradiction/optimizable_predicate_spec.rb +43 -0
- data/spec/unit/axiom/optimizer/function/predicate/greater_than_or_equal_to/tautology/optimizable_predicate_spec.rb +43 -0
- data/spec/unit/axiom/optimizer/function/predicate/inclusion/empty_right/optimize_spec.rb +45 -0
- data/spec/unit/axiom/optimizer/function/predicate/inclusion/one_right/optimize_spec.rb +66 -0
- data/spec/unit/axiom/optimizer/function/predicate/inequality/contradiction/optimizable_predicate_spec.rb +29 -0
- data/spec/unit/axiom/optimizer/function/predicate/less_than/contradiction/optimizable_predicate_spec.rb +43 -0
- data/spec/unit/axiom/optimizer/function/predicate/less_than/tautology/optimizable_predicate_spec.rb +28 -0
- data/spec/unit/axiom/optimizer/function/predicate/less_than_or_equal_to/contradiction/optimizable_predicate_spec.rb +43 -0
- data/spec/unit/axiom/optimizer/function/predicate/less_than_or_equal_to/tautology/optimizable_predicate_spec.rb +43 -0
- data/spec/unit/axiom/optimizer/function/predicate/tautology/optimize_spec.rb +18 -0
- data/spec/unit/axiom/optimizer/function/unary/constant_operand/optimizable_predicate_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/function/unary/constant_operand/optimize_spec.rb +18 -0
- data/spec/unit/axiom/optimizer/function/unary/operand_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/function/unary/unoptimized_operand/optimizable_predicate_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/function/unary/unoptimized_operand/optimize_spec.rb +18 -0
- data/spec/unit/axiom/optimizer/function/util/class_methods/attribute_spec.rb +21 -0
- data/spec/unit/axiom/optimizer/function/util/class_methods/constant_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/function/util/class_methods/max_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/function/util/class_methods/min_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/operation_spec.rb +13 -0
- data/spec/unit/axiom/optimizer/optimizable/class_methods/optimizer_spec.rb +34 -0
- data/spec/unit/axiom/optimizer/optimizable/optimize_spec.rb +38 -0
- data/spec/unit/axiom/optimizer/optimizable_predicate_spec.rb +17 -0
- data/spec/unit/axiom/optimizer/optimize_spec.rb +17 -0
- data/spec/unit/axiom/optimizer/predicate_partition/left_spec.rb +149 -0
- data/spec/unit/axiom/optimizer/predicate_partition/remainder_spec.rb +149 -0
- data/spec/unit/axiom/optimizer/predicate_partition/right_spec.rb +149 -0
- data/spec/unit/axiom/optimizer/relation/materialized/empty_operand/optimizable_predicate_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/relation/materialized/empty_operand/optimize_spec.rb +21 -0
- data/spec/unit/axiom/optimizer/relation/operation/binary/empty_left/optimizable_predicate_spec.rb +28 -0
- data/spec/unit/axiom/optimizer/relation/operation/binary/empty_right/optimizable_predicate_spec.rb +28 -0
- data/spec/unit/axiom/optimizer/relation/operation/binary/equal_operands/optimizable_predicate_spec.rb +31 -0
- data/spec/unit/axiom/optimizer/relation/operation/binary/left_spec.rb +15 -0
- data/spec/unit/axiom/optimizer/relation/operation/binary/materialized_operands/optimizable_predicate_spec.rb +37 -0
- data/spec/unit/axiom/optimizer/relation/operation/binary/materialized_operands/optimize_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/relation/operation/binary/order_left/optimizable_predicate_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/relation/operation/binary/order_left/optimize_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/relation/operation/binary/order_right/optimizable_predicate_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/relation/operation/binary/order_right/optimize_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/relation/operation/binary/right_spec.rb +15 -0
- data/spec/unit/axiom/optimizer/relation/operation/binary/unoptimized_operands/optimizable_predicate_spec.rb +40 -0
- data/spec/unit/axiom/optimizer/relation/operation/binary/unoptimized_operands/optimize_spec.rb +24 -0
- data/spec/unit/axiom/optimizer/relation/operation/combination/optimize_spec.rb +18 -0
- data/spec/unit/axiom/optimizer/relation/operation/limit/equal_limit_operand/optimizable_predicate_spec.rb +33 -0
- data/spec/unit/axiom/optimizer/relation/operation/limit/equal_limit_operand/optimize_spec.rb +18 -0
- data/spec/unit/axiom/optimizer/relation/operation/limit/limit_operand/optimizable_predicate_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/relation/operation/limit/limit_operand/optimize_spec.rb +35 -0
- data/spec/unit/axiom/optimizer/relation/operation/limit/unoptimized_operand/optimizable_predicate_spec.rb +28 -0
- data/spec/unit/axiom/optimizer/relation/operation/limit/unoptimized_operand/optimize_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/relation/operation/limit/zero_limit/optimizable_predicate_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/relation/operation/limit/zero_limit/optimize_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/relation/operation/offset/offset_operand/optimizable_predicate_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/relation/operation/offset/offset_operand/optimize_spec.rb +21 -0
- data/spec/unit/axiom/optimizer/relation/operation/offset/unoptimized_operand/optimizable_predicate_spec.rb +28 -0
- data/spec/unit/axiom/optimizer/relation/operation/offset/unoptimized_operand/optimize_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/relation/operation/offset/zero_offset/optimizable_predicate_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/relation/operation/offset/zero_offset/optimize_spec.rb +17 -0
- data/spec/unit/axiom/optimizer/relation/operation/order/one_limit_operand/optimizable_predicate_spec.rb +33 -0
- data/spec/unit/axiom/optimizer/relation/operation/order/one_limit_operand/optimize_spec.rb +18 -0
- data/spec/unit/axiom/optimizer/relation/operation/order/order_operand/optimizable_predicate_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/relation/operation/order/order_operand/optimize_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/relation/operation/order/unoptimized_operand/optimizable_predicate_spec.rb +28 -0
- data/spec/unit/axiom/optimizer/relation/operation/order/unoptimized_operand/optimize_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/relation/operation/reverse/order_operand/optimizable_predicate_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/relation/operation/reverse/order_operand/optimize_spec.rb +22 -0
- data/spec/unit/axiom/optimizer/relation/operation/reverse/reverse_operand/optimizable_predicate_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/relation/operation/reverse/reverse_operand/optimize_spec.rb +19 -0
- data/spec/unit/axiom/optimizer/relation/operation/reverse/unoptimized_operand/optimizable_predicate_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/relation/operation/reverse/unoptimized_operand/optimize_spec.rb +24 -0
- data/spec/unit/axiom/optimizer/relation/operation/unary/empty_operand/optimizable_predicate_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/relation/operation/unary/empty_operand/optimize_spec.rb +17 -0
- data/spec/unit/axiom/optimizer/relation/operation/unary/header_spec.rb +15 -0
- data/spec/unit/axiom/optimizer/relation/operation/unary/materialized_operand/optimizable_predicate_spec.rb +23 -0
- data/spec/unit/axiom/optimizer/relation/operation/unary/materialized_operand/optimize_spec.rb +20 -0
- data/spec/unit/axiom/optimizer/relation/operation/unary/operand_spec.rb +16 -0
- data/spec/unit/axiom/optimizer/relation/operation/unary/order_operand/optimizable_predicate_spec.rb +28 -0
- data/spec/unit/axiom/optimizer/relation/operation/unary/order_operand/optimize_spec.rb +27 -0
- data/spec/unit/axiom/optimizer/relation/operation/unary/unchanged_header/optimizable_predicate_spec.rb +24 -0
- data/spec/unit/axiom/optimizer/relation/operation/unary/unchanged_header/optimize_spec.rb +14 -0
- metadata +697 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 36b3b6f4025783f94a149341825fa522193892e3
|
4
|
+
data.tar.gz: 3bf6368e2943f1d4fb0a8640a71a6a857b48fe67
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2d78a4f99334b80b65fff5cfef9ae4a050b6156a6d81d4508bc0b6ae211423f759eaecd7dd78c7f47eb2d2369f4c65af2e7ab0e94d2002a3a7bef7f9719159b7
|
7
|
+
data.tar.gz: b131979736952d33d94e473730e7066e33711837922342f7124a20128560dc58e05cd56ef2432d2706bba594be7514f8cc7b1a2fe1e2a5e76bf0fcdda7f505c0
|
data/.gemtest
ADDED
File without changes
|
data/.gitignore
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
## MAC OS
|
2
|
+
.DS_Store
|
3
|
+
|
4
|
+
## TEXTMATE
|
5
|
+
*.tmproj
|
6
|
+
tmtags
|
7
|
+
|
8
|
+
## EMACS
|
9
|
+
*~
|
10
|
+
\#*
|
11
|
+
.\#*
|
12
|
+
|
13
|
+
## VIM
|
14
|
+
*.swp
|
15
|
+
|
16
|
+
## Rubinius
|
17
|
+
*.rbc
|
18
|
+
.rbx
|
19
|
+
|
20
|
+
## PROJECT::GENERAL
|
21
|
+
*.gem
|
22
|
+
coverage
|
23
|
+
profiling
|
24
|
+
turbulence
|
25
|
+
rdoc
|
26
|
+
pkg
|
27
|
+
tmp
|
28
|
+
doc
|
29
|
+
log
|
30
|
+
.yardoc
|
31
|
+
measurements
|
32
|
+
|
33
|
+
## BUNDLER
|
34
|
+
.bundle
|
35
|
+
Gemfile.lock
|
36
|
+
|
37
|
+
## PROJECT::SPECIFIC
|
data/.rspec
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use @$(basename `pwd`) --create
|
data/.travis.yml
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
language: ruby
|
2
|
+
before_install: gem install bundler
|
3
|
+
bundler_args: --without yard guard benchmarks
|
4
|
+
script: "bundle exec rake ci"
|
5
|
+
rvm:
|
6
|
+
- ree
|
7
|
+
- 1.8.7
|
8
|
+
- 1.9.2
|
9
|
+
- 1.9.3
|
10
|
+
- 2.0.0
|
11
|
+
- ruby-head
|
12
|
+
- rbx-18mode
|
13
|
+
- rbx-19mode
|
14
|
+
- jruby-18mode
|
15
|
+
notifications:
|
16
|
+
irc:
|
17
|
+
channels:
|
18
|
+
- "irc.freenode.org#datamapper"
|
19
|
+
on_success: never
|
20
|
+
on_failure: change
|
21
|
+
email:
|
22
|
+
recipients:
|
23
|
+
- dan.kubb@gmail.com
|
24
|
+
on_success: never
|
25
|
+
on_failure: change
|
26
|
+
matrix:
|
27
|
+
include:
|
28
|
+
- rvm: jruby-19mode
|
29
|
+
env: JRUBY_OPTS="$JRUBY_OPTS --debug"
|
30
|
+
- rvm: jruby-head
|
31
|
+
env: JRUBY_OPTS="$JRUBY_OPTS --debug"
|
32
|
+
allow_failures:
|
33
|
+
# mutant fails
|
34
|
+
- rvm: 1.9.3
|
35
|
+
- rvm: rbx-19mode
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
Contributing
|
2
|
+
------------
|
3
|
+
|
4
|
+
* If you want your code merged into the mainline, please discuss the proposed changes with me before doing any work on it. This library is still in early development, and the direction it is going may not always be clear. Some features may not be appropriate yet, may need to be deferred until later when the foundation for them is laid, or may be more applicable in a plugin.
|
5
|
+
* Fork the project.
|
6
|
+
* Make your feature addition or bug fix.
|
7
|
+
* Follow this [style guide](https://github.com/dkubb/styleguide).
|
8
|
+
* Add specs for it. This is important so I don't break it in a future version unintentionally. Tests must cover all branches within the code, and code must be fully covered.
|
9
|
+
* Commit, do not mess with Rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
10
|
+
* Run "rake ci". This must pass and not show any regressions in the metrics for the code to be merged.
|
11
|
+
* Send me a pull request. Bonus points for topic branches.
|
data/Gemfile
ADDED
data/Gemfile.devtools
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
group :development do
|
4
|
+
gem 'rake', '~> 10.0.4'
|
5
|
+
gem 'rspec', '~> 2.13.0'
|
6
|
+
gem 'yard', '~> 0.8.5.2'
|
7
|
+
end
|
8
|
+
|
9
|
+
group :yard do
|
10
|
+
gem 'kramdown', '~> 1.0.1'
|
11
|
+
end
|
12
|
+
|
13
|
+
group :guard do
|
14
|
+
gem 'guard', '~> 1.7.0'
|
15
|
+
gem 'guard-bundler', '~> 1.0.0'
|
16
|
+
gem 'guard-rspec', '~> 2.5.2'
|
17
|
+
|
18
|
+
# file system change event handling
|
19
|
+
gem 'listen', '~> 0.7.3'
|
20
|
+
gem 'rb-fchange', '~> 0.0.6', :require => false
|
21
|
+
gem 'rb-fsevent', '~> 0.9.3', :require => false
|
22
|
+
gem 'rb-inotify', '~> 0.9.0', :require => false
|
23
|
+
|
24
|
+
# notification handling
|
25
|
+
gem 'libnotify', '~> 0.8.0', :require => false
|
26
|
+
gem 'rb-notifu', '~> 0.0.4', :require => false
|
27
|
+
gem 'terminal-notifier-guard', '~> 1.5.3', :require => false
|
28
|
+
end
|
29
|
+
|
30
|
+
group :metrics do
|
31
|
+
gem 'backports', '~> 3.3', '>= 3.3.0'
|
32
|
+
gem 'coveralls', '~> 0.6.4'
|
33
|
+
gem 'flay', '~> 2.1.0'
|
34
|
+
gem 'flog', '~> 3.2.3'
|
35
|
+
gem 'reek', '~> 1.3.1', :git => 'https://github.com/troessner/reek.git'
|
36
|
+
gem 'simplecov', '~> 0.7.1'
|
37
|
+
gem 'yardstick', '~> 0.9.5'
|
38
|
+
gem 'yard-spellcheck', '~> 0.1.5'
|
39
|
+
|
40
|
+
platforms :mri_19, :rbx do
|
41
|
+
gem 'mutant', '~> 0.2.20'
|
42
|
+
end
|
43
|
+
|
44
|
+
platforms :rbx do
|
45
|
+
gem 'pelusa', '~> 0.2.2'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
group :benchmarks do
|
50
|
+
gem 'rbench', '~> 0.2.3'
|
51
|
+
end
|
52
|
+
|
53
|
+
platform :jruby do
|
54
|
+
group :jruby do
|
55
|
+
gem 'jruby-openssl', '~> 0.8.5'
|
56
|
+
end
|
57
|
+
end
|
data/Guardfile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
guard :bundler do
|
4
|
+
watch('Gemfile')
|
5
|
+
end
|
6
|
+
|
7
|
+
guard :rspec, :cli => File.read('.rspec').split.join(' '), :keep_failed => false do
|
8
|
+
# run all specs if configuration is modified
|
9
|
+
watch('Guardfile') { 'spec' }
|
10
|
+
watch('Gemfile.lock') { 'spec' }
|
11
|
+
watch('spec/spec_helper.rb') { 'spec' }
|
12
|
+
|
13
|
+
# run all specs if supporting files files are modified
|
14
|
+
watch(%r{\Aspec/(?:lib|support|shared)/.+\.rb\z}) { 'spec' }
|
15
|
+
|
16
|
+
# run unit specs if associated lib code is modified
|
17
|
+
watch(%r{\Alib/(.+)\.rb\z}) { |m| Dir["spec/unit/#{m[1]}"] }
|
18
|
+
watch(%r{\Alib/(.+)/support/(.+)\.rb\z}) { |m| Dir["spec/unit/#{m[1]}/#{m[2]}"] }
|
19
|
+
watch("lib/#{File.basename(File.expand_path('../', __FILE__))}.rb") { 'spec' }
|
20
|
+
|
21
|
+
# run a spec if it is modified
|
22
|
+
watch(%r{\Aspec/(?:unit|integration)/.+_spec\.rb\z})
|
23
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011-2013 Dan Kubb
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
axiom-optimizer
|
2
|
+
===============
|
3
|
+
|
4
|
+
Relational algebra optimizer
|
5
|
+
|
6
|
+
[![Gem Version](https://badge.fury.io/rb/axiom-optimizer.png)][gem]
|
7
|
+
[![Build Status](https://secure.travis-ci.org/dkubb/axiom-optimizer.png?branch=master)][travis]
|
8
|
+
[![Dependency Status](https://gemnasium.com/dkubb/axiom-optimizer.png)][gemnasium]
|
9
|
+
[![Code Climate](https://codeclimate.com/github/dkubb/axiom-optimizer.png)][codeclimate]
|
10
|
+
[![Coverage Status](https://coveralls.io/repos/dkubb/axiom-optimizer/badge.png?branch=master)][coveralls]
|
11
|
+
|
12
|
+
[gem]: https://rubygems.org/gems/axiom-optimizer
|
13
|
+
[travis]: https://travis-ci.org/dkubb/axiom-optimizer
|
14
|
+
[gemnasium]: https://gemnasium.com/dkubb/axiom-optimizer
|
15
|
+
[codeclimate]: https://codeclimate.com/github/dkubb/axiom-optimizer
|
16
|
+
[coveralls]: https://coveralls.io/r/dkubb/axiom-optimizer
|
17
|
+
|
18
|
+
Installation
|
19
|
+
------------
|
20
|
+
|
21
|
+
With Rubygems:
|
22
|
+
|
23
|
+
```bash
|
24
|
+
$ gem install axiom-optimizer
|
25
|
+
$ irb -rubygems
|
26
|
+
>> require 'axiom-optimizer'
|
27
|
+
=> true
|
28
|
+
```
|
29
|
+
|
30
|
+
With git and local working copy:
|
31
|
+
|
32
|
+
```bash
|
33
|
+
$ git clone git://github.com/dkubb/axiom-optimizer.git
|
34
|
+
$ cd axiom-optimizer
|
35
|
+
$ rake install
|
36
|
+
$ irb -rubygems
|
37
|
+
>> require 'axiom-optimizer'
|
38
|
+
=> true
|
39
|
+
```
|
40
|
+
|
41
|
+
Usage
|
42
|
+
-----
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
# optimize a relation
|
46
|
+
new_relation = relation.optimize
|
47
|
+
new_relation = relation.optimize(optimizer)
|
48
|
+
|
49
|
+
# optimize a scalar function
|
50
|
+
new_function = function.optimize
|
51
|
+
new_function = function.optimize(optimizer)
|
52
|
+
|
53
|
+
# optimize an aggregate function
|
54
|
+
new_aggregate = function.aggregate
|
55
|
+
new_aggregate = function.aggregate(optimizer)
|
56
|
+
```
|
57
|
+
|
58
|
+
Description
|
59
|
+
-----------
|
60
|
+
|
61
|
+
The purpose of this gem is to provide a simple API that can be used to optimize a [axiom](https://github.com/dkubb/axiom) relation, scalar or aggregate function. An optional optimizer can be passed in to the #optimize method and return an equivalent but simplified version of the object.
|
62
|
+
|
63
|
+
One of the primary benefits of Relational Algebra is that it's based on logic, and the rules for simplifying logic are well known and studied. An optimizer can pass through user-generated objects and typically find ways to simplify or organize them in a way that will be more efficient when the operation is executed.
|
64
|
+
|
65
|
+
The goal is not to replace the advanced optimizers that are inside most databases and datastores, but to augment it with some simple optimizations that make the user provided query easier for the datastore to accept. On the ruby side we have knowledge about intent and can perform semantic optimization that the datastore otherwise would not be able to perform. In many cases we have richer constraints and data than many datastores and we can use that information to simplify and possibly short-circuit queries that could otherwise never return valid results.
|
66
|
+
|
67
|
+
With the ability to provide custom optimizers we can even target output to a structure optimized for specific datastores. All operations in relational algebra can be transformed into other equivalent operations, ones that are more efficient for the target datastore to execute. The built-in optimizers included in this gem are only a starting point; the intention is to expand them as well as help others create custom optimizers that are optimized for each datastore.
|
68
|
+
|
69
|
+
Design
|
70
|
+
------
|
71
|
+
|
72
|
+
The contract for an optimizer instance is simple:
|
73
|
+
|
74
|
+
1. it must respond to #call, and accept an optimizable object as it's only argument
|
75
|
+
2. it must return an equivalent object
|
76
|
+
3. it must return the exact object when it cannot perform further optimizations
|
77
|
+
|
78
|
+
The optimizer can perform whatever logic it wishes on the object or any of it's contained objects as far down the tree as it likes as long as the requirements for (2) and (3) are met.
|
79
|
+
|
80
|
+
Inside this gem we have the concept of an optimizer chain. It's a chain of responsibility, which means it's a set of objects chained together to form a pipeline. The object is passed into the head of the pipeline and is either matched and returned by one of the optimizers, or it is already fully optimized and passes through to the end of the chain and is returned as-is. This chain organization has proven to be extremely effective, and it is trivial to re-order or add new optimizers into the middle of the chain as needed. Further work will be made to provide APIs to make this even simpler.
|
81
|
+
|
82
|
+
Here is an example of an optimizer chain for the restriction operator (think WHERE clause in SQL):
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
Axiom::Algebra::Restriction.optimizer = chain(
|
86
|
+
Tautology, # does the predicate match everything?
|
87
|
+
Contradiction, # does the predicate match nothing?
|
88
|
+
RestrictionOperand, # does the restriction contain another restriction?
|
89
|
+
SetOperand, # does the restriction contain a set operation?
|
90
|
+
OrderOperand, # does the restriction contain an order?
|
91
|
+
EmptyOperand, # does the restriction contain an empty relation?
|
92
|
+
MaterializedOperand, # does the restriction contain a materialized relation?
|
93
|
+
UnoptimizedOperand # does the restriction contain an unoptimized relation?
|
94
|
+
)
|
95
|
+
```
|
96
|
+
|
97
|
+
The restriction operator enters this pipeline, and tests are made at each stage. If the test returns true, then an optimization is performed. Usually the goal is to eliminate work performed by the system or collapse the tree of operations down into something simpler. More aggressive optimizations are usually checked first because we would like to prune as much of the tree as possible up-front. In this case, the first test checks to see if the restriction matches everything, in which case it's pretty much a no-op, and we can drop it altogether. If that's not the case, we then test to see if it matches nothing, if that's the case then we can return an empty relation. Then we test if it's another restriction, in which case we can "AND" the predicates for both restrictions together and return a single restriction operation. And so on down the list with the first match winning.
|
98
|
+
|
99
|
+
We always perform at least two optimization passes on each object, because once a tree has been simplified there could be further optimizations possible. Essentially we keep passing the objects into their corresponding optimizer chains until it passes through unchanged. This may seem rather expensive, and I guess it is, but optimization is very fast. Also it doesn't appear to affect performance much in practice due to our convention of testing for the most aggressive optimizations first; often it results in something that is completely optimized on the first try.
|
100
|
+
|
101
|
+
Once the optimization passes are finished, and no further optimization is possible, the result of an #optimize call is memoized. Further calls to #optimize will always return the same object.
|
102
|
+
|
103
|
+
Contributing
|
104
|
+
------------
|
105
|
+
|
106
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
|
107
|
+
|
108
|
+
Copyright
|
109
|
+
---------
|
110
|
+
|
111
|
+
Copyright © 2011-2013 Dan Kubb. See LICENSE for details.
|
data/Rakefile
ADDED
data/TODO
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
* Add optimizer for empty right operand to an Insertion
|
2
|
+
* Should factor out the Insertion
|
3
|
+
|
4
|
+
* Add optimizer for empty left operand to a Deletion
|
5
|
+
* Should return an Empty relation, since deleting anything from an empty
|
6
|
+
relation always results in an empty Relation
|
7
|
+
* Add optimizer for empty right operand to a Deletion
|
8
|
+
* Should factor out the Deletion
|
9
|
+
|
10
|
+
* Add an assertion to every #optimize spec that if #optimizable? is true, then
|
11
|
+
the object returned by #optimize must *not* be equivalent. This will ensure
|
12
|
+
that the guard clause in #optimizable? only evaluates to true if the
|
13
|
+
optimization is actually going to return a new object; no point in going
|
14
|
+
through the work of optimizing if it won't result in any change, and it should
|
15
|
+
be possible to test for this before carrying out the work.
|
16
|
+
* Add a shared spec for #optimize and #optimizable?. Note that the current
|
17
|
+
shared spec for #optimize is for the Relation#optimize integration specs
|
18
|
+
(it should probably be renamed to avoid confusion)
|
19
|
+
* Should ensure that when #optimize is being tested #optimizable? should
|
20
|
+
only return true.
|
21
|
+
* Should ensure #optimizable? only returns true if #optimize returns an
|
22
|
+
object that is different (should return equivalent tuples, but have
|
23
|
+
different internal state, otherwise the #optimize step was totally
|
24
|
+
unecessary)
|
25
|
+
|
26
|
+
* Rename the Util.constant? method as Util.value?
|
27
|
+
|
28
|
+
* Pull up Rename rather than pushing it down
|
29
|
+
* Currently a Rename applies to every tuple in a result-set, and
|
30
|
+
doing the rename prematurely means that lots of tuples that would
|
31
|
+
otherwise be filtered out are going to be processed. A better
|
32
|
+
approach should be to push the rename up, dropping renames that
|
33
|
+
are projected away. It should not distribute over Binary ops
|
34
|
+
unless the other side of the binary op has he same aliases.
|
35
|
+
|
36
|
+
* For Binary operations, when the left or right is materialized then
|
37
|
+
change the other relation to use a restriction to filter the records.
|
38
|
+
* This will help optimize the fetching of the underlying records.
|
39
|
+
|
40
|
+
* More optimizations:
|
41
|
+
* Union
|
42
|
+
* A Union of relations with the same base, header, and restrictions should
|
43
|
+
try to combine into a single relation with the restrictions using OR.
|
44
|
+
|
45
|
+
* Intersection
|
46
|
+
* An Intersection of relations with the same base, header, and restrictions
|
47
|
+
should try to combine into a single relation with the restrictions using
|
48
|
+
AND.
|
49
|
+
* Use the Join::RightMaterializedOperand and Join::LeftMaterializedOperand
|
50
|
+
optimizers to simplify Intersection operations
|
51
|
+
|
52
|
+
* Difference
|
53
|
+
* A Difference of relations with the same base and restrictions should
|
54
|
+
try to combine into a single relation with the restrictions using NOT.
|
55
|
+
|
56
|
+
* Summarization
|
57
|
+
* Add OrderSummarizePer for factoring out Order objects inside a Summarization
|
58
|
+
* When there are no aggregate functions, drop the Summarization and
|
59
|
+
return the summarize_per (?)
|
60
|
+
* Use the UnchangedHeader optimizer as a base class
|
61
|
+
* When summarize_per is an Order, the Order can be dropped.
|
62
|
+
|
63
|
+
* Projection
|
64
|
+
* When it contains a Restriction, if the removed attributes are *not*
|
65
|
+
used in the predicate, then move the Restriction to contain the
|
66
|
+
Projection.
|
67
|
+
* When a Projection contains a Restriction, wrap the Projection
|
68
|
+
in the Restriction, projecting away any attributes not used in
|
69
|
+
the restriction. If there are any remaining attributes, then
|
70
|
+
wrap the operation in a Projection removing those attributes.
|
71
|
+
* If all attributes are being used in the Restriction do nothing
|
72
|
+
* When an attribute is renamed, then projected away, the alias should be
|
73
|
+
removed from the rename.
|
74
|
+
* When an attribute is added by a summarization, then projected away, the
|
75
|
+
attribute should be removed from the summarization.
|
76
|
+
* It does not distribute over Intersection or Difference, but see if
|
77
|
+
perhaps an exception can be made if there is a functional dependency
|
78
|
+
between the columns projected away and the one remaining. Then I *think*
|
79
|
+
it might still work, but more research will be needed.
|
80
|
+
* When a Projection contains a Join, wrap the Join with a Projection
|
81
|
+
of all the headers, minus those used in the Join. If there were
|
82
|
+
any used, then wrap the whole operation in a Projection with
|
83
|
+
the remaining attributes.
|
84
|
+
* If all the attributes are used in the Join, do nothing
|
85
|
+
* Try to use the same approach for Product
|
86
|
+
* Test if it's possible to fully distribute projections over
|
87
|
+
joins rather than splitting it up like this.
|
88
|
+
|
89
|
+
* Rename
|
90
|
+
* When wrapping a Summarization or Extension, and renaming the new attribute,
|
91
|
+
it should change the new attribute name, and remove it from the rename.
|
92
|
+
|
93
|
+
* Restriction
|
94
|
+
* Figure out how to reorganize the Restriction predicates so that all
|
95
|
+
similar operations are closer together to allow more efficient
|
96
|
+
optimizations. This would allow optimizations of stuff like this:
|
97
|
+
|
98
|
+
"attr1 = ? OR attr2 = ? OR attr1 = ?"
|
99
|
+
|
100
|
+
Into:
|
101
|
+
|
102
|
+
"attr1 IN(..) OR attr2 = ?"
|
103
|
+
|
104
|
+
* When it has an equality on a unique attribute:
|
105
|
+
* Limit with a limit >= 1 can be factored out
|
106
|
+
* Offset with an offset > 0 can be transformed into an empty
|
107
|
+
relation, since at most there can be only one match.
|
108
|
+
|
109
|
+
* When wrapping a Product and the predicate only contains
|
110
|
+
equality/conjunction between attributes from the left and right
|
111
|
+
operands, then transform into a Join.
|
112
|
+
|
113
|
+
* Order
|
114
|
+
* When the operation is an instance of Order, and the operand is sorted in
|
115
|
+
reversed order, change to a Reverse operation. This should occur after the
|
116
|
+
Order optimization that collapses two Order objects into one; it would be
|
117
|
+
expected that the operand is a Limit or Offset, but it probably isn't
|
118
|
+
necessary to test that.
|
119
|
+
|
120
|
+
* Connective
|
121
|
+
* "attr > ? OR attr > ?" -> "attr > ?", with the least restrictive value
|
122
|
+
* Do the same for >=, <, <=
|
123
|
+
* "attr > ? AND attr > ?" -> "attr > ?", with the most restrictive value
|
124
|
+
* Do the same for >=, <, <=
|
125
|
+
* "attr > 5 OR attr == 5" -> "attr >= 5"
|
126
|
+
* "attr < 5 OR attr == 5" -> "attr <= 5"
|
127
|
+
* "attr" = "string" AND "attr" =~ /string/ -> "attr" = "string"
|
128
|
+
* If the regexp matches the constant, then it should be
|
129
|
+
optimized down to a constant match. If it does not match
|
130
|
+
then it should be optimized to a Contradiction.
|
131
|
+
* Constant folding, eg:
|
132
|
+
"attr1 > attr2 AND attr1 = 5" -> "5 > attr2 AND attr1 = 5"
|
133
|
+
* This will probably only work across Conjunctions.
|
134
|
+
* "attr > 5 AND attr = 6" -> "attr = 6", because attr must be
|
135
|
+
equal to 6. this will probably be related to constant folding;
|
136
|
+
the first expression will become 6 > 5, which evaluates to a
|
137
|
+
Tautology, then the expression is a Tautology AND attr = 6,
|
138
|
+
which simplifies down to attr = 6.
|
139
|
+
* "attr < 5 AND attr = 6" -> "Contradiction", because attr must be equal to
|
140
|
+
6, and 6 < 5 evaluates to a Contradiction. A Contradiction AND attr = 6
|
141
|
+
simplifies down to a Contradiction.
|
142
|
+
|
143
|
+
* Inclusion/Exclusion
|
144
|
+
* When the enumerable is a contiguous sequence transform it into a Range
|