dbmlite3 1.0.a3 → 1.0.a6

Sign up to get free protection for your applications and to get access to all the features.
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
  - - ">"