factbase 0.9.9 → 0.10.0

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: 72ae2c1184dfd8ab966591846cd054c3155b0536d8c7f2f7acf636df1eb7e045
4
- data.tar.gz: fcf929766bf80cc040744ce9caa719503548fac719d956f676e9604374d78b8c
3
+ metadata.gz: b91c02657bba3cc0c5d801a273b49c9fd18f0faeb94bf366f5e5f7f224dd703b
4
+ data.tar.gz: c6a77ef66e2a6b06d6e072c229b1b90f602adc8769f3434239d08b02f119b9c4
5
5
  SHA512:
6
- metadata.gz: 0d6c3b87fd94afe4fc7984ca17be09ffd6dbff5d93951e264720201e2e5680e387fc0215331af563af7cc78ac3db9e199ca8a0aadc39d989fb377b975d3e1b8d
7
- data.tar.gz: 26c9ffe593d79fc17d80949208cc0833d4147684a0fcd221dc6abd669c545da678dc4fd52723913bc29a68662ca43cf7470a9523022d0919af6dd42a440d69ca
6
+ metadata.gz: 50d3c7680612b0a02bec34b560581b3e1575e95d30511ec61bc7fa1504a42566116960532e2c9f9b0bb1ee6441d0c4eeed3a1b7e9076a7436af7a0a2c3e077ab
7
+ data.tar.gz: 69d6fb049f6631fbc9d17ee24d414cfa7c3acd6d3789f73f4613cb10230c0a697c2427eaf8a028db6f61ea1c2e08fb61cf51c34e79cd722c235c0a6127f3c06a
data/Gemfile.lock CHANGED
@@ -48,7 +48,7 @@ GEM
48
48
  os (1.1.4)
49
49
  others (0.0.3)
50
50
  parallel (1.26.3)
51
- parser (3.3.7.3)
51
+ parser (3.3.7.4)
52
52
  ast (~> 2.4.1)
53
53
  racc
54
54
  prism (1.4.0)
@@ -67,7 +67,7 @@ GEM
67
67
  psych (>= 4.0.0)
68
68
  regexp_parser (2.10.0)
69
69
  rexml (3.4.1)
70
- rubocop (1.75.1)
70
+ rubocop (1.75.2)
71
71
  json (~> 2.3)
72
72
  language_server-protocol (~> 3.17.0.2)
73
73
  lint_roller (~> 1.1.0)
@@ -75,19 +75,19 @@ GEM
75
75
  parser (>= 3.3.0.2)
76
76
  rainbow (>= 2.2.2, < 4.0)
77
77
  regexp_parser (>= 2.9.3, < 3.0)
78
- rubocop-ast (>= 1.43.0, < 2.0)
78
+ rubocop-ast (>= 1.44.0, < 2.0)
79
79
  ruby-progressbar (~> 1.7)
80
80
  unicode-display_width (>= 2.4.0, < 4.0)
81
- rubocop-ast (1.43.0)
81
+ rubocop-ast (1.44.0)
82
82
  parser (>= 3.3.7.2)
83
83
  prism (~> 1.4)
84
- rubocop-minitest (0.37.1)
84
+ rubocop-minitest (0.38.0)
85
85
  lint_roller (~> 1.1)
86
- rubocop (>= 1.72.1, < 2.0)
86
+ rubocop (>= 1.75.0, < 2.0)
87
87
  rubocop-ast (>= 1.38.0, < 2.0)
88
- rubocop-performance (1.24.0)
88
+ rubocop-performance (1.25.0)
89
89
  lint_roller (~> 1.1)
90
- rubocop (>= 1.72.1, < 2.0)
90
+ rubocop (>= 1.75.0, < 2.0)
91
91
  rubocop-ast (>= 1.38.0, < 2.0)
92
92
  rubocop-rake (0.7.1)
93
93
  lint_roller (~> 1.1)
data/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # Single-Table NoSQL-ish In-Memory Database
2
2
 
3
- [![DevOps By Rultor.com](http://www.rultor.com/b/yegor256/factbase)](http://www.rultor.com/p/yegor256/factbase)
3
+ [![DevOps By Rultor.com](https://www.rultor.com/b/yegor256/factbase)](https://www.rultor.com/p/yegor256/factbase)
4
4
  [![We recommend RubyMine](https://www.elegantobjects.org/rubymine.svg)](https://www.jetbrains.com/ruby/)
5
5
 
6
6
  [![rake](https://github.com/yegor256/factbase/actions/workflows/rake.yml/badge.svg)](https://github.com/yegor256/factbase/actions/workflows/rake.yml)
7
- [![PDD status](http://www.0pdd.com/svg?name=yegor256/factbase)](http://www.0pdd.com/p?name=yegor256/factbase)
8
- [![Gem Version](https://badge.fury.io/rb/factbase.svg)](http://badge.fury.io/rb/factbase)
7
+ [![PDD status](https://www.0pdd.com/svg?name=yegor256/factbase)](https://www.0pdd.com/p?name=yegor256/factbase)
8
+ [![Gem Version](https://badge.fury.io/rb/factbase.svg)](https://badge.fury.io/rb/factbase)
9
9
  [![Test Coverage](https://img.shields.io/codecov/c/github/yegor256/factbase.svg)](https://codecov.io/github/yegor256/factbase?branch=master)
10
- [![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](http://rubydoc.info/github/yegor256/factbase/master/frames)
10
+ [![Yard Docs](https://img.shields.io/badge/yard-docs-blue.svg)](https://rubydoc.info/github/yegor256/factbase/master/frames)
11
11
  [![Hits-of-Code](https://hitsofcode.com/github/yegor256/factbase)](https://hitsofcode.com/view/github/yegor256/factbase)
12
12
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/yegor256/factbase/blob/master/LICENSE.txt)
13
13
  [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fyegor256%2Ffactbase.svg?type=shield&issueType=license)](https://app.fossa.com/projects/git%2Bgithub.com%2Fyegor256%2Ffactbase?ref=badge_shield&issueType=license)
@@ -210,33 +210,33 @@ This is the result of the benchmark:
210
210
  <!-- benchmark_begin -->
211
211
  ```text
212
212
  user system total real
213
- insert 20000 facts 0.597725 0.004012 0.601737 ( 0.601785)
214
- export 20000 facts 0.020481 0.003039 0.023520 ( 0.023523)
215
- import 410961 bytes (20000 facts) 0.021204 0.002017 0.023221 ( 0.023223)
216
- insert 10 facts 0.042456 0.002961 0.045417 ( 0.045418)
217
- query 10 times w/txn 1.594704 0.026991 1.621695 ( 1.621807)
218
- query 10 times w/o txn 0.057308 0.000013 0.057321 ( 0.057322)
219
- modify 10 attrs w/txn 1.225101 0.013972 1.239073 ( 1.239349)
220
- delete 10 facts w/txn 0.735944 0.001018 0.736962 ( 0.737102)
221
- (and (eq what 'issue-was-closed') (exists... -> 200 2.068974 0.008005 2.076979 ( 2.077134)
222
- (and (eq what 'issue-was-closed') (exists... -> 200/txn 1.094799 0.000000 1.094799 ( 1.094849)
223
- (and (eq what 'issue-was-closed') (exists... -> zero 2.384214 0.001004 2.385218 ( 2.385610)
224
- (and (eq what 'issue-was-closed') (exists... -> zero/txn 1.255267 0.001916 1.257183 ( 1.257310)
225
- (gt time '2024-03-23T03:21:43Z') 0.110972 0.002000 0.112972 ( 0.112986)
226
- (gt cost 50) 0.087402 0.000000 0.087402 ( 0.087411)
227
- (eq title 'Object Thinking 5000') 0.002488 0.000000 0.002488 ( 0.002488)
228
- (and (eq foo 42.998) (or (gt bar 200) (absent zzz))) 0.022121 0.000001 0.022122 ( 0.022123)
229
- (eq id (agg (always) (max id))) 0.237595 0.000000 0.237595 ( 0.237605)
230
- (join "c<=cost,b<=bar" (eq id (agg (always) (max id)))) 0.635953 0.003996 0.639949 ( 0.640016)
231
- delete! 0.060744 0.000997 0.061741 ( 0.061741)
232
- Taped.append() x50000 0.037044 0.002000 0.039044 ( 0.039048)
233
- Taped.each() x125 1.259629 0.002997 1.262626 ( 1.262661)
234
- Taped.delete_if() x375 0.810420 0.000005 0.810425 ( 0.810483)
213
+ insert 20000 facts 0.584619 0.003744 0.588363 ( 0.588372)
214
+ export 20000 facts 0.019872 0.004992 0.024864 ( 0.024870)
215
+ import 411135 bytes (20000 facts) 0.030978 0.004000 0.034978 ( 0.034983)
216
+ insert 10 facts 0.043662 0.002056 0.045718 ( 0.045738)
217
+ query 10 times w/txn 1.809973 0.034886 1.844859 ( 1.845456)
218
+ query 10 times w/o txn 0.039074 0.004004 0.043078 ( 0.043081)
219
+ modify 10 attrs w/txn 1.705921 0.015961 1.721882 ( 1.722316)
220
+ delete 10 facts w/txn 1.021624 0.007014 1.028638 ( 1.028692)
221
+ (and (eq what 'issue-was-closed') (exists... -> 200 2.110981 0.005000 2.115981 ( 2.116099)
222
+ (and (eq what 'issue-was-closed') (exists... -> 200/txn 1.125909 0.000000 1.125909 ( 1.125962)
223
+ (and (eq what 'issue-was-closed') (exists... -> zero 2.417743 0.000993 2.418736 ( 2.418869)
224
+ (and (eq what 'issue-was-closed') (exists... -> zero/txn 1.282409 0.003006 1.285415 ( 1.285498)
225
+ (gt time '2024-03-23T03:21:43Z') 0.092167 0.000000 0.092167 ( 0.092169)
226
+ (gt cost 50) 0.107435 0.000000 0.107435 ( 0.107438)
227
+ (eq title 'Object Thinking 5000') 0.002544 0.000000 0.002544 ( 0.002546)
228
+ (and (eq foo 42.998) (or (gt bar 200) (absent zzz))) 0.022142 0.000000 0.022142 ( 0.022143)
229
+ (eq id (agg (always) (max id))) 0.244818 0.000000 0.244818 ( 0.244835)
230
+ (join "c<=cost,b<=bar" (eq id (agg (always) (max id)))) 0.672133 0.001998 0.674131 ( 0.674186)
231
+ delete! 0.074661 0.000000 0.074661 ( 0.074663)
232
+ Taped.append() x50000 0.037757 0.004997 0.042754 ( 0.042759)
233
+ Taped.each() x125 1.283630 0.001995 1.285625 ( 1.285706)
234
+ Taped.delete_if() x375 0.819901 0.000000 0.819901 ( 0.819968)
235
235
  ```
236
236
 
237
237
  The results were calculated in [this GHA job][benchmark-gha]
238
- on 2025-03-30 at 05:03,
238
+ on 2025-04-07 at 10:33,
239
239
  on Linux with 4 CPUs.
240
240
  <!-- benchmark_end -->
241
241
 
242
- [benchmark-gha]: https://github.com/yegor256/factbase/actions/runs/14152813171
242
+ [benchmark-gha]: https://github.com/yegor256/factbase/actions/runs/14306969571
data/Rakefile CHANGED
@@ -35,7 +35,7 @@ task :picks do
35
35
  next if OS.windows?
36
36
  %w[test lib].each do |d|
37
37
  Dir["#{d}/**/*.rb"].each do |f|
38
- qbash("bundle exec ruby #{Shellwords.escape(f)}", log: $stdout)
38
+ qbash("bundle exec ruby #{Shellwords.escape(f)}", log: $stdout, env: { 'PICKS' => 'yes' })
39
39
  end
40
40
  end
41
41
  end
@@ -46,7 +46,7 @@ class Factbase::Accum
46
46
  vv.uniq!
47
47
  vv.empty? ? nil : vv
48
48
  elsif @props[k].nil?
49
- @fact.method_missing(*args)
49
+ @fact.public_send(*args)
50
50
  else
51
51
  @props[k][0]
52
52
  end
data/lib/factbase/tee.rb CHANGED
@@ -38,7 +38,7 @@ class Factbase::Tee
38
38
  r = [r] unless r.respond_to?(:each) || r.nil?
39
39
  r
40
40
  else
41
- @fact.send(*args)
41
+ @fact.public_send(*args)
42
42
  end
43
43
  end
44
44
  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.9' unless const_defined?(:VERSION)
85
+ VERSION = '0.10.0' 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
@@ -176,7 +176,7 @@ class Factbase
176
176
  end
177
177
  require_relative 'factbase/taped'
178
178
  taped = Factbase::Taped.new(before)
179
- begin
179
+ catch :commit do
180
180
  require_relative 'factbase/light'
181
181
  yield Factbase::Light.new(Factbase.new(taped))
182
182
  rescue Factbase::Rollback
@@ -15,9 +15,9 @@ class TestCachedFactbase < Factbase::Test
15
15
  def test_inserts_and_queries
16
16
  fb = Factbase::CachedFactbase.new(Factbase.new)
17
17
  f = fb.insert
18
- f.foo = 1
18
+ f.foo_bar = 1
19
19
  f.bar = 'test'
20
- assert_equal(1, fb.query('(and (eq foo 1) (eq bar "test"))').each.to_a.size)
20
+ assert_equal(1, fb.query('(and (eq foo_bar 1) (eq bar "test"))').each.to_a.size)
21
21
  end
22
22
 
23
23
  def test_queries_after_update_in_txn
@@ -13,6 +13,12 @@ require_relative '../../../lib/factbase/indexed/indexed_factbase'
13
13
  # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
14
14
  # License:: MIT
15
15
  class TestIndexedQuery < Factbase::Test
16
+ def test_converts_to_string
17
+ fb = Factbase.new
18
+ fb.insert.foo = 42
19
+ refute_nil(Factbase::IndexedQuery.new(fb.query('(exists foo)'), {}, fb).to_s)
20
+ end
21
+
16
22
  def test_queries_and_updates_origin
17
23
  fb = Factbase.new
18
24
  fb.insert.foo = 42
@@ -8,6 +8,10 @@ require_relative '../../lib/factbase'
8
8
  require_relative '../../lib/factbase/accum'
9
9
  require_relative '../../lib/factbase/fact'
10
10
 
11
+ def global_function_for_this_test_only(foo)
12
+ raise foo
13
+ end
14
+
11
15
  # Accum test.
12
16
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
13
17
  # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
@@ -24,6 +28,14 @@ class TestAccum < Factbase::Test
24
28
  assert_equal([42], props['foo'])
25
29
  end
26
30
 
31
+ def test_fetches_without_conflict_with_global_name
32
+ t = Factbase::Accum.new(
33
+ Factbase::Fact.new({ 'global_function_for_this_test_only' => [2] }),
34
+ {}, true
35
+ )
36
+ assert_equal(2, t.global_function_for_this_test_only)
37
+ end
38
+
27
39
  def test_passes_props
28
40
  map = {}
29
41
  f = Factbase::Fact.new(map)
@@ -15,11 +15,11 @@ class TestFact < Factbase::Test
15
15
  def test_injects_data_correctly
16
16
  map = {}
17
17
  f = Factbase::Fact.new(map)
18
- f.foo = 1
18
+ f.foo_bar = 1
19
19
  f.bar = 2
20
20
  f.bar = 3
21
21
  assert_equal(2, map.size)
22
- assert_equal([1], map['foo'])
22
+ assert_equal([1], map['foo_bar'])
23
23
  assert_equal([2, 3], map['bar'])
24
24
  end
25
25
 
@@ -5,9 +5,14 @@
5
5
 
6
6
  require_relative '../test__helper'
7
7
  require_relative '../../lib/factbase'
8
+ require_relative '../../lib/factbase/accum'
8
9
  require_relative '../../lib/factbase/tee'
9
10
  require_relative '../../lib/factbase/fact'
10
11
 
12
+ def global_function_for_test_only(foo)
13
+ raise foo
14
+ end
15
+
11
16
  # Tee test.
12
17
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
13
18
  # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
@@ -30,6 +35,25 @@ class TestTee < Factbase::Test
30
35
  assert_nil(t['$foo'])
31
36
  end
32
37
 
38
+ def test_fetches_simply
39
+ t = Factbase::Accum.new(
40
+ Factbase::Tee.new(
41
+ Factbase::Fact.new({ 'foo_bar' => [987] }),
42
+ Factbase::Fact.new({})
43
+ ),
44
+ {}, true
45
+ )
46
+ assert_equal(987, t.foo_bar)
47
+ end
48
+
49
+ def test_fetches_without_conflict_with_global_name
50
+ t = Factbase::Tee.new(
51
+ Factbase::Fact.new({ 'global_function_for_test_only' => [2] }),
52
+ Factbase::Fact.new({})
53
+ )
54
+ assert_equal(2, t.global_function_for_test_only)
55
+ end
56
+
33
57
  def test_all_properties
34
58
  prim = Factbase::Fact.new({})
35
59
  prim.foo = 42
data/test/test__helper.rb CHANGED
@@ -6,14 +6,27 @@
6
6
  $stdout.sync = true
7
7
 
8
8
  require 'simplecov'
9
- SimpleCov.external_at_exit = true
10
- SimpleCov.start
11
-
12
9
  require 'simplecov-cobertura'
13
- SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter
10
+ unless SimpleCov.running || ENV['PICKS']
11
+ SimpleCov.command_name('test')
12
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
13
+ [
14
+ SimpleCov::Formatter::HTMLFormatter,
15
+ SimpleCov::Formatter::CoberturaFormatter
16
+ ]
17
+ )
18
+ SimpleCov.minimum_coverage 95
19
+ SimpleCov.minimum_coverage_by_file 90
20
+ SimpleCov.start do
21
+ add_filter 'test/'
22
+ add_filter 'vendor/'
23
+ add_filter 'target/'
24
+ track_files 'lib/**/*.rb'
25
+ track_files '*.rb'
26
+ end
27
+ end
14
28
 
15
29
  require 'minitest/autorun'
16
-
17
30
  require 'minitest/reporters'
18
31
  Minitest::Reporters.use! [Minitest::Reporters::SpecReporter.new]
19
32
 
@@ -134,7 +134,7 @@ class TestFactbase < Factbase::Test
134
134
  assert_raises(StandardError) do
135
135
  fb.txn do |fbt|
136
136
  fbt.insert.foo = 42
137
- throw 'intentionally'
137
+ raise 'intentionally'
138
138
  end
139
139
  end.message, 'intentionally'
140
140
  )
@@ -193,7 +193,7 @@ class TestFactbase < Factbase::Test
193
193
  assert_raises(StandardError) do
194
194
  d.txn do |fbt|
195
195
  fbt.insert
196
- throw 'oops'
196
+ raise 'oops'
197
197
  end
198
198
  end
199
199
  d.import(d.export)
@@ -476,4 +476,13 @@ class TestFactbase < Factbase::Test
476
476
  assert_equal(100, factbase.query('(eq foo 42)').each.to_a.size)
477
477
  end
478
478
  end
479
+
480
+ def test_commits_on_exit_by_throw
481
+ fb = Factbase.new
482
+ fb.txn do |fbt|
483
+ fbt.insert.foo = 1
484
+ throw :commit
485
+ end
486
+ assert_equal(1, fb.size)
487
+ end
479
488
  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.9
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-03-30 00:00:00.000000000 Z
10
+ date: 2025-04-15 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: backtrace
@@ -163,7 +163,6 @@ files:
163
163
  - ".pdd"
164
164
  - ".rubocop.yml"
165
165
  - ".rultor.yml"
166
- - ".simplecov"
167
166
  - Gemfile
168
167
  - Gemfile.lock
169
168
  - LICENSE.txt
data/.simplecov DELETED
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- #
4
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
5
- # SPDX-License-Identifier: MIT
6
-
7
- if Gem.win_platform?
8
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
9
- SimpleCov::Formatter::HTMLFormatter
10
- ]
11
- SimpleCov.start do
12
- add_filter '/test/'
13
- add_filter '/features/'
14
- end
15
- else
16
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
17
- [SimpleCov::Formatter::HTMLFormatter]
18
- )
19
- SimpleCov.start do
20
- add_filter '/test/'
21
- add_filter '/features/'
22
- minimum_coverage 20
23
- end
24
- end