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.
Files changed (27) hide show
  1. relationalai/semantics/frontend/base.py +3 -0
  2. relationalai/semantics/frontend/front_compiler.py +5 -2
  3. relationalai/semantics/metamodel/builtins.py +2 -1
  4. relationalai/semantics/metamodel/metamodel.py +32 -4
  5. relationalai/semantics/metamodel/pprint.py +5 -3
  6. relationalai/semantics/metamodel/typer.py +324 -297
  7. relationalai/semantics/std/aggregates.py +0 -1
  8. relationalai/semantics/std/datetime.py +4 -1
  9. relationalai/shims/executor.py +22 -4
  10. relationalai/shims/mm2v0.py +108 -38
  11. {relationalai-1.0.0a1.dist-info → relationalai-1.0.0a2.dist-info}/METADATA +1 -1
  12. {relationalai-1.0.0a1.dist-info → relationalai-1.0.0a2.dist-info}/RECORD +27 -27
  13. v0/relationalai/errors.py +23 -0
  14. v0/relationalai/semantics/internal/internal.py +4 -4
  15. v0/relationalai/semantics/internal/snowflake.py +2 -1
  16. v0/relationalai/semantics/lqp/executor.py +16 -11
  17. v0/relationalai/semantics/lqp/model2lqp.py +42 -4
  18. v0/relationalai/semantics/lqp/passes.py +1 -1
  19. v0/relationalai/semantics/lqp/rewrite/cdc.py +1 -1
  20. v0/relationalai/semantics/lqp/rewrite/extract_keys.py +53 -12
  21. v0/relationalai/semantics/metamodel/builtins.py +8 -6
  22. v0/relationalai/semantics/metamodel/rewrite/flatten.py +9 -4
  23. v0/relationalai/semantics/reasoners/graph/core.py +8 -9
  24. v0/relationalai/semantics/sql/compiler.py +2 -2
  25. {relationalai-1.0.0a1.dist-info → relationalai-1.0.0a2.dist-info}/WHEEL +0 -0
  26. {relationalai-1.0.0a1.dist-info → relationalai-1.0.0a2.dist-info}/entry_points.txt +0 -0
  27. {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:
@@ -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(Config().get("reasoner.rule.use_lqp", True))
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:
@@ -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=r.name,
285
- fields=self.translate_frozen(r.fields, r, ctx), # type: ignore
306
+ name=name,
307
+ fields=frozen(*fields), # type: ignore
286
308
  requires=self.translate_frozen(r.requires, r, ctx), # type: ignore
287
- annotations=self.translate_frozen(r.annotations, r, ctx), # type: ignore
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
- annotations.append(v0_builtins.from_cdc_annotation)
340
- for col in t.columns:
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=t.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 effectively a no-op since it cannot affect the query. Just return the outputs.
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
- else:
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 take the 6nf column relations and pull them into a single wide lookup
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 is_col:
804
- self.column_map[l.args[0]][l.relation] = args[-1]
805
- # we always lookup the full table, so replace the relation and args
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
- for arg, field in zip(l.args, l.relation.fields):
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)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: relationalai
3
- Version: 1.0.0a1
3
+ Version: 1.0.0a2
4
4
  Summary: RelationalAI Library and CLI
5
5
  Author-email: RelationalAI <support@relational.ai>
6
6
  Requires-Python: >=3.10
@@ -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=9JgD-re_E2GakehRd7fbW3HG_Aq5qxwEy64NguzXCrE,65652
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=a8LEGudqL4MTHV2QTQC9LJo43g_fxQ7K-HlRDwrfySg,57241
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=85XxoPeQstc9yy5HkB_gsak3zh_kl-WYC5gF5l_rHkw,6950
26
- relationalai/semantics/metamodel/metamodel.py,sha256=-DfYtsDTaAGGYS7aRmVvpxaZFqP1d8x0okfW_RniFfQ,12778
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=RqXi5gEArG4bMqQ4q2_MAoCikSKgAXkVivOWqdPpayk,15567
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=6DIAIigfrRwf3Soi43MMHPDjxG9VuzboIpq2QdorVy0,52707
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=uuMhRobpib0aZaH_fAyJZ-8YI9_0fuEDFtgLekTOODk,6278
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=6XMc8ZevrV7rzxdG89_aOpoK8R8Kd6zkvEq4kYkK524,21372
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=NegQJqrEXWEQVfhy7FzF_oGazf0IHvVNCiDMX1z4Ws0,6755
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=oksKidw6dU1r5Aq99uuv-Y1nLCG17FXEzsx2GqY_xGw,59702
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=V7CzFJf2L5g348luz8ZA9PyB3YKAg8DDF7spi66gKsY,94951
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=pGF0kaQoYcwTQ-lq9G_QHyR78K1KFIcapcBtnNkefa4,150789
361
- v0/relationalai/semantics/internal/snowflake.py,sha256=Sk-dRruRz69ZZc0fQQygW6MZSnTWQOzX8r-MPCyTqBA,13494
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=65xRwmCVqqcNB3f_s9c4XFnQ3xsjQTJlBpGEhm-4-cM,21651
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=5xOMSXvrActc3G3zddMyn0osviPOW7Mq_G-H2EZ21zs,36990
370
- v0/relationalai/semantics/lqp/passes.py,sha256=hMOXbztIiyhy95bD5M7Ru91eiscIQhZkiXOejsMqjRc,28642
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=tX5vcf6ULm7eFwOxfyT4EfbCSXLcaSrrLJqVy1IbGPo,10402
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=tLo9GSmplDM1TrwbMfYNS4lI1zQKpuSzMHa4E6-aD9M,19332
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=O26klqMH4ud5nqb2Os6ISsxaPsCj5X1eVKD5RuGUmtA,38657
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=HN8X4JXvSwJiljMWaV3x8iDeLOYg2ZC5O0AbqQym8QE,22528
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=PFBQl3RoiQZk8P6aglPo-vuPdilbpix4YcEEtbgN9Ko,399548
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=wVLKx26Lfb3yqpcBZsDc6f0xVvg1N2omQ7em4UnZVA8,129198
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.0a1.dist-info/METADATA,sha256=EGwVxgfa8vs2t23NVNdD-17Tq0nWXPBF-EQnKFqbu4g,1368
486
- relationalai-1.0.0a1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
487
- relationalai-1.0.0a1.dist-info/entry_points.txt,sha256=u_anMN5_VCOQNA5E2mTLT2LWc9r1i-F9yQmy3ZNAAck,91
488
- relationalai-1.0.0a1.dist-info/top_level.txt,sha256=Y9cfzWf-p2omqqmVy_98m287xf0OJbj6OB5RRdkGql4,16
489
- relationalai-1.0.0a1.dist-info/RECORD,,
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
- self._rel = b.Relationship(self._fqn, fields=[b.Field(name="RowId", type_str=self._fqn, type=self._concept)] + table_info.fields)
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
- e = errors.RelQueryError(problem, source)
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) :