dirsql 0.3.76__tar.gz → 0.3.77__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 (137) hide show
  1. {dirsql-0.3.76 → dirsql-0.3.77}/Cargo.lock +1 -1
  2. {dirsql-0.3.76 → dirsql-0.3.77}/PKG-INFO +1 -1
  3. {dirsql-0.3.76 → dirsql-0.3.77}/docs/reference/sdk.md +14 -1
  4. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/Cargo.toml +1 -1
  5. {dirsql-0.3.76/packages/rust → dirsql-0.3.77/packages/python}/docs/reference/sdk.md +14 -1
  6. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/e2e-attestation.json +2 -2
  7. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/src/lib.rs +31 -6
  8. {dirsql-0.3.76/packages/python → dirsql-0.3.77/packages/rust}/docs/reference/sdk.md +14 -1
  9. {dirsql-0.3.76 → dirsql-0.3.77}/Cargo.toml +0 -0
  10. {dirsql-0.3.76 → dirsql-0.3.77}/README.md +0 -0
  11. {dirsql-0.3.76 → dirsql-0.3.77}/dirsql/__init__.py +0 -0
  12. {dirsql-0.3.76 → dirsql-0.3.77}/dirsql/_async.py +0 -0
  13. {dirsql-0.3.76 → dirsql-0.3.77}/dirsql/_dirsql.pyi +0 -0
  14. {dirsql-0.3.76 → dirsql-0.3.77}/dirsql/cli/__init__.py +0 -0
  15. {dirsql-0.3.76 → dirsql-0.3.77}/dirsql/cli/binary_path.py +0 -0
  16. {dirsql-0.3.76 → dirsql-0.3.77}/dirsql/cli/is_windows.py +0 -0
  17. {dirsql-0.3.76 → dirsql-0.3.77}/dirsql/cli/main.py +0 -0
  18. {dirsql-0.3.76 → dirsql-0.3.77}/dirsql/cli/resolve_config_extensions.py +0 -0
  19. {dirsql-0.3.76 → dirsql-0.3.77}/dirsql/py.typed +0 -0
  20. {dirsql-0.3.76 → dirsql-0.3.77}/dirsql/resolve_config_extensions.py +0 -0
  21. {dirsql-0.3.76 → dirsql-0.3.77}/dirsql/resolve_extension.py +0 -0
  22. {dirsql-0.3.76 → dirsql-0.3.77}/docs/.claude/CLAUDE.md +0 -0
  23. {dirsql-0.3.76 → dirsql-0.3.77}/docs/.vitepress/config.ts +0 -0
  24. {dirsql-0.3.76 → dirsql-0.3.77}/docs/.vitepress/theme/index.ts +0 -0
  25. {dirsql-0.3.76 → dirsql-0.3.77}/docs/.vitepress/theme/lang.ts +0 -0
  26. {dirsql-0.3.76 → dirsql-0.3.77}/docs/AGENTS.md +0 -0
  27. {dirsql-0.3.76 → dirsql-0.3.77}/docs/explanation.md +0 -0
  28. {dirsql-0.3.76 → dirsql-0.3.77}/docs/getting-started.md +0 -0
  29. {dirsql-0.3.76 → dirsql-0.3.77}/docs/howto/columns-from-paths.md +0 -0
  30. {dirsql-0.3.76 → dirsql-0.3.77}/docs/howto/define-tables.md +0 -0
  31. {dirsql-0.3.76 → dirsql-0.3.77}/docs/howto/embed.md +0 -0
  32. {dirsql-0.3.76 → dirsql-0.3.77}/docs/howto/extract-from-contents.md +0 -0
  33. {dirsql-0.3.76 → dirsql-0.3.77}/docs/howto/load-extension.md +0 -0
  34. {dirsql-0.3.76 → dirsql-0.3.77}/docs/howto/persist.md +0 -0
  35. {dirsql-0.3.76 → dirsql-0.3.77}/docs/howto/react-to-changes.md +0 -0
  36. {dirsql-0.3.76 → dirsql-0.3.77}/docs/howto/search-by-meaning.md +0 -0
  37. {dirsql-0.3.76 → dirsql-0.3.77}/docs/howto/skip-files.md +0 -0
  38. {dirsql-0.3.76 → dirsql-0.3.77}/docs/index.md +0 -0
  39. {dirsql-0.3.76 → dirsql-0.3.77}/docs/migrations.md +0 -0
  40. {dirsql-0.3.76 → dirsql-0.3.77}/docs/package.json +0 -0
  41. {dirsql-0.3.76 → dirsql-0.3.77}/docs/playwright.config.ts +0 -0
  42. {dirsql-0.3.76 → dirsql-0.3.77}/docs/pnpm-lock.yaml +0 -0
  43. {dirsql-0.3.76 → dirsql-0.3.77}/docs/pnpm-workspace.yaml +0 -0
  44. {dirsql-0.3.76 → dirsql-0.3.77}/docs/reference/cli.md +0 -0
  45. {dirsql-0.3.76 → dirsql-0.3.77}/docs/reference/columns.md +0 -0
  46. {dirsql-0.3.76 → dirsql-0.3.77}/docs/reference/config.md +0 -0
  47. {dirsql-0.3.76 → dirsql-0.3.77}/docs/reference/hooks.md +0 -0
  48. {dirsql-0.3.76 → dirsql-0.3.77}/docs/reference/http-api.md +0 -0
  49. {dirsql-0.3.76 → dirsql-0.3.77}/docs/tests/integration/home.spec.ts +0 -0
  50. {dirsql-0.3.76 → dirsql-0.3.77}/docs/tests/integration/language-flag.spec.ts +0 -0
  51. {dirsql-0.3.76 → dirsql-0.3.77}/docs/tests/integration/sidebar.spec.ts +0 -0
  52. {dirsql-0.3.76 → dirsql-0.3.77}/docs/tests/unit/config.test.ts +0 -0
  53. {dirsql-0.3.76 → dirsql-0.3.77}/docs/tests/unit/lang.test.ts +0 -0
  54. {dirsql-0.3.76 → dirsql-0.3.77}/docs/vitest.config.ts +0 -0
  55. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/README.md +0 -0
  56. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/conftest.py +0 -0
  57. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/.claude/CLAUDE.md +0 -0
  58. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/.vitepress/config.ts +0 -0
  59. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/.vitepress/theme/index.ts +0 -0
  60. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
  61. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/AGENTS.md +0 -0
  62. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/explanation.md +0 -0
  63. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/getting-started.md +0 -0
  64. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/howto/columns-from-paths.md +0 -0
  65. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/howto/define-tables.md +0 -0
  66. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/howto/embed.md +0 -0
  67. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/howto/extract-from-contents.md +0 -0
  68. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/howto/load-extension.md +0 -0
  69. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/howto/persist.md +0 -0
  70. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/howto/react-to-changes.md +0 -0
  71. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/howto/search-by-meaning.md +0 -0
  72. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/howto/skip-files.md +0 -0
  73. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/index.md +0 -0
  74. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/migrations.md +0 -0
  75. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/package.json +0 -0
  76. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/playwright.config.ts +0 -0
  77. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/pnpm-lock.yaml +0 -0
  78. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/pnpm-workspace.yaml +0 -0
  79. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/reference/cli.md +0 -0
  80. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/reference/columns.md +0 -0
  81. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/reference/config.md +0 -0
  82. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/reference/hooks.md +0 -0
  83. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/reference/http-api.md +0 -0
  84. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/tests/integration/home.spec.ts +0 -0
  85. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/tests/integration/language-flag.spec.ts +0 -0
  86. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/tests/integration/sidebar.spec.ts +0 -0
  87. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/tests/unit/config.test.ts +0 -0
  88. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/tests/unit/lang.test.ts +0 -0
  89. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/docs/vitest.config.ts +0 -0
  90. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/tests/__init__.py +0 -0
  91. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/tests/binding/__init__.py +0 -0
  92. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/tests/conftest.py +0 -0
  93. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/tests/e2e/__init__.py +0 -0
  94. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/tests/integration/__init__.py +0 -0
  95. {dirsql-0.3.76 → dirsql-0.3.77}/packages/python/tests/smoke/__init__.py +0 -0
  96. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/Cargo.toml +0 -0
  97. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/README.md +0 -0
  98. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/benches/db_bench.rs +0 -0
  99. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/benches/differ_bench.rs +0 -0
  100. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/benches/matcher_bench.rs +0 -0
  101. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/benches/scanner_bench.rs +0 -0
  102. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/docs/explanation.md +0 -0
  103. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/docs/getting-started.md +0 -0
  104. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/docs/howto/columns-from-paths.md +0 -0
  105. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/docs/howto/define-tables.md +0 -0
  106. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/docs/howto/embed.md +0 -0
  107. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/docs/howto/extract-from-contents.md +0 -0
  108. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/docs/howto/load-extension.md +0 -0
  109. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/docs/howto/persist.md +0 -0
  110. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/docs/howto/react-to-changes.md +0 -0
  111. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/docs/howto/search-by-meaning.md +0 -0
  112. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/docs/howto/skip-files.md +0 -0
  113. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/docs/index.md +0 -0
  114. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/docs/migrations.md +0 -0
  115. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/docs/reference/cli.md +0 -0
  116. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/docs/reference/columns.md +0 -0
  117. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/docs/reference/config.md +0 -0
  118. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/docs/reference/hooks.md +0 -0
  119. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/docs/reference/http-api.md +0 -0
  120. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/src/bin/dirsql.rs +0 -0
  121. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/src/cli/execute.rs +0 -0
  122. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/src/cli/init.rs +0 -0
  123. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/src/cli/mod.rs +0 -0
  124. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/src/cli/router.rs +0 -0
  125. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/src/cli/serialize.rs +0 -0
  126. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/src/cli/server.rs +0 -0
  127. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/src/command.rs +0 -0
  128. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/src/config.rs +0 -0
  129. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/src/db.rs +0 -0
  130. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/src/default_config.toml +0 -0
  131. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/src/differ.rs +0 -0
  132. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/src/lib.rs +0 -0
  133. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/src/matcher.rs +0 -0
  134. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/src/persist.rs +0 -0
  135. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/src/scanner.rs +0 -0
  136. {dirsql-0.3.76 → dirsql-0.3.77}/packages/rust/src/watcher.rs +0 -0
  137. {dirsql-0.3.76 → dirsql-0.3.77}/pyproject.toml +0 -0
@@ -500,7 +500,7 @@ dependencies = [
500
500
 
501
501
  [[package]]
502
502
  name = "dirsql-py-ext"
503
- version = "0.3.76"
503
+ version = "0.3.77"
504
504
  dependencies = [
505
505
  "dirsql",
506
506
  "pyo3",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dirsql
3
- Version: 0.3.76
3
+ Version: 0.3.77
4
4
  Summary: Ephemeral SQL index over a local directory
5
5
  Keywords: sql,filesystem,directory,sqlite,index
6
6
  Author: Kevin Scott
@@ -210,6 +210,12 @@ Executes a SQL query and returns rows keyed by column name.
210
210
  | BLOB | `bytes` | `Buffer` | `Value::Blob` |
211
211
  | NULL | `None` | `null` | `Value::Null` |
212
212
 
213
+ An `INTEGER` outside JavaScript's safe integer range (magnitude greater
214
+ than `Number.MAX_SAFE_INTEGER`, 2^53 − 1) cannot be represented as a JS
215
+ `number` without precision loss, so the TypeScript SDK **throws** rather
216
+ than return a rounded value. Python's `int` is unbounded, so it always
217
+ round-trips.
218
+
213
219
  ### `watch`
214
220
 
215
221
  ::: code-group
@@ -351,7 +357,14 @@ An `extract` callback (and the SQLite columns it feeds) accepts:
351
357
  | SQLite column | Python value | TypeScript value | Rust `Value` |
352
358
  |---|---|---|---|
353
359
  | TEXT | `str` | `string` | `Value::Text(String)` |
354
- | INTEGER | `int`, `bool` | `number`, `boolean` | `Value::Integer(i64)` |
360
+ | INTEGER | `int`, `bool` | `number`, `boolean`, `bigint` | `Value::Integer(i64)` |
355
361
  | REAL | `float` | `number` | `Value::Real(f64)` |
356
362
  | BLOB | `bytes` | `Buffer` / `Uint8Array` | `Value::Blob(Vec<u8>)` |
357
363
  | NULL | `None` | `null` | `Value::Null` |
364
+
365
+ Integers are stored as a signed 64-bit `Value::Integer`. A value that does
366
+ not fit that range is a hard error, not a lossy conversion: Python raises
367
+ `OverflowError`, and a TypeScript `bigint` outside the `i64` range throws.
368
+ A TypeScript `bigint` **within** `i64` range maps to `INTEGER`. Only a real
369
+ `bytes`/`bytearray` (Python) or `Buffer`/`Uint8Array` (TypeScript) maps to
370
+ `BLOB` — a list/array of integers does not.
@@ -4,7 +4,7 @@ name = "dirsql-py-ext"
4
4
  # pypi/maturin handler can rewrite it via `write-version` before
5
5
  # `maturin build`. `pyproject.toml` declares `dynamic = ["version"]`
6
6
  # and maturin reads this field. Mirrors `packages/rust/Cargo.toml`.
7
- version = "0.3.76"
7
+ version = "0.3.77"
8
8
  edition.workspace = true
9
9
  publish = false
10
10
  readme = "README.md"
@@ -210,6 +210,12 @@ Executes a SQL query and returns rows keyed by column name.
210
210
  | BLOB | `bytes` | `Buffer` | `Value::Blob` |
211
211
  | NULL | `None` | `null` | `Value::Null` |
212
212
 
213
+ An `INTEGER` outside JavaScript's safe integer range (magnitude greater
214
+ than `Number.MAX_SAFE_INTEGER`, 2^53 − 1) cannot be represented as a JS
215
+ `number` without precision loss, so the TypeScript SDK **throws** rather
216
+ than return a rounded value. Python's `int` is unbounded, so it always
217
+ round-trips.
218
+
213
219
  ### `watch`
214
220
 
215
221
  ::: code-group
@@ -351,7 +357,14 @@ An `extract` callback (and the SQLite columns it feeds) accepts:
351
357
  | SQLite column | Python value | TypeScript value | Rust `Value` |
352
358
  |---|---|---|---|
353
359
  | TEXT | `str` | `string` | `Value::Text(String)` |
354
- | INTEGER | `int`, `bool` | `number`, `boolean` | `Value::Integer(i64)` |
360
+ | INTEGER | `int`, `bool` | `number`, `boolean`, `bigint` | `Value::Integer(i64)` |
355
361
  | REAL | `float` | `number` | `Value::Real(f64)` |
356
362
  | BLOB | `bytes` | `Buffer` / `Uint8Array` | `Value::Blob(Vec<u8>)` |
357
363
  | NULL | `None` | `null` | `Value::Null` |
364
+
365
+ Integers are stored as a signed 64-bit `Value::Integer`. A value that does
366
+ not fit that range is a hard error, not a lossy conversion: Python raises
367
+ `OverflowError`, and a TypeScript `bigint` outside the `i64` range throws.
368
+ A TypeScript `bigint` **within** `i64` range maps to `INTEGER`. Only a real
369
+ `bytes`/`bytearray` (Python) or `Buffer`/`Uint8Array` (TypeScript) maps to
370
+ `BLOB` — a list/array of integers does not.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "command": "uv run python -m pytest tests/e2e/ -x -q",
3
- "ran_at": 1783522894,
3
+ "ran_at": 1783524611,
4
4
  "exit_code": 0,
5
- "commit": "aff7a746e4dfcd46d9f52f11f5cd7f680f5464ae"
5
+ "commit": "ee0a7c75d1e80868ace1390d0a99c92420c2f60e"
6
6
  }
@@ -13,9 +13,9 @@
13
13
  #[cfg(feature = "extension-module")]
14
14
  mod python {
15
15
  use ::dirsql::{DirSQL, Extension, Row, RowEvent, Table, Value, db::parse_table_name};
16
- use pyo3::exceptions::PyRuntimeError;
16
+ use pyo3::exceptions::{PyOverflowError, PyRuntimeError};
17
17
  use pyo3::prelude::*;
18
- use pyo3::types::{PyDict, PyList};
18
+ use pyo3::types::{PyBool, PyByteArray, PyBytes, PyDict, PyInt, PyList};
19
19
  use std::collections::HashMap;
20
20
  use std::path::PathBuf;
21
21
  use std::time::Duration;
@@ -361,21 +361,34 @@ mod python {
361
361
  }
362
362
 
363
363
  // bool must precede int (bool is a subclass of int in Python).
364
- if bound.is_instance_of::<pyo3::types::PyBool>() {
364
+ if bound.is_instance_of::<PyBool>() {
365
365
  let b: bool = bound.extract()?;
366
366
  return Ok(Value::Integer(if b { 1 } else { 0 }));
367
367
  }
368
368
 
369
- if let Ok(i) = bound.extract::<i64>() {
370
- return Ok(Value::Integer(i));
369
+ // A Python int must round-trip losslessly or fail loudly. Falling
370
+ // through to f64/str would silently corrupt an out-of-i64 value
371
+ // (lossy Real, or a TEXT repr).
372
+ if bound.is_instance_of::<PyInt>() {
373
+ return match bound.extract::<i64>() {
374
+ Ok(i) => Ok(Value::Integer(i)),
375
+ Err(_) => Err(PyOverflowError::new_err(int_overflow_message(
376
+ &bound.str()?.to_string(),
377
+ ))),
378
+ };
371
379
  }
380
+
372
381
  if let Ok(f) = bound.extract::<f64>() {
373
382
  return Ok(Value::Real(f));
374
383
  }
375
384
  if let Ok(s) = bound.extract::<String>() {
376
385
  return Ok(Value::Text(s));
377
386
  }
378
- if let Ok(b) = bound.extract::<Vec<u8>>() {
387
+ // Only genuine binary types map to BLOB. A list/tuple of ints must
388
+ // NOT be probed as bytes (that turned `[1,2,3]` into a BLOB by
389
+ // magnitude); it falls through to the repr like any other sequence.
390
+ if bound.is_instance_of::<PyBytes>() || bound.is_instance_of::<PyByteArray>() {
391
+ let b: Vec<u8> = bound.extract()?;
379
392
  return Ok(Value::Blob(b));
380
393
  }
381
394
 
@@ -383,6 +396,11 @@ mod python {
383
396
  Ok(Value::Text(bound.str()?.to_string()))
384
397
  }
385
398
 
399
+ /// The range-error message for a Python int that does not fit `i64`.
400
+ fn int_overflow_message(repr: &str) -> String {
401
+ format!("integer {repr} exceeds the 64-bit signed range dirsql can store")
402
+ }
403
+
386
404
  fn value_to_py(py: Python<'_>, value: &Value) -> Py<PyAny> {
387
405
  match value {
388
406
  Value::Null => py.None(),
@@ -481,5 +499,12 @@ mod python {
481
499
  fn extract_error_displays_inner() {
482
500
  assert_eq!(ExtractError("bad".to_string()).to_string(), "bad");
483
501
  }
502
+
503
+ #[test]
504
+ fn int_overflow_message_names_the_value() {
505
+ let m = int_overflow_message("9223372036854775808");
506
+ assert!(m.contains("9223372036854775808"));
507
+ assert!(m.contains("exceeds"));
508
+ }
484
509
  }
485
510
  }
@@ -210,6 +210,12 @@ Executes a SQL query and returns rows keyed by column name.
210
210
  | BLOB | `bytes` | `Buffer` | `Value::Blob` |
211
211
  | NULL | `None` | `null` | `Value::Null` |
212
212
 
213
+ An `INTEGER` outside JavaScript's safe integer range (magnitude greater
214
+ than `Number.MAX_SAFE_INTEGER`, 2^53 − 1) cannot be represented as a JS
215
+ `number` without precision loss, so the TypeScript SDK **throws** rather
216
+ than return a rounded value. Python's `int` is unbounded, so it always
217
+ round-trips.
218
+
213
219
  ### `watch`
214
220
 
215
221
  ::: code-group
@@ -351,7 +357,14 @@ An `extract` callback (and the SQLite columns it feeds) accepts:
351
357
  | SQLite column | Python value | TypeScript value | Rust `Value` |
352
358
  |---|---|---|---|
353
359
  | TEXT | `str` | `string` | `Value::Text(String)` |
354
- | INTEGER | `int`, `bool` | `number`, `boolean` | `Value::Integer(i64)` |
360
+ | INTEGER | `int`, `bool` | `number`, `boolean`, `bigint` | `Value::Integer(i64)` |
355
361
  | REAL | `float` | `number` | `Value::Real(f64)` |
356
362
  | BLOB | `bytes` | `Buffer` / `Uint8Array` | `Value::Blob(Vec<u8>)` |
357
363
  | NULL | `None` | `null` | `Value::Null` |
364
+
365
+ Integers are stored as a signed 64-bit `Value::Integer`. A value that does
366
+ not fit that range is a hard error, not a lossy conversion: Python raises
367
+ `OverflowError`, and a TypeScript `bigint` outside the `i64` range throws.
368
+ A TypeScript `bigint` **within** `i64` range maps to `INTEGER`. Only a real
369
+ `bytes`/`bytearray` (Python) or `Buffer`/`Uint8Array` (TypeScript) maps to
370
+ `BLOB` — a list/array of integers does not.
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes