Class: Oinky::Internal::CursorBase
- Inherits:
-
Object
- Object
- Oinky::Internal::CursorBase
- Defined in:
- lib/oinky.rb
Overview
The cursor types and implementation methods are different for index cursors and table cursors. However, they operate almost identically. This is the common implementation. Index and Table specialize only slightly.
Direct Known Subclasses
Class Method Summary collapse
Instance Method Summary collapse
- #at_end? ⇒ Boolean
- #before_begin? ⇒ Boolean
- #clone ⇒ Object
- #column_selector_default(cs = nil) ⇒ Object
- #each_backward(cs = nil) ⇒ Object
-
#each_forward(cs = nil) ⇒ Object
Move this cursor forward until the end (or until enumeration is stopped).
-
#initialize(host) ⇒ CursorBase
constructor
A new instance of CursorBase.
- #is_valid? ⇒ Boolean
- #seek_first ⇒ Object
- #seek_last ⇒ Object
- #seek_next ⇒ Object
- #seek_prev ⇒ Object
- #select(cs = nil) ⇒ Object
- #select_all ⇒ Object
- #select_all_values ⇒ Object
-
#select_values(cs = nil) ⇒ Object
Like <select>, but just returns values as an array, rather than as a hash.
- #state_val ⇒ Object
Constructor Details
#initialize(host) ⇒ CursorBase
Returns a new instance of CursorBase.
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 |
# File 'lib/oinky.rb', line 524 def initialize(host) if host.is_a? host_class @host = host @hosthandle = @host.send(:eval, "@handle") c = FFI::MemoryPointer.new(:pointer) Internal.wrap_oinky(impl(:cursor_new).call(@hosthandle, c)) @handle = c.read_pointer seek_first elsif host.is_a? self.class c = FFI::MemoryPointer.new(:pointer) h, @hosthandle, @host = host.send(:eval, "[@handle, @hosthandle, @host]") Internal.wrap_oinky(impl(:cursor_clone).call(@hosthandle, h, c)) @handle = c.read_pointer else raise OinkyException.new("Unknown argument type to #{self.class}.new") end # Cursors are automatically destroyed when the DB is destroyed. # If we call cursor deletion after DB deletion, that is equivalent to # freeing twice. It's bad. But we have no way of controlling the # order of finalizer invocation (between cursor and DB) short of # referencing the DB in the cursor finalizer. But that causes the DB # to stick around for a whole extra GC cycle. Generally, that overhead # is much worse than leaking the cursor objects for the lifetime of # the DB. So, we have two options: # 1) Keep a reference on the DB object in the cursor finalizer, causing # a full GC-cycle delay in freeing DB resources. # 2) Leak cursor objects always, letting them be cleaned up implicitly # when the DB is destroyed. # This is a configuration property called Oinky.implicit_cursor_cleanup # which defaults to 'true', indicating that we pursue strategy 2. It # is a property of the database object instance which applies to all # cursors derived from that instance (table or index). # cursors # applies to all cursors created after the property is set. # Changing the global or db-local value dynamically at any time is # safe. It should generally only be set to 'false' for instances that # will be long-lived, where the aggregate overhead of cursors created # (tens of bytes) might compare to the overhead of the database itself. unless @host.db.implicit_cursor_cleanup ObjectSpace.define_finalizer( self, self.class.finalize(impl(:cursor_free), @handle, {:db=>@host.db}) ) end end |
Class Method Details
.finalize(m, ptr, refs) ⇒ Object
569 570 571 |
# File 'lib/oinky.rb', line 569 def self.finalize(m, ptr, refs) proc { m.call(ptr); refs[:db] = nil } end |
Instance Method Details
#at_end? ⇒ Boolean
595 596 597 |
# File 'lib/oinky.rb', line 595 def at_end? state_val == 1 end |
#before_begin? ⇒ Boolean
598 599 600 |
# File 'lib/oinky.rb', line 598 def before_begin? state_val == -1 end |
#clone ⇒ Object
601 602 603 |
# File 'lib/oinky.rb', line 601 def clone self.class.new(self) end |
#column_selector_default(cs = nil) ⇒ Object
604 605 606 607 608 |
# File 'lib/oinky.rb', line 604 def column_selector_default(cs = nil) cs = self.table.select_all_columns unless cs cs = self.table.select_columns(cs) unless cs.is_a? ColumnSelector cs end |
#each_backward(cs = nil) ⇒ Object
651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 |
# File 'lib/oinky.rb', line 651 def each_backward(cs = nil) e = ValuesEnumerator.new {|blk| # The cursor may not begin in a valid position self.seek_prev unless self.is_valid? while self.is_valid? blk.yield self.select(cs) self.seek_prev end } if block_given? e.each{|k| yield k} else return e end self end |
#each_forward(cs = nil) ⇒ Object
Move this cursor forward until the end (or until enumeration is stopped)
635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 |
# File 'lib/oinky.rb', line 635 def each_forward(cs = nil) e = ValuesEnumerator.new {|blk| # The cursor may not begin in a valid position self.seek_next unless self.is_valid? while self.is_valid? blk.yield self.select(cs) self.seek_next end } if block_given? e.each{|k| yield k} else return e end self end |
#is_valid? ⇒ Boolean
592 593 594 |
# File 'lib/oinky.rb', line 592 def is_valid? state_val == 0 end |
#seek_first ⇒ Object
573 574 575 576 |
# File 'lib/oinky.rb', line 573 def seek_first Internal.wrap_oinky(impl(:cursor_seek_first).call(@hosthandle, @handle)) self end |
#seek_last ⇒ Object
577 578 579 580 |
# File 'lib/oinky.rb', line 577 def seek_last Internal.wrap_oinky(impl(:cursor_seek_last).call(@hosthandle, @handle)) self end |
#seek_next ⇒ Object
581 582 583 584 |
# File 'lib/oinky.rb', line 581 def seek_next Internal.wrap_oinky(impl(:cursor_seek_next).call(@hosthandle, @handle)) self end |
#seek_prev ⇒ Object
585 586 587 588 |
# File 'lib/oinky.rb', line 585 def seek_prev Internal.wrap_oinky(impl(:cursor_seek_prev).call(@hosthandle, @handle)) self end |
#select(cs = nil) ⇒ Object
609 610 611 612 613 614 615 616 617 618 |
# File 'lib/oinky.rb', line 609 def select(cs = nil) cs = self.column_selector_default(cs) vals = self.select_values(cs) r = ExHash.new cns = cs.cols vals.each_with_index{|v,i| r[cns[i]] = v } return r end |
#select_all ⇒ Object
619 620 621 |
# File 'lib/oinky.rb', line 619 def select_all self.select(nil) end |
#select_all_values ⇒ Object
631 632 633 |
# File 'lib/oinky.rb', line 631 def select_all_values self.select_values(nil) end |
#select_values(cs = nil) ⇒ Object
Like <select>, but just returns values as an array, rather than as a hash
624 625 626 627 628 629 630 |
# File 'lib/oinky.rb', line 624 def select_values(cs = nil) cs = column_selector_default(cs) vs = Internal::VariantSet.new(cs.size) out_count = FFI::MemoryPointer.new :size_t Internal.wrap_oinky(impl(:cursor_get_values).call(@handle, cs.handle, cs.size, vs, out_count)) (0..out_count.read_int-1).map{|i| vs[i].rb_val } end |
#state_val ⇒ Object
589 590 591 |
# File 'lib/oinky.rb', line 589 def state_val impl(:cursor_state).call(@hosthandle, @handle) end |