relationalai 0.13.5__py3-none-any.whl → 1.0.0a2__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 (856) hide show
  1. relationalai/__init__.py +1 -256
  2. relationalai/config/__init__.py +56 -0
  3. relationalai/config/config.py +289 -0
  4. relationalai/config/config_fields.py +86 -0
  5. relationalai/config/connections/__init__.py +46 -0
  6. relationalai/config/connections/base.py +23 -0
  7. relationalai/config/connections/duckdb.py +29 -0
  8. relationalai/config/connections/snowflake.py +243 -0
  9. relationalai/config/external/__init__.py +17 -0
  10. relationalai/config/external/dbt_converter.py +101 -0
  11. relationalai/config/external/dbt_models.py +93 -0
  12. relationalai/config/external/snowflake_converter.py +41 -0
  13. relationalai/config/external/snowflake_models.py +85 -0
  14. relationalai/config/external/utils.py +19 -0
  15. relationalai/config/shims.py +1 -0
  16. relationalai/semantics/__init__.py +146 -22
  17. relationalai/semantics/backends/lqp/annotations.py +11 -0
  18. relationalai/semantics/backends/sql/sql_compiler.py +327 -0
  19. relationalai/semantics/frontend/base.py +1719 -0
  20. relationalai/semantics/frontend/core.py +179 -0
  21. relationalai/semantics/frontend/front_compiler.py +1316 -0
  22. relationalai/semantics/frontend/pprint.py +408 -0
  23. relationalai/semantics/metamodel/__init__.py +6 -40
  24. relationalai/semantics/metamodel/builtins.py +206 -772
  25. relationalai/semantics/metamodel/metamodel.py +465 -0
  26. relationalai/semantics/metamodel/metamodel_analyzer.py +519 -0
  27. relationalai/semantics/metamodel/pprint.py +414 -0
  28. relationalai/semantics/metamodel/rewriter.py +266 -0
  29. relationalai/semantics/metamodel/typer.py +1213 -0
  30. relationalai/semantics/std/__init__.py +60 -40
  31. relationalai/semantics/std/aggregates.py +148 -0
  32. relationalai/semantics/std/common.py +44 -0
  33. relationalai/semantics/std/constraints.py +37 -43
  34. relationalai/semantics/std/datetime.py +249 -135
  35. relationalai/semantics/std/decimals.py +45 -52
  36. relationalai/semantics/std/floats.py +13 -5
  37. relationalai/semantics/std/integers.py +26 -11
  38. relationalai/semantics/std/math.py +183 -112
  39. relationalai/semantics/std/numbers.py +86 -0
  40. relationalai/semantics/std/re.py +80 -62
  41. relationalai/semantics/std/strings.py +101 -46
  42. relationalai/shims/executor.py +179 -0
  43. relationalai/shims/helpers.py +126 -0
  44. relationalai/shims/hoister.py +221 -0
  45. relationalai/shims/mm2v0.py +1394 -0
  46. relationalai/tools/cli/__init__.py +6 -0
  47. relationalai/tools/cli/cli.py +90 -0
  48. relationalai/tools/cli/components/__init__.py +5 -0
  49. relationalai/tools/cli/components/progress_reader.py +1524 -0
  50. relationalai/tools/cli/components/utils.py +58 -0
  51. relationalai/tools/cli/config_template.py +45 -0
  52. relationalai/tools/cli/dev.py +19 -0
  53. relationalai/tools/debugger.py +289 -183
  54. relationalai/tools/typer_debugger.py +93 -0
  55. relationalai/util/dataclasses.py +43 -0
  56. relationalai/util/docutils.py +40 -0
  57. relationalai/util/error.py +199 -0
  58. relationalai/util/format.py +48 -109
  59. relationalai/util/naming.py +145 -0
  60. relationalai/util/python.py +35 -0
  61. relationalai/util/runtime.py +156 -0
  62. relationalai/util/schema.py +197 -0
  63. relationalai/util/source.py +185 -0
  64. relationalai/util/structures.py +163 -0
  65. relationalai/util/tracing.py +261 -0
  66. relationalai-1.0.0a2.dist-info/METADATA +44 -0
  67. relationalai-1.0.0a2.dist-info/RECORD +489 -0
  68. relationalai-1.0.0a2.dist-info/WHEEL +5 -0
  69. relationalai-1.0.0a2.dist-info/entry_points.txt +3 -0
  70. relationalai-1.0.0a2.dist-info/top_level.txt +2 -0
  71. v0/relationalai/__init__.py +216 -0
  72. v0/relationalai/clients/__init__.py +5 -0
  73. v0/relationalai/clients/azure.py +477 -0
  74. v0/relationalai/clients/client.py +912 -0
  75. v0/relationalai/clients/config.py +673 -0
  76. v0/relationalai/clients/direct_access_client.py +118 -0
  77. v0/relationalai/clients/hash_util.py +31 -0
  78. v0/relationalai/clients/local.py +571 -0
  79. v0/relationalai/clients/profile_polling.py +73 -0
  80. v0/relationalai/clients/result_helpers.py +420 -0
  81. v0/relationalai/clients/snowflake.py +3869 -0
  82. v0/relationalai/clients/types.py +113 -0
  83. v0/relationalai/clients/use_index_poller.py +980 -0
  84. v0/relationalai/clients/util.py +356 -0
  85. v0/relationalai/debugging.py +389 -0
  86. v0/relationalai/dsl.py +1749 -0
  87. v0/relationalai/early_access/builder/__init__.py +30 -0
  88. v0/relationalai/early_access/builder/builder/__init__.py +35 -0
  89. v0/relationalai/early_access/builder/snowflake/__init__.py +12 -0
  90. v0/relationalai/early_access/builder/std/__init__.py +25 -0
  91. v0/relationalai/early_access/builder/std/decimals/__init__.py +12 -0
  92. v0/relationalai/early_access/builder/std/integers/__init__.py +12 -0
  93. v0/relationalai/early_access/builder/std/math/__init__.py +12 -0
  94. v0/relationalai/early_access/builder/std/strings/__init__.py +14 -0
  95. v0/relationalai/early_access/devtools/__init__.py +12 -0
  96. v0/relationalai/early_access/devtools/benchmark_lqp/__init__.py +12 -0
  97. v0/relationalai/early_access/devtools/extract_lqp/__init__.py +12 -0
  98. v0/relationalai/early_access/dsl/adapters/orm/adapter_qb.py +427 -0
  99. v0/relationalai/early_access/dsl/adapters/orm/parser.py +636 -0
  100. v0/relationalai/early_access/dsl/adapters/owl/adapter.py +176 -0
  101. v0/relationalai/early_access/dsl/adapters/owl/parser.py +160 -0
  102. v0/relationalai/early_access/dsl/bindings/common.py +402 -0
  103. v0/relationalai/early_access/dsl/bindings/csv.py +170 -0
  104. v0/relationalai/early_access/dsl/bindings/legacy/binding_models.py +143 -0
  105. v0/relationalai/early_access/dsl/bindings/snowflake.py +64 -0
  106. v0/relationalai/early_access/dsl/codegen/binder.py +411 -0
  107. v0/relationalai/early_access/dsl/codegen/common.py +79 -0
  108. v0/relationalai/early_access/dsl/codegen/helpers.py +23 -0
  109. v0/relationalai/early_access/dsl/codegen/relations.py +700 -0
  110. v0/relationalai/early_access/dsl/codegen/weaver.py +417 -0
  111. v0/relationalai/early_access/dsl/core/builders/__init__.py +47 -0
  112. v0/relationalai/early_access/dsl/core/builders/logic.py +19 -0
  113. v0/relationalai/early_access/dsl/core/builders/scalar_constraint.py +11 -0
  114. v0/relationalai/early_access/dsl/core/constraints/predicate/atomic.py +455 -0
  115. v0/relationalai/early_access/dsl/core/constraints/predicate/universal.py +73 -0
  116. v0/relationalai/early_access/dsl/core/constraints/scalar.py +310 -0
  117. v0/relationalai/early_access/dsl/core/context.py +13 -0
  118. v0/relationalai/early_access/dsl/core/cset.py +132 -0
  119. v0/relationalai/early_access/dsl/core/exprs/__init__.py +116 -0
  120. v0/relationalai/early_access/dsl/core/exprs/relational.py +18 -0
  121. v0/relationalai/early_access/dsl/core/exprs/scalar.py +412 -0
  122. v0/relationalai/early_access/dsl/core/instances.py +44 -0
  123. v0/relationalai/early_access/dsl/core/logic/__init__.py +193 -0
  124. v0/relationalai/early_access/dsl/core/logic/aggregation.py +98 -0
  125. v0/relationalai/early_access/dsl/core/logic/exists.py +223 -0
  126. v0/relationalai/early_access/dsl/core/logic/helper.py +163 -0
  127. v0/relationalai/early_access/dsl/core/namespaces.py +32 -0
  128. v0/relationalai/early_access/dsl/core/relations.py +276 -0
  129. v0/relationalai/early_access/dsl/core/rules.py +112 -0
  130. v0/relationalai/early_access/dsl/core/std/__init__.py +45 -0
  131. v0/relationalai/early_access/dsl/core/temporal/recall.py +6 -0
  132. v0/relationalai/early_access/dsl/core/types/__init__.py +270 -0
  133. v0/relationalai/early_access/dsl/core/types/concepts.py +128 -0
  134. v0/relationalai/early_access/dsl/core/types/constrained/__init__.py +267 -0
  135. v0/relationalai/early_access/dsl/core/types/constrained/nominal.py +143 -0
  136. v0/relationalai/early_access/dsl/core/types/constrained/subtype.py +124 -0
  137. v0/relationalai/early_access/dsl/core/types/standard.py +92 -0
  138. v0/relationalai/early_access/dsl/core/types/unconstrained.py +50 -0
  139. v0/relationalai/early_access/dsl/core/types/variables.py +203 -0
  140. v0/relationalai/early_access/dsl/ir/compiler.py +318 -0
  141. v0/relationalai/early_access/dsl/ir/executor.py +260 -0
  142. v0/relationalai/early_access/dsl/ontologies/constraints.py +88 -0
  143. v0/relationalai/early_access/dsl/ontologies/export.py +30 -0
  144. v0/relationalai/early_access/dsl/ontologies/models.py +453 -0
  145. v0/relationalai/early_access/dsl/ontologies/python_printer.py +303 -0
  146. v0/relationalai/early_access/dsl/ontologies/readings.py +60 -0
  147. v0/relationalai/early_access/dsl/ontologies/relationships.py +322 -0
  148. v0/relationalai/early_access/dsl/ontologies/roles.py +87 -0
  149. v0/relationalai/early_access/dsl/ontologies/subtyping.py +55 -0
  150. v0/relationalai/early_access/dsl/orm/constraints.py +438 -0
  151. v0/relationalai/early_access/dsl/orm/measures/dimensions.py +200 -0
  152. v0/relationalai/early_access/dsl/orm/measures/initializer.py +16 -0
  153. v0/relationalai/early_access/dsl/orm/measures/measure_rules.py +275 -0
  154. v0/relationalai/early_access/dsl/orm/measures/measures.py +299 -0
  155. v0/relationalai/early_access/dsl/orm/measures/role_exprs.py +268 -0
  156. v0/relationalai/early_access/dsl/orm/models.py +256 -0
  157. v0/relationalai/early_access/dsl/orm/object_oriented_printer.py +344 -0
  158. v0/relationalai/early_access/dsl/orm/printer.py +469 -0
  159. v0/relationalai/early_access/dsl/orm/reasoners.py +480 -0
  160. v0/relationalai/early_access/dsl/orm/relations.py +19 -0
  161. v0/relationalai/early_access/dsl/orm/relationships.py +251 -0
  162. v0/relationalai/early_access/dsl/orm/types.py +42 -0
  163. v0/relationalai/early_access/dsl/orm/utils.py +79 -0
  164. v0/relationalai/early_access/dsl/orm/verb.py +204 -0
  165. v0/relationalai/early_access/dsl/physical_metadata/tables.py +133 -0
  166. v0/relationalai/early_access/dsl/relations.py +170 -0
  167. v0/relationalai/early_access/dsl/rulesets.py +69 -0
  168. v0/relationalai/early_access/dsl/schemas/__init__.py +450 -0
  169. v0/relationalai/early_access/dsl/schemas/builder.py +48 -0
  170. v0/relationalai/early_access/dsl/schemas/comp_names.py +51 -0
  171. v0/relationalai/early_access/dsl/schemas/components.py +203 -0
  172. v0/relationalai/early_access/dsl/schemas/contexts.py +156 -0
  173. v0/relationalai/early_access/dsl/schemas/exprs.py +89 -0
  174. v0/relationalai/early_access/dsl/schemas/fragments.py +464 -0
  175. v0/relationalai/early_access/dsl/serialization.py +79 -0
  176. v0/relationalai/early_access/dsl/serialize/exporter.py +163 -0
  177. v0/relationalai/early_access/dsl/snow/api.py +104 -0
  178. v0/relationalai/early_access/dsl/snow/common.py +76 -0
  179. v0/relationalai/early_access/dsl/state_mgmt/__init__.py +129 -0
  180. v0/relationalai/early_access/dsl/state_mgmt/state_charts.py +125 -0
  181. v0/relationalai/early_access/dsl/state_mgmt/transitions.py +130 -0
  182. v0/relationalai/early_access/dsl/types/__init__.py +40 -0
  183. v0/relationalai/early_access/dsl/types/concepts.py +12 -0
  184. v0/relationalai/early_access/dsl/types/entities.py +135 -0
  185. v0/relationalai/early_access/dsl/types/values.py +17 -0
  186. v0/relationalai/early_access/dsl/utils.py +102 -0
  187. v0/relationalai/early_access/graphs/__init__.py +13 -0
  188. v0/relationalai/early_access/lqp/__init__.py +12 -0
  189. v0/relationalai/early_access/lqp/compiler/__init__.py +12 -0
  190. v0/relationalai/early_access/lqp/constructors/__init__.py +18 -0
  191. v0/relationalai/early_access/lqp/executor/__init__.py +12 -0
  192. v0/relationalai/early_access/lqp/ir/__init__.py +12 -0
  193. v0/relationalai/early_access/lqp/passes/__init__.py +12 -0
  194. v0/relationalai/early_access/lqp/pragmas/__init__.py +12 -0
  195. v0/relationalai/early_access/lqp/primitives/__init__.py +12 -0
  196. v0/relationalai/early_access/lqp/types/__init__.py +12 -0
  197. v0/relationalai/early_access/lqp/utils/__init__.py +12 -0
  198. v0/relationalai/early_access/lqp/validators/__init__.py +12 -0
  199. v0/relationalai/early_access/metamodel/__init__.py +58 -0
  200. v0/relationalai/early_access/metamodel/builtins/__init__.py +12 -0
  201. v0/relationalai/early_access/metamodel/compiler/__init__.py +12 -0
  202. v0/relationalai/early_access/metamodel/dependency/__init__.py +12 -0
  203. v0/relationalai/early_access/metamodel/factory/__init__.py +17 -0
  204. v0/relationalai/early_access/metamodel/helpers/__init__.py +12 -0
  205. v0/relationalai/early_access/metamodel/ir/__init__.py +14 -0
  206. v0/relationalai/early_access/metamodel/rewrite/__init__.py +7 -0
  207. v0/relationalai/early_access/metamodel/typer/__init__.py +3 -0
  208. v0/relationalai/early_access/metamodel/typer/typer/__init__.py +12 -0
  209. v0/relationalai/early_access/metamodel/types/__init__.py +15 -0
  210. v0/relationalai/early_access/metamodel/util/__init__.py +15 -0
  211. v0/relationalai/early_access/metamodel/visitor/__init__.py +12 -0
  212. v0/relationalai/early_access/rel/__init__.py +12 -0
  213. v0/relationalai/early_access/rel/executor/__init__.py +12 -0
  214. v0/relationalai/early_access/rel/rel_utils/__init__.py +12 -0
  215. v0/relationalai/early_access/rel/rewrite/__init__.py +7 -0
  216. v0/relationalai/early_access/solvers/__init__.py +19 -0
  217. v0/relationalai/early_access/sql/__init__.py +11 -0
  218. v0/relationalai/early_access/sql/executor/__init__.py +3 -0
  219. v0/relationalai/early_access/sql/rewrite/__init__.py +3 -0
  220. v0/relationalai/early_access/tests/logging/__init__.py +12 -0
  221. v0/relationalai/early_access/tests/test_snapshot_base/__init__.py +12 -0
  222. v0/relationalai/early_access/tests/utils/__init__.py +12 -0
  223. v0/relationalai/environments/__init__.py +35 -0
  224. v0/relationalai/environments/base.py +381 -0
  225. v0/relationalai/environments/colab.py +14 -0
  226. v0/relationalai/environments/generic.py +71 -0
  227. v0/relationalai/environments/ipython.py +68 -0
  228. v0/relationalai/environments/jupyter.py +9 -0
  229. v0/relationalai/environments/snowbook.py +169 -0
  230. v0/relationalai/errors.py +2478 -0
  231. v0/relationalai/experimental/SF.py +38 -0
  232. v0/relationalai/experimental/inspect.py +47 -0
  233. v0/relationalai/experimental/pathfinder/__init__.py +158 -0
  234. v0/relationalai/experimental/pathfinder/api.py +160 -0
  235. v0/relationalai/experimental/pathfinder/automaton.py +584 -0
  236. v0/relationalai/experimental/pathfinder/bridge.py +226 -0
  237. v0/relationalai/experimental/pathfinder/compiler.py +416 -0
  238. v0/relationalai/experimental/pathfinder/datalog.py +214 -0
  239. v0/relationalai/experimental/pathfinder/diagnostics.py +56 -0
  240. v0/relationalai/experimental/pathfinder/filter.py +236 -0
  241. v0/relationalai/experimental/pathfinder/glushkov.py +439 -0
  242. v0/relationalai/experimental/pathfinder/options.py +265 -0
  243. v0/relationalai/experimental/pathfinder/rpq.py +344 -0
  244. v0/relationalai/experimental/pathfinder/transition.py +200 -0
  245. v0/relationalai/experimental/pathfinder/utils.py +26 -0
  246. v0/relationalai/experimental/paths/api.py +143 -0
  247. v0/relationalai/experimental/paths/benchmarks/grid_graph.py +37 -0
  248. v0/relationalai/experimental/paths/examples/basic_example.py +40 -0
  249. v0/relationalai/experimental/paths/examples/minimal_engine_warmup.py +3 -0
  250. v0/relationalai/experimental/paths/examples/movie_example.py +77 -0
  251. v0/relationalai/experimental/paths/examples/paths_benchmark.py +115 -0
  252. v0/relationalai/experimental/paths/examples/paths_example.py +116 -0
  253. v0/relationalai/experimental/paths/examples/pattern_to_automaton.py +28 -0
  254. v0/relationalai/experimental/paths/find_paths_via_automaton.py +85 -0
  255. v0/relationalai/experimental/paths/graph.py +185 -0
  256. v0/relationalai/experimental/paths/path_algorithms/find_paths.py +280 -0
  257. v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +26 -0
  258. v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +111 -0
  259. v0/relationalai/experimental/paths/path_algorithms/single.py +59 -0
  260. v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +39 -0
  261. v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +103 -0
  262. v0/relationalai/experimental/paths/path_algorithms/usp-old.py +130 -0
  263. v0/relationalai/experimental/paths/path_algorithms/usp-tuple.py +183 -0
  264. v0/relationalai/experimental/paths/path_algorithms/usp.py +150 -0
  265. v0/relationalai/experimental/paths/product_graph.py +93 -0
  266. v0/relationalai/experimental/paths/rpq/automaton.py +584 -0
  267. v0/relationalai/experimental/paths/rpq/diagnostics.py +56 -0
  268. v0/relationalai/experimental/paths/rpq/rpq.py +378 -0
  269. v0/relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +90 -0
  270. v0/relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +119 -0
  271. v0/relationalai/experimental/paths/tests/tests_limit_sp_single.py +104 -0
  272. v0/relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +113 -0
  273. v0/relationalai/experimental/paths/tests/tests_limit_walks_single.py +149 -0
  274. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +70 -0
  275. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +64 -0
  276. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +115 -0
  277. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +75 -0
  278. v0/relationalai/experimental/paths/tests/tests_single_paths.py +152 -0
  279. v0/relationalai/experimental/paths/tests/tests_single_walks.py +208 -0
  280. v0/relationalai/experimental/paths/tests/tests_single_walks_undirected.py +297 -0
  281. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +107 -0
  282. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +76 -0
  283. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +76 -0
  284. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +110 -0
  285. v0/relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +229 -0
  286. v0/relationalai/experimental/paths/tests/tests_usp_nsp_single.py +108 -0
  287. v0/relationalai/experimental/paths/tree_agg.py +168 -0
  288. v0/relationalai/experimental/paths/utilities/iterators.py +27 -0
  289. v0/relationalai/experimental/paths/utilities/prefix_sum.py +91 -0
  290. v0/relationalai/experimental/solvers.py +1087 -0
  291. v0/relationalai/loaders/csv.py +195 -0
  292. v0/relationalai/loaders/loader.py +177 -0
  293. v0/relationalai/loaders/types.py +23 -0
  294. v0/relationalai/rel_emitter.py +373 -0
  295. v0/relationalai/rel_utils.py +185 -0
  296. v0/relationalai/semantics/__init__.py +29 -0
  297. v0/relationalai/semantics/devtools/benchmark_lqp.py +536 -0
  298. v0/relationalai/semantics/devtools/compilation_manager.py +294 -0
  299. v0/relationalai/semantics/devtools/extract_lqp.py +110 -0
  300. v0/relationalai/semantics/internal/internal.py +3785 -0
  301. v0/relationalai/semantics/internal/snowflake.py +325 -0
  302. v0/relationalai/semantics/lqp/builtins.py +16 -0
  303. v0/relationalai/semantics/lqp/compiler.py +22 -0
  304. v0/relationalai/semantics/lqp/constructors.py +68 -0
  305. v0/relationalai/semantics/lqp/executor.py +474 -0
  306. v0/relationalai/semantics/lqp/intrinsics.py +24 -0
  307. v0/relationalai/semantics/lqp/ir.py +124 -0
  308. v0/relationalai/semantics/lqp/model2lqp.py +877 -0
  309. v0/relationalai/semantics/lqp/passes.py +680 -0
  310. v0/relationalai/semantics/lqp/primitives.py +252 -0
  311. v0/relationalai/semantics/lqp/result_helpers.py +202 -0
  312. v0/relationalai/semantics/lqp/rewrite/__init__.py +18 -0
  313. v0/relationalai/semantics/lqp/rewrite/annotate_constraints.py +57 -0
  314. v0/relationalai/semantics/lqp/rewrite/cdc.py +216 -0
  315. v0/relationalai/semantics/lqp/rewrite/extract_common.py +338 -0
  316. v0/relationalai/semantics/lqp/rewrite/extract_keys.py +490 -0
  317. v0/relationalai/semantics/lqp/rewrite/function_annotations.py +114 -0
  318. v0/relationalai/semantics/lqp/rewrite/functional_dependencies.py +314 -0
  319. v0/relationalai/semantics/lqp/rewrite/quantify_vars.py +296 -0
  320. v0/relationalai/semantics/lqp/rewrite/splinter.py +76 -0
  321. v0/relationalai/semantics/lqp/types.py +101 -0
  322. v0/relationalai/semantics/lqp/utils.py +160 -0
  323. v0/relationalai/semantics/lqp/validators.py +57 -0
  324. v0/relationalai/semantics/metamodel/__init__.py +40 -0
  325. v0/relationalai/semantics/metamodel/builtins.py +776 -0
  326. v0/relationalai/semantics/metamodel/compiler.py +133 -0
  327. v0/relationalai/semantics/metamodel/dependency.py +862 -0
  328. v0/relationalai/semantics/metamodel/executor.py +61 -0
  329. v0/relationalai/semantics/metamodel/factory.py +287 -0
  330. v0/relationalai/semantics/metamodel/helpers.py +361 -0
  331. v0/relationalai/semantics/metamodel/ir.py +923 -0
  332. v0/relationalai/semantics/metamodel/rewrite/__init__.py +7 -0
  333. v0/relationalai/semantics/metamodel/rewrite/discharge_constraints.py +39 -0
  334. v0/relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +210 -0
  335. v0/relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +78 -0
  336. v0/relationalai/semantics/metamodel/rewrite/flatten.py +554 -0
  337. v0/relationalai/semantics/metamodel/rewrite/format_outputs.py +165 -0
  338. v0/relationalai/semantics/metamodel/typer/checker.py +353 -0
  339. v0/relationalai/semantics/metamodel/typer/typer.py +1395 -0
  340. v0/relationalai/semantics/metamodel/util.py +505 -0
  341. v0/relationalai/semantics/metamodel/visitor.py +944 -0
  342. v0/relationalai/semantics/reasoners/__init__.py +10 -0
  343. v0/relationalai/semantics/reasoners/graph/__init__.py +37 -0
  344. v0/relationalai/semantics/reasoners/graph/core.py +9019 -0
  345. v0/relationalai/semantics/reasoners/optimization/__init__.py +68 -0
  346. v0/relationalai/semantics/reasoners/optimization/common.py +88 -0
  347. v0/relationalai/semantics/reasoners/optimization/solvers_dev.py +568 -0
  348. v0/relationalai/semantics/reasoners/optimization/solvers_pb.py +1163 -0
  349. v0/relationalai/semantics/rel/builtins.py +40 -0
  350. v0/relationalai/semantics/rel/compiler.py +989 -0
  351. v0/relationalai/semantics/rel/executor.py +359 -0
  352. v0/relationalai/semantics/rel/rel.py +482 -0
  353. v0/relationalai/semantics/rel/rel_utils.py +276 -0
  354. v0/relationalai/semantics/snowflake/__init__.py +3 -0
  355. v0/relationalai/semantics/sql/compiler.py +2503 -0
  356. v0/relationalai/semantics/sql/executor/duck_db.py +52 -0
  357. v0/relationalai/semantics/sql/executor/result_helpers.py +64 -0
  358. v0/relationalai/semantics/sql/executor/snowflake.py +145 -0
  359. v0/relationalai/semantics/sql/rewrite/denormalize.py +222 -0
  360. v0/relationalai/semantics/sql/rewrite/double_negation.py +49 -0
  361. v0/relationalai/semantics/sql/rewrite/recursive_union.py +127 -0
  362. v0/relationalai/semantics/sql/rewrite/sort_output_query.py +246 -0
  363. v0/relationalai/semantics/sql/sql.py +504 -0
  364. v0/relationalai/semantics/std/__init__.py +54 -0
  365. v0/relationalai/semantics/std/constraints.py +43 -0
  366. v0/relationalai/semantics/std/datetime.py +363 -0
  367. v0/relationalai/semantics/std/decimals.py +62 -0
  368. v0/relationalai/semantics/std/floats.py +7 -0
  369. v0/relationalai/semantics/std/integers.py +22 -0
  370. v0/relationalai/semantics/std/math.py +141 -0
  371. v0/relationalai/semantics/std/pragmas.py +11 -0
  372. v0/relationalai/semantics/std/re.py +83 -0
  373. v0/relationalai/semantics/std/std.py +14 -0
  374. v0/relationalai/semantics/std/strings.py +63 -0
  375. v0/relationalai/semantics/tests/__init__.py +0 -0
  376. v0/relationalai/semantics/tests/test_snapshot_abstract.py +143 -0
  377. v0/relationalai/semantics/tests/test_snapshot_base.py +9 -0
  378. v0/relationalai/semantics/tests/utils.py +46 -0
  379. v0/relationalai/std/__init__.py +70 -0
  380. v0/relationalai/tools/__init__.py +0 -0
  381. v0/relationalai/tools/cli.py +1940 -0
  382. v0/relationalai/tools/cli_controls.py +1826 -0
  383. v0/relationalai/tools/cli_helpers.py +390 -0
  384. v0/relationalai/tools/debugger.py +183 -0
  385. v0/relationalai/tools/debugger_client.py +109 -0
  386. v0/relationalai/tools/debugger_server.py +302 -0
  387. v0/relationalai/tools/dev.py +685 -0
  388. v0/relationalai/tools/qb_debugger.py +425 -0
  389. v0/relationalai/util/clean_up_databases.py +95 -0
  390. v0/relationalai/util/format.py +123 -0
  391. v0/relationalai/util/list_databases.py +9 -0
  392. v0/relationalai/util/otel_configuration.py +25 -0
  393. v0/relationalai/util/otel_handler.py +484 -0
  394. v0/relationalai/util/snowflake_handler.py +88 -0
  395. v0/relationalai/util/span_format_test.py +43 -0
  396. v0/relationalai/util/span_tracker.py +207 -0
  397. v0/relationalai/util/spans_file_handler.py +72 -0
  398. v0/relationalai/util/tracing_handler.py +34 -0
  399. frontend/debugger/dist/.gitignore +0 -2
  400. frontend/debugger/dist/assets/favicon-Dy0ZgA6N.png +0 -0
  401. frontend/debugger/dist/assets/index-Cssla-O7.js +0 -208
  402. frontend/debugger/dist/assets/index-DlHsYx1V.css +0 -9
  403. frontend/debugger/dist/index.html +0 -17
  404. relationalai/clients/__init__.py +0 -18
  405. relationalai/clients/client.py +0 -946
  406. relationalai/clients/config.py +0 -673
  407. relationalai/clients/direct_access_client.py +0 -118
  408. relationalai/clients/exec_txn_poller.py +0 -153
  409. relationalai/clients/hash_util.py +0 -31
  410. relationalai/clients/local.py +0 -594
  411. relationalai/clients/profile_polling.py +0 -73
  412. relationalai/clients/resources/__init__.py +0 -8
  413. relationalai/clients/resources/azure/azure.py +0 -502
  414. relationalai/clients/resources/snowflake/__init__.py +0 -20
  415. relationalai/clients/resources/snowflake/cli_resources.py +0 -98
  416. relationalai/clients/resources/snowflake/direct_access_resources.py +0 -739
  417. relationalai/clients/resources/snowflake/engine_service.py +0 -381
  418. relationalai/clients/resources/snowflake/engine_state_handlers.py +0 -315
  419. relationalai/clients/resources/snowflake/error_handlers.py +0 -240
  420. relationalai/clients/resources/snowflake/export_procedure.py.jinja +0 -249
  421. relationalai/clients/resources/snowflake/resources_factory.py +0 -99
  422. relationalai/clients/resources/snowflake/snowflake.py +0 -3193
  423. relationalai/clients/resources/snowflake/use_index_poller.py +0 -1019
  424. relationalai/clients/resources/snowflake/use_index_resources.py +0 -188
  425. relationalai/clients/resources/snowflake/util.py +0 -387
  426. relationalai/clients/result_helpers.py +0 -420
  427. relationalai/clients/types.py +0 -118
  428. relationalai/clients/util.py +0 -356
  429. relationalai/debugging.py +0 -389
  430. relationalai/dsl.py +0 -1749
  431. relationalai/early_access/builder/__init__.py +0 -30
  432. relationalai/early_access/builder/builder/__init__.py +0 -35
  433. relationalai/early_access/builder/snowflake/__init__.py +0 -12
  434. relationalai/early_access/builder/std/__init__.py +0 -25
  435. relationalai/early_access/builder/std/decimals/__init__.py +0 -12
  436. relationalai/early_access/builder/std/integers/__init__.py +0 -12
  437. relationalai/early_access/builder/std/math/__init__.py +0 -12
  438. relationalai/early_access/builder/std/strings/__init__.py +0 -14
  439. relationalai/early_access/devtools/__init__.py +0 -12
  440. relationalai/early_access/devtools/benchmark_lqp/__init__.py +0 -12
  441. relationalai/early_access/devtools/extract_lqp/__init__.py +0 -12
  442. relationalai/early_access/dsl/adapters/orm/adapter_qb.py +0 -427
  443. relationalai/early_access/dsl/adapters/orm/parser.py +0 -636
  444. relationalai/early_access/dsl/adapters/owl/adapter.py +0 -176
  445. relationalai/early_access/dsl/adapters/owl/parser.py +0 -160
  446. relationalai/early_access/dsl/bindings/common.py +0 -402
  447. relationalai/early_access/dsl/bindings/csv.py +0 -170
  448. relationalai/early_access/dsl/bindings/legacy/binding_models.py +0 -143
  449. relationalai/early_access/dsl/bindings/snowflake.py +0 -64
  450. relationalai/early_access/dsl/codegen/binder.py +0 -411
  451. relationalai/early_access/dsl/codegen/common.py +0 -79
  452. relationalai/early_access/dsl/codegen/helpers.py +0 -23
  453. relationalai/early_access/dsl/codegen/relations.py +0 -700
  454. relationalai/early_access/dsl/codegen/weaver.py +0 -417
  455. relationalai/early_access/dsl/core/builders/__init__.py +0 -47
  456. relationalai/early_access/dsl/core/builders/logic.py +0 -19
  457. relationalai/early_access/dsl/core/builders/scalar_constraint.py +0 -11
  458. relationalai/early_access/dsl/core/constraints/predicate/atomic.py +0 -455
  459. relationalai/early_access/dsl/core/constraints/predicate/universal.py +0 -73
  460. relationalai/early_access/dsl/core/constraints/scalar.py +0 -310
  461. relationalai/early_access/dsl/core/context.py +0 -13
  462. relationalai/early_access/dsl/core/cset.py +0 -132
  463. relationalai/early_access/dsl/core/exprs/__init__.py +0 -116
  464. relationalai/early_access/dsl/core/exprs/relational.py +0 -18
  465. relationalai/early_access/dsl/core/exprs/scalar.py +0 -412
  466. relationalai/early_access/dsl/core/instances.py +0 -44
  467. relationalai/early_access/dsl/core/logic/__init__.py +0 -193
  468. relationalai/early_access/dsl/core/logic/aggregation.py +0 -98
  469. relationalai/early_access/dsl/core/logic/exists.py +0 -223
  470. relationalai/early_access/dsl/core/logic/helper.py +0 -163
  471. relationalai/early_access/dsl/core/namespaces.py +0 -32
  472. relationalai/early_access/dsl/core/relations.py +0 -276
  473. relationalai/early_access/dsl/core/rules.py +0 -112
  474. relationalai/early_access/dsl/core/std/__init__.py +0 -45
  475. relationalai/early_access/dsl/core/temporal/recall.py +0 -6
  476. relationalai/early_access/dsl/core/types/__init__.py +0 -270
  477. relationalai/early_access/dsl/core/types/concepts.py +0 -128
  478. relationalai/early_access/dsl/core/types/constrained/__init__.py +0 -267
  479. relationalai/early_access/dsl/core/types/constrained/nominal.py +0 -143
  480. relationalai/early_access/dsl/core/types/constrained/subtype.py +0 -124
  481. relationalai/early_access/dsl/core/types/standard.py +0 -92
  482. relationalai/early_access/dsl/core/types/unconstrained.py +0 -50
  483. relationalai/early_access/dsl/core/types/variables.py +0 -203
  484. relationalai/early_access/dsl/ir/compiler.py +0 -318
  485. relationalai/early_access/dsl/ir/executor.py +0 -260
  486. relationalai/early_access/dsl/ontologies/constraints.py +0 -88
  487. relationalai/early_access/dsl/ontologies/export.py +0 -30
  488. relationalai/early_access/dsl/ontologies/models.py +0 -453
  489. relationalai/early_access/dsl/ontologies/python_printer.py +0 -303
  490. relationalai/early_access/dsl/ontologies/readings.py +0 -60
  491. relationalai/early_access/dsl/ontologies/relationships.py +0 -322
  492. relationalai/early_access/dsl/ontologies/roles.py +0 -87
  493. relationalai/early_access/dsl/ontologies/subtyping.py +0 -55
  494. relationalai/early_access/dsl/orm/constraints.py +0 -438
  495. relationalai/early_access/dsl/orm/measures/dimensions.py +0 -200
  496. relationalai/early_access/dsl/orm/measures/initializer.py +0 -16
  497. relationalai/early_access/dsl/orm/measures/measure_rules.py +0 -275
  498. relationalai/early_access/dsl/orm/measures/measures.py +0 -299
  499. relationalai/early_access/dsl/orm/measures/role_exprs.py +0 -268
  500. relationalai/early_access/dsl/orm/models.py +0 -256
  501. relationalai/early_access/dsl/orm/object_oriented_printer.py +0 -344
  502. relationalai/early_access/dsl/orm/printer.py +0 -469
  503. relationalai/early_access/dsl/orm/reasoners.py +0 -480
  504. relationalai/early_access/dsl/orm/relations.py +0 -19
  505. relationalai/early_access/dsl/orm/relationships.py +0 -251
  506. relationalai/early_access/dsl/orm/types.py +0 -42
  507. relationalai/early_access/dsl/orm/utils.py +0 -79
  508. relationalai/early_access/dsl/orm/verb.py +0 -204
  509. relationalai/early_access/dsl/physical_metadata/tables.py +0 -133
  510. relationalai/early_access/dsl/relations.py +0 -170
  511. relationalai/early_access/dsl/rulesets.py +0 -69
  512. relationalai/early_access/dsl/schemas/__init__.py +0 -450
  513. relationalai/early_access/dsl/schemas/builder.py +0 -48
  514. relationalai/early_access/dsl/schemas/comp_names.py +0 -51
  515. relationalai/early_access/dsl/schemas/components.py +0 -203
  516. relationalai/early_access/dsl/schemas/contexts.py +0 -156
  517. relationalai/early_access/dsl/schemas/exprs.py +0 -89
  518. relationalai/early_access/dsl/schemas/fragments.py +0 -464
  519. relationalai/early_access/dsl/serialization.py +0 -79
  520. relationalai/early_access/dsl/serialize/exporter.py +0 -163
  521. relationalai/early_access/dsl/snow/api.py +0 -105
  522. relationalai/early_access/dsl/snow/common.py +0 -76
  523. relationalai/early_access/dsl/state_mgmt/__init__.py +0 -129
  524. relationalai/early_access/dsl/state_mgmt/state_charts.py +0 -125
  525. relationalai/early_access/dsl/state_mgmt/transitions.py +0 -130
  526. relationalai/early_access/dsl/types/__init__.py +0 -40
  527. relationalai/early_access/dsl/types/concepts.py +0 -12
  528. relationalai/early_access/dsl/types/entities.py +0 -135
  529. relationalai/early_access/dsl/types/values.py +0 -17
  530. relationalai/early_access/dsl/utils.py +0 -102
  531. relationalai/early_access/graphs/__init__.py +0 -13
  532. relationalai/early_access/lqp/__init__.py +0 -12
  533. relationalai/early_access/lqp/compiler/__init__.py +0 -12
  534. relationalai/early_access/lqp/constructors/__init__.py +0 -18
  535. relationalai/early_access/lqp/executor/__init__.py +0 -12
  536. relationalai/early_access/lqp/ir/__init__.py +0 -12
  537. relationalai/early_access/lqp/passes/__init__.py +0 -12
  538. relationalai/early_access/lqp/pragmas/__init__.py +0 -12
  539. relationalai/early_access/lqp/primitives/__init__.py +0 -12
  540. relationalai/early_access/lqp/types/__init__.py +0 -12
  541. relationalai/early_access/lqp/utils/__init__.py +0 -12
  542. relationalai/early_access/lqp/validators/__init__.py +0 -12
  543. relationalai/early_access/metamodel/__init__.py +0 -58
  544. relationalai/early_access/metamodel/builtins/__init__.py +0 -12
  545. relationalai/early_access/metamodel/compiler/__init__.py +0 -12
  546. relationalai/early_access/metamodel/dependency/__init__.py +0 -12
  547. relationalai/early_access/metamodel/factory/__init__.py +0 -17
  548. relationalai/early_access/metamodel/helpers/__init__.py +0 -12
  549. relationalai/early_access/metamodel/ir/__init__.py +0 -14
  550. relationalai/early_access/metamodel/rewrite/__init__.py +0 -7
  551. relationalai/early_access/metamodel/typer/__init__.py +0 -3
  552. relationalai/early_access/metamodel/typer/typer/__init__.py +0 -12
  553. relationalai/early_access/metamodel/types/__init__.py +0 -15
  554. relationalai/early_access/metamodel/util/__init__.py +0 -15
  555. relationalai/early_access/metamodel/visitor/__init__.py +0 -12
  556. relationalai/early_access/rel/__init__.py +0 -12
  557. relationalai/early_access/rel/executor/__init__.py +0 -12
  558. relationalai/early_access/rel/rel_utils/__init__.py +0 -12
  559. relationalai/early_access/rel/rewrite/__init__.py +0 -7
  560. relationalai/early_access/solvers/__init__.py +0 -19
  561. relationalai/early_access/sql/__init__.py +0 -11
  562. relationalai/early_access/sql/executor/__init__.py +0 -3
  563. relationalai/early_access/sql/rewrite/__init__.py +0 -3
  564. relationalai/early_access/tests/logging/__init__.py +0 -12
  565. relationalai/early_access/tests/test_snapshot_base/__init__.py +0 -12
  566. relationalai/early_access/tests/utils/__init__.py +0 -12
  567. relationalai/environments/__init__.py +0 -35
  568. relationalai/environments/base.py +0 -381
  569. relationalai/environments/colab.py +0 -14
  570. relationalai/environments/generic.py +0 -71
  571. relationalai/environments/ipython.py +0 -68
  572. relationalai/environments/jupyter.py +0 -9
  573. relationalai/environments/snowbook.py +0 -169
  574. relationalai/errors.py +0 -2496
  575. relationalai/experimental/SF.py +0 -38
  576. relationalai/experimental/inspect.py +0 -47
  577. relationalai/experimental/pathfinder/__init__.py +0 -158
  578. relationalai/experimental/pathfinder/api.py +0 -160
  579. relationalai/experimental/pathfinder/automaton.py +0 -584
  580. relationalai/experimental/pathfinder/bridge.py +0 -226
  581. relationalai/experimental/pathfinder/compiler.py +0 -416
  582. relationalai/experimental/pathfinder/datalog.py +0 -214
  583. relationalai/experimental/pathfinder/diagnostics.py +0 -56
  584. relationalai/experimental/pathfinder/filter.py +0 -236
  585. relationalai/experimental/pathfinder/glushkov.py +0 -439
  586. relationalai/experimental/pathfinder/options.py +0 -265
  587. relationalai/experimental/pathfinder/pathfinder-v0.7.0.rel +0 -1951
  588. relationalai/experimental/pathfinder/rpq.py +0 -344
  589. relationalai/experimental/pathfinder/transition.py +0 -200
  590. relationalai/experimental/pathfinder/utils.py +0 -26
  591. relationalai/experimental/paths/README.md +0 -107
  592. relationalai/experimental/paths/api.py +0 -143
  593. relationalai/experimental/paths/benchmarks/grid_graph.py +0 -37
  594. relationalai/experimental/paths/code_organization.md +0 -2
  595. relationalai/experimental/paths/examples/Movies.ipynb +0 -16328
  596. relationalai/experimental/paths/examples/basic_example.py +0 -40
  597. relationalai/experimental/paths/examples/minimal_engine_warmup.py +0 -3
  598. relationalai/experimental/paths/examples/movie_example.py +0 -77
  599. relationalai/experimental/paths/examples/movies_data/actedin.csv +0 -193
  600. relationalai/experimental/paths/examples/movies_data/directed.csv +0 -45
  601. relationalai/experimental/paths/examples/movies_data/follows.csv +0 -7
  602. relationalai/experimental/paths/examples/movies_data/movies.csv +0 -39
  603. relationalai/experimental/paths/examples/movies_data/person.csv +0 -134
  604. relationalai/experimental/paths/examples/movies_data/produced.csv +0 -16
  605. relationalai/experimental/paths/examples/movies_data/ratings.csv +0 -10
  606. relationalai/experimental/paths/examples/movies_data/wrote.csv +0 -11
  607. relationalai/experimental/paths/examples/paths_benchmark.py +0 -115
  608. relationalai/experimental/paths/examples/paths_example.py +0 -116
  609. relationalai/experimental/paths/examples/pattern_to_automaton.py +0 -28
  610. relationalai/experimental/paths/find_paths_via_automaton.py +0 -85
  611. relationalai/experimental/paths/graph.py +0 -185
  612. relationalai/experimental/paths/path_algorithms/find_paths.py +0 -280
  613. relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +0 -26
  614. relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +0 -111
  615. relationalai/experimental/paths/path_algorithms/single.py +0 -59
  616. relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +0 -39
  617. relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +0 -103
  618. relationalai/experimental/paths/path_algorithms/usp-old.py +0 -130
  619. relationalai/experimental/paths/path_algorithms/usp-tuple.py +0 -183
  620. relationalai/experimental/paths/path_algorithms/usp.py +0 -150
  621. relationalai/experimental/paths/product_graph.py +0 -93
  622. relationalai/experimental/paths/rpq/automaton.py +0 -584
  623. relationalai/experimental/paths/rpq/diagnostics.py +0 -56
  624. relationalai/experimental/paths/rpq/rpq.py +0 -378
  625. relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +0 -90
  626. relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +0 -119
  627. relationalai/experimental/paths/tests/tests_limit_sp_single.py +0 -104
  628. relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +0 -113
  629. relationalai/experimental/paths/tests/tests_limit_walks_single.py +0 -149
  630. relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +0 -70
  631. relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +0 -64
  632. relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +0 -115
  633. relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +0 -75
  634. relationalai/experimental/paths/tests/tests_single_paths.py +0 -152
  635. relationalai/experimental/paths/tests/tests_single_walks.py +0 -208
  636. relationalai/experimental/paths/tests/tests_single_walks_undirected.py +0 -297
  637. relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +0 -107
  638. relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +0 -76
  639. relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +0 -76
  640. relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +0 -110
  641. relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +0 -229
  642. relationalai/experimental/paths/tests/tests_usp_nsp_single.py +0 -108
  643. relationalai/experimental/paths/tree_agg.py +0 -168
  644. relationalai/experimental/paths/utilities/iterators.py +0 -27
  645. relationalai/experimental/paths/utilities/prefix_sum.py +0 -91
  646. relationalai/experimental/solvers.py +0 -1095
  647. relationalai/loaders/csv.py +0 -195
  648. relationalai/loaders/loader.py +0 -177
  649. relationalai/loaders/types.py +0 -23
  650. relationalai/rel_emitter.py +0 -373
  651. relationalai/rel_utils.py +0 -185
  652. relationalai/semantics/designs/query_builder/identify_by.md +0 -106
  653. relationalai/semantics/devtools/benchmark_lqp.py +0 -535
  654. relationalai/semantics/devtools/compilation_manager.py +0 -294
  655. relationalai/semantics/devtools/extract_lqp.py +0 -110
  656. relationalai/semantics/internal/internal.py +0 -3785
  657. relationalai/semantics/internal/snowflake.py +0 -329
  658. relationalai/semantics/lqp/README.md +0 -34
  659. relationalai/semantics/lqp/algorithms.py +0 -173
  660. relationalai/semantics/lqp/builtins.py +0 -213
  661. relationalai/semantics/lqp/compiler.py +0 -22
  662. relationalai/semantics/lqp/constructors.py +0 -68
  663. relationalai/semantics/lqp/executor.py +0 -518
  664. relationalai/semantics/lqp/export_rewriter.py +0 -40
  665. relationalai/semantics/lqp/intrinsics.py +0 -24
  666. relationalai/semantics/lqp/ir.py +0 -150
  667. relationalai/semantics/lqp/model2lqp.py +0 -1056
  668. relationalai/semantics/lqp/passes.py +0 -38
  669. relationalai/semantics/lqp/primitives.py +0 -252
  670. relationalai/semantics/lqp/result_helpers.py +0 -266
  671. relationalai/semantics/lqp/rewrite/__init__.py +0 -32
  672. relationalai/semantics/lqp/rewrite/algorithm.py +0 -385
  673. relationalai/semantics/lqp/rewrite/annotate_constraints.py +0 -69
  674. relationalai/semantics/lqp/rewrite/cdc.py +0 -216
  675. relationalai/semantics/lqp/rewrite/constants_to_vars.py +0 -70
  676. relationalai/semantics/lqp/rewrite/deduplicate_vars.py +0 -104
  677. relationalai/semantics/lqp/rewrite/eliminate_data.py +0 -108
  678. relationalai/semantics/lqp/rewrite/extract_common.py +0 -340
  679. relationalai/semantics/lqp/rewrite/extract_keys.py +0 -577
  680. relationalai/semantics/lqp/rewrite/flatten_script.py +0 -301
  681. relationalai/semantics/lqp/rewrite/function_annotations.py +0 -114
  682. relationalai/semantics/lqp/rewrite/functional_dependencies.py +0 -348
  683. relationalai/semantics/lqp/rewrite/period_math.py +0 -77
  684. relationalai/semantics/lqp/rewrite/quantify_vars.py +0 -339
  685. relationalai/semantics/lqp/rewrite/splinter.py +0 -76
  686. relationalai/semantics/lqp/rewrite/unify_definitions.py +0 -323
  687. relationalai/semantics/lqp/types.py +0 -101
  688. relationalai/semantics/lqp/utils.py +0 -170
  689. relationalai/semantics/lqp/validators.py +0 -70
  690. relationalai/semantics/metamodel/compiler.py +0 -134
  691. relationalai/semantics/metamodel/dependency.py +0 -880
  692. relationalai/semantics/metamodel/executor.py +0 -78
  693. relationalai/semantics/metamodel/factory.py +0 -287
  694. relationalai/semantics/metamodel/helpers.py +0 -368
  695. relationalai/semantics/metamodel/ir.py +0 -924
  696. relationalai/semantics/metamodel/rewrite/__init__.py +0 -8
  697. relationalai/semantics/metamodel/rewrite/discharge_constraints.py +0 -39
  698. relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +0 -220
  699. relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +0 -78
  700. relationalai/semantics/metamodel/rewrite/flatten.py +0 -590
  701. relationalai/semantics/metamodel/rewrite/format_outputs.py +0 -256
  702. relationalai/semantics/metamodel/rewrite/handle_aggregations_and_ranks.py +0 -237
  703. relationalai/semantics/metamodel/typer/checker.py +0 -355
  704. relationalai/semantics/metamodel/typer/typer.py +0 -1396
  705. relationalai/semantics/metamodel/util.py +0 -506
  706. relationalai/semantics/metamodel/visitor.py +0 -945
  707. relationalai/semantics/reasoners/__init__.py +0 -10
  708. relationalai/semantics/reasoners/graph/README.md +0 -620
  709. relationalai/semantics/reasoners/graph/__init__.py +0 -37
  710. relationalai/semantics/reasoners/graph/core.py +0 -9019
  711. relationalai/semantics/reasoners/graph/design/beyond_demand_transform.md +0 -797
  712. relationalai/semantics/reasoners/graph/tests/README.md +0 -21
  713. relationalai/semantics/reasoners/optimization/__init__.py +0 -68
  714. relationalai/semantics/reasoners/optimization/common.py +0 -88
  715. relationalai/semantics/reasoners/optimization/solvers_dev.py +0 -568
  716. relationalai/semantics/reasoners/optimization/solvers_pb.py +0 -1407
  717. relationalai/semantics/rel/builtins.py +0 -40
  718. relationalai/semantics/rel/compiler.py +0 -994
  719. relationalai/semantics/rel/executor.py +0 -363
  720. relationalai/semantics/rel/rel.py +0 -482
  721. relationalai/semantics/rel/rel_utils.py +0 -276
  722. relationalai/semantics/snowflake/__init__.py +0 -3
  723. relationalai/semantics/sql/compiler.py +0 -2503
  724. relationalai/semantics/sql/executor/duck_db.py +0 -52
  725. relationalai/semantics/sql/executor/result_helpers.py +0 -64
  726. relationalai/semantics/sql/executor/snowflake.py +0 -149
  727. relationalai/semantics/sql/rewrite/denormalize.py +0 -222
  728. relationalai/semantics/sql/rewrite/double_negation.py +0 -49
  729. relationalai/semantics/sql/rewrite/recursive_union.py +0 -127
  730. relationalai/semantics/sql/rewrite/sort_output_query.py +0 -246
  731. relationalai/semantics/sql/sql.py +0 -504
  732. relationalai/semantics/std/pragmas.py +0 -11
  733. relationalai/semantics/std/std.py +0 -14
  734. relationalai/semantics/tests/lqp/algorithms.py +0 -345
  735. relationalai/semantics/tests/test_snapshot_abstract.py +0 -144
  736. relationalai/semantics/tests/test_snapshot_base.py +0 -9
  737. relationalai/semantics/tests/utils.py +0 -46
  738. relationalai/std/__init__.py +0 -70
  739. relationalai/tools/cli.py +0 -2089
  740. relationalai/tools/cli_controls.py +0 -1975
  741. relationalai/tools/cli_helpers.py +0 -802
  742. relationalai/tools/debugger_client.py +0 -109
  743. relationalai/tools/debugger_server.py +0 -302
  744. relationalai/tools/dev.py +0 -685
  745. relationalai/tools/notes +0 -7
  746. relationalai/tools/qb_debugger.py +0 -425
  747. relationalai/tools/txn_progress.py +0 -188
  748. relationalai/util/clean_up_databases.py +0 -95
  749. relationalai/util/list_databases.py +0 -9
  750. relationalai/util/otel_configuration.py +0 -26
  751. relationalai/util/otel_handler.py +0 -484
  752. relationalai/util/snowflake_handler.py +0 -88
  753. relationalai/util/span_format_test.py +0 -43
  754. relationalai/util/span_tracker.py +0 -207
  755. relationalai/util/spans_file_handler.py +0 -72
  756. relationalai/util/tracing_handler.py +0 -34
  757. relationalai-0.13.5.dist-info/METADATA +0 -74
  758. relationalai-0.13.5.dist-info/RECORD +0 -473
  759. relationalai-0.13.5.dist-info/WHEEL +0 -4
  760. relationalai-0.13.5.dist-info/entry_points.txt +0 -3
  761. relationalai-0.13.5.dist-info/licenses/LICENSE +0 -202
  762. relationalai_test_util/__init__.py +0 -4
  763. relationalai_test_util/fixtures.py +0 -233
  764. relationalai_test_util/snapshot.py +0 -252
  765. relationalai_test_util/traceback.py +0 -118
  766. /relationalai/{analysis → semantics/frontend}/__init__.py +0 -0
  767. /relationalai/{auth/__init__.py → semantics/metamodel/metamodel_compiler.py} +0 -0
  768. /relationalai/{early_access → shims}/__init__.py +0 -0
  769. {relationalai/early_access/dsl/adapters → v0/relationalai/analysis}/__init__.py +0 -0
  770. {relationalai → v0/relationalai}/analysis/mechanistic.py +0 -0
  771. {relationalai → v0/relationalai}/analysis/whynot.py +0 -0
  772. {relationalai/early_access/dsl/adapters/orm → v0/relationalai/auth}/__init__.py +0 -0
  773. {relationalai → v0/relationalai}/auth/jwt_generator.py +0 -0
  774. {relationalai → v0/relationalai}/auth/oauth_callback_server.py +0 -0
  775. {relationalai → v0/relationalai}/auth/token_handler.py +0 -0
  776. {relationalai → v0/relationalai}/auth/util.py +0 -0
  777. {relationalai/clients/resources/snowflake → v0/relationalai/clients}/cache_store.py +0 -0
  778. {relationalai → v0/relationalai}/compiler.py +0 -0
  779. {relationalai → v0/relationalai}/dependencies.py +0 -0
  780. {relationalai → v0/relationalai}/docutils.py +0 -0
  781. {relationalai/early_access/dsl/adapters/owl → v0/relationalai/early_access}/__init__.py +0 -0
  782. {relationalai → v0/relationalai}/early_access/dsl/__init__.py +0 -0
  783. {relationalai/early_access/dsl/bindings → v0/relationalai/early_access/dsl/adapters}/__init__.py +0 -0
  784. {relationalai/early_access/dsl/bindings/legacy → v0/relationalai/early_access/dsl/adapters/orm}/__init__.py +0 -0
  785. {relationalai → v0/relationalai}/early_access/dsl/adapters/orm/model.py +0 -0
  786. {relationalai/early_access/dsl/codegen → v0/relationalai/early_access/dsl/adapters/owl}/__init__.py +0 -0
  787. {relationalai → v0/relationalai}/early_access/dsl/adapters/owl/model.py +0 -0
  788. {relationalai/early_access/dsl/core/temporal → v0/relationalai/early_access/dsl/bindings}/__init__.py +0 -0
  789. {relationalai/early_access/dsl/ir → v0/relationalai/early_access/dsl/bindings/legacy}/__init__.py +0 -0
  790. {relationalai/early_access/dsl/ontologies → v0/relationalai/early_access/dsl/codegen}/__init__.py +0 -0
  791. {relationalai → v0/relationalai}/early_access/dsl/constants.py +0 -0
  792. {relationalai → v0/relationalai}/early_access/dsl/core/__init__.py +0 -0
  793. {relationalai → v0/relationalai}/early_access/dsl/core/constraints/__init__.py +0 -0
  794. {relationalai → v0/relationalai}/early_access/dsl/core/constraints/predicate/__init__.py +0 -0
  795. {relationalai → v0/relationalai}/early_access/dsl/core/stack.py +0 -0
  796. {relationalai/early_access/dsl/orm → v0/relationalai/early_access/dsl/core/temporal}/__init__.py +0 -0
  797. {relationalai → v0/relationalai}/early_access/dsl/core/utils.py +0 -0
  798. {relationalai/early_access/dsl/orm/measures → v0/relationalai/early_access/dsl/ir}/__init__.py +0 -0
  799. {relationalai/early_access/dsl/physical_metadata → v0/relationalai/early_access/dsl/ontologies}/__init__.py +0 -0
  800. {relationalai → v0/relationalai}/early_access/dsl/ontologies/raw_source.py +0 -0
  801. {relationalai/early_access/dsl/serialize → v0/relationalai/early_access/dsl/orm}/__init__.py +0 -0
  802. {relationalai/early_access/dsl/snow → v0/relationalai/early_access/dsl/orm/measures}/__init__.py +0 -0
  803. {relationalai → v0/relationalai}/early_access/dsl/orm/reasoner_errors.py +0 -0
  804. {relationalai/loaders → v0/relationalai/early_access/dsl/physical_metadata}/__init__.py +0 -0
  805. {relationalai/semantics/tests → v0/relationalai/early_access/dsl/serialize}/__init__.py +0 -0
  806. {relationalai → v0/relationalai}/early_access/dsl/serialize/binding_model.py +0 -0
  807. {relationalai → v0/relationalai}/early_access/dsl/serialize/model.py +0 -0
  808. {relationalai/semantics/tests/lqp → v0/relationalai/early_access/dsl/snow}/__init__.py +0 -0
  809. {relationalai → v0/relationalai}/early_access/tests/__init__.py +0 -0
  810. {relationalai → v0/relationalai}/environments/ci.py +0 -0
  811. {relationalai → v0/relationalai}/environments/hex.py +0 -0
  812. {relationalai → v0/relationalai}/environments/terminal.py +0 -0
  813. {relationalai → v0/relationalai}/experimental/__init__.py +0 -0
  814. {relationalai → v0/relationalai}/experimental/graphs.py +0 -0
  815. {relationalai → v0/relationalai}/experimental/paths/__init__.py +0 -0
  816. {relationalai → v0/relationalai}/experimental/paths/benchmarks/__init__.py +0 -0
  817. {relationalai → v0/relationalai}/experimental/paths/path_algorithms/__init__.py +0 -0
  818. {relationalai → v0/relationalai}/experimental/paths/rpq/__init__.py +0 -0
  819. {relationalai → v0/relationalai}/experimental/paths/rpq/filter.py +0 -0
  820. {relationalai → v0/relationalai}/experimental/paths/rpq/glushkov.py +0 -0
  821. {relationalai → v0/relationalai}/experimental/paths/rpq/transition.py +0 -0
  822. {relationalai → v0/relationalai}/experimental/paths/utilities/__init__.py +0 -0
  823. {relationalai → v0/relationalai}/experimental/paths/utilities/utilities.py +0 -0
  824. {relationalai/tools → v0/relationalai/loaders}/__init__.py +0 -0
  825. {relationalai → v0/relationalai}/metagen.py +0 -0
  826. {relationalai → v0/relationalai}/metamodel.py +0 -0
  827. {relationalai → v0/relationalai}/rel.py +0 -0
  828. {relationalai → v0/relationalai}/semantics/devtools/__init__.py +0 -0
  829. {relationalai → v0/relationalai}/semantics/internal/__init__.py +0 -0
  830. {relationalai → v0/relationalai}/semantics/internal/annotations.py +0 -0
  831. {relationalai → v0/relationalai}/semantics/lqp/__init__.py +0 -0
  832. {relationalai → v0/relationalai}/semantics/lqp/pragmas.py +0 -0
  833. {relationalai → v0/relationalai}/semantics/metamodel/dataflow.py +0 -0
  834. {relationalai → v0/relationalai}/semantics/metamodel/typer/__init__.py +0 -0
  835. {relationalai → v0/relationalai}/semantics/metamodel/types.py +0 -0
  836. {relationalai → v0/relationalai}/semantics/reasoners/experimental/__init__.py +0 -0
  837. {relationalai → v0/relationalai}/semantics/rel/__init__.py +0 -0
  838. {relationalai → v0/relationalai}/semantics/sql/__init__.py +0 -0
  839. {relationalai → v0/relationalai}/semantics/sql/executor/__init__.py +0 -0
  840. {relationalai → v0/relationalai}/semantics/sql/rewrite/__init__.py +0 -0
  841. {relationalai → v0/relationalai}/semantics/tests/logging.py +0 -0
  842. {relationalai → v0/relationalai}/std/aggregates.py +0 -0
  843. {relationalai → v0/relationalai}/std/dates.py +0 -0
  844. {relationalai → v0/relationalai}/std/graphs.py +0 -0
  845. {relationalai → v0/relationalai}/std/inspect.py +0 -0
  846. {relationalai → v0/relationalai}/std/math.py +0 -0
  847. {relationalai → v0/relationalai}/std/re.py +0 -0
  848. {relationalai → v0/relationalai}/std/strings.py +0 -0
  849. {relationalai → v0/relationalai}/tools/cleanup_snapshots.py +0 -0
  850. {relationalai → v0/relationalai}/tools/constants.py +0 -0
  851. {relationalai → v0/relationalai}/tools/query_utils.py +0 -0
  852. {relationalai → v0/relationalai}/tools/snapshot_viewer.py +0 -0
  853. {relationalai → v0/relationalai}/util/__init__.py +0 -0
  854. {relationalai → v0/relationalai}/util/constants.py +0 -0
  855. {relationalai → v0/relationalai}/util/graph.py +0 -0
  856. {relationalai → v0/relationalai}/util/timeout.py +0 -0
@@ -0,0 +1,1394 @@
1
+ from __future__ import annotations
2
+
3
+ from collections import defaultdict
4
+ from dataclasses import dataclass, field, replace as dc_replace
5
+ from typing import Dict, Sequence as seq, Iterable
6
+ from enum import Enum
7
+ from math import pi
8
+
9
+ # PyRel imports
10
+ from ..util.naming import sanitize
11
+ from ..semantics.metamodel import metamodel as mm
12
+ from ..semantics.metamodel.builtins import builtins as b, is_abstract
13
+ from ..semantics.metamodel.metamodel_analyzer import Normalize
14
+ # ensure std libs are loaded
15
+ from ..semantics.metamodel.metamodel_analyzer import VarFinder
16
+ from ..semantics.metamodel.rewriter import Walker
17
+ from ..semantics.std import aggregates, common, math, numbers, re, strings, decimals, datetime, floats
18
+ from ..semantics.backends.lqp import annotations as lqp_annotations
19
+
20
+ # V0 imports
21
+ from v0.relationalai.semantics.metamodel import ir as v0, builtins as v0_builtins, types as v0_types, factory as f
22
+ from v0.relationalai.semantics.metamodel.util import FrozenOrderedSet, frozen, ordered_set, filter_by_type, OrderedSet
23
+ from v0.relationalai.semantics.internal.internal import literal_value_to_type
24
+ from v0.relationalai.semantics.metamodel.typer import typer as v0_typer
25
+ from v0.relationalai.clients.util import IdentityParser
26
+
27
+ from .hoister import Hoister
28
+ from .helpers import is_output_update, is_main_output
29
+
30
+ #------------------------------------------------------
31
+ # Simplified translation API
32
+ #------------------------------------------------------
33
+ def translate(model: mm.Model) -> v0.Model:
34
+ return Translator().translate_model(model)
35
+
36
+ #------------------------------------------------------
37
+ # Implementation
38
+ #------------------------------------------------------
39
+ class Context(Enum):
40
+ # when translating tasks (i.e. runtime behavior)
41
+ TASK = 1
42
+ # when translating the static structure of the model (types, relations, etc.)
43
+ MODEL = 2
44
+
45
+ @dataclass
46
+ class Translator():
47
+
48
+ stack: list[mm.Node] = field(default_factory=list)
49
+
50
+ # maps from mm.Node id to the v0.Node created for it
51
+ # for Context=TASK
52
+ task_map: Dict[int, v0.Node] = field(default_factory=dict)
53
+ # for Context=MODEL
54
+ model_map: Dict[int, v0.Node] = field(default_factory=dict)
55
+
56
+ # map from a var that is bound to a table, to the list of vars that were used to construct
57
+ # this var. This var is going to be used as a key to an output.
58
+ key_map: Dict[mm.Var, seq[v0.Var]] = field(default_factory=dict)
59
+
60
+ # map from a var that is bound to a data, to the data itself. This is used to translate
61
+ # lookups on this var into v0 Data nodes.
62
+ data_map: Dict[mm.Var, mm.Var] = field(default_factory=dict)
63
+
64
+ # map from a var that is bound to an external table, to the vars of its fields
65
+ column_map: defaultdict[mm.Var, dict[mm.Relation, v0.Value]] = field(default_factory=lambda: defaultdict(dict))
66
+
67
+ # used tables
68
+ used_tables: OrderedSet[mm.Table] = field(default_factory=lambda: ordered_set())
69
+
70
+ # when translating a relation that has multiple readings, we need to translate to multiple
71
+ # relations in v0, and we need to add rules to populate those relations. We also need rules
72
+ # to populate super types from sub types.
73
+ maintenance_rules: list[v0.Logical] = field(default_factory=list)
74
+
75
+ # outputs that are exports
76
+ exports: set[v0.Output] = field(default_factory=set)
77
+
78
+ hoister = Hoister()
79
+ normalize = Normalize()
80
+
81
+ def get(self, ctx: Context, node: mm.Node):
82
+ if ctx == Context.MODEL:
83
+ return self.model_map.get(node.id, None)
84
+ else:
85
+ return self.task_map.get(node.id, None)
86
+ def set(self, ctx: Context, node: mm.Node, value: v0.Node):
87
+ if ctx == Context.MODEL:
88
+ self.model_map[node.id] = value # type: ignore
89
+ else:
90
+ self.task_map[node.id] = value # type: ignore
91
+
92
+ def translate_node(self, node: mm.Node, parent=None, ctx=Context.TASK) -> v0.Node|seq[v0.Node]:
93
+ x = self.get(ctx, node)
94
+ if x is not None:
95
+ return x
96
+
97
+ source_class_name = node.__class__.__name__.lower()
98
+ translator = getattr(self, f"translate_{source_class_name}", None)
99
+ if translator is None:
100
+ raise NotImplementedError(f"No translator for node type: {source_class_name}")
101
+
102
+ if parent:
103
+ self.stack.append(parent)
104
+ result = translator(node, parent, ctx)
105
+ if parent:
106
+ self.stack.pop()
107
+
108
+ self.set(ctx, node, result)
109
+ return result
110
+
111
+ def translate_value(self, value: mm.Value, parent, ctx) -> v0.Value:
112
+ # Value = _Union[Var, Literal, Type, Relation, seq["Value"], None]
113
+ if value is None:
114
+ return None
115
+ elif isinstance(value, mm.ScalarType) or isinstance(value, mm.Relation):
116
+ return self.translate_node(value, parent, Context.MODEL) # type: ignore
117
+ elif isinstance(value, seq):
118
+ return self.translate_seq(value, parent, ctx) # type: ignore
119
+ return self.translate_node(value, parent, ctx) # type: ignore
120
+
121
+
122
+ def translate_seq(self, nodes: seq[mm.Node], parent, ctx) -> tuple[v0.Node,...]:
123
+ res = []
124
+ for n in nodes:
125
+ x = self.translate_node(n, parent, ctx)
126
+ # flat map would be great here
127
+ if isinstance(x, list) or isinstance(x, tuple):
128
+ res.extend(x)
129
+ elif x is not None:
130
+ res.append(x)
131
+ return tuple(res)
132
+
133
+ def translate_frozen(self, nodes: seq[mm.Node], parent, ctx) -> FrozenOrderedSet[v0.Node]:
134
+ return frozen(*self.translate_seq(nodes, parent, ctx))
135
+
136
+ #------------------------------------------------------
137
+ # Helper
138
+ #------------------------------------------------------
139
+
140
+ # NOTE: This has to match what is done in the v0 snowflake.Table class as that is what CDC
141
+ # produces. If there's a quote in the table name, then we take it verbatim, otherwise we lowercase it.
142
+ def translate_table_name(self, table: mm.Table) -> str:
143
+ name = IdentityParser(table.name).identifier
144
+ name = name.lower() if '"' not in table.name else table.name.replace('"', '_')
145
+ return sanitize(name)
146
+
147
+ #-----------------------------------------------------------------------------
148
+ # Capabilities, Reasoners
149
+ #-----------------------------------------------------------------------------
150
+
151
+ def translate_capability(self, c: mm.Capability, parent: mm.Reasoner, ctx) -> v0.Capability:
152
+ return v0.Capability(name=c.name)
153
+
154
+ def translate_reasoner(self, r: mm.Reasoner|None, parent, ctx) -> v0.Engine|None:
155
+ if r is None:
156
+ return None
157
+ return v0.Engine(
158
+ name=f"{r.id}", # no name field in v0, so use id
159
+ platform=r.type,
160
+ info=r.info,
161
+ capabilities=self.translate_frozen(r.capabilities, r, ctx), # type: ignore
162
+ relations=self.translate_frozen(r.relations, r, ctx), # type: ignore
163
+ annotations=self.translate_frozen(r.annotations, r, ctx) # type: ignore
164
+ )
165
+
166
+ # -----------------------------------------------------------------------------
167
+ # Relation
168
+ # -----------------------------------------------------------------------------
169
+
170
+ def translate_field(self, f: mm.Field, parent, ctx) -> v0.Field:
171
+ return v0.Field(
172
+ name=f.name,
173
+ type=self.translate_node(f.type, f, Context.MODEL), # type: ignore
174
+ input=f.input,
175
+ )
176
+
177
+ def translate_reading(self, r: mm.Reading, parent: mm.Relation, ctx) -> v0.Relation:
178
+ # Readings in v0 are represented as separate Relation nodes with different field orders
179
+ fields = []
180
+ for i in r.field_order:
181
+ fields.append(self.translate_field(parent.fields[i], r, ctx))
182
+
183
+ # this is not totally correct, we are translating the parent's overloads here, but
184
+ # the order of fields would be different. However, it's unlikely we will have multiple
185
+ # readings AND overloads in the same relation, so this is acceptable for now.
186
+ return v0.Relation(
187
+ name=f"{parent.name}_{parent.readings.index(r)}",
188
+ fields=tuple(fields),
189
+ requires=frozen(),
190
+ annotations=frozen(),
191
+ overloads=self.translate_frozen(parent.overloads, parent, ctx), # type: ignore
192
+ )
193
+
194
+ def translate_overload(self, o: mm.Overload, parent: mm.Relation, ctx) -> v0.Relation:
195
+ # Overloads in v0 are represented as separate Relation nodes with different types
196
+ fields = []
197
+ for field, typ in zip(parent.fields, o.types):
198
+ fields.append(
199
+ v0.Field(name=field.name, type=self.translate_node(typ, field, ctx), input=field.input) # type: ignore
200
+ )
201
+ return v0.Relation(
202
+ name=parent.name,
203
+ fields=tuple(fields),
204
+ requires=frozen(),
205
+ annotations=frozen(),
206
+ overloads=frozen()
207
+ )
208
+
209
+ # map builtin relations by name
210
+ BUILTIN_RELATION_MAP = {}
211
+ RENAMES = {
212
+ "degrees": "rad2deg",
213
+ "radians": "deg2rad",
214
+ "len": "num_chars",
215
+ "power": "pow",
216
+ "^": "pow",
217
+ "like": "like_match",
218
+ "regex_escape": "escape_regex_metachars",
219
+ }
220
+ for lib in ["core", "aggregates", "common", "datetime", "floats", "math", "numbers", "strings", "re", "lqp"]:
221
+ for x in b._libraries[lib].data.values():
222
+ v0_name = RENAMES.get(x.name, x.name)
223
+ if v0_name in v0_builtins.builtin_relations_by_name:
224
+ BUILTIN_RELATION_MAP[x] = v0_builtins.builtin_relations_by_name[v0_name]
225
+
226
+ def translate_relation(self, r: mm.Relation, parent, ctx):
227
+ if r in self.BUILTIN_RELATION_MAP:
228
+ return self.BUILTIN_RELATION_MAP[r]
229
+
230
+ if r is b.numbers.parse_number:
231
+ if isinstance(parent, mm.Lookup):
232
+ assert(isinstance(parent.args[1], mm.Var))
233
+ out_type = parent.args[1].type
234
+ assert(isinstance(out_type, mm.NumberType))
235
+ if out_type.scale == 0:
236
+ return v0_builtins.parse_int128 if out_type.precision > 19 else v0_builtins.parse_int64
237
+ else:
238
+ return v0_builtins.parse_decimal
239
+
240
+ # relations can be accessed by any context; if it exists in the other context, use it
241
+ other_ctx = Context.MODEL if ctx == Context.TASK else Context.TASK
242
+ x = self.get(other_ctx, r)
243
+ if x is not None:
244
+ return x # type: ignore
245
+
246
+ if len(r.readings) > 1:
247
+ # if there are multiple readings, create a relation per reading
248
+ relations = self.translate_seq(r.readings, r, ctx) # type: ignore
249
+
250
+ # also create a rule to populate the other readings from the main relation
251
+ main_relation = relations[0]
252
+ assert isinstance(main_relation, v0.Relation)
253
+ main_relation_args = tuple(v0.Var(type=field.type, name=field.name) for field in main_relation.fields)
254
+ for reading in r.readings[1:]:
255
+ relation = relations[r.readings.index(reading)]
256
+ assert isinstance(relation, v0.Relation)
257
+ # lookup from main_relation and derive into this relation
258
+ self.maintenance_rules.append(v0.Logical(
259
+ engine=None,
260
+ hoisted=(),
261
+ body=(
262
+ v0.Lookup(
263
+ engine=None,
264
+ relation=main_relation,
265
+ args=main_relation_args,
266
+ annotations=frozen(),
267
+ ),
268
+ v0.Update(
269
+ engine=None,
270
+ relation=relation,
271
+ args=tuple([main_relation_args[idx] for idx in reading.field_order]),
272
+ effect=v0.Effect.derive,
273
+ annotations=frozen(),
274
+ )
275
+ ),
276
+ annotations=frozen(),
277
+ ))
278
+ return relations
279
+ else:
280
+ # if there are no readings or a single reading, create a single relation
281
+
282
+ # if this is a placeholder relation, fill overloads with all non-placeholder relations
283
+ # with the same name
284
+ overloads = ordered_set()
285
+ if all(field.type == b.core.Any for field in r.fields):
286
+ for rr in self.relations_by_name[r.name]:
287
+ if any(field.type != b.core.Any for field in rr.fields):
288
+ x = self.translate_relation(rr, r, ctx)
289
+ if isinstance(x, v0.Relation):
290
+ overloads.add(x)
291
+ else:
292
+ overloads.update(x) # type: ignore
293
+ overloads.update(self.translate_frozen(r.overloads, r, ctx)) # type: ignore
294
+ annotations = self.translate_seq(r.annotations, r, ctx) # type: ignore
295
+ name = r.name
296
+ fields = self.translate_seq(r.fields, r, ctx) # type: ignore
297
+ # We need to turn column relations into what the CDC pass would otherwise produce
298
+ # by making the relation name be the table name and adding a symbol field at the front
299
+ # representing the column name
300
+ if r.fields and isinstance(r.fields[0].type, mm.Table) and r in r.fields[0].type.columns:
301
+ name = self.translate_table_name(r.fields[0].type)
302
+ fields = (v0.Field("symbol", v0_types.Symbol, False), *fields) # type: ignore
303
+ annotations = annotations + (v0_builtins.external_annotation,)
304
+
305
+ return v0.Relation(
306
+ name=name,
307
+ fields=frozen(*fields), # type: ignore
308
+ requires=self.translate_frozen(r.requires, r, ctx), # type: ignore
309
+ annotations=frozen(*annotations), # type: ignore
310
+ overloads=overloads.frozen(), # type: ignore
311
+ )
312
+
313
+ def translate_unresolvedrelation(self, r: mm.UnresolvedRelation, parent, ctx):
314
+ # treat unresolved relations the same as normal relations for now
315
+ return self.translate_relation(r, parent, ctx)
316
+
317
+ #------------------------------------------------------
318
+ # Annotation
319
+ #------------------------------------------------------
320
+
321
+ def translate_annotation(self, a: mm.Annotation, parent, ctx) -> v0.Annotation:
322
+ if a.relation.name in v0_builtins.builtin_annotations_by_name:
323
+ return getattr(v0_builtins, a.relation.name + "_annotation") # type: ignore
324
+
325
+ return v0.Annotation(
326
+ relation=self.translate_node(a.relation, a, Context.MODEL), # type: ignore
327
+ args=tuple(self.translate_value(arg, a, ctx) for arg in a.args)
328
+ )
329
+
330
+ #-----------------------------------------------------------------------------
331
+ # Types
332
+ #-----------------------------------------------------------------------------
333
+
334
+ BUILTIN_TYPE_MAP = {
335
+ # Abstract types (should be removed once our typer is done because they should not
336
+ # show up in the typed metamodel.)
337
+ b.core.Any: v0_types.Any,
338
+ # b.core.AnyEntity: v0_types.AnyEntity,
339
+ b.core.Number: v0_types.Number, # v0 typer can figure the rest out
340
+ # Concrete types
341
+ b.core.Boolean: v0_types.Bool,
342
+ b.core.String: v0_types.String,
343
+ b.core.Date: v0_types.Date,
344
+ b.core.DateTime: v0_types.DateTime,
345
+ b.core.Float: v0_types.Float,
346
+ b.core.Hash: v0_types.Hash,
347
+ }
348
+
349
+ def translate_scalartype(self, t: mm.ScalarType, parent: mm.Node, ctx) -> v0.ScalarType|v0.Relation|None:
350
+ if t in self.BUILTIN_TYPE_MAP:
351
+ return self.BUILTIN_TYPE_MAP[t]
352
+
353
+ if ctx == Context.TASK:
354
+ # in task context, this is a lookup or update on a concept population relation
355
+ # TODO - removing this filter for now
356
+ actual_type = self.translate_node(t, t, Context.MODEL)
357
+ assert isinstance(actual_type, v0.ScalarType)
358
+ fields = [v0.Field(name="entity", type=actual_type, input=False)] # type: ignore
359
+ annotations = [v0_builtins.concept_relation_annotation]
360
+ name = t.name
361
+ if isinstance(t, mm.Table):
362
+ annotations.append(v0_builtins.external_annotation)
363
+ name = self.translate_table_name(t)
364
+ fields.insert(0, v0.Field(name="symbol", type=v0_types.Symbol, input=False)) # type: ignore
365
+
366
+ type_relation = v0.Relation(
367
+ name=name,
368
+ fields=tuple(fields), # type: ignore
369
+ requires=frozen(),
370
+ annotations=frozen(*annotations), # type: ignore
371
+ overloads=frozen()
372
+ )
373
+ for super_type in t.super_types:
374
+ super_rel = self.translate_node(super_type, t, Context.TASK)
375
+ if not super_rel:
376
+ continue
377
+ assert isinstance(super_rel, v0.Relation)
378
+ v = v0.Var(type=actual_type, name=type_relation.name.lower())
379
+ self.maintenance_rules.append(v0.Logical(
380
+ engine=None,
381
+ hoisted=(),
382
+ body=(
383
+ v0.Lookup(
384
+ engine=None,
385
+ relation=type_relation,
386
+ args=(v,),
387
+ annotations=frozen(),
388
+ ),
389
+ v0.Update(
390
+ engine=None,
391
+ relation=super_rel,
392
+ args=(v,),
393
+ effect=v0.Effect.derive,
394
+ annotations=frozen(),
395
+ )
396
+ ),
397
+ annotations=frozen(),
398
+ ))
399
+ return type_relation
400
+
401
+ extends=[]
402
+ if isinstance(t, mm.Table):
403
+ extends.append(v0_types.RowId)
404
+
405
+ for st in t.super_types:
406
+ # for now make all value types extending number be Int64, we will fix this with a new typer
407
+ if st == b.core.Number:
408
+ translated_st = v0_types.Number
409
+ else:
410
+ translated_st = self.translate_node(st, t, ctx)
411
+ extends.append(translated_st)
412
+
413
+ return v0.ScalarType(
414
+ name=t.name,
415
+ super_types=frozen(*extends), # type: ignore
416
+ # super_types=self.translate_frozen(t.super_types, t, ctx), # type: ignore
417
+ annotations=self.translate_frozen(t.annotations, t, ctx) # type: ignore
418
+ )
419
+
420
+ def translate_numbertype(self, t: mm.NumberType, parent, ctx):
421
+ if t.scale == 0:
422
+ return v0_types.Int128 if t.precision > 19 else v0_types.Int64
423
+ return v0.DecimalType(
424
+ name=t.name,
425
+ precision=t.precision,
426
+ scale=t.scale,
427
+ super_types=frozen(),
428
+ annotations=self.translate_frozen(t.annotations, t, ctx) # type: ignore
429
+ )
430
+
431
+ def translate_uniontype(self, t: mm.UnionType, parent, ctx) -> v0.UnionType:
432
+ return v0.UnionType(
433
+ types=self.translate_frozen(t.types, t, ctx), # type: ignore
434
+ )
435
+
436
+ def translate_listtype(self, t: mm.ListType, parent, ctx) -> v0.ListType:
437
+ return v0.ListType(
438
+ element_type=self.translate_node(t.element_type, t, ctx), # type: ignore
439
+ )
440
+
441
+ def translate_tupletype(self, t: mm.TupleType, parent, ctx) -> v0.TupleType:
442
+ return v0.TupleType(
443
+ types=self.translate_seq(t.element_types, t, ctx), # type: ignore
444
+ )
445
+
446
+
447
+ #------------------------------------------------------
448
+ # Table
449
+ #------------------------------------------------------
450
+
451
+ # TODO - this depends on what is using it, it may become an Output
452
+ # class Table(ScalarType):
453
+ # columns: seq[Relation] = tuple_field()
454
+ # uri: str = ""
455
+
456
+ def translate_table(self, t: mm.Table, parent, ctx):
457
+ return self.translate_scalartype(t, parent, ctx)
458
+
459
+
460
+ # -----------------------------------------------------------------------------
461
+ # Values
462
+ # -----------------------------------------------------------------------------
463
+
464
+ # Primitive = _Union[str, int, float, bool, _dt.datetime, None]
465
+
466
+ def translate_var(self, v: mm.Var, parent, ctx) -> v0.Var:
467
+ if isinstance(parent, mm.Lookup):
468
+ root_type = parent.relation.fields[0].type
469
+ root_arg = parent.args[0]
470
+ if isinstance(root_arg, mm.Var) \
471
+ and isinstance(root_type, mm.Table) \
472
+ and (existing := self.column_map[root_arg].get(parent.relation)):
473
+ return existing # type: ignore
474
+
475
+ return v0.Var(
476
+ type=self.translate_node(v.type, v, Context.MODEL), # type: ignore
477
+ name=v.name
478
+ )
479
+
480
+ def translate_literal(self, l: mm.Literal, parent, ctx) -> v0.Literal:
481
+ typ = None
482
+ if l.type is None or is_abstract(l.type):
483
+ # force int64 for literals, it can be widened later if needed
484
+ if type(l.value) == int:
485
+ typ = v0_types.Int64
486
+ else:
487
+ # using v0's map of literal to type
488
+ typ = literal_value_to_type(l.value)
489
+ else:
490
+ typ = self.translate_node(l.type, l, Context.MODEL)
491
+ if type is None:
492
+ pass
493
+ return v0.Literal(
494
+ type=typ, # type: ignore
495
+ value=l.value
496
+ )
497
+
498
+ # Value = _Union[Var, Literal, Type, Relation, seq["Value"], None]
499
+
500
+ # # -----------------------------------------------------------------------------
501
+ # # Tasks (process algebra)
502
+ # # -----------------------------------------------------------------------------
503
+
504
+ # @dataclass(frozen=True, kw_only=True)
505
+ # class Task(Node):
506
+ # reasoner: Optional[Reasoner] = None
507
+
508
+ # -----------------------------
509
+ # Control Flow
510
+ # -----------------------------
511
+
512
+ def _merge_outputs(self, children: seq[v0.Node], outputs:list[v0.Output]):
513
+ # We need to always rewrite the outputs, even if there's only one, because
514
+ # we may need to mark it as an export and handle the NO_KEYS case.
515
+ # if len(outputs) < 2:
516
+ # return children
517
+
518
+ children = list(children)
519
+
520
+ # merge all outputs, accumulating keys and aliases
521
+ keys = ordered_set()
522
+ aliases = ordered_set()
523
+ for output in outputs:
524
+ assert isinstance(output, v0.Output)
525
+ children.remove(output)
526
+ if output.keys is not None:
527
+ keys.update(output.keys)
528
+ aliases.update(output.aliases)
529
+
530
+ # add a single, merged output
531
+ is_export = any(output in self.exports for output in outputs)
532
+ annos = (v0_builtins.export_annotation,) if is_export else ()
533
+ if is_export and not keys:
534
+ key_var = v0.Var(type=v0_types.Hash, name="export_key")
535
+ vals = [alias[1] for alias in aliases]
536
+ children.append(v0.Construct(
537
+ engine=None,
538
+ values=(v0.Literal(type=v0_types.String, value="NO_KEYS"), *vals),
539
+ id_var=key_var,
540
+ ))
541
+ keys.add(key_var)
542
+
543
+ children.append(
544
+ v0.Output(
545
+ engine=None,
546
+ aliases=frozen(*aliases),
547
+ keys=frozen(*keys),
548
+ annotations=frozen(*annos)
549
+ )
550
+ )
551
+ return tuple(children)
552
+
553
+ def get_outputs(self, children: seq[v0.Node]) -> list[v0.Output]:
554
+ return list(filter(lambda o: isinstance(o, v0.Output), children)) # type: ignore
555
+
556
+ def translate_logical(self, l: mm.Logical, parent, ctx):
557
+ # first process children
558
+ children = self.translate_seq(l.body, l, ctx)
559
+
560
+ # inline logicals if possible
561
+ new_children = []
562
+ for c in children:
563
+ if isinstance(c, v0.Logical) and not c.hoisted and len(c.body) == 1 and not isinstance(c.body[0], (v0.Aggregate, v0.Rank)):
564
+ new_children.extend(c.body)
565
+ else:
566
+ new_children.append(c)
567
+ # children = children if len(children) == len(new_children) else tuple(new_children)
568
+ children = tuple(new_children)
569
+
570
+ # compute variables to hoist, wrapping in Default if the logical is optional
571
+ if l.optional:
572
+ hoisted = tuple([v0.Default(self.translate_node(v, l, ctx), None) for v in self.hoister.hoisted(l)]) # type: ignore
573
+ else:
574
+ hoisted = tuple([self.translate_node(v, l, ctx) for v in self.hoister.hoisted(l)]) # type: ignore
575
+
576
+ # Nots can never hoist variables upwards
577
+ if isinstance(parent, mm.Not):
578
+ hoisted = ()
579
+
580
+ # if there are no outputs, just return the logical
581
+ outputs = self.get_outputs(children)
582
+ if not outputs:
583
+ return v0.Logical(
584
+ engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
585
+ hoisted=hoisted, # type: ignore
586
+ body=children, # type: ignore
587
+ annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
588
+ )
589
+
590
+
591
+ # if there's a main output here, we need to merge all outputs as a single one
592
+ has_main_output = any(is_main_output(c) for c in l.body)
593
+ if has_main_output:
594
+ return v0.Logical(
595
+ engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
596
+ hoisted=hoisted, # type: ignore
597
+ body=self._merge_outputs(children, outputs), # type: ignore
598
+ annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
599
+ )
600
+ else:
601
+ # this logical has an output but it's not the main one; so we return the outputs
602
+ # side-by-side with the logical. This assumes that the parent is a logical that
603
+ # will splat these tasks and we will eventually get into a logical with a main
604
+ # output that will merge them all.
605
+
606
+ # remove outputs from children
607
+ children = tuple([c for c in children if not isinstance(c, v0.Output)])
608
+ if not children:
609
+ return outputs
610
+
611
+ # if this is an optional logical but we're not hoisting anything and not updating,
612
+ # then it's possible we're filtering an outer variable, but only for this column. If
613
+ # so, we need to alias the output and hoist it.
614
+ # this is important because the LQP stack blows up if there's a logical with no effect
615
+ if l.optional and not hoisted and not any(isinstance(c, v0.Update) for c in children):
616
+ # if there are no lookups, then this really is a no-op, just return outputs
617
+ # LQP blows up with e.g. a match-only logical
618
+ if not any(isinstance(c, v0.Lookup) for c in children):
619
+ return outputs
620
+ # otherwise, make sure we filter the outer variable through aliasing
621
+ new_children = [*children]
622
+ new_hoists = []
623
+ new_outputs = []
624
+ # add an eq to a new var for the output, hoist the new var, change the output to use the new var
625
+ for output in outputs:
626
+ # shim outputs always only have one alias
627
+ (name, orig_var) = output.aliases.data[0]
628
+ # if the original var is not a Var or Literal, or it's already in the keys, skip (we can't filter keys)
629
+ if not isinstance(orig_var, (v0.Var, v0.Literal)) or (output.keys and orig_var in output.keys): #type: ignore
630
+ new_outputs.append(output)
631
+ continue
632
+ new_var = v0.Var(
633
+ type=orig_var.type,
634
+ name=f"{orig_var.name if isinstance(orig_var, v0.Var) else 'literal'}_hoisted"
635
+ )
636
+ new_output = v0.Output(
637
+ engine=None,
638
+ aliases=frozen((name, new_var)),
639
+ keys=output.keys,
640
+ annotations=output.annotations
641
+ )
642
+ eq = v0.Lookup(
643
+ engine=None,
644
+ relation=v0_builtins.eq,
645
+ args=(new_var, orig_var),
646
+ annotations=frozen()
647
+ )
648
+ new_children.append(eq)
649
+ new_hoists.append(v0.Default(new_var, None))
650
+ new_outputs.append(new_output)
651
+ outputs = new_outputs
652
+ hoisted = tuple(new_hoists)
653
+ children = tuple(new_children)
654
+ # return outputs
655
+
656
+ # return outputs + a logical with the other children
657
+ outputs.append(
658
+ v0.Logical(
659
+ engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
660
+ hoisted=hoisted, # type: ignore
661
+ body=children, # type: ignore
662
+ annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
663
+ ))
664
+ return outputs
665
+
666
+
667
+
668
+
669
+ def translate_sequence(self, s: mm.Sequence, parent, ctx) -> v0.Sequence:
670
+ return v0.Sequence(
671
+ engine=self.translate_reasoner(s.reasoner, s, Context.MODEL),
672
+ hoisted=self.translate_seq(self.hoister.hoisted(s), s, ctx), # type: ignore
673
+ tasks=self.translate_seq(s.tasks, s, ctx), # type: ignore
674
+ annotations=self.translate_frozen(s.annotations, s, ctx) # type: ignore
675
+ )
676
+
677
+ def translate_union(self, u: mm.Union, parent, ctx) -> v0.Union:
678
+ return v0.Union(
679
+ engine=self.translate_reasoner(u.reasoner, u, Context.MODEL),
680
+ hoisted=self.translate_seq(self.hoister.hoisted(u), u, ctx), # type: ignore
681
+ tasks=self.translate_seq(u.tasks, u, ctx), # type: ignore
682
+ annotations=self.translate_frozen(u.annotations, u, ctx) # type: ignore
683
+ )
684
+
685
+ def translate_match(self, m: mm.Match, parent, ctx) -> v0.Match:
686
+ return v0.Match(
687
+ engine=self.translate_reasoner(m.reasoner, m, Context.MODEL),
688
+ hoisted=self.translate_seq(self.hoister.hoisted(m), m, ctx), # type: ignore
689
+ tasks=self.translate_seq(m.tasks, m, ctx), # type: ignore
690
+ annotations=self.translate_frozen(m.annotations, m, ctx) # type: ignore
691
+ )
692
+
693
+ def translate_until(self, u: mm.Until, parent, ctx) -> v0.Until:
694
+ return v0.Until(
695
+ engine=self.translate_reasoner(u.reasoner, u, Context.MODEL),
696
+ hoisted=self.translate_seq(self.hoister.hoisted(u), u, ctx), # type: ignore
697
+ check=self.translate_node(u.check, u, ctx), # type: ignore
698
+ body=self.translate_node(u.body, u, ctx), # type: ignore
699
+ annotations=self.translate_frozen(u.annotations, u, ctx) # type: ignore
700
+ )
701
+
702
+ def translate_wait(self, w: mm.Wait, parent, ctx) -> v0.Wait:
703
+ return v0.Wait(
704
+ engine=self.translate_reasoner(w.reasoner, w, Context.MODEL),
705
+ hoisted=self.translate_seq(self.hoister.hoisted(w), w, ctx), # type: ignore
706
+ check=self.translate_node(w.check, w, ctx), # type: ignore
707
+ annotations=self.translate_frozen(w.annotations, w, ctx) # type: ignore
708
+ )
709
+
710
+ def translate_loop(self, l: mm.Loop, parent, ctx) -> v0.Loop:
711
+ # TODO - loop is incompatible because over has multiple vars, so this is a best
712
+ # attempt (does not matter much as this is not used in practice)
713
+ return v0.Loop(
714
+ engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
715
+ hoisted=self.translate_seq(self.hoister.hoisted(l), l, ctx), # type: ignore
716
+ iter=self.translate_node(l.over[0], l, ctx), # type: ignore
717
+ body=self.translate_node(l.body, l, ctx), # type: ignore
718
+ annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
719
+ )
720
+
721
+ def translate_break(self, b: mm.Break, parent, ctx) -> v0.Break:
722
+ return v0.Break(
723
+ engine=self.translate_reasoner(b.reasoner, b, Context.MODEL),
724
+ check=self.translate_node(b.check, b, ctx), # type: ignore
725
+ annotations=self.translate_frozen(b.annotations, b, ctx) # type: ignore
726
+ )
727
+
728
+ # -----------------------------
729
+ # Constraints
730
+ # -----------------------------
731
+
732
+ def translate_require(self, r: mm.Require, parent, ctx) -> v0.Require|None:
733
+ # check if this is a unique_fields constraint
734
+ assert isinstance(r.domain, mm.Logical)
735
+ assert isinstance(r.check, mm.Logical)
736
+ if not r.domain.body and all(isinstance(c, mm.Lookup) and c.relation is b.constraints.unique_fields for c in r.check.body):
737
+ return
738
+ v0_reqs = []
739
+ # v0 expects a check with both the domain and the relation in it followed by the unique
740
+ # constraint, so we construct a logical with all of that in it
741
+ for c in r.check.body:
742
+ assert isinstance(c, mm.Lookup)
743
+ fields = c.args[0] # tuple of fields
744
+ assert isinstance(fields, tuple) and all(isinstance(f, mm.Field) for f in fields)
745
+ first_field = fields[0]
746
+ if isinstance(first_field.type, mm.Table):
747
+ # skip union types for now
748
+ continue
749
+ assert isinstance(first_field, mm.Field)
750
+ relation = first_field._relation
751
+ domain = self.translate_node(mm.Logical(()), r, ctx)
752
+ all_vars = [mm.Var(type=field.type, name=field.name + "_var") for field in relation.fields]
753
+ check_tasks = [
754
+ mm.Lookup(relation, tuple(all_vars)),
755
+ mm.Lookup(b.constraints.unique, (tuple(all_vars[0:len(fields)]),))
756
+ ]
757
+ check_logical = self.translate_node(mm.Logical(tuple(check_tasks)), r, Context.TASK)
758
+ check = v0.Check(
759
+ check=check_logical, # type: ignore
760
+ error=None,
761
+ annotations=self.translate_frozen(r.annotations, r, ctx) # type: ignore
762
+ )
763
+ v0_reqs.append(v0.Require(
764
+ engine=self.translate_reasoner(r.reasoner, r, Context.MODEL),
765
+ domain=domain, # type: ignore
766
+ checks=(check,), # type: ignore
767
+ annotations=self.translate_frozen(r.annotations, r, ctx) # type: ignore
768
+ ))
769
+ return v0_reqs # type: ignore
770
+
771
+ # check = v0.Check(
772
+ # check=self.translate_node(r.check, r, ctx), # type: ignore
773
+ # error=self.translate_node(r.error, r, ctx) if r.error else None, # type: ignore
774
+ # annotations=self.translate_frozen(r.annotations, r, ctx) # type: ignore
775
+ # )
776
+ # return v0.Require(
777
+ # engine=self.translate_reasoner(r.reasoner, r, Context.MODEL),
778
+ # domain=self.translate_node(r.domain, r, ctx), # type: ignore
779
+ # checks=(check,), # type: ignore
780
+ # annotations=self.translate_frozen(r.annotations, r, ctx) # type: ignore
781
+ # )
782
+ return None
783
+
784
+ # -----------------------------
785
+ # Quantifiers
786
+ # -----------------------------
787
+
788
+ def translate_not(self, n: mm.Not, parent, ctx) -> v0.Not:
789
+ return v0.Not(
790
+ engine=self.translate_reasoner(n.reasoner, n, Context.MODEL),
791
+ task=self.translate_node(n.task, n, ctx), # type: ignore
792
+ annotations=self.translate_frozen(n.annotations, n, ctx) # type: ignore
793
+ )
794
+
795
+ def translate_exists(self, e: mm.Exists, parent, ctx) -> v0.Exists:
796
+ return v0.Exists(
797
+ engine=self.translate_reasoner(e.reasoner, e, Context.MODEL),
798
+ vars=self.translate_seq(e.vars, e, ctx), # type: ignore
799
+ task=self.translate_node(e.task, e, ctx), # type: ignore
800
+ annotations=self.translate_frozen(e.annotations, e, ctx) # type: ignore
801
+ )
802
+
803
+ # -----------------------------
804
+ # Relation Ops
805
+ # -----------------------------
806
+
807
+ def translate_effect(self, e: mm.Effect, parent, ctx) -> v0.Effect:
808
+ if e == mm.Effect.derive:
809
+ return v0.Effect.derive
810
+ elif e == mm.Effect.insert:
811
+ return v0.Effect.insert
812
+ elif e == mm.Effect.delete:
813
+ return v0.Effect.delete
814
+
815
+ def translate_lookup(self, l: mm.Lookup, parent, ctx):
816
+ # Data Node lookups
817
+ if isinstance(l.relation, mm.Data):
818
+ vars = [self.translate_value(l.args[0], l, ctx)]
819
+ for col in l.relation.columns:
820
+ v = v0.Var(
821
+ type=self.translate_node(col.fields[-1].type, col, Context.MODEL), # type: ignore
822
+ name=f"{col.name}"
823
+ )
824
+ vars.append(v)
825
+ assert isinstance(l.args[0], mm.Var)
826
+ self.column_map[l.args[0]][col] = v
827
+ return v0.Data(
828
+ engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
829
+ data=l.relation.data,
830
+ vars=frozen(*vars) # type: ignore
831
+ )
832
+ elif l.args and l.args[0] in self.column_map and l.relation in self.column_map[l.args[0]]: # type: ignore
833
+ assert isinstance(l.args[0], mm.Var)
834
+ var = self.translate_value(l.args[1], l, ctx)
835
+ col_var = self.column_map[l.args[0]][l.relation] # ensure entry exists
836
+ if var != col_var:
837
+ return v0.Lookup(
838
+ engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
839
+ relation=v0_builtins.eq,
840
+ args=(var, col_var), # type: ignore
841
+ annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
842
+ )
843
+ # if this is a data column, we just ignore it as the data node already binds the variables
844
+ elif isinstance(l.args[0].type, mm.Data):
845
+ return None
846
+ # Otherwise we keep the lookup because that's what the LQP stack expect (the lookup gets repeated for
847
+ # each column)
848
+
849
+
850
+ relation, args = self._resolve_reading(l, ctx)
851
+ if relation is None:
852
+ return None
853
+
854
+ # External Table Column lookups
855
+ # we have to prepend the column symbol to the args
856
+ root_type = l.relation.fields[0].type
857
+ if isinstance(root_type, mm.Table):
858
+ self.used_tables.add(root_type)
859
+ is_table = l.relation == root_type
860
+ if is_table or l.relation in root_type.columns:
861
+ sym = "METADATA$KEY" if is_table else l.relation.name
862
+ args = (v0.Literal(type=v0_types.Symbol, value=sym), *args)
863
+
864
+ # Specific rewrites
865
+ rewrite = self.rewrite_lookup(l, parent, ctx)
866
+ if rewrite is None:
867
+ # General translation
868
+ rewrite = v0.Lookup(
869
+ engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
870
+ relation=relation, # type: ignore
871
+ args=args,
872
+ annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
873
+ )
874
+
875
+ return rewrite
876
+
877
+
878
+ def translate_update(self, u: mm.Update, parent, ctx) -> v0.Update|v0.Output|None:
879
+ if isinstance(u.relation, mm.Table):
880
+ # ignore updates to tables for now
881
+ return None
882
+
883
+ if is_output_update(u):
884
+ # this is an output, the last arg is the value for the output column, the other
885
+ # args are part of the key
886
+
887
+ # get the list of key vars created during construction
888
+ keys = list(self.key_map[u.args[0]]) # type: ignore
889
+ # if there are no keys in the key map, this is a constructor of output without
890
+ # keys; we still need to remove the output from the args, so count is 1
891
+ arg_count = len(keys) if keys else 1
892
+ # append any other args used for the key
893
+ for arg in u.args[arg_count:-1]:
894
+ x = self.translate_value(arg, u, ctx)
895
+ keys.append(x) # type: ignore
896
+ if any(anno.relation is b.core["output_value_is_key"] for anno in u.annotations):
897
+ # if the output_value_is_key annotation is present, add the output value to the keys
898
+ keys.append(self.translate_value(u.args[-1], u, ctx)) # type: ignore
899
+
900
+ # there will be a single alias here, the output column
901
+ aliases = ordered_set((u.relation.name, self.translate_value(u.args[-1], u, ctx))).frozen()
902
+
903
+ out = v0.Output(
904
+ engine=self.translate_reasoner(u.reasoner, u, Context.MODEL),
905
+ keys=frozen(*keys), # type: ignore
906
+ aliases=aliases,
907
+ annotations=self.translate_frozen(u.annotations, u, ctx) # type: ignore
908
+ )
909
+ table = u.relation.fields[0].type
910
+ if isinstance(table, mm.Table) and not table.uri.startswith("dataframe://"):
911
+ self.exports.add(out)
912
+ return out
913
+ else:
914
+ relation, args = self._resolve_reading(u, ctx)
915
+
916
+ return v0.Update(
917
+ engine=self.translate_reasoner(u.reasoner, u, Context.MODEL),
918
+ relation=relation, # type: ignore
919
+ args=args,
920
+ effect=self.translate_effect(u.effect, u, ctx),
921
+ annotations=self.translate_frozen(u.annotations, u, ctx) # type: ignore
922
+ )
923
+
924
+ def _resolve_reading(self, task: mm.Lookup|mm.Update, ctx):
925
+ relation = self.translate_node(task.relation, task, ctx)
926
+ args = tuple(self.translate_value(arg, task, ctx) for arg in task.args)
927
+ if isinstance(relation, seq):
928
+ # Updates should always write to the root so that the reading maintenance rules
929
+ # can populate the other readings
930
+ if task.reading_hint is not None and isinstance(task, mm.Lookup):
931
+ relation = relation[task.relation.readings.index(task.reading_hint)]
932
+ args = tuple([args[i] for i in task.reading_hint.field_order])
933
+ else:
934
+ relation = relation[0]
935
+
936
+ return relation, args
937
+
938
+
939
+ def translate_aggregate(self, a: mm.Aggregate, parent, ctx) -> v0.Aggregate:
940
+
941
+ # hoist the return variables (those that are not inputs to the aggregation)
942
+ return_args = []
943
+ for field, arg in zip(a.aggregation.fields, a.args):
944
+ if not field.input:
945
+ return_args.append(arg)
946
+ hoisted=self.translate_seq(return_args, a, ctx)
947
+
948
+ # body must contain the aggregate body plus the aggregate itself
949
+ body = self.translate_node(a.body, a, ctx)
950
+ body = list(body.body if isinstance(body, v0.Logical) else [body])
951
+
952
+ # construct the aggregate node
953
+ engine = self.translate_reasoner(a.reasoner, a, Context.MODEL)
954
+ aggregation = self.translate_node(a.aggregation, a, ctx)
955
+ projection = self.translate_seq(a.projection, a, ctx)
956
+ group = self.translate_seq(a.group, a, ctx)
957
+ args = tuple(self.translate_value(arg, a, ctx) for arg in a.args)
958
+ annotations = self.translate_frozen(a.annotations, a, ctx)
959
+
960
+ v0_agg = None
961
+ if a.aggregation == b.aggregates.rank:
962
+ assert isinstance(args[0], tuple)
963
+ assert isinstance(args[1], tuple)
964
+ v0_agg = v0.Rank(engine, projection, group, args[0], tuple(l.value for l in args[1]), args[-1], 0, annotations,) # type: ignore
965
+ elif a.aggregation == b.aggregates.limit:
966
+ assert isinstance(args[0], v0.Literal)
967
+ assert isinstance(args[1], tuple)
968
+ assert isinstance(args[2], tuple)
969
+ result = v0.Var(type=v0_types.Int64, name="limit_result")
970
+ v0_agg = v0.Rank(engine, projection, group, args[1], tuple(l.value for l in args[2]), result, args[0].value, annotations,) # type: ignore
971
+ else:
972
+ v0_agg = v0.Aggregate(engine, aggregation, projection, group, args, annotations) # type: ignore
973
+
974
+ body.append(v0_agg)
975
+ return v0.Logical(
976
+ engine=None,
977
+ hoisted=hoisted, # type: ignore
978
+ body=tuple(body) # type: ignore
979
+ )
980
+
981
+ def translate_construct(self, c: mm.Construct, parent, ctx) -> v0.Construct|None:
982
+ if isinstance(c.id_var.type, mm.Table):
983
+ # we are constructing the key for an output. If there are no values, there is no
984
+ # key in v0, so we can just ignore this
985
+ if not c.values:
986
+ self.key_map[c.id_var] = []
987
+ return None
988
+ # now create a new v0 var to represent the hashed key, record that this key is
989
+ # to be used by updates, and generate the constructor
990
+ v = v0.Var(type=v0_types.Hash, name=c.id_var.name)
991
+ self.key_map[c.id_var] = [v]
992
+ values = [v0_types.Hash]
993
+ values.extend(self.translate_seq(c.values, c, ctx)) # type: ignore
994
+ return v0.Construct(
995
+ engine=self.translate_reasoner(c.reasoner, c, Context.MODEL),
996
+ values=tuple(values), # type: ignore
997
+ id_var=v,
998
+ annotations=self.translate_frozen(c.annotations, c, ctx) # type: ignore
999
+ )
1000
+ return v0.Construct(
1001
+ engine=self.translate_reasoner(c.reasoner, c, Context.MODEL),
1002
+ values=self.translate_seq(c.values, c, ctx), # type: ignore
1003
+ id_var=self.translate_node(c.id_var, c, ctx), # type: ignore
1004
+ annotations=self.translate_frozen(c.annotations, c, ctx) # type: ignore
1005
+ )
1006
+
1007
+
1008
+ def translate_data(self, d: mm.Data, parent, ctx):
1009
+ if isinstance(parent, mm.Field) or isinstance(parent, mm.Var):
1010
+ return v0_types.Int128
1011
+
1012
+ # -----------------------------------------------------------------------------
1013
+ # Model
1014
+ # -----------------------------------------------------------------------------
1015
+
1016
+ def translate_model(self, source_model: mm.Model, parent=None, ctx=None) -> v0.Model:
1017
+ try:
1018
+ # first analyze the model to compute variables that need to be hoisted
1019
+ self.hoister.analyze(source_model)
1020
+
1021
+ self.relations_by_name = defaultdict(list)
1022
+ for r in source_model.relations:
1023
+ self.relations_by_name[r.name].append(r)
1024
+
1025
+ # translate root first as it may create relations from types (e.g. concept populations)
1026
+ root = self.translate_node(source_model.root, source_model, Context.TASK)
1027
+
1028
+ # translate all declared relations
1029
+ relations:OrderedSet[v0.Relation] = ordered_set(*self.translate_seq(source_model.relations, source_model, Context.MODEL)) # type: ignore
1030
+ # add relations created during task translation
1031
+ relations.update(filter_by_type(self.task_map.values(), v0.Relation)) # type: ignore
1032
+ # v0 needs all overloads also added to the model
1033
+ for r in list(relations):
1034
+ relations.update(r.overloads) # type: ignore
1035
+
1036
+ # if there are reading maintenance rules, add them as well
1037
+ if self.maintenance_rules:
1038
+ root = v0.Logical(
1039
+ engine=None,
1040
+ hoisted=(),
1041
+ body=(
1042
+ root, # type: ignore
1043
+ *self.maintenance_rules
1044
+ ),
1045
+ annotations=frozen()
1046
+ )
1047
+ engines=self.translate_frozen(source_model.reasoners, source_model, Context.MODEL) # type: ignore
1048
+ types=self.translate_frozen(source_model.types, source_model, Context.MODEL) # type: ignore
1049
+
1050
+ return v0.Model(
1051
+ engines=engines, # type: ignore
1052
+ relations=relations.frozen(), # type: ignore
1053
+ types=types, # type: ignore
1054
+ root=root # type: ignore
1055
+ )
1056
+ finally:
1057
+ self.hoister.clear()
1058
+
1059
+ # -----------------------------------------------------------------------------
1060
+ # Translate query
1061
+ # -----------------------------------------------------------------------------
1062
+
1063
+ def translate_query(self, source_query: mm.Task) -> v0.Logical:
1064
+ try:
1065
+ # first analyze the model to compute variables that need to be hoisted
1066
+ self.hoister.analyze_task(source_query)
1067
+
1068
+ # translate the query logical
1069
+ return self.translate_node(source_query, source_query, Context.TASK) # type: ignore
1070
+ finally:
1071
+ self.hoister.clear()
1072
+
1073
+ # -----------------------------------------------------------------------------
1074
+ # Library-specific rewrites
1075
+ # -----------------------------------------------------------------------------
1076
+
1077
+ def adjust_index(self, l: mm.Lookup, indices: list[int], ctx, args=None, no_outputs=False):
1078
+ """ Rewrite the lookup such that the args at `indices` are adjusted to convert from
1079
+ 0-based indexing (as in the mm) to 1-based indexing (as in v0's backend).
1080
+
1081
+ If the field at the given index is input, we increment the arg by 1 before passing
1082
+ it to the lookup. If the field is output, we create a tmp var to hold the result
1083
+ of the lookup, and then create a subsequent task to decrement the tmp var by 1.
1084
+
1085
+ `args` can be used to provide a different set of args than l.args, in case they need
1086
+ reordering (e.g. strings.split).
1087
+ """
1088
+ if args is None:
1089
+ args = l.args
1090
+ # vars to hold the result from the v0 lookup
1091
+ tmps = {}
1092
+ for i in indices:
1093
+ index_type = l.relation.fields[i].type
1094
+ tmps[i] = mm.Var(type=index_type, name=f"tmp")
1095
+ # insert tmp at index
1096
+ replaced_args = []
1097
+ for i, arg in enumerate(args):
1098
+ if i in indices:
1099
+ replaced_args.append(tmps[i])
1100
+ else:
1101
+ replaced_args.append(arg)
1102
+ # translate the lookup
1103
+ lookup = v0.Lookup(
1104
+ engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
1105
+ relation=self.translate_node(l.relation), # type: ignore
1106
+ args=tuple(self.translate_value(arg, l, ctx) for arg in replaced_args),
1107
+ annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
1108
+ )
1109
+ # subtract 1 from the index to convert from 1-based to 0-based
1110
+ tasks = []
1111
+ for index in indices:
1112
+ arg = args[index]
1113
+ if isinstance(arg, mm.Literal):
1114
+ if l.relation.fields[index].input:
1115
+ new = mm.Literal(arg.type, arg.value + 1) # type: ignore
1116
+ else:
1117
+ new = mm.Literal(arg.type, arg.value + 1) # type: ignore
1118
+ tasks.append(v0.Lookup(
1119
+ engine=None,
1120
+ relation=v0_builtins.eq, # type: ignore
1121
+ args=(
1122
+ self.translate_value(tmps[index], lookup, ctx),
1123
+ self.translate_value(new, lookup, ctx),
1124
+ )
1125
+ ))
1126
+ elif l.relation.fields[index].input:
1127
+ tasks.append(v0.Lookup(
1128
+ engine=None,
1129
+ relation=v0_builtins.plus, # type: ignore
1130
+ args=(
1131
+ self.translate_value(args[index], lookup, ctx),
1132
+ v0.Literal(v0_types.Int128, 1),
1133
+ self.translate_value(tmps[index], lookup, ctx),
1134
+ ),
1135
+ )
1136
+ )
1137
+ else:
1138
+ tasks.append(v0.Lookup(
1139
+ engine=None,
1140
+ relation=v0_builtins.minus, # type: ignore
1141
+ args=(
1142
+ self.translate_value(tmps[index], lookup, ctx),
1143
+ v0.Literal(v0_types.Int128, 1),
1144
+ self.translate_value(args[index], lookup, ctx),
1145
+ ),
1146
+ )
1147
+ )
1148
+ # do casts
1149
+ tasks.extend(self.cast(lookup, ctx, no_outputs=no_outputs))
1150
+
1151
+ return tasks
1152
+
1153
+ def decrement(self, l: mm.Lookup, index: int, ctx):
1154
+ """ Rewrite the lookup such that the arg at `index` is decremented by 1 before the
1155
+ lookup. """
1156
+ x = l.args[index]
1157
+ if isinstance(x, mm.Literal):
1158
+ # if the arg is a literal, just decrement the literal directly
1159
+ new_literal = mm.Literal(type=x.type, value=x.value - 1) # type: ignore
1160
+ return v0.Lookup(
1161
+ engine=None,
1162
+ relation=self.translate_node(l.relation), # type: ignore
1163
+ args=tuple(self.translate_value(arg, l, ctx) if i != index else self.translate_value(new_literal, l, ctx) for i, arg in enumerate(l.args)),
1164
+ annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
1165
+ )
1166
+
1167
+ # arg is not a literal, so we need to create a tmp var to store the decremented value
1168
+ tmp = self.translate_value(mm.Var(type=b.core.Number, name="tmp"), l, ctx)
1169
+ # lookup(..., tmp, ...)
1170
+ new = v0.Lookup(
1171
+ engine=None,
1172
+ relation=self.translate_node(l.relation), # type: ignore
1173
+ args=tuple(self.translate_value(arg, l, ctx) if i != index else tmp for i, arg in enumerate(l.args)),
1174
+ annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
1175
+ )
1176
+ casted = self.cast(new, ctx)
1177
+ return (
1178
+ # tmp = l.args[index] - 1
1179
+ v0.Lookup(
1180
+ engine=None,
1181
+ relation=v0_builtins.minus, # type: ignore
1182
+ args=(
1183
+ self.translate_value(l.args[index], l, ctx),
1184
+ v0.Literal(v0_types.Int128, 1),
1185
+ tmp,
1186
+ ),
1187
+ ),
1188
+ *casted
1189
+ )
1190
+
1191
+ def cast(self, l: v0.Lookup, ctx, no_outputs=False):
1192
+ # note that everything here is in v0
1193
+ inputs = []
1194
+ outputs = []
1195
+ args = []
1196
+ fields = l.relation.fields
1197
+ # if there are overloads, we need to cast based on the most compatible overload
1198
+ if l.relation.overloads:
1199
+ inf = float("inf")
1200
+ min_cost = inf
1201
+ for overload in l.relation.overloads:
1202
+ total = 0
1203
+ for arg, field in zip(l.args, overload.fields):
1204
+ if v0_typer.to_type(arg) != field.type:
1205
+ total += 1
1206
+ if total < min_cost:
1207
+ min_cost = total
1208
+ fields = overload.fields
1209
+
1210
+ for arg, field in zip(l.args, fields):
1211
+ target_type = field.type
1212
+ if target_type is None or not isinstance(arg, (v0.Var, v0.Literal)) or arg.type == target_type:
1213
+ args.append(arg)
1214
+ continue
1215
+ if field.input:
1216
+ cast_var = v0.Var(type=target_type, name="cast_var")
1217
+ args.append(cast_var)
1218
+ inputs.append(v0.Lookup(
1219
+ engine=None,
1220
+ relation=v0_builtins.cast, # type: ignore
1221
+ args=(target_type, arg, cast_var),
1222
+ ))
1223
+ elif not no_outputs:
1224
+ cast_var = v0.Var(type=target_type, name="cast_var")
1225
+ args.append(cast_var)
1226
+ outputs.append(v0.Lookup(
1227
+ engine=None,
1228
+ relation=v0_builtins.cast, # type: ignore
1229
+ args=(arg.type, cast_var, arg),
1230
+ ))
1231
+ else:
1232
+ # This is ridiculous, but there are cases where we need to force the type
1233
+ # of the var, but not through an actual cast operation. E.g. due to the way
1234
+ # the LQP stack handles dates.
1235
+ object.__setattr__(arg, 'type', target_type)
1236
+ args.append(arg)
1237
+
1238
+ lookup = v0.Lookup(
1239
+ engine=l.engine,
1240
+ relation=l.relation,
1241
+ args=tuple(args),
1242
+ annotations=l.annotations
1243
+ )
1244
+ if no_outputs:
1245
+ outputs = []
1246
+ return [*inputs, lookup, *outputs]
1247
+
1248
+ def rewrite_lookup(self, l: mm.Lookup, parent, ctx):
1249
+ """ Special cases for v1 builtins that either have some different shape in v0 or
1250
+ do not exist as a primitive in the engine, so we want to compose the result so that
1251
+ LQP works. Return None if no rewrite is needed.
1252
+
1253
+ Note that this type of adjustment will need to be made by emitters anyways, so we
1254
+ will want to have a good API for them. But in that case, they should do
1255
+ transformations still in the mm, whereas this is doing it during translation to v0.
1256
+ """
1257
+
1258
+ # -----------------------------------------------------------------------------
1259
+ # Common
1260
+ # -----------------------------------------------------------------------------
1261
+ if l.relation == b.common.range:
1262
+ # python/PyRel range has inclusive start but exclusive stop, whereas LQP/Rel has
1263
+ # inclusive stop, so we have to decrement the stop index by 1
1264
+ # tmp, lookup = self.decrement(l, 1, ctx)
1265
+ # return [tmp] + self.cast(lookup, [v0_types.Int64, v0_types.Int64, v0_types.Int64, v0_types.Int64], ctx)
1266
+ return self.decrement(l, 1, ctx)
1267
+
1268
+ elif l.relation == b.core.cast:
1269
+ return v0.Lookup(
1270
+ engine=self.translate_reasoner(l.reasoner, l, Context.TASK),
1271
+ relation=v0_builtins.builtin_relations_by_name["cast"], # type: ignore
1272
+ args=(
1273
+ self.translate_value(l.args[0], l, Context.MODEL),
1274
+ self.translate_value(l.args[1], l, Context.TASK),
1275
+ self.translate_value(l.args[2], l, Context.TASK)
1276
+ ),
1277
+ annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
1278
+ )
1279
+
1280
+ # -----------------------------------------------------------------------------
1281
+ # Strings
1282
+ # -----------------------------------------------------------------------------
1283
+
1284
+ elif l.relation == b.strings.len:
1285
+ lookup = v0.Lookup(
1286
+ engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
1287
+ relation=v0_builtins.builtin_relations_by_name["num_chars"], # type: ignore
1288
+ args=(
1289
+ self.translate_value(l.args[0], l, ctx),
1290
+ self.translate_value(l.args[1], l, ctx),
1291
+ ),
1292
+ annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
1293
+ )
1294
+ return self.cast(lookup, ctx)
1295
+
1296
+ elif l.relation == b.strings.split:
1297
+ # swap first two args because that's how rel and v0 expect them
1298
+ args = l.args[1], l.args[0], l.args[2], l.args[3]
1299
+ return self.adjust_index(l, [2], ctx, args=args)
1300
+
1301
+ elif l.relation == b.strings.substring:
1302
+ return self.adjust_index(l, [1], ctx)
1303
+
1304
+ # -----------------------------------------------------------------------------
1305
+ # RE
1306
+ # -----------------------------------------------------------------------------
1307
+ elif l.relation == b.re.regex_match_all:
1308
+ return self.adjust_index(l, [2], ctx)
1309
+
1310
+ # -----------------------------------------------------------------------------
1311
+ # Math
1312
+ # -----------------------------------------------------------------------------
1313
+ elif l.relation == b.math.degrees:
1314
+ # degrees(radians, x) = /(radians, (pi/180.0), x)
1315
+ return v0.Lookup(
1316
+ engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
1317
+ relation=v0_builtins.builtin_relations_by_name["/"], # type: ignore
1318
+ args=(
1319
+ self.translate_value(l.args[0], l, ctx),
1320
+ v0.Literal(v0_types.Float, pi / 180.0),
1321
+ self.translate_value(l.args[1], l, ctx)
1322
+ ),
1323
+ annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
1324
+ )
1325
+ elif l.relation == b.math.radians:
1326
+ # radians(degrees, x) = /(degrees, (180.0/pi), x)
1327
+ return v0.Lookup(
1328
+ engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
1329
+ relation=v0_builtins.builtin_relations_by_name["/"], # type: ignore
1330
+ args=(
1331
+ self.translate_value(l.args[0], l, ctx),
1332
+ v0.Literal(v0_types.Float, 180.0 / pi),
1333
+ self.translate_value(l.args[1], l, ctx)
1334
+ ),
1335
+ annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
1336
+ )
1337
+
1338
+ # -----------------------------------------------------------------------------
1339
+ # Datetime
1340
+ # -----------------------------------------------------------------------------
1341
+ #
1342
+ # elif l.relation == b.datetime.date_range:
1343
+ # return self.rewrite_date_range(l, parent, ctx)
1344
+ # elif l.relation == b.datetime.datetime_range:
1345
+ # pass
1346
+
1347
+ elif l.relation == b.datetime.date_add:
1348
+ return v0.Lookup(
1349
+ engine=self.translate_reasoner(l.reasoner, l, Context.MODEL),
1350
+ relation=self.translate_relation(l.relation, l, ctx), # type: ignore
1351
+ args=self.translate_seq(l.args, l, ctx), # type: ignore
1352
+ annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
1353
+ )
1354
+
1355
+ if b.datetime[l.relation.name] is l.relation:
1356
+ return self.adjust_index(l, [], ctx, no_outputs=True)
1357
+
1358
+ v0_rel = self.translate_node(l.relation, l, ctx)
1359
+ if isinstance(v0_rel, v0.Relation) and any(f.type == v0_types.Int64 for f in v0_rel.fields):
1360
+ return self.adjust_index(l, [], ctx)
1361
+
1362
+ return None
1363
+
1364
+
1365
+ # TODO - Currently implemented in the std.datetime itself.
1366
+ # def rewrite_date_range(self, l: mm.Lookup, parent, ctx: Context):
1367
+ # start, end, freq, date = l.args
1368
+ # result = []
1369
+
1370
+ # range_end = num_days = mm.Var(type=b.core.Number, name="num_days")
1371
+ # result.append(mm.Lookup(b.datetime.dates_period_days, (start, end, num_days)))
1372
+
1373
+ # assert isinstance(freq, mm.Literal) and isinstance(freq.value, str)
1374
+ # if freq.value in ["W", "M", "Y"]:
1375
+ # range_end = mm.Var(type=b.core.Number, name="range_end")
1376
+ # x = mm.Var(type=b.core.Number, name="x")
1377
+ # result.append(mm.Lookup(b.core.mul, (num_days, mm.Literal(b.core.Float, _days[freq.value]), x)))
1378
+ # result.append(mm.Lookup(b.math.ceil, (x, range_end)))
1379
+
1380
+ # # date_range is inclusive. add 1 since std.range is exclusive
1381
+ # tmp = mm.Var(type=b.core.Number, name="tmp")
1382
+ # result.append(mm.Lookup(b.core["+"], (range_end, mm.Literal(b.core.Number, 1), tmp)))
1383
+ # ix = mm.Var(type=b.core.Number, name="ix")
1384
+ # result.append(mm.Lookup(b.common.range, (mm.Literal(b.core.Number, 0), tmp, mm.Literal(b.core.Number, 1), ix)))
1385
+
1386
+ # tmp2 = mm.Var(type=b.core.Number, name="tmp2")
1387
+ # result.append(mm.Lookup(_periods[freq.value], (ix, tmp2)))
1388
+ # result.append(mm.Lookup(b.datetime.date_add, (start, tmp2, date)))
1389
+
1390
+ # result.append(mm.Lookup(b.core[">="], (end, date)))
1391
+
1392
+ # return self.translate_node(mm.Logical(
1393
+ # body=tuple(result)
1394
+ # ))