iris-vector-graph 1.63.0__tar.gz → 1.63.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.
Files changed (243) hide show
  1. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/PKG-INFO +11 -3
  2. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/README.md +8 -0
  3. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/Traversal.cls +42 -7
  4. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/bulk_loader.py +5 -5
  5. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/cypher/translator.py +4 -1
  6. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/engine.py +41 -6
  7. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/schema.py +7 -32
  8. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/pyproject.toml +3 -3
  9. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_cypher_e2e_new_features.py +95 -0
  10. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/.gitignore +0 -0
  11. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/LICENSE +0 -0
  12. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/demo_biomedical.py +0 -0
  13. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/demo_fraud_detection.py +0 -0
  14. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/demo_fraud_detection_sql.py +0 -0
  15. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/demo_utils.py +0 -0
  16. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/demo_working_system.py +0 -0
  17. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/domains/__init__.py +0 -0
  18. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/domains/biomedical/__init__.py +0 -0
  19. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/domains/biomedical/loaders.py +0 -0
  20. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/domains/biomedical/resolver.py +0 -0
  21. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/domains/biomedical/types.py +0 -0
  22. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/domains/biomedical_legacy/__init__.py +0 -0
  23. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/domains/biomedical_legacy/biomedical_engine.py +0 -0
  24. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/domains/biomedical_legacy/biomedical_schema.py +0 -0
  25. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/domains/biomedical_legacy/legacy_wrapper.py +0 -0
  26. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/domains/fraud/__init__.py +0 -0
  27. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/domains/fraud/loaders.py +0 -0
  28. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/domains/fraud/resolver.py +0 -0
  29. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/domains/fraud/types.py +0 -0
  30. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/graphQL.http +0 -0
  31. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/hybrid_vector_graph_query.cypher +0 -0
  32. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/examples/rest.http +0 -0
  33. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/Algorithms.cls +0 -0
  34. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/ArnoAccel.cls +0 -0
  35. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/BM25Index.cls +0 -0
  36. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/BenchFormat.cls +0 -0
  37. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/BenchSeeder.cls +0 -0
  38. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/Benchmark.cls +0 -0
  39. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/Edge.cls +0 -0
  40. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/EdgeScan.cls +0 -0
  41. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/GraphIndex.cls +0 -0
  42. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/IVFIndex.cls +0 -0
  43. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/Loader.cls +0 -0
  44. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/MCPService.cls +0 -0
  45. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/MCPToolSet.cls +0 -0
  46. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/MCPTools.cls +0 -0
  47. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/Meta.cls +0 -0
  48. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/PLAIDSearch.cls +0 -0
  49. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/PageRank.cls +0 -0
  50. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/PyOps.cls +0 -0
  51. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/Service.cls +0 -0
  52. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/Snapshot.cls +0 -0
  53. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/Subgraph.cls +0 -0
  54. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/TemporalIndex.cls +0 -0
  55. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/TestEdge.cls +0 -0
  56. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/Graph/KG/VecIndex.cls +0 -0
  57. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/PageRankEmbedded.cls +0 -0
  58. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/User.Exec.cls +0 -0
  59. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_src/src/iris/vector/graph/GraphOperators.cls +0 -0
  60. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/__init__.py +0 -0
  61. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/bolt_server.py +0 -0
  62. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/capabilities.py +0 -0
  63. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/cypher/__init__.py +0 -0
  64. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/cypher/algorithms/__init__.py +0 -0
  65. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/cypher/algorithms/paths.py +0 -0
  66. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/cypher/ast.py +0 -0
  67. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/cypher/lexer.py +0 -0
  68. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/cypher/parser.py +0 -0
  69. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/cypher_api.py +0 -0
  70. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/embedded.py +0 -0
  71. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/fusion.py +0 -0
  72. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/gql/__init__.py +0 -0
  73. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/gql/constants.py +0 -0
  74. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/gql/engine.py +0 -0
  75. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/gql/pooling.py +0 -0
  76. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/gql/resolvers.py +0 -0
  77. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/gql/schema.py +0 -0
  78. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/models.py +0 -0
  79. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/operators.py +0 -0
  80. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/py.typed +0 -0
  81. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/security.py +0 -0
  82. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/text_search.py +0 -0
  83. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/utils.py +0 -0
  84. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/iris_vector_graph/vector_utils.py +0 -0
  85. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/sql/fhir_bridges.sql +0 -0
  86. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/sql/fraud_sample_data.sql +0 -0
  87. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/sql/globals_schema.sql +0 -0
  88. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/sql/graph_path_globals.sql +0 -0
  89. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/sql/graph_walk_tvf.sql +0 -0
  90. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/sql/migrations/000_base_schema_iris.sql +0 -0
  91. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/sql/migrations/001_add_nodepk_table.sql +0 -0
  92. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/sql/migrations/001_rollback_nodepk.sql +0 -0
  93. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/sql/migrations/002_add_fk_constraints.sql +0 -0
  94. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/sql/operators.sql +0 -0
  95. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/sql/operators_fixed.sql +0 -0
  96. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/sql/procedures/kg_PageRank.sql +0 -0
  97. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/sql/rdf_reifications.sql +0 -0
  98. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/sql/schema.sql +0 -0
  99. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/TESTING.md +0 -0
  100. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/benchmark_parser.py +0 -0
  101. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/benchmarks/benchmark_neo4j.py +0 -0
  102. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/benchmarks/bfs_benchmark.py +0 -0
  103. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/benchmarks/establish_baseline.py +0 -0
  104. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/benchmarks/graph_gen.py +0 -0
  105. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/benchmarks/iris_baseline_run.py +0 -0
  106. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/benchmarks/iris_os_run.py +0 -0
  107. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/benchmarks/load_neo4j.py +0 -0
  108. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/benchmarks/synthetic_baseline.csv +0 -0
  109. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/conftest.py +0 -0
  110. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/contract/__init__.py +0 -0
  111. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/contract/test_cypher_api.py +0 -0
  112. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/contract/test_cypher_api_errors.py +0 -0
  113. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/contract/test_graphql_queries.py +0 -0
  114. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/contract/test_graphql_schema.py +0 -0
  115. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/contract/test_ppr_api.py +0 -0
  116. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/curl_suite.sh +0 -0
  117. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/__init__.py +0 -0
  118. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/conftest.py +0 -0
  119. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_biomedical_demo.py +0 -0
  120. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_biomedical_ui.py +0 -0
  121. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_cypher_coerce_e2e.py +0 -0
  122. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_cypher_sprints_e2e.py +0 -0
  123. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_cypher_vector_search.py +0 -0
  124. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_fhir_bridges_e2e.py +0 -0
  125. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_fraud_demo.py +0 -0
  126. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_fraud_ui.py +0 -0
  127. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_gql_autogen_startup.py +0 -0
  128. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_gql_cypher_passthrough.py +0 -0
  129. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_gql_node_queries.py +0 -0
  130. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_gql_semantic_search.py +0 -0
  131. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_gql_traversal.py +0 -0
  132. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_graph_kernels_e2e.py +0 -0
  133. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_hla_kg_e2e.py +0 -0
  134. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_multi_query_engine_platform.py +0 -0
  135. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_named_paths_e2e.py +0 -0
  136. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_nkg_index_e2e.py +0 -0
  137. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_operator_wiring_e2e.py +0 -0
  138. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_plaid_search_e2e.py +0 -0
  139. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_ppr_cls_fast_path.py +0 -0
  140. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_ppr_guided_e2e.py +0 -0
  141. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_procedure_installation.py +0 -0
  142. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_reification_e2e.py +0 -0
  143. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_schema_procedures_e2e.py +0 -0
  144. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_subgraph_e2e.py +0 -0
  145. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_subquery_call_e2e.py +0 -0
  146. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/e2e/test_vecindex_e2e.py +0 -0
  147. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/__init__.py +0 -0
  148. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/conftest.py +0 -0
  149. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/gql/__init__.py +0 -0
  150. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/gql/test_graphql_mutations.py +0 -0
  151. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/gql/test_graphql_nested_queries.py +0 -0
  152. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/gql/test_graphql_queries.py +0 -0
  153. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/gql/test_graphql_vector_search.py +0 -0
  154. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_bidirectional_ppr.py +0 -0
  155. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_cls_layer.py +0 -0
  156. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_cypher_advanced.py +0 -0
  157. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_cypher_enhancements.py +0 -0
  158. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_cypher_multi_type.py +0 -0
  159. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_cypher_rd.py +0 -0
  160. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_cypher_rel_vars.py +0 -0
  161. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_cypher_single_type.py +0 -0
  162. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_cypher_untyped.py +0 -0
  163. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_cypher_vector_search.py +0 -0
  164. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_embeddings_api.py +0 -0
  165. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_fastapi_graphql.py +0 -0
  166. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_fhir_bridges_integration.py +0 -0
  167. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_named_paths_integration.py +0 -0
  168. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_nodepk_advanced_benchmarks.py +0 -0
  169. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_nodepk_constraints.py +0 -0
  170. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_nodepk_graph_analytics.py +0 -0
  171. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_nodepk_migration.py +0 -0
  172. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_nodepk_performance.py +0 -0
  173. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_nodepk_production_scale.py +0 -0
  174. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_objectscript_classes.py +0 -0
  175. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_pagerank_sql_optimization.py +0 -0
  176. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_reification_integration.py +0 -0
  177. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_schema_migration.py +0 -0
  178. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_stored_procedure_install.py +0 -0
  179. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/integration/test_subquery_call_integration.py +0 -0
  180. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/performance/conftest.py +0 -0
  181. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/performance/scale_benchmark.py +0 -0
  182. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/performance/test_ppr_stress.py +0 -0
  183. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/performance/test_stress_v1_5.py +0 -0
  184. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/python/run_all_tests.py +0 -0
  185. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/python/test_iris_rest_api.py +0 -0
  186. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/python/test_networkx_loader.py +0 -0
  187. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/python/test_performance_benchmarks.py +0 -0
  188. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/python/test_pyops_vector_conversion.py +0 -0
  189. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/python/test_python_operators.py +0 -0
  190. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/python/test_python_sdk.py +0 -0
  191. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/python/test_schema_validation.py +0 -0
  192. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/python/test_sql_queries.py +0 -0
  193. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/python/test_vector_functions.py +0 -0
  194. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/cypher/__init__.py +0 -0
  195. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/cypher/test_lexer.py +0 -0
  196. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/cypher/test_lexer_advanced.py +0 -0
  197. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/cypher/test_parser.py +0 -0
  198. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/cypher/test_parser_advanced.py +0 -0
  199. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_batch_mutations.py +0 -0
  200. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_bfs_arno.py +0 -0
  201. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_bm25_index.py +0 -0
  202. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_bolt_server.py +0 -0
  203. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_cls_deployment.py +0 -0
  204. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_cypher_benchmark.py +0 -0
  205. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_cypher_benchmark_scale.py +0 -0
  206. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_cypher_case_when.py +0 -0
  207. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_cypher_functions.py +0 -0
  208. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_cypher_parser.py +0 -0
  209. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_cypher_posos_bugs.py +0 -0
  210. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_cypher_procedures.py +0 -0
  211. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_cypher_translator.py +0 -0
  212. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_cypher_union_exists.py +0 -0
  213. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_cypher_var_length.py +0 -0
  214. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_cypher_vector_search.py +0 -0
  215. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_edge_embeddings.py +0 -0
  216. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_edgeprop_ndjson.py +0 -0
  217. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_embedded.py +0 -0
  218. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_engine_dimension_fix.py +0 -0
  219. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_engine_embeddings.py +0 -0
  220. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_fhir_bridges.py +0 -0
  221. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_get_nodes.py +0 -0
  222. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_graph_kernels.py +0 -0
  223. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_graphql_dataloader.py +0 -0
  224. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_ingest_formats.py +0 -0
  225. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_ivf_index.py +0 -0
  226. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_named_graphs.py +0 -0
  227. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_named_paths.py +0 -0
  228. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_operators_wiring.py +0 -0
  229. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_plaid_search.py +0 -0
  230. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_ppr_guided_subgraph.py +0 -0
  231. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_reification.py +0 -0
  232. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_schema_init.py +0 -0
  233. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_schema_procedures.py +0 -0
  234. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_shortest_path.py +0 -0
  235. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_snapshot.py +0 -0
  236. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_sql_splitter.py +0 -0
  237. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_sql_table_bridge.py +0 -0
  238. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_subgraph.py +0 -0
  239. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_subquery_call.py +0 -0
  240. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_temporal_cypher.py +0 -0
  241. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_temporal_edges.py +0 -0
  242. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_unified_edge_store.py +0 -0
  243. {iris_vector_graph-1.63.0 → iris_vector_graph-1.63.2}/tests/unit/test_weighted_shortest_path.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iris-vector-graph
3
- Version: 1.63.0
3
+ Version: 1.63.2
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
@@ -23,14 +23,14 @@ Classifier: Topic :: Database
23
23
  Classifier: Topic :: Scientific/Engineering
24
24
  Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
25
25
  Requires-Python: >=3.10
26
- Requires-Dist: intersystems-irispython>=3.2.0
26
+ Requires-Dist: intersystems-iris>=1.0.0
27
27
  Provides-Extra: biodata
28
28
  Requires-Dist: biopython>=1.81; extra == 'biodata'
29
29
  Requires-Dist: bioservices>=1.11.0; extra == 'biodata'
30
30
  Requires-Dist: mygene>=3.2.0; extra == 'biodata'
31
31
  Requires-Dist: obonet>=1.0.0; extra == 'biodata'
32
32
  Provides-Extra: core
33
- Requires-Dist: intersystems-irispython>=3.2.0; extra == 'core'
33
+ Requires-Dist: intersystems-iris>=1.0.0; extra == 'core'
34
34
  Provides-Extra: demo
35
35
  Requires-Dist: python-fasthtml>=0.12.0; extra == 'demo'
36
36
  Provides-Extra: dev
@@ -655,6 +655,14 @@ anchors = engine.get_kg_anchors(icd_codes=["J18.0", "E11.9"])
655
655
 
656
656
  ## Changelog
657
657
 
658
+ ### v1.63.2 (2026-04-25)
659
+ - fix: `MATCH (a)-[r*1..N]-(b)` undirected BFS now traverses `^KG("in",...)` for inbound edges (was outbound-only)
660
+ - fix: `MATCH (a)<-[r*1..N]-(b)` inbound-only BFS now works
661
+ - fix: `initialize_schema()` ObjectScript LoadDir tries Docker `/tmp/src/` before Mac path — fixes silent compile failure in test containers
662
+ - 4 E2E tests: directed-out, undirected, multihop undirected, directed-in all passing
663
+ - Arno BFSJson falls back gracefully to BFSFastJson for graphs >3.5MB adjacency string (299K+ long-ID edges); per-seed export is spec 079 future work
664
+
665
+
658
666
  ### v1.63.0 (2026-04-25)
659
667
  - feat: Arno/Rust fast path for BFS (`_execute_var_length_cypher`) — when `libarno_callout.so` is loaded with `Graph.KG.NKGAccel.BFSJson`, var-length Cypher queries use Rust BFS over `^NKG` integer adjacency instead of ObjectScript `BFSFastJson`. Projected 128ms → <30ms p50 for 6K+ result BFS at 10K/50K scale. Falls back transparently to `BFSFastJson` when Arno not loaded. (spec 079, arno spec 035)
660
668
 
@@ -583,6 +583,14 @@ anchors = engine.get_kg_anchors(icd_codes=["J18.0", "E11.9"])
583
583
 
584
584
  ## Changelog
585
585
 
586
+ ### v1.63.2 (2026-04-25)
587
+ - fix: `MATCH (a)-[r*1..N]-(b)` undirected BFS now traverses `^KG("in",...)` for inbound edges (was outbound-only)
588
+ - fix: `MATCH (a)<-[r*1..N]-(b)` inbound-only BFS now works
589
+ - fix: `initialize_schema()` ObjectScript LoadDir tries Docker `/tmp/src/` before Mac path — fixes silent compile failure in test containers
590
+ - 4 E2E tests: directed-out, undirected, multihop undirected, directed-in all passing
591
+ - Arno BFSJson falls back gracefully to BFSFastJson for graphs >3.5MB adjacency string (299K+ long-ID edges); per-seed export is spec 079 future work
592
+
593
+
586
594
  ### v1.63.0 (2026-04-25)
587
595
  - feat: Arno/Rust fast path for BFS (`_execute_var_length_cypher`) — when `libarno_callout.so` is loaded with `Graph.KG.NKGAccel.BFSJson`, var-length Cypher queries use Rust BFS over `^NKG` integer adjacency instead of ObjectScript `BFSFastJson`. Projected 128ms → <30ms p50 for 6K+ result BFS at 10K/50K scale. Falls back transparently to `BFSFastJson` when Arno not loaded. (spec 079, arno spec 035)
588
596
 
@@ -151,8 +151,9 @@ ClassMethod TraverseAllPredicates(s As %String, hop As %Integer, maxHops As %Int
151
151
  }
152
152
 
153
153
  /// Optimized BFS using Process-Private Globals and $ListBuild to bypass object bottleneck
154
+ /// @param direction "out" (default), "in", or "both" for undirected BFS
154
155
  /// @returns Number of edges found. Results are in ^||BFS.Results(i) = $lb(s, p, o, w, step)
155
- ClassMethod BFSFast(srcId As %String, preds As %DynamicArray = "", maxHops As %Integer = 2, dstLabel As %String = "") As %Integer
156
+ ClassMethod BFSFast(srcId As %String, preds As %DynamicArray = "", maxHops As %Integer = 2, dstLabel As %String = "", direction As %String = "out") As %Integer
156
157
  {
157
158
  Kill ^||BFS.Results
158
159
  If (srcId = "") || (maxHops <= 0) Return 0
@@ -171,10 +172,20 @@ ClassMethod BFSFast(srcId As %String, preds As %DynamicArray = "", maxHops As %I
171
172
  Set s = $Order(frontier(s))
172
173
  If s = "" Quit
173
174
 
174
- If fixedP '= "" {
175
- Do ..TraverseWithPredicateFast(s, fixedP, hop, maxHops, nextP, dstLabel, .count, .nextFrontier, .seen)
176
- } Else {
177
- Do ..TraverseAllPredicatesFast(s, hop, maxHops, nextP, dstLabel, .count, .nextFrontier, .seen)
175
+ If direction = "out" || (direction = "both") {
176
+ If fixedP '= "" {
177
+ Do ..TraverseWithPredicateFast(s, fixedP, hop, maxHops, nextP, dstLabel, .count, .nextFrontier, .seen)
178
+ } Else {
179
+ Do ..TraverseAllPredicatesFast(s, hop, maxHops, nextP, dstLabel, .count, .nextFrontier, .seen)
180
+ }
181
+ }
182
+
183
+ If direction = "in" || (direction = "both") {
184
+ If fixedP '= "" {
185
+ Do ..TraverseWithPredicateFastInbound(s, fixedP, hop, .count, .nextFrontier, .seen)
186
+ } Else {
187
+ Do ..TraverseAllPredicatesFastInbound(s, hop, .count, .nextFrontier, .seen)
188
+ }
178
189
  }
179
190
  }
180
191
 
@@ -216,6 +227,30 @@ ClassMethod TraverseAllPredicatesFast(s As %String, hop As %Integer, maxHops As
216
227
  }
217
228
  }
218
229
 
230
+ /// Inbound BFS: traverse ^KG("in", 0, s, p, o) where s is the target, o is the source.
231
+ /// Result stored as (o, p, s) to preserve original edge direction.
232
+ ClassMethod TraverseWithPredicateFastInbound(s As %String, p As %String, hop As %Integer, ByRef count As %Integer, ByRef nextFrontier, ByRef seen) [ Internal, Private ]
233
+ {
234
+ Set o = ""
235
+ For {
236
+ Set o = $Order(^KG("in", 0, s, p, o))
237
+ If o = "" Quit
238
+ Set count = count + 1
239
+ Set ^||BFS.Results(count) = $ListBuild(s, p, o, $Get(^KG("out", 0, o, p, s), 1.0), hop)
240
+ If '$Data(seen(o)) Set nextFrontier(o) = ""
241
+ }
242
+ }
243
+
244
+ ClassMethod TraverseAllPredicatesFastInbound(s As %String, hop As %Integer, ByRef count As %Integer, ByRef nextFrontier, ByRef seen) [ Internal, Private ]
245
+ {
246
+ Set p = ""
247
+ For {
248
+ Set p = $Order(^KG("in", 0, s, p))
249
+ If p = "" Quit
250
+ Do ..TraverseWithPredicateFastInbound(s, p, hop, .count, .nextFrontier, .seen)
251
+ }
252
+ }
253
+
219
254
  /// Main BFS implementation
220
255
  ClassMethod BFS(srcId As %String, preds As %DynamicArray = "", maxHops As %Integer = 2, dstLabel As %String = "") As %DynamicArray
221
256
  {
@@ -287,7 +322,7 @@ ClassMethod BFSJSON(srcId As %String, preds As %DynamicArray, maxHops As %Intege
287
322
  /// @param maxHops Maximum hops (default 2)
288
323
  /// @param dstLabel Filter destination nodes by label (empty = no filter)
289
324
  /// @returns JSON array: [{"s":..,"p":..,"o":..,"w":..,"step":..}, ...] in traversal order
290
- ClassMethod BFSFastJson(srcId As %String, predsJson As %String = "", maxHops As %Integer = 2, dstLabel As %String = "") As %String
325
+ ClassMethod BFSFastJson(srcId As %String, predsJson As %String = "", maxHops As %Integer = 2, dstLabel As %String = "", direction As %String = "out") As %String
291
326
  {
292
327
  // Parse predicates JSON into a %DynamicArray (null/"" means all predicates)
293
328
  Set preds = ""
@@ -300,7 +335,7 @@ ClassMethod BFSFastJson(srcId As %String, predsJson As %String = "", maxHops As
300
335
  }
301
336
 
302
337
  // Run BFSFast -- writes to ^||BFS.Results(i) = $ListBuild(s,p,o,w,step)
303
- Set count = ..BFSFast(srcId, preds, maxHops, dstLabel)
338
+ Set count = ..BFSFast(srcId, preds, maxHops, dstLabel, direction)
304
339
 
305
340
  If count = 0 Return "[]"
306
341
 
@@ -273,8 +273,8 @@ class BulkLoader:
273
273
  Must be called after load_edges(use_noindex=True).
274
274
  Also rebuilds bitmap extent indexes for correct COUNT(*).
275
275
  """
276
- import intersystems_iris
277
- iris_obj = intersystems_iris.createIRIS(self.conn)
276
+ import iris
277
+ iris_obj = iris.createIRIS(self.conn)
278
278
  results = {}
279
279
 
280
280
  for cls in ["Graph.KG.rdfedges", "Graph.KG.rdflabels", "Graph.KG.rdfprops", "Graph.KG.nodes"]:
@@ -301,8 +301,8 @@ class BulkLoader:
301
301
  Returns True if successful.
302
302
  """
303
303
  try:
304
- import intersystems_iris
305
- iris_obj = intersystems_iris.createIRIS(self.conn)
304
+ import iris
305
+ iris_obj = iris.createIRIS(self.conn)
306
306
  logger.info("Building ^KG + ^NKG globals from SQL tables...")
307
307
  t0 = time.time()
308
308
  iris_obj.classMethodVoid("Graph.KG.Traversal", "BuildKG")
@@ -422,7 +422,7 @@ def main():
422
422
  logger.info(f"Graph: {G.number_of_nodes():,} nodes, {G.number_of_edges():,} edges")
423
423
 
424
424
 
425
- from intersystems_iris.dbapi._DBAPI import connect
425
+ from iris.dbapi._DBAPI import connect # intersystems_iris.dbapi = iris.dbapi
426
426
  conn = connect(args.host, args.port, args.namespace, args.user, args.password)
427
427
  logger.info(f"Connected to IRIS {args.host}:{args.port}/{args.namespace}")
428
428
 
@@ -1744,6 +1744,9 @@ def translate_relationship_pattern(
1744
1744
  def _resolve_id_param(node):
1745
1745
  id_val = node.properties.get("id")
1746
1746
  if id_val is None:
1747
+ if node.variable and node.variable in context.input_params:
1748
+ val = context.input_params[node.variable]
1749
+ return f"${node.variable}" if isinstance(val, str) else None
1747
1750
  return None
1748
1751
  if isinstance(id_val, ast.Variable):
1749
1752
  return f"${id_val.name}"
@@ -1756,7 +1759,7 @@ def translate_relationship_pattern(
1756
1759
  src_id_param = _resolve_id_param(source_node)
1757
1760
  dst_id_param = _resolve_id_param(target_node)
1758
1761
 
1759
- direction_str = "both" if rel.direction == ast.Direction.BOTH else "out"
1762
+ direction_str = "both" if rel.direction == ast.Direction.BOTH else ("in" if rel.direction == ast.Direction.INCOMING else "out")
1760
1763
 
1761
1764
  context.var_length_paths.append(
1762
1765
  {
@@ -1025,6 +1025,31 @@ class IRISGraphEngine:
1025
1025
  source_id = _resolve(vl.get("src_id_param"))
1026
1026
  target_id = _resolve(vl.get("dst_id_param"))
1027
1027
 
1028
+ if source_id is None and parameters:
1029
+ src_var = vl.get("source_var")
1030
+ if src_var and src_var in parameters:
1031
+ source_id = str(parameters[src_var])
1032
+ else:
1033
+ source_id = next(
1034
+ (str(v) for v in parameters.values() if isinstance(v, str)), None
1035
+ )
1036
+
1037
+ if target_id is None and parameters:
1038
+ dst_var = vl.get("target_var")
1039
+ if dst_var and dst_var in parameters:
1040
+ target_id = str(parameters[dst_var])
1041
+ else:
1042
+ vals = [str(v) for v in parameters.values() if isinstance(v, str)]
1043
+ target_id = vals[1] if len(vals) > 1 else None
1044
+
1045
+ if source_id is None or target_id is None:
1046
+ sql_params = sql_query.parameters[0] if sql_query.parameters else []
1047
+ str_params = [p for p in sql_params if isinstance(p, str) and not p.startswith("Graph_KG")]
1048
+ if source_id is None and len(str_params) >= 1:
1049
+ source_id = str_params[0]
1050
+ if target_id is None and len(str_params) >= 2:
1051
+ target_id = str_params[1]
1052
+
1028
1053
  if source_id is None or target_id is None:
1029
1054
  raise ValueError(
1030
1055
  "shortestPath requires both source and target node IDs to be bound. "
@@ -1131,7 +1156,11 @@ class IRISGraphEngine:
1131
1156
  source_id = item
1132
1157
  break
1133
1158
  if source_id is None and parameters:
1134
- source_id = next(iter(parameters.values()), None)
1159
+ src_var = vl.get("source_var")
1160
+ if src_var and src_var in parameters:
1161
+ source_id = str(parameters[src_var])
1162
+ else:
1163
+ source_id = next(iter(parameters.values()), None)
1135
1164
 
1136
1165
  if source_id is None:
1137
1166
  return {
@@ -1177,6 +1206,7 @@ class IRISGraphEngine:
1177
1206
  predicates_json,
1178
1207
  max_hops,
1179
1208
  "",
1209
+ vl.get("direction", "out"),
1180
1210
  )
1181
1211
  bfs_results = _json.loads(str(bfs_json)) if bfs_json else []
1182
1212
  except Exception as e:
@@ -1214,9 +1244,14 @@ class IRISGraphEngine:
1214
1244
  seen.add(oid)
1215
1245
  target_ids.append(oid)
1216
1246
 
1247
+ import re as _re
1248
+ sql_str = sql_query.sql if isinstance(sql_query.sql, str) else ""
1249
+ alias_match = _re.search(r'SELECT\s+DISTINCT\s+\S+\s+AS\s+(\w+)|SELECT\s+\S+\s+AS\s+(\w+)', sql_str, _re.IGNORECASE)
1250
+ col_name = (alias_match.group(1) or alias_match.group(2)) if alias_match else "b_id"
1251
+
1217
1252
  if not target_ids:
1218
1253
  return {
1219
- "columns": ["b_id", "b_labels", "b_props"],
1254
+ "columns": [col_name, "b_labels", "b_props"],
1220
1255
  "rows": [],
1221
1256
  "sql": "",
1222
1257
  "params": [],
@@ -1236,7 +1271,7 @@ class IRISGraphEngine:
1236
1271
  )
1237
1272
 
1238
1273
  return {
1239
- "columns": ["b_id", "b_labels", "b_props"],
1274
+ "columns": [col_name, "b_labels", "b_props"],
1240
1275
  "rows": [list(r) for r in rows],
1241
1276
  "sql": f"BFSFastJson({source_id}, {predicates_json}, {max_hops})",
1242
1277
  "params": [],
@@ -4853,7 +4888,7 @@ class IRISGraphEngine:
4853
4888
  try:
4854
4889
  iris_obj = self._iris_obj()
4855
4890
  result = iris_obj.classMethodValue(
4856
- "Graph.KG.Traversal", "BFSFastJson", seed, "", hops, ""
4891
+ "Graph.KG.Traversal", "BFSFastJson", seed, "", hops, "", "out"
4857
4892
  )
4858
4893
  if result:
4859
4894
  edges = json.loads(str(result))
@@ -4916,9 +4951,9 @@ class IRISGraphEngine:
4916
4951
 
4917
4952
  return iris.createIRIS(self.conn)
4918
4953
  except (TypeError, AttributeError):
4919
- import intersystems_iris
4954
+ import iris
4920
4955
 
4921
- return intersystems_iris.createIRIS(self.conn)
4956
+ return iris.createIRIS(self.conn)
4922
4957
 
4923
4958
  def vec_create_index(
4924
4959
  self,
@@ -17,43 +17,18 @@ logger = logging.getLogger(__name__)
17
17
 
18
18
 
19
19
  def _call_classmethod(conn_or_cursor, class_name: str, method_name: str, *args) -> Any:
20
- """Call an IRIS ObjectScript class method using the native API.
21
-
22
- Works with both the ``iris`` package (iris.createIRIS) and the
23
- ``intersystems_iris`` package (intersystems_iris.createIRIS). Tries
24
- ``iris.createIRIS`` first because it accepts the connection objects
25
- returned by ``iris.connect()`` (the standard test-fixture connection).
26
-
27
- Resolves the connection from either a connection object directly or from
28
- ``cursor._connection`` if a cursor is passed.
29
-
30
- Returns the method's return value, or raises if the class/method does not
31
- exist or the native API is unavailable.
32
- """
33
- # Accept either a connection or a cursor
34
20
  if hasattr(conn_or_cursor, "cursor"):
35
- conn = conn_or_cursor # it's a connection
21
+ conn = conn_or_cursor
36
22
  elif hasattr(conn_or_cursor, "_connection"):
37
- conn = conn_or_cursor._connection # it's a cursor
23
+ conn = conn_or_cursor._connection
38
24
  else:
39
- conn = conn_or_cursor # best-effort fallback
40
-
41
- # Try iris.createIRIS first (accepts iris.IRISConnection from iris.connect())
42
- try:
43
- import iris as _iris_pkg # type: ignore[import]
44
-
45
- iris_obj = _iris_pkg.createIRIS(conn)
46
- return iris_obj.classMethodValue(class_name, method_name, *args)
47
- except (ImportError, AttributeError, TypeError):
48
- pass
49
-
50
- # Fall back to intersystems_iris.createIRIS (accepts intersystems_iris.IRISConnection)
51
- import intersystems_iris as _iris_pkg2 # type: ignore[import]
52
-
53
- iris_obj = _iris_pkg2.createIRIS(conn)
25
+ conn = conn_or_cursor
26
+ import iris as _iris_pkg
27
+ iris_obj = _iris_pkg.createIRIS(conn)
54
28
  return iris_obj.classMethodValue(class_name, method_name, *args)
55
29
 
56
30
 
31
+
57
32
  class GraphSchema:
58
33
  """Domain-agnostic RDF-style graph schema management"""
59
34
 
@@ -782,7 +757,7 @@ LANGUAGE OBJECTSCRIPT
782
757
 
783
758
  src_dir = str(iris_src_path / "src") if iris_src_path else ""
784
759
  deployed = False
785
- for candidate_dir in [src_dir, "/tmp/src/", "/irisdev/app/iris_src/src/"]:
760
+ for candidate_dir in ["/tmp/src/", "/irisdev/app/iris_src/src/", src_dir]:
786
761
  if not candidate_dir:
787
762
  continue
788
763
  try:
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "iris-vector-graph"
7
- version = "1.63.0"
7
+ version = "1.63.2"
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"
@@ -38,12 +38,12 @@ requires-python = ">=3.10"
38
38
 
39
39
  # Core dependencies
40
40
  dependencies = [
41
- "intersystems-irispython>=3.2.0",
41
+ "intersystems-iris>=1.0.0",
42
42
  ]
43
43
 
44
44
  [project.optional-dependencies]
45
45
  core = [
46
- "intersystems-irispython>=3.2.0",
46
+ "intersystems-iris>=1.0.0",
47
47
  ]
48
48
  full = [
49
49
  "numpy>=1.24.0",
@@ -457,3 +457,98 @@ class TestCypherRound2E2E:
457
457
  q = "MATCH (n) WHERE n.id = $id CALL ivg.vector.search('Gene','embedding',[0.1,0.2,0.3,0.4],5) YIELD node, score RETURN n.id, node, score"
458
458
  r = translate_to_sql(parse_query(q), {"id": "x"})
459
459
  assert r.var_length_paths is not None or r.sql is not None
460
+
461
+
462
+ @pytest.mark.skipif(SKIP_IRIS_TESTS, reason="SKIP_IRIS_TESTS=true")
463
+ class TestUndirectedBFSE2E:
464
+
465
+ @pytest.fixture(autouse=True)
466
+ def setup(self, iris_connection):
467
+ from iris_vector_graph.engine import IRISGraphEngine
468
+ self.conn = iris_connection
469
+ self.engine = IRISGraphEngine(iris_connection, embedding_dimension=4)
470
+ self.engine.initialize_schema()
471
+ self._run = uuid.uuid4().hex[:8]
472
+ self._nodes = []
473
+ yield
474
+ cursor = self.conn.cursor()
475
+ for nid in self._nodes:
476
+ try:
477
+ cursor.execute("DELETE FROM Graph_KG.rdf_edges WHERE s=? OR o_id=?", [nid, nid])
478
+ cursor.execute("DELETE FROM Graph_KG.rdf_labels WHERE s=?", [nid])
479
+ cursor.execute("DELETE FROM Graph_KG.nodes WHERE node_id=?", [nid])
480
+ except Exception:
481
+ pass
482
+ try:
483
+ self.conn.commit()
484
+ except Exception:
485
+ self.conn.rollback()
486
+
487
+ def _node(self, suffix):
488
+ nid = f"ubfs_{self._run}_{suffix}"
489
+ self._nodes.append(nid)
490
+ self.engine.create_node(nid, labels=["Gene"])
491
+ return nid
492
+
493
+ def _edge(self, s, p, o):
494
+ self.engine.create_edge(s, p, o)
495
+
496
+ def test_directed_out_returns_outbound_only(self):
497
+ a = self._node("A")
498
+ b = self._node("B")
499
+ c = self._node("C")
500
+ self._edge(a, "REL", b)
501
+ self._edge(c, "REL", a)
502
+
503
+ result = self.engine.execute_cypher(
504
+ "MATCH (x)-[r*1..1]->(y) WHERE x.id = $id RETURN y.id",
505
+ {"id": a},
506
+ )
507
+ ids = {row[0] for row in result["rows"]}
508
+ assert b in ids
509
+ assert c not in ids
510
+
511
+ def test_undirected_returns_both_inbound_and_outbound(self):
512
+ a = self._node("hub")
513
+ b = self._node("outbound")
514
+ c = self._node("inbound")
515
+ self._edge(a, "REL", b)
516
+ self._edge(c, "REL", a)
517
+
518
+ result = self.engine.execute_cypher(
519
+ "MATCH (x)-[r*1..1]-(y) WHERE x.id = $id RETURN y.id",
520
+ {"id": a},
521
+ )
522
+ ids = {row[0] for row in result["rows"]}
523
+ assert b in ids, f"outbound neighbor missing: {ids}"
524
+ assert c in ids, f"inbound neighbor missing: {ids}"
525
+
526
+ def test_undirected_multihop(self):
527
+ a = self._node("mh_a")
528
+ b = self._node("mh_b")
529
+ c = self._node("mh_c")
530
+ self._edge(b, "REL", a)
531
+ self._edge(b, "REL", c)
532
+
533
+ result = self.engine.execute_cypher(
534
+ "MATCH (x)-[r*1..2]-(y) WHERE x.id = $id RETURN y.id",
535
+ {"id": a},
536
+ )
537
+ ids = {row[0] for row in result["rows"]}
538
+ assert b in ids
539
+ assert c in ids
540
+
541
+ def test_directed_in_returns_inbound_only(self):
542
+ a = self._node("tgt")
543
+ b = self._node("src")
544
+ c = self._node("other")
545
+ self._edge(b, "REL", a)
546
+ self._edge(a, "REL", c)
547
+
548
+ result = self.engine.execute_cypher(
549
+ "MATCH (x)<-[r*1..1]-(y) WHERE x.id = $id RETURN y.id",
550
+ {"id": a},
551
+ )
552
+ ids = {row[0] for row in result["rows"]}
553
+ assert b in ids, f"inbound src missing: {ids}"
554
+ assert c not in ids, f"outbound dst should not appear: {ids}"