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