data-factory-utils 3.2.2__tar.gz → 3.4.0__tar.gz
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.
- {data_factory_utils-3.2.2 → data_factory_utils-3.4.0}/PKG-INFO +1 -1
- {data_factory_utils-3.2.2 → data_factory_utils-3.4.0}/pyproject.toml +1 -1
- {data_factory_utils-3.2.2 → data_factory_utils-3.4.0}/pyproject.toml.orig +1 -1
- {data_factory_utils-3.2.2 → data_factory_utils-3.4.0}/src/data_factory_utils/athena.py +13 -14
- {data_factory_utils-3.2.2 → data_factory_utils-3.4.0}/src/data_factory_utils/query.py +56 -6
- {data_factory_utils-3.2.2 → data_factory_utils-3.4.0}/README.md +0 -0
- {data_factory_utils-3.2.2 → data_factory_utils-3.4.0}/src/data_factory_utils/__init__.py +0 -0
- {data_factory_utils-3.2.2 → data_factory_utils-3.4.0}/src/data_factory_utils/environment.py +0 -0
|
@@ -200,24 +200,23 @@ class AthenaQuery:
|
|
|
200
200
|
# Get the raw query results from the API
|
|
201
201
|
responses = self._get_responses()
|
|
202
202
|
|
|
203
|
-
|
|
204
|
-
|
|
203
|
+
column_names: list[str | None] | None = None
|
|
204
|
+
columns: list[list[str | None]] = []
|
|
205
|
+
|
|
205
206
|
for response in responses:
|
|
206
207
|
for row in response["ResultSet"]["Rows"]:
|
|
207
208
|
row_data = [column.get("VarCharValue") for column in row["Data"]]
|
|
208
|
-
rows.append(row_data)
|
|
209
|
-
|
|
210
|
-
if len(rows) == 0:
|
|
211
|
-
return pl.DataFrame({})
|
|
212
209
|
|
|
213
|
-
|
|
214
|
-
|
|
210
|
+
# The first row returned by the response is the names of the columns.
|
|
211
|
+
if column_names is None:
|
|
212
|
+
column_names = row_data
|
|
213
|
+
columns = [[] for _ in column_names]
|
|
214
|
+
continue
|
|
215
215
|
|
|
216
|
-
|
|
217
|
-
|
|
216
|
+
for column, value in zip(columns, row_data, strict=True):
|
|
217
|
+
column.append(value)
|
|
218
218
|
|
|
219
|
-
|
|
220
|
-
|
|
219
|
+
if column_names is None:
|
|
220
|
+
return pl.DataFrame({})
|
|
221
221
|
|
|
222
|
-
|
|
223
|
-
return pl.DataFrame(dict(zip(column_names, values_in_columns, strict=True)))
|
|
222
|
+
return pl.DataFrame(dict(zip(column_names, columns, strict=True)))
|
|
@@ -79,6 +79,23 @@ class WhereBasicComparison(NamedTuple):
|
|
|
79
79
|
brackets: Literal["open", "close", "wrap"] | None = None
|
|
80
80
|
|
|
81
81
|
|
|
82
|
+
class WhereExistsComparison(NamedTuple):
|
|
83
|
+
"""Config for WHERE EXISTS comparisons."""
|
|
84
|
+
|
|
85
|
+
subquery: Subquery
|
|
86
|
+
negative: bool = False
|
|
87
|
+
prefix: Literal["AND", "OR", "NOT"] | None = "AND"
|
|
88
|
+
brackets: Literal["open", "close", "wrap"] | None = None
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class WhereNotExistsComparison(NamedTuple):
|
|
92
|
+
"""Config for WHERE NOT EXISTS comparisons."""
|
|
93
|
+
|
|
94
|
+
subquery: Subquery
|
|
95
|
+
prefix: Literal["AND", "OR", "NOT"] | None = "AND"
|
|
96
|
+
brackets: Literal["open", "close", "wrap"] | None = None
|
|
97
|
+
|
|
98
|
+
|
|
82
99
|
class WhereRangeComparison(NamedTuple):
|
|
83
100
|
"""Config for WHERE BETWEEN comparisons."""
|
|
84
101
|
|
|
@@ -120,6 +137,17 @@ class WhereLikeRegex(NamedTuple):
|
|
|
120
137
|
brackets: Literal["open", "close", "wrap"] | None = None
|
|
121
138
|
|
|
122
139
|
|
|
140
|
+
WhereCondition = (
|
|
141
|
+
WhereBasicComparison
|
|
142
|
+
| WhereExistsComparison
|
|
143
|
+
| WhereNotExistsComparison
|
|
144
|
+
| WhereRangeComparison
|
|
145
|
+
| WhereSetMembership
|
|
146
|
+
| WherePatternMatch
|
|
147
|
+
| WhereLikeRegex
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
|
|
123
151
|
class Subquery:
|
|
124
152
|
"""Method to wrap queries as subqueries."""
|
|
125
153
|
|
|
@@ -537,6 +565,30 @@ def _build_where_between(config: WhereRangeComparison) -> str:
|
|
|
537
565
|
return query_str
|
|
538
566
|
|
|
539
567
|
|
|
568
|
+
def _build_where_exists_comparison(config: WhereExistsComparison | WhereNotExistsComparison) -> str:
|
|
569
|
+
"""Build a statement for EXISTS / NOT EXISTS.
|
|
570
|
+
|
|
571
|
+
Accepted styles:
|
|
572
|
+
- WHERE EXISTS (subquery)
|
|
573
|
+
- WHERE NOT EXISTS (subquery)
|
|
574
|
+
- AND EXISTS (subquery)
|
|
575
|
+
- AND NOT EXISTS (subquery)
|
|
576
|
+
- OR EXISTS (subquery)
|
|
577
|
+
- OR NOT EXISTS (subquery)
|
|
578
|
+
"""
|
|
579
|
+
if not isinstance(config.subquery, Subquery):
|
|
580
|
+
msg = "EXISTS condition requires a Subquery instance"
|
|
581
|
+
raise TypeError(msg)
|
|
582
|
+
|
|
583
|
+
negative = getattr(config, "negative", False) or isinstance(config, WhereNotExistsComparison)
|
|
584
|
+
op = "NOT EXISTS" if negative else "EXISTS"
|
|
585
|
+
query_str = f"{op} {config.subquery}"
|
|
586
|
+
|
|
587
|
+
if config.brackets:
|
|
588
|
+
query_str = _wrap(loc=config.brackets, text=query_str)
|
|
589
|
+
return query_str
|
|
590
|
+
|
|
591
|
+
|
|
540
592
|
def _build_where_set_membership(config: WhereSetMembership) -> str:
|
|
541
593
|
"""Build a statement for set membership.
|
|
542
594
|
|
|
@@ -607,9 +659,7 @@ def _build_where_regex_like(config: WhereLikeRegex) -> str:
|
|
|
607
659
|
|
|
608
660
|
|
|
609
661
|
def _validate_combined_where_conditions(
|
|
610
|
-
conditions: list[
|
|
611
|
-
WhereBasicComparison | WhereRangeComparison | WhereSetMembership | WherePatternMatch | WhereLikeRegex
|
|
612
|
-
],
|
|
662
|
+
conditions: list[WhereCondition],
|
|
613
663
|
) -> bool:
|
|
614
664
|
"""Validate WHERE conditions when used as a list."""
|
|
615
665
|
open_bracket = []
|
|
@@ -803,9 +853,7 @@ class Query:
|
|
|
803
853
|
|
|
804
854
|
def WHERE( # noqa: N802
|
|
805
855
|
self,
|
|
806
|
-
conditions: list[
|
|
807
|
-
WhereBasicComparison | WhereRangeComparison | WhereSetMembership | WherePatternMatch | WhereLikeRegex
|
|
808
|
-
],
|
|
856
|
+
conditions: list[WhereCondition],
|
|
809
857
|
) -> Self:
|
|
810
858
|
"""Write WHERE conditions."""
|
|
811
859
|
query_str = []
|
|
@@ -824,6 +872,8 @@ class Query:
|
|
|
824
872
|
cond_str = _build_where_pattern_match(condition)
|
|
825
873
|
case WhereLikeRegex():
|
|
826
874
|
cond_str = _build_where_regex_like(condition)
|
|
875
|
+
case WhereExistsComparison() | WhereNotExistsComparison():
|
|
876
|
+
cond_str = _build_where_exists_comparison(condition)
|
|
827
877
|
case _:
|
|
828
878
|
msg = "WHERE statement has no valid conditions."
|
|
829
879
|
raise ValueError(msg)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|