bmg 0.19.1 → 0.20.1
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 +4 -4
 - data/README.md +39 -2
 - data/lib/bmg/operator/allbut.rb +4 -4
 - data/lib/bmg/operator/constants.rb +25 -25
 - data/lib/bmg/operator/extend.rb +10 -5
 - data/lib/bmg/operator/project.rb +4 -4
 - data/lib/bmg/operator/rename.rb +5 -4
 - data/lib/bmg/operator/restrict.rb +12 -0
 - data/lib/bmg/relation/in_memory/mutable.rb +23 -0
 - data/lib/bmg/relation/in_memory.rb +1 -0
 - data/lib/bmg/relation.rb +6 -6
 - data/lib/bmg/sequel/predicate_translator.rb +22 -0
 - data/lib/bmg/sequel/relation.rb +18 -4
 - data/lib/bmg/sequel/translator.rb +6 -22
 - data/lib/bmg/sequel.rb +1 -0
 - data/lib/bmg/sql/processor/extend.rb +33 -0
 - data/lib/bmg/sql/processor/reorder.rb +1 -1
 - data/lib/bmg/sql/processor/where.rb +2 -1
 - data/lib/bmg/sql/processor.rb +1 -0
 - data/lib/bmg/sql/relation.rb +20 -3
 - data/lib/bmg/version.rb +1 -1
 - data/lib/bmg.rb +5 -0
 - metadata +5 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 35789fefdd2032b4e807b730fb2fc6f5abe163e1
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 2f20b907d1f66560cbe802c6b3fe3e4064b7bfd0
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 8c1182190f70a94825505f358701e3ba728eadcfe7026da40f10b7b7dc9b2ff21d8f2f9ec2ccf24baa880b81728e9ef530830e168a33a2742a196c135445d0e5
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: b2e7ef1f3bf5983cfd3ff6fbaff820a04f9f118e39df88728ad6c87fec7261269b9fe22f60d44f9d141ce47c78db5e91399345475835f5c88c7b44b16a1c5873
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -1,7 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # Bmg, a relational algebra (Alf's successor)!
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            [](https://travis-ci.com/enspirit/bmg)
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
3 
     | 
    
         
             
            Bmg is a relational algebra implemented as a ruby library. It implements the
         
     | 
| 
       6 
4 
     | 
    
         
             
            [Relation as First-Class Citizen](http://www.try-alf.org/blog/2013-10-21-relations-as-first-class-citizen)
         
     | 
| 
       7 
5 
     | 
    
         
             
            paradigm contributed with [Alf](http://www.try-alf.org/) a few years ago.
         
     | 
| 
         @@ -18,6 +16,7 @@ further down this README. 
     | 
|
| 
       18 
16 
     | 
    
         
             
              * [Memory relations](#memory-relations)
         
     | 
| 
       19 
17 
     | 
    
         
             
              * [Connecting to SQL databases](#connecting-to-sql-databases)
         
     | 
| 
       20 
18 
     | 
    
         
             
              * [Reading files (csv, excel, text)](#reading-files-csv-excel-text)
         
     | 
| 
      
 19 
     | 
    
         
            +
              * [Connecting to Redis databases](#connecting-to-redis-databases)
         
     | 
| 
       21 
20 
     | 
    
         
             
              * [Your own relations](#your-own-relations)
         
     | 
| 
       22 
21 
     | 
    
         
             
            * [List of supported operators](#supported-operators)
         
     | 
| 
       23 
22 
     | 
    
         
             
            * [How is this different?](#how-is-this-different)
         
     | 
| 
         @@ -174,6 +173,43 @@ r.type.attrlist 
     | 
|
| 
       174 
173 
     | 
    
         
             
            In this scenario, non matching lines are skipped. The `:line` attribute keeps
         
     | 
| 
       175 
174 
     | 
    
         
             
            being used to have at least one candidate key (so to speak).
         
     | 
| 
       176 
175 
     | 
    
         | 
| 
      
 176 
     | 
    
         
            +
            ### Connecting to Redis databases
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
            Bmg currently requires `bmg-redis` and `redis >= 4.6` to connect
         
     | 
| 
      
 179 
     | 
    
         
            +
            to Redis databases. You also need to require `bmg/redis`.
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
            ```Gemfile
         
     | 
| 
      
 182 
     | 
    
         
            +
            gem 'bmg'
         
     | 
| 
      
 183 
     | 
    
         
            +
            gem 'bmg-redis'
         
     | 
| 
      
 184 
     | 
    
         
            +
            ```
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 187 
     | 
    
         
            +
            require 'redis'      #  also done by 'bmg/redis' below
         
     | 
| 
      
 188 
     | 
    
         
            +
            require 'bmg'
         
     | 
| 
      
 189 
     | 
    
         
            +
            require 'bmg/redis'
         
     | 
| 
      
 190 
     | 
    
         
            +
            ```
         
     | 
| 
      
 191 
     | 
    
         
            +
             
     | 
| 
      
 192 
     | 
    
         
            +
            Then, you can create Redis relation variables (aka relvars) like
         
     | 
| 
      
 193 
     | 
    
         
            +
            this:
         
     | 
| 
      
 194 
     | 
    
         
            +
             
     | 
| 
      
 195 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 196 
     | 
    
         
            +
            type = Bmg::Type::ANY.with_keys([[:id]])
         
     | 
| 
      
 197 
     | 
    
         
            +
            r = Bmg.redis(type, {
         
     | 
| 
      
 198 
     | 
    
         
            +
              key_prefix: "suppliers",
         
     | 
| 
      
 199 
     | 
    
         
            +
              redis: Redis.new,
         
     | 
| 
      
 200 
     | 
    
         
            +
              serializer: :marshal
         
     | 
| 
      
 201 
     | 
    
         
            +
            })
         
     | 
| 
      
 202 
     | 
    
         
            +
            ```
         
     | 
| 
      
 203 
     | 
    
         
            +
             
     | 
| 
      
 204 
     | 
    
         
            +
            The key prefix will be used to distinguish the tuples from other
         
     | 
| 
      
 205 
     | 
    
         
            +
            elements in the same database (e.g. tuples from other relvars).
         
     | 
| 
      
 206 
     | 
    
         
            +
            The serializer is either `:marshal` or `:json`. Please note that
         
     | 
| 
      
 207 
     | 
    
         
            +
            types are not preserved when using the second one (all attribute
         
     | 
| 
      
 208 
     | 
    
         
            +
            values will come back as strings, but keys will be symbolized).
         
     | 
| 
      
 209 
     | 
    
         
            +
             
     | 
| 
      
 210 
     | 
    
         
            +
            The redis relvars support basic algorithms for insert/update/delete.
         
     | 
| 
      
 211 
     | 
    
         
            +
            No optimization is currently supported.
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
       177 
213 
     | 
    
         
             
            ### Your own relations
         
     | 
| 
       178 
214 
     | 
    
         | 
| 
       179 
215 
     | 
    
         
             
            As noted earlier, Bmg has a simple relation interface where you only have to
         
     | 
| 
         @@ -210,6 +246,7 @@ r.autowrap(split: '_')                       # structure a flat relation, split: 
     | 
|
| 
       210 
246 
     | 
    
         
             
            r.autosummarize([:a, :b, ...], x: :sum)      # (experimental) usual summarizers supported
         
     | 
| 
       211 
247 
     | 
    
         
             
            r.constants(x: 12, ...)                      # add constant attributes (sometimes useful in unions)
         
     | 
| 
       212 
248 
     | 
    
         
             
            r.extend(x: ->(t){ ... }, ...)               # add computed attributes
         
     | 
| 
      
 249 
     | 
    
         
            +
            r.extend(x: :y)                              # shortcut for r.extend(x: ->(t){ t[:y] })
         
     | 
| 
       213 
250 
     | 
    
         
             
            r.exclude(predicate)                         # shortcut for restrict(!predicate)
         
     | 
| 
       214 
251 
     | 
    
         
             
            r.group([:a, :b, ...], :x)                   # relation-valued attribute from attributes
         
     | 
| 
       215 
252 
     | 
    
         
             
            r.image(right, :x, [:a, :b, ...])            # relation-valued attribute from another relation
         
     | 
    
        data/lib/bmg/operator/allbut.rb
    CHANGED
    
    | 
         @@ -50,12 +50,12 @@ module Bmg 
     | 
|
| 
       50 
50 
     | 
    
         
             
                    end
         
     | 
| 
       51 
51 
     | 
    
         
             
                  end
         
     | 
| 
       52 
52 
     | 
    
         | 
| 
       53 
     | 
    
         
            -
                  def update(tuple)
         
     | 
| 
       54 
     | 
    
         
            -
                    operand.update(valid_tuple!(tuple))
         
     | 
| 
      
 53 
     | 
    
         
            +
                  def update(tuple, predicate = Predicate.tautology)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    operand.update(valid_tuple!(tuple), predicate)
         
     | 
| 
       55 
55 
     | 
    
         
             
                  end
         
     | 
| 
       56 
56 
     | 
    
         | 
| 
       57 
     | 
    
         
            -
                  def delete
         
     | 
| 
       58 
     | 
    
         
            -
                    operand.delete
         
     | 
| 
      
 57 
     | 
    
         
            +
                  def delete(predicate = Predicate.tautology)
         
     | 
| 
      
 58 
     | 
    
         
            +
                    operand.delete(predicate)
         
     | 
| 
       59 
59 
     | 
    
         
             
                  end
         
     | 
| 
       60 
60 
     | 
    
         | 
| 
       61 
61 
     | 
    
         
             
                  def to_ast
         
     | 
| 
         @@ -10,15 +10,15 @@ module Bmg 
     | 
|
| 
       10 
10 
     | 
    
         
             
                class Constants
         
     | 
| 
       11 
11 
     | 
    
         
             
                  include Operator::Unary
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
                  def initialize(type, operand,  
     | 
| 
      
 13 
     | 
    
         
            +
                  def initialize(type, operand, the_constants)
         
     | 
| 
       14 
14 
     | 
    
         
             
                    @type = type
         
     | 
| 
       15 
15 
     | 
    
         
             
                    @operand = operand
         
     | 
| 
       16 
     | 
    
         
            -
                    @ 
     | 
| 
      
 16 
     | 
    
         
            +
                    @the_constants = the_constants
         
     | 
| 
       17 
17 
     | 
    
         
             
                  end
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
       19 
19 
     | 
    
         
             
                protected
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
                  attr_reader : 
     | 
| 
      
 21 
     | 
    
         
            +
                  attr_reader :the_constants
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
       23 
23 
     | 
    
         
             
                public
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
         @@ -32,27 +32,27 @@ module Bmg 
     | 
|
| 
       32 
32 
     | 
    
         
             
                  def insert(arg)
         
     | 
| 
       33 
33 
     | 
    
         
             
                    case arg
         
     | 
| 
       34 
34 
     | 
    
         
             
                    when Hash       then operand.insert(allbut_constants(arg))
         
     | 
| 
       35 
     | 
    
         
            -
                    when Relation   then operand.insert(arg.allbut( 
     | 
| 
      
 35 
     | 
    
         
            +
                    when Relation   then operand.insert(arg.allbut(the_constants.keys))
         
     | 
| 
       36 
36 
     | 
    
         
             
                    when Enumerable then operand.insert(arg.map{|t| allbut_constants(t) })
         
     | 
| 
       37 
37 
     | 
    
         
             
                    else
         
     | 
| 
       38 
38 
     | 
    
         
             
                      super
         
     | 
| 
       39 
39 
     | 
    
         
             
                    end
         
     | 
| 
       40 
40 
     | 
    
         
             
                  end
         
     | 
| 
       41 
41 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
                  def update(tuple)
         
     | 
| 
       43 
     | 
    
         
            -
                    shared = tuple.keys &  
     | 
| 
      
 42 
     | 
    
         
            +
                  def update(tuple, predicate = Predicate.tautology)
         
     | 
| 
      
 43 
     | 
    
         
            +
                    shared = tuple.keys & the_constants.keys
         
     | 
| 
       44 
44 
     | 
    
         
             
                    on_tuple = TupleAlgebra.project(tuple, shared)
         
     | 
| 
       45 
     | 
    
         
            -
                    on_const = TupleAlgebra.project( 
     | 
| 
      
 45 
     | 
    
         
            +
                    on_const = TupleAlgebra.project(the_constants, shared)
         
     | 
| 
       46 
46 
     | 
    
         
             
                    raise InvalidUpdateError, "Cannot violate relvar predicate" unless on_tuple == on_const
         
     | 
| 
       47 
     | 
    
         
            -
                    operand.update(allbut_constants(tuple))
         
     | 
| 
      
 47 
     | 
    
         
            +
                    operand.update(allbut_constants(tuple), predicate)
         
     | 
| 
       48 
48 
     | 
    
         
             
                  end
         
     | 
| 
       49 
49 
     | 
    
         | 
| 
       50 
     | 
    
         
            -
                  def delete
         
     | 
| 
       51 
     | 
    
         
            -
                    operand.delete
         
     | 
| 
      
 50 
     | 
    
         
            +
                  def delete(predicate = Predicate.tautology)
         
     | 
| 
      
 51 
     | 
    
         
            +
                    operand.delete(predicate)
         
     | 
| 
       52 
52 
     | 
    
         
             
                  end
         
     | 
| 
       53 
53 
     | 
    
         | 
| 
       54 
54 
     | 
    
         
             
                  def to_ast
         
     | 
| 
       55 
     | 
    
         
            -
                    [ :constants, operand.to_ast,  
     | 
| 
      
 55 
     | 
    
         
            +
                    [ :constants, operand.to_ast, the_constants.dup ]
         
     | 
| 
       56 
56 
     | 
    
         
             
                  end
         
     | 
| 
       57 
57 
     | 
    
         | 
| 
       58 
58 
     | 
    
         
             
                public ### for internal reasons
         
     | 
| 
         @@ -65,32 +65,32 @@ module Bmg 
     | 
|
| 
       65 
65 
     | 
    
         | 
| 
       66 
66 
     | 
    
         
             
                  def _page(type, ordering, page_index, options)
         
     | 
| 
       67 
67 
     | 
    
         
             
                    attrs = ordering.map{|(k,v)| k}
         
     | 
| 
       68 
     | 
    
         
            -
                    cs_attrs =  
     | 
| 
      
 68 
     | 
    
         
            +
                    cs_attrs = the_constants.keys
         
     | 
| 
       69 
69 
     | 
    
         
             
                    if (attrs & cs_attrs).empty?
         
     | 
| 
       70 
70 
     | 
    
         
             
                      operand
         
     | 
| 
       71 
71 
     | 
    
         
             
                        .page(ordering, page_index, options)
         
     | 
| 
       72 
     | 
    
         
            -
                        .constants( 
     | 
| 
      
 72 
     | 
    
         
            +
                        .constants(the_constants)
         
     | 
| 
       73 
73 
     | 
    
         
             
                    else
         
     | 
| 
       74 
74 
     | 
    
         
             
                      super
         
     | 
| 
       75 
75 
     | 
    
         
             
                    end
         
     | 
| 
       76 
76 
     | 
    
         
             
                  end
         
     | 
| 
       77 
77 
     | 
    
         | 
| 
       78 
78 
     | 
    
         
             
                  def _restrict(type, predicate)
         
     | 
| 
       79 
     | 
    
         
            -
                    # bottom_p makes no reference to  
     | 
| 
      
 79 
     | 
    
         
            +
                    # bottom_p makes no reference to the_constants, top_p possibly
         
     | 
| 
       80 
80 
     | 
    
         
             
                    # does...
         
     | 
| 
       81 
     | 
    
         
            -
                    top_p, bottom_p = predicate.and_split( 
     | 
| 
      
 81 
     | 
    
         
            +
                    top_p, bottom_p = predicate.and_split(the_constants.keys)
         
     | 
| 
       82 
82 
     | 
    
         
             
                    if top_p.tautology?
         
     | 
| 
       83 
     | 
    
         
            -
                      # push all situation: predicate made no reference to  
     | 
| 
      
 83 
     | 
    
         
            +
                      # push all situation: predicate made no reference to the_constants
         
     | 
| 
       84 
84 
     | 
    
         
             
                      result = operand
         
     | 
| 
       85 
85 
     | 
    
         
             
                      result = result.restrict(bottom_p)
         
     | 
| 
       86 
     | 
    
         
            -
                      result = result.constants( 
     | 
| 
      
 86 
     | 
    
         
            +
                      result = result.constants(the_constants)
         
     | 
| 
       87 
87 
     | 
    
         
             
                      result
         
     | 
| 
       88 
     | 
    
         
            -
                    elsif (top_p.free_variables -  
     | 
| 
       89 
     | 
    
         
            -
                      # top_p applies to  
     | 
| 
       90 
     | 
    
         
            -
                      if eval = top_p.evaluate( 
     | 
| 
      
 88 
     | 
    
         
            +
                    elsif (top_p.free_variables - the_constants.keys).empty?
         
     | 
| 
      
 89 
     | 
    
         
            +
                      # top_p applies to the_constants only
         
     | 
| 
      
 90 
     | 
    
         
            +
                      if eval = top_p.evaluate(the_constants)
         
     | 
| 
       91 
91 
     | 
    
         
             
                        result = operand
         
     | 
| 
       92 
92 
     | 
    
         
             
                        result = result.restrict(bottom_p)
         
     | 
| 
       93 
     | 
    
         
            -
                        result = result.constants( 
     | 
| 
      
 93 
     | 
    
         
            +
                        result = result.constants(the_constants)
         
     | 
| 
       94 
94 
     | 
    
         
             
                        result
         
     | 
| 
       95 
95 
     | 
    
         
             
                      else
         
     | 
| 
       96 
96 
     | 
    
         
             
                        Relation.empty(type)
         
     | 
| 
         @@ -104,7 +104,7 @@ module Bmg 
     | 
|
| 
       104 
104 
     | 
    
         
             
                      # of them
         
     | 
| 
       105 
105 
     | 
    
         
             
                      result = operand
         
     | 
| 
       106 
106 
     | 
    
         
             
                      result = result.restrict(bottom_p)
         
     | 
| 
       107 
     | 
    
         
            -
                      result = result.constants( 
     | 
| 
      
 107 
     | 
    
         
            +
                      result = result.constants(the_constants)
         
     | 
| 
       108 
108 
     | 
    
         
             
                      result = result.restrict(top_p)
         
     | 
| 
       109 
109 
     | 
    
         
             
                      result
         
     | 
| 
       110 
110 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -115,17 +115,17 @@ module Bmg 
     | 
|
| 
       115 
115 
     | 
    
         
             
                protected ### inspect
         
     | 
| 
       116 
116 
     | 
    
         | 
| 
       117 
117 
     | 
    
         
             
                  def args
         
     | 
| 
       118 
     | 
    
         
            -
                    [  
     | 
| 
      
 118 
     | 
    
         
            +
                    [ the_constants ]
         
     | 
| 
       119 
119 
     | 
    
         
             
                  end
         
     | 
| 
       120 
120 
     | 
    
         | 
| 
       121 
121 
     | 
    
         
             
                private
         
     | 
| 
       122 
122 
     | 
    
         | 
| 
       123 
123 
     | 
    
         
             
                  def extend_it(tuple)
         
     | 
| 
       124 
     | 
    
         
            -
                    tuple.merge(@ 
     | 
| 
      
 124 
     | 
    
         
            +
                    tuple.merge(@the_constants)
         
     | 
| 
       125 
125 
     | 
    
         
             
                  end
         
     | 
| 
       126 
126 
     | 
    
         | 
| 
       127 
127 
     | 
    
         
             
                  def allbut_constants(tuple)
         
     | 
| 
       128 
     | 
    
         
            -
                    TupleAlgebra.allbut(tuple,  
     | 
| 
      
 128 
     | 
    
         
            +
                    TupleAlgebra.allbut(tuple, the_constants.keys)
         
     | 
| 
       129 
129 
     | 
    
         
             
                  end
         
     | 
| 
       130 
130 
     | 
    
         | 
| 
       131 
131 
     | 
    
         
             
                end # class Constants
         
     | 
    
        data/lib/bmg/operator/extend.rb
    CHANGED
    
    | 
         @@ -42,12 +42,12 @@ module Bmg 
     | 
|
| 
       42 
42 
     | 
    
         
             
                    end
         
     | 
| 
       43 
43 
     | 
    
         
             
                  end
         
     | 
| 
       44 
44 
     | 
    
         | 
| 
       45 
     | 
    
         
            -
                  def update(tuple)
         
     | 
| 
       46 
     | 
    
         
            -
                    operand.update(allbut_extkeys(tuple))
         
     | 
| 
      
 45 
     | 
    
         
            +
                  def update(tuple, predicate = Predicate.tautology)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    operand.update(allbut_extkeys(tuple), predicate)
         
     | 
| 
       47 
47 
     | 
    
         
             
                  end
         
     | 
| 
       48 
48 
     | 
    
         | 
| 
       49 
     | 
    
         
            -
                  def delete
         
     | 
| 
       50 
     | 
    
         
            -
                    operand.delete
         
     | 
| 
      
 49 
     | 
    
         
            +
                  def delete(predicate = Predicate.tautology)
         
     | 
| 
      
 50 
     | 
    
         
            +
                    operand.delete(predicate)
         
     | 
| 
       51 
51 
     | 
    
         
             
                  end
         
     | 
| 
       52 
52 
     | 
    
         | 
| 
       53 
53 
     | 
    
         
             
                  def to_ast
         
     | 
| 
         @@ -160,7 +160,12 @@ module Bmg 
     | 
|
| 
       160 
160 
     | 
    
         | 
| 
       161 
161 
     | 
    
         
             
                  def extend_it(tuple)
         
     | 
| 
       162 
162 
     | 
    
         
             
                    @extension.each_with_object(tuple.dup) { |(k,v), memo|
         
     | 
| 
       163 
     | 
    
         
            -
                      memo[k] = v 
     | 
| 
      
 163 
     | 
    
         
            +
                      memo[k] = case v
         
     | 
| 
      
 164 
     | 
    
         
            +
                      when Symbol
         
     | 
| 
      
 165 
     | 
    
         
            +
                        tuple[v]
         
     | 
| 
      
 166 
     | 
    
         
            +
                      else
         
     | 
| 
      
 167 
     | 
    
         
            +
                        v.call(tuple)
         
     | 
| 
      
 168 
     | 
    
         
            +
                      end
         
     | 
| 
       164 
169 
     | 
    
         
             
                      memo
         
     | 
| 
       165 
170 
     | 
    
         
             
                    }
         
     | 
| 
       166 
171 
     | 
    
         
             
                  end
         
     | 
    
        data/lib/bmg/operator/project.rb
    CHANGED
    
    | 
         @@ -49,12 +49,12 @@ module Bmg 
     | 
|
| 
       49 
49 
     | 
    
         
             
                    end
         
     | 
| 
       50 
50 
     | 
    
         
             
                  end
         
     | 
| 
       51 
51 
     | 
    
         | 
| 
       52 
     | 
    
         
            -
                  def update(tuple)
         
     | 
| 
       53 
     | 
    
         
            -
                    operand.update(valid_tuple!(tuple))
         
     | 
| 
      
 52 
     | 
    
         
            +
                  def update(tuple, predicate = Predicate.tautology)
         
     | 
| 
      
 53 
     | 
    
         
            +
                    operand.update(valid_tuple!(tuple), predicate)
         
     | 
| 
       54 
54 
     | 
    
         
             
                  end
         
     | 
| 
       55 
55 
     | 
    
         | 
| 
       56 
     | 
    
         
            -
                  def delete
         
     | 
| 
       57 
     | 
    
         
            -
                    operand.delete
         
     | 
| 
      
 56 
     | 
    
         
            +
                  def delete(predicate = Predicate.tautology)
         
     | 
| 
      
 57 
     | 
    
         
            +
                    operand.delete(predicate)
         
     | 
| 
       58 
58 
     | 
    
         
             
                  end
         
     | 
| 
       59 
59 
     | 
    
         | 
| 
       60 
60 
     | 
    
         
             
                  def to_ast
         
     | 
    
        data/lib/bmg/operator/rename.rb
    CHANGED
    
    | 
         @@ -45,16 +45,17 @@ module Bmg 
     | 
|
| 
       45 
45 
     | 
    
         
             
                    end
         
     | 
| 
       46 
46 
     | 
    
         
             
                  end
         
     | 
| 
       47 
47 
     | 
    
         | 
| 
       48 
     | 
    
         
            -
                  def update(arg)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  def update(arg, predicate = Predicate.tautology)
         
     | 
| 
       49 
49 
     | 
    
         
             
                    case arg
         
     | 
| 
       50 
     | 
    
         
            -
                    when Hash 
     | 
| 
      
 50 
     | 
    
         
            +
                    when Hash
         
     | 
| 
      
 51 
     | 
    
         
            +
                      operand.update(rename_tuple(arg, reverse_renaming), predicate)
         
     | 
| 
       51 
52 
     | 
    
         
             
                    else
         
     | 
| 
       52 
53 
     | 
    
         
             
                      super
         
     | 
| 
       53 
54 
     | 
    
         
             
                    end
         
     | 
| 
       54 
55 
     | 
    
         
             
                  end
         
     | 
| 
       55 
56 
     | 
    
         | 
| 
       56 
     | 
    
         
            -
                  def delete
         
     | 
| 
       57 
     | 
    
         
            -
                    operand.delete
         
     | 
| 
      
 57 
     | 
    
         
            +
                  def delete(predicate = Predicate.tautology)
         
     | 
| 
      
 58 
     | 
    
         
            +
                    operand.delete(predicate)
         
     | 
| 
       58 
59 
     | 
    
         
             
                  end
         
     | 
| 
       59 
60 
     | 
    
         | 
| 
       60 
61 
     | 
    
         
             
                  def to_ast
         
     | 
| 
         @@ -32,6 +32,18 @@ module Bmg 
     | 
|
| 
       32 
32 
     | 
    
         
             
                    end
         
     | 
| 
       33 
33 
     | 
    
         
             
                  end
         
     | 
| 
       34 
34 
     | 
    
         | 
| 
      
 35 
     | 
    
         
            +
                  def insert(tuple)
         
     | 
| 
      
 36 
     | 
    
         
            +
                    operand.insert(tuple)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  def update(updating, predicate = Predicate.tautology)
         
     | 
| 
      
 40 
     | 
    
         
            +
                    operand.update(updating, predicate & self.predicate)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  def delete(predicate = Predicate.tautology)
         
     | 
| 
      
 44 
     | 
    
         
            +
                    operand.delete(predicate & self.predicate)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
       35 
47 
     | 
    
         
             
                  def to_ast
         
     | 
| 
       36 
48 
     | 
    
         
             
                    [ :restrict, operand.to_ast, predicate.sexpr ]
         
     | 
| 
       37 
49 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Bmg
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Relation
         
     | 
| 
      
 3 
     | 
    
         
            +
                class InMemory
         
     | 
| 
      
 4 
     | 
    
         
            +
                  class Mutable < InMemory
         
     | 
| 
      
 5 
     | 
    
         
            +
                    def insert(arg)
         
     | 
| 
      
 6 
     | 
    
         
            +
                      raise ArgumentError unless arg.is_a?(Hash)
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                      @operand << arg.dup
         
     | 
| 
      
 9 
     | 
    
         
            +
                    end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                    def update(updating, predicate = Predicate.tautology)
         
     | 
| 
      
 12 
     | 
    
         
            +
                      @operand = @operand.map{|t|
         
     | 
| 
      
 13 
     | 
    
         
            +
                        predicate.call(t) ? t.merge(updating) : t
         
     | 
| 
      
 14 
     | 
    
         
            +
                      }
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    def delete(predicate = Predicate.tautology)
         
     | 
| 
      
 18 
     | 
    
         
            +
                      @operand = @operand.select{|t| predicate.call(t) }
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end # class Mutable
         
     | 
| 
      
 21 
     | 
    
         
            +
                end # class InMemory
         
     | 
| 
      
 22 
     | 
    
         
            +
              end # module Relation
         
     | 
| 
      
 23 
     | 
    
         
            +
            end # module Bmg
         
     | 
    
        data/lib/bmg/relation.rb
    CHANGED
    
    | 
         @@ -74,16 +74,16 @@ module Bmg 
     | 
|
| 
       74 
74 
     | 
    
         
             
                  one_or_yield{ nil }
         
     | 
| 
       75 
75 
     | 
    
         
             
                end
         
     | 
| 
       76 
76 
     | 
    
         | 
| 
       77 
     | 
    
         
            -
                def insert( 
     | 
| 
       78 
     | 
    
         
            -
                  raise InvalidUpdateError, "Cannot insert into  
     | 
| 
      
 77 
     | 
    
         
            +
                def insert(*args, &bl)
         
     | 
| 
      
 78 
     | 
    
         
            +
                  raise InvalidUpdateError, "Cannot insert into #{self.class.name}"
         
     | 
| 
       79 
79 
     | 
    
         
             
                end
         
     | 
| 
       80 
80 
     | 
    
         | 
| 
       81 
     | 
    
         
            -
                def update( 
     | 
| 
       82 
     | 
    
         
            -
                  raise InvalidUpdateError, "Cannot update  
     | 
| 
      
 81 
     | 
    
         
            +
                def update(*args, &bl)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  raise InvalidUpdateError, "Cannot update #{self.class.name}"
         
     | 
| 
       83 
83 
     | 
    
         
             
                end
         
     | 
| 
       84 
84 
     | 
    
         | 
| 
       85 
     | 
    
         
            -
                def delete
         
     | 
| 
       86 
     | 
    
         
            -
                  raise InvalidUpdateError, "Cannot delete from  
     | 
| 
      
 85 
     | 
    
         
            +
                def delete(*args, &bl)
         
     | 
| 
      
 86 
     | 
    
         
            +
                  raise InvalidUpdateError, "Cannot delete from #{self.class.name}"
         
     | 
| 
       87 
87 
     | 
    
         
             
                end
         
     | 
| 
       88 
88 
     | 
    
         | 
| 
       89 
89 
     | 
    
         
             
                def visit(&visitor)
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Bmg
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Sequel
         
     | 
| 
      
 3 
     | 
    
         
            +
                class PredicateTranslator < Sexpr::Processor
         
     | 
| 
      
 4 
     | 
    
         
            +
                  include ::Predicate::ToSequel::Methods
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  def initialize(parent)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @parent = parent
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                public ### Predicate hack
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def on_opaque(sexpr)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @parent.apply(sexpr.last)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def on_exists(sexpr)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    @parent.apply(sexpr.last).exists
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                end # class PredicateTranslator
         
     | 
| 
      
 21 
     | 
    
         
            +
              end # module Sequel
         
     | 
| 
      
 22 
     | 
    
         
            +
            end # module Bmg
         
     | 
    
        data/lib/bmg/sequel/relation.rb
    CHANGED
    
    | 
         @@ -13,8 +13,13 @@ module Bmg 
     | 
|
| 
       13 
13 
     | 
    
         
             
                    dataset.each(&bl)
         
     | 
| 
       14 
14 
     | 
    
         
             
                  end
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
                  def delete
         
     | 
| 
       17 
     | 
    
         
            -
                    base_table 
     | 
| 
      
 16 
     | 
    
         
            +
                  def delete(predicate = Predicate.tautology)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    target = base_table
         
     | 
| 
      
 18 
     | 
    
         
            +
                    unless predicate.tautology?
         
     | 
| 
      
 19 
     | 
    
         
            +
                      compiled = compile_predicate(predicate)
         
     | 
| 
      
 20 
     | 
    
         
            +
                      target = base_table.where(compiled)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
                    target.delete
         
     | 
| 
       18 
23 
     | 
    
         
             
                  end
         
     | 
| 
       19 
24 
     | 
    
         | 
| 
       20 
25 
     | 
    
         
             
                  def insert(arg)
         
     | 
| 
         @@ -30,8 +35,13 @@ module Bmg 
     | 
|
| 
       30 
35 
     | 
    
         
             
                    end
         
     | 
| 
       31 
36 
     | 
    
         
             
                  end
         
     | 
| 
       32 
37 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
                  def update(arg)
         
     | 
| 
       34 
     | 
    
         
            -
                    base_table 
     | 
| 
      
 38 
     | 
    
         
            +
                  def update(arg, predicate = Predicate.tautology)
         
     | 
| 
      
 39 
     | 
    
         
            +
                    target = base_table
         
     | 
| 
      
 40 
     | 
    
         
            +
                    unless predicate.tautology?
         
     | 
| 
      
 41 
     | 
    
         
            +
                      compiled = compile_predicate(predicate)
         
     | 
| 
      
 42 
     | 
    
         
            +
                      target = base_table.where(compiled)
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
                    target.update(arg)
         
     | 
| 
       35 
45 
     | 
    
         
             
                  end
         
     | 
| 
       36 
46 
     | 
    
         | 
| 
       37 
47 
     | 
    
         
             
                  def _count
         
     | 
| 
         @@ -73,6 +83,10 @@ module Bmg 
     | 
|
| 
       73 
83 
     | 
    
         
             
                    operand.expr
         
     | 
| 
       74 
84 
     | 
    
         
             
                  end
         
     | 
| 
       75 
85 
     | 
    
         | 
| 
      
 86 
     | 
    
         
            +
                  def compile_predicate(predicate)
         
     | 
| 
      
 87 
     | 
    
         
            +
                    Translator.new(sequel_db).compile_predicate(predicate)
         
     | 
| 
      
 88 
     | 
    
         
            +
                  end
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
       76 
90 
     | 
    
         
             
                end # class Relation
         
     | 
| 
       77 
91 
     | 
    
         
             
              end # module Sequel
         
     | 
| 
       78 
92 
     | 
    
         
             
            end # module Bmg
         
     | 
| 
         @@ -81,6 +81,7 @@ module Bmg 
     | 
|
| 
       81 
81 
     | 
    
         
             
                    case sexpr.func_name
         
     | 
| 
       82 
82 
     | 
    
         
             
                    when :cast
         
     | 
| 
       83 
83 
     | 
    
         
             
                      to_cast = apply(sexpr.func_args.first)
         
     | 
| 
      
 84 
     | 
    
         
            +
                      to_cast = ::Sequel.expr(nil) if to_cast.nil?
         
     | 
| 
       84 
85 
     | 
    
         
             
                      type = sexpr.func_args.last.last
         
     | 
| 
       85 
86 
     | 
    
         
             
                      to_cast.cast(type)
         
     | 
| 
       86 
87 
     | 
    
         
             
                    else
         
     | 
| 
         @@ -178,36 +179,19 @@ module Bmg 
     | 
|
| 
       178 
179 
     | 
    
         
             
                    sexpr.last
         
     | 
| 
       179 
180 
     | 
    
         
             
                  end
         
     | 
| 
       180 
181 
     | 
    
         | 
| 
       181 
     | 
    
         
            -
                 
     | 
| 
       182 
     | 
    
         
            -
             
     | 
| 
       183 
     | 
    
         
            -
                  def dataset(expr)
         
     | 
| 
       184 
     | 
    
         
            -
                    return expr if ::Sequel::Dataset===expr
         
     | 
| 
       185 
     | 
    
         
            -
                    sequel_db[expr]
         
     | 
| 
       186 
     | 
    
         
            -
                  end
         
     | 
| 
      
 182 
     | 
    
         
            +
                public
         
     | 
| 
       187 
183 
     | 
    
         | 
| 
       188 
184 
     | 
    
         
             
                  def compile_predicate(predicate)
         
     | 
| 
       189 
185 
     | 
    
         
             
                    PredicateTranslator.new(self).call(predicate)
         
     | 
| 
       190 
186 
     | 
    
         
             
                  end
         
     | 
| 
       191 
187 
     | 
    
         | 
| 
       192 
     | 
    
         
            -
                 
     | 
| 
       193 
     | 
    
         
            -
                  include ::Predicate::ToSequel::Methods
         
     | 
| 
       194 
     | 
    
         
            -
             
     | 
| 
       195 
     | 
    
         
            -
                  def initialize(parent)
         
     | 
| 
       196 
     | 
    
         
            -
                    @parent = parent
         
     | 
| 
       197 
     | 
    
         
            -
                  end
         
     | 
| 
       198 
     | 
    
         
            -
             
     | 
| 
       199 
     | 
    
         
            -
                public ### Predicate hack
         
     | 
| 
       200 
     | 
    
         
            -
             
     | 
| 
       201 
     | 
    
         
            -
                  def on_opaque(sexpr)
         
     | 
| 
       202 
     | 
    
         
            -
                    @parent.apply(sexpr.last)
         
     | 
| 
       203 
     | 
    
         
            -
                  end
         
     | 
| 
      
 188 
     | 
    
         
            +
                private
         
     | 
| 
       204 
189 
     | 
    
         | 
| 
       205 
     | 
    
         
            -
                  def  
     | 
| 
       206 
     | 
    
         
            -
                     
     | 
| 
      
 190 
     | 
    
         
            +
                  def dataset(expr)
         
     | 
| 
      
 191 
     | 
    
         
            +
                    return expr if ::Sequel::Dataset===expr
         
     | 
| 
      
 192 
     | 
    
         
            +
                    sequel_db[expr]
         
     | 
| 
       207 
193 
     | 
    
         
             
                  end
         
     | 
| 
       208 
194 
     | 
    
         | 
| 
       209 
     | 
    
         
            -
                end
         
     | 
| 
       210 
     | 
    
         
            -
             
     | 
| 
       211 
195 
     | 
    
         
             
                end # class Translator
         
     | 
| 
       212 
196 
     | 
    
         
             
              end # module Sequel
         
     | 
| 
       213 
197 
     | 
    
         
             
            end # module Bmg
         
     | 
    
        data/lib/bmg/sequel.rb
    CHANGED
    
    
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Bmg
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Sql
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Processor
         
     | 
| 
      
 4 
     | 
    
         
            +
                  class Extend < Processor
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                    def initialize(extension, builder)
         
     | 
| 
      
 7 
     | 
    
         
            +
                      super(builder)
         
     | 
| 
      
 8 
     | 
    
         
            +
                      @extension = extension
         
     | 
| 
      
 9 
     | 
    
         
            +
                    end
         
     | 
| 
      
 10 
     | 
    
         
            +
                    attr_reader :extension
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                    def on_set_operator(sexpr)
         
     | 
| 
      
 13 
     | 
    
         
            +
                      apply(builder.from_self(sexpr))
         
     | 
| 
      
 14 
     | 
    
         
            +
                    end
         
     | 
| 
      
 15 
     | 
    
         
            +
                    alias :on_union     :on_set_operator
         
     | 
| 
      
 16 
     | 
    
         
            +
                    alias :on_except    :on_set_operator
         
     | 
| 
      
 17 
     | 
    
         
            +
                    alias :on_intersect :on_set_operator
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    def on_select_star(sexpr)
         
     | 
| 
      
 20 
     | 
    
         
            +
                      raise NotImplementedError, "Extend on * is not supported"
         
     | 
| 
      
 21 
     | 
    
         
            +
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                    def on_select_list(sexpr)
         
     | 
| 
      
 24 
     | 
    
         
            +
                      sexpr + extension.each_pair.map{|(k,v)|
         
     | 
| 
      
 25 
     | 
    
         
            +
                        desaliased = sexpr.desaliaser[v]
         
     | 
| 
      
 26 
     | 
    
         
            +
                        [:select_item, desaliased, [:column_name, k] ]
         
     | 
| 
      
 27 
     | 
    
         
            +
                      }
         
     | 
| 
      
 28 
     | 
    
         
            +
                    end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  end # class Extend
         
     | 
| 
      
 31 
     | 
    
         
            +
                end # class Processor
         
     | 
| 
      
 32 
     | 
    
         
            +
              end # module Sql
         
     | 
| 
      
 33 
     | 
    
         
            +
            end # module Bmg
         
     | 
| 
         @@ -39,9 +39,10 @@ module Bmg 
     | 
|
| 
       39 
39 
     | 
    
         
             
                    def falsy?(sexpr)
         
     | 
| 
       40 
40 
     | 
    
         
             
                      return false unless sexpr.respond_to?(:predicate)
         
     | 
| 
       41 
41 
     | 
    
         
             
                      return false if sexpr.predicate.nil?
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
       42 
43 
     | 
    
         
             
                      left  = Predicate.new(Predicate::Grammar.sexpr(sexpr.predicate)).unqualify
         
     | 
| 
       43 
44 
     | 
    
         
             
                      right = Predicate.new(Predicate::Grammar.sexpr(@predicate.sexpr)).unqualify
         
     | 
| 
       44 
     | 
    
         
            -
                       
     | 
| 
      
 45 
     | 
    
         
            +
                      (left & right).contradiction?
         
     | 
| 
       45 
46 
     | 
    
         
             
                    end
         
     | 
| 
       46 
47 
     | 
    
         | 
| 
       47 
48 
     | 
    
         
             
                  end # class Where
         
     | 
    
        data/lib/bmg/sql/processor.rb
    CHANGED
    
    | 
         @@ -71,6 +71,7 @@ require_relative 'processor/distinct' 
     | 
|
| 
       71 
71 
     | 
    
         
             
            require_relative 'processor/all'
         
     | 
| 
       72 
72 
     | 
    
         
             
            require_relative 'processor/clip'
         
     | 
| 
       73 
73 
     | 
    
         
             
            require_relative 'processor/constants'
         
     | 
| 
      
 74 
     | 
    
         
            +
            require_relative 'processor/extend'
         
     | 
| 
       74 
75 
     | 
    
         
             
            require_relative 'processor/star'
         
     | 
| 
       75 
76 
     | 
    
         
             
            require_relative 'processor/rename'
         
     | 
| 
       76 
77 
     | 
    
         
             
            require_relative 'processor/order_by'
         
     | 
    
        data/lib/bmg/sql/relation.rb
    CHANGED
    
    | 
         @@ -27,15 +27,15 @@ module Bmg 
     | 
|
| 
       27 
27 
     | 
    
         
             
                    raise NotImplementedError
         
     | 
| 
       28 
28 
     | 
    
         
             
                  end
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
                  def delete
         
     | 
| 
      
 30 
     | 
    
         
            +
                  def delete(*args, &bl)
         
     | 
| 
       31 
31 
     | 
    
         
             
                    raise NotImplementedError
         
     | 
| 
       32 
32 
     | 
    
         
             
                  end
         
     | 
| 
       33 
33 
     | 
    
         | 
| 
       34 
     | 
    
         
            -
                  def insert( 
     | 
| 
      
 34 
     | 
    
         
            +
                  def insert(*args, &bl)
         
     | 
| 
       35 
35 
     | 
    
         
             
                    raise NotImplementedError
         
     | 
| 
       36 
36 
     | 
    
         
             
                  end
         
     | 
| 
       37 
37 
     | 
    
         | 
| 
       38 
     | 
    
         
            -
                  def update( 
     | 
| 
      
 38 
     | 
    
         
            +
                  def update(*args, &bl)
         
     | 
| 
       39 
39 
     | 
    
         
             
                    raise NotImplementedError
         
     | 
| 
       40 
40 
     | 
    
         
             
                  end
         
     | 
| 
       41 
41 
     | 
    
         | 
| 
         @@ -57,6 +57,23 @@ module Bmg 
     | 
|
| 
       57 
57 
     | 
    
         
             
                    _instance(type, builder, expr)
         
     | 
| 
       58 
58 
     | 
    
         
             
                  end
         
     | 
| 
       59 
59 
     | 
    
         | 
| 
      
 60 
     | 
    
         
            +
                  def _extend(type, extension)
         
     | 
| 
      
 61 
     | 
    
         
            +
                    supported, unsupported = {}, {}
         
     | 
| 
      
 62 
     | 
    
         
            +
                    extension.each_pair do |k,v|
         
     | 
| 
      
 63 
     | 
    
         
            +
                      (v.is_a?(Symbol) ? supported : unsupported)[k] = v
         
     | 
| 
      
 64 
     | 
    
         
            +
                    end
         
     | 
| 
      
 65 
     | 
    
         
            +
                    if supported.empty?
         
     | 
| 
      
 66 
     | 
    
         
            +
                      Operator::Extend.new(type, self, extension)
         
     | 
| 
      
 67 
     | 
    
         
            +
                    elsif unsupported.empty?
         
     | 
| 
      
 68 
     | 
    
         
            +
                      expr = Processor::Extend.new(supported, builder).call(self.expr)
         
     | 
| 
      
 69 
     | 
    
         
            +
                      _instance(type, builder, expr)
         
     | 
| 
      
 70 
     | 
    
         
            +
                    else
         
     | 
| 
      
 71 
     | 
    
         
            +
                      expr = Processor::Extend.new(supported, builder).call(self.expr)
         
     | 
| 
      
 72 
     | 
    
         
            +
                      operand = _instance(type.allbut(unsupported.keys), builder, expr)
         
     | 
| 
      
 73 
     | 
    
         
            +
                      Operator::Extend.new(type, operand, unsupported)
         
     | 
| 
      
 74 
     | 
    
         
            +
                    end
         
     | 
| 
      
 75 
     | 
    
         
            +
                  end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
       60 
77 
     | 
    
         
             
                  def _join(type, right, on)
         
     | 
| 
       61 
78 
     | 
    
         
             
                    if right_expr = extract_compatible_sexpr(right)
         
     | 
| 
       62 
79 
     | 
    
         
             
                      right_expr = Processor::Requalify.new(builder).call(right_expr)
         
     | 
    
        data/lib/bmg/version.rb
    CHANGED
    
    
    
        data/lib/bmg.rb
    CHANGED
    
    | 
         @@ -4,6 +4,11 @@ require 'forwardable' 
     | 
|
| 
       4 
4 
     | 
    
         
             
            require 'set'
         
     | 
| 
       5 
5 
     | 
    
         
             
            module Bmg
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
      
 7 
     | 
    
         
            +
              def mutable(enumerable, type = Type::ANY)
         
     | 
| 
      
 8 
     | 
    
         
            +
                Relation::InMemory::Mutable.new(type, enumerable).spied(main_spy)
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
              module_function :mutable
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
       7 
12 
     | 
    
         
             
              def in_memory(enumerable, type = Type::ANY)
         
     | 
| 
       8 
13 
     | 
    
         
             
                Relation::InMemory.new(type, enumerable).spied(main_spy)
         
     | 
| 
       9 
14 
     | 
    
         
             
              end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: bmg
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.20.1
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Bernard Lambeau
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2022- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2022-05-31 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: predicate
         
     | 
| 
         @@ -174,11 +174,13 @@ files: 
     | 
|
| 
       174 
174 
     | 
    
         
             
            - lib/bmg/relation.rb
         
     | 
| 
       175 
175 
     | 
    
         
             
            - lib/bmg/relation/empty.rb
         
     | 
| 
       176 
176 
     | 
    
         
             
            - lib/bmg/relation/in_memory.rb
         
     | 
| 
      
 177 
     | 
    
         
            +
            - lib/bmg/relation/in_memory/mutable.rb
         
     | 
| 
       177 
178 
     | 
    
         
             
            - lib/bmg/relation/materialized.rb
         
     | 
| 
       178 
179 
     | 
    
         
             
            - lib/bmg/relation/proxy.rb
         
     | 
| 
       179 
180 
     | 
    
         
             
            - lib/bmg/relation/spied.rb
         
     | 
| 
       180 
181 
     | 
    
         
             
            - lib/bmg/sequel.rb
         
     | 
| 
       181 
182 
     | 
    
         
             
            - lib/bmg/sequel/ext.rb
         
     | 
| 
      
 183 
     | 
    
         
            +
            - lib/bmg/sequel/predicate_translator.rb
         
     | 
| 
       182 
184 
     | 
    
         
             
            - lib/bmg/sequel/relation.rb
         
     | 
| 
       183 
185 
     | 
    
         
             
            - lib/bmg/sequel/translator.rb
         
     | 
| 
       184 
186 
     | 
    
         
             
            - lib/bmg/sequel/type_inference.rb
         
     | 
| 
         @@ -248,6 +250,7 @@ files: 
     | 
|
| 
       248 
250 
     | 
    
         
             
            - lib/bmg/sql/processor/clip.rb
         
     | 
| 
       249 
251 
     | 
    
         
             
            - lib/bmg/sql/processor/constants.rb
         
     | 
| 
       250 
252 
     | 
    
         
             
            - lib/bmg/sql/processor/distinct.rb
         
     | 
| 
      
 253 
     | 
    
         
            +
            - lib/bmg/sql/processor/extend.rb
         
     | 
| 
       251 
254 
     | 
    
         
             
            - lib/bmg/sql/processor/flatten.rb
         
     | 
| 
       252 
255 
     | 
    
         
             
            - lib/bmg/sql/processor/from_self.rb
         
     | 
| 
       253 
256 
     | 
    
         
             
            - lib/bmg/sql/processor/join.rb
         
     |