alf-sequel 0.13.0 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ # 0.14.0 / 2013-10-01
2
+
3
+ * Added SQL implementation of `page` and `frame`
4
+ * Fix SQL bug on compilation of joins
5
+
1
6
  # 0.13.0 / 2013-07-29
2
7
 
3
8
  The 0.13.0 version is a new birthday for alf. See `alf` main for CHANGELOG
data/Gemfile CHANGED
@@ -1,8 +1,7 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
3
  group :runtime do
4
- #gem "alf-core", :git => "git://github.com/alf-tool/alf-core.git"
5
- gem "alf-core", "~> 0.13.0"
4
+ gem "alf-core", "~> 0.14.0"
6
5
  gem "sequel", "~> 3.48"
7
6
  end
8
7
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- alf-core (0.13.0)
4
+ alf-core (0.14.0)
5
5
  domain (~> 1.0)
6
6
  myrrha (~> 3.0)
7
7
  path (~> 1.3)
@@ -11,7 +11,7 @@ GEM
11
11
  jdbc-sqlite3 (3.7.2.1)
12
12
  myrrha (3.0.0)
13
13
  domain (~> 1.0)
14
- path (1.3.1)
14
+ path (1.3.3)
15
15
  rake (10.1.0)
16
16
  rspec (2.14.1)
17
17
  rspec-core (~> 2.14.0)
@@ -30,7 +30,7 @@ PLATFORMS
30
30
  ruby
31
31
 
32
32
  DEPENDENCIES
33
- alf-core (~> 0.13.0)
33
+ alf-core (~> 0.14.0)
34
34
  jdbc-sqlite3 (~> 3.7)
35
35
  rake (~> 10.1)
36
36
  rspec (~> 2.14)
@@ -3,7 +3,8 @@ module Alf
3
3
  class Cog
4
4
  include Engine::Cog
5
5
 
6
- def initialize(connection, opts)
6
+ def initialize(expr, connection, opts)
7
+ super(expr)
7
8
  @connection = connection
8
9
  @opts = opts
9
10
  end
@@ -24,41 +25,45 @@ module Alf
24
25
 
25
26
  ### Delegation to Dataset, that is, facade over ::Sequel itself
26
27
 
27
- def select(attrs)
28
- branch dataset: dataset.select(*qualify(attrs))
28
+ def select(expr, attrs)
29
+ branch expr, dataset: dataset.select(*qualify(attrs))
29
30
  end
30
31
 
31
- def rename(attrs, opts)
32
- branch dataset: dataset.select(*qualify(attrs)).from_self(opts),
33
- as: opts[:alias]
32
+ def rename(expr, attrs, opts)
33
+ branch expr, dataset: dataset.select(*qualify(attrs)).from_self(opts),
34
+ as: opts[:alias]
34
35
  end
35
36
 
36
- def distinct(*args, &bl)
37
- branch dataset: dataset.distinct(*args, &bl)
37
+ def distinct(expr, *args, &bl)
38
+ branch expr, dataset: dataset.distinct(*args, &bl)
38
39
  end
39
40
 
40
- def order(*args, &bl)
41
- branch dataset: dataset.order(*args, &bl)
41
+ def order(expr, *args, &bl)
42
+ branch expr, dataset: dataset.order(*args, &bl)
42
43
  end
43
44
 
44
- def filter(*args, &bl)
45
- branch dataset: dataset.filter(*args, &bl)
45
+ def filter(expr, *args, &bl)
46
+ branch expr, dataset: dataset.filter(*args, &bl)
46
47
  end
47
48
 
48
- def intersect(other, opts={})
49
- branch dataset: dataset.intersect(other.dataset, opts),
50
- as: opts[:alias]
49
+ def intersect(expr, other, opts={})
50
+ branch expr, dataset: dataset.intersect(other.dataset, opts),
51
+ as: opts[:alias]
51
52
  end
52
53
 
53
- def join(other, cols, opts={})
54
- join = dataset.inner_join(other.dataset, cols, :table_alias => opts[:alias])
55
- branch dataset: join.from_self(opts),
56
- as: opts[:alias]
54
+ def join(expr, other, cols, opts={})
55
+ join = dataset.from_self.inner_join(other.dataset, cols, :table_alias => opts[:alias])
56
+ branch expr, dataset: join.from_self(opts),
57
+ as: opts[:alias]
57
58
  end
58
59
 
59
- def union(other, opts={})
60
- branch dataset: dataset.union(other.dataset, opts),
61
- as: opts[:alias]
60
+ def union(expr, other, opts={})
61
+ branch expr, dataset: dataset.union(other.dataset, opts),
62
+ as: opts[:alias]
63
+ end
64
+
65
+ def limit(expr, *args, &bl)
66
+ branch expr, dataset: dataset.limit(*args, &bl)
62
67
  end
63
68
 
64
69
  ### compilation tools
@@ -79,8 +84,8 @@ module Alf
79
84
  end
80
85
  end
81
86
 
82
- def branch(opts = {})
83
- Cog.new connection, self.opts.merge(opts)
87
+ def branch(expr, opts = {})
88
+ Cog.new expr, connection, self.opts.merge(opts)
84
89
  end
85
90
 
86
91
  def to_s
@@ -14,7 +14,7 @@ module Alf
14
14
 
15
15
  def on_leaf_operand(expr)
16
16
  if Algebra::Operand::Named===expr
17
- expr.connection.cog(expr.name, :alias => next_alias)
17
+ expr.connection.cog(expr.name, expr, :alias => next_alias)
18
18
  else
19
19
  expr.to_cog
20
20
  end
@@ -29,53 +29,61 @@ module Alf
29
29
 
30
30
  def on_clip(expr)
31
31
  rewrite(expr){|rw|
32
- rw.operand.select(expr.stay_attributes)
32
+ rw.operand.select(expr, expr.stay_attributes)
33
33
  }
34
34
  end
35
35
 
36
36
  def on_compact(expr)
37
37
  rewrite(expr){|rw|
38
- rw.operand.distinct
38
+ rw.operand.distinct(expr)
39
39
  }
40
40
  end
41
41
 
42
42
  def on_sort(expr)
43
43
  rewrite(expr){|rw|
44
- operand = rw.operand
45
- ordering = expr.ordering.to_a.map{|(col,dir)|
46
- ::Sequel.send(dir, operand.qualify(col))
47
- }
48
- operand.order(*ordering)
44
+ operand = rw.operand
45
+ ordering = to_sequel_ordering(operand, expr.ordering)
46
+ operand.order(expr, *ordering)
49
47
  }
50
48
  end
51
49
 
52
50
  ### relational
53
51
 
54
52
  alias :on_extend :pass
53
+
54
+ def on_frame(expr)
55
+ rewrite(expr){|rw|
56
+ offset, limit, ordering = expr.offset, expr.limit, expr.total_ordering
57
+ operand = rw.operand
58
+ ordering = to_sequel_ordering(operand, ordering)
59
+ operand.order(expr, *ordering).limit(expr, limit, offset)
60
+ }
61
+ end
62
+
55
63
  alias :on_group :pass
56
64
  alias :on_infer_heading :pass
57
65
 
58
66
  def on_intersect(expr)
59
67
  rewrite(expr){|rw|
60
- rw.left.intersect(rw.right, :alias => next_alias)
68
+ rw.left.intersect(expr, rw.right, {:alias => next_alias})
61
69
  }
62
70
  end
63
71
 
64
72
  def on_join(expr)
65
73
  rewrite(expr){|rw|
66
- rw.left.join(rw.right, expr.common_attributes.to_a, :alias => next_alias)
74
+ rw.left.join(expr, rw.right, expr.common_attributes.to_a, {:alias => next_alias})
67
75
  }
68
76
  end
69
77
 
70
78
  def on_matching(expr)
71
79
  rewrite(expr) do |rw|
72
- rw.left.filter(matching2filter(expr, rw))
80
+ rw.left.filter(expr, matching2filter(expr, rw))
73
81
  end
74
82
  end
75
83
 
76
84
  def on_not_matching(expr)
77
85
  rewrite(expr) do |rw|
78
- rw.left.filter(~matching2filter(expr, rw))
86
+ rw.left.filter(expr, ~matching2filter(expr, rw))
79
87
  end
80
88
  end
81
89
 
@@ -83,7 +91,7 @@ module Alf
83
91
  commons = expr.common_attributes.to_a
84
92
  if commons.size==1
85
93
  # (NOT) IN (SELECT ...)
86
- pred = ::Alf::Predicate.in(commons.first, rw.right.select(commons).dataset)
94
+ pred = ::Alf::Predicate.in(commons.first, rw.right.select(expr, commons).dataset)
87
95
  Predicate.new(:qualifier => rw.left.as).call(pred)
88
96
  elsif commons.size==0
89
97
  # (NOT) EXISTS (SELECT ... no join condition ...)
@@ -92,17 +100,26 @@ module Alf
92
100
  # (NOT) EXISTS (SELECT ...)
93
101
  filter = Hash[rw.left.qualify(commons).zip(rw.right.qualify(commons))]
94
102
  filter = ::Sequel.expr filter
95
- filter = rw.right.filter(filter)
103
+ filter = rw.right.filter(expr, filter)
96
104
  filter.dataset.exists
97
105
  end
98
106
  end
99
107
 
100
108
  alias :on_minus :pass
101
109
 
110
+ def on_page(expr)
111
+ rewrite(expr){|rw|
112
+ index, size, ordering = expr.page_index, expr.page_size, expr.total_ordering
113
+ operand, offset, limit = rw.operand, (index.abs - 1) * size, size
114
+ ordering = to_sequel_ordering(operand, index >= 0 ? ordering : ordering.reverse)
115
+ operand.order(expr, *ordering).limit(expr, offset , limit)
116
+ }
117
+ end
118
+
102
119
  def on_project(expr)
103
120
  rewrite(expr){|rw|
104
- compiled = rw.operand.select(expr.stay_attributes)
105
- compiled = compiled.distinct unless key_preserving?(expr){ false }
121
+ compiled = rw.operand.select(expr, expr.stay_attributes)
122
+ compiled = compiled.distinct(expr) unless key_preserving?(expr){ false }
106
123
  compiled
107
124
  }
108
125
  end
@@ -112,14 +129,14 @@ module Alf
112
129
 
113
130
  def on_rename(expr)
114
131
  rewrite(expr){|rw|
115
- rw.operand.rename(expr.complete_renaming.to_hash, :alias => next_alias)
132
+ rw.operand.rename(expr, expr.complete_renaming.to_hash, :alias => next_alias)
116
133
  }
117
134
  end
118
135
 
119
136
  def on_restrict(expr)
120
137
  rewrite(expr){|rw|
121
138
  filter = Predicate.new(:qualifier => rw.operand.as).call(rw.predicate)
122
- rw.operand.filter(filter)
139
+ rw.operand.filter(expr, filter)
123
140
  }
124
141
  end
125
142
 
@@ -128,7 +145,7 @@ module Alf
128
145
 
129
146
  def on_union(expr)
130
147
  rewrite(expr){|rw|
131
- rw.left.union(rw.right, :alias => next_alias)
148
+ rw.left.union(expr, rw.right, :alias => next_alias)
132
149
  }
133
150
  end
134
151
 
@@ -137,6 +154,13 @@ module Alf
137
154
 
138
155
  private
139
156
 
157
+ def to_sequel_ordering(operand, ordering)
158
+ ordering.to_a.map{|(sel,dir)|
159
+ raise NotSupportedError if sel.composite?
160
+ ::Sequel.send(dir, operand.qualify(sel.outcoerce))
161
+ }
162
+ end
163
+
140
164
  def key_preserving?(expr)
141
165
  expr.key_preserving?
142
166
  rescue NotSupportedError
@@ -146,12 +170,29 @@ module Alf
146
170
  private
147
171
 
148
172
  def rewrite(expr)
149
- rewrited = copy_and_apply(expr)
150
- if block_given? and rewrited.operands.all?{|op| recognized?(op) }
151
- catch(:pass){ rewrited = yield(rewrited) }
173
+ # copy and apply on expr. the result is the same expression, but
174
+ # with cogs instead of operands
175
+ rewritten = copy_and_apply(expr)
176
+
177
+ # Continue compilation process provided all operands are recognized.
178
+ if block_given? and rewritten.operands.all?{|op| recognized?(op) }
179
+ # Compilation of predicates may throw a pass
180
+ catch(:pass){
181
+ rewritten = yield(rewritten)
182
+ }
183
+ end
184
+
185
+ # If the result is itself recognized, proceed
186
+ # Otherwise, give a change to the upper-stage compiler with a proxy
187
+ if recognized?(rewritten)
188
+ rewritten
189
+ else
190
+ operands = rewritten.operands.map{|op|
191
+ Algebra::Operand::Proxy.new(op)
192
+ }
193
+ rewritten = rewritten.with_operands(*operands)
194
+ engine.call(rewritten)
152
195
  end
153
- rewrited = engine.call(rewrited) unless recognized?(rewrited)
154
- rewrited
155
196
  end
156
197
 
157
198
  def recognized?(op)
@@ -11,11 +11,11 @@ module Alf
11
11
  sequel_db[name]
12
12
  end
13
13
 
14
- def cog(name, opts={})
14
+ def cog(name, expr = nil, opts = {})
15
15
  if as = opts[:alias]
16
- Cog.new(self, dataset: dataset(:"#{name}___#{as}"), as: as)
16
+ Cog.new(expr, self, dataset: dataset(:"#{name}___#{as}"), as: as)
17
17
  else
18
- Cog.new(self, dataset: dataset(name))
18
+ Cog.new(expr, self, dataset: dataset(name))
19
19
  end
20
20
  end
21
21
 
@@ -40,8 +40,8 @@ module Alf
40
40
  else
41
41
  filter = mr.tuple_extract.to_hash
42
42
  tuples = connection.cog(@relvar_name)
43
- .filter(filter)
44
- .select(pkey.to_a)
43
+ .filter(nil, filter)
44
+ .select(nil, pkey.to_a)
45
45
  Relation(tuples)
46
46
  end
47
47
  end
@@ -3,7 +3,7 @@ module Alf
3
3
  module Version
4
4
 
5
5
  MAJOR = 0
6
- MINOR = 13
6
+ MINOR = 14
7
7
  TINY = 0
8
8
 
9
9
  def self.to_s
@@ -0,0 +1,89 @@
1
+ require 'compiler_helper'
2
+ module Alf
3
+ module Sequel
4
+ describe Compiler, "frame" do
5
+
6
+ subject{ compile(expr) }
7
+
8
+ let(:expr){
9
+ frame(operand, ordering, offset, limit)
10
+ }
11
+
12
+ context 'when fully compilable' do
13
+ let(:operand){ suppliers }
14
+
15
+ [
16
+ [ [[:name, :asc]], 0, 8, "SELECT * FROM `suppliers` AS 't1' ORDER BY `t1`.`name` ASC LIMIT 8 OFFSET 0" ],
17
+ [ [[:name, :asc]], 2, 8, "SELECT * FROM `suppliers` AS 't1' ORDER BY `t1`.`name` ASC LIMIT 8 OFFSET 2" ],
18
+ [ [[:city, :asc]], 0, 8, "SELECT * FROM `suppliers` AS 't1' ORDER BY `t1`.`city` ASC, `t1`.`sid` ASC LIMIT 8 OFFSET 0" ],
19
+ [ [[:city, :desc]], 2, 8, "SELECT * FROM `suppliers` AS 't1' ORDER BY `t1`.`city` DESC, `t1`.`sid` ASC LIMIT 8 OFFSET 2" ],
20
+ ].each do |(ordering,offset,limit,expected)|
21
+
22
+ context "frame(#{ordering}, #{offset}, #{limit})" do
23
+ let(:ordering){ ordering }
24
+ let(:offset) { offset }
25
+ let(:limit) { limit }
26
+
27
+ it 'should compile as expected' do
28
+ subject.sql.should eq(expected)
29
+ end
30
+ end
31
+
32
+ end
33
+ end # fully compilable
34
+
35
+ context 'when immediately uncompilable yet known keys' do
36
+ let(:operand){
37
+ Algebra::Operand::Fake.new.with_keys([:sid], [:name])
38
+ }
39
+
40
+ [
41
+ [ [[:name, :asc]], 2, 8, [[:name, :asc]] ],
42
+ [ [[:city, :asc]], 2, 8, [[:city, :asc], [:sid, :asc]] ]
43
+ ].each do |ordering, offset, limit, expected|
44
+
45
+ context "frame(#{ordering}, #{offset}, #{limit})" do
46
+ let(:ordering){ ordering }
47
+ let(:offset) { offset }
48
+ let(:limit) { limit }
49
+
50
+ it{ should be_a(Engine::Take) }
51
+
52
+ it 'should have sort with good ordering' do
53
+ subject.operand.should be_a(Engine::Sort)
54
+ subject.operand.ordering.should eq(Ordering.new(expected))
55
+ end
56
+ end
57
+
58
+ end
59
+ end
60
+
61
+ context 'when immediately uncompilable yet unknown keys' do
62
+ let(:operand){
63
+ Algebra::Operand::Fake.new
64
+ }
65
+
66
+ [
67
+ [ [[:name, :asc]], 2, 8, [[:name, :asc]] ],
68
+ [ [[:city, :asc]], 2, 8, [[:city, :asc]] ]
69
+ ].each do |ordering, offset, limit, expected|
70
+
71
+ context "frame(#{ordering}, #{offset}, #{limit})" do
72
+ let(:ordering){ ordering }
73
+ let(:offset) { offset }
74
+ let(:limit) { limit }
75
+
76
+ it{ should be_a(Engine::Take) }
77
+
78
+ it 'should have sort with good ordering' do
79
+ subject.operand.should be_a(Engine::Sort)
80
+ subject.operand.ordering.should eq(Ordering.new(expected))
81
+ end
82
+ end
83
+
84
+ end
85
+ end
86
+
87
+ end
88
+ end
89
+ end
@@ -9,7 +9,15 @@ module Alf
9
9
  let(:expr){ join(suppliers, supplies) }
10
10
 
11
11
  specify do
12
- subject.sql.should eq("SELECT * FROM (SELECT * FROM `suppliers` AS 't1' INNER JOIN (SELECT * FROM `supplies` AS 't2') AS 't3' USING (`sid`)) AS 't3'")
12
+ subject.sql.should eq("SELECT * FROM (SELECT * FROM (SELECT * FROM `suppliers` AS 't1') AS 't1' INNER JOIN (SELECT * FROM `supplies` AS 't2') AS 't3' USING (`sid`)) AS 't3'")
13
+ end
14
+ end
15
+
16
+ context 'when the left operand is a projection' do
17
+ let(:expr){ join(project(suppliers, [:sid]), supplies) }
18
+
19
+ specify do
20
+ subject.sql.should eq("SELECT * FROM (SELECT * FROM (SELECT `t1`.`sid` FROM `suppliers` AS 't1') AS 't1' INNER JOIN (SELECT * FROM `supplies` AS 't2') AS 't3' USING (`sid`)) AS 't3'")
13
21
  end
14
22
  end
15
23
 
@@ -9,7 +9,7 @@ module Alf
9
9
  let(:expr){ matching(suppliers, project(supplies, [:part_id])) }
10
10
 
11
11
  specify do
12
- subject.sql.should eq("SELECT * FROM `suppliers` AS 't1' WHERE (EXISTS (SELECT `t2`.`part_id` FROM `supplies` AS 't2'))")
12
+ subject.sql.should eq("SELECT * FROM `suppliers` AS 't1' WHERE (EXISTS (SELECT DISTINCT `t2`.`part_id` FROM `supplies` AS 't2'))")
13
13
  end
14
14
  end
15
15
 
@@ -9,7 +9,7 @@ module Alf
9
9
  let(:expr){ not_matching(suppliers, project(supplies, [:part_id])) }
10
10
 
11
11
  specify do
12
- subject.sql.should eq("SELECT * FROM `suppliers` AS 't1' WHERE NOT (EXISTS (SELECT `t2`.`part_id` FROM `supplies` AS 't2'))")
12
+ subject.sql.should eq("SELECT * FROM `suppliers` AS 't1' WHERE NOT (EXISTS (SELECT DISTINCT `t2`.`part_id` FROM `supplies` AS 't2'))")
13
13
  end
14
14
  end
15
15
 
@@ -0,0 +1,86 @@
1
+ require 'compiler_helper'
2
+ module Alf
3
+ module Sequel
4
+ describe Compiler, "page" do
5
+
6
+ subject{ compile(expr) }
7
+
8
+ let(:expr){
9
+ page(operand, ordering, page_index, page_size: 8)
10
+ }
11
+
12
+ context 'when fully compilable' do
13
+ let(:operand){ suppliers }
14
+
15
+ [
16
+ [ [[:name, :asc]], 2, "SELECT * FROM `suppliers` AS 't1' ORDER BY `t1`.`name` ASC LIMIT 8 OFFSET 8" ],
17
+ [ [[:name, :asc]], -2, "SELECT * FROM `suppliers` AS 't1' ORDER BY `t1`.`name` DESC LIMIT 8 OFFSET 8" ],
18
+ [ [[:city, :asc]], 2, "SELECT * FROM `suppliers` AS 't1' ORDER BY `t1`.`city` ASC, `t1`.`sid` ASC LIMIT 8 OFFSET 8" ],
19
+ [ [[:city, :asc]], -2, "SELECT * FROM `suppliers` AS 't1' ORDER BY `t1`.`city` DESC, `t1`.`sid` DESC LIMIT 8 OFFSET 8" ],
20
+ ].each do |(ordering,page_index,expected)|
21
+
22
+ context "page(#{ordering}, #{page_index})" do
23
+ let(:ordering) { ordering }
24
+ let(:page_index){ page_index }
25
+
26
+ it 'should compile as expected' do
27
+ subject.sql.should eq(expected)
28
+ end
29
+ end
30
+
31
+ end
32
+ end # fully compilable
33
+
34
+ context 'when immediately uncompilable yet known keys' do
35
+ let(:operand){
36
+ Algebra::Operand::Fake.new.with_keys([:sid], [:name])
37
+ }
38
+
39
+ [
40
+ [ [[:name, :asc]], 2, [[:name, :asc]] ],
41
+ [ [[:city, :asc]], 2, [[:city, :asc], [:sid, :asc]] ]
42
+ ].each do |ordering, page_index, expected|
43
+
44
+ context "page(#{ordering}, #{page_index})" do
45
+ let(:ordering) { ordering }
46
+ let(:page_index){ page_index }
47
+
48
+ it{ should be_a(Engine::Take) }
49
+
50
+ it 'should have sort with good ordering' do
51
+ subject.operand.should be_a(Engine::Sort)
52
+ subject.operand.ordering.should eq(Ordering.new(expected))
53
+ end
54
+ end
55
+
56
+ end
57
+ end
58
+
59
+ context 'when immediately uncompilable yet unknown keys' do
60
+ let(:operand){
61
+ Algebra::Operand::Fake.new
62
+ }
63
+
64
+ [
65
+ [ [[:name, :asc]], 2, [[:name, :asc]] ],
66
+ [ [[:city, :asc]], 2, [[:city, :asc]] ]
67
+ ].each do |ordering, page_index, expected|
68
+
69
+ context "page(#{ordering}, #{page_index})" do
70
+ let(:ordering) { ordering }
71
+ let(:page_index){ page_index }
72
+
73
+ it{ should be_a(Engine::Take) }
74
+
75
+ it 'should have sort with good ordering' do
76
+ subject.operand.should be_a(Engine::Sort)
77
+ subject.operand.ordering.should eq(Ordering.new(expected))
78
+ end
79
+ end
80
+
81
+ end
82
+ end
83
+
84
+ end
85
+ end
86
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alf-sequel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 0.14.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-07-29 00:00:00.000000000 Z
12
+ date: 2013-10-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -50,7 +50,7 @@ dependencies:
50
50
  requirements:
51
51
  - - ~>
52
52
  - !ruby/object:Gem::Version
53
- version: 0.13.0
53
+ version: 0.14.0
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
@@ -58,7 +58,7 @@ dependencies:
58
58
  requirements:
59
59
  - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: 0.13.0
61
+ version: 0.14.0
62
62
  - !ruby/object:Gem::Dependency
63
63
  name: sequel
64
64
  requirement: !ruby/object:Gem::Requirement
@@ -111,11 +111,13 @@ files:
111
111
  - spec/compiler/test_clip.rb
112
112
  - spec/compiler/test_compact.rb
113
113
  - spec/compiler/test_extend.rb
114
+ - spec/compiler/test_frame.rb
114
115
  - spec/compiler/test_intersect.rb
115
116
  - spec/compiler/test_join.rb
116
117
  - spec/compiler/test_leaf_operand.rb
117
118
  - spec/compiler/test_matching.rb
118
119
  - spec/compiler/test_not_matching.rb
120
+ - spec/compiler/test_page.rb
119
121
  - spec/compiler/test_predicate.rb
120
122
  - spec/compiler/test_project.rb
121
123
  - spec/compiler/test_rename.rb
@@ -158,7 +160,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
158
160
  version: '0'
159
161
  segments:
160
162
  - 0
161
- hash: 2828513476823415639
163
+ hash: 3191817765128165623
162
164
  required_rubygems_version: !ruby/object:Gem::Requirement
163
165
  none: false
164
166
  requirements: