dbmlite3 1.0.a3 → 1.0.a6

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: 17eae0eb8bfbfa0da5aee38d17a957d9555faaa07de11b7959853cc51a92e55a
4
- data.tar.gz: 7122901693d010af7fd6bfa78f473345c7fe7a74ec09c036959bc3f24fb31b8a
3
+ metadata.gz: d12b628f0823e2d5fd82cc4c42de1065bff042fda9939307e407e2cf68145b27
4
+ data.tar.gz: 33e48ca6b0d79e1ba34094c75ae4dfb372fe6b04c8d8222ee19d74f63e4032d9
5
5
  SHA512:
6
- metadata.gz: a83e7f6f4540d45171e2e2e21d034e2a98aa2040d4e7baecafc819f829f20984cca123a890111c190db4bcebfd4421d97401b0b0776034322a22faef7507e6e1
7
- data.tar.gz: c3a98e630431c99018b01f68e597cb2beea6ea92a6089af7f29c237f604f1eef4c599696e7ce30153ddd243fe381b92f5b58d78d579ab6b576bbee448a5e81e0
6
+ metadata.gz: cd7627ee298e9d15bcf01ac49cb386c46a3b7dead470e51719a10aab739b56727dba49c041410bac01add87abf57f9df4468373b4ebeb560bdd5b6b2f092ff17
7
+ data.tar.gz: 9e94a03983764ae51034d9092ca2a3ea285f3d8a28fc0e999c59edfa901da77aabdba169601fc8001841c632d95b2fd6ff726bee75159c4c1844c6c22dee1c35
data/README.md CHANGED
@@ -102,6 +102,15 @@ If you need to do a large number of accesses in a short amount of
102
102
  time (e.g. loading data from a file), it is significantly faster to
103
103
  do these in batches in one or more transactions.
104
104
 
105
+ ### Serialization Safety
106
+
107
+ `Lite3::DBM` stores Ruby data by first serializing values using the
108
+ `Marshal` or `Psych` modules. This can pose a security risk if an
109
+ untrusted third party has direct access to the underlying SQLite3
110
+ database. This tends to be pretty rare for most use-cases but if it
111
+ is a concern, you can always configure `Lite3::DBM` to store its
112
+ values as plain strings.
113
+
105
114
  ### Forking safely
106
115
 
107
116
  It is a documented limitation of SQLite3 that database objects
@@ -3,7 +3,7 @@
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = 'dbmlite3'
6
- s.version = '1.0.a3'
6
+ s.version = '1.0.a6'
7
7
  s.date = '2022-02-21'
8
8
  s.summary = "A DBM-style key-value store using SQLite3"
9
9
  s.description = <<-EOF
@@ -21,12 +21,12 @@ EOF
21
21
 
22
22
  # I'm just going to add everything so that if you've got the gem,
23
23
  # you've also got the source distribution. Yay! Open source!
24
- s.files = ["README.md", "LICENSE.txt", "DBMLite3.gemspec",
24
+ s.files = ["README.md", "LICENSE.txt", "dbmlite3.gemspec",
25
25
  "Rakefile", ".yardopts"] +
26
26
  Dir.glob('doc/**/*') +
27
27
  Dir.glob('{spec,lib}/*.rb')
28
28
 
29
- s.required_ruby_version = '>= 2.7.0'
29
+ s.required_ruby_version = '>= 2.2.0'
30
30
  s.requirements << "sqlite3, the usual devtools"
31
31
 
32
32
  s.add_runtime_dependency "sqlite3", '~> 1.4'
data/doc/Lite3/DBM.html CHANGED
@@ -144,9 +144,15 @@ string. you will need to do this instead:</p>
144
144
  <p>Unlike DBM, values may (optionally) be any serializable Ruby type.</p>
145
145
 
146
146
  <p>You can select the serialization method with an optional third
147
- constructor argument. Options are <code>YAML</code> (the default), <code>Marshal</code>
148
- or simple string conversion with <code>to_s</code>. Each of these methods will
149
- have their own pros and cons.</p>
147
+ constructor argument. Options are YAML (the default), <code>Marshal</code>
148
+ or simple string conversion with <code>to_s</code>. Each of these methods
149
+ will have their own pros and cons.</p>
150
+
151
+ <p><strong>WARNING:</strong> Both YAML and Marshal serialization have the usual
152
+ security caveats as described in the documentation for <code>Marshal</code>
153
+ and <code>Psych</code>. If you are going to let an untrusted entity modify
154
+ the database, you should not use these methods and instead stick
155
+ to string conversion.</p>
150
156
 
151
157
  <p>The table name must be a valid name identifier (i.e. matches
152
158
  /^[a-zA-Z_]\w*$/).</p>
@@ -912,16 +918,17 @@ serialization method for converting Ruby values into storable
912
918
  strings. There are three options:</p>
913
919
 
914
920
  <ul>
915
- <li><code>:yaml</code> uses the <code>YAML</code> module.</li>
921
+ <li><code>:yaml</code> uses the <code>Psych</code> module.</li>
916
922
  <li><code>:marshal</code> uses the <code>Marshal</code> module.</li>
917
923
  <li><code>:string</code> simply uses the default <code>to_s</code> method, just like the
918
924
  stock <code>DBM</code>.</li>
919
925
  </ul>
920
926
 
921
927
  <p>Each of these will have their pros and cons. The default is
922
- <code>:yaml</code> because that is the most portable across Ruby versions.
923
- <code>:marshal</code> tends to be faster but is not stable across Ruby
924
- versions. Note that <code>DBM</code> does not check your Marshal version.</p>
928
+ <code>:yaml</code> because that is the most portable. <code>:marshal</code> tends to
929
+ be faster but is incompatible across minor Ruby versions.</p>
930
+
931
+ <p>(Note that <code>DBM</code> does not check your Marshal version.)</p>
925
932
 
926
933
  <p>Your serializer choice is registered in a metadata table when
927
934
  <code>tablename</code> is created in the SQLite3 file. Afterward, it is an
@@ -940,13 +947,6 @@ and will result in a Lite3::Error exception.</p>
940
947
  <pre class="lines">
941
948
 
942
949
 
943
- 409
944
- 410
945
- 411
946
- 412
947
- 413
948
- 414
949
- 415
950
950
  416
951
951
  417
952
952
  418
@@ -960,10 +960,17 @@ and will result in a Lite3::Error exception.</p>
960
960
  426
961
961
  427
962
962
  428
963
- 429</pre>
963
+ 429
964
+ 430
965
+ 431
966
+ 432
967
+ 433
968
+ 434
969
+ 435
970
+ 436</pre>
964
971
  </td>
965
972
  <td>
966
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 409</span>
973
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 416</span>
967
974
 
968
975
  <span class='kw'>def</span> <span class='id identifier rubyid_initialize'>initialize</span><span class='lparen'>(</span><span class='id identifier rubyid_filename'>filename</span><span class='comma'>,</span> <span class='id identifier rubyid_tablename'>tablename</span><span class='comma'>,</span> <span class='id identifier rubyid_serializer'>serializer</span> <span class='op'>=</span> <span class='symbol'>:yaml</span><span class='rparen'>)</span>
969
976
  <span class='ivar'>@filename</span> <span class='op'>=</span> <span class='id identifier rubyid_filename'>filename</span>
@@ -1025,19 +1032,19 @@ This is analagous to <code>File.open</code>.</p>
1025
1032
  <pre class="lines">
1026
1033
 
1027
1034
 
1028
- 435
1029
- 436
1030
- 437
1031
- 438
1032
- 439
1033
- 440
1034
- 441
1035
1035
  442
1036
1036
  443
1037
- 444</pre>
1037
+ 444
1038
+ 445
1039
+ 446
1040
+ 447
1041
+ 448
1042
+ 449
1043
+ 450
1044
+ 451</pre>
1038
1045
  </td>
1039
1046
  <td>
1040
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 435</span>
1047
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 442</span>
1041
1048
 
1042
1049
  <span class='kw'>def</span> <span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_open'>open</span><span class='lparen'>(</span><span class='id identifier rubyid_filename'>filename</span><span class='comma'>,</span> <span class='id identifier rubyid_tablename'>tablename</span><span class='comma'>,</span> <span class='id identifier rubyid_serializer'>serializer</span> <span class='op'>=</span> <span class='symbol'>:yaml</span><span class='comma'>,</span> <span class='op'>&amp;</span><span class='id identifier rubyid_block'>block</span><span class='rparen'>)</span>
1043
1050
  <span class='id identifier rubyid_instance'>instance</span> <span class='op'>=</span> <span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span><span class='lparen'>(</span><span class='id identifier rubyid_filename'>filename</span><span class='comma'>,</span> <span class='id identifier rubyid_tablename'>tablename</span><span class='comma'>,</span> <span class='id identifier rubyid_serializer'>serializer</span><span class='rparen'>)</span>
@@ -1086,12 +1093,12 @@ nil if it is not present.</p>
1086
1093
  <pre class="lines">
1087
1094
 
1088
1095
 
1089
- 615
1090
- 616
1091
- 617</pre>
1096
+ 662
1097
+ 663
1098
+ 664</pre>
1092
1099
  </td>
1093
1100
  <td>
1094
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 615</span>
1101
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 662</span>
1095
1102
 
1096
1103
  <span class='kw'>def</span> <span class='op'>[]</span><span class='lparen'>(</span><span class='id identifier rubyid_key'>key</span><span class='rparen'>)</span>
1097
1104
  <span class='kw'>return</span> <span class='id identifier rubyid_fetch'>fetch</span><span class='lparen'>(</span><span class='id identifier rubyid_key'>key</span><span class='comma'>,</span> <span class='kw'>nil</span><span class='rparen'>)</span>
@@ -1135,34 +1142,92 @@ serialization method you have chosen.</p>
1135
1142
  <pre class="lines">
1136
1143
 
1137
1144
 
1138
- 597
1139
- 598
1140
- 599
1141
- 600
1142
- 601
1143
- 602
1144
- 603
1145
- 604
1146
- 605
1147
- 606
1148
- 607
1149
- 608
1150
- 609
1151
- 610</pre>
1145
+ 615
1146
+ 616
1147
+ 617
1148
+ 618
1149
+ 619
1150
+ 620
1151
+ 621
1152
+ 622
1153
+ 623
1154
+ 624
1155
+ 625
1156
+ 626
1157
+ 627
1158
+ 628
1159
+ 629
1160
+ 630
1161
+ 631
1162
+ 632
1163
+ 633
1164
+ 634
1165
+ 635
1166
+ 636
1167
+ 637
1168
+ 638
1169
+ 639
1170
+ 640
1171
+ 641
1172
+ 642
1173
+ 643
1174
+ 644
1175
+ 645
1176
+ 646
1177
+ 647
1178
+ 648
1179
+ 649
1180
+ 650
1181
+ 651
1182
+ 652
1183
+ 653
1184
+ 654
1185
+ 655
1186
+ 656
1187
+ 657</pre>
1152
1188
  </td>
1153
1189
  <td>
1154
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 597</span>
1190
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 615</span>
1155
1191
 
1156
1192
  <span class='kw'>def</span> <span class='op'>[]=</span><span class='lparen'>(</span><span class='id identifier rubyid_key'>key</span><span class='comma'>,</span> <span class='id identifier rubyid_value'>value</span><span class='rparen'>)</span>
1157
1193
  <span class='id identifier rubyid_key'>key</span> <span class='op'>=</span> <span class='id identifier rubyid_check_key'>check_key</span><span class='lparen'>(</span><span class='id identifier rubyid_key'>key</span><span class='rparen'>)</span>
1158
1194
  <span class='id identifier rubyid_valstr'>valstr</span> <span class='op'>=</span> <span class='const'>SQLite3</span><span class='op'>::</span><span class='const'>Blob</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span><span class='lparen'>(</span> <span class='ivar'>@valenc</span><span class='period'>.</span><span class='id identifier rubyid_call'>call</span><span class='lparen'>(</span><span class='id identifier rubyid_value'>value</span><span class='rparen'>)</span> <span class='rparen'>)</span>
1159
1195
 
1160
- <span class='id identifier rubyid_insert'>insert</span> <span class='op'>=</span> <span class='heredoc_beg'>&lt;&lt;~SQL</span>
1161
- <span class='tstring_content'> insert into </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_actual_tbl'>actual_tbl</span><span class='embexpr_end'>}</span><span class='tstring_content'> (key, value) values (?,?)
1162
- </span><span class='tstring_content'> on conflict(key) do update set value = ?;
1163
- </span><span class='heredoc_end'> SQL
1196
+ <span class='comment'># At one point, this operation was done with SQLite3&#39;s UPSERT:
1197
+ </span> <span class='comment'>#
1198
+ </span> <span class='comment'># insert into #{actual_tbl} (key, value) values (?,?)
1199
+ </span> <span class='comment'># on conflict(key) do update set value = ?;
1200
+ </span> <span class='comment'>#
1201
+ </span> <span class='comment'># Unfortunately, this capability was only added to SQLite3 in
1202
+ </span> <span class='comment'># 2018, which means that at the time of this writing (2022)
1203
+ </span> <span class='comment'># there are still a lot of systems out there that have older
1204
+ </span> <span class='comment'># versions of SQLite3 and so can&#39;t do this.
1205
+ </span> <span class='comment'>#
1206
+ </span> <span class='comment'># The venerable `insert or replace` feature **almost** does what
1207
+ </span> <span class='comment'># I want:
1208
+ </span> <span class='comment'>#
1209
+ </span> <span class='comment'># insert or replace into #{actual_tbl} (key, value) values (?, ?);
1210
+ </span> <span class='comment'>#
1211
+ </span> <span class='comment'># The one problem is that it changes the order of the rows,
1212
+ </span> <span class='comment'># which we need to preserve in order to remain consistent with
1213
+ </span> <span class='comment'># `Hash` semantics (and because it&#39;s useful).
1214
+ </span> <span class='comment'>#
1215
+ </span> <span class='comment'># So we kick it old school and do a `select` followed by an
1216
+ </span> <span class='comment'># `insert` or `update` wrapped in a transaction.
1164
1217
  </span> <span class='id identifier rubyid_transaction'>transaction</span> <span class='lbrace'>{</span>
1165
- <span class='ivar'>@handle</span><span class='period'>.</span><span class='id identifier rubyid_sql'>sql</span><span class='lparen'>(</span><span class='id identifier rubyid_insert'>insert</span><span class='comma'>,</span> <span class='lbracket'>[</span><span class='id identifier rubyid_key'>key</span><span class='comma'>,</span> <span class='id identifier rubyid_valstr'>valstr</span><span class='comma'>,</span> <span class='id identifier rubyid_valstr'>valstr</span><span class='rbracket'>]</span><span class='rparen'>)</span>
1218
+ <span class='id identifier rubyid_rowid'>rowid</span> <span class='op'>=</span> <span class='kw'>nil</span>
1219
+ <span class='id identifier rubyid_select'>select</span> <span class='op'>=</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>select rowid, key, value from </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_actual_tbl'>actual_tbl</span><span class='embexpr_end'>}</span><span class='tstring_content'> where key = ?;</span><span class='tstring_end'>&quot;</span></span>
1220
+ <span class='ivar'>@handle</span><span class='period'>.</span><span class='id identifier rubyid_sql'>sql</span><span class='lparen'>(</span><span class='id identifier rubyid_select'>select</span><span class='comma'>,</span> <span class='lbracket'>[</span><span class='id identifier rubyid_key'>key</span><span class='rbracket'>]</span><span class='rparen'>)</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_row'>row</span><span class='op'>|</span>
1221
+ <span class='id identifier rubyid_rowid'>rowid</span> <span class='op'>=</span> <span class='id identifier rubyid_row'>row</span><span class='lbracket'>[</span><span class='int'>0</span><span class='rbracket'>]</span>
1222
+ <span class='rbrace'>}</span>
1223
+
1224
+ <span class='kw'>if</span> <span class='id identifier rubyid_rowid'>rowid</span>
1225
+ <span class='id identifier rubyid_update'>update</span> <span class='op'>=</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>update </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_actual_tbl'>actual_tbl</span><span class='embexpr_end'>}</span><span class='tstring_content'> set value = ? where rowid = ?;</span><span class='tstring_end'>&quot;</span></span>
1226
+ <span class='ivar'>@handle</span><span class='period'>.</span><span class='id identifier rubyid_sql'>sql</span><span class='lparen'>(</span><span class='id identifier rubyid_update'>update</span><span class='comma'>,</span> <span class='lbracket'>[</span><span class='id identifier rubyid_valstr'>valstr</span><span class='comma'>,</span> <span class='id identifier rubyid_rowid'>rowid</span><span class='rbracket'>]</span><span class='rparen'>)</span>
1227
+ <span class='kw'>else</span>
1228
+ <span class='id identifier rubyid_insert'>insert</span> <span class='op'>=</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>insert into </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_actual_tbl'>actual_tbl</span><span class='embexpr_end'>}</span><span class='tstring_content'> (key, value) values (?,?);</span><span class='tstring_end'>&quot;</span></span>
1229
+ <span class='ivar'>@handle</span><span class='period'>.</span><span class='id identifier rubyid_sql'>sql</span><span class='lparen'>(</span><span class='id identifier rubyid_insert'>insert</span><span class='comma'>,</span> <span class='lbracket'>[</span><span class='id identifier rubyid_key'>key</span><span class='comma'>,</span> <span class='id identifier rubyid_valstr'>valstr</span><span class='rbracket'>]</span><span class='rparen'>)</span>
1230
+ <span class='kw'>end</span>
1166
1231
  <span class='rbrace'>}</span>
1167
1232
 
1168
1233
  <span class='kw'>return</span> <span class='id identifier rubyid_value'>value</span>
@@ -1197,12 +1262,12 @@ serialization method you have chosen.</p>
1197
1262
  <pre class="lines">
1198
1263
 
1199
1264
 
1200
- 699
1201
- 700
1202
- 701</pre>
1265
+ 746
1266
+ 747
1267
+ 748</pre>
1203
1268
  </td>
1204
1269
  <td>
1205
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 699</span>
1270
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 746</span>
1206
1271
 
1207
1272
  <span class='kw'>def</span> <span class='id identifier rubyid_clear'>clear</span>
1208
1273
  <span class='id identifier rubyid_transaction'>transaction</span> <span class='lbrace'>{</span> <span class='ivar'>@handle</span><span class='period'>.</span><span class='id identifier rubyid_sql'>sql</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>delete from </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_actual_tbl'>actual_tbl</span><span class='embexpr_end'>}</span><span class='tstring_content'>;</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span> <span class='lbracket'>[</span><span class='rbracket'>]</span><span class='rparen'>)</span> <span class='rbrace'>}</span>
@@ -1242,13 +1307,13 @@ no other <code>DBM</code> objects using that file.</p>
1242
1307
  <pre class="lines">
1243
1308
 
1244
1309
 
1245
- 532
1246
- 533
1247
- 534
1248
- 535</pre>
1310
+ 550
1311
+ 551
1312
+ 552
1313
+ 553</pre>
1249
1314
  </td>
1250
1315
  <td>
1251
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 532</span>
1316
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 550</span>
1252
1317
 
1253
1318
  <span class='kw'>def</span> <span class='id identifier rubyid_close'>close</span>
1254
1319
  <span class='ivar'>@handle</span><span class='period'>.</span><span class='id identifier rubyid_delref'>delref</span><span class='lparen'>(</span><span class='kw'>self</span><span class='rparen'>)</span>
@@ -1298,12 +1363,12 @@ closed <code>DBM</code>.</p>
1298
1363
  <pre class="lines">
1299
1364
 
1300
1365
 
1301
- 539
1302
- 540
1303
- 541</pre>
1366
+ 557
1367
+ 558
1368
+ 559</pre>
1304
1369
  </td>
1305
1370
  <td>
1306
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 539</span>
1371
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 557</span>
1307
1372
 
1308
1373
  <span class='kw'>def</span> <span class='id identifier rubyid_closed?'>closed?</span><span class='lparen'>(</span><span class='rparen'>)</span>
1309
1374
  <span class='kw'>return</span> <span class='ivar'>@handle</span><span class='period'>.</span><span class='id identifier rubyid_is_a?'>is_a?</span> <span class='const'>ClosedHandle</span>
@@ -1339,14 +1404,14 @@ not present, does nothing.</p>
1339
1404
  <pre class="lines">
1340
1405
 
1341
1406
 
1342
- 788
1343
- 789
1344
- 790
1345
- 791
1346
- 792</pre>
1407
+ 835
1408
+ 836
1409
+ 837
1410
+ 838
1411
+ 839</pre>
1347
1412
  </td>
1348
1413
  <td>
1349
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 788</span>
1414
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 835</span>
1350
1415
 
1351
1416
  <span class='kw'>def</span> <span class='id identifier rubyid_delete'>delete</span><span class='lparen'>(</span><span class='id identifier rubyid_key'>key</span><span class='rparen'>)</span>
1352
1417
  <span class='id identifier rubyid_transaction'>transaction</span> <span class='lbrace'>{</span>
@@ -1405,14 +1470,14 @@ each entry for which the block returns true.</p>
1405
1470
  <pre class="lines">
1406
1471
 
1407
1472
 
1408
- 798
1409
- 799
1410
- 800
1411
- 801
1412
- 802</pre>
1473
+ 845
1474
+ 846
1475
+ 847
1476
+ 848
1477
+ 849</pre>
1413
1478
  </td>
1414
1479
  <td>
1415
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 798</span>
1480
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 845</span>
1416
1481
 
1417
1482
  <span class='kw'>def</span> <span class='id identifier rubyid_delete_if'>delete_if</span><span class='lparen'>(</span><span class='op'>&amp;</span><span class='id identifier rubyid_block'>block</span><span class='rparen'>)</span>
1418
1483
  <span class='id identifier rubyid_transaction'>transaction</span> <span class='lbrace'>{</span>
@@ -1477,14 +1542,14 @@ own transaction.</p>
1477
1542
  <pre class="lines">
1478
1543
 
1479
1544
 
1480
- 713
1481
- 714
1482
- 715
1483
- 716
1484
- 717</pre>
1545
+ 760
1546
+ 761
1547
+ 762
1548
+ 763
1549
+ 764</pre>
1485
1550
  </td>
1486
1551
  <td>
1487
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 713</span>
1552
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 760</span>
1488
1553
 
1489
1554
  <span class='kw'>def</span> <span class='id identifier rubyid_each'>each</span><span class='lparen'>(</span><span class='op'>&amp;</span><span class='id identifier rubyid_block'>block</span><span class='rparen'>)</span>
1490
1555
  <span class='kw'>return</span> <span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_to_enum'>to_enum</span><span class='lparen'>(</span><span class='symbol'>:nt_each</span><span class='rparen'>)</span> <span class='kw'>unless</span> <span class='id identifier rubyid_block'>block</span>
@@ -1539,13 +1604,13 @@ own transaction.</p>
1539
1604
  <pre class="lines">
1540
1605
 
1541
1606
 
1542
- 763
1543
- 764
1544
- 765
1545
- 766</pre>
1607
+ 810
1608
+ 811
1609
+ 812
1610
+ 813</pre>
1546
1611
  </td>
1547
1612
  <td>
1548
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 763</span>
1613
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 810</span>
1549
1614
 
1550
1615
  <span class='kw'>def</span> <span class='id identifier rubyid_each_key'>each_key</span><span class='lparen'>(</span><span class='op'>&amp;</span><span class='id identifier rubyid_block'>block</span><span class='rparen'>)</span>
1551
1616
  <span class='kw'>return</span> <span class='const'>Enumerator</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span><span class='lbrace'>{</span><span class='op'>|</span><span class='id identifier rubyid_y'>y</span><span class='op'>|</span> <span class='id identifier rubyid_nt_each'>nt_each</span><span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_k'>k</span><span class='comma'>,</span><span class='id identifier rubyid_v'>v</span><span class='op'>|</span> <span class='id identifier rubyid_y'>y</span> <span class='op'>&lt;&lt;</span> <span class='id identifier rubyid_k'>k</span> <span class='rbrace'>}</span> <span class='rbrace'>}</span> <span class='kw'>unless</span> <span class='id identifier rubyid_block'>block</span>
@@ -1599,13 +1664,13 @@ own transaction.</p>
1599
1664
  <pre class="lines">
1600
1665
 
1601
1666
 
1602
- 772
1603
- 773
1604
- 774
1605
- 775</pre>
1667
+ 819
1668
+ 820
1669
+ 821
1670
+ 822</pre>
1606
1671
  </td>
1607
1672
  <td>
1608
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 772</span>
1673
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 819</span>
1609
1674
 
1610
1675
  <span class='kw'>def</span> <span class='id identifier rubyid_each_value'>each_value</span><span class='lparen'>(</span><span class='op'>&amp;</span><span class='id identifier rubyid_block'>block</span><span class='rparen'>)</span>
1611
1676
  <span class='kw'>return</span> <span class='const'>Enumerator</span><span class='period'>.</span><span class='id identifier rubyid_new'>new</span><span class='lbrace'>{</span><span class='op'>|</span><span class='id identifier rubyid_y'>y</span><span class='op'>|</span> <span class='id identifier rubyid_nt_each'>nt_each</span><span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_k'>k</span><span class='comma'>,</span><span class='id identifier rubyid_v'>v</span><span class='op'>|</span> <span class='id identifier rubyid_y'>y</span> <span class='op'>&lt;&lt;</span> <span class='id identifier rubyid_v'>v</span> <span class='rbrace'>}</span> <span class='rbrace'>}</span> <span class='kw'>unless</span> <span class='id identifier rubyid_block'>block</span>
@@ -1654,12 +1719,12 @@ own transaction.</p>
1654
1719
  <pre class="lines">
1655
1720
 
1656
1721
 
1657
- 815
1658
- 816
1659
- 817</pre>
1722
+ 862
1723
+ 863
1724
+ 864</pre>
1660
1725
  </td>
1661
1726
  <td>
1662
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 815</span>
1727
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 862</span>
1663
1728
 
1664
1729
  <span class='kw'>def</span> <span class='id identifier rubyid_empty?'>empty?</span>
1665
1730
  <span class='kw'>return</span> <span class='id identifier rubyid_size'>size</span> <span class='op'>==</span> <span class='int'>0</span>
@@ -1735,36 +1800,36 @@ exception.</p>
1735
1800
  <pre class="lines">
1736
1801
 
1737
1802
 
1738
- 633
1739
- 634
1740
- 635
1741
- 636
1742
- 637
1743
- 638
1744
- 639
1745
- 640
1746
- 641
1747
- 642
1748
- 643
1749
- 644
1750
- 645
1751
- 646
1752
- 647
1753
- 648
1754
- 649
1755
- 650
1756
- 651
1757
- 652
1758
- 653
1759
- 654
1760
- 655
1761
- 656
1762
- 657
1763
- 658
1764
- 659</pre>
1803
+ 680
1804
+ 681
1805
+ 682
1806
+ 683
1807
+ 684
1808
+ 685
1809
+ 686
1810
+ 687
1811
+ 688
1812
+ 689
1813
+ 690
1814
+ 691
1815
+ 692
1816
+ 693
1817
+ 694
1818
+ 695
1819
+ 696
1820
+ 697
1821
+ 698
1822
+ 699
1823
+ 700
1824
+ 701
1825
+ 702
1826
+ 703
1827
+ 704
1828
+ 705
1829
+ 706</pre>
1765
1830
  </td>
1766
1831
  <td>
1767
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 633</span>
1832
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 680</span>
1768
1833
 
1769
1834
  <span class='kw'>def</span> <span class='id identifier rubyid_fetch'>fetch</span><span class='lparen'>(</span><span class='id identifier rubyid_key'>key</span><span class='comma'>,</span> <span class='op'>*</span><span class='id identifier rubyid_args'>args</span><span class='comma'>,</span> <span class='op'>&amp;</span><span class='id identifier rubyid_default_block'>default_block</span><span class='rparen'>)</span>
1770
1835
 
@@ -1840,12 +1905,12 @@ to help with unit tests.</p>
1840
1905
  <pre class="lines">
1841
1906
 
1842
1907
 
1843
- 548
1844
- 549
1845
- 550</pre>
1908
+ 566
1909
+ 567
1910
+ 568</pre>
1846
1911
  </td>
1847
1912
  <td>
1848
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 548</span>
1913
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 566</span>
1849
1914
 
1850
1915
  <span class='kw'>def</span> <span class='id identifier rubyid_handle_closed?'>handle_closed?</span>
1851
1916
  <span class='kw'>return</span> <span class='ivar'>@handle</span><span class='period'>.</span><span class='id identifier rubyid_closed?'>closed?</span>
@@ -1898,14 +1963,14 @@ to help with unit tests.</p>
1898
1963
  <pre class="lines">
1899
1964
 
1900
1965
 
1901
- 689
1902
- 690
1903
- 691
1904
- 692
1905
- 693</pre>
1966
+ 736
1967
+ 737
1968
+ 738
1969
+ 739
1970
+ 740</pre>
1906
1971
  </td>
1907
1972
  <td>
1908
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 689</span>
1973
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 736</span>
1909
1974
 
1910
1975
  <span class='kw'>def</span> <span class='id identifier rubyid_has_key?'>has_key?</span><span class='lparen'>(</span><span class='id identifier rubyid_key'>key</span><span class='rparen'>)</span>
1911
1976
  <span class='kw'>return</span> <span class='kw'>false</span> <span class='kw'>unless</span> <span class='id identifier rubyid_key'>key</span><span class='period'>.</span><span class='id identifier rubyid_class'>class</span> <span class='op'>==</span> <span class='const'>String</span> <span class='op'>||</span> <span class='id identifier rubyid_key'>key</span><span class='period'>.</span><span class='id identifier rubyid_class'>class</span> <span class='op'>==</span> <span class='const'>Symbol</span>
@@ -1961,13 +2026,13 @@ to help with unit tests.</p>
1961
2026
  <pre class="lines">
1962
2027
 
1963
2028
 
1964
- 858
1965
- 859
1966
- 860
1967
- 861</pre>
2029
+ 905
2030
+ 906
2031
+ 907
2032
+ 908</pre>
1968
2033
  </td>
1969
2034
  <td>
1970
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 858</span>
2035
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 905</span>
1971
2036
 
1972
2037
  <span class='kw'>def</span> <span class='id identifier rubyid_has_value?'>has_value?</span><span class='lparen'>(</span><span class='id identifier rubyid_val'>val</span><span class='rparen'>)</span>
1973
2038
  <span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_each'>each</span><span class='lbrace'>{</span><span class='op'>|</span><span class='id identifier rubyid_k'>k</span><span class='comma'>,</span><span class='id identifier rubyid_v'>v</span><span class='op'>|</span> <span class='kw'>return</span> <span class='kw'>true</span> <span class='kw'>if</span> <span class='id identifier rubyid_v'>v</span> <span class='op'>==</span> <span class='id identifier rubyid_val'>val</span><span class='rbrace'>}</span>
@@ -2008,14 +2073,14 @@ program.</p>
2008
2073
  <pre class="lines">
2009
2074
 
2010
2075
 
2011
- 870
2012
- 871
2013
- 872
2014
- 873
2015
- 874</pre>
2076
+ 917
2077
+ 918
2078
+ 919
2079
+ 920
2080
+ 921</pre>
2016
2081
  </td>
2017
2082
  <td>
2018
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 870</span>
2083
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 917</span>
2019
2084
 
2020
2085
  <span class='kw'>def</span> <span class='id identifier rubyid_invert'>invert</span>
2021
2086
  <span class='id identifier rubyid_result'>result</span> <span class='op'>=</span> <span class='lbrace'>{</span><span class='rbrace'>}</span>
@@ -2055,14 +2120,14 @@ that the result could exceed available memory.</p>
2055
2120
  <pre class="lines">
2056
2121
 
2057
2122
 
2058
- 671
2059
- 672
2060
- 673
2061
- 674
2062
- 675</pre>
2123
+ 718
2124
+ 719
2125
+ 720
2126
+ 721
2127
+ 722</pre>
2063
2128
  </td>
2064
2129
  <td>
2065
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 671</span>
2130
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 718</span>
2066
2131
 
2067
2132
  <span class='kw'>def</span> <span class='id identifier rubyid_keys'>keys</span>
2068
2133
  <span class='id identifier rubyid_keys'>keys</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='rbracket'>]</span>
@@ -2101,19 +2166,19 @@ as determined by SQLite3.</p>
2101
2166
  <pre class="lines">
2102
2167
 
2103
2168
 
2104
- 879
2105
- 880
2106
- 881
2107
- 882
2108
- 883
2109
- 884
2110
- 885
2111
- 886
2112
- 887
2113
- 888</pre>
2169
+ 926
2170
+ 927
2171
+ 928
2172
+ 929
2173
+ 930
2174
+ 931
2175
+ 932
2176
+ 933
2177
+ 934
2178
+ 935</pre>
2114
2179
  </td>
2115
2180
  <td>
2116
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 879</span>
2181
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 926</span>
2117
2182
 
2118
2183
  <span class='kw'>def</span> <span class='id identifier rubyid_shift'>shift</span>
2119
2184
  <span class='id identifier rubyid_transaction'>transaction</span> <span class='lbrace'>{</span>
@@ -2159,15 +2224,15 @@ as determined by SQLite3.</p>
2159
2224
  <pre class="lines">
2160
2225
 
2161
2226
 
2162
- 806
2163
- 807
2164
- 808
2165
- 809
2166
- 810
2167
- 811</pre>
2227
+ 853
2228
+ 854
2229
+ 855
2230
+ 856
2231
+ 857
2232
+ 858</pre>
2168
2233
  </td>
2169
2234
  <td>
2170
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 806</span>
2235
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 853</span>
2171
2236
 
2172
2237
  <span class='kw'>def</span> <span class='id identifier rubyid_size'>size</span>
2173
2238
  <span class='ivar'>@handle</span><span class='period'>.</span><span class='id identifier rubyid_sql'>sql</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>select count(*) from </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_actual_tbl'>actual_tbl</span><span class='embexpr_end'>}</span><span class='tstring_content'>;</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span> <span class='lbracket'>[</span><span class='rbracket'>]</span><span class='rparen'>)</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_row'>row</span><span class='op'>|</span>
@@ -2210,14 +2275,14 @@ program.</p>
2210
2275
  <pre class="lines">
2211
2276
 
2212
2277
 
2213
- 843
2214
- 844
2215
- 845
2216
- 846
2217
- 847</pre>
2278
+ 890
2279
+ 891
2280
+ 892
2281
+ 893
2282
+ 894</pre>
2218
2283
  </td>
2219
2284
  <td>
2220
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 843</span>
2285
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 890</span>
2221
2286
 
2222
2287
  <span class='kw'>def</span> <span class='id identifier rubyid_to_a'>to_a</span>
2223
2288
  <span class='id identifier rubyid_result'>result</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='rbracket'>]</span>
@@ -2258,14 +2323,14 @@ program.</p>
2258
2323
  <pre class="lines">
2259
2324
 
2260
2325
 
2261
- 830
2262
- 831
2263
- 832
2264
- 833
2265
- 834</pre>
2326
+ 877
2327
+ 878
2328
+ 879
2329
+ 880
2330
+ 881</pre>
2266
2331
  </td>
2267
2332
  <td>
2268
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 830</span>
2333
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 877</span>
2269
2334
 
2270
2335
  <span class='kw'>def</span> <span class='id identifier rubyid_to_hash'>to_hash</span>
2271
2336
  <span class='id identifier rubyid_result'>result</span> <span class='op'>=</span> <span class='lbrace'>{</span><span class='rbrace'>}</span>
@@ -2296,14 +2361,14 @@ program.</p>
2296
2361
  <pre class="lines">
2297
2362
 
2298
2363
 
2299
- 519
2300
- 520
2301
- 521
2302
- 522
2303
- 523</pre>
2364
+ 537
2365
+ 538
2366
+ 539
2367
+ 540
2368
+ 541</pre>
2304
2369
  </td>
2305
2370
  <td>
2306
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 519</span>
2371
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 537</span>
2307
2372
 
2308
2373
  <span class='kw'>def</span> <span class='id identifier rubyid_to_s'>to_s</span>
2309
2374
  <span class='id identifier rubyid_openstr'>openstr</span> <span class='op'>=</span> <span class='id identifier rubyid_closed?'>closed?</span> <span class='op'>?</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>CLOSED</span><span class='tstring_end'>&#39;</span></span> <span class='op'>:</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>OPEN</span><span class='tstring_end'>&#39;</span></span>
@@ -2371,12 +2436,12 @@ argument.</p>
2371
2436
  <pre class="lines">
2372
2437
 
2373
2438
 
2374
- 576
2375
- 577
2376
- 578</pre>
2439
+ 594
2440
+ 595
2441
+ 596</pre>
2377
2442
  </td>
2378
2443
  <td>
2379
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 576</span>
2444
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 594</span>
2380
2445
 
2381
2446
  <span class='kw'>def</span> <span class='id identifier rubyid_transaction'>transaction</span><span class='lparen'>(</span><span class='op'>&amp;</span><span class='id identifier rubyid_block'>block</span><span class='rparen'>)</span>
2382
2447
  <span class='kw'>return</span> <span class='ivar'>@handle</span><span class='period'>.</span><span class='id identifier rubyid_transaction'>transaction</span> <span class='lbrace'>{</span> <span class='id identifier rubyid_block'>block</span><span class='period'>.</span><span class='id identifier rubyid_call'>call</span><span class='lparen'>(</span><span class='kw'>self</span><span class='rparen'>)</span> <span class='rbrace'>}</span>
@@ -2424,12 +2489,12 @@ argument.</p>
2424
2489
  <pre class="lines">
2425
2490
 
2426
2491
 
2427
- 581
2428
- 582
2429
- 583</pre>
2492
+ 599
2493
+ 600
2494
+ 601</pre>
2430
2495
  </td>
2431
2496
  <td>
2432
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 581</span>
2497
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 599</span>
2433
2498
 
2434
2499
  <span class='kw'>def</span> <span class='id identifier rubyid_transaction_active?'>transaction_active?</span>
2435
2500
  <span class='kw'>return</span> <span class='ivar'>@handle</span><span class='period'>.</span><span class='id identifier rubyid_transaction_active?'>transaction_active?</span>
@@ -2466,14 +2531,14 @@ including <code>Hash</code> and <code>DBM</code> objects.</p>
2466
2531
  <pre class="lines">
2467
2532
 
2468
2533
 
2469
- 780
2470
- 781
2471
- 782
2472
- 783
2473
- 784</pre>
2534
+ 827
2535
+ 828
2536
+ 829
2537
+ 830
2538
+ 831</pre>
2474
2539
  </td>
2475
2540
  <td>
2476
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 780</span>
2541
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 827</span>
2477
2542
 
2478
2543
  <span class='kw'>def</span> <span class='id identifier rubyid_update'>update</span><span class='lparen'>(</span><span class='id identifier rubyid_hash'>hash</span><span class='rparen'>)</span>
2479
2544
  <span class='id identifier rubyid_transaction'>transaction</span> <span class='lbrace'>{</span>
@@ -2513,14 +2578,14 @@ that the result could exceed available memory.</p>
2513
2578
  <pre class="lines">
2514
2579
 
2515
2580
 
2516
- 681
2517
- 682
2518
- 683
2519
- 684
2520
- 685</pre>
2581
+ 728
2582
+ 729
2583
+ 730
2584
+ 731
2585
+ 732</pre>
2521
2586
  </td>
2522
2587
  <td>
2523
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 681</span>
2588
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 728</span>
2524
2589
 
2525
2590
  <span class='kw'>def</span> <span class='id identifier rubyid_values'>values</span>
2526
2591
  <span class='id identifier rubyid_values'>values</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='rbracket'>]</span>
@@ -2558,12 +2623,12 @@ given keys.</p>
2558
2623
  <pre class="lines">
2559
2624
 
2560
2625
 
2561
- 663
2562
- 664
2563
- 665</pre>
2626
+ 710
2627
+ 711
2628
+ 712</pre>
2564
2629
  </td>
2565
2630
  <td>
2566
- <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 663</span>
2631
+ <pre class="code"><span class="info file"># File 'lib/dbmlite3.rb', line 710</span>
2567
2632
 
2568
2633
  <span class='kw'>def</span> <span class='id identifier rubyid_values_at'>values_at</span><span class='lparen'>(</span><span class='op'>*</span><span class='id identifier rubyid_keys'>keys</span><span class='rparen'>)</span>
2569
2634
  <span class='kw'>return</span> <span class='id identifier rubyid_keys'>keys</span><span class='period'>.</span><span class='id identifier rubyid_map'>map</span><span class='lbrace'>{</span><span class='op'>|</span><span class='id identifier rubyid_k'>k</span><span class='op'>|</span> <span class='kw'>self</span><span class='lbracket'>[</span><span class='id identifier rubyid_k'>k</span><span class='rbracket'>]</span><span class='rbrace'>}</span>
@@ -2578,7 +2643,7 @@ given keys.</p>
2578
2643
  </div>
2579
2644
 
2580
2645
  <div id="footer">
2581
- Generated on Fri Feb 25 20:47:04 2022 by
2646
+ Generated on Sat Feb 26 14:54:02 2022 by
2582
2647
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
2583
2648
  0.9.25 (ruby-2.7.0).
2584
2649
  </div>
data/doc/Lite3/Error.html CHANGED
@@ -125,7 +125,7 @@
125
125
  </div>
126
126
 
127
127
  <div id="footer">
128
- Generated on Fri Feb 25 20:47:04 2022 by
128
+ Generated on Sat Feb 26 14:54:02 2022 by
129
129
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
130
130
  0.9.25 (ruby-2.7.0).
131
131
  </div>
data/doc/Lite3/SQL.html CHANGED
@@ -380,7 +380,7 @@ thread safe. Just a wrapper around <code>SQLite3.threadsafe?</code></p>
380
380
  </div>
381
381
 
382
382
  <div id="footer">
383
- Generated on Fri Feb 25 20:47:04 2022 by
383
+ Generated on Sat Feb 26 14:54:02 2022 by
384
384
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
385
385
  0.9.25 (ruby-2.7.0).
386
386
  </div>
data/doc/Lite3.html CHANGED
@@ -107,7 +107,7 @@
107
107
  </div>
108
108
 
109
109
  <div id="footer">
110
- Generated on Fri Feb 25 20:47:04 2022 by
110
+ Generated on Sat Feb 26 14:54:02 2022 by
111
111
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
112
112
  0.9.25 (ruby-2.7.0).
113
113
  </div>
data/doc/_index.html CHANGED
@@ -142,7 +142,7 @@
142
142
  </div>
143
143
 
144
144
  <div id="footer">
145
- Generated on Fri Feb 25 20:47:04 2022 by
145
+ Generated on Sat Feb 26 14:54:02 2022 by
146
146
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
147
147
  0.9.25 (ruby-2.7.0).
148
148
  </div>
data/doc/file.README.html CHANGED
@@ -163,6 +163,15 @@ only one program accesses the table at a time.</p>
163
163
  time (e.g. loading data from a file), it is significantly faster to
164
164
  do these in batches in one or more transactions.</p>
165
165
 
166
+ <h3 id="serialization-safety">Serialization Safety</h3>
167
+
168
+ <p><code>Lite3::DBM</code> stores Ruby data by first serializing values using the
169
+ <code>Marshal</code> or <code>Psych</code> modules. This can pose a security risk if an
170
+ untrusted third party has direct access to the underlying SQLite3
171
+ database. This tends to be pretty rare for most use-cases but if it
172
+ is a concern, you can always configure <code>Lite3::DBM</code> to store its
173
+ values as plain strings.</p>
174
+
166
175
  <h3 id="forking-safely">Forking safely</h3>
167
176
 
168
177
  <p>It is a documented limitation of SQLite3 that database objects
@@ -193,7 +202,7 @@ make sense of them.</p>
193
202
  </div></div>
194
203
 
195
204
  <div id="footer">
196
- Generated on Fri Feb 25 20:47:04 2022 by
205
+ Generated on Sat Feb 26 14:54:02 2022 by
197
206
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
198
207
  0.9.25 (ruby-2.7.0).
199
208
  </div>
data/doc/index.html CHANGED
@@ -163,6 +163,15 @@ only one program accesses the table at a time.</p>
163
163
  time (e.g. loading data from a file), it is significantly faster to
164
164
  do these in batches in one or more transactions.</p>
165
165
 
166
+ <h3 id="serialization-safety">Serialization Safety</h3>
167
+
168
+ <p><code>Lite3::DBM</code> stores Ruby data by first serializing values using the
169
+ <code>Marshal</code> or <code>Psych</code> modules. This can pose a security risk if an
170
+ untrusted third party has direct access to the underlying SQLite3
171
+ database. This tends to be pretty rare for most use-cases but if it
172
+ is a concern, you can always configure <code>Lite3::DBM</code> to store its
173
+ values as plain strings.</p>
174
+
166
175
  <h3 id="forking-safely">Forking safely</h3>
167
176
 
168
177
  <p>It is a documented limitation of SQLite3 that database objects
@@ -193,7 +202,7 @@ make sense of them.</p>
193
202
  </div></div>
194
203
 
195
204
  <div id="footer">
196
- Generated on Fri Feb 25 20:47:04 2022 by
205
+ Generated on Sat Feb 26 14:54:02 2022 by
197
206
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
198
207
  0.9.25 (ruby-2.7.0).
199
208
  </div>
@@ -100,7 +100,7 @@
100
100
  </div>
101
101
 
102
102
  <div id="footer">
103
- Generated on Fri Feb 25 20:47:04 2022 by
103
+ Generated on Sat Feb 26 14:54:02 2022 by
104
104
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
105
105
  0.9.25 (ruby-2.7.0).
106
106
  </div>
data/lib/dbmlite3.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  gem "sqlite3", "~> 1.4"
3
3
 
4
4
  require 'sqlite3'
5
- require 'yaml'
5
+ require 'psych'
6
6
  require 'set'
7
7
 
8
8
 
@@ -340,13 +340,19 @@ module Lite3
340
340
  # string. you will need to do this instead:
341
341
  #
342
342
  # db.keys.include?('foo') or raise AbjectFailure.new
343
- #
343
+ #
344
344
  # Unlike DBM, values may (optionally) be any serializable Ruby type.
345
345
  #
346
346
  # You can select the serialization method with an optional third
347
- # constructor argument. Options are `YAML` (the default), `Marshal`
348
- # or simple string conversion with `to_s`. Each of these methods will
349
- # have their own pros and cons.
347
+ # constructor argument. Options are YAML (the default), `Marshal`
348
+ # or simple string conversion with `to_s`. Each of these methods
349
+ # will have their own pros and cons.
350
+ #
351
+ # **WARNING:** Both YAML and Marshal serialization have the usual
352
+ # security caveats as described in the documentation for `Marshal`
353
+ # and `Psych`. If you are going to let an untrusted entity modify
354
+ # the database, you should not use these methods and instead stick
355
+ # to string conversion.
350
356
  #
351
357
  # The table name must be a valid name identifier (i.e. matches
352
358
  # /^[a-zA-Z_]\w*$/).
@@ -391,15 +397,16 @@ module Lite3
391
397
  # serialization method for converting Ruby values into storable
392
398
  # strings. There are three options:
393
399
  #
394
- # * `:yaml` uses the `YAML` module.
400
+ # * `:yaml` uses the `Psych` module.
395
401
  # * `:marshal` uses the `Marshal` module.
396
402
  # * `:string` simply uses the default `to_s` method, just like the
397
403
  # stock `DBM`.
398
404
  #
399
405
  # Each of these will have their pros and cons. The default is
400
- # `:yaml` because that is the most portable across Ruby versions.
401
- # `:marshal` tends to be faster but is not stable across Ruby
402
- # versions. Note that `DBM` does not check your Marshal version.
406
+ # `:yaml` because that is the most portable. `:marshal` tends to
407
+ # be faster but is incompatible across minor Ruby versions.
408
+ #
409
+ # (Note that `DBM` does not check your Marshal version.)
403
410
  #
404
411
  # Your serializer choice is registered in a metadata table when
405
412
  # `tablename` is created in the SQLite3 file. Afterward, it is an
@@ -450,8 +457,19 @@ module Lite3
450
457
  def value_encoders(serializer)
451
458
  case serializer
452
459
  when :yaml
453
- enc = proc{ |val| YAML.dump(val) }
454
- dec = proc{ |val| YAML.load(val) }
460
+ enc = proc{ |val| Psych.dump(val) }
461
+
462
+ # Psych (and module YAML) has gradually moved from defaulting
463
+ # from unsafe loading to safe loading. This is a pain for us
464
+ # because old versions don't provide `unsafe_load` as an alias
465
+ # to `load` and new versions default `load` to `safe_load`.
466
+ # So we have to do this thing to pick `unsafe_load` if it's
467
+ # available and `load` otherwise.
468
+ if Psych.respond_to? :unsafe_load
469
+ dec = proc{ |val| Psych.unsafe_load(val) }
470
+ else
471
+ dec = proc{ |val| Psych.load(val) }
472
+ end
455
473
 
456
474
  when :marshal
457
475
  enc = proc { |val| Marshal.dump(val) }
@@ -598,12 +616,41 @@ SQL
598
616
  key = check_key(key)
599
617
  valstr = SQLite3::Blob.new( @valenc.call(value) )
600
618
 
601
- insert = <<~SQL
602
- insert into #{actual_tbl} (key, value) values (?,?)
603
- on conflict(key) do update set value = ?;
604
- SQL
619
+ # At one point, this operation was done with SQLite3's UPSERT:
620
+ #
621
+ # insert into #{actual_tbl} (key, value) values (?,?)
622
+ # on conflict(key) do update set value = ?;
623
+ #
624
+ # Unfortunately, this capability was only added to SQLite3 in
625
+ # 2018, which means that at the time of this writing (2022)
626
+ # there are still a lot of systems out there that have older
627
+ # versions of SQLite3 and so can't do this.
628
+ #
629
+ # The venerable `insert or replace` feature **almost** does what
630
+ # I want:
631
+ #
632
+ # insert or replace into #{actual_tbl} (key, value) values (?, ?);
633
+ #
634
+ # The one problem is that it changes the order of the rows,
635
+ # which we need to preserve in order to remain consistent with
636
+ # `Hash` semantics (and because it's useful).
637
+ #
638
+ # So we kick it old school and do a `select` followed by an
639
+ # `insert` or `update` wrapped in a transaction.
605
640
  transaction {
606
- @handle.sql(insert, [key, valstr, valstr])
641
+ rowid = nil
642
+ select = "select rowid, key, value from #{actual_tbl} where key = ?;"
643
+ @handle.sql(select, [key]) { |row|
644
+ rowid = row[0]
645
+ }
646
+
647
+ if rowid
648
+ update = "update #{actual_tbl} set value = ? where rowid = ?;"
649
+ @handle.sql(update, [valstr, rowid])
650
+ else
651
+ insert = "insert into #{actual_tbl} (key, value) values (?,?);"
652
+ @handle.sql(insert, [key, valstr])
653
+ end
607
654
  }
608
655
 
609
656
  return value
@@ -120,6 +120,25 @@ Serializations = Set.new
120
120
  db.close
121
121
  end
122
122
 
123
+ it "preserves order after modification" do
124
+ path = Tmp.file
125
+ db = newdb.call(path, "floop")
126
+
127
+ expect( db.keys ) .to eq []
128
+ expect( db.values ) .to eq []
129
+
130
+ db["foo"] = 42
131
+ db["bar"] = 99
132
+ db["quux"] = 123
133
+
134
+ db["foo"] = 88
135
+
136
+ expect( db.keys ) .to eq %w{foo bar quux}
137
+ expect( db.values ) .to eq [88, 99, 123]
138
+
139
+ db.close
140
+ end
141
+
123
142
  it "implements has_key?" do
124
143
  path = Tmp.file
125
144
  db = newdb.call(path, "floop")
@@ -938,15 +957,12 @@ describe Lite3::SQL do
938
957
  expect( db1.closed? ) .to be true
939
958
  expect( db1.to_s.class ) .to be String
940
959
 
941
- # Everything else shoudl raise an error
960
+ # Everything else should raise an error
942
961
  expect{ db1["foo"] } .to raise_error Lite3::Error
943
962
  expect{ db1["foo"] = 42 } .to raise_error Lite3::Error
944
963
  expect{ db1.each{} } .to raise_error Lite3::Error
945
964
  expect{ db1.size } .to raise_error Lite3::Error
946
965
  expect{ db1.to_a } .to raise_error Lite3::Error
947
-
948
- # Ensure we haven't accidentally overridded superclass methods.
949
- expect( db1.object_id.class ) .to be Integer
950
966
  end
951
967
  end
952
968
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dbmlite3
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.a3
4
+ version: 1.0.a6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Reuter
@@ -79,10 +79,10 @@ extensions: []
79
79
  extra_rdoc_files: []
80
80
  files:
81
81
  - ".yardopts"
82
- - DBMLite3.gemspec
83
82
  - LICENSE.txt
84
83
  - README.md
85
84
  - Rakefile
85
+ - dbmlite3.gemspec
86
86
  - doc/Lite3.html
87
87
  - doc/Lite3/DBM.html
88
88
  - doc/Lite3/Error.html
@@ -116,7 +116,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
116
116
  requirements:
117
117
  - - ">="
118
118
  - !ruby/object:Gem::Version
119
- version: 2.7.0
119
+ version: 2.2.0
120
120
  required_rubygems_version: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - ">"