Class: Factbase::IndexedFactbase

Inherits:
Object
  • Object
show all
Defined in:
lib/factbase/indexed/indexed_factbase.rb

Overview

A factbase with an index.

Author

Yegor Bugayenko ([email protected])

Copyright

Copyright © 2024-2026 Yegor Bugayenko

License

MIT

Instance Method Summary collapse

Constructor Details

#initialize(origin, idx = {}, fresh = Set.new) ⇒ IndexedFactbase

Constructor.



25
26
27
28
29
30
31
# File 'lib/factbase/indexed/indexed_factbase.rb', line 25

def initialize(origin, idx = {}, fresh = Set.new)
  raise 'Wrong type of original' unless origin.respond_to?(:query)
  @origin = origin
  raise 'Wrong type of index' unless idx.is_a?(Hash)
  @idx = idx
  @fresh = fresh
end

Instance Method Details

#exportString

Export it into a chain of bytes, including both data and index.

Here is how you can export it to a file, for example:

fb = Factbase::IndexedFactbase.new(Factbase.new)
fb.insert.foo = 42
File.binwrite("foo.fb", fb.export)

The data is binary, it’s not a text!



84
85
86
# File 'lib/factbase/indexed/indexed_factbase.rb', line 84

def export
  Marshal.dump({ maps: @origin.export, idx: @idx })
end

#import(bytes) ⇒ Object

Import from a chain of bytes, including both data and index.

Here is how you can read it from a file, for example:

fb = Factbase::IndexedFactbase.new(Factbase.new)
fb.import(File.binread("foo.fb"))

The facts that existed in the factbase before importing will remain there. The facts from the incoming byte stream will be added to them. If the byte stream doesn’t contain an index (for backward compatibility), the index will be empty and will be built on first use.



101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/factbase/indexed/indexed_factbase.rb', line 101

def import(bytes)
  raise 'Empty input, cannot load a factbase' if bytes.empty?
  data = Marshal.load(bytes)
  if data.is_a?(Hash) && data.key?(:maps)
    @origin.import(data[:maps])
    @idx.merge!(data[:idx]) if data[:idx].is_a?(Hash)
  else
    @origin.import(bytes)
    @idx.clear
  end
  @fresh.clear
end

#insertFactbase::Fact

Insert a new fact and return it.



35
36
37
38
39
# File 'lib/factbase/indexed/indexed_factbase.rb', line 35

def insert
  f = Factbase::IndexedFact.new(@origin.insert, @idx, @fresh)
  @fresh.add(f.object_id)
  f
end

#query(term, maps = nil) ⇒ Object

Create a query capable of iterating.



53
54
55
56
57
58
59
# File 'lib/factbase/indexed/indexed_factbase.rb', line 53

def query(term, maps = nil)
  term = to_term(term) if term.is_a?(String)
  q = @origin.query(term, maps)
  q = Factbase::IndexedQuery.new(q, @idx, self, @fresh)
  @fresh.clear
  q
end

#sizeInteger

Size, the total number of facts in the factbase.



116
117
118
# File 'lib/factbase/indexed/indexed_factbase.rb', line 116

def size
  @origin.size
end

#to_term(query) ⇒ Factbase::Term

Convert a query to a term.



44
45
46
47
48
# File 'lib/factbase/indexed/indexed_factbase.rb', line 44

def to_term(query)
  t = @origin.to_term(query)
  t.redress!(Factbase::IndexedTerm, idx: @idx)
  t
end

#txnFactbase::Churn

Run an ACID transaction.



63
64
65
66
67
68
69
70
71
# File 'lib/factbase/indexed/indexed_factbase.rb', line 63

def txn
  result =
    @origin.txn do |fbt|
      yield Factbase::IndexedFactbase.new(fbt, @idx, @fresh)
    end
  @idx.clear
  @fresh.clear
  result
end