factbase 0.9.7 → 0.9.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e7d1b649fb808d571609f3231f90dbd57ba57683993d52ee2eaddd674e2aeb65
4
- data.tar.gz: 717ea095ae2e1092d71509b39f1581cfc4b65d47ca9f39cb704d694eabbd91d9
3
+ metadata.gz: 72ae2c1184dfd8ab966591846cd054c3155b0536d8c7f2f7acf636df1eb7e045
4
+ data.tar.gz: fcf929766bf80cc040744ce9caa719503548fac719d956f676e9604374d78b8c
5
5
  SHA512:
6
- metadata.gz: 9f6955bdf61ad153a2cf956935310fbd1d59782a34e479ae94e48c70ab8a1002dfdf61f2384e968bbdedb0be58d19ea556841d7b7300aa110927f78f1fdabaf9
7
- data.tar.gz: 2364a4421fcf35c42b6e316e33f11afaf4abc69b33502b475fa08fc28e2e45b8dbe138cf72d26b8938212d2807dfd8c3b50aa40b166e481e15f363d2cf5629c8
6
+ metadata.gz: 0d6c3b87fd94afe4fc7984ca17be09ffd6dbff5d93951e264720201e2e5680e387fc0215331af563af7cc78ac3db9e199ca8a0aadc39d989fb377b975d3e1b8d
7
+ data.tar.gz: 26c9ffe593d79fc17d80949208cc0833d4147684a0fcd221dc6abd669c545da678dc4fd52723913bc29a68662ca43cf7470a9523022d0919af6dd42a440d69ca
@@ -19,3 +19,5 @@ queries:
19
19
  size: 3
20
20
  - query: (and (exists man) (empty (and (exists woman) (eq woman $wife))))
21
21
  size: 1
22
+ - query: (empty (eq woman $woman))
23
+ size: 4
@@ -54,8 +54,7 @@ module Factbase::IndexedTerm
54
54
  end
55
55
  vv =
56
56
  if @operands[1].is_a?(Symbol)
57
- sym = @operands[1].to_s.gsub(/^\$/, '')
58
- params[sym] || []
57
+ params[@operands[1].to_s] || []
59
58
  else
60
59
  [@operands[1]]
61
60
  end
@@ -84,8 +83,7 @@ module Factbase::IndexedTerm
84
83
  tuples = _as_tuples(
85
84
  @operands.sort_by { |o| o.operands.first }.map do |o|
86
85
  if o.operands[1].is_a?(Symbol)
87
- sym = o.operands[1].to_s.gsub(/^\$/, '')
88
- params[sym] || []
86
+ params[o.operands[1].to_s] || []
89
87
  else
90
88
  [o.operands[1]]
91
89
  end
@@ -44,7 +44,7 @@ class Factbase::Query
44
44
  return to_enum(__method__, fb, params) unless block_given?
45
45
  yielded = 0
46
46
  params = params.transform_keys(&:to_s) if params.is_a?(Hash)
47
- maybe = @term.predict(@maps, params)
47
+ maybe = @term.predict(@maps, Factbase::Tee.new({}, params))
48
48
  (maybe || @maps).each do |m|
49
49
  extras = {}
50
50
  f = Factbase::Fact.new(m)
@@ -61,7 +61,6 @@ class Factbase::Rules
61
61
  # Fact decorator.
62
62
  #
63
63
  # This is an internal class, it is not supposed to be instantiated directly.
64
- #
65
64
  class Fact
66
65
  def initialize(fact, check, fb)
67
66
  @fact = fact
@@ -130,9 +129,10 @@ class Factbase::Rules
130
129
  end
131
130
 
132
131
  def it(fact, _fb)
132
+ return if @uid.nil?
133
133
  a = fact[@uid]
134
134
  return if a.nil?
135
- @facts << a[0] unless @uid.nil?
135
+ @facts << a[0]
136
136
  end
137
137
 
138
138
  def include?(fact)
data/lib/factbase/tee.rb CHANGED
@@ -31,12 +31,14 @@ class Factbase::Tee
31
31
  end
32
32
 
33
33
  others do |*args|
34
- if args[0].to_s == '[]' && args[1].to_s.start_with?('$')
34
+ if args[0].to_s == '[]' && args[1].start_with?('$')
35
35
  n = args[1].to_s
36
36
  n = n[1..] unless @upper.is_a?(Factbase::Tee)
37
- @upper[n]
37
+ r = @upper[n]
38
+ r = [r] unless r.respond_to?(:each) || r.nil?
39
+ r
38
40
  else
39
- @fact.method_missing(*args)
41
+ @fact.send(*args)
40
42
  end
41
43
  end
42
44
  end
data/lib/factbase/term.rb CHANGED
@@ -218,6 +218,10 @@ class Factbase::Term
218
218
  [v]
219
219
  end
220
220
  end
221
+ raise 'Why not array?' unless v.is_a?(Array)
222
+ unless v.all? { |i| [Float, Integer, String, Time, TrueClass, FalseClass].any? { |t| i.is_a?(t) } }
223
+ raise 'Wrong type inside'
224
+ end
221
225
  v
222
226
  end
223
227
  end
data/lib/factbase.rb CHANGED
@@ -82,7 +82,7 @@ require 'yaml'
82
82
  # License:: MIT
83
83
  class Factbase
84
84
  # Current version of the gem (changed by .rultor.yml on every release)
85
- VERSION = '0.9.7' unless const_defined?(:VERSION)
85
+ VERSION = '0.9.9' unless const_defined?(:VERSION)
86
86
 
87
87
  # An exception that may be thrown in a transaction, to roll it back.
88
88
  class Rollback < StandardError; end
@@ -40,6 +40,15 @@ class TestIndexedQuery < Factbase::Test
40
40
  end
41
41
  end
42
42
 
43
+ def test_fills_up_the_index
44
+ idx = {}
45
+ fb = Factbase::IndexedFactbase.new(Factbase.new, idx)
46
+ fb.query('(eq x 1)').each.to_a
47
+ assert_equal(1, idx.size)
48
+ fb.insert
49
+ assert_empty(idx)
50
+ end
51
+
43
52
  def test_finds_by_eq_with_symbol
44
53
  fb = Factbase::IndexedFactbase.new(Factbase.new)
45
54
  f = fb.insert
@@ -159,6 +168,15 @@ class TestIndexedQuery < Factbase::Test
159
168
  end
160
169
  end
161
170
 
171
+ def test_joins_simple_one
172
+ idx = {}
173
+ fb = Factbase::IndexedFactbase.new(Factbase.new, idx)
174
+ fb.insert.who = 4
175
+ fb.insert.friend = 4
176
+ assert_equal(1, fb.query('(and (exists who) (join "f<=friend" (eq friend $who)))').each.to_a.size)
177
+ assert_equal(2, idx.size)
178
+ end
179
+
162
180
  def test_joins_too
163
181
  fb = Factbase::IndexedFactbase.new(Factbase.new)
164
182
  total = 10_000
@@ -19,7 +19,7 @@ class TestIndexedTerm < Factbase::Test
19
19
  idx = {}
20
20
  term.redress!(Factbase::IndexedTerm, idx:)
21
21
  maps = Factbase::Taped.new([{ 'foo' => [42] }, { 'bar' => [7] }, { 'foo' => [22, 42] }, { 'foo' => [] }])
22
- n = term.predict(maps, { a: 1 })
22
+ n = term.predict(maps, {})
23
23
  assert_equal(2, n.size)
24
24
  assert_kind_of(Factbase::Taped, n)
25
25
  end
@@ -29,7 +29,7 @@ class TestIndexedTerm < Factbase::Test
29
29
  idx = {}
30
30
  term.redress!(Factbase::IndexedTerm, idx:)
31
31
  maps = Factbase::Taped.new([{ 'foo' => [42] }, { 'bar' => [7] }, { 'foo' => [22, 42] }, { 'foo' => [] }])
32
- n = term.predict(maps, { a: 1 })
32
+ n = term.predict(maps, {})
33
33
  assert_equal(3, n.size)
34
34
  assert_kind_of(Factbase::Taped, n)
35
35
  end
@@ -39,7 +39,7 @@ class TestIndexedTerm < Factbase::Test
39
39
  idx = {}
40
40
  term.redress!(Factbase::IndexedTerm, idx:)
41
41
  maps = Factbase::Taped.new([{ 'foo' => [42] }, { 'bar' => [7] }, { 'foo' => [22, 42] }, { 'foo' => [] }])
42
- n = term.predict(maps, { a: 1 })
42
+ n = term.predict(maps, {})
43
43
  assert_equal(1, n.size)
44
44
  assert_kind_of(Factbase::Taped, n)
45
45
  end
@@ -49,7 +49,7 @@ class TestIndexedTerm < Factbase::Test
49
49
  idx = {}
50
50
  term.redress!(Factbase::IndexedTerm, idx:)
51
51
  maps = Factbase::Taped.new([{ 'foo' => [42] }, { 'bar' => [7], 'foo' => [22, 42] }, { 'foo' => [22] }])
52
- n = term.predict(maps, { a: 1 })
52
+ n = term.predict(maps, {})
53
53
  assert_equal(1, n.size)
54
54
  assert_kind_of(Factbase::Taped, n)
55
55
  end
@@ -59,13 +59,13 @@ class TestIndexedTerm < Factbase::Test
59
59
  :and,
60
60
  [
61
61
  Factbase::Term.new(:eq, [:foo, 42]),
62
- Factbase::Term.new(:eq, %i[bar $a])
62
+ Factbase::Term.new(:eq, %i[bar $jeff])
63
63
  ]
64
64
  )
65
65
  idx = {}
66
66
  term.redress!(Factbase::IndexedTerm, idx:)
67
67
  maps = Factbase::Taped.new([{ 'foo' => [42] }, { 'bar' => [7], 'foo' => [22, 42] }, { 'foo' => [22, 42] }])
68
- n = term.predict(maps, { 'a' => [7] })
68
+ n = term.predict(maps, Factbase::Tee.new({}, { 'jeff' => [7] }))
69
69
  assert_equal(1, n.size)
70
70
  assert_kind_of(Factbase::Taped, n)
71
71
  end
@@ -90,7 +90,7 @@ class TestIndexedTerm < Factbase::Test
90
90
  idx = {}
91
91
  term.redress!(Factbase::IndexedTerm, idx:)
92
92
  maps = Factbase::Taped.new([{ 'foo' => [42] }, { 'bar' => [7], 'foo' => [22, 42] }, { 'foo' => [22, 42] }])
93
- n = term.predict(maps, { a: 1 })
93
+ n = term.predict(maps, {})
94
94
  assert_equal(3, n.size)
95
95
  assert_kind_of(Factbase::Taped, n)
96
96
  end
@@ -100,7 +100,7 @@ class TestIndexedTerm < Factbase::Test
100
100
  idx = {}
101
101
  term.redress!(Factbase::IndexedTerm, idx:)
102
102
  maps = Factbase::Taped.new([{ 'foo' => [42] }, { 'alpha' => [] }, {}])
103
- n = term.predict(maps, { a: 1 })
103
+ n = term.predict(maps, {})
104
104
  assert_nil(n)
105
105
  end
106
106
  end
@@ -57,7 +57,7 @@ class TestAggregates < Factbase::Test
57
57
  { 'a' => [4], 'b' => [55] }
58
58
  ]
59
59
  t = Factbase::Syntax.new('(empty (eq b $x))').to_term
60
- assert(t.evaluate(Factbase::Fact.new({ 'x' => 42 }), maps, Factbase.new))
61
- refute(t.evaluate(Factbase::Fact.new({ 'x' => 44 }), maps, Factbase.new))
60
+ assert(t.evaluate(Factbase::Fact.new({ 'x' => [42] }), maps, Factbase.new))
61
+ refute(t.evaluate(Factbase::Fact.new({ 'x' => [44] }), maps, Factbase.new))
62
62
  end
63
63
  end
@@ -116,7 +116,10 @@ class TestQuery < Factbase::Test
116
116
  "(and (exists time) (not (\t\texists pi)))" => 1,
117
117
  '(undef something)' => 3,
118
118
  "(or (eq num +66) (lt time #{(Time.now - 200).utc.iso8601}))" => 1,
119
- '(eq 3 (agg (eq num $num) (count)))' => 1
119
+ '(eq 3 (agg (eq num $num) (count)))' => 1,
120
+ '(and (eq num 42) (not (empty (eq name "Jeff"))))' => 2,
121
+ '(and (eq num 42) (empty (eq x $name)))' => 2,
122
+ '(and (eq num 42) (not (empty (eq name $name))))' => 2
120
123
  }
121
124
  maps = [
122
125
  { 'num' => [42], 'name' => ['Jeff'] },
@@ -156,18 +159,22 @@ class TestQuery < Factbase::Test
156
159
 
157
160
  def test_reading_one
158
161
  maps = [
159
- { 'foo' => [42] },
162
+ { 'foo' => [42], 'hello' => [4] },
160
163
  { 'bar' => [4, 5] }
161
164
  ]
162
165
  with_factbases(maps) do |badge, fb|
163
166
  {
167
+ '(agg (and (eq foo 42) (eq hello $v)) (min foo))' => 42,
168
+ '(agg (or (eq foo 42) (eq bar 4)) (min foo))' => 42,
164
169
  '(agg (exists foo) (first foo))' => [42],
165
170
  '(agg (exists z) (first z))' => nil,
166
171
  '(agg (always) (count))' => 2,
167
172
  '(agg (eq bar $v) (count))' => 1,
173
+ '(agg (eq foo 42) (min foo))' => 42,
174
+ '(agg (and (eq foo 42)) (min foo))' => 42,
168
175
  '(agg (eq z 40) (count))' => 0
169
176
  }.each do |q, expected|
170
- result = fb.query(q).one(fb, v: 4)
177
+ result = fb.query(q).one(fb, 'v' => 4)
171
178
  if expected.nil?
172
179
  assert_nil(result, "#{q} -> nil in #{badge}")
173
180
  else
@@ -190,6 +197,16 @@ class TestQuery < Factbase::Test
190
197
  end
191
198
  end
192
199
 
200
+ def test_finds_with_subsitution
201
+ maps = [{ 'foo' => [42] }, { 'bar' => [7] }, { 'foo' => [666] }]
202
+ with_factbases(maps) do |badge, fb|
203
+ assert_equal(0, fb.query('(eq 2 (agg (eq foo $foo) (count)))').each.to_a.size, "with #{badge}")
204
+ fb.txn do |fbt|
205
+ assert_equal(0, fbt.query('(eq 2 (agg (eq foo $foo) (count)))').each.to_a.size, "with #{badge} (txn)")
206
+ end
207
+ end
208
+ end
209
+
193
210
  def test_scans_and_inserts
194
211
  with_factbases do |_, fb|
195
212
  fb.insert.foo = 42
@@ -277,8 +294,8 @@ class TestQuery < Factbase::Test
277
294
  found += 1
278
295
  end
279
296
  assert_equal(1, found)
280
- assert_equal(1, Factbase::Query.new(maps, '(eq foo $bar)', Factbase.new).each(Factbase.new, bar: 42).to_a.size)
281
- assert_equal(0, Factbase::Query.new(maps, '(eq foo $bar)', Factbase.new).each(Factbase.new, bar: 555).to_a.size)
297
+ assert_equal(1, Factbase::Query.new(maps, '(eq foo $bar)', Factbase.new).each(Factbase.new, bar: [42]).to_a.size)
298
+ assert_equal(0, Factbase::Query.new(maps, '(eq foo $bar)', Factbase.new).each(Factbase.new, bar: [555]).to_a.size)
282
299
  end
283
300
 
284
301
  def test_with_nil_alias
@@ -23,6 +23,13 @@ class TestTee < Factbase::Test
23
23
  assert_equal([13], t['$bar'])
24
24
  end
25
25
 
26
+ def test_no_trip_to_prim_if_not_found
27
+ prim = Factbase::Fact.new({})
28
+ prim.foo = 777
29
+ t = Factbase::Tee.new(prim, Factbase::Fact.new({}))
30
+ assert_nil(t['$foo'])
31
+ end
32
+
26
33
  def test_all_properties
27
34
  prim = Factbase::Fact.new({})
28
35
  prim.foo = 42
@@ -37,10 +44,10 @@ class TestTee < Factbase::Test
37
44
  map = {}
38
45
  prim = Factbase::Fact.new(map)
39
46
  prim.foo = 42
40
- t = Factbase::Tee.new(Factbase::Fact.new({}), { 'bar' => 7 })
41
- assert_equal(7, t['$bar'])
47
+ t = Factbase::Tee.new(Factbase::Fact.new({}), { 'bar' => [7] })
48
+ assert_equal([7], t['$bar'])
42
49
  t = Factbase::Tee.new(prim, t)
43
- assert_equal(7, t['$bar'])
50
+ assert_equal([7], t['$bar'])
44
51
  end
45
52
 
46
53
  def test_prints_to_string
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: factbase
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.7
4
+ version: 0.9.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko