Class: Factbase::Query

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/factbase/query.rb

Overview

Query.

This is an internal class, it is not supposed to be instantiated directly. It is created by the query() method of the Factbase class.

It is NOT thread-safe!

Author

Yegor Bugayenko (yegor256@gmail.com)

Copyright

Copyright © 2024-2026 Yegor Bugayenko

License

MIT

Instance Method Summary collapse

Constructor Details

#initialize(maps, term, fb) ⇒ Query

Constructor.

Parameters:

  • maps (Array<Fact>)

    Array of facts to start with

  • term (String|Factbase::Term)

    The query term



28
29
30
31
32
# File 'lib/factbase/query.rb', line 28

def initialize(maps, term, fb)
  @maps = maps
  @term = term.is_a?(String) ? Factbase::Syntax.new(term).to_term : term
  @fb = fb
end

Instance Method Details

#delete!(fb = @fb, id: '_id') ⇒ Integer

Delete all facts that match the query.

Parameters:

  • fb (Factbase) (defaults to: @fb)

    The factbase to delete from

  • id (String) (defaults to: '_id')

    The id of facts that uniquely identify them

Returns:

  • (Integer)

    Total number of facts deleted



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/factbase/query.rb', line 83

def delete!(fb = @fb, id: '_id')
  deleted = 0
  ids = []
  each(fb) do |f|
    i = f[id]
    unless i
      ids = nil
      break
    end
    ids << i.first
  end
  @maps.delete_if do |m|
    d =
      if ids
        i = m[id]&.first
        i && ids.include?(i)
      else
        @term.evaluate(Factbase::Fact.new(m), @maps, fb)
      end
    deleted += 1 if d
    d
  end
  deleted
end

#each(fb = @fb, params = {}) {|Fact| ... } ⇒ Integer

Iterate facts one by one.

Parameters:

  • fb (Factbase) (defaults to: @fb)

    The factbase

  • params (Hash) (defaults to: {})

    Optional params accessible in the query via the “$” symbol

Yields:

  • (Fact)

    Facts one-by-one

Returns:

  • (Integer)

    Total number of facts yielded (if block given), otherwise enumerator



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/factbase/query.rb', line 45

def each(fb = @fb, params = {})
  return to_enum(__method__, fb, params) unless block_given?
  yielded = 0
  params = params.transform_keys(&:to_s) if params.is_a?(Hash)
  maybe = @term.predict(@maps, fb, Factbase::Tee.new({}, params))
  maybe ||= @maps unless maybe.equal?(@maps)
  maybe.each do |m|
    extras = {}
    f = Factbase::Fact.new(m)
    f = Factbase::Tee.new(f, params)
    r = @term.evaluate(Factbase::Accum.new(f, extras, false), @maps, fb)
    unless r.is_a?(TrueClass) || r.is_a?(FalseClass)
      raise(ArgumentError, "Unexpected evaluation result of type #{r.class}, must be Boolean at #{@term.inspect}")
    end
    next unless r
    yield(Factbase::Accum.new(f, extras, true))
    yielded += 1
  end
  yielded
end

#one(fb = @fb, params = {}) ⇒ String|Integer|Float|Time|Array|NilClass

Read a single value.

Parameters:

  • fb (Factbase) (defaults to: @fb)

    The factbase

  • params (Hash) (defaults to: {})

    Optional params accessible in the query via the “$” symbol

Returns:

  • (String|Integer|Float|Time|Array|NilClass)

    The value evaluated



70
71
72
73
74
75
76
77
# File 'lib/factbase/query.rb', line 70

def one(fb = @fb, params = {})
  params = params.transform_keys(&:to_s) if params.is_a?(Hash)
  r = @term.evaluate(Factbase::Tee.new(Factbase::Fact.new({}), params), @maps, fb)
  unless %w[String Integer Float Time Array NilClass].include?(r.class.to_s)
    raise(StandardError, "Incorrect type #{r.class} returned by #{@term.inspect}")
  end
  r
end

#to_sString

Print it as a string.

Returns:

  • (String)

    The query as a string



36
37
38
# File 'lib/factbase/query.rb', line 36

def to_s
  @term.to_s
end