ducpy 3.0.5__tar.gz → 3.1.1__tar.gz

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.
Files changed (31) hide show
  1. {ducpy-3.0.5 → ducpy-3.1.1}/Cargo.lock +44 -42
  2. {ducpy-3.0.5 → ducpy-3.1.1}/Cargo.toml +0 -1
  3. {ducpy-3.0.5 → ducpy-3.1.1}/PKG-INFO +1 -1
  4. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducpy/crate/Cargo.toml +1 -1
  5. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducrs/build.rs +56 -0
  6. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducrs/src/db/bootstrap.rs +46 -1
  7. ducpy-3.1.1/packages/ducrs/src/lib.rs +297 -0
  8. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducrs/src/parse.rs +230 -43
  9. ducpy-3.1.1/packages/ducrs/src/serde_utils.rs +90 -0
  10. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducrs/src/serialize.rs +30 -6
  11. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducrs/src/types.rs +56 -21
  12. ducpy-3.0.5/packages/ducrs/src/lib.rs +0 -94
  13. {ducpy-3.0.5 → ducpy-3.1.1}/LICENSE +0 -0
  14. {ducpy-3.0.5 → ducpy-3.1.1}/README.md +0 -0
  15. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducpy/crate/src/lib.rs +0 -0
  16. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducrs/.gitignore +0 -0
  17. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducrs/Cargo.toml +0 -0
  18. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducrs/LICENSE +0 -0
  19. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducrs/README.md +0 -0
  20. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducrs/package.json +0 -0
  21. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducrs/release.config.cjs +0 -0
  22. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducrs/src/api/document.rs +0 -0
  23. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducrs/src/api/meta.rs +0 -0
  24. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducrs/src/api/mod.rs +0 -0
  25. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducrs/src/api/version_control.rs +0 -0
  26. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducrs/src/db/mod.rs +0 -0
  27. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducrs/src/db/native.rs +0 -0
  28. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducrs/src/db/wasm.rs +0 -0
  29. {ducpy-3.0.5 → ducpy-3.1.1}/packages/ducrs/tests/.gitignore +0 -0
  30. {ducpy-3.0.5 → ducpy-3.1.1}/pyproject.toml +0 -0
  31. {ducpy-3.0.5 → ducpy-3.1.1}/src/ducpy_native/__init__.py +0 -0
@@ -288,9 +288,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
288
288
 
289
289
  [[package]]
290
290
  name = "crypto-common"
291
- version = "0.1.6"
291
+ version = "0.1.7"
292
292
  source = "registry+https://github.com/rust-lang/crates.io-index"
293
- checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
293
+ checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
294
294
  dependencies = [
295
295
  "generic-array",
296
296
  "typenum",
@@ -318,9 +318,9 @@ dependencies = [
318
318
 
319
319
  [[package]]
320
320
  name = "deranged"
321
- version = "0.5.4"
321
+ version = "0.5.8"
322
322
  source = "registry+https://github.com/rust-lang/crates.io-index"
323
- checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071"
323
+ checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
324
324
  dependencies = [
325
325
  "powerfmt",
326
326
  ]
@@ -411,7 +411,7 @@ dependencies = [
411
411
 
412
412
  [[package]]
413
413
  name = "ducpy-native"
414
- version = "3.0.5"
414
+ version = "3.1.1"
415
415
  dependencies = [
416
416
  "duc",
417
417
  "pyo3",
@@ -579,9 +579,9 @@ checksum = "4e42f72dc65ff480af54c73c63d4b425936aac4167a01b7c9e1ed15aacace22c"
579
579
 
580
580
  [[package]]
581
581
  name = "generic-array"
582
- version = "0.14.9"
582
+ version = "0.14.7"
583
583
  source = "registry+https://github.com/rust-lang/crates.io-index"
584
- checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2"
584
+ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
585
585
  dependencies = [
586
586
  "typenum",
587
587
  "version_check",
@@ -713,10 +713,11 @@ checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
713
713
 
714
714
  [[package]]
715
715
  name = "hipdf"
716
- version = "1.3.3"
716
+ version = "1.3.7"
717
717
  source = "registry+https://github.com/rust-lang/crates.io-index"
718
- checksum = "5d8e0025c137fd7f666ec73ba8a1c8c7f4940edb83fdb77013e5e12703204c80"
718
+ checksum = "2dfe672796312ef1e60b2866d6dac03b67c32dc7276a71c6d34b573dd00502f1"
719
719
  dependencies = [
720
+ "image",
720
721
  "jpeg-decoder",
721
722
  "lopdf",
722
723
  "miniz_oxide",
@@ -764,6 +765,7 @@ dependencies = [
764
765
  "byteorder-lite",
765
766
  "color_quant",
766
767
  "gif",
768
+ "image-webp",
767
769
  "moxcms",
768
770
  "num-traits",
769
771
  "png 0.18.0",
@@ -880,24 +882,24 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
880
882
 
881
883
  [[package]]
882
884
  name = "jiff"
883
- version = "0.2.15"
885
+ version = "0.2.23"
884
886
  source = "registry+https://github.com/rust-lang/crates.io-index"
885
- checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49"
887
+ checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359"
886
888
  dependencies = [
887
889
  "jiff-static",
888
890
  "jiff-tzdb-platform",
889
891
  "log",
890
892
  "portable-atomic",
891
893
  "portable-atomic-util",
892
- "serde",
893
- "windows-sys 0.59.0",
894
+ "serde_core",
895
+ "windows-sys 0.61.2",
894
896
  ]
895
897
 
896
898
  [[package]]
897
899
  name = "jiff-static"
898
- version = "0.2.15"
900
+ version = "0.2.23"
899
901
  source = "registry+https://github.com/rust-lang/crates.io-index"
900
- checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4"
902
+ checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4"
901
903
  dependencies = [
902
904
  "proc-macro2",
903
905
  "quote",
@@ -906,9 +908,9 @@ dependencies = [
906
908
 
907
909
  [[package]]
908
910
  name = "jiff-tzdb"
909
- version = "0.1.4"
911
+ version = "0.1.6"
910
912
  source = "registry+https://github.com/rust-lang/crates.io-index"
911
- checksum = "c1283705eb0a21404d2bfd6eef2a7593d240bc42a0bdb39db0ad6fa2ec026524"
913
+ checksum = "c900ef84826f1338a557697dc8fc601df9ca9af4ac137c7fb61d4c6f2dfd3076"
912
914
 
913
915
  [[package]]
914
916
  name = "jiff-tzdb-platform"
@@ -1166,9 +1168,9 @@ dependencies = [
1166
1168
 
1167
1169
  [[package]]
1168
1170
  name = "num-conv"
1169
- version = "0.1.0"
1171
+ version = "0.2.0"
1170
1172
  source = "registry+https://github.com/rust-lang/crates.io-index"
1171
- checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
1173
+ checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050"
1172
1174
 
1173
1175
  [[package]]
1174
1176
  name = "num-traits"
@@ -1322,9 +1324,9 @@ checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
1322
1324
 
1323
1325
  [[package]]
1324
1326
  name = "portable-atomic-util"
1325
- version = "0.2.4"
1327
+ version = "0.2.5"
1326
1328
  source = "registry+https://github.com/rust-lang/crates.io-index"
1327
- checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
1329
+ checksum = "7a9db96d7fa8782dd8c15ce32ffe8680bbd1e978a43bf51a34d39483540495f5"
1328
1330
  dependencies = [
1329
1331
  "portable-atomic",
1330
1332
  ]
@@ -1478,18 +1480,18 @@ dependencies = [
1478
1480
 
1479
1481
  [[package]]
1480
1482
  name = "rand_core"
1481
- version = "0.9.3"
1483
+ version = "0.9.5"
1482
1484
  source = "registry+https://github.com/rust-lang/crates.io-index"
1483
- checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
1485
+ checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
1484
1486
  dependencies = [
1485
1487
  "getrandom",
1486
1488
  ]
1487
1489
 
1488
1490
  [[package]]
1489
1491
  name = "rangemap"
1490
- version = "1.6.0"
1492
+ version = "1.7.1"
1491
1493
  source = "registry+https://github.com/rust-lang/crates.io-index"
1492
- checksum = "f93e7e49bb0bf967717f7bd674458b3d6b0c5f48ec7e3038166026a69fc22223"
1494
+ checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68"
1493
1495
 
1494
1496
  [[package]]
1495
1497
  name = "rayon"
@@ -1978,30 +1980,30 @@ dependencies = [
1978
1980
 
1979
1981
  [[package]]
1980
1982
  name = "time"
1981
- version = "0.3.44"
1983
+ version = "0.3.47"
1982
1984
  source = "registry+https://github.com/rust-lang/crates.io-index"
1983
- checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d"
1985
+ checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c"
1984
1986
  dependencies = [
1985
1987
  "deranged",
1986
1988
  "itoa",
1987
1989
  "num-conv",
1988
1990
  "powerfmt",
1989
- "serde",
1991
+ "serde_core",
1990
1992
  "time-core",
1991
1993
  "time-macros",
1992
1994
  ]
1993
1995
 
1994
1996
  [[package]]
1995
1997
  name = "time-core"
1996
- version = "0.1.6"
1998
+ version = "0.1.8"
1997
1999
  source = "registry+https://github.com/rust-lang/crates.io-index"
1998
- checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b"
2000
+ checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca"
1999
2001
 
2000
2002
  [[package]]
2001
2003
  name = "time-macros"
2002
- version = "0.2.24"
2004
+ version = "0.2.27"
2003
2005
  source = "registry+https://github.com/rust-lang/crates.io-index"
2004
- checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3"
2006
+ checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215"
2005
2007
  dependencies = [
2006
2008
  "num-conv",
2007
2009
  "time-core",
@@ -2104,9 +2106,9 @@ checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06"
2104
2106
 
2105
2107
  [[package]]
2106
2108
  name = "unicode-normalization"
2107
- version = "0.1.24"
2109
+ version = "0.1.25"
2108
2110
  source = "registry+https://github.com/rust-lang/crates.io-index"
2109
- checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
2111
+ checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8"
2110
2112
  dependencies = [
2111
2113
  "tinyvec",
2112
2114
  ]
@@ -2182,9 +2184,9 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
2182
2184
 
2183
2185
  [[package]]
2184
2186
  name = "wasip2"
2185
- version = "1.0.1+wasi-0.2.4"
2187
+ version = "1.0.2+wasi-0.2.9"
2186
2188
  source = "registry+https://github.com/rust-lang/crates.io-index"
2187
- checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
2189
+ checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
2188
2190
  dependencies = [
2189
2191
  "wit-bindgen",
2190
2192
  ]
@@ -2429,9 +2431,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
2429
2431
 
2430
2432
  [[package]]
2431
2433
  name = "wit-bindgen"
2432
- version = "0.46.0"
2434
+ version = "0.51.0"
2433
2435
  source = "registry+https://github.com/rust-lang/crates.io-index"
2434
- checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
2436
+ checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
2435
2437
 
2436
2438
  [[package]]
2437
2439
  name = "write-fonts"
@@ -2477,18 +2479,18 @@ dependencies = [
2477
2479
 
2478
2480
  [[package]]
2479
2481
  name = "zerocopy"
2480
- version = "0.8.27"
2482
+ version = "0.8.42"
2481
2483
  source = "registry+https://github.com/rust-lang/crates.io-index"
2482
- checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
2484
+ checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3"
2483
2485
  dependencies = [
2484
2486
  "zerocopy-derive",
2485
2487
  ]
2486
2488
 
2487
2489
  [[package]]
2488
2490
  name = "zerocopy-derive"
2489
- version = "0.8.27"
2491
+ version = "0.8.42"
2490
2492
  source = "registry+https://github.com/rust-lang/crates.io-index"
2491
- checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
2493
+ checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f"
2492
2494
  dependencies = [
2493
2495
  "proc-macro2",
2494
2496
  "quote",
@@ -2,7 +2,6 @@
2
2
  resolver = "2"
3
3
  members = ["packages/ducrs", "packages/ducpy/crate"]
4
4
 
5
-
6
5
  [profile.release]
7
6
  lto = true
8
7
  opt-level = "s"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ducpy
3
- Version: 3.0.5
3
+ Version: 3.1.1
4
4
  Classifier: License :: OSI Approved :: MIT License
5
5
  Requires-Dist: nanoid>=2.0.0
6
6
  License-File: LICENSE
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "ducpy-native"
3
- version = "3.0.5"
3
+ version = "3.1.1"
4
4
  edition = "2021"
5
5
  description = "Python native extension for the duc file format (used by ducpy)"
6
6
  publish = false
@@ -43,7 +43,63 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
43
43
  }
44
44
  println!("cargo:rerun-if-changed={}", src.display());
45
45
  }
46
+ // Scan schema/migrations/*.sql, parse (from, to) from filenames like
47
+ // "3000000_to_3000001.sql", and generate migrations_registry.rs with a
48
+ // sorted static array of (from_version, to_version, sql) tuples.
49
+ // Adding a new migration requires only a new SQL file — no Rust changes.
50
+ let migrations_dir = schema_dir.join("migrations");
51
+ let mut migrations: Vec<(i64, i64, String)> = Vec::new();
46
52
 
53
+ if migrations_dir.is_dir() {
54
+ for entry in fs::read_dir(&migrations_dir)? {
55
+ let entry = entry?;
56
+ let path = entry.path();
57
+ if path.extension().and_then(|e| e.to_str()) != Some("sql") {
58
+ continue;
59
+ }
60
+ let stem = match path.file_stem().and_then(|s| s.to_str()) {
61
+ Some(s) => s.to_owned(),
62
+ None => continue,
63
+ };
64
+ // Expect exactly "<from>_to_<to>".
65
+ if let Some((from_str, to_str)) = stem.split_once("_to_") {
66
+ if let (Ok(from), Ok(to)) = (from_str.parse::<i64>(), to_str.parse::<i64>()) {
67
+ let sql = fs::read_to_string(&path)?;
68
+ migrations.push((from, to, sql));
69
+ println!("cargo:rerun-if-changed={}", path.display());
70
+ } else {
71
+ eprintln!("cargo:warning=Skipping migration file with non-integer versions: {stem}.sql");
72
+ }
73
+ } else {
74
+ eprintln!("cargo:warning=Skipping migration file with unexpected name: {stem}.sql");
75
+ }
76
+ }
77
+ println!("cargo:rerun-if-changed={}", migrations_dir.display());
78
+ }
79
+
80
+ // Sort ascending by from_version so chained migrations apply in order.
81
+ migrations.sort_by_key(|(from, _, _)| *from);
82
+
83
+ // Emit migrations_registry.rs: a static array included by bootstrap.rs.
84
+ let mut reg = String::from(
85
+ "// Auto-generated by build.rs — do not edit by hand.\n\
86
+ // Each entry: (from_version, to_version, sql).\n\
87
+ pub(crate) static MIGRATIONS: &[(i64, i64, &str)] = &[\n",
88
+ );
89
+ for (from, to, sql) in &migrations {
90
+ reg.push_str(&format!(" ({from}i64, {to}i64, \""));
91
+ for c in sql.chars() {
92
+ match c {
93
+ '"' => reg.push_str("\\\""),
94
+ '\\' => reg.push_str("\\\\"),
95
+ '\r' => {} // normalise CRLF → LF
96
+ c => reg.push(c),
97
+ }
98
+ }
99
+ reg.push_str("\"),\n");
100
+ }
101
+ reg.push_str("];\n");
102
+ fs::write(out_dir.join("migrations_registry.rs"), reg)?;
47
103
  let sql_path = schema_dir.join("duc.sql");
48
104
  let (user_version, semver_version) = match fs::read_to_string(&sql_path) {
49
105
  Ok(sql) => {
@@ -18,6 +18,24 @@ const SEARCH_SCHEMA: &str = include_str!(concat!(env!("OUT_DIR"), "/search.sql")
18
18
  /// Expected `application_id` written by `duc.sql`.
19
19
  const APP_ID: i64 = 1_146_569_567; // "DUC_" in ASCII
20
20
 
21
+ /// Schema version read from `duc.sql` at compile time by `build.rs`.
22
+ /// Never hardcode this — it is always in sync with the SQL file.
23
+ const CURRENT_VERSION: i64 = {
24
+ // build.rs emits DUC_SCHEMA_USER_VERSION as a decimal integer string.
25
+ let bytes = env!("DUC_SCHEMA_USER_VERSION").as_bytes();
26
+ let mut val: i64 = 0;
27
+ let mut i = 0;
28
+ while i < bytes.len() {
29
+ val = val * 10 + (bytes[i] - b'0') as i64;
30
+ i += 1;
31
+ }
32
+ val
33
+ };
34
+
35
+ // Migration registry auto-generated by build.rs from `schema/migrations/*.sql`.
36
+ // Each entry is (from_version, to_version, sql). Sorted ascending by from_version.
37
+ include!(concat!(env!("OUT_DIR"), "/migrations_registry.rs"));
38
+
21
39
  /// Per-connection PRAGMAs that must be re-applied on every open (they are
22
40
  /// either ephemeral or take effect only after the first statement on the
23
41
  /// connection).
@@ -57,8 +75,35 @@ pub(crate) fn bootstrap(conn: &Connection) -> Result<(), DbError> {
57
75
  "unexpected application_id after bootstrap: {app_id} (expected {APP_ID})"
58
76
  )));
59
77
  }
78
+ } else if user_version == CURRENT_VERSION {
79
+ // Current schema — just ensure per-connection pragmas are active.
80
+ conn.execute_batch(CONN_PRAGMAS)
81
+ .map_err(|e| DbError::Bootstrap(format!("pragma apply failed: {e}")))?;
60
82
  } else {
61
- // Existing database just ensure per-connection pragmas are active.
83
+ // Walk the migration chain until we reach CURRENT_VERSION.
84
+ // build.rs generates MIGRATIONS sorted by from_version, so chaining
85
+ // (e.g. 3000000→3000001→3000002) works without any code changes here.
86
+ let mut current = user_version;
87
+ loop {
88
+ match MIGRATIONS.iter().find(|(from, _, _)| *from == current) {
89
+ Some((from, to, sql)) => {
90
+ conn.execute_batch(sql).map_err(|e| {
91
+ DbError::Bootstrap(format!("migration {from}\u{2192}{to} failed: {e}"))
92
+ })?;
93
+ // Re-read the version the migration SQL set via PRAGMA user_version.
94
+ current =
95
+ conn.pragma_query_value(None, "user_version", |r| r.get(0))?;
96
+ if current == CURRENT_VERSION {
97
+ break;
98
+ }
99
+ }
100
+ None => {
101
+ return Err(DbError::Bootstrap(format!(
102
+ "unsupported schema version {user_version}; expected 0 or {CURRENT_VERSION}"
103
+ )));
104
+ }
105
+ }
106
+ }
62
107
  conn.execute_batch(CONN_PRAGMAS)
63
108
  .map_err(|e| DbError::Bootstrap(format!("pragma apply failed: {e}")))?;
64
109
  }