relationalai 1.0.0a1__py3-none-any.whl → 1.0.0a2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- relationalai/semantics/frontend/base.py +3 -0
- relationalai/semantics/frontend/front_compiler.py +5 -2
- relationalai/semantics/metamodel/builtins.py +2 -1
- relationalai/semantics/metamodel/metamodel.py +32 -4
- relationalai/semantics/metamodel/pprint.py +5 -3
- relationalai/semantics/metamodel/typer.py +324 -297
- relationalai/semantics/std/aggregates.py +0 -1
- relationalai/semantics/std/datetime.py +4 -1
- relationalai/shims/executor.py +22 -4
- relationalai/shims/mm2v0.py +108 -38
- {relationalai-1.0.0a1.dist-info → relationalai-1.0.0a2.dist-info}/METADATA +1 -1
- {relationalai-1.0.0a1.dist-info → relationalai-1.0.0a2.dist-info}/RECORD +27 -27
- v0/relationalai/errors.py +23 -0
- v0/relationalai/semantics/internal/internal.py +4 -4
- v0/relationalai/semantics/internal/snowflake.py +2 -1
- v0/relationalai/semantics/lqp/executor.py +16 -11
- v0/relationalai/semantics/lqp/model2lqp.py +42 -4
- v0/relationalai/semantics/lqp/passes.py +1 -1
- v0/relationalai/semantics/lqp/rewrite/cdc.py +1 -1
- v0/relationalai/semantics/lqp/rewrite/extract_keys.py +53 -12
- v0/relationalai/semantics/metamodel/builtins.py +8 -6
- v0/relationalai/semantics/metamodel/rewrite/flatten.py +9 -4
- v0/relationalai/semantics/reasoners/graph/core.py +8 -9
- v0/relationalai/semantics/sql/compiler.py +2 -2
- {relationalai-1.0.0a1.dist-info → relationalai-1.0.0a2.dist-info}/WHEEL +0 -0
- {relationalai-1.0.0a1.dist-info → relationalai-1.0.0a2.dist-info}/entry_points.txt +0 -0
- {relationalai-1.0.0a1.dist-info → relationalai-1.0.0a2.dist-info}/top_level.txt +0 -0
|
@@ -10,7 +10,6 @@ AggValue = Value | Distinct
|
|
|
10
10
|
# Aggregates
|
|
11
11
|
#------------------------------------------------------
|
|
12
12
|
|
|
13
|
-
# TODO - overloads
|
|
14
13
|
_sum = library.Relation("sum", fields=[Field.input("value", Numeric), Field("result", Numeric)],
|
|
15
14
|
overloads=[[Number, Number], [Float, Float]])
|
|
16
15
|
_count = library.Relation("count", fields=[Field("result", Integer)])
|
|
@@ -3,8 +3,9 @@ from __future__ import annotations
|
|
|
3
3
|
from relationalai.semantics.std import floats
|
|
4
4
|
|
|
5
5
|
from . import StringValue, IntegerValue, DateValue, DateTimeValue, math, common
|
|
6
|
-
from ..frontend.base import Aggregate, Library, Concept, NumberConcept, Expression, Field, Literal, Variable
|
|
6
|
+
from ..frontend.base import Aggregate, Library, Concept, MetaRef, NumberConcept, Expression, Field, Literal, Variable
|
|
7
7
|
from ..frontend.core import Float, Number, String, Integer, Date, DateTime
|
|
8
|
+
from ..frontend import core
|
|
8
9
|
from .. import select
|
|
9
10
|
|
|
10
11
|
from typing import Union, Literal
|
|
@@ -162,6 +163,7 @@ class date:
|
|
|
162
163
|
num_days = cls.period_days(start, end)
|
|
163
164
|
if freq in ["W", "M", "Y"]:
|
|
164
165
|
range_end = math.ceil(num_days * _days[freq])
|
|
166
|
+
range_end = core.cast(MetaRef(Integer), range_end)
|
|
165
167
|
else:
|
|
166
168
|
range_end = num_days
|
|
167
169
|
# date_range is inclusive. add 1 since std.range is exclusive
|
|
@@ -348,6 +350,7 @@ class datetime:
|
|
|
348
350
|
_end = num_ms
|
|
349
351
|
else:
|
|
350
352
|
_end = math.ceil(num_ms * Float(_milliseconds[freq]))
|
|
353
|
+
_end = core.cast(MetaRef(Integer), _end)
|
|
351
354
|
# datetime_range is inclusive. add 1 since common.range is exclusive
|
|
352
355
|
ix = common.range(0, _end + 1, 1)
|
|
353
356
|
else:
|
relationalai/shims/executor.py
CHANGED
|
@@ -29,10 +29,28 @@ TYPER_DEBUGGER=False
|
|
|
29
29
|
# PRINT_RESULT=True
|
|
30
30
|
# TYPER_DEBUGGER=True
|
|
31
31
|
|
|
32
|
+
@lru_cache()
|
|
33
|
+
def get_config():
|
|
34
|
+
return Config()
|
|
35
|
+
|
|
36
|
+
def with_source(item: mm.Node):
|
|
37
|
+
if not hasattr(item, "source"):
|
|
38
|
+
raise ValueError(f"Item {item} has no source")
|
|
39
|
+
elif item.source is None:
|
|
40
|
+
return {}
|
|
41
|
+
elif debugging.DEBUG:
|
|
42
|
+
source = item.source.block
|
|
43
|
+
if source:
|
|
44
|
+
return { "file": source.file, "line": source.line, "source": source.source }
|
|
45
|
+
else:
|
|
46
|
+
return {"file":item.source.file, "line":item.source.line}
|
|
47
|
+
else:
|
|
48
|
+
return {"file":item.source.file, "line":item.source.line}
|
|
49
|
+
|
|
32
50
|
def execute(query: Fragment, model: Model|None = None, executor=None, export_to="", update=False):
|
|
33
51
|
if not executor:
|
|
34
52
|
# use_lqp = Config().reasoner.rule.use_lqp
|
|
35
|
-
use_lqp = bool(
|
|
53
|
+
use_lqp = bool(get_config().get("reasoner.rule.use_lqp", True))
|
|
36
54
|
executor = "lqp" if use_lqp else "rel"
|
|
37
55
|
mm_model = model.to_metamodel() if model else None
|
|
38
56
|
mm_query = query.to_metamodel()
|
|
@@ -41,7 +59,7 @@ def execute(query: Fragment, model: Model|None = None, executor=None, export_to=
|
|
|
41
59
|
|
|
42
60
|
def execute_mm(mm_query: mm.Task, mm_model: mm.Model|None = None, executor="lqp", export_to="", update=False, model: Model|None = None):
|
|
43
61
|
# perform type inference
|
|
44
|
-
typer = Typer()
|
|
62
|
+
typer = Typer(enforce=False)
|
|
45
63
|
# normalize the metamodel
|
|
46
64
|
normalizer = Normalize()
|
|
47
65
|
# translate the metamodel into a v0 query
|
|
@@ -117,7 +135,7 @@ def execute_mm(mm_query: mm.Task, mm_model: mm.Model|None = None, executor="lqp"
|
|
|
117
135
|
f.write(msg)
|
|
118
136
|
f.write('\n')
|
|
119
137
|
|
|
120
|
-
if DRY_RUN:
|
|
138
|
+
if DRY_RUN or get_config().get("compiler.dry_run", False):
|
|
121
139
|
results = []
|
|
122
140
|
else:
|
|
123
141
|
# create snowflake tables for all the tables that have been used
|
|
@@ -132,7 +150,7 @@ def execute_mm(mm_query: mm.Task, mm_model: mm.Model|None = None, executor="lqp"
|
|
|
132
150
|
|
|
133
151
|
# get an executor and execute
|
|
134
152
|
executor = _get_executor(executor, model.name if model else "")
|
|
135
|
-
with debugging.span("query", tag=None, export_to=export_to) as query_span:
|
|
153
|
+
with debugging.span("query", tag=None, export_to=export_to, dsl="", **with_source(mm_query)) as query_span:
|
|
136
154
|
if isinstance(executor, (LQPExecutor, RelExecutor)):
|
|
137
155
|
results = executor.execute(v0_model, v0_query, export_to=export_table, update=update)
|
|
138
156
|
else:
|
relationalai/shims/mm2v0.py
CHANGED
|
@@ -21,6 +21,8 @@ from ..semantics.backends.lqp import annotations as lqp_annotations
|
|
|
21
21
|
from v0.relationalai.semantics.metamodel import ir as v0, builtins as v0_builtins, types as v0_types, factory as f
|
|
22
22
|
from v0.relationalai.semantics.metamodel.util import FrozenOrderedSet, frozen, ordered_set, filter_by_type, OrderedSet
|
|
23
23
|
from v0.relationalai.semantics.internal.internal import literal_value_to_type
|
|
24
|
+
from v0.relationalai.semantics.metamodel.typer import typer as v0_typer
|
|
25
|
+
from v0.relationalai.clients.util import IdentityParser
|
|
24
26
|
|
|
25
27
|
from .hoister import Hoister
|
|
26
28
|
from .helpers import is_output_update, is_main_output
|
|
@@ -131,6 +133,16 @@ class Translator():
|
|
|
131
133
|
def translate_frozen(self, nodes: seq[mm.Node], parent, ctx) -> FrozenOrderedSet[v0.Node]:
|
|
132
134
|
return frozen(*self.translate_seq(nodes, parent, ctx))
|
|
133
135
|
|
|
136
|
+
#------------------------------------------------------
|
|
137
|
+
# Helper
|
|
138
|
+
#------------------------------------------------------
|
|
139
|
+
|
|
140
|
+
# NOTE: This has to match what is done in the v0 snowflake.Table class as that is what CDC
|
|
141
|
+
# produces. If there's a quote in the table name, then we take it verbatim, otherwise we lowercase it.
|
|
142
|
+
def translate_table_name(self, table: mm.Table) -> str:
|
|
143
|
+
name = IdentityParser(table.name).identifier
|
|
144
|
+
name = name.lower() if '"' not in table.name else table.name.replace('"', '_')
|
|
145
|
+
return sanitize(name)
|
|
134
146
|
|
|
135
147
|
#-----------------------------------------------------------------------------
|
|
136
148
|
# Capabilities, Reasoners
|
|
@@ -279,12 +291,22 @@ class Translator():
|
|
|
279
291
|
else:
|
|
280
292
|
overloads.update(x) # type: ignore
|
|
281
293
|
overloads.update(self.translate_frozen(r.overloads, r, ctx)) # type: ignore
|
|
294
|
+
annotations = self.translate_seq(r.annotations, r, ctx) # type: ignore
|
|
295
|
+
name = r.name
|
|
296
|
+
fields = self.translate_seq(r.fields, r, ctx) # type: ignore
|
|
297
|
+
# We need to turn column relations into what the CDC pass would otherwise produce
|
|
298
|
+
# by making the relation name be the table name and adding a symbol field at the front
|
|
299
|
+
# representing the column name
|
|
300
|
+
if r.fields and isinstance(r.fields[0].type, mm.Table) and r in r.fields[0].type.columns:
|
|
301
|
+
name = self.translate_table_name(r.fields[0].type)
|
|
302
|
+
fields = (v0.Field("symbol", v0_types.Symbol, False), *fields) # type: ignore
|
|
303
|
+
annotations = annotations + (v0_builtins.external_annotation,)
|
|
282
304
|
|
|
283
305
|
return v0.Relation(
|
|
284
|
-
name=
|
|
285
|
-
fields=
|
|
306
|
+
name=name,
|
|
307
|
+
fields=frozen(*fields), # type: ignore
|
|
286
308
|
requires=self.translate_frozen(r.requires, r, ctx), # type: ignore
|
|
287
|
-
annotations=
|
|
309
|
+
annotations=frozen(*annotations), # type: ignore
|
|
288
310
|
overloads=overloads.frozen(), # type: ignore
|
|
289
311
|
)
|
|
290
312
|
|
|
@@ -321,6 +343,7 @@ class Translator():
|
|
|
321
343
|
b.core.Date: v0_types.Date,
|
|
322
344
|
b.core.DateTime: v0_types.DateTime,
|
|
323
345
|
b.core.Float: v0_types.Float,
|
|
346
|
+
b.core.Hash: v0_types.Hash,
|
|
324
347
|
}
|
|
325
348
|
|
|
326
349
|
def translate_scalartype(self, t: mm.ScalarType, parent: mm.Node, ctx) -> v0.ScalarType|v0.Relation|None:
|
|
@@ -334,18 +357,14 @@ class Translator():
|
|
|
334
357
|
assert isinstance(actual_type, v0.ScalarType)
|
|
335
358
|
fields = [v0.Field(name="entity", type=actual_type, input=False)] # type: ignore
|
|
336
359
|
annotations = [v0_builtins.concept_relation_annotation]
|
|
360
|
+
name = t.name
|
|
337
361
|
if isinstance(t, mm.Table):
|
|
338
362
|
annotations.append(v0_builtins.external_annotation)
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
fields.append(v0.Field(
|
|
342
|
-
name=col.name,
|
|
343
|
-
type=self.translate_node(col.fields[-1].type, col, Context.MODEL), # type: ignore
|
|
344
|
-
input=False
|
|
345
|
-
))
|
|
363
|
+
name = self.translate_table_name(t)
|
|
364
|
+
fields.insert(0, v0.Field(name="symbol", type=v0_types.Symbol, input=False)) # type: ignore
|
|
346
365
|
|
|
347
366
|
type_relation = v0.Relation(
|
|
348
|
-
name=
|
|
367
|
+
name=name,
|
|
349
368
|
fields=tuple(fields), # type: ignore
|
|
350
369
|
requires=frozen(),
|
|
351
370
|
annotations=frozen(*annotations), # type: ignore
|
|
@@ -541,7 +560,7 @@ class Translator():
|
|
|
541
560
|
# inline logicals if possible
|
|
542
561
|
new_children = []
|
|
543
562
|
for c in children:
|
|
544
|
-
if isinstance(c, v0.Logical) and not c.hoisted and len(c.body) == 1:
|
|
563
|
+
if isinstance(c, v0.Logical) and not c.hoisted and len(c.body) == 1 and not isinstance(c.body[0], (v0.Aggregate, v0.Rank)):
|
|
545
564
|
new_children.extend(c.body)
|
|
546
565
|
else:
|
|
547
566
|
new_children.append(c)
|
|
@@ -590,10 +609,49 @@ class Translator():
|
|
|
590
609
|
return outputs
|
|
591
610
|
|
|
592
611
|
# if this is an optional logical but we're not hoisting anything and not updating,
|
|
593
|
-
# then it's
|
|
612
|
+
# then it's possible we're filtering an outer variable, but only for this column. If
|
|
613
|
+
# so, we need to alias the output and hoist it.
|
|
594
614
|
# this is important because the LQP stack blows up if there's a logical with no effect
|
|
595
615
|
if l.optional and not hoisted and not any(isinstance(c, v0.Update) for c in children):
|
|
596
|
-
return outputs
|
|
616
|
+
# if there are no lookups, then this really is a no-op, just return outputs
|
|
617
|
+
# LQP blows up with e.g. a match-only logical
|
|
618
|
+
if not any(isinstance(c, v0.Lookup) for c in children):
|
|
619
|
+
return outputs
|
|
620
|
+
# otherwise, make sure we filter the outer variable through aliasing
|
|
621
|
+
new_children = [*children]
|
|
622
|
+
new_hoists = []
|
|
623
|
+
new_outputs = []
|
|
624
|
+
# add an eq to a new var for the output, hoist the new var, change the output to use the new var
|
|
625
|
+
for output in outputs:
|
|
626
|
+
# shim outputs always only have one alias
|
|
627
|
+
(name, orig_var) = output.aliases.data[0]
|
|
628
|
+
# if the original var is not a Var or Literal, or it's already in the keys, skip (we can't filter keys)
|
|
629
|
+
if not isinstance(orig_var, (v0.Var, v0.Literal)) or (output.keys and orig_var in output.keys): #type: ignore
|
|
630
|
+
new_outputs.append(output)
|
|
631
|
+
continue
|
|
632
|
+
new_var = v0.Var(
|
|
633
|
+
type=orig_var.type,
|
|
634
|
+
name=f"{orig_var.name if isinstance(orig_var, v0.Var) else 'literal'}_hoisted"
|
|
635
|
+
)
|
|
636
|
+
new_output = v0.Output(
|
|
637
|
+
engine=None,
|
|
638
|
+
aliases=frozen((name, new_var)),
|
|
639
|
+
keys=output.keys,
|
|
640
|
+
annotations=output.annotations
|
|
641
|
+
)
|
|
642
|
+
eq = v0.Lookup(
|
|
643
|
+
engine=None,
|
|
644
|
+
relation=v0_builtins.eq,
|
|
645
|
+
args=(new_var, orig_var),
|
|
646
|
+
annotations=frozen()
|
|
647
|
+
)
|
|
648
|
+
new_children.append(eq)
|
|
649
|
+
new_hoists.append(v0.Default(new_var, None))
|
|
650
|
+
new_outputs.append(new_output)
|
|
651
|
+
outputs = new_outputs
|
|
652
|
+
hoisted = tuple(new_hoists)
|
|
653
|
+
children = tuple(new_children)
|
|
654
|
+
# return outputs
|
|
597
655
|
|
|
598
656
|
# return outputs + a logical with the other children
|
|
599
657
|
outputs.append(
|
|
@@ -782,40 +840,26 @@ class Translator():
|
|
|
782
840
|
args=(var, col_var), # type: ignore
|
|
783
841
|
annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
|
|
784
842
|
)
|
|
785
|
-
|
|
843
|
+
# if this is a data column, we just ignore it as the data node already binds the variables
|
|
844
|
+
elif isinstance(l.args[0].type, mm.Data):
|
|
786
845
|
return None
|
|
846
|
+
# Otherwise we keep the lookup because that's what the LQP stack expect (the lookup gets repeated for
|
|
847
|
+
# each column)
|
|
848
|
+
|
|
787
849
|
|
|
788
850
|
relation, args = self._resolve_reading(l, ctx)
|
|
789
851
|
if relation is None:
|
|
790
852
|
return None
|
|
791
853
|
|
|
792
854
|
# External Table Column lookups
|
|
793
|
-
# we have to
|
|
794
|
-
# making sure that the variable get mapped correctly. To match the expectations of
|
|
795
|
-
# v0, we also have to make sure that if we're looking up the table row itself, that
|
|
796
|
-
# it is wrapped in its own logical
|
|
855
|
+
# we have to prepend the column symbol to the args
|
|
797
856
|
root_type = l.relation.fields[0].type
|
|
798
857
|
if isinstance(root_type, mm.Table):
|
|
799
858
|
self.used_tables.add(root_type)
|
|
800
|
-
assert isinstance(l.args[0], mm.Var)
|
|
801
|
-
is_col = l.relation in root_type.columns
|
|
802
859
|
is_table = l.relation == root_type
|
|
803
|
-
if
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
relation = self.translate_node(root_type, l, ctx)
|
|
807
|
-
|
|
808
|
-
# this is a lookup on the table itself or the columns, translate to the column vars
|
|
809
|
-
if is_col or is_table:
|
|
810
|
-
mapped = self.column_map.get(l.args[0], {})
|
|
811
|
-
col_args = []
|
|
812
|
-
for col in root_type.columns:
|
|
813
|
-
v = mapped.setdefault(col, v0.Var(
|
|
814
|
-
type=self.translate_node(col.fields[-1].type, col, Context.MODEL), # type: ignore
|
|
815
|
-
name=f"{col.name}"
|
|
816
|
-
))
|
|
817
|
-
col_args.append(v)
|
|
818
|
-
args = tuple([args[0], *col_args]) # type: ignore
|
|
860
|
+
if is_table or l.relation in root_type.columns:
|
|
861
|
+
sym = "METADATA$KEY" if is_table else l.relation.name
|
|
862
|
+
args = (v0.Literal(type=v0_types.Symbol, value=sym), *args)
|
|
819
863
|
|
|
820
864
|
# Specific rewrites
|
|
821
865
|
rewrite = self.rewrite_lookup(l, parent, ctx)
|
|
@@ -1109,6 +1153,18 @@ class Translator():
|
|
|
1109
1153
|
def decrement(self, l: mm.Lookup, index: int, ctx):
|
|
1110
1154
|
""" Rewrite the lookup such that the arg at `index` is decremented by 1 before the
|
|
1111
1155
|
lookup. """
|
|
1156
|
+
x = l.args[index]
|
|
1157
|
+
if isinstance(x, mm.Literal):
|
|
1158
|
+
# if the arg is a literal, just decrement the literal directly
|
|
1159
|
+
new_literal = mm.Literal(type=x.type, value=x.value - 1) # type: ignore
|
|
1160
|
+
return v0.Lookup(
|
|
1161
|
+
engine=None,
|
|
1162
|
+
relation=self.translate_node(l.relation), # type: ignore
|
|
1163
|
+
args=tuple(self.translate_value(arg, l, ctx) if i != index else self.translate_value(new_literal, l, ctx) for i, arg in enumerate(l.args)),
|
|
1164
|
+
annotations=self.translate_frozen(l.annotations, l, ctx) # type: ignore
|
|
1165
|
+
)
|
|
1166
|
+
|
|
1167
|
+
# arg is not a literal, so we need to create a tmp var to store the decremented value
|
|
1112
1168
|
tmp = self.translate_value(mm.Var(type=b.core.Number, name="tmp"), l, ctx)
|
|
1113
1169
|
# lookup(..., tmp, ...)
|
|
1114
1170
|
new = v0.Lookup(
|
|
@@ -1137,7 +1193,21 @@ class Translator():
|
|
|
1137
1193
|
inputs = []
|
|
1138
1194
|
outputs = []
|
|
1139
1195
|
args = []
|
|
1140
|
-
|
|
1196
|
+
fields = l.relation.fields
|
|
1197
|
+
# if there are overloads, we need to cast based on the most compatible overload
|
|
1198
|
+
if l.relation.overloads:
|
|
1199
|
+
inf = float("inf")
|
|
1200
|
+
min_cost = inf
|
|
1201
|
+
for overload in l.relation.overloads:
|
|
1202
|
+
total = 0
|
|
1203
|
+
for arg, field in zip(l.args, overload.fields):
|
|
1204
|
+
if v0_typer.to_type(arg) != field.type:
|
|
1205
|
+
total += 1
|
|
1206
|
+
if total < min_cost:
|
|
1207
|
+
min_cost = total
|
|
1208
|
+
fields = overload.fields
|
|
1209
|
+
|
|
1210
|
+
for arg, field in zip(l.args, fields):
|
|
1141
1211
|
target_type = field.type
|
|
1142
1212
|
if target_type is None or not isinstance(arg, (v0.Var, v0.Literal)) or arg.type == target_type:
|
|
1143
1213
|
args.append(arg)
|
|
@@ -17,23 +17,23 @@ relationalai/semantics/__init__.py,sha256=N3rTlD4oIyIkCqTNNWWUjQbJMyEbot6XNR_Nvm
|
|
|
17
17
|
relationalai/semantics/backends/lqp/annotations.py,sha256=TUk_fuXyBWs7H4BHx-4jZGonSD8MdgPswt-D2k7QC-4,390
|
|
18
18
|
relationalai/semantics/backends/sql/sql_compiler.py,sha256=p_1YjROlcmu0kwvI32qUWAmMQntp_A6H3_vgGDDLiQk,10628
|
|
19
19
|
relationalai/semantics/frontend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
-
relationalai/semantics/frontend/base.py,sha256=
|
|
20
|
+
relationalai/semantics/frontend/base.py,sha256=yUBeXvF0cRYzKk4sTSh7Ja5PUSwEszvyuQjT1E25Cjc,65783
|
|
21
21
|
relationalai/semantics/frontend/core.py,sha256=mwPG9HxQWrh77O5n7j_M9lt96gTyYsoUE_BFz7qcfXw,7396
|
|
22
|
-
relationalai/semantics/frontend/front_compiler.py,sha256=
|
|
22
|
+
relationalai/semantics/frontend/front_compiler.py,sha256=q84SDS1AQllKSnZya1k8gUG_SD12zIl9QbWIU9zFliU,57403
|
|
23
23
|
relationalai/semantics/frontend/pprint.py,sha256=IMkKwkZs3ohOIjYUIjT10poa1L39F_PrLdSjV-D4wpk,14977
|
|
24
24
|
relationalai/semantics/metamodel/__init__.py,sha256=mISE8niHeEAD6QjX8pi_apFfMIVCZ7dGeCXFGtFPTvk,364
|
|
25
|
-
relationalai/semantics/metamodel/builtins.py,sha256=
|
|
26
|
-
relationalai/semantics/metamodel/metamodel.py,sha256
|
|
25
|
+
relationalai/semantics/metamodel/builtins.py,sha256=rmeVdjw3kDSsx7TjpnFpy8W6OrHuUV1GQwazWhaWrG0,7009
|
|
26
|
+
relationalai/semantics/metamodel/metamodel.py,sha256=TgIufxJslJZkf5_RleTU19i2h0DTW6CodSYqwyVcLEc,13899
|
|
27
27
|
relationalai/semantics/metamodel/metamodel_analyzer.py,sha256=tusDRO2az1yiF951SDg-cHOaNQ1M7qw1HG1cxV3YuxU,16228
|
|
28
28
|
relationalai/semantics/metamodel/metamodel_compiler.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
|
-
relationalai/semantics/metamodel/pprint.py,sha256=
|
|
29
|
+
relationalai/semantics/metamodel/pprint.py,sha256=65t7tZTfBP2qOlKShYM8nwrbsiS3gKaCYkUJepu0a2o,15684
|
|
30
30
|
relationalai/semantics/metamodel/rewriter.py,sha256=CEkYxsyFPF-nEHktJxwzOY6RQzo9Nr4Welhw2YDq9q8,8313
|
|
31
|
-
relationalai/semantics/metamodel/typer.py,sha256=
|
|
31
|
+
relationalai/semantics/metamodel/typer.py,sha256=Q35spCuIRMGE2BslgWiyZvQWb3Z0VzCx1YF_Lzk1Sts,55268
|
|
32
32
|
relationalai/semantics/std/__init__.py,sha256=_cbDmeCT634GtdGJ0CqgfJw6pFaJR0ajR3B_bWCr_9A,2627
|
|
33
|
-
relationalai/semantics/std/aggregates.py,sha256=
|
|
33
|
+
relationalai/semantics/std/aggregates.py,sha256=uCwoBLmuRBBq9lTf5ACD3yosvtp5Wi8IQUCF_dKWS80,6259
|
|
34
34
|
relationalai/semantics/std/common.py,sha256=raWuvX2u4juKPU0BKtqF5xvJSDjKHF1BWQVFioBmOf8,1658
|
|
35
35
|
relationalai/semantics/std/constraints.py,sha256=ePaVEWdlmO1AkawC-QaOKzXw2j2YUFD_-2bstBN8Rto,1587
|
|
36
|
-
relationalai/semantics/std/datetime.py,sha256=
|
|
36
|
+
relationalai/semantics/std/datetime.py,sha256=p2pKTWqARsc5SytfPdnXp9J6Ot4IsSCfGIvfIUJe5NM,21529
|
|
37
37
|
relationalai/semantics/std/decimals.py,sha256=tkYGiOyLuzJPTXb8bHHlx7bA0e_FnVFGyFkzaFzGsdc,1863
|
|
38
38
|
relationalai/semantics/std/floats.py,sha256=UpHkgMeUdvqu_pRAlay_KOqWb0e-uz3SK51sH4kNAWQ,490
|
|
39
39
|
relationalai/semantics/std/integers.py,sha256=YxNk-pLtbYtuBVr2BTzdAmhiNxkZJW3wwHDYLk63wfo,1053
|
|
@@ -42,10 +42,10 @@ relationalai/semantics/std/numbers.py,sha256=AcmESbBXIQDkDL6YGZXYKmpo7uyYD1or7su
|
|
|
42
42
|
relationalai/semantics/std/re.py,sha256=xMuQY5sG3fEL1efHDNFnVpnXVkDJMmDVUEbHiPr1oqA,4375
|
|
43
43
|
relationalai/semantics/std/strings.py,sha256=w0k06gDfyMS6GODPjhG0gl2SkJ0aH5aYezS8jG9jsU8,5617
|
|
44
44
|
relationalai/shims/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
45
|
-
relationalai/shims/executor.py,sha256=
|
|
45
|
+
relationalai/shims/executor.py,sha256=KKPno0Jfeb8KK9jSdLl-T5EeBkcxWDC7HDUcMxTQkw4,7405
|
|
46
46
|
relationalai/shims/helpers.py,sha256=1v6D-wDq3nCwDz4egdGUeleRC0fK6wfo9fIQIeQCfZA,4508
|
|
47
47
|
relationalai/shims/hoister.py,sha256=YXXi9pWpKQ7Sd5DzRVl_78z4OYCoKzFfIMMp6OIN3EM,8797
|
|
48
|
-
relationalai/shims/mm2v0.py,sha256=
|
|
48
|
+
relationalai/shims/mm2v0.py,sha256=xt08HGv06ABxR1u1EZsdDc_2qVuNw5XNLQ8HKuK_YxU,63715
|
|
49
49
|
relationalai/tools/debugger.py,sha256=B8QIE1-WFdfkiPoFFn1yztr9t6yf5PI32Y9Y9XzQOJk,10798
|
|
50
50
|
relationalai/tools/typer_debugger.py,sha256=__oLODEBwgt6pYIn1jgIPlenFmiK7iqXfTY_mozHxXA,3182
|
|
51
51
|
relationalai/tools/cli/__init__.py,sha256=jkIlp7wftUuSIlczwZD4_siT5cs6mzpsNGrQ_kMkLZ4,74
|
|
@@ -72,7 +72,7 @@ v0/relationalai/debugging.py,sha256=AuzbwLT1s71tctuIbYNhfWY2vR_opB7ItbmlqFVHgrY,
|
|
|
72
72
|
v0/relationalai/dependencies.py,sha256=tL113efcISkJUiDXYHmRdU_usdD7gmee-VRHA7N4EFA,16574
|
|
73
73
|
v0/relationalai/docutils.py,sha256=1gVv9mk0ytdMB2W7_NvslJefmSQtTOg8LHTCDcGCjyE,1554
|
|
74
74
|
v0/relationalai/dsl.py,sha256=9BdpqzDNcW4717GyxVAYIMZ7ctE_bvXS-5sNLIbXQZ0,66128
|
|
75
|
-
v0/relationalai/errors.py,sha256=
|
|
75
|
+
v0/relationalai/errors.py,sha256=2rFE3tWDhhZ3GCzG1UNuCkns3xxsscUU6wx_3VvoVWI,95976
|
|
76
76
|
v0/relationalai/metagen.py,sha256=o10PNvR_myr_61DC8g6lkB093bFo9qXGUkZKgKyfXiE,26821
|
|
77
77
|
v0/relationalai/metamodel.py,sha256=P1hliwHd1nYxbXON4LZeaYZD6T6pZm97HgmFBFrWyCk,32886
|
|
78
78
|
v0/relationalai/rel.py,sha256=ePmAXx4NxOdsPcHNHyGH3Jkp_cB3QzfKu5p_EQSHPh0,38293
|
|
@@ -357,17 +357,17 @@ v0/relationalai/semantics/devtools/compilation_manager.py,sha256=DDHY5DNwRK0hD9P
|
|
|
357
357
|
v0/relationalai/semantics/devtools/extract_lqp.py,sha256=Ccvhw3W-8VHYi2Kui64lCUmCrliygGqFc6C0LQlvgWM,3702
|
|
358
358
|
v0/relationalai/semantics/internal/__init__.py,sha256=BS0WE1GbT-HpQ5p_zMr9Fcvph562WMvMQNI9czfKNt0,798
|
|
359
359
|
v0/relationalai/semantics/internal/annotations.py,sha256=PkrRN-gHO2ksh1hDKB1VVIB39dONvLdTd8_Y0rCR3fE,367
|
|
360
|
-
v0/relationalai/semantics/internal/internal.py,sha256
|
|
361
|
-
v0/relationalai/semantics/internal/snowflake.py,sha256=
|
|
360
|
+
v0/relationalai/semantics/internal/internal.py,sha256=-juUQ8AL1kAoh6PgpBQJ5Jp3qjwSgjx64s3IKeKXVYk,150821
|
|
361
|
+
v0/relationalai/semantics/internal/snowflake.py,sha256=Zw-jC2XmsWwZlOn_5zwfu_gCxs-dH0XlSOcAELAc70k,13588
|
|
362
362
|
v0/relationalai/semantics/lqp/__init__.py,sha256=XgcQZxK-zz_LqPDVtwREhsIvjTuUIt4BZhIedCeMY-s,48
|
|
363
363
|
v0/relationalai/semantics/lqp/builtins.py,sha256=Xst9-UxkCAwDqL-hFOby8B3GKh705oidFUjEozxn71Y,585
|
|
364
364
|
v0/relationalai/semantics/lqp/compiler.py,sha256=xpGIQAqTMwLi3Vrbe79Yal7O_mfNxpBLioZjqeV2hzc,955
|
|
365
365
|
v0/relationalai/semantics/lqp/constructors.py,sha256=x7G85vbJzLIXzUCMKVdJVsr4PrcUsAOzCCfvimHLMVU,2366
|
|
366
|
-
v0/relationalai/semantics/lqp/executor.py,sha256=
|
|
366
|
+
v0/relationalai/semantics/lqp/executor.py,sha256=DeZw71K3TAXI8mZDWa4c9N3V3HQfOVn1YNIPhuKcFcU,21875
|
|
367
367
|
v0/relationalai/semantics/lqp/intrinsics.py,sha256=8kgH4ndYKBCNnoNOn7iWOU0wnMTSiov0kYaKocQ45RY,880
|
|
368
368
|
v0/relationalai/semantics/lqp/ir.py,sha256=6W9mUH0W7u5eIfF1S3o33uSOfQuM3UcqEkxrxpr1X_8,1867
|
|
369
|
-
v0/relationalai/semantics/lqp/model2lqp.py,sha256=
|
|
370
|
-
v0/relationalai/semantics/lqp/passes.py,sha256=
|
|
369
|
+
v0/relationalai/semantics/lqp/model2lqp.py,sha256=J_QofcYgq_Yb5dhOOP4lXvxsxFMEGHVnaNXoCMK_ak8,38639
|
|
370
|
+
v0/relationalai/semantics/lqp/passes.py,sha256=Jwj6VgTU9jyp6oVTqUpFKa7ZjFRbc7HWNLmJiKf389w,28652
|
|
371
371
|
v0/relationalai/semantics/lqp/pragmas.py,sha256=FzzldrJEAZ1AIcEw6D-FfaVg3CoahRYgPCFo7xHfg1g,375
|
|
372
372
|
v0/relationalai/semantics/lqp/primitives.py,sha256=OxdcCx-0528113CrR2Ia-ZE0lewCmOCS1fezPwvmYa0,11044
|
|
373
373
|
v0/relationalai/semantics/lqp/result_helpers.py,sha256=ArYlBafNL2zB4ipwhQWiwVSOXp3lp0DefICFHxw9_mc,10135
|
|
@@ -376,15 +376,15 @@ v0/relationalai/semantics/lqp/utils.py,sha256=T9Ic_38iNc9DW3ufdHTMpRSoaFM_Mw_2_V
|
|
|
376
376
|
v0/relationalai/semantics/lqp/validators.py,sha256=-tapIMa9Hq-qlRP_Vr03_jIkH6RTERnSKdWbrxdWbhQ,1564
|
|
377
377
|
v0/relationalai/semantics/lqp/rewrite/__init__.py,sha256=V9ERED9qdh4VvY9Ud_M8Zn8lhVANdOGIgW03l55sGj0,492
|
|
378
378
|
v0/relationalai/semantics/lqp/rewrite/annotate_constraints.py,sha256=zOm-OUzWBhk2iMc_eURII1-okIGJ-teDbEcJ30WDjUU,2325
|
|
379
|
-
v0/relationalai/semantics/lqp/rewrite/cdc.py,sha256=
|
|
379
|
+
v0/relationalai/semantics/lqp/rewrite/cdc.py,sha256=cx_fpQrzkzkeAGHE_kV10nd1-0Jduws6yiIRq650f4c,10412
|
|
380
380
|
v0/relationalai/semantics/lqp/rewrite/extract_common.py,sha256=johHGsS9SDDVbonMIE8Ck9rCuidllwdeJZDruW_5kQs,14705
|
|
381
|
-
v0/relationalai/semantics/lqp/rewrite/extract_keys.py,sha256=
|
|
381
|
+
v0/relationalai/semantics/lqp/rewrite/extract_keys.py,sha256=lDO1e5pC_Z-nYMXt5zeLBxWQUjNgkhLMiaRLYkF7ZqU,21070
|
|
382
382
|
v0/relationalai/semantics/lqp/rewrite/function_annotations.py,sha256=WAHpqRVBqpUIDL2MA1aBmyOTvcpH_yfdeWBS1vAEtzA,4675
|
|
383
383
|
v0/relationalai/semantics/lqp/rewrite/functional_dependencies.py,sha256=LTwMvU19FMdgCG8nJwV2wyiW8Hu9oCj-hIKKSMOYZYE,12727
|
|
384
384
|
v0/relationalai/semantics/lqp/rewrite/quantify_vars.py,sha256=3l_pDMc4r-izuE274MP_ffNgZ6g7Rk5ysg3CXqKKlBU,12016
|
|
385
385
|
v0/relationalai/semantics/lqp/rewrite/splinter.py,sha256=ggZ41OjaT8GA-CgUejbJfR7G6vZB6EmNY-WqyQxgeok,3205
|
|
386
386
|
v0/relationalai/semantics/metamodel/__init__.py,sha256=I-XqQAGycD0nKkKYvnF3G9d0QK_1LIM4xXICw8g8fBA,805
|
|
387
|
-
v0/relationalai/semantics/metamodel/builtins.py,sha256=
|
|
387
|
+
v0/relationalai/semantics/metamodel/builtins.py,sha256=HN-F5lpnwZiMsl2kBUxdXDSa3LPjVDUIuPF0AbbgqNU,39024
|
|
388
388
|
v0/relationalai/semantics/metamodel/compiler.py,sha256=YRRqvA_PJeE02P0IVte4gQtolqgBVu9HEhwOgf4WKuY,4534
|
|
389
389
|
v0/relationalai/semantics/metamodel/dataflow.py,sha256=wfj1tARrR4yEAaTwUTrAcxEcz81VkUal4U_AX1esovk,3929
|
|
390
390
|
v0/relationalai/semantics/metamodel/dependency.py,sha256=khgS8DitIYxbgfMeJ5NP-ZCf7zMOagAgpPfQ9IOTzWc,33932
|
|
@@ -399,7 +399,7 @@ v0/relationalai/semantics/metamodel/rewrite/__init__.py,sha256=9ONWFSdMPHkWpObDM
|
|
|
399
399
|
v0/relationalai/semantics/metamodel/rewrite/discharge_constraints.py,sha256=jilU6ZNaqhoFRwNdxArSfYb3Rbeahig9kDjdYoJR9Q4,1955
|
|
400
400
|
v0/relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py,sha256=TZykhhhwkYQsJjNxDac0YY4A6bmzOrNKJwB1LFQOsb4,8001
|
|
401
401
|
v0/relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py,sha256=i5KSANUCtI5Gq03cMiJv0lR4-0M5qc7gu50gsReo72I,3369
|
|
402
|
-
v0/relationalai/semantics/metamodel/rewrite/flatten.py,sha256=
|
|
402
|
+
v0/relationalai/semantics/metamodel/rewrite/flatten.py,sha256=fi4blz2P1ZE0Y70b29fLS69QXcr-g3HGhDCzaM-C6tk,22846
|
|
403
403
|
v0/relationalai/semantics/metamodel/rewrite/format_outputs.py,sha256=MDDa48LFk3M5NF02h18Ej3wgODg8cF2CRFAZiRNZnhk,6240
|
|
404
404
|
v0/relationalai/semantics/metamodel/typer/__init__.py,sha256=E3ydmhWRdm-cAqWsNR24_Qd3NcwiHx8ElO2tzNysAXc,143
|
|
405
405
|
v0/relationalai/semantics/metamodel/typer/checker.py,sha256=XzvGAZWmJGHuZ0XHGc8-dy9uIWrwZsIWi1v1_4TzKKQ,19190
|
|
@@ -407,7 +407,7 @@ v0/relationalai/semantics/metamodel/typer/typer.py,sha256=2_eKanWV5xVnAwUlIcbXQM
|
|
|
407
407
|
v0/relationalai/semantics/reasoners/__init__.py,sha256=SmcmkK5TqMjGzDZjFIbkYwaMuQe9y09NaAyWrIMG60Y,306
|
|
408
408
|
v0/relationalai/semantics/reasoners/experimental/__init__.py,sha256=ZWXb3Oun7m_G2c3ijKnqxbEsAzTMVa7ciBXjdi4dCNI,144
|
|
409
409
|
v0/relationalai/semantics/reasoners/graph/__init__.py,sha256=7G6M2c0eBbsxtP9iq7E6y02wBJlD6GxsLeDPAJPJ1MM,1285
|
|
410
|
-
v0/relationalai/semantics/reasoners/graph/core.py,sha256=
|
|
410
|
+
v0/relationalai/semantics/reasoners/graph/core.py,sha256=Bth2oe5ulItBChZCoFTgP-oPMbnCNp7Ln8G8P5FZlTk,399513
|
|
411
411
|
v0/relationalai/semantics/reasoners/optimization/__init__.py,sha256=HZlyy3Od7ArXI_HMhWrxrQPnyZGScgiVdmMul51lx7Q,2218
|
|
412
412
|
v0/relationalai/semantics/reasoners/optimization/common.py,sha256=gmJrJAPNyaBqik2_QaxjCoFPZKqdroxmNXUeoDGwOtY,3130
|
|
413
413
|
v0/relationalai/semantics/reasoners/optimization/solvers_dev.py,sha256=MqCvdDk1l_XSBlHd5-XpHVfcvD8INjCNbCttaomv6SY,24517
|
|
@@ -420,7 +420,7 @@ v0/relationalai/semantics/rel/rel.py,sha256=mQTykcHz63P1w8nhvA8SwYRtIi0LEud19vGr
|
|
|
420
420
|
v0/relationalai/semantics/rel/rel_utils.py,sha256=B9qR7hUouybwluuo9zUYemv6tWPnDPaV4da-emsTrRQ,9569
|
|
421
421
|
v0/relationalai/semantics/snowflake/__init__.py,sha256=QRcuGvnK-TeNOWvHpBu5Z4hJHcMRXb5IPOokvLihy1U,169
|
|
422
422
|
v0/relationalai/semantics/sql/__init__.py,sha256=59uuKmQOFUzwlYwc7anSuwhQ45bJTYVmd9nOJXr9mQs,80
|
|
423
|
-
v0/relationalai/semantics/sql/compiler.py,sha256=
|
|
423
|
+
v0/relationalai/semantics/sql/compiler.py,sha256=dars-hVkUytvwtNaWh6FC_NM2XSUY2UkipDQ8i-sc2c,129230
|
|
424
424
|
v0/relationalai/semantics/sql/sql.py,sha256=a3EBJKPp92EoVpl1qct2jdBwXQflFpG1nJ2OLNc5go8,17125
|
|
425
425
|
v0/relationalai/semantics/sql/executor/__init__.py,sha256=F3HqQPJVP9wgV3rkwI5jy1_QBCD_3qj2IGxbdT_pX9k,120
|
|
426
426
|
v0/relationalai/semantics/sql/executor/duck_db.py,sha256=FriWhN_IvpQ1YH0YcQ9vlnPRkM1ARoqKDZd0koSk0SM,1918
|
|
@@ -482,8 +482,8 @@ v0/relationalai/util/span_tracker.py,sha256=7vyvEBdI9uCj1dxVZCQT_W5vPMxIzxewrlRR
|
|
|
482
482
|
v0/relationalai/util/spans_file_handler.py,sha256=w34WVw19ubtrjPBkKmg0Hb-9MldICmowF1OW85KCJN0,3209
|
|
483
483
|
v0/relationalai/util/timeout.py,sha256=2o6BVNFnFc-B2j-i1pEkZcQbMRto9ps2emci0XwiA4I,783
|
|
484
484
|
v0/relationalai/util/tracing_handler.py,sha256=wJQN52PRw8R2XB1_qd-POgfGZStrj9OFL7wa5Xr6SEM,1732
|
|
485
|
-
relationalai-1.0.
|
|
486
|
-
relationalai-1.0.
|
|
487
|
-
relationalai-1.0.
|
|
488
|
-
relationalai-1.0.
|
|
489
|
-
relationalai-1.0.
|
|
485
|
+
relationalai-1.0.0a2.dist-info/METADATA,sha256=j3ofGijkfDIsTfki1G_l7ycajPA4m9hLrUWYIuNI9dg,1368
|
|
486
|
+
relationalai-1.0.0a2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
487
|
+
relationalai-1.0.0a2.dist-info/entry_points.txt,sha256=u_anMN5_VCOQNA5E2mTLT2LWc9r1i-F9yQmy3ZNAAck,91
|
|
488
|
+
relationalai-1.0.0a2.dist-info/top_level.txt,sha256=Y9cfzWf-p2omqqmVy_98m287xf0OJbj6OB5RRdkGql4,16
|
|
489
|
+
relationalai-1.0.0a2.dist-info/RECORD,,
|
v0/relationalai/errors.py
CHANGED
|
@@ -2168,6 +2168,29 @@ class DirectAccessInvalidAuthWarning(RAIWarning):
|
|
|
2168
2168
|
Direct access requires one of the following authenticators: {valid_authenticators_str}
|
|
2169
2169
|
""")
|
|
2170
2170
|
|
|
2171
|
+
class NonDefaultLQPSemanticsVersionWarning(RAIWarning):
|
|
2172
|
+
def __init__(self, current_version: str, default_version: str):
|
|
2173
|
+
self.current_version = current_version
|
|
2174
|
+
self.default_version = default_version
|
|
2175
|
+
self.name = "Non-default LQP Semantics Version"
|
|
2176
|
+
self.message = f"Using non-default LQP semantics version {current_version}. Default is {default_version}."
|
|
2177
|
+
self.content = self.format_message()
|
|
2178
|
+
super().__init__(self.message, self.name, self.content)
|
|
2179
|
+
|
|
2180
|
+
def format_message(self):
|
|
2181
|
+
return textwrap.dedent(f"""
|
|
2182
|
+
{self.message}
|
|
2183
|
+
|
|
2184
|
+
You are using a non-default LQP semantics version, likely to avoid a change in
|
|
2185
|
+
behaviour that broke one of your models. This is a reminder to ensure you switch
|
|
2186
|
+
back to the default version once any blocking issues have been resolved.
|
|
2187
|
+
|
|
2188
|
+
To do so you need to remove the following section from your raiconfig.toml:
|
|
2189
|
+
|
|
2190
|
+
[reasoner.rule]
|
|
2191
|
+
lqp.semantics_version = {self.current_version}
|
|
2192
|
+
""")
|
|
2193
|
+
|
|
2171
2194
|
class InsecureKeychainWarning(RAIWarning):
|
|
2172
2195
|
def __init__(self):
|
|
2173
2196
|
self.message = "Insecure keyring detected. Please use a secure keyring backend."
|
|
@@ -884,12 +884,12 @@ class Concept(Producer):
|
|
|
884
884
|
raise ValueError("Concept names cannot start with '_'")
|
|
885
885
|
|
|
886
886
|
# Check if it matches either allowed format
|
|
887
|
-
pattern_a = r'^[a-zA-Z0-9_.]+$'
|
|
888
|
-
pattern_b = r'^[a-zA-Z0-9_.]+\([0-9]+,[0-9]+\)$'
|
|
887
|
+
pattern_a = r'^[a-zA-Z0-9_."-]+$'
|
|
888
|
+
pattern_b = r'^[a-zA-Z0-9_."-]+\([0-9]+,[0-9]+\)$'
|
|
889
889
|
|
|
890
890
|
if not (re.match(pattern_a, name) or re.match(pattern_b, name)):
|
|
891
891
|
raise ValueError(f"Concept name '{name}' contains invalid characters. "
|
|
892
|
-
f"Names must contain only letters, digits, dots, and underscores, "
|
|
892
|
+
f"Names must contain only letters, digits, dots, double quotes, hyphens, and underscores, "
|
|
893
893
|
f"optionally followed by precision/scale in parentheses like 'Decimal(38,14)'")
|
|
894
894
|
|
|
895
895
|
def __init__(self, name:str, extends:list[Any] = [], model:Model|None=None, identify_by:dict[str, Any]={}):
|
|
@@ -1365,7 +1365,7 @@ class Relationship(Producer):
|
|
|
1365
1365
|
|
|
1366
1366
|
def _parse_schema_format(self, format_string:str):
|
|
1367
1367
|
# Pattern to extract fields like {Type} or {name:Type}, where Type can have precision and scale, like Decimal(38,14)
|
|
1368
|
-
pattern = r'\{([a-zA-Z0-9_.]+(?:\([0-9]+,[0-9]+\))?)(?::([a-zA-Z0-9_.]+(?:\([0-9]+,[0-9]+\))?))?\}'
|
|
1368
|
+
pattern = r'\{([a-zA-Z0-9_."-]+(?:\([0-9]+,[0-9]+\))?)(?::([a-zA-Z0-9_."-]+(?:\([0-9]+,[0-9]+\))?))?\}'
|
|
1369
1369
|
matches = re.findall(pattern, format_string)
|
|
1370
1370
|
|
|
1371
1371
|
namer = NameCache()
|
|
@@ -230,7 +230,8 @@ class Table():
|
|
|
230
230
|
if self._table not in schema_info.fetched:
|
|
231
231
|
schema_info.fetch()
|
|
232
232
|
table_info = schema_info.tables[self._table]
|
|
233
|
-
|
|
233
|
+
CDC_name = self._fqn.lower() if '"' not in self._fqn else self._fqn.replace("\"", "_")
|
|
234
|
+
self._rel = b.Relationship(CDC_name, fields=[b.Field(name="RowId", type_str=self._fqn, type=self._concept)] + table_info.fields)
|
|
234
235
|
self._rel.annotate(anns.external).annotate(anns.from_cdc)
|
|
235
236
|
|
|
236
237
|
def __getattr__(self, name: str):
|
|
@@ -10,6 +10,7 @@ from snowflake.snowpark import Session
|
|
|
10
10
|
import v0.relationalai as rai
|
|
11
11
|
|
|
12
12
|
from v0.relationalai import debugging
|
|
13
|
+
from v0.relationalai.errors import NonDefaultLQPSemanticsVersionWarning
|
|
13
14
|
from v0.relationalai.semantics.lqp import result_helpers
|
|
14
15
|
from v0.relationalai.semantics.metamodel import ir, factory as f, executor as e
|
|
15
16
|
from v0.relationalai.semantics.lqp.compiler import Compiler
|
|
@@ -29,6 +30,9 @@ from v0.relationalai.tools.query_utils import prepare_metadata_for_headers
|
|
|
29
30
|
if TYPE_CHECKING:
|
|
30
31
|
from v0.relationalai.semantics.snowflake import Table
|
|
31
32
|
|
|
33
|
+
# Whenever the logic engine introduces a breaking change in behaviour, we bump this version
|
|
34
|
+
# once the client is ready to handle it.
|
|
35
|
+
DEFAULT_LQP_SEMANTICS_VERSION = "0"
|
|
32
36
|
|
|
33
37
|
class LQPExecutor(e.Executor):
|
|
34
38
|
"""Executes LQP using the RAI client."""
|
|
@@ -147,17 +151,7 @@ class LQPExecutor(e.Executor):
|
|
|
147
151
|
elif code == "PYREL_ERROR":
|
|
148
152
|
pyrel_errors[problem["props"]["pyrel_id"]].append(problem)
|
|
149
153
|
elif abort_on_error:
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if code == 'SYSTEM_INTERNAL':
|
|
153
|
-
supplementary_message = "Troubleshooting:\n" + \
|
|
154
|
-
" 1. Please retry with a new name for your model. This can work around state-related issues.\n" + \
|
|
155
|
-
" 2. If the error persists, please retry with the `use_lqp` flag set to `False`, for example:\n" + \
|
|
156
|
-
" `model = Model(..., use_lqp=False)`\n" + \
|
|
157
|
-
" This will switch the execution to the legacy backend, which may avoid the issue with some performance cost.\n"
|
|
158
|
-
|
|
159
|
-
e.content = f"{e.content}{supplementary_message}"
|
|
160
|
-
all_errors.append(e)
|
|
154
|
+
all_errors.append(errors.RelQueryError(problem, source))
|
|
161
155
|
else:
|
|
162
156
|
if code == "ARITY_MISMATCH":
|
|
163
157
|
errors.ArityMismatch(problem, source)
|
|
@@ -311,6 +305,17 @@ class LQPExecutor(e.Executor):
|
|
|
311
305
|
ivm_flag = self.config.get('reasoner.rule.incremental_maintenance', None)
|
|
312
306
|
if ivm_flag:
|
|
313
307
|
config_dict['ivm.maintenance_level'] = lqp_ir.Value(value=ivm_flag, meta=None)
|
|
308
|
+
|
|
309
|
+
# Set semantics_version from config, defaulting to 0
|
|
310
|
+
semantics_version: str | Any = self.config.get('reasoner.rule.lqp.semantics_version', DEFAULT_LQP_SEMANTICS_VERSION)
|
|
311
|
+
config_dict['semantics_version'] = lqp_ir.Value(value=int(semantics_version), meta=None)
|
|
312
|
+
|
|
313
|
+
# Warn if a non-default semantics version is used. Most likely, this is due to a
|
|
314
|
+
# user manually reverting to an older version. We want them to not get stuck on that
|
|
315
|
+
# version for longer than necessary.
|
|
316
|
+
if semantics_version != DEFAULT_LQP_SEMANTICS_VERSION:
|
|
317
|
+
debugging.warn(NonDefaultLQPSemanticsVersionWarning(semantics_version, DEFAULT_LQP_SEMANTICS_VERSION))
|
|
318
|
+
|
|
314
319
|
return construct_configure(config_dict, None)
|
|
315
320
|
|
|
316
321
|
def _should_sync(self, model) :
|