relationalai 0.13.0.dev0__py3-none-any.whl → 0.13.2__py3-none-any.whl

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 (838) hide show
  1. frontend/debugger/dist/.gitignore +2 -0
  2. frontend/debugger/dist/assets/favicon-Dy0ZgA6N.png +0 -0
  3. frontend/debugger/dist/assets/index-Cssla-O7.js +208 -0
  4. frontend/debugger/dist/assets/index-DlHsYx1V.css +9 -0
  5. frontend/debugger/dist/index.html +17 -0
  6. relationalai/__init__.py +256 -1
  7. relationalai/clients/__init__.py +18 -0
  8. relationalai/clients/client.py +947 -0
  9. relationalai/clients/config.py +673 -0
  10. relationalai/clients/direct_access_client.py +118 -0
  11. relationalai/clients/exec_txn_poller.py +91 -0
  12. relationalai/clients/hash_util.py +31 -0
  13. relationalai/clients/local.py +586 -0
  14. relationalai/clients/profile_polling.py +73 -0
  15. relationalai/clients/resources/__init__.py +8 -0
  16. relationalai/clients/resources/azure/azure.py +502 -0
  17. relationalai/clients/resources/snowflake/__init__.py +20 -0
  18. relationalai/clients/resources/snowflake/cli_resources.py +98 -0
  19. relationalai/clients/resources/snowflake/direct_access_resources.py +734 -0
  20. relationalai/clients/resources/snowflake/engine_service.py +381 -0
  21. relationalai/clients/resources/snowflake/engine_state_handlers.py +315 -0
  22. relationalai/clients/resources/snowflake/error_handlers.py +240 -0
  23. relationalai/clients/resources/snowflake/export_procedure.py.jinja +249 -0
  24. relationalai/clients/resources/snowflake/resources_factory.py +99 -0
  25. relationalai/clients/resources/snowflake/snowflake.py +3185 -0
  26. relationalai/clients/resources/snowflake/use_index_poller.py +1019 -0
  27. relationalai/clients/resources/snowflake/use_index_resources.py +188 -0
  28. relationalai/clients/resources/snowflake/util.py +387 -0
  29. relationalai/clients/result_helpers.py +420 -0
  30. relationalai/clients/types.py +118 -0
  31. relationalai/clients/util.py +356 -0
  32. relationalai/debugging.py +389 -0
  33. relationalai/dsl.py +1749 -0
  34. relationalai/early_access/builder/__init__.py +30 -0
  35. relationalai/early_access/builder/builder/__init__.py +35 -0
  36. relationalai/early_access/builder/snowflake/__init__.py +12 -0
  37. relationalai/early_access/builder/std/__init__.py +25 -0
  38. relationalai/early_access/builder/std/decimals/__init__.py +12 -0
  39. relationalai/early_access/builder/std/integers/__init__.py +12 -0
  40. relationalai/early_access/builder/std/math/__init__.py +12 -0
  41. relationalai/early_access/builder/std/strings/__init__.py +14 -0
  42. relationalai/early_access/devtools/__init__.py +12 -0
  43. relationalai/early_access/devtools/benchmark_lqp/__init__.py +12 -0
  44. relationalai/early_access/devtools/extract_lqp/__init__.py +12 -0
  45. relationalai/early_access/dsl/adapters/orm/adapter_qb.py +427 -0
  46. relationalai/early_access/dsl/adapters/orm/parser.py +636 -0
  47. relationalai/early_access/dsl/adapters/owl/adapter.py +176 -0
  48. relationalai/early_access/dsl/adapters/owl/parser.py +160 -0
  49. relationalai/early_access/dsl/bindings/common.py +402 -0
  50. relationalai/early_access/dsl/bindings/csv.py +170 -0
  51. relationalai/early_access/dsl/bindings/legacy/binding_models.py +143 -0
  52. relationalai/early_access/dsl/bindings/snowflake.py +64 -0
  53. relationalai/early_access/dsl/codegen/binder.py +411 -0
  54. relationalai/early_access/dsl/codegen/common.py +79 -0
  55. relationalai/early_access/dsl/codegen/helpers.py +23 -0
  56. relationalai/early_access/dsl/codegen/relations.py +700 -0
  57. relationalai/early_access/dsl/codegen/weaver.py +417 -0
  58. relationalai/early_access/dsl/core/builders/__init__.py +47 -0
  59. relationalai/early_access/dsl/core/builders/logic.py +19 -0
  60. relationalai/early_access/dsl/core/builders/scalar_constraint.py +11 -0
  61. relationalai/early_access/dsl/core/constraints/predicate/atomic.py +455 -0
  62. relationalai/early_access/dsl/core/constraints/predicate/universal.py +73 -0
  63. relationalai/early_access/dsl/core/constraints/scalar.py +310 -0
  64. relationalai/early_access/dsl/core/context.py +13 -0
  65. relationalai/early_access/dsl/core/cset.py +132 -0
  66. relationalai/early_access/dsl/core/exprs/__init__.py +116 -0
  67. relationalai/early_access/dsl/core/exprs/relational.py +18 -0
  68. relationalai/early_access/dsl/core/exprs/scalar.py +412 -0
  69. relationalai/early_access/dsl/core/instances.py +44 -0
  70. relationalai/early_access/dsl/core/logic/__init__.py +193 -0
  71. relationalai/early_access/dsl/core/logic/aggregation.py +98 -0
  72. relationalai/early_access/dsl/core/logic/exists.py +223 -0
  73. relationalai/early_access/dsl/core/logic/helper.py +163 -0
  74. relationalai/early_access/dsl/core/namespaces.py +32 -0
  75. relationalai/early_access/dsl/core/relations.py +276 -0
  76. relationalai/early_access/dsl/core/rules.py +112 -0
  77. relationalai/early_access/dsl/core/std/__init__.py +45 -0
  78. relationalai/early_access/dsl/core/temporal/recall.py +6 -0
  79. relationalai/early_access/dsl/core/types/__init__.py +270 -0
  80. relationalai/early_access/dsl/core/types/concepts.py +128 -0
  81. relationalai/early_access/dsl/core/types/constrained/__init__.py +267 -0
  82. relationalai/early_access/dsl/core/types/constrained/nominal.py +143 -0
  83. relationalai/early_access/dsl/core/types/constrained/subtype.py +124 -0
  84. relationalai/early_access/dsl/core/types/standard.py +92 -0
  85. relationalai/early_access/dsl/core/types/unconstrained.py +50 -0
  86. relationalai/early_access/dsl/core/types/variables.py +203 -0
  87. relationalai/early_access/dsl/ir/compiler.py +318 -0
  88. relationalai/early_access/dsl/ir/executor.py +260 -0
  89. relationalai/early_access/dsl/ontologies/constraints.py +88 -0
  90. relationalai/early_access/dsl/ontologies/export.py +30 -0
  91. relationalai/early_access/dsl/ontologies/models.py +453 -0
  92. relationalai/early_access/dsl/ontologies/python_printer.py +303 -0
  93. relationalai/early_access/dsl/ontologies/readings.py +60 -0
  94. relationalai/early_access/dsl/ontologies/relationships.py +322 -0
  95. relationalai/early_access/dsl/ontologies/roles.py +87 -0
  96. relationalai/early_access/dsl/ontologies/subtyping.py +55 -0
  97. relationalai/early_access/dsl/orm/constraints.py +438 -0
  98. relationalai/early_access/dsl/orm/measures/dimensions.py +200 -0
  99. relationalai/early_access/dsl/orm/measures/initializer.py +16 -0
  100. relationalai/early_access/dsl/orm/measures/measure_rules.py +275 -0
  101. relationalai/early_access/dsl/orm/measures/measures.py +299 -0
  102. relationalai/early_access/dsl/orm/measures/role_exprs.py +268 -0
  103. relationalai/early_access/dsl/orm/models.py +256 -0
  104. relationalai/early_access/dsl/orm/object_oriented_printer.py +344 -0
  105. relationalai/early_access/dsl/orm/printer.py +469 -0
  106. relationalai/early_access/dsl/orm/reasoners.py +480 -0
  107. relationalai/early_access/dsl/orm/relations.py +19 -0
  108. relationalai/early_access/dsl/orm/relationships.py +251 -0
  109. relationalai/early_access/dsl/orm/types.py +42 -0
  110. relationalai/early_access/dsl/orm/utils.py +79 -0
  111. relationalai/early_access/dsl/orm/verb.py +204 -0
  112. relationalai/early_access/dsl/physical_metadata/tables.py +133 -0
  113. relationalai/early_access/dsl/relations.py +170 -0
  114. relationalai/early_access/dsl/rulesets.py +69 -0
  115. relationalai/early_access/dsl/schemas/__init__.py +450 -0
  116. relationalai/early_access/dsl/schemas/builder.py +48 -0
  117. relationalai/early_access/dsl/schemas/comp_names.py +51 -0
  118. relationalai/early_access/dsl/schemas/components.py +203 -0
  119. relationalai/early_access/dsl/schemas/contexts.py +156 -0
  120. relationalai/early_access/dsl/schemas/exprs.py +89 -0
  121. relationalai/early_access/dsl/schemas/fragments.py +464 -0
  122. relationalai/early_access/dsl/serialization.py +79 -0
  123. relationalai/early_access/dsl/serialize/exporter.py +163 -0
  124. relationalai/early_access/dsl/snow/api.py +105 -0
  125. relationalai/early_access/dsl/snow/common.py +76 -0
  126. relationalai/early_access/dsl/state_mgmt/__init__.py +129 -0
  127. relationalai/early_access/dsl/state_mgmt/state_charts.py +125 -0
  128. relationalai/early_access/dsl/state_mgmt/transitions.py +130 -0
  129. relationalai/early_access/dsl/types/__init__.py +40 -0
  130. relationalai/early_access/dsl/types/concepts.py +12 -0
  131. relationalai/early_access/dsl/types/entities.py +135 -0
  132. relationalai/early_access/dsl/types/values.py +17 -0
  133. relationalai/early_access/dsl/utils.py +102 -0
  134. relationalai/early_access/graphs/__init__.py +13 -0
  135. relationalai/early_access/lqp/__init__.py +12 -0
  136. relationalai/early_access/lqp/compiler/__init__.py +12 -0
  137. relationalai/early_access/lqp/constructors/__init__.py +18 -0
  138. relationalai/early_access/lqp/executor/__init__.py +12 -0
  139. relationalai/early_access/lqp/ir/__init__.py +12 -0
  140. relationalai/early_access/lqp/passes/__init__.py +12 -0
  141. relationalai/early_access/lqp/pragmas/__init__.py +12 -0
  142. relationalai/early_access/lqp/primitives/__init__.py +12 -0
  143. relationalai/early_access/lqp/types/__init__.py +12 -0
  144. relationalai/early_access/lqp/utils/__init__.py +12 -0
  145. relationalai/early_access/lqp/validators/__init__.py +12 -0
  146. relationalai/early_access/metamodel/__init__.py +58 -0
  147. relationalai/early_access/metamodel/builtins/__init__.py +12 -0
  148. relationalai/early_access/metamodel/compiler/__init__.py +12 -0
  149. relationalai/early_access/metamodel/dependency/__init__.py +12 -0
  150. relationalai/early_access/metamodel/factory/__init__.py +17 -0
  151. relationalai/early_access/metamodel/helpers/__init__.py +12 -0
  152. relationalai/early_access/metamodel/ir/__init__.py +14 -0
  153. relationalai/early_access/metamodel/rewrite/__init__.py +7 -0
  154. relationalai/early_access/metamodel/typer/__init__.py +3 -0
  155. relationalai/early_access/metamodel/typer/typer/__init__.py +12 -0
  156. relationalai/early_access/metamodel/types/__init__.py +15 -0
  157. relationalai/early_access/metamodel/util/__init__.py +15 -0
  158. relationalai/early_access/metamodel/visitor/__init__.py +12 -0
  159. relationalai/early_access/rel/__init__.py +12 -0
  160. relationalai/early_access/rel/executor/__init__.py +12 -0
  161. relationalai/early_access/rel/rel_utils/__init__.py +12 -0
  162. relationalai/early_access/rel/rewrite/__init__.py +7 -0
  163. relationalai/early_access/solvers/__init__.py +19 -0
  164. relationalai/early_access/sql/__init__.py +11 -0
  165. relationalai/early_access/sql/executor/__init__.py +3 -0
  166. relationalai/early_access/sql/rewrite/__init__.py +3 -0
  167. relationalai/early_access/tests/logging/__init__.py +12 -0
  168. relationalai/early_access/tests/test_snapshot_base/__init__.py +12 -0
  169. relationalai/early_access/tests/utils/__init__.py +12 -0
  170. relationalai/environments/__init__.py +35 -0
  171. relationalai/environments/base.py +381 -0
  172. relationalai/environments/colab.py +14 -0
  173. relationalai/environments/generic.py +71 -0
  174. relationalai/environments/ipython.py +68 -0
  175. relationalai/environments/jupyter.py +9 -0
  176. relationalai/environments/snowbook.py +169 -0
  177. relationalai/errors.py +2496 -0
  178. relationalai/experimental/SF.py +38 -0
  179. relationalai/experimental/inspect.py +47 -0
  180. relationalai/experimental/pathfinder/__init__.py +158 -0
  181. relationalai/experimental/pathfinder/api.py +160 -0
  182. relationalai/experimental/pathfinder/automaton.py +584 -0
  183. relationalai/experimental/pathfinder/bridge.py +226 -0
  184. relationalai/experimental/pathfinder/compiler.py +416 -0
  185. relationalai/experimental/pathfinder/datalog.py +214 -0
  186. relationalai/experimental/pathfinder/diagnostics.py +56 -0
  187. relationalai/experimental/pathfinder/filter.py +236 -0
  188. relationalai/experimental/pathfinder/glushkov.py +439 -0
  189. relationalai/experimental/pathfinder/options.py +265 -0
  190. relationalai/experimental/pathfinder/pathfinder-v0.7.0.rel +1951 -0
  191. relationalai/experimental/pathfinder/rpq.py +344 -0
  192. relationalai/experimental/pathfinder/transition.py +200 -0
  193. relationalai/experimental/pathfinder/utils.py +26 -0
  194. relationalai/experimental/paths/README.md +107 -0
  195. relationalai/experimental/paths/api.py +143 -0
  196. relationalai/experimental/paths/benchmarks/grid_graph.py +37 -0
  197. relationalai/experimental/paths/code_organization.md +2 -0
  198. relationalai/experimental/paths/examples/Movies.ipynb +16328 -0
  199. relationalai/experimental/paths/examples/basic_example.py +40 -0
  200. relationalai/experimental/paths/examples/minimal_engine_warmup.py +3 -0
  201. relationalai/experimental/paths/examples/movie_example.py +77 -0
  202. relationalai/experimental/paths/examples/movies_data/actedin.csv +193 -0
  203. relationalai/experimental/paths/examples/movies_data/directed.csv +45 -0
  204. relationalai/experimental/paths/examples/movies_data/follows.csv +7 -0
  205. relationalai/experimental/paths/examples/movies_data/movies.csv +39 -0
  206. relationalai/experimental/paths/examples/movies_data/person.csv +134 -0
  207. relationalai/experimental/paths/examples/movies_data/produced.csv +16 -0
  208. relationalai/experimental/paths/examples/movies_data/ratings.csv +10 -0
  209. relationalai/experimental/paths/examples/movies_data/wrote.csv +11 -0
  210. relationalai/experimental/paths/examples/paths_benchmark.py +115 -0
  211. relationalai/experimental/paths/examples/paths_example.py +116 -0
  212. relationalai/experimental/paths/examples/pattern_to_automaton.py +28 -0
  213. relationalai/experimental/paths/find_paths_via_automaton.py +85 -0
  214. relationalai/experimental/paths/graph.py +185 -0
  215. relationalai/experimental/paths/path_algorithms/find_paths.py +280 -0
  216. relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +26 -0
  217. relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +111 -0
  218. relationalai/experimental/paths/path_algorithms/single.py +59 -0
  219. relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +39 -0
  220. relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +103 -0
  221. relationalai/experimental/paths/path_algorithms/usp-old.py +130 -0
  222. relationalai/experimental/paths/path_algorithms/usp-tuple.py +183 -0
  223. relationalai/experimental/paths/path_algorithms/usp.py +150 -0
  224. relationalai/experimental/paths/product_graph.py +93 -0
  225. relationalai/experimental/paths/rpq/automaton.py +584 -0
  226. relationalai/experimental/paths/rpq/diagnostics.py +56 -0
  227. relationalai/experimental/paths/rpq/rpq.py +378 -0
  228. relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +90 -0
  229. relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +119 -0
  230. relationalai/experimental/paths/tests/tests_limit_sp_single.py +104 -0
  231. relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +113 -0
  232. relationalai/experimental/paths/tests/tests_limit_walks_single.py +149 -0
  233. relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +70 -0
  234. relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +64 -0
  235. relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +115 -0
  236. relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +75 -0
  237. relationalai/experimental/paths/tests/tests_single_paths.py +152 -0
  238. relationalai/experimental/paths/tests/tests_single_walks.py +208 -0
  239. relationalai/experimental/paths/tests/tests_single_walks_undirected.py +297 -0
  240. relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +107 -0
  241. relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +76 -0
  242. relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +76 -0
  243. relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +110 -0
  244. relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +229 -0
  245. relationalai/experimental/paths/tests/tests_usp_nsp_single.py +108 -0
  246. relationalai/experimental/paths/tree_agg.py +168 -0
  247. relationalai/experimental/paths/utilities/iterators.py +27 -0
  248. relationalai/experimental/paths/utilities/prefix_sum.py +91 -0
  249. relationalai/experimental/solvers.py +1087 -0
  250. relationalai/loaders/csv.py +195 -0
  251. relationalai/loaders/loader.py +177 -0
  252. relationalai/loaders/types.py +23 -0
  253. relationalai/rel_emitter.py +373 -0
  254. relationalai/rel_utils.py +185 -0
  255. relationalai/semantics/__init__.py +22 -146
  256. relationalai/semantics/designs/query_builder/identify_by.md +106 -0
  257. relationalai/semantics/devtools/benchmark_lqp.py +535 -0
  258. relationalai/semantics/devtools/compilation_manager.py +294 -0
  259. relationalai/semantics/devtools/extract_lqp.py +110 -0
  260. relationalai/semantics/internal/internal.py +3785 -0
  261. relationalai/semantics/internal/snowflake.py +325 -0
  262. relationalai/semantics/lqp/README.md +34 -0
  263. relationalai/semantics/lqp/builtins.py +16 -0
  264. relationalai/semantics/lqp/compiler.py +22 -0
  265. relationalai/semantics/lqp/constructors.py +68 -0
  266. relationalai/semantics/lqp/executor.py +469 -0
  267. relationalai/semantics/lqp/intrinsics.py +24 -0
  268. relationalai/semantics/lqp/model2lqp.py +877 -0
  269. relationalai/semantics/lqp/passes.py +680 -0
  270. relationalai/semantics/lqp/primitives.py +252 -0
  271. relationalai/semantics/lqp/result_helpers.py +202 -0
  272. relationalai/semantics/lqp/rewrite/annotate_constraints.py +57 -0
  273. relationalai/semantics/lqp/rewrite/cdc.py +216 -0
  274. relationalai/semantics/lqp/rewrite/extract_common.py +338 -0
  275. relationalai/semantics/lqp/rewrite/extract_keys.py +512 -0
  276. relationalai/semantics/lqp/rewrite/function_annotations.py +114 -0
  277. relationalai/semantics/lqp/rewrite/functional_dependencies.py +314 -0
  278. relationalai/semantics/lqp/rewrite/quantify_vars.py +296 -0
  279. relationalai/semantics/lqp/rewrite/splinter.py +76 -0
  280. relationalai/semantics/lqp/types.py +101 -0
  281. relationalai/semantics/lqp/utils.py +160 -0
  282. relationalai/semantics/lqp/validators.py +57 -0
  283. relationalai/semantics/metamodel/__init__.py +40 -6
  284. relationalai/semantics/metamodel/builtins.py +771 -205
  285. relationalai/semantics/metamodel/compiler.py +133 -0
  286. relationalai/semantics/metamodel/dependency.py +862 -0
  287. relationalai/semantics/metamodel/executor.py +61 -0
  288. relationalai/semantics/metamodel/factory.py +287 -0
  289. relationalai/semantics/metamodel/helpers.py +361 -0
  290. relationalai/semantics/metamodel/rewrite/discharge_constraints.py +39 -0
  291. relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +210 -0
  292. relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +78 -0
  293. relationalai/semantics/metamodel/rewrite/flatten.py +554 -0
  294. relationalai/semantics/metamodel/rewrite/format_outputs.py +165 -0
  295. relationalai/semantics/metamodel/typer/checker.py +353 -0
  296. relationalai/semantics/metamodel/typer/typer.py +1399 -0
  297. relationalai/semantics/metamodel/util.py +506 -0
  298. relationalai/semantics/reasoners/__init__.py +10 -0
  299. relationalai/semantics/reasoners/graph/README.md +620 -0
  300. relationalai/semantics/reasoners/graph/__init__.py +37 -0
  301. relationalai/semantics/reasoners/graph/core.py +9019 -0
  302. relationalai/semantics/reasoners/graph/design/beyond_demand_transform.md +797 -0
  303. relationalai/semantics/reasoners/graph/tests/README.md +21 -0
  304. relationalai/semantics/reasoners/optimization/__init__.py +68 -0
  305. relationalai/semantics/reasoners/optimization/common.py +88 -0
  306. relationalai/semantics/reasoners/optimization/solvers_dev.py +568 -0
  307. relationalai/semantics/reasoners/optimization/solvers_pb.py +1414 -0
  308. relationalai/semantics/rel/builtins.py +40 -0
  309. relationalai/semantics/rel/compiler.py +989 -0
  310. relationalai/semantics/rel/executor.py +362 -0
  311. relationalai/semantics/rel/rel.py +482 -0
  312. relationalai/semantics/rel/rel_utils.py +276 -0
  313. relationalai/semantics/snowflake/__init__.py +3 -0
  314. relationalai/semantics/sql/compiler.py +2503 -0
  315. relationalai/semantics/sql/executor/duck_db.py +52 -0
  316. relationalai/semantics/sql/executor/result_helpers.py +64 -0
  317. relationalai/semantics/sql/executor/snowflake.py +149 -0
  318. relationalai/semantics/sql/rewrite/denormalize.py +222 -0
  319. relationalai/semantics/sql/rewrite/double_negation.py +49 -0
  320. relationalai/semantics/sql/rewrite/recursive_union.py +127 -0
  321. relationalai/semantics/sql/rewrite/sort_output_query.py +246 -0
  322. relationalai/semantics/sql/sql.py +504 -0
  323. relationalai/semantics/std/__init__.py +40 -60
  324. relationalai/semantics/std/constraints.py +43 -37
  325. relationalai/semantics/std/datetime.py +135 -246
  326. relationalai/semantics/std/decimals.py +52 -45
  327. relationalai/semantics/std/floats.py +5 -13
  328. relationalai/semantics/std/integers.py +11 -26
  329. relationalai/semantics/std/math.py +112 -183
  330. relationalai/semantics/std/pragmas.py +11 -0
  331. relationalai/semantics/std/re.py +62 -80
  332. relationalai/semantics/std/std.py +14 -0
  333. relationalai/semantics/std/strings.py +60 -117
  334. relationalai/semantics/tests/test_snapshot_abstract.py +143 -0
  335. relationalai/semantics/tests/test_snapshot_base.py +9 -0
  336. relationalai/semantics/tests/utils.py +46 -0
  337. relationalai/std/__init__.py +70 -0
  338. relationalai/tools/cli.py +2089 -0
  339. relationalai/tools/cli_controls.py +1826 -0
  340. relationalai/tools/cli_helpers.py +802 -0
  341. relationalai/tools/debugger.py +183 -289
  342. relationalai/tools/debugger_client.py +109 -0
  343. relationalai/tools/debugger_server.py +302 -0
  344. relationalai/tools/dev.py +685 -0
  345. relationalai/tools/notes +7 -0
  346. relationalai/tools/qb_debugger.py +425 -0
  347. relationalai/util/clean_up_databases.py +95 -0
  348. relationalai/util/format.py +106 -48
  349. relationalai/util/list_databases.py +9 -0
  350. relationalai/util/otel_configuration.py +26 -0
  351. relationalai/util/otel_handler.py +484 -0
  352. relationalai/util/snowflake_handler.py +88 -0
  353. relationalai/util/span_format_test.py +43 -0
  354. relationalai/util/span_tracker.py +207 -0
  355. relationalai/util/spans_file_handler.py +72 -0
  356. relationalai/util/tracing_handler.py +34 -0
  357. relationalai-0.13.2.dist-info/METADATA +74 -0
  358. relationalai-0.13.2.dist-info/RECORD +460 -0
  359. relationalai-0.13.2.dist-info/WHEEL +4 -0
  360. relationalai-0.13.2.dist-info/entry_points.txt +3 -0
  361. relationalai-0.13.2.dist-info/licenses/LICENSE +202 -0
  362. relationalai_test_util/__init__.py +4 -0
  363. relationalai_test_util/fixtures.py +233 -0
  364. relationalai_test_util/snapshot.py +252 -0
  365. relationalai_test_util/traceback.py +118 -0
  366. relationalai/config/__init__.py +0 -56
  367. relationalai/config/config.py +0 -289
  368. relationalai/config/config_fields.py +0 -86
  369. relationalai/config/connections/__init__.py +0 -46
  370. relationalai/config/connections/base.py +0 -23
  371. relationalai/config/connections/duckdb.py +0 -29
  372. relationalai/config/connections/snowflake.py +0 -243
  373. relationalai/config/external/__init__.py +0 -17
  374. relationalai/config/external/dbt_converter.py +0 -101
  375. relationalai/config/external/dbt_models.py +0 -93
  376. relationalai/config/external/snowflake_converter.py +0 -41
  377. relationalai/config/external/snowflake_models.py +0 -85
  378. relationalai/config/external/utils.py +0 -19
  379. relationalai/semantics/backends/lqp/annotations.py +0 -11
  380. relationalai/semantics/backends/sql/sql_compiler.py +0 -327
  381. relationalai/semantics/frontend/base.py +0 -1707
  382. relationalai/semantics/frontend/core.py +0 -179
  383. relationalai/semantics/frontend/front_compiler.py +0 -1313
  384. relationalai/semantics/frontend/pprint.py +0 -408
  385. relationalai/semantics/metamodel/metamodel.py +0 -437
  386. relationalai/semantics/metamodel/metamodel_analyzer.py +0 -519
  387. relationalai/semantics/metamodel/metamodel_compiler.py +0 -0
  388. relationalai/semantics/metamodel/pprint.py +0 -412
  389. relationalai/semantics/metamodel/rewriter.py +0 -266
  390. relationalai/semantics/metamodel/typer.py +0 -1378
  391. relationalai/semantics/std/aggregates.py +0 -149
  392. relationalai/semantics/std/common.py +0 -44
  393. relationalai/semantics/std/numbers.py +0 -86
  394. relationalai/shims/executor.py +0 -147
  395. relationalai/shims/helpers.py +0 -126
  396. relationalai/shims/hoister.py +0 -221
  397. relationalai/shims/mm2v0.py +0 -1290
  398. relationalai/tools/cli/__init__.py +0 -6
  399. relationalai/tools/cli/cli.py +0 -90
  400. relationalai/tools/cli/components/__init__.py +0 -5
  401. relationalai/tools/cli/components/progress_reader.py +0 -1524
  402. relationalai/tools/cli/components/utils.py +0 -58
  403. relationalai/tools/cli/config_template.py +0 -45
  404. relationalai/tools/cli/dev.py +0 -19
  405. relationalai/tools/typer_debugger.py +0 -93
  406. relationalai/util/dataclasses.py +0 -43
  407. relationalai/util/docutils.py +0 -40
  408. relationalai/util/error.py +0 -199
  409. relationalai/util/naming.py +0 -145
  410. relationalai/util/python.py +0 -35
  411. relationalai/util/runtime.py +0 -156
  412. relationalai/util/schema.py +0 -197
  413. relationalai/util/source.py +0 -185
  414. relationalai/util/structures.py +0 -163
  415. relationalai/util/tracing.py +0 -261
  416. relationalai-0.13.0.dev0.dist-info/METADATA +0 -46
  417. relationalai-0.13.0.dev0.dist-info/RECORD +0 -488
  418. relationalai-0.13.0.dev0.dist-info/WHEEL +0 -5
  419. relationalai-0.13.0.dev0.dist-info/entry_points.txt +0 -3
  420. relationalai-0.13.0.dev0.dist-info/top_level.txt +0 -2
  421. v0/relationalai/__init__.py +0 -216
  422. v0/relationalai/clients/__init__.py +0 -5
  423. v0/relationalai/clients/azure.py +0 -477
  424. v0/relationalai/clients/client.py +0 -912
  425. v0/relationalai/clients/config.py +0 -673
  426. v0/relationalai/clients/direct_access_client.py +0 -118
  427. v0/relationalai/clients/hash_util.py +0 -31
  428. v0/relationalai/clients/local.py +0 -571
  429. v0/relationalai/clients/profile_polling.py +0 -73
  430. v0/relationalai/clients/result_helpers.py +0 -420
  431. v0/relationalai/clients/snowflake.py +0 -3869
  432. v0/relationalai/clients/types.py +0 -113
  433. v0/relationalai/clients/use_index_poller.py +0 -980
  434. v0/relationalai/clients/util.py +0 -356
  435. v0/relationalai/debugging.py +0 -389
  436. v0/relationalai/dsl.py +0 -1749
  437. v0/relationalai/early_access/builder/__init__.py +0 -30
  438. v0/relationalai/early_access/builder/builder/__init__.py +0 -35
  439. v0/relationalai/early_access/builder/snowflake/__init__.py +0 -12
  440. v0/relationalai/early_access/builder/std/__init__.py +0 -25
  441. v0/relationalai/early_access/builder/std/decimals/__init__.py +0 -12
  442. v0/relationalai/early_access/builder/std/integers/__init__.py +0 -12
  443. v0/relationalai/early_access/builder/std/math/__init__.py +0 -12
  444. v0/relationalai/early_access/builder/std/strings/__init__.py +0 -14
  445. v0/relationalai/early_access/devtools/__init__.py +0 -12
  446. v0/relationalai/early_access/devtools/benchmark_lqp/__init__.py +0 -12
  447. v0/relationalai/early_access/devtools/extract_lqp/__init__.py +0 -12
  448. v0/relationalai/early_access/dsl/adapters/orm/adapter_qb.py +0 -427
  449. v0/relationalai/early_access/dsl/adapters/orm/parser.py +0 -636
  450. v0/relationalai/early_access/dsl/adapters/owl/adapter.py +0 -176
  451. v0/relationalai/early_access/dsl/adapters/owl/parser.py +0 -160
  452. v0/relationalai/early_access/dsl/bindings/common.py +0 -402
  453. v0/relationalai/early_access/dsl/bindings/csv.py +0 -170
  454. v0/relationalai/early_access/dsl/bindings/legacy/binding_models.py +0 -143
  455. v0/relationalai/early_access/dsl/bindings/snowflake.py +0 -64
  456. v0/relationalai/early_access/dsl/codegen/binder.py +0 -411
  457. v0/relationalai/early_access/dsl/codegen/common.py +0 -79
  458. v0/relationalai/early_access/dsl/codegen/helpers.py +0 -23
  459. v0/relationalai/early_access/dsl/codegen/relations.py +0 -700
  460. v0/relationalai/early_access/dsl/codegen/weaver.py +0 -417
  461. v0/relationalai/early_access/dsl/core/builders/__init__.py +0 -47
  462. v0/relationalai/early_access/dsl/core/builders/logic.py +0 -19
  463. v0/relationalai/early_access/dsl/core/builders/scalar_constraint.py +0 -11
  464. v0/relationalai/early_access/dsl/core/constraints/predicate/atomic.py +0 -455
  465. v0/relationalai/early_access/dsl/core/constraints/predicate/universal.py +0 -73
  466. v0/relationalai/early_access/dsl/core/constraints/scalar.py +0 -310
  467. v0/relationalai/early_access/dsl/core/context.py +0 -13
  468. v0/relationalai/early_access/dsl/core/cset.py +0 -132
  469. v0/relationalai/early_access/dsl/core/exprs/__init__.py +0 -116
  470. v0/relationalai/early_access/dsl/core/exprs/relational.py +0 -18
  471. v0/relationalai/early_access/dsl/core/exprs/scalar.py +0 -412
  472. v0/relationalai/early_access/dsl/core/instances.py +0 -44
  473. v0/relationalai/early_access/dsl/core/logic/__init__.py +0 -193
  474. v0/relationalai/early_access/dsl/core/logic/aggregation.py +0 -98
  475. v0/relationalai/early_access/dsl/core/logic/exists.py +0 -223
  476. v0/relationalai/early_access/dsl/core/logic/helper.py +0 -163
  477. v0/relationalai/early_access/dsl/core/namespaces.py +0 -32
  478. v0/relationalai/early_access/dsl/core/relations.py +0 -276
  479. v0/relationalai/early_access/dsl/core/rules.py +0 -112
  480. v0/relationalai/early_access/dsl/core/std/__init__.py +0 -45
  481. v0/relationalai/early_access/dsl/core/temporal/recall.py +0 -6
  482. v0/relationalai/early_access/dsl/core/types/__init__.py +0 -270
  483. v0/relationalai/early_access/dsl/core/types/concepts.py +0 -128
  484. v0/relationalai/early_access/dsl/core/types/constrained/__init__.py +0 -267
  485. v0/relationalai/early_access/dsl/core/types/constrained/nominal.py +0 -143
  486. v0/relationalai/early_access/dsl/core/types/constrained/subtype.py +0 -124
  487. v0/relationalai/early_access/dsl/core/types/standard.py +0 -92
  488. v0/relationalai/early_access/dsl/core/types/unconstrained.py +0 -50
  489. v0/relationalai/early_access/dsl/core/types/variables.py +0 -203
  490. v0/relationalai/early_access/dsl/ir/compiler.py +0 -318
  491. v0/relationalai/early_access/dsl/ir/executor.py +0 -260
  492. v0/relationalai/early_access/dsl/ontologies/constraints.py +0 -88
  493. v0/relationalai/early_access/dsl/ontologies/export.py +0 -30
  494. v0/relationalai/early_access/dsl/ontologies/models.py +0 -453
  495. v0/relationalai/early_access/dsl/ontologies/python_printer.py +0 -303
  496. v0/relationalai/early_access/dsl/ontologies/readings.py +0 -60
  497. v0/relationalai/early_access/dsl/ontologies/relationships.py +0 -322
  498. v0/relationalai/early_access/dsl/ontologies/roles.py +0 -87
  499. v0/relationalai/early_access/dsl/ontologies/subtyping.py +0 -55
  500. v0/relationalai/early_access/dsl/orm/constraints.py +0 -438
  501. v0/relationalai/early_access/dsl/orm/measures/dimensions.py +0 -200
  502. v0/relationalai/early_access/dsl/orm/measures/initializer.py +0 -16
  503. v0/relationalai/early_access/dsl/orm/measures/measure_rules.py +0 -275
  504. v0/relationalai/early_access/dsl/orm/measures/measures.py +0 -299
  505. v0/relationalai/early_access/dsl/orm/measures/role_exprs.py +0 -268
  506. v0/relationalai/early_access/dsl/orm/models.py +0 -256
  507. v0/relationalai/early_access/dsl/orm/object_oriented_printer.py +0 -344
  508. v0/relationalai/early_access/dsl/orm/printer.py +0 -469
  509. v0/relationalai/early_access/dsl/orm/reasoners.py +0 -480
  510. v0/relationalai/early_access/dsl/orm/relations.py +0 -19
  511. v0/relationalai/early_access/dsl/orm/relationships.py +0 -251
  512. v0/relationalai/early_access/dsl/orm/types.py +0 -42
  513. v0/relationalai/early_access/dsl/orm/utils.py +0 -79
  514. v0/relationalai/early_access/dsl/orm/verb.py +0 -204
  515. v0/relationalai/early_access/dsl/physical_metadata/tables.py +0 -133
  516. v0/relationalai/early_access/dsl/relations.py +0 -170
  517. v0/relationalai/early_access/dsl/rulesets.py +0 -69
  518. v0/relationalai/early_access/dsl/schemas/__init__.py +0 -450
  519. v0/relationalai/early_access/dsl/schemas/builder.py +0 -48
  520. v0/relationalai/early_access/dsl/schemas/comp_names.py +0 -51
  521. v0/relationalai/early_access/dsl/schemas/components.py +0 -203
  522. v0/relationalai/early_access/dsl/schemas/contexts.py +0 -156
  523. v0/relationalai/early_access/dsl/schemas/exprs.py +0 -89
  524. v0/relationalai/early_access/dsl/schemas/fragments.py +0 -464
  525. v0/relationalai/early_access/dsl/serialization.py +0 -79
  526. v0/relationalai/early_access/dsl/serialize/exporter.py +0 -163
  527. v0/relationalai/early_access/dsl/snow/api.py +0 -104
  528. v0/relationalai/early_access/dsl/snow/common.py +0 -76
  529. v0/relationalai/early_access/dsl/state_mgmt/__init__.py +0 -129
  530. v0/relationalai/early_access/dsl/state_mgmt/state_charts.py +0 -125
  531. v0/relationalai/early_access/dsl/state_mgmt/transitions.py +0 -130
  532. v0/relationalai/early_access/dsl/types/__init__.py +0 -40
  533. v0/relationalai/early_access/dsl/types/concepts.py +0 -12
  534. v0/relationalai/early_access/dsl/types/entities.py +0 -135
  535. v0/relationalai/early_access/dsl/types/values.py +0 -17
  536. v0/relationalai/early_access/dsl/utils.py +0 -102
  537. v0/relationalai/early_access/graphs/__init__.py +0 -13
  538. v0/relationalai/early_access/lqp/__init__.py +0 -12
  539. v0/relationalai/early_access/lqp/compiler/__init__.py +0 -12
  540. v0/relationalai/early_access/lqp/constructors/__init__.py +0 -18
  541. v0/relationalai/early_access/lqp/executor/__init__.py +0 -12
  542. v0/relationalai/early_access/lqp/ir/__init__.py +0 -12
  543. v0/relationalai/early_access/lqp/passes/__init__.py +0 -12
  544. v0/relationalai/early_access/lqp/pragmas/__init__.py +0 -12
  545. v0/relationalai/early_access/lqp/primitives/__init__.py +0 -12
  546. v0/relationalai/early_access/lqp/types/__init__.py +0 -12
  547. v0/relationalai/early_access/lqp/utils/__init__.py +0 -12
  548. v0/relationalai/early_access/lqp/validators/__init__.py +0 -12
  549. v0/relationalai/early_access/metamodel/__init__.py +0 -58
  550. v0/relationalai/early_access/metamodel/builtins/__init__.py +0 -12
  551. v0/relationalai/early_access/metamodel/compiler/__init__.py +0 -12
  552. v0/relationalai/early_access/metamodel/dependency/__init__.py +0 -12
  553. v0/relationalai/early_access/metamodel/factory/__init__.py +0 -17
  554. v0/relationalai/early_access/metamodel/helpers/__init__.py +0 -12
  555. v0/relationalai/early_access/metamodel/ir/__init__.py +0 -14
  556. v0/relationalai/early_access/metamodel/rewrite/__init__.py +0 -7
  557. v0/relationalai/early_access/metamodel/typer/__init__.py +0 -3
  558. v0/relationalai/early_access/metamodel/typer/typer/__init__.py +0 -12
  559. v0/relationalai/early_access/metamodel/types/__init__.py +0 -15
  560. v0/relationalai/early_access/metamodel/util/__init__.py +0 -15
  561. v0/relationalai/early_access/metamodel/visitor/__init__.py +0 -12
  562. v0/relationalai/early_access/rel/__init__.py +0 -12
  563. v0/relationalai/early_access/rel/executor/__init__.py +0 -12
  564. v0/relationalai/early_access/rel/rel_utils/__init__.py +0 -12
  565. v0/relationalai/early_access/rel/rewrite/__init__.py +0 -7
  566. v0/relationalai/early_access/solvers/__init__.py +0 -19
  567. v0/relationalai/early_access/sql/__init__.py +0 -11
  568. v0/relationalai/early_access/sql/executor/__init__.py +0 -3
  569. v0/relationalai/early_access/sql/rewrite/__init__.py +0 -3
  570. v0/relationalai/early_access/tests/logging/__init__.py +0 -12
  571. v0/relationalai/early_access/tests/test_snapshot_base/__init__.py +0 -12
  572. v0/relationalai/early_access/tests/utils/__init__.py +0 -12
  573. v0/relationalai/environments/__init__.py +0 -35
  574. v0/relationalai/environments/base.py +0 -381
  575. v0/relationalai/environments/colab.py +0 -14
  576. v0/relationalai/environments/generic.py +0 -71
  577. v0/relationalai/environments/ipython.py +0 -68
  578. v0/relationalai/environments/jupyter.py +0 -9
  579. v0/relationalai/environments/snowbook.py +0 -169
  580. v0/relationalai/errors.py +0 -2455
  581. v0/relationalai/experimental/SF.py +0 -38
  582. v0/relationalai/experimental/inspect.py +0 -47
  583. v0/relationalai/experimental/pathfinder/__init__.py +0 -158
  584. v0/relationalai/experimental/pathfinder/api.py +0 -160
  585. v0/relationalai/experimental/pathfinder/automaton.py +0 -584
  586. v0/relationalai/experimental/pathfinder/bridge.py +0 -226
  587. v0/relationalai/experimental/pathfinder/compiler.py +0 -416
  588. v0/relationalai/experimental/pathfinder/datalog.py +0 -214
  589. v0/relationalai/experimental/pathfinder/diagnostics.py +0 -56
  590. v0/relationalai/experimental/pathfinder/filter.py +0 -236
  591. v0/relationalai/experimental/pathfinder/glushkov.py +0 -439
  592. v0/relationalai/experimental/pathfinder/options.py +0 -265
  593. v0/relationalai/experimental/pathfinder/rpq.py +0 -344
  594. v0/relationalai/experimental/pathfinder/transition.py +0 -200
  595. v0/relationalai/experimental/pathfinder/utils.py +0 -26
  596. v0/relationalai/experimental/paths/api.py +0 -143
  597. v0/relationalai/experimental/paths/benchmarks/grid_graph.py +0 -37
  598. v0/relationalai/experimental/paths/examples/basic_example.py +0 -40
  599. v0/relationalai/experimental/paths/examples/minimal_engine_warmup.py +0 -3
  600. v0/relationalai/experimental/paths/examples/movie_example.py +0 -77
  601. v0/relationalai/experimental/paths/examples/paths_benchmark.py +0 -115
  602. v0/relationalai/experimental/paths/examples/paths_example.py +0 -116
  603. v0/relationalai/experimental/paths/examples/pattern_to_automaton.py +0 -28
  604. v0/relationalai/experimental/paths/find_paths_via_automaton.py +0 -85
  605. v0/relationalai/experimental/paths/graph.py +0 -185
  606. v0/relationalai/experimental/paths/path_algorithms/find_paths.py +0 -280
  607. v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +0 -26
  608. v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +0 -111
  609. v0/relationalai/experimental/paths/path_algorithms/single.py +0 -59
  610. v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +0 -39
  611. v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +0 -103
  612. v0/relationalai/experimental/paths/path_algorithms/usp-old.py +0 -130
  613. v0/relationalai/experimental/paths/path_algorithms/usp-tuple.py +0 -183
  614. v0/relationalai/experimental/paths/path_algorithms/usp.py +0 -150
  615. v0/relationalai/experimental/paths/product_graph.py +0 -93
  616. v0/relationalai/experimental/paths/rpq/automaton.py +0 -584
  617. v0/relationalai/experimental/paths/rpq/diagnostics.py +0 -56
  618. v0/relationalai/experimental/paths/rpq/rpq.py +0 -378
  619. v0/relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +0 -90
  620. v0/relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +0 -119
  621. v0/relationalai/experimental/paths/tests/tests_limit_sp_single.py +0 -104
  622. v0/relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +0 -113
  623. v0/relationalai/experimental/paths/tests/tests_limit_walks_single.py +0 -149
  624. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +0 -70
  625. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +0 -64
  626. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +0 -115
  627. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +0 -75
  628. v0/relationalai/experimental/paths/tests/tests_single_paths.py +0 -152
  629. v0/relationalai/experimental/paths/tests/tests_single_walks.py +0 -208
  630. v0/relationalai/experimental/paths/tests/tests_single_walks_undirected.py +0 -297
  631. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +0 -107
  632. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +0 -76
  633. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +0 -76
  634. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +0 -110
  635. v0/relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +0 -229
  636. v0/relationalai/experimental/paths/tests/tests_usp_nsp_single.py +0 -108
  637. v0/relationalai/experimental/paths/tree_agg.py +0 -168
  638. v0/relationalai/experimental/paths/utilities/iterators.py +0 -27
  639. v0/relationalai/experimental/paths/utilities/prefix_sum.py +0 -91
  640. v0/relationalai/experimental/solvers.py +0 -1087
  641. v0/relationalai/loaders/csv.py +0 -195
  642. v0/relationalai/loaders/loader.py +0 -177
  643. v0/relationalai/loaders/types.py +0 -23
  644. v0/relationalai/rel_emitter.py +0 -373
  645. v0/relationalai/rel_utils.py +0 -185
  646. v0/relationalai/semantics/__init__.py +0 -29
  647. v0/relationalai/semantics/devtools/benchmark_lqp.py +0 -536
  648. v0/relationalai/semantics/devtools/compilation_manager.py +0 -294
  649. v0/relationalai/semantics/devtools/extract_lqp.py +0 -110
  650. v0/relationalai/semantics/internal/internal.py +0 -3785
  651. v0/relationalai/semantics/internal/snowflake.py +0 -324
  652. v0/relationalai/semantics/lqp/builtins.py +0 -16
  653. v0/relationalai/semantics/lqp/compiler.py +0 -22
  654. v0/relationalai/semantics/lqp/constructors.py +0 -68
  655. v0/relationalai/semantics/lqp/executor.py +0 -469
  656. v0/relationalai/semantics/lqp/intrinsics.py +0 -24
  657. v0/relationalai/semantics/lqp/model2lqp.py +0 -839
  658. v0/relationalai/semantics/lqp/passes.py +0 -680
  659. v0/relationalai/semantics/lqp/primitives.py +0 -252
  660. v0/relationalai/semantics/lqp/result_helpers.py +0 -202
  661. v0/relationalai/semantics/lqp/rewrite/annotate_constraints.py +0 -57
  662. v0/relationalai/semantics/lqp/rewrite/cdc.py +0 -216
  663. v0/relationalai/semantics/lqp/rewrite/extract_common.py +0 -338
  664. v0/relationalai/semantics/lqp/rewrite/extract_keys.py +0 -449
  665. v0/relationalai/semantics/lqp/rewrite/function_annotations.py +0 -114
  666. v0/relationalai/semantics/lqp/rewrite/functional_dependencies.py +0 -314
  667. v0/relationalai/semantics/lqp/rewrite/quantify_vars.py +0 -296
  668. v0/relationalai/semantics/lqp/rewrite/splinter.py +0 -76
  669. v0/relationalai/semantics/lqp/types.py +0 -101
  670. v0/relationalai/semantics/lqp/utils.py +0 -160
  671. v0/relationalai/semantics/lqp/validators.py +0 -57
  672. v0/relationalai/semantics/metamodel/__init__.py +0 -40
  673. v0/relationalai/semantics/metamodel/builtins.py +0 -774
  674. v0/relationalai/semantics/metamodel/compiler.py +0 -133
  675. v0/relationalai/semantics/metamodel/dependency.py +0 -862
  676. v0/relationalai/semantics/metamodel/executor.py +0 -61
  677. v0/relationalai/semantics/metamodel/factory.py +0 -287
  678. v0/relationalai/semantics/metamodel/helpers.py +0 -361
  679. v0/relationalai/semantics/metamodel/rewrite/discharge_constraints.py +0 -39
  680. v0/relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +0 -210
  681. v0/relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +0 -78
  682. v0/relationalai/semantics/metamodel/rewrite/flatten.py +0 -549
  683. v0/relationalai/semantics/metamodel/rewrite/format_outputs.py +0 -165
  684. v0/relationalai/semantics/metamodel/typer/checker.py +0 -353
  685. v0/relationalai/semantics/metamodel/typer/typer.py +0 -1395
  686. v0/relationalai/semantics/metamodel/util.py +0 -505
  687. v0/relationalai/semantics/reasoners/__init__.py +0 -10
  688. v0/relationalai/semantics/reasoners/graph/__init__.py +0 -37
  689. v0/relationalai/semantics/reasoners/graph/core.py +0 -9020
  690. v0/relationalai/semantics/reasoners/optimization/__init__.py +0 -68
  691. v0/relationalai/semantics/reasoners/optimization/common.py +0 -88
  692. v0/relationalai/semantics/reasoners/optimization/solvers_dev.py +0 -568
  693. v0/relationalai/semantics/reasoners/optimization/solvers_pb.py +0 -1163
  694. v0/relationalai/semantics/rel/builtins.py +0 -40
  695. v0/relationalai/semantics/rel/compiler.py +0 -989
  696. v0/relationalai/semantics/rel/executor.py +0 -359
  697. v0/relationalai/semantics/rel/rel.py +0 -482
  698. v0/relationalai/semantics/rel/rel_utils.py +0 -276
  699. v0/relationalai/semantics/snowflake/__init__.py +0 -3
  700. v0/relationalai/semantics/sql/compiler.py +0 -2503
  701. v0/relationalai/semantics/sql/executor/duck_db.py +0 -52
  702. v0/relationalai/semantics/sql/executor/result_helpers.py +0 -64
  703. v0/relationalai/semantics/sql/executor/snowflake.py +0 -145
  704. v0/relationalai/semantics/sql/rewrite/denormalize.py +0 -222
  705. v0/relationalai/semantics/sql/rewrite/double_negation.py +0 -49
  706. v0/relationalai/semantics/sql/rewrite/recursive_union.py +0 -127
  707. v0/relationalai/semantics/sql/rewrite/sort_output_query.py +0 -246
  708. v0/relationalai/semantics/sql/sql.py +0 -504
  709. v0/relationalai/semantics/std/__init__.py +0 -54
  710. v0/relationalai/semantics/std/constraints.py +0 -43
  711. v0/relationalai/semantics/std/datetime.py +0 -363
  712. v0/relationalai/semantics/std/decimals.py +0 -62
  713. v0/relationalai/semantics/std/floats.py +0 -7
  714. v0/relationalai/semantics/std/integers.py +0 -22
  715. v0/relationalai/semantics/std/math.py +0 -141
  716. v0/relationalai/semantics/std/pragmas.py +0 -11
  717. v0/relationalai/semantics/std/re.py +0 -83
  718. v0/relationalai/semantics/std/std.py +0 -14
  719. v0/relationalai/semantics/std/strings.py +0 -63
  720. v0/relationalai/semantics/tests/__init__.py +0 -0
  721. v0/relationalai/semantics/tests/test_snapshot_abstract.py +0 -143
  722. v0/relationalai/semantics/tests/test_snapshot_base.py +0 -9
  723. v0/relationalai/semantics/tests/utils.py +0 -46
  724. v0/relationalai/std/__init__.py +0 -70
  725. v0/relationalai/tools/__init__.py +0 -0
  726. v0/relationalai/tools/cli.py +0 -1940
  727. v0/relationalai/tools/cli_controls.py +0 -1826
  728. v0/relationalai/tools/cli_helpers.py +0 -390
  729. v0/relationalai/tools/debugger.py +0 -183
  730. v0/relationalai/tools/debugger_client.py +0 -109
  731. v0/relationalai/tools/debugger_server.py +0 -302
  732. v0/relationalai/tools/dev.py +0 -685
  733. v0/relationalai/tools/qb_debugger.py +0 -425
  734. v0/relationalai/util/clean_up_databases.py +0 -95
  735. v0/relationalai/util/format.py +0 -123
  736. v0/relationalai/util/list_databases.py +0 -9
  737. v0/relationalai/util/otel_configuration.py +0 -25
  738. v0/relationalai/util/otel_handler.py +0 -484
  739. v0/relationalai/util/snowflake_handler.py +0 -88
  740. v0/relationalai/util/span_format_test.py +0 -43
  741. v0/relationalai/util/span_tracker.py +0 -207
  742. v0/relationalai/util/spans_file_handler.py +0 -72
  743. v0/relationalai/util/tracing_handler.py +0 -34
  744. /relationalai/{semantics/frontend → analysis}/__init__.py +0 -0
  745. {v0/relationalai → relationalai}/analysis/mechanistic.py +0 -0
  746. {v0/relationalai → relationalai}/analysis/whynot.py +0 -0
  747. /relationalai/{shims → auth}/__init__.py +0 -0
  748. {v0/relationalai → relationalai}/auth/jwt_generator.py +0 -0
  749. {v0/relationalai → relationalai}/auth/oauth_callback_server.py +0 -0
  750. {v0/relationalai → relationalai}/auth/token_handler.py +0 -0
  751. {v0/relationalai → relationalai}/auth/util.py +0 -0
  752. {v0/relationalai/clients → relationalai/clients/resources/snowflake}/cache_store.py +0 -0
  753. {v0/relationalai → relationalai}/compiler.py +0 -0
  754. {v0/relationalai → relationalai}/dependencies.py +0 -0
  755. {v0/relationalai → relationalai}/docutils.py +0 -0
  756. {v0/relationalai/analysis → relationalai/early_access}/__init__.py +0 -0
  757. {v0/relationalai → relationalai}/early_access/dsl/__init__.py +0 -0
  758. {v0/relationalai/auth → relationalai/early_access/dsl/adapters}/__init__.py +0 -0
  759. {v0/relationalai/early_access → relationalai/early_access/dsl/adapters/orm}/__init__.py +0 -0
  760. {v0/relationalai → relationalai}/early_access/dsl/adapters/orm/model.py +0 -0
  761. {v0/relationalai/early_access/dsl/adapters → relationalai/early_access/dsl/adapters/owl}/__init__.py +0 -0
  762. {v0/relationalai → relationalai}/early_access/dsl/adapters/owl/model.py +0 -0
  763. {v0/relationalai/early_access/dsl/adapters/orm → relationalai/early_access/dsl/bindings}/__init__.py +0 -0
  764. {v0/relationalai/early_access/dsl/adapters/owl → relationalai/early_access/dsl/bindings/legacy}/__init__.py +0 -0
  765. {v0/relationalai/early_access/dsl/bindings → relationalai/early_access/dsl/codegen}/__init__.py +0 -0
  766. {v0/relationalai → relationalai}/early_access/dsl/constants.py +0 -0
  767. {v0/relationalai → relationalai}/early_access/dsl/core/__init__.py +0 -0
  768. {v0/relationalai → relationalai}/early_access/dsl/core/constraints/__init__.py +0 -0
  769. {v0/relationalai → relationalai}/early_access/dsl/core/constraints/predicate/__init__.py +0 -0
  770. {v0/relationalai → relationalai}/early_access/dsl/core/stack.py +0 -0
  771. {v0/relationalai/early_access/dsl/bindings/legacy → relationalai/early_access/dsl/core/temporal}/__init__.py +0 -0
  772. {v0/relationalai → relationalai}/early_access/dsl/core/utils.py +0 -0
  773. {v0/relationalai/early_access/dsl/codegen → relationalai/early_access/dsl/ir}/__init__.py +0 -0
  774. {v0/relationalai/early_access/dsl/core/temporal → relationalai/early_access/dsl/ontologies}/__init__.py +0 -0
  775. {v0/relationalai → relationalai}/early_access/dsl/ontologies/raw_source.py +0 -0
  776. {v0/relationalai/early_access/dsl/ir → relationalai/early_access/dsl/orm}/__init__.py +0 -0
  777. {v0/relationalai/early_access/dsl/ontologies → relationalai/early_access/dsl/orm/measures}/__init__.py +0 -0
  778. {v0/relationalai → relationalai}/early_access/dsl/orm/reasoner_errors.py +0 -0
  779. {v0/relationalai/early_access/dsl/orm → relationalai/early_access/dsl/physical_metadata}/__init__.py +0 -0
  780. {v0/relationalai/early_access/dsl/orm/measures → relationalai/early_access/dsl/serialize}/__init__.py +0 -0
  781. {v0/relationalai → relationalai}/early_access/dsl/serialize/binding_model.py +0 -0
  782. {v0/relationalai → relationalai}/early_access/dsl/serialize/model.py +0 -0
  783. {v0/relationalai/early_access/dsl/physical_metadata → relationalai/early_access/dsl/snow}/__init__.py +0 -0
  784. {v0/relationalai → relationalai}/early_access/tests/__init__.py +0 -0
  785. {v0/relationalai → relationalai}/environments/ci.py +0 -0
  786. {v0/relationalai → relationalai}/environments/hex.py +0 -0
  787. {v0/relationalai → relationalai}/environments/terminal.py +0 -0
  788. {v0/relationalai → relationalai}/experimental/__init__.py +0 -0
  789. {v0/relationalai → relationalai}/experimental/graphs.py +0 -0
  790. {v0/relationalai → relationalai}/experimental/paths/__init__.py +0 -0
  791. {v0/relationalai → relationalai}/experimental/paths/benchmarks/__init__.py +0 -0
  792. {v0/relationalai → relationalai}/experimental/paths/path_algorithms/__init__.py +0 -0
  793. {v0/relationalai → relationalai}/experimental/paths/rpq/__init__.py +0 -0
  794. {v0/relationalai → relationalai}/experimental/paths/rpq/filter.py +0 -0
  795. {v0/relationalai → relationalai}/experimental/paths/rpq/glushkov.py +0 -0
  796. {v0/relationalai → relationalai}/experimental/paths/rpq/transition.py +0 -0
  797. {v0/relationalai → relationalai}/experimental/paths/utilities/__init__.py +0 -0
  798. {v0/relationalai → relationalai}/experimental/paths/utilities/utilities.py +0 -0
  799. {v0/relationalai/early_access/dsl/serialize → relationalai/loaders}/__init__.py +0 -0
  800. {v0/relationalai → relationalai}/metagen.py +0 -0
  801. {v0/relationalai → relationalai}/metamodel.py +0 -0
  802. {v0/relationalai → relationalai}/rel.py +0 -0
  803. {v0/relationalai → relationalai}/semantics/devtools/__init__.py +0 -0
  804. {v0/relationalai → relationalai}/semantics/internal/__init__.py +0 -0
  805. {v0/relationalai → relationalai}/semantics/internal/annotations.py +0 -0
  806. {v0/relationalai → relationalai}/semantics/lqp/__init__.py +0 -0
  807. {v0/relationalai → relationalai}/semantics/lqp/ir.py +0 -0
  808. {v0/relationalai → relationalai}/semantics/lqp/pragmas.py +0 -0
  809. {v0/relationalai → relationalai}/semantics/lqp/rewrite/__init__.py +0 -0
  810. {v0/relationalai → relationalai}/semantics/metamodel/dataflow.py +0 -0
  811. {v0/relationalai → relationalai}/semantics/metamodel/ir.py +0 -0
  812. {v0/relationalai → relationalai}/semantics/metamodel/rewrite/__init__.py +0 -0
  813. {v0/relationalai → relationalai}/semantics/metamodel/typer/__init__.py +0 -0
  814. {v0/relationalai → relationalai}/semantics/metamodel/types.py +0 -0
  815. {v0/relationalai → relationalai}/semantics/metamodel/visitor.py +0 -0
  816. {v0/relationalai → relationalai}/semantics/reasoners/experimental/__init__.py +0 -0
  817. {v0/relationalai → relationalai}/semantics/rel/__init__.py +0 -0
  818. {v0/relationalai → relationalai}/semantics/sql/__init__.py +0 -0
  819. {v0/relationalai → relationalai}/semantics/sql/executor/__init__.py +0 -0
  820. {v0/relationalai → relationalai}/semantics/sql/rewrite/__init__.py +0 -0
  821. {v0/relationalai/early_access/dsl/snow → relationalai/semantics/tests}/__init__.py +0 -0
  822. {v0/relationalai → relationalai}/semantics/tests/logging.py +0 -0
  823. {v0/relationalai → relationalai}/std/aggregates.py +0 -0
  824. {v0/relationalai → relationalai}/std/dates.py +0 -0
  825. {v0/relationalai → relationalai}/std/graphs.py +0 -0
  826. {v0/relationalai → relationalai}/std/inspect.py +0 -0
  827. {v0/relationalai → relationalai}/std/math.py +0 -0
  828. {v0/relationalai → relationalai}/std/re.py +0 -0
  829. {v0/relationalai → relationalai}/std/strings.py +0 -0
  830. {v0/relationalai/loaders → relationalai/tools}/__init__.py +0 -0
  831. {v0/relationalai → relationalai}/tools/cleanup_snapshots.py +0 -0
  832. {v0/relationalai → relationalai}/tools/constants.py +0 -0
  833. {v0/relationalai → relationalai}/tools/query_utils.py +0 -0
  834. {v0/relationalai → relationalai}/tools/snapshot_viewer.py +0 -0
  835. {v0/relationalai → relationalai}/util/__init__.py +0 -0
  836. {v0/relationalai → relationalai}/util/constants.py +0 -0
  837. {v0/relationalai → relationalai}/util/graph.py +0 -0
  838. {v0/relationalai → relationalai}/util/timeout.py +0 -0
@@ -0,0 +1,877 @@
1
+ from relationalai.semantics.metamodel import ir, builtins, helpers, types
2
+ from relationalai.semantics.metamodel.visitor import collect_by_type
3
+ from relationalai.semantics.metamodel.util import FrozenOrderedSet
4
+ from relationalai.semantics.lqp import ir as lqp, utils, types as lqp_types, builtins as lqp_builtins
5
+ from relationalai.semantics.lqp.primitives import lqp_avg_op, lqp_operator, build_primitive
6
+ from relationalai.semantics.lqp.pragmas import pragma_to_lqp_name
7
+ from relationalai.semantics.lqp.types import meta_type_to_lqp
8
+ from relationalai.semantics.lqp.constructors import (
9
+ mk_abstraction, mk_and, mk_exists, mk_or, mk_pragma, mk_primitive,
10
+ mk_specialized_value, mk_type, mk_value, mk_attribute
11
+ )
12
+ from relationalai.semantics.lqp.utils import TranslationCtx, gen_unique_var
13
+ from relationalai.semantics.lqp.validators import assert_valid_input
14
+ from relationalai.semantics.lqp.rewrite.functional_dependencies import (
15
+ normalized_fd, contains_only_declarable_constraints
16
+ )
17
+ from decimal import Decimal as PyDecimal
18
+ from datetime import datetime, date, timezone
19
+ from typing import Tuple, cast, Union, Optional
20
+ from warnings import warn
21
+ import re
22
+ import uuid
23
+
24
+ # Main access point for translating metamodel to lqp. Converts the model IR to an LQP epoch.
25
+ def to_lqp(model: ir.Model, fragment_name: bytes, ctx: TranslationCtx) -> tuple[Optional[tuple], lqp.Epoch]:
26
+ assert_valid_input(model)
27
+ decls: list[lqp.Declaration] = []
28
+ reads: list[lqp.Read] = []
29
+
30
+ # LQP only accepts logical tasks
31
+ # These are asserted at init time
32
+ root = cast(ir.Logical, model.root)
33
+ for subtask in root.body:
34
+ assert isinstance(subtask, ir.Logical)
35
+ new_decls = _translate_to_decls(ctx, subtask)
36
+ decls.extend(new_decls)
37
+
38
+ # Add pyrel error attributes to reads.
39
+ for err_id in _extract_pyrel_error_ids(ctx, model):
40
+ ctx.output_ids.append(err_id)
41
+
42
+ reads.extend(_get_output_reads(ctx.output_ids))
43
+
44
+ export_info = None
45
+ if len(ctx.export_ids) > 0:
46
+ export_filename, col_types, export_reads = _get_export_reads(ctx.export_ids)
47
+ reads.extend(export_reads)
48
+ export_info = (export_filename, col_types)
49
+
50
+ debug_info = lqp.DebugInfo(id_to_orig_name=ctx.rel_id_to_orig_name, meta=None)
51
+ fragment_id = lqp.FragmentId(id=fragment_name, meta=None)
52
+ fragment = lqp.Fragment(id=fragment_id, declarations=decls, meta=None, debug_info=debug_info)
53
+ define_op = lqp.Define(fragment=fragment, meta=None)
54
+
55
+ txn = lqp.Epoch(
56
+ reads=reads,
57
+ writes=[lqp.Write(write_type=define_op, meta=None)],
58
+ meta=None
59
+ )
60
+
61
+ return (export_info, txn)
62
+
63
+ def _effect_bindings(effect: Union[ir.Output, ir.Update]) -> list[ir.Value]:
64
+ if isinstance(effect, ir.Output):
65
+ # Unions may not return anything. The generated IR contains a None value when this
66
+ # happens. We ignore it here.
67
+ return [v for v in helpers.output_values(effect.aliases) if v]
68
+ else:
69
+ return list(effect.args)
70
+
71
+ def _get_output_reads(output_ids: list[tuple[lqp.RelationId, str]]) -> list[lqp.Read]:
72
+ reads = []
73
+ for (rel_id, name) in output_ids:
74
+ assert isinstance(rel_id, lqp.RelationId)
75
+ output = lqp.Output(name=name, relation_id=rel_id, meta=None)
76
+ reads.append(lqp.Read(read_type=output, meta=None))
77
+ return reads
78
+
79
+ def _get_export_reads(export_ids: list[tuple[lqp.RelationId, int, lqp.Type]]) -> tuple[str, list, list[lqp.Read]]:
80
+ reads = []
81
+ csv_columns = []
82
+ col_info = []
83
+ for (col_id, col_num, col_type) in sorted(export_ids, key=lambda x: x[1]):
84
+ col_name = f"col{col_num:03}"
85
+ csv_columns.append(lqp.ExportCSVColumn(column_name=col_name, column_data=col_id, meta=None))
86
+ col_info.append((col_name, col_type))
87
+
88
+ # Generate a random name for the internal export path
89
+ export_filename = "export_" + str(uuid.uuid4()).replace("-", "_")
90
+
91
+ # Note that the engine will append the transaction id to the export path for access
92
+ # control reasons. So the actual final path will be
93
+ # `.../export/{export_filename}/data_{txn_id}`
94
+ export_path = f"snowflake://APP_STATE.RAI_INTERNAL_STAGE/export/{export_filename}/data"
95
+ export_csv_config = lqp.ExportCSVConfig(
96
+ path=export_path,
97
+ data_columns=csv_columns,
98
+ compression="gzip",
99
+ partition_size=200,
100
+ syntax_escapechar='"', # To follow Snowflake's expected format
101
+ meta=None,
102
+ )
103
+ reads.append(lqp.Read(read_type=lqp.Export(config=export_csv_config, meta=None), meta=None))
104
+ return (export_filename, col_info, reads)
105
+
106
+ def _translate_to_decls(ctx: TranslationCtx, rule: ir.Logical) -> list[lqp.Declaration]:
107
+ if contains_only_declarable_constraints(rule):
108
+ return _translate_to_constraint_decls(ctx, rule)
109
+ else:
110
+ return _translate_to_standard_decl(ctx, rule)
111
+
112
+ def _translate_to_constraint_decls(ctx: TranslationCtx, rule: ir.Logical) -> list[lqp.Declaration]:
113
+ constraint_decls: list[lqp.Declaration] = []
114
+ for task in rule.body:
115
+ assert isinstance(task, ir.Require)
116
+ fd = normalized_fd(task)
117
+ assert fd is not None
118
+
119
+ # check for unresolved types
120
+ if any(types.is_any(var.type) for var in fd.keys + fd.values):
121
+ warn(f"Ignoring FD with unresolved type: {fd}")
122
+ continue
123
+
124
+ lqp_typed_keys = [_translate_term(ctx, key) for key in fd.keys]
125
+ lqp_typed_values = [_translate_term(ctx, value) for value in fd.values]
126
+ lqp_typed_vars:list[Tuple[lqp.Var, lqp.Type]] = lqp_typed_keys + lqp_typed_values # type: ignore
127
+ lqp_guard_atoms = [_translate_to_atom(ctx, atom) for atom in fd.guard]
128
+ lqp_guard = mk_abstraction(lqp_typed_vars, mk_and(lqp_guard_atoms))
129
+ lqp_keys:list[lqp.Var] = [var for (var, _) in lqp_typed_keys] # type: ignore
130
+ lqp_values:list[lqp.Var] = [var for (var, _) in lqp_typed_values] # type: ignore
131
+
132
+ fd_decl = lqp.FunctionalDependency(
133
+ guard=lqp_guard,
134
+ keys=lqp_keys,
135
+ values=lqp_values,
136
+ meta=None
137
+ )
138
+
139
+ constraint_decls.append(fd_decl)
140
+
141
+ return constraint_decls
142
+
143
+ def _translate_to_standard_decl(ctx: TranslationCtx, rule: ir.Logical) -> list[lqp.Declaration]:
144
+ effects = collect_by_type((ir.Output, ir.Update), rule)
145
+ aggregates = collect_by_type(ir.Aggregate, rule)
146
+ ranks = collect_by_type(ir.Rank, rule)
147
+
148
+ # TODO: should this ever actually come in as input?
149
+ if len(effects) == 0:
150
+ return []
151
+
152
+ assert len(ranks) == 0 or len(aggregates) == 0, "rules cannot have both aggregates and ranks"
153
+
154
+ conjuncts = []
155
+ for task in rule.body:
156
+ if isinstance(task, (ir.Output, ir.Update)):
157
+ continue
158
+ conjuncts.append(_translate_to_formula(ctx, task))
159
+
160
+ # Aggregates reduce over the body
161
+ if aggregates or ranks:
162
+ aggr_body = mk_and(conjuncts)
163
+ conjuncts = []
164
+ for aggr in aggregates:
165
+ conjuncts.append(_translate_aggregate(ctx, aggr, aggr_body))
166
+ for rank in ranks:
167
+ conjuncts.append(_translate_rank(ctx, rank, aggr_body))
168
+
169
+ return [_translate_effect(ctx, effect, mk_and(conjuncts)) for effect in effects]
170
+
171
+ def _translate_annotations(annotations: FrozenOrderedSet[ir.Annotation]) -> list[lqp.Attribute]:
172
+ attributes = []
173
+ for annotation in annotations:
174
+
175
+ if annotation.relation.name in lqp_builtins.annotations_to_emit:
176
+ if any(not isinstance(a, ir.Literal) for a in annotation.args):
177
+ warn("LQP currently ignores annotation parameters with non-literal values")
178
+ continue
179
+
180
+ # Convert literal arguments to LQP values
181
+ args = []
182
+ for a in annotation.args:
183
+ assert isinstance(a, ir.Literal)
184
+ args.append(mk_value(a.value))
185
+ attributes.append(mk_attribute(annotation.relation.name, args))
186
+ return attributes
187
+
188
+ # Translates an effect (export, output, or update) into the corresponding def. Note that
189
+ # this method only generates the def and not the LQP read operation, which is added later by
190
+ # `_get_output_reads` and `_get_export_reads`.
191
+ def _translate_effect(ctx: TranslationCtx, effect: Union[ir.Output, ir.Update], body: lqp.Formula) -> lqp.Declaration:
192
+ bindings = _effect_bindings(effect)
193
+
194
+ def _is_export(e):
195
+ return isinstance(e, ir.Output) and builtins.export_annotation in e.annotations
196
+
197
+ if isinstance(effect, ir.Output):
198
+ projection, eqs, suffix = _translate_output_bindings(ctx, bindings)
199
+ meta_id = effect.id
200
+
201
+ if _is_export(effect):
202
+ def_name = "export_relation" + suffix
203
+ else:
204
+ def_name = "output" + suffix
205
+
206
+ def_name = ctx.output_names.get_name_by_id(meta_id, def_name)
207
+ rel_id = get_output_id(ctx, def_name, meta_id)
208
+ else:
209
+ projection, eqs = _translate_bindings(ctx, bindings)
210
+ def_name = effect.relation.name
211
+ rel_id = get_relation_id(ctx, effect.relation, projection)
212
+
213
+ eqs.append(body)
214
+ new_body = mk_and(eqs)
215
+
216
+ # Context bookkeeping for exports and outputs
217
+ if _is_export(effect):
218
+ # The row id is the first n-1 elements, and the actual data is the last element. Its
219
+ # type is stored in the first element of the tuple.
220
+ col_type = projection[-1][1]
221
+ _col_num_match = re.search(r"export_relation_col([0-9]+)", def_name)
222
+ assert _col_num_match, f"Could not find column number in suffix: {def_name}"
223
+ col_num = int(_col_num_match.group(1))
224
+ ctx.export_ids.append((rel_id, col_num, col_type))
225
+ elif isinstance(effect, ir.Output):
226
+ ctx.output_ids.append((rel_id, def_name))
227
+
228
+ # First we collect annotations on the effect itself, e.g. from something like
229
+ # `select(...).annotate(...)`.
230
+ annotations = effect.annotations
231
+ if isinstance(effect, ir.Update):
232
+ # Then we translate annotations on the relation itself, e.g.
233
+ # ```
234
+ # Bar.foo = model.Relationship(...)
235
+ # Bar.foo.annotate(...)
236
+ # ```
237
+ annotations = annotations | effect.relation.annotations
238
+
239
+ return lqp.Def(
240
+ name = rel_id,
241
+ body = mk_abstraction(projection, new_body),
242
+ attrs = _translate_annotations(annotations),
243
+ meta = None,
244
+ )
245
+
246
+ def _translate_output_bindings(ctx: TranslationCtx, bindings: list[ir.Value]) -> Tuple[list[Tuple[lqp.Var, lqp.Type]], list[lqp.Formula], str]:
247
+ symbol_literals = []
248
+ non_symbols = []
249
+ for binding in bindings:
250
+ if isinstance(binding, ir.Literal) and binding.type == types.Symbol:
251
+ symbol_literals.append(binding.value)
252
+ else:
253
+ non_symbols.append(binding)
254
+ projection, eqs = _translate_bindings(ctx, non_symbols)
255
+ if len(symbol_literals) > 0:
256
+ name_suffix = "_"
257
+ name_suffix += "_".join(symbol_literals)
258
+ else:
259
+ name_suffix = ""
260
+
261
+ return projection, eqs, name_suffix
262
+
263
+ def _translate_rank(ctx: TranslationCtx, rank: ir.Rank, body: lqp.Formula) -> lqp.Formula:
264
+ # Ascending rank is constructed using rel_primitive_sort. If a limit is added to an
265
+ # ascending rank we can use rel_primitive_top for an efficient evaluation.
266
+ #
267
+ # Descending rank is constructed as an ascending sort, then the ascending rank is
268
+ # subtracted from a count of the elements (plus 1 so that we still start at 1).
269
+ # Adding a limit to a descending rank is done by adding a filter of rank <= limit.
270
+
271
+ # Limits are the sort plus a filter on rank <= limit.
272
+ if all(o for o in rank.arg_is_ascending):
273
+ ascending = True
274
+ elif all(not o for o in rank.arg_is_ascending):
275
+ ascending = False
276
+ else:
277
+ raise Exception("Mixed orderings in rank are not supported yet.")
278
+
279
+ # Filter out the group-by variables, since they are introduced outside the rank.
280
+ input_args, input_eqs = _translate_bindings(ctx, list(rank.args))
281
+ introduced_meta_projs = [arg for arg in rank.projection if arg not in rank.group and arg not in rank.args]
282
+ projected_args, projected_eqs = _translate_bindings(ctx, list(introduced_meta_projs))
283
+
284
+ # rank expects an Int128 result, but the primitive will return an Int64 result.
285
+ # we need to set up an intermediary variable to hold the Int64 result, and a cast
286
+ # to convert it to Int128.
287
+ result_var, _ = _translate_term(ctx, rank.result)
288
+ # The primitive will return an Int64 result, so we need a var to hold the intermediary.
289
+ result_64_var = gen_unique_var(ctx, "v_rank")
290
+ result_64_type = mk_type(lqp.TypeName.INT)
291
+
292
+ cast = lqp.Cast(input=result_64_var, result=result_var, meta=None)
293
+
294
+ body = mk_and([body] + input_eqs + projected_eqs)
295
+ abstr_args = input_args + projected_args
296
+
297
+ if ascending:
298
+ ranker = _translate_ascending_rank(ctx, rank.limit, result_64_var, body, abstr_args)
299
+ else:
300
+ ranker = _translate_descending_rank(ctx, rank.limit, result_64_var, body, abstr_args)
301
+
302
+ return mk_exists([(result_64_var, result_64_type)], mk_and([ranker, cast]))
303
+
304
+ def _translate_descending_rank(ctx: TranslationCtx, limit: int, result: lqp.Var, body: lqp.Formula, abstr_args) -> lqp.Formula:
305
+ result_var = result
306
+ result_type = mk_type(lqp.TypeName.INT)
307
+
308
+ # Rename abstracted args in the body to new variable names
309
+ var_map = {var.name: gen_unique_var(ctx, 't_' + var.name) for (var, _) in abstr_args}
310
+ body = utils.rename_vars_formula(body, var_map)
311
+ new_abstr_args = [(var_map[var.name], typ) for (var, typ) in abstr_args]
312
+
313
+ # Construct a conjunction of the ranking, a counter for the body, a subtraction
314
+ # of the rank from the count and an addition of 1. Wrap this in an abstraction.
315
+ count_res = gen_unique_var(ctx, "count_res")
316
+
317
+ # Add one to the count to account for the rank starting at 1.
318
+ one, one_eq = constant_to_var(ctx, to_lqp_value(1, types.Int64), "one")
319
+ one_bigger = gen_unique_var(ctx, "one_bigger")
320
+ addition = mk_primitive("rel_primitive_add_monotype", [count_res, one, one_bigger])
321
+
322
+ # Subtract the rank from the count + 1
323
+ asc_rank = gen_unique_var(ctx, "asc_rank")
324
+ subtraction = mk_primitive("rel_primitive_subtract_monotype", [one_bigger, result_var, asc_rank])
325
+
326
+ # Construct the ranking
327
+ desc_ranking_terms = [asc_rank] + [v[0] for v in abstr_args]
328
+ ranking = lqp.FFI(
329
+ meta=None,
330
+ name="rel_primitive_sort",
331
+ args=[mk_abstraction(new_abstr_args, body)],
332
+ terms=desc_ranking_terms,
333
+ )
334
+
335
+ # Count the number of rows in the body
336
+ count_type = meta_type_to_lqp(types.Int64)
337
+ count_var, count_eq = constant_to_var(ctx, to_lqp_value(1, types.Int64), "counter")
338
+ desc_body = mk_and([body, count_eq])
339
+ aggr_abstr_args = new_abstr_args + [(count_var, count_type)]
340
+ count_aggr = lqp.Reduce(
341
+ op=lqp_operator(
342
+ ctx,
343
+ "count",
344
+ "count",
345
+ mk_type(lqp.TypeName.INT)
346
+ ),
347
+ body=mk_abstraction(aggr_abstr_args, desc_body),
348
+ terms=[count_res],
349
+ meta=None
350
+ )
351
+
352
+ # Bring it all together and do the maths.
353
+ ranking = mk_exists(
354
+ vars=[
355
+ (asc_rank, result_type),
356
+ (count_res, result_type),
357
+ (one, result_type),
358
+ (one_bigger, result_type)
359
+ ],
360
+ value=mk_and([ranking, count_aggr, one_eq, addition, subtraction])
361
+ )
362
+
363
+ # If there is a limit, we need to add a filter to the ranking.
364
+ # Wrap with a rank <= limit
365
+ if limit != 0:
366
+ limit_term, _ = _translate_term(ctx, ir.Literal(types.Int64, limit))
367
+ limiter = mk_primitive("rel_primitive_lt_eq_monotype", [result_var, limit_term])
368
+ ranking = mk_and([ranking, limiter])
369
+
370
+ return ranking
371
+
372
+ def _translate_ascending_rank(ctx: TranslationCtx, limit: int, result_var: lqp.Var, body: lqp.Formula, abstr_args) -> lqp.Formula:
373
+ terms = [result_var] + [v[0] for v in abstr_args]
374
+
375
+ # Rename abstracted args in the body to new variable names
376
+ var_map = {var.name: gen_unique_var(ctx, 't_' + var.name) for (var, _) in abstr_args}
377
+ body = utils.rename_vars_formula(body, var_map)
378
+ new_abstr_args = [(var_map[var.name], typ) for (var, typ) in abstr_args]
379
+ sort_abstr = mk_abstraction(new_abstr_args, body)
380
+
381
+ if limit == 0:
382
+ return lqp.FFI(
383
+ meta=None,
384
+ name="rel_primitive_sort",
385
+ args=[sort_abstr],
386
+ terms=terms,
387
+ )
388
+ else:
389
+ limit_type = meta_type_to_lqp(types.Int64)
390
+ limit_var, limit_eq = constant_to_var(ctx, to_lqp_value(limit, types.Int64), "limit")
391
+ limit_abstr = mk_abstraction([(limit_var, limit_type)], limit_eq)
392
+ return lqp.FFI(
393
+ meta=None,
394
+ name="rel_primitive_top",
395
+ args=[sort_abstr, limit_abstr],
396
+ terms=terms,
397
+ )
398
+
399
+ def _rename_shadowed_abstraction_vars(
400
+ ctx: TranslationCtx,
401
+ aggr: ir.Aggregate,
402
+ abstr_args: list[Tuple[lqp.Var, lqp.Type]],
403
+ body_conjs: list[lqp.Formula]
404
+ ) -> list[Tuple[lqp.Var, lqp.Type]]:
405
+ """
406
+ Rename abstraction variables that shadow group-by variables.
407
+
408
+ This can happen when the same variable appears in both aggr.group and as an input
409
+ to the aggregation, e.g., min(Person.age).per(Person.age). The group-by variables
410
+ are in the outer scope, while the abstraction parameters are in the inner scope,
411
+ so we need different names to avoid shadowing.
412
+ """
413
+ # Get the LQP names of group-by variables
414
+ group_var_names = set()
415
+ for group_var in aggr.group:
416
+ lqp_var = _translate_var(ctx, group_var)
417
+ group_var_names.add(lqp_var.name)
418
+
419
+ # Rename any abstraction parameters that conflict with group-by variables
420
+ renamed_abstr_args = []
421
+ for var, typ in abstr_args:
422
+ if var.name in group_var_names:
423
+ # This variable shadows a group-by variable, so rename it
424
+ fresh_var = gen_unique_var(ctx, var.name)
425
+ # Add an equality constraint: fresh_var == var
426
+ # var is a free variable referring to the outer scope group-by variable
427
+ body_conjs.append(mk_primitive("rel_primitive_eq", [fresh_var, var]))
428
+ renamed_abstr_args.append((fresh_var, typ))
429
+ else:
430
+ renamed_abstr_args.append((var, typ))
431
+
432
+ return renamed_abstr_args
433
+
434
+ def _translate_aggregate(ctx: TranslationCtx, aggr: ir.Aggregate, body: lqp.Formula) -> Union[lqp.Reduce, lqp.Formula]:
435
+ # TODO: handle this properly
436
+ aggr_name = aggr.aggregation.name
437
+ supported_aggrs = ("sum", "count", "avg", "min", "max", "rel_primitive_solverlib_ho_appl")
438
+ assert aggr_name in supported_aggrs, f"only support {supported_aggrs} for now, not {aggr.aggregation.name}"
439
+
440
+ meta_output_terms = []
441
+ meta_input_terms = []
442
+
443
+ for (field, arg) in zip(aggr.aggregation.fields, aggr.args):
444
+ if field.input:
445
+ meta_input_terms.append(arg)
446
+ else:
447
+ meta_output_terms.append(arg)
448
+
449
+ output_terms = [_translate_term(ctx, term) for term in meta_output_terms]
450
+ output_vars = [term[0] for term in output_terms]
451
+
452
+ body_conjs = [body]
453
+ input_args, input_eqs = _translate_bindings(ctx, meta_input_terms)
454
+
455
+ # TODO: Can this safely be applied to all aggregates?
456
+ if aggr_name in ("sum", "min", "max"):
457
+ assert len(output_terms) == 1, f"{aggr_name} expects a single output variable"
458
+ assert len(meta_input_terms) == 1, f"{aggr_name} expects a single input variable"
459
+ assert isinstance(meta_output_terms[0], ir.Var)
460
+ assert input_args[0][1] == output_terms[0][1], f"{aggr_name}({input_args[0][1].type_name}) had output type of {output_terms[0][1].type_name}"
461
+
462
+ # Filter out the group-by variables, since they are introduced outside the aggregation.
463
+ # Input terms are added later below.
464
+ introduced_meta_projs = [arg for arg in aggr.projection if arg not in aggr.group and arg not in meta_input_terms]
465
+ projected_args, projected_eqs = _translate_bindings(ctx, list(introduced_meta_projs))
466
+ body_conjs.extend(input_eqs)
467
+ body_conjs.extend(projected_eqs)
468
+ abstr_args: list[Tuple[lqp.Var, lqp.Type]] = projected_args + input_args
469
+
470
+ # Rename abstraction variables that shadow group-by variables
471
+ abstr_args = _rename_shadowed_abstraction_vars(ctx, aggr, abstr_args, body_conjs)
472
+
473
+ if aggr_name == "count":
474
+ assert len(output_terms) == 1, "Count and avg expect a single output variable"
475
+ assert isinstance(meta_output_terms[0], ir.Var)
476
+ # Count sums up "1" for each row. We use the expected output type for the type
477
+ # of the count variable.
478
+ typ = meta_type_to_lqp(meta_output_terms[0].type)
479
+ one_var, eq = constant_to_var(ctx, to_lqp_value(1, meta_output_terms[0].type), "one")
480
+ body_conjs.append(eq)
481
+ abstr_args.append((one_var, typ))
482
+
483
+ # Average needs to wrap the reduce in Exists(Conjunction(Reduce, div))
484
+ if aggr_name == "avg":
485
+ assert len(output_vars) == 1, "avg should only have one output variable"
486
+ output_var = output_vars[0]
487
+
488
+ # Count sums up "1" for each row. We make the reasonably safe assumption that there
489
+ # are less than 2^31 rows in the body.
490
+ count_type = meta_type_to_lqp(types.Int64)
491
+ one_var, eq = constant_to_var(ctx, to_lqp_value(1, types.Int64), "one")
492
+ body_conjs.append(eq)
493
+ abstr_args.append((one_var, count_type))
494
+
495
+ # The average will produce two output variables: sum and count.
496
+ sum_result = gen_unique_var(ctx, "sum")
497
+ count_result = gen_unique_var(ctx, "count")
498
+
499
+ # Second to last is the variable we're summing over.
500
+ (sum_var, sum_type) = abstr_args[-2]
501
+ body = mk_and(body_conjs)
502
+
503
+ result = lqp.Reduce(
504
+ op=lqp_avg_op(ctx, aggr.aggregation.name, sum_var.name, sum_type),
505
+ body=mk_abstraction(abstr_args, body),
506
+ terms=[sum_result, count_result],
507
+ meta=None,
508
+ )
509
+
510
+ if sum_type == count_type:
511
+ div = mk_primitive("rel_primitive_divide_monotype", [sum_result, count_result, output_var])
512
+ conjunction = mk_and([result, div])
513
+
514
+ # Finally, we need to wrap everything in an `exists` to project away the sum and
515
+ # count variables and only keep the result of the division.
516
+ result_terms = [(sum_result, sum_type), (count_result, count_type)]
517
+ else:
518
+ # If the sum type and count type don't match, we need to cast the count
519
+ count_casted = gen_unique_var(ctx, "count_casted")
520
+ count_cast = lqp.Cast(input=count_result, result=count_casted, meta=None)
521
+
522
+ div = mk_primitive("rel_primitive_divide_monotype", [sum_result, count_casted, output_var])
523
+ conjunction = mk_and([result, count_cast, div])
524
+
525
+ # Finally, we need to wrap everything in an `exists` to project away the sum and
526
+ # count variables and only keep the result of the division.
527
+ result_terms = [(sum_result, sum_type), (count_result, count_type), (count_casted, sum_type)]
528
+
529
+ return mk_exists(result_terms, conjunction)
530
+
531
+ # `input_args` hold the types of the input arguments, but they may have been modified
532
+ # if we're dealing with a count, so we use `abstr_args` to find the type.
533
+ (aggr_arg, aggr_arg_type) = abstr_args[-1]
534
+ body = mk_and(body_conjs)
535
+
536
+ # Group-bys do not need to be handled at all, since they are introduced outside already
537
+ reduce = lqp.Reduce(
538
+ op=lqp_operator(ctx, aggr.aggregation.name, aggr_arg.name, aggr_arg_type),
539
+ body=mk_abstraction(abstr_args, body),
540
+ terms=output_vars,
541
+ meta=None
542
+ )
543
+ return reduce
544
+
545
+ def _translate_to_formula(ctx: TranslationCtx, task: ir.Task) -> lqp.Formula:
546
+ if isinstance(task, ir.Logical):
547
+ conjuncts = [_translate_to_formula(ctx, child) for child in task.body]
548
+ return mk_and(conjuncts)
549
+ elif isinstance(task, ir.Lookup):
550
+ return _translate_to_atom(ctx, task)
551
+ elif isinstance(task, ir.Not):
552
+ return lqp.Not(arg=_translate_to_formula(ctx, task.task), meta=None)
553
+ elif isinstance(task, ir.Exists):
554
+ lqp_vars, conjuncts = _translate_bindings(ctx, list(task.vars))
555
+ conjuncts.append(_translate_to_formula(ctx, task.task))
556
+ return mk_exists(lqp_vars, mk_and(conjuncts))
557
+ elif isinstance(task, ir.Construct):
558
+ assert len(task.values) >= 1, "Construct should have at least one value"
559
+ terms = [_translate_term(ctx, arg) for arg in task.values]
560
+ result_term = _translate_term(ctx, task.id_var)
561
+ terms.append(result_term)
562
+ assert result_term[1].type_name == lqp.TypeName.UINT128, \
563
+ f"Attempting to store a {task.id_var} in a type `{result_term[1].type_name}`"
564
+
565
+ return mk_primitive("rel_primitive_hash_tuple_uint128", [v for v, _ in terms])
566
+ elif isinstance(task, ir.Union):
567
+ # TODO: handle hoisted vars if needed
568
+ disjs = [_translate_to_formula(ctx, child) for child in task.tasks]
569
+ return mk_or(disjs)
570
+ elif isinstance(task, (ir.Aggregate, ir.Output, ir.Update)):
571
+ # Nothing to do here, handled in _translate_to_decls
572
+ return mk_and([])
573
+ elif isinstance(task, ir.Rank):
574
+ # Nothing to do here, handled in _translate_to_decls
575
+ return mk_and([])
576
+ else:
577
+ raise NotImplementedError(f"Unknown task type (formula): {type(task)}")
578
+
579
+ # Only used for translating terms on relatoms, which can be specialized values.
580
+ def _translate_relterm(ctx: TranslationCtx, term: ir.Value) -> Tuple[lqp.RelTerm, lqp.Type]:
581
+ if isinstance(term, ir.Literal) and term.type == types.Symbol:
582
+ if isinstance(term.value, str):
583
+ value = mk_value(term.value)
584
+ return mk_specialized_value(value), meta_type_to_lqp(types.String)
585
+ elif isinstance(term.value, int):
586
+ value = mk_value(term.value)
587
+ return mk_specialized_value(value), meta_type_to_lqp(types.Int64)
588
+ else:
589
+ raise NotImplementedError(f"Cannot specialize literal of type {type(term.value)}")
590
+ return _translate_term(ctx, term)
591
+
592
+ def _translate_term(ctx: TranslationCtx, term: ir.Value) -> Tuple[lqp.Term, lqp.Type]:
593
+ if isinstance(term, ir.ScalarType):
594
+ # TODO: ScalarType is not like other terms, should be handled separately.
595
+ return to_lqp_value(term.name, types.String), meta_type_to_lqp(types.String)
596
+ elif isinstance(term, ir.Var):
597
+ t = meta_type_to_lqp(term.type)
598
+ return _translate_var(ctx, term), t
599
+ else:
600
+ assert isinstance(term, ir.Literal), f"Cannot translate value {term!r} of type {type(term)} to LQP Term; neither Var nor Literal."
601
+ v = to_lqp_value(term.value, term.type)
602
+ return v, meta_type_to_lqp(term.type)
603
+
604
+ def _translate_to_atom(ctx: TranslationCtx, task: ir.Lookup) -> lqp.Formula:
605
+ if task.relation == builtins.cast:
606
+ assert len(task.args) == 3, f"expected three terms for {task.relation.name}, got {len(task.args)}"
607
+
608
+ terms = []
609
+ for arg in task.args[1:]:
610
+ term, _ = _translate_relterm(ctx, arg)
611
+ terms.append(term)
612
+ return lqp.Cast(input=terms[0], result=terms[1], meta=None)
613
+
614
+ if task.relation == builtins.join:
615
+ return _translate_join(ctx, task)
616
+ elif task.relation == builtins.infomap:
617
+ return _translate_infomap(ctx, task)
618
+ elif task.relation == builtins.louvain:
619
+ return _translate_louvain(ctx, task)
620
+ elif task.relation == builtins.label_propagation:
621
+ return _translate_label_propagation(ctx, task)
622
+
623
+ terms = []
624
+ term_types = []
625
+ for arg in task.args:
626
+ # Handle varargs, which come wrapped in a tuple.
627
+ if isinstance(arg, tuple):
628
+ for vararg in arg:
629
+ term, ty = _translate_relterm(ctx, vararg)
630
+ terms.append(term)
631
+ term_types.append(ty)
632
+ else:
633
+ term, ty = _translate_relterm(ctx, arg)
634
+ terms.append(term)
635
+ term_types.append(ty)
636
+
637
+ if builtins.is_pragma(task.relation):
638
+ lqp_name = pragma_to_lqp_name(task.relation.name)
639
+ return mk_pragma(lqp_name, terms)
640
+
641
+ if builtins.is_builtin(task.relation):
642
+ return build_primitive(task.relation.name, terms, term_types)
643
+
644
+ if helpers.is_external(task.relation):
645
+ return lqp.RelAtom(name=task.relation.name, terms=terms, meta=None)
646
+
647
+ projection, _ = _translate_bindings(ctx, list(task.args))
648
+ rid = get_relation_id(ctx, task.relation, projection)
649
+ return lqp.Atom(name=rid, terms=terms, meta=None)
650
+
651
+
652
+ def get_relation_id(ctx: TranslationCtx, relation: ir.Relation, projection: list[Tuple[lqp.Var, lqp.Type]] = []) -> lqp.RelationId:
653
+ types = "_".join([str(t.type_name) for (_, t) in projection])
654
+ if types:
655
+ types = "_" + types
656
+ if relation.id in ctx.def_names.id_to_name:
657
+ unique_name = ctx.def_names.id_to_name[relation.id]
658
+ else:
659
+ name = helpers.relation_name_prefix(relation) + relation.name
660
+ name = helpers.sanitize(name)
661
+ unique_name = ctx.def_names.get_name_by_id(relation.id, name)
662
+
663
+ return utils.gen_rel_id(ctx, unique_name, types)
664
+
665
+ def get_output_id(ctx: TranslationCtx, orig_name: str, metamodel_id: int) -> lqp.RelationId:
666
+ unique_name = ctx.output_names.get_name_by_id(metamodel_id, orig_name)
667
+ return utils.gen_rel_id(ctx, unique_name)
668
+
669
+ def _translate_bindings(ctx: TranslationCtx, bindings: list[ir.Value]) -> Tuple[list[Tuple[lqp.Var, lqp.Type]], list[lqp.Formula]]:
670
+ lqp_vars = []
671
+ conjuncts = []
672
+ for binding in bindings:
673
+ lqp_var, typ, eq = binding_to_lqp_var(ctx, binding)
674
+ lqp_vars.append((lqp_var, typ))
675
+ if eq is not None:
676
+ conjuncts.append(eq)
677
+
678
+ return lqp_vars, conjuncts
679
+
680
+ def binding_to_lqp_var(ctx: TranslationCtx, binding: ir.Value) -> Tuple[lqp.Var, lqp.Type, Union[None, lqp.Formula]]:
681
+ if isinstance(binding, ir.Var):
682
+ var, typ = _translate_term(ctx, binding)
683
+ assert isinstance(var, lqp.Var)
684
+ return var, typ, None
685
+ elif isinstance(binding, ir.Literal):
686
+ lqp_value = to_lqp_value(binding.value, binding.type)
687
+ var, formula = constant_to_var(ctx, lqp_value)
688
+ return var, meta_type_to_lqp(binding.type), formula
689
+ else:
690
+ raise Exception(f"Unsupported binding type: {type(binding)}")
691
+
692
+ def to_lqp_value(value: ir.PyValue, value_type: ir.Type) -> lqp.Value:
693
+ typ = meta_type_to_lqp(value_type)
694
+
695
+ # Ensure int values match the requested integer type.
696
+ if typ.type_name == lqp.TypeName.INT and isinstance(value, int):
697
+ assert lqp_types.INT_MIN <= value <= lqp_types.INT_MAX, f"{value} out of range for a 64-bit INT value"
698
+ val = value
699
+ elif typ.type_name == lqp.TypeName.INT128 and isinstance(value, int):
700
+ assert lqp_types.INT128_MIN <= value <= lqp_types.INT128_MAX, f"{value} out of range for an INT128 value"
701
+ val = lqp.Int128Value(value=value, meta=None)
702
+ elif typ.type_name == lqp.TypeName.UINT128 and isinstance(value, int):
703
+ assert lqp_types.UINT128_MIN <= value <= lqp_types.UINT128_MAX, f"{value} out of range for an UINT128 value"
704
+ val = lqp.UInt128Value(value=value, meta=None)
705
+ elif typ.type_name == lqp.TypeName.FLOAT and isinstance(value, float):
706
+ val = value
707
+ elif typ.type_name == lqp.TypeName.STRING and isinstance(value, str):
708
+ val = value
709
+ elif typ.type_name == lqp.TypeName.DECIMAL and isinstance(value, (int, float, PyDecimal)):
710
+ precision = typ.parameters[0].value
711
+ scale = typ.parameters[1].value
712
+ assert isinstance(precision, int) and isinstance(scale, int)
713
+ val = lqp.DecimalValue(precision=precision, scale=scale, value=PyDecimal(value), meta=None)
714
+ elif typ.type_name == lqp.TypeName.DATE and isinstance(value, date):
715
+ val = lqp.DateValue(value=value, meta=None)
716
+ elif typ.type_name == lqp.TypeName.DATETIME and isinstance(value, datetime):
717
+ utc_value = value.astimezone(timezone.utc) if value.tzinfo is not None else value # Convert to UTC cf. Iceberg
718
+ val = lqp.DateTimeValue(value=utc_value, meta=None)
719
+ elif typ.type_name == lqp.TypeName.BOOLEAN and isinstance(value, bool):
720
+ val = lqp.BooleanValue(value=value, meta=None)
721
+ else:
722
+ raise Exception(f"Unsupported type for constant: {typ.type_name} with value {value} of type {type(value)}")
723
+
724
+ return mk_value(val)
725
+
726
+ def constant_to_var(ctx: TranslationCtx, value: lqp.Value, name_hint: str = "cvar") -> Tuple[lqp.Var, lqp.Formula]:
727
+ var = gen_unique_var(ctx, name_hint)
728
+ eq = mk_primitive("rel_primitive_eq", [var, value])
729
+ return var, eq
730
+
731
+ def _extract_pyrel_error_ids(ctx: TranslationCtx, model: ir.Model) -> list[Tuple[lqp.RelationId, str]]:
732
+ effects = collect_by_type(ir.Update, model)
733
+ pyrel_error_attrs = []
734
+ # We use a separate counter here to avoid modifying the current model.
735
+ i = 1
736
+ for effect in effects:
737
+ if "pyrel_error_attrs" not in effect.relation.name:
738
+ continue
739
+ projection, _ = _translate_bindings(ctx, _effect_bindings(effect))
740
+ rel_id = get_relation_id(ctx, effect.relation, projection)
741
+ name = f"{effect.relation.name}_{i}"
742
+ pyrel_error_attrs.append((rel_id, name))
743
+ i += 1
744
+
745
+ return pyrel_error_attrs
746
+
747
+ # Translate a relation reference into an abstraction over its fields.
748
+ def _translate_relation_ref(ctx: TranslationCtx, relation: ir.Relation) -> lqp.Abstraction:
749
+ projection = []
750
+ for field in relation.fields:
751
+ var = gen_unique_var(ctx, field.name)
752
+ typ = meta_type_to_lqp(field.type)
753
+ projection.append((var, typ))
754
+
755
+ rid = get_relation_id(ctx, relation, projection)
756
+ atom = lqp.Atom(name=rid, terms=[var for (var, _) in projection], meta=None)
757
+ return mk_abstraction(projection, atom)
758
+
759
+ # Common translation logic for graph algorithms.
760
+ # task.args[0] : normalized weight list (int64, int64, float)
761
+ # task.args[1] : normalized node count (relation or constant int64)
762
+ # task.args[2] : normalized edge count (relation or constant int64)
763
+ # task.args[3:-3] : algorithm parameters (var or constant)
764
+ # task.args[-3] : diagnostic info
765
+ # task.args[-2] : node index
766
+ # task.args[-1] : community ident
767
+ def _translate_graph_common(name: str, ctx: TranslationCtx, task: ir.Lookup):
768
+ abstractions = []
769
+
770
+ assert isinstance(task.args[0], ir.Relation), \
771
+ f"Expected relation as first arg to {name}, got {task.args[0]}:{type(task.args[0])}"
772
+ abstractions.append(_translate_relation_ref(ctx, task.args[0]))
773
+
774
+ # Allow constant args for node and edge count
775
+ for arg in task.args[1:3]:
776
+ if isinstance(arg, ir.Relation):
777
+ abst = _translate_relation_ref(ctx, arg)
778
+ typ = abst.vars[0][1]
779
+ assert typ.type_name == lqp.TypeName.INT, \
780
+ f"Expected Int64 types for node and edge counts, got type {typ.type_name}"
781
+ abstractions.append(abst)
782
+ else:
783
+ var, typ, eq = binding_to_lqp_var(ctx, arg)
784
+ assert eq is not None, \
785
+ f"Expected equality formula for {name} arg {arg}:{type(arg)}"
786
+ abstractions.append(mk_abstraction([(var, typ)], mk_and([eq])))
787
+
788
+ for arg in task.args[3:-3]:
789
+ var, typ, eq = binding_to_lqp_var(ctx, arg)
790
+ if eq:
791
+ abstractions.append(mk_abstraction([(var, typ)], mk_and([eq])))
792
+ else:
793
+ print(f"Primitive graph algorithm arg without eq:\n var:{var}, typ:{typ}\n arg:{arg}:{type(arg)}")
794
+ abstractions.append(mk_abstraction([(var, typ)], mk_and([])))
795
+
796
+ terms = []
797
+ for arg in task.args[-3:]:
798
+ term, _ = _translate_relterm(ctx, arg)
799
+ terms.append(term)
800
+
801
+ return (abstractions, terms)
802
+
803
+ def _translate_infomap(ctx: TranslationCtx, task: ir.Lookup) -> lqp.Formula:
804
+ abstractions, terms = _translate_graph_common("infomap", ctx, task)
805
+
806
+ return lqp.FFI(
807
+ meta=None,
808
+ name="rel_primitive_infomap",
809
+ args=abstractions,
810
+ terms=terms,
811
+ )
812
+
813
+ def _translate_louvain(ctx: TranslationCtx, task: ir.Lookup) -> lqp.Formula:
814
+ abstractions, terms = _translate_graph_common("louvain", ctx, task)
815
+
816
+ return lqp.FFI(
817
+ meta=None,
818
+ name="rel_primitive_louvain",
819
+ args=abstractions,
820
+ terms=terms,
821
+ )
822
+
823
+ def _translate_label_propagation(ctx: TranslationCtx, task: ir.Lookup) -> lqp.Formula:
824
+ abstractions, terms = _translate_graph_common("label_propagation", ctx, task)
825
+
826
+ return lqp.FFI(
827
+ meta=None,
828
+ name="rel_primitive_async_label_propagation",
829
+ args=abstractions,
830
+ terms=terms,
831
+ )
832
+
833
+ # Hard-coded implementation of Rel's string_join
834
+ def _translate_join(ctx: TranslationCtx, task: ir.Lookup) -> lqp.Formula:
835
+ assert len(task.args) == 3
836
+ (strs, separator, target) = task.args
837
+ assert isinstance(separator, ir.Node)
838
+ assert isinstance(target, ir.Var)
839
+ assert isinstance(strs, tuple)
840
+
841
+ # Enumerate the strings we're going to be reducing over
842
+ enumerated_conjunctions = []
843
+ index_var, index_type = gen_unique_var(ctx, "idx"), meta_type_to_lqp(types.Int64)
844
+ string_var, string_type = gen_unique_var(ctx, "s"), meta_type_to_lqp(types.String)
845
+ for i, s in enumerate(strs):
846
+ index = to_lqp_value(i, types.Int64)
847
+ string = _translate_term(ctx, s)[0]
848
+ eq_idx = mk_primitive("rel_primitive_eq", [index_var, index])
849
+ eq_string = mk_primitive("rel_primitive_eq", [string_var, string])
850
+ enumerated_conjunctions.append(mk_and([eq_idx, eq_string]))
851
+ body = mk_abstraction([(index_var, index_type), (string_var, string_type)], mk_or(enumerated_conjunctions))
852
+
853
+ # Make the function we're reducing
854
+ a_var, a_type = gen_unique_var(ctx, "a"), meta_type_to_lqp(types.String)
855
+ b_var, b_type = gen_unique_var(ctx, "b"), meta_type_to_lqp(types.String)
856
+ curr_var, curr_type = gen_unique_var(ctx, "curr"), meta_type_to_lqp(types.String)
857
+ res_var, res_type = gen_unique_var(ctx, "res"), meta_type_to_lqp(types.String)
858
+
859
+ sep, _ = _translate_term(ctx, separator)
860
+
861
+ op = mk_abstraction(
862
+ [(a_var, a_type), (b_var, b_type), (curr_var, curr_type)],
863
+ mk_exists([(res_var, res_type)],
864
+ mk_and([
865
+ mk_primitive("rel_primitive_concat", [res_var, b_var, curr_var]),
866
+ mk_primitive("rel_primitive_concat", [a_var, sep, res_var])
867
+ ])
868
+ )
869
+ )
870
+
871
+ output_term = _translate_term(ctx, target)[0]
872
+
873
+ return lqp.Reduce(meta=None, op=op, body=body, terms=[output_term])
874
+
875
+ def _translate_var(ctx: TranslationCtx, term: ir.Var) -> lqp.Var:
876
+ name = ctx.var_names.get_name_by_id(term.id, term.name)
877
+ return lqp.Var(name=name, meta=None)