relationalai 1.0.0a3__py3-none-any.whl → 1.0.0a5__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.
- relationalai/config/config.py +47 -21
- relationalai/config/connections/__init__.py +5 -2
- relationalai/config/connections/duckdb.py +2 -2
- relationalai/config/connections/local.py +31 -0
- relationalai/config/connections/snowflake.py +0 -1
- relationalai/config/external/raiconfig_converter.py +235 -0
- relationalai/config/external/raiconfig_models.py +202 -0
- relationalai/config/external/utils.py +31 -0
- relationalai/config/shims.py +1 -0
- relationalai/semantics/__init__.py +10 -8
- relationalai/semantics/backends/sql/sql_compiler.py +1 -4
- relationalai/semantics/experimental/__init__.py +0 -0
- relationalai/semantics/experimental/builder.py +295 -0
- relationalai/semantics/experimental/builtins.py +154 -0
- relationalai/semantics/frontend/base.py +67 -42
- relationalai/semantics/frontend/core.py +34 -6
- relationalai/semantics/frontend/front_compiler.py +209 -37
- relationalai/semantics/frontend/pprint.py +6 -2
- relationalai/semantics/metamodel/__init__.py +7 -0
- relationalai/semantics/metamodel/metamodel.py +2 -0
- relationalai/semantics/metamodel/metamodel_analyzer.py +58 -16
- relationalai/semantics/metamodel/pprint.py +6 -1
- relationalai/semantics/metamodel/rewriter.py +11 -7
- relationalai/semantics/metamodel/typer.py +116 -41
- relationalai/semantics/reasoners/__init__.py +11 -0
- relationalai/semantics/reasoners/graph/__init__.py +35 -0
- relationalai/semantics/reasoners/graph/core.py +9028 -0
- relationalai/semantics/std/__init__.py +30 -10
- relationalai/semantics/std/aggregates.py +641 -12
- relationalai/semantics/std/common.py +146 -13
- relationalai/semantics/std/constraints.py +71 -1
- relationalai/semantics/std/datetime.py +904 -21
- relationalai/semantics/std/decimals.py +143 -2
- relationalai/semantics/std/floats.py +57 -4
- relationalai/semantics/std/integers.py +98 -4
- relationalai/semantics/std/math.py +857 -35
- relationalai/semantics/std/numbers.py +216 -20
- relationalai/semantics/std/re.py +213 -5
- relationalai/semantics/std/strings.py +437 -44
- relationalai/shims/executor.py +60 -52
- relationalai/shims/fixtures.py +85 -0
- relationalai/shims/helpers.py +26 -2
- relationalai/shims/hoister.py +28 -9
- relationalai/shims/mm2v0.py +204 -173
- relationalai/tools/cli/cli.py +192 -10
- relationalai/tools/cli/components/progress_reader.py +1 -1
- relationalai/tools/cli/docs.py +394 -0
- relationalai/tools/debugger.py +11 -4
- relationalai/tools/qb_debugger.py +435 -0
- relationalai/tools/typer_debugger.py +1 -2
- relationalai/util/dataclasses.py +3 -5
- relationalai/util/docutils.py +1 -2
- relationalai/util/error.py +2 -5
- relationalai/util/python.py +23 -0
- relationalai/util/runtime.py +1 -2
- relationalai/util/schema.py +2 -4
- relationalai/util/structures.py +4 -2
- relationalai/util/tracing.py +8 -2
- {relationalai-1.0.0a3.dist-info → relationalai-1.0.0a5.dist-info}/METADATA +8 -5
- {relationalai-1.0.0a3.dist-info → relationalai-1.0.0a5.dist-info}/RECORD +118 -95
- {relationalai-1.0.0a3.dist-info → relationalai-1.0.0a5.dist-info}/WHEEL +1 -1
- v0/relationalai/__init__.py +1 -1
- v0/relationalai/clients/client.py +52 -18
- v0/relationalai/clients/exec_txn_poller.py +122 -0
- v0/relationalai/clients/local.py +23 -8
- v0/relationalai/clients/resources/azure/azure.py +36 -11
- v0/relationalai/clients/resources/snowflake/__init__.py +4 -4
- v0/relationalai/clients/resources/snowflake/cli_resources.py +12 -1
- v0/relationalai/clients/resources/snowflake/direct_access_resources.py +124 -100
- v0/relationalai/clients/resources/snowflake/engine_service.py +381 -0
- v0/relationalai/clients/resources/snowflake/engine_state_handlers.py +35 -29
- v0/relationalai/clients/resources/snowflake/error_handlers.py +43 -2
- v0/relationalai/clients/resources/snowflake/snowflake.py +277 -179
- v0/relationalai/clients/resources/snowflake/use_index_poller.py +8 -0
- v0/relationalai/clients/types.py +5 -0
- v0/relationalai/errors.py +19 -1
- v0/relationalai/semantics/lqp/algorithms.py +173 -0
- v0/relationalai/semantics/lqp/builtins.py +199 -2
- v0/relationalai/semantics/lqp/executor.py +68 -37
- v0/relationalai/semantics/lqp/ir.py +28 -2
- v0/relationalai/semantics/lqp/model2lqp.py +215 -45
- v0/relationalai/semantics/lqp/passes.py +13 -658
- v0/relationalai/semantics/lqp/rewrite/__init__.py +12 -0
- v0/relationalai/semantics/lqp/rewrite/algorithm.py +385 -0
- v0/relationalai/semantics/lqp/rewrite/constants_to_vars.py +70 -0
- v0/relationalai/semantics/lqp/rewrite/deduplicate_vars.py +104 -0
- v0/relationalai/semantics/lqp/rewrite/eliminate_data.py +108 -0
- v0/relationalai/semantics/lqp/rewrite/extract_keys.py +25 -3
- v0/relationalai/semantics/lqp/rewrite/period_math.py +77 -0
- v0/relationalai/semantics/lqp/rewrite/quantify_vars.py +65 -31
- v0/relationalai/semantics/lqp/rewrite/unify_definitions.py +317 -0
- v0/relationalai/semantics/lqp/utils.py +11 -1
- v0/relationalai/semantics/lqp/validators.py +14 -1
- v0/relationalai/semantics/metamodel/builtins.py +2 -1
- v0/relationalai/semantics/metamodel/compiler.py +2 -1
- v0/relationalai/semantics/metamodel/dependency.py +12 -3
- v0/relationalai/semantics/metamodel/executor.py +11 -1
- v0/relationalai/semantics/metamodel/factory.py +2 -2
- v0/relationalai/semantics/metamodel/helpers.py +7 -0
- v0/relationalai/semantics/metamodel/ir.py +3 -2
- v0/relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +30 -20
- v0/relationalai/semantics/metamodel/rewrite/flatten.py +50 -13
- v0/relationalai/semantics/metamodel/rewrite/format_outputs.py +9 -3
- v0/relationalai/semantics/metamodel/typer/checker.py +6 -4
- v0/relationalai/semantics/metamodel/typer/typer.py +4 -3
- v0/relationalai/semantics/metamodel/visitor.py +4 -3
- v0/relationalai/semantics/reasoners/optimization/solvers_dev.py +1 -1
- v0/relationalai/semantics/reasoners/optimization/solvers_pb.py +336 -86
- v0/relationalai/semantics/rel/compiler.py +2 -1
- v0/relationalai/semantics/rel/executor.py +3 -2
- v0/relationalai/semantics/tests/lqp/__init__.py +0 -0
- v0/relationalai/semantics/tests/lqp/algorithms.py +345 -0
- v0/relationalai/tools/cli.py +339 -186
- v0/relationalai/tools/cli_controls.py +216 -67
- v0/relationalai/tools/cli_helpers.py +410 -6
- v0/relationalai/util/format.py +5 -2
- {relationalai-1.0.0a3.dist-info → relationalai-1.0.0a5.dist-info}/entry_points.txt +0 -0
- {relationalai-1.0.0a3.dist-info → relationalai-1.0.0a5.dist-info}/top_level.txt +0 -0
|
@@ -13,7 +13,8 @@ class Flatten(Pass):
|
|
|
13
13
|
"""
|
|
14
14
|
Traverses the model's root to flatten it as much as possible. The result of this pass is
|
|
15
15
|
a Logical root where all nested tasks that represent a rule in Rel are extracted to the
|
|
16
|
-
top level.
|
|
16
|
+
top level. Additionally, any Sequence is promoted to the top level Logical (but
|
|
17
|
+
encapsulated by a Logical).
|
|
17
18
|
|
|
18
19
|
- nested logical with updates becomes a top-level logical (a rule)
|
|
19
20
|
|
|
@@ -122,6 +123,35 @@ class Flatten(Pass):
|
|
|
122
123
|
Logical
|
|
123
124
|
lookup tmp2
|
|
124
125
|
output
|
|
126
|
+
|
|
127
|
+
- a Sequence is promoted to the top level Logical, encapsulated by a Logical:
|
|
128
|
+
From:
|
|
129
|
+
Logical
|
|
130
|
+
Logical
|
|
131
|
+
lookup
|
|
132
|
+
derive foo
|
|
133
|
+
Sequence
|
|
134
|
+
Logical
|
|
135
|
+
...
|
|
136
|
+
Loop
|
|
137
|
+
Sequence
|
|
138
|
+
...
|
|
139
|
+
Logical
|
|
140
|
+
...
|
|
141
|
+
To:
|
|
142
|
+
Logical
|
|
143
|
+
Logical
|
|
144
|
+
lookup
|
|
145
|
+
derive foo
|
|
146
|
+
Logical
|
|
147
|
+
Sequence
|
|
148
|
+
Logical
|
|
149
|
+
...
|
|
150
|
+
Loop
|
|
151
|
+
Sequence
|
|
152
|
+
...
|
|
153
|
+
Logical
|
|
154
|
+
...
|
|
125
155
|
"""
|
|
126
156
|
|
|
127
157
|
def __init__(self, use_sql: bool=False):
|
|
@@ -181,11 +211,8 @@ class Flatten(Pass):
|
|
|
181
211
|
def handle(self, task: ir.Task, ctx: Context) -> Flatten.HandleResult:
|
|
182
212
|
if isinstance(task, ir.Logical):
|
|
183
213
|
return self.handle_logical(task, ctx)
|
|
184
|
-
elif isinstance(task, ir.Union) and
|
|
185
|
-
#
|
|
186
|
-
# then the Union acts as a filter, and it can be inefficient to flatten it.
|
|
187
|
-
#
|
|
188
|
-
# However, for the SQL backend, we always need to flatten Unions for correct SQL
|
|
214
|
+
elif isinstance(task, ir.Union) and self._use_sql:
|
|
215
|
+
# The SQL backend needs to flatten Unions for correct SQL
|
|
189
216
|
# generation.
|
|
190
217
|
return self.handle_union(task, ctx)
|
|
191
218
|
elif isinstance(task, ir.Match):
|
|
@@ -194,6 +221,8 @@ class Flatten(Pass):
|
|
|
194
221
|
return self.handle_require(task, ctx)
|
|
195
222
|
elif isinstance(task, ir.Not):
|
|
196
223
|
return self.handle_not(task, ctx)
|
|
224
|
+
elif isinstance(task, ir.Sequence):
|
|
225
|
+
return self.handle_sequence(task, ctx)
|
|
197
226
|
else:
|
|
198
227
|
return Flatten.HandleResult(task)
|
|
199
228
|
|
|
@@ -253,9 +282,9 @@ class Flatten(Pass):
|
|
|
253
282
|
|
|
254
283
|
for output in groups["outputs"]:
|
|
255
284
|
assert(isinstance(output, ir.Output))
|
|
256
|
-
new_body = info.task_dependencies(output)
|
|
257
|
-
new_body.update(ctx.extra_tasks)
|
|
258
|
-
new_body.add(output)
|
|
285
|
+
new_body = OrderedSet.from_iterable(t.clone() for t in info.task_dependencies(output))
|
|
286
|
+
new_body.update(t.clone() for t in ctx.extra_tasks)
|
|
287
|
+
new_body.add(output.clone())
|
|
259
288
|
ctx.rewrite_ctx.top_level.append(ir.Logical(task.engine, task.hoisted, tuple(new_body), task.annotations))
|
|
260
289
|
|
|
261
290
|
return Flatten.HandleResult(None)
|
|
@@ -263,9 +292,9 @@ class Flatten(Pass):
|
|
|
263
292
|
# if there are updates, extract as a new top level rule
|
|
264
293
|
if groups["updates"]:
|
|
265
294
|
# add task dependencies to the body
|
|
266
|
-
body.prefix(ctx.info.task_dependencies(task))
|
|
295
|
+
body.prefix(t.clone() for t in ctx.info.task_dependencies(task))
|
|
267
296
|
# potentially add context extra tasks
|
|
268
|
-
body.update(ctx.extra_tasks)
|
|
297
|
+
body.update(t.clone() for t in ctx.extra_tasks)
|
|
269
298
|
ctx.rewrite_ctx.top_level.append(ir.Logical(task.engine, task.hoisted, tuple(body), task.annotations))
|
|
270
299
|
return Flatten.HandleResult(None)
|
|
271
300
|
|
|
@@ -278,7 +307,7 @@ class Flatten(Pass):
|
|
|
278
307
|
agg = cast(ir.Aggregate, groups["aggregates"].some())
|
|
279
308
|
|
|
280
309
|
# add agg dependencies to the body
|
|
281
|
-
body.prefix(ctx.info.task_dependencies(agg))
|
|
310
|
+
body.prefix(t.clone() for t in ctx.info.task_dependencies(agg))
|
|
282
311
|
|
|
283
312
|
# extract a new logical for the aggregate, exposing aggregate group-by and results
|
|
284
313
|
exposed_vars = OrderedSet.from_iterable(list(agg.group) + helpers.aggregate_outputs(agg))
|
|
@@ -298,7 +327,7 @@ class Flatten(Pass):
|
|
|
298
327
|
rank = cast(ir.Rank, groups["ranks"].some())
|
|
299
328
|
|
|
300
329
|
# add rank dependencies to the body
|
|
301
|
-
body.prefix(ctx.info.task_dependencies(rank))
|
|
330
|
+
body.prefix(t.clone() for t in ctx.info.task_dependencies(rank))
|
|
302
331
|
# for rank, we sort by the args, but the result includes the keys to preserve bag semantics.
|
|
303
332
|
exposed_vars_raw = list(rank.projection) + list(rank.group) + list(rank.args) +[rank.result]
|
|
304
333
|
# deduplicate vars
|
|
@@ -487,6 +516,14 @@ class Flatten(Pass):
|
|
|
487
516
|
task.annotations
|
|
488
517
|
))
|
|
489
518
|
|
|
519
|
+
def handle_sequence(self, task: ir.Sequence, ctx: Context):
|
|
520
|
+
new_logical = f.logical(
|
|
521
|
+
body = [task],
|
|
522
|
+
engine = task.engine
|
|
523
|
+
)
|
|
524
|
+
ctx.rewrite_ctx.top_level.append(new_logical)
|
|
525
|
+
return Flatten.HandleResult(None)
|
|
526
|
+
|
|
490
527
|
#--------------------------------------------------
|
|
491
528
|
# Helpers
|
|
492
529
|
#--------------------------------------------------
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
from typing import Tuple
|
|
3
3
|
|
|
4
|
-
from v0.relationalai.semantics.metamodel import builtins, ir, factory as f, types, visitor
|
|
4
|
+
from v0.relationalai.semantics.metamodel import builtins, ir, factory as f, types, visitor, helpers
|
|
5
5
|
from v0.relationalai.semantics.metamodel.compiler import Pass, group_tasks
|
|
6
6
|
from v0.relationalai.semantics.metamodel.util import OrderedSet
|
|
7
7
|
from v0.relationalai.semantics.metamodel.util import FrozenOrderedSet
|
|
@@ -63,7 +63,7 @@ def adjust_outputs(task: ir.Logical, outputs: OrderedSet[ir.Task], wide_outputs:
|
|
|
63
63
|
# Remove the original output. This is replaced by per-column outputs below
|
|
64
64
|
body.remove(output)
|
|
65
65
|
|
|
66
|
-
is_export =
|
|
66
|
+
is_export = helpers.is_export(output)
|
|
67
67
|
|
|
68
68
|
# Generate an output for each "column"
|
|
69
69
|
# output looks like def output(:cols, :col000, key0, key1, value):
|
|
@@ -100,7 +100,13 @@ def _generate_output_column(output: ir.Output, idx: int, alias: tuple[str, ir.Va
|
|
|
100
100
|
(not is_primitive(alias[1].type) or alias[1].type == types.Hash)):
|
|
101
101
|
|
|
102
102
|
uuid = f.var(f"{alias[0]}_{idx}_uuid", types.String)
|
|
103
|
-
|
|
103
|
+
|
|
104
|
+
if not is_primitive(alias[1].type):
|
|
105
|
+
# For non-primitive types, we keep the original alias
|
|
106
|
+
aliases.append((alias[0], uuid))
|
|
107
|
+
else:
|
|
108
|
+
# For Hash types, we use the uuid name as alias
|
|
109
|
+
aliases.append((uuid.name, uuid))
|
|
104
110
|
|
|
105
111
|
return [
|
|
106
112
|
ir.Lookup(None, builtins.uuid_to_string, (alias[1], uuid)),
|
|
@@ -5,7 +5,7 @@ from dataclasses import dataclass, field
|
|
|
5
5
|
from typing import Optional, List, Union as PyUnion, Tuple, cast
|
|
6
6
|
|
|
7
7
|
from v0.relationalai.semantics.metamodel.util import OrderedSet, ordered_set
|
|
8
|
-
from v0.relationalai.semantics.metamodel import ir, types, visitor, compiler
|
|
8
|
+
from v0.relationalai.semantics.metamodel import ir, types, visitor, compiler, executor
|
|
9
9
|
import rich
|
|
10
10
|
|
|
11
11
|
|
|
@@ -39,7 +39,8 @@ class CheckEnv:
|
|
|
39
39
|
|
|
40
40
|
def _complain(self, node: ir.Node, msg: str):
|
|
41
41
|
"""Report an error."""
|
|
42
|
-
|
|
42
|
+
if not executor.SUPPRESS_TYPE_ERRORS:
|
|
43
|
+
self.diags.append(CheckError(msg, node))
|
|
43
44
|
|
|
44
45
|
|
|
45
46
|
@dataclass
|
|
@@ -306,8 +307,9 @@ class CheckModel(visitor.DAGVisitor):
|
|
|
306
307
|
for x in node.hoisted:
|
|
307
308
|
if not CheckModel._variable_occurs_in(x, node.body):
|
|
308
309
|
self.env._complain(node, f"Variable {ir.node_to_string(x).strip()} is hoisted but not used in the body of {ir.node_to_string(node).strip()}.")
|
|
309
|
-
|
|
310
|
-
|
|
310
|
+
for iter_var in node.iter:
|
|
311
|
+
if not CheckModel._variable_occurs_in(iter_var, node.body):
|
|
312
|
+
self.env._complain(node, f"Variable {iter_var} is the loop iterator but is not used in the body of {ir.node_to_string(node).strip()}.")
|
|
311
313
|
return super().visit_loop(node, parent)
|
|
312
314
|
|
|
313
315
|
def visit_update(self, node: ir.Update, parent: Optional[ir.Node]=None):
|
|
@@ -6,7 +6,7 @@ import datetime
|
|
|
6
6
|
from decimal import Decimal as PyDecimal
|
|
7
7
|
from typing import Optional, Union, Tuple
|
|
8
8
|
from v0.relationalai import debugging
|
|
9
|
-
from v0.relationalai.semantics.metamodel import builtins, helpers, ir, types, visitor, compiler, factory as f
|
|
9
|
+
from v0.relationalai.semantics.metamodel import builtins, helpers, ir, types, visitor, compiler, factory as f, executor
|
|
10
10
|
from v0.relationalai.semantics.metamodel.util import OrderedSet, ordered_set
|
|
11
11
|
import rich
|
|
12
12
|
import sys
|
|
@@ -1389,7 +1389,8 @@ class InferTypes(compiler.Pass):
|
|
|
1389
1389
|
with debugging.span("type.replace"):
|
|
1390
1390
|
final = Replacer(w.net).walk(model)
|
|
1391
1391
|
|
|
1392
|
-
|
|
1393
|
-
|
|
1392
|
+
if not executor.SUPPRESS_TYPE_ERRORS:
|
|
1393
|
+
for err in w.net.errors:
|
|
1394
|
+
rich.print(str(err), file=sys.stderr)
|
|
1394
1395
|
|
|
1395
1396
|
return final
|
|
@@ -466,7 +466,8 @@ class Visitor(GenericVisitor[None]):
|
|
|
466
466
|
self._walk_engine(node.engine, node)
|
|
467
467
|
for h in node.hoisted:
|
|
468
468
|
self._walk_var_or_default(h, node)
|
|
469
|
-
|
|
469
|
+
for iter in node.iter:
|
|
470
|
+
self._walk_var(iter, node)
|
|
470
471
|
self._walk_node(node.body, node)
|
|
471
472
|
for a in node.annotations:
|
|
472
473
|
self._walk_node(a, node)
|
|
@@ -935,9 +936,9 @@ class Rewriter():
|
|
|
935
936
|
#
|
|
936
937
|
def handle_loop(self, node: ir.Loop, parent: ir.Node):
|
|
937
938
|
hoisted = rewrite_list(ir.VarOrDefault, lambda n: self.walk(n, node), node.hoisted)
|
|
938
|
-
|
|
939
|
+
iter = rewrite_list(ir.Var, lambda n: self.walk(n, node), node.iter)
|
|
939
940
|
body = self.walk(node.body, node)
|
|
940
|
-
return node.reconstruct(node.engine, hoisted,
|
|
941
|
+
return node.reconstruct(node.engine, hoisted, iter, body, node.concurrency, node.annotations)
|
|
941
942
|
|
|
942
943
|
def handle_break(self, node: ir.Break, parent: ir.Node):
|
|
943
944
|
check = self.walk(node.check, node)
|
|
@@ -333,7 +333,7 @@ class SolverModelDev:
|
|
|
333
333
|
executor.execute_raw(textwrap.dedent(f"""
|
|
334
334
|
def delete[:{self.point._name}]: {self.point._name}
|
|
335
335
|
def insert(:{self.point._name}, var, val): {self.points._name}(int128[{i}], var, val)
|
|
336
|
-
""")
|
|
336
|
+
"""))
|
|
337
337
|
return None
|
|
338
338
|
|
|
339
339
|
# print summary of the solver result
|