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

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