pytrilogy 0.0.3.110__py3-none-any.whl → 0.0.3.111__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.110
3
+ Version: 0.0.3.111
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
5
  Classifier: Programming Language :: Python
6
6
  Classifier: Programming Language :: Python :: 3
@@ -1,8 +1,8 @@
1
- pytrilogy-0.0.3.110.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
2
- trilogy/__init__.py,sha256=eQXK52ADInFKSjwAH2CwNZJ13e5H52e9Jr2wLo7cJkk,304
1
+ pytrilogy-0.0.3.111.dist-info/licenses/LICENSE.md,sha256=5ZRvtTyCCFwz1THxDTjAu3Lidds9WjPvvzgVwPSYNDo,1042
2
+ trilogy/__init__.py,sha256=t3BBsjUY17XlIDGxHsMUFEuSMUyVnnWEzcU49iVEQNE,304
3
3
  trilogy/constants.py,sha256=g_zkVCNjGop6coZ1kM8eXXAzCnUN22ldx3TYFz0E9sc,1747
4
- trilogy/engine.py,sha256=3MiADf5MKcmxqiHBuRqiYdsXiLj7oitDfVvXvHrfjkA,2178
5
- trilogy/executor.py,sha256=-VeOV0bTGmchHRHpRwFJDyl8FElUxDpwUTUix7hhIFM,17429
4
+ trilogy/engine.py,sha256=v4TpNktM4zZ9OX7jZH2nde4dpX5uAH2U23ELfULTCSg,2280
5
+ trilogy/executor.py,sha256=f7ry_mtWMgwnPKV0MJszPqhNueOIrF4atfEigPlm9Dk,17959
6
6
  trilogy/parser.py,sha256=o4cfk3j3yhUFoiDKq9ZX_GjBF3dKhDjXEwb63rcBkBM,293
7
7
  trilogy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  trilogy/render.py,sha256=qQWwduymauOlB517UtM-VGbVe8Cswa4UJub5aGbSO6c,1512
@@ -32,7 +32,7 @@ trilogy/core/functions.py,sha256=sdV6Z3NUVfwL1d18eNcaAXllVNqzLez23McsJ6xIp7M,331
32
32
  trilogy/core/graph_models.py,sha256=4EWFTHGfYd72zvS2HYoV6hm7nMC_VEd7vWr6txY-ig0,3400
33
33
  trilogy/core/internal.py,sha256=r9QagDB2GvpqlyD_I7VrsfbVfIk5mnok2znEbv72Aa4,2681
34
34
  trilogy/core/optimization.py,sha256=Km0ITEx9n6Iv5ReX6tm4uXO5uniSv_ooahycNNiET3g,9212
35
- trilogy/core/query_processor.py,sha256=uqygDJqkjIH4vLP-lbGRgTN7rRcYEkr3KGqNimNw_80,20345
35
+ trilogy/core/query_processor.py,sha256=rMrtLSQxVm7yeyh0nWjDNI9nnu4Xi0NgHvBJ14gvu4I,20384
36
36
  trilogy/core/utility.py,sha256=3VC13uSQWcZNghgt7Ot0ZTeEmNqs__cx122abVq9qhM,410
37
37
  trilogy/core/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
38
  trilogy/core/models/author.py,sha256=3I7PFpJgoQT9RPOT3DfiqAjEtkcQPJnScs60I2UoyWo,81461
@@ -41,7 +41,7 @@ trilogy/core/models/build_environment.py,sha256=mpx7MKGc60fnZLVdeLi2YSREy7eQbQYy
41
41
  trilogy/core/models/core.py,sha256=iT9WdZoiXeglmUHWn6bZyXCTBpkApTGPKtNm_Mhbu_g,12987
42
42
  trilogy/core/models/datasource.py,sha256=wogTevZ-9CyUW2a8gjzqMCieircxi-J5lkI7EOAZnck,9596
43
43
  trilogy/core/models/environment.py,sha256=hwTIRnJgaHUdCYof7U5A9NPitGZ2s9yxqiW5O2SaJ9Y,28759
44
- trilogy/core/models/execute.py,sha256=pdL3voYB4dCQR_KMHwFaofP3ZpRbALRC2ELHueWyTko,42191
44
+ trilogy/core/models/execute.py,sha256=3fgEdho2e7S0outq91cCzb9jFwz6L1hTbsTrJwGvIFs,42311
45
45
  trilogy/core/optimizations/__init__.py,sha256=yspWc25M5SgAuvXYoSt5J8atyPbDlOfsKjIo5yGD9s4,368
46
46
  trilogy/core/optimizations/base_optimization.py,sha256=gzDOKImoFn36k7XBD3ysEYDnbnb6vdVIztUfFQZsGnM,513
47
47
  trilogy/core/optimizations/hide_unused_concept.py,sha256=DbsP8NqQOxmPv9omDOoFNPUGObUkqsRRNrr5d1xDxx4,1962
@@ -61,7 +61,7 @@ trilogy/core/processing/node_generators/constant_node.py,sha256=LfpDq2WrBRZ3tGsL
61
61
  trilogy/core/processing/node_generators/filter_node.py,sha256=cJ5od1fAfvalaUDO2O4Y6Yrr2RukOCqey7f3zrKSBbI,10808
62
62
  trilogy/core/processing/node_generators/group_node.py,sha256=sIm1QYrF4EY6sk56A48B6MieCZqvaJLSQebih_aiKnQ,8567
63
63
  trilogy/core/processing/node_generators/group_to_node.py,sha256=jKcNCDOY6fNblrdZwaRU0sbUSr9H0moQbAxrGgX6iGA,3832
64
- trilogy/core/processing/node_generators/multiselect_node.py,sha256=a505AEixjsjp5jI8Ng3H5KF_AaehkS6HfRfTef64l_o,7063
64
+ trilogy/core/processing/node_generators/multiselect_node.py,sha256=dHPDoSKU0FF6Ue_t_LkZxTd0Q-Sf-EpYdsMYdyUlFQc,7120
65
65
  trilogy/core/processing/node_generators/node_merge_node.py,sha256=hNcZxnDLTZyYJWfojg769zH9HB9PfZfESmpN1lcHWXg,23172
66
66
  trilogy/core/processing/node_generators/recursive_node.py,sha256=l5zdh0dURKwmAy8kK4OpMtZfyUEQRk6N-PwSWIyBpSM,2468
67
67
  trilogy/core/processing/node_generators/rowset_node.py,sha256=MuVNIexXhqGONho_mewqMOwaYXNUnjjvyPvk_RDGNYE,5943
@@ -74,10 +74,10 @@ trilogy/core/processing/node_generators/window_node.py,sha256=wNvmumGO6AIQ7C9bDU
74
74
  trilogy/core/processing/node_generators/select_helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
75
  trilogy/core/processing/node_generators/select_helpers/datasource_injection.py,sha256=m2YQ4OmG0N2O61a7NEq1ZzbTa7JsCC00lxB2ymjcYRI,8224
76
76
  trilogy/core/processing/nodes/__init__.py,sha256=zTge1EzwzEydlcMliIFO_TT7h7lS8l37lyZuQDir1h0,5487
77
- trilogy/core/processing/nodes/base_node.py,sha256=6LPQ5zP_dZJ6-k_dmX9ZSLsHaQMHgqiR5DEylpHYGZA,18478
77
+ trilogy/core/processing/nodes/base_node.py,sha256=k4Z9qdL9BXxxHH66L5udQwSDcYeiaWEn3bRmy84SShs,18559
78
78
  trilogy/core/processing/nodes/filter_node.py,sha256=5VtRfKbCORx0dV-vQfgy3gOEkmmscL9f31ExvlODwvY,2461
79
79
  trilogy/core/processing/nodes/group_node.py,sha256=Ku8El9KQvRiTiHCZDS_jX0DjErSDNv7IIQMcd1Gsk7I,7449
80
- trilogy/core/processing/nodes/merge_node.py,sha256=uc0tlz30Yt9SnCwLhMcWuPVbXLzm3dzy0XqbyirqqTo,16521
80
+ trilogy/core/processing/nodes/merge_node.py,sha256=4y_itKoipHKjpCIQjK9SHga-Fq-HqyeQLwAoSIFQ1hM,16567
81
81
  trilogy/core/processing/nodes/recursive_node.py,sha256=k0rizxR8KE64ievfHx_GPfQmU8QAP118Laeyq5BLUOk,1526
82
82
  trilogy/core/processing/nodes/select_node_v2.py,sha256=IWyKyNgFlV8A2S1FUTPdIaogg6PzaHh-HmQo6v24sbg,8862
83
83
  trilogy/core/processing/nodes/union_node.py,sha256=hLAXXVWqEgMWi7dlgSHfCF59fon64av14-uPgJzoKzM,1870
@@ -97,9 +97,9 @@ trilogy/core/validation/fix.py,sha256=Z818UFNLxndMTLiyhB3doLxIfnOZ-16QGvVFWuD7Us
97
97
  trilogy/dialect/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
98
98
  trilogy/dialect/base.py,sha256=Qk4HkjKlnAnhcZwwLte9Arb_1pVnBmkgRlwRFX1A_GQ,50680
99
99
  trilogy/dialect/bigquery.py,sha256=XS3hpybeowgfrOrkycAigAF3NX2YUzTzfgE6f__2fT4,4316
100
- trilogy/dialect/common.py,sha256=n9sQeXQ0bOXHDN_jQRuxr1rG7xPBRwaizvSz16MjIDY,5663
100
+ trilogy/dialect/common.py,sha256=I5Ku_TR5MwJTB3ZhcQenrtvXhH2RvTQ8wQe9w5lfkfA,5708
101
101
  trilogy/dialect/config.py,sha256=olnyeVU5W5T6b9-dMeNAnvxuPlyc2uefb7FRME094Ec,3834
102
- trilogy/dialect/dataframe.py,sha256=RUbNgReEa9g3pL6H7fP9lPTrAij5pkqedpZ99D8_5AE,1522
102
+ trilogy/dialect/dataframe.py,sha256=nDTHMSd7GiGjEhjAobrZND0w4zjr-vgOalM2Cdxjets,1596
103
103
  trilogy/dialect/duckdb.py,sha256=cRPyqnuMgjhZVaW9BYA360p-5OXle_1Xt65Yy0Vzbr4,5901
104
104
  trilogy/dialect/enums.py,sha256=FRNYQ5-w-B6-X0yXKNU5g9GowsMlERFogTC5u2nxL_s,4740
105
105
  trilogy/dialect/metadata.py,sha256=p_V-MYPQ2iR6fcTjagnptCIWtsZe4fTfoS_iXpavPzY,7098
@@ -132,8 +132,8 @@ trilogy/std/money.preql,sha256=XWwvAV3WxBsHX9zfptoYRnBigcfYwrYtBHXTME0xJuQ,2082
132
132
  trilogy/std/net.preql,sha256=WZCuvH87_rZntZiuGJMmBDMVKkdhTtxeHOkrXNwJ1EE,416
133
133
  trilogy/std/ranking.preql,sha256=LDoZrYyz4g3xsII9XwXfmstZD-_92i1Eox1UqkBIfi8,83
134
134
  trilogy/std/report.preql,sha256=LbV-XlHdfw0jgnQ8pV7acG95xrd1-p65fVpiIc-S7W4,202
135
- pytrilogy-0.0.3.110.dist-info/METADATA,sha256=WPrZFC0_2AmSkZqYb0Aefl8XPAlNXyQ3dohVqIGDicU,13289
136
- pytrilogy-0.0.3.110.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
137
- pytrilogy-0.0.3.110.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
138
- pytrilogy-0.0.3.110.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
139
- pytrilogy-0.0.3.110.dist-info/RECORD,,
135
+ pytrilogy-0.0.3.111.dist-info/METADATA,sha256=QagDSTPXJqU3Xa3OBJANdEauKslRIGUCczAVvV9HNcU,13289
136
+ pytrilogy-0.0.3.111.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
137
+ pytrilogy-0.0.3.111.dist-info/entry_points.txt,sha256=ewBPU2vLnVexZVnB-NrVj-p3E-4vukg83Zk8A55Wp2w,56
138
+ pytrilogy-0.0.3.111.dist-info/top_level.txt,sha256=cAy__NW_eMAa_yT9UnUNlZLFfxcg6eimUAZ184cdNiE,8
139
+ pytrilogy-0.0.3.111.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.110"
7
+ __version__ = "0.0.3.111"
8
8
 
9
9
  __all__ = ["parse", "Executor", "Dialects", "Environment", "CONFIG"]
@@ -500,6 +500,7 @@ class BaseJoin(BaseModel):
500
500
  concepts: Optional[List[BuildConcept]] = None
501
501
  left_datasource: Optional[Union[BuildDatasource, "QueryDatasource"]] = None
502
502
  concept_pairs: list[ConceptPair] | None = None
503
+ modifiers: List[Modifier] = Field(default_factory=list)
503
504
 
504
505
  @model_validator(mode="after")
505
506
  def validate_join(self) -> "BaseJoin":
@@ -1103,6 +1104,7 @@ class Join(BaseModel):
1103
1104
  inlined_ctes: set[str] = Field(default_factory=set)
1104
1105
  quote: str | None = None
1105
1106
  condition: BuildConditional | BuildComparison | BuildParenthetical | None = None
1107
+ modifiers: List[Modifier] = Field(default_factory=list)
1106
1108
 
1107
1109
  def inline_cte(self, cte: CTE):
1108
1110
  self.inlined_ctes.add(cte.name)
@@ -3,7 +3,7 @@ from itertools import combinations
3
3
  from typing import List
4
4
 
5
5
  from trilogy.constants import logger
6
- from trilogy.core.enums import JoinType, Purpose
6
+ from trilogy.core.enums import JoinType, Modifier, Purpose
7
7
  from trilogy.core.models.build import (
8
8
  BuildConcept,
9
9
  BuildGrain,
@@ -47,6 +47,7 @@ def extra_align_joins(
47
47
  right_node=right,
48
48
  concepts=matched_concepts,
49
49
  join_type=JoinType.FULL,
50
+ modifiers=[Modifier.NULLABLE],
50
51
  )
51
52
  )
52
53
  return resolve_join_order(output)
@@ -1,11 +1,12 @@
1
1
  from collections import defaultdict
2
- from dataclasses import dataclass
2
+ from dataclasses import dataclass, field
3
3
  from typing import List, Optional
4
4
 
5
5
  from trilogy.core.enums import (
6
6
  BooleanOperator,
7
7
  Derivation,
8
8
  JoinType,
9
+ Modifier,
9
10
  SourceType,
10
11
  )
11
12
  from trilogy.core.models.build import (
@@ -436,6 +437,7 @@ class NodeJoin:
436
437
  join_type: JoinType
437
438
  filter_to_mutual: bool = False
438
439
  concept_pairs: list[ConceptPair] | None = None
440
+ modifiers: List[Modifier] = field(default_factory=list)
439
441
 
440
442
  def __post_init__(self):
441
443
  if self.left_node == self.right_node:
@@ -169,6 +169,7 @@ class MergeNode(StrategyNode):
169
169
  join_type=join.join_type,
170
170
  concepts=join.concepts,
171
171
  concept_pairs=join.concept_pairs,
172
+ modifiers=join.modifiers,
172
173
  )
173
174
  )
174
175
  return joins
@@ -122,6 +122,7 @@ def base_join_to_join(
122
122
  right_cte=right_cte,
123
123
  jointype=base_join.join_type,
124
124
  joinkey_pairs=final_pairs,
125
+ modifiers=base_join.modifiers,
125
126
  )
126
127
 
127
128
 
trilogy/dialect/common.py CHANGED
@@ -131,7 +131,8 @@ def render_join(
131
131
  ),
132
132
  pair.modifiers
133
133
  + (pair.left.modifiers or [])
134
- + (pair.right.modifiers or []),
134
+ + (pair.right.modifiers or [])
135
+ + (join.modifiers or []),
135
136
  )
136
137
  for pair in join.joinkey_pairs
137
138
  ]
@@ -45,3 +45,6 @@ class DataframeConnectionWrapper(ExecutionEngine):
45
45
 
46
46
  def connect(self) -> Any:
47
47
  return self.engine.connect()
48
+
49
+ def dispose(self, close=True):
50
+ return super().dispose(close)
trilogy/engine.py CHANGED
@@ -33,6 +33,9 @@ class EngineConnection(Protocol):
33
33
  def rollback(self):
34
34
  raise NotImplementedError()
35
35
 
36
+ def close(self) -> None:
37
+ return
38
+
36
39
 
37
40
  class ExecutionEngine(Protocol):
38
41
  pass
@@ -43,6 +46,9 @@ class ExecutionEngine(Protocol):
43
46
  def setup(self, env: Environment, connection):
44
47
  pass
45
48
 
49
+ def dispose(self, close: bool = True):
50
+ pass
51
+
46
52
 
47
53
  ### Begin default SQLAlchemy implementation
48
54
  class SqlAlchemyResult:
trilogy/executor.py CHANGED
@@ -47,7 +47,7 @@ from trilogy.dialect.metadata import (
47
47
  handle_processed_validate_statement,
48
48
  handle_show_statement_outputs,
49
49
  )
50
- from trilogy.engine import ExecutionEngine, ResultProtocol
50
+ from trilogy.engine import EngineConnection, ExecutionEngine, ResultProtocol
51
51
  from trilogy.hooks.base_hook import BaseHook
52
52
  from trilogy.parser import parse_text
53
53
  from trilogy.render import get_dialect_generator
@@ -69,11 +69,27 @@ class Executor(object):
69
69
  self.logger = logger
70
70
  self.hooks = hooks
71
71
  self.generator = get_dialect_generator(self.dialect, rendering)
72
- self.connection = self.engine.connect()
72
+ self.connection = self.connect()
73
73
  # TODO: make generic
74
74
  if self.dialect == Dialects.DATAFRAME:
75
75
  self.engine.setup(self.environment, self.connection)
76
76
 
77
+ def connect(self) -> EngineConnection:
78
+ self.connection = self.engine.connect()
79
+ self.connected = True
80
+ return self.connection
81
+
82
+ def close(self):
83
+ self.engine.dispose(close=True)
84
+ if self.dialect == Dialects.DUCK_DB:
85
+ import duckdb
86
+
87
+ duckdb.default_connection().close()
88
+ import gc
89
+
90
+ gc.collect()
91
+ self.connected = False
92
+
77
93
  def execute_statement(
78
94
  self,
79
95
  statement: PROCESSED_STATEMENT_TYPES,
@@ -244,7 +260,9 @@ class Executor(object):
244
260
  """generate SQL for execution"""
245
261
  _, parsed = parse_text(command, self.environment)
246
262
  generatable = [
247
- x for x in parsed if isinstance(x, (SelectStatement, PersistStatement))
263
+ x
264
+ for x in parsed
265
+ if isinstance(x, (SelectStatement, PersistStatement, MultiSelectStatement))
248
266
  ]
249
267
  sql = self.generator.generate_queries(
250
268
  self.environment, generatable, hooks=self.hooks
@@ -419,6 +437,9 @@ class Executor(object):
419
437
  def execute_text(
420
438
  self, command: str, non_interactive: bool = False
421
439
  ) -> List[ResultProtocol]:
440
+ if not self.connected:
441
+ self.connect()
442
+
422
443
  """Run a trilogy query expressed as text."""
423
444
  output: list[ResultProtocol] = []
424
445
  # connection = self.engine.connect()