iris-vector-graph 1.63.2__tar.gz → 1.63.3__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.
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/PKG-INFO +45 -1
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/README.md +44 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/Traversal.cls +21 -3
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/__init__.py +1 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/engine.py +143 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/security.py +4 -1
- iris_vector_graph-1.63.3/iris_vector_graph/status.py +136 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/pyproject.toml +1 -1
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_e2e_new_features.py +81 -0
- iris_vector_graph-1.63.3/tests/unit/test_engine_status.py +192 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/.gitignore +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/LICENSE +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/demo_biomedical.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/demo_fraud_detection.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/demo_fraud_detection_sql.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/demo_utils.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/demo_working_system.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/__init__.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/biomedical/__init__.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/biomedical/loaders.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/biomedical/resolver.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/biomedical/types.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/biomedical_legacy/__init__.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/biomedical_legacy/biomedical_engine.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/biomedical_legacy/biomedical_schema.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/biomedical_legacy/legacy_wrapper.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/fraud/__init__.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/fraud/loaders.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/fraud/resolver.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/domains/fraud/types.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/graphQL.http +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/hybrid_vector_graph_query.cypher +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/examples/rest.http +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/Algorithms.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/ArnoAccel.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/BM25Index.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/BenchFormat.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/BenchSeeder.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/Benchmark.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/Edge.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/EdgeScan.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/GraphIndex.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/IVFIndex.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/Loader.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/MCPService.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/MCPToolSet.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/MCPTools.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/Meta.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/PLAIDSearch.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/PageRank.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/PyOps.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/Service.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/Snapshot.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/Subgraph.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/TemporalIndex.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/TestEdge.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/Graph/KG/VecIndex.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/PageRankEmbedded.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/User.Exec.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_src/src/iris/vector/graph/GraphOperators.cls +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/bolt_server.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/bulk_loader.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/capabilities.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/cypher/__init__.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/cypher/algorithms/__init__.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/cypher/algorithms/paths.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/cypher/ast.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/cypher/lexer.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/cypher/parser.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/cypher/translator.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/cypher_api.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/embedded.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/fusion.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/gql/__init__.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/gql/constants.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/gql/engine.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/gql/pooling.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/gql/resolvers.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/gql/schema.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/models.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/operators.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/py.typed +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/schema.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/text_search.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/utils.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/iris_vector_graph/vector_utils.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/fhir_bridges.sql +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/fraud_sample_data.sql +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/globals_schema.sql +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/graph_path_globals.sql +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/graph_walk_tvf.sql +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/migrations/000_base_schema_iris.sql +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/migrations/001_add_nodepk_table.sql +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/migrations/001_rollback_nodepk.sql +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/migrations/002_add_fk_constraints.sql +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/operators.sql +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/operators_fixed.sql +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/procedures/kg_PageRank.sql +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/rdf_reifications.sql +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/sql/schema.sql +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/TESTING.md +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/benchmark_parser.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/benchmarks/benchmark_neo4j.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/benchmarks/bfs_benchmark.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/benchmarks/establish_baseline.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/benchmarks/graph_gen.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/benchmarks/iris_baseline_run.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/benchmarks/iris_os_run.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/benchmarks/load_neo4j.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/benchmarks/synthetic_baseline.csv +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/conftest.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/contract/__init__.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/contract/test_cypher_api.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/contract/test_cypher_api_errors.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/contract/test_graphql_queries.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/contract/test_graphql_schema.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/contract/test_ppr_api.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/curl_suite.sh +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/__init__.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/conftest.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_biomedical_demo.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_biomedical_ui.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_cypher_coerce_e2e.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_cypher_sprints_e2e.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_cypher_vector_search.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_fhir_bridges_e2e.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_fraud_demo.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_fraud_ui.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_gql_autogen_startup.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_gql_cypher_passthrough.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_gql_node_queries.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_gql_semantic_search.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_gql_traversal.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_graph_kernels_e2e.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_hla_kg_e2e.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_multi_query_engine_platform.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_named_paths_e2e.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_nkg_index_e2e.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_operator_wiring_e2e.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_plaid_search_e2e.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_ppr_cls_fast_path.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_ppr_guided_e2e.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_procedure_installation.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_reification_e2e.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_schema_procedures_e2e.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_subgraph_e2e.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_subquery_call_e2e.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/e2e/test_vecindex_e2e.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/__init__.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/conftest.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/gql/__init__.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/gql/test_graphql_mutations.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/gql/test_graphql_nested_queries.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/gql/test_graphql_queries.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/gql/test_graphql_vector_search.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_bidirectional_ppr.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_cls_layer.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_cypher_advanced.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_cypher_enhancements.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_cypher_multi_type.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_cypher_rd.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_cypher_rel_vars.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_cypher_single_type.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_cypher_untyped.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_cypher_vector_search.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_embeddings_api.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_fastapi_graphql.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_fhir_bridges_integration.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_named_paths_integration.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_nodepk_advanced_benchmarks.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_nodepk_constraints.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_nodepk_graph_analytics.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_nodepk_migration.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_nodepk_performance.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_nodepk_production_scale.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_objectscript_classes.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_pagerank_sql_optimization.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_reification_integration.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_schema_migration.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_stored_procedure_install.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/integration/test_subquery_call_integration.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/performance/conftest.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/performance/scale_benchmark.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/performance/test_ppr_stress.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/performance/test_stress_v1_5.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/python/run_all_tests.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/python/test_iris_rest_api.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/python/test_networkx_loader.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/python/test_performance_benchmarks.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/python/test_pyops_vector_conversion.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/python/test_python_operators.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/python/test_python_sdk.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/python/test_schema_validation.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/python/test_sql_queries.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/python/test_vector_functions.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/cypher/__init__.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/cypher/test_lexer.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/cypher/test_lexer_advanced.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/cypher/test_parser.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/cypher/test_parser_advanced.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_batch_mutations.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_bfs_arno.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_bm25_index.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_bolt_server.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cls_deployment.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_benchmark.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_benchmark_scale.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_case_when.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_functions.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_parser.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_posos_bugs.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_procedures.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_translator.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_union_exists.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_var_length.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_vector_search.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_edge_embeddings.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_edgeprop_ndjson.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_embedded.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_engine_dimension_fix.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_engine_embeddings.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_fhir_bridges.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_get_nodes.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_graph_kernels.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_graphql_dataloader.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_ingest_formats.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_ivf_index.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_named_graphs.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_named_paths.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_operators_wiring.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_plaid_search.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_ppr_guided_subgraph.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_reification.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_schema_init.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_schema_procedures.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_shortest_path.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_snapshot.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_sql_splitter.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_sql_table_bridge.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_subgraph.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_subquery_call.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_temporal_cypher.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_temporal_edges.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_unified_edge_store.py +0 -0
- {iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/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.
|
|
3
|
+
Version: 1.63.3
|
|
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
|
|
@@ -407,6 +407,43 @@ Returns `[{"s": str, "p": str, "o_id": str, "score": float}, ...]` sorted descen
|
|
|
407
407
|
|
|
408
408
|
---
|
|
409
409
|
|
|
410
|
+
## Engine Status
|
|
411
|
+
|
|
412
|
+
Call `engine.status()` at any time to get a structured snapshot of all components. This is the canonical answer to "why is query X returning nothing?"
|
|
413
|
+
|
|
414
|
+
```python
|
|
415
|
+
s = engine.status()
|
|
416
|
+
print(s.report())
|
|
417
|
+
|
|
418
|
+
# Readiness gates — use before running query types
|
|
419
|
+
s.ready_for_bfs # var-length / undirected / shortestPath — needs ^KG + edges
|
|
420
|
+
s.ready_for_vector_search # needs node embeddings
|
|
421
|
+
s.ready_for_edge_search # needs edge embeddings
|
|
422
|
+
s.ready_for_full_text # needs BM25 index
|
|
423
|
+
|
|
424
|
+
# Example: rebuild ^KG if stale
|
|
425
|
+
if not s.ready_for_bfs and s.tables.edges > 0:
|
|
426
|
+
engine.build_graph_globals() # calls BuildKG()
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
Sample output:
|
|
430
|
+
```
|
|
431
|
+
IVG Engine Status
|
|
432
|
+
══════════════════════════════════════════
|
|
433
|
+
SQL Tables (probe: 23ms)
|
|
434
|
+
nodes 10,000
|
|
435
|
+
edges 50,000
|
|
436
|
+
...
|
|
437
|
+
Adjacency Globals
|
|
438
|
+
✓ ^KG (50,000 source nodes indexed)
|
|
439
|
+
✗ ^NKG (Arno integer index)
|
|
440
|
+
...
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
`status()` is explicit-call only — never run automatically at init or before queries. Cost ~50ms.
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
410
447
|
## PLAID Multi-Vector Search
|
|
411
448
|
|
|
412
449
|
```python
|
|
@@ -655,6 +692,13 @@ anchors = engine.get_kg_anchors(icd_codes=["J18.0", "E11.9"])
|
|
|
655
692
|
|
|
656
693
|
## Changelog
|
|
657
694
|
|
|
695
|
+
### v1.63.3 (2026-04-26)
|
|
696
|
+
- feat: `engine.status() -> EngineStatus` — structured runtime snapshot: SQL row counts, `^KG`/`^NKG` population, ObjectScript classes, Arno capabilities, HNSW/IVF/BM25/PLAID index inventory. Readiness properties: `ready_for_bfs`, `ready_for_vector_search`, `ready_for_edge_search`, `ready_for_full_text`. Detects `^KG`/`rdf_edges` predicate mismatch (stale ^KG from different data snapshot). (spec 080)
|
|
697
|
+
- fix: `BuildKG()` `Traversal.cls` SQL cursors now use fully-qualified `Graph_KG.rdf_edges`, `Graph_KG.rdf_labels`, `Graph_KG.rdf_props` — fixes predicate mismatch when IRIS namespace default SQL schema is not `Graph_KG` (e.g. MINDWALK namespace with `SQLUser` default)
|
|
698
|
+
- fix: `kg_IVFMeta`, `kg_BM25Meta`, `kg_PlaidMeta` added to security allowlist
|
|
699
|
+
- `EngineStatus` exported from top-level `iris_vector_graph`
|
|
700
|
+
|
|
701
|
+
|
|
658
702
|
### v1.63.2 (2026-04-25)
|
|
659
703
|
- fix: `MATCH (a)-[r*1..N]-(b)` undirected BFS now traverses `^KG("in",...)` for inbound edges (was outbound-only)
|
|
660
704
|
- fix: `MATCH (a)<-[r*1..N]-(b)` inbound-only BFS now works
|
|
@@ -335,6 +335,43 @@ Returns `[{"s": str, "p": str, "o_id": str, "score": float}, ...]` sorted descen
|
|
|
335
335
|
|
|
336
336
|
---
|
|
337
337
|
|
|
338
|
+
## Engine Status
|
|
339
|
+
|
|
340
|
+
Call `engine.status()` at any time to get a structured snapshot of all components. This is the canonical answer to "why is query X returning nothing?"
|
|
341
|
+
|
|
342
|
+
```python
|
|
343
|
+
s = engine.status()
|
|
344
|
+
print(s.report())
|
|
345
|
+
|
|
346
|
+
# Readiness gates — use before running query types
|
|
347
|
+
s.ready_for_bfs # var-length / undirected / shortestPath — needs ^KG + edges
|
|
348
|
+
s.ready_for_vector_search # needs node embeddings
|
|
349
|
+
s.ready_for_edge_search # needs edge embeddings
|
|
350
|
+
s.ready_for_full_text # needs BM25 index
|
|
351
|
+
|
|
352
|
+
# Example: rebuild ^KG if stale
|
|
353
|
+
if not s.ready_for_bfs and s.tables.edges > 0:
|
|
354
|
+
engine.build_graph_globals() # calls BuildKG()
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
Sample output:
|
|
358
|
+
```
|
|
359
|
+
IVG Engine Status
|
|
360
|
+
══════════════════════════════════════════
|
|
361
|
+
SQL Tables (probe: 23ms)
|
|
362
|
+
nodes 10,000
|
|
363
|
+
edges 50,000
|
|
364
|
+
...
|
|
365
|
+
Adjacency Globals
|
|
366
|
+
✓ ^KG (50,000 source nodes indexed)
|
|
367
|
+
✗ ^NKG (Arno integer index)
|
|
368
|
+
...
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
`status()` is explicit-call only — never run automatically at init or before queries. Cost ~50ms.
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
338
375
|
## PLAID Multi-Vector Search
|
|
339
376
|
|
|
340
377
|
```python
|
|
@@ -583,6 +620,13 @@ anchors = engine.get_kg_anchors(icd_codes=["J18.0", "E11.9"])
|
|
|
583
620
|
|
|
584
621
|
## Changelog
|
|
585
622
|
|
|
623
|
+
### v1.63.3 (2026-04-26)
|
|
624
|
+
- feat: `engine.status() -> EngineStatus` — structured runtime snapshot: SQL row counts, `^KG`/`^NKG` population, ObjectScript classes, Arno capabilities, HNSW/IVF/BM25/PLAID index inventory. Readiness properties: `ready_for_bfs`, `ready_for_vector_search`, `ready_for_edge_search`, `ready_for_full_text`. Detects `^KG`/`rdf_edges` predicate mismatch (stale ^KG from different data snapshot). (spec 080)
|
|
625
|
+
- fix: `BuildKG()` `Traversal.cls` SQL cursors now use fully-qualified `Graph_KG.rdf_edges`, `Graph_KG.rdf_labels`, `Graph_KG.rdf_props` — fixes predicate mismatch when IRIS namespace default SQL schema is not `Graph_KG` (e.g. MINDWALK namespace with `SQLUser` default)
|
|
626
|
+
- fix: `kg_IVFMeta`, `kg_BM25Meta`, `kg_PlaidMeta` added to security allowlist
|
|
627
|
+
- `EngineStatus` exported from top-level `iris_vector_graph`
|
|
628
|
+
|
|
629
|
+
|
|
586
630
|
### v1.63.2 (2026-04-25)
|
|
587
631
|
- fix: `MATCH (a)-[r*1..N]-(b)` undirected BFS now traverses `^KG("in",...)` for inbound edges (was outbound-only)
|
|
588
632
|
- fix: `MATCH (a)<-[r*1..N]-(b)` inbound-only BFS now works
|
|
@@ -13,7 +13,7 @@ ClassMethod BuildKG() As %Status
|
|
|
13
13
|
TStart
|
|
14
14
|
|
|
15
15
|
// 1. Labels
|
|
16
|
-
&sql(DECLARE c1 CURSOR FOR SELECT s, label FROM rdf_labels)
|
|
16
|
+
&sql(DECLARE c1 CURSOR FOR SELECT s, label FROM Graph_KG.rdf_labels)
|
|
17
17
|
&sql(OPEN c1)
|
|
18
18
|
For {
|
|
19
19
|
&sql(FETCH c1 INTO :s, :label)
|
|
@@ -23,7 +23,7 @@ ClassMethod BuildKG() As %Status
|
|
|
23
23
|
&sql(CLOSE c1)
|
|
24
24
|
|
|
25
25
|
// 2. Props
|
|
26
|
-
&sql(DECLARE c2 CURSOR FOR SELECT s, key, val FROM rdf_props)
|
|
26
|
+
&sql(DECLARE c2 CURSOR FOR SELECT s, key, val FROM Graph_KG.rdf_props)
|
|
27
27
|
&sql(OPEN c2)
|
|
28
28
|
For {
|
|
29
29
|
&sql(FETCH c2 INTO :s, :key, :val)
|
|
@@ -34,7 +34,7 @@ ClassMethod BuildKG() As %Status
|
|
|
34
34
|
|
|
35
35
|
// 3. Edges & Stats (including weights)
|
|
36
36
|
Set count = 0
|
|
37
|
-
&sql(DECLARE c3 CURSOR FOR SELECT s, p, o_id, qualifiers FROM rdf_edges)
|
|
37
|
+
&sql(DECLARE c3 CURSOR FOR SELECT s, p, o_id, qualifiers FROM Graph_KG.rdf_edges)
|
|
38
38
|
&sql(OPEN c3)
|
|
39
39
|
For {
|
|
40
40
|
&sql(FETCH c3 INTO :s, :p, :o, :qual)
|
|
@@ -675,4 +675,22 @@ ClassMethod DijkstraProc(srcId As %String, dstId As %String, weightProp As %Stri
|
|
|
675
675
|
Quit ..DijkstraJson(srcId, dstId, weightProp, maxCost, maxHops, direction)
|
|
676
676
|
}
|
|
677
677
|
|
|
678
|
+
ClassMethod KGEdgeCount(maxCount As %Integer = 10000) As %Integer
|
|
679
|
+
{
|
|
680
|
+
Set count = 0
|
|
681
|
+
Set s = ""
|
|
682
|
+
For {
|
|
683
|
+
Set s = $Order(^KG("out", 0, s))
|
|
684
|
+
Quit:s=""
|
|
685
|
+
Set count = count + 1
|
|
686
|
+
If count >= maxCount Quit
|
|
687
|
+
}
|
|
688
|
+
Return count
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
ClassMethod NKGPopulated() As %Integer
|
|
692
|
+
{
|
|
693
|
+
Return ($Data(^NKG) > 0)
|
|
694
|
+
}
|
|
695
|
+
|
|
678
696
|
}
|
|
@@ -20,6 +20,10 @@ from iris_vector_graph.cypher.translator import (
|
|
|
20
20
|
)
|
|
21
21
|
from iris_vector_graph.schema import GraphSchema, _call_classmethod
|
|
22
22
|
from iris_vector_graph.capabilities import IRISCapabilities
|
|
23
|
+
from iris_vector_graph.status import (
|
|
24
|
+
EngineStatus, TableCounts, AdjacencyStatus,
|
|
25
|
+
ObjectScriptStatus, ArnoStatus, IndexInventory,
|
|
26
|
+
)
|
|
23
27
|
from iris_vector_graph.security import validate_table_name
|
|
24
28
|
|
|
25
29
|
logger = logging.getLogger(__name__)
|
|
@@ -2054,6 +2058,145 @@ class IRISGraphEngine:
|
|
|
2054
2058
|
|
|
2055
2059
|
return {"id": row_map[id_key], "labels": labels, "properties": props}
|
|
2056
2060
|
|
|
2061
|
+
def status(self) -> "EngineStatus":
|
|
2062
|
+
import time as _time
|
|
2063
|
+
t0 = _time.perf_counter()
|
|
2064
|
+
errors: list = []
|
|
2065
|
+
cursor = self.conn.cursor()
|
|
2066
|
+
|
|
2067
|
+
def _count(sql):
|
|
2068
|
+
try:
|
|
2069
|
+
cursor.execute(sql)
|
|
2070
|
+
row = cursor.fetchone()
|
|
2071
|
+
return int(row[0]) if row else 0
|
|
2072
|
+
except Exception as e:
|
|
2073
|
+
errors.append(f"count probe failed: {e}")
|
|
2074
|
+
return 0
|
|
2075
|
+
|
|
2076
|
+
tables = TableCounts(
|
|
2077
|
+
nodes=_count(f"SELECT COUNT(*) FROM {_table('nodes')}"),
|
|
2078
|
+
edges=_count(f"SELECT COUNT(*) FROM {_table('rdf_edges')}"),
|
|
2079
|
+
labels=_count(f"SELECT COUNT(*) FROM {_table('rdf_labels')}"),
|
|
2080
|
+
props=_count(f"SELECT COUNT(*) FROM {_table('rdf_props')}"),
|
|
2081
|
+
node_embeddings=_count(f"SELECT COUNT(*) FROM {_table('kg_NodeEmbeddings')}"),
|
|
2082
|
+
edge_embeddings=_count(f"SELECT COUNT(*) FROM {_table('kg_EdgeEmbeddings')}"),
|
|
2083
|
+
)
|
|
2084
|
+
|
|
2085
|
+
kg_count = 0
|
|
2086
|
+
kg_capped = False
|
|
2087
|
+
kg_populated = False
|
|
2088
|
+
nkg_populated = False
|
|
2089
|
+
try:
|
|
2090
|
+
native = self._iris_obj()
|
|
2091
|
+
kg_count = int(native.classMethodValue("Graph.KG.Traversal", "KGEdgeCount", 10000))
|
|
2092
|
+
kg_populated = kg_count > 0
|
|
2093
|
+
kg_capped = kg_count >= 10000
|
|
2094
|
+
nkg_populated = bool(int(native.classMethodValue("Graph.KG.Traversal", "NKGPopulated")))
|
|
2095
|
+
except Exception as e:
|
|
2096
|
+
try:
|
|
2097
|
+
iris_native = self._iris_obj()
|
|
2098
|
+
kg_populated = bool(iris_native.isDefined(["KG", "out"]))
|
|
2099
|
+
except Exception:
|
|
2100
|
+
errors.append(f"^KG probe failed: {e}")
|
|
2101
|
+
|
|
2102
|
+
adjacency = AdjacencyStatus(
|
|
2103
|
+
kg_populated=kg_populated,
|
|
2104
|
+
kg_edge_count=kg_count,
|
|
2105
|
+
kg_edge_count_capped=kg_capped,
|
|
2106
|
+
nkg_populated=nkg_populated,
|
|
2107
|
+
)
|
|
2108
|
+
|
|
2109
|
+
if kg_populated and tables.edges > 0:
|
|
2110
|
+
try:
|
|
2111
|
+
native = self._iris_obj()
|
|
2112
|
+
kg_pred = str(native.get(["KG", "out", 0, ""])) or ""
|
|
2113
|
+
if not kg_pred:
|
|
2114
|
+
s_val = ""
|
|
2115
|
+
kg_pred_node = native.orderAll(["KG", "out", 0, s_val])
|
|
2116
|
+
if kg_pred_node:
|
|
2117
|
+
kg_pred = str(native.orderAll(
|
|
2118
|
+
["KG", "out", 0, str(kg_pred_node), ""]
|
|
2119
|
+
) or "")
|
|
2120
|
+
except Exception:
|
|
2121
|
+
kg_pred = ""
|
|
2122
|
+
|
|
2123
|
+
if kg_pred:
|
|
2124
|
+
try:
|
|
2125
|
+
cursor.execute(
|
|
2126
|
+
f"SELECT COUNT(*) FROM {_table('rdf_edges')} WHERE p = ?",
|
|
2127
|
+
[kg_pred],
|
|
2128
|
+
)
|
|
2129
|
+
row = cursor.fetchone()
|
|
2130
|
+
if row and int(row[0]) == 0:
|
|
2131
|
+
errors.append(
|
|
2132
|
+
f"^KG predicate mismatch: ^KG has '{kg_pred[:60]}' "
|
|
2133
|
+
f"but rdf_edges has no matching p — "
|
|
2134
|
+
f"^KG is stale from a different data snapshot. "
|
|
2135
|
+
f"Run BuildKG() after reloading graph data."
|
|
2136
|
+
)
|
|
2137
|
+
except Exception:
|
|
2138
|
+
pass
|
|
2139
|
+
|
|
2140
|
+
os_classes = []
|
|
2141
|
+
os_deployed = self.capabilities.objectscript_deployed
|
|
2142
|
+
_known_classes = [
|
|
2143
|
+
"Graph.KG.Traversal", "Graph.KG.PageRank", "Graph.KG.IVFIndex",
|
|
2144
|
+
"Graph.KG.BM25Index", "Graph.KG.ArnoAccel", "Graph.KG.Snapshot",
|
|
2145
|
+
"Graph.KG.Dijkstra",
|
|
2146
|
+
]
|
|
2147
|
+
if os_deployed:
|
|
2148
|
+
for cls in _known_classes:
|
|
2149
|
+
try:
|
|
2150
|
+
cursor.execute(
|
|
2151
|
+
"SELECT COUNT(*) FROM %Dictionary.ClassDefinition WHERE Name = ?",
|
|
2152
|
+
[cls],
|
|
2153
|
+
)
|
|
2154
|
+
row = cursor.fetchone()
|
|
2155
|
+
if row and int(row[0]) > 0:
|
|
2156
|
+
os_classes.append(cls)
|
|
2157
|
+
except Exception:
|
|
2158
|
+
pass
|
|
2159
|
+
|
|
2160
|
+
objectscript = ObjectScriptStatus(deployed=os_deployed, classes=os_classes)
|
|
2161
|
+
|
|
2162
|
+
self._detect_arno()
|
|
2163
|
+
arno = ArnoStatus(
|
|
2164
|
+
loaded=bool(self._arno_available),
|
|
2165
|
+
capabilities=dict(self._arno_capabilities),
|
|
2166
|
+
)
|
|
2167
|
+
|
|
2168
|
+
hnsw_built = _count(f"SELECT COUNT(*) FROM {_table('kg_NodeEmbeddings_optimized')}") > 0
|
|
2169
|
+
|
|
2170
|
+
def _list_index(sql):
|
|
2171
|
+
try:
|
|
2172
|
+
cursor.execute(sql)
|
|
2173
|
+
return [row[0] for row in cursor.fetchall() if row[0]]
|
|
2174
|
+
except Exception:
|
|
2175
|
+
return []
|
|
2176
|
+
|
|
2177
|
+
ivf = _list_index(f"SELECT DISTINCT name FROM {_table('kg_IVFMeta')}")
|
|
2178
|
+
bm25 = _list_index(f"SELECT DISTINCT name FROM {_table('kg_BM25Meta')}")
|
|
2179
|
+
plaid = _list_index(f"SELECT DISTINCT idx_name FROM {_table('kg_PlaidMeta')}")
|
|
2180
|
+
|
|
2181
|
+
indexes = IndexInventory(
|
|
2182
|
+
hnsw_built=hnsw_built,
|
|
2183
|
+
ivf_indexes=ivf,
|
|
2184
|
+
bm25_indexes=bm25,
|
|
2185
|
+
plaid_indexes=plaid,
|
|
2186
|
+
)
|
|
2187
|
+
|
|
2188
|
+
probe_ms = (_time.perf_counter() - t0) * 1000
|
|
2189
|
+
return EngineStatus(
|
|
2190
|
+
tables=tables,
|
|
2191
|
+
adjacency=adjacency,
|
|
2192
|
+
objectscript=objectscript,
|
|
2193
|
+
arno=arno,
|
|
2194
|
+
indexes=indexes,
|
|
2195
|
+
embedding_dimension=self.embedding_dimension,
|
|
2196
|
+
probe_ms=probe_ms,
|
|
2197
|
+
errors=errors,
|
|
2198
|
+
)
|
|
2199
|
+
|
|
2057
2200
|
def count_nodes(self, label: Optional[str] = None) -> int:
|
|
2058
2201
|
"""
|
|
2059
2202
|
Count nodes in the graph using optimized SQL.
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import Any, Dict, List
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class TableCounts:
|
|
9
|
+
nodes: int = 0
|
|
10
|
+
edges: int = 0
|
|
11
|
+
labels: int = 0
|
|
12
|
+
props: int = 0
|
|
13
|
+
node_embeddings: int = 0
|
|
14
|
+
edge_embeddings: int = 0
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class AdjacencyStatus:
|
|
19
|
+
kg_populated: bool = False
|
|
20
|
+
kg_edge_count: int = 0
|
|
21
|
+
kg_edge_count_capped: bool = False
|
|
22
|
+
nkg_populated: bool = False
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class ObjectScriptStatus:
|
|
27
|
+
deployed: bool = False
|
|
28
|
+
classes: List[str] = field(default_factory=list)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class ArnoStatus:
|
|
33
|
+
loaded: bool = False
|
|
34
|
+
capabilities: Dict[str, Any] = field(default_factory=dict)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class IndexInventory:
|
|
39
|
+
hnsw_built: bool = False
|
|
40
|
+
ivf_indexes: List[str] = field(default_factory=list)
|
|
41
|
+
bm25_indexes: List[str] = field(default_factory=list)
|
|
42
|
+
plaid_indexes: List[str] = field(default_factory=list)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass
|
|
46
|
+
class EngineStatus:
|
|
47
|
+
tables: TableCounts = field(default_factory=TableCounts)
|
|
48
|
+
adjacency: AdjacencyStatus = field(default_factory=AdjacencyStatus)
|
|
49
|
+
objectscript: ObjectScriptStatus = field(default_factory=ObjectScriptStatus)
|
|
50
|
+
arno: ArnoStatus = field(default_factory=ArnoStatus)
|
|
51
|
+
indexes: IndexInventory = field(default_factory=IndexInventory)
|
|
52
|
+
embedding_dimension: int = 768
|
|
53
|
+
probe_ms: float = 0.0
|
|
54
|
+
errors: List[str] = field(default_factory=list)
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def ready_for_bfs(self) -> bool:
|
|
58
|
+
return self.adjacency.kg_populated and self.tables.edges > 0
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def ready_for_vector_search(self) -> bool:
|
|
62
|
+
return self.tables.node_embeddings > 0
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def ready_for_edge_search(self) -> bool:
|
|
66
|
+
return self.tables.edge_embeddings > 0
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def ready_for_full_text(self) -> bool:
|
|
70
|
+
return bool(self.indexes.bm25_indexes)
|
|
71
|
+
|
|
72
|
+
def report(self) -> str:
|
|
73
|
+
def tick(ok: bool) -> str:
|
|
74
|
+
return "✓" if ok else "✗"
|
|
75
|
+
|
|
76
|
+
kg_count = (
|
|
77
|
+
f"≥{self.adjacency.kg_edge_count:,}"
|
|
78
|
+
if self.adjacency.kg_edge_count_capped
|
|
79
|
+
else f"{self.adjacency.kg_edge_count:,}"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
lines = [
|
|
83
|
+
"IVG Engine Status",
|
|
84
|
+
"═" * 50,
|
|
85
|
+
f"\nSQL Tables (probe: {self.probe_ms:.0f}ms)",
|
|
86
|
+
f" nodes {self.tables.nodes:>10,}",
|
|
87
|
+
f" edges {self.tables.edges:>10,}",
|
|
88
|
+
f" labels {self.tables.labels:>10,}",
|
|
89
|
+
f" properties {self.tables.props:>10,}",
|
|
90
|
+
f" node embeddings {self.tables.node_embeddings:>10,}",
|
|
91
|
+
f" edge embeddings {self.tables.edge_embeddings:>10,}",
|
|
92
|
+
f" embedding dim {self.embedding_dimension:>10}",
|
|
93
|
+
f"\nAdjacency Globals",
|
|
94
|
+
f" {tick(self.adjacency.kg_populated)} ^KG ({kg_count} source nodes indexed)",
|
|
95
|
+
f" {tick(self.adjacency.nkg_populated)} ^NKG (Arno integer index)",
|
|
96
|
+
]
|
|
97
|
+
|
|
98
|
+
if not self.adjacency.kg_populated and self.tables.edges > 0:
|
|
99
|
+
lines.append(
|
|
100
|
+
" ⚠ ^KG empty but edges exist — "
|
|
101
|
+
"call BuildKG() or rebuild on container startup"
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
lines += [
|
|
105
|
+
f"\nObjectScript Classes",
|
|
106
|
+
f" {tick(self.objectscript.deployed)} Deployed",
|
|
107
|
+
]
|
|
108
|
+
for cls in sorted(self.objectscript.classes):
|
|
109
|
+
lines.append(f" · {cls}")
|
|
110
|
+
|
|
111
|
+
lines.append(f"\nArno Accelerator")
|
|
112
|
+
if self.arno.loaded:
|
|
113
|
+
algos = [k for k, v in self.arno.capabilities.items()
|
|
114
|
+
if v and k not in ("nkg_data",)]
|
|
115
|
+
lines.append(f" ✓ Loaded — algorithms: {', '.join(algos) or 'none'}")
|
|
116
|
+
else:
|
|
117
|
+
lines.append(" ✗ Not loaded (BFS/PPR using ObjectScript fallback)")
|
|
118
|
+
|
|
119
|
+
lines += [
|
|
120
|
+
f"\nIndexes",
|
|
121
|
+
f" {tick(self.indexes.hnsw_built)} HNSW node vector index",
|
|
122
|
+
f" {'✓' if self.indexes.ivf_indexes else '·'} IVF: "
|
|
123
|
+
f"{', '.join(self.indexes.ivf_indexes) or 'none'}",
|
|
124
|
+
f" {'✓' if self.indexes.bm25_indexes else '·'} BM25: "
|
|
125
|
+
f"{', '.join(self.indexes.bm25_indexes) or 'none'}",
|
|
126
|
+
f" {'✓' if self.indexes.plaid_indexes else '·'} PLAID: "
|
|
127
|
+
f"{', '.join(self.indexes.plaid_indexes) or 'none'}",
|
|
128
|
+
]
|
|
129
|
+
|
|
130
|
+
if self.errors:
|
|
131
|
+
lines.append(f"\nProbe errors ({len(self.errors)})")
|
|
132
|
+
for e in self.errors:
|
|
133
|
+
lines.append(f" ! {e}")
|
|
134
|
+
|
|
135
|
+
lines.append("\n" + "═" * 50)
|
|
136
|
+
return "\n".join(lines)
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "iris-vector-graph"
|
|
7
|
-
version = "1.63.
|
|
7
|
+
version = "1.63.3"
|
|
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"
|
{iris_vector_graph-1.63.2 → iris_vector_graph-1.63.3}/tests/unit/test_cypher_e2e_new_features.py
RENAMED
|
@@ -552,3 +552,84 @@ class TestUndirectedBFSE2E:
|
|
|
552
552
|
ids = {row[0] for row in result["rows"]}
|
|
553
553
|
assert b in ids, f"inbound src missing: {ids}"
|
|
554
554
|
assert c not in ids, f"outbound dst should not appear: {ids}"
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
@pytest.mark.skipif(SKIP_IRIS_TESTS, reason="SKIP_IRIS_TESTS=true")
|
|
558
|
+
class TestAdjacencyIndexBuilt:
|
|
559
|
+
"""
|
|
560
|
+
Guard test: BFS silently returns empty results if ^KG is not populated.
|
|
561
|
+
This test catches the class of bug where BuildKG() was never called after
|
|
562
|
+
graph load (e.g. missing from iris-init.sh on container restart).
|
|
563
|
+
"""
|
|
564
|
+
|
|
565
|
+
@pytest.fixture(autouse=True)
|
|
566
|
+
def setup(self, iris_connection):
|
|
567
|
+
from iris_vector_graph.engine import IRISGraphEngine
|
|
568
|
+
self.conn = iris_connection
|
|
569
|
+
self.engine = IRISGraphEngine(iris_connection, embedding_dimension=4)
|
|
570
|
+
self.engine.initialize_schema()
|
|
571
|
+
self._run = uuid.uuid4().hex[:8]
|
|
572
|
+
self._nodes = []
|
|
573
|
+
yield
|
|
574
|
+
cursor = self.conn.cursor()
|
|
575
|
+
for nid in self._nodes:
|
|
576
|
+
try:
|
|
577
|
+
cursor.execute("DELETE FROM Graph_KG.rdf_edges WHERE s=? OR o_id=?", [nid, nid])
|
|
578
|
+
cursor.execute("DELETE FROM Graph_KG.rdf_labels WHERE s=?", [nid])
|
|
579
|
+
cursor.execute("DELETE FROM Graph_KG.nodes WHERE node_id=?", [nid])
|
|
580
|
+
except Exception:
|
|
581
|
+
pass
|
|
582
|
+
try:
|
|
583
|
+
self.conn.commit()
|
|
584
|
+
except Exception:
|
|
585
|
+
self.conn.rollback()
|
|
586
|
+
|
|
587
|
+
def _node(self, suffix):
|
|
588
|
+
nid = f"adj_{self._run}_{suffix}"
|
|
589
|
+
self._nodes.append(nid)
|
|
590
|
+
self.engine.create_node(nid, labels=["Gene"])
|
|
591
|
+
return nid
|
|
592
|
+
|
|
593
|
+
def test_bfs_returns_results_after_edge_creation(self):
|
|
594
|
+
"""
|
|
595
|
+
After create_edge(), BFS must return the neighbor.
|
|
596
|
+
If ^KG is empty (BuildKG never called), this returns 0 rows silently.
|
|
597
|
+
The real enforcement: create_edge() calls WriteAdjacency() per-edge,
|
|
598
|
+
so ^KG is always populated incrementally without needing a separate BuildKG.
|
|
599
|
+
"""
|
|
600
|
+
src = self._node("src")
|
|
601
|
+
dst = self._node("dst")
|
|
602
|
+
self.engine.create_edge(src, "KNOWS", dst)
|
|
603
|
+
|
|
604
|
+
result = self.engine.execute_cypher(
|
|
605
|
+
"MATCH (a)-[r*1..1]->(b) WHERE a.id = $id RETURN b.id",
|
|
606
|
+
{"id": src},
|
|
607
|
+
)
|
|
608
|
+
rows = result.get("rows", [])
|
|
609
|
+
ids = {row[0] for row in rows}
|
|
610
|
+
assert dst in ids, (
|
|
611
|
+
f"BFS returned 0 results after create_edge(). "
|
|
612
|
+
f"^KG may not be populated — check that WriteAdjacency() is called "
|
|
613
|
+
f"in create_edge() and that BuildKG() runs on container startup "
|
|
614
|
+
f"(iris-init.sh) after bulk loads."
|
|
615
|
+
)
|
|
616
|
+
|
|
617
|
+
def test_bulk_create_edges_populates_adjacency(self):
|
|
618
|
+
"""bulk_create_edges() calls BuildKG() in finally block — verify."""
|
|
619
|
+
nodes = [self._node(f"bulk_{i}") for i in range(4)]
|
|
620
|
+
edges = [
|
|
621
|
+
{"source_id": nodes[0], "predicate": "REL", "target_id": nodes[1]},
|
|
622
|
+
{"source_id": nodes[1], "predicate": "REL", "target_id": nodes[2]},
|
|
623
|
+
{"source_id": nodes[2], "predicate": "REL", "target_id": nodes[3]},
|
|
624
|
+
]
|
|
625
|
+
self.engine.bulk_create_edges(edges)
|
|
626
|
+
|
|
627
|
+
result = self.engine.execute_cypher(
|
|
628
|
+
"MATCH (a)-[r*1..3]->(b) WHERE a.id = $id RETURN b.id",
|
|
629
|
+
{"id": nodes[0]},
|
|
630
|
+
)
|
|
631
|
+
ids = {row[0] for row in result.get("rows", [])}
|
|
632
|
+
assert nodes[1] in ids and nodes[3] in ids, (
|
|
633
|
+
f"bulk_create_edges BFS returned {ids} — expected all 3 downstream nodes. "
|
|
634
|
+
f"Check that BuildKG() is called in the finally block of bulk_create_edges()."
|
|
635
|
+
)
|