relationalai 0.13.0__py3-none-any.whl → 0.13.0.dev0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (836) 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/semantics/__init__.py +146 -22
  16. relationalai/semantics/backends/lqp/annotations.py +11 -0
  17. relationalai/semantics/backends/sql/sql_compiler.py +327 -0
  18. relationalai/semantics/frontend/base.py +1707 -0
  19. relationalai/semantics/frontend/core.py +179 -0
  20. relationalai/semantics/frontend/front_compiler.py +1313 -0
  21. relationalai/semantics/frontend/pprint.py +408 -0
  22. relationalai/semantics/metamodel/__init__.py +6 -40
  23. relationalai/semantics/metamodel/builtins.py +205 -771
  24. relationalai/semantics/metamodel/metamodel.py +437 -0
  25. relationalai/semantics/metamodel/metamodel_analyzer.py +519 -0
  26. relationalai/semantics/metamodel/pprint.py +412 -0
  27. relationalai/semantics/metamodel/rewriter.py +266 -0
  28. relationalai/semantics/metamodel/typer.py +1378 -0
  29. relationalai/semantics/std/__init__.py +60 -40
  30. relationalai/semantics/std/aggregates.py +149 -0
  31. relationalai/semantics/std/common.py +44 -0
  32. relationalai/semantics/std/constraints.py +37 -43
  33. relationalai/semantics/std/datetime.py +246 -135
  34. relationalai/semantics/std/decimals.py +45 -52
  35. relationalai/semantics/std/floats.py +13 -5
  36. relationalai/semantics/std/integers.py +26 -11
  37. relationalai/semantics/std/math.py +183 -112
  38. relationalai/semantics/std/numbers.py +86 -0
  39. relationalai/semantics/std/re.py +80 -62
  40. relationalai/semantics/std/strings.py +117 -60
  41. relationalai/shims/executor.py +147 -0
  42. relationalai/shims/helpers.py +126 -0
  43. relationalai/shims/hoister.py +221 -0
  44. relationalai/shims/mm2v0.py +1290 -0
  45. relationalai/tools/cli/__init__.py +6 -0
  46. relationalai/tools/cli/cli.py +90 -0
  47. relationalai/tools/cli/components/__init__.py +5 -0
  48. relationalai/tools/cli/components/progress_reader.py +1524 -0
  49. relationalai/tools/cli/components/utils.py +58 -0
  50. relationalai/tools/cli/config_template.py +45 -0
  51. relationalai/tools/cli/dev.py +19 -0
  52. relationalai/tools/debugger.py +289 -183
  53. relationalai/tools/typer_debugger.py +93 -0
  54. relationalai/util/dataclasses.py +43 -0
  55. relationalai/util/docutils.py +40 -0
  56. relationalai/util/error.py +199 -0
  57. relationalai/util/format.py +48 -106
  58. relationalai/util/naming.py +145 -0
  59. relationalai/util/python.py +35 -0
  60. relationalai/util/runtime.py +156 -0
  61. relationalai/util/schema.py +197 -0
  62. relationalai/util/source.py +185 -0
  63. relationalai/util/structures.py +163 -0
  64. relationalai/util/tracing.py +261 -0
  65. relationalai-0.13.0.dev0.dist-info/METADATA +46 -0
  66. relationalai-0.13.0.dev0.dist-info/RECORD +488 -0
  67. relationalai-0.13.0.dev0.dist-info/WHEEL +5 -0
  68. relationalai-0.13.0.dev0.dist-info/entry_points.txt +3 -0
  69. relationalai-0.13.0.dev0.dist-info/top_level.txt +2 -0
  70. v0/relationalai/__init__.py +216 -0
  71. v0/relationalai/clients/__init__.py +5 -0
  72. v0/relationalai/clients/azure.py +477 -0
  73. v0/relationalai/clients/client.py +912 -0
  74. v0/relationalai/clients/config.py +673 -0
  75. v0/relationalai/clients/direct_access_client.py +118 -0
  76. v0/relationalai/clients/hash_util.py +31 -0
  77. v0/relationalai/clients/local.py +571 -0
  78. v0/relationalai/clients/profile_polling.py +73 -0
  79. v0/relationalai/clients/result_helpers.py +420 -0
  80. v0/relationalai/clients/snowflake.py +3869 -0
  81. v0/relationalai/clients/types.py +113 -0
  82. v0/relationalai/clients/use_index_poller.py +980 -0
  83. v0/relationalai/clients/util.py +356 -0
  84. v0/relationalai/debugging.py +389 -0
  85. v0/relationalai/dsl.py +1749 -0
  86. v0/relationalai/early_access/builder/__init__.py +30 -0
  87. v0/relationalai/early_access/builder/builder/__init__.py +35 -0
  88. v0/relationalai/early_access/builder/snowflake/__init__.py +12 -0
  89. v0/relationalai/early_access/builder/std/__init__.py +25 -0
  90. v0/relationalai/early_access/builder/std/decimals/__init__.py +12 -0
  91. v0/relationalai/early_access/builder/std/integers/__init__.py +12 -0
  92. v0/relationalai/early_access/builder/std/math/__init__.py +12 -0
  93. v0/relationalai/early_access/builder/std/strings/__init__.py +14 -0
  94. v0/relationalai/early_access/devtools/__init__.py +12 -0
  95. v0/relationalai/early_access/devtools/benchmark_lqp/__init__.py +12 -0
  96. v0/relationalai/early_access/devtools/extract_lqp/__init__.py +12 -0
  97. v0/relationalai/early_access/dsl/adapters/orm/adapter_qb.py +427 -0
  98. v0/relationalai/early_access/dsl/adapters/orm/parser.py +636 -0
  99. v0/relationalai/early_access/dsl/adapters/owl/adapter.py +176 -0
  100. v0/relationalai/early_access/dsl/adapters/owl/parser.py +160 -0
  101. v0/relationalai/early_access/dsl/bindings/common.py +402 -0
  102. v0/relationalai/early_access/dsl/bindings/csv.py +170 -0
  103. v0/relationalai/early_access/dsl/bindings/legacy/binding_models.py +143 -0
  104. v0/relationalai/early_access/dsl/bindings/snowflake.py +64 -0
  105. v0/relationalai/early_access/dsl/codegen/binder.py +411 -0
  106. v0/relationalai/early_access/dsl/codegen/common.py +79 -0
  107. v0/relationalai/early_access/dsl/codegen/helpers.py +23 -0
  108. v0/relationalai/early_access/dsl/codegen/relations.py +700 -0
  109. v0/relationalai/early_access/dsl/codegen/weaver.py +417 -0
  110. v0/relationalai/early_access/dsl/core/builders/__init__.py +47 -0
  111. v0/relationalai/early_access/dsl/core/builders/logic.py +19 -0
  112. v0/relationalai/early_access/dsl/core/builders/scalar_constraint.py +11 -0
  113. v0/relationalai/early_access/dsl/core/constraints/predicate/atomic.py +455 -0
  114. v0/relationalai/early_access/dsl/core/constraints/predicate/universal.py +73 -0
  115. v0/relationalai/early_access/dsl/core/constraints/scalar.py +310 -0
  116. v0/relationalai/early_access/dsl/core/context.py +13 -0
  117. v0/relationalai/early_access/dsl/core/cset.py +132 -0
  118. v0/relationalai/early_access/dsl/core/exprs/__init__.py +116 -0
  119. v0/relationalai/early_access/dsl/core/exprs/relational.py +18 -0
  120. v0/relationalai/early_access/dsl/core/exprs/scalar.py +412 -0
  121. v0/relationalai/early_access/dsl/core/instances.py +44 -0
  122. v0/relationalai/early_access/dsl/core/logic/__init__.py +193 -0
  123. v0/relationalai/early_access/dsl/core/logic/aggregation.py +98 -0
  124. v0/relationalai/early_access/dsl/core/logic/exists.py +223 -0
  125. v0/relationalai/early_access/dsl/core/logic/helper.py +163 -0
  126. v0/relationalai/early_access/dsl/core/namespaces.py +32 -0
  127. v0/relationalai/early_access/dsl/core/relations.py +276 -0
  128. v0/relationalai/early_access/dsl/core/rules.py +112 -0
  129. v0/relationalai/early_access/dsl/core/std/__init__.py +45 -0
  130. v0/relationalai/early_access/dsl/core/temporal/recall.py +6 -0
  131. v0/relationalai/early_access/dsl/core/types/__init__.py +270 -0
  132. v0/relationalai/early_access/dsl/core/types/concepts.py +128 -0
  133. v0/relationalai/early_access/dsl/core/types/constrained/__init__.py +267 -0
  134. v0/relationalai/early_access/dsl/core/types/constrained/nominal.py +143 -0
  135. v0/relationalai/early_access/dsl/core/types/constrained/subtype.py +124 -0
  136. v0/relationalai/early_access/dsl/core/types/standard.py +92 -0
  137. v0/relationalai/early_access/dsl/core/types/unconstrained.py +50 -0
  138. v0/relationalai/early_access/dsl/core/types/variables.py +203 -0
  139. v0/relationalai/early_access/dsl/ir/compiler.py +318 -0
  140. v0/relationalai/early_access/dsl/ir/executor.py +260 -0
  141. v0/relationalai/early_access/dsl/ontologies/constraints.py +88 -0
  142. v0/relationalai/early_access/dsl/ontologies/export.py +30 -0
  143. v0/relationalai/early_access/dsl/ontologies/models.py +453 -0
  144. v0/relationalai/early_access/dsl/ontologies/python_printer.py +303 -0
  145. v0/relationalai/early_access/dsl/ontologies/readings.py +60 -0
  146. v0/relationalai/early_access/dsl/ontologies/relationships.py +322 -0
  147. v0/relationalai/early_access/dsl/ontologies/roles.py +87 -0
  148. v0/relationalai/early_access/dsl/ontologies/subtyping.py +55 -0
  149. v0/relationalai/early_access/dsl/orm/constraints.py +438 -0
  150. v0/relationalai/early_access/dsl/orm/measures/dimensions.py +200 -0
  151. v0/relationalai/early_access/dsl/orm/measures/initializer.py +16 -0
  152. v0/relationalai/early_access/dsl/orm/measures/measure_rules.py +275 -0
  153. v0/relationalai/early_access/dsl/orm/measures/measures.py +299 -0
  154. v0/relationalai/early_access/dsl/orm/measures/role_exprs.py +268 -0
  155. v0/relationalai/early_access/dsl/orm/models.py +256 -0
  156. v0/relationalai/early_access/dsl/orm/object_oriented_printer.py +344 -0
  157. v0/relationalai/early_access/dsl/orm/printer.py +469 -0
  158. v0/relationalai/early_access/dsl/orm/reasoners.py +480 -0
  159. v0/relationalai/early_access/dsl/orm/relations.py +19 -0
  160. v0/relationalai/early_access/dsl/orm/relationships.py +251 -0
  161. v0/relationalai/early_access/dsl/orm/types.py +42 -0
  162. v0/relationalai/early_access/dsl/orm/utils.py +79 -0
  163. v0/relationalai/early_access/dsl/orm/verb.py +204 -0
  164. v0/relationalai/early_access/dsl/physical_metadata/tables.py +133 -0
  165. v0/relationalai/early_access/dsl/relations.py +170 -0
  166. v0/relationalai/early_access/dsl/rulesets.py +69 -0
  167. v0/relationalai/early_access/dsl/schemas/__init__.py +450 -0
  168. v0/relationalai/early_access/dsl/schemas/builder.py +48 -0
  169. v0/relationalai/early_access/dsl/schemas/comp_names.py +51 -0
  170. v0/relationalai/early_access/dsl/schemas/components.py +203 -0
  171. v0/relationalai/early_access/dsl/schemas/contexts.py +156 -0
  172. v0/relationalai/early_access/dsl/schemas/exprs.py +89 -0
  173. v0/relationalai/early_access/dsl/schemas/fragments.py +464 -0
  174. v0/relationalai/early_access/dsl/serialization.py +79 -0
  175. v0/relationalai/early_access/dsl/serialize/exporter.py +163 -0
  176. v0/relationalai/early_access/dsl/snow/api.py +104 -0
  177. v0/relationalai/early_access/dsl/snow/common.py +76 -0
  178. v0/relationalai/early_access/dsl/state_mgmt/__init__.py +129 -0
  179. v0/relationalai/early_access/dsl/state_mgmt/state_charts.py +125 -0
  180. v0/relationalai/early_access/dsl/state_mgmt/transitions.py +130 -0
  181. v0/relationalai/early_access/dsl/types/__init__.py +40 -0
  182. v0/relationalai/early_access/dsl/types/concepts.py +12 -0
  183. v0/relationalai/early_access/dsl/types/entities.py +135 -0
  184. v0/relationalai/early_access/dsl/types/values.py +17 -0
  185. v0/relationalai/early_access/dsl/utils.py +102 -0
  186. v0/relationalai/early_access/graphs/__init__.py +13 -0
  187. v0/relationalai/early_access/lqp/__init__.py +12 -0
  188. v0/relationalai/early_access/lqp/compiler/__init__.py +12 -0
  189. v0/relationalai/early_access/lqp/constructors/__init__.py +18 -0
  190. v0/relationalai/early_access/lqp/executor/__init__.py +12 -0
  191. v0/relationalai/early_access/lqp/ir/__init__.py +12 -0
  192. v0/relationalai/early_access/lqp/passes/__init__.py +12 -0
  193. v0/relationalai/early_access/lqp/pragmas/__init__.py +12 -0
  194. v0/relationalai/early_access/lqp/primitives/__init__.py +12 -0
  195. v0/relationalai/early_access/lqp/types/__init__.py +12 -0
  196. v0/relationalai/early_access/lqp/utils/__init__.py +12 -0
  197. v0/relationalai/early_access/lqp/validators/__init__.py +12 -0
  198. v0/relationalai/early_access/metamodel/__init__.py +58 -0
  199. v0/relationalai/early_access/metamodel/builtins/__init__.py +12 -0
  200. v0/relationalai/early_access/metamodel/compiler/__init__.py +12 -0
  201. v0/relationalai/early_access/metamodel/dependency/__init__.py +12 -0
  202. v0/relationalai/early_access/metamodel/factory/__init__.py +17 -0
  203. v0/relationalai/early_access/metamodel/helpers/__init__.py +12 -0
  204. v0/relationalai/early_access/metamodel/ir/__init__.py +14 -0
  205. v0/relationalai/early_access/metamodel/rewrite/__init__.py +7 -0
  206. v0/relationalai/early_access/metamodel/typer/__init__.py +3 -0
  207. v0/relationalai/early_access/metamodel/typer/typer/__init__.py +12 -0
  208. v0/relationalai/early_access/metamodel/types/__init__.py +15 -0
  209. v0/relationalai/early_access/metamodel/util/__init__.py +15 -0
  210. v0/relationalai/early_access/metamodel/visitor/__init__.py +12 -0
  211. v0/relationalai/early_access/rel/__init__.py +12 -0
  212. v0/relationalai/early_access/rel/executor/__init__.py +12 -0
  213. v0/relationalai/early_access/rel/rel_utils/__init__.py +12 -0
  214. v0/relationalai/early_access/rel/rewrite/__init__.py +7 -0
  215. v0/relationalai/early_access/solvers/__init__.py +19 -0
  216. v0/relationalai/early_access/sql/__init__.py +11 -0
  217. v0/relationalai/early_access/sql/executor/__init__.py +3 -0
  218. v0/relationalai/early_access/sql/rewrite/__init__.py +3 -0
  219. v0/relationalai/early_access/tests/logging/__init__.py +12 -0
  220. v0/relationalai/early_access/tests/test_snapshot_base/__init__.py +12 -0
  221. v0/relationalai/early_access/tests/utils/__init__.py +12 -0
  222. v0/relationalai/environments/__init__.py +35 -0
  223. v0/relationalai/environments/base.py +381 -0
  224. v0/relationalai/environments/colab.py +14 -0
  225. v0/relationalai/environments/generic.py +71 -0
  226. v0/relationalai/environments/ipython.py +68 -0
  227. v0/relationalai/environments/jupyter.py +9 -0
  228. v0/relationalai/environments/snowbook.py +169 -0
  229. v0/relationalai/errors.py +2455 -0
  230. v0/relationalai/experimental/SF.py +38 -0
  231. v0/relationalai/experimental/inspect.py +47 -0
  232. v0/relationalai/experimental/pathfinder/__init__.py +158 -0
  233. v0/relationalai/experimental/pathfinder/api.py +160 -0
  234. v0/relationalai/experimental/pathfinder/automaton.py +584 -0
  235. v0/relationalai/experimental/pathfinder/bridge.py +226 -0
  236. v0/relationalai/experimental/pathfinder/compiler.py +416 -0
  237. v0/relationalai/experimental/pathfinder/datalog.py +214 -0
  238. v0/relationalai/experimental/pathfinder/diagnostics.py +56 -0
  239. v0/relationalai/experimental/pathfinder/filter.py +236 -0
  240. v0/relationalai/experimental/pathfinder/glushkov.py +439 -0
  241. v0/relationalai/experimental/pathfinder/options.py +265 -0
  242. v0/relationalai/experimental/pathfinder/rpq.py +344 -0
  243. v0/relationalai/experimental/pathfinder/transition.py +200 -0
  244. v0/relationalai/experimental/pathfinder/utils.py +26 -0
  245. v0/relationalai/experimental/paths/api.py +143 -0
  246. v0/relationalai/experimental/paths/benchmarks/grid_graph.py +37 -0
  247. v0/relationalai/experimental/paths/examples/basic_example.py +40 -0
  248. v0/relationalai/experimental/paths/examples/minimal_engine_warmup.py +3 -0
  249. v0/relationalai/experimental/paths/examples/movie_example.py +77 -0
  250. v0/relationalai/experimental/paths/examples/paths_benchmark.py +115 -0
  251. v0/relationalai/experimental/paths/examples/paths_example.py +116 -0
  252. v0/relationalai/experimental/paths/examples/pattern_to_automaton.py +28 -0
  253. v0/relationalai/experimental/paths/find_paths_via_automaton.py +85 -0
  254. v0/relationalai/experimental/paths/graph.py +185 -0
  255. v0/relationalai/experimental/paths/path_algorithms/find_paths.py +280 -0
  256. v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +26 -0
  257. v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +111 -0
  258. v0/relationalai/experimental/paths/path_algorithms/single.py +59 -0
  259. v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +39 -0
  260. v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +103 -0
  261. v0/relationalai/experimental/paths/path_algorithms/usp-old.py +130 -0
  262. v0/relationalai/experimental/paths/path_algorithms/usp-tuple.py +183 -0
  263. v0/relationalai/experimental/paths/path_algorithms/usp.py +150 -0
  264. v0/relationalai/experimental/paths/product_graph.py +93 -0
  265. v0/relationalai/experimental/paths/rpq/automaton.py +584 -0
  266. v0/relationalai/experimental/paths/rpq/diagnostics.py +56 -0
  267. v0/relationalai/experimental/paths/rpq/rpq.py +378 -0
  268. v0/relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +90 -0
  269. v0/relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +119 -0
  270. v0/relationalai/experimental/paths/tests/tests_limit_sp_single.py +104 -0
  271. v0/relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +113 -0
  272. v0/relationalai/experimental/paths/tests/tests_limit_walks_single.py +149 -0
  273. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +70 -0
  274. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +64 -0
  275. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +115 -0
  276. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +75 -0
  277. v0/relationalai/experimental/paths/tests/tests_single_paths.py +152 -0
  278. v0/relationalai/experimental/paths/tests/tests_single_walks.py +208 -0
  279. v0/relationalai/experimental/paths/tests/tests_single_walks_undirected.py +297 -0
  280. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +107 -0
  281. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +76 -0
  282. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +76 -0
  283. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +110 -0
  284. v0/relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +229 -0
  285. v0/relationalai/experimental/paths/tests/tests_usp_nsp_single.py +108 -0
  286. v0/relationalai/experimental/paths/tree_agg.py +168 -0
  287. v0/relationalai/experimental/paths/utilities/iterators.py +27 -0
  288. v0/relationalai/experimental/paths/utilities/prefix_sum.py +91 -0
  289. v0/relationalai/experimental/solvers.py +1087 -0
  290. v0/relationalai/loaders/__init__.py +0 -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/model2lqp.py +839 -0
  308. v0/relationalai/semantics/lqp/passes.py +680 -0
  309. v0/relationalai/semantics/lqp/primitives.py +252 -0
  310. v0/relationalai/semantics/lqp/result_helpers.py +202 -0
  311. v0/relationalai/semantics/lqp/rewrite/annotate_constraints.py +57 -0
  312. v0/relationalai/semantics/lqp/rewrite/cdc.py +216 -0
  313. v0/relationalai/semantics/lqp/rewrite/extract_common.py +338 -0
  314. v0/relationalai/semantics/lqp/rewrite/extract_keys.py +449 -0
  315. v0/relationalai/semantics/lqp/rewrite/function_annotations.py +114 -0
  316. v0/relationalai/semantics/lqp/rewrite/functional_dependencies.py +314 -0
  317. v0/relationalai/semantics/lqp/rewrite/quantify_vars.py +296 -0
  318. v0/relationalai/semantics/lqp/rewrite/splinter.py +76 -0
  319. v0/relationalai/semantics/lqp/types.py +101 -0
  320. v0/relationalai/semantics/lqp/utils.py +160 -0
  321. v0/relationalai/semantics/lqp/validators.py +57 -0
  322. v0/relationalai/semantics/metamodel/__init__.py +40 -0
  323. v0/relationalai/semantics/metamodel/builtins.py +774 -0
  324. v0/relationalai/semantics/metamodel/compiler.py +133 -0
  325. v0/relationalai/semantics/metamodel/dependency.py +862 -0
  326. v0/relationalai/semantics/metamodel/executor.py +61 -0
  327. v0/relationalai/semantics/metamodel/factory.py +287 -0
  328. v0/relationalai/semantics/metamodel/helpers.py +361 -0
  329. v0/relationalai/semantics/metamodel/rewrite/discharge_constraints.py +39 -0
  330. v0/relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +210 -0
  331. v0/relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +78 -0
  332. v0/relationalai/semantics/metamodel/rewrite/flatten.py +549 -0
  333. v0/relationalai/semantics/metamodel/rewrite/format_outputs.py +165 -0
  334. v0/relationalai/semantics/metamodel/typer/checker.py +353 -0
  335. v0/relationalai/semantics/metamodel/typer/typer.py +1395 -0
  336. v0/relationalai/semantics/metamodel/util.py +505 -0
  337. v0/relationalai/semantics/reasoners/__init__.py +10 -0
  338. v0/relationalai/semantics/reasoners/graph/__init__.py +37 -0
  339. v0/relationalai/semantics/reasoners/graph/core.py +9020 -0
  340. v0/relationalai/semantics/reasoners/optimization/__init__.py +68 -0
  341. v0/relationalai/semantics/reasoners/optimization/common.py +88 -0
  342. v0/relationalai/semantics/reasoners/optimization/solvers_dev.py +568 -0
  343. v0/relationalai/semantics/reasoners/optimization/solvers_pb.py +1163 -0
  344. v0/relationalai/semantics/rel/builtins.py +40 -0
  345. v0/relationalai/semantics/rel/compiler.py +989 -0
  346. v0/relationalai/semantics/rel/executor.py +359 -0
  347. v0/relationalai/semantics/rel/rel.py +482 -0
  348. v0/relationalai/semantics/rel/rel_utils.py +276 -0
  349. v0/relationalai/semantics/snowflake/__init__.py +3 -0
  350. v0/relationalai/semantics/sql/compiler.py +2503 -0
  351. v0/relationalai/semantics/sql/executor/duck_db.py +52 -0
  352. v0/relationalai/semantics/sql/executor/result_helpers.py +64 -0
  353. v0/relationalai/semantics/sql/executor/snowflake.py +145 -0
  354. v0/relationalai/semantics/sql/rewrite/denormalize.py +222 -0
  355. v0/relationalai/semantics/sql/rewrite/double_negation.py +49 -0
  356. v0/relationalai/semantics/sql/rewrite/recursive_union.py +127 -0
  357. v0/relationalai/semantics/sql/rewrite/sort_output_query.py +246 -0
  358. v0/relationalai/semantics/sql/sql.py +504 -0
  359. v0/relationalai/semantics/std/__init__.py +54 -0
  360. v0/relationalai/semantics/std/constraints.py +43 -0
  361. v0/relationalai/semantics/std/datetime.py +363 -0
  362. v0/relationalai/semantics/std/decimals.py +62 -0
  363. v0/relationalai/semantics/std/floats.py +7 -0
  364. v0/relationalai/semantics/std/integers.py +22 -0
  365. v0/relationalai/semantics/std/math.py +141 -0
  366. v0/relationalai/semantics/std/pragmas.py +11 -0
  367. v0/relationalai/semantics/std/re.py +83 -0
  368. v0/relationalai/semantics/std/std.py +14 -0
  369. v0/relationalai/semantics/std/strings.py +63 -0
  370. v0/relationalai/semantics/tests/__init__.py +0 -0
  371. v0/relationalai/semantics/tests/test_snapshot_abstract.py +143 -0
  372. v0/relationalai/semantics/tests/test_snapshot_base.py +9 -0
  373. v0/relationalai/semantics/tests/utils.py +46 -0
  374. v0/relationalai/std/__init__.py +70 -0
  375. v0/relationalai/tools/__init__.py +0 -0
  376. v0/relationalai/tools/cli.py +1940 -0
  377. v0/relationalai/tools/cli_controls.py +1826 -0
  378. v0/relationalai/tools/cli_helpers.py +390 -0
  379. v0/relationalai/tools/debugger.py +183 -0
  380. v0/relationalai/tools/debugger_client.py +109 -0
  381. v0/relationalai/tools/debugger_server.py +302 -0
  382. v0/relationalai/tools/dev.py +685 -0
  383. v0/relationalai/tools/qb_debugger.py +425 -0
  384. v0/relationalai/util/clean_up_databases.py +95 -0
  385. v0/relationalai/util/format.py +123 -0
  386. v0/relationalai/util/list_databases.py +9 -0
  387. v0/relationalai/util/otel_configuration.py +25 -0
  388. v0/relationalai/util/otel_handler.py +484 -0
  389. v0/relationalai/util/snowflake_handler.py +88 -0
  390. v0/relationalai/util/span_format_test.py +43 -0
  391. v0/relationalai/util/span_tracker.py +207 -0
  392. v0/relationalai/util/spans_file_handler.py +72 -0
  393. v0/relationalai/util/tracing_handler.py +34 -0
  394. frontend/debugger/dist/.gitignore +0 -2
  395. frontend/debugger/dist/assets/favicon-Dy0ZgA6N.png +0 -0
  396. frontend/debugger/dist/assets/index-Cssla-O7.js +0 -208
  397. frontend/debugger/dist/assets/index-DlHsYx1V.css +0 -9
  398. frontend/debugger/dist/index.html +0 -17
  399. relationalai/clients/__init__.py +0 -18
  400. relationalai/clients/client.py +0 -912
  401. relationalai/clients/config.py +0 -673
  402. relationalai/clients/direct_access_client.py +0 -118
  403. relationalai/clients/hash_util.py +0 -31
  404. relationalai/clients/local.py +0 -571
  405. relationalai/clients/profile_polling.py +0 -73
  406. relationalai/clients/resources/__init__.py +0 -8
  407. relationalai/clients/resources/azure/azure.py +0 -477
  408. relationalai/clients/resources/snowflake/__init__.py +0 -20
  409. relationalai/clients/resources/snowflake/cli_resources.py +0 -87
  410. relationalai/clients/resources/snowflake/direct_access_resources.py +0 -711
  411. relationalai/clients/resources/snowflake/engine_state_handlers.py +0 -309
  412. relationalai/clients/resources/snowflake/error_handlers.py +0 -199
  413. relationalai/clients/resources/snowflake/export_procedure.py.jinja +0 -249
  414. relationalai/clients/resources/snowflake/resources_factory.py +0 -99
  415. relationalai/clients/resources/snowflake/snowflake.py +0 -3083
  416. relationalai/clients/resources/snowflake/use_index_poller.py +0 -1011
  417. relationalai/clients/resources/snowflake/use_index_resources.py +0 -188
  418. relationalai/clients/resources/snowflake/util.py +0 -387
  419. relationalai/clients/result_helpers.py +0 -420
  420. relationalai/clients/types.py +0 -113
  421. relationalai/clients/util.py +0 -356
  422. relationalai/debugging.py +0 -389
  423. relationalai/dsl.py +0 -1749
  424. relationalai/early_access/builder/__init__.py +0 -30
  425. relationalai/early_access/builder/builder/__init__.py +0 -35
  426. relationalai/early_access/builder/snowflake/__init__.py +0 -12
  427. relationalai/early_access/builder/std/__init__.py +0 -25
  428. relationalai/early_access/builder/std/decimals/__init__.py +0 -12
  429. relationalai/early_access/builder/std/integers/__init__.py +0 -12
  430. relationalai/early_access/builder/std/math/__init__.py +0 -12
  431. relationalai/early_access/builder/std/strings/__init__.py +0 -14
  432. relationalai/early_access/devtools/__init__.py +0 -12
  433. relationalai/early_access/devtools/benchmark_lqp/__init__.py +0 -12
  434. relationalai/early_access/devtools/extract_lqp/__init__.py +0 -12
  435. relationalai/early_access/dsl/adapters/orm/adapter_qb.py +0 -427
  436. relationalai/early_access/dsl/adapters/orm/parser.py +0 -636
  437. relationalai/early_access/dsl/adapters/owl/adapter.py +0 -176
  438. relationalai/early_access/dsl/adapters/owl/parser.py +0 -160
  439. relationalai/early_access/dsl/bindings/common.py +0 -402
  440. relationalai/early_access/dsl/bindings/csv.py +0 -170
  441. relationalai/early_access/dsl/bindings/legacy/binding_models.py +0 -143
  442. relationalai/early_access/dsl/bindings/snowflake.py +0 -64
  443. relationalai/early_access/dsl/codegen/binder.py +0 -411
  444. relationalai/early_access/dsl/codegen/common.py +0 -79
  445. relationalai/early_access/dsl/codegen/helpers.py +0 -23
  446. relationalai/early_access/dsl/codegen/relations.py +0 -700
  447. relationalai/early_access/dsl/codegen/weaver.py +0 -417
  448. relationalai/early_access/dsl/core/builders/__init__.py +0 -47
  449. relationalai/early_access/dsl/core/builders/logic.py +0 -19
  450. relationalai/early_access/dsl/core/builders/scalar_constraint.py +0 -11
  451. relationalai/early_access/dsl/core/constraints/predicate/atomic.py +0 -455
  452. relationalai/early_access/dsl/core/constraints/predicate/universal.py +0 -73
  453. relationalai/early_access/dsl/core/constraints/scalar.py +0 -310
  454. relationalai/early_access/dsl/core/context.py +0 -13
  455. relationalai/early_access/dsl/core/cset.py +0 -132
  456. relationalai/early_access/dsl/core/exprs/__init__.py +0 -116
  457. relationalai/early_access/dsl/core/exprs/relational.py +0 -18
  458. relationalai/early_access/dsl/core/exprs/scalar.py +0 -412
  459. relationalai/early_access/dsl/core/instances.py +0 -44
  460. relationalai/early_access/dsl/core/logic/__init__.py +0 -193
  461. relationalai/early_access/dsl/core/logic/aggregation.py +0 -98
  462. relationalai/early_access/dsl/core/logic/exists.py +0 -223
  463. relationalai/early_access/dsl/core/logic/helper.py +0 -163
  464. relationalai/early_access/dsl/core/namespaces.py +0 -32
  465. relationalai/early_access/dsl/core/relations.py +0 -276
  466. relationalai/early_access/dsl/core/rules.py +0 -112
  467. relationalai/early_access/dsl/core/std/__init__.py +0 -45
  468. relationalai/early_access/dsl/core/temporal/recall.py +0 -6
  469. relationalai/early_access/dsl/core/types/__init__.py +0 -270
  470. relationalai/early_access/dsl/core/types/concepts.py +0 -128
  471. relationalai/early_access/dsl/core/types/constrained/__init__.py +0 -267
  472. relationalai/early_access/dsl/core/types/constrained/nominal.py +0 -143
  473. relationalai/early_access/dsl/core/types/constrained/subtype.py +0 -124
  474. relationalai/early_access/dsl/core/types/standard.py +0 -92
  475. relationalai/early_access/dsl/core/types/unconstrained.py +0 -50
  476. relationalai/early_access/dsl/core/types/variables.py +0 -203
  477. relationalai/early_access/dsl/ir/compiler.py +0 -318
  478. relationalai/early_access/dsl/ir/executor.py +0 -260
  479. relationalai/early_access/dsl/ontologies/constraints.py +0 -88
  480. relationalai/early_access/dsl/ontologies/export.py +0 -30
  481. relationalai/early_access/dsl/ontologies/models.py +0 -453
  482. relationalai/early_access/dsl/ontologies/python_printer.py +0 -303
  483. relationalai/early_access/dsl/ontologies/readings.py +0 -60
  484. relationalai/early_access/dsl/ontologies/relationships.py +0 -322
  485. relationalai/early_access/dsl/ontologies/roles.py +0 -87
  486. relationalai/early_access/dsl/ontologies/subtyping.py +0 -55
  487. relationalai/early_access/dsl/orm/constraints.py +0 -438
  488. relationalai/early_access/dsl/orm/measures/dimensions.py +0 -200
  489. relationalai/early_access/dsl/orm/measures/initializer.py +0 -16
  490. relationalai/early_access/dsl/orm/measures/measure_rules.py +0 -275
  491. relationalai/early_access/dsl/orm/measures/measures.py +0 -299
  492. relationalai/early_access/dsl/orm/measures/role_exprs.py +0 -268
  493. relationalai/early_access/dsl/orm/models.py +0 -256
  494. relationalai/early_access/dsl/orm/object_oriented_printer.py +0 -344
  495. relationalai/early_access/dsl/orm/printer.py +0 -469
  496. relationalai/early_access/dsl/orm/reasoners.py +0 -480
  497. relationalai/early_access/dsl/orm/relations.py +0 -19
  498. relationalai/early_access/dsl/orm/relationships.py +0 -251
  499. relationalai/early_access/dsl/orm/types.py +0 -42
  500. relationalai/early_access/dsl/orm/utils.py +0 -79
  501. relationalai/early_access/dsl/orm/verb.py +0 -204
  502. relationalai/early_access/dsl/physical_metadata/tables.py +0 -133
  503. relationalai/early_access/dsl/relations.py +0 -170
  504. relationalai/early_access/dsl/rulesets.py +0 -69
  505. relationalai/early_access/dsl/schemas/__init__.py +0 -450
  506. relationalai/early_access/dsl/schemas/builder.py +0 -48
  507. relationalai/early_access/dsl/schemas/comp_names.py +0 -51
  508. relationalai/early_access/dsl/schemas/components.py +0 -203
  509. relationalai/early_access/dsl/schemas/contexts.py +0 -156
  510. relationalai/early_access/dsl/schemas/exprs.py +0 -89
  511. relationalai/early_access/dsl/schemas/fragments.py +0 -464
  512. relationalai/early_access/dsl/serialization.py +0 -79
  513. relationalai/early_access/dsl/serialize/exporter.py +0 -163
  514. relationalai/early_access/dsl/snow/api.py +0 -105
  515. relationalai/early_access/dsl/snow/common.py +0 -76
  516. relationalai/early_access/dsl/state_mgmt/__init__.py +0 -129
  517. relationalai/early_access/dsl/state_mgmt/state_charts.py +0 -125
  518. relationalai/early_access/dsl/state_mgmt/transitions.py +0 -130
  519. relationalai/early_access/dsl/types/__init__.py +0 -40
  520. relationalai/early_access/dsl/types/concepts.py +0 -12
  521. relationalai/early_access/dsl/types/entities.py +0 -135
  522. relationalai/early_access/dsl/types/values.py +0 -17
  523. relationalai/early_access/dsl/utils.py +0 -102
  524. relationalai/early_access/graphs/__init__.py +0 -13
  525. relationalai/early_access/lqp/__init__.py +0 -12
  526. relationalai/early_access/lqp/compiler/__init__.py +0 -12
  527. relationalai/early_access/lqp/constructors/__init__.py +0 -18
  528. relationalai/early_access/lqp/executor/__init__.py +0 -12
  529. relationalai/early_access/lqp/ir/__init__.py +0 -12
  530. relationalai/early_access/lqp/passes/__init__.py +0 -12
  531. relationalai/early_access/lqp/pragmas/__init__.py +0 -12
  532. relationalai/early_access/lqp/primitives/__init__.py +0 -12
  533. relationalai/early_access/lqp/types/__init__.py +0 -12
  534. relationalai/early_access/lqp/utils/__init__.py +0 -12
  535. relationalai/early_access/lqp/validators/__init__.py +0 -12
  536. relationalai/early_access/metamodel/__init__.py +0 -58
  537. relationalai/early_access/metamodel/builtins/__init__.py +0 -12
  538. relationalai/early_access/metamodel/compiler/__init__.py +0 -12
  539. relationalai/early_access/metamodel/dependency/__init__.py +0 -12
  540. relationalai/early_access/metamodel/factory/__init__.py +0 -17
  541. relationalai/early_access/metamodel/helpers/__init__.py +0 -12
  542. relationalai/early_access/metamodel/ir/__init__.py +0 -14
  543. relationalai/early_access/metamodel/rewrite/__init__.py +0 -7
  544. relationalai/early_access/metamodel/typer/__init__.py +0 -3
  545. relationalai/early_access/metamodel/typer/typer/__init__.py +0 -12
  546. relationalai/early_access/metamodel/types/__init__.py +0 -15
  547. relationalai/early_access/metamodel/util/__init__.py +0 -15
  548. relationalai/early_access/metamodel/visitor/__init__.py +0 -12
  549. relationalai/early_access/rel/__init__.py +0 -12
  550. relationalai/early_access/rel/executor/__init__.py +0 -12
  551. relationalai/early_access/rel/rel_utils/__init__.py +0 -12
  552. relationalai/early_access/rel/rewrite/__init__.py +0 -7
  553. relationalai/early_access/solvers/__init__.py +0 -19
  554. relationalai/early_access/sql/__init__.py +0 -11
  555. relationalai/early_access/sql/executor/__init__.py +0 -3
  556. relationalai/early_access/sql/rewrite/__init__.py +0 -3
  557. relationalai/early_access/tests/logging/__init__.py +0 -12
  558. relationalai/early_access/tests/test_snapshot_base/__init__.py +0 -12
  559. relationalai/early_access/tests/utils/__init__.py +0 -12
  560. relationalai/environments/__init__.py +0 -35
  561. relationalai/environments/base.py +0 -381
  562. relationalai/environments/colab.py +0 -14
  563. relationalai/environments/generic.py +0 -71
  564. relationalai/environments/ipython.py +0 -68
  565. relationalai/environments/jupyter.py +0 -9
  566. relationalai/environments/snowbook.py +0 -169
  567. relationalai/errors.py +0 -2478
  568. relationalai/experimental/SF.py +0 -38
  569. relationalai/experimental/inspect.py +0 -47
  570. relationalai/experimental/pathfinder/__init__.py +0 -158
  571. relationalai/experimental/pathfinder/api.py +0 -160
  572. relationalai/experimental/pathfinder/automaton.py +0 -584
  573. relationalai/experimental/pathfinder/bridge.py +0 -226
  574. relationalai/experimental/pathfinder/compiler.py +0 -416
  575. relationalai/experimental/pathfinder/datalog.py +0 -214
  576. relationalai/experimental/pathfinder/diagnostics.py +0 -56
  577. relationalai/experimental/pathfinder/filter.py +0 -236
  578. relationalai/experimental/pathfinder/glushkov.py +0 -439
  579. relationalai/experimental/pathfinder/options.py +0 -265
  580. relationalai/experimental/pathfinder/pathfinder-v0.7.0.rel +0 -1951
  581. relationalai/experimental/pathfinder/rpq.py +0 -344
  582. relationalai/experimental/pathfinder/transition.py +0 -200
  583. relationalai/experimental/pathfinder/utils.py +0 -26
  584. relationalai/experimental/paths/README.md +0 -107
  585. relationalai/experimental/paths/api.py +0 -143
  586. relationalai/experimental/paths/benchmarks/grid_graph.py +0 -37
  587. relationalai/experimental/paths/code_organization.md +0 -2
  588. relationalai/experimental/paths/examples/Movies.ipynb +0 -16328
  589. relationalai/experimental/paths/examples/basic_example.py +0 -40
  590. relationalai/experimental/paths/examples/minimal_engine_warmup.py +0 -3
  591. relationalai/experimental/paths/examples/movie_example.py +0 -77
  592. relationalai/experimental/paths/examples/movies_data/actedin.csv +0 -193
  593. relationalai/experimental/paths/examples/movies_data/directed.csv +0 -45
  594. relationalai/experimental/paths/examples/movies_data/follows.csv +0 -7
  595. relationalai/experimental/paths/examples/movies_data/movies.csv +0 -39
  596. relationalai/experimental/paths/examples/movies_data/person.csv +0 -134
  597. relationalai/experimental/paths/examples/movies_data/produced.csv +0 -16
  598. relationalai/experimental/paths/examples/movies_data/ratings.csv +0 -10
  599. relationalai/experimental/paths/examples/movies_data/wrote.csv +0 -11
  600. relationalai/experimental/paths/examples/paths_benchmark.py +0 -115
  601. relationalai/experimental/paths/examples/paths_example.py +0 -116
  602. relationalai/experimental/paths/examples/pattern_to_automaton.py +0 -28
  603. relationalai/experimental/paths/find_paths_via_automaton.py +0 -85
  604. relationalai/experimental/paths/graph.py +0 -185
  605. relationalai/experimental/paths/path_algorithms/find_paths.py +0 -280
  606. relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +0 -26
  607. relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +0 -111
  608. relationalai/experimental/paths/path_algorithms/single.py +0 -59
  609. relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +0 -39
  610. relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +0 -103
  611. relationalai/experimental/paths/path_algorithms/usp-old.py +0 -130
  612. relationalai/experimental/paths/path_algorithms/usp-tuple.py +0 -183
  613. relationalai/experimental/paths/path_algorithms/usp.py +0 -150
  614. relationalai/experimental/paths/product_graph.py +0 -93
  615. relationalai/experimental/paths/rpq/automaton.py +0 -584
  616. relationalai/experimental/paths/rpq/diagnostics.py +0 -56
  617. relationalai/experimental/paths/rpq/rpq.py +0 -378
  618. relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +0 -90
  619. relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +0 -119
  620. relationalai/experimental/paths/tests/tests_limit_sp_single.py +0 -104
  621. relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +0 -113
  622. relationalai/experimental/paths/tests/tests_limit_walks_single.py +0 -149
  623. relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +0 -70
  624. relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +0 -64
  625. relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +0 -115
  626. relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +0 -75
  627. relationalai/experimental/paths/tests/tests_single_paths.py +0 -152
  628. relationalai/experimental/paths/tests/tests_single_walks.py +0 -208
  629. relationalai/experimental/paths/tests/tests_single_walks_undirected.py +0 -297
  630. relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +0 -107
  631. relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +0 -76
  632. relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +0 -76
  633. relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +0 -110
  634. relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +0 -229
  635. relationalai/experimental/paths/tests/tests_usp_nsp_single.py +0 -108
  636. relationalai/experimental/paths/tree_agg.py +0 -168
  637. relationalai/experimental/paths/utilities/iterators.py +0 -27
  638. relationalai/experimental/paths/utilities/prefix_sum.py +0 -91
  639. relationalai/experimental/solvers.py +0 -1087
  640. relationalai/loaders/csv.py +0 -195
  641. relationalai/loaders/loader.py +0 -177
  642. relationalai/loaders/types.py +0 -23
  643. relationalai/rel_emitter.py +0 -373
  644. relationalai/rel_utils.py +0 -185
  645. relationalai/semantics/designs/query_builder/identify_by.md +0 -106
  646. relationalai/semantics/devtools/benchmark_lqp.py +0 -535
  647. relationalai/semantics/devtools/compilation_manager.py +0 -294
  648. relationalai/semantics/devtools/extract_lqp.py +0 -110
  649. relationalai/semantics/internal/internal.py +0 -3785
  650. relationalai/semantics/internal/snowflake.py +0 -325
  651. relationalai/semantics/lqp/README.md +0 -34
  652. relationalai/semantics/lqp/builtins.py +0 -16
  653. relationalai/semantics/lqp/compiler.py +0 -22
  654. relationalai/semantics/lqp/constructors.py +0 -68
  655. relationalai/semantics/lqp/executor.py +0 -469
  656. relationalai/semantics/lqp/intrinsics.py +0 -24
  657. relationalai/semantics/lqp/model2lqp.py +0 -877
  658. relationalai/semantics/lqp/passes.py +0 -680
  659. relationalai/semantics/lqp/primitives.py +0 -252
  660. relationalai/semantics/lqp/result_helpers.py +0 -202
  661. relationalai/semantics/lqp/rewrite/annotate_constraints.py +0 -57
  662. relationalai/semantics/lqp/rewrite/cdc.py +0 -216
  663. relationalai/semantics/lqp/rewrite/extract_common.py +0 -338
  664. relationalai/semantics/lqp/rewrite/extract_keys.py +0 -506
  665. relationalai/semantics/lqp/rewrite/function_annotations.py +0 -114
  666. relationalai/semantics/lqp/rewrite/functional_dependencies.py +0 -314
  667. relationalai/semantics/lqp/rewrite/quantify_vars.py +0 -296
  668. relationalai/semantics/lqp/rewrite/splinter.py +0 -76
  669. relationalai/semantics/lqp/types.py +0 -101
  670. relationalai/semantics/lqp/utils.py +0 -160
  671. relationalai/semantics/lqp/validators.py +0 -57
  672. relationalai/semantics/metamodel/compiler.py +0 -133
  673. relationalai/semantics/metamodel/dependency.py +0 -862
  674. relationalai/semantics/metamodel/executor.py +0 -61
  675. relationalai/semantics/metamodel/factory.py +0 -287
  676. relationalai/semantics/metamodel/helpers.py +0 -361
  677. relationalai/semantics/metamodel/rewrite/discharge_constraints.py +0 -39
  678. relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +0 -210
  679. relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +0 -78
  680. relationalai/semantics/metamodel/rewrite/flatten.py +0 -554
  681. relationalai/semantics/metamodel/rewrite/format_outputs.py +0 -165
  682. relationalai/semantics/metamodel/typer/checker.py +0 -353
  683. relationalai/semantics/metamodel/typer/typer.py +0 -1395
  684. relationalai/semantics/metamodel/util.py +0 -506
  685. relationalai/semantics/reasoners/__init__.py +0 -10
  686. relationalai/semantics/reasoners/graph/README.md +0 -620
  687. relationalai/semantics/reasoners/graph/__init__.py +0 -37
  688. relationalai/semantics/reasoners/graph/core.py +0 -9019
  689. relationalai/semantics/reasoners/graph/design/beyond_demand_transform.md +0 -797
  690. relationalai/semantics/reasoners/graph/tests/README.md +0 -21
  691. relationalai/semantics/reasoners/optimization/__init__.py +0 -68
  692. relationalai/semantics/reasoners/optimization/common.py +0 -88
  693. relationalai/semantics/reasoners/optimization/solvers_dev.py +0 -568
  694. relationalai/semantics/reasoners/optimization/solvers_pb.py +0 -1163
  695. relationalai/semantics/rel/builtins.py +0 -40
  696. relationalai/semantics/rel/compiler.py +0 -989
  697. relationalai/semantics/rel/executor.py +0 -362
  698. relationalai/semantics/rel/rel.py +0 -482
  699. relationalai/semantics/rel/rel_utils.py +0 -276
  700. relationalai/semantics/snowflake/__init__.py +0 -3
  701. relationalai/semantics/sql/compiler.py +0 -2503
  702. relationalai/semantics/sql/executor/duck_db.py +0 -52
  703. relationalai/semantics/sql/executor/result_helpers.py +0 -64
  704. relationalai/semantics/sql/executor/snowflake.py +0 -149
  705. relationalai/semantics/sql/rewrite/denormalize.py +0 -222
  706. relationalai/semantics/sql/rewrite/double_negation.py +0 -49
  707. relationalai/semantics/sql/rewrite/recursive_union.py +0 -127
  708. relationalai/semantics/sql/rewrite/sort_output_query.py +0 -246
  709. relationalai/semantics/sql/sql.py +0 -504
  710. relationalai/semantics/std/pragmas.py +0 -11
  711. relationalai/semantics/std/std.py +0 -14
  712. relationalai/semantics/tests/test_snapshot_abstract.py +0 -143
  713. relationalai/semantics/tests/test_snapshot_base.py +0 -9
  714. relationalai/semantics/tests/utils.py +0 -46
  715. relationalai/std/__init__.py +0 -70
  716. relationalai/tools/cli.py +0 -1936
  717. relationalai/tools/cli_controls.py +0 -1826
  718. relationalai/tools/cli_helpers.py +0 -398
  719. relationalai/tools/debugger_client.py +0 -109
  720. relationalai/tools/debugger_server.py +0 -302
  721. relationalai/tools/dev.py +0 -685
  722. relationalai/tools/notes +0 -7
  723. relationalai/tools/qb_debugger.py +0 -425
  724. relationalai/util/clean_up_databases.py +0 -95
  725. relationalai/util/list_databases.py +0 -9
  726. relationalai/util/otel_configuration.py +0 -26
  727. relationalai/util/otel_handler.py +0 -484
  728. relationalai/util/snowflake_handler.py +0 -88
  729. relationalai/util/span_format_test.py +0 -43
  730. relationalai/util/span_tracker.py +0 -207
  731. relationalai/util/spans_file_handler.py +0 -72
  732. relationalai/util/tracing_handler.py +0 -34
  733. relationalai-0.13.0.dist-info/METADATA +0 -74
  734. relationalai-0.13.0.dist-info/RECORD +0 -458
  735. relationalai-0.13.0.dist-info/WHEEL +0 -4
  736. relationalai-0.13.0.dist-info/entry_points.txt +0 -3
  737. relationalai-0.13.0.dist-info/licenses/LICENSE +0 -202
  738. relationalai_test_util/__init__.py +0 -4
  739. relationalai_test_util/fixtures.py +0 -229
  740. relationalai_test_util/snapshot.py +0 -252
  741. relationalai_test_util/traceback.py +0 -118
  742. /relationalai/{analysis → semantics/frontend}/__init__.py +0 -0
  743. /relationalai/{auth/__init__.py → semantics/metamodel/metamodel_compiler.py} +0 -0
  744. /relationalai/{early_access → shims}/__init__.py +0 -0
  745. {relationalai/early_access/dsl/adapters → v0/relationalai/analysis}/__init__.py +0 -0
  746. {relationalai → v0/relationalai}/analysis/mechanistic.py +0 -0
  747. {relationalai → v0/relationalai}/analysis/whynot.py +0 -0
  748. {relationalai/early_access/dsl/adapters/orm → v0/relationalai/auth}/__init__.py +0 -0
  749. {relationalai → v0/relationalai}/auth/jwt_generator.py +0 -0
  750. {relationalai → v0/relationalai}/auth/oauth_callback_server.py +0 -0
  751. {relationalai → v0/relationalai}/auth/token_handler.py +0 -0
  752. {relationalai → v0/relationalai}/auth/util.py +0 -0
  753. {relationalai/clients/resources/snowflake → v0/relationalai/clients}/cache_store.py +0 -0
  754. {relationalai → v0/relationalai}/compiler.py +0 -0
  755. {relationalai → v0/relationalai}/dependencies.py +0 -0
  756. {relationalai → v0/relationalai}/docutils.py +0 -0
  757. {relationalai/early_access/dsl/adapters/owl → v0/relationalai/early_access}/__init__.py +0 -0
  758. {relationalai → v0/relationalai}/early_access/dsl/__init__.py +0 -0
  759. {relationalai/early_access/dsl/bindings → v0/relationalai/early_access/dsl/adapters}/__init__.py +0 -0
  760. {relationalai/early_access/dsl/bindings/legacy → v0/relationalai/early_access/dsl/adapters/orm}/__init__.py +0 -0
  761. {relationalai → v0/relationalai}/early_access/dsl/adapters/orm/model.py +0 -0
  762. {relationalai/early_access/dsl/codegen → v0/relationalai/early_access/dsl/adapters/owl}/__init__.py +0 -0
  763. {relationalai → v0/relationalai}/early_access/dsl/adapters/owl/model.py +0 -0
  764. {relationalai/early_access/dsl/core/temporal → v0/relationalai/early_access/dsl/bindings}/__init__.py +0 -0
  765. {relationalai/early_access/dsl/ir → v0/relationalai/early_access/dsl/bindings/legacy}/__init__.py +0 -0
  766. {relationalai/early_access/dsl/ontologies → v0/relationalai/early_access/dsl/codegen}/__init__.py +0 -0
  767. {relationalai → v0/relationalai}/early_access/dsl/constants.py +0 -0
  768. {relationalai → v0/relationalai}/early_access/dsl/core/__init__.py +0 -0
  769. {relationalai → v0/relationalai}/early_access/dsl/core/constraints/__init__.py +0 -0
  770. {relationalai → v0/relationalai}/early_access/dsl/core/constraints/predicate/__init__.py +0 -0
  771. {relationalai → v0/relationalai}/early_access/dsl/core/stack.py +0 -0
  772. {relationalai/early_access/dsl/orm → v0/relationalai/early_access/dsl/core/temporal}/__init__.py +0 -0
  773. {relationalai → v0/relationalai}/early_access/dsl/core/utils.py +0 -0
  774. {relationalai/early_access/dsl/orm/measures → v0/relationalai/early_access/dsl/ir}/__init__.py +0 -0
  775. {relationalai/early_access/dsl/physical_metadata → v0/relationalai/early_access/dsl/ontologies}/__init__.py +0 -0
  776. {relationalai → v0/relationalai}/early_access/dsl/ontologies/raw_source.py +0 -0
  777. {relationalai/early_access/dsl/serialize → v0/relationalai/early_access/dsl/orm}/__init__.py +0 -0
  778. {relationalai/early_access/dsl/snow → v0/relationalai/early_access/dsl/orm/measures}/__init__.py +0 -0
  779. {relationalai → v0/relationalai}/early_access/dsl/orm/reasoner_errors.py +0 -0
  780. {relationalai/loaders → v0/relationalai/early_access/dsl/physical_metadata}/__init__.py +0 -0
  781. {relationalai/semantics/tests → v0/relationalai/early_access/dsl/serialize}/__init__.py +0 -0
  782. {relationalai → v0/relationalai}/early_access/dsl/serialize/binding_model.py +0 -0
  783. {relationalai → v0/relationalai}/early_access/dsl/serialize/model.py +0 -0
  784. {relationalai/tools → v0/relationalai/early_access/dsl/snow}/__init__.py +0 -0
  785. {relationalai → v0/relationalai}/early_access/tests/__init__.py +0 -0
  786. {relationalai → v0/relationalai}/environments/ci.py +0 -0
  787. {relationalai → v0/relationalai}/environments/hex.py +0 -0
  788. {relationalai → v0/relationalai}/environments/terminal.py +0 -0
  789. {relationalai → v0/relationalai}/experimental/__init__.py +0 -0
  790. {relationalai → v0/relationalai}/experimental/graphs.py +0 -0
  791. {relationalai → v0/relationalai}/experimental/paths/__init__.py +0 -0
  792. {relationalai → v0/relationalai}/experimental/paths/benchmarks/__init__.py +0 -0
  793. {relationalai → v0/relationalai}/experimental/paths/path_algorithms/__init__.py +0 -0
  794. {relationalai → v0/relationalai}/experimental/paths/rpq/__init__.py +0 -0
  795. {relationalai → v0/relationalai}/experimental/paths/rpq/filter.py +0 -0
  796. {relationalai → v0/relationalai}/experimental/paths/rpq/glushkov.py +0 -0
  797. {relationalai → v0/relationalai}/experimental/paths/rpq/transition.py +0 -0
  798. {relationalai → v0/relationalai}/experimental/paths/utilities/__init__.py +0 -0
  799. {relationalai → v0/relationalai}/experimental/paths/utilities/utilities.py +0 -0
  800. {relationalai → v0/relationalai}/metagen.py +0 -0
  801. {relationalai → v0/relationalai}/metamodel.py +0 -0
  802. {relationalai → v0/relationalai}/rel.py +0 -0
  803. {relationalai → v0/relationalai}/semantics/devtools/__init__.py +0 -0
  804. {relationalai → v0/relationalai}/semantics/internal/__init__.py +0 -0
  805. {relationalai → v0/relationalai}/semantics/internal/annotations.py +0 -0
  806. {relationalai → v0/relationalai}/semantics/lqp/__init__.py +0 -0
  807. {relationalai → v0/relationalai}/semantics/lqp/ir.py +0 -0
  808. {relationalai → v0/relationalai}/semantics/lqp/pragmas.py +0 -0
  809. {relationalai → v0/relationalai}/semantics/lqp/rewrite/__init__.py +0 -0
  810. {relationalai → v0/relationalai}/semantics/metamodel/dataflow.py +0 -0
  811. {relationalai → v0/relationalai}/semantics/metamodel/ir.py +0 -0
  812. {relationalai → v0/relationalai}/semantics/metamodel/rewrite/__init__.py +0 -0
  813. {relationalai → v0/relationalai}/semantics/metamodel/typer/__init__.py +0 -0
  814. {relationalai → v0/relationalai}/semantics/metamodel/types.py +0 -0
  815. {relationalai → v0/relationalai}/semantics/metamodel/visitor.py +0 -0
  816. {relationalai → v0/relationalai}/semantics/reasoners/experimental/__init__.py +0 -0
  817. {relationalai → v0/relationalai}/semantics/rel/__init__.py +0 -0
  818. {relationalai → v0/relationalai}/semantics/sql/__init__.py +0 -0
  819. {relationalai → v0/relationalai}/semantics/sql/executor/__init__.py +0 -0
  820. {relationalai → v0/relationalai}/semantics/sql/rewrite/__init__.py +0 -0
  821. {relationalai → v0/relationalai}/semantics/tests/logging.py +0 -0
  822. {relationalai → v0/relationalai}/std/aggregates.py +0 -0
  823. {relationalai → v0/relationalai}/std/dates.py +0 -0
  824. {relationalai → v0/relationalai}/std/graphs.py +0 -0
  825. {relationalai → v0/relationalai}/std/inspect.py +0 -0
  826. {relationalai → v0/relationalai}/std/math.py +0 -0
  827. {relationalai → v0/relationalai}/std/re.py +0 -0
  828. {relationalai → v0/relationalai}/std/strings.py +0 -0
  829. {relationalai → v0/relationalai}/tools/cleanup_snapshots.py +0 -0
  830. {relationalai → v0/relationalai}/tools/constants.py +0 -0
  831. {relationalai → v0/relationalai}/tools/query_utils.py +0 -0
  832. {relationalai → v0/relationalai}/tools/snapshot_viewer.py +0 -0
  833. {relationalai → v0/relationalai}/util/__init__.py +0 -0
  834. {relationalai → v0/relationalai}/util/constants.py +0 -0
  835. {relationalai → v0/relationalai}/util/graph.py +0 -0
  836. {relationalai → v0/relationalai}/util/timeout.py +0 -0
@@ -1,1011 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import Iterable, Dict, Optional, List, cast, TYPE_CHECKING
4
- import json
5
- import logging
6
- import uuid
7
-
8
- from .... import debugging
9
- from .cache_store import GraphIndexCache
10
- from .util import collect_error_messages
11
- from ...util import (
12
- get_pyrel_version,
13
- normalize_datetime,
14
- poll_with_specified_overhead,
15
- )
16
- from ....errors import (
17
- ERPNotRunningError,
18
- EngineProvisioningFailed,
19
- SnowflakeChangeTrackingNotEnabledException,
20
- SnowflakeTableObjectsException,
21
- SnowflakeTableObject,
22
- SnowflakeRaiAppNotStarted,
23
- )
24
- from ....tools.cli_controls import (
25
- DebuggingSpan,
26
- create_progress,
27
- TASK_CATEGORY_INDEXING,
28
- TASK_CATEGORY_PROVISIONING,
29
- TASK_CATEGORY_CHANGE_TRACKING,
30
- TASK_CATEGORY_CACHE,
31
- TASK_CATEGORY_RELATIONS,
32
- TASK_CATEGORY_STATUS,
33
- TASK_CATEGORY_VALIDATION,
34
- )
35
- from ....tools.constants import WAIT_FOR_STREAM_SYNC, Generation
36
-
37
- # Set up logger for this module
38
- logger = logging.getLogger(__name__)
39
-
40
-
41
- try:
42
- from rich.console import Console
43
- from rich.table import Table
44
- except ImportError:
45
- Console = None
46
- Table = None
47
-
48
- if TYPE_CHECKING:
49
- from .snowflake import Resources
50
- from .direct_access_resources import DirectAccessResources
51
-
52
- # Maximum number of items to show individual subtasks for
53
- # If more items than this, show a single summary subtask instead
54
- MAX_INDIVIDUAL_SUBTASKS = 5
55
-
56
- # Special engine name for CDC managed engine
57
- CDC_MANAGED_ENGINE = "CDC_MANAGED_ENGINE"
58
-
59
- # Maximum number of data source subtasks to show simultaneously
60
- # When one completes, the next one from the queue will be added
61
- MAX_DATA_SOURCE_SUBTASKS = 10
62
-
63
- # How often to check ERP status (every N iterations)
64
- # To limit performance overhead, we only check ERP status periodically
65
- ERP_CHECK_FREQUENCY = 15
66
-
67
- # Polling behavior constants
68
- POLL_OVERHEAD_RATE = 0.1 # Overhead rate for exponential backoff
69
- POLL_MAX_DELAY = 2.5 # Maximum delay between polls in seconds
70
-
71
- # SQL query template for getting stream column hashes
72
- # This query calculates a hash of column metadata (name, type, precision, scale, nullable)
73
- # to detect if source table schema has changed since stream was created
74
- STREAM_COLUMN_HASH_QUERY = """
75
- WITH stream_columns AS (
76
- SELECT
77
- fq_object_name,
78
- HASH(
79
- value:name::VARCHAR,
80
- CASE
81
- WHEN value:precision IS NOT NULL AND value:scale IS NOT NULL THEN CASE value:type::VARCHAR
82
- WHEN 'FIXED' THEN 'NUMBER'
83
- WHEN 'REAL' THEN 'FLOAT'
84
- WHEN 'TEXT' THEN 'TEXT'
85
- ELSE value:type::VARCHAR
86
- END || '(' || value:precision || ',' || value:scale || ')'
87
- WHEN value:precision IS NOT NULL AND value:scale IS NULL THEN CASE value:type::VARCHAR
88
- WHEN 'FIXED' THEN 'NUMBER'
89
- WHEN 'REAL' THEN 'FLOAT'
90
- WHEN 'TEXT' THEN 'TEXT'
91
- ELSE value:type::VARCHAR
92
- END || '(0,' || value:precision || ')'
93
- WHEN value:length IS NOT NULL THEN CASE value:type::VARCHAR
94
- WHEN 'FIXED' THEN 'NUMBER'
95
- WHEN 'REAL' THEN 'FLOAT'
96
- WHEN 'TEXT' THEN 'TEXT'
97
- ELSE value:type::VARCHAR
98
- END || '(' || value:length || ')'
99
- ELSE CASE value:type::VARCHAR
100
- WHEN 'FIXED' THEN 'NUMBER'
101
- WHEN 'REAL' THEN 'FLOAT'
102
- WHEN 'TEXT' THEN 'TEXT'
103
- ELSE value:type::VARCHAR
104
- END
105
- END,
106
- IFF(value:nullable::BOOLEAN, 'YES', 'NO')
107
- ) AS column_signature
108
- FROM {app_name}.api.data_streams,
109
- LATERAL FLATTEN(input => columns)
110
- WHERE rai_database = '{rai_database}'
111
- AND fq_object_name IN ({fqn_list})
112
- )
113
- SELECT
114
- fq_object_name AS FQ_OBJECT_NAME,
115
- HEX_ENCODE(HASH_AGG(column_signature)) AS STREAM_HASH
116
- FROM stream_columns
117
- GROUP BY fq_object_name;
118
- """
119
-
120
-
121
- class UseIndexPoller:
122
- """
123
- Encapsulates the polling logic for `use_index` streams.
124
- """
125
-
126
- def _add_stream_subtask(self, progress, fq_name: str, status: str, batches_count: int) -> bool:
127
- """Add a stream subtask if we haven't reached the limit.
128
-
129
- Returns:
130
- True if subtask was added, False if limit reached
131
- """
132
- if fq_name not in self.stream_task_ids and len(self.stream_task_ids) < MAX_DATA_SOURCE_SUBTASKS:
133
- # Get the position in the stream order (should already be there)
134
- if fq_name in self.stream_order:
135
- stream_position = self.stream_order.index(fq_name) + 1
136
- else:
137
- # Fallback if not in order (shouldn't happen)
138
- stream_position = 1
139
-
140
- # Build initial message based on status and batch count
141
- if status == "synced":
142
- initial_message = f"{fq_name} already synced"
143
- elif batches_count > 0:
144
- # Show stream position (x/y) before batch count
145
- initial_message = f"Syncing {fq_name} ({stream_position}/{self.total_streams}), batches: {batches_count}"
146
- else:
147
- initial_message = f"Syncing {fq_name} ({stream_position}/{self.total_streams})"
148
-
149
- self.stream_task_ids[fq_name] = progress.add_sub_task(initial_message, task_id=fq_name, category=TASK_CATEGORY_INDEXING)
150
-
151
- # Complete immediately if already synced (without recording completion time)
152
- if status == "synced":
153
- progress.complete_sub_task(fq_name, record_time=False)
154
-
155
- return True
156
- return False
157
-
158
- def __init__(
159
- self,
160
- resource: "Resources",
161
- app_name: str,
162
- sources: Iterable[str],
163
- model: str,
164
- engine_name: str,
165
- engine_size: Optional[str],
166
- language: str = "rel",
167
- program_span_id: Optional[str] = None,
168
- headers: Optional[Dict] = None,
169
- generation: Optional[Generation] = None,
170
- ):
171
- self.res = resource
172
- self.app_name = app_name
173
- self.sources = list(sources)
174
- self.model = model
175
- self.engine_name = engine_name
176
- self.engine_size = engine_size or self.res.config.get_default_engine_size()
177
- self.language = language
178
- self.program_span_id = program_span_id
179
- self.headers = headers or {}
180
- self.counter = 1
181
- self.check_ready_count = 0
182
- self.tables_with_not_enabled_change_tracking: List = []
183
- self.table_objects_with_other_errors: List = []
184
- self.engine_errors: List = []
185
- # Flag to only ensure the engine is created asynchronously the initial call
186
- self.init_engine_async = True
187
- # Initially, we assume that cdc is not checked,
188
- # then on subsequent calls, if we get if cdc is enabled, if it is not, we will check it
189
- # on every 5th iteration we reset the cdc status, so it will be checked again
190
- self.should_check_cdc = True
191
-
192
- self.wait_for_stream_sync = self.res.config.get(
193
- "wait_for_stream_sync", WAIT_FOR_STREAM_SYNC
194
- )
195
- current_user = self.res.get_sf_session().get_current_user()
196
- assert current_user is not None, "current_user must be set"
197
- self.data_freshness = self.res.config.get_data_freshness_mins()
198
- self.cache = GraphIndexCache(current_user, model, self.data_freshness, self.sources)
199
- self.sources = self.cache.choose_sources()
200
- # execution_id is allowed to group use_index call, which belongs to the same loop iteration
201
- self.execution_id = str(uuid.uuid4())
202
-
203
- self.pyrel_version = get_pyrel_version(generation)
204
-
205
- self.source_info = self.res._check_source_updates(self.sources)
206
-
207
- # Track subtask IDs for streams, engines, and relations across multiple poll iterations
208
- self.stream_task_ids = {}
209
- self.engine_task_ids = {}
210
- self.relations_task_id = None
211
- self._erp_check_task_id = None
212
-
213
- # Track total number of streams and current stream position for (x/y) progress display
214
- self.total_streams = 0
215
- self.stream_position = 0
216
- self.stream_order = [] # Track the order of streams as they appear in data
217
-
218
- # Timing will be tracked by TaskProgress
219
-
220
- def poll(self) -> None:
221
- """
222
- Standard stream-based polling for use_index.
223
- """
224
- # Read show_duration_summary config flag (defaults to True for backward compatibility)
225
- show_duration_summary = bool(self.res.config.get("show_duration_summary", True))
226
-
227
- with create_progress(
228
- description="Initializing data index",
229
- success_message="", # We'll handle this in the context manager
230
- leading_newline=True,
231
- trailing_newline=True,
232
- show_duration_summary=show_duration_summary,
233
- ) as progress:
234
- # Set process start time
235
- progress.set_process_start_time()
236
- progress.update_main_status("Validating data sources")
237
- self._maybe_delete_stale(progress)
238
-
239
- # Add cache usage subtask
240
- self._add_cache_subtask(progress)
241
-
242
- progress.update_main_status("Initializing data index")
243
- self._poll_loop(progress)
244
- self._post_check(progress)
245
-
246
- # Set process end time (summary will be automatically printed by __exit__)
247
- progress.set_process_end_time()
248
-
249
- def _add_cache_subtask(self, progress) -> None:
250
- """Add a subtask showing cache usage information only when cache is used."""
251
- if self.cache.using_cache:
252
- # Cache was used - show how many sources were cached
253
- total_sources = len(self.cache.sources)
254
- cached_sources = total_sources - len(self.sources)
255
-
256
- # Get the timestamp when sources were cached
257
- entry = self.cache._metadata.get("cachedIndices", {}).get(self.cache.key, {})
258
- cached_timestamp = entry.get("last_use_index_update_on", "")
259
-
260
- message = f"Using cached data for {cached_sources}/{total_sources} data streams"
261
- # Format the message with timestamp
262
- if cached_timestamp:
263
- message += f" (cached at {cached_timestamp})"
264
-
265
- progress.add_sub_task(message, task_id="cache_usage", category=TASK_CATEGORY_CACHE)
266
- # Complete the subtask immediately since it's just informational
267
- progress.complete_sub_task("cache_usage")
268
-
269
- def _get_stream_column_hashes(self, sources: List[str], progress) -> Dict[str, str]:
270
- """
271
- Query data_streams to get current column hashes for the given sources.
272
-
273
- Args:
274
- sources: List of source FQNs to query
275
- progress: TaskProgress instance for updating status on error
276
-
277
- Returns:
278
- Dict mapping FQN -> column hash
279
-
280
- Raises:
281
- ValueError: If the query fails (permissions, table doesn't exist, etc.)
282
- """
283
- from relationalai.clients.resources.snowflake import PYREL_ROOT_DB
284
-
285
- # Build FQN list for SQL IN clause
286
- fqn_list = ", ".join([f"'{source}'" for source in sources])
287
-
288
- # Format query template with actual values
289
- hash_query = STREAM_COLUMN_HASH_QUERY.format(
290
- app_name=self.app_name,
291
- rai_database=PYREL_ROOT_DB,
292
- fqn_list=fqn_list
293
- )
294
-
295
- try:
296
- hash_results = self.res._exec(hash_query)
297
- return {row["FQ_OBJECT_NAME"]: row["STREAM_HASH"] for row in hash_results}
298
-
299
- except Exception as e:
300
- logger.error(f"Failed to query stream column hashes: {e}")
301
- logger.error(f" Query: {hash_query[:200]}...")
302
- logger.error(f" Sources: {sources}")
303
- progress.update_main_status("❌ Failed to validate data stream metadata")
304
- raise ValueError(
305
- f"Failed to validate stream column hashes. This may indicate a permissions "
306
- f"issue or missing data_streams table. Error: {e}"
307
- ) from e
308
-
309
- def _filter_truly_stale_sources(self, stale_sources: List[str], progress) -> List[str]:
310
- """
311
- Filter stale sources to only include those with mismatched column hashes.
312
-
313
- Args:
314
- stale_sources: List of source FQNs marked as stale
315
- progress: TaskProgress instance for updating status on error
316
-
317
- Returns:
318
- List of truly stale sources that need to be deleted/recreated
319
-
320
- A source is truly stale if any of the following apply:
321
- - The stream doesn't exist (needs to be created)
322
- - The source table was recreated after the stream (table creation timestamp is newer)
323
- - The column hashes don't match (schema drift needs cleanup)
324
- """
325
- stream_hashes = self._get_stream_column_hashes(stale_sources, progress)
326
-
327
- truly_stale = []
328
- for source in stale_sources:
329
- source_hash = self.source_info[source].get("columns_hash")
330
- stream_hash = stream_hashes.get(source)
331
- table_created_at_raw = self.source_info[source].get("table_created_at")
332
- stream_created_at_raw = self.source_info[source].get("stream_created_at")
333
-
334
- table_created_at = normalize_datetime(table_created_at_raw)
335
- stream_created_at = normalize_datetime(stream_created_at_raw)
336
-
337
- recreated_table = False
338
- if table_created_at is not None and stream_created_at is not None:
339
- # If the source table was recreated (new creation timestamp) but kept
340
- # the same column definitions, we still need to recycle the stream so
341
- # that Snowflake picks up the new table instance.
342
- recreated_table = table_created_at > stream_created_at
343
-
344
- # Log hash comparison for debugging
345
- logger.debug(f"Source: {source}")
346
- logger.debug(f" Source table hash: {source_hash}")
347
- logger.debug(f" Stream hash: {stream_hash}")
348
- logger.debug(f" Match: {source_hash == stream_hash}")
349
- if recreated_table:
350
- logger.debug(" Table appears to have been recreated (table_created_at > stream_created_at)")
351
- logger.debug(f" table_created_at: {table_created_at}")
352
- logger.debug(f" stream_created_at: {stream_created_at}")
353
-
354
- if stream_hash is None or source_hash != stream_hash or recreated_table:
355
- logger.debug(" Action: DELETE (stale)")
356
- truly_stale.append(source)
357
- else:
358
- logger.debug(" Action: KEEP (valid)")
359
-
360
- logger.debug(f"Stale sources summary: {len(truly_stale)}/{len(stale_sources)} truly stale")
361
-
362
- return truly_stale
363
-
364
- def _add_deletion_subtasks(self, progress, sources: List[str]) -> None:
365
- """Add progress subtasks for source deletion.
366
-
367
- Args:
368
- progress: TaskProgress instance
369
- sources: List of source FQNs to be deleted
370
- """
371
- if len(sources) <= MAX_INDIVIDUAL_SUBTASKS:
372
- for i, source in enumerate(sources):
373
- progress.add_sub_task(
374
- f"Removing stale stream {source} ({i+1}/{len(sources)})",
375
- task_id=f"stale_source_{i}",
376
- category=TASK_CATEGORY_VALIDATION
377
- )
378
- else:
379
- progress.add_sub_task(
380
- f"Removing {len(sources)} stale data sources",
381
- task_id="stale_sources_summary",
382
- category=TASK_CATEGORY_VALIDATION
383
- )
384
-
385
- def _complete_deletion_subtasks(self, progress, sources: List[str], deleted_count: int) -> None:
386
- """Complete progress subtasks for source deletion.
387
-
388
- Args:
389
- progress: TaskProgress instance
390
- sources: List of source FQNs that were processed
391
- deleted_count: Number of sources successfully deleted
392
- """
393
- if len(sources) <= MAX_INDIVIDUAL_SUBTASKS:
394
- for i in range(len(sources)):
395
- if f"stale_source_{i}" in progress._tasks:
396
- progress.complete_sub_task(f"stale_source_{i}")
397
- else:
398
- if "stale_sources_summary" in progress._tasks:
399
- if deleted_count > 0:
400
- s = "s" if deleted_count > 1 else ""
401
- progress.update_sub_task(
402
- "stale_sources_summary",
403
- f"Removed {deleted_count} stale data source{s}"
404
- )
405
- progress.complete_sub_task("stale_sources_summary")
406
-
407
- def _maybe_delete_stale(self, progress) -> None:
408
- """Check for and delete stale data streams that need recreation.
409
-
410
- Args:
411
- progress: TaskProgress instance for tracking deletion progress
412
- """
413
- with debugging.span("check_sources"):
414
- stale_sources = [
415
- source
416
- for source, info in self.source_info.items()
417
- if info.get("state") == "STALE"
418
- ]
419
-
420
- if not stale_sources:
421
- return
422
-
423
- with DebuggingSpan("validate_sources"):
424
- try:
425
- # Validate which sources truly need deletion by comparing column hashes
426
- truly_stale = self._filter_truly_stale_sources(stale_sources, progress)
427
-
428
- if not truly_stale:
429
- return
430
-
431
- # Delete truly stale streams
432
- from relationalai.clients.resources.snowflake import PYREL_ROOT_DB
433
- query = f"CALL {self.app_name}.api.delete_data_streams({truly_stale}, '{PYREL_ROOT_DB}');"
434
-
435
- self._add_deletion_subtasks(progress, truly_stale)
436
-
437
- delete_response = self.res._exec(query)
438
- delete_json_str = delete_response[0]["DELETE_DATA_STREAMS"].lower()
439
- delete_data = json.loads(delete_json_str)
440
- deleted_count = delete_data.get("deleted", 0)
441
-
442
- self._complete_deletion_subtasks(progress, truly_stale, deleted_count)
443
-
444
- # Check for errors
445
- diff = len(truly_stale) - deleted_count
446
- if diff > 0:
447
- errors = delete_data.get("errors", None)
448
- if errors:
449
- raise Exception(f"Error(s) deleting streams with modified sources: {errors}")
450
-
451
- except Exception as e:
452
- # Complete any remaining subtasks
453
- self._complete_deletion_subtasks(progress, stale_sources, 0)
454
- if "stale_sources_summary" in progress._tasks:
455
- progress.update_sub_task(
456
- "stale_sources_summary",
457
- f"❌ Failed to remove stale sources: {str(e)}"
458
- )
459
-
460
- # Don't raise if streams don't exist - this is expected
461
- messages = collect_error_messages(e)
462
- if not any("data streams do not exist" in msg for msg in messages):
463
- raise e from None
464
-
465
- def _poll_loop(self, progress) -> None:
466
- """Main polling loop for use_index streams.
467
-
468
- Args:
469
- progress: TaskProgress instance for tracking polling progress
470
- """
471
- source_references = self.res._get_source_references(self.source_info)
472
- sources_object_references_str = ", ".join(source_references)
473
-
474
- def check_ready(progress) -> bool:
475
- self.check_ready_count += 1
476
-
477
- # To limit the performance overhead, we only check if ERP is running every N iterations
478
- if self.check_ready_count % ERP_CHECK_FREQUENCY == 0:
479
- with debugging.span("check_erp_status"):
480
- # Add subtask for ERP status check
481
- if self._erp_check_task_id is None:
482
- self._erp_check_task_id = progress.add_sub_task("Checking system status", task_id="erp_check", category=TASK_CATEGORY_STATUS)
483
-
484
- if not self.res.is_erp_running(self.app_name):
485
- progress.update_sub_task("erp_check", "❌ System status check failed")
486
- progress.complete_sub_task("erp_check")
487
- raise ERPNotRunningError
488
- else:
489
- progress.update_sub_task("erp_check", "System status check complete")
490
- progress.complete_sub_task("erp_check")
491
-
492
- use_index_id = f"{self.model}_{self.execution_id}"
493
-
494
- params = json.dumps({
495
- "model": self.model,
496
- "engine": self.engine_name,
497
- "default_engine_size": self.engine_size, # engine_size
498
- "user_agent": self.pyrel_version,
499
- "use_index_id": use_index_id,
500
- "pyrel_program_id": self.program_span_id,
501
- "wait_for_stream_sync": self.wait_for_stream_sync,
502
- "should_check_cdc": self.should_check_cdc,
503
- "init_engine_async": self.init_engine_async,
504
- "language": self.language,
505
- "data_freshness_mins": self.data_freshness,
506
- })
507
-
508
- request_headers = debugging.add_current_propagation_headers(self.headers)
509
-
510
- sql_string = f"CALL {self.app_name}.api.use_index([{sources_object_references_str}], PARSE_JSON(?), {request_headers});"
511
-
512
- with debugging.span("wait", counter=self.counter, use_index_id=use_index_id) as span:
513
- results = self.res._exec(sql_string, [params])
514
-
515
- # Extract the JSON string from the `USE_INDEX` field
516
- use_index_json_str = results[0]["USE_INDEX"]
517
-
518
- # Parse the JSON string into a Python dictionary
519
- try:
520
- use_index_data = json.loads(use_index_json_str)
521
- except json.JSONDecodeError as e:
522
- logger.error(f"Invalid JSON from use_index API: {e}")
523
- logger.error(f"Raw response (first 500 chars): {use_index_json_str[:500]}")
524
- progress.update_main_status("❌ Received invalid response from server")
525
- raise ValueError(f"Invalid JSON response from use_index: {e}") from e
526
-
527
- span.update(use_index_data)
528
-
529
- # Log the full use_index_data for debugging if needed
530
- logger.debug(f"use_index_data: {json.dumps(use_index_data, indent=4)}")
531
-
532
- all_data = use_index_data.get("data", [])
533
- ready = use_index_data.get("ready", False)
534
- engines = use_index_data.get("engines", [])
535
- errors = use_index_data.get("errors", [])
536
- relations = use_index_data.get("relations", {})
537
- cdc_enabled = use_index_data.get("cdcEnabled", False)
538
- if self.check_ready_count % ERP_CHECK_FREQUENCY == 0 or not cdc_enabled:
539
- self.should_check_cdc = True
540
- else:
541
- self.should_check_cdc = False
542
-
543
- if engines and self.init_engine_async:
544
- self.init_engine_async = False
545
-
546
- break_loop = False
547
- has_stream_errors = False
548
- has_general_errors = False
549
-
550
- # Update main progress message
551
- if ready:
552
- progress.update_main_status("Done")
553
-
554
- # Handle streams data
555
- if not ready and all_data:
556
- progress.update_main_status("Processing background tasks. This may take a while...")
557
-
558
- # Build complete stream order first (only on first iteration with data)
559
- if self.total_streams == 0:
560
- for data in all_data:
561
- if data is None:
562
- continue
563
- fq_name = data.get("fq_object_name", "Unknown")
564
- if fq_name not in self.stream_order:
565
- self.stream_order.append(fq_name)
566
-
567
- # Set total streams count based on complete order (only once)
568
- self.total_streams = len(self.stream_order)
569
-
570
- # Add new streams as subtasks if we haven't reached the limit
571
- for data in all_data:
572
- fq_name = data.get("fq_object_name", "Unknown")
573
- status = data.get("data_sync_status", "").lower() if data else ""
574
- batches_count = data.get("pending_batches_count", 0)
575
-
576
- # Only add if we haven't seen this stream and we're under the limit
577
- self._add_stream_subtask(progress, fq_name, status, batches_count)
578
-
579
- # Handle errors for existing streams
580
- if fq_name in self.stream_task_ids and data.get("errors", []):
581
- for error in data.get("errors", []):
582
- error_msg = f"{error.get('error')}, source: {error.get('source')}"
583
- # Some failures indicate the RAI app is not started/active; surface
584
- # them as a rich, actionable error instead of aggregating.
585
- self._raise_if_app_not_started(error_msg)
586
- self.table_objects_with_other_errors.append(
587
- SnowflakeTableObject(error_msg, fq_name)
588
- )
589
- # Mark stream as failed
590
- progress.update_sub_task(fq_name, f"❌ Failed: {fq_name}")
591
- has_stream_errors = True
592
-
593
- # Update stream status (only for streams that aren't already completed)
594
- if fq_name in self.stream_task_ids and fq_name in progress._tasks and not progress._tasks[fq_name].completed:
595
- # Get the stream position from the stream order
596
- if fq_name in self.stream_order:
597
- stream_position = self.stream_order.index(fq_name) + 1
598
- else:
599
- # Fallback to 1 if not in order (shouldn't happen)
600
- stream_position = 1
601
-
602
- # Build status message
603
- if batches_count > 0 and status == 'syncing':
604
- status_message = f"Syncing {fq_name} ({stream_position}/{self.total_streams}), batches: {batches_count}"
605
- else:
606
- status_message = f"Pending {fq_name} ({stream_position}/{self.total_streams})..."
607
-
608
- progress.update_sub_task(fq_name, status_message)
609
-
610
- # Complete the stream if it's synced
611
- if status == "synced":
612
- progress.complete_sub_task(fq_name)
613
-
614
- # Add more streams from the queue if we have space and more streams exist
615
- if len(self.stream_task_ids) < MAX_DATA_SOURCE_SUBTASKS:
616
- for data in all_data:
617
- fq_name = data.get("fq_object_name", "Unknown")
618
- status = data.get("data_sync_status", "").lower()
619
- batches_count = data.get("pending_batches_count", 0)
620
-
621
- self._add_stream_subtask(progress, fq_name, status, batches_count)
622
-
623
- self.counter += 1
624
-
625
- # Handle engines data
626
- if not ready and engines:
627
- # Add new engines as subtasks if they don't exist
628
- for engine in engines:
629
- if not engine or not isinstance(engine, dict):
630
- continue
631
- size = self.engine_size
632
- name = engine.get("name", "Unknown")
633
- status = (engine.get("status") or "").lower()
634
- sub_task_id = self.engine_task_ids.get(name, None)
635
- sub_task_status_message = ""
636
-
637
- # Complete the sub task if it exists and the engine status is ready
638
- if sub_task_id and name in progress._tasks and not progress._tasks[name].completed and (status == "ready"):
639
- sub_task_status_message = f"Engine {name} ({size}) ready"
640
- progress.update_sub_task(name, sub_task_status_message)
641
- progress.complete_sub_task(name)
642
-
643
- # Add the sub task if it doesn't exist and the engine status is pending
644
- if not sub_task_id and status == "pending":
645
- writer = engine.get("writer", False)
646
- engine_type = "writer engine" if writer else "engine"
647
- sub_task_status_message = f"Provisioning {engine_type} {name} ({size})"
648
- self.engine_task_ids[name] = progress.add_sub_task(sub_task_status_message, task_id=name, category=TASK_CATEGORY_PROVISIONING)
649
-
650
- # Special handling for CDC_MANAGED_ENGINE - mark ready when any stream starts processing
651
- cdc_task = progress._tasks.get(CDC_MANAGED_ENGINE) if CDC_MANAGED_ENGINE in progress._tasks else None
652
- if CDC_MANAGED_ENGINE in self.engine_task_ids and cdc_task and not cdc_task.completed:
653
-
654
- has_processing_streams = any(
655
- stream.get("next_batch_status", "") == "processing"
656
- for stream in all_data
657
- )
658
- if has_processing_streams and cdc_task and not cdc_task.completed:
659
- progress.update_sub_task(CDC_MANAGED_ENGINE, f"Engine {CDC_MANAGED_ENGINE} ({self.engine_size}) ready")
660
- progress.complete_sub_task(CDC_MANAGED_ENGINE)
661
-
662
- self.counter += 1
663
-
664
- # Handle relations data
665
- if relations and isinstance(relations, dict):
666
- txn = relations.get("txn", {}) or {}
667
- txn_id = txn.get("id", None)
668
-
669
- # Only show relations subtask if there is a valid txn object
670
- if txn_id:
671
- status = relations.get("status", "").upper()
672
-
673
- # Create relations subtask if it doesn't exist
674
- if self.relations_task_id is None:
675
- self.relations_task_id = progress.add_sub_task("Populating relations", task_id="relations", category=TASK_CATEGORY_RELATIONS)
676
-
677
- # Set the start time from the JSON if available (always update)
678
- start_time_ms = relations.get("start_time")
679
- if start_time_ms:
680
- start_time_seconds = start_time_ms / 1000.0
681
- progress._tasks["relations"].added_time = start_time_seconds
682
-
683
- # Update relations status
684
- if status == "COMPLETED":
685
- progress.update_sub_task("relations", f"Relations populated (txn: {txn_id})")
686
-
687
- # Set the completion time from the JSON if available
688
- end_time_ms = relations.get("end_time")
689
- if end_time_ms:
690
- end_time_seconds = end_time_ms / 1000.0
691
- progress._tasks["relations"].completed_time = end_time_seconds
692
-
693
- progress.complete_sub_task("relations", record_time=False) # Don't record local time
694
- else:
695
- progress.update_sub_task("relations", f"Relations populating (txn: {txn_id})")
696
-
697
- self.counter += 1
698
-
699
- # Handle errors
700
- if not ready and errors:
701
- for error in errors:
702
- if error is None:
703
- continue
704
- if error.get("type") == "data":
705
- message = error.get("message", "").lower()
706
- if ("change_tracking" in message or "change tracking" in message):
707
- err_source = error.get("source")
708
- err_source_type = self.source_info.get(err_source, {}).get("type")
709
- self.tables_with_not_enabled_change_tracking.append((err_source, err_source_type))
710
- else:
711
- self._raise_if_app_not_started(error.get("message", ""))
712
- self.table_objects_with_other_errors.append(
713
- SnowflakeTableObject(error.get("message"), error.get("source"))
714
- )
715
- elif error.get("type") == "engine":
716
- self.engine_errors.append(error)
717
- else:
718
- # Other types of errors, e.g. "validation"
719
- self._raise_if_app_not_started(error.get("message", ""))
720
- self.table_objects_with_other_errors.append(
721
- SnowflakeTableObject(error.get("message"), error.get("source"))
722
- )
723
- has_general_errors = True
724
-
725
- # If ready, complete all remaining subtasks
726
- if ready:
727
- self.cache.record_update(self.source_info)
728
- # Complete any remaining stream subtasks
729
- for fq_name in self.stream_task_ids:
730
- if fq_name in progress._tasks and not progress._tasks[fq_name].completed:
731
- progress.complete_sub_task(fq_name)
732
- # Complete any remaining engine subtasks
733
- for name in self.engine_task_ids:
734
- if name in progress._tasks and not progress._tasks[name].completed:
735
- progress.complete_sub_task(name)
736
- # Complete relations subtask if it exists and isn't completed
737
- if self.relations_task_id and "relations" in progress._tasks and not progress._tasks["relations"].completed:
738
- progress.complete_sub_task("relations")
739
- break_loop = True
740
- elif has_stream_errors or has_general_errors:
741
- # Break the loop if there are errors, but only after reporting all progress
742
- break_loop = True
743
-
744
- return break_loop
745
-
746
- poll_with_specified_overhead(lambda: check_ready(progress), overhead_rate=POLL_OVERHEAD_RATE, max_delay=POLL_MAX_DELAY)
747
-
748
- def _raise_if_app_not_started(self, message: str) -> None:
749
- """Detect Snowflake-side 'app not active / service not started' messages and raise a rich exception.
750
-
751
- The use_index stored procedure reports many failures inside the returned JSON payload
752
- (use_index_data['errors']) rather than raising them as Snowflake exceptions, so the
753
- standard `_exec()` error handlers won't run. We detect the known activation-needed
754
- signals here and raise `SnowflakeRaiAppNotStarted` for nicer formatting.
755
- """
756
- if not message:
757
- return
758
- msg = str(message).lower()
759
- if (
760
- "service has not been started" in msg
761
- or "call app.activate()" in msg
762
- or "app_not_active_exception" in msg
763
- or "application is not active" in msg
764
- or "use the app.activate()" in msg
765
- ):
766
- app_name = self.res.config.get("rai_app_name", "") if hasattr(self.res, "config") else ""
767
- if not isinstance(app_name, str) or not app_name:
768
- app_name = self.app_name
769
- raise SnowflakeRaiAppNotStarted(app_name)
770
-
771
- def _post_check(self, progress) -> None:
772
- """Run post-processing checks including change tracking enablement.
773
-
774
- Args:
775
- progress: TaskProgress instance for tracking progress
776
-
777
- Raises:
778
- SnowflakeChangeTrackingNotEnabledException: If change tracking cannot be enabled
779
- SnowflakeTableObjectsException: If there are table-related errors
780
- EngineProvisioningFailed: If engine provisioning fails
781
- """
782
- num_tables_altered = 0
783
- failed_tables = [] # Track tables that failed to enable change tracking
784
-
785
- enabled_tables = []
786
- if (
787
- self.tables_with_not_enabled_change_tracking
788
- and self.res.config.get("ensure_change_tracking", False)
789
- ):
790
- tables_to_process = self.tables_with_not_enabled_change_tracking
791
- # Track timing for change tracking
792
-
793
- # Add subtasks based on count
794
- if len(tables_to_process) <= MAX_INDIVIDUAL_SUBTASKS:
795
- # Add individual subtasks for each table
796
- for i, table in enumerate(tables_to_process):
797
- fqn, kind = table
798
- progress.add_sub_task(f"Enabling change tracking on {fqn} ({i+1}/{len(tables_to_process)})", task_id=f"change_tracking_{i}", category=TASK_CATEGORY_CHANGE_TRACKING)
799
- else:
800
- # Add single summary subtask for many tables
801
- progress.add_sub_task(f"Enabling change tracking on {len(tables_to_process)} tables", task_id="change_tracking_summary", category=TASK_CATEGORY_CHANGE_TRACKING)
802
-
803
- # Process tables
804
- for i, table in enumerate(tables_to_process):
805
- fqn, kind = table # Unpack outside try block to ensure fqn is defined
806
-
807
- try:
808
- # Validate table_type to prevent SQL injection
809
- # Should only be TABLE or VIEW
810
- if kind not in ("TABLE", "VIEW"):
811
- logger.error(f"Invalid table kind '{kind}' for {fqn}, skipping")
812
- failed_tables.append((fqn, f"Invalid table kind: {kind}"))
813
- # Mark as failed in progress
814
- if len(tables_to_process) <= MAX_INDIVIDUAL_SUBTASKS:
815
- if f"change_tracking_{i}" in progress._tasks:
816
- progress.update_sub_task(f"change_tracking_{i}", f"❌ Invalid type: {fqn}")
817
- progress.complete_sub_task(f"change_tracking_{i}")
818
- continue
819
-
820
- # Execute ALTER statement
821
- # Note: fqn should already be properly quoted from source_info
822
- self.res._exec(f"ALTER {kind} {fqn} SET CHANGE_TRACKING = TRUE;")
823
- enabled_tables.append(table)
824
- num_tables_altered += 1
825
-
826
- # Update progress based on subtask type
827
- if len(tables_to_process) <= MAX_INDIVIDUAL_SUBTASKS:
828
- # Complete individual table subtask
829
- progress.complete_sub_task(f"change_tracking_{i}")
830
- else:
831
- # Update summary subtask with progress
832
- progress.update_sub_task("change_tracking_summary",
833
- f"Enabling change tracking on {len(tables_to_process)} tables... ({i+1}/{len(tables_to_process)})")
834
- except Exception as e:
835
- # Log the error for debugging
836
- logger.warning(f"Failed to enable change tracking on {fqn}: {e}")
837
- failed_tables.append((fqn, str(e)))
838
-
839
- # Handle errors based on subtask type
840
- if len(tables_to_process) <= MAX_INDIVIDUAL_SUBTASKS:
841
- # Mark the individual subtask as failed and complete it
842
- if f"change_tracking_{i}" in progress._tasks:
843
- progress.update_sub_task(f"change_tracking_{i}", f"❌ Failed: {fqn}")
844
- progress.complete_sub_task(f"change_tracking_{i}")
845
- # Continue processing other tables despite this failure
846
-
847
- # Complete summary subtask if used
848
- if len(tables_to_process) > MAX_INDIVIDUAL_SUBTASKS and "change_tracking_summary" in progress._tasks:
849
- if num_tables_altered > 0:
850
- s = "s" if num_tables_altered > 1 else ""
851
- success_msg = f"Enabled change tracking on {num_tables_altered} table{s}"
852
- if failed_tables:
853
- success_msg += f" ({len(failed_tables)} failed)"
854
- progress.update_sub_task("change_tracking_summary", success_msg)
855
- elif failed_tables:
856
- progress.update_sub_task("change_tracking_summary", f"❌ Failed on {len(failed_tables)} table(s)")
857
- progress.complete_sub_task("change_tracking_summary")
858
-
859
- # Log summary of failed tables
860
- if failed_tables:
861
- logger.warning(f"Failed to enable change tracking on {len(failed_tables)} table(s)")
862
- for fqn, error in failed_tables:
863
- logger.warning(f" {fqn}: {error}")
864
-
865
- # Remove the tables that were successfully enabled from the list of not enabled tables
866
- # so that we don't raise an exception for them later
867
- self.tables_with_not_enabled_change_tracking = [
868
- t for t in self.tables_with_not_enabled_change_tracking if t not in enabled_tables
869
- ]
870
-
871
- if self.tables_with_not_enabled_change_tracking:
872
- progress.update_main_status("Errors found. See below for details.")
873
- raise SnowflakeChangeTrackingNotEnabledException(
874
- self.tables_with_not_enabled_change_tracking
875
- )
876
-
877
- if self.table_objects_with_other_errors:
878
- progress.update_main_status("Errors found. See below for details.")
879
- raise SnowflakeTableObjectsException(self.table_objects_with_other_errors)
880
- if self.engine_errors:
881
- progress.update_main_status("Errors found. See below for details.")
882
- # if there is an engine error, probably auto create engine failed
883
- # Create a synthetic exception from the first engine error
884
- first_error = self.engine_errors[0]
885
- error_message = first_error.get("message", "Unknown engine error")
886
- synthetic_exception = Exception(f"Engine error: {error_message}")
887
- raise EngineProvisioningFailed(self.engine_name, synthetic_exception)
888
-
889
- if num_tables_altered > 0:
890
- self._poll_loop(progress)
891
-
892
- class DirectUseIndexPoller(UseIndexPoller):
893
- """
894
- Extends UseIndexPoller to handle direct-access prepare_index when no sources.
895
- """
896
- def __init__(
897
- self,
898
- resource: "DirectAccessResources",
899
- app_name: str,
900
- sources: Iterable[str],
901
- model: str,
902
- engine_name: str,
903
- engine_size: Optional[str],
904
- language: str = "rel",
905
- program_span_id: Optional[str] = None,
906
- headers: Optional[Dict] = None,
907
- generation: Optional[Generation] = None,
908
- ):
909
- super().__init__(
910
- resource=resource,
911
- app_name=app_name,
912
- sources=sources,
913
- model=model,
914
- engine_name=engine_name,
915
- engine_size=engine_size,
916
- language=language,
917
- program_span_id=program_span_id,
918
- headers=headers,
919
- generation=generation,
920
- )
921
- from relationalai.clients.resources.snowflake import DirectAccessResources
922
- self.res: DirectAccessResources = cast(DirectAccessResources, self.res)
923
-
924
- def poll(self) -> None:
925
- if not self.sources:
926
- from relationalai.errors import RAIException
927
- collected_errors: List[Dict] = []
928
- attempt = 1
929
-
930
- def check_direct(progress) -> bool:
931
- nonlocal attempt
932
- with debugging.span("wait", counter=self.counter) as span:
933
- span.update({"attempt": attempt, "engine_name": self.engine_name, "model": self.model})
934
- # we are skipping pulling relations here, as direct access only handle non-sources cases
935
- # and we don't need to pull relations for that, therefore, we pass empty list for rai_relations
936
- # and set skip_pull_relations to True
937
- resp = self.res._prepare_index(
938
- model=self.model,
939
- engine_name=self.engine_name,
940
- engine_size=self.engine_size,
941
- language=self.language,
942
- rai_relations=[],
943
- pyrel_program_id=self.program_span_id,
944
- skip_pull_relations=True,
945
- headers=self.headers,
946
- )
947
- span.update(resp)
948
- caller_engine = resp.get("caller_engine", {})
949
- # Handle case where caller_engine might be None
950
- ce_status = caller_engine.get("status", "").lower() if caller_engine else ""
951
- errors = resp.get("errors", [])
952
-
953
- ready = resp.get("ready", False)
954
-
955
- # Update main progress message
956
- if ready:
957
- progress.update_main_status("Done")
958
- else:
959
- progress.update_main_status("Preparing your data...")
960
-
961
- if ready:
962
- return True
963
- else:
964
- if ce_status == "pending":
965
- # Add or update engine subtask
966
- engine_name = caller_engine.get('name', self.engine_name)
967
- if not hasattr(progress, '_engine_task_id'):
968
- progress._engine_task_id = progress.add_sub_task(f"Waiting for engine '{engine_name}' to be ready...", task_id=engine_name)
969
- else:
970
- progress.update_sub_task(engine_name, f"Waiting for engine '{engine_name}' to be ready...")
971
- else:
972
- # Handle errors as subtasks
973
- if errors:
974
- progress.update_main_status("Encountered errors during preparation...")
975
- for i, err in enumerate(errors):
976
- error_id = f"error_{i}"
977
- if not hasattr(progress, f'_error_task_id_{i}'):
978
- error_msg = err.get('message', 'Unknown error')
979
- setattr(progress, f'_error_task_id_{i}', progress.add_sub_task(f"❌ {error_msg}", task_id=error_id))
980
- else:
981
- error_msg = err.get('message', 'Unknown error')
982
- progress.update_sub_task(error_id, f"❌ {error_msg}")
983
- collected_errors.append(err)
984
-
985
- attempt += 1
986
- return False
987
-
988
- # Read show_duration_summary config flag (defaults to True for backward compatibility)
989
- show_duration_summary = bool(self.res.config.get("show_duration_summary", True))
990
-
991
- with create_progress(
992
- description="Preparing your data...",
993
- success_message="Done",
994
- leading_newline=True,
995
- trailing_newline=True,
996
- show_duration_summary=show_duration_summary,
997
- ) as progress:
998
- # Add cache usage subtask
999
- self._add_cache_subtask(progress)
1000
-
1001
- with debugging.span("poll_direct"):
1002
- poll_with_specified_overhead(lambda: check_direct(progress), overhead_rate=POLL_OVERHEAD_RATE, max_delay=POLL_MAX_DELAY)
1003
-
1004
- # Run the same post-check logic as UseIndexPoller
1005
- self._post_check(progress)
1006
-
1007
- if collected_errors:
1008
- msg = "; ".join(e.get("message", "") for e in collected_errors)
1009
- raise RAIException(msg)
1010
- else:
1011
- super().poll()