bmg 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7b43a1cda1c1650f7678db8e4a9213e7065d26a5
4
- data.tar.gz: 6f130fa599d6d24b4eaa0450883cfef539b95e6f
3
+ metadata.gz: 381472a4bb34f2a614c0520261508fb2c6ff6032
4
+ data.tar.gz: 562ca2c457720e0b7a12a5e9b9ccd33e1609b778
5
5
  SHA512:
6
- metadata.gz: 0ac9c79f0c348dbd7685a5c922a28a315192a72ce6b42da708b3233f1fb53da1b64da97659ddb3935aad39a4bdf3141d06be24ff102d202be0e7d8677fbb9f8a
7
- data.tar.gz: 40aea311e6e4d372ca07ffd91fd5c6ad102f3dd67da5443287121233848e3470ccded49eea97ef4e1f9d4a01afebeb4b43425e7426081ee2472cb0b8a95833ed
6
+ metadata.gz: 195468c7f66d2aa11d49678effe9dc5122e67aec2fbe3161549f6a351835a11f8957aaca4004143bc00256c121d4638c68d466f6267623d35ac5288855e5d7df
7
+ data.tar.gz: 1590b7723bec6a826e88a0eef3e1e659c80c355f41de3d61c5d31d4a6c872398f6698290ac464ea795e8bd67e1e5a4eebaaa4052468e61933a6a36b79df81db7
data/Gemfile CHANGED
@@ -1,2 +1,4 @@
1
1
  source "https://rubygems.org"
2
2
  gemspec
3
+
4
+ gem 'predicate', path: '../predicate'
data/lib/bmg.rb CHANGED
@@ -15,6 +15,7 @@ module Bmg
15
15
  end
16
16
  require_relative 'bmg/version'
17
17
  require_relative 'bmg/error'
18
+ require_relative 'bmg/support'
18
19
  require_relative 'bmg/algebra'
19
20
  require_relative 'bmg/type'
20
21
  require_relative 'bmg/relation'
@@ -6,4 +6,7 @@ module Bmg
6
6
  # Raised by Relation#one when the relation is not a singleton
7
7
  class OneError < Error; end
8
8
 
9
+ # Raised when an update is invalid for some reason
10
+ class InvalidUpdateError < Error; end
11
+
9
12
  end
@@ -41,6 +41,23 @@ module Bmg
41
41
  end
42
42
  end
43
43
 
44
+ def insert(arg)
45
+ case arg
46
+ when Hash then operand.insert(valid_tuple!(arg))
47
+ when Enumerable then operand.insert(arg.map{|t| valid_tuple!(t) })
48
+ else
49
+ super
50
+ end
51
+ end
52
+
53
+ def update(tuple)
54
+ operand.update(valid_tuple!(tuple))
55
+ end
56
+
57
+ def delete
58
+ operand.delete
59
+ end
60
+
44
61
  def to_ast
45
62
  [:allbut, operand.to_ast, butlist.dup]
46
63
  end
@@ -54,7 +71,13 @@ module Bmg
54
71
  private
55
72
 
56
73
  def tuple_allbut(tuple)
57
- tuple.delete_if{|k,_| @butlist.include?(k) }
74
+ TupleAlgebra.allbut(tuple, @butlist)
75
+ end
76
+
77
+ def valid_tuple!(tuple)
78
+ offending = tuple.keys & butlist
79
+ raise InvalidUpdateError, "#{offending.inspect} cannot be updated" unless offending.empty?
80
+ tuple
58
81
  end
59
82
 
60
83
  end # class Allbut
@@ -42,6 +42,21 @@ module Bmg
42
42
  [:autosummarize, operand.to_ast, by.dup, sums.dup]
43
43
  end
44
44
 
45
+ protected
46
+
47
+ def _restrict(type, predicate)
48
+ top, bottom = predicate.and_split(sums.keys)
49
+ if top == predicate
50
+ super
51
+ else
52
+ op = operand
53
+ op = op.restrict(bottom)
54
+ op = op.autosummarize(by, sums)
55
+ op = op.restrict(top)
56
+ op
57
+ end
58
+ end
59
+
45
60
  private
46
61
 
47
62
  # Returns the tuple determinant.
@@ -29,6 +29,28 @@ module Bmg
29
29
  end
30
30
  end
31
31
 
32
+ def insert(arg)
33
+ case arg
34
+ when Hash then operand.insert(allbut_constants(arg))
35
+ when Relation then operand.insert(arg.allbut(constants.keys))
36
+ when Enumerable then operand.insert(arg.map{|t| allbut_constants(t) })
37
+ else
38
+ super
39
+ end
40
+ end
41
+
42
+ def update(tuple)
43
+ shared = tuple.keys & constants.keys
44
+ on_tuple = TupleAlgebra.project(tuple, shared)
45
+ on_const = TupleAlgebra.project(constants, shared)
46
+ raise InvalidUpdateError, "Cannot violate relvar predicate" unless on_tuple == on_const
47
+ operand.update(allbut_constants(tuple))
48
+ end
49
+
50
+ def delete
51
+ operand.delete
52
+ end
53
+
32
54
  def to_ast
33
55
  [ :constants, operand.to_ast, constants.dup ]
34
56
  end
@@ -78,6 +100,10 @@ module Bmg
78
100
  tuple.merge(@constants)
79
101
  end
80
102
 
103
+ def allbut_constants(tuple)
104
+ TupleAlgebra.allbut(tuple, constants.keys)
105
+ end
106
+
81
107
  end # class Constants
82
108
  end # module Operator
83
109
  end # module Bmg
@@ -32,10 +32,43 @@ module Bmg
32
32
  end
33
33
  end
34
34
 
35
+ def insert(arg)
36
+ case arg
37
+ when Hash then operand.insert(allbut_extkeys(arg))
38
+ when Relation then operand.insert(arg.allbut(extension.keys))
39
+ when Enumerable then operand.insert(arg.map{|t| allbut_extkeys(t) })
40
+ else
41
+ super
42
+ end
43
+ end
44
+
45
+ def update(tuple)
46
+ operand.update(allbut_extkeys(tuple))
47
+ end
48
+
49
+ def delete
50
+ operand.delete
51
+ end
52
+
35
53
  def to_ast
36
54
  [ :extend, operand.to_ast, extension.dup ]
37
55
  end
38
56
 
57
+ protected ### optimization
58
+
59
+ def _restrict(type, predicate)
60
+ top, bottom = predicate.and_split(extension.keys)
61
+ if top == predicate
62
+ super
63
+ else
64
+ op = operand
65
+ op = op.restrict(bottom)
66
+ op = op.extend(extension)
67
+ op = op.restrict(top)
68
+ op
69
+ end
70
+ end
71
+
39
72
  private
40
73
 
41
74
  def extend_it(tuple)
@@ -45,6 +78,10 @@ module Bmg
45
78
  }
46
79
  end
47
80
 
81
+ def allbut_extkeys(tuple)
82
+ TupleAlgebra.allbut(tuple, extension.keys)
83
+ end
84
+
48
85
  end # class Extend
49
86
  end # module Operator
50
87
  end # module Bmg
@@ -96,11 +96,11 @@ module Bmg
96
96
  private
97
97
 
98
98
  def tuple_project(tuple, on)
99
- on.each_with_object({}){|k,t| t[k] = tuple[k] }
99
+ TupleAlgebra.project(tuple, on)
100
100
  end
101
101
 
102
102
  def tuple_image(tuple, on)
103
- tuple.dup.delete_if{|k,_| on.include?(k) }
103
+ TupleAlgebra.allbut(tuple, on)
104
104
  end
105
105
 
106
106
  def image_type
@@ -40,6 +40,23 @@ module Bmg
40
40
  end
41
41
  end
42
42
 
43
+ def insert(arg)
44
+ case arg
45
+ when Hash then operand.insert(valid_tuple!(arg))
46
+ when Enumerable then operand.insert(arg.map{|t| valid_tuple!(t) })
47
+ else
48
+ super
49
+ end
50
+ end
51
+
52
+ def update(tuple)
53
+ operand.update(valid_tuple!(tuple))
54
+ end
55
+
56
+ def delete
57
+ operand.delete
58
+ end
59
+
43
60
  def to_ast
44
61
  [ :project, operand.to_ast, attrlist ]
45
62
  end
@@ -56,6 +73,12 @@ module Bmg
56
73
  tuple.delete_if{|k,_| !@attrlist.include?(k) }
57
74
  end
58
75
 
76
+ def valid_tuple!(tuple)
77
+ offending = tuple.keys - attrlist
78
+ raise InvalidUpdateError, "#{offending.inspect} cannot be updated" unless offending.empty?
79
+ tuple
80
+ end
81
+
59
82
  end # class Project
60
83
  end # module Operator
61
84
  end # module Bmg
@@ -31,25 +31,53 @@ module Bmg
31
31
 
32
32
  def each
33
33
  @operand.each do |tuple|
34
- yield rename(tuple)
34
+ yield rename(tuple, renaming)
35
35
  end
36
36
  end
37
37
 
38
+ def insert(arg)
39
+ case arg
40
+ when Hash then operand.insert(rename(arg, reverse_renaming))
41
+ when Relation then operand.insert(arg.rename(reverse_renaming))
42
+ when Enumerable then operand.insert(arg.map{|t| rename(t, reverse_renaming) })
43
+ else
44
+ super
45
+ end
46
+ end
47
+
48
+ def update(arg)
49
+ case arg
50
+ when Hash then operand.update(rename(arg, reverse_renaming))
51
+ else
52
+ super
53
+ end
54
+ end
55
+
56
+ def delete
57
+ operand.delete
58
+ end
59
+
38
60
  def to_ast
39
61
  [ :rename, operand.to_ast, renaming.dup ]
40
62
  end
41
63
 
64
+ protected ### optimization
65
+
66
+ def _restrict(type, predicate)
67
+ operand.restrict(predicate.rename(reverse_renaming)).rename(renaming)
68
+ end
69
+
42
70
  private
43
71
 
44
- def rename(tuple)
72
+ def rename(tuple, renaming)
45
73
  tuple.each_with_object({}){|(k,v),h|
46
- h[rename_key(k)] = v
74
+ h[renaming[k] || k] = v
47
75
  h
48
76
  }
49
77
  end
50
78
 
51
- def rename_key(k)
52
- @renaming[k] || k
79
+ def reverse_renaming
80
+ renaming.each_with_object({}){|(k,v),h| h[v] = k }
53
81
  end
54
82
 
55
83
  end # class Rename
@@ -35,6 +35,23 @@ module Bmg
35
35
  one_or_yield{ nil }
36
36
  end
37
37
 
38
+ def insert(arg)
39
+ raise InvalidUpdateError, "Cannot insert into this Relvar"
40
+ end
41
+
42
+ def update(arg)
43
+ raise InvalidUpdateError, "Cannot update this Relvar"
44
+ end
45
+
46
+ def delete
47
+ raise InvalidUpdateError, "Cannot delete from this Relvar"
48
+ end
49
+
50
+ # Returns a json representation
51
+ def to_json(*args, &bl)
52
+ to_a.to_json(*args, &bl)
53
+ end
54
+
38
55
  # Converts to an sexpr expression.
39
56
  def to_ast
40
57
  raise "Bmg is missing a feature!"
@@ -19,6 +19,18 @@ module Bmg
19
19
  @dataset.each(&bl)
20
20
  end
21
21
 
22
+ def delete
23
+ dataset.delete
24
+ end
25
+
26
+ def insert(arg)
27
+ dataset.insert(arg)
28
+ end
29
+
30
+ def update(arg)
31
+ dataset.update(arg)
32
+ end
33
+
22
34
  def to_ast
23
35
  [:sequel, @dataset.sql]
24
36
  end
@@ -0,0 +1 @@
1
+ require_relative 'support/tuple_algebra'
@@ -0,0 +1,15 @@
1
+ module Bmg
2
+ module TupleAlgebra
3
+
4
+ def allbut(tuple, butlist)
5
+ tuple.reject{|k,v| butlist.include?(k) }
6
+ end
7
+ module_function :allbut
8
+
9
+ def project(tuple, attrlist)
10
+ tuple.reject{|k,v| !attrlist.include?(k) }
11
+ end
12
+ module_function :project
13
+
14
+ end # module TupleAlgebra
15
+ end # module Bmg
@@ -1,8 +1,8 @@
1
1
  module Bmg
2
2
  module Version
3
3
  MAJOR = 0
4
- MINOR = 4
5
- TINY = 1
4
+ MINOR = 5
5
+ TINY = 0
6
6
  end
7
7
  VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::TINY}"
8
8
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bmg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bernard Lambeau
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.2'
19
+ version: '1.3'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.2'
26
+ version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -141,6 +141,8 @@ files:
141
141
  - lib/bmg/relation/empty.rb
142
142
  - lib/bmg/sequel.rb
143
143
  - lib/bmg/sequel/relation.rb
144
+ - lib/bmg/support.rb
145
+ - lib/bmg/support/tuple_algebra.rb
144
146
  - lib/bmg/type.rb
145
147
  - lib/bmg/version.rb
146
148
  - tasks/gem.rake