pydoptic-sql 0.0.2.post1.dev1__tar.gz → 0.0.2.post1.dev2__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.
- {pydoptic_sql-0.0.2.post1.dev1/src/pydoptic_sql.egg-info → pydoptic_sql-0.0.2.post1.dev2}/PKG-INFO +1 -1
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql/sql_computed.py +1 -1
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql/sql_query.py +11 -11
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql/sql_service.py +42 -42
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2/src/pydoptic_sql.egg-info}/PKG-INFO +1 -1
- pydoptic_sql-0.0.2.post1.dev2/src/pydoptic_sql.egg-info/scm_version.json +8 -0
- pydoptic_sql-0.0.2.post1.dev1/src/pydoptic_sql.egg-info/scm_version.json +0 -8
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/LICENSE +0 -0
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/README.md +0 -0
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/pyproject.toml +0 -0
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/setup.cfg +0 -0
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql/__init__.py +0 -0
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql/py.typed +0 -0
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql/sql_constraint.py +0 -0
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql/sql_having.py +0 -0
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql/sql_order.py +0 -0
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql/sql_table.py +0 -0
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql.egg-info/SOURCES.txt +0 -0
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql.egg-info/dependency_links.txt +0 -0
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql.egg-info/requires.txt +0 -0
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql.egg-info/scm_file_list.json +0 -0
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql.egg-info/top_level.txt +0 -0
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/test/test_sql_computed.py +0 -0
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/test/test_sql_constraint.py +0 -0
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/test/test_sql_having.py +0 -0
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/test/test_sql_params.py +0 -0
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/test/test_sql_query.py +0 -0
- {pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/test/test_sql_service.py +0 -0
{pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql/sql_computed.py
RENAMED
|
@@ -19,7 +19,7 @@ class AggregateFunction(Enum):
|
|
|
19
19
|
class ComputedResult(Selectable['ComputedResult']):
|
|
20
20
|
"""
|
|
21
21
|
Dict-backed holder for the computed (aggregate) columns of a query result row, keyed by each
|
|
22
|
-
`Computed`'s alias. Mirrors `
|
|
22
|
+
`Computed`'s alias. Mirrors `Partial`'s shape but isn't backed by a model class -- there's
|
|
23
23
|
no schema behind an aggregate expression, just whatever aliases the query selected.
|
|
24
24
|
"""
|
|
25
25
|
__slots__ = ['_dict']
|
{pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql/sql_query.py
RENAMED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
from dataclasses import dataclass
|
|
3
3
|
from enum import Enum
|
|
4
4
|
from typing import Any, Generic, List, Sequence, Tuple, Type, TypeVar, cast
|
|
5
|
-
from pydoptic import
|
|
5
|
+
from pydoptic import Partial
|
|
6
6
|
from pydoptic.selector import PropSelect, Prop, PropOpt, Param
|
|
7
7
|
from pydoptic_sql import SqlTable
|
|
8
8
|
from pydoptic_sql.sql_constraint import A, TC, TC1, TC2, TC3, Constraint, Constraint2, Constraint3, Constraint4, _qualified_label
|
|
@@ -25,7 +25,7 @@ from pydoptic_sql.sql_table import (
|
|
|
25
25
|
R = TypeVar('R')
|
|
26
26
|
|
|
27
27
|
class SqlQuery(Generic[R]):
|
|
28
|
-
# R is the result type of executing the query (e.g.
|
|
28
|
+
# R is the result type of executing the query (e.g. Partial[TC], or None); table type(s) are tracked separately per subclass.
|
|
29
29
|
def to_sql(self) -> str:
|
|
30
30
|
"""Render this query as a single SQL string with values interpolated -- for display/debugging only."""
|
|
31
31
|
raise NotImplementedError()
|
|
@@ -146,7 +146,7 @@ class JoinType(Enum):
|
|
|
146
146
|
# calling incr_arity() on them when set, and QueryN/ComputedQueryN are directly executable
|
|
147
147
|
# (to_sql()/to_sql_params()) at every stage, builder and "terminal" alike -- hence one class per arity
|
|
148
148
|
# instead of two. select_computed(_more) still splits off into a separate ComputedQueryN from QueryN,
|
|
149
|
-
# since the result type R differs (
|
|
149
|
+
# since the result type R differs (Partial[...] vs Tuple[..., ComputedResult]) and R can't vary
|
|
150
150
|
# at runtime for a single dataclass.
|
|
151
151
|
#
|
|
152
152
|
# _order_by/_group_by/_computed still widen by one union member per table added (rather than gaining
|
|
@@ -155,7 +155,7 @@ class JoinType(Enum):
|
|
|
155
155
|
# exactly as valid after it, with no re-wrapping needed.
|
|
156
156
|
|
|
157
157
|
@dataclass(frozen=True)
|
|
158
|
-
class Query1(Generic[TC], SqlQuery[
|
|
158
|
+
class Query1(Generic[TC], SqlQuery[Partial[TC]]):
|
|
159
159
|
table1: Type[TC]
|
|
160
160
|
_selection: Sequence[PropSelect[TC, Any]] | None = None
|
|
161
161
|
_where: Constraint[TC] | None = None
|
|
@@ -225,7 +225,7 @@ class Query1(Generic[TC], SqlQuery[PartialModel[TC]]):
|
|
|
225
225
|
return f'SELECT {selections} FROM {self.table1.__name__.lower()} WHERE {where_clause}{group_by_clause}{order_by_clause};', params
|
|
226
226
|
|
|
227
227
|
@dataclass(frozen=True)
|
|
228
|
-
class ComputedQuery1(Generic[TC], SqlQuery[Tuple[
|
|
228
|
+
class ComputedQuery1(Generic[TC], SqlQuery[Tuple[Partial[TC], ComputedResult]]):
|
|
229
229
|
table1: Type[TC]
|
|
230
230
|
_selection: Sequence[PropSelect[TC, Any]] | None = None
|
|
231
231
|
_where: Constraint[TC] | None = None
|
|
@@ -460,7 +460,7 @@ class DeleteQuery(Generic[TC], SqlQuery[None]):
|
|
|
460
460
|
# --- 2 tables ---
|
|
461
461
|
|
|
462
462
|
@dataclass(frozen=True)
|
|
463
|
-
class Query2(Generic[TC, TC1], SqlQuery[Tuple[
|
|
463
|
+
class Query2(Generic[TC, TC1], SqlQuery[Tuple[Partial[TC], Partial[TC1]]]):
|
|
464
464
|
table1: Type[TC]
|
|
465
465
|
table2: Type[TC1]
|
|
466
466
|
join_type_2: JoinType
|
|
@@ -558,7 +558,7 @@ class Query2(Generic[TC, TC1], SqlQuery[Tuple[PartialModel[TC], PartialModel[TC1
|
|
|
558
558
|
return f'SELECT {selections} FROM {from_clause} WHERE {where_clause}{group_by_clause}{order_by_clause};', params
|
|
559
559
|
|
|
560
560
|
@dataclass(frozen=True)
|
|
561
|
-
class ComputedQuery2(Generic[TC, TC1], SqlQuery[Tuple[
|
|
561
|
+
class ComputedQuery2(Generic[TC, TC1], SqlQuery[Tuple[Partial[TC], Partial[TC1], ComputedResult]]):
|
|
562
562
|
table1: Type[TC]
|
|
563
563
|
table2: Type[TC1]
|
|
564
564
|
join_type_2: JoinType
|
|
@@ -679,7 +679,7 @@ class ComputedQuery2(Generic[TC, TC1], SqlQuery[Tuple[PartialModel[TC], PartialM
|
|
|
679
679
|
# --- 3 tables ---
|
|
680
680
|
|
|
681
681
|
@dataclass(frozen=True)
|
|
682
|
-
class Query3(Generic[TC, TC1, TC2], SqlQuery[Tuple[
|
|
682
|
+
class Query3(Generic[TC, TC1, TC2], SqlQuery[Tuple[Partial[TC], Partial[TC1], Partial[TC2]]]):
|
|
683
683
|
table1: Type[TC]
|
|
684
684
|
table2: Type[TC1]
|
|
685
685
|
table3: Type[TC2]
|
|
@@ -787,7 +787,7 @@ class Query3(Generic[TC, TC1, TC2], SqlQuery[Tuple[PartialModel[TC], PartialMode
|
|
|
787
787
|
return f'SELECT {selections} FROM {from_clause} WHERE {where_clause}{group_by_clause}{order_by_clause};', params
|
|
788
788
|
|
|
789
789
|
@dataclass(frozen=True)
|
|
790
|
-
class ComputedQuery3(Generic[TC, TC1, TC2], SqlQuery[Tuple[
|
|
790
|
+
class ComputedQuery3(Generic[TC, TC1, TC2], SqlQuery[Tuple[Partial[TC], Partial[TC1], Partial[TC2], ComputedResult]]):
|
|
791
791
|
table1: Type[TC]
|
|
792
792
|
table2: Type[TC1]
|
|
793
793
|
table3: Type[TC2]
|
|
@@ -918,7 +918,7 @@ class ComputedQuery3(Generic[TC, TC1, TC2], SqlQuery[Tuple[PartialModel[TC], Par
|
|
|
918
918
|
# --- 4 tables ---
|
|
919
919
|
|
|
920
920
|
@dataclass(frozen=True)
|
|
921
|
-
class Query4(Generic[TC, TC1, TC2, TC3], SqlQuery[Tuple[
|
|
921
|
+
class Query4(Generic[TC, TC1, TC2, TC3], SqlQuery[Tuple[Partial[TC], Partial[TC1], Partial[TC2], Partial[TC3]]]):
|
|
922
922
|
table1: Type[TC]
|
|
923
923
|
table2: Type[TC1]
|
|
924
924
|
table3: Type[TC2]
|
|
@@ -1022,7 +1022,7 @@ class Query4(Generic[TC, TC1, TC2, TC3], SqlQuery[Tuple[PartialModel[TC], Partia
|
|
|
1022
1022
|
return f'SELECT {selections} FROM {from_clause} WHERE {where_clause}{group_by_clause}{order_by_clause};', params
|
|
1023
1023
|
|
|
1024
1024
|
@dataclass(frozen=True)
|
|
1025
|
-
class ComputedQuery4(Generic[TC, TC1, TC2, TC3], SqlQuery[Tuple[
|
|
1025
|
+
class ComputedQuery4(Generic[TC, TC1, TC2, TC3], SqlQuery[Tuple[Partial[TC], Partial[TC1], Partial[TC2], Partial[TC3], ComputedResult]]):
|
|
1026
1026
|
table1: Type[TC]
|
|
1027
1027
|
table2: Type[TC1]
|
|
1028
1028
|
table3: Type[TC2]
|
{pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql/sql_service.py
RENAMED
|
@@ -4,7 +4,7 @@ from contextlib import contextmanager
|
|
|
4
4
|
from dataclasses import dataclass
|
|
5
5
|
from typing import Any, Dict, Generic, Iterator, List, Sequence, Tuple, Type, cast
|
|
6
6
|
|
|
7
|
-
from pydoptic.base_model import
|
|
7
|
+
from pydoptic.base_model import Partial
|
|
8
8
|
from pydoptic.selector import PropSelect
|
|
9
9
|
from pydoptic_sql import SqlQuery
|
|
10
10
|
from pydoptic_sql.sql_computed import Computed, ComputedResult
|
|
@@ -53,58 +53,58 @@ def _computed_record(computed: Sequence[Computed[Any, Any]], sql_record: Tuple[A
|
|
|
53
53
|
return ComputedResult(**{c.label: sql_record[offset + i] for i, c in enumerate(computed)})
|
|
54
54
|
|
|
55
55
|
@dataclass
|
|
56
|
-
class PsycoPgSqlResponse(Generic[TC], SqlResponse[
|
|
56
|
+
class PsycoPgSqlResponse(Generic[TC], SqlResponse[Partial[TC]]):
|
|
57
57
|
model: Type[TC]
|
|
58
58
|
cursor: Cursor
|
|
59
59
|
selection: Sequence[PropSelect[TC, Any]]
|
|
60
60
|
|
|
61
|
-
def __make_record(self, sql_record: Tuple[Any,...]) ->
|
|
61
|
+
def __make_record(self, sql_record: Tuple[Any,...]) -> Partial[TC]:
|
|
62
62
|
data: Dict[str, Any] = {}
|
|
63
63
|
for i, prop in enumerate(self.selection):
|
|
64
64
|
data[prop.label] = sql_record[i]
|
|
65
|
-
return
|
|
65
|
+
return Partial(self.model, **data)
|
|
66
66
|
|
|
67
|
-
def fetchone(self) ->
|
|
67
|
+
def fetchone(self) -> Partial[TC] | None:
|
|
68
68
|
result = self.cursor.fetchone()
|
|
69
69
|
if result is not None:
|
|
70
70
|
return self.__make_record(result)
|
|
71
71
|
return None
|
|
72
72
|
|
|
73
|
-
def stream(self) -> Iterator[
|
|
73
|
+
def stream(self) -> Iterator[Partial[TC]]:
|
|
74
74
|
for row in self.cursor:
|
|
75
75
|
yield self.__make_record(row)
|
|
76
76
|
|
|
77
77
|
@dataclass
|
|
78
|
-
class PsycoPgComputedResponse1(Generic[TC], SqlResponse[Tuple[
|
|
78
|
+
class PsycoPgComputedResponse1(Generic[TC], SqlResponse[Tuple[Partial[TC], ComputedResult]]):
|
|
79
79
|
model: Type[TC]
|
|
80
80
|
cursor: Cursor
|
|
81
81
|
selection: Sequence[PropSelect[TC, Any]]
|
|
82
82
|
computed: Sequence[Computed[TC, Any]]
|
|
83
83
|
|
|
84
|
-
def __make_record(self, sql_record: Tuple[Any, ...]) -> Tuple[
|
|
84
|
+
def __make_record(self, sql_record: Tuple[Any, ...]) -> Tuple[Partial[TC], ComputedResult]:
|
|
85
85
|
data: Dict[str, Any] = {}
|
|
86
86
|
for i, prop in enumerate(self.selection):
|
|
87
87
|
data[prop.label] = sql_record[i]
|
|
88
|
-
return
|
|
88
|
+
return Partial(self.model, **data), _computed_record(self.computed, sql_record, len(self.selection))
|
|
89
89
|
|
|
90
|
-
def fetchone(self) -> Tuple[
|
|
90
|
+
def fetchone(self) -> Tuple[Partial[TC], ComputedResult] | None:
|
|
91
91
|
result = self.cursor.fetchone()
|
|
92
92
|
if result is not None:
|
|
93
93
|
return self.__make_record(result)
|
|
94
94
|
return None
|
|
95
95
|
|
|
96
|
-
def stream(self) -> Iterator[Tuple[
|
|
96
|
+
def stream(self) -> Iterator[Tuple[Partial[TC], ComputedResult]]:
|
|
97
97
|
for row in self.cursor:
|
|
98
98
|
yield self.__make_record(row)
|
|
99
99
|
|
|
100
100
|
@dataclass
|
|
101
|
-
class PsycoPgJoinResponse2(Generic[TC, TC1], SqlResponse[Tuple[
|
|
101
|
+
class PsycoPgJoinResponse2(Generic[TC, TC1], SqlResponse[Tuple[Partial[TC], Partial[TC1]]]):
|
|
102
102
|
table1: Type[TC]
|
|
103
103
|
table2: Type[TC1]
|
|
104
104
|
cursor: Cursor
|
|
105
105
|
selection: Sequence[PropSelect[TC, Any] | PropSelect[TC1, Any]]
|
|
106
106
|
|
|
107
|
-
def __make_record(self, sql_record: Tuple[Any, ...]) -> Tuple[
|
|
107
|
+
def __make_record(self, sql_record: Tuple[Any, ...]) -> Tuple[Partial[TC], Partial[TC1]]:
|
|
108
108
|
data1: Dict[str, Any] = {}
|
|
109
109
|
data2: Dict[str, Any] = {}
|
|
110
110
|
for i, prop in enumerate(self.selection):
|
|
@@ -112,27 +112,27 @@ class PsycoPgJoinResponse2(Generic[TC, TC1], SqlResponse[Tuple[PartialModel[TC],
|
|
|
112
112
|
data1[prop.label] = sql_record[i]
|
|
113
113
|
else:
|
|
114
114
|
data2[prop.label] = sql_record[i]
|
|
115
|
-
return
|
|
115
|
+
return Partial(self.table1, **data1), Partial(self.table2, **data2)
|
|
116
116
|
|
|
117
|
-
def fetchone(self) -> Tuple[
|
|
117
|
+
def fetchone(self) -> Tuple[Partial[TC], Partial[TC1]] | None:
|
|
118
118
|
result = self.cursor.fetchone()
|
|
119
119
|
if result is not None:
|
|
120
120
|
return self.__make_record(result)
|
|
121
121
|
return None
|
|
122
122
|
|
|
123
|
-
def stream(self) -> Iterator[Tuple[
|
|
123
|
+
def stream(self) -> Iterator[Tuple[Partial[TC], Partial[TC1]]]:
|
|
124
124
|
for row in self.cursor:
|
|
125
125
|
yield self.__make_record(row)
|
|
126
126
|
|
|
127
127
|
@dataclass
|
|
128
|
-
class PsycoPgComputedResponse2(Generic[TC, TC1], SqlResponse[Tuple[
|
|
128
|
+
class PsycoPgComputedResponse2(Generic[TC, TC1], SqlResponse[Tuple[Partial[TC], Partial[TC1], ComputedResult]]):
|
|
129
129
|
table1: Type[TC]
|
|
130
130
|
table2: Type[TC1]
|
|
131
131
|
cursor: Cursor
|
|
132
132
|
selection: Sequence[PropSelect[TC, Any] | PropSelect[TC1, Any]]
|
|
133
133
|
computed: Sequence[Computed[TC, Any] | Computed[TC1, Any]]
|
|
134
134
|
|
|
135
|
-
def __make_record(self, sql_record: Tuple[Any, ...]) -> Tuple[
|
|
135
|
+
def __make_record(self, sql_record: Tuple[Any, ...]) -> Tuple[Partial[TC], Partial[TC1], ComputedResult]:
|
|
136
136
|
data1: Dict[str, Any] = {}
|
|
137
137
|
data2: Dict[str, Any] = {}
|
|
138
138
|
for i, prop in enumerate(self.selection):
|
|
@@ -140,27 +140,27 @@ class PsycoPgComputedResponse2(Generic[TC, TC1], SqlResponse[Tuple[PartialModel[
|
|
|
140
140
|
data1[prop.label] = sql_record[i]
|
|
141
141
|
else:
|
|
142
142
|
data2[prop.label] = sql_record[i]
|
|
143
|
-
return
|
|
143
|
+
return Partial(self.table1, **data1), Partial(self.table2, **data2), _computed_record(self.computed, sql_record, len(self.selection))
|
|
144
144
|
|
|
145
|
-
def fetchone(self) -> Tuple[
|
|
145
|
+
def fetchone(self) -> Tuple[Partial[TC], Partial[TC1], ComputedResult] | None:
|
|
146
146
|
result = self.cursor.fetchone()
|
|
147
147
|
if result is not None:
|
|
148
148
|
return self.__make_record(result)
|
|
149
149
|
return None
|
|
150
150
|
|
|
151
|
-
def stream(self) -> Iterator[Tuple[
|
|
151
|
+
def stream(self) -> Iterator[Tuple[Partial[TC], Partial[TC1], ComputedResult]]:
|
|
152
152
|
for row in self.cursor:
|
|
153
153
|
yield self.__make_record(row)
|
|
154
154
|
|
|
155
155
|
@dataclass
|
|
156
|
-
class PsycoPgJoinResponse3(Generic[TC, TC1, TC2], SqlResponse[Tuple[
|
|
156
|
+
class PsycoPgJoinResponse3(Generic[TC, TC1, TC2], SqlResponse[Tuple[Partial[TC], Partial[TC1], Partial[TC2]]]):
|
|
157
157
|
table1: Type[TC]
|
|
158
158
|
table2: Type[TC1]
|
|
159
159
|
table3: Type[TC2]
|
|
160
160
|
cursor: Cursor
|
|
161
161
|
selection: Sequence[PropSelect[TC, Any] | PropSelect[TC1, Any] | PropSelect[TC2, Any]]
|
|
162
162
|
|
|
163
|
-
def __make_record(self, sql_record: Tuple[Any, ...]) -> Tuple[
|
|
163
|
+
def __make_record(self, sql_record: Tuple[Any, ...]) -> Tuple[Partial[TC], Partial[TC1], Partial[TC2]]:
|
|
164
164
|
data1: Dict[str, Any] = {}
|
|
165
165
|
data2: Dict[str, Any] = {}
|
|
166
166
|
data3: Dict[str, Any] = {}
|
|
@@ -171,20 +171,20 @@ class PsycoPgJoinResponse3(Generic[TC, TC1, TC2], SqlResponse[Tuple[PartialModel
|
|
|
171
171
|
data2[prop.label] = sql_record[i]
|
|
172
172
|
else:
|
|
173
173
|
data3[prop.label] = sql_record[i]
|
|
174
|
-
return
|
|
174
|
+
return Partial(self.table1, **data1), Partial(self.table2, **data2), Partial(self.table3, **data3)
|
|
175
175
|
|
|
176
|
-
def fetchone(self) -> Tuple[
|
|
176
|
+
def fetchone(self) -> Tuple[Partial[TC], Partial[TC1], Partial[TC2]] | None:
|
|
177
177
|
result = self.cursor.fetchone()
|
|
178
178
|
if result is not None:
|
|
179
179
|
return self.__make_record(result)
|
|
180
180
|
return None
|
|
181
181
|
|
|
182
|
-
def stream(self) -> Iterator[Tuple[
|
|
182
|
+
def stream(self) -> Iterator[Tuple[Partial[TC], Partial[TC1], Partial[TC2]]]:
|
|
183
183
|
for row in self.cursor:
|
|
184
184
|
yield self.__make_record(row)
|
|
185
185
|
|
|
186
186
|
@dataclass
|
|
187
|
-
class PsycoPgComputedResponse3(Generic[TC, TC1, TC2], SqlResponse[Tuple[
|
|
187
|
+
class PsycoPgComputedResponse3(Generic[TC, TC1, TC2], SqlResponse[Tuple[Partial[TC], Partial[TC1], Partial[TC2], ComputedResult]]):
|
|
188
188
|
table1: Type[TC]
|
|
189
189
|
table2: Type[TC1]
|
|
190
190
|
table3: Type[TC2]
|
|
@@ -192,7 +192,7 @@ class PsycoPgComputedResponse3(Generic[TC, TC1, TC2], SqlResponse[Tuple[PartialM
|
|
|
192
192
|
selection: Sequence[PropSelect[TC, Any] | PropSelect[TC1, Any] | PropSelect[TC2, Any]]
|
|
193
193
|
computed: Sequence[Computed[TC, Any] | Computed[TC1, Any] | Computed[TC2, Any]]
|
|
194
194
|
|
|
195
|
-
def __make_record(self, sql_record: Tuple[Any, ...]) -> Tuple[
|
|
195
|
+
def __make_record(self, sql_record: Tuple[Any, ...]) -> Tuple[Partial[TC], Partial[TC1], Partial[TC2], ComputedResult]:
|
|
196
196
|
data1: Dict[str, Any] = {}
|
|
197
197
|
data2: Dict[str, Any] = {}
|
|
198
198
|
data3: Dict[str, Any] = {}
|
|
@@ -203,20 +203,20 @@ class PsycoPgComputedResponse3(Generic[TC, TC1, TC2], SqlResponse[Tuple[PartialM
|
|
|
203
203
|
data2[prop.label] = sql_record[i]
|
|
204
204
|
else:
|
|
205
205
|
data3[prop.label] = sql_record[i]
|
|
206
|
-
return
|
|
206
|
+
return Partial(self.table1, **data1), Partial(self.table2, **data2), Partial(self.table3, **data3), _computed_record(self.computed, sql_record, len(self.selection))
|
|
207
207
|
|
|
208
|
-
def fetchone(self) -> Tuple[
|
|
208
|
+
def fetchone(self) -> Tuple[Partial[TC], Partial[TC1], Partial[TC2], ComputedResult] | None:
|
|
209
209
|
result = self.cursor.fetchone()
|
|
210
210
|
if result is not None:
|
|
211
211
|
return self.__make_record(result)
|
|
212
212
|
return None
|
|
213
213
|
|
|
214
|
-
def stream(self) -> Iterator[Tuple[
|
|
214
|
+
def stream(self) -> Iterator[Tuple[Partial[TC], Partial[TC1], Partial[TC2], ComputedResult]]:
|
|
215
215
|
for row in self.cursor:
|
|
216
216
|
yield self.__make_record(row)
|
|
217
217
|
|
|
218
218
|
@dataclass
|
|
219
|
-
class PsycoPgJoinResponse4(Generic[TC, TC1, TC2, TC3], SqlResponse[Tuple[
|
|
219
|
+
class PsycoPgJoinResponse4(Generic[TC, TC1, TC2, TC3], SqlResponse[Tuple[Partial[TC], Partial[TC1], Partial[TC2], Partial[TC3]]]):
|
|
220
220
|
table1: Type[TC]
|
|
221
221
|
table2: Type[TC1]
|
|
222
222
|
table3: Type[TC2]
|
|
@@ -224,7 +224,7 @@ class PsycoPgJoinResponse4(Generic[TC, TC1, TC2, TC3], SqlResponse[Tuple[Partial
|
|
|
224
224
|
cursor: Cursor
|
|
225
225
|
selection: Sequence[PropSelect[TC, Any] | PropSelect[TC1, Any] | PropSelect[TC2, Any] | PropSelect[TC3, Any]]
|
|
226
226
|
|
|
227
|
-
def __make_record(self, sql_record: Tuple[Any, ...]) -> Tuple[
|
|
227
|
+
def __make_record(self, sql_record: Tuple[Any, ...]) -> Tuple[Partial[TC], Partial[TC1], Partial[TC2], Partial[TC3]]:
|
|
228
228
|
data1: Dict[str, Any] = {}
|
|
229
229
|
data2: Dict[str, Any] = {}
|
|
230
230
|
data3: Dict[str, Any] = {}
|
|
@@ -238,20 +238,20 @@ class PsycoPgJoinResponse4(Generic[TC, TC1, TC2, TC3], SqlResponse[Tuple[Partial
|
|
|
238
238
|
data3[prop.label] = sql_record[i]
|
|
239
239
|
else:
|
|
240
240
|
data4[prop.label] = sql_record[i]
|
|
241
|
-
return
|
|
241
|
+
return Partial(self.table1, **data1), Partial(self.table2, **data2), Partial(self.table3, **data3), Partial(self.table4, **data4)
|
|
242
242
|
|
|
243
|
-
def fetchone(self) -> Tuple[
|
|
243
|
+
def fetchone(self) -> Tuple[Partial[TC], Partial[TC1], Partial[TC2], Partial[TC3]] | None:
|
|
244
244
|
result = self.cursor.fetchone()
|
|
245
245
|
if result is not None:
|
|
246
246
|
return self.__make_record(result)
|
|
247
247
|
return None
|
|
248
248
|
|
|
249
|
-
def stream(self) -> Iterator[Tuple[
|
|
249
|
+
def stream(self) -> Iterator[Tuple[Partial[TC], Partial[TC1], Partial[TC2], Partial[TC3]]]:
|
|
250
250
|
for row in self.cursor:
|
|
251
251
|
yield self.__make_record(row)
|
|
252
252
|
|
|
253
253
|
@dataclass
|
|
254
|
-
class PsycoPgComputedResponse4(Generic[TC, TC1, TC2, TC3], SqlResponse[Tuple[
|
|
254
|
+
class PsycoPgComputedResponse4(Generic[TC, TC1, TC2, TC3], SqlResponse[Tuple[Partial[TC], Partial[TC1], Partial[TC2], Partial[TC3], ComputedResult]]):
|
|
255
255
|
table1: Type[TC]
|
|
256
256
|
table2: Type[TC1]
|
|
257
257
|
table3: Type[TC2]
|
|
@@ -260,7 +260,7 @@ class PsycoPgComputedResponse4(Generic[TC, TC1, TC2, TC3], SqlResponse[Tuple[Par
|
|
|
260
260
|
selection: Sequence[PropSelect[TC, Any] | PropSelect[TC1, Any] | PropSelect[TC2, Any] | PropSelect[TC3, Any]]
|
|
261
261
|
computed: Sequence[Computed[TC, Any] | Computed[TC1, Any] | Computed[TC2, Any] | Computed[TC3, Any]]
|
|
262
262
|
|
|
263
|
-
def __make_record(self, sql_record: Tuple[Any, ...]) -> Tuple[
|
|
263
|
+
def __make_record(self, sql_record: Tuple[Any, ...]) -> Tuple[Partial[TC], Partial[TC1], Partial[TC2], Partial[TC3], ComputedResult]:
|
|
264
264
|
data1: Dict[str, Any] = {}
|
|
265
265
|
data2: Dict[str, Any] = {}
|
|
266
266
|
data3: Dict[str, Any] = {}
|
|
@@ -274,15 +274,15 @@ class PsycoPgComputedResponse4(Generic[TC, TC1, TC2, TC3], SqlResponse[Tuple[Par
|
|
|
274
274
|
data3[prop.label] = sql_record[i]
|
|
275
275
|
else:
|
|
276
276
|
data4[prop.label] = sql_record[i]
|
|
277
|
-
return
|
|
277
|
+
return Partial(self.table1, **data1), Partial(self.table2, **data2), Partial(self.table3, **data3), Partial(self.table4, **data4), _computed_record(self.computed, sql_record, len(self.selection))
|
|
278
278
|
|
|
279
|
-
def fetchone(self) -> Tuple[
|
|
279
|
+
def fetchone(self) -> Tuple[Partial[TC], Partial[TC1], Partial[TC2], Partial[TC3], ComputedResult] | None:
|
|
280
280
|
result = self.cursor.fetchone()
|
|
281
281
|
if result is not None:
|
|
282
282
|
return self.__make_record(result)
|
|
283
283
|
return None
|
|
284
284
|
|
|
285
|
-
def stream(self) -> Iterator[Tuple[
|
|
285
|
+
def stream(self) -> Iterator[Tuple[Partial[TC], Partial[TC1], Partial[TC2], Partial[TC3], ComputedResult]]:
|
|
286
286
|
for row in self.cursor:
|
|
287
287
|
yield self.__make_record(row)
|
|
288
288
|
|
|
@@ -313,7 +313,7 @@ class PsycoPgSqlTransaction(SqlTransaction):
|
|
|
313
313
|
case ComputedQuery4():
|
|
314
314
|
return cast(SqlResponse[R], PsycoPgComputedResponse4(query.table1, query.table2, query.table3, query.table4, self.cursor, query._resolved_selection(), query._computed))
|
|
315
315
|
case Query1():
|
|
316
|
-
# Query1[TC]'s R is always
|
|
316
|
+
# Query1[TC]'s R is always Partial[TC], which is exactly the caller's R here,
|
|
317
317
|
# but match narrowing can't invert R back to TC to prove that statically.
|
|
318
318
|
return cast(SqlResponse[R], PsycoPgSqlResponse(query.table1, self.cursor, query._resolved_selection()))
|
|
319
319
|
case Query2():
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql/sql_constraint.py
RENAMED
|
File without changes
|
{pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql/sql_having.py
RENAMED
|
File without changes
|
{pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql/sql_order.py
RENAMED
|
File without changes
|
{pydoptic_sql-0.0.2.post1.dev1 → pydoptic_sql-0.0.2.post1.dev2}/src/pydoptic_sql/sql_table.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|