veritas-optimizer 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +4 -3
- data/Gemfile +17 -15
- data/Guardfile +0 -4
- data/{README.rdoc → README.md} +77 -44
- data/Rakefile +2 -2
- data/TODO +0 -9
- data/config/flay.yml +2 -2
- data/config/site.reek +6 -1
- data/lib/veritas/optimizer/algebra/difference.rb +2 -1
- data/lib/veritas/optimizer/algebra/extension.rb +6 -2
- data/lib/veritas/optimizer/algebra/join.rb +5 -5
- data/lib/veritas/optimizer/algebra/product.rb +2 -2
- data/lib/veritas/optimizer/algebra/projection.rb +3 -3
- data/lib/veritas/optimizer/algebra/rename.rb +9 -11
- data/lib/veritas/optimizer/algebra/restriction.rb +7 -6
- data/lib/veritas/optimizer/algebra/summarization.rb +14 -5
- data/lib/veritas/optimizer/function/binary.rb +2 -2
- data/lib/veritas/optimizer/function/connective/conjunction.rb +1 -2
- data/lib/veritas/optimizer/function/connective/disjunction.rb +1 -2
- data/lib/veritas/optimizer/function/predicate/comparable.rb +6 -6
- data/lib/veritas/optimizer/function/predicate/enumerable.rb +4 -4
- data/lib/veritas/optimizer/function/predicate/exclusion.rb +1 -1
- data/lib/veritas/optimizer/function/predicate/inclusion.rb +1 -1
- data/lib/veritas/optimizer/function/unary.rb +1 -1
- data/lib/veritas/optimizer/function.rb +5 -5
- data/lib/veritas/optimizer/relation/materialized.rb +2 -1
- data/lib/veritas/optimizer/relation/operation/combination.rb +2 -1
- data/lib/veritas/optimizer/relation/operation/limit.rb +4 -3
- data/lib/veritas/optimizer/relation/operation/offset.rb +2 -2
- data/lib/veritas/optimizer/relation/operation/order.rb +2 -4
- data/lib/veritas/optimizer/relation/operation/reverse.rb +2 -3
- data/lib/veritas/optimizer/relation/operation/unary.rb +0 -1
- data/lib/veritas/optimizer/version.rb +1 -1
- data/spec/integration/veritas/relation/materialized/optimize_spec.rb +0 -10
- data/spec/shared/optimize_method_behavior.rb +2 -2
- data/spec/unit/veritas/optimizer/algebra/difference/equal_operands/optimize_spec.rb +2 -0
- data/spec/unit/veritas/optimizer/algebra/projection/empty_operand/optimize_spec.rb +2 -0
- data/spec/unit/veritas/optimizer/algebra/rename/empty_operand/optimize_spec.rb +2 -0
- data/spec/unit/veritas/optimizer/algebra/restriction/contradiction/optimize_spec.rb +2 -0
- data/spec/unit/veritas/optimizer/algebra/summarization/empty_summarize_per/optimize_spec.rb +2 -0
- data/spec/unit/veritas/optimizer/algebra/summarization/unoptimized_operand/optimize_spec.rb +1 -1
- data/spec/unit/veritas/optimizer/relation/materialized/empty_operand/optimize_spec.rb +2 -0
- data/spec/unit/veritas/optimizer/relation/operation/combination/optimize_spec.rb +2 -0
- data/spec/unit/veritas/optimizer/relation/operation/limit/zero_limit/optimize_spec.rb +2 -0
- data/veritas-optimizer.gemspec +15 -15
- metadata +34 -34
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
source :rubygems
|
4
4
|
|
5
|
-
gem 'veritas', '~> 0.0.
|
5
|
+
gem 'veritas', '~> 0.0.6', :git => 'git://github.com/dkubb/veritas.git'
|
6
6
|
|
7
7
|
group :development do
|
8
8
|
gem 'backports', '~> 2.3.0'
|
@@ -13,10 +13,9 @@ group :development do
|
|
13
13
|
end
|
14
14
|
|
15
15
|
group :guard do
|
16
|
-
gem 'guard', '~> 0.
|
16
|
+
gem 'guard', '~> 0.7.0'
|
17
17
|
gem 'guard-bundler', '~> 0.1.3'
|
18
|
-
gem 'guard-
|
19
|
-
gem 'guard-rspec', '~> 0.4.0'
|
18
|
+
gem 'guard-rspec', '~> 0.4.5'
|
20
19
|
end
|
21
20
|
|
22
21
|
platform :jruby do
|
@@ -27,16 +26,19 @@ end
|
|
27
26
|
|
28
27
|
platforms :mri_18 do
|
29
28
|
group :metrics do
|
30
|
-
gem '
|
31
|
-
gem '
|
32
|
-
gem '
|
33
|
-
gem '
|
34
|
-
gem '
|
35
|
-
gem '
|
36
|
-
gem '
|
37
|
-
gem '
|
38
|
-
gem '
|
39
|
-
gem '
|
40
|
-
gem '
|
29
|
+
gem 'arrayfields', '~> 4.7.4'
|
30
|
+
gem 'fattr', '~> 2.2.0'
|
31
|
+
gem 'flay', '~> 1.4.2'
|
32
|
+
gem 'flog', '~> 2.5.3'
|
33
|
+
gem 'heckle', '~> 1.4.3'
|
34
|
+
gem 'json', '~> 1.6.1'
|
35
|
+
gem 'map', '~> 4.4.0'
|
36
|
+
gem 'metric_fu', '~> 2.1.1'
|
37
|
+
gem 'mspec', '~> 1.5.17'
|
38
|
+
gem 'rcov', '~> 0.9.9'
|
39
|
+
gem 'reek', '~> 1.2.8', :git => 'git://github.com/dkubb/reek.git'
|
40
|
+
gem 'roodi', '~> 2.1.0'
|
41
|
+
gem 'ruby2ruby', '= 1.2.2'
|
42
|
+
gem 'yardstick', '~> 0.4.0'
|
41
43
|
end
|
42
44
|
end
|
data/Guardfile
CHANGED
data/{README.rdoc → README.md}
RENAMED
@@ -1,26 +1,65 @@
|
|
1
|
-
|
1
|
+
# Veritas Optimizer
|
2
2
|
|
3
3
|
Relational algebra optimizer
|
4
4
|
|
5
|
-
|
5
|
+
[![Build Status](https://secure.travis-ci.org/dkubb/veritas-optimizer.png)](http://travis-ci.org/dkubb/veritas-optimizer)
|
6
6
|
|
7
|
-
|
7
|
+
## Installation
|
8
8
|
|
9
|
-
|
10
|
-
new_relation = relation.optimize
|
11
|
-
new_relation = relation.optimize(optimizer)
|
9
|
+
With Rubygems:
|
12
10
|
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
```bash
|
12
|
+
$ gem install veritas-optimizer
|
13
|
+
$ irb -rubygems
|
14
|
+
>> require 'veritas-optimizer'
|
15
|
+
=> true
|
16
|
+
```
|
16
17
|
|
17
|
-
|
18
|
-
new_aggregate = function.aggregate
|
19
|
-
new_aggregate = function.aggregate(optimizer)
|
18
|
+
With git and local working copy:
|
20
19
|
|
21
|
-
|
20
|
+
```bash
|
21
|
+
$ git clone git://github.com/dkubb/veritas-optimizer.git
|
22
|
+
$ cd veritas-optimizer
|
23
|
+
$ rake install
|
24
|
+
$ irb -rubygems
|
25
|
+
>> require 'veritas-optimizer'
|
26
|
+
=> true
|
27
|
+
```
|
22
28
|
|
23
|
-
|
29
|
+
NOTE: This gem works best with ruby 1.9, however if you are using ruby 1.8 you must also install [backports](https://rubygems.org/gems/backports), then require backports and backports/basic_object, eg:
|
30
|
+
|
31
|
+
```bash
|
32
|
+
$ ruby -e 'puts RUBY_VERSION'
|
33
|
+
=> 1.8.7
|
34
|
+
$ gem install backports
|
35
|
+
$ irb -rubygems
|
36
|
+
>> require 'backports'
|
37
|
+
=> true
|
38
|
+
>> require 'backports/basic_object'
|
39
|
+
=> true
|
40
|
+
>> require 'veritas-optimizer' # assuming it was installed by one of the two methods above
|
41
|
+
=> true
|
42
|
+
```
|
43
|
+
|
44
|
+
## Usage
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
# optimize a relation
|
48
|
+
new_relation = relation.optimize
|
49
|
+
new_relation = relation.optimize(optimizer)
|
50
|
+
|
51
|
+
# optimize a scalar function
|
52
|
+
new_function = function.optimize
|
53
|
+
new_function = function.optimize(optimizer)
|
54
|
+
|
55
|
+
# optimize an aggregate function
|
56
|
+
new_aggregate = function.aggregate
|
57
|
+
new_aggregate = function.aggregate(optimizer)
|
58
|
+
```
|
59
|
+
|
60
|
+
## Description
|
61
|
+
|
62
|
+
The purpose of this gem is to provide a simple API that can be used to optimize a [veritas](https://github.com/dkubb/veritas) 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.
|
24
63
|
|
25
64
|
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.
|
26
65
|
|
@@ -28,30 +67,32 @@ The goal is not to replace the advanced optimizers that are inside most database
|
|
28
67
|
|
29
68
|
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.
|
30
69
|
|
31
|
-
|
70
|
+
## Design
|
32
71
|
|
33
72
|
The contract for an optimizer instance is simple:
|
34
73
|
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
38
77
|
|
39
|
-
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 (
|
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.
|
40
79
|
|
41
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.
|
42
81
|
|
43
82
|
Here is an example of an optimizer chain for the restriction operator (think WHERE clause in SQL):
|
44
83
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
84
|
+
```ruby
|
85
|
+
Veritas::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
|
+
```
|
55
96
|
|
56
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.
|
57
98
|
|
@@ -59,26 +100,18 @@ We always perform at least two optimization passes on each object, because once
|
|
59
100
|
|
60
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.
|
61
102
|
|
62
|
-
|
103
|
+
## Note on Patches/Pull Requests
|
63
104
|
|
64
|
-
* If you want your code merged into the mainline, please discuss
|
65
|
-
the proposed changes with me before doing any work on it. This
|
66
|
-
library is still in early development, and it may not always be
|
67
|
-
clear the direction it is going. Some features may not be appropriate
|
68
|
-
yet, may need to be deferred until later when the foundation for
|
69
|
-
them is laid, or may be more applicable in a plugin.
|
105
|
+
* 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 it may not always be clear the direction it is going. 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.
|
70
106
|
* Fork the project.
|
71
107
|
* Make your feature addition or bug fix.
|
72
|
-
* Follow this
|
73
|
-
* Add specs for it. This is important so I don't break it in a
|
74
|
-
|
75
|
-
within the code, and code must be fully covered.
|
76
|
-
* Commit, do not mess with Rakefile, version, or history.
|
77
|
-
(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)
|
108
|
+
* Follow this [style guide](https://github.com/dkubb/styleguide).
|
109
|
+
* 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.
|
110
|
+
* 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)
|
78
111
|
* Run "rake ci". This must pass and not show any regressions in the
|
79
112
|
metrics for the code to be merged.
|
80
113
|
* Send me a pull request. Bonus points for topic branches.
|
81
114
|
|
82
|
-
|
115
|
+
## Copyright
|
83
116
|
|
84
|
-
Copyright
|
117
|
+
Copyright © 2011 Dan Kubb. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -5,7 +5,7 @@ require 'rake'
|
|
5
5
|
require File.expand_path('../lib/veritas/optimizer/version', __FILE__)
|
6
6
|
|
7
7
|
begin
|
8
|
-
gem('jeweler', '~> 1.6.
|
8
|
+
gem('jeweler', '~> 1.6.4') 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.
|
26
|
+
puts 'Jeweler (or a dependency) not available. Install it with: gem install jeweler -v 1.6.4'
|
27
27
|
end
|
data/TODO
CHANGED
@@ -10,15 +10,6 @@
|
|
10
10
|
change the other relation to use a restriction to filter the records.
|
11
11
|
* This will help optimize the fetching of the underlying records.
|
12
12
|
|
13
|
-
* Convert all the direct Veritas class usage to use the corresponding
|
14
|
-
methods. So for example instead of Algebra::Join.new(left, right) I
|
15
|
-
would want left.join(right).
|
16
|
-
* The reason for this is that as the Relation Gateway is created
|
17
|
-
it will have operands that will not be directly joinable without
|
18
|
-
gateway specific processing. By using the method directly I give the
|
19
|
-
chance for the gateway to step in and perform other work before
|
20
|
-
delegating up to the built-in operators in veritas.
|
21
|
-
|
22
13
|
* More optimizations:
|
23
14
|
* Union
|
24
15
|
* A Union of relations with the same base, header, and restrictions should
|
data/config/flay.yml
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
---
|
2
|
-
threshold:
|
3
|
-
total_score:
|
2
|
+
threshold: 113
|
3
|
+
total_score: 845
|
data/config/site.reek
CHANGED
@@ -46,7 +46,12 @@ UncommunicativeModuleName:
|
|
46
46
|
- !ruby/regexp /[0-9]$/
|
47
47
|
NestedIterators:
|
48
48
|
ignore_iterators: []
|
49
|
-
exclude: [
|
49
|
+
exclude: [
|
50
|
+
# none of these use nested iterators, they use nested blocks only
|
51
|
+
Veritas::Optimizer::Algebra::Extension#wrap_operand,
|
52
|
+
Veritas::Optimizer::Algebra::Summarization#wrap_operand,
|
53
|
+
Veritas::Optimizer::Algebra::Summarization::EmptyOperand#optimize
|
54
|
+
]
|
50
55
|
enabled: true
|
51
56
|
max_allowed_nesting: 1
|
52
57
|
LongMethod:
|
@@ -41,7 +41,11 @@ module Veritas
|
|
41
41
|
#
|
42
42
|
# @api private
|
43
43
|
def wrap_operand(operand = operand.operand)
|
44
|
-
|
44
|
+
operand.extend do |context|
|
45
|
+
extensions.each do |extension|
|
46
|
+
context.add(*extension)
|
47
|
+
end
|
48
|
+
end
|
45
49
|
end
|
46
50
|
|
47
51
|
# Optimize when the operand is an Order
|
@@ -79,7 +83,7 @@ module Veritas
|
|
79
83
|
#
|
80
84
|
# @api private
|
81
85
|
def extensions_optimizable?
|
82
|
-
!extensions.eql?(operation.extensions)
|
86
|
+
! extensions.eql?(operation.extensions)
|
83
87
|
end
|
84
88
|
|
85
89
|
end # class UnoptimizedOperand
|
@@ -49,7 +49,7 @@ module Veritas
|
|
49
49
|
#
|
50
50
|
# @api private
|
51
51
|
def optimize
|
52
|
-
|
52
|
+
left.intersect(right)
|
53
53
|
end
|
54
54
|
|
55
55
|
end # class EqualHeaders
|
@@ -63,7 +63,7 @@ module Veritas
|
|
63
63
|
#
|
64
64
|
# @api private
|
65
65
|
def optimizable?
|
66
|
-
left.materialized? && !right_matching_left?
|
66
|
+
left.materialized? && ! right_matching_left?
|
67
67
|
end
|
68
68
|
|
69
69
|
# Return the join of the left and right with the right restricted
|
@@ -72,7 +72,7 @@ module Veritas
|
|
72
72
|
#
|
73
73
|
# @api private
|
74
74
|
def optimize
|
75
|
-
|
75
|
+
left.join(right.restrict { materialized_predicate })
|
76
76
|
end
|
77
77
|
|
78
78
|
private
|
@@ -107,7 +107,7 @@ module Veritas
|
|
107
107
|
#
|
108
108
|
# @api private
|
109
109
|
def optimizable?
|
110
|
-
right.materialized? && !left_matching_right?
|
110
|
+
right.materialized? && ! left_matching_right?
|
111
111
|
end
|
112
112
|
|
113
113
|
# Return the join of the left and right with the left restricted
|
@@ -116,7 +116,7 @@ module Veritas
|
|
116
116
|
#
|
117
117
|
# @api private
|
118
118
|
def optimize
|
119
|
-
|
119
|
+
left.restrict { materialized_predicate }.join(right)
|
120
120
|
end
|
121
121
|
|
122
122
|
private
|
@@ -17,7 +17,7 @@ module Veritas
|
|
17
17
|
# @api private
|
18
18
|
def optimizable?
|
19
19
|
left = self.left
|
20
|
-
left.header.empty? && !left.kind_of?(Veritas::Relation::Empty)
|
20
|
+
left.header.empty? && ! left.kind_of?(Veritas::Relation::Empty)
|
21
21
|
end
|
22
22
|
|
23
23
|
# A Product with a left TABLE DEE is equivalent to the right operand
|
@@ -41,7 +41,7 @@ module Veritas
|
|
41
41
|
# @api private
|
42
42
|
def optimizable?
|
43
43
|
right = self.right
|
44
|
-
right.header.empty? && !right.kind_of?(Veritas::Relation::Empty)
|
44
|
+
right.header.empty? && ! right.kind_of?(Veritas::Relation::Empty)
|
45
45
|
end
|
46
46
|
|
47
47
|
# A Product with a right TABLE DEE is equivalent to the left operand
|
@@ -15,7 +15,7 @@ module Veritas
|
|
15
15
|
#
|
16
16
|
# @api private
|
17
17
|
def wrap_operand(operand = operand.operand)
|
18
|
-
|
18
|
+
operand.project(header)
|
19
19
|
end
|
20
20
|
|
21
21
|
# Optimize when the operand is a Projection
|
@@ -59,7 +59,7 @@ module Veritas
|
|
59
59
|
#
|
60
60
|
# @api private
|
61
61
|
def optimize
|
62
|
-
|
62
|
+
wrap_left.union(wrap_right)
|
63
63
|
end
|
64
64
|
|
65
65
|
private
|
@@ -107,7 +107,7 @@ module Veritas
|
|
107
107
|
#
|
108
108
|
# @api private
|
109
109
|
def optimize
|
110
|
-
Veritas::Relation::Empty.new(header)
|
110
|
+
Veritas::Relation::Empty.new(header, operation)
|
111
111
|
end
|
112
112
|
|
113
113
|
end # class EmptyOperand
|
@@ -34,7 +34,7 @@ module Veritas
|
|
34
34
|
#
|
35
35
|
# @api private
|
36
36
|
def wrap_operand(operand = operand.operand)
|
37
|
-
|
37
|
+
operand.rename(aliases)
|
38
38
|
end
|
39
39
|
|
40
40
|
# Optimize when the operand is a Rename
|
@@ -112,7 +112,7 @@ module Veritas
|
|
112
112
|
#
|
113
113
|
# @api private
|
114
114
|
def optimize
|
115
|
-
|
115
|
+
wrap_operand.project(header)
|
116
116
|
end
|
117
117
|
|
118
118
|
private
|
@@ -124,7 +124,7 @@ module Veritas
|
|
124
124
|
# @api private
|
125
125
|
def distributive?
|
126
126
|
names = alias_names
|
127
|
-
removed_attributes.all? { |attribute| !names.include?(attribute.name) }
|
127
|
+
removed_attributes.all? { |attribute| ! names.include?(attribute.name) }
|
128
128
|
end
|
129
129
|
|
130
130
|
# Return the aliases as an inverted Hash
|
@@ -166,7 +166,7 @@ module Veritas
|
|
166
166
|
#
|
167
167
|
# @api private
|
168
168
|
def optimize
|
169
|
-
|
169
|
+
wrap_operand.restrict { rename_predicate }
|
170
170
|
end
|
171
171
|
|
172
172
|
private
|
@@ -243,7 +243,7 @@ module Veritas
|
|
243
243
|
#
|
244
244
|
# @api private
|
245
245
|
def optimize
|
246
|
-
|
246
|
+
wrap_operand.reverse
|
247
247
|
end
|
248
248
|
|
249
249
|
end # class ReverseOperand
|
@@ -258,7 +258,7 @@ module Veritas
|
|
258
258
|
#
|
259
259
|
# @api private
|
260
260
|
def optimize
|
261
|
-
|
261
|
+
wrap_operand.sort_by { directions }
|
262
262
|
end
|
263
263
|
|
264
264
|
private
|
@@ -292,8 +292,7 @@ module Veritas
|
|
292
292
|
#
|
293
293
|
# @api private
|
294
294
|
def optimize
|
295
|
-
operand
|
296
|
-
operand.class.new(wrap_operand, operand.limit)
|
295
|
+
wrap_operand.take(operand.limit)
|
297
296
|
end
|
298
297
|
|
299
298
|
end # class LimitOperand
|
@@ -316,8 +315,7 @@ module Veritas
|
|
316
315
|
#
|
317
316
|
# @api private
|
318
317
|
def optimize
|
319
|
-
operand
|
320
|
-
operand.class.new(wrap_operand, operand.offset)
|
318
|
+
wrap_operand.drop(operand.offset)
|
321
319
|
end
|
322
320
|
|
323
321
|
end # class OffsetOperand
|
@@ -340,7 +338,7 @@ module Veritas
|
|
340
338
|
#
|
341
339
|
# @api private
|
342
340
|
def optimize
|
343
|
-
Veritas::Relation::Empty.new(header)
|
341
|
+
Veritas::Relation::Empty.new(header, operation)
|
344
342
|
end
|
345
343
|
|
346
344
|
end # class EmptyOperand
|
@@ -32,7 +32,7 @@ module Veritas
|
|
32
32
|
#
|
33
33
|
# @api private
|
34
34
|
def wrap_operand(operand = operand.operand)
|
35
|
-
|
35
|
+
operand.restrict { predicate }
|
36
36
|
end
|
37
37
|
|
38
38
|
# Return true if the predicate is a true value
|
@@ -52,7 +52,7 @@ module Veritas
|
|
52
52
|
#
|
53
53
|
# @api private
|
54
54
|
def constant_false_predicate?
|
55
|
-
!(predicate.respond_to?(:call) || constant_true_predicate?)
|
55
|
+
! (predicate.respond_to?(:call) || constant_true_predicate?)
|
56
56
|
end
|
57
57
|
|
58
58
|
# Optimize when the predicate is a tautology
|
@@ -98,7 +98,8 @@ module Veritas
|
|
98
98
|
#
|
99
99
|
# @api private
|
100
100
|
def optimize
|
101
|
-
|
101
|
+
operation = self.operation
|
102
|
+
Veritas::Relation::Empty.new(operation.header, operation)
|
102
103
|
end
|
103
104
|
|
104
105
|
end # class Contradiction
|
@@ -132,7 +133,7 @@ module Veritas
|
|
132
133
|
#
|
133
134
|
# @api private
|
134
135
|
def predicate
|
135
|
-
|
136
|
+
operand.predicate.and(super).optimize
|
136
137
|
end
|
137
138
|
|
138
139
|
end # class RestrictionOperand
|
@@ -180,7 +181,7 @@ module Veritas
|
|
180
181
|
#
|
181
182
|
# @api private
|
182
183
|
def restriction_commutative?
|
183
|
-
!(partition_left_tautology? && partition_right_tautology?)
|
184
|
+
! (partition_left_tautology? && partition_right_tautology?)
|
184
185
|
end
|
185
186
|
|
186
187
|
# Test if the predicate for the left operand would match everything
|
@@ -341,7 +342,7 @@ module Veritas
|
|
341
342
|
#
|
342
343
|
# @api private
|
343
344
|
def optimizable?
|
344
|
-
super || !predicate.equal?(operation.predicate)
|
345
|
+
super || ! predicate.equal?(operation.predicate)
|
345
346
|
end
|
346
347
|
|
347
348
|
# Return a Restriction with an optimized operand
|
@@ -58,7 +58,11 @@ module Veritas
|
|
58
58
|
#
|
59
59
|
# @api private
|
60
60
|
def wrap_operand(operand = operand.operand)
|
61
|
-
|
61
|
+
operand.summarize(summarize_per) do |context|
|
62
|
+
summarizers.each do |summarizer|
|
63
|
+
context.add(*summarizer)
|
64
|
+
end
|
65
|
+
end
|
62
66
|
end
|
63
67
|
|
64
68
|
# Optimize when the operand is Empty
|
@@ -92,7 +96,11 @@ module Veritas
|
|
92
96
|
#
|
93
97
|
# @api private
|
94
98
|
def optimize
|
95
|
-
|
99
|
+
summarize_per.extend do |context|
|
100
|
+
extensions.each do |extension|
|
101
|
+
context.add(*extension)
|
102
|
+
end
|
103
|
+
end
|
96
104
|
end
|
97
105
|
|
98
106
|
private
|
@@ -130,7 +138,8 @@ module Veritas
|
|
130
138
|
#
|
131
139
|
# @api private
|
132
140
|
def optimize
|
133
|
-
|
141
|
+
operation = self.operation
|
142
|
+
Veritas::Relation::Empty.new(operation.header, operation)
|
134
143
|
end
|
135
144
|
|
136
145
|
end # class EmptySummarizePer
|
@@ -172,7 +181,7 @@ module Veritas
|
|
172
181
|
#
|
173
182
|
# @api private
|
174
183
|
def summarize_per_optimizable?
|
175
|
-
!summarize_per.equal?(operation.summarize_per)
|
184
|
+
! summarize_per.equal?(operation.summarize_per)
|
176
185
|
end
|
177
186
|
|
178
187
|
# Test if the summarizers are optimizable
|
@@ -181,7 +190,7 @@ module Veritas
|
|
181
190
|
#
|
182
191
|
# @api private
|
183
192
|
def summarizers_optimizable?
|
184
|
-
!summarizers.eql?(operation.summarizers)
|
193
|
+
! summarizers.eql?(operation.summarizers)
|
185
194
|
end
|
186
195
|
|
187
196
|
end # class UnoptimizedOperand
|
@@ -105,7 +105,7 @@ module Veritas
|
|
105
105
|
#
|
106
106
|
# @api private
|
107
107
|
def left_optimizable?
|
108
|
-
!left.equal?(operation.left)
|
108
|
+
! left.equal?(operation.left)
|
109
109
|
end
|
110
110
|
|
111
111
|
# Test if the right operand is optimizable
|
@@ -114,7 +114,7 @@ module Veritas
|
|
114
114
|
#
|
115
115
|
# @api private
|
116
116
|
def right_optimizable?
|
117
|
-
!right.equal?(operation.right)
|
117
|
+
! right.equal?(operation.right)
|
118
118
|
end
|
119
119
|
|
120
120
|
end # module UnoptimizedOperands
|
@@ -72,8 +72,7 @@ module Veritas
|
|
72
72
|
#
|
73
73
|
# @api private
|
74
74
|
def optimize
|
75
|
-
left
|
76
|
-
Veritas::Function::Predicate::Exclusion.new(left.left, merged_right_enumerables).optimize
|
75
|
+
left.left.exclude(merged_right_enumerables).optimize
|
77
76
|
end
|
78
77
|
|
79
78
|
end # class OptimizableToExclusion
|
@@ -72,8 +72,7 @@ module Veritas
|
|
72
72
|
#
|
73
73
|
# @api private
|
74
74
|
def optimize
|
75
|
-
left
|
76
|
-
Veritas::Function::Predicate::Inclusion.new(left.left, merged_right_enumerables).optimize
|
75
|
+
left.left.include(merged_right_enumerables).optimize
|
77
76
|
end
|
78
77
|
|
79
78
|
end # class OptimizableToInclusion
|
@@ -45,7 +45,7 @@ module Veritas
|
|
45
45
|
if util.constant?(left) then left_invalid_constant?
|
46
46
|
elsif util.constant?(right) then right_invalid_constant?
|
47
47
|
else
|
48
|
-
!joinable?
|
48
|
+
! joinable?
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
@@ -57,7 +57,7 @@ module Veritas
|
|
57
57
|
#
|
58
58
|
# @api private
|
59
59
|
def left_invalid_constant?
|
60
|
-
!right.valid_value?(left)
|
60
|
+
! right.valid_value?(left)
|
61
61
|
end
|
62
62
|
|
63
63
|
# Test if the right operand is an invalid constant
|
@@ -66,7 +66,7 @@ module Veritas
|
|
66
66
|
#
|
67
67
|
# @api private
|
68
68
|
def right_invalid_constant?
|
69
|
-
!left.valid_value?(right)
|
69
|
+
! left.valid_value?(right)
|
70
70
|
end
|
71
71
|
|
72
72
|
# Test if the left and right operand are joinable
|
@@ -106,7 +106,7 @@ module Veritas
|
|
106
106
|
#
|
107
107
|
# @api private
|
108
108
|
def left_invalid_constant?
|
109
|
-
!right.valid_primitive?(left)
|
109
|
+
! right.valid_primitive?(left)
|
110
110
|
end
|
111
111
|
|
112
112
|
# Test if the right operand is an invalid constant
|
@@ -115,7 +115,7 @@ module Veritas
|
|
115
115
|
#
|
116
116
|
# @api private
|
117
117
|
def right_invalid_constant?
|
118
|
-
!left.valid_primitive?(right)
|
118
|
+
! left.valid_primitive?(right)
|
119
119
|
end
|
120
120
|
|
121
121
|
# Test if the left and right operand are not comparable
|
@@ -125,7 +125,7 @@ module Veritas
|
|
125
125
|
# @api private
|
126
126
|
def not_comparable?
|
127
127
|
left = self.left
|
128
|
-
!(left.respond_to?(:comparable?) && left.comparable?(right))
|
128
|
+
! (left.respond_to?(:comparable?) && left.comparable?(right))
|
129
129
|
end
|
130
130
|
|
131
131
|
end # module NeverComparable
|
@@ -41,7 +41,7 @@ module Veritas
|
|
41
41
|
#
|
42
42
|
# @api private
|
43
43
|
def self.constant?(operand)
|
44
|
-
!operand.nil?
|
44
|
+
! (operand.nil? || operand.respond_to?(:call))
|
45
45
|
end
|
46
46
|
|
47
47
|
# Test if the operand is an attribute
|
@@ -60,8 +60,8 @@ module Veritas
|
|
60
60
|
# @api private
|
61
61
|
def self.min(operand)
|
62
62
|
case operand
|
63
|
-
|
64
|
-
|
63
|
+
when Attribute::String then operand.min_length
|
64
|
+
when Attribute::Numeric then operand.range.first
|
65
65
|
else
|
66
66
|
operand
|
67
67
|
end
|
@@ -74,8 +74,8 @@ module Veritas
|
|
74
74
|
# @api private
|
75
75
|
def self.max(operand)
|
76
76
|
case operand
|
77
|
-
|
78
|
-
|
77
|
+
when Attribute::String then operand.max_length
|
78
|
+
when Attribute::Numeric then operand.range.last
|
79
79
|
else
|
80
80
|
operand
|
81
81
|
end
|
@@ -37,7 +37,8 @@ module Veritas
|
|
37
37
|
#
|
38
38
|
# @api private
|
39
39
|
def optimize
|
40
|
-
|
40
|
+
operation = self.operation
|
41
|
+
Veritas::Relation::Empty.new(operation.header, operation)
|
41
42
|
end
|
42
43
|
|
43
44
|
end # class ZeroLimit
|
@@ -94,7 +95,7 @@ module Veritas
|
|
94
95
|
#
|
95
96
|
# @api private
|
96
97
|
def optimize
|
97
|
-
|
98
|
+
operand.operand.take(min_limit)
|
98
99
|
end
|
99
100
|
|
100
101
|
private
|
@@ -120,7 +121,7 @@ module Veritas
|
|
120
121
|
#
|
121
122
|
# @api private
|
122
123
|
def optimize
|
123
|
-
|
124
|
+
operand.take(limit)
|
124
125
|
end
|
125
126
|
|
126
127
|
end # class UnoptimizedOperand
|
@@ -60,7 +60,7 @@ module Veritas
|
|
60
60
|
#
|
61
61
|
# @api private
|
62
62
|
def optimize
|
63
|
-
|
63
|
+
operand.operand.drop(sum_offset)
|
64
64
|
end
|
65
65
|
|
66
66
|
private
|
@@ -86,7 +86,7 @@ module Veritas
|
|
86
86
|
#
|
87
87
|
# @api private
|
88
88
|
def optimize
|
89
|
-
|
89
|
+
operand.drop(offset)
|
90
90
|
end
|
91
91
|
|
92
92
|
end # class UnoptimizedOperand
|
@@ -26,8 +26,7 @@ module Veritas
|
|
26
26
|
#
|
27
27
|
# @api private
|
28
28
|
def optimize
|
29
|
-
|
30
|
-
operation.class.new(operand.operand, operation.directions)
|
29
|
+
operand.operand.sort_by { operation.directions }
|
31
30
|
end
|
32
31
|
|
33
32
|
end # class OrderOperand
|
@@ -67,8 +66,7 @@ module Veritas
|
|
67
66
|
#
|
68
67
|
# @api private
|
69
68
|
def optimize
|
70
|
-
|
71
|
-
operation.class.new(operand, operation.directions)
|
69
|
+
operand.sort_by { operation.directions }
|
72
70
|
end
|
73
71
|
|
74
72
|
end # class UnoptimizedOperand
|
@@ -49,8 +49,7 @@ module Veritas
|
|
49
49
|
#
|
50
50
|
# @api private
|
51
51
|
def optimize
|
52
|
-
operand
|
53
|
-
operand.class.new(operand.operand, operation.directions)
|
52
|
+
operand.operand.sort_by { operation.directions }
|
54
53
|
end
|
55
54
|
|
56
55
|
end # class OrderOperand
|
@@ -65,7 +64,7 @@ module Veritas
|
|
65
64
|
#
|
66
65
|
# @api private
|
67
66
|
def optimize
|
68
|
-
|
67
|
+
operand.reverse
|
69
68
|
end
|
70
69
|
|
71
70
|
end # class UnoptimizedOperand
|
@@ -16,11 +16,6 @@ describe Relation::Materialized, '#optimize' do
|
|
16
16
|
should == object
|
17
17
|
end
|
18
18
|
|
19
|
-
it 'does not execute body#each' do
|
20
|
-
body.should_not_receive(:each)
|
21
|
-
subject
|
22
|
-
end
|
23
|
-
|
24
19
|
it_should_behave_like 'an optimize method'
|
25
20
|
end
|
26
21
|
|
@@ -29,11 +24,6 @@ describe Relation::Materialized, '#optimize' do
|
|
29
24
|
|
30
25
|
it { should equal(object) }
|
31
26
|
|
32
|
-
it 'does not execute body#each' do
|
33
|
-
body.should_not_receive(:each)
|
34
|
-
subject
|
35
|
-
end
|
36
|
-
|
37
27
|
it_should_behave_like 'an optimize method'
|
38
28
|
end
|
39
29
|
end
|
@@ -5,12 +5,12 @@ shared_examples_for 'an optimize method' do
|
|
5
5
|
|
6
6
|
it 'it memoizes itself for #optimize' do
|
7
7
|
optimized = subject
|
8
|
-
optimized.memoized(
|
8
|
+
optimized.memoized(:optimize).should equal(optimized)
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'does not optimize further' do
|
12
12
|
optimized = subject
|
13
|
-
optimized.memoize(
|
13
|
+
optimized.memoize(:optimize, nil) # clear memoized value
|
14
14
|
optimized.optimize.should eql(optimized)
|
15
15
|
end
|
16
16
|
end
|
@@ -26,5 +26,5 @@ describe Optimizer::Algebra::Summarization::UnoptimizedOperand, '#optimize' do
|
|
26
26
|
|
27
27
|
its(:summarize_per) { should equal(TABLE_DEE) }
|
28
28
|
|
29
|
-
its(:summarizers) {
|
29
|
+
its(:summarizers) { should == { attribute => Aggregate::Sum.new(1) } }
|
30
30
|
end
|
data/veritas-optimizer.gemspec
CHANGED
@@ -4,17 +4,17 @@
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
|
-
s.name =
|
8
|
-
s.version = "0.0.
|
7
|
+
s.name = "veritas-optimizer"
|
8
|
+
s.version = "0.0.6"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.authors = [
|
12
|
-
s.date =
|
13
|
-
s.description =
|
14
|
-
s.email =
|
11
|
+
s.authors = ["Dan Kubb"]
|
12
|
+
s.date = "2011-10-04"
|
13
|
+
s.description = "Optimizes veritas relations"
|
14
|
+
s.email = "dan.kubb@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE",
|
17
|
-
"README.
|
17
|
+
"README.md",
|
18
18
|
"TODO"
|
19
19
|
]
|
20
20
|
s.files = [
|
@@ -24,7 +24,7 @@ Gem::Specification.new do |s|
|
|
24
24
|
"Gemfile",
|
25
25
|
"Guardfile",
|
26
26
|
"LICENSE",
|
27
|
-
"README.
|
27
|
+
"README.md",
|
28
28
|
"Rakefile",
|
29
29
|
"TODO",
|
30
30
|
"config/flay.yml",
|
@@ -360,23 +360,23 @@ Gem::Specification.new do |s|
|
|
360
360
|
"tasks/yard.rake",
|
361
361
|
"veritas-optimizer.gemspec"
|
362
362
|
]
|
363
|
-
s.homepage =
|
364
|
-
s.require_paths = [
|
365
|
-
s.rubygems_version =
|
366
|
-
s.summary =
|
363
|
+
s.homepage = "https://github.com/dkubb/veritas-optimizer"
|
364
|
+
s.require_paths = ["lib"]
|
365
|
+
s.rubygems_version = "1.8.10"
|
366
|
+
s.summary = "Relational algebra optimizer"
|
367
367
|
|
368
368
|
if s.respond_to? :specification_version then
|
369
369
|
s.specification_version = 3
|
370
370
|
|
371
371
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
372
|
-
s.add_runtime_dependency(%q<veritas>, ["~> 0.0.
|
372
|
+
s.add_runtime_dependency(%q<veritas>, ["~> 0.0.6"])
|
373
373
|
s.add_development_dependency(%q<backports>, ["~> 2.3.0"])
|
374
374
|
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
375
375
|
s.add_development_dependency(%q<rake>, ["~> 0.9.2"])
|
376
376
|
s.add_development_dependency(%q<rspec>, ["~> 1.3.2"])
|
377
377
|
s.add_development_dependency(%q<yard>, ["~> 0.7.2"])
|
378
378
|
else
|
379
|
-
s.add_dependency(%q<veritas>, ["~> 0.0.
|
379
|
+
s.add_dependency(%q<veritas>, ["~> 0.0.6"])
|
380
380
|
s.add_dependency(%q<backports>, ["~> 2.3.0"])
|
381
381
|
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
382
382
|
s.add_dependency(%q<rake>, ["~> 0.9.2"])
|
@@ -384,7 +384,7 @@ Gem::Specification.new do |s|
|
|
384
384
|
s.add_dependency(%q<yard>, ["~> 0.7.2"])
|
385
385
|
end
|
386
386
|
else
|
387
|
-
s.add_dependency(%q<veritas>, ["~> 0.0.
|
387
|
+
s.add_dependency(%q<veritas>, ["~> 0.0.6"])
|
388
388
|
s.add_dependency(%q<backports>, ["~> 2.3.0"])
|
389
389
|
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
390
390
|
s.add_dependency(%q<rake>, ["~> 0.9.2"])
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: veritas-optimizer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 6
|
10
|
+
version: 0.0.6
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Dan Kubb
|
@@ -15,26 +15,28 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-10-04 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
22
24
|
none: false
|
23
25
|
requirements:
|
24
26
|
- - ~>
|
25
27
|
- !ruby/object:Gem::Version
|
26
|
-
hash:
|
28
|
+
hash: 19
|
27
29
|
segments:
|
28
30
|
- 0
|
29
31
|
- 0
|
30
|
-
-
|
31
|
-
version: 0.0.
|
32
|
-
|
33
|
-
requirement: *id001
|
34
|
-
prerelease: false
|
32
|
+
- 6
|
33
|
+
version: 0.0.6
|
34
|
+
version_requirements: *id001
|
35
35
|
name: veritas
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
|
-
|
37
|
+
type: :development
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
40
|
none: false
|
39
41
|
requirements:
|
40
42
|
- - ~>
|
@@ -45,12 +47,12 @@ dependencies:
|
|
45
47
|
- 3
|
46
48
|
- 0
|
47
49
|
version: 2.3.0
|
48
|
-
|
49
|
-
requirement: *id002
|
50
|
-
prerelease: false
|
50
|
+
version_requirements: *id002
|
51
51
|
name: backports
|
52
52
|
- !ruby/object:Gem::Dependency
|
53
|
-
|
53
|
+
type: :development
|
54
|
+
prerelease: false
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
54
56
|
none: false
|
55
57
|
requirements:
|
56
58
|
- - ~>
|
@@ -61,12 +63,12 @@ dependencies:
|
|
61
63
|
- 6
|
62
64
|
- 4
|
63
65
|
version: 1.6.4
|
64
|
-
|
65
|
-
requirement: *id003
|
66
|
-
prerelease: false
|
66
|
+
version_requirements: *id003
|
67
67
|
name: jeweler
|
68
68
|
- !ruby/object:Gem::Dependency
|
69
|
-
|
69
|
+
type: :development
|
70
|
+
prerelease: false
|
71
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
70
72
|
none: false
|
71
73
|
requirements:
|
72
74
|
- - ~>
|
@@ -77,12 +79,12 @@ dependencies:
|
|
77
79
|
- 9
|
78
80
|
- 2
|
79
81
|
version: 0.9.2
|
80
|
-
|
81
|
-
requirement: *id004
|
82
|
-
prerelease: false
|
82
|
+
version_requirements: *id004
|
83
83
|
name: rake
|
84
84
|
- !ruby/object:Gem::Dependency
|
85
|
-
|
85
|
+
type: :development
|
86
|
+
prerelease: false
|
87
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
86
88
|
none: false
|
87
89
|
requirements:
|
88
90
|
- - ~>
|
@@ -93,12 +95,12 @@ dependencies:
|
|
93
95
|
- 3
|
94
96
|
- 2
|
95
97
|
version: 1.3.2
|
96
|
-
|
97
|
-
requirement: *id005
|
98
|
-
prerelease: false
|
98
|
+
version_requirements: *id005
|
99
99
|
name: rspec
|
100
100
|
- !ruby/object:Gem::Dependency
|
101
|
-
|
101
|
+
type: :development
|
102
|
+
prerelease: false
|
103
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
102
104
|
none: false
|
103
105
|
requirements:
|
104
106
|
- - ~>
|
@@ -109,9 +111,7 @@ dependencies:
|
|
109
111
|
- 7
|
110
112
|
- 2
|
111
113
|
version: 0.7.2
|
112
|
-
|
113
|
-
requirement: *id006
|
114
|
-
prerelease: false
|
114
|
+
version_requirements: *id006
|
115
115
|
name: yard
|
116
116
|
description: Optimizes veritas relations
|
117
117
|
email: dan.kubb@gmail.com
|
@@ -121,7 +121,7 @@ extensions: []
|
|
121
121
|
|
122
122
|
extra_rdoc_files:
|
123
123
|
- LICENSE
|
124
|
-
- README.
|
124
|
+
- README.md
|
125
125
|
- TODO
|
126
126
|
files:
|
127
127
|
- .gemtest
|
@@ -130,7 +130,7 @@ files:
|
|
130
130
|
- Gemfile
|
131
131
|
- Guardfile
|
132
132
|
- LICENSE
|
133
|
-
- README.
|
133
|
+
- README.md
|
134
134
|
- Rakefile
|
135
135
|
- TODO
|
136
136
|
- config/flay.yml
|
@@ -494,7 +494,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
494
494
|
requirements: []
|
495
495
|
|
496
496
|
rubyforge_project:
|
497
|
-
rubygems_version: 1.8.
|
497
|
+
rubygems_version: 1.8.10
|
498
498
|
signing_key:
|
499
499
|
specification_version: 3
|
500
500
|
summary: Relational algebra optimizer
|