relationalai 0.12.13__py3-none-any.whl → 0.13.0.dev0__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 (825) hide show
  1. relationalai/__init__.py +1 -209
  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/semantics/__init__.py +146 -22
  16. relationalai/semantics/backends/lqp/annotations.py +11 -0
  17. relationalai/semantics/backends/sql/sql_compiler.py +327 -0
  18. relationalai/semantics/frontend/base.py +1707 -0
  19. relationalai/semantics/frontend/core.py +179 -0
  20. relationalai/semantics/frontend/front_compiler.py +1313 -0
  21. relationalai/semantics/frontend/pprint.py +408 -0
  22. relationalai/semantics/metamodel/__init__.py +6 -40
  23. relationalai/semantics/metamodel/builtins.py +205 -769
  24. relationalai/semantics/metamodel/metamodel.py +437 -0
  25. relationalai/semantics/metamodel/metamodel_analyzer.py +519 -0
  26. relationalai/semantics/metamodel/pprint.py +412 -0
  27. relationalai/semantics/metamodel/rewriter.py +266 -0
  28. relationalai/semantics/metamodel/typer.py +1378 -0
  29. relationalai/semantics/std/__init__.py +60 -40
  30. relationalai/semantics/std/aggregates.py +149 -0
  31. relationalai/semantics/std/common.py +44 -0
  32. relationalai/semantics/std/constraints.py +37 -43
  33. relationalai/semantics/std/datetime.py +246 -135
  34. relationalai/semantics/std/decimals.py +45 -52
  35. relationalai/semantics/std/floats.py +13 -5
  36. relationalai/semantics/std/integers.py +26 -11
  37. relationalai/semantics/std/math.py +183 -112
  38. relationalai/semantics/std/numbers.py +86 -0
  39. relationalai/semantics/std/re.py +80 -62
  40. relationalai/semantics/std/strings.py +117 -60
  41. relationalai/shims/executor.py +147 -0
  42. relationalai/shims/helpers.py +126 -0
  43. relationalai/shims/hoister.py +221 -0
  44. relationalai/shims/mm2v0.py +1290 -0
  45. relationalai/tools/cli/__init__.py +6 -0
  46. relationalai/tools/cli/cli.py +90 -0
  47. relationalai/tools/cli/components/__init__.py +5 -0
  48. relationalai/tools/cli/components/progress_reader.py +1524 -0
  49. relationalai/tools/cli/components/utils.py +58 -0
  50. relationalai/tools/cli/config_template.py +45 -0
  51. relationalai/tools/cli/dev.py +19 -0
  52. relationalai/tools/debugger.py +289 -183
  53. relationalai/tools/typer_debugger.py +93 -0
  54. relationalai/util/dataclasses.py +43 -0
  55. relationalai/util/docutils.py +40 -0
  56. relationalai/util/error.py +199 -0
  57. relationalai/util/format.py +48 -106
  58. relationalai/util/naming.py +145 -0
  59. relationalai/util/python.py +35 -0
  60. relationalai/util/runtime.py +156 -0
  61. relationalai/util/schema.py +197 -0
  62. relationalai/util/source.py +185 -0
  63. relationalai/util/structures.py +163 -0
  64. relationalai/util/tracing.py +261 -0
  65. relationalai-0.13.0.dev0.dist-info/METADATA +46 -0
  66. relationalai-0.13.0.dev0.dist-info/RECORD +488 -0
  67. relationalai-0.13.0.dev0.dist-info/WHEEL +5 -0
  68. relationalai-0.13.0.dev0.dist-info/entry_points.txt +3 -0
  69. relationalai-0.13.0.dev0.dist-info/top_level.txt +2 -0
  70. v0/relationalai/__init__.py +216 -0
  71. v0/relationalai/clients/azure.py +477 -0
  72. v0/relationalai/clients/client.py +912 -0
  73. v0/relationalai/clients/config.py +673 -0
  74. v0/relationalai/clients/direct_access_client.py +118 -0
  75. v0/relationalai/clients/hash_util.py +31 -0
  76. v0/relationalai/clients/local.py +571 -0
  77. v0/relationalai/clients/profile_polling.py +73 -0
  78. v0/relationalai/clients/result_helpers.py +420 -0
  79. v0/relationalai/clients/snowflake.py +3869 -0
  80. v0/relationalai/clients/types.py +113 -0
  81. v0/relationalai/clients/use_index_poller.py +980 -0
  82. v0/relationalai/clients/util.py +356 -0
  83. v0/relationalai/debugging.py +389 -0
  84. v0/relationalai/dsl.py +1749 -0
  85. v0/relationalai/early_access/builder/__init__.py +30 -0
  86. v0/relationalai/early_access/builder/builder/__init__.py +35 -0
  87. v0/relationalai/early_access/builder/snowflake/__init__.py +12 -0
  88. v0/relationalai/early_access/builder/std/__init__.py +25 -0
  89. v0/relationalai/early_access/builder/std/decimals/__init__.py +12 -0
  90. v0/relationalai/early_access/builder/std/integers/__init__.py +12 -0
  91. v0/relationalai/early_access/builder/std/math/__init__.py +12 -0
  92. v0/relationalai/early_access/builder/std/strings/__init__.py +14 -0
  93. v0/relationalai/early_access/devtools/__init__.py +12 -0
  94. v0/relationalai/early_access/devtools/benchmark_lqp/__init__.py +12 -0
  95. v0/relationalai/early_access/devtools/extract_lqp/__init__.py +12 -0
  96. v0/relationalai/early_access/dsl/adapters/orm/adapter_qb.py +427 -0
  97. v0/relationalai/early_access/dsl/adapters/orm/parser.py +636 -0
  98. v0/relationalai/early_access/dsl/adapters/owl/adapter.py +176 -0
  99. v0/relationalai/early_access/dsl/adapters/owl/parser.py +160 -0
  100. v0/relationalai/early_access/dsl/bindings/common.py +402 -0
  101. v0/relationalai/early_access/dsl/bindings/csv.py +170 -0
  102. v0/relationalai/early_access/dsl/bindings/legacy/binding_models.py +143 -0
  103. v0/relationalai/early_access/dsl/bindings/snowflake.py +64 -0
  104. v0/relationalai/early_access/dsl/codegen/binder.py +411 -0
  105. v0/relationalai/early_access/dsl/codegen/common.py +79 -0
  106. v0/relationalai/early_access/dsl/codegen/helpers.py +23 -0
  107. v0/relationalai/early_access/dsl/codegen/relations.py +700 -0
  108. v0/relationalai/early_access/dsl/codegen/weaver.py +417 -0
  109. v0/relationalai/early_access/dsl/core/builders/__init__.py +47 -0
  110. v0/relationalai/early_access/dsl/core/builders/logic.py +19 -0
  111. v0/relationalai/early_access/dsl/core/builders/scalar_constraint.py +11 -0
  112. v0/relationalai/early_access/dsl/core/constraints/predicate/atomic.py +455 -0
  113. v0/relationalai/early_access/dsl/core/constraints/predicate/universal.py +73 -0
  114. v0/relationalai/early_access/dsl/core/constraints/scalar.py +310 -0
  115. v0/relationalai/early_access/dsl/core/context.py +13 -0
  116. v0/relationalai/early_access/dsl/core/cset.py +132 -0
  117. v0/relationalai/early_access/dsl/core/exprs/__init__.py +116 -0
  118. v0/relationalai/early_access/dsl/core/exprs/relational.py +18 -0
  119. v0/relationalai/early_access/dsl/core/exprs/scalar.py +412 -0
  120. v0/relationalai/early_access/dsl/core/instances.py +44 -0
  121. v0/relationalai/early_access/dsl/core/logic/__init__.py +193 -0
  122. v0/relationalai/early_access/dsl/core/logic/aggregation.py +98 -0
  123. v0/relationalai/early_access/dsl/core/logic/exists.py +223 -0
  124. v0/relationalai/early_access/dsl/core/logic/helper.py +163 -0
  125. v0/relationalai/early_access/dsl/core/namespaces.py +32 -0
  126. v0/relationalai/early_access/dsl/core/relations.py +276 -0
  127. v0/relationalai/early_access/dsl/core/rules.py +112 -0
  128. v0/relationalai/early_access/dsl/core/std/__init__.py +45 -0
  129. v0/relationalai/early_access/dsl/core/temporal/recall.py +6 -0
  130. v0/relationalai/early_access/dsl/core/types/__init__.py +270 -0
  131. v0/relationalai/early_access/dsl/core/types/concepts.py +128 -0
  132. v0/relationalai/early_access/dsl/core/types/constrained/__init__.py +267 -0
  133. v0/relationalai/early_access/dsl/core/types/constrained/nominal.py +143 -0
  134. v0/relationalai/early_access/dsl/core/types/constrained/subtype.py +124 -0
  135. v0/relationalai/early_access/dsl/core/types/standard.py +92 -0
  136. v0/relationalai/early_access/dsl/core/types/unconstrained.py +50 -0
  137. v0/relationalai/early_access/dsl/core/types/variables.py +203 -0
  138. v0/relationalai/early_access/dsl/ir/compiler.py +318 -0
  139. v0/relationalai/early_access/dsl/ir/executor.py +260 -0
  140. v0/relationalai/early_access/dsl/ontologies/constraints.py +88 -0
  141. v0/relationalai/early_access/dsl/ontologies/export.py +30 -0
  142. v0/relationalai/early_access/dsl/ontologies/models.py +453 -0
  143. v0/relationalai/early_access/dsl/ontologies/python_printer.py +303 -0
  144. v0/relationalai/early_access/dsl/ontologies/readings.py +60 -0
  145. v0/relationalai/early_access/dsl/ontologies/relationships.py +322 -0
  146. v0/relationalai/early_access/dsl/ontologies/roles.py +87 -0
  147. v0/relationalai/early_access/dsl/ontologies/subtyping.py +55 -0
  148. v0/relationalai/early_access/dsl/orm/constraints.py +438 -0
  149. v0/relationalai/early_access/dsl/orm/measures/dimensions.py +200 -0
  150. v0/relationalai/early_access/dsl/orm/measures/initializer.py +16 -0
  151. v0/relationalai/early_access/dsl/orm/measures/measure_rules.py +275 -0
  152. v0/relationalai/early_access/dsl/orm/measures/measures.py +299 -0
  153. v0/relationalai/early_access/dsl/orm/measures/role_exprs.py +268 -0
  154. v0/relationalai/early_access/dsl/orm/models.py +256 -0
  155. v0/relationalai/early_access/dsl/orm/object_oriented_printer.py +344 -0
  156. v0/relationalai/early_access/dsl/orm/printer.py +469 -0
  157. v0/relationalai/early_access/dsl/orm/reasoners.py +480 -0
  158. v0/relationalai/early_access/dsl/orm/relations.py +19 -0
  159. v0/relationalai/early_access/dsl/orm/relationships.py +251 -0
  160. v0/relationalai/early_access/dsl/orm/types.py +42 -0
  161. v0/relationalai/early_access/dsl/orm/utils.py +79 -0
  162. v0/relationalai/early_access/dsl/orm/verb.py +204 -0
  163. v0/relationalai/early_access/dsl/physical_metadata/tables.py +133 -0
  164. v0/relationalai/early_access/dsl/relations.py +170 -0
  165. v0/relationalai/early_access/dsl/rulesets.py +69 -0
  166. v0/relationalai/early_access/dsl/schemas/__init__.py +450 -0
  167. v0/relationalai/early_access/dsl/schemas/builder.py +48 -0
  168. v0/relationalai/early_access/dsl/schemas/comp_names.py +51 -0
  169. v0/relationalai/early_access/dsl/schemas/components.py +203 -0
  170. v0/relationalai/early_access/dsl/schemas/contexts.py +156 -0
  171. v0/relationalai/early_access/dsl/schemas/exprs.py +89 -0
  172. v0/relationalai/early_access/dsl/schemas/fragments.py +464 -0
  173. v0/relationalai/early_access/dsl/serialization.py +79 -0
  174. v0/relationalai/early_access/dsl/serialize/exporter.py +163 -0
  175. v0/relationalai/early_access/dsl/snow/api.py +104 -0
  176. v0/relationalai/early_access/dsl/snow/common.py +76 -0
  177. v0/relationalai/early_access/dsl/state_mgmt/__init__.py +129 -0
  178. v0/relationalai/early_access/dsl/state_mgmt/state_charts.py +125 -0
  179. v0/relationalai/early_access/dsl/state_mgmt/transitions.py +130 -0
  180. v0/relationalai/early_access/dsl/types/__init__.py +40 -0
  181. v0/relationalai/early_access/dsl/types/concepts.py +12 -0
  182. v0/relationalai/early_access/dsl/types/entities.py +135 -0
  183. v0/relationalai/early_access/dsl/types/values.py +17 -0
  184. v0/relationalai/early_access/dsl/utils.py +102 -0
  185. v0/relationalai/early_access/graphs/__init__.py +13 -0
  186. v0/relationalai/early_access/lqp/__init__.py +12 -0
  187. v0/relationalai/early_access/lqp/compiler/__init__.py +12 -0
  188. v0/relationalai/early_access/lqp/constructors/__init__.py +18 -0
  189. v0/relationalai/early_access/lqp/executor/__init__.py +12 -0
  190. v0/relationalai/early_access/lqp/ir/__init__.py +12 -0
  191. v0/relationalai/early_access/lqp/passes/__init__.py +12 -0
  192. v0/relationalai/early_access/lqp/pragmas/__init__.py +12 -0
  193. v0/relationalai/early_access/lqp/primitives/__init__.py +12 -0
  194. v0/relationalai/early_access/lqp/types/__init__.py +12 -0
  195. v0/relationalai/early_access/lqp/utils/__init__.py +12 -0
  196. v0/relationalai/early_access/lqp/validators/__init__.py +12 -0
  197. v0/relationalai/early_access/metamodel/__init__.py +58 -0
  198. v0/relationalai/early_access/metamodel/builtins/__init__.py +12 -0
  199. v0/relationalai/early_access/metamodel/compiler/__init__.py +12 -0
  200. v0/relationalai/early_access/metamodel/dependency/__init__.py +12 -0
  201. v0/relationalai/early_access/metamodel/factory/__init__.py +17 -0
  202. v0/relationalai/early_access/metamodel/helpers/__init__.py +12 -0
  203. v0/relationalai/early_access/metamodel/ir/__init__.py +14 -0
  204. v0/relationalai/early_access/metamodel/rewrite/__init__.py +7 -0
  205. v0/relationalai/early_access/metamodel/typer/__init__.py +3 -0
  206. v0/relationalai/early_access/metamodel/typer/typer/__init__.py +12 -0
  207. v0/relationalai/early_access/metamodel/types/__init__.py +15 -0
  208. v0/relationalai/early_access/metamodel/util/__init__.py +15 -0
  209. v0/relationalai/early_access/metamodel/visitor/__init__.py +12 -0
  210. v0/relationalai/early_access/rel/__init__.py +12 -0
  211. v0/relationalai/early_access/rel/executor/__init__.py +12 -0
  212. v0/relationalai/early_access/rel/rel_utils/__init__.py +12 -0
  213. v0/relationalai/early_access/rel/rewrite/__init__.py +7 -0
  214. v0/relationalai/early_access/solvers/__init__.py +19 -0
  215. v0/relationalai/early_access/sql/__init__.py +11 -0
  216. v0/relationalai/early_access/sql/executor/__init__.py +3 -0
  217. v0/relationalai/early_access/sql/rewrite/__init__.py +3 -0
  218. v0/relationalai/early_access/tests/logging/__init__.py +12 -0
  219. v0/relationalai/early_access/tests/test_snapshot_base/__init__.py +12 -0
  220. v0/relationalai/early_access/tests/utils/__init__.py +12 -0
  221. v0/relationalai/environments/__init__.py +35 -0
  222. v0/relationalai/environments/base.py +381 -0
  223. v0/relationalai/environments/colab.py +14 -0
  224. v0/relationalai/environments/generic.py +71 -0
  225. v0/relationalai/environments/ipython.py +68 -0
  226. v0/relationalai/environments/jupyter.py +9 -0
  227. v0/relationalai/environments/snowbook.py +169 -0
  228. v0/relationalai/errors.py +2455 -0
  229. v0/relationalai/experimental/SF.py +38 -0
  230. v0/relationalai/experimental/inspect.py +47 -0
  231. v0/relationalai/experimental/pathfinder/__init__.py +158 -0
  232. v0/relationalai/experimental/pathfinder/api.py +160 -0
  233. v0/relationalai/experimental/pathfinder/automaton.py +584 -0
  234. v0/relationalai/experimental/pathfinder/bridge.py +226 -0
  235. v0/relationalai/experimental/pathfinder/compiler.py +416 -0
  236. v0/relationalai/experimental/pathfinder/datalog.py +214 -0
  237. v0/relationalai/experimental/pathfinder/diagnostics.py +56 -0
  238. v0/relationalai/experimental/pathfinder/filter.py +236 -0
  239. v0/relationalai/experimental/pathfinder/glushkov.py +439 -0
  240. v0/relationalai/experimental/pathfinder/options.py +265 -0
  241. v0/relationalai/experimental/pathfinder/rpq.py +344 -0
  242. v0/relationalai/experimental/pathfinder/transition.py +200 -0
  243. v0/relationalai/experimental/pathfinder/utils.py +26 -0
  244. v0/relationalai/experimental/paths/api.py +143 -0
  245. v0/relationalai/experimental/paths/benchmarks/grid_graph.py +37 -0
  246. v0/relationalai/experimental/paths/examples/basic_example.py +40 -0
  247. v0/relationalai/experimental/paths/examples/minimal_engine_warmup.py +3 -0
  248. v0/relationalai/experimental/paths/examples/movie_example.py +77 -0
  249. v0/relationalai/experimental/paths/examples/paths_benchmark.py +115 -0
  250. v0/relationalai/experimental/paths/examples/paths_example.py +116 -0
  251. v0/relationalai/experimental/paths/examples/pattern_to_automaton.py +28 -0
  252. v0/relationalai/experimental/paths/find_paths_via_automaton.py +85 -0
  253. v0/relationalai/experimental/paths/graph.py +185 -0
  254. v0/relationalai/experimental/paths/path_algorithms/find_paths.py +280 -0
  255. v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +26 -0
  256. v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +111 -0
  257. v0/relationalai/experimental/paths/path_algorithms/single.py +59 -0
  258. v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +39 -0
  259. v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +103 -0
  260. v0/relationalai/experimental/paths/path_algorithms/usp-old.py +130 -0
  261. v0/relationalai/experimental/paths/path_algorithms/usp-tuple.py +183 -0
  262. v0/relationalai/experimental/paths/path_algorithms/usp.py +150 -0
  263. v0/relationalai/experimental/paths/product_graph.py +93 -0
  264. v0/relationalai/experimental/paths/rpq/automaton.py +584 -0
  265. v0/relationalai/experimental/paths/rpq/diagnostics.py +56 -0
  266. v0/relationalai/experimental/paths/rpq/rpq.py +378 -0
  267. v0/relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +90 -0
  268. v0/relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +119 -0
  269. v0/relationalai/experimental/paths/tests/tests_limit_sp_single.py +104 -0
  270. v0/relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +113 -0
  271. v0/relationalai/experimental/paths/tests/tests_limit_walks_single.py +149 -0
  272. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +70 -0
  273. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +64 -0
  274. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +115 -0
  275. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +75 -0
  276. v0/relationalai/experimental/paths/tests/tests_single_paths.py +152 -0
  277. v0/relationalai/experimental/paths/tests/tests_single_walks.py +208 -0
  278. v0/relationalai/experimental/paths/tests/tests_single_walks_undirected.py +297 -0
  279. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +107 -0
  280. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +76 -0
  281. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +76 -0
  282. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +110 -0
  283. v0/relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +229 -0
  284. v0/relationalai/experimental/paths/tests/tests_usp_nsp_single.py +108 -0
  285. v0/relationalai/experimental/paths/tree_agg.py +168 -0
  286. v0/relationalai/experimental/paths/utilities/iterators.py +27 -0
  287. v0/relationalai/experimental/paths/utilities/prefix_sum.py +91 -0
  288. v0/relationalai/experimental/solvers.py +1087 -0
  289. v0/relationalai/loaders/__init__.py +0 -0
  290. v0/relationalai/loaders/csv.py +195 -0
  291. v0/relationalai/loaders/loader.py +177 -0
  292. v0/relationalai/loaders/types.py +23 -0
  293. v0/relationalai/rel_emitter.py +373 -0
  294. v0/relationalai/rel_utils.py +185 -0
  295. v0/relationalai/semantics/__init__.py +29 -0
  296. v0/relationalai/semantics/devtools/benchmark_lqp.py +536 -0
  297. v0/relationalai/semantics/devtools/compilation_manager.py +294 -0
  298. v0/relationalai/semantics/devtools/extract_lqp.py +110 -0
  299. v0/relationalai/semantics/internal/internal.py +3785 -0
  300. v0/relationalai/semantics/internal/snowflake.py +324 -0
  301. v0/relationalai/semantics/lqp/builtins.py +16 -0
  302. v0/relationalai/semantics/lqp/compiler.py +22 -0
  303. v0/relationalai/semantics/lqp/constructors.py +68 -0
  304. v0/relationalai/semantics/lqp/executor.py +469 -0
  305. v0/relationalai/semantics/lqp/intrinsics.py +24 -0
  306. v0/relationalai/semantics/lqp/model2lqp.py +839 -0
  307. v0/relationalai/semantics/lqp/passes.py +680 -0
  308. v0/relationalai/semantics/lqp/primitives.py +252 -0
  309. v0/relationalai/semantics/lqp/result_helpers.py +202 -0
  310. v0/relationalai/semantics/lqp/rewrite/annotate_constraints.py +57 -0
  311. v0/relationalai/semantics/lqp/rewrite/cdc.py +216 -0
  312. v0/relationalai/semantics/lqp/rewrite/extract_common.py +338 -0
  313. v0/relationalai/semantics/lqp/rewrite/extract_keys.py +449 -0
  314. v0/relationalai/semantics/lqp/rewrite/function_annotations.py +114 -0
  315. v0/relationalai/semantics/lqp/rewrite/functional_dependencies.py +314 -0
  316. v0/relationalai/semantics/lqp/rewrite/quantify_vars.py +296 -0
  317. v0/relationalai/semantics/lqp/rewrite/splinter.py +76 -0
  318. v0/relationalai/semantics/lqp/types.py +101 -0
  319. v0/relationalai/semantics/lqp/utils.py +160 -0
  320. v0/relationalai/semantics/lqp/validators.py +57 -0
  321. v0/relationalai/semantics/metamodel/__init__.py +40 -0
  322. v0/relationalai/semantics/metamodel/builtins.py +774 -0
  323. v0/relationalai/semantics/metamodel/compiler.py +133 -0
  324. v0/relationalai/semantics/metamodel/dependency.py +862 -0
  325. v0/relationalai/semantics/metamodel/executor.py +61 -0
  326. v0/relationalai/semantics/metamodel/factory.py +287 -0
  327. v0/relationalai/semantics/metamodel/helpers.py +361 -0
  328. v0/relationalai/semantics/metamodel/rewrite/discharge_constraints.py +39 -0
  329. v0/relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +210 -0
  330. v0/relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +78 -0
  331. v0/relationalai/semantics/metamodel/rewrite/flatten.py +549 -0
  332. v0/relationalai/semantics/metamodel/rewrite/format_outputs.py +165 -0
  333. v0/relationalai/semantics/metamodel/typer/checker.py +353 -0
  334. v0/relationalai/semantics/metamodel/typer/typer.py +1395 -0
  335. v0/relationalai/semantics/reasoners/__init__.py +10 -0
  336. v0/relationalai/semantics/reasoners/graph/__init__.py +37 -0
  337. v0/relationalai/semantics/reasoners/graph/core.py +9020 -0
  338. v0/relationalai/semantics/reasoners/optimization/__init__.py +68 -0
  339. v0/relationalai/semantics/reasoners/optimization/common.py +88 -0
  340. v0/relationalai/semantics/reasoners/optimization/solvers_dev.py +568 -0
  341. v0/relationalai/semantics/reasoners/optimization/solvers_pb.py +1163 -0
  342. v0/relationalai/semantics/rel/builtins.py +40 -0
  343. v0/relationalai/semantics/rel/compiler.py +989 -0
  344. v0/relationalai/semantics/rel/executor.py +359 -0
  345. v0/relationalai/semantics/rel/rel.py +482 -0
  346. v0/relationalai/semantics/rel/rel_utils.py +276 -0
  347. v0/relationalai/semantics/snowflake/__init__.py +3 -0
  348. v0/relationalai/semantics/sql/compiler.py +2503 -0
  349. v0/relationalai/semantics/sql/executor/duck_db.py +52 -0
  350. v0/relationalai/semantics/sql/executor/result_helpers.py +64 -0
  351. v0/relationalai/semantics/sql/executor/snowflake.py +145 -0
  352. v0/relationalai/semantics/sql/rewrite/denormalize.py +222 -0
  353. v0/relationalai/semantics/sql/rewrite/double_negation.py +49 -0
  354. v0/relationalai/semantics/sql/rewrite/recursive_union.py +127 -0
  355. v0/relationalai/semantics/sql/rewrite/sort_output_query.py +246 -0
  356. v0/relationalai/semantics/sql/sql.py +504 -0
  357. v0/relationalai/semantics/std/__init__.py +54 -0
  358. v0/relationalai/semantics/std/constraints.py +43 -0
  359. v0/relationalai/semantics/std/datetime.py +363 -0
  360. v0/relationalai/semantics/std/decimals.py +62 -0
  361. v0/relationalai/semantics/std/floats.py +7 -0
  362. v0/relationalai/semantics/std/integers.py +22 -0
  363. v0/relationalai/semantics/std/math.py +141 -0
  364. v0/relationalai/semantics/std/pragmas.py +11 -0
  365. v0/relationalai/semantics/std/re.py +83 -0
  366. v0/relationalai/semantics/std/std.py +14 -0
  367. v0/relationalai/semantics/std/strings.py +63 -0
  368. v0/relationalai/semantics/tests/__init__.py +0 -0
  369. v0/relationalai/semantics/tests/test_snapshot_abstract.py +143 -0
  370. v0/relationalai/semantics/tests/test_snapshot_base.py +9 -0
  371. v0/relationalai/semantics/tests/utils.py +46 -0
  372. v0/relationalai/std/__init__.py +70 -0
  373. v0/relationalai/tools/__init__.py +0 -0
  374. v0/relationalai/tools/cli.py +1940 -0
  375. v0/relationalai/tools/cli_controls.py +1826 -0
  376. v0/relationalai/tools/cli_helpers.py +390 -0
  377. v0/relationalai/tools/debugger.py +183 -0
  378. v0/relationalai/tools/debugger_client.py +109 -0
  379. v0/relationalai/tools/debugger_server.py +302 -0
  380. v0/relationalai/tools/dev.py +685 -0
  381. v0/relationalai/tools/qb_debugger.py +425 -0
  382. v0/relationalai/util/clean_up_databases.py +95 -0
  383. v0/relationalai/util/format.py +123 -0
  384. v0/relationalai/util/list_databases.py +9 -0
  385. v0/relationalai/util/otel_configuration.py +25 -0
  386. v0/relationalai/util/otel_handler.py +484 -0
  387. v0/relationalai/util/snowflake_handler.py +88 -0
  388. v0/relationalai/util/span_format_test.py +43 -0
  389. v0/relationalai/util/span_tracker.py +207 -0
  390. v0/relationalai/util/spans_file_handler.py +72 -0
  391. v0/relationalai/util/tracing_handler.py +34 -0
  392. frontend/debugger/dist/.gitignore +0 -2
  393. frontend/debugger/dist/assets/favicon-Dy0ZgA6N.png +0 -0
  394. frontend/debugger/dist/assets/index-Cssla-O7.js +0 -208
  395. frontend/debugger/dist/assets/index-DlHsYx1V.css +0 -9
  396. frontend/debugger/dist/index.html +0 -17
  397. relationalai/clients/azure.py +0 -477
  398. relationalai/clients/client.py +0 -912
  399. relationalai/clients/config.py +0 -673
  400. relationalai/clients/direct_access_client.py +0 -118
  401. relationalai/clients/export_procedure.py.jinja +0 -249
  402. relationalai/clients/hash_util.py +0 -31
  403. relationalai/clients/local.py +0 -571
  404. relationalai/clients/profile_polling.py +0 -73
  405. relationalai/clients/result_helpers.py +0 -420
  406. relationalai/clients/snowflake.py +0 -3869
  407. relationalai/clients/types.py +0 -113
  408. relationalai/clients/use_index_poller.py +0 -980
  409. relationalai/clients/util.py +0 -356
  410. relationalai/debugging.py +0 -389
  411. relationalai/dsl.py +0 -1749
  412. relationalai/early_access/builder/__init__.py +0 -30
  413. relationalai/early_access/builder/builder/__init__.py +0 -35
  414. relationalai/early_access/builder/snowflake/__init__.py +0 -12
  415. relationalai/early_access/builder/std/__init__.py +0 -25
  416. relationalai/early_access/builder/std/decimals/__init__.py +0 -12
  417. relationalai/early_access/builder/std/integers/__init__.py +0 -12
  418. relationalai/early_access/builder/std/math/__init__.py +0 -12
  419. relationalai/early_access/builder/std/strings/__init__.py +0 -14
  420. relationalai/early_access/devtools/__init__.py +0 -12
  421. relationalai/early_access/devtools/benchmark_lqp/__init__.py +0 -12
  422. relationalai/early_access/devtools/extract_lqp/__init__.py +0 -12
  423. relationalai/early_access/dsl/adapters/orm/adapter_qb.py +0 -427
  424. relationalai/early_access/dsl/adapters/orm/parser.py +0 -636
  425. relationalai/early_access/dsl/adapters/owl/adapter.py +0 -176
  426. relationalai/early_access/dsl/adapters/owl/parser.py +0 -160
  427. relationalai/early_access/dsl/bindings/common.py +0 -402
  428. relationalai/early_access/dsl/bindings/csv.py +0 -170
  429. relationalai/early_access/dsl/bindings/legacy/binding_models.py +0 -143
  430. relationalai/early_access/dsl/bindings/snowflake.py +0 -64
  431. relationalai/early_access/dsl/codegen/binder.py +0 -411
  432. relationalai/early_access/dsl/codegen/common.py +0 -79
  433. relationalai/early_access/dsl/codegen/helpers.py +0 -23
  434. relationalai/early_access/dsl/codegen/relations.py +0 -700
  435. relationalai/early_access/dsl/codegen/weaver.py +0 -417
  436. relationalai/early_access/dsl/core/builders/__init__.py +0 -47
  437. relationalai/early_access/dsl/core/builders/logic.py +0 -19
  438. relationalai/early_access/dsl/core/builders/scalar_constraint.py +0 -11
  439. relationalai/early_access/dsl/core/constraints/predicate/atomic.py +0 -455
  440. relationalai/early_access/dsl/core/constraints/predicate/universal.py +0 -73
  441. relationalai/early_access/dsl/core/constraints/scalar.py +0 -310
  442. relationalai/early_access/dsl/core/context.py +0 -13
  443. relationalai/early_access/dsl/core/cset.py +0 -132
  444. relationalai/early_access/dsl/core/exprs/__init__.py +0 -116
  445. relationalai/early_access/dsl/core/exprs/relational.py +0 -18
  446. relationalai/early_access/dsl/core/exprs/scalar.py +0 -412
  447. relationalai/early_access/dsl/core/instances.py +0 -44
  448. relationalai/early_access/dsl/core/logic/__init__.py +0 -193
  449. relationalai/early_access/dsl/core/logic/aggregation.py +0 -98
  450. relationalai/early_access/dsl/core/logic/exists.py +0 -223
  451. relationalai/early_access/dsl/core/logic/helper.py +0 -163
  452. relationalai/early_access/dsl/core/namespaces.py +0 -32
  453. relationalai/early_access/dsl/core/relations.py +0 -276
  454. relationalai/early_access/dsl/core/rules.py +0 -112
  455. relationalai/early_access/dsl/core/std/__init__.py +0 -45
  456. relationalai/early_access/dsl/core/temporal/recall.py +0 -6
  457. relationalai/early_access/dsl/core/types/__init__.py +0 -270
  458. relationalai/early_access/dsl/core/types/concepts.py +0 -128
  459. relationalai/early_access/dsl/core/types/constrained/__init__.py +0 -267
  460. relationalai/early_access/dsl/core/types/constrained/nominal.py +0 -143
  461. relationalai/early_access/dsl/core/types/constrained/subtype.py +0 -124
  462. relationalai/early_access/dsl/core/types/standard.py +0 -92
  463. relationalai/early_access/dsl/core/types/unconstrained.py +0 -50
  464. relationalai/early_access/dsl/core/types/variables.py +0 -203
  465. relationalai/early_access/dsl/ir/compiler.py +0 -318
  466. relationalai/early_access/dsl/ir/executor.py +0 -260
  467. relationalai/early_access/dsl/ontologies/constraints.py +0 -88
  468. relationalai/early_access/dsl/ontologies/export.py +0 -30
  469. relationalai/early_access/dsl/ontologies/models.py +0 -453
  470. relationalai/early_access/dsl/ontologies/python_printer.py +0 -303
  471. relationalai/early_access/dsl/ontologies/readings.py +0 -60
  472. relationalai/early_access/dsl/ontologies/relationships.py +0 -322
  473. relationalai/early_access/dsl/ontologies/roles.py +0 -87
  474. relationalai/early_access/dsl/ontologies/subtyping.py +0 -55
  475. relationalai/early_access/dsl/orm/constraints.py +0 -438
  476. relationalai/early_access/dsl/orm/measures/dimensions.py +0 -200
  477. relationalai/early_access/dsl/orm/measures/initializer.py +0 -16
  478. relationalai/early_access/dsl/orm/measures/measure_rules.py +0 -275
  479. relationalai/early_access/dsl/orm/measures/measures.py +0 -299
  480. relationalai/early_access/dsl/orm/measures/role_exprs.py +0 -268
  481. relationalai/early_access/dsl/orm/models.py +0 -256
  482. relationalai/early_access/dsl/orm/object_oriented_printer.py +0 -344
  483. relationalai/early_access/dsl/orm/printer.py +0 -469
  484. relationalai/early_access/dsl/orm/reasoners.py +0 -480
  485. relationalai/early_access/dsl/orm/relations.py +0 -19
  486. relationalai/early_access/dsl/orm/relationships.py +0 -251
  487. relationalai/early_access/dsl/orm/types.py +0 -42
  488. relationalai/early_access/dsl/orm/utils.py +0 -79
  489. relationalai/early_access/dsl/orm/verb.py +0 -204
  490. relationalai/early_access/dsl/physical_metadata/tables.py +0 -133
  491. relationalai/early_access/dsl/relations.py +0 -170
  492. relationalai/early_access/dsl/rulesets.py +0 -69
  493. relationalai/early_access/dsl/schemas/__init__.py +0 -450
  494. relationalai/early_access/dsl/schemas/builder.py +0 -48
  495. relationalai/early_access/dsl/schemas/comp_names.py +0 -51
  496. relationalai/early_access/dsl/schemas/components.py +0 -203
  497. relationalai/early_access/dsl/schemas/contexts.py +0 -156
  498. relationalai/early_access/dsl/schemas/exprs.py +0 -89
  499. relationalai/early_access/dsl/schemas/fragments.py +0 -464
  500. relationalai/early_access/dsl/serialization.py +0 -79
  501. relationalai/early_access/dsl/serialize/exporter.py +0 -163
  502. relationalai/early_access/dsl/snow/api.py +0 -104
  503. relationalai/early_access/dsl/snow/common.py +0 -76
  504. relationalai/early_access/dsl/state_mgmt/__init__.py +0 -129
  505. relationalai/early_access/dsl/state_mgmt/state_charts.py +0 -125
  506. relationalai/early_access/dsl/state_mgmt/transitions.py +0 -130
  507. relationalai/early_access/dsl/types/__init__.py +0 -40
  508. relationalai/early_access/dsl/types/concepts.py +0 -12
  509. relationalai/early_access/dsl/types/entities.py +0 -135
  510. relationalai/early_access/dsl/types/values.py +0 -17
  511. relationalai/early_access/dsl/utils.py +0 -102
  512. relationalai/early_access/graphs/__init__.py +0 -13
  513. relationalai/early_access/lqp/__init__.py +0 -12
  514. relationalai/early_access/lqp/compiler/__init__.py +0 -12
  515. relationalai/early_access/lqp/constructors/__init__.py +0 -18
  516. relationalai/early_access/lqp/executor/__init__.py +0 -12
  517. relationalai/early_access/lqp/ir/__init__.py +0 -12
  518. relationalai/early_access/lqp/passes/__init__.py +0 -12
  519. relationalai/early_access/lqp/pragmas/__init__.py +0 -12
  520. relationalai/early_access/lqp/primitives/__init__.py +0 -12
  521. relationalai/early_access/lqp/types/__init__.py +0 -12
  522. relationalai/early_access/lqp/utils/__init__.py +0 -12
  523. relationalai/early_access/lqp/validators/__init__.py +0 -12
  524. relationalai/early_access/metamodel/__init__.py +0 -58
  525. relationalai/early_access/metamodel/builtins/__init__.py +0 -12
  526. relationalai/early_access/metamodel/compiler/__init__.py +0 -12
  527. relationalai/early_access/metamodel/dependency/__init__.py +0 -12
  528. relationalai/early_access/metamodel/factory/__init__.py +0 -17
  529. relationalai/early_access/metamodel/helpers/__init__.py +0 -12
  530. relationalai/early_access/metamodel/ir/__init__.py +0 -14
  531. relationalai/early_access/metamodel/rewrite/__init__.py +0 -7
  532. relationalai/early_access/metamodel/typer/__init__.py +0 -3
  533. relationalai/early_access/metamodel/typer/typer/__init__.py +0 -12
  534. relationalai/early_access/metamodel/types/__init__.py +0 -15
  535. relationalai/early_access/metamodel/util/__init__.py +0 -15
  536. relationalai/early_access/metamodel/visitor/__init__.py +0 -12
  537. relationalai/early_access/rel/__init__.py +0 -12
  538. relationalai/early_access/rel/executor/__init__.py +0 -12
  539. relationalai/early_access/rel/rel_utils/__init__.py +0 -12
  540. relationalai/early_access/rel/rewrite/__init__.py +0 -7
  541. relationalai/early_access/solvers/__init__.py +0 -19
  542. relationalai/early_access/sql/__init__.py +0 -11
  543. relationalai/early_access/sql/executor/__init__.py +0 -3
  544. relationalai/early_access/sql/rewrite/__init__.py +0 -3
  545. relationalai/early_access/tests/logging/__init__.py +0 -12
  546. relationalai/early_access/tests/test_snapshot_base/__init__.py +0 -12
  547. relationalai/early_access/tests/utils/__init__.py +0 -12
  548. relationalai/environments/__init__.py +0 -35
  549. relationalai/environments/base.py +0 -381
  550. relationalai/environments/colab.py +0 -14
  551. relationalai/environments/generic.py +0 -71
  552. relationalai/environments/ipython.py +0 -68
  553. relationalai/environments/jupyter.py +0 -9
  554. relationalai/environments/snowbook.py +0 -169
  555. relationalai/errors.py +0 -2455
  556. relationalai/experimental/SF.py +0 -38
  557. relationalai/experimental/inspect.py +0 -47
  558. relationalai/experimental/pathfinder/__init__.py +0 -158
  559. relationalai/experimental/pathfinder/api.py +0 -160
  560. relationalai/experimental/pathfinder/automaton.py +0 -584
  561. relationalai/experimental/pathfinder/bridge.py +0 -226
  562. relationalai/experimental/pathfinder/compiler.py +0 -416
  563. relationalai/experimental/pathfinder/datalog.py +0 -214
  564. relationalai/experimental/pathfinder/diagnostics.py +0 -56
  565. relationalai/experimental/pathfinder/filter.py +0 -236
  566. relationalai/experimental/pathfinder/glushkov.py +0 -439
  567. relationalai/experimental/pathfinder/options.py +0 -265
  568. relationalai/experimental/pathfinder/pathfinder-v0.7.0.rel +0 -1951
  569. relationalai/experimental/pathfinder/rpq.py +0 -344
  570. relationalai/experimental/pathfinder/transition.py +0 -200
  571. relationalai/experimental/pathfinder/utils.py +0 -26
  572. relationalai/experimental/paths/README.md +0 -107
  573. relationalai/experimental/paths/api.py +0 -143
  574. relationalai/experimental/paths/benchmarks/grid_graph.py +0 -37
  575. relationalai/experimental/paths/code_organization.md +0 -2
  576. relationalai/experimental/paths/examples/Movies.ipynb +0 -16328
  577. relationalai/experimental/paths/examples/basic_example.py +0 -40
  578. relationalai/experimental/paths/examples/minimal_engine_warmup.py +0 -3
  579. relationalai/experimental/paths/examples/movie_example.py +0 -77
  580. relationalai/experimental/paths/examples/movies_data/actedin.csv +0 -193
  581. relationalai/experimental/paths/examples/movies_data/directed.csv +0 -45
  582. relationalai/experimental/paths/examples/movies_data/follows.csv +0 -7
  583. relationalai/experimental/paths/examples/movies_data/movies.csv +0 -39
  584. relationalai/experimental/paths/examples/movies_data/person.csv +0 -134
  585. relationalai/experimental/paths/examples/movies_data/produced.csv +0 -16
  586. relationalai/experimental/paths/examples/movies_data/ratings.csv +0 -10
  587. relationalai/experimental/paths/examples/movies_data/wrote.csv +0 -11
  588. relationalai/experimental/paths/examples/paths_benchmark.py +0 -115
  589. relationalai/experimental/paths/examples/paths_example.py +0 -116
  590. relationalai/experimental/paths/examples/pattern_to_automaton.py +0 -28
  591. relationalai/experimental/paths/find_paths_via_automaton.py +0 -85
  592. relationalai/experimental/paths/graph.py +0 -185
  593. relationalai/experimental/paths/path_algorithms/find_paths.py +0 -280
  594. relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +0 -26
  595. relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +0 -111
  596. relationalai/experimental/paths/path_algorithms/single.py +0 -59
  597. relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +0 -39
  598. relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +0 -103
  599. relationalai/experimental/paths/path_algorithms/usp-old.py +0 -130
  600. relationalai/experimental/paths/path_algorithms/usp-tuple.py +0 -183
  601. relationalai/experimental/paths/path_algorithms/usp.py +0 -150
  602. relationalai/experimental/paths/product_graph.py +0 -93
  603. relationalai/experimental/paths/rpq/automaton.py +0 -584
  604. relationalai/experimental/paths/rpq/diagnostics.py +0 -56
  605. relationalai/experimental/paths/rpq/rpq.py +0 -378
  606. relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +0 -90
  607. relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +0 -119
  608. relationalai/experimental/paths/tests/tests_limit_sp_single.py +0 -104
  609. relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +0 -113
  610. relationalai/experimental/paths/tests/tests_limit_walks_single.py +0 -149
  611. relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +0 -70
  612. relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +0 -64
  613. relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +0 -115
  614. relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +0 -75
  615. relationalai/experimental/paths/tests/tests_single_paths.py +0 -152
  616. relationalai/experimental/paths/tests/tests_single_walks.py +0 -208
  617. relationalai/experimental/paths/tests/tests_single_walks_undirected.py +0 -297
  618. relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +0 -107
  619. relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +0 -76
  620. relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +0 -76
  621. relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +0 -110
  622. relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +0 -229
  623. relationalai/experimental/paths/tests/tests_usp_nsp_single.py +0 -108
  624. relationalai/experimental/paths/tree_agg.py +0 -168
  625. relationalai/experimental/paths/utilities/iterators.py +0 -27
  626. relationalai/experimental/paths/utilities/prefix_sum.py +0 -91
  627. relationalai/experimental/solvers.py +0 -1087
  628. relationalai/loaders/csv.py +0 -195
  629. relationalai/loaders/loader.py +0 -177
  630. relationalai/loaders/types.py +0 -23
  631. relationalai/rel_emitter.py +0 -373
  632. relationalai/rel_utils.py +0 -185
  633. relationalai/semantics/designs/query_builder/identify_by.md +0 -106
  634. relationalai/semantics/devtools/benchmark_lqp.py +0 -536
  635. relationalai/semantics/devtools/compilation_manager.py +0 -294
  636. relationalai/semantics/devtools/extract_lqp.py +0 -110
  637. relationalai/semantics/internal/internal.py +0 -3785
  638. relationalai/semantics/internal/snowflake.py +0 -324
  639. relationalai/semantics/lqp/README.md +0 -34
  640. relationalai/semantics/lqp/builtins.py +0 -16
  641. relationalai/semantics/lqp/compiler.py +0 -22
  642. relationalai/semantics/lqp/constructors.py +0 -68
  643. relationalai/semantics/lqp/executor.py +0 -469
  644. relationalai/semantics/lqp/intrinsics.py +0 -24
  645. relationalai/semantics/lqp/model2lqp.py +0 -839
  646. relationalai/semantics/lqp/passes.py +0 -680
  647. relationalai/semantics/lqp/primitives.py +0 -252
  648. relationalai/semantics/lqp/result_helpers.py +0 -202
  649. relationalai/semantics/lqp/rewrite/annotate_constraints.py +0 -57
  650. relationalai/semantics/lqp/rewrite/cdc.py +0 -216
  651. relationalai/semantics/lqp/rewrite/extract_common.py +0 -338
  652. relationalai/semantics/lqp/rewrite/extract_keys.py +0 -449
  653. relationalai/semantics/lqp/rewrite/function_annotations.py +0 -114
  654. relationalai/semantics/lqp/rewrite/functional_dependencies.py +0 -314
  655. relationalai/semantics/lqp/rewrite/quantify_vars.py +0 -296
  656. relationalai/semantics/lqp/rewrite/splinter.py +0 -76
  657. relationalai/semantics/lqp/types.py +0 -101
  658. relationalai/semantics/lqp/utils.py +0 -160
  659. relationalai/semantics/lqp/validators.py +0 -57
  660. relationalai/semantics/metamodel/compiler.py +0 -133
  661. relationalai/semantics/metamodel/dependency.py +0 -862
  662. relationalai/semantics/metamodel/executor.py +0 -61
  663. relationalai/semantics/metamodel/factory.py +0 -287
  664. relationalai/semantics/metamodel/helpers.py +0 -361
  665. relationalai/semantics/metamodel/rewrite/discharge_constraints.py +0 -39
  666. relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +0 -210
  667. relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +0 -78
  668. relationalai/semantics/metamodel/rewrite/flatten.py +0 -549
  669. relationalai/semantics/metamodel/rewrite/format_outputs.py +0 -165
  670. relationalai/semantics/metamodel/typer/checker.py +0 -353
  671. relationalai/semantics/metamodel/typer/typer.py +0 -1395
  672. relationalai/semantics/reasoners/__init__.py +0 -10
  673. relationalai/semantics/reasoners/graph/README.md +0 -620
  674. relationalai/semantics/reasoners/graph/__init__.py +0 -37
  675. relationalai/semantics/reasoners/graph/core.py +0 -9020
  676. relationalai/semantics/reasoners/graph/design/beyond_demand_transform.md +0 -797
  677. relationalai/semantics/reasoners/graph/tests/README.md +0 -21
  678. relationalai/semantics/reasoners/optimization/__init__.py +0 -68
  679. relationalai/semantics/reasoners/optimization/common.py +0 -88
  680. relationalai/semantics/reasoners/optimization/solvers_dev.py +0 -568
  681. relationalai/semantics/reasoners/optimization/solvers_pb.py +0 -1163
  682. relationalai/semantics/rel/builtins.py +0 -40
  683. relationalai/semantics/rel/compiler.py +0 -989
  684. relationalai/semantics/rel/executor.py +0 -359
  685. relationalai/semantics/rel/rel.py +0 -482
  686. relationalai/semantics/rel/rel_utils.py +0 -276
  687. relationalai/semantics/snowflake/__init__.py +0 -3
  688. relationalai/semantics/sql/compiler.py +0 -2503
  689. relationalai/semantics/sql/executor/duck_db.py +0 -52
  690. relationalai/semantics/sql/executor/result_helpers.py +0 -64
  691. relationalai/semantics/sql/executor/snowflake.py +0 -145
  692. relationalai/semantics/sql/rewrite/denormalize.py +0 -222
  693. relationalai/semantics/sql/rewrite/double_negation.py +0 -49
  694. relationalai/semantics/sql/rewrite/recursive_union.py +0 -127
  695. relationalai/semantics/sql/rewrite/sort_output_query.py +0 -246
  696. relationalai/semantics/sql/sql.py +0 -504
  697. relationalai/semantics/std/pragmas.py +0 -11
  698. relationalai/semantics/std/std.py +0 -14
  699. relationalai/semantics/tests/test_snapshot_abstract.py +0 -143
  700. relationalai/semantics/tests/test_snapshot_base.py +0 -9
  701. relationalai/semantics/tests/utils.py +0 -46
  702. relationalai/std/__init__.py +0 -70
  703. relationalai/tools/cli.py +0 -1940
  704. relationalai/tools/cli_controls.py +0 -1826
  705. relationalai/tools/cli_helpers.py +0 -390
  706. relationalai/tools/debugger_client.py +0 -109
  707. relationalai/tools/debugger_server.py +0 -302
  708. relationalai/tools/dev.py +0 -685
  709. relationalai/tools/notes +0 -7
  710. relationalai/tools/qb_debugger.py +0 -425
  711. relationalai/util/clean_up_databases.py +0 -95
  712. relationalai/util/list_databases.py +0 -9
  713. relationalai/util/otel_configuration.py +0 -25
  714. relationalai/util/otel_handler.py +0 -484
  715. relationalai/util/snowflake_handler.py +0 -88
  716. relationalai/util/span_format_test.py +0 -43
  717. relationalai/util/span_tracker.py +0 -207
  718. relationalai/util/spans_file_handler.py +0 -72
  719. relationalai/util/tracing_handler.py +0 -34
  720. relationalai-0.12.13.dist-info/METADATA +0 -74
  721. relationalai-0.12.13.dist-info/RECORD +0 -449
  722. relationalai-0.12.13.dist-info/WHEEL +0 -4
  723. relationalai-0.12.13.dist-info/entry_points.txt +0 -3
  724. relationalai-0.12.13.dist-info/licenses/LICENSE +0 -202
  725. relationalai_test_util/__init__.py +0 -4
  726. relationalai_test_util/fixtures.py +0 -228
  727. relationalai_test_util/snapshot.py +0 -252
  728. relationalai_test_util/traceback.py +0 -118
  729. /relationalai/{analysis → semantics/frontend}/__init__.py +0 -0
  730. /relationalai/{auth/__init__.py → semantics/metamodel/metamodel_compiler.py} +0 -0
  731. /relationalai/{early_access → shims}/__init__.py +0 -0
  732. {relationalai/early_access/dsl/adapters → v0/relationalai/analysis}/__init__.py +0 -0
  733. {relationalai → v0/relationalai}/analysis/mechanistic.py +0 -0
  734. {relationalai → v0/relationalai}/analysis/whynot.py +0 -0
  735. {relationalai/early_access/dsl/adapters/orm → v0/relationalai/auth}/__init__.py +0 -0
  736. {relationalai → v0/relationalai}/auth/jwt_generator.py +0 -0
  737. {relationalai → v0/relationalai}/auth/oauth_callback_server.py +0 -0
  738. {relationalai → v0/relationalai}/auth/token_handler.py +0 -0
  739. {relationalai → v0/relationalai}/auth/util.py +0 -0
  740. {relationalai → v0/relationalai}/clients/__init__.py +0 -0
  741. {relationalai → v0/relationalai}/clients/cache_store.py +0 -0
  742. {relationalai → v0/relationalai}/compiler.py +0 -0
  743. {relationalai → v0/relationalai}/dependencies.py +0 -0
  744. {relationalai → v0/relationalai}/docutils.py +0 -0
  745. {relationalai/early_access/dsl/adapters/owl → v0/relationalai/early_access}/__init__.py +0 -0
  746. {relationalai → v0/relationalai}/early_access/dsl/__init__.py +0 -0
  747. {relationalai/early_access/dsl/bindings → v0/relationalai/early_access/dsl/adapters}/__init__.py +0 -0
  748. {relationalai/early_access/dsl/bindings/legacy → v0/relationalai/early_access/dsl/adapters/orm}/__init__.py +0 -0
  749. {relationalai → v0/relationalai}/early_access/dsl/adapters/orm/model.py +0 -0
  750. {relationalai/early_access/dsl/codegen → v0/relationalai/early_access/dsl/adapters/owl}/__init__.py +0 -0
  751. {relationalai → v0/relationalai}/early_access/dsl/adapters/owl/model.py +0 -0
  752. {relationalai/early_access/dsl/core/temporal → v0/relationalai/early_access/dsl/bindings}/__init__.py +0 -0
  753. {relationalai/early_access/dsl/ir → v0/relationalai/early_access/dsl/bindings/legacy}/__init__.py +0 -0
  754. {relationalai/early_access/dsl/ontologies → v0/relationalai/early_access/dsl/codegen}/__init__.py +0 -0
  755. {relationalai → v0/relationalai}/early_access/dsl/constants.py +0 -0
  756. {relationalai → v0/relationalai}/early_access/dsl/core/__init__.py +0 -0
  757. {relationalai → v0/relationalai}/early_access/dsl/core/constraints/__init__.py +0 -0
  758. {relationalai → v0/relationalai}/early_access/dsl/core/constraints/predicate/__init__.py +0 -0
  759. {relationalai → v0/relationalai}/early_access/dsl/core/stack.py +0 -0
  760. {relationalai/early_access/dsl/orm → v0/relationalai/early_access/dsl/core/temporal}/__init__.py +0 -0
  761. {relationalai → v0/relationalai}/early_access/dsl/core/utils.py +0 -0
  762. {relationalai/early_access/dsl/orm/measures → v0/relationalai/early_access/dsl/ir}/__init__.py +0 -0
  763. {relationalai/early_access/dsl/physical_metadata → v0/relationalai/early_access/dsl/ontologies}/__init__.py +0 -0
  764. {relationalai → v0/relationalai}/early_access/dsl/ontologies/raw_source.py +0 -0
  765. {relationalai/early_access/dsl/serialize → v0/relationalai/early_access/dsl/orm}/__init__.py +0 -0
  766. {relationalai/early_access/dsl/snow → v0/relationalai/early_access/dsl/orm/measures}/__init__.py +0 -0
  767. {relationalai → v0/relationalai}/early_access/dsl/orm/reasoner_errors.py +0 -0
  768. {relationalai/loaders → v0/relationalai/early_access/dsl/physical_metadata}/__init__.py +0 -0
  769. {relationalai/semantics/tests → v0/relationalai/early_access/dsl/serialize}/__init__.py +0 -0
  770. {relationalai → v0/relationalai}/early_access/dsl/serialize/binding_model.py +0 -0
  771. {relationalai → v0/relationalai}/early_access/dsl/serialize/model.py +0 -0
  772. {relationalai/tools → v0/relationalai/early_access/dsl/snow}/__init__.py +0 -0
  773. {relationalai → v0/relationalai}/early_access/tests/__init__.py +0 -0
  774. {relationalai → v0/relationalai}/environments/ci.py +0 -0
  775. {relationalai → v0/relationalai}/environments/hex.py +0 -0
  776. {relationalai → v0/relationalai}/environments/terminal.py +0 -0
  777. {relationalai → v0/relationalai}/experimental/__init__.py +0 -0
  778. {relationalai → v0/relationalai}/experimental/graphs.py +0 -0
  779. {relationalai → v0/relationalai}/experimental/paths/__init__.py +0 -0
  780. {relationalai → v0/relationalai}/experimental/paths/benchmarks/__init__.py +0 -0
  781. {relationalai → v0/relationalai}/experimental/paths/path_algorithms/__init__.py +0 -0
  782. {relationalai → v0/relationalai}/experimental/paths/rpq/__init__.py +0 -0
  783. {relationalai → v0/relationalai}/experimental/paths/rpq/filter.py +0 -0
  784. {relationalai → v0/relationalai}/experimental/paths/rpq/glushkov.py +0 -0
  785. {relationalai → v0/relationalai}/experimental/paths/rpq/transition.py +0 -0
  786. {relationalai → v0/relationalai}/experimental/paths/utilities/__init__.py +0 -0
  787. {relationalai → v0/relationalai}/experimental/paths/utilities/utilities.py +0 -0
  788. {relationalai → v0/relationalai}/metagen.py +0 -0
  789. {relationalai → v0/relationalai}/metamodel.py +0 -0
  790. {relationalai → v0/relationalai}/rel.py +0 -0
  791. {relationalai → v0/relationalai}/semantics/devtools/__init__.py +0 -0
  792. {relationalai → v0/relationalai}/semantics/internal/__init__.py +0 -0
  793. {relationalai → v0/relationalai}/semantics/internal/annotations.py +0 -0
  794. {relationalai → v0/relationalai}/semantics/lqp/__init__.py +0 -0
  795. {relationalai → v0/relationalai}/semantics/lqp/ir.py +0 -0
  796. {relationalai → v0/relationalai}/semantics/lqp/pragmas.py +0 -0
  797. {relationalai → v0/relationalai}/semantics/lqp/rewrite/__init__.py +0 -0
  798. {relationalai → v0/relationalai}/semantics/metamodel/dataflow.py +0 -0
  799. {relationalai → v0/relationalai}/semantics/metamodel/ir.py +0 -0
  800. {relationalai → v0/relationalai}/semantics/metamodel/rewrite/__init__.py +0 -0
  801. {relationalai → v0/relationalai}/semantics/metamodel/typer/__init__.py +0 -0
  802. {relationalai → v0/relationalai}/semantics/metamodel/types.py +0 -0
  803. {relationalai → v0/relationalai}/semantics/metamodel/util.py +0 -0
  804. {relationalai → v0/relationalai}/semantics/metamodel/visitor.py +0 -0
  805. {relationalai → v0/relationalai}/semantics/reasoners/experimental/__init__.py +0 -0
  806. {relationalai → v0/relationalai}/semantics/rel/__init__.py +0 -0
  807. {relationalai → v0/relationalai}/semantics/sql/__init__.py +0 -0
  808. {relationalai → v0/relationalai}/semantics/sql/executor/__init__.py +0 -0
  809. {relationalai → v0/relationalai}/semantics/sql/rewrite/__init__.py +0 -0
  810. {relationalai → v0/relationalai}/semantics/tests/logging.py +0 -0
  811. {relationalai → v0/relationalai}/std/aggregates.py +0 -0
  812. {relationalai → v0/relationalai}/std/dates.py +0 -0
  813. {relationalai → v0/relationalai}/std/graphs.py +0 -0
  814. {relationalai → v0/relationalai}/std/inspect.py +0 -0
  815. {relationalai → v0/relationalai}/std/math.py +0 -0
  816. {relationalai → v0/relationalai}/std/re.py +0 -0
  817. {relationalai → v0/relationalai}/std/strings.py +0 -0
  818. {relationalai → v0/relationalai}/tools/cleanup_snapshots.py +0 -0
  819. {relationalai → v0/relationalai}/tools/constants.py +0 -0
  820. {relationalai → v0/relationalai}/tools/query_utils.py +0 -0
  821. {relationalai → v0/relationalai}/tools/snapshot_viewer.py +0 -0
  822. {relationalai → v0/relationalai}/util/__init__.py +0 -0
  823. {relationalai → v0/relationalai}/util/constants.py +0 -0
  824. {relationalai → v0/relationalai}/util/graph.py +0 -0
  825. {relationalai → v0/relationalai}/util/timeout.py +0 -0
@@ -0,0 +1,1313 @@
1
+ from __future__ import annotations
2
+ from contextlib import contextmanager
3
+ from enum import Enum
4
+ from functools import lru_cache, wraps
5
+ from itertools import chain
6
+ from re import sub
7
+ from typing import Any, Optional, Sequence, cast
8
+ from collections.abc import Iterable
9
+
10
+ from ...util.naming import Namer, sanitize
11
+ from ...util.source import SourcePos
12
+ from ...util.structures import KeyedDict, KeyedSet, OrderedSet
13
+ from .pprint import pprint
14
+ from ..metamodel.builtins import builtins as bt
15
+ from ..metamodel.pprint import pprint as mmpp, print_tree
16
+ from ...util.error import Diagnostic, Part, err, warn, source as err_source, exc
17
+
18
+ from .base import (
19
+ Alias, AsBool, CoreConcepts, CoreRelationships, DSLBase, Data, DerivedColumn, Distinct, Field, FieldRef, FilterBy, Group, Library, Literal, Model, Fragment, ModelEnum, New, Not, Chain,
20
+ Property, Ref, Relationship, Concept, Expression, Statement, Table, TableSchema, TupleVariable, Value, Variable, Match, Union, dsl_key, is_primitive,
21
+ NumberConcept, Reading, Aggregate, MetaRef
22
+ )
23
+ from ..metamodel.metamodel import (
24
+ Aggregate as mAggregate, Annotation, Construct, Effect, FieldType, ISeq, ListType, Logical, Node, NoneType, NumberType, Relation, RelationType, Require, ScalarType, Overload,
25
+ Lookup, TupleType, TypeNode, UnresolvedRelation, Var, Task, Literal as mLiteral, Value as mValue, Table as mTable, Update,
26
+ Field as mField, Not as mNot, Reading as mReading, Match as mMatch, Union as mUnion, Data as mData, Model as mModel
27
+ )
28
+
29
+ #------------------------------------------------------
30
+ # Memoize
31
+ #------------------------------------------------------
32
+
33
+ def memoize_in_ctx(method):
34
+ """Cache results in ctx.seen using id(node) as the key."""
35
+ @wraps(method)
36
+ def wrapper(self, ctx, node, *args, **kwargs):
37
+ seen = ctx.seen
38
+ key = id(node)
39
+ if key in seen:
40
+ return seen[key]
41
+ seen[key] = result = method(self, ctx, node, *args, **kwargs)
42
+ return result
43
+ return wrapper
44
+
45
+ #------------------------------------------------------
46
+ # Helpers
47
+ #------------------------------------------------------
48
+
49
+ def find_keys(item: Value | Statement, root_only: bool = False) -> list[Value]:
50
+ if isinstance(item, (Concept, Ref)):
51
+ return [item]
52
+ if isinstance(item, Chain):
53
+ keys = []
54
+ if not root_only and not isinstance(item._next, Property) and len(item._next._fields) > 1:
55
+ keys.extend([FieldRef(item, ix + 1, field, ix + 1) for ix, field in enumerate(item._next._fields[1:-1])])
56
+ keys.append(item)
57
+ keys.extend(find_keys(item._start, root_only))
58
+ return keys
59
+ if isinstance(item, Relationship):
60
+ if root_only:
61
+ return [item]
62
+ return list(item._fields[:-1])
63
+ if isinstance(item, FieldRef):
64
+ return find_keys(item._root, root_only)
65
+ if isinstance(item, Expression):
66
+ root = item._root if item._root is not None else item._op
67
+ is_func = isinstance(root, Relationship) and any(field.is_input for field in root._fields)
68
+ if root_only and item._root is not None and not(is_func):
69
+ # We ignore "function-like relationships" (those with inputs) since they are never a root
70
+ if isinstance(item._root, Relationship):
71
+ return [item]
72
+ return find_keys(item._root, root_only=True)
73
+ args = item._args[:-1] if isinstance(item._op, Property) else item._args
74
+ if is_func:
75
+ assert isinstance(root, Relationship)
76
+ args = [item._args[ix] for ix, field in enumerate(root._fields) if field.is_input]
77
+ keys = []
78
+ for arg in args:
79
+ keys.extend(find_keys(arg, root_only))
80
+ return keys
81
+ if isinstance(item, Fragment):
82
+ keys = []
83
+ for subitem in item._select:
84
+ keys.extend(find_keys(subitem, root_only))
85
+ return keys
86
+ if isinstance(item, DerivedColumn):
87
+ return find_keys(item._table, root_only)
88
+ if isinstance(item, Union):
89
+ # Unions should always act as sets and so have no keys
90
+ return []
91
+ if isinstance(item, Match):
92
+ keys = []
93
+ if root_only:
94
+ keys.extend(find_keys(item._items[0], root_only))
95
+ else:
96
+ for subitem in item._items:
97
+ keys.extend(find_keys(subitem, root_only))
98
+ return keys
99
+ if isinstance(item, TupleVariable):
100
+ keys = []
101
+ for subitem in item._items:
102
+ keys.extend(find_keys(subitem, root_only))
103
+ return keys
104
+ return []
105
+
106
+ def mm_value_type(value: mValue) -> TypeNode:
107
+ if isinstance(value, (Var, mLiteral)):
108
+ return value.type
109
+ elif isinstance(value, TypeNode):
110
+ return value
111
+ elif isinstance(value, Relation):
112
+ return RelationType
113
+ elif isinstance(value, Field):
114
+ return FieldType
115
+ elif isinstance(value, Iterable):
116
+ return TupleType(element_types=tuple(mm_value_type(v) for v in value))
117
+ elif value is None:
118
+ return NoneType
119
+ else:
120
+ raise NotImplementedError(f"mm_value_type not implemented for value type: {type(value)}")
121
+
122
+ @lru_cache(maxsize=1)
123
+ def _get_core():
124
+ from . import core
125
+ return core
126
+
127
+ @lru_cache(maxsize=1)
128
+ def _get_constraints():
129
+ from ..std import constraints
130
+ return constraints
131
+
132
+ def is_core_concept(concept):
133
+ core = _get_core()
134
+ if concept._model is core.Core:
135
+ return True
136
+ return any(is_core_concept(a) for a in concept._extends)
137
+
138
+ def concept_var_name(concept: Concept|Relationship) -> str:
139
+ if isinstance(concept, Relationship):
140
+ return sanitize(concept._short_name).lower()
141
+ core = _get_core()
142
+ if isinstance(concept, core.NumberConcept) or concept is core.Numeric:
143
+ return "number"
144
+ return sanitize(concept._name).lower()
145
+
146
+
147
+ #------------------------------------------------------
148
+ # Reference scheme handling
149
+ #------------------------------------------------------
150
+
151
+ def report_missing(concept:Concept, missing:OrderedSet[str], required:OrderedSet[str], source, ctx:Context):
152
+ if missing:
153
+ missing_str = ", ".join([f"`{name}`" for name in missing])
154
+ required_str = ", ".join([f"[bold red]{name}[/bold red]" if name in missing else name for name in required])
155
+ message = "values for properties" if len(missing) > 1 else "a value for property"
156
+ ctx.err("Missing identity", f"Missing {message} {missing_str} in concept `{concept._name}`.", [
157
+ err_source(source),
158
+ f"{concept._name} requires {required_str}"
159
+ ])
160
+ return True
161
+ return False
162
+
163
+ def make_construct(compiler:FrontCompiler,ctx:Context, concept:Concept, kwargs:dict[str, Any], ident_args:list[str], target:Var, source:Any=None):
164
+ construct_args:list[mValue] = [
165
+ ctx.to_value(concept._name),
166
+ *[compiler.lookup(ctx, kwargs[ident]) for ident in ident_args]
167
+ ]
168
+ return Construct(tuple(construct_args), target, source=source)
169
+
170
+ def handle_concept_expression(compiler:FrontCompiler, ctx:Context, expr:Expression) -> Var:
171
+ assert isinstance(expr._op, Concept)
172
+ source = expr._source
173
+ passed_concept = expr._op
174
+ kwargs = {k.lower(): v for k, v in expr._kwargs.items()}
175
+
176
+ root_concept = None
177
+ hierarchy:list[Concept] = []
178
+ constructs = KeyedDict[Concept, list[str]](dsl_key)
179
+ required = OrderedSet[str]()
180
+ missing = OrderedSet[str]()
181
+
182
+ def walk_extends(c:Concept):
183
+ nonlocal root_concept
184
+ if c in hierarchy:
185
+ return
186
+ for ext in c._extends:
187
+ walk_extends(ext)
188
+ hierarchy.append(c)
189
+ if c._identify_by and root_concept is None:
190
+ root_concept = c
191
+ ident_args = []
192
+ for ident_rel in c._identify_by:
193
+ ident = ident_rel._short_name.lower()
194
+ required.add(ident)
195
+ if ident in kwargs:
196
+ ident_args.append(ident)
197
+ else:
198
+ missing.add(ident)
199
+ constructs[c] = ident_args
200
+
201
+ walk_extends(passed_concept)
202
+
203
+ if root_concept is None:
204
+ root_concept = hierarchy[0]
205
+ if isinstance(expr, New) and expr._row_ids:
206
+ names = [f"_row_id_{t._name}" for t in expr._row_ids]
207
+ kwargs.update({name: expr._row_ids[ix] for ix, name in enumerate(names)})
208
+ constructs[root_concept] = list(sorted(names))
209
+ else:
210
+ constructs[root_concept] = list(sorted(kwargs.keys()))
211
+
212
+ root_id = ctx.to_value(expr)
213
+ assert isinstance(root_id, Var)
214
+ root_args = constructs[root_concept]
215
+
216
+ if isinstance(expr, New) and ctx.in_update:
217
+ # New requires that none of the identity args are missing
218
+ if report_missing(passed_concept, missing, required, source, ctx):
219
+ return root_id
220
+
221
+ # construct the root identity
222
+ ctx.add(make_construct(compiler, ctx, root_concept, kwargs, root_args, root_id, source=source))
223
+ if expr not in ctx.construct_handled:
224
+ ctx.add_update(passed_concept, [root_id], source=source)
225
+
226
+ # Update identity and non-identity attributes
227
+ for k, v in kwargs.items():
228
+ rel = passed_concept._dot(k)
229
+ ctx.add_update(rel, [root_id, compiler.lookup(ctx, v)], source=source)
230
+
231
+ ctx.construct_handled.add(expr)
232
+
233
+ elif isinstance(expr, New):
234
+ # New requires that none of the identity args are missing
235
+ if report_missing(passed_concept, missing, required, source, ctx):
236
+ return root_id
237
+
238
+ # just construct the root identity and then look it up in the subtype
239
+ # population
240
+ ctx.add(make_construct(compiler, ctx, root_concept, kwargs, root_args, root_id, source=source))
241
+ ctx.add_lookup(passed_concept, [root_id], source=source)
242
+
243
+ # Any non-identity attributes are filters
244
+ for k, v in kwargs.items():
245
+ if k not in root_args:
246
+ rel = passed_concept._dot(k)
247
+ ctx.add_lookup(rel, [root_id, compiler.lookup(ctx, v)], source=source)
248
+
249
+ elif isinstance(expr, FilterBy):
250
+ # check if _any_ concept has all the identity args it needs as a
251
+ if len(root_args) == len(root_concept._identify_by):
252
+ ctx.add(make_construct(compiler, ctx, root_concept, kwargs, root_args, root_id, source=source))
253
+ else:
254
+ # if we don't have all the identity args for the root, we need to look up any partials
255
+ root_args = []
256
+
257
+ ctx.add_lookup(passed_concept, [root_id], source=source)
258
+ for k, v in kwargs.items():
259
+ if k not in root_args:
260
+ rel = passed_concept._dot(k)
261
+ ctx.add_lookup(rel, [root_id, compiler.lookup(ctx, v)], source=source)
262
+ else:
263
+ exc("Invalid concept expression", f"Expected a `New` or `FilterBy` expression, got `{type(expr).__name__}`.", [err_source(source)])
264
+
265
+ return root_id
266
+
267
+ #------------------------------------------------------
268
+ # Match union branch keys
269
+ #------------------------------------------------------
270
+
271
+ def get_branch_keys(compiler:FrontCompiler, ctx:Context, branch:Match|Union) -> list[tuple[Value, Var]]:
272
+ keys = KeyedSet(dsl_key)
273
+ for item in branch._items:
274
+ if not isinstance(item, Fragment):
275
+ keys.update(find_keys(item))
276
+ branch_keys = []
277
+ seen_keys = set()
278
+ for key in keys:
279
+ k_var = ctx.to_value(key)
280
+ if k_var not in seen_keys and isinstance(k_var, Var) and not ctx.is_var_available(k_var, ignore_current=True):
281
+ seen_keys.add(k_var)
282
+ branch_keys.append((key, k_var))
283
+ return branch_keys
284
+
285
+ def normalize_branch_keys(compiler:FrontCompiler, ctx:Context, branch_keys:list[tuple[Value, Var]], branch:Statement):
286
+ for key, var in branch_keys:
287
+ if var not in ctx.frame_vars:
288
+ source = branch._source if isinstance(branch, DSLBase) else var.source
289
+ if not isinstance(key, (Concept, Ref)):
290
+ return ctx.err("Invalid branch", "Branch key must be a concept or reference.", [err_source(source)])
291
+ concept = key._to_concept()
292
+ if is_core_concept(concept):
293
+ return ctx.err("Invalid branch", "Branch key must be an entity, not a primitive.", [err_source(source)])
294
+ else:
295
+ ctx.add(Construct((ctx.to_value(concept._name + "_NONE_SENTINEL"),), var, source=key._source))
296
+
297
+
298
+ #------------------------------------------------------
299
+ # Context
300
+ #------------------------------------------------------
301
+
302
+ class Frame:
303
+ def __init__(self):
304
+ self.nodes:OrderedSet[Task] = OrderedSet()
305
+ self.in_update = False
306
+ self.used_vars:OrderedSet[Var] = OrderedSet()
307
+ self.seen:dict[Value, mValue] = {}
308
+
309
+ class Context:
310
+ def __init__(self, compiler:FrontCompiler):
311
+ self.compiler = compiler
312
+ self.stack:list[Frame] = [Frame()]
313
+ self.value_map:KeyedDict[Value|tuple[Value, Value], mValue] = KeyedDict(dsl_key)
314
+ self.has_error = False
315
+ self._in_update = False
316
+ self.construct_handled:KeyedSet[New] = KeyedSet(dsl_key)
317
+
318
+ #------------------------------------------------------
319
+ # subcontext
320
+ #------------------------------------------------------
321
+
322
+ @contextmanager
323
+ def subcontext(self):
324
+ self.stack.append(Frame())
325
+ try:
326
+ yield
327
+ finally:
328
+ prev = self.stack.pop()
329
+ self.stack[-1].used_vars.update(prev.used_vars)
330
+
331
+ #------------------------------------------------------
332
+ # in_update
333
+ #------------------------------------------------------
334
+
335
+ @contextmanager
336
+ def updating(self):
337
+ prev = self.in_update
338
+ self._in_update = True
339
+ try:
340
+ yield
341
+ finally:
342
+ self._in_update = prev
343
+ if not self._in_update:
344
+ self.construct_handled.clear()
345
+
346
+ @property
347
+ def in_update(self) -> bool:
348
+ return self._in_update
349
+
350
+ #------------------------------------------------------
351
+ # Errors/warnings
352
+ #------------------------------------------------------
353
+
354
+ def err(self, name: str, message: str, parts: Optional[list[Part]] = None) -> Diagnostic:
355
+ self.has_error = True
356
+ return err(name, message, parts)
357
+
358
+ def warn(self, name: str, message: str, parts: Optional[list[Part]] = None) -> Diagnostic:
359
+ self.has_error = True
360
+ return warn(name, message, parts)
361
+
362
+ #------------------------------------------------------
363
+ # Task capture
364
+ #------------------------------------------------------
365
+
366
+ def _check_frames(self, node:Task):
367
+ for frame in reversed(self.stack[:-1]):
368
+ if node in frame.nodes:
369
+ return True
370
+ return False
371
+
372
+ def add(self, node:Task):
373
+ if self._check_frames(node):
374
+ return
375
+ self.stack[-1].nodes.add(node)
376
+
377
+ def extend(self, nodes:Sequence[Task]):
378
+ for node in nodes:
379
+ self.add(node)
380
+
381
+ def add_lookup(self, relationship:Relationship|Concept, args:Sequence[mValue], source:Any=None):
382
+ op = self.compiler.to_relation(relationship)
383
+ hint = None
384
+ if isinstance(relationship, Reading):
385
+ hint = self.compiler.find_reading(relationship)
386
+ # reorder the args to match the correct ordering
387
+ new_args:list[Any] = [None] * len(hint.field_order)
388
+ for cur, new in enumerate(hint.field_order):
389
+ new_args[new] = args[cur]
390
+ args = new_args
391
+ self.add(Lookup(op, tuple(args), reading_hint=hint, source=source))
392
+
393
+ def add_update(self, relationship:Relationship|Concept, args:Sequence[mValue], effect=Effect.derive, source:Any=None):
394
+ op = self.compiler.to_relation(relationship)
395
+ hint = None
396
+ if isinstance(relationship, Reading):
397
+ hint = self.compiler.reading_map[relationship]
398
+ # reorder the args to match the correct ordering
399
+ new_args:list[Any] = [None] * len(hint.field_order)
400
+ for cur, new in enumerate(hint.field_order):
401
+ new_args[new] = args[cur]
402
+ args = new_args
403
+ self.add(Update(op, tuple(args), effect=effect, reading_hint=hint, source=source))
404
+
405
+ def add_eq(self, left:mValue, right:mValue, source:Any=None):
406
+ self.add(Lookup(getattr(bt.core, "="), (left, right), source=source))
407
+
408
+ @property
409
+ def nodes(self):
410
+ return self.stack[-1].nodes
411
+
412
+ #------------------------------------------------------
413
+ # Value mapping
414
+ #------------------------------------------------------
415
+
416
+ def to_value(self, value:Value, source:Optional[Value]=None) -> mValue:
417
+ key = (source, value) if source is not None else value
418
+ if res := self.value_map.get(key):
419
+ if isinstance(res, Var):
420
+ self.stack[-1].used_vars.add(res)
421
+ return res
422
+
423
+ node = None
424
+ if isinstance(value, Concept):
425
+ value_type = self.compiler.to_type(value)
426
+ node = Var(value_type, concept_var_name(value), source=value._source)
427
+ elif isinstance(value, Chain):
428
+ node = self.to_value(value._next._fields[-1], value)
429
+ elif isinstance(value, Ref):
430
+ value_type = self.compiler.to_type(value._concept)
431
+ name = sanitize(value._name).lower() if value._name else f"{concept_var_name(value._concept)}{value._id}"
432
+ node = Var(value_type, name, source=value._source)
433
+ elif isinstance(value, Field):
434
+ value_type = self.compiler.to_type(value.type)
435
+ node = Var(value_type, sanitize(value.name).lower())
436
+ elif isinstance(value, New):
437
+ value_type = self.compiler.to_type(value._op)
438
+ node = Var(value_type, f"{concept_var_name(value._op)}", source=value._source)
439
+ elif isinstance(value, FieldRef):
440
+ node = self.to_value(value._resolved, source=value._root)
441
+ elif isinstance(value, Expression):
442
+ node = self.to_value(value._args[-1])
443
+ elif isinstance(value, Aggregate):
444
+ node = self.to_value(value._args[-1])
445
+ elif isinstance(value, DerivedColumn):
446
+ value_type = self.compiler.to_type(value._type) if value._type is not None else bt.core.Any
447
+ node = Var(value_type, f"v", source=value._source)
448
+ elif isinstance(value, Literal):
449
+ value_type = self.compiler.to_type(value._type)
450
+ node = mLiteral(type=value_type, value=value._value, source=value._source)
451
+ elif isinstance(value, AsBool):
452
+ node = Var(bt.core.Boolean, f"v", source=value._source)
453
+ elif isinstance(value, MetaRef):
454
+ if isinstance(value._target, Concept):
455
+ node = self.compiler.to_type(value._target)
456
+ elif isinstance(value._target, Relationship):
457
+ node = self.compiler.to_relation(value._target)
458
+ elif isinstance(value._target, Field):
459
+ node = self.compiler.to_field(value._target)
460
+ else:
461
+ node = self.to_value(value._target)
462
+ elif is_primitive(value):
463
+ type_ = self.compiler.to_type(Literal._get_type(value))
464
+ node = mLiteral(type=type_, value=value)
465
+ else:
466
+ raise NotImplementedError(f"to_value not implemented for value type: {type(value)}")
467
+
468
+ if isinstance(node, Var):
469
+ self.stack[-1].used_vars.add(node)
470
+ self.value_map[key] = node
471
+ return node
472
+
473
+ @property
474
+ def frame_vars(self) -> OrderedSet[Var]:
475
+ return self.stack[-1].used_vars
476
+
477
+ def is_var_available(self, var:Var, ignore_current=False) -> bool:
478
+ stack = self.stack[:-1] if ignore_current else self.stack
479
+ for frame in reversed(stack):
480
+ if var in frame.used_vars:
481
+ return True
482
+ return False
483
+
484
+ @property
485
+ def seen(self) -> dict[Value, mValue]:
486
+ return self.stack[-1].seen
487
+
488
+ #------------------------------------------------------
489
+ # Compiler
490
+ #------------------------------------------------------
491
+
492
+ class FrontCompiler:
493
+ def __init__(self, model: Model):
494
+ self.model = model
495
+ self.relations:KeyedDict[DSLBase, Relation] = KeyedDict(dsl_key)
496
+ self.fields:KeyedDict[Field, mField] = KeyedDict(dsl_key)
497
+ self.reading_map: KeyedDict[Reading, mReading] = KeyedDict(dsl_key)
498
+ self.imported_libraries: set[Model] = set()
499
+ self.relation_constraints: OrderedSet[Lookup] = OrderedSet()
500
+ self.global_namer = Namer()
501
+
502
+ #------------------------------------------------------
503
+ # Library handling
504
+ #------------------------------------------------------
505
+
506
+ def check_import(self, node: Any):
507
+ if not isinstance(node, DSLBase):
508
+ return
509
+ if isinstance(node, Aggregate):
510
+ self.check_import(node._op)
511
+ model = node._model
512
+ if model and model != self.model and model not in self.imported_libraries:
513
+ if model not in self.model.libraries:
514
+ self.model.libraries.append(model)
515
+ self.imported_libraries.add(model)
516
+ self.relations.update(model._compiler.relations)
517
+ self.relation_constraints.update(model._compiler.relation_constraints)
518
+ return True
519
+
520
+ #------------------------------------------------------
521
+ # Model elements
522
+ #------------------------------------------------------
523
+
524
+ def find_reading(self, reading:Reading) -> mReading:
525
+ if found := self.reading_map.get(reading):
526
+ return found
527
+ # It's possible that readings were added after the first time we encounter
528
+ # the relationship, so we need to re-create them here and update the relationship
529
+ root = reading._relationship
530
+ rel = self.to_relation(root)
531
+ readings = self.to_readings(root, start=len(rel.readings))
532
+ rel._dangerous_set_readings(rel.readings + readings)
533
+ return self.reading_map[reading]
534
+
535
+ def to_readings(self, relationship: Relationship, start=0) -> tuple[mReading, ...]:
536
+ readings = tuple(mReading(name=reading._short_name, parts=tuple(reading._parts), source=reading._source) for reading in relationship._readings[start:])
537
+ self.reading_map.update((reading, mreading) for reading, mreading in zip(relationship._readings[start:], readings))
538
+ return readings
539
+
540
+ def to_annotation(self, node: Expression | Relationship) -> Annotation:
541
+ if isinstance(node, Expression):
542
+ args = []
543
+ for arg in node._args:
544
+ if isinstance(arg, Literal):
545
+ args.append(mLiteral(type=self.to_type(arg._type), value=arg._value, source=arg._source))
546
+ elif isinstance(arg, Concept) or isinstance(arg, Relationship):
547
+ args.append(self.to_relation(arg))
548
+ elif isinstance(arg, Chain):
549
+ args.append(self.to_relation(arg._next))
550
+ else:
551
+ exc("Invalid annotation", f"Invalid annotation argument type: {type(arg).__name__}", [
552
+ err_source(arg._source),
553
+ "Only Concepts, Relationships, and Literals are allowed as annotation arguments."
554
+ ])
555
+ return Annotation(relation=self.to_relation(node._op), args=tuple(args), source=node._source)
556
+ elif isinstance(node, Relationship):
557
+ return Annotation(relation=self.to_relation(node), args=(), source=node._source)
558
+ else:
559
+ raise ValueError(f"Unknown annotation type: {type(node)} - {node}")
560
+
561
+ def to_field(self, node: Field) -> mField:
562
+ if res := self.fields.get(node):
563
+ return res
564
+ field_type = self.to_type(node.type)
565
+ if node.is_list:
566
+ field_type = ListType(element_type=field_type)
567
+ field = mField(name=node.name, type=field_type, input=node.is_input, source=node._source)
568
+ self.fields[node] = field
569
+ return field
570
+
571
+ def to_relation(self, node: Any) -> Relation:
572
+ if res := self.relations.get(node):
573
+ return res
574
+ elif self.check_import(node) and (res := self.relations.get(node)):
575
+ return res
576
+
577
+ rel = None
578
+ if isinstance(node, Reading):
579
+ rel = self.to_relation(node._relationship)
580
+ elif isinstance(node, Relationship):
581
+ annos = tuple(self.to_annotation(anno) for anno in node._annotations)
582
+ readings = self.to_readings(node)
583
+ fields = [self.to_field(field) for field in node._fields]
584
+ if node._short_name == '':
585
+ name = self.global_namer.get_name(sub(r"[{}: ]", "_", str(node._readings[0]._reading)).strip("_"))
586
+ else:
587
+ name = node._short_name
588
+ overloads = []
589
+ if node._overloads:
590
+ for overload in node._overloads:
591
+ overload_types = tuple(self.to_type(concept) for concept in overload)
592
+ overloads.append(Overload(overload_types))
593
+ if node._is_unresolved:
594
+ rel = UnresolvedRelation(name=name, fields=tuple(fields), source=node._source, readings=readings, annotations=annos, overloads=tuple(overloads))
595
+ else:
596
+ rel = Relation(name=name, fields=tuple(fields), source=node._source, readings=readings, annotations=annos, overloads=tuple(overloads))
597
+ if isinstance(node, Property):
598
+ # Add a uniqueness constraint for properties
599
+ _get_constraints()
600
+ self.relation_constraints.add(Lookup(bt.constraints.unique_fields, (tuple(fields[:-1]),)))
601
+ elif isinstance(node, Data):
602
+ rel = mData(name=f"Data{node._id}", data=node._data, source=node._source)
603
+ self.relations[node] = rel
604
+ rel._force_columns(tuple(self.to_relation(col) for col in node._columns))
605
+ elif isinstance(node, Table):
606
+ rel = mTable(name=node._name, source=node._source)
607
+ self.relations[node] = rel
608
+ rel._force_columns(tuple(self.to_relation(col) for col in node._columns))
609
+ elif isinstance(node, NumberConcept):
610
+ super_types=tuple(self.to_type(ancestor) for ancestor in node._extends)
611
+ rel = NumberType(name=node._name, precision=node._precision, scale=node._scale, source=node._source, super_types=super_types)
612
+ elif isinstance(node, Concept):
613
+ annos = tuple(self.to_annotation(anno) for anno in node._annotations)
614
+ super_types=tuple(self.to_type(ancestor) for ancestor in node._extends)
615
+ rel = ScalarType(name=node._name, annotations=annos, source=node._source, super_types=super_types)
616
+ self.relations[node] = rel
617
+ identify_by_rels = tuple(self.to_relation(rel) for rel in node._identify_by)
618
+ rel._force_identify_by(identify_by_rels)
619
+ else:
620
+ raise ValueError(f"Unknown node type: {type(node)} - {node}")
621
+ self.relations[node] = rel
622
+ return rel
623
+
624
+ def to_type(self, node: Any) -> ScalarType:
625
+ rel = self.to_relation(node)
626
+ if not isinstance(rel, ScalarType):
627
+ raise ValueError(f"Node is not a ScalarType: {node}")
628
+ return rel
629
+
630
+ #------------------------------------------------------
631
+ # Compile
632
+ #------------------------------------------------------
633
+
634
+ def compile(self, fragment: Fragment) -> Task|list[Task]:
635
+ ctx = Context(self)
636
+ # pprint(fragment)
637
+ return self.fragment(ctx, fragment)
638
+
639
+ def compile_model(self, model: Model) -> mModel:
640
+ def as_seq(x):
641
+ return x if isinstance(x, (list, tuple)) else (x,)
642
+
643
+ # init enums
644
+ for enum in model.enums:
645
+ enum._init_members()
646
+
647
+ self.check_invariants(model)
648
+
649
+ for concept in model.concepts:
650
+ self.to_relation(concept)
651
+ for relationship in model.relationships:
652
+ self.to_relation(relationship)
653
+ for table in model.tables:
654
+ self.to_relation(table)
655
+
656
+ # compile + flatten defines/requires in one pass
657
+ compiled:list[Task] = []
658
+ compiled.extend(chain.from_iterable(
659
+ as_seq(self.compile(item)) for item in chain(model.defines, model.requires)
660
+ ))
661
+ # partition relation values into types vs non-types
662
+ rel_vals = list(self.relations.values())
663
+ types = tuple(r for r in rel_vals if isinstance(r, TypeNode))
664
+ relations = tuple(r for r in rel_vals if not isinstance(r, TypeNode))
665
+
666
+ compiled.insert(0, Require(check=Logical(tuple(self.relation_constraints), source=model._source)))
667
+
668
+ source = model._source
669
+ root = Logical(tuple(compiled), source=source)
670
+
671
+ return mModel(
672
+ reasoners=(),
673
+ relations=relations,
674
+ types=types,
675
+ root=root,
676
+ source=source,
677
+ )
678
+
679
+ #------------------------------------------------------
680
+ # Invariants
681
+ #------------------------------------------------------
682
+
683
+ def check_invariants(self, model: Model):
684
+ # Ensure that all concepts with identify_by have at least one relationship
685
+ has_errors = False
686
+ for concept in model.concepts:
687
+ for k, v in concept._relationships.items():
688
+ for ext in concept._extends:
689
+ if k in ext._relationships:
690
+ kind = "Property" if isinstance(v, Property) else "Relationship"
691
+ parent_kind = "property" if isinstance(ext._relationships[k], Property) else "relationship"
692
+ err(f"{kind} conflict",
693
+ f"{kind} `{k}` in concept `{concept._name}` conflicts with {parent_kind} in parent concept `{ext._name}`.",
694
+ [
695
+ f"Parent {parent_kind}",
696
+ err_source(ext._relationships[k]),
697
+ f"Child {kind.lower()}",
698
+ err_source(v)
699
+ ])
700
+ has_errors = True
701
+
702
+ if has_errors:
703
+ exc("Invalid model", "Model has invariant violations, see errors for details.")
704
+
705
+ #------------------------------------------------------
706
+ # Fragment
707
+ #------------------------------------------------------
708
+
709
+ def fragment(self, ctx: Context, fragment: Fragment):
710
+ if fragment._require:
711
+ return self.require(ctx, fragment, scope=True)
712
+ else:
713
+ annos = tuple(self.to_annotation(anno) for anno in fragment._annotations)
714
+ self.where(ctx, fragment, fragment._where)
715
+ self.select(ctx, fragment, fragment._select)
716
+ self.define(ctx, fragment, fragment._define)
717
+ return Logical(tuple(ctx.nodes), scope=True, annotations=annos, source=fragment._source)
718
+
719
+ #------------------------------------------------------
720
+ # Where
721
+ #------------------------------------------------------
722
+
723
+ def where(self, ctx: Context, fragment:Fragment, exprs: list[Value]):
724
+ for expr in exprs:
725
+ self.lookup(ctx, expr)
726
+
727
+ #------------------------------------------------------
728
+ # Select
729
+ #------------------------------------------------------
730
+
731
+ def select(self, ctx: Context, fragment:Fragment, exprs: Sequence[Value]):
732
+ if not exprs:
733
+ return
734
+
735
+ source = fragment._source
736
+ output_name = f"output{fragment._id}"
737
+
738
+ uri = f"dataframe://{output_name}" if fragment._into is None else f"table://{fragment._into._name}"
739
+ table = mTable(name=f"Output{fragment._id}", uri=uri, source=source)
740
+ table_var = Var(type=table, name=output_name, source=source)
741
+
742
+ keys:KeyedSet[Value] = KeyedSet(dsl_key)
743
+ items:list[Task] = []
744
+
745
+ # Unwrap distinct if present
746
+ is_distinct = any(isinstance(expr, Distinct) for expr in exprs)
747
+ if is_distinct:
748
+ if len(exprs) != 1 or not isinstance(exprs[0], Distinct):
749
+ return ctx.err("Invalid distinct", "Distinct must be applied to the entire select.", [
750
+ err_source(source)
751
+ ])
752
+ exprs = exprs[0]._items
753
+
754
+ # Build out the table columns
755
+ # v0, v1, etc, for generic elements like literals or the unnamed result of union/matches
756
+ range_namer = Namer(range=True)
757
+ # v, v_2, v_3, etc, for elements where we want to preserve the original name if there
758
+ # are no collisions, like chain expressions, aggregates, etc
759
+ namer = Namer()
760
+
761
+ # we have to first find all the roots, the roots need to be looked up in the outer scope
762
+ # we then need to find the keys for each expr, any keys that aren't roots need to be added
763
+ # to the column relation
764
+ roots = KeyedSet(dsl_key)
765
+ for expr in exprs:
766
+ if is_distinct:
767
+ roots.add(expr)
768
+ else:
769
+ roots.update(find_keys(expr, root_only=True))
770
+
771
+ # look the roots up in the outer scope
772
+ root_vars:OrderedSet[mValue] = OrderedSet()
773
+ for root in roots:
774
+ root_v = self.lookup(ctx, root)
775
+ # For top-level relationships, the fields of the relationship are
776
+ # the root vars, since all of them behave like keys. For Properties,
777
+ # we ignore the last field since it's functionally determined by the others.
778
+ # Expressions use their args
779
+ if isinstance(root, Property):
780
+ root_vars.update(ctx.to_value(field) for field in root._fields[:-1])
781
+ elif isinstance(root, Relationship):
782
+ root_vars.update(ctx.to_value(field) for field in root._fields)
783
+ elif isinstance(root, Expression):
784
+ root_vars.update(ctx.to_value(arg) for arg in root._args)
785
+ else:
786
+ root_vars.add(root_v)
787
+
788
+ # handle order_by/limit
789
+ if fragment._order_by or fragment._limit != 0:
790
+ from ..std.aggregates import _sort_agg
791
+ args = fragment._order_by if fragment._order_by else fragment._select
792
+ sort_agg = _sort_agg(fragment._limit, *args)
793
+ self.lookup(ctx, sort_agg)
794
+
795
+ # build columns
796
+ table_cols = []
797
+ for expr in exprs:
798
+ expr_keys = [expr] if is_distinct else find_keys(expr)
799
+
800
+ with ctx.subcontext():
801
+ col = self.lookup(ctx, expr)
802
+ # Columns may need their own keys beyond the roots to guarantee that multiple values end up
803
+ # available for the same root. E.g. people having multiple pets
804
+ maybe_col_keys = [ctx.to_value(col_key) for col_key in expr_keys]
805
+ col_keys = [col_key for col_key in maybe_col_keys
806
+ if isinstance(col_key, Var) and col_key != col and col_key not in root_vars]
807
+ col_key_fields = [mField(name=key.name, type=key.type) for key in col_keys]
808
+
809
+ # build the relation
810
+ col_name = (expr._alias if isinstance(expr, Alias) else
811
+ range_namer.get_name(col.name) if isinstance(col, Var) and isinstance(expr, (Union, Match)) else
812
+ namer.get_name(self.to_relation(expr._op).name) if isinstance(expr, Aggregate) else
813
+ namer.get_name(col.name) if isinstance(col, Var) else
814
+ range_namer.get_name("v"))
815
+ col_type = mm_value_type(col)
816
+ col_relation = Relation(col_name, (
817
+ mField(name="table", type=table),
818
+ *col_key_fields,
819
+ mField(name=col_name, type=col_type)
820
+ ), source=source)
821
+ table_cols.append(col_relation)
822
+
823
+ # The shim needs a hint that this output is both a key and a value
824
+ annos = ()
825
+ if col in maybe_col_keys and col not in root_vars:
826
+ annos = (Annotation(relation=bt.core["output_value_is_key"], args=(), source=source),)
827
+ ctx.add(Update(col_relation, args=tuple([table_var, *col_keys, col]), annotations=annos, source=source))
828
+
829
+ optional = True
830
+ # rank and limit should always just get pushed to the root - they can never be null
831
+ if isinstance(expr, Aggregate):
832
+ op = self.to_relation(expr._op)
833
+ optional = not (op is bt.aggregates.rank or op is bt.aggregates.limit)
834
+
835
+ node_tuple = tuple(ctx.nodes)
836
+ if len(ctx.nodes) == 1:
837
+ items.append(node_tuple[0])
838
+ else:
839
+ items.append(Logical(node_tuple, source=source, optional=optional))
840
+
841
+ # add the columns to the output table
842
+ table._force_columns(tuple(table_cols))
843
+
844
+ # Construct followed by adding the row to the table and then each column
845
+ ctx.add(Construct(tuple(root_vars), table_var, source=source))
846
+ ctx.add(Update(table, tuple([table_var]), source=source))
847
+ ctx.extend(items)
848
+
849
+ #------------------------------------------------------
850
+ # Define
851
+ #------------------------------------------------------
852
+
853
+ def define(self, ctx: Context, fragment:Fragment, exprs: list[Value]):
854
+ with ctx.updating():
855
+ for expr in exprs:
856
+ source = expr._source if isinstance(expr, DSLBase) else fragment._source
857
+ with ctx.subcontext():
858
+ self.update(ctx, expr, root_source=fragment._source)
859
+ nodes = tuple(ctx.nodes)
860
+ ctx.add(Logical(nodes, source=source, optional=True))
861
+
862
+ #------------------------------------------------------
863
+ # Require
864
+ #------------------------------------------------------
865
+
866
+ def require(self, ctx: Context, fragment:Fragment, scope:bool=False):
867
+ source = fragment._source
868
+ reqs = []
869
+ annos = tuple(self.to_annotation(anno) for anno in fragment._annotations)
870
+ with ctx.subcontext():
871
+ self.where(ctx, fragment, fragment._where)
872
+ domain_body = tuple(ctx.nodes)
873
+ domain_vars = ctx.frame_vars
874
+ for expr in fragment._require:
875
+ with ctx.subcontext():
876
+ self.lookup(ctx, expr)
877
+ check = Logical(tuple(ctx.nodes), source=source)
878
+ hoisted = tuple(v for v in ctx.frame_vars if v in domain_vars)
879
+ reqs.append(Require(Logical(domain_body, source=source), check, scope=scope, annotations=annos, source=source))
880
+ if len(reqs) == 1:
881
+ return reqs[0]
882
+ return reqs
883
+
884
+ #------------------------------------------------------
885
+ # Lookup
886
+ #------------------------------------------------------
887
+
888
+ # @memoize_in_ctx
889
+ def lookup(self, ctx: Context, node: Any) -> mValue:
890
+ source = node._source if not is_primitive(node) else None
891
+ self.check_import(node)
892
+
893
+ #------------------------------------------------------
894
+ # Concept / Concept expressions (includes Data and Table)
895
+ #------------------------------------------------------
896
+
897
+ if isinstance(node, Concept):
898
+ final_var = ctx.to_value(node)
899
+ if not is_core_concept(node):
900
+ ctx.add_lookup(node, [final_var], source=source)
901
+ return final_var
902
+
903
+ elif isinstance(node, Ref):
904
+ final_var = ctx.to_value(node)
905
+ if not is_core_concept(node._concept):
906
+ ctx.add_lookup(node._concept, [final_var], source=source)
907
+ return final_var
908
+
909
+ elif isinstance(node, New):
910
+ # If we encounter a New nested inside of an update, we want to treat this
911
+ # new as an update as well so that you can write Person.new(.., pet=Pet.new(..))
912
+ if ctx.in_update and not node._identity_only:
913
+ return self.update(ctx, node, root_source=node._source)
914
+
915
+ # Otherwise we're just checking this exists
916
+ return handle_concept_expression(self, ctx, node)
917
+
918
+ elif isinstance(node, FilterBy):
919
+ return handle_concept_expression(self, ctx, node)
920
+
921
+ #------------------------------------------------------
922
+ # Relationship
923
+ #------------------------------------------------------
924
+
925
+ elif isinstance(node, Relationship):
926
+ # we need vars for each field, but how do we store them?
927
+ args = [ctx.to_value(field) for field in node._fields]
928
+ ctx.add_lookup(node, args, source=source)
929
+ return args[-1]
930
+
931
+ elif isinstance(node, FieldRef):
932
+ self.lookup(ctx, node._root)
933
+ # If the source of the field ref is an expression, this is an ArgumentRef, so
934
+ # return the expression var directly
935
+ if isinstance(node._root, Expression):
936
+ return self.lookup(ctx, node._root._args[node._resolved_ix])
937
+ # If this is a reference to the relationship itself, then we want that to
938
+ # unify with any other references to the given field. If it's through a chain
939
+ # or expression, then it should be sourced from there.
940
+ field_source = node._root if not isinstance(node._root, Relationship) else None
941
+ return ctx.to_value(node._resolved, source=field_source)
942
+
943
+ #------------------------------------------------------
944
+ # Expressions
945
+ #------------------------------------------------------
946
+
947
+ elif isinstance(node, Expression):
948
+ # For auto-filled expressions, there's no reason to lookup the last ref and
949
+ # do a population check
950
+ if node._auto_filled:
951
+ args = [self.lookup(ctx, arg) for arg in node._args[:-1]] + [ctx.to_value(node._args[-1])]
952
+ ctx.add_lookup(node._op, args, source=source)
953
+ return args[-1]
954
+ # if we are casting e.g. with something like `Discount(0.6)` we should return a literal with that
955
+ # type
956
+ elif isinstance(node._op, Concept) and is_core_concept(node._op):
957
+ if isinstance(node._args[0], Literal):
958
+ return mLiteral(type=self.to_type(node._op), value=node._args[0]._value, source=source)
959
+ else:
960
+ cur = self.lookup(ctx, node._args[-1])
961
+ ret = ctx.to_value(node._op, source=node)
962
+ ctx.add_lookup(CoreRelationships["cast"], [self.to_type(node._op), cur, ret], source=source)
963
+ return ret
964
+ # Normal expression
965
+ else:
966
+ args = [self.lookup(ctx, a) for a in node._args]
967
+ ctx.add_lookup(node._op, args, source=source)
968
+ return args[-1]
969
+
970
+ elif isinstance(node, Chain):
971
+ start = self.lookup(ctx, node._start)
972
+ final_var = ctx.to_value(node)
973
+ # Unaries are special, the chain's var is just the start var
974
+ if len(node._next._fields) == 1:
975
+ ctx.add_lookup(node._next, [start], source=source)
976
+ return start
977
+ else:
978
+ # If the relation has more than 2 fields, we need to create vars for the
979
+ # unreferrenced ones in the middle
980
+ middle_args = [ctx.to_value(field, source=node) for field in node._next._fields[1:-1]]
981
+ args = [start, *middle_args, final_var]
982
+ ctx.add_lookup(node._next, args, source=source)
983
+ return final_var
984
+
985
+ #------------------------------------------------------
986
+ # Aggregates
987
+ #------------------------------------------------------
988
+
989
+ elif isinstance(node, Aggregate):
990
+ agg = self.to_relation(node._op)
991
+ input_args = [arg for ix, arg in enumerate(node._args) if agg.fields[ix].input]
992
+
993
+ proj_set:KeyedSet[Value] = KeyedSet(dsl_key)
994
+ if not node._distinct:
995
+ for item in [*node._projection_args, *input_args]:
996
+ proj_set.update(find_keys(item))
997
+ proj_set.update(node._projection_args)
998
+ proj = cast(OrderedSet[Var], OrderedSet([ctx.to_value(p) for p in proj_set]))
999
+ group = cast(list[Var], [self.lookup(ctx, arg) for arg in node._group._args])
1000
+
1001
+ if agg is bt.aggregates.rank:
1002
+ assert isinstance(node._args[0], TupleVariable)
1003
+ for arg in node._args[0]._items:
1004
+ self.lookup(ctx, arg)
1005
+ elif agg is bt.aggregates.limit:
1006
+ assert isinstance(node._args[1], TupleVariable)
1007
+ for arg in node._args[1]._items:
1008
+ self.lookup(ctx, arg)
1009
+
1010
+ with ctx.subcontext():
1011
+ for item in node._where._where:
1012
+ self.lookup(ctx, item)
1013
+ for projected in proj_set:
1014
+ self.lookup(ctx, projected)
1015
+ args = cast(list[Var], [self.lookup(ctx, arg) for arg in node._args])
1016
+ where = Logical(tuple(ctx.nodes), source=source)
1017
+
1018
+ ctx.add(mAggregate(agg, tuple(proj), tuple(group), tuple(args), where, source=source))
1019
+ return args[-1] if not isinstance(args[-1], tuple) else None
1020
+
1021
+ elif isinstance(node, Group):
1022
+ for arg in node._args:
1023
+ self.lookup(ctx, arg)
1024
+ return
1025
+
1026
+ #------------------------------------------------------
1027
+ # Quantifiers
1028
+ #------------------------------------------------------
1029
+
1030
+ elif isinstance(node, Not):
1031
+ with ctx.subcontext():
1032
+ for item in node._items:
1033
+ self.lookup(ctx, item)
1034
+ not_ = mNot(Logical(tuple(ctx.nodes)), source=source)
1035
+ ctx.add(not_)
1036
+ return
1037
+
1038
+ #------------------------------------------------------
1039
+ # Nested fragment
1040
+ #------------------------------------------------------
1041
+
1042
+ elif isinstance(node, Fragment):
1043
+ if node._require or node._define:
1044
+ ctx.err("Invalid subquery", "Nested queries with `require` or `define` are not supported.", [
1045
+ err_source(source)
1046
+ ])
1047
+ if node._select:
1048
+ with ctx.subcontext():
1049
+ for where in node._where:
1050
+ self.lookup(ctx, where)
1051
+ # cols = cast(ISeq[Var], tuple(ctx.to_value(col) for col in node._columns))
1052
+ vals = [self.lookup(ctx, sel) for sel in node._select]
1053
+ ctx.value_map.update(zip(node._columns, vals))
1054
+ # for col, val in zip(cols, vals):
1055
+ # ctx.add_eq(col, val, source=source)
1056
+ nodes = tuple(ctx.nodes)
1057
+ ctx.add(Logical(nodes, source=source))
1058
+ return vals[-1]
1059
+ else:
1060
+ for where in node._where:
1061
+ self.lookup(ctx, where)
1062
+ return None
1063
+
1064
+ #------------------------------------------------------
1065
+ # Match / Union
1066
+ #------------------------------------------------------
1067
+
1068
+ elif isinstance(node, (Match, Union)):
1069
+ branches = []
1070
+ outputs = cast(ISeq[Var], tuple(ctx.to_value(col) for col in node._columns) if node._arg_count() > 0 else tuple())
1071
+ branch_keys = get_branch_keys(self, ctx, node)
1072
+ for item in node._items:
1073
+ item_source = item._source if isinstance(item, Variable) else source
1074
+ if isinstance(item, Fragment):
1075
+ if item._select:
1076
+ # map the select columns to the match/union outputs
1077
+ for ix, col in enumerate(item._columns):
1078
+ ctx.value_map[col] = outputs[ix]
1079
+ with ctx.subcontext():
1080
+ self.lookup(ctx, item)
1081
+ # unwrap the nested logical
1082
+ wrapper = ctx.nodes[0]
1083
+ assert isinstance(wrapper, Logical)
1084
+ for subnode in wrapper.body:
1085
+ ctx.add(subnode)
1086
+
1087
+ normalize_branch_keys(self, ctx, branch_keys, item)
1088
+ # add the output column equalities
1089
+ for ix, col in enumerate(item._columns):
1090
+ ctx.add_eq(outputs[ix], ctx.to_value(col), source=item_source)
1091
+ branches.append(Logical(tuple(ctx.nodes)[1:], source=item_source))
1092
+ else:
1093
+ with ctx.subcontext():
1094
+ for where in item._where:
1095
+ self.lookup(ctx, where)
1096
+ branches.append(Logical(tuple(ctx.nodes), source=item_source))
1097
+ else:
1098
+ with ctx.subcontext():
1099
+ res = self.lookup(ctx, item)
1100
+ normalize_branch_keys(self, ctx, branch_keys, item)
1101
+ if outputs:
1102
+ ctx.add_eq(outputs[0], res, source=item_source)
1103
+ branches.append(Logical(tuple(ctx.nodes), source=item_source))
1104
+
1105
+ if isinstance(node, Union):
1106
+ ctx.add(mUnion(tuple(branches), source=source))
1107
+ else:
1108
+ ctx.add(mMatch(tuple(branches), source=source))
1109
+
1110
+ return outputs[-1] if outputs else None
1111
+
1112
+ #------------------------------------------------------
1113
+ # Value-likes
1114
+ #------------------------------------------------------
1115
+
1116
+ elif isinstance(node, (Field, MetaRef)):
1117
+ return ctx.to_value(node)
1118
+
1119
+ elif isinstance(node, TupleVariable):
1120
+ # exc("TupleVariable unsupported", "TupleVariable is not supported yet.", [err_source(source)])
1121
+ items = [self.lookup(ctx, item) for item in node._items]
1122
+ return tuple(items)
1123
+
1124
+ elif isinstance(node, TableSchema):
1125
+ exc("Invalid value", "A schema cannot be used as a value outside of a `.new(..)` or `.select(..)` call.", [err_source(source)])
1126
+ return None
1127
+
1128
+ elif is_primitive(node):
1129
+ type_ = self.to_type(Literal._get_type(node))
1130
+ return mLiteral(type_, node)
1131
+
1132
+ elif isinstance(node, DerivedColumn):
1133
+ self.lookup(ctx, node._table)
1134
+ return ctx.to_value(node)
1135
+
1136
+ elif isinstance(node, Literal):
1137
+ return mLiteral(type=self.to_type(node._type), value=node._value, source=source)
1138
+
1139
+ elif isinstance(node, ModelEnum):
1140
+ return self.lookup(ctx, node._compile_lookup())
1141
+
1142
+ elif isinstance(node, Alias):
1143
+ return self.lookup(ctx, node._source)
1144
+
1145
+ elif isinstance(node, AsBool):
1146
+ # we need to create a match with two branches that returns true/false
1147
+ out = ctx.to_value(node)
1148
+ assert isinstance(out, Var)
1149
+ with ctx.subcontext():
1150
+ self.lookup(ctx, node._item)
1151
+ ctx.add_eq(out, mLiteral(bt.core.Boolean, True), source=node._source)
1152
+ true_branch = Logical(tuple(ctx.nodes), source=source)
1153
+ with ctx.subcontext():
1154
+ ctx.add_eq(out, mLiteral(bt.core.Boolean, False), source=node._source)
1155
+ false_branch = Logical(tuple(ctx.nodes), source=source)
1156
+ ctx.add(mMatch((true_branch, false_branch), source=source))
1157
+ return out
1158
+
1159
+ #------------------------------------------------------
1160
+ # Invalid nodes
1161
+ #------------------------------------------------------
1162
+
1163
+ elif isinstance(node, Distinct):
1164
+ ctx.err("Invalid distinct", "Distinct can only be used in `select(distinct(..))` or aggregates like `count(distinct(..))`.", [
1165
+ err_source(source)
1166
+ ])
1167
+ return None
1168
+
1169
+ else:
1170
+ raise NotImplementedError(f"Lookup not implemented for node type: {type(node)}")
1171
+
1172
+ #------------------------------------------------------
1173
+ # Update
1174
+ #------------------------------------------------------
1175
+
1176
+ def update(self, ctx: Context, node: Any, root_source:SourcePos) -> mValue:
1177
+ source = node._source if not is_primitive(node) else root_source
1178
+ self.check_import(node)
1179
+
1180
+ #------------------------------------------------------
1181
+ # Concept / Concept expressions (includes Data and Table)
1182
+ #------------------------------------------------------
1183
+
1184
+ if isinstance(node, Concept):
1185
+ final_var = ctx.to_value(node)
1186
+ ctx.add_update(node, [final_var], source=source)
1187
+ return final_var
1188
+
1189
+ elif isinstance(node, New):
1190
+ if node._identity_only:
1191
+ ctx.err("Invalid define", "Cannot define just an identity.", [
1192
+ err_source(source),
1193
+ "Did you mean to use `.new(..)`?"
1194
+ ])
1195
+ return
1196
+ return handle_concept_expression(self, ctx, node)
1197
+
1198
+ #------------------------------------------------------
1199
+ # Relationship
1200
+ #------------------------------------------------------
1201
+
1202
+ elif isinstance(node, Relationship):
1203
+ ctx.err("Invalid define", "Cannot define a relationship without values for its fields.", [
1204
+ err_source(root_source),
1205
+ ])
1206
+
1207
+ #------------------------------------------------------
1208
+ # Expressions
1209
+ #------------------------------------------------------
1210
+
1211
+ elif isinstance(node, Expression):
1212
+ if node._auto_filled or len(node._args) == 0:
1213
+ field_name = node._op._fields[-1].name if isinstance(node._op, Relationship) else node._op._name.lower()
1214
+ ctx.err("Invalid define", f"Define requires that all args be provided, but the value for the `{field_name}` field is missing.", [
1215
+ err_source(source),
1216
+ ])
1217
+ return
1218
+ args = [self.lookup(ctx, arg) for arg in node._args]
1219
+ if node._op is CoreRelationships["="]:
1220
+ if isinstance(node._args[0], (Relationship, Chain)):
1221
+ return self.update(ctx, node._args[0](node._args[1]), root_source=source)
1222
+ elif isinstance(node._args[1], (Relationship, Chain)):
1223
+ return self.update(ctx, node._args[1](node._args[0]), root_source=source)
1224
+ else:
1225
+ ctx.err("Invalid define", "Cannot set a non-relationship via `=` in a define.", [
1226
+ err_source(source),
1227
+ ])
1228
+ else:
1229
+ if isinstance(node._op, Concept) and is_core_concept(node._op):
1230
+ return self.lookup(ctx, node)
1231
+ ctx.add_update(node._op, args, source=source)
1232
+ return args[-1]
1233
+
1234
+ elif isinstance(node, Chain):
1235
+ # all fields have to be specified for a define, so a chain only works
1236
+ # if the relationship is unary
1237
+ if len(node._next._fields) > 1:
1238
+ ctx.err("Invalid define", "All fields must have a value when defining a relationship.", [
1239
+ err_source(source),
1240
+ f"You need something like [cyan]`.{node._next._short_name}(" + ", ".join([field.name for field in node._next._fields[1:]]) + ")`"
1241
+ ])
1242
+ return
1243
+
1244
+ start = self.lookup(ctx, node._start)
1245
+ ctx.add_update(node._next, [start], source=source)
1246
+ return start
1247
+
1248
+ #------------------------------------------------------
1249
+ # Invalids
1250
+ #------------------------------------------------------
1251
+
1252
+ elif is_primitive(node):
1253
+ ctx.err("Invalid define", "Cannot define a primitive value.", [
1254
+ err_source(source)
1255
+ ])
1256
+ return
1257
+
1258
+ elif isinstance(node, (FilterBy, Ref, FieldRef, Aggregate, Group, Not, Fragment, Match, Field, DerivedColumn, Literal, Alias, Distinct)):
1259
+ ctx.err("Invalid define", f"Cannot define a value of type `{type(node).__name__}`.", [
1260
+ err_source(node._source)
1261
+ ])
1262
+ return
1263
+
1264
+ else:
1265
+ raise NotImplementedError(f"Lookup not implemented for node type: {type(node)}")
1266
+
1267
+
1268
+
1269
+ #------------------------------------------------------
1270
+ # TODO
1271
+ #------------------------------------------------------
1272
+ """
1273
+ - vars shared between columns need to end up as column keys
1274
+ - check sub-selects now that we went back to optional logicals
1275
+ - roots for union/matches/fragments
1276
+ - ref scheme mappings
1277
+ - what do we want to do about Error/require errors?
1278
+ - None columns in selects
1279
+
1280
+ x Concept
1281
+ x DerivedColumn
1282
+ x Field
1283
+ x Relationship
1284
+ x Reading
1285
+ x Property
1286
+ x Literal
1287
+ x Chain
1288
+ x Expression
1289
+ x FieldRef
1290
+ x Alias
1291
+ x Match / Union
1292
+ x Not
1293
+ x Distinct
1294
+ x nested Fragments
1295
+ x New
1296
+ x Concept expression with kwargs
1297
+ x select
1298
+ x where
1299
+ x Data
1300
+ x Table
1301
+ x Group
1302
+ x Aggregate
1303
+ x defining an expression allows you to have one fewer var than you should
1304
+ x define
1305
+ x require
1306
+ x distinct for aggregates
1307
+ x don't do pop checks on primitives
1308
+ x handle library imports
1309
+ x nested news
1310
+ x bool handling (as_bool, select(x > y))
1311
+ x generate constraints for Property?
1312
+ x wrong arg count in an update isn't providing an error
1313
+ """