iris-vector-graph 1.55.2__tar.gz → 1.56.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 (236) hide show
  1. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/PKG-INFO +17 -1
  2. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/README.md +16 -0
  3. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/Traversal.cls +146 -0
  4. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/cypher/ast.py +1 -0
  5. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/cypher/lexer.py +8 -1
  6. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/cypher/parser.py +2 -0
  7. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/cypher/translator.py +85 -6
  8. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/engine.py +192 -7
  9. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/pyproject.toml +1 -1
  10. iris_vector_graph-1.56.0/tests/unit/test_weighted_shortest_path.py +112 -0
  11. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/.gitignore +0 -0
  12. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/LICENSE +0 -0
  13. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/demo_biomedical.py +0 -0
  14. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/demo_fraud_detection.py +0 -0
  15. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/demo_fraud_detection_sql.py +0 -0
  16. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/demo_utils.py +0 -0
  17. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/demo_working_system.py +0 -0
  18. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/domains/__init__.py +0 -0
  19. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/domains/biomedical/__init__.py +0 -0
  20. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/domains/biomedical/loaders.py +0 -0
  21. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/domains/biomedical/resolver.py +0 -0
  22. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/domains/biomedical/types.py +0 -0
  23. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/domains/biomedical_legacy/__init__.py +0 -0
  24. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/domains/biomedical_legacy/biomedical_engine.py +0 -0
  25. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/domains/biomedical_legacy/biomedical_schema.py +0 -0
  26. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/domains/biomedical_legacy/legacy_wrapper.py +0 -0
  27. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/domains/fraud/__init__.py +0 -0
  28. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/domains/fraud/loaders.py +0 -0
  29. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/domains/fraud/resolver.py +0 -0
  30. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/domains/fraud/types.py +0 -0
  31. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/graphQL.http +0 -0
  32. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/hybrid_vector_graph_query.cypher +0 -0
  33. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/examples/rest.http +0 -0
  34. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/Algorithms.cls +0 -0
  35. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/ArnoAccel.cls +0 -0
  36. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/BM25Index.cls +0 -0
  37. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/BenchFormat.cls +0 -0
  38. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/BenchSeeder.cls +0 -0
  39. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/Benchmark.cls +0 -0
  40. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/Edge.cls +0 -0
  41. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/EdgeScan.cls +0 -0
  42. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/GraphIndex.cls +0 -0
  43. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/IVFIndex.cls +0 -0
  44. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/Loader.cls +0 -0
  45. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/MCPService.cls +0 -0
  46. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/MCPToolSet.cls +0 -0
  47. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/MCPTools.cls +0 -0
  48. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/Meta.cls +0 -0
  49. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/PLAIDSearch.cls +0 -0
  50. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/PageRank.cls +0 -0
  51. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/PyOps.cls +0 -0
  52. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/Service.cls +0 -0
  53. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/Subgraph.cls +0 -0
  54. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/TemporalIndex.cls +0 -0
  55. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/TestEdge.cls +0 -0
  56. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/Graph/KG/VecIndex.cls +0 -0
  57. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/PageRankEmbedded.cls +0 -0
  58. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/User.Exec.cls +0 -0
  59. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_src/src/iris/vector/graph/GraphOperators.cls +0 -0
  60. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/__init__.py +0 -0
  61. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/bolt_server.py +0 -0
  62. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/bulk_loader.py +0 -0
  63. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/capabilities.py +0 -0
  64. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/cypher/__init__.py +0 -0
  65. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/cypher/algorithms/__init__.py +0 -0
  66. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/cypher/algorithms/paths.py +0 -0
  67. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/cypher_api.py +0 -0
  68. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/embedded.py +0 -0
  69. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/fusion.py +0 -0
  70. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/gql/__init__.py +0 -0
  71. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/gql/constants.py +0 -0
  72. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/gql/engine.py +0 -0
  73. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/gql/pooling.py +0 -0
  74. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/gql/resolvers.py +0 -0
  75. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/gql/schema.py +0 -0
  76. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/models.py +0 -0
  77. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/operators.py +0 -0
  78. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/py.typed +0 -0
  79. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/schema.py +0 -0
  80. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/security.py +0 -0
  81. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/text_search.py +0 -0
  82. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/utils.py +0 -0
  83. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/iris_vector_graph/vector_utils.py +0 -0
  84. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/sql/fhir_bridges.sql +0 -0
  85. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/sql/fraud_sample_data.sql +0 -0
  86. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/sql/globals_schema.sql +0 -0
  87. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/sql/graph_path_globals.sql +0 -0
  88. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/sql/graph_walk_tvf.sql +0 -0
  89. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/sql/migrations/000_base_schema_iris.sql +0 -0
  90. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/sql/migrations/001_add_nodepk_table.sql +0 -0
  91. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/sql/migrations/001_rollback_nodepk.sql +0 -0
  92. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/sql/migrations/002_add_fk_constraints.sql +0 -0
  93. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/sql/operators.sql +0 -0
  94. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/sql/operators_fixed.sql +0 -0
  95. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/sql/procedures/kg_PageRank.sql +0 -0
  96. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/sql/rdf_reifications.sql +0 -0
  97. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/sql/schema.sql +0 -0
  98. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/TESTING.md +0 -0
  99. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/benchmark_parser.py +0 -0
  100. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/benchmarks/benchmark_neo4j.py +0 -0
  101. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/benchmarks/bfs_benchmark.py +0 -0
  102. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/benchmarks/establish_baseline.py +0 -0
  103. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/benchmarks/graph_gen.py +0 -0
  104. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/benchmarks/iris_baseline_run.py +0 -0
  105. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/benchmarks/iris_os_run.py +0 -0
  106. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/benchmarks/load_neo4j.py +0 -0
  107. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/benchmarks/synthetic_baseline.csv +0 -0
  108. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/conftest.py +0 -0
  109. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/contract/__init__.py +0 -0
  110. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/contract/test_cypher_api.py +0 -0
  111. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/contract/test_cypher_api_errors.py +0 -0
  112. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/contract/test_graphql_queries.py +0 -0
  113. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/contract/test_graphql_schema.py +0 -0
  114. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/contract/test_ppr_api.py +0 -0
  115. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/curl_suite.sh +0 -0
  116. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/__init__.py +0 -0
  117. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/conftest.py +0 -0
  118. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_biomedical_demo.py +0 -0
  119. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_biomedical_ui.py +0 -0
  120. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_cypher_coerce_e2e.py +0 -0
  121. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_cypher_sprints_e2e.py +0 -0
  122. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_cypher_vector_search.py +0 -0
  123. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_fhir_bridges_e2e.py +0 -0
  124. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_fraud_demo.py +0 -0
  125. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_fraud_ui.py +0 -0
  126. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_gql_autogen_startup.py +0 -0
  127. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_gql_cypher_passthrough.py +0 -0
  128. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_gql_node_queries.py +0 -0
  129. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_gql_semantic_search.py +0 -0
  130. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_gql_traversal.py +0 -0
  131. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_graph_kernels_e2e.py +0 -0
  132. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_hla_kg_e2e.py +0 -0
  133. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_multi_query_engine_platform.py +0 -0
  134. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_named_paths_e2e.py +0 -0
  135. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_nkg_index_e2e.py +0 -0
  136. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_operator_wiring_e2e.py +0 -0
  137. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_plaid_search_e2e.py +0 -0
  138. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_ppr_cls_fast_path.py +0 -0
  139. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_ppr_guided_e2e.py +0 -0
  140. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_procedure_installation.py +0 -0
  141. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_reification_e2e.py +0 -0
  142. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_schema_procedures_e2e.py +0 -0
  143. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_subgraph_e2e.py +0 -0
  144. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_subquery_call_e2e.py +0 -0
  145. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/e2e/test_vecindex_e2e.py +0 -0
  146. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/__init__.py +0 -0
  147. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/conftest.py +0 -0
  148. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/gql/__init__.py +0 -0
  149. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/gql/test_graphql_mutations.py +0 -0
  150. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/gql/test_graphql_nested_queries.py +0 -0
  151. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/gql/test_graphql_queries.py +0 -0
  152. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/gql/test_graphql_vector_search.py +0 -0
  153. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_bidirectional_ppr.py +0 -0
  154. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_cls_layer.py +0 -0
  155. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_cypher_advanced.py +0 -0
  156. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_cypher_enhancements.py +0 -0
  157. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_cypher_multi_type.py +0 -0
  158. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_cypher_rd.py +0 -0
  159. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_cypher_rel_vars.py +0 -0
  160. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_cypher_single_type.py +0 -0
  161. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_cypher_untyped.py +0 -0
  162. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_cypher_vector_search.py +0 -0
  163. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_embeddings_api.py +0 -0
  164. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_fastapi_graphql.py +0 -0
  165. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_fhir_bridges_integration.py +0 -0
  166. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_named_paths_integration.py +0 -0
  167. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_nodepk_advanced_benchmarks.py +0 -0
  168. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_nodepk_constraints.py +0 -0
  169. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_nodepk_graph_analytics.py +0 -0
  170. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_nodepk_migration.py +0 -0
  171. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_nodepk_performance.py +0 -0
  172. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_nodepk_production_scale.py +0 -0
  173. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_objectscript_classes.py +0 -0
  174. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_pagerank_sql_optimization.py +0 -0
  175. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_reification_integration.py +0 -0
  176. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_schema_migration.py +0 -0
  177. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_stored_procedure_install.py +0 -0
  178. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/integration/test_subquery_call_integration.py +0 -0
  179. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/performance/conftest.py +0 -0
  180. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/performance/scale_benchmark.py +0 -0
  181. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/performance/test_ppr_stress.py +0 -0
  182. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/performance/test_stress_v1_5.py +0 -0
  183. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/python/run_all_tests.py +0 -0
  184. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/python/test_iris_rest_api.py +0 -0
  185. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/python/test_networkx_loader.py +0 -0
  186. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/python/test_performance_benchmarks.py +0 -0
  187. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/python/test_pyops_vector_conversion.py +0 -0
  188. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/python/test_python_operators.py +0 -0
  189. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/python/test_python_sdk.py +0 -0
  190. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/python/test_schema_validation.py +0 -0
  191. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/python/test_sql_queries.py +0 -0
  192. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/python/test_vector_functions.py +0 -0
  193. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/cypher/__init__.py +0 -0
  194. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/cypher/test_lexer.py +0 -0
  195. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/cypher/test_lexer_advanced.py +0 -0
  196. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/cypher/test_parser.py +0 -0
  197. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/cypher/test_parser_advanced.py +0 -0
  198. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_batch_mutations.py +0 -0
  199. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_bm25_index.py +0 -0
  200. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_bolt_server.py +0 -0
  201. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_cls_deployment.py +0 -0
  202. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_cypher_case_when.py +0 -0
  203. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_cypher_functions.py +0 -0
  204. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_cypher_parser.py +0 -0
  205. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_cypher_posos_bugs.py +0 -0
  206. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_cypher_procedures.py +0 -0
  207. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_cypher_translator.py +0 -0
  208. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_cypher_union_exists.py +0 -0
  209. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_cypher_var_length.py +0 -0
  210. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_cypher_vector_search.py +0 -0
  211. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_edgeprop_ndjson.py +0 -0
  212. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_embedded.py +0 -0
  213. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_engine_dimension_fix.py +0 -0
  214. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_engine_embeddings.py +0 -0
  215. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_fhir_bridges.py +0 -0
  216. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_get_nodes.py +0 -0
  217. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_graph_kernels.py +0 -0
  218. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_graphql_dataloader.py +0 -0
  219. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_ingest_formats.py +0 -0
  220. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_ivf_index.py +0 -0
  221. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_named_graphs.py +0 -0
  222. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_named_paths.py +0 -0
  223. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_operators_wiring.py +0 -0
  224. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_plaid_search.py +0 -0
  225. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_ppr_guided_subgraph.py +0 -0
  226. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_reification.py +0 -0
  227. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_schema_init.py +0 -0
  228. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_schema_procedures.py +0 -0
  229. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_shortest_path.py +0 -0
  230. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_sql_splitter.py +0 -0
  231. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_sql_table_bridge.py +0 -0
  232. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_subgraph.py +0 -0
  233. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_subquery_call.py +0 -0
  234. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_temporal_cypher.py +0 -0
  235. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_temporal_edges.py +0 -0
  236. {iris_vector_graph-1.55.2 → iris_vector_graph-1.56.0}/tests/unit/test_unified_edge_store.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iris-vector-graph
3
- Version: 1.55.2
3
+ Version: 1.56.0
4
4
  Summary: Transactional Graph + Vector retrieval system for InterSystems IRIS with hybrid search, openCypher, and GraphQL APIs
5
5
  Project-URL: Homepage, https://github.com/intersystems-community/iris-vector-graph
6
6
  Project-URL: Documentation, https://github.com/intersystems-community/iris-vector-graph/tree/main/docs
@@ -556,6 +556,22 @@ anchors = engine.get_kg_anchors(icd_codes=["J18.0", "E11.9"])
556
556
 
557
557
  ## Changelog
558
558
 
559
+ ### v1.56.0 (2026-04-19)
560
+ - feat: `CALL ivg.shortestPath.weighted(from, to, weightProp, maxCost, maxHops) YIELD path, totalCost` — Dijkstra minimum-cost path in pure ObjectScript
561
+ - Uses edge weights from `^KG("out",0,...)` globals (set by create_edge WriteAdjacency)
562
+ - Falls back to unit weight 1.0 when weightProp not found
563
+ - Supports directed ("out") and undirected ("both") traversal
564
+ - 4 E2E tests: prefer lower-cost longer path, no path, same source/target, unit weight fallback
565
+
566
+
567
+ ### v1.55.3 (2026-04-19)
568
+ - fix: Bug 6 final — SQLCODE -400 on rdf_edges CREATE INDEX now debug-level (ALTER TABLE fallback handles it)
569
+ - fix: type(r) now returns edge predicate column (e.p) not node_id
570
+ - fix: id(n) now returns actual node_id column
571
+ - feat: =~ regex match operator — translates to IRIS %MATCHES
572
+ - fix: N-Quads import captures graph URI from quad's 4th element as graph_id
573
+
574
+
559
575
  ### v1.55.2 (2026-04-19)
560
576
  - fix: Bug 6 (final) — SQLCODE -400 on rdf_edges index creation now falls back to ALTER TABLE ADD INDEX; all standard indexes created even when Graph.KG.Edge class was never compiled
561
577
 
@@ -484,6 +484,22 @@ anchors = engine.get_kg_anchors(icd_codes=["J18.0", "E11.9"])
484
484
 
485
485
  ## Changelog
486
486
 
487
+ ### v1.56.0 (2026-04-19)
488
+ - feat: `CALL ivg.shortestPath.weighted(from, to, weightProp, maxCost, maxHops) YIELD path, totalCost` — Dijkstra minimum-cost path in pure ObjectScript
489
+ - Uses edge weights from `^KG("out",0,...)` globals (set by create_edge WriteAdjacency)
490
+ - Falls back to unit weight 1.0 when weightProp not found
491
+ - Supports directed ("out") and undirected ("both") traversal
492
+ - 4 E2E tests: prefer lower-cost longer path, no path, same source/target, unit weight fallback
493
+
494
+
495
+ ### v1.55.3 (2026-04-19)
496
+ - fix: Bug 6 final — SQLCODE -400 on rdf_edges CREATE INDEX now debug-level (ALTER TABLE fallback handles it)
497
+ - fix: type(r) now returns edge predicate column (e.p) not node_id
498
+ - fix: id(n) now returns actual node_id column
499
+ - feat: =~ regex match operator — translates to IRIS %MATCHES
500
+ - fix: N-Quads import captures graph URI from quad's 4th element as graph_id
501
+
502
+
487
503
  ### v1.55.2 (2026-04-19)
488
504
  - fix: Bug 6 (final) — SQLCODE -400 on rdf_edges index creation now falls back to ALTER TABLE ADD INDEX; all standard indexes created even when Graph.KG.Edge class was never compiled
489
505
 
@@ -494,4 +494,150 @@ ClassMethod BacktrackPath(srcId As %String, dstId As %String, depth As %Integer)
494
494
  Return path
495
495
  }
496
496
 
497
+ ClassMethod DijkstraJson(srcId As %String, dstId As %String, weightProp As %String = "", maxCost As %Double = 9999, maxHops As %Integer = 10, direction As %String = "out") As %String
498
+ {
499
+ Kill ^||Dij.pq, ^||Dij.parent, ^||Dij.seen, ^||Dij.dist
500
+
501
+ Set srcId = $Get(srcId, "")
502
+ Set dstId = $Get(dstId, "")
503
+ Set weightProp = $Get(weightProp, "")
504
+
505
+ If srcId = "" || (dstId = "") {
506
+ Kill ^||Dij.pq, ^||Dij.parent, ^||Dij.seen, ^||Dij.dist
507
+ Return "{}"
508
+ }
509
+
510
+ If srcId = dstId {
511
+ Set result = ##class(%DynamicObject).%New()
512
+ Set nodes = ##class(%DynamicArray).%New()
513
+ Do nodes.%Push(srcId)
514
+ Do result.%Set("nodes", nodes)
515
+ Do result.%Set("rels", ##class(%DynamicArray).%New())
516
+ Do result.%Set("costs", ##class(%DynamicArray).%New())
517
+ Do result.%Set("length", 0)
518
+ Do result.%Set("totalCost", 0)
519
+ Kill ^||Dij.pq, ^||Dij.parent, ^||Dij.seen, ^||Dij.dist
520
+ Return result.%ToJSON()
521
+ }
522
+
523
+ Set ^||Dij.pq(0, srcId) = ""
524
+ Set ^||Dij.dist(srcId) = 0
525
+
526
+ For {
527
+ Set minCost = $Order(^||Dij.pq(""))
528
+ Quit:minCost=""
529
+ Set curNode = $Order(^||Dij.pq(minCost, ""))
530
+ Quit:curNode=""
531
+ Kill ^||Dij.pq(minCost, curNode)
532
+
533
+ If $Data(^||Dij.seen(curNode)) Continue
534
+ Set ^||Dij.seen(curNode) = ""
535
+
536
+ If curNode = dstId {
537
+ Set result = ..DijkstraBacktrack(srcId, dstId, +minCost)
538
+ Kill ^||Dij.pq, ^||Dij.parent, ^||Dij.seen, ^||Dij.dist
539
+ Return result
540
+ }
541
+
542
+ If minCost >= maxCost Continue
543
+
544
+ If direction = "out" || (direction = "both") {
545
+ Set p = ""
546
+ For {
547
+ Set p = $Order(^KG("out", 0, curNode, p))
548
+ Quit:p=""
549
+ Set neighbor = ""
550
+ For {
551
+ Set neighbor = $Order(^KG("out", 0, curNode, p, neighbor))
552
+ Quit:neighbor=""
553
+ If $Data(^||Dij.seen(neighbor)) Continue
554
+ Set rawW = $Get(^KG("out", 0, curNode, p, neighbor), 1)
555
+ Set edgeW = +rawW
556
+ If edgeW <= 0 Set edgeW = 1.0
557
+ Set newCost = minCost + edgeW
558
+ If newCost > maxCost Continue
559
+ If '$Data(^||Dij.seen(neighbor)) {
560
+ If '$Data(^||Dij.dist(neighbor)) || (newCost < ^||Dij.dist(neighbor)) {
561
+ Set ^||Dij.dist(neighbor) = newCost
562
+ Set ^||Dij.pq(newCost, neighbor) = ""
563
+ Set ^||Dij.parent(neighbor) = $ListBuild(curNode, p, edgeW)
564
+ }
565
+ }
566
+ }
567
+ }
568
+ }
569
+
570
+ If direction = "both" {
571
+ Set p = ""
572
+ For {
573
+ Set p = $Order(^KG("in", 0, curNode, p))
574
+ Quit:p=""
575
+ Set neighbor = ""
576
+ For {
577
+ Set neighbor = $Order(^KG("in", 0, curNode, p, neighbor))
578
+ Quit:neighbor=""
579
+ If $Data(^||Dij.seen(neighbor)) Continue
580
+ Set rawW = $Get(^KG("in", 0, curNode, p, neighbor), 1)
581
+ Set edgeW = +rawW
582
+ If edgeW <= 0 Set edgeW = 1.0
583
+ Set newCost = minCost + edgeW
584
+ If newCost > maxCost Continue
585
+ If '$Data(^||Dij.dist(neighbor)) || (newCost < ^||Dij.dist(neighbor)) {
586
+ Set ^||Dij.dist(neighbor) = newCost
587
+ Set ^||Dij.pq(newCost, neighbor) = ""
588
+ Set ^||Dij.parent(neighbor) = $ListBuild(curNode, p, edgeW)
589
+ }
590
+ }
591
+ }
592
+ }
593
+ }
594
+
595
+ Kill ^||Dij.pq, ^||Dij.parent, ^||Dij.seen, ^||Dij.dist
596
+ Return "{}"
597
+ }
598
+
599
+ ClassMethod DijkstraBacktrack(srcId As %String, dstId As %String, totalCost As %Double) As %String [ Private ]
600
+ {
601
+ Set nodeStack = $ListBuild(dstId)
602
+ Set relStack = ""
603
+ Set costStack = ""
604
+ Set cur = dstId
605
+
606
+ While cur '= srcId {
607
+ Set lb = $Get(^||Dij.parent(cur))
608
+ If lb = "" Quit
609
+ Set parentNode = $ListGet(lb, 1)
610
+ Set relType = $ListGet(lb, 2)
611
+ Set edgeCost = +$ListGet(lb, 3)
612
+ Set nodeStack = $ListBuild(parentNode) _ nodeStack
613
+ Set relStack = $ListBuild(relType) _ relStack
614
+ Set costStack = $ListBuild(edgeCost) _ costStack
615
+ Set cur = parentNode
616
+ }
617
+
618
+ Set nodes = ##class(%DynamicArray).%New()
619
+ Set rels = ##class(%DynamicArray).%New()
620
+ Set costs = ##class(%DynamicArray).%New()
621
+
622
+ Set ptr = 0
623
+ While $ListNext(nodeStack, ptr, n) { Do nodes.%Push(n) }
624
+ Set ptr = 0
625
+ While $ListNext(relStack, ptr, r) { Do rels.%Push(r) }
626
+ Set ptr = 0
627
+ While $ListNext(costStack, ptr, c) { Do costs.%Push(+c) }
628
+
629
+ Set result = ##class(%DynamicObject).%New()
630
+ Do result.%Set("nodes", nodes)
631
+ Do result.%Set("rels", rels)
632
+ Do result.%Set("costs", costs)
633
+ Do result.%Set("length", nodes.%Size() - 1)
634
+ Do result.%Set("totalCost", totalCost)
635
+ Return result.%ToJSON()
636
+ }
637
+
638
+ ClassMethod DijkstraProc(srcId As %String, dstId As %String, weightProp As %String = "", maxCost As %Double = 9999, maxHops As %Integer = 10, direction As %String = "out") As %String [ SqlProc, SqlName = DijkstraPath ]
639
+ {
640
+ Quit ..DijkstraJson(srcId, dstId, weightProp, maxCost, maxHops, direction)
641
+ }
642
+
497
643
  }
@@ -42,6 +42,7 @@ class BooleanOperator(Enum):
42
42
  STARTS_WITH = "STARTS WITH"
43
43
  ENDS_WITH = "ENDS WITH"
44
44
  CONTAINS = "CONTAINS"
45
+ REGEX_MATCH = "=~"
45
46
 
46
47
 
47
48
  # ==============================================================================
@@ -77,6 +77,8 @@ class TokenType(enum.Enum):
77
77
  MINUS = "-"
78
78
  STAR = "*"
79
79
  SLASH = "/"
80
+ TILDE = "~"
81
+ REGEX_MATCH = "=~"
80
82
  PERCENT = "%"
81
83
  CARET = "^"
82
84
  FOREACH = "FOREACH"
@@ -148,7 +150,12 @@ class Lexer:
148
150
  case "^":
149
151
  self._add_token(TokenType.CARET, char)
150
152
  case "=":
151
- self._add_token(TokenType.EQUALS, char)
153
+ if self._peek() == "~":
154
+ self.cursor += 1
155
+ self.column += 1
156
+ self._add_token(TokenType.REGEX_MATCH, "=~")
157
+ else:
158
+ self._add_token(TokenType.EQUALS, char)
152
159
  case "<":
153
160
  if self._peek() == ">":
154
161
  self.cursor += 1
@@ -838,6 +838,8 @@ class Parser:
838
838
  already_consumed = True
839
839
  case TokenType.CONTAINS:
840
840
  op = ast.BooleanOperator.CONTAINS
841
+ case TokenType.REGEX_MATCH:
842
+ op = ast.BooleanOperator.REGEX_MATCH
841
843
  case TokenType.IN:
842
844
  op = ast.BooleanOperator.IN
843
845
  case TokenType.IS:
@@ -247,10 +247,11 @@ def translate_procedure_call(
247
247
 
248
248
  Supported procedures:
249
249
  - ivg.vector.search(label, property, query_input, limit [, options])
250
- - ivg.neighbors(source_node_or_list, predicate, direction)
251
- - ivg.ppr(seed_node_or_list, alpha, max_iterations)
252
- - ivg.bm25.search(name, query, k)
253
- - ivg.ivf.search(name, query_vec, k, nprobe)
250
+ - ivg.neighbors(source_node_or_list, predicate, direction)
251
+ - ivg.ppr(seed_node_or_list, alpha, max_iterations)
252
+ - ivg.bm25.search(name, query, k)
253
+ - ivg.ivf.search(name, query_vec, k, nprobe)
254
+ - ivg.shortestPath.weighted(from, to, weightProp, maxCost, maxHops)
254
255
  """
255
256
  name = proc.procedure_name
256
257
  if name == "ivg.vector.search":
@@ -263,9 +264,11 @@ def translate_procedure_call(
263
264
  _translate_bm25_search(proc, context)
264
265
  elif name == "ivg.ivf.search":
265
266
  _translate_ivf_search(proc, context)
267
+ elif name == "ivg.shortestpath.weighted" or name == "ivg.shortestPath.weighted":
268
+ _translate_weighted_shortest_path(proc, context)
266
269
  else:
267
270
  raise ValueError(
268
- f"Unknown procedure: {name!r}. Supported: ivg.vector.search, ivg.neighbors, ivg.ppr, ivg.bm25.search, ivg.ivf.search"
271
+ f"Unknown procedure: {name!r}. Supported: ivg.vector.search, ivg.neighbors, ivg.ppr, ivg.bm25.search, ivg.ivf.search, ivg.shortestPath.weighted"
269
272
  )
270
273
 
271
274
 
@@ -653,6 +656,66 @@ def _translate_ivf_search(
653
656
  context.scalar_variables.add("score")
654
657
 
655
658
 
659
+ def _translate_weighted_shortest_path(
660
+ proc: ast.CypherProcedureCall, context: TranslationContext
661
+ ) -> None:
662
+ args = proc.arguments
663
+ if len(args) < 2:
664
+ raise ValueError(
665
+ "ivg.shortestPath.weighted requires at least 2 arguments: from, to"
666
+ )
667
+
668
+ from_id = _resolve_arg(args[0], context, "ivg.shortestPath.weighted")
669
+ to_id = _resolve_arg(args[1], context, "ivg.shortestPath.weighted")
670
+ weight_prop = (
671
+ str(_resolve_arg(args[2], context, "ivg.shortestPath.weighted"))
672
+ if len(args) > 2
673
+ else "weight"
674
+ )
675
+ max_cost = (
676
+ float(_resolve_arg(args[3], context, "ivg.shortestPath.weighted"))
677
+ if len(args) > 3
678
+ else 9999.0
679
+ )
680
+ max_hops = (
681
+ int(_resolve_arg(args[4], context, "ivg.shortestPath.weighted"))
682
+ if len(args) > 4
683
+ else 10
684
+ )
685
+ direction = (
686
+ str(_resolve_arg(args[5], context, "ivg.shortestPath.weighted"))
687
+ if len(args) > 5
688
+ else "out"
689
+ )
690
+
691
+ if not isinstance(from_id, str) or not isinstance(to_id, str):
692
+ raise ValueError(
693
+ "ivg.shortestPath.weighted: from and to must be string literals or $param"
694
+ )
695
+
696
+ context.var_length_paths.append(
697
+ {
698
+ "weighted": True,
699
+ "src_id_param": from_id
700
+ if not isinstance(from_id, str) or from_id.startswith("$")
701
+ else f"'{from_id}'",
702
+ "dst_id_param": to_id
703
+ if not isinstance(to_id, str) or to_id.startswith("$")
704
+ else f"'{to_id}'",
705
+ "weight_prop": weight_prop,
706
+ "max_cost": max_cost,
707
+ "max_hops": max_hops,
708
+ "direction": direction,
709
+ "return_path_funcs": list(proc.yield_items),
710
+ }
711
+ )
712
+
713
+ for item in proc.yield_items:
714
+ if item in ("path", "totalCost", "totalcost", "node"):
715
+ context.variable_aliases[item] = "WS"
716
+ context.scalar_variables.add(item)
717
+
718
+
656
719
  _TEMPORAL_TS_OPS = {
657
720
  ast.BooleanOperator.GREATER_THAN_OR_EQUAL,
658
721
  ast.BooleanOperator.LESS_THAN_OR_EQUAL,
@@ -1979,6 +2042,8 @@ def translate_boolean_expression(expr, context) -> str:
1979
2042
  return f"{left} LIKE ('%' || {right})"
1980
2043
  if op == ast.BooleanOperator.CONTAINS:
1981
2044
  return f"{left} LIKE ('%' || {right} || '%')"
2045
+ if op == ast.BooleanOperator.REGEX_MATCH:
2046
+ return f"{left} %MATCHES {right}"
1982
2047
  if op == ast.BooleanOperator.IN:
1983
2048
  return f"{left} IN {right}"
1984
2049
  raise ValueError(f"Unsupported operator: {op}")
@@ -2310,8 +2375,22 @@ def translate_expression(expr, context, segment="select") -> str:
2310
2375
  fn, args_exprs = expr.function_name.lower(), expr.arguments
2311
2376
  args = [translate_expression(a, context, segment=segment) for a in args_exprs]
2312
2377
 
2313
- if fn in ("id", "type"):
2378
+ if fn == "type":
2379
+ if args_exprs and isinstance(args_exprs[0], ast.Variable):
2380
+ var_name = args_exprs[0].name
2381
+ alias = context.variable_aliases.get(var_name, "")
2382
+ if alias:
2383
+ return f"{alias}.p"
2384
+ return args[0] if args else "NULL"
2385
+
2386
+ if fn == "id":
2387
+ if args_exprs and isinstance(args_exprs[0], ast.Variable):
2388
+ var_name = args_exprs[0].name
2389
+ alias = context.variable_aliases.get(var_name, "")
2390
+ if alias:
2391
+ return f"{alias}.node_id"
2314
2392
  return args[0] if args else "NULL"
2393
+
2315
2394
  if fn == "labels":
2316
2395
  return labels_subquery(args[0] if args else "NULL")
2317
2396
  if fn == "properties":
@@ -469,10 +469,28 @@ class IRISGraphEngine:
469
469
  and "already has a" not in err
470
470
  and "already has index" not in err
471
471
  ):
472
- if any(
473
- p in err or p in stmt.lower() for p in _OPTIONAL_DDL_PATTERNS
472
+ import re as _re_ddl
473
+
474
+ _sqlcode = _re_ddl.search(
475
+ r"sqlcode.*?<(-?\d+)>", err
476
+ ) or _re_ddl.search(r"<(-\d+)>", err)
477
+ _sqlcode_val = _sqlcode.group(1) if _sqlcode else ""
478
+ is_index_on_rdf_edges = (
479
+ _sqlcode_val == "-400"
480
+ and "rdf_edges" in stmt.lower()
481
+ and "create index" in stmt.lower()
482
+ )
483
+ if (
484
+ any(
485
+ p in err or p in stmt.lower()
486
+ for p in _OPTIONAL_DDL_PATTERNS
487
+ )
488
+ or is_index_on_rdf_edges
474
489
  ):
475
- logger.debug("Optional DDL skipped: %s", stmt[:80])
490
+ logger.debug(
491
+ "Optional DDL skipped (will retry via ALTER TABLE): %s",
492
+ stmt[:80],
493
+ )
476
494
  else:
477
495
  logger.warning(
478
496
  "Schema setup warning: %s | Statement: %.100s", e, stmt
@@ -782,6 +800,8 @@ class IRISGraphEngine:
782
800
 
783
801
  if sql_query.var_length_paths:
784
802
  vl0 = sql_query.var_length_paths[0]
803
+ if vl0.get("weighted"):
804
+ return self._execute_weighted_shortest_path(sql_query, parameters)
785
805
  if vl0.get("shortest") or vl0.get("all_shortest"):
786
806
  return self._execute_shortest_path_cypher(sql_query, parameters)
787
807
  return self._execute_var_length_cypher(sql_query, parameters)
@@ -847,6 +867,109 @@ class IRISGraphEngine:
847
867
  "metadata": metadata,
848
868
  }
849
869
 
870
+ def _execute_weighted_shortest_path(
871
+ self, sql_query, parameters=None
872
+ ) -> Dict[str, Any]:
873
+ import json as _json
874
+
875
+ vl = sql_query.var_length_paths[0]
876
+
877
+ def _resolve(param_ref):
878
+ if param_ref is None:
879
+ return None
880
+ s = str(param_ref)
881
+ if s.startswith("'") and s.endswith("'"):
882
+ return s[1:-1]
883
+ if s.startswith("$"):
884
+ name = s[1:]
885
+ if parameters and name in parameters:
886
+ return str(parameters[name])
887
+ return None
888
+ return s
889
+
890
+ source_id = _resolve(vl.get("src_id_param"))
891
+ target_id = _resolve(vl.get("dst_id_param"))
892
+
893
+ if source_id is None or target_id is None:
894
+ raise ValueError(
895
+ "ivg.shortestPath.weighted requires both from and to to be bound IDs"
896
+ )
897
+
898
+ weight_prop = vl.get("weight_prop", "weight") or "weight"
899
+ max_cost = float(vl.get("max_cost", 9999))
900
+ max_hops = int(vl.get("max_hops", 10))
901
+ direction = vl.get("direction", "out") or "out"
902
+
903
+ try:
904
+ raw = _call_classmethod(
905
+ self.conn,
906
+ "Graph.KG.Traversal",
907
+ "DijkstraJson",
908
+ source_id,
909
+ target_id,
910
+ weight_prop,
911
+ max_cost,
912
+ max_hops,
913
+ direction,
914
+ )
915
+ result_str = str(raw) if raw else "{}"
916
+ except Exception as e:
917
+ logger.warning(f"DijkstraJson failed: {e}")
918
+ return {
919
+ "columns": ["path", "totalCost"],
920
+ "rows": [],
921
+ "sql": "",
922
+ "params": [],
923
+ "metadata": sql_query.query_metadata,
924
+ }
925
+
926
+ if not result_str or result_str == "{}":
927
+ return {
928
+ "columns": ["path", "totalCost"],
929
+ "rows": [],
930
+ "sql": "",
931
+ "params": [],
932
+ "metadata": sql_query.query_metadata,
933
+ }
934
+
935
+ try:
936
+ path_obj = _json.loads(result_str)
937
+ except Exception:
938
+ return {
939
+ "columns": ["path", "totalCost"],
940
+ "rows": [],
941
+ "sql": "",
942
+ "params": [],
943
+ "metadata": sql_query.query_metadata,
944
+ }
945
+
946
+ total_cost = float(path_obj.get("totalCost", 0))
947
+ return_funcs = vl.get("return_path_funcs", [])
948
+
949
+ row = []
950
+ cols = []
951
+ if not return_funcs or "path" in return_funcs:
952
+ row.append(result_str)
953
+ cols.append("path")
954
+ if "totalCost" in return_funcs or "totalcost" in return_funcs:
955
+ row.append(total_cost)
956
+ cols.append("totalCost")
957
+ if "node" in return_funcs:
958
+ nodes = path_obj.get("nodes", [])
959
+ row.append(nodes[-1] if nodes else None)
960
+ cols.append("node")
961
+ if not cols:
962
+ row = [result_str, total_cost]
963
+ cols = ["path", "totalCost"]
964
+
965
+ return {
966
+ "columns": cols,
967
+ "rows": [row],
968
+ "sql": f"DijkstraJson({source_id}, {target_id})",
969
+ "params": [],
970
+ "metadata": sql_query.query_metadata,
971
+ }
972
+
850
973
  def _execute_shortest_path_cypher(
851
974
  self, sql_query, parameters=None
852
975
  ) -> Dict[str, Any]:
@@ -1142,6 +1265,62 @@ class IRISGraphEngine:
1142
1265
  def _try_system_procedure(self, proc) -> Optional[Dict[str, Any]]:
1143
1266
  name = proc.procedure_name.lower()
1144
1267
 
1268
+ if name in ("ivg.shortestpath.weighted", "ivg.shortestpath.weighted"):
1269
+ args = proc.arguments
1270
+ from iris_vector_graph.cypher import ast as cypher_ast
1271
+
1272
+ def _arg_str(a, params=None):
1273
+ if isinstance(a, cypher_ast.Literal):
1274
+ return str(a.value)
1275
+ if isinstance(a, cypher_ast.Variable):
1276
+ if params and a.name in params:
1277
+ return str(params[a.name])
1278
+ return a.name
1279
+ return str(a)
1280
+
1281
+ source_id = _arg_str(args[0]) if len(args) > 0 else None
1282
+ target_id = _arg_str(args[1]) if len(args) > 1 else None
1283
+ weight_prop = _arg_str(args[2]) if len(args) > 2 else "weight"
1284
+ max_cost = float(_arg_str(args[3])) if len(args) > 3 else 9999.0
1285
+ max_hops = int(float(_arg_str(args[4]))) if len(args) > 4 else 10
1286
+ direction = _arg_str(args[5]) if len(args) > 5 else "out"
1287
+
1288
+ if not source_id or not target_id:
1289
+ return {"columns": ["path", "totalCost"], "rows": []}
1290
+
1291
+ import json as _json
1292
+
1293
+ try:
1294
+ raw = _call_classmethod(
1295
+ self.conn,
1296
+ "Graph.KG.Traversal",
1297
+ "DijkstraJson",
1298
+ source_id,
1299
+ target_id,
1300
+ weight_prop,
1301
+ max_cost,
1302
+ max_hops,
1303
+ direction,
1304
+ )
1305
+ result_str = str(raw) if raw else "{}"
1306
+ except Exception as e:
1307
+ logger.warning(f"DijkstraJson failed: {e}")
1308
+ return {"columns": ["path", "totalCost"], "rows": []}
1309
+
1310
+ if not result_str or result_str == "{}":
1311
+ return {"columns": ["path", "totalCost"], "rows": []}
1312
+
1313
+ try:
1314
+ path_obj = _json.loads(result_str)
1315
+ except Exception:
1316
+ return {"columns": ["path", "totalCost"], "rows": []}
1317
+
1318
+ total_cost = float(path_obj.get("totalCost", 0))
1319
+ return {
1320
+ "columns": ["path", "totalCost"],
1321
+ "rows": [[result_str, total_cost]],
1322
+ }
1323
+
1145
1324
  if name == "db.labels":
1146
1325
  cursor = self.conn.cursor()
1147
1326
  cursor.execute(
@@ -2203,12 +2382,12 @@ class IRISGraphEngine:
2203
2382
  for nid in batch_nodes:
2204
2383
  if _ensure_node(nid):
2205
2384
  nodes_inserted += 1
2206
- for s, p, o in batch_edges:
2385
+ for s, p, o, edge_graph in batch_edges:
2207
2386
  try:
2208
- if graph:
2387
+ if edge_graph:
2209
2388
  cursor.execute(
2210
2389
  f"INSERT INTO {_table('rdf_edges')} (s, p, o_id, graph_id) SELECT ?, ?, ?, ? WHERE NOT EXISTS (SELECT 1 FROM {_table('rdf_edges')} WHERE s = ? AND p = ? AND o_id = ? AND graph_id = ?)",
2211
- [s, p, o, graph, s, p, o, graph],
2390
+ [s, p, o, edge_graph, s, p, o, edge_graph],
2212
2391
  )
2213
2392
  else:
2214
2393
  cursor.execute(
@@ -2243,6 +2422,12 @@ class IRISGraphEngine:
2243
2422
  p_str = _node_id(p)
2244
2423
  batch_nodes.add(s_id)
2245
2424
 
2425
+ effective_graph = graph
2426
+ if graph_ctx is not None:
2427
+ ctx_str = str(graph_ctx)
2428
+ if ctx_str and ctx_str not in ("", "DEFAULT", "urn:x-rdflib:default"):
2429
+ effective_graph = ctx_str
2430
+
2246
2431
  if isinstance(o, RDFLiteral):
2247
2432
  key = p_str.rsplit("/", 1)[-1].rsplit("#", 1)[-1][:128]
2248
2433
  val = str(o)
@@ -2256,7 +2441,7 @@ class IRISGraphEngine:
2256
2441
  elif isinstance(o, (URIRef, BNode)):
2257
2442
  o_id = _node_id(o)
2258
2443
  batch_nodes.add(o_id)
2259
- batch_edges.append((s_id, p_str, o_id))
2444
+ batch_edges.append((s_id, p_str, o_id, effective_graph))
2260
2445
  else:
2261
2446
  batch_props.append((s_id, p_str[:128], str(o)[:64000]))
2262
2447
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "iris-vector-graph"
7
- version = "1.55.2"
7
+ version = "1.56.0"
8
8
  description = "Transactional Graph + Vector retrieval system for InterSystems IRIS with hybrid search, openCypher, and GraphQL APIs"
9
9
  readme = "README.md"
10
10
  license = "MIT"