relationalai 0.13.5__py3-none-any.whl → 1.0.0a2__py3-none-any.whl

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