factbase 0.9.0 → 0.9.2
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 +4 -4
- data/Gemfile +4 -2
- data/Gemfile.lock +26 -15
- data/README.md +24 -24
- data/Rakefile +20 -1
- data/lib/factbase/inv.rb +18 -6
- data/lib/factbase/logged.rb +40 -38
- data/lib/factbase/rules.rb +2 -2
- data/lib/factbase/tallied.rb +2 -2
- data/lib/factbase/taped.rb +8 -0
- data/lib/factbase/term.rb +11 -11
- data/lib/factbase/terms/aggregates.rb +1 -1
- data/lib/factbase/terms/aliases.rb +1 -1
- data/lib/factbase/terms/casting.rb +1 -1
- data/lib/factbase/terms/debug.rb +1 -1
- data/lib/factbase/terms/defn.rb +1 -1
- data/lib/factbase/terms/logical.rb +1 -1
- data/lib/factbase/terms/math.rb +1 -1
- data/lib/factbase/terms/meta.rb +1 -1
- data/lib/factbase/terms/ordering.rb +1 -1
- data/lib/factbase/terms/strings.rb +1 -1
- data/lib/factbase/terms/system.rb +1 -1
- data/lib/factbase.rb +1 -1
- data/test/factbase/terms/test_aliases.rb +1 -0
- data/test/factbase/test_query.rb +33 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b0b91a22c7ec63e9ec1b98bc325006645243b11d2b0fa1ca591f005c5e7b34e
|
4
|
+
data.tar.gz: 60014d07339a593674ec768b63c99a4a993f7b22a0a6f1eb1386e8137c90db30
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 82e2abb7c56c198486d512ee9145c22399f01342107b4ebac14556977f87d8811908230522473b926057b04f355e890e391c313e488580cf1a1bb17b658e1dd7
|
7
|
+
data.tar.gz: 03225a085c0acb3d9bc57ddaf71ed4c2a878c1cafc88858b39ee0872ff29348ad28d772506eca16fbf6f2183e9a55ddb56e77899b49289f15d72bc92193d6b98
|
data/Gemfile
CHANGED
@@ -6,11 +6,13 @@
|
|
6
6
|
source 'https://rubygems.org'
|
7
7
|
gemspec
|
8
8
|
|
9
|
-
gem 'minitest', '5.25.
|
9
|
+
gem 'minitest', '5.25.5', require: false
|
10
10
|
gem 'minitest-reporters', '1.7.1', require: false
|
11
|
+
gem 'os', '>0', require: false
|
12
|
+
gem 'qbash', '>0', require: false
|
11
13
|
gem 'rake', '13.2.1', require: false
|
12
14
|
gem 'rspec-rails', '7.1.1', require: false
|
13
|
-
gem 'rubocop', '1.
|
15
|
+
gem 'rubocop', '1.74.0', require: false
|
14
16
|
gem 'rubocop-minitest', '>0', require: false
|
15
17
|
gem 'rubocop-performance', '>0', require: false
|
16
18
|
gem 'rubocop-rake', '>0', require: false
|
data/Gemfile.lock
CHANGED
@@ -14,9 +14,9 @@ PATH
|
|
14
14
|
GEM
|
15
15
|
remote: https://rubygems.org/
|
16
16
|
specs:
|
17
|
-
actionpack (8.0.
|
18
|
-
actionview (= 8.0.
|
19
|
-
activesupport (= 8.0.
|
17
|
+
actionpack (8.0.2)
|
18
|
+
actionview (= 8.0.2)
|
19
|
+
activesupport (= 8.0.2)
|
20
20
|
nokogiri (>= 1.8.5)
|
21
21
|
rack (>= 2.2.4)
|
22
22
|
rack-session (>= 1.0.1)
|
@@ -24,13 +24,13 @@ GEM
|
|
24
24
|
rails-dom-testing (~> 2.2)
|
25
25
|
rails-html-sanitizer (~> 1.6)
|
26
26
|
useragent (~> 0.16)
|
27
|
-
actionview (8.0.
|
28
|
-
activesupport (= 8.0.
|
27
|
+
actionview (8.0.2)
|
28
|
+
activesupport (= 8.0.2)
|
29
29
|
builder (~> 3.1)
|
30
30
|
erubi (~> 1.11)
|
31
31
|
rails-dom-testing (~> 2.2)
|
32
32
|
rails-html-sanitizer (~> 1.6)
|
33
|
-
activesupport (8.0.
|
33
|
+
activesupport (8.0.2)
|
34
34
|
base64
|
35
35
|
benchmark (>= 0.3)
|
36
36
|
bigdecimal
|
@@ -58,6 +58,9 @@ GEM
|
|
58
58
|
diff-lcs (1.6.0)
|
59
59
|
docile (1.4.1)
|
60
60
|
drb (2.2.1)
|
61
|
+
elapsed (0.0.1)
|
62
|
+
loog (> 0)
|
63
|
+
tago (> 0)
|
61
64
|
erubi (1.13.1)
|
62
65
|
i18n (1.14.7)
|
63
66
|
concurrent-ruby (~> 1.0)
|
@@ -66,7 +69,7 @@ GEM
|
|
66
69
|
pp (>= 0.6.0)
|
67
70
|
rdoc (>= 4.0.0)
|
68
71
|
reline (>= 0.4.2)
|
69
|
-
json (2.10.
|
72
|
+
json (2.10.2)
|
70
73
|
language_server-protocol (3.17.0.4)
|
71
74
|
lint_roller (1.1.0)
|
72
75
|
logger (1.6.6)
|
@@ -74,7 +77,7 @@ GEM
|
|
74
77
|
crass (~> 1.0.2)
|
75
78
|
nokogiri (>= 1.12.0)
|
76
79
|
loog (0.6.0)
|
77
|
-
minitest (5.25.
|
80
|
+
minitest (5.25.5)
|
78
81
|
minitest-reporters (1.7.1)
|
79
82
|
ansi
|
80
83
|
builder
|
@@ -88,6 +91,7 @@ GEM
|
|
88
91
|
racc (~> 1.4)
|
89
92
|
nokogiri (1.18.3-x86_64-linux-gnu)
|
90
93
|
racc (~> 1.4)
|
94
|
+
os (1.1.4)
|
91
95
|
others (0.0.3)
|
92
96
|
parallel (1.26.3)
|
93
97
|
parser (3.3.7.1)
|
@@ -99,8 +103,13 @@ GEM
|
|
99
103
|
psych (5.2.3)
|
100
104
|
date
|
101
105
|
stringio
|
106
|
+
qbash (0.4.0)
|
107
|
+
backtrace (> 0)
|
108
|
+
elapsed (> 0)
|
109
|
+
loog (> 0)
|
110
|
+
tago (> 0)
|
102
111
|
racc (1.8.1)
|
103
|
-
rack (3.1.
|
112
|
+
rack (3.1.12)
|
104
113
|
rack-session (2.1.0)
|
105
114
|
base64 (>= 0.1.0)
|
106
115
|
rack (>= 3.0.0)
|
@@ -115,9 +124,9 @@ GEM
|
|
115
124
|
rails-html-sanitizer (1.6.2)
|
116
125
|
loofah (~> 2.21)
|
117
126
|
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
|
118
|
-
railties (8.0.
|
119
|
-
actionpack (= 8.0.
|
120
|
-
activesupport (= 8.0.
|
127
|
+
railties (8.0.2)
|
128
|
+
actionpack (= 8.0.2)
|
129
|
+
activesupport (= 8.0.2)
|
121
130
|
irb (~> 1.13)
|
122
131
|
rackup (>= 1.0.0)
|
123
132
|
rake (>= 12.2)
|
@@ -148,7 +157,7 @@ GEM
|
|
148
157
|
rspec-mocks (~> 3.13)
|
149
158
|
rspec-support (~> 3.13)
|
150
159
|
rspec-support (3.13.2)
|
151
|
-
rubocop (1.
|
160
|
+
rubocop (1.74.0)
|
152
161
|
json (~> 2.3)
|
153
162
|
language_server-protocol (~> 3.17.0.2)
|
154
163
|
lint_roller (~> 1.1.0)
|
@@ -214,11 +223,13 @@ PLATFORMS
|
|
214
223
|
|
215
224
|
DEPENDENCIES
|
216
225
|
factbase!
|
217
|
-
minitest (= 5.25.
|
226
|
+
minitest (= 5.25.5)
|
218
227
|
minitest-reporters (= 1.7.1)
|
228
|
+
os (> 0)
|
229
|
+
qbash (> 0)
|
219
230
|
rake (= 13.2.1)
|
220
231
|
rspec-rails (= 7.1.1)
|
221
|
-
rubocop (= 1.
|
232
|
+
rubocop (= 1.74.0)
|
222
233
|
rubocop-minitest (> 0)
|
223
234
|
rubocop-performance (> 0)
|
224
235
|
rubocop-rake (> 0)
|
data/README.md
CHANGED
@@ -209,33 +209,33 @@ This is the result of the benchmark:
|
|
209
209
|
<!-- benchmark_begin -->
|
210
210
|
```text
|
211
211
|
user system total real
|
212
|
-
insert 20000 facts 0.
|
213
|
-
export 20000 facts 0.
|
214
|
-
import
|
215
|
-
insert 10 facts 0.
|
216
|
-
query 10 times w/txn
|
217
|
-
query 10 times w/o txn 0.
|
218
|
-
modify 10 attrs w/txn 1.
|
219
|
-
delete 10 facts w/txn 0.
|
220
|
-
(and (eq what 'issue-was-closed') (exists... -> 200 2.
|
221
|
-
(and (eq what 'issue-was-closed') (exists... -> 200/txn 2.
|
222
|
-
(and (eq what 'issue-was-closed') (exists... -> zero 4.
|
223
|
-
(and (eq what 'issue-was-closed') (exists... -> zero/txn 4.
|
224
|
-
(gt time '2024-03-23T03:21:43Z') 0.
|
225
|
-
(gt cost 50) 0.
|
226
|
-
(eq title 'Object Thinking 5000') 0.
|
227
|
-
(and (eq foo 42.998) (or (gt bar 200) (absent zzz))) 0.
|
228
|
-
(eq id (agg (always) (max id))) 0.
|
229
|
-
(join "c<=cost,b<=bar" (eq id (agg (always) (max id)))) 1.
|
230
|
-
delete! 0.
|
231
|
-
Taped.append() x50000 0.
|
232
|
-
Taped.each() x125 1.
|
233
|
-
Taped.delete_if() x375 0.
|
212
|
+
insert 20000 facts 0.584859 0.005297 0.590156 ( 0.590186)
|
213
|
+
export 20000 facts 0.018342 0.005935 0.024277 ( 0.024282)
|
214
|
+
import 410974 bytes (20000 facts) 0.028027 0.004994 0.033021 ( 0.033026)
|
215
|
+
insert 10 facts 0.041771 0.000989 0.042760 ( 0.042763)
|
216
|
+
query 10 times w/txn 2.020294 0.038146 2.058440 ( 2.059555)
|
217
|
+
query 10 times w/o txn 0.727753 0.001014 0.728767 ( 0.728806)
|
218
|
+
modify 10 attrs w/txn 1.919959 0.014025 1.933984 ( 1.934328)
|
219
|
+
delete 10 facts w/txn 0.739267 0.000000 0.739267 ( 0.739299)
|
220
|
+
(and (eq what 'issue-was-closed') (exists... -> 200 2.717595 0.003012 2.720607 ( 2.720777)
|
221
|
+
(and (eq what 'issue-was-closed') (exists... -> 200/txn 2.732913 0.002012 2.734925 ( 2.735227)
|
222
|
+
(and (eq what 'issue-was-closed') (exists... -> zero 4.149053 0.001010 4.150063 ( 4.150436)
|
223
|
+
(and (eq what 'issue-was-closed') (exists... -> zero/txn 4.116972 0.001001 4.117973 ( 4.119644)
|
224
|
+
(gt time '2024-03-23T03:21:43Z') 0.107332 0.000002 0.107334 ( 0.107336)
|
225
|
+
(gt cost 50) 0.094454 0.000000 0.094454 ( 0.094458)
|
226
|
+
(eq title 'Object Thinking 5000') 0.003828 0.000000 0.003828 ( 0.003830)
|
227
|
+
(and (eq foo 42.998) (or (gt bar 200) (absent zzz))) 0.055983 0.000000 0.055983 ( 0.055986)
|
228
|
+
(eq id (agg (always) (max id))) 0.329920 0.001995 0.331915 ( 0.332005)
|
229
|
+
(join "c<=cost,b<=bar" (eq id (agg (always) (max id)))) 1.448262 0.002005 1.450267 ( 1.450350)
|
230
|
+
delete! 0.056928 0.000000 0.056928 ( 0.056932)
|
231
|
+
Taped.append() x50000 0.035070 0.001000 0.036070 ( 0.036074)
|
232
|
+
Taped.each() x125 1.310450 0.000000 1.310450 ( 1.310521)
|
233
|
+
Taped.delete_if() x375 0.819224 0.000001 0.819225 ( 0.819270)
|
234
234
|
```
|
235
235
|
|
236
236
|
The results were calculated in [this GHA job][benchmark-gha]
|
237
|
-
on 2025-03-
|
237
|
+
on 2025-03-14 at 09:14,
|
238
238
|
on Linux with 4 CPUs.
|
239
239
|
<!-- benchmark_end -->
|
240
240
|
|
241
|
-
[benchmark-gha]: https://github.com/yegor256/factbase/actions/runs/
|
241
|
+
[benchmark-gha]: https://github.com/yegor256/factbase/actions/runs/13853425019
|
data/Rakefile
CHANGED
@@ -3,9 +3,12 @@
|
|
3
3
|
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
4
4
|
# SPDX-License-Identifier: MIT
|
5
5
|
|
6
|
+
require 'qbash'
|
6
7
|
require 'rubygems'
|
7
8
|
require 'rake'
|
8
9
|
require 'rake/clean'
|
10
|
+
require 'shellwords'
|
11
|
+
require 'os'
|
9
12
|
|
10
13
|
def name
|
11
14
|
@name ||= File.basename(Dir['*.gemspec'].first, '.*')
|
@@ -15,7 +18,7 @@ def version
|
|
15
18
|
Gem::Specification.load(Dir['*.gemspec'].first).version
|
16
19
|
end
|
17
20
|
|
18
|
-
task default: %i[clean test rubocop yard]
|
21
|
+
task default: %i[clean test picks reqs rubocop yard]
|
19
22
|
|
20
23
|
require 'rake/testtask'
|
21
24
|
desc 'Run all unit tests'
|
@@ -27,6 +30,22 @@ Rake::TestTask.new(:test) do |test|
|
|
27
30
|
test.verbose = false
|
28
31
|
end
|
29
32
|
|
33
|
+
desc 'Run them via Ruby, one by one'
|
34
|
+
task :picks do
|
35
|
+
next if OS.windows?
|
36
|
+
Dir['test/**/*.rb'].each do |f|
|
37
|
+
qbash("bundle exec ruby #{Shellwords.escape(f)}", log: $stdout)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
desc 'Require them via Ruby, one by one'
|
42
|
+
task :reqs do
|
43
|
+
next if OS.windows?
|
44
|
+
Dir['lib/**/*.rb'].each do |f|
|
45
|
+
qbash("bundle exec ruby #{Shellwords.escape(f)}", log: $stdout)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
30
49
|
require 'yard'
|
31
50
|
desc 'Build Yard documentation'
|
32
51
|
YARD::Rake::YardocTask.new do |t|
|
data/lib/factbase/inv.rb
CHANGED
@@ -8,6 +8,17 @@ require 'decoor'
|
|
8
8
|
require_relative '../factbase'
|
9
9
|
|
10
10
|
# A decorator of a Factbase, that checks invariants on every set.
|
11
|
+
#
|
12
|
+
# For example, you can use this decorator if you want to check that every
|
13
|
+
# fact has +when+:
|
14
|
+
#
|
15
|
+
# fb = Factbase::Inv.new(Factbase.new) do |f, fbt|
|
16
|
+
# assert !f['when'].nil?
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# The second argument passed to the block is the factbase, while the first
|
20
|
+
# one is the fact just touched.
|
21
|
+
#
|
11
22
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
12
23
|
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
13
24
|
# License:: MIT
|
@@ -23,8 +34,8 @@ class Factbase::Inv
|
|
23
34
|
Fact.new(@fb.insert, @block)
|
24
35
|
end
|
25
36
|
|
26
|
-
def query(query)
|
27
|
-
Query.new(@fb.query(query), @block)
|
37
|
+
def query(query, maps = nil)
|
38
|
+
Query.new(@fb.query(query, maps), @block, self)
|
28
39
|
end
|
29
40
|
|
30
41
|
def txn
|
@@ -65,14 +76,15 @@ class Factbase::Inv
|
|
65
76
|
class Query
|
66
77
|
decoor(:query)
|
67
78
|
|
68
|
-
def initialize(query, block)
|
79
|
+
def initialize(query, block, fb)
|
69
80
|
@query = query
|
70
81
|
@block = block
|
82
|
+
@fb = fb
|
71
83
|
end
|
72
84
|
|
73
|
-
def each
|
74
|
-
return to_enum(__method__) unless block_given?
|
75
|
-
@query.each do |f|
|
85
|
+
def each(fb = @fb, params = {})
|
86
|
+
return to_enum(__method__, fb, params) unless block_given?
|
87
|
+
@query.each(fb, params) do |f|
|
76
88
|
yield Fact.new(f, @block)
|
77
89
|
end
|
78
90
|
end
|
data/lib/factbase/logged.rb
CHANGED
@@ -22,7 +22,7 @@ class Factbase::Logged
|
|
22
22
|
# @param [Print] tube The tube to use, if log is NIL
|
23
23
|
def initialize(fb, log = nil, time_tolerate: 1, tube: nil)
|
24
24
|
raise 'The "fb" is nil' if fb.nil?
|
25
|
-
@
|
25
|
+
@origin = fb
|
26
26
|
if log.nil?
|
27
27
|
raise 'Either "log" or "tube" must be non-NIL' if tube.nil?
|
28
28
|
@tube = tube
|
@@ -31,17 +31,18 @@ class Factbase::Logged
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
decoor(:
|
34
|
+
decoor(:origin)
|
35
35
|
|
36
36
|
def insert
|
37
37
|
start = Time.now
|
38
|
-
f = @
|
39
|
-
@tube.say(start, "Inserted new fact ##{@
|
38
|
+
f = @origin.insert
|
39
|
+
@tube.say(start, "Inserted new fact ##{@origin.size} in #{start.ago}")
|
40
40
|
Fact.new(f, tube: @tube)
|
41
41
|
end
|
42
42
|
|
43
|
-
def query(
|
44
|
-
|
43
|
+
def query(term, maps = nil)
|
44
|
+
term = to_term(term) if term.is_a?(String)
|
45
|
+
Query.new(term, maps, @tube, @origin)
|
45
46
|
end
|
46
47
|
|
47
48
|
def txn
|
@@ -49,7 +50,7 @@ class Factbase::Logged
|
|
49
50
|
id = nil
|
50
51
|
rollback = false
|
51
52
|
r =
|
52
|
-
@
|
53
|
+
@origin.txn do |fbt|
|
53
54
|
id = fbt.object_id
|
54
55
|
yield Factbase::Logged.new(fbt, tube: @tube)
|
55
56
|
rescue Factbase::Rollback => e
|
@@ -122,40 +123,25 @@ class Factbase::Logged
|
|
122
123
|
# Query decorator.
|
123
124
|
#
|
124
125
|
# This is an internal class, it is not supposed to be instantiated directly.
|
125
|
-
#
|
126
126
|
class Query
|
127
|
-
def initialize(
|
128
|
-
@
|
127
|
+
def initialize(term, maps, tube, fb)
|
128
|
+
@term = term
|
129
|
+
@maps = maps
|
129
130
|
@tube = tube
|
130
131
|
@fb = fb
|
131
132
|
end
|
132
133
|
|
133
|
-
def
|
134
|
-
|
135
|
-
q = Factbase::Syntax.new(@expr).to_term.to_s
|
136
|
-
r = nil
|
137
|
-
tail =
|
138
|
-
Factbase::Logged.elapsed do
|
139
|
-
r = fb.query(@expr).one(fb, params)
|
140
|
-
end
|
141
|
-
if r.nil?
|
142
|
-
@tube.say(start, "Nothing found by '#{q}' #{tail}")
|
143
|
-
else
|
144
|
-
@tube.say(start, "Found #{r} (#{r.class}) by '#{q}' #{tail}")
|
145
|
-
end
|
146
|
-
r
|
147
|
-
end
|
148
|
-
|
149
|
-
def each(fb = @fb, params = {}, &)
|
134
|
+
def each(fb = nil, params = {}, &)
|
135
|
+
return to_enum(__method__, fb, params) unless block_given?
|
150
136
|
start = Time.now
|
151
|
-
q = Factbase::Syntax.new(@
|
137
|
+
q = Factbase::Syntax.new(@term).to_term.to_s
|
152
138
|
if block_given?
|
153
139
|
r = nil
|
154
140
|
tail =
|
155
141
|
Factbase::Logged.elapsed do
|
156
|
-
r = fb.query(@
|
142
|
+
r = @fb.query(@term, @maps).each(@fb, params, &)
|
157
143
|
end
|
158
|
-
raise ".each of #{@
|
144
|
+
raise ".each of #{@term.class} returned #{r.class}" unless r.is_a?(Integer)
|
159
145
|
if r.zero?
|
160
146
|
@tube.say(start, "Nothing found by '#{q}' #{tail}")
|
161
147
|
else
|
@@ -166,7 +152,7 @@ class Factbase::Logged
|
|
166
152
|
array = []
|
167
153
|
tail =
|
168
154
|
Factbase::Logged.elapsed do
|
169
|
-
fb.query(@
|
155
|
+
@fb.query(@term, @maps).each(@fb, params) do |f|
|
170
156
|
array << f
|
171
157
|
end
|
172
158
|
end
|
@@ -179,21 +165,37 @@ class Factbase::Logged
|
|
179
165
|
end
|
180
166
|
end
|
181
167
|
|
182
|
-
def
|
168
|
+
def one(_fb = nil, params = {})
|
169
|
+
start = Time.now
|
170
|
+
q = Factbase::Syntax.new(@term).to_term.to_s
|
171
|
+
r = nil
|
172
|
+
tail =
|
173
|
+
Factbase::Logged.elapsed do
|
174
|
+
r = @fb.query(@term, @maps).one(@fb, params)
|
175
|
+
end
|
176
|
+
if r.nil?
|
177
|
+
@tube.say(start, "Nothing found by '#{q}' #{tail}")
|
178
|
+
else
|
179
|
+
@tube.say(start, "Found #{r} (#{r.class}) by '#{q}' #{tail}")
|
180
|
+
end
|
181
|
+
r
|
182
|
+
end
|
183
|
+
|
184
|
+
def delete!(_fb = nil)
|
183
185
|
r = nil
|
184
186
|
start = Time.now
|
185
|
-
before = fb.size
|
187
|
+
before = @fb.size
|
186
188
|
tail =
|
187
189
|
Factbase::Logged.elapsed do
|
188
|
-
r = @fb.query(@
|
190
|
+
r = @fb.query(@term).delete!(@fb)
|
189
191
|
end
|
190
|
-
raise ".delete! of #{@
|
192
|
+
raise ".delete! of #{@term.class} returned #{r.class}" unless r.is_a?(Integer)
|
191
193
|
if before.zero?
|
192
|
-
@tube.say(start, "There were no facts, nothing deleted by '#{@
|
194
|
+
@tube.say(start, "There were no facts, nothing deleted by '#{@term}' #{tail}")
|
193
195
|
elsif r.zero?
|
194
|
-
@tube.say(start, "No facts out of #{before} deleted by '#{@
|
196
|
+
@tube.say(start, "No facts out of #{before} deleted by '#{@term}' #{tail}")
|
195
197
|
else
|
196
|
-
@tube.say(start, "Deleted #{r} fact(s) out of #{before} by '#{@
|
198
|
+
@tube.say(start, "Deleted #{r} fact(s) out of #{before} by '#{@term}' #{tail}")
|
197
199
|
end
|
198
200
|
r
|
199
201
|
end
|
data/lib/factbase/rules.rb
CHANGED
data/lib/factbase/tallied.rb
CHANGED
data/lib/factbase/taped.rb
CHANGED
data/lib/factbase/term.rb
CHANGED
@@ -45,37 +45,37 @@ class Factbase::Term
|
|
45
45
|
attr_reader :operands
|
46
46
|
|
47
47
|
require_relative 'terms/math'
|
48
|
-
include Factbase::
|
48
|
+
include Factbase::Math
|
49
49
|
|
50
50
|
require_relative 'terms/logical'
|
51
|
-
include Factbase::
|
51
|
+
include Factbase::Logical
|
52
52
|
|
53
53
|
require_relative 'terms/aggregates'
|
54
|
-
include Factbase::
|
54
|
+
include Factbase::Aggregates
|
55
55
|
|
56
56
|
require_relative 'terms/strings'
|
57
|
-
include Factbase::
|
57
|
+
include Factbase::Strings
|
58
58
|
|
59
59
|
require_relative 'terms/casting'
|
60
|
-
include Factbase::
|
60
|
+
include Factbase::Casting
|
61
61
|
|
62
62
|
require_relative 'terms/meta'
|
63
|
-
include Factbase::
|
63
|
+
include Factbase::Meta
|
64
64
|
|
65
65
|
require_relative 'terms/aliases'
|
66
|
-
include Factbase::
|
66
|
+
include Factbase::Aliases
|
67
67
|
|
68
68
|
require_relative 'terms/ordering'
|
69
|
-
include Factbase::
|
69
|
+
include Factbase::Ordering
|
70
70
|
|
71
71
|
require_relative 'terms/defn'
|
72
|
-
include Factbase::
|
72
|
+
include Factbase::Defn
|
73
73
|
|
74
74
|
require_relative 'terms/system'
|
75
|
-
include Factbase::
|
75
|
+
include Factbase::System
|
76
76
|
|
77
77
|
require_relative 'terms/debug'
|
78
|
-
include Factbase::
|
78
|
+
include Factbase::Debug
|
79
79
|
|
80
80
|
# Ctor.
|
81
81
|
# @param [Symbol] operator Operator
|
@@ -10,7 +10,7 @@ require_relative '../../factbase'
|
|
10
10
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
11
11
|
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
12
12
|
# License:: MIT
|
13
|
-
module Factbase::
|
13
|
+
module Factbase::Aggregates
|
14
14
|
def min(_fact, maps, _fb)
|
15
15
|
assert_args(1)
|
16
16
|
_best(maps) { |v, b| v < b }
|
@@ -10,7 +10,7 @@ require_relative '../../factbase'
|
|
10
10
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
11
11
|
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
12
12
|
# License:: MIT
|
13
|
-
module Factbase::
|
13
|
+
module Factbase::Aliases
|
14
14
|
def as(fact, maps, fb)
|
15
15
|
assert_args(2)
|
16
16
|
a = @operands[0]
|
@@ -10,7 +10,7 @@ require_relative '../../factbase'
|
|
10
10
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
11
11
|
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
12
12
|
# License:: MIT
|
13
|
-
module Factbase::
|
13
|
+
module Factbase::Casting
|
14
14
|
def to_string(fact, maps, fb)
|
15
15
|
assert_args(1)
|
16
16
|
vv = _values(0, fact, maps, fb)
|
data/lib/factbase/terms/debug.rb
CHANGED
@@ -10,7 +10,7 @@ require_relative '../../factbase'
|
|
10
10
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
11
11
|
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
12
12
|
# License:: MIT
|
13
|
-
module Factbase::
|
13
|
+
module Factbase::Debug
|
14
14
|
def traced(fact, maps, fb)
|
15
15
|
assert_args(1)
|
16
16
|
t = @operands[0]
|
data/lib/factbase/terms/defn.rb
CHANGED
@@ -10,7 +10,7 @@ require_relative '../../factbase'
|
|
10
10
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
11
11
|
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
12
12
|
# License:: MIT
|
13
|
-
module Factbase::
|
13
|
+
module Factbase::Defn
|
14
14
|
def defn(_fact, _maps, _fb)
|
15
15
|
assert_args(2)
|
16
16
|
fn = @operands[0]
|
@@ -10,7 +10,7 @@ require_relative '../../factbase'
|
|
10
10
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
11
11
|
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
12
12
|
# License:: MIT
|
13
|
-
module Factbase::
|
13
|
+
module Factbase::Logical
|
14
14
|
# Always returns true, regardless of the fact
|
15
15
|
# @param [Factbase::Fact] _fact The fact (unused)
|
16
16
|
# @param [Array<Factbase::Fact>] _maps All maps available (unused)
|
data/lib/factbase/terms/math.rb
CHANGED
@@ -10,7 +10,7 @@ require_relative '../../factbase'
|
|
10
10
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
11
11
|
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
12
12
|
# License:: MIT
|
13
|
-
module Factbase::
|
13
|
+
module Factbase::Math
|
14
14
|
def plus(fact, maps, fb)
|
15
15
|
_arithmetic(:+, fact, maps, fb)
|
16
16
|
end
|
data/lib/factbase/terms/meta.rb
CHANGED
@@ -10,7 +10,7 @@ require_relative '../../factbase'
|
|
10
10
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
11
11
|
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
12
12
|
# License:: MIT
|
13
|
-
module Factbase::
|
13
|
+
module Factbase::Meta
|
14
14
|
def exists(fact, _maps, _fb)
|
15
15
|
assert_args(1)
|
16
16
|
!_by_symbol(0, fact).nil?
|
@@ -10,7 +10,7 @@ require_relative '../../factbase'
|
|
10
10
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
11
11
|
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
12
12
|
# License:: MIT
|
13
|
-
module Factbase::
|
13
|
+
module Factbase::Ordering
|
14
14
|
def prev(fact, maps, fb)
|
15
15
|
assert_args(1)
|
16
16
|
before = @prev
|
@@ -10,7 +10,7 @@ require_relative '../../factbase'
|
|
10
10
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
11
11
|
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
12
12
|
# License:: MIT
|
13
|
-
module Factbase::
|
13
|
+
module Factbase::Strings
|
14
14
|
def concat(fact, maps, fb)
|
15
15
|
(0..@operands.length - 1).map { |i| _values(i, fact, maps, fb)&.first }.join
|
16
16
|
end
|
@@ -10,7 +10,7 @@ require_relative '../../factbase'
|
|
10
10
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
11
11
|
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
12
12
|
# License:: MIT
|
13
|
-
module Factbase::
|
13
|
+
module Factbase::System
|
14
14
|
def env(fact, maps, fb)
|
15
15
|
assert_args(2)
|
16
16
|
n = _values(0, fact, maps, fb)[0]
|
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.
|
85
|
+
VERSION = '0.9.2' 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
|
data/test/factbase/test_query.rb
CHANGED
@@ -4,9 +4,15 @@
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
5
5
|
|
6
6
|
require_relative '../test__helper'
|
7
|
+
require 'loog'
|
7
8
|
require 'time'
|
8
9
|
require_relative '../../lib/factbase'
|
9
10
|
require_relative '../../lib/factbase/query'
|
11
|
+
require_relative '../../lib/factbase/logged'
|
12
|
+
require_relative '../../lib/factbase/pre'
|
13
|
+
require_relative '../../lib/factbase/inv'
|
14
|
+
require_relative '../../lib/factbase/rules'
|
15
|
+
require_relative '../../lib/factbase/tallied'
|
10
16
|
require_relative '../../lib/factbase/cached/cached_factbase'
|
11
17
|
require_relative '../../lib/factbase/indexed/indexed_factbase'
|
12
18
|
require_relative '../../lib/factbase/sync/sync_factbase'
|
@@ -38,7 +44,12 @@ class TestQuery < Factbase::Test
|
|
38
44
|
size = q['size']
|
39
45
|
assert_equal(size, fb.query(qry).each.to_a.size, "#{base}: #{qry} at #{badge}")
|
40
46
|
fb.txn do |fbt|
|
41
|
-
|
47
|
+
facts = fbt.query(qry).each.to_a
|
48
|
+
assert_equal(size, facts.size, "#{base}: #{qry} at #{badge} (in txn)")
|
49
|
+
facts.each do |fact|
|
50
|
+
refute_empty(fact.all_properties)
|
51
|
+
refute_nil(fact.to_s)
|
52
|
+
end
|
42
53
|
end
|
43
54
|
else
|
44
55
|
ret = q['one']
|
@@ -227,13 +238,34 @@ class TestQuery < Factbase::Test
|
|
227
238
|
def with_factbases(maps = [], &)
|
228
239
|
{
|
229
240
|
'plain' => Factbase.new(maps),
|
241
|
+
'pre+plain' => Factbase::Pre.new(Factbase.new(maps)) { nil },
|
242
|
+
'rules+plain' => Factbase::Rules.new(Factbase.new(maps), '(always)'),
|
243
|
+
'inv+plain' => Factbase::Inv.new(Factbase.new(maps)) { nil },
|
230
244
|
'sync+plain' => Factbase::SyncFactbase.new(Factbase.new(maps)),
|
245
|
+
'tallied+plain' => Factbase::Tallied.new(Factbase.new(maps)),
|
231
246
|
'indexed+plain' => Factbase::IndexedFactbase.new(Factbase.new(maps)),
|
232
247
|
'cached+plain' => Factbase::CachedFactbase.new(Factbase.new(maps)),
|
248
|
+
'logged+plain' => Factbase::Logged.new(Factbase.new(maps), Loog::NULL),
|
233
249
|
'indexed+cached+plain' => Factbase::IndexedFactbase.new(Factbase::CachedFactbase.new(Factbase.new(maps))),
|
234
250
|
'cached+indexed+plain' => Factbase::CachedFactbase.new(Factbase::IndexedFactbase.new(Factbase.new(maps))),
|
235
251
|
'sync+cached+indexed+plain' => Factbase::SyncFactbase.new(
|
236
252
|
Factbase::CachedFactbase.new(Factbase::IndexedFactbase.new(Factbase.new(maps)))
|
253
|
+
),
|
254
|
+
'all+plain' => Factbase::Tallied.new(
|
255
|
+
Factbase::Pre.new(
|
256
|
+
Factbase::Rules.new(
|
257
|
+
Factbase::Inv.new(
|
258
|
+
Factbase::SyncFactbase.new(
|
259
|
+
Factbase::CachedFactbase.new(
|
260
|
+
Factbase::IndexedFactbase.new(
|
261
|
+
Factbase.new(maps)
|
262
|
+
)
|
263
|
+
)
|
264
|
+
)
|
265
|
+
) { nil },
|
266
|
+
'(always)'
|
267
|
+
)
|
268
|
+
) { nil }
|
237
269
|
)
|
238
270
|
}.each(&)
|
239
271
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: factbase
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-03-
|
10
|
+
date: 2025-03-14 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: backtrace
|