tracktolib 0.49.0__py3-none-any.whl → 0.50.0__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.
- tracktolib/pg/__init__.py +1 -0
- tracktolib/pg/query.py +5 -0
- tracktolib/pg_sync.py +3 -1
- tracktolib/pg_utils.py +15 -2
- {tracktolib-0.49.0.dist-info → tracktolib-0.50.0.dist-info}/METADATA +1 -1
- {tracktolib-0.49.0.dist-info → tracktolib-0.50.0.dist-info}/RECORD +8 -8
- {tracktolib-0.49.0.dist-info → tracktolib-0.50.0.dist-info}/LICENSE +0 -0
- {tracktolib-0.49.0.dist-info → tracktolib-0.50.0.dist-info}/WHEEL +0 -0
tracktolib/pg/__init__.py
CHANGED
tracktolib/pg/query.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import typing
|
|
2
2
|
from dataclasses import dataclass, field
|
|
3
3
|
from typing import TypeVar, Iterable, Callable, Generic, Iterator, TypeAlias, overload, Any, Literal
|
|
4
|
+
|
|
4
5
|
from ..pg_utils import get_conflict_query
|
|
5
6
|
|
|
6
7
|
try:
|
|
@@ -32,6 +33,7 @@ def _get_on_conflict_query(
|
|
|
32
33
|
constraint: K | None,
|
|
33
34
|
on_conflict: K | None,
|
|
34
35
|
where: K | None,
|
|
36
|
+
merge_columns: Iterable[K] | None,
|
|
35
37
|
) -> str:
|
|
36
38
|
_on_conflict = get_conflict_query(
|
|
37
39
|
columns=columns,
|
|
@@ -40,6 +42,7 @@ def _get_on_conflict_query(
|
|
|
40
42
|
constraint=constraint,
|
|
41
43
|
on_conflict=on_conflict,
|
|
42
44
|
where=where,
|
|
45
|
+
merge_columns=merge_columns,
|
|
43
46
|
)
|
|
44
47
|
return f"{query} {_on_conflict}"
|
|
45
48
|
|
|
@@ -72,6 +75,7 @@ class PGConflictQuery(Generic[K]):
|
|
|
72
75
|
query: str | None = None
|
|
73
76
|
constraint: str | None = None
|
|
74
77
|
where: str | None = None
|
|
78
|
+
merge_keys: Iterable[K] | None = None
|
|
75
79
|
|
|
76
80
|
def __post_init__(self):
|
|
77
81
|
_has_keys = 1 if (self.keys or self.ignore_keys) else 0
|
|
@@ -172,6 +176,7 @@ class PGInsertQuery(PGQuery):
|
|
|
172
176
|
self.on_conflict.constraint,
|
|
173
177
|
self.on_conflict.query,
|
|
174
178
|
self.on_conflict.where,
|
|
179
|
+
self.on_conflict.merge_keys,
|
|
175
180
|
)
|
|
176
181
|
|
|
177
182
|
# Returning
|
tracktolib/pg_sync.py
CHANGED
|
@@ -18,6 +18,7 @@ from .pg_utils import get_tmp_table_query
|
|
|
18
18
|
def fetch_all(engine: Connection, query: LiteralString, *data) -> list[dict]:
|
|
19
19
|
with engine.cursor(row_factory=dict_row) as cur:
|
|
20
20
|
resp = (cur.execute(query) if not data else cur.execute(query, data)).fetchall()
|
|
21
|
+
engine.commit()
|
|
21
22
|
return resp
|
|
22
23
|
|
|
23
24
|
|
|
@@ -27,7 +28,7 @@ def fetch_count(engine: Connection, table: str, *args, where: str | None = None)
|
|
|
27
28
|
query = f"{query} WHERE {where}"
|
|
28
29
|
with engine.cursor() as cur:
|
|
29
30
|
count = cur.execute(cast(LiteralString, query), params=args).fetchone()
|
|
30
|
-
|
|
31
|
+
engine.commit()
|
|
31
32
|
return count[0] if count else None
|
|
32
33
|
|
|
33
34
|
|
|
@@ -46,6 +47,7 @@ def fetch_one(engine: Connection, query: Query, *args) -> dict | None: ...
|
|
|
46
47
|
def fetch_one(engine: Connection, query: Query, *args, required: bool = False) -> dict | None:
|
|
47
48
|
with engine.cursor(row_factory=dict_row) as cur:
|
|
48
49
|
_data = cur.execute(query, args).fetchone()
|
|
50
|
+
engine.commit()
|
|
49
51
|
if required and not _data:
|
|
50
52
|
raise ValueError("No value found for query")
|
|
51
53
|
return _data
|
tracktolib/pg_utils.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
from typing_extensions import LiteralString
|
|
2
1
|
from typing import Iterable
|
|
3
2
|
from typing import cast
|
|
4
3
|
|
|
4
|
+
from typing_extensions import LiteralString
|
|
5
|
+
|
|
5
6
|
|
|
6
7
|
def get_tmp_table_query(
|
|
7
8
|
schema: LiteralString,
|
|
@@ -41,6 +42,7 @@ def get_conflict_query(
|
|
|
41
42
|
constraint: str | None = None,
|
|
42
43
|
on_conflict: str | None = None,
|
|
43
44
|
where: str | None = None,
|
|
45
|
+
merge_columns: Iterable[str] | None = None,
|
|
44
46
|
) -> LiteralString:
|
|
45
47
|
if on_conflict:
|
|
46
48
|
return cast(LiteralString, on_conflict)
|
|
@@ -55,8 +57,19 @@ def get_conflict_query(
|
|
|
55
57
|
else:
|
|
56
58
|
raise NotImplementedError("update_keys or constraint must be set")
|
|
57
59
|
|
|
58
|
-
|
|
60
|
+
_update_columns = update_columns or []
|
|
61
|
+
_ignore_columns = ignore_columns or []
|
|
62
|
+
_merge_columns = merge_columns or []
|
|
63
|
+
|
|
64
|
+
if set(_merge_columns) & set(_update_columns):
|
|
65
|
+
raise ValueError("Duplicate keys found between merge and update")
|
|
66
|
+
if set(_merge_columns) & set(_ignore_columns):
|
|
67
|
+
raise ValueError("Merge column cannot be ignored")
|
|
68
|
+
|
|
69
|
+
_ignore_columns = [*_update_columns, *_ignore_columns, *_merge_columns]
|
|
59
70
|
fields = ", ".join(f"{x} = COALESCE(EXCLUDED.{x}, t.{x})" for x in columns if x not in _ignore_columns)
|
|
71
|
+
if merge_columns:
|
|
72
|
+
fields += ", ".join(f"{x} = COALESCE(t.{x}, jsonb_build_object()) || EXCLUDED.{x}" for x in merge_columns)
|
|
60
73
|
if not fields:
|
|
61
74
|
raise ValueError("No fields set")
|
|
62
75
|
|
|
@@ -3,17 +3,17 @@ tracktolib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
3
3
|
tracktolib/api.py,sha256=xArVgRj_g7bw2tEDbjC9qs9f55b9X0-kJoc8-s1rsYo,9616
|
|
4
4
|
tracktolib/http_utils.py,sha256=c10JGmHaBw3VSDMYhz2dvVw2lo4PUAq1xMub74I7xDc,2625
|
|
5
5
|
tracktolib/logs.py,sha256=M5RZ8OYKgLEBJeC1AwUCSRbFAH09hwdTjjs-AQ9QGg8,2204
|
|
6
|
-
tracktolib/pg/__init__.py,sha256=
|
|
7
|
-
tracktolib/pg/query.py,sha256=
|
|
6
|
+
tracktolib/pg/__init__.py,sha256=j67e3B3gBbCHLD20QBybptmNdbbVMzNhZE6XjIPuKVo,349
|
|
7
|
+
tracktolib/pg/query.py,sha256=otLukOink4qQDUAN2VaPvlq5Ig8Sz7yfQlg-8gjI4iY,13744
|
|
8
8
|
tracktolib/pg/utils.py,sha256=cL24KEt4SWJQ7LJPzaO3c8Xg0ZLmjhn22DtTWg86nwc,6324
|
|
9
|
-
tracktolib/pg_sync.py,sha256=
|
|
10
|
-
tracktolib/pg_utils.py,sha256=
|
|
9
|
+
tracktolib/pg_sync.py,sha256=z6EB0hELq6t129gnVnX0rNXv2McZXxI8khy-TEG65Ag,5165
|
|
10
|
+
tracktolib/pg_utils.py,sha256=asFAyTC_RCRaYr9fiJxTiSs3yxZM6xyoOKLA6olg6yg,2529
|
|
11
11
|
tracktolib/s3/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
12
|
tracktolib/s3/minio.py,sha256=wMEjkSes9Fp39fD17IctALpD6zB2xwDRQEmO7Vzan3g,1387
|
|
13
13
|
tracktolib/s3/s3.py,sha256=d0Q63Zb62ef4jAt05zQwpgYvAoxHC9kSQuHzzK90VvE,4825
|
|
14
14
|
tracktolib/tests.py,sha256=Pbc4yGQrIWFLBEgX-kDBxhMCqH-bfOJtkH2agvaM6ZQ,382
|
|
15
15
|
tracktolib/utils.py,sha256=jwLww8bqDu8zEip9uN4yW0lE5_YMWfrAHYtagr8sYOA,5295
|
|
16
|
-
tracktolib-0.
|
|
17
|
-
tracktolib-0.
|
|
18
|
-
tracktolib-0.
|
|
19
|
-
tracktolib-0.
|
|
16
|
+
tracktolib-0.50.0.dist-info/LICENSE,sha256=uUanH0X7SeZEPdsRTHegMSMTiIHMurt9H0jSwEwKE1Y,1081
|
|
17
|
+
tracktolib-0.50.0.dist-info/METADATA,sha256=MbyudDqUlbPAKAomAy94zIDnKTnhKPnvxSzI9VUQU2s,3641
|
|
18
|
+
tracktolib-0.50.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
19
|
+
tracktolib-0.50.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|