pyturso 0.2.0rc15__tar.gz → 0.2.2__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.
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/Cargo.lock +27 -27
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/Cargo.toml +17 -17
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/PKG-INFO +1 -1
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/incremental/compiler.rs +25 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/incremental/filter_operator.rs +216 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/io/unix.rs +3 -2
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/lib.rs +39 -9
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/mvcc/database/mod.rs +14 -2
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/mvcc/database/tests.rs +13 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/index.rs +31 -2
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/insert.rs +7 -1
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/vdbe/builder.rs +6 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/vdbe/execute.rs +90 -16
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/vdbe/explain.rs +14 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/vdbe/insn.rs +13 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/vdbe/sorter.rs +1 -1
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/bindings/python/Cargo.toml +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/bindings/python/build.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/bindings/python/example.py +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/bindings/python/requirements-dev.txt +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/bindings/python/requirements.txt +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/bindings/python/src/errors.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/bindings/python/src/lib.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/bindings/python/tests/__init__.py +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/bindings/python/tests/test_database.py +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/bindings/python/turso/__init__.py +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/bindings/python/turso/py.typed +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/Cargo.toml +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/assert.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/benches/benchmark.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/benches/json_benchmark.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/benches/mvcc_benchmark.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/benches/tpc_h_benchmark.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/build.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/error.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/ext/dynamic.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/ext/mod.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/ext/vtab_xconnect.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/fast_lock.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/function.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/functions/datetime.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/functions/mod.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/functions/printf.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/functions/strftime.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/incremental/aggregate_operator.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/incremental/cursor.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/incremental/dbsp.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/incremental/expr_compiler.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/incremental/input_operator.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/incremental/join_operator.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/incremental/merge_operator.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/incremental/mod.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/incremental/operator.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/incremental/persistence.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/incremental/project_operator.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/incremental/view.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/info.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/io/clock.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/io/common.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/io/generic.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/io/io_uring.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/io/memory.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/io/mod.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/io/vfs.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/io/windows.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/json/cache.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/json/error.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/json/jsonb.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/json/mod.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/json/ops.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/json/path.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/json/vtab.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/mvcc/clock.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/mvcc/cursor.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/mvcc/database/checkpoint_state_machine.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/mvcc/mod.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/mvcc/persistent_storage/logical_log.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/mvcc/persistent_storage/mod.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/numeric/mod.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/numeric/nonnan.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/parameters.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/pragma.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/pseudo.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/schema.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/series.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/state_machine.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/storage/btree.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/storage/buffer_pool.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/storage/checksum.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/storage/database.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/storage/encryption.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/storage/mod.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/storage/page_cache.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/storage/pager.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/storage/slot_bitmap.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/storage/sqlite3_ondisk.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/storage/state_machines.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/storage/wal.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/time/internal.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/time/mod.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/aggregation.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/alter.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/analyze.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/attach.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/collate.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/compound_select.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/delete.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/display.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/emitter.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/expr.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/group_by.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/integrity_check.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/logical.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/main_loop.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/mod.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/optimizer/OPTIMIZER.md +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/optimizer/access_method.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/optimizer/constraints.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/optimizer/cost.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/optimizer/join.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/optimizer/lift_common_subexpressions.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/optimizer/mod.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/optimizer/order.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/order_by.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/plan.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/planner.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/pragma.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/result_row.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/rollback.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/schema.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/select.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/subquery.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/transaction.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/update.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/upsert.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/values.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/view.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/translate/window.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/types.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/util.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/uuid.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/vdbe/likeop.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/vdbe/metrics.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/vdbe/mod.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/vector/distance/euclidean.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/vector/distance.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/vector/mod.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/vector/vector_types.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/core/vtab.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/extensions/core/Cargo.toml +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/extensions/core/README.md +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/extensions/core/build.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/extensions/core/src/functions.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/extensions/core/src/lib.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/extensions/core/src/types.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/extensions/core/src/vfs_modules.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/extensions/core/src/vtabs.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/macros/Cargo.toml +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/macros/src/ext/agg_derive.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/macros/src/ext/match_ignore_ascii_case.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/macros/src/ext/mod.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/macros/src/ext/scalars.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/macros/src/ext/vfs_derive.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/macros/src/ext/vtab_derive.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/macros/src/lib.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/parser/Cargo.toml +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/parser/README.md +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/parser/benches/parser_benchmark.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/parser/src/ast/check.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/parser/src/ast/fmt.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/parser/src/ast.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/parser/src/error.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/parser/src/lexer.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/parser/src/lib.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/parser/src/parser.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/parser/src/token.rs +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/pyproject.toml +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/turso/__init__.py +0 -0
- {pyturso-0.2.0rc15 → pyturso-0.2.2}/turso/py.typed +0 -0
|
@@ -690,7 +690,7 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
|
|
690
690
|
|
|
691
691
|
[[package]]
|
|
692
692
|
name = "core_tester"
|
|
693
|
-
version = "0.2.
|
|
693
|
+
version = "0.2.2"
|
|
694
694
|
dependencies = [
|
|
695
695
|
"anyhow",
|
|
696
696
|
"assert_cmd",
|
|
@@ -2278,7 +2278,7 @@ dependencies = [
|
|
|
2278
2278
|
|
|
2279
2279
|
[[package]]
|
|
2280
2280
|
name = "limbo_completion"
|
|
2281
|
-
version = "0.2.
|
|
2281
|
+
version = "0.2.2"
|
|
2282
2282
|
dependencies = [
|
|
2283
2283
|
"mimalloc",
|
|
2284
2284
|
"turso_ext",
|
|
@@ -2286,7 +2286,7 @@ dependencies = [
|
|
|
2286
2286
|
|
|
2287
2287
|
[[package]]
|
|
2288
2288
|
name = "limbo_crypto"
|
|
2289
|
-
version = "0.2.
|
|
2289
|
+
version = "0.2.2"
|
|
2290
2290
|
dependencies = [
|
|
2291
2291
|
"blake3",
|
|
2292
2292
|
"data-encoding",
|
|
@@ -2299,7 +2299,7 @@ dependencies = [
|
|
|
2299
2299
|
|
|
2300
2300
|
[[package]]
|
|
2301
2301
|
name = "limbo_csv"
|
|
2302
|
-
version = "0.2.
|
|
2302
|
+
version = "0.2.2"
|
|
2303
2303
|
dependencies = [
|
|
2304
2304
|
"csv",
|
|
2305
2305
|
"mimalloc",
|
|
@@ -2309,7 +2309,7 @@ dependencies = [
|
|
|
2309
2309
|
|
|
2310
2310
|
[[package]]
|
|
2311
2311
|
name = "limbo_fuzzy"
|
|
2312
|
-
version = "0.2.
|
|
2312
|
+
version = "0.2.2"
|
|
2313
2313
|
dependencies = [
|
|
2314
2314
|
"mimalloc",
|
|
2315
2315
|
"turso_ext",
|
|
@@ -2317,7 +2317,7 @@ dependencies = [
|
|
|
2317
2317
|
|
|
2318
2318
|
[[package]]
|
|
2319
2319
|
name = "limbo_ipaddr"
|
|
2320
|
-
version = "0.2.
|
|
2320
|
+
version = "0.2.2"
|
|
2321
2321
|
dependencies = [
|
|
2322
2322
|
"ipnetwork",
|
|
2323
2323
|
"mimalloc",
|
|
@@ -2326,7 +2326,7 @@ dependencies = [
|
|
|
2326
2326
|
|
|
2327
2327
|
[[package]]
|
|
2328
2328
|
name = "limbo_percentile"
|
|
2329
|
-
version = "0.2.
|
|
2329
|
+
version = "0.2.2"
|
|
2330
2330
|
dependencies = [
|
|
2331
2331
|
"mimalloc",
|
|
2332
2332
|
"turso_ext",
|
|
@@ -2334,7 +2334,7 @@ dependencies = [
|
|
|
2334
2334
|
|
|
2335
2335
|
[[package]]
|
|
2336
2336
|
name = "limbo_regexp"
|
|
2337
|
-
version = "0.2.
|
|
2337
|
+
version = "0.2.2"
|
|
2338
2338
|
dependencies = [
|
|
2339
2339
|
"mimalloc",
|
|
2340
2340
|
"regex",
|
|
@@ -2343,7 +2343,7 @@ dependencies = [
|
|
|
2343
2343
|
|
|
2344
2344
|
[[package]]
|
|
2345
2345
|
name = "limbo_sim"
|
|
2346
|
-
version = "0.2.
|
|
2346
|
+
version = "0.2.2"
|
|
2347
2347
|
dependencies = [
|
|
2348
2348
|
"anyhow",
|
|
2349
2349
|
"bitmaps",
|
|
@@ -2380,7 +2380,7 @@ dependencies = [
|
|
|
2380
2380
|
|
|
2381
2381
|
[[package]]
|
|
2382
2382
|
name = "limbo_sqlite_test_ext"
|
|
2383
|
-
version = "0.2.
|
|
2383
|
+
version = "0.2.2"
|
|
2384
2384
|
dependencies = [
|
|
2385
2385
|
"cc",
|
|
2386
2386
|
]
|
|
@@ -3116,7 +3116,7 @@ dependencies = [
|
|
|
3116
3116
|
|
|
3117
3117
|
[[package]]
|
|
3118
3118
|
name = "py-turso"
|
|
3119
|
-
version = "0.2.
|
|
3119
|
+
version = "0.2.2"
|
|
3120
3120
|
dependencies = [
|
|
3121
3121
|
"anyhow",
|
|
3122
3122
|
"pyo3",
|
|
@@ -3843,7 +3843,7 @@ checksum = "d372029cb5195f9ab4e4b9aef550787dce78b124fcaee8d82519925defcd6f0d"
|
|
|
3843
3843
|
|
|
3844
3844
|
[[package]]
|
|
3845
3845
|
name = "sql_generation"
|
|
3846
|
-
version = "0.2.
|
|
3846
|
+
version = "0.2.2"
|
|
3847
3847
|
dependencies = [
|
|
3848
3848
|
"anarchist-readable-name-generator-lib 0.2.0",
|
|
3849
3849
|
"anyhow",
|
|
@@ -4357,7 +4357,7 @@ dependencies = [
|
|
|
4357
4357
|
|
|
4358
4358
|
[[package]]
|
|
4359
4359
|
name = "turso"
|
|
4360
|
-
version = "0.2.
|
|
4360
|
+
version = "0.2.2"
|
|
4361
4361
|
dependencies = [
|
|
4362
4362
|
"rand 0.9.2",
|
|
4363
4363
|
"rand_chacha 0.9.0",
|
|
@@ -4369,7 +4369,7 @@ dependencies = [
|
|
|
4369
4369
|
|
|
4370
4370
|
[[package]]
|
|
4371
4371
|
name = "turso-java"
|
|
4372
|
-
version = "0.2.
|
|
4372
|
+
version = "0.2.2"
|
|
4373
4373
|
dependencies = [
|
|
4374
4374
|
"jni",
|
|
4375
4375
|
"thiserror 2.0.16",
|
|
@@ -4378,7 +4378,7 @@ dependencies = [
|
|
|
4378
4378
|
|
|
4379
4379
|
[[package]]
|
|
4380
4380
|
name = "turso_cli"
|
|
4381
|
-
version = "0.2.
|
|
4381
|
+
version = "0.2.2"
|
|
4382
4382
|
dependencies = [
|
|
4383
4383
|
"anyhow",
|
|
4384
4384
|
"cfg-if",
|
|
@@ -4414,7 +4414,7 @@ dependencies = [
|
|
|
4414
4414
|
|
|
4415
4415
|
[[package]]
|
|
4416
4416
|
name = "turso_core"
|
|
4417
|
-
version = "0.2.
|
|
4417
|
+
version = "0.2.2"
|
|
4418
4418
|
dependencies = [
|
|
4419
4419
|
"aegis",
|
|
4420
4420
|
"aes",
|
|
@@ -4473,7 +4473,7 @@ dependencies = [
|
|
|
4473
4473
|
|
|
4474
4474
|
[[package]]
|
|
4475
4475
|
name = "turso_dart"
|
|
4476
|
-
version = "0.2.
|
|
4476
|
+
version = "0.2.2"
|
|
4477
4477
|
dependencies = [
|
|
4478
4478
|
"flutter_rust_bridge",
|
|
4479
4479
|
"turso_core",
|
|
@@ -4481,7 +4481,7 @@ dependencies = [
|
|
|
4481
4481
|
|
|
4482
4482
|
[[package]]
|
|
4483
4483
|
name = "turso_ext"
|
|
4484
|
-
version = "0.2.
|
|
4484
|
+
version = "0.2.2"
|
|
4485
4485
|
dependencies = [
|
|
4486
4486
|
"chrono",
|
|
4487
4487
|
"getrandom 0.3.2",
|
|
@@ -4490,7 +4490,7 @@ dependencies = [
|
|
|
4490
4490
|
|
|
4491
4491
|
[[package]]
|
|
4492
4492
|
name = "turso_ext_tests"
|
|
4493
|
-
version = "0.2.
|
|
4493
|
+
version = "0.2.2"
|
|
4494
4494
|
dependencies = [
|
|
4495
4495
|
"env_logger 0.11.7",
|
|
4496
4496
|
"lazy_static",
|
|
@@ -4501,7 +4501,7 @@ dependencies = [
|
|
|
4501
4501
|
|
|
4502
4502
|
[[package]]
|
|
4503
4503
|
name = "turso_macros"
|
|
4504
|
-
version = "0.2.
|
|
4504
|
+
version = "0.2.2"
|
|
4505
4505
|
dependencies = [
|
|
4506
4506
|
"proc-macro2",
|
|
4507
4507
|
"quote",
|
|
@@ -4510,7 +4510,7 @@ dependencies = [
|
|
|
4510
4510
|
|
|
4511
4511
|
[[package]]
|
|
4512
4512
|
name = "turso_node"
|
|
4513
|
-
version = "0.2.
|
|
4513
|
+
version = "0.2.2"
|
|
4514
4514
|
dependencies = [
|
|
4515
4515
|
"chrono",
|
|
4516
4516
|
"napi",
|
|
@@ -4523,7 +4523,7 @@ dependencies = [
|
|
|
4523
4523
|
|
|
4524
4524
|
[[package]]
|
|
4525
4525
|
name = "turso_parser"
|
|
4526
|
-
version = "0.2.
|
|
4526
|
+
version = "0.2.2"
|
|
4527
4527
|
dependencies = [
|
|
4528
4528
|
"bitflags 2.9.4",
|
|
4529
4529
|
"criterion",
|
|
@@ -4539,7 +4539,7 @@ dependencies = [
|
|
|
4539
4539
|
|
|
4540
4540
|
[[package]]
|
|
4541
4541
|
name = "turso_sqlite3"
|
|
4542
|
-
version = "0.2.
|
|
4542
|
+
version = "0.2.2"
|
|
4543
4543
|
dependencies = [
|
|
4544
4544
|
"env_logger 0.11.7",
|
|
4545
4545
|
"libc",
|
|
@@ -4552,7 +4552,7 @@ dependencies = [
|
|
|
4552
4552
|
|
|
4553
4553
|
[[package]]
|
|
4554
4554
|
name = "turso_stress"
|
|
4555
|
-
version = "0.2.
|
|
4555
|
+
version = "0.2.2"
|
|
4556
4556
|
dependencies = [
|
|
4557
4557
|
"anarchist-readable-name-generator-lib 0.1.2",
|
|
4558
4558
|
"antithesis_sdk",
|
|
@@ -4568,7 +4568,7 @@ dependencies = [
|
|
|
4568
4568
|
|
|
4569
4569
|
[[package]]
|
|
4570
4570
|
name = "turso_sync_engine"
|
|
4571
|
-
version = "0.2.
|
|
4571
|
+
version = "0.2.2"
|
|
4572
4572
|
dependencies = [
|
|
4573
4573
|
"base64",
|
|
4574
4574
|
"bytes",
|
|
@@ -4595,7 +4595,7 @@ dependencies = [
|
|
|
4595
4595
|
|
|
4596
4596
|
[[package]]
|
|
4597
4597
|
name = "turso_sync_js"
|
|
4598
|
-
version = "0.2.
|
|
4598
|
+
version = "0.2.2"
|
|
4599
4599
|
dependencies = [
|
|
4600
4600
|
"genawaiter",
|
|
4601
4601
|
"napi",
|
|
@@ -4610,7 +4610,7 @@ dependencies = [
|
|
|
4610
4610
|
|
|
4611
4611
|
[[package]]
|
|
4612
4612
|
name = "turso_whopper"
|
|
4613
|
-
version = "0.2.
|
|
4613
|
+
version = "0.2.2"
|
|
4614
4614
|
dependencies = [
|
|
4615
4615
|
"anyhow",
|
|
4616
4616
|
"clap",
|
|
@@ -8,29 +8,29 @@ exclude = [
|
|
|
8
8
|
]
|
|
9
9
|
|
|
10
10
|
[workspace.package]
|
|
11
|
-
version = "0.2.
|
|
11
|
+
version = "0.2.2"
|
|
12
12
|
authors = ["the Limbo authors"]
|
|
13
13
|
edition = "2021"
|
|
14
14
|
license = "MIT"
|
|
15
15
|
repository = "https://github.com/tursodatabase/turso"
|
|
16
16
|
|
|
17
17
|
[workspace.dependencies]
|
|
18
|
-
turso = { path = "bindings/rust", version = "0.2.
|
|
19
|
-
turso_node = { path = "bindings/javascript", version = "0.2.
|
|
20
|
-
limbo_completion = { path = "extensions/completion", version = "0.2.
|
|
21
|
-
turso_core = { path = "core", version = "0.2.
|
|
22
|
-
turso_sync_engine = { path = "sync/engine", version = "0.2.
|
|
23
|
-
limbo_crypto = { path = "extensions/crypto", version = "0.2.
|
|
24
|
-
limbo_csv = { path = "extensions/csv", version = "0.2.
|
|
25
|
-
turso_ext = { path = "extensions/core", version = "0.2.
|
|
26
|
-
turso_ext_tests = { path = "extensions/tests", version = "0.2.
|
|
27
|
-
limbo_ipaddr = { path = "extensions/ipaddr", version = "0.2.
|
|
28
|
-
turso_macros = { path = "macros", version = "0.2.
|
|
29
|
-
limbo_percentile = { path = "extensions/percentile", version = "0.2.
|
|
30
|
-
limbo_regexp = { path = "extensions/regexp", version = "0.2.
|
|
31
|
-
limbo_uuid = { path = "extensions/uuid", version = "0.2.
|
|
32
|
-
turso_parser = { path = "parser", version = "0.2.
|
|
33
|
-
limbo_fuzzy = { path = "extensions/fuzzy", version = "0.2.
|
|
18
|
+
turso = { path = "bindings/rust", version = "0.2.2" }
|
|
19
|
+
turso_node = { path = "bindings/javascript", version = "0.2.2" }
|
|
20
|
+
limbo_completion = { path = "extensions/completion", version = "0.2.2" }
|
|
21
|
+
turso_core = { path = "core", version = "0.2.2" }
|
|
22
|
+
turso_sync_engine = { path = "sync/engine", version = "0.2.2" }
|
|
23
|
+
limbo_crypto = { path = "extensions/crypto", version = "0.2.2" }
|
|
24
|
+
limbo_csv = { path = "extensions/csv", version = "0.2.2" }
|
|
25
|
+
turso_ext = { path = "extensions/core", version = "0.2.2" }
|
|
26
|
+
turso_ext_tests = { path = "extensions/tests", version = "0.2.2" }
|
|
27
|
+
limbo_ipaddr = { path = "extensions/ipaddr", version = "0.2.2" }
|
|
28
|
+
turso_macros = { path = "macros", version = "0.2.2" }
|
|
29
|
+
limbo_percentile = { path = "extensions/percentile", version = "0.2.2" }
|
|
30
|
+
limbo_regexp = { path = "extensions/regexp", version = "0.2.2" }
|
|
31
|
+
limbo_uuid = { path = "extensions/uuid", version = "0.2.2" }
|
|
32
|
+
turso_parser = { path = "parser", version = "0.2.2" }
|
|
33
|
+
limbo_fuzzy = { path = "extensions/fuzzy", version = "0.2.2" }
|
|
34
34
|
sql_generation = { path = "sql_generation" }
|
|
35
35
|
strum = { version = "0.26", features = ["derive"] }
|
|
36
36
|
strum_macros = "0.26"
|
|
@@ -2149,6 +2149,31 @@ impl DbspCompiler {
|
|
|
2149
2149
|
))
|
|
2150
2150
|
}
|
|
2151
2151
|
}
|
|
2152
|
+
LogicalExpr::IsNull { expr, negated } => {
|
|
2153
|
+
// Extract column index from the inner expression
|
|
2154
|
+
if let LogicalExpr::Column(col) = expr.as_ref() {
|
|
2155
|
+
let column_idx = schema
|
|
2156
|
+
.columns
|
|
2157
|
+
.iter()
|
|
2158
|
+
.position(|c| c.name == col.name)
|
|
2159
|
+
.ok_or_else(|| {
|
|
2160
|
+
LimboError::ParseError(format!(
|
|
2161
|
+
"Column '{}' not found in schema for IS NULL filter",
|
|
2162
|
+
col.name
|
|
2163
|
+
))
|
|
2164
|
+
})?;
|
|
2165
|
+
|
|
2166
|
+
if *negated {
|
|
2167
|
+
Ok(FilterPredicate::IsNotNull { column_idx })
|
|
2168
|
+
} else {
|
|
2169
|
+
Ok(FilterPredicate::IsNull { column_idx })
|
|
2170
|
+
}
|
|
2171
|
+
} else {
|
|
2172
|
+
Err(LimboError::ParseError(
|
|
2173
|
+
"IS NULL/IS NOT NULL expects a column reference".to_string(),
|
|
2174
|
+
))
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2152
2177
|
_ => Err(LimboError::ParseError(format!(
|
|
2153
2178
|
"Unsupported filter expression: {expr:?}"
|
|
2154
2179
|
))),
|
|
@@ -39,6 +39,11 @@ pub enum FilterPredicate {
|
|
|
39
39
|
/// Column <= Column comparisons
|
|
40
40
|
ColumnLessThanOrEqual { left_idx: usize, right_idx: usize },
|
|
41
41
|
|
|
42
|
+
/// Column IS NULL check
|
|
43
|
+
IsNull { column_idx: usize },
|
|
44
|
+
/// Column IS NOT NULL check
|
|
45
|
+
IsNotNull { column_idx: usize },
|
|
46
|
+
|
|
42
47
|
/// Logical AND of two predicates
|
|
43
48
|
And(Box<FilterPredicate>, Box<FilterPredicate>),
|
|
44
49
|
/// Logical OR of two predicates
|
|
@@ -214,6 +219,18 @@ impl FilterOperator {
|
|
|
214
219
|
}
|
|
215
220
|
false
|
|
216
221
|
}
|
|
222
|
+
FilterPredicate::IsNull { column_idx } => {
|
|
223
|
+
if let Some(v) = values.get(*column_idx) {
|
|
224
|
+
return matches!(v, Value::Null);
|
|
225
|
+
}
|
|
226
|
+
false
|
|
227
|
+
}
|
|
228
|
+
FilterPredicate::IsNotNull { column_idx } => {
|
|
229
|
+
if let Some(v) = values.get(*column_idx) {
|
|
230
|
+
return !matches!(v, Value::Null);
|
|
231
|
+
}
|
|
232
|
+
false
|
|
233
|
+
}
|
|
217
234
|
}
|
|
218
235
|
}
|
|
219
236
|
}
|
|
@@ -293,3 +310,202 @@ impl IncrementalOperator for FilterOperator {
|
|
|
293
310
|
self.tracker = Some(tracker);
|
|
294
311
|
}
|
|
295
312
|
}
|
|
313
|
+
|
|
314
|
+
#[cfg(test)]
|
|
315
|
+
mod tests {
|
|
316
|
+
use super::*;
|
|
317
|
+
use crate::types::Text;
|
|
318
|
+
|
|
319
|
+
#[test]
|
|
320
|
+
fn test_is_null_predicate() {
|
|
321
|
+
let predicate = FilterPredicate::IsNull { column_idx: 1 };
|
|
322
|
+
let filter = FilterOperator::new(predicate);
|
|
323
|
+
|
|
324
|
+
// Test with NULL value
|
|
325
|
+
let values_with_null = vec![
|
|
326
|
+
Value::Integer(1),
|
|
327
|
+
Value::Null,
|
|
328
|
+
Value::Text(Text::from("test")),
|
|
329
|
+
];
|
|
330
|
+
assert!(filter.evaluate_predicate(&values_with_null));
|
|
331
|
+
|
|
332
|
+
// Test with non-NULL value
|
|
333
|
+
let values_without_null = vec![
|
|
334
|
+
Value::Integer(1),
|
|
335
|
+
Value::Integer(42),
|
|
336
|
+
Value::Text(Text::from("test")),
|
|
337
|
+
];
|
|
338
|
+
assert!(!filter.evaluate_predicate(&values_without_null));
|
|
339
|
+
|
|
340
|
+
// Test with different non-NULL types
|
|
341
|
+
let values_with_text = vec![
|
|
342
|
+
Value::Integer(1),
|
|
343
|
+
Value::Text(Text::from("not null")),
|
|
344
|
+
Value::Text(Text::from("test")),
|
|
345
|
+
];
|
|
346
|
+
assert!(!filter.evaluate_predicate(&values_with_text));
|
|
347
|
+
|
|
348
|
+
let values_with_blob = vec![
|
|
349
|
+
Value::Integer(1),
|
|
350
|
+
Value::Blob(vec![1, 2, 3]),
|
|
351
|
+
Value::Text(Text::from("test")),
|
|
352
|
+
];
|
|
353
|
+
assert!(!filter.evaluate_predicate(&values_with_blob));
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
#[test]
|
|
357
|
+
fn test_is_not_null_predicate() {
|
|
358
|
+
let predicate = FilterPredicate::IsNotNull { column_idx: 1 };
|
|
359
|
+
let filter = FilterOperator::new(predicate);
|
|
360
|
+
|
|
361
|
+
// Test with NULL value
|
|
362
|
+
let values_with_null = vec![
|
|
363
|
+
Value::Integer(1),
|
|
364
|
+
Value::Null,
|
|
365
|
+
Value::Text(Text::from("test")),
|
|
366
|
+
];
|
|
367
|
+
assert!(!filter.evaluate_predicate(&values_with_null));
|
|
368
|
+
|
|
369
|
+
// Test with non-NULL value (Integer)
|
|
370
|
+
let values_with_integer = vec![
|
|
371
|
+
Value::Integer(1),
|
|
372
|
+
Value::Integer(42),
|
|
373
|
+
Value::Text(Text::from("test")),
|
|
374
|
+
];
|
|
375
|
+
assert!(filter.evaluate_predicate(&values_with_integer));
|
|
376
|
+
|
|
377
|
+
// Test with non-NULL value (Text)
|
|
378
|
+
let values_with_text = vec![
|
|
379
|
+
Value::Integer(1),
|
|
380
|
+
Value::Text(Text::from("not null")),
|
|
381
|
+
Value::Text(Text::from("test")),
|
|
382
|
+
];
|
|
383
|
+
assert!(filter.evaluate_predicate(&values_with_text));
|
|
384
|
+
|
|
385
|
+
// Test with non-NULL value (Blob)
|
|
386
|
+
let values_with_blob = vec![
|
|
387
|
+
Value::Integer(1),
|
|
388
|
+
Value::Blob(vec![1, 2, 3]),
|
|
389
|
+
Value::Text(Text::from("test")),
|
|
390
|
+
];
|
|
391
|
+
assert!(filter.evaluate_predicate(&values_with_blob));
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
#[test]
|
|
395
|
+
fn test_is_null_with_and() {
|
|
396
|
+
// Test: column_0 = 1 AND column_1 IS NULL
|
|
397
|
+
let predicate = FilterPredicate::And(
|
|
398
|
+
Box::new(FilterPredicate::Equals {
|
|
399
|
+
column_idx: 0,
|
|
400
|
+
value: Value::Integer(1),
|
|
401
|
+
}),
|
|
402
|
+
Box::new(FilterPredicate::IsNull { column_idx: 1 }),
|
|
403
|
+
);
|
|
404
|
+
let filter = FilterOperator::new(predicate);
|
|
405
|
+
|
|
406
|
+
// Should match: column_0 = 1 AND column_1 IS NULL
|
|
407
|
+
let values_match = vec![
|
|
408
|
+
Value::Integer(1),
|
|
409
|
+
Value::Null,
|
|
410
|
+
Value::Text(Text::from("test")),
|
|
411
|
+
];
|
|
412
|
+
assert!(filter.evaluate_predicate(&values_match));
|
|
413
|
+
|
|
414
|
+
// Should not match: column_0 = 2 AND column_1 IS NULL
|
|
415
|
+
let values_wrong_first = vec![
|
|
416
|
+
Value::Integer(2),
|
|
417
|
+
Value::Null,
|
|
418
|
+
Value::Text(Text::from("test")),
|
|
419
|
+
];
|
|
420
|
+
assert!(!filter.evaluate_predicate(&values_wrong_first));
|
|
421
|
+
|
|
422
|
+
// Should not match: column_0 = 1 AND column_1 IS NOT NULL
|
|
423
|
+
let values_not_null = vec![
|
|
424
|
+
Value::Integer(1),
|
|
425
|
+
Value::Integer(42),
|
|
426
|
+
Value::Text(Text::from("test")),
|
|
427
|
+
];
|
|
428
|
+
assert!(!filter.evaluate_predicate(&values_not_null));
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
#[test]
|
|
432
|
+
fn test_is_not_null_with_or() {
|
|
433
|
+
// Test: column_0 = 1 OR column_1 IS NOT NULL
|
|
434
|
+
let predicate = FilterPredicate::Or(
|
|
435
|
+
Box::new(FilterPredicate::Equals {
|
|
436
|
+
column_idx: 0,
|
|
437
|
+
value: Value::Integer(1),
|
|
438
|
+
}),
|
|
439
|
+
Box::new(FilterPredicate::IsNotNull { column_idx: 1 }),
|
|
440
|
+
);
|
|
441
|
+
let filter = FilterOperator::new(predicate);
|
|
442
|
+
|
|
443
|
+
// Should match: column_0 = 1 (regardless of column_1)
|
|
444
|
+
let values_first_matches = vec![
|
|
445
|
+
Value::Integer(1),
|
|
446
|
+
Value::Null,
|
|
447
|
+
Value::Text(Text::from("test")),
|
|
448
|
+
];
|
|
449
|
+
assert!(filter.evaluate_predicate(&values_first_matches));
|
|
450
|
+
|
|
451
|
+
// Should match: column_1 IS NOT NULL (regardless of column_0)
|
|
452
|
+
let values_second_matches = vec![
|
|
453
|
+
Value::Integer(2),
|
|
454
|
+
Value::Integer(42),
|
|
455
|
+
Value::Text(Text::from("test")),
|
|
456
|
+
];
|
|
457
|
+
assert!(filter.evaluate_predicate(&values_second_matches));
|
|
458
|
+
|
|
459
|
+
// Should not match: column_0 != 1 AND column_1 IS NULL
|
|
460
|
+
let values_no_match = vec![
|
|
461
|
+
Value::Integer(2),
|
|
462
|
+
Value::Null,
|
|
463
|
+
Value::Text(Text::from("test")),
|
|
464
|
+
];
|
|
465
|
+
assert!(!filter.evaluate_predicate(&values_no_match));
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
#[test]
|
|
469
|
+
fn test_complex_null_predicates() {
|
|
470
|
+
// Test: (column_0 IS NULL OR column_1 IS NOT NULL) AND column_2 = 'test'
|
|
471
|
+
let predicate = FilterPredicate::And(
|
|
472
|
+
Box::new(FilterPredicate::Or(
|
|
473
|
+
Box::new(FilterPredicate::IsNull { column_idx: 0 }),
|
|
474
|
+
Box::new(FilterPredicate::IsNotNull { column_idx: 1 }),
|
|
475
|
+
)),
|
|
476
|
+
Box::new(FilterPredicate::Equals {
|
|
477
|
+
column_idx: 2,
|
|
478
|
+
value: Value::Text(Text::from("test")),
|
|
479
|
+
}),
|
|
480
|
+
);
|
|
481
|
+
let filter = FilterOperator::new(predicate);
|
|
482
|
+
|
|
483
|
+
// Should match: column_0 IS NULL, column_2 = 'test'
|
|
484
|
+
let values1 = vec![Value::Null, Value::Null, Value::Text(Text::from("test"))];
|
|
485
|
+
assert!(filter.evaluate_predicate(&values1));
|
|
486
|
+
|
|
487
|
+
// Should match: column_1 IS NOT NULL, column_2 = 'test'
|
|
488
|
+
let values2 = vec![
|
|
489
|
+
Value::Integer(1),
|
|
490
|
+
Value::Integer(42),
|
|
491
|
+
Value::Text(Text::from("test")),
|
|
492
|
+
];
|
|
493
|
+
assert!(filter.evaluate_predicate(&values2));
|
|
494
|
+
|
|
495
|
+
// Should not match: column_2 != 'test'
|
|
496
|
+
let values3 = vec![
|
|
497
|
+
Value::Null,
|
|
498
|
+
Value::Integer(42),
|
|
499
|
+
Value::Text(Text::from("other")),
|
|
500
|
+
];
|
|
501
|
+
assert!(!filter.evaluate_predicate(&values3));
|
|
502
|
+
|
|
503
|
+
// Should not match: column_0 IS NOT NULL AND column_1 IS NULL AND column_2 = 'test'
|
|
504
|
+
let values4 = vec![
|
|
505
|
+
Value::Integer(1),
|
|
506
|
+
Value::Null,
|
|
507
|
+
Value::Text(Text::from("test")),
|
|
508
|
+
];
|
|
509
|
+
assert!(!filter.evaluate_predicate(&values4));
|
|
510
|
+
}
|
|
511
|
+
}
|
|
@@ -50,8 +50,9 @@ fn try_pwritev_raw(
|
|
|
50
50
|
let mut iov_count = 0;
|
|
51
51
|
for (i, b) in bufs.iter().enumerate().skip(start_idx).take(iov_len) {
|
|
52
52
|
let s = b.as_slice();
|
|
53
|
-
let
|
|
54
|
-
let
|
|
53
|
+
let slice = if i == start_idx { &s[start_off..] } else { s };
|
|
54
|
+
let ptr = slice.as_ptr();
|
|
55
|
+
let len = slice.len();
|
|
55
56
|
|
|
56
57
|
if let Some((last_ptr, last_len)) = last_end {
|
|
57
58
|
// Check if this buffer is adjacent to the last
|
|
@@ -62,6 +62,7 @@ pub use io::{
|
|
|
62
62
|
};
|
|
63
63
|
use parking_lot::RwLock;
|
|
64
64
|
use schema::Schema;
|
|
65
|
+
use std::cell::Cell;
|
|
65
66
|
use std::{
|
|
66
67
|
borrow::Cow,
|
|
67
68
|
cell::RefCell,
|
|
@@ -217,7 +218,7 @@ pub struct Database {
|
|
|
217
218
|
shared_wal: Arc<RwLock<WalFileShared>>,
|
|
218
219
|
db_state: Arc<AtomicDbState>,
|
|
219
220
|
init_lock: Arc<Mutex<()>>,
|
|
220
|
-
open_flags: OpenFlags
|
|
221
|
+
open_flags: Cell<OpenFlags>,
|
|
221
222
|
builtin_syms: RwLock<SymbolTable>,
|
|
222
223
|
opts: DatabaseOpts,
|
|
223
224
|
n_connections: AtomicUsize,
|
|
@@ -231,7 +232,7 @@ impl fmt::Debug for Database {
|
|
|
231
232
|
let mut debug_struct = f.debug_struct("Database");
|
|
232
233
|
debug_struct
|
|
233
234
|
.field("path", &self.path)
|
|
234
|
-
.field("open_flags", &self.open_flags);
|
|
235
|
+
.field("open_flags", &self.open_flags.get());
|
|
235
236
|
|
|
236
237
|
// Database state information
|
|
237
238
|
let db_state_value = match self.db_state.get() {
|
|
@@ -407,6 +408,31 @@ impl Database {
|
|
|
407
408
|
opts: DatabaseOpts,
|
|
408
409
|
encryption_opts: Option<EncryptionOpts>,
|
|
409
410
|
) -> Result<Arc<Database>> {
|
|
411
|
+
// Currently, if a non-zero-sized WAL file exists, the database cannot be opened in MVCC mode.
|
|
412
|
+
// FIXME: this should initiate immediate checkpoint from WAL->DB in MVCC mode.
|
|
413
|
+
if opts.enable_mvcc
|
|
414
|
+
&& std::path::Path::exists(std::path::Path::new(wal_path))
|
|
415
|
+
&& std::path::Path::new(wal_path).metadata().unwrap().len() > 0
|
|
416
|
+
{
|
|
417
|
+
return Err(LimboError::InvalidArgument(format!(
|
|
418
|
+
"WAL file exists for database {path}, but MVCC is enabled. This is currently not supported. Open the database in non-MVCC mode and run PRAGMA wal_checkpoint(TRUNCATE) to truncate the WAL."
|
|
419
|
+
)));
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// If a non-zero-sized logical log file exists, the database cannot be opened in non-MVCC mode,
|
|
423
|
+
// because the changes in the logical log would not be visible to the non-MVCC connections.
|
|
424
|
+
if !opts.enable_mvcc {
|
|
425
|
+
let db_path = std::path::Path::new(path);
|
|
426
|
+
let log_path = db_path.with_extension("db-log");
|
|
427
|
+
if std::path::Path::exists(log_path.as_path())
|
|
428
|
+
&& log_path.as_path().metadata().unwrap().len() > 0
|
|
429
|
+
{
|
|
430
|
+
return Err(LimboError::InvalidArgument(format!(
|
|
431
|
+
"MVCC logical log file exists for database {path}, but MVCC is disabled. This is not supported. Open the database in MVCC mode and run PRAGMA wal_checkpoint(TRUNCATE) to truncate the logical log.",
|
|
432
|
+
)));
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
410
436
|
let shared_wal = WalFileShared::open_shared_if_exists(&io, wal_path)?;
|
|
411
437
|
|
|
412
438
|
let mv_store = if opts.enable_mvcc {
|
|
@@ -443,7 +469,7 @@ impl Database {
|
|
|
443
469
|
db_file,
|
|
444
470
|
builtin_syms: syms.into(),
|
|
445
471
|
io: io.clone(),
|
|
446
|
-
open_flags: flags,
|
|
472
|
+
open_flags: flags.into(),
|
|
447
473
|
db_state: Arc::new(AtomicDbState::new(db_state)),
|
|
448
474
|
init_lock: Arc::new(Mutex::new(())),
|
|
449
475
|
opts,
|
|
@@ -574,7 +600,7 @@ impl Database {
|
|
|
574
600
|
}
|
|
575
601
|
|
|
576
602
|
pub fn is_readonly(&self) -> bool {
|
|
577
|
-
self.open_flags.contains(OpenFlags::ReadOnly)
|
|
603
|
+
self.open_flags.get().contains(OpenFlags::ReadOnly)
|
|
578
604
|
}
|
|
579
605
|
|
|
580
606
|
/// If we do not have a physical WAL file, but we know the database file is initialized on disk,
|
|
@@ -1502,9 +1528,7 @@ impl Connection {
|
|
|
1502
1528
|
db_opts: DatabaseOpts,
|
|
1503
1529
|
io: Arc<dyn IO>,
|
|
1504
1530
|
) -> Result<Arc<Database>> {
|
|
1505
|
-
let
|
|
1506
|
-
// FIXME: for now, only support read only attach
|
|
1507
|
-
opts.mode = OpenMode::ReadOnly;
|
|
1531
|
+
let opts = OpenOptions::parse(uri)?;
|
|
1508
1532
|
let flags = opts.get_flags()?;
|
|
1509
1533
|
let io = opts.vfs.map(Database::io_for_vfs).unwrap_or(Ok(io))?;
|
|
1510
1534
|
let db = Database::open_file_with_flags(io.clone(), &opts.path, flags, db_opts, None)?;
|
|
@@ -2065,9 +2089,15 @@ impl Connection {
|
|
|
2065
2089
|
.with_indexes(use_indexes)
|
|
2066
2090
|
.with_views(use_views)
|
|
2067
2091
|
.with_strict(use_strict);
|
|
2068
|
-
let
|
|
2092
|
+
let io: Arc<dyn IO> = if path.contains(":memory:") {
|
|
2093
|
+
Arc::new(MemoryIO::new())
|
|
2094
|
+
} else {
|
|
2095
|
+
Arc::new(PlatformIO::new()?)
|
|
2096
|
+
};
|
|
2097
|
+
let db = Self::from_uri_attached(path, db_opts, io)?;
|
|
2069
2098
|
let pager = Arc::new(db.init_pager(None)?);
|
|
2070
|
-
|
|
2099
|
+
// FIXME: for now, only support read only attach
|
|
2100
|
+
db.open_flags.set(OpenFlags::ReadOnly);
|
|
2071
2101
|
self.attached_databases.write().insert(alias, (db, pager));
|
|
2072
2102
|
|
|
2073
2103
|
Ok(())
|