bud 0.1.0.pre1 → 0.9.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.
@@ -1,5 +1,6 @@
1
- require "set"
1
+ require 'set'
2
2
  require 'bud/collections'
3
+
3
4
  ELEMENT_BUFSIZE = 1
4
5
 
5
6
  module Bud
@@ -14,8 +15,8 @@ module Bud
14
15
  class PushElement < BudCollection
15
16
  attr_accessor :elem_name
16
17
  attr_accessor :rescan, :invalidated
17
- attr_reader :arity, :inputs, :found_delta, :refcount, :wired_by, :outputs
18
-
18
+ attr_reader :inputs, :found_delta, :refcount, :wired_by, :outputs
19
+
19
20
  def initialize(name_in, bud_instance, collection_name=nil, given_schema=nil, defer_schema=false, &blk)
20
21
  super(name_in, bud_instance, given_schema, defer_schema)
21
22
  @blk = blk
@@ -27,7 +28,6 @@ module Bud
27
28
  @elem_name = name_in
28
29
  @found_delta = false
29
30
  @refcount = 1
30
- @each_index = 0
31
31
  @collection_name = collection_name
32
32
  @invalidated = true
33
33
  @rescan = true
@@ -42,7 +42,7 @@ module Bud
42
42
  end
43
43
 
44
44
  public
45
- def print_wiring(depth=0, accum = "")
45
+ def print_wiring(depth=0, accum="")
46
46
  depth.times {print " "}
47
47
  puts "#{accum} #{(self.object_id*2).to_s(16)}: #{qualified_tabname} (#{self.class})"
48
48
 
@@ -54,11 +54,11 @@ module Bud
54
54
  next_accum = "+> "
55
55
  when @deletes.object_id, @delete_keys.object_id
56
56
  next_accum = "-> "
57
- end
58
-
57
+ end
58
+
59
59
  kind.each do |o|
60
- if o.respond_to?(:print_wiring)
61
- o.print_wiring(depth+1, next_accum)
60
+ if o.respond_to?(:print_wiring)
61
+ o.print_wiring(depth+1, next_accum)
62
62
  else
63
63
  (depth+1).times {print " "}
64
64
  print "#{next_accum} "
@@ -74,16 +74,16 @@ module Bud
74
74
 
75
75
  def check_wiring
76
76
  if @blk.nil? and @outputs.empty? and @pendings.empty? and @deletes.empty? and @delete_keys.empty?
77
- raise "no output specified for PushElement #{@qualified_tabname}"
77
+ raise Bud::Error, "no output specified for PushElement #{@qualified_tabname}"
78
78
  end
79
79
  end
80
-
80
+
81
81
  def set_block(&blk)
82
82
  @blk = blk
83
83
  end
84
84
  def wire_to(element)
85
- unless element.methods.include? :insert or element.methods.include? "insert"
86
- raise Bud::Error, "attempt to wire_to element without insert method"
85
+ unless element.respond_to? :insert
86
+ raise Bud::Error, "attempt to wire_to element without insert method"
87
87
  end
88
88
  # elem_name = element.respond_to?(:tabname) ? element.tabname : element.elem_name
89
89
  # puts "wiring #{self.elem_name} to #{elem_name}"
@@ -91,22 +91,28 @@ module Bud
91
91
  element.wired_by << self if element.respond_to? :wired_by
92
92
  end
93
93
  def wire_to_pending(element)
94
- raise Bud::Error, "attempt to wire_to_pending element without pending_merge method" unless element.methods.include? "pending_merge" or element.methods.include? :pending_merge
95
- elem_name = element.respond_to?(:tabname) ? element.tabname : element.elem_name
94
+ unless element.respond_to? :pending_merge
95
+ raise Bud::Error, "attempt to wire_to_pending element without pending_merge method"
96
+ end
97
+ # elem_name = element.respond_to?(:tabname) ? element.tabname : element.elem_name
96
98
  # puts "wiring #{self.elem_name} to #{elem_name}(pending)"
97
99
  @pendings << element
98
100
  element.wired_by << self if element.respond_to? :wired_by
99
101
  end
100
102
  def wire_to_delete(element)
101
- raise Bud::Error, "attempt to wire_to_delete element without pending_delete method" unless element.methods.include? "pending_delete" or element.methods.include? :pending_delete
102
- elem_name = element.respond_to?(:tabname) ? element.tabname : element.elem_name
103
+ unless element.respond_to? :pending_delete
104
+ raise Bud::Error, "attempt to wire_to_delete element without pending_delete method"
105
+ end
106
+ # elem_name = element.respond_to?(:tabname) ? element.tabname : element.elem_name
103
107
  # puts "wiring #{self.elem_name} to #{elem_name}(delete)"
104
108
  @deletes << element
105
109
  element.wired_by << self if element.respond_to? :wired_by
106
110
  end
107
111
  def wire_to_delete_by_key(element)
108
- raise Bud::Error, "attempt to wire_to_delete_by_key element without pending_delete_keys method" unless element.methods.include? "pending_delete_keys" or element.methods.include? :pending_delete_keys
109
- elem_name = element.respond_to?(:tabname) ? element.tabname : element.elem_name
112
+ unless element.respond_to? :pending_delete_keys
113
+ raise Bud::Error, "attempt to wire_to_delete_by_key element without pending_delete_keys method"
114
+ end
115
+ # elem_name = element.respond_to?(:tabname) ? element.tabname : element.elem_name
110
116
  # puts "wiring #{self.elem_name} to #{elem_name}(delete)"
111
117
  @delete_keys << element
112
118
  element.wired_by << self if element.respond_to? :wired_by
@@ -116,7 +122,6 @@ module Bud
116
122
  false
117
123
  end
118
124
 
119
-
120
125
  def insert(item, source=nil)
121
126
  push_out(item)
122
127
  end
@@ -131,36 +136,34 @@ module Bud
131
136
 
132
137
  def push_out(item, do_block=true)
133
138
  if item
134
- blk = @blk if do_block
135
- if blk
136
- item = item.to_a if blk.arity > 1
137
- begin
138
- item = blk.call item
139
- rescue Exception
140
- raise
141
- end
139
+ if do_block && @blk
140
+ item = item.to_a if @blk.arity > 1
141
+ item = @blk.call item
142
142
  end
143
- @outputs.each do |ou|
144
- if ou.class <= Bud::PushElement
145
- #the_name = ou.elem_name
146
- # puts "#{self.object_id%10000} (#{elem_name}) -> #{ou.object_id%10000} (#{the_name}): #{item.inspect}"
147
- ou.insert(item,self)
148
- elsif ou.class <= Bud::BudCollection
149
- # the_name = ou.tabname
150
- # puts "#{self.object_id%10000} (#{elem_name}) -> #{ou.object_id%10000} (#{the_name}): #{item.inspect}"
151
- ou.do_insert(item,ou.new_delta)
152
- else
153
- raise "Expected either a PushElement or a BudCollection"
143
+
144
+ unless item.nil?
145
+ @outputs.each do |ou|
146
+ if ou.class <= Bud::PushElement
147
+ #the_name = ou.elem_name
148
+ # puts "#{self.object_id%10000} (#{elem_name}) -> #{ou.object_id%10000} (#{the_name}): #{item.inspect}"
149
+ ou.insert(item, self)
150
+ elsif ou.class <= Bud::BudCollection
151
+ # the_name = ou.tabname
152
+ # puts "#{self.object_id%10000} (#{elem_name}) -> #{ou.object_id%10000} (#{the_name}): #{item.inspect}"
153
+ ou.do_insert(item, ou.new_delta)
154
+ else
155
+ raise Bud::Error, "expected either a PushElement or a BudCollection"
156
+ end
154
157
  end
155
- end unless item.nil?
156
- # for all the following, o is a BudCollection
157
- @deletes.each{|o| o.pending_delete([item])} unless item.nil?
158
- @delete_keys.each{|o| o.pending_delete_keys([item])} unless item.nil?
159
- @pendings.each{|o| o.pending_merge([item])} unless item.nil?
158
+
159
+ # for all the following, o is a BudCollection
160
+ @deletes.each{|o| o.pending_delete([item])}
161
+ @delete_keys.each{|o| o.pending_delete_keys([item])}
162
+ @pendings.each{|o| o.pending_merge([item])}
163
+ end
160
164
  end
161
165
  end
162
166
 
163
-
164
167
  # default for stateless elements
165
168
  public
166
169
  def add_rescan_invalidate(rescan, invalidate)
@@ -170,23 +173,25 @@ module Bud
170
173
  rescan << self
171
174
  end
172
175
 
173
- # pass the current state to the non-element outputs, and see if they end up marking this node for rescan
176
+ # pass the current state to the non-element outputs, and see if they end
177
+ # up marking this node for rescan
174
178
  invalidate_tables(rescan, invalidate)
175
179
 
176
- # finally, if this node is in rescan, pass the request on to all source elements
180
+ # finally, if this node is in rescan, pass the request on to all source
181
+ # elements
177
182
  if rescan.member? self
178
- srcs.each{|e| rescan << e} # propagate a rescan request to all sources.
183
+ rescan += srcs
179
184
  end
180
185
  end
181
186
 
182
187
  def invalidate_tables(rescan, invalidate)
183
- # exchange rescan and invalidate information with tables. If this node is in rescan, it may invalidate a target
184
- # table (if it is a scratch). And if the target node is invalidated, this node marks itself for rescan to
188
+ # exchange rescan and invalidate information with tables. If this node is
189
+ # in rescan, it may invalidate a target table (if it is a scratch). And if
190
+ # the target node is invalidated, this node marks itself for rescan to
185
191
  # enable a refill of that table at run-time
186
-
187
192
  @outputs.each do |o|
188
193
  unless o.class <= PushElement
189
- o.add_rescan_invalidate(rescan, invalidate) unless o.class <= PushElement
194
+ o.add_rescan_invalidate(rescan, invalidate)
190
195
  rescan << self if invalidate.member? o
191
196
  end
192
197
  end
@@ -211,45 +216,48 @@ module Bud
211
216
  # setup_accessors
212
217
  #end
213
218
 
214
-
219
+
215
220
  ####
216
221
  # and now, the Bloom-facing methods
217
222
  public
218
- def pro(the_name = @elem_name, the_schema = schema, &blk)
223
+ def pro(the_name=@elem_name, the_schema=schema, &blk)
219
224
  toplevel = @bud_instance.toplevel
220
- elem = Bud::PushElement.new('project' + object_id.to_s, toplevel.this_rule_context, @collection_name, the_schema)
221
- #elem.init_schema(the_schema) unless the_schema.nil?
225
+ elem = Bud::PushElement.new('project' + object_id.to_s,
226
+ toplevel.this_rule_context,
227
+ @collection_name, the_schema)
222
228
  self.wire_to(elem)
223
229
  elem.set_block(&blk)
224
- toplevel.push_elems[[self.object_id,:pro,blk]] = elem
230
+ toplevel.push_elems[[self.object_id, :pro, blk]] = elem
225
231
  return elem
226
232
  end
227
-
233
+
228
234
  alias each pro
229
-
235
+
230
236
  public
231
- def each_with_index(the_name = elem_name, the_schema = schema, &blk)
237
+ def each_with_index(the_name=elem_name, the_schema=schema, &blk)
232
238
  toplevel = @bud_instance.toplevel
233
- elem = Bud::PushEachWithIndex.new('each_with_index' + object_id.to_s, toplevel.this_rule_context, @collection_name)
239
+ elem = Bud::PushEachWithIndex.new('each_with_index' + object_id.to_s,
240
+ toplevel.this_rule_context,
241
+ @collection_name)
234
242
  elem.set_block(&blk)
235
243
  self.wire_to(elem)
236
- toplevel.push_elems[[self.object_id,:each,blk]] = elem
244
+ toplevel.push_elems[[self.object_id, :each, blk]] = elem
237
245
  end
238
-
246
+
239
247
  def join(elem2, &blk)
240
248
  # cached = @bud_instance.push_elems[[self.object_id,:join,[self,elem2], @bud_instance, blk]]
241
249
  # if cached.nil?
242
250
  elem2 = elem2.to_push_elem unless elem2.class <= PushElement
243
251
  toplevel = @bud_instance.toplevel
244
- join = Bud::PushSHJoin.new([self,elem2], toplevel.this_rule_context, [])
252
+ join = Bud::PushSHJoin.new([self, elem2], toplevel.this_rule_context, [])
245
253
  self.wire_to(join)
246
254
  elem2.wire_to(join)
247
- toplevel.push_elems[[self.object_id,:join,[self,elem2], toplevel, blk]] = join
255
+ toplevel.push_elems[[self.object_id, :join, [self, elem2], toplevel, blk]] = join
248
256
  toplevel.push_joins[toplevel.this_stratum] << join
249
257
  # else
250
258
  # cached.refcount += 1
251
259
  # end
252
- return toplevel.push_elems[[self.object_id,:join,[self,elem2], toplevel, blk]]
260
+ return toplevel.push_elems[[self.object_id, :join, [self, elem2], toplevel, blk]]
253
261
  end
254
262
  def *(elem2, &blk)
255
263
  join(elem2, &blk)
@@ -260,7 +268,7 @@ module Bud
260
268
  notin_elem = Bud::PushNotIn.new([self, elem2], toplevel.this_rule_context, preds, &blk)
261
269
  self.wire_to(notin_elem)
262
270
  elem2.wire_to(notin_elem)
263
- toplevel.push_elems[[self.object_id, :notin, collection, toplevel, blk]] == notin_elem
271
+ toplevel.push_elems[[self.object_id, :notin, collection, toplevel, blk]] = notin_elem
264
272
  return notin_elem
265
273
  end
266
274
 
@@ -268,20 +276,20 @@ module Bud
268
276
  if source.class <= PushElement and wiring?
269
277
  source.wire_to(self)
270
278
  else
271
- source.each{|i| self << i}
279
+ source.each {|i| self << i}
272
280
  end
273
281
  end
274
282
  alias <= merge
275
283
  superator "<~" do |o|
276
- raise Bud::Error, "Illegal use of <~ with pusher '#{tabname}' on left"
284
+ raise Bud::Error, "illegal use of <~ with pusher '#{tabname}' on left"
277
285
  end
278
286
 
279
287
  superator "<-" do |o|
280
- raise Bud::Error, "Illegal use of <- with pusher '#{tabname}' on left"
288
+ raise Bud::Error, "illegal use of <- with pusher '#{tabname}' on left"
281
289
  end
282
290
 
283
291
  superator "<+" do |o|
284
- raise Bud::Error, "Illegal use of <+ with pusher '#{tabname}' on left"
292
+ raise Bud::Error, "illegal use of <+ with pusher '#{tabname}' on left"
285
293
  end
286
294
 
287
295
  def group(keycols, *aggpairs, &blk)
@@ -293,13 +301,13 @@ module Bud
293
301
  aggcols = []
294
302
  aggcolsdups.each_with_index do |n, i|
295
303
  aggcols << "#{n.downcase}_#{i}".to_sym
296
- end
304
+ end
297
305
  if aggcols.empty?
298
306
  the_schema = keynames
299
307
  else
300
308
  the_schema = { keynames => aggcols }
301
309
  end
302
-
310
+
303
311
  aggpairs = aggpairs.map{|ap| ap[1].nil? ? [ap[0]] : [ap[0], canonicalize_col(ap[1])]}
304
312
  toplevel = @bud_instance.toplevel
305
313
  # if @bud_instance.push_elems[[self.object_id, :group, keycols, aggpairs, blk]].nil?
@@ -325,7 +333,7 @@ module Bud
325
333
  k[2]
326
334
  end
327
335
  end
328
- aggpairs = [[agg,collection]]
336
+ aggpairs = [[agg, collection]]
329
337
  # if toplevel.push_elems[[self.object_id,:argagg, gbkey_cols, aggpairs, blk]].nil?
330
338
  aa = Bud::PushArgAgg.new('argagg'+Time.new.tv_usec.to_s, toplevel.this_rule_context, @collection_name, gbkey_cols, aggpairs, schema, &blk)
331
339
  self.wire_to(aa)
@@ -345,8 +353,10 @@ module Bud
345
353
  wire_to(elem)
346
354
  elem
347
355
  end
348
- def push_predicate(pred_symbol, name=nil, bud_instance=nil, the_schema=nil, &blk)
349
- elem = Bud::PushPredicate.new(pred_symbol, name, bud_instance, the_schema, &blk)
356
+ def push_predicate(pred_symbol, name=nil, bud_instance=nil,
357
+ the_schema=nil, &blk)
358
+ elem = Bud::PushPredicate.new(pred_symbol, name, bud_instance,
359
+ the_schema, &blk)
350
360
  wire_to(elem)
351
361
  elem
352
362
  end
@@ -368,44 +378,45 @@ module Bud
368
378
  def one?(name=nil, bud_instance=nil, the_schema=nil, &blk)
369
379
  push_predicate(:one?, name, bud_instance, the_schema, &blk)
370
380
  end
371
-
381
+
372
382
  def reduce(initial, &blk)
373
383
  @memo = initial
374
- retval = Bud::PushReduce.new('reduce'+Time.new.tv_usec.to_s, @bud_instance, @collection_name, schema, initial, &blk)
384
+ retval = Bud::PushReduce.new("reduce#{Time.new.tv_usec}",
385
+ @bud_instance, @collection_name,
386
+ schema, initial, &blk)
375
387
  self.wire_to(retval)
376
388
  retval
377
389
  end
378
-
390
+
379
391
  alias on_exists? pro
380
392
  def on_include?(item, &blk)
381
393
  toplevel = @bud_instance.toplevel
382
- if toplevel.push_elems[[self.object_id,:on_include?, item, blk]].nil?
394
+ if toplevel.push_elems[[self.object_id, :on_include?, item, blk]].nil?
383
395
  inc = pro{|i| blk.call(item) if i == item and not blk.nil?}
384
396
  wire_to(inc)
385
- toplevel.push_elems[[self.object_id,:on_include?, item, blk]] = inc
397
+ toplevel.push_elems[[self.object_id, :on_include?, item, blk]] = inc
386
398
  end
387
- toplevel.push_elems[[self.object_id,:on_include?, item, blk]]
399
+ toplevel.push_elems[[self.object_id, :on_include?, item, blk]]
388
400
  end
389
401
  def inspected
390
402
  toplevel = @bud_instance.toplevel
391
- if toplevel.push_elems[[self.object_id,:inspected]].nil?
403
+ if toplevel.push_elems[[self.object_id, :inspected]].nil?
392
404
  ins = pro{|i| [i.inspect]}
393
405
  self.wire_to(ins)
394
- toplevel.push_elems[[self.object_id,:inspected]] = ins
406
+ toplevel.push_elems[[self.object_id, :inspected]] = ins
395
407
  end
396
- toplevel.push_elems[[self.object_id,:inspected]]
408
+ toplevel.push_elems[[self.object_id, :inspected]]
397
409
  end
398
-
410
+
399
411
  def to_enum
400
- # scr = @bud_instance.scratch(("scratch_" + Process.pid.to_s + "_" + object_id.to_s + "_" + rand(10000).to_s).to_sym, schema)
401
- scr = []
402
- self.wire_to(scr)
403
- scr
412
+ # scr = @bud_instance.scratch(("scratch_" + Process.pid.to_s + "_" + object_id.to_s + "_" + rand(10000).to_s).to_sym, schema)
413
+ scr = []
414
+ self.wire_to(scr)
415
+ scr
404
416
  end
405
- end
417
+ end
406
418
 
407
419
  class PushStatefulElement < PushElement
408
-
409
420
  def rescan_at_tick
410
421
  true
411
422
  end
@@ -415,10 +426,9 @@ module Bud
415
426
  end
416
427
 
417
428
  def add_rescan_invalidate(rescan, invalidate)
418
- # If an upstream node is set to rescan, a stateful node invalidates its cache
419
- # In addition, a stateful node always rescans its own contents (doesn't need to pass a rescan request to its
420
- # its source nodes
421
-
429
+ # If an upstream node is set to rescan, a stateful node invalidates its
430
+ # cache. In addition, a stateful node always rescans its own contents
431
+ # (doesn't need to pass a rescan request to its its source nodes).
422
432
  rescan << self
423
433
  srcs = non_temporal_predecessors
424
434
  if srcs.any? {|p| rescan.member? p}
@@ -435,7 +445,7 @@ module Bud
435
445
  @in_buf = []
436
446
  super(elem_name, bud_instance, collection_name, schema_in, &blk)
437
447
  end
438
-
448
+
439
449
  def insert(item, source)
440
450
  @in_buf << item
441
451
  end
@@ -450,13 +460,14 @@ module Bud
450
460
  @in_buf.clear
451
461
  end
452
462
  end
453
-
463
+
454
464
  class PushSort < PushStatefulElement
455
- def initialize(elem_name=nil, bud_instance=nil, collection_name=nil, schema_in=nil, &blk)
465
+ def initialize(elem_name=nil, bud_instance=nil, collection_name=nil,
466
+ schema_in=nil, &blk)
456
467
  @sortbuf = []
457
468
  super(elem_name, bud_instance, collection_name, schema_in, &blk)
458
469
  end
459
-
470
+
460
471
  def insert(item, source)
461
472
  @sortbuf << item
462
473
  end
@@ -476,12 +487,13 @@ module Bud
476
487
  @sortbuf = []
477
488
  end
478
489
  end
479
-
490
+
480
491
  class ScannerElement < PushElement
481
492
  attr_reader :collection
482
493
  attr_reader :rescan_set, :invalidate_set
483
- def initialize(elem_name, bud_instance, collection_in, the_schema=collection_in.schema, &blk)
484
- # puts self.class
494
+
495
+ def initialize(elem_name, bud_instance, collection_in,
496
+ the_schema=collection_in.schema, &blk)
485
497
  super(elem_name, bud_instance, collection_in.qualified_tabname, the_schema)
486
498
  @collection = collection_in
487
499
  @rescan_set = []
@@ -496,8 +508,9 @@ module Bud
496
508
  @collection.invalidate_at_tick # need to scan afresh if collection invalidated.
497
509
  end
498
510
 
511
+ # collection of others to rescan/invalidate if this scanner's collection
512
+ # were to be invalidated.
499
513
  def invalidate_at_tick(rescan, invalidate)
500
- # collection of others to rescan/invalidate if this scanner's collection were to be invalidated.
501
514
  @rescan_set = rescan
502
515
  @invalidate_set = invalidate
503
516
  end
@@ -507,19 +520,19 @@ module Bud
507
520
  # scanner elements are never directly connected to tables.
508
521
  rescan << self if invalidate.member? @collection
509
522
 
510
- # Note also that this node can be nominated for rescan by a target node; in other words, a scanner element
511
- # can be set to rescan even if the collection is not invalidated.
523
+ # Note also that this node can be nominated for rescan by a target node;
524
+ # in other words, a scanner element can be set to rescan even if the
525
+ # collection is not invalidated.
512
526
  end
513
527
 
514
528
  def scan(first_iter)
515
- if (first_iter)
529
+ if first_iter
516
530
  if rescan
517
- # scan entire storage
518
- @collection.each_raw {|item|
519
- push_out(item)
520
- }
531
+ # Scan entire storage
532
+ @collection.each_raw {|item| push_out(item)}
521
533
  else
522
- # In the first iteration, tick_delta would be non-null IFF the collection has grown in an earlier stratum
534
+ # In the first iteration, tick_delta would be non-null IFF the
535
+ # collection has grown in an earlier stratum
523
536
  @collection.tick_delta.each {|item| push_out(item)}
524
537
  end
525
538
  end
@@ -530,14 +543,15 @@ module Bud
530
543
  end
531
544
 
532
545
  class PushReduce < PushStatefulElement
533
- def initialize(elem_name, bud_instance, collection_name, schema_in, initial, &blk)
546
+ def initialize(elem_name, bud_instance, collection_name,
547
+ schema_in, initial, &blk)
534
548
  @memo = initial
535
549
  @blk = blk
536
550
  super(elem_name, bud_instance, collection_name, schema)
537
551
  end
538
552
 
539
553
  def insert(i, source=nil)
540
- @memo = @blk.call(@memo,i)
554
+ @memo = @blk.call(@memo, i)
541
555
  end
542
556
 
543
557
  def invalidate_cache
@@ -567,11 +581,12 @@ module Bud
567
581
 
568
582
  invalidate_tables(rescan, invalidate)
569
583
 
570
- # This node has some state (@each_index), but not the tuples. If it is in rescan mode, then it must ask its
571
- # sources to rescan, and restart its index.
584
+ # This node has some state (@each_index), but not the tuples. If it is in
585
+ # rescan mode, then it must ask its sources to rescan, and restart its
586
+ # index.
572
587
  if rescan.member? self
573
588
  invalidate << self
574
- srcs.each {|e| rescan << e}
589
+ rescan += srcs
575
590
  end
576
591
  end
577
592
 
@@ -585,7 +600,7 @@ module Bud
585
600
 
586
601
  def insert(item, source=nil)
587
602
  ix = @each_index
588
- @each_index = ix + 1
603
+ @each_index += 1
589
604
  push_out([item, ix])
590
605
  end
591
606
  end
@@ -5,7 +5,7 @@ module Bud
5
5
  def initialize(elem_name, bud_instance, collection_name, keys_in, aggpairs_in, schema_in, &blk)
6
6
  @groups = {}
7
7
  if keys_in.nil?
8
- @keys = []
8
+ @keys = []
9
9
  else
10
10
  @keys = keys_in.map{|k| k[1]}
11
11
  end
@@ -13,9 +13,9 @@ module Bud
13
13
  @aggpairs = aggpairs_in.map{|ap| ap[1].nil? ? [ap[0]] : [ap[0], ap[1][1]]}
14
14
  super(elem_name, bud_instance, collection_name, schema_in, &blk)
15
15
  end
16
-
16
+
17
17
  def insert(item, source)
18
- key = @keys.map{|k| item[k]}
18
+ key = @keys.map{|k| item[k]}
19
19
  @aggpairs.each_with_index do |ap, agg_ix|
20
20
  agg_input = ap[1].nil? ? item : item[ap[1]]
21
21
  agg = (@groups[key].nil? or @groups[key][agg_ix].nil?) ? ap[0].send(:init, agg_input) : ap[0].send(:trans, @groups[key][agg_ix], agg_input)[0]
@@ -43,7 +43,7 @@ module Bud
43
43
  #@groups = {}
44
44
  end
45
45
  end
46
-
46
+
47
47
  class PushArgAgg < PushGroup
48
48
  def initialize(elem_name, bud_instance, collection_name, keys_in, aggpairs_in, schema_in, &blk)
49
49
  raise "Multiple aggpairs #{aggpairs_in.map{|a| a.class.name}} in ArgAgg; only one allowed" if aggpairs_in.length > 1
@@ -63,7 +63,7 @@ module Bud
63
63
  def insert(item, source)
64
64
  key = @keys.map{|k| item[k]}
65
65
  @aggpairs.each_with_index do |ap, agg_ix|
66
- agg_input = item[ap[1]]
66
+ agg_input = item[ap[1]]
67
67
  if @groups[key].nil?
68
68
  agg = ap[0].send(:init, agg_input)
69
69
  @winners[key] = [item]
@@ -88,7 +88,7 @@ module Bud
88
88
  @groups[key] ||= Array.new(@aggpairs.length)
89
89
  @groups[key][agg_ix] = agg
90
90
  #push_out(nil)
91
- end
91
+ end
92
92
  end
93
93
 
94
94
  def flush