iris-vector-graph 1.74.0__tar.gz → 1.76.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/PKG-INFO +1 -1
  2. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/Meta.cls +21 -0
  3. iris_vector_graph-1.76.0/iris_src/src/IVG/Percentile.cls +29 -0
  4. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/bolt_server.py +11 -2
  5. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/cypher/ast.py +6 -0
  6. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/cypher/parser.py +18 -0
  7. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/cypher/translator.py +72 -15
  8. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/schema.py +2 -2
  9. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/pyproject.toml +1 -1
  10. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/.gitignore +0 -0
  11. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/LICENSE +0 -0
  12. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/README.md +0 -0
  13. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/demo_biomedical.py +0 -0
  14. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/demo_fraud_detection.py +0 -0
  15. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/demo_fraud_detection_sql.py +0 -0
  16. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/demo_utils.py +0 -0
  17. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/demo_working_system.py +0 -0
  18. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/domains/__init__.py +0 -0
  19. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/domains/biomedical/__init__.py +0 -0
  20. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/domains/biomedical/loaders.py +0 -0
  21. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/domains/biomedical/resolver.py +0 -0
  22. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/domains/biomedical/types.py +0 -0
  23. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/domains/biomedical_legacy/__init__.py +0 -0
  24. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/domains/biomedical_legacy/biomedical_engine.py +0 -0
  25. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/domains/biomedical_legacy/biomedical_schema.py +0 -0
  26. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/domains/biomedical_legacy/legacy_wrapper.py +0 -0
  27. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/domains/fraud/__init__.py +0 -0
  28. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/domains/fraud/loaders.py +0 -0
  29. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/domains/fraud/resolver.py +0 -0
  30. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/domains/fraud/types.py +0 -0
  31. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/graphQL.http +0 -0
  32. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/hybrid_vector_graph_query.cypher +0 -0
  33. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/examples/rest.http +0 -0
  34. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/Algorithms.cls +0 -0
  35. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/ArnoAccel.cls +0 -0
  36. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/BM25Index.cls +0 -0
  37. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/BenchFormat.cls +0 -0
  38. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/BenchSeeder.cls +0 -0
  39. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/Benchmark.cls +0 -0
  40. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/Edge.cls +0 -0
  41. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/EdgeScan.cls +0 -0
  42. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/GraphIndex.cls +0 -0
  43. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/IVFIndex.cls +0 -0
  44. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/Loader.cls +0 -0
  45. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/MCPService.cls +0 -0
  46. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/MCPToolSet.cls +0 -0
  47. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/MCPTools.cls +0 -0
  48. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/NKGAccel.cls +0 -0
  49. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/PLAIDSearch.cls +0 -0
  50. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/PageRank.cls +0 -0
  51. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/PyOps.cls +0 -0
  52. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/Service.cls +0 -0
  53. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/Snapshot.cls +0 -0
  54. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/Subgraph.cls +0 -0
  55. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/TemporalIndex.cls +0 -0
  56. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/TestEdge.cls +0 -0
  57. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/Traversal.cls +0 -0
  58. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/Graph/KG/VecIndex.cls +0 -0
  59. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/PageRankEmbedded.cls +0 -0
  60. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/User.Exec.cls +0 -0
  61. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_src/src/iris/vector/graph/GraphOperators.cls +0 -0
  62. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/__init__.py +0 -0
  63. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/bulk_loader.py +0 -0
  64. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/capabilities.py +0 -0
  65. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/cypher/__init__.py +0 -0
  66. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/cypher/algorithms/__init__.py +0 -0
  67. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/cypher/algorithms/paths.py +0 -0
  68. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/cypher/lexer.py +0 -0
  69. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/cypher_api.py +0 -0
  70. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/embedded.py +0 -0
  71. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/engine.py +0 -0
  72. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/fusion.py +0 -0
  73. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/gql/__init__.py +0 -0
  74. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/gql/constants.py +0 -0
  75. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/gql/engine.py +0 -0
  76. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/gql/pooling.py +0 -0
  77. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/gql/resolvers.py +0 -0
  78. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/gql/schema.py +0 -0
  79. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/models.py +0 -0
  80. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/operators.py +0 -0
  81. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/py.typed +0 -0
  82. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/security.py +0 -0
  83. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/status.py +0 -0
  84. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/text_search.py +0 -0
  85. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/utils.py +0 -0
  86. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/iris_vector_graph/vector_utils.py +0 -0
  87. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/sql/fhir_bridges.sql +0 -0
  88. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/sql/fraud_sample_data.sql +0 -0
  89. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/sql/globals_schema.sql +0 -0
  90. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/sql/graph_path_globals.sql +0 -0
  91. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/sql/graph_walk_tvf.sql +0 -0
  92. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/sql/migrations/000_base_schema_iris.sql +0 -0
  93. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/sql/migrations/001_add_nodepk_table.sql +0 -0
  94. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/sql/migrations/001_rollback_nodepk.sql +0 -0
  95. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/sql/migrations/002_add_fk_constraints.sql +0 -0
  96. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/sql/operators.sql +0 -0
  97. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/sql/operators_fixed.sql +0 -0
  98. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/sql/procedures/kg_PageRank.sql +0 -0
  99. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/sql/rdf_reifications.sql +0 -0
  100. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/sql/schema.sql +0 -0
  101. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/TESTING.md +0 -0
  102. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/benchmark_parser.py +0 -0
  103. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/benchmarks/benchmark_neo4j.py +0 -0
  104. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/benchmarks/bfs_benchmark.py +0 -0
  105. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/benchmarks/establish_baseline.py +0 -0
  106. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/benchmarks/graph_gen.py +0 -0
  107. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/benchmarks/iris_baseline_run.py +0 -0
  108. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/benchmarks/iris_os_run.py +0 -0
  109. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/benchmarks/load_neo4j.py +0 -0
  110. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/benchmarks/synthetic_baseline.csv +0 -0
  111. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/conftest.py +0 -0
  112. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/contract/__init__.py +0 -0
  113. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/contract/test_cypher_api.py +0 -0
  114. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/contract/test_cypher_api_errors.py +0 -0
  115. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/contract/test_graphql_queries.py +0 -0
  116. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/contract/test_graphql_schema.py +0 -0
  117. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/contract/test_ppr_api.py +0 -0
  118. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/curl_suite.sh +0 -0
  119. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/__init__.py +0 -0
  120. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/conftest.py +0 -0
  121. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_biomedical_demo.py +0 -0
  122. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_biomedical_ui.py +0 -0
  123. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_cypher_coerce_e2e.py +0 -0
  124. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_cypher_sprints_e2e.py +0 -0
  125. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_cypher_vector_search.py +0 -0
  126. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_fhir_bridges_e2e.py +0 -0
  127. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_fraud_demo.py +0 -0
  128. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_fraud_ui.py +0 -0
  129. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_gql_autogen_startup.py +0 -0
  130. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_gql_cypher_passthrough.py +0 -0
  131. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_gql_node_queries.py +0 -0
  132. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_gql_semantic_search.py +0 -0
  133. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_gql_traversal.py +0 -0
  134. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_graph_kernels_e2e.py +0 -0
  135. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_hla_kg_e2e.py +0 -0
  136. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_multi_query_engine_platform.py +0 -0
  137. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_named_paths_e2e.py +0 -0
  138. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_nkg_index_e2e.py +0 -0
  139. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_operator_wiring_e2e.py +0 -0
  140. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_plaid_search_e2e.py +0 -0
  141. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_ppr_cls_fast_path.py +0 -0
  142. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_ppr_guided_e2e.py +0 -0
  143. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_procedure_installation.py +0 -0
  144. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_reification_e2e.py +0 -0
  145. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_schema_procedures_e2e.py +0 -0
  146. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_subgraph_e2e.py +0 -0
  147. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_subquery_call_e2e.py +0 -0
  148. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/e2e/test_vecindex_e2e.py +0 -0
  149. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/__init__.py +0 -0
  150. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/conftest.py +0 -0
  151. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/gql/__init__.py +0 -0
  152. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/gql/test_graphql_mutations.py +0 -0
  153. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/gql/test_graphql_nested_queries.py +0 -0
  154. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/gql/test_graphql_queries.py +0 -0
  155. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/gql/test_graphql_vector_search.py +0 -0
  156. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_bidirectional_ppr.py +0 -0
  157. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_cls_layer.py +0 -0
  158. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_cypher_advanced.py +0 -0
  159. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_cypher_enhancements.py +0 -0
  160. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_cypher_multi_type.py +0 -0
  161. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_cypher_rd.py +0 -0
  162. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_cypher_rel_vars.py +0 -0
  163. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_cypher_single_type.py +0 -0
  164. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_cypher_untyped.py +0 -0
  165. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_cypher_vector_search.py +0 -0
  166. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_embeddings_api.py +0 -0
  167. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_fastapi_graphql.py +0 -0
  168. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_fhir_bridges_integration.py +0 -0
  169. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_named_paths_integration.py +0 -0
  170. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_nodepk_advanced_benchmarks.py +0 -0
  171. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_nodepk_constraints.py +0 -0
  172. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_nodepk_graph_analytics.py +0 -0
  173. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_nodepk_migration.py +0 -0
  174. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_nodepk_performance.py +0 -0
  175. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_nodepk_production_scale.py +0 -0
  176. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_objectscript_classes.py +0 -0
  177. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_pagerank_sql_optimization.py +0 -0
  178. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_reification_integration.py +0 -0
  179. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_schema_migration.py +0 -0
  180. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_stored_procedure_install.py +0 -0
  181. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/integration/test_subquery_call_integration.py +0 -0
  182. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/performance/conftest.py +0 -0
  183. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/performance/scale_benchmark.py +0 -0
  184. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/performance/test_ppr_stress.py +0 -0
  185. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/performance/test_stress_v1_5.py +0 -0
  186. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/python/run_all_tests.py +0 -0
  187. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/python/test_iris_rest_api.py +0 -0
  188. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/python/test_networkx_loader.py +0 -0
  189. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/python/test_performance_benchmarks.py +0 -0
  190. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/python/test_pyops_vector_conversion.py +0 -0
  191. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/python/test_python_operators.py +0 -0
  192. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/python/test_python_sdk.py +0 -0
  193. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/python/test_schema_validation.py +0 -0
  194. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/python/test_sql_queries.py +0 -0
  195. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/python/test_vector_functions.py +0 -0
  196. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/cypher/__init__.py +0 -0
  197. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/cypher/test_lexer.py +0 -0
  198. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/cypher/test_lexer_advanced.py +0 -0
  199. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/cypher/test_parser.py +0 -0
  200. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/cypher/test_parser_advanced.py +0 -0
  201. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_batch_mutations.py +0 -0
  202. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_bfs_arno.py +0 -0
  203. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_bm25_index.py +0 -0
  204. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_bolt_server.py +0 -0
  205. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_cls_deployment.py +0 -0
  206. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_cypher_benchmark.py +0 -0
  207. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_cypher_benchmark_scale.py +0 -0
  208. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_cypher_case_when.py +0 -0
  209. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_cypher_e2e_new_features.py +0 -0
  210. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_cypher_functions.py +0 -0
  211. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_cypher_parser.py +0 -0
  212. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_cypher_posos_bugs.py +0 -0
  213. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_cypher_procedures.py +0 -0
  214. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_cypher_translator.py +0 -0
  215. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_cypher_union_exists.py +0 -0
  216. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_cypher_var_length.py +0 -0
  217. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_cypher_vector_search.py +0 -0
  218. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_edge_embeddings.py +0 -0
  219. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_edgeprop_ndjson.py +0 -0
  220. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_embedded.py +0 -0
  221. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_engine_dimension_fix.py +0 -0
  222. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_engine_embeddings.py +0 -0
  223. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_engine_status.py +0 -0
  224. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_fhir_bridges.py +0 -0
  225. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_get_nodes.py +0 -0
  226. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_graph_kernels.py +0 -0
  227. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_graphql_dataloader.py +0 -0
  228. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_ingest_formats.py +0 -0
  229. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_ivf_index.py +0 -0
  230. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_named_graphs.py +0 -0
  231. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_named_paths.py +0 -0
  232. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_operators_wiring.py +0 -0
  233. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_plaid_search.py +0 -0
  234. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_ppr_guided_subgraph.py +0 -0
  235. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_reification.py +0 -0
  236. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_schema_init.py +0 -0
  237. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_schema_procedures.py +0 -0
  238. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_shortest_path.py +0 -0
  239. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_snapshot.py +0 -0
  240. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_sql_splitter.py +0 -0
  241. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_sql_table_bridge.py +0 -0
  242. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_subgraph.py +0 -0
  243. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_subquery_call.py +0 -0
  244. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_temporal_cypher.py +0 -0
  245. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_temporal_edges.py +0 -0
  246. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/tests/unit/test_unified_edge_store.py +0 -0
  247. {iris_vector_graph-1.74.0 → iris_vector_graph-1.76.0}/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.74.0
3
+ Version: 1.76.0
4
4
  Summary: Transactional Graph + Vector retrieval system for InterSystems IRIS with hybrid search, openCypher, and GraphQL APIs
5
5
  Project-URL: Homepage, https://github.com/intersystems-community/iris-vector-graph
6
6
  Project-URL: Documentation, https://github.com/intersystems-community/iris-vector-graph/tree/main/docs
@@ -62,4 +62,25 @@ ClassMethod GetKG(s1 As %String = "", s2 As %String = "", s3 As %String = "", s4
62
62
  Return ""
63
63
  }
64
64
 
65
+ ClassMethod IVG_PDISC(vals As %String, p As %Double) As %String [ SqlProc ]
66
+ {
67
+ Set arr = ##class(%Library.DynamicArray).%FromJSON(vals)
68
+ Set n = arr.%Size()
69
+ If n = 0 { Quit "" }
70
+ Set i = n * p \ 1
71
+ If i >= n { Set i = n - 1 }
72
+ Quit arr.%Get(i)
73
+ }
74
+
75
+ ClassMethod IVG_PCONT(vals As %String, p As %Double) As %Double [ SqlProc ]
76
+ {
77
+ Set arr = ##class(%Library.DynamicArray).%FromJSON(vals)
78
+ Set n = arr.%Size()
79
+ If n = 0 { Quit 0 }
80
+ Set lower = n * p \ 1
81
+ If lower >= n - 1 { Quit arr.%Get(n-1) + 0 }
82
+ Set frac = (n * p) - lower
83
+ Quit arr.%Get(lower) + frac * (arr.%Get(lower+1) - arr.%Get(lower))
84
+ }
85
+
65
86
  }
@@ -0,0 +1,29 @@
1
+ /// Percentile aggregate helpers for IVG Cypher engine.
2
+ Class IVG.Percentile Extends %RegisteredObject [ SqlSchemaName = IVG ]
3
+ {
4
+
5
+ /// percentileDisc(vals, p) — discrete Nth percentile of JSON array.
6
+ ClassMethod PDISC(vals As %String, p As %Double) As %String [ SqlProc ]
7
+ {
8
+ Set arr = ##class(%Library.DynamicArray).%FromJSON(vals)
9
+ Set n = arr.%Size()
10
+ If n = 0 { Quit "" }
11
+ Set i = (n - 1) * p \ 1
12
+ If i >= (n - 1) { Set i = n - 1 }
13
+ Quit arr.%Get(i)
14
+ }
15
+
16
+ /// percentileCont(vals, p) — continuous Nth percentile (linear interpolation).
17
+ ClassMethod PCONT(vals As %String, p As %Double) As %Double [ SqlProc ]
18
+ {
19
+ Set arr = ##class(%Library.DynamicArray).%FromJSON(vals)
20
+ Set n = arr.%Size()
21
+ If n = 0 { Quit 0 }
22
+ Set pos = (n - 1) * p
23
+ Set lower = pos \ 1
24
+ If lower >= (n - 1) { Quit arr.%Get(n-1) + 0 }
25
+ Set frac = pos - lower
26
+ Quit arr.%Get(lower) + frac * (arr.%Get(lower+1) - arr.%Get(lower))
27
+ }
28
+
29
+ }
@@ -691,7 +691,15 @@ class BoltSession:
691
691
  columns[i+2].endswith("_props") and
692
692
  col[:-3] == columns[i+1][:-7] == columns[i+2][:-6]):
693
693
  var_name = col[:-3]
694
- node_id = str(row[i]) if row[i] is not None else ""
694
+ node_id = str(row[i]) if row[i] is not None else None
695
+
696
+ if node_id is None:
697
+ new_cols.append(var_name)
698
+ new_row.append(None)
699
+ prev_node_id = None
700
+ i += 3
701
+ continue
702
+
695
703
  labels_raw = row[i+1]
696
704
  props_raw = row[i+2]
697
705
 
@@ -713,7 +721,8 @@ class BoltSession:
713
721
  not col.endswith("_props") and
714
722
  "_" not in col and
715
723
  i + 1 < len(columns) and
716
- columns[i+1].endswith("_id")):
724
+ columns[i+1].endswith("_id") and
725
+ columns[i+1][:-3] == col):
717
726
  rel_type = str(row[i]) if row[i] is not None else "RELATED_TO"
718
727
  start_id = _node_int_id(prev_node_id) if prev_node_id else 0
719
728
  end_node_id_str = str(row[i+1]) if i+1 < len(row) else ""
@@ -210,6 +210,12 @@ class MapLiteral:
210
210
  entries: dict
211
211
 
212
212
 
213
+ @dataclass(slots=True)
214
+ class MapProjection:
215
+ variable: str
216
+ keys: list
217
+
218
+
213
219
  @dataclass(slots=True)
214
220
  class SubscriptExpression:
215
221
  expression: Any
@@ -1140,6 +1140,24 @@ class Parser:
1140
1140
  "Expected property name", prop_tok.line, prop_tok.column
1141
1141
  )
1142
1142
  return ast.PropertyReference(name, prop_tok.value)
1143
+ if self.peek().kind == TokenType.LBRACE:
1144
+ lookahead = self.lexer.peek_ahead(1)
1145
+ if lookahead.kind == TokenType.DOT or (
1146
+ lookahead.kind == TokenType.IDENTIFIER and self.lexer.peek_ahead(2).kind == TokenType.COLON
1147
+ ) or lookahead.kind == TokenType.RBRACE:
1148
+ self.eat()
1149
+ keys = []
1150
+ while not self.matches(TokenType.RBRACE):
1151
+ if self.peek().kind == TokenType.DOT:
1152
+ self.eat()
1153
+ k = self.expect(TokenType.IDENTIFIER)
1154
+ keys.append(("." + k.value, None))
1155
+ elif self.peek().kind == TokenType.IDENTIFIER:
1156
+ k = self.eat().value
1157
+ keys.append((k, None))
1158
+ if self.peek().kind == TokenType.COMMA:
1159
+ self.eat()
1160
+ return ast.MapProjection(variable=name, keys=keys)
1143
1161
  return ast.Variable(name)
1144
1162
 
1145
1163
  if tok.kind == TokenType.PARAMETER:
@@ -1152,6 +1152,22 @@ def translate_to_sql(
1152
1152
  if stage_name in [s.split(" AS ")[0].strip() for s in context.stages]:
1153
1153
  sql = sql.replace("SELECT \nFROM", f"SELECT *\nFROM", 1)
1154
1154
  sql = sql.replace("SELECT DISTINCT \nFROM", f"SELECT DISTINCT *\nFROM", 1)
1155
+ if hasattr(context, '_percentile_queries') and context._percentile_queries:
1156
+ import re as _re
1157
+ from_match = _re.search(r'\nFROM\s+(.*?)(?:\nWHERE|\nORDER|\nLIMIT|\nGROUP|\nHAVING|$)', sql, _re.DOTALL)
1158
+ if from_match and len(context._percentile_queries) == 1:
1159
+ from_clause = from_match.group(0).strip()
1160
+ val_expr, pct_val, fn_name, var_name, alias = context._percentile_queries[0]
1161
+ col_alias = _re.search(r'AS\s+(\w+)\s*$', sql.split('\n')[0])
1162
+ out_alias = col_alias.group(1) if col_alias else "result"
1163
+ proc = "PCONT" if fn_name == "percentilecont" else "PDISC"
1164
+ inner_col = val_expr.split('.')[-1] if '.' in val_expr else val_expr
1165
+ sql = (
1166
+ f"SELECT IVG.Percentile_{proc}("
1167
+ f"(SELECT JSON_ARRAYAGG(CAST({val_expr} AS DOUBLE)) "
1168
+ f"\n{from_clause}), {pct_val}) AS {out_alias}"
1169
+ )
1170
+ p = []
1155
1171
  sql = apply_pagination(sql, cypher_query, context, order_by_items)
1156
1172
  vl = context.var_length_paths or None
1157
1173
 
@@ -1326,7 +1342,13 @@ def translate_create_clause(create, context, metadata):
1326
1342
  node_id_expr = node.properties.get("id") or node.properties.get("node_id")
1327
1343
  if node_id_expr is None:
1328
1344
  import uuid as _uuid
1329
- node_id_expr = ast.Literal(str(_uuid.uuid4()))
1345
+ generated_id = str(_uuid.uuid4())
1346
+ node_id_expr = ast.Literal(generated_id)
1347
+ key = f"__create_id_{node.variable}" if node.variable else f"__create_id_anon_{id(node)}"
1348
+ context.input_params[key] = generated_id
1349
+ if not hasattr(context, '_anon_node_keys'):
1350
+ context._anon_node_keys = {}
1351
+ context._anon_node_keys[id(node)] = generated_id
1330
1352
 
1331
1353
  var_alias = None
1332
1354
  if isinstance(node_id_expr, ast.Variable):
@@ -1390,8 +1412,15 @@ def translate_create_clause(create, context, metadata):
1390
1412
 
1391
1413
  def _resolve_id(id_expr, node):
1392
1414
  if id_expr is None:
1393
- if node.variable and node.variable in context.input_params:
1394
- return context.input_params[node.variable]
1415
+ if node.variable:
1416
+ stored = context.input_params.get(f"__create_id_{node.variable}")
1417
+ if stored:
1418
+ return stored
1419
+ if node.variable in context.input_params:
1420
+ return context.input_params[node.variable]
1421
+ anon_id = getattr(context, '_anon_node_keys', {}).get(id(node))
1422
+ if anon_id:
1423
+ return anon_id
1395
1424
  return None
1396
1425
  if isinstance(id_expr, ast.Literal):
1397
1426
  return id_expr.value
@@ -2454,26 +2483,29 @@ def translate_expression(expr, context, segment="select") -> str:
2454
2483
  return f"(({inner}) > 0)"
2455
2484
 
2456
2485
  if isinstance(expr, ast.ListComprehension):
2457
- source_sql = translate_expression(expr.source, context, segment=segment)
2486
+ source_sql = translate_expression(expr.source, context, segment="inline")
2458
2487
  var = sanitize_identifier(expr.variable)
2459
2488
  alias = context.next_alias("lc")
2460
2489
  context.variable_aliases[expr.variable] = alias
2461
2490
  where_clause = ""
2462
2491
  if expr.predicate:
2463
- pred_sql = translate_expression(expr.predicate, context, segment=segment)
2492
+ if isinstance(expr.predicate, ast.BooleanExpression):
2493
+ pred_sql = translate_boolean_expression(expr.predicate, context)
2494
+ else:
2495
+ pred_sql = translate_expression(expr.predicate, context, segment="inline")
2464
2496
  for col in ("node_id", "p", "val", "label"):
2465
2497
  pred_sql = pred_sql.replace(f"{alias}.{col}", f"{alias}.{var}")
2466
2498
  where_clause = f" WHERE {pred_sql}"
2467
2499
  select_expr = f"{alias}.{var}"
2468
2500
  if expr.projection:
2469
- proj_sql = translate_expression(expr.projection, context, segment=segment)
2501
+ proj_sql = translate_expression(expr.projection, context, segment="inline")
2470
2502
  for col in ("node_id", "p", "val", "label"):
2471
2503
  proj_sql = proj_sql.replace(f"{alias}.{col}", f"{alias}.{var}")
2472
2504
  select_expr = proj_sql
2473
2505
  del context.variable_aliases[expr.variable]
2474
2506
  return (
2475
2507
  f"(SELECT JSON_ARRAYAGG({select_expr}) FROM "
2476
- f"JSON_TABLE({source_sql}, '$[*]' COLUMNS({var} VARCHAR(1000) PATH '$')) {alias}"
2508
+ f"JSON_TABLE({source_sql}, '$[*]' COLUMNS({var} INTEGER PATH '$')) {alias}"
2477
2509
  f"{where_clause})"
2478
2510
  )
2479
2511
 
@@ -2508,20 +2540,23 @@ def translate_expression(expr, context, segment="select") -> str:
2508
2540
  return f"(({inner}) > 0)"
2509
2541
 
2510
2542
  if isinstance(expr, ast.ListComprehension):
2511
- source_sql = translate_expression(expr.source, context, segment=segment)
2543
+ source_sql = translate_expression(expr.source, context, segment="inline")
2512
2544
  var = sanitize_identifier(expr.variable)
2513
2545
  alias = context.next_alias("lc")
2514
2546
  where_clause = ""
2515
2547
  if expr.predicate:
2516
- pred_sql = translate_expression(expr.predicate, context, segment=segment)
2548
+ if isinstance(expr.predicate, ast.BooleanExpression):
2549
+ pred_sql = translate_boolean_expression(expr.predicate, context)
2550
+ else:
2551
+ pred_sql = translate_expression(expr.predicate, context, segment="inline")
2517
2552
  where_clause = f" WHERE {pred_sql.replace(var, f'{alias}.{var}')}"
2518
2553
  select_expr = f"{alias}.{var}"
2519
2554
  if expr.projection:
2520
- proj_sql = translate_expression(expr.projection, context, segment=segment)
2555
+ proj_sql = translate_expression(expr.projection, context, segment="inline")
2521
2556
  select_expr = proj_sql.replace(var, f"{alias}.{var}")
2522
2557
  return (
2523
2558
  f"(SELECT JSON_ARRAYAGG({select_expr}) FROM "
2524
- f"JSON_TABLE({source_sql}, '$[*]' COLUMNS({var} VARCHAR(1000) PATH '$')) {alias}"
2559
+ f"JSON_TABLE({source_sql}, '$[*]' COLUMNS({var} INTEGER PATH '$')) {alias}"
2525
2560
  f"{where_clause})"
2526
2561
  )
2527
2562
 
@@ -2618,6 +2653,20 @@ def translate_expression(expr, context, segment="select") -> str:
2618
2653
  f'LEFT JOIN {_table("rdf_props")} {p_alias} ON {p_alias}.s = {alias}.node_id AND {p_alias}."key" = {context.add_join_param(expr.property_name)}'
2619
2654
  )
2620
2655
  return f"{p_alias}.val"
2656
+ if isinstance(expr, ast.MapProjection):
2657
+ alias = context.variable_aliases.get(expr.variable, "")
2658
+ parts = []
2659
+ for key_spec, _ in expr.keys:
2660
+ prop = key_spec.lstrip(".")
2661
+ p_alias = context.next_alias("p")
2662
+ context.join_clauses.append(
2663
+ f"LEFT JOIN {_table('rdf_props')} {p_alias} ON {p_alias}.s = {alias}.node_id AND {p_alias}.\"key\" = {context.add_join_param(prop)}"
2664
+ )
2665
+ safe_prop = prop.replace("'", "''")
2666
+ parts.append(f"'\"'||'{safe_prop}'||'\":'||COALESCE('\"'||{p_alias}.val||'\"','null')")
2667
+ if not parts:
2668
+ return "'{}'"
2669
+ return "('{'||" + "||','||".join(parts) + "||'}')"
2621
2670
  if isinstance(expr, ast.MapLiteral):
2622
2671
  if not expr.entries:
2623
2672
  return "'{}'"
@@ -2966,10 +3015,18 @@ def translate_expression(expr, context, segment="select") -> str:
2966
3015
  return f"STDDEV({args[0]})" if args else "NULL"
2967
3016
  if fn in ("stdevp",):
2968
3017
  return f"STDDEV_POP({args[0]})" if args else "NULL"
2969
- if fn in ("percentiledisc",):
2970
- return f"PERCENTILE_DISC({args[1] if len(args)>1 else '0.5'}) WITHIN GROUP (ORDER BY {args[0]})" if args else "NULL"
2971
- if fn in ("percentilecont",):
2972
- return f"PERCENTILE_CONT({args[1] if len(args)>1 else '0.5'}) WITHIN GROUP (ORDER BY {args[0]})" if args else "NULL"
3018
+ if fn in ("percentiledisc", "percentilecont"):
3019
+ if not args:
3020
+ return "NULL"
3021
+ val_expr = args[0]
3022
+ pct_expr = args[1] if len(args) > 1 else "0.5"
3023
+ context._percentile_queries = getattr(context, "_percentile_queries", [])
3024
+ if args_exprs and isinstance(args_exprs[0], ast.Variable):
3025
+ var_name = args_exprs[0].name
3026
+ alias = context.variable_aliases.get(var_name, "")
3027
+ pct_val = float(pct_expr) if isinstance(pct_expr, str) and pct_expr.replace('.','',1).isdigit() else 0.5
3028
+ context._percentile_queries.append((val_expr, pct_val, fn, var_name, alias))
3029
+ return f"__PERCENTILE_PLACEHOLDER_{len(context._percentile_queries)-1 if context._percentile_queries else 0}__"
2973
3030
  if fn == "haversin":
2974
3031
  return f"(1 - COS({args[0]})) / 2" if args else "NULL"
2975
3032
  if fn == "e":
@@ -592,10 +592,10 @@ CREATE OR REPLACE FUNCTION SQLUser.RAND() RETURNS DOUBLE LANGUAGE OBJECTSCRIPT {
592
592
  CREATE OR REPLACE FUNCTION SQLUser.NEWID() RETURNS VARCHAR(36) LANGUAGE OBJECTSCRIPT { Quit $SYSTEM.Util.CreateGUID() }
593
593
  """,
594
594
  """
595
- CREATE OR REPLACE FUNCTION SQLUser.LIST_REVERSE(j VARCHAR(32000)) RETURNS VARCHAR(32000) LANGUAGE OBJECTSCRIPT { Set arr = ##class(%Library.DynamicArray).%FromJSON(j), out = ##class(%Library.DynamicArray).%New(), n = arr.%Size() For i = n-1:-1:0 { Do out.%Push(arr.%Get(i)) } Quit out.%ToJSON() }
595
+ CREATE OR REPLACE FUNCTION SQLUser.LIST_REVERSE(j VARCHAR(32000)) RETURNS VARCHAR(32000) LANGUAGE OBJECTSCRIPT { Set arr = ##class(%Library.DynamicArray).%FromJSON(j), out = ##class(%Library.DynamicArray).%New(), n = arr.%Size(), i = n-1 While i >= 0 { Do out.%Push(arr.%Get(i)) Set i = i-1 } Quit out.%ToJSON() }
596
596
  """,
597
597
  """
598
- CREATE OR REPLACE FUNCTION SQLUser.LIST_TAIL(j VARCHAR(32000)) RETURNS VARCHAR(32000) LANGUAGE OBJECTSCRIPT { Set arr = ##class(%Library.DynamicArray).%FromJSON(j), out = ##class(%Library.DynamicArray).%New(), n = arr.%Size() For i = 1:1:n-1 { Do out.%Push(arr.%Get(i)) } Quit out.%ToJSON() }
598
+ CREATE OR REPLACE FUNCTION SQLUser.LIST_TAIL(j VARCHAR(32000)) RETURNS VARCHAR(32000) LANGUAGE OBJECTSCRIPT { Set arr = ##class(%Library.DynamicArray).%FromJSON(j), out = ##class(%Library.DynamicArray).%New(), n = arr.%Size(), i = 1 While i < n { Do out.%Push(arr.%Get(i)) Set i = i+1 } Quit out.%ToJSON() }
599
599
  """,
600
600
  """
601
601
  CREATE OR REPLACE FUNCTION SQLUser.REGEX_MATCH(s VARCHAR(4000), p VARCHAR(4000)) RETURNS INTEGER LANGUAGE OBJECTSCRIPT { Quit $MATCH(s, p) }
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "iris-vector-graph"
7
- version = "1.74.0"
7
+ version = "1.76.0"
8
8
  description = "Transactional Graph + Vector retrieval system for InterSystems IRIS with hybrid search, openCypher, and GraphQL APIs"
9
9
  readme = "README.md"
10
10
  license = "MIT"