pytrilogy 0.0.3.84__py3-none-any.whl → 0.0.3.86__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.

Potentially problematic release.


This version of pytrilogy might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytrilogy
3
- Version: 0.0.3.84
3
+ Version: 0.0.3.86
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
5
  Home-page:
6
6
  Author:
@@ -1,5 +1,5 @@
1
- pytrilogy-0.0.3.84.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
2
- trilogy/__init__.py,sha256=b0Bn2iqQWc-ybYMseprmaaiHheIdhoVAhJDfyMQJNkI,303
1
+ pytrilogy-0.0.3.86.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
2
+ trilogy/__init__.py,sha256=5dzQ0vpbEueUVSZmFxf4YBdZiiISnPSLYO_1sIGq8Rs,303
3
3
  trilogy/compiler.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  trilogy/constants.py,sha256=eKb_EJvSqjN9tGbdVEViwdtwwh8fZ3-jpOEDqL71y70,1691
5
5
  trilogy/engine.py,sha256=OK2RuqCIUId6yZ5hfF8J1nxGP0AJqHRZiafcowmW0xc,1728
@@ -23,7 +23,7 @@ trilogy/core/optimization.py,sha256=ojpn-p79lr03SSVQbbw74iPCyoYpDYBmj1dbZ3oXCjI,
23
23
  trilogy/core/query_processor.py,sha256=5aFgv-2LVM1Uku9cR_tFuTRDwyLnxc95bCMAHeFy2AY,20332
24
24
  trilogy/core/utility.py,sha256=3VC13uSQWcZNghgt7Ot0ZTeEmNqs__cx122abVq9qhM,410
25
25
  trilogy/core/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
- trilogy/core/models/author.py,sha256=Xt_TRVl4xHF6fe-KTKPSt4Z8Srmplnv2KQe2grZXX3w,78411
26
+ trilogy/core/models/author.py,sha256=WBrPQh-n7rmKULpJxx0aY1PZAqE2lOKScEttMEuetoc,78263
27
27
  trilogy/core/models/build.py,sha256=0TRcL__hvajLcpFwYeLjCV35cow5oVPbJHXA3oO09XA,65931
28
28
  trilogy/core/models/build_environment.py,sha256=s_C9xAHuD3yZ26T15pWVBvoqvlp2LdZ8yjsv2_HdXLk,5363
29
29
  trilogy/core/models/core.py,sha256=q-8ExAaSB3PoSDX2XOqfZ01HBBvT1pZFs7jGg1vZizc,11096
@@ -41,7 +41,7 @@ trilogy/core/processing/discovery_node_factory.py,sha256=5QVYUsci_h6iYWhS0GCoDow
41
41
  trilogy/core/processing/discovery_utility.py,sha256=eY4n7_r6_R-cx_Sm8FiouMXh78v2iO2SGhi0aI5jvDg,4549
42
42
  trilogy/core/processing/discovery_validation.py,sha256=eZ4HfHMpqZLI8MGG2jez8arS8THs6ceuVrQFIY6gXrU,5364
43
43
  trilogy/core/processing/graph_utils.py,sha256=8QUVrkE9j-9C1AyrCb1nQEh8daCe0u1HuXl-Te85lag,1205
44
- trilogy/core/processing/utility.py,sha256=I7KgLJc1oLYPZoArMzoYMr-w2y3wv80u2VfVYbBNfkM,22716
44
+ trilogy/core/processing/utility.py,sha256=PGQKZgX58kI3gG4nprY8HRGayc2D8fF5RmbvBhQj8ok,23319
45
45
  trilogy/core/processing/node_generators/__init__.py,sha256=iVJ-crowPxYeut-hFjyEjfibKIDq7PfB4LEuDAUCjGY,943
46
46
  trilogy/core/processing/node_generators/basic_node.py,sha256=TLZCv4WS196a-0g5xgKuJGthnGP8Ugm46iz85_3NIY4,5626
47
47
  trilogy/core/processing/node_generators/common.py,sha256=PdysdroW9DUADP7f5Wv_GKPUyCTROZV1g3L45fawxi8,9443
@@ -82,7 +82,7 @@ trilogy/dialect/bigquery.py,sha256=8xhEu0z_lKANjbvzvBbC7CeKrJf1iP8YyrHqNale-ug,4
82
82
  trilogy/dialect/common.py,sha256=tSthIZOXXRPQ4KeMKnDDsH7KlTmf2EVqigVtLyoc4zc,6071
83
83
  trilogy/dialect/config.py,sha256=olnyeVU5W5T6b9-dMeNAnvxuPlyc2uefb7FRME094Ec,3834
84
84
  trilogy/dialect/dataframe.py,sha256=RUbNgReEa9g3pL6H7fP9lPTrAij5pkqedpZ99D8_5AE,1522
85
- trilogy/dialect/duckdb.py,sha256=uqnZEd1IH4tO8FSbbUXe3Jl9EjoyrDde406k0VDuMXw,5544
85
+ trilogy/dialect/duckdb.py,sha256=JoUvQ19WvgxoaJkGLM7DPXOd1H0394k3vBiblksQzOI,5631
86
86
  trilogy/dialect/enums.py,sha256=FRNYQ5-w-B6-X0yXKNU5g9GowsMlERFogTC5u2nxL_s,4740
87
87
  trilogy/dialect/postgres.py,sha256=el2PKwfyvWGk5EZtLudqAH5ewLitY1sFHJiocBSyxyM,3393
88
88
  trilogy/dialect/presto.py,sha256=yzSF8SZ6o1dizj1UueAa7S3lR0qNYJdSXbF78EHyhY0,3668
@@ -98,21 +98,21 @@ trilogy/parsing/common.py,sha256=yV1AckK0h8u1OFeGQBTMu-wuW5m63c5CcZuPicsTH_w,306
98
98
  trilogy/parsing/config.py,sha256=Z-DaefdKhPDmSXLgg5V4pebhSB0h590vI0_VtHnlukI,111
99
99
  trilogy/parsing/exceptions.py,sha256=Xwwsv2C9kSNv2q-HrrKC1f60JNHShXcCMzstTSEbiCw,154
100
100
  trilogy/parsing/helpers.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
101
- trilogy/parsing/parse_engine.py,sha256=MXG5nzQWd1tVaJddF_NDst96N_ayALQ0EB3JMh8kWaY,78776
101
+ trilogy/parsing/parse_engine.py,sha256=bIrct01a9_BVqyOBge_T3Nbjou3CTapyZufGa7yvzjg,78898
102
102
  trilogy/parsing/render.py,sha256=HSNntD82GiiwHT-TWPLXAaIMWLYVV5B5zQEsgwrHIBE,19605
103
- trilogy/parsing/trilogy.lark,sha256=B7onP5W7ZIW_uKObJ5rL1sQCpnWiMeZ2azQ9j2U2ssE,15368
103
+ trilogy/parsing/trilogy.lark,sha256=PCcvtvjuadYgUx1dBEuEwjdU4Ey69SBPzs10Pg5BzbU,15388
104
104
  trilogy/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
105
105
  trilogy/scripts/trilogy.py,sha256=1L0XrH4mVHRt1C9T1HnaDv2_kYEfbWTb5_-cBBke79w,3774
106
106
  trilogy/std/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
107
107
  trilogy/std/date.preql,sha256=HWZm4t4HWyxr5geWRsY05RnHBVDMci8z8YA2cu0-OOw,188
108
108
  trilogy/std/display.preql,sha256=nm7lox87Xf6lBvXCVCS6x2HskguMKzndEBucJ5pktzk,175
109
- trilogy/std/geography.preql,sha256=qLnHmDU5EnvjTbfqZF-NEclSYM5_e9rZra7QjV01rZ4,582
109
+ trilogy/std/geography.preql,sha256=1A9Sq5PPMBnEPPf7f-rPVYxJfsnWpQ8oV_k4Fm3H2dU,675
110
110
  trilogy/std/money.preql,sha256=XWwvAV3WxBsHX9zfptoYRnBigcfYwrYtBHXTME0xJuQ,2082
111
- trilogy/std/net.preql,sha256=7l7MqIjs6TDCpO6dBAoNJU81Ex255jZRK36kBgE1GDs,158
111
+ trilogy/std/net.preql,sha256=WZCuvH87_rZntZiuGJMmBDMVKkdhTtxeHOkrXNwJ1EE,416
112
112
  trilogy/std/ranking.preql,sha256=LDoZrYyz4g3xsII9XwXfmstZD-_92i1Eox1UqkBIfi8,83
113
113
  trilogy/std/report.preql,sha256=LbV-XlHdfw0jgnQ8pV7acG95xrd1-p65fVpiIc-S7W4,202
114
- pytrilogy-0.0.3.84.dist-info/METADATA,sha256=geu9WBXvLdcteqUAJuFHuDkeyxc8h7l-t9PgRkk7J4o,9589
115
- pytrilogy-0.0.3.84.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
116
- pytrilogy-0.0.3.84.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
117
- pytrilogy-0.0.3.84.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
118
- pytrilogy-0.0.3.84.dist-info/RECORD,,
114
+ pytrilogy-0.0.3.86.dist-info/METADATA,sha256=flJ_PrQGqM6Q9oa5UxfFX603fEhG40plDOVqE6yiqg8,9589
115
+ pytrilogy-0.0.3.86.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
116
+ pytrilogy-0.0.3.86.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
117
+ pytrilogy-0.0.3.86.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
118
+ pytrilogy-0.0.3.86.dist-info/RECORD,,
trilogy/__init__.py CHANGED
@@ -4,6 +4,6 @@ from trilogy.dialect.enums import Dialects
4
4
  from trilogy.executor import Executor
5
5
  from trilogy.parser import parse
6
6
 
7
- __version__ = "0.0.3.84"
7
+ __version__ = "0.0.3.86"
8
8
 
9
9
  __all__ = ["parse", "Executor", "Dialects", "Environment", "CONFIG"]
@@ -637,33 +637,31 @@ class Comparison(ConceptArgs, Mergeable, DataTyped, Namespaced, BaseModel):
637
637
 
638
638
  @model_validator(mode="after")
639
639
  def validate_comparison(self):
640
+ left_type = arg_to_datatype(self.left)
641
+ right_type = arg_to_datatype(self.right)
640
642
  if self.operator in (ComparisonOperator.IS, ComparisonOperator.IS_NOT):
641
- if self.right != MagicConstants.NULL and DataType.BOOL != arg_to_datatype(
642
- self.right
643
- ):
643
+ if self.right != MagicConstants.NULL and DataType.BOOL != right_type:
644
644
  raise SyntaxError(
645
645
  f"Cannot use {self.operator.value} with non-null or boolean value {self.right}"
646
646
  )
647
647
  elif self.operator in (ComparisonOperator.IN, ComparisonOperator.NOT_IN):
648
- right_type = arg_to_datatype(self.right)
648
+
649
649
  if isinstance(right_type, ArrayType) and not is_compatible_datatype(
650
- arg_to_datatype(self.left), right_type.value_data_type
650
+ left_type, right_type.value_data_type
651
651
  ):
652
652
  raise SyntaxError(
653
- f"Cannot compare {arg_to_datatype(self.left)} and {right_type} with operator {self.operator} in {str(self)}"
653
+ f"Cannot compare {left_type} and {right_type} with operator {self.operator} in {str(self)}"
654
654
  )
655
655
  elif isinstance(self.right, Concept) and not is_compatible_datatype(
656
- arg_to_datatype(self.left), arg_to_datatype(self.right)
656
+ left_type, right_type
657
657
  ):
658
658
  raise SyntaxError(
659
- f"Cannot compare {arg_to_datatype(self.left)} and {arg_to_datatype(self.right)} with operator {self.operator} in {str(self)}"
659
+ f"Cannot compare {left_type.name} and {right_type.name} with operator {self.operator} in {str(self)}"
660
660
  )
661
661
  else:
662
- if not is_compatible_datatype(
663
- arg_to_datatype(self.left), arg_to_datatype(self.right)
664
- ):
662
+ if not is_compatible_datatype(left_type, right_type):
665
663
  raise SyntaxError(
666
- f"Cannot compare {arg_to_datatype(self.left)} and {arg_to_datatype(self.right)} of different types with operator {self.operator} in {str(self)}"
664
+ f"Cannot compare {left_type.name} ({self.left}) and {right_type.name} ({self.right}) of different types with operator {self.operator.value} in {str(self)}"
667
665
  )
668
666
 
669
667
  return self
@@ -161,6 +161,9 @@ def resolve_join_order_v2(
161
161
  left_is_partial = any(
162
162
  key in partials.get(left_candidate, []) for key in common
163
163
  )
164
+ left_is_nullable = any(
165
+ key in nullables.get(left_candidate, []) for key in common
166
+ )
164
167
  right_is_partial = any(key in partials.get(right, []) for key in common)
165
168
  # we don't care if left is nullable for join type (just keys), but if we did
166
169
  # left_is_nullable = any(
@@ -169,21 +172,29 @@ def resolve_join_order_v2(
169
172
  right_is_nullable = any(
170
173
  key in nullables.get(right, []) for key in common
171
174
  )
172
- if left_is_partial or right_is_nullable:
175
+ if left_is_nullable and right_is_nullable:
176
+ join_type = JoinType.FULL
177
+ elif left_is_partial and right_is_partial:
178
+ join_type = JoinType.FULL
179
+ elif left_is_partial:
173
180
  join_type = JoinType.FULL
174
- elif right_is_partial:
181
+ elif right_is_nullable:
182
+ join_type = JoinType.RIGHT_OUTER
183
+ elif right_is_partial or left_is_nullable:
175
184
  join_type = JoinType.LEFT_OUTER
176
185
  # we can't inner join if the left was an outer join
177
186
  else:
178
187
  join_type = JoinType.INNER
188
+
179
189
  join_types.add(join_type)
180
190
  joinkeys[left_candidate] = common
181
-
182
191
  final_join_type = JoinType.INNER
183
- if any([x == JoinType.LEFT_OUTER for x in join_types]):
184
- final_join_type = JoinType.LEFT_OUTER
185
- elif any([x == JoinType.FULL for x in join_types]):
192
+ if any([x == JoinType.FULL for x in join_types]):
186
193
  final_join_type = JoinType.FULL
194
+ elif any([x == JoinType.LEFT_OUTER for x in join_types]):
195
+ final_join_type = JoinType.LEFT_OUTER
196
+ elif any([x == JoinType.RIGHT_OUTER for x in join_types]):
197
+ final_join_type = JoinType.RIGHT_OUTER
187
198
  output.append(
188
199
  JoinOrderOutput(
189
200
  # left=left_candidate,
@@ -608,13 +619,12 @@ def find_nullable_concepts(
608
619
  local_nullable = [
609
620
  x for x in datasources if k in [v.address for v in x.nullable_concepts]
610
621
  ]
611
- if all(
612
- [
613
- k in [v.address for v in x.nullable_concepts]
614
- for x in datasources
615
- if k in [z.address for z in x.output_concepts]
616
- ]
617
- ):
622
+ nullable_matches = [
623
+ k in [v.address for v in x.nullable_concepts]
624
+ for x in datasources
625
+ if k in [z.address for z in x.output_concepts]
626
+ ]
627
+ if all(nullable_matches) and len(nullable_matches) > 0:
618
628
  final_nullable.add(k)
619
629
  all_ds = set([ds for ds in local_nullable]).union(nullable_datasources)
620
630
  if nullable_datasources:
trilogy/dialect/duckdb.py CHANGED
@@ -76,6 +76,7 @@ FUNCTION_MAP = {
76
76
  FunctionType.DATE: lambda x: f"cast({x[0]} as date)",
77
77
  FunctionType.DATE_TRUNCATE: lambda x: f"date_trunc('{x[1]}', {x[0]})",
78
78
  FunctionType.DATE_ADD: lambda x: f"date_add({x[0]}, {x[2]} * INTERVAL 1 {x[1]})",
79
+ FunctionType.DATE_SUB: lambda x: f"date_add({x[0]}, -{x[2]} * INTERVAL 1 {x[1]})",
79
80
  FunctionType.DATE_PART: lambda x: f"date_part('{x[1]}', {x[0]})",
80
81
  FunctionType.DATE_DIFF: lambda x: f"date_diff('{x[2]}', {x[0]}, {x[1]})",
81
82
  FunctionType.CONCAT: lambda x: f"({' || '.join(x)})",
@@ -683,7 +683,9 @@ class ParseToObjects(Transformer):
683
683
  )
684
684
  # let constant purposes exist to support round-tripping
685
685
  # as a build concept may end up with a constant based on constant inlining happening recursively
686
- if (
686
+ if purpose == Purpose.KEY and concept.purpose != Purpose.KEY:
687
+ concept.purpose = Purpose.KEY
688
+ elif (
687
689
  purpose
688
690
  and purpose != Purpose.AUTO
689
691
  and concept.purpose != purpose
@@ -367,7 +367,7 @@
367
367
  fyear: _YEAR expr ")"
368
368
 
369
369
  DATE_PART: "DAY"i | "WEEK"i | "MONTH"i | "QUARTER"i | "YEAR"i | "MINUTE"i | "HOUR"i | "SECOND"i | "DAY_OF_WEEK"i
370
- _DATE_TRUNC.1: "date_trunc("i
370
+ _DATE_TRUNC.1: "date_trunc("i | "date_truncate("i
371
371
  fdate_trunc: _DATE_TRUNC expr "," DATE_PART ")"
372
372
  _DATE_PART.1: "date_part("i
373
373
  fdate_part: _DATE_PART expr "," DATE_PART ")"
@@ -9,10 +9,11 @@ type us_zip_code string; # US ZIP code
9
9
  ## generic types
10
10
  type latitude float; # Latitude in degrees
11
11
  type longitude float; # Longitude in degrees
12
- type lat_long string; # Latitude and longitude in degrees
12
+ type lat_long string; # Latitude and longitude in degrees, as a coordinate pair
13
13
 
14
14
  type city string; # City name
15
- type country string; # Country name
15
+ type country string; # Full Country Name
16
+ type country_code string; # ISO-3166 Country code - ex US, CA, GB
16
17
  type timezone string; # Timezone name
17
18
  type region string; # Region name
18
19
 
trilogy/std/net.preql CHANGED
@@ -1,9 +1,14 @@
1
1
 
2
+ ## network types
3
+ type url string; # URL string
4
+ type url_image string; # URL of an image
5
+ type domain string; # Domain name
6
+ type ip_net_mask string; # IP network mask
7
+ type ipv6_address string; # IPv6 address
8
+ type ipv4_address string; # IPv4 address
2
9
 
3
- type url string;
4
- type domain string;
5
- type ip_net_mask string;
6
- type ipv6_address string;
7
- type ipv4_address string;
8
- type suffix string;
9
- type url_image string;
10
+ ## communication types
11
+ type email_address string; # Email address, including @
12
+
13
+ ## shared types
14
+ type suffix string; # A file suffix or extension, like .txt, .jpg, etc.