lora-python 0.4.0__tar.gz → 0.5.0__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 (119) hide show
  1. {lora_python-0.4.0 → lora_python-0.5.0}/Cargo.lock +65 -14
  2. {lora_python-0.4.0 → lora_python-0.5.0}/Cargo.toml +10 -9
  3. {lora_python-0.4.0 → lora_python-0.5.0}/PKG-INFO +22 -1
  4. {lora_python-0.4.0 → lora_python-0.5.0}/README.md +21 -0
  5. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-compiler/src/logical.rs +11 -0
  6. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-compiler/src/optimizer.rs +94 -0
  7. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-compiler/src/physical.rs +11 -0
  8. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/Cargo.toml +1 -0
  9. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/benches/perf_smoke_baseline.json +28 -6
  10. lora_python-0.5.0/crates/lora-database/benches/perf_smoke_benchmarks.rs +274 -0
  11. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/benches/wal_benchmarks.rs +160 -2
  12. lora_python-0.5.0/crates/lora-database/src/archive.rs +314 -0
  13. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/src/database.rs +358 -59
  14. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/src/lib.rs +11 -1
  15. lora_python-0.5.0/crates/lora-database/src/named.rs +124 -0
  16. lora_python-0.5.0/crates/lora-database/src/stream.rs +490 -0
  17. lora_python-0.5.0/crates/lora-database/src/transaction.rs +844 -0
  18. lora_python-0.5.0/crates/lora-database/tests/transactions.rs +1885 -0
  19. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/wal.rs +100 -2
  20. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-executor/src/errors.rs +3 -0
  21. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-executor/src/executor.rs +671 -51
  22. lora_python-0.5.0/crates/lora-executor/src/lib.rs +13 -0
  23. lora_python-0.5.0/crates/lora-executor/src/pull.rs +2500 -0
  24. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-python/Cargo.toml +6 -0
  25. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-python/README.md +21 -0
  26. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-python/build.rs +6 -2
  27. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-python/src/lib.rs +379 -44
  28. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-python/tests/test_async.py +51 -5
  29. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-python/tests/test_sync.py +90 -12
  30. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-store/src/graph.rs +65 -0
  31. lora_python-0.5.0/crates/lora-store/src/memory.rs +2737 -0
  32. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-store/src/mutation.rs +2 -2
  33. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-wal/src/config.rs +5 -5
  34. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-wal/src/error.rs +1 -1
  35. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-wal/src/lib.rs +1 -1
  36. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-wal/src/record.rs +38 -6
  37. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-wal/src/recorder_adapter.rs +92 -60
  38. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-wal/src/replay.rs +18 -4
  39. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-wal/src/segment.rs +1 -1
  40. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-wal/src/wal.rs +37 -7
  41. {lora_python-0.4.0 → lora_python-0.5.0}/pyproject.toml +1 -1
  42. {lora_python-0.4.0 → lora_python-0.5.0}/python/lora_python/_async.py +61 -23
  43. lora_python-0.5.0/python/lora_python/_native.pyi +84 -0
  44. lora_python-0.4.0/crates/lora-database/benches/perf_smoke_benchmarks.rs +0 -122
  45. lora_python-0.4.0/crates/lora-executor/src/lib.rs +0 -7
  46. lora_python-0.4.0/crates/lora-store/src/memory.rs +0 -1400
  47. lora_python-0.4.0/python/lora_python/_native.pyi +0 -42
  48. {lora_python-0.4.0 → lora_python-0.5.0}/LICENSE +0 -0
  49. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-analyzer/Cargo.toml +0 -0
  50. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-analyzer/src/analyzer.rs +0 -0
  51. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-analyzer/src/errors.rs +0 -0
  52. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-analyzer/src/lib.rs +0 -0
  53. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-analyzer/src/resolved.rs +0 -0
  54. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-analyzer/src/scope.rs +0 -0
  55. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-analyzer/src/symbols.rs +0 -0
  56. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-ast/Cargo.toml +0 -0
  57. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-ast/src/ast.rs +0 -0
  58. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-ast/src/lib.rs +0 -0
  59. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-compiler/Cargo.toml +0 -0
  60. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-compiler/src/lib.rs +0 -0
  61. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-compiler/src/pattern.rs +0 -0
  62. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-compiler/src/planner.rs +0 -0
  63. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/benches/advanced_benchmarks.rs +0 -0
  64. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/benches/engine_benchmarks.rs +0 -0
  65. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/benches/fixtures.rs +0 -0
  66. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/benches/scale_benchmarks.rs +0 -0
  67. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/benches/temporal_spatial_benchmarks.rs +0 -0
  68. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/advanced_queries.rs +0 -0
  69. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/aggregation.rs +0 -0
  70. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/backend_stub.rs +0 -0
  71. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/create.rs +0 -0
  72. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/errors.rs +0 -0
  73. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/expressions.rs +0 -0
  74. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/functions_extended.rs +0 -0
  75. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/invariants.rs +0 -0
  76. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/match.rs +0 -0
  77. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/merge.rs +0 -0
  78. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/ordering.rs +0 -0
  79. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/parameters.rs +0 -0
  80. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/parser.rs +0 -0
  81. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/paths.rs +0 -0
  82. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/projection.rs +0 -0
  83. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/seeds.rs +0 -0
  84. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/snapshot.rs +0 -0
  85. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/spatial.rs +0 -0
  86. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/temporal.rs +0 -0
  87. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/test_helpers.rs +0 -0
  88. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/types_advanced.rs +0 -0
  89. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/union.rs +0 -0
  90. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/update.rs +0 -0
  91. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/vectors.rs +0 -0
  92. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/where_clause.rs +0 -0
  93. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-database/tests/with.rs +0 -0
  94. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-executor/Cargo.toml +0 -0
  95. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-executor/src/eval.rs +0 -0
  96. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-executor/src/value.rs +0 -0
  97. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-parser/Cargo.toml +0 -0
  98. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-parser/src/cypher.pest +0 -0
  99. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-parser/src/error.rs +0 -0
  100. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-parser/src/lib.rs +0 -0
  101. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-parser/src/parser.rs +0 -0
  102. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-python/.gitignore +0 -0
  103. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-python/LICENSE +0 -0
  104. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-python/examples/async_demo.py +0 -0
  105. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-python/examples/basic.py +0 -0
  106. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-store/Cargo.toml +0 -0
  107. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-store/src/lib.rs +0 -0
  108. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-store/src/snapshot.rs +0 -0
  109. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-store/src/spatial.rs +0 -0
  110. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-store/src/temporal.rs +0 -0
  111. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-store/src/vector.rs +0 -0
  112. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-wal/Cargo.toml +0 -0
  113. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-wal/src/dir.rs +0 -0
  114. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-wal/src/lock.rs +0 -0
  115. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-wal/src/lsn.rs +0 -0
  116. {lora_python-0.4.0 → lora_python-0.5.0}/crates/lora-wal/src/testing.rs +0 -0
  117. {lora_python-0.4.0 → lora_python-0.5.0}/python/lora_python/__init__.py +0 -0
  118. {lora_python-0.4.0 → lora_python-0.5.0}/python/lora_python/py.typed +0 -0
  119. {lora_python-0.4.0 → lora_python-0.5.0}/python/lora_python/types.py +0 -0
@@ -2,6 +2,12 @@
2
2
  # It is not intended for manual editing.
3
3
  version = 4
4
4
 
5
+ [[package]]
6
+ name = "adler2"
7
+ version = "2.0.1"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
10
+
5
11
  [[package]]
6
12
  name = "aho-corasick"
7
13
  version = "1.1.4"
@@ -164,6 +170,12 @@ version = "3.20.2"
164
170
  source = "registry+https://github.com/rust-lang/crates.io-index"
165
171
  checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
166
172
 
173
+ [[package]]
174
+ name = "byteorder"
175
+ version = "1.5.0"
176
+ source = "registry+https://github.com/rust-lang/crates.io-index"
177
+ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
178
+
167
179
  [[package]]
168
180
  name = "bytes"
169
181
  version = "1.11.1"
@@ -409,6 +421,16 @@ version = "0.1.9"
409
421
  source = "registry+https://github.com/rust-lang/crates.io-index"
410
422
  checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
411
423
 
424
+ [[package]]
425
+ name = "flate2"
426
+ version = "1.1.9"
427
+ source = "registry+https://github.com/rust-lang/crates.io-index"
428
+ checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
429
+ dependencies = [
430
+ "crc32fast",
431
+ "miniz_oxide",
432
+ ]
433
+
412
434
  [[package]]
413
435
  name = "form_urlencoded"
414
436
  version = "1.2.2"
@@ -629,7 +651,7 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
629
651
 
630
652
  [[package]]
631
653
  name = "lora-analyzer"
632
- version = "0.4.0"
654
+ version = "0.5.0"
633
655
  dependencies = [
634
656
  "lora-ast",
635
657
  "lora-parser",
@@ -639,14 +661,14 @@ dependencies = [
639
661
 
640
662
  [[package]]
641
663
  name = "lora-ast"
642
- version = "0.4.0"
664
+ version = "0.5.0"
643
665
  dependencies = [
644
666
  "smallvec 2.0.0-alpha.12",
645
667
  ]
646
668
 
647
669
  [[package]]
648
670
  name = "lora-compiler"
649
- version = "0.4.0"
671
+ version = "0.5.0"
650
672
  dependencies = [
651
673
  "lora-analyzer",
652
674
  "lora-ast",
@@ -654,7 +676,7 @@ dependencies = [
654
676
 
655
677
  [[package]]
656
678
  name = "lora-database"
657
- version = "0.4.0"
679
+ version = "0.5.0"
658
680
  dependencies = [
659
681
  "anyhow",
660
682
  "criterion",
@@ -667,11 +689,12 @@ dependencies = [
667
689
  "lora-wal",
668
690
  "serde_json",
669
691
  "tower",
692
+ "zip",
670
693
  ]
671
694
 
672
695
  [[package]]
673
696
  name = "lora-executor"
674
- version = "0.4.0"
697
+ version = "0.5.0"
675
698
  dependencies = [
676
699
  "lora-analyzer",
677
700
  "lora-ast",
@@ -685,7 +708,7 @@ dependencies = [
685
708
 
686
709
  [[package]]
687
710
  name = "lora-ffi"
688
- version = "0.4.0"
711
+ version = "0.5.0"
689
712
  dependencies = [
690
713
  "lora-database",
691
714
  "lora-store",
@@ -695,7 +718,7 @@ dependencies = [
695
718
 
696
719
  [[package]]
697
720
  name = "lora-node"
698
- version = "0.4.0"
721
+ version = "0.5.0"
699
722
  dependencies = [
700
723
  "anyhow",
701
724
  "lora-database",
@@ -709,7 +732,7 @@ dependencies = [
709
732
 
710
733
  [[package]]
711
734
  name = "lora-parser"
712
- version = "0.4.0"
735
+ version = "0.5.0"
713
736
  dependencies = [
714
737
  "lora-ast",
715
738
  "pest",
@@ -720,7 +743,7 @@ dependencies = [
720
743
 
721
744
  [[package]]
722
745
  name = "lora-python"
723
- version = "0.4.0"
746
+ version = "0.5.0"
724
747
  dependencies = [
725
748
  "anyhow",
726
749
  "lora-database",
@@ -732,7 +755,7 @@ dependencies = [
732
755
 
733
756
  [[package]]
734
757
  name = "lora-server"
735
- version = "0.4.0"
758
+ version = "0.5.0"
736
759
  dependencies = [
737
760
  "anyhow",
738
761
  "axum",
@@ -746,7 +769,7 @@ dependencies = [
746
769
 
747
770
  [[package]]
748
771
  name = "lora-store"
749
- version = "0.4.0"
772
+ version = "0.5.0"
750
773
  dependencies = [
751
774
  "bincode",
752
775
  "crc32fast",
@@ -758,7 +781,7 @@ dependencies = [
758
781
 
759
782
  [[package]]
760
783
  name = "lora-wal"
761
- version = "0.4.0"
784
+ version = "0.5.0"
762
785
  dependencies = [
763
786
  "bincode",
764
787
  "crc32fast",
@@ -769,7 +792,7 @@ dependencies = [
769
792
 
770
793
  [[package]]
771
794
  name = "lora-wasm"
772
- version = "0.4.0"
795
+ version = "0.5.0"
773
796
  dependencies = [
774
797
  "anyhow",
775
798
  "console_error_panic_hook",
@@ -784,7 +807,7 @@ dependencies = [
784
807
 
785
808
  [[package]]
786
809
  name = "lora_ruby"
787
- version = "0.4.0"
810
+ version = "0.5.0"
788
811
  dependencies = [
789
812
  "anyhow",
790
813
  "lora-database",
@@ -852,6 +875,16 @@ version = "0.2.1"
852
875
  source = "registry+https://github.com/rust-lang/crates.io-index"
853
876
  checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
854
877
 
878
+ [[package]]
879
+ name = "miniz_oxide"
880
+ version = "0.8.9"
881
+ source = "registry+https://github.com/rust-lang/crates.io-index"
882
+ checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
883
+ dependencies = [
884
+ "adler2",
885
+ "simd-adler32",
886
+ ]
887
+
855
888
  [[package]]
856
889
  name = "mio"
857
890
  version = "1.1.1"
@@ -1357,6 +1390,12 @@ version = "1.3.0"
1357
1390
  source = "registry+https://github.com/rust-lang/crates.io-index"
1358
1391
  checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
1359
1392
 
1393
+ [[package]]
1394
+ name = "simd-adler32"
1395
+ version = "0.3.9"
1396
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1397
+ checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
1398
+
1360
1399
  [[package]]
1361
1400
  name = "slab"
1362
1401
  version = "0.4.12"
@@ -1709,6 +1748,18 @@ dependencies = [
1709
1748
  "syn",
1710
1749
  ]
1711
1750
 
1751
+ [[package]]
1752
+ name = "zip"
1753
+ version = "0.6.6"
1754
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1755
+ checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261"
1756
+ dependencies = [
1757
+ "byteorder",
1758
+ "crc32fast",
1759
+ "crossbeam-utils",
1760
+ "flate2",
1761
+ ]
1762
+
1712
1763
  [[package]]
1713
1764
  name = "zmij"
1714
1765
  version = "1.0.21"
@@ -4,7 +4,7 @@ resolver = "2"
4
4
 
5
5
  [workspace.package]
6
6
  edition = "2021"
7
- version = "0.4.0"
7
+ version = "0.5.0"
8
8
  license = "BUSL-1.1"
9
9
  authors = ["LoraDB, Inc."]
10
10
  repository = "https://github.com/lora-db/lora"
@@ -15,14 +15,14 @@ rust-version = "1.87"
15
15
  # Internal crates — versions are kept in lockstep with [workspace.package].version
16
16
  # by `scripts/sync-versions.mjs`. Both `path` and `version` are set so that
17
17
  # `cargo publish` works (crates.io cannot resolve path-only deps).
18
- lora-ast = { path = "crates/lora-ast", version = "=0.4.0" }
19
- lora-parser = { path = "crates/lora-parser", version = "=0.4.0" }
20
- lora-analyzer = { path = "crates/lora-analyzer", version = "=0.4.0" }
21
- lora-compiler = { path = "crates/lora-compiler", version = "=0.4.0" }
22
- lora-store = { path = "crates/lora-store", version = "=0.4.0" }
23
- lora-wal = { path = "crates/lora-wal", version = "=0.4.0" }
24
- lora-executor = { path = "crates/lora-executor", version = "=0.4.0" }
25
- lora-database = { path = "crates/lora-database", version = "=0.4.0" }
18
+ lora-ast = { path = "crates/lora-ast", version = "=0.5.0" }
19
+ lora-parser = { path = "crates/lora-parser", version = "=0.5.0" }
20
+ lora-analyzer = { path = "crates/lora-analyzer", version = "=0.5.0" }
21
+ lora-compiler = { path = "crates/lora-compiler", version = "=0.5.0" }
22
+ lora-store = { path = "crates/lora-store", version = "=0.5.0" }
23
+ lora-wal = { path = "crates/lora-wal", version = "=0.5.0" }
24
+ lora-executor = { path = "crates/lora-executor", version = "=0.5.0" }
25
+ lora-database = { path = "crates/lora-database", version = "=0.5.0" }
26
26
 
27
27
  # External crates.
28
28
  anyhow = "1"
@@ -40,3 +40,4 @@ tower = "0.5.3"
40
40
  criterion = { version = "0.8.2", features = ["html_reports"] }
41
41
  bincode = "1.3"
42
42
  crc32fast = "1.4"
43
+ zip = { version = "0.6", default-features = false, features = ["deflate"] }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lora-python
3
- Version: 0.4.0
3
+ Version: 0.5.0
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: 3
6
6
  Classifier: Programming Language :: Python :: 3.8
@@ -159,6 +159,27 @@ binding exposes WAL-backed initialization plus the existing
159
159
  `save_snapshot` / `load_snapshot` APIs, but not checkpoint, truncate,
160
160
  status, or sync-mode controls.
161
161
 
162
+ Snapshots accept the same broad shapes in sync and async APIs:
163
+
164
+ ```python
165
+ import io
166
+ from lora_python import Database
167
+
168
+ db = Database.create()
169
+ db.execute("CREATE (:Person {name: 'Alice'})")
170
+
171
+ meta = db.save_snapshot("./graph.lorasnap") # path / PathLike
172
+ raw = db.save_snapshot("binary") # bytes
173
+ text = db.save_snapshot("base64") # base64 str
174
+ buf = io.BytesIO()
175
+ meta = db.save_snapshot(buf) # binary writer
176
+
177
+ db.load_snapshot("./graph.lorasnap")
178
+ db.load_snapshot(raw)
179
+ db.load_snapshot(io.BytesIO(buf.getvalue()))
180
+ db.load_snapshot(text, format="base64")
181
+ ```
182
+
162
183
  ## Architecture
163
184
 
164
185
  ```
@@ -129,6 +129,27 @@ binding exposes WAL-backed initialization plus the existing
129
129
  `save_snapshot` / `load_snapshot` APIs, but not checkpoint, truncate,
130
130
  status, or sync-mode controls.
131
131
 
132
+ Snapshots accept the same broad shapes in sync and async APIs:
133
+
134
+ ```python
135
+ import io
136
+ from lora_python import Database
137
+
138
+ db = Database.create()
139
+ db.execute("CREATE (:Person {name: 'Alice'})")
140
+
141
+ meta = db.save_snapshot("./graph.lorasnap") # path / PathLike
142
+ raw = db.save_snapshot("binary") # bytes
143
+ text = db.save_snapshot("base64") # base64 str
144
+ buf = io.BytesIO()
145
+ meta = db.save_snapshot(buf) # binary writer
146
+
147
+ db.load_snapshot("./graph.lorasnap")
148
+ db.load_snapshot(raw)
149
+ db.load_snapshot(io.BytesIO(buf.getvalue()))
150
+ db.load_snapshot(text, format="base64")
151
+ ```
152
+
132
153
  ## Architecture
133
154
 
134
155
  ```
@@ -17,6 +17,7 @@ pub struct LogicalPlan {
17
17
  pub enum LogicalOp {
18
18
  Argument(Argument),
19
19
  NodeScan(NodeScan),
20
+ NodeByPropertyScan(NodeByPropertyScan),
20
21
  Expand(Expand),
21
22
  Filter(Filter),
22
23
  Projection(Projection),
@@ -70,6 +71,16 @@ pub struct NodeScan {
70
71
  pub labels: Vec<Vec<String>>,
71
72
  }
72
73
 
74
+ #[derive(Debug, Clone)]
75
+ pub struct NodeByPropertyScan {
76
+ pub input: Option<PlanNodeId>,
77
+ pub var: VarId,
78
+ /// Each inner Vec is a disjunctive group (OR). Outer Vec is conjunctive (AND).
79
+ pub labels: Vec<Vec<String>>,
80
+ pub key: String,
81
+ pub value: ResolvedExpr,
82
+ }
83
+
73
84
  #[derive(Debug, Clone)]
74
85
  pub struct Expand {
75
86
  pub input: PlanNodeId,
@@ -1,6 +1,7 @@
1
1
  use crate::logical::*;
2
2
  use crate::physical::*;
3
3
  use lora_analyzer::{symbols::VarId, ResolvedExpr};
4
+ use lora_ast::BinaryOp;
4
5
  use std::collections::BTreeSet;
5
6
 
6
7
  pub struct Optimizer;
@@ -18,6 +19,7 @@ impl Optimizer {
18
19
 
19
20
  pub fn optimize(&mut self, mut plan: LogicalPlan) -> LogicalPlan {
20
21
  self.push_filter_below_projection(&mut plan);
22
+ self.use_property_indexed_node_scans(&mut plan);
21
23
  self.remove_redundant_limit(&mut plan);
22
24
  plan
23
25
  }
@@ -79,6 +81,41 @@ impl Optimizer {
79
81
  // placeholder for future rules
80
82
  }
81
83
 
84
+ fn use_property_indexed_node_scans(&self, plan: &mut LogicalPlan) {
85
+ let len = plan.nodes.len();
86
+
87
+ for i in 0..len {
88
+ let (input_id, predicate) = match &plan.nodes[i] {
89
+ LogicalOp::Filter(f) => (f.input, &f.predicate),
90
+ _ => continue,
91
+ };
92
+
93
+ let (var, key, value) =
94
+ match property_equality_candidate(predicate, &plan.nodes[input_id]) {
95
+ Some(candidate) => candidate,
96
+ None => continue,
97
+ };
98
+
99
+ let replacement = match &plan.nodes[input_id] {
100
+ LogicalOp::NodeScan(scan) => {
101
+ Some(LogicalOp::NodeByPropertyScan(NodeByPropertyScan {
102
+ input: scan.input,
103
+ var,
104
+ labels: scan.labels.clone(),
105
+ key,
106
+ value,
107
+ }))
108
+ }
109
+ LogicalOp::NodeByPropertyScan(_) => None,
110
+ _ => None,
111
+ };
112
+
113
+ if let Some(replacement) = replacement {
114
+ plan.nodes[input_id] = replacement;
115
+ }
116
+ }
117
+ }
118
+
82
119
  /// Lower a logical plan by consuming it — each op's owned payload
83
120
  /// (expressions, patterns, items) is moved into the physical op rather
84
121
  /// than cloned. Callers should not need the logical plan after this.
@@ -105,6 +142,16 @@ impl Optimizer {
105
142
  }
106
143
  }
107
144
 
145
+ LogicalOp::NodeByPropertyScan(scan) => {
146
+ PhysicalOp::NodeByPropertyScan(NodeByPropertyScanExec {
147
+ input: scan.input,
148
+ var: scan.var,
149
+ labels: scan.labels,
150
+ key: scan.key,
151
+ value: scan.value,
152
+ })
153
+ }
154
+
108
155
  LogicalOp::Expand(expand) => PhysicalOp::Expand(ExpandExec {
109
156
  input: expand.input,
110
157
  src: expand.src,
@@ -204,6 +251,53 @@ fn collect_vars(expr: &ResolvedExpr) -> BTreeSet<VarId> {
204
251
  vars
205
252
  }
206
253
 
254
+ fn property_equality_candidate(
255
+ predicate: &ResolvedExpr,
256
+ input: &LogicalOp,
257
+ ) -> Option<(VarId, String, ResolvedExpr)> {
258
+ let LogicalOp::NodeScan(scan) = input else {
259
+ return None;
260
+ };
261
+
262
+ property_equality_for_var(predicate, scan.var)
263
+ }
264
+
265
+ fn property_equality_for_var(
266
+ predicate: &ResolvedExpr,
267
+ var: VarId,
268
+ ) -> Option<(VarId, String, ResolvedExpr)> {
269
+ let ResolvedExpr::Binary { lhs, op, rhs } = predicate else {
270
+ return None;
271
+ };
272
+
273
+ if matches!(op, BinaryOp::And) {
274
+ return property_equality_for_var(lhs, var).or_else(|| property_equality_for_var(rhs, var));
275
+ }
276
+
277
+ if !matches!(op, BinaryOp::Eq) {
278
+ return None;
279
+ }
280
+
281
+ property_access_for_var(lhs, var)
282
+ .filter(|_| !collect_vars(rhs).contains(&var))
283
+ .map(|key| (var, key, (**rhs).clone()))
284
+ .or_else(|| {
285
+ property_access_for_var(rhs, var)
286
+ .filter(|_| !collect_vars(lhs).contains(&var))
287
+ .map(|key| (var, key, (**lhs).clone()))
288
+ })
289
+ }
290
+
291
+ fn property_access_for_var(expr: &ResolvedExpr, var: VarId) -> Option<String> {
292
+ match expr {
293
+ ResolvedExpr::Property { expr, property } => match &**expr {
294
+ ResolvedExpr::Variable(v) if *v == var => Some(property.clone()),
295
+ _ => None,
296
+ },
297
+ _ => None,
298
+ }
299
+ }
300
+
207
301
  fn collect_vars_inner(expr: &ResolvedExpr, out: &mut BTreeSet<VarId>) {
208
302
  match expr {
209
303
  ResolvedExpr::Variable(v) => {
@@ -18,6 +18,7 @@ pub enum PhysicalOp {
18
18
  Argument(ArgumentExec),
19
19
  NodeScan(NodeScanExec),
20
20
  NodeByLabelScan(NodeByLabelScanExec),
21
+ NodeByPropertyScan(NodeByPropertyScanExec),
21
22
  Expand(ExpandExec),
22
23
  Filter(FilterExec),
23
24
  Projection(ProjectionExec),
@@ -69,6 +70,16 @@ pub struct NodeByLabelScanExec {
69
70
  pub labels: Vec<Vec<String>>,
70
71
  }
71
72
 
73
+ #[derive(Debug, Clone)]
74
+ pub struct NodeByPropertyScanExec {
75
+ pub input: Option<PhysicalNodeId>,
76
+ pub var: VarId,
77
+ /// Each inner Vec is a disjunctive group (OR). Outer Vec is conjunctive (AND).
78
+ pub labels: Vec<Vec<String>>,
79
+ pub key: String,
80
+ pub value: ResolvedExpr,
81
+ }
82
+
72
83
  #[derive(Debug, Clone)]
73
84
  pub struct ExpandExec {
74
85
  pub input: PhysicalNodeId,
@@ -16,6 +16,7 @@ bench = false
16
16
 
17
17
  [dependencies]
18
18
  anyhow.workspace = true
19
+ zip.workspace = true
19
20
 
20
21
  lora-ast.workspace = true
21
22
  lora-parser.workspace = true
@@ -2,22 +2,44 @@
2
2
  "_meta": {
3
3
  "purpose": "Baseline ns/iter for the perf_smoke_benchmarks suite. Used by scripts/check-perf-smoke.mjs to detect major (>=3x) regressions. NOT an authoritative performance record. See docs/performance/perf-smoke.md.",
4
4
  "refresh": "node scripts/check-perf-smoke.mjs --update <bencher-output>",
5
- "default_threshold": 3.0,
5
+ "default_threshold": 3,
6
6
  "seeded_on": "2026-04-24",
7
- "seeded_from": "Rough scaling of docs/performance/benchmarks.md numbers to allow for ubuntu-latest CI being slower and noisier than the reference Apple Silicon run. Replace with real CI-measured values on first green run."
7
+ "seeded_from": "Rough scaling of docs/performance/benchmarks.md numbers to allow for ubuntu-latest CI being slower and noisier than the reference Apple Silicon run. Replace with real CI-measured values on first green run.",
8
+ "last_updated": "2026-04-26"
8
9
  },
9
10
  "benchmarks": {
10
11
  "perf_smoke/scan_1k": {
11
- "ns": 500000
12
+ "ns": 293999
12
13
  },
13
14
  "perf_smoke/filter_1k": {
14
- "ns": 700000
15
+ "ns": 383337
15
16
  },
16
17
  "perf_smoke/traversal_chain_500": {
17
- "ns": 500000
18
+ "ns": 262341
18
19
  },
19
20
  "perf_smoke/write_batch_100": {
20
- "ns": 300000
21
+ "ns": 132457
22
+ },
23
+ "perf_smoke/stream_scan_1k": {
24
+ "ns": 281758
25
+ },
26
+ "perf_smoke/stream_pull_one": {
27
+ "ns": 100948
28
+ },
29
+ "perf_smoke/stream_write_100": {
30
+ "ns": 85205
31
+ },
32
+ "perf_smoke/stream_write_sort_100": {
33
+ "ns": 252797
34
+ },
35
+ "perf_smoke/tx_roundtrip_empty": {
36
+ "ns": 182
37
+ },
38
+ "perf_smoke/tx_read_1k": {
39
+ "ns": 294197
40
+ },
41
+ "perf_smoke/tx_write_100": {
42
+ "ns": 114336
21
43
  }
22
44
  }
23
45
  }