factbase 0.14.0 → 0.14.1

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: e275580781c232bdbea9b569d456ff3955c4a1fe1add33101398d00acc9605e5
4
- data.tar.gz: 5c3a6d0e61c81a8bc7a2cc0a3ca6f003a77ad0cd9fdae1d68e2ecb55d386b169
3
+ metadata.gz: 0dd01490add2a273a8eb479d1cbbb13ab7489f08e2654de8e4d2ce6b141ff9c7
4
+ data.tar.gz: d04b49fb4e9a0caa991143c5d7830d6d2a240a1753090f2c6ac52219e1460e2a
5
5
  SHA512:
6
- metadata.gz: 0d764be837fc143d2a39b7f58d40cc33f93a3fb37a8608cca74b514b41a1ecbfac64c5e4b5bde836fa414fb33ae6cd0c7b7668802a8431f6a6f3a428a3bd6f90
7
- data.tar.gz: 4aa141144fb2b41a4b6a47b0ca2acde9b3c35d1c8bd487700e9fe0d88a19ea6eac0224dd0390969a3377856b0f84d1af3d54f6a870ce63300065f151e2e828f9
6
+ metadata.gz: e7979d0c8e440a3f93891182d50d069b84fdbf403e080dfcc55999d9f12e848554c8282533214e56ad34a9467a8ac9d6700d64e08dff876c70fa6d521afb4f00
7
+ data.tar.gz: 6a9d7711e79ed74ae956f29d13de51e4c6715910c394c273636c875acaf5526223b1813a2d780f977f4049d19e6b734b5cf8832178b69a1f264b3e38888244bd
data/Gemfile.lock CHANGED
@@ -24,12 +24,12 @@ GEM
24
24
  date (3.4.1)
25
25
  decoor (0.1.0)
26
26
  docile (1.4.1)
27
- elapsed (0.1.0)
28
- loog (> 0)
29
- tago (> 0)
27
+ elapsed (0.2.0)
28
+ loog (~> 0.6)
29
+ tago (~> 0.1)
30
30
  ellipsized (0.3.0)
31
31
  erb (5.0.2)
32
- json (2.13.0)
32
+ json (2.13.2)
33
33
  language_server-protocol (3.17.0.5)
34
34
  lint_roller (1.1.0)
35
35
  logger (1.7.0)
@@ -52,7 +52,7 @@ GEM
52
52
  os (1.1.4)
53
53
  others (0.1.1)
54
54
  parallel (1.27.0)
55
- parser (3.3.8.0)
55
+ parser (3.3.9.0)
56
56
  ast (~> 2.4.1)
57
57
  racc
58
58
  prism (1.4.0)
@@ -72,7 +72,7 @@ GEM
72
72
  psych (>= 4.0.0)
73
73
  regexp_parser (2.10.0)
74
74
  rexml (3.4.1)
75
- rubocop (1.78.0)
75
+ rubocop (1.79.0)
76
76
  json (~> 2.3)
77
77
  language_server-protocol (~> 3.17.0.2)
78
78
  lint_roller (~> 1.1.0)
@@ -80,8 +80,9 @@ GEM
80
80
  parser (>= 3.3.0.2)
81
81
  rainbow (>= 2.2.2, < 4.0)
82
82
  regexp_parser (>= 2.9.3, < 3.0)
83
- rubocop-ast (>= 1.45.1, < 2.0)
83
+ rubocop-ast (>= 1.46.0, < 2.0)
84
84
  ruby-progressbar (~> 1.7)
85
+ tsort (>= 0.2.0)
85
86
  unicode-display_width (>= 2.4.0, < 4.0)
86
87
  rubocop-ast (1.46.0)
87
88
  parser (>= 3.3.7.2)
@@ -112,6 +113,7 @@ GEM
112
113
  threads (0.4.1)
113
114
  backtrace (~> 0)
114
115
  concurrent-ruby (~> 1.0)
116
+ tsort (0.2.0)
115
117
  unicode-display_width (3.1.4)
116
118
  unicode-emoji (~> 4.0, >= 4.0.4)
117
119
  unicode-emoji (4.0.4)
data/README.md CHANGED
@@ -210,33 +210,35 @@ This is the result of the benchmark:
210
210
  <!-- benchmark_begin -->
211
211
  ```text
212
212
  user
213
- insert 20000 facts 0.618307
214
- export 20000 facts 0.021391
215
- import 410726 bytes (20000 facts) 0.030150
216
- insert 10 facts 0.045651
217
- query 10 times w/txn 1.970434
218
- query 10 times w/o txn 0.039459
219
- modify 10 attrs w/txn 1.819769
220
- delete 10 facts w/txn 1.056563
221
- (and (eq what 'issue-was-closed') (exists... -> 200 2.125753
222
- (and (eq what 'issue-was-closed') (exists... -> 200/txn 1.135618
223
- (and (eq what 'issue-was-closed') (exists... -> zero 2.422668
224
- (and (eq what 'issue-was-closed') (exists... -> zero/txn 1.288236
225
- (gt time '2024-03-23T03:21:43Z') 0.108849
226
- (gt cost 50) 0.090092
227
- (eq title 'Object Thinking 5000') 0.002640
228
- (and (eq foo 42.998) (or (gt bar 200) (absent zzz))) 0.023785
229
- (eq id (agg (always) (max id))) 0.252980
230
- (join "c<=cost,b<=bar" (eq id (agg (always) (max id)))) 0.655997
231
- delete! 0.075510
232
- Taped.append() x50000 0.042923
233
- Taped.each() x125 1.343819
234
- Taped.delete_if() x375 0.830124
213
+ insert 20000 facts 0.658630
214
+ export 20000 facts 0.025967
215
+ import 411020 bytes (20000 facts) 0.024282
216
+ insert 10 facts 0.050191
217
+ query 10 times w/txn 2.063964
218
+ query 10 times w/o txn 0.044326
219
+ modify 10 attrs w/txn 1.745367
220
+ delete 10 facts w/txn 1.023205
221
+ (and (eq what 'issue-was-closed') (exists... -> 200 2.043080
222
+ (and (eq what 'issue-was-closed') (exists... -> 200/txn 1.019861
223
+ (and (eq what 'issue-was-closed') (exists... -> zero 2.350912
224
+ (and (eq what 'issue-was-closed') (exists... -> zero/txn 1.187649
225
+ (gt time '2024-03-23T03:21:43Z') 0.304861
226
+ (gt cost 50) 0.234136
227
+ (eq title 'Object Thinking 5000') 0.091766
228
+ (and (eq foo 42.998) (or (gt bar 200) (absent z... 0.049974
229
+ (and (exists foo) (not (exists blue))) 0.926298
230
+ (eq id (agg (always) (max id))) 0.606111
231
+ (join "c<=cost,b<=bar" (eq id (agg (always) (ma... 1.276007
232
+ (and (eq what "foo") (join "w<=what" (and (eq i... 6.827440
233
+ delete! 0.218373
234
+ Taped.append() x50000 0.023564
235
+ Taped.each() x125 1.348705
236
+ Taped.delete_if() x375 0.812740
235
237
  ```
236
238
 
237
239
  The results were calculated in [this GHA job][benchmark-gha]
238
- on 2025-06-21 at 08:24,
240
+ on 2025-07-28 at 17:02,
239
241
  on Linux with 4 CPUs.
240
242
  <!-- benchmark_end -->
241
243
 
242
- [benchmark-gha]: https://github.com/yegor256/factbase/actions/runs/15793882855
244
+ [benchmark-gha]: https://github.com/yegor256/factbase/actions/runs/16575338618
@@ -3,12 +3,16 @@
3
3
  # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
+ require 'ellipsized'
7
+ require 'timeout'
6
8
  require_relative '../lib/factbase'
7
9
 
8
10
  def bench_query(bmk, fb)
9
11
  total = 20_000
10
12
  total.times do |i|
11
13
  f = fb.insert
14
+ f.what = 'foo'
15
+ f.where = 'github'
12
16
  f.id = i
13
17
  f.title = "Object Thinking #{i}"
14
18
  f.time = Time.now.iso8601
@@ -20,7 +24,7 @@ def bench_query(bmk, fb)
20
24
  f.zzz = "Extra#{i}" if (i % 10).zero?
21
25
  end
22
26
 
23
- runs = 10
27
+ runs = 3
24
28
  [
25
29
  '(gt time \'2024-03-23T03:21:43Z\')',
26
30
  '(gt cost 50)',
@@ -28,11 +32,21 @@ def bench_query(bmk, fb)
28
32
  '(and (eq foo 42.998) (or (gt bar 200) (absent zzz)))',
29
33
  '(and (exists foo) (not (exists blue)))',
30
34
  '(eq id (agg (always) (max id)))',
31
- '(join "c<=cost,b<=bar" (eq id (agg (always) (max id))))'
35
+ '(join "c<=cost,b<=bar" (eq id (agg (always) (max id))))',
36
+ '(and
37
+ (eq what "foo")
38
+ (join "w<=what"
39
+ (and
40
+ (eq id $id)
41
+ (eq what "foo")
42
+ (eq where "github")))
43
+ (assert "has it" (one id)))'
32
44
  ].each do |q|
33
- bmk.report(q) do
34
- runs.times do
35
- fb.query(q).each.to_a
45
+ bmk.report(q.tr("\n", ' ').gsub(/\s+/, ' ').ellipsized(50, :right)) do
46
+ Timeout.timeout(runs * 3) do
47
+ runs.times do
48
+ fb.query(q).each.to_a
49
+ end
36
50
  end
37
51
  end
38
52
  end
@@ -11,7 +11,10 @@ facts:
11
11
  - person: Walter
12
12
  age: 45
13
13
  queries:
14
- - query: (and (join 'age<=age' (eq person $name)) (exists age))
14
+ - query: |
15
+ (and
16
+ (join 'age<=age' (eq person $name))
17
+ (exists age))
15
18
  size: 4
16
19
  - query: (and (join 'age' (eq person $name)) (exists age))
17
20
  size: 4
@@ -94,10 +94,7 @@ module Factbase::IndexedTerm
94
94
  else
95
95
  @operands.each do |o|
96
96
  n = o.predict(maps, params)
97
- if n.nil?
98
- r = nil
99
- break
100
- end
97
+ break if n.nil?
101
98
  if r.nil?
102
99
  r = n
103
100
  else
@@ -45,7 +45,8 @@ class Factbase::Query
45
45
  yielded = 0
46
46
  params = params.transform_keys(&:to_s) if params.is_a?(Hash)
47
47
  maybe = @term.predict(@maps, Factbase::Tee.new({}, params))
48
- (maybe || @maps).each do |m|
48
+ maybe ||= @maps unless maybe.equal?(@maps)
49
+ maybe.each do |m|
49
50
  extras = {}
50
51
  f = Factbase::Fact.new(m)
51
52
  f = Factbase::Tee.new(f, params)
data/lib/factbase/term.rb CHANGED
@@ -90,6 +90,7 @@ class Factbase::Term
90
90
  # @param [Hash] args Attributes to set
91
91
  def redress!(type, **args)
92
92
  extend type
93
+
93
94
  args.each { |k, v| send(:instance_variable_set, :"@#{k}", v) }
94
95
  @operands.map do |op|
95
96
  if op.is_a?(Factbase::Term)
@@ -163,19 +164,22 @@ class Factbase::Term
163
164
  # Turns it into a string.
164
165
  # @return [String] The string of it
165
166
  def to_s
166
- items = []
167
- items << @op
168
- items +=
169
- @operands.map do |o|
170
- if o.is_a?(String)
171
- "'#{o.gsub("'", "\\\\'").gsub('"', '\\\\"')}'"
172
- elsif o.is_a?(Time)
173
- o.utc.iso8601
174
- else
175
- o.to_s
176
- end
167
+ @to_s ||=
168
+ begin
169
+ items = []
170
+ items << @op
171
+ items +=
172
+ @operands.map do |o|
173
+ if o.is_a?(String)
174
+ "'#{o.gsub("'", "\\\\'").gsub('"', '\\\\"')}'"
175
+ elsif o.is_a?(Time)
176
+ o.utc.iso8601
177
+ else
178
+ o.to_s
179
+ end
180
+ end
181
+ "(#{items.join(' ')})"
177
182
  end
178
- "(#{items.join(' ')})"
179
183
  end
180
184
 
181
185
  def at(fact, maps, fb)
@@ -9,5 +9,5 @@
9
9
  # License:: MIT
10
10
  class Factbase
11
11
  # Current version of the gem (changed by .rultor.yml on every release)
12
- VERSION = '0.14.0' unless const_defined?(:VERSION)
12
+ VERSION = '0.14.1' unless const_defined?(:VERSION)
13
13
  end
@@ -4,7 +4,9 @@
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
6
  require_relative '../../test__helper'
7
+ require_relative '../../../lib/factbase/accum'
7
8
  require_relative '../../../lib/factbase/term'
9
+ require_relative '../../../lib/factbase/syntax'
8
10
 
9
11
  # Logical test.
10
12
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -96,29 +96,29 @@ class TestImpatient < Factbase::Test
96
96
  end
97
97
 
98
98
  def test_query_one_timeout
99
- slow_fb = SlowFactbase.new
100
- 1000.times do
101
- slow_fb.insert.value = rand(1000)
99
+ slow = SlowFactbase.new
100
+ 10_000.times do
101
+ slow.insert.value = rand(1000)
102
102
  end
103
- fb = Factbase::Impatient.new(slow_fb, timeout: 0.1)
103
+ fb = Factbase::Impatient.new(slow, timeout: 0.01)
104
104
  ex =
105
105
  assert_raises(StandardError) do
106
- fb.query('(always)').one
106
+ fb.query('(agg (min value))').one
107
107
  end
108
- assert_includes(ex.message, 'Query timed out after 0.1 seconds')
108
+ assert_includes(ex.message, 'Query timed out after 0.01 seconds')
109
109
  end
110
110
 
111
111
  def test_delete_timeout
112
- slow_fb = SlowDeleteFactbase.new
112
+ slow = SlowDeleteFactbase.new
113
113
  1000.times do |i|
114
- slow_fb.insert.value = i
114
+ slow.insert.value = i
115
115
  end
116
- fb = Factbase::Impatient.new(slow_fb, timeout: 0.1)
116
+ fb = Factbase::Impatient.new(slow, timeout: 0.01)
117
117
  ex =
118
118
  assert_raises(StandardError) do
119
119
  fb.query('(gt value 500)').delete!
120
120
  end
121
- assert_includes(ex.message, 'Query timed out after 0.1 seconds')
121
+ assert_includes(ex.message, 'Query timed out after 0.01 seconds')
122
122
  end
123
123
 
124
124
  def test_with_txn
@@ -184,9 +184,9 @@ class TestImpatient < Factbase::Test
184
184
  end
185
185
 
186
186
  def test_custom_timeout
187
- slow_fb = SlowEnoughFactbase.new
188
- slow_fb.insert.value = 42
189
- fb = Factbase::Impatient.new(slow_fb, timeout: 2)
187
+ slow = SlowEnoughFactbase.new
188
+ slow.insert.value = 42
189
+ fb = Factbase::Impatient.new(slow, timeout: 2)
190
190
  start = Time.now
191
191
  result = fb.query('(agg (eq value 42) (first value))').one
192
192
  elapsed = Time.now - start
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.14.0
4
+ version: 0.14.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko