dbmlite3 1.0.a1
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 +7 -0
- data/.yardopts +3 -0
- data/DBMLite3.gemspec +39 -0
- data/LICENSE.txt +21 -0
- data/README.md +137 -0
- data/Rakefile +29 -0
- data/doc/Lite3/DBM.html +2588 -0
- data/doc/Lite3/Error.html +135 -0
- data/doc/Lite3/SQL.html +390 -0
- data/doc/Lite3.html +117 -0
- data/doc/_index.html +152 -0
- data/doc/class_list.html +51 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +58 -0
- data/doc/css/style.css +496 -0
- data/doc/file.README.html +203 -0
- data/doc/file_list.html +56 -0
- data/doc/frames.html +17 -0
- data/doc/index.html +203 -0
- data/doc/js/app.js +314 -0
- data/doc/js/full_list.js +216 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +307 -0
- data/doc/top-level-namespace.html +110 -0
- data/lib/dbmlite3.rb +909 -0
- data/spec/dbmlite3_spec.rb +960 -0
- data/spec/spec_helper.rb +3 -0
- metadata +131 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 546ca0010f91757ca1346cd87ca9f2846318e65123668363239b61e8f1f5bbdd
|
4
|
+
data.tar.gz: 5500f44eec01f68da64ed8e8d8ec73a1325ffafeab274a2ae00604a68e16ae61
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 45e67ef18cff8f3f17610e888a7153bb83d83438334c8ce0d204fdda7c599926e5ec210e09cb67bf909dbfa829fb17046b46a540e5373960b049bccb77526cf1
|
7
|
+
data.tar.gz: 7c113a41818d9bdea1aec2b8e3d5fe1f54c4c134e8fa777a6e19a6c0f8546c326f6ef901caddc4b65985df1b50a89d809db6b32196eb157034e619fd9cebade5
|
data/.yardopts
ADDED
data/DBMLite3.gemspec
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
|
2
|
+
# Skeleton gemspec
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'dbmlite3'
|
6
|
+
s.version = '1.0.a1'
|
7
|
+
s.date = '2022-02-21'
|
8
|
+
s.summary = "A DBM-style key-value store using SQLite3"
|
9
|
+
s.description = <<-EOF
|
10
|
+
Lite3::DBM is an object that behaves like a Ruby Hash but stores
|
11
|
+
its data in a SQLite3 database table. It is a drop-in replacement
|
12
|
+
for DBM.
|
13
|
+
|
14
|
+
Values are optionally serialized with YAML or Marshal, allowing
|
15
|
+
(almost) any Ruby type to be stored. In addition, there is
|
16
|
+
rudimentary support for transactions with emphasis on simplicity
|
17
|
+
and safety.
|
18
|
+
EOF
|
19
|
+
s.authors = ["Chris Reuter"]
|
20
|
+
s.email = 'chris@isplitonyourgrave.com'
|
21
|
+
|
22
|
+
# I'm just going to add everything so that if you've got the gem,
|
23
|
+
# you've also got the source distribution. Yay! Open source!
|
24
|
+
s.files = ["README.md", "LICENSE.txt", "DBMLite3.gemspec",
|
25
|
+
"Rakefile", ".yardopts"] +
|
26
|
+
Dir.glob('doc/**/*') +
|
27
|
+
Dir.glob('{spec,lib}/*.rb')
|
28
|
+
|
29
|
+
s.required_ruby_version = '>= 2.7.0'
|
30
|
+
s.requirements << "sqlite3, the usual devtools"
|
31
|
+
|
32
|
+
s.add_runtime_dependency "sqlite3", '~> 1.4'
|
33
|
+
|
34
|
+
s.add_development_dependency "rspec", '~> 3.10', '>= 3.10.0'
|
35
|
+
s.add_development_dependency "yard", '~> 0.9.25', '>= 0.9.25'
|
36
|
+
|
37
|
+
s.homepage = 'https://codeberg.org/suetanvil/dbmlite3-ruby'
|
38
|
+
s.license = 'MIT'
|
39
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2022 Chris Reuter
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
# Simple DBM-style key-value database using SQLite3
|
2
|
+
|
3
|
+
## Description
|
4
|
+
|
5
|
+
`dbmlite3` is a simple key-value store built on top of SQLite3 that
|
6
|
+
provides a Hash-like interface. It is a drop-in replacement for `DBM`
|
7
|
+
or `YAML::DBM` that uses SQLite3 to do the underlying storage.
|
8
|
+
|
9
|
+
## Why?
|
10
|
+
|
11
|
+
Because DBM is really simple and SQLite3 is solid, reliable,
|
12
|
+
ubiquitous, and file-format-compatible across all platforms. This gem
|
13
|
+
gives you the best of both worlds.
|
14
|
+
|
15
|
+
|
16
|
+
## Synopsis
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
require 'dbmlite3'
|
20
|
+
|
21
|
+
# Open a table in a database
|
22
|
+
settings = Lite3::DBM.new("config.sqlite3", "settings")
|
23
|
+
|
24
|
+
# You use it like a hash
|
25
|
+
settings["speed"] = 88
|
26
|
+
settings["date"] = Date.new(1955, 11, 5) # Normal Ruby values are allowed
|
27
|
+
settings["power_threshold"] = 2.2
|
28
|
+
|
29
|
+
puts settings['power_threshold']
|
30
|
+
|
31
|
+
settings.each{|k,v| puts "setting: #{k} = #{v}" }
|
32
|
+
|
33
|
+
# But you also have transactions
|
34
|
+
settings.transaction{
|
35
|
+
settings["speed"] = settings["speed"] * 2
|
36
|
+
}
|
37
|
+
|
38
|
+
# You can open other tables in the same database if you want, as above
|
39
|
+
# or with a block
|
40
|
+
Lite3::DBM.open("config.sqlite3", "stats") { |stats|
|
41
|
+
stats["max"] = 42
|
42
|
+
|
43
|
+
# You can even open multiple handles to the same table if you need to
|
44
|
+
Lite3::DBM.open("config.sqlite3", "stats") { |stats2|
|
45
|
+
stats2["max"] += 1
|
46
|
+
}
|
47
|
+
|
48
|
+
puts "stats=#{stats["max"]}"
|
49
|
+
}
|
50
|
+
|
51
|
+
settings.close
|
52
|
+
```
|
53
|
+
|
54
|
+
Complete documentation is available in the accompanying rdoc.
|
55
|
+
|
56
|
+
## Installation
|
57
|
+
|
58
|
+
`dbmlite3` is available as a gem:
|
59
|
+
|
60
|
+
$ [sudo] gem install dbmlite3
|
61
|
+
|
62
|
+
Alternately, you can fetch the source code from GitLab and build it yourself:
|
63
|
+
|
64
|
+
$ git clone https://gitlab.com/suetanvil/dbmlite3
|
65
|
+
$ cd dbmlite3
|
66
|
+
$ rake
|
67
|
+
|
68
|
+
Obviously, it depends on the gem `sqlite3`.
|
69
|
+
|
70
|
+
## Quirks and Hints
|
71
|
+
|
72
|
+
### Remember that a `DBM` is a (potentially) shared file
|
73
|
+
|
74
|
+
It is important to keep in mind that while `Lite3::DBM` objects
|
75
|
+
look like Hashes, they are accessing files on disk that other
|
76
|
+
processes could modify at any time.
|
77
|
+
|
78
|
+
For example, an innocuous-looking expression like
|
79
|
+
|
80
|
+
db['foo'] = db['foo'] + 1
|
81
|
+
|
82
|
+
or its shorter equivalent
|
83
|
+
|
84
|
+
db['foo'] += 1
|
85
|
+
|
86
|
+
contains a race condition. If (e.g.) two copies of this script are
|
87
|
+
running at the same time, it is possible for both to perform the read
|
88
|
+
before one of them writes, losing the others' result.
|
89
|
+
|
90
|
+
There are two ways to deal with this. You can wrap the
|
91
|
+
read-modify-write cycle in a transaction:
|
92
|
+
|
93
|
+
db.transaction { db['foo'] += 1 }
|
94
|
+
|
95
|
+
Or, of course, you could just design your script or program so that
|
96
|
+
only one program accesses the table at a time.
|
97
|
+
|
98
|
+
|
99
|
+
### Transactions and performance
|
100
|
+
|
101
|
+
If you need to do a large number of accesses in a short amount of
|
102
|
+
time (e.g. loading data from a file), it is significantly faster to
|
103
|
+
do these in batches in one or more transactions.
|
104
|
+
|
105
|
+
### Forking safely
|
106
|
+
|
107
|
+
It is a documented limitation of SQLite3 that database objects
|
108
|
+
cannot be carried across a process fork. Either the parent or the
|
109
|
+
child process will keep the open handle and the other one must
|
110
|
+
forget it completely.
|
111
|
+
|
112
|
+
For this reason, if you need both the parent and child process to
|
113
|
+
be able to use `Lite3::DBM` after a `fork`, you must first call
|
114
|
+
`Lite3::SQL.close_all`. Not only will this make it safe but it
|
115
|
+
also lets the child and parent use the same `Lite3::DBM` objects.
|
116
|
+
|
117
|
+
### `Lite3::DBM` objects act like file handles but are not
|
118
|
+
|
119
|
+
While it is generally safe to treat `Lite3::DBM` as a wrapper
|
120
|
+
around file handle (i.e. `open` and `close` work as expected), you
|
121
|
+
should be aware that this is not precisely the way things
|
122
|
+
actually work. Instead, the gem maintains a pool of database
|
123
|
+
handles, one per file, and associates them with `Lite3::DBM`
|
124
|
+
instances as needed. This is necessary for transactions to work
|
125
|
+
correctly.
|
126
|
+
|
127
|
+
See the reference doc for `Lite3::SQL` for more details.
|
128
|
+
|
129
|
+
Mostly, you don't need to worry about this but certain types of
|
130
|
+
bugs could behave in unexpected ways and knowing this may help you
|
131
|
+
make sense of them.
|
132
|
+
|
133
|
+
|
134
|
+
|
135
|
+
|
136
|
+
|
137
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'yard'
|
4
|
+
|
5
|
+
RSpec::Core::RakeTask.new(:test) do |t|
|
6
|
+
t.pattern = Dir.glob('spec/*_spec.rb')
|
7
|
+
end
|
8
|
+
|
9
|
+
YARD::Rake::YardocTask.new(:docs_via_yard) do |t|
|
10
|
+
t.files = ['lib/*.rb']
|
11
|
+
end
|
12
|
+
|
13
|
+
task :gem do
|
14
|
+
`gem build dbmlite3`
|
15
|
+
end
|
16
|
+
|
17
|
+
task :clean do
|
18
|
+
gems = Dir.glob("dbmlite3-*.gem")
|
19
|
+
rm gems if gems.size > 0
|
20
|
+
rm_rf "doc"
|
21
|
+
end
|
22
|
+
|
23
|
+
task :clobber => [:clean] do
|
24
|
+
rm_rf ".yardoc"
|
25
|
+
end
|
26
|
+
|
27
|
+
task :doc => :docs_via_yard
|
28
|
+
|
29
|
+
task :default => [:doc, :test, :gem]
|