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 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
@@ -0,0 +1,3 @@
1
+ --markup markdown
2
+ --readme README.md
3
+ lib/*.rb
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]