apexdevkit 1.17.7__tar.gz → 1.17.9__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.
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/PKG-INFO +1 -1
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/repository/mssql.py +56 -153
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/repository/sqlite.py +65 -145
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/pyproject.toml +1 -1
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/LICENSE +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/README.md +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/__init__.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/annotation/__init__.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/annotation/deprecate.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/environment.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/error.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/fastapi/__init__.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/fastapi/builder.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/fastapi/dependable.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/fastapi/docs.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/fastapi/name.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/fastapi/request.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/fastapi/resource.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/fastapi/response.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/fastapi/router.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/fastapi/schema.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/fastapi/service.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/fluent.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/formatter.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/http/__init__.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/http/fake.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/http/fluent.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/http/httpx.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/http/json.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/http/url.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/key_fn.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/py.typed +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/repository/__init__.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/repository/base.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/repository/connector.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/repository/database.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/repository/decorator.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/repository/in_memory.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/repository/interface.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/repository/mongo.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/server.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/synchronization.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/testing/__init__.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/testing/database.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/testing/fake.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/testing/rest.py +0 -0
- {apexdevkit-1.17.7 → apexdevkit-1.17.9}/apexdevkit/value.py +0 -0
|
@@ -144,9 +144,6 @@ class MsSqlTableBuilder(Generic[ItemT]):
|
|
|
144
144
|
table: str | None = None
|
|
145
145
|
formatter: Formatter[dict[str, Any], ItemT] | None = None
|
|
146
146
|
fields: list[MsSqlField] | None = None
|
|
147
|
-
ordering: list[str] | None = None
|
|
148
|
-
parent_field: str | None = None
|
|
149
|
-
parent_value: Any | None = None
|
|
150
147
|
|
|
151
148
|
def with_username(self, value: str) -> MsSqlTableBuilder[ItemT]:
|
|
152
149
|
return MsSqlTableBuilder[ItemT](
|
|
@@ -155,9 +152,6 @@ class MsSqlTableBuilder(Generic[ItemT]):
|
|
|
155
152
|
self.table,
|
|
156
153
|
self.formatter,
|
|
157
154
|
self.fields,
|
|
158
|
-
self.ordering,
|
|
159
|
-
self.parent_field,
|
|
160
|
-
self.parent_value,
|
|
161
155
|
)
|
|
162
156
|
|
|
163
157
|
def with_schema(self, value: str) -> MsSqlTableBuilder[ItemT]:
|
|
@@ -167,9 +161,6 @@ class MsSqlTableBuilder(Generic[ItemT]):
|
|
|
167
161
|
self.table,
|
|
168
162
|
self.formatter,
|
|
169
163
|
self.fields,
|
|
170
|
-
self.ordering,
|
|
171
|
-
self.parent_field,
|
|
172
|
-
self.parent_value,
|
|
173
164
|
)
|
|
174
165
|
|
|
175
166
|
def with_table(self, value: str) -> MsSqlTableBuilder[ItemT]:
|
|
@@ -179,9 +170,6 @@ class MsSqlTableBuilder(Generic[ItemT]):
|
|
|
179
170
|
value,
|
|
180
171
|
self.formatter,
|
|
181
172
|
self.fields,
|
|
182
|
-
self.ordering,
|
|
183
|
-
self.parent_field,
|
|
184
|
-
self.parent_value,
|
|
185
173
|
)
|
|
186
174
|
|
|
187
175
|
def with_formatter(
|
|
@@ -193,73 +181,20 @@ class MsSqlTableBuilder(Generic[ItemT]):
|
|
|
193
181
|
self.table,
|
|
194
182
|
value,
|
|
195
183
|
self.fields,
|
|
196
|
-
self.ordering,
|
|
197
|
-
self.parent_field,
|
|
198
|
-
self.parent_value,
|
|
199
184
|
)
|
|
200
185
|
|
|
201
|
-
def with_fields(self,
|
|
186
|
+
def with_fields(self, value: Iterable[MsSqlField]) -> MsSqlTableBuilder[ItemT]:
|
|
187
|
+
field_list = list(value)
|
|
188
|
+
if len([field for field in field_list if field.is_id]) != 1:
|
|
189
|
+
raise ValueError("Pass only one identifier field.")
|
|
190
|
+
if len([field for field in field_list if field.is_parent]) > 1:
|
|
191
|
+
raise ValueError("Pass only one parent field.")
|
|
202
192
|
return MsSqlTableBuilder[ItemT](
|
|
203
193
|
self.username,
|
|
204
194
|
self.schema,
|
|
205
195
|
self.table,
|
|
206
196
|
self.formatter,
|
|
207
|
-
|
|
208
|
-
self.ordering,
|
|
209
|
-
self.parent_field,
|
|
210
|
-
self.parent_value,
|
|
211
|
-
)
|
|
212
|
-
|
|
213
|
-
def with_order_fields(self, ordering: Iterable[str]) -> MsSqlTableBuilder[ItemT]:
|
|
214
|
-
ordered = list(ordering)
|
|
215
|
-
assert self.fields is not None, "Set fields first."
|
|
216
|
-
|
|
217
|
-
for key in ordered:
|
|
218
|
-
if key not in [field.name for field in self.fields]:
|
|
219
|
-
raise ValueError("Missing fields in the table.")
|
|
220
|
-
return MsSqlTableBuilder[ItemT](
|
|
221
|
-
self.username,
|
|
222
|
-
self.schema,
|
|
223
|
-
self.table,
|
|
224
|
-
self.formatter,
|
|
225
|
-
self.fields,
|
|
226
|
-
ordered,
|
|
227
|
-
self.parent_field,
|
|
228
|
-
self.parent_value,
|
|
229
|
-
)
|
|
230
|
-
|
|
231
|
-
def with_id(self, identifier: str) -> MsSqlTableBuilder[ItemT]:
|
|
232
|
-
assert self.fields is not None, "Set fields first."
|
|
233
|
-
if identifier not in [field.name for field in self.fields]:
|
|
234
|
-
raise ValueError("Missing fields in the table.")
|
|
235
|
-
|
|
236
|
-
return MsSqlTableBuilder[ItemT](
|
|
237
|
-
self.username,
|
|
238
|
-
self.schema,
|
|
239
|
-
self.table,
|
|
240
|
-
self.formatter,
|
|
241
|
-
[MsSqlField(field.name, field.name == identifier) for field in self.fields],
|
|
242
|
-
self.ordering,
|
|
243
|
-
self.parent_field,
|
|
244
|
-
self.parent_value,
|
|
245
|
-
)
|
|
246
|
-
|
|
247
|
-
def with_parent(
|
|
248
|
-
self, parent_field: str, parent_value: Any
|
|
249
|
-
) -> MsSqlTableBuilder[ItemT]:
|
|
250
|
-
assert self.fields is not None, "Set fields first."
|
|
251
|
-
if parent_field not in [field.name for field in self.fields]:
|
|
252
|
-
raise ValueError("Missing fields in the table.")
|
|
253
|
-
|
|
254
|
-
return MsSqlTableBuilder[ItemT](
|
|
255
|
-
self.username,
|
|
256
|
-
self.schema,
|
|
257
|
-
self.table,
|
|
258
|
-
self.formatter,
|
|
259
|
-
self.fields,
|
|
260
|
-
self.ordering,
|
|
261
|
-
parent_field,
|
|
262
|
-
parent_value,
|
|
197
|
+
field_list,
|
|
263
198
|
)
|
|
264
199
|
|
|
265
200
|
def build(self) -> SqlTable[ItemT]:
|
|
@@ -267,50 +202,38 @@ class MsSqlTableBuilder(Generic[ItemT]):
|
|
|
267
202
|
raise ValueError("Cannot build sql table.")
|
|
268
203
|
|
|
269
204
|
return DefaultSqlTable(
|
|
270
|
-
self.username,
|
|
271
205
|
self.schema,
|
|
272
206
|
self.table,
|
|
273
207
|
self.formatter,
|
|
274
208
|
self.fields,
|
|
275
|
-
self.
|
|
276
|
-
self.parent_field,
|
|
277
|
-
self.parent_value,
|
|
209
|
+
self.username,
|
|
278
210
|
)
|
|
279
211
|
|
|
280
212
|
|
|
281
213
|
@dataclass(frozen=True)
|
|
282
214
|
class DefaultSqlTable(SqlTable[ItemT]):
|
|
283
|
-
username: str | None
|
|
284
215
|
schema: str
|
|
285
216
|
table: str
|
|
286
217
|
formatter: Formatter[dict[str, Any], ItemT]
|
|
287
218
|
fields: list[MsSqlField]
|
|
288
|
-
|
|
289
|
-
parent_key: str | None
|
|
290
|
-
parent_value: Any | None
|
|
219
|
+
username: str | None = None
|
|
291
220
|
|
|
292
221
|
def count_all(self) -> DatabaseCommand:
|
|
293
|
-
where_statement = ""
|
|
294
|
-
if self.parent_key is not None:
|
|
295
|
-
where_statement += (
|
|
296
|
-
"WHERE [" + self.parent_key + "] = " + self._parent_value_sql
|
|
297
|
-
)
|
|
298
|
-
|
|
299
222
|
return DatabaseCommand(f"""
|
|
300
223
|
{self._user_check}
|
|
301
224
|
SELECT count(*) AS n_items
|
|
302
225
|
FROM [{self.schema}].[{self.table}]
|
|
303
|
-
{
|
|
226
|
+
{self._where_statement(include_id=False)}
|
|
304
227
|
REVERT
|
|
305
|
-
""")
|
|
228
|
+
""").with_data(self._data_with_fixed({}))
|
|
306
229
|
|
|
307
230
|
def insert(self, item: ItemT) -> DatabaseCommand:
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
231
|
+
columns = ", ".join(
|
|
232
|
+
["[" + field.name + "]" for field in self.fields if field.include_in_insert]
|
|
233
|
+
)
|
|
234
|
+
placeholders = ", ".join(
|
|
235
|
+
[f"%({key.name})s" for key in self.fields if key.include_in_insert]
|
|
236
|
+
)
|
|
314
237
|
output = ", ".join(["INSERTED." + field.name for field in self.fields])
|
|
315
238
|
|
|
316
239
|
return DatabaseCommand(f"""
|
|
@@ -323,17 +246,9 @@ class DefaultSqlTable(SqlTable[ItemT]):
|
|
|
323
246
|
{placeholders}
|
|
324
247
|
)
|
|
325
248
|
REVERT
|
|
326
|
-
""").with_data(
|
|
249
|
+
""").with_data(self._data_with_fixed(self.formatter.dump(item)))
|
|
327
250
|
|
|
328
251
|
def select(self, item_id: str) -> DatabaseCommand:
|
|
329
|
-
raw: dict[str, Any] = {self._id: item_id}
|
|
330
|
-
where_statement = f"WHERE [{self._id}] = %({self._id})s"
|
|
331
|
-
if self.parent_key is not None:
|
|
332
|
-
raw[self.parent_key] = self.parent_value
|
|
333
|
-
where_statement += (
|
|
334
|
-
" AND [" + self.parent_key + "] = %(" + self.parent_key + ")s"
|
|
335
|
-
)
|
|
336
|
-
|
|
337
252
|
columns = ", ".join(["[" + field.name + "]" for field in self.fields])
|
|
338
253
|
|
|
339
254
|
return DatabaseCommand(f"""
|
|
@@ -341,44 +256,29 @@ class DefaultSqlTable(SqlTable[ItemT]):
|
|
|
341
256
|
SELECT
|
|
342
257
|
{columns}
|
|
343
258
|
FROM [{self.schema}].[{self.table}]
|
|
344
|
-
{
|
|
259
|
+
{self._where_statement(include_id=True)}
|
|
345
260
|
REVERT
|
|
346
|
-
""").with_data(
|
|
261
|
+
""").with_data(self._data_with_fixed({self._id: item_id}))
|
|
347
262
|
|
|
348
263
|
def select_all(self) -> DatabaseCommand:
|
|
349
264
|
columns = ", ".join(["[" + field.name + "]" for field in self.fields])
|
|
350
|
-
where_statement = ""
|
|
351
|
-
if self.parent_key is not None:
|
|
352
|
-
where_statement += (
|
|
353
|
-
"WHERE [" + self.parent_key + "] = " + self._parent_value_sql
|
|
354
|
-
)
|
|
355
265
|
|
|
356
266
|
return DatabaseCommand(f"""
|
|
357
267
|
{self._user_check}
|
|
358
268
|
SELECT
|
|
359
269
|
{columns}
|
|
360
270
|
FROM [{self.schema}].[{self.table}]
|
|
361
|
-
{
|
|
271
|
+
{self._where_statement(include_id=False)}
|
|
362
272
|
{self._order}
|
|
363
273
|
REVERT
|
|
364
|
-
""")
|
|
274
|
+
""").with_data(self._data_with_fixed({}))
|
|
365
275
|
|
|
366
276
|
def update(self, item: ItemT) -> DatabaseCommand:
|
|
367
|
-
dumped = self.formatter.dump(item)
|
|
368
|
-
if self.parent_key is not None:
|
|
369
|
-
dumped[self.parent_key] = self.parent_value
|
|
370
|
-
|
|
371
|
-
where_statement = f"WHERE [{self._id}] = %({self._id})s"
|
|
372
|
-
if self.parent_key is not None:
|
|
373
|
-
where_statement += (
|
|
374
|
-
" AND [" + self.parent_key + "] = %(" + self.parent_key + ")s"
|
|
375
|
-
)
|
|
376
|
-
|
|
377
277
|
updates = ", ".join(
|
|
378
278
|
[
|
|
379
279
|
f"{field.name} = %({field.name})s"
|
|
380
280
|
for field in self.fields
|
|
381
|
-
if not field.is_id and field.
|
|
281
|
+
if not field.is_id and not field.is_parent
|
|
382
282
|
]
|
|
383
283
|
)
|
|
384
284
|
|
|
@@ -387,41 +287,27 @@ class DefaultSqlTable(SqlTable[ItemT]):
|
|
|
387
287
|
UPDATE [{self.schema}].[{self.table}]
|
|
388
288
|
SET
|
|
389
289
|
{updates}
|
|
390
|
-
{
|
|
290
|
+
{self._where_statement(include_id=True)}
|
|
391
291
|
REVERT
|
|
392
|
-
""").with_data(
|
|
292
|
+
""").with_data(self._data_with_fixed(self.formatter.dump(item)))
|
|
393
293
|
|
|
394
294
|
def delete(self, item_id: str) -> DatabaseCommand:
|
|
395
|
-
raw: dict[str, Any] = {self._id: item_id}
|
|
396
|
-
where_statement = f"WHERE [{self._id}] = %({self._id})s"
|
|
397
|
-
if self.parent_key is not None:
|
|
398
|
-
raw[self.parent_key] = self.parent_value
|
|
399
|
-
where_statement += (
|
|
400
|
-
" AND [" + self.parent_key + "] = %(" + self.parent_key + ")s"
|
|
401
|
-
)
|
|
402
|
-
|
|
403
295
|
return DatabaseCommand(f"""
|
|
404
296
|
{self._user_check}
|
|
405
297
|
DELETE
|
|
406
298
|
FROM [{self.schema}].[{self.table}]
|
|
407
|
-
{
|
|
299
|
+
{self._where_statement(include_id=True)}
|
|
408
300
|
REVERT
|
|
409
|
-
""").with_data(
|
|
301
|
+
""").with_data(self._data_with_fixed({self._id: item_id}))
|
|
410
302
|
|
|
411
303
|
def delete_all(self) -> DatabaseCommand:
|
|
412
|
-
where_statement = ""
|
|
413
|
-
if self.parent_key is not None:
|
|
414
|
-
where_statement += (
|
|
415
|
-
"WHERE [" + self.parent_key + "] = " + self._parent_value_sql
|
|
416
|
-
)
|
|
417
|
-
|
|
418
304
|
return DatabaseCommand(f"""
|
|
419
305
|
{self._user_check}
|
|
420
306
|
DELETE
|
|
421
307
|
FROM [{self.schema}].[{self.table}]
|
|
422
|
-
{
|
|
308
|
+
{self._where_statement(include_id=False)}
|
|
423
309
|
REVERT
|
|
424
|
-
""")
|
|
310
|
+
""").with_data(self._data_with_fixed({}))
|
|
425
311
|
|
|
426
312
|
def load(self, data: dict[str, Any]) -> ItemT:
|
|
427
313
|
return self.formatter.load(data)
|
|
@@ -432,6 +318,22 @@ class DefaultSqlTable(SqlTable[ItemT]):
|
|
|
432
318
|
lambda i: f"{self._id}<{raw[self._id]}>"
|
|
433
319
|
)
|
|
434
320
|
|
|
321
|
+
def _where_statement(self, include_id: bool = False) -> str:
|
|
322
|
+
result = next((field for field in self.fields if field.is_parent), None)
|
|
323
|
+
if result is None:
|
|
324
|
+
return f"WHERE [{self._id}] = %({self._id})s" if include_id else ""
|
|
325
|
+
else:
|
|
326
|
+
statement = "WHERE [" + result.name + "] = %(" + result.name + ")s"
|
|
327
|
+
if include_id:
|
|
328
|
+
statement += f" AND [{self._id}] = %({self._id})s"
|
|
329
|
+
return statement
|
|
330
|
+
|
|
331
|
+
def _data_with_fixed(self, data: dict[str, Any]) -> dict[str, Any]:
|
|
332
|
+
for field in self.fields:
|
|
333
|
+
if field.is_parent or field.is_fixed:
|
|
334
|
+
data[field.name] = field.fixed_value
|
|
335
|
+
return data
|
|
336
|
+
|
|
435
337
|
@property
|
|
436
338
|
def _id(self) -> str:
|
|
437
339
|
result = next((field for field in self.fields if field.is_id), None)
|
|
@@ -448,20 +350,21 @@ class DefaultSqlTable(SqlTable[ItemT]):
|
|
|
448
350
|
|
|
449
351
|
@property
|
|
450
352
|
def _order(self) -> str:
|
|
451
|
-
|
|
452
|
-
|
|
353
|
+
ordering = [field.name for field in self.fields if field.is_ordered]
|
|
354
|
+
if len(ordering) > 0:
|
|
355
|
+
return "ORDER BY " + ", ".join(ordering)
|
|
453
356
|
else:
|
|
454
357
|
return ""
|
|
455
358
|
|
|
456
|
-
@property
|
|
457
|
-
def _parent_value_sql(self) -> str:
|
|
458
|
-
if isinstance(self.parent_value, str):
|
|
459
|
-
return "'" + self.parent_value + "'"
|
|
460
|
-
else:
|
|
461
|
-
return str(self.parent_value)
|
|
462
|
-
|
|
463
359
|
|
|
464
360
|
@dataclass(frozen=True)
|
|
465
361
|
class MsSqlField:
|
|
466
362
|
name: str
|
|
467
|
-
is_id: bool
|
|
363
|
+
is_id: bool = False
|
|
364
|
+
is_ordered: bool = False
|
|
365
|
+
include_in_insert: bool = True
|
|
366
|
+
|
|
367
|
+
is_parent: bool = False
|
|
368
|
+
|
|
369
|
+
is_fixed: bool = False
|
|
370
|
+
fixed_value: Any | None = None
|
|
@@ -103,91 +103,35 @@ class SqliteTableBuilder(Generic[ItemT]):
|
|
|
103
103
|
table_name: str | None = None
|
|
104
104
|
formatter: Formatter[dict[str, Any], ItemT] | None = None
|
|
105
105
|
fields: list[SqliteField] | None = None
|
|
106
|
-
parent_field: str | None = None
|
|
107
|
-
parent_value: Any | None = None
|
|
108
106
|
|
|
109
107
|
def with_name(self, value: str) -> SqliteTableBuilder[ItemT]:
|
|
110
|
-
return SqliteTableBuilder[ItemT](
|
|
111
|
-
value, self.formatter, self.fields, self.parent_field, self.parent_value
|
|
112
|
-
)
|
|
108
|
+
return SqliteTableBuilder[ItemT](value, self.formatter, self.fields)
|
|
113
109
|
|
|
114
110
|
def with_formatter(
|
|
115
111
|
self, value: Formatter[dict[str, Any], ItemT]
|
|
116
112
|
) -> SqliteTableBuilder[ItemT]:
|
|
117
|
-
return SqliteTableBuilder[ItemT](
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
[SqliteField(field, field == "id", False) for field in list(fields)],
|
|
126
|
-
self.parent_field,
|
|
127
|
-
self.parent_value,
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
def with_id(self, identifier: str) -> SqliteTableBuilder[ItemT]:
|
|
131
|
-
assert self.fields is not None, "Set fields first."
|
|
132
|
-
if identifier not in [field.name for field in self.fields]:
|
|
133
|
-
raise ValueError("Missing fields in the table.")
|
|
134
|
-
|
|
135
|
-
return SqliteTableBuilder[ItemT](
|
|
136
|
-
self.table_name,
|
|
137
|
-
self.formatter,
|
|
138
|
-
[
|
|
139
|
-
SqliteField(field.name, field.name == identifier, field.is_composite)
|
|
140
|
-
for field in self.fields
|
|
141
|
-
],
|
|
142
|
-
self.parent_field,
|
|
143
|
-
self.parent_value,
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
def with_composite_key(
|
|
147
|
-
self, composites: Iterable[str]
|
|
148
|
-
) -> SqliteTableBuilder[ItemT]:
|
|
149
|
-
assert self.fields is not None, "Set fields first."
|
|
150
|
-
|
|
151
|
-
names = [field.name for field in self.fields]
|
|
152
|
-
if not all(field in names for field in list(composites)):
|
|
153
|
-
raise ValueError("Missing fields in the table.")
|
|
154
|
-
|
|
155
|
-
return SqliteTableBuilder[ItemT](
|
|
156
|
-
self.table_name,
|
|
157
|
-
self.formatter,
|
|
158
|
-
[
|
|
159
|
-
SqliteField(field.name, field.is_id, field.name in list(composites))
|
|
160
|
-
for field in self.fields
|
|
161
|
-
],
|
|
162
|
-
self.parent_field,
|
|
163
|
-
self.parent_value,
|
|
164
|
-
)
|
|
165
|
-
|
|
166
|
-
def with_parent(
|
|
167
|
-
self, parent_field: str, parent_value: Any
|
|
168
|
-
) -> SqliteTableBuilder[ItemT]:
|
|
169
|
-
assert self.fields is not None, "Set fields first."
|
|
170
|
-
if parent_field not in [field.name for field in self.fields]:
|
|
171
|
-
raise ValueError("Missing fields in the table.")
|
|
172
|
-
|
|
113
|
+
return SqliteTableBuilder[ItemT](self.table_name, value, self.fields)
|
|
114
|
+
|
|
115
|
+
def with_fields(self, value: Iterable[SqliteField]) -> SqliteTableBuilder[ItemT]:
|
|
116
|
+
field_list = list(value)
|
|
117
|
+
if len([field for field in field_list if field.is_id]) != 1:
|
|
118
|
+
raise ValueError("Pass only one identifier field.")
|
|
119
|
+
if len([field for field in field_list if field.is_parent]) > 1:
|
|
120
|
+
raise ValueError("Pass only one parent field.")
|
|
173
121
|
return SqliteTableBuilder[ItemT](
|
|
174
122
|
self.table_name,
|
|
175
123
|
self.formatter,
|
|
176
|
-
|
|
177
|
-
parent_field,
|
|
178
|
-
parent_value,
|
|
124
|
+
field_list,
|
|
179
125
|
)
|
|
180
126
|
|
|
181
127
|
def build(self) -> SqlTable[ItemT]:
|
|
182
128
|
if not self.table_name or not self.formatter or not self.fields:
|
|
183
|
-
raise ValueError("
|
|
129
|
+
raise ValueError("Parameter missing.")
|
|
184
130
|
|
|
185
131
|
return _DefaultSqlTable(
|
|
186
132
|
self.table_name,
|
|
187
133
|
self.formatter,
|
|
188
134
|
self.fields,
|
|
189
|
-
self.parent_field,
|
|
190
|
-
self.parent_value,
|
|
191
135
|
)
|
|
192
136
|
|
|
193
137
|
|
|
@@ -196,54 +140,41 @@ class _DefaultSqlTable(SqlTable[ItemT]):
|
|
|
196
140
|
table_name: str
|
|
197
141
|
formatter: Formatter[dict[str, Any], ItemT]
|
|
198
142
|
fields: list[SqliteField]
|
|
199
|
-
parent_key: str | None
|
|
200
|
-
parent_value: Any | None
|
|
201
143
|
|
|
202
144
|
def count_all(self) -> DatabaseCommand:
|
|
203
|
-
where_statement = ""
|
|
204
|
-
if self.parent_key is not None:
|
|
205
|
-
where_statement += (
|
|
206
|
-
"WHERE " + self.parent_key + " = " + self._parent_value_sql
|
|
207
|
-
)
|
|
208
|
-
|
|
209
145
|
return DatabaseCommand(f"""
|
|
210
146
|
SELECT count(*) as n_items
|
|
211
|
-
FROM {self.table_name.
|
|
212
|
-
{
|
|
213
|
-
""")
|
|
147
|
+
FROM {self.table_name.upper()}
|
|
148
|
+
{self._where_statement(include_id=False)};
|
|
149
|
+
""").with_data(self._data_with_fixed({}))
|
|
214
150
|
|
|
215
151
|
def insert(self, item: ItemT) -> DatabaseCommand:
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
152
|
+
insert_columns = ", ".join(
|
|
153
|
+
[field.name for field in self.fields if field.include_in_insert]
|
|
154
|
+
)
|
|
155
|
+
return_columns = ", ".join([field.name for field in self.fields])
|
|
156
|
+
placeholders = ", ".join(
|
|
157
|
+
[f":{key.name}" for key in self.fields if key.include_in_insert]
|
|
158
|
+
)
|
|
222
159
|
|
|
223
160
|
return DatabaseCommand(f"""
|
|
224
|
-
INSERT INTO {self.table_name.
|
|
225
|
-
{
|
|
161
|
+
INSERT INTO {self.table_name.upper()} (
|
|
162
|
+
{insert_columns}
|
|
226
163
|
) VALUES (
|
|
227
164
|
{placeholders}
|
|
228
165
|
)
|
|
229
|
-
RETURNING {
|
|
230
|
-
""").with_data(
|
|
166
|
+
RETURNING {return_columns};
|
|
167
|
+
""").with_data(self._data_with_fixed(self.formatter.dump(item)))
|
|
231
168
|
|
|
232
169
|
def select(self, item_id: str) -> DatabaseCommand:
|
|
233
|
-
raw: dict[str, Any] = {self._id: item_id}
|
|
234
|
-
where_statement = f"WHERE {self._id} = :{self._id}"
|
|
235
|
-
if self.parent_key is not None:
|
|
236
|
-
raw[self.parent_key] = self.parent_value
|
|
237
|
-
where_statement += " AND " + self.parent_key + " = :" + self.parent_key
|
|
238
|
-
|
|
239
170
|
columns = ", ".join([field.name for field in self.fields])
|
|
240
171
|
|
|
241
172
|
return DatabaseCommand(f"""
|
|
242
173
|
SELECT
|
|
243
174
|
{columns}
|
|
244
|
-
FROM {self.table_name.
|
|
245
|
-
{
|
|
246
|
-
""").with_data(
|
|
175
|
+
FROM {self.table_name.upper()}
|
|
176
|
+
{self._where_statement(include_id=True)};
|
|
177
|
+
""").with_data(self._data_with_fixed({self._id: item_id}))
|
|
247
178
|
|
|
248
179
|
def select_duplicate(self, item: ItemT) -> DatabaseCommand:
|
|
249
180
|
raw = self.formatter.dump(item)
|
|
@@ -254,75 +185,49 @@ class _DefaultSqlTable(SqlTable[ItemT]):
|
|
|
254
185
|
return DatabaseCommand(f"""
|
|
255
186
|
SELECT
|
|
256
187
|
{columns}
|
|
257
|
-
FROM {self.table_name.
|
|
188
|
+
FROM {self.table_name.upper()}
|
|
258
189
|
WHERE {duplicates};
|
|
259
190
|
""").with_data({key: raw[key] for key in raw if key in self._composite})
|
|
260
191
|
|
|
261
192
|
def select_all(self) -> DatabaseCommand:
|
|
262
|
-
where_statement = ""
|
|
263
|
-
if self.parent_key is not None:
|
|
264
|
-
where_statement += (
|
|
265
|
-
"WHERE " + self.parent_key + " = " + self._parent_value_sql
|
|
266
|
-
)
|
|
267
|
-
|
|
268
193
|
columns = ", ".join([field.name for field in self.fields])
|
|
269
194
|
|
|
270
195
|
return DatabaseCommand(f"""
|
|
271
196
|
SELECT
|
|
272
197
|
{columns}
|
|
273
198
|
FROM {self.table_name.capitalize()}
|
|
274
|
-
{
|
|
275
|
-
""")
|
|
199
|
+
{self._where_statement(include_id=False)};
|
|
200
|
+
""").with_data(self._data_with_fixed({}))
|
|
276
201
|
|
|
277
202
|
def update(self, item: ItemT) -> DatabaseCommand:
|
|
278
|
-
dumped = self.formatter.dump(item)
|
|
279
|
-
if self.parent_key is not None:
|
|
280
|
-
dumped[self.parent_key] = self.parent_value
|
|
281
|
-
|
|
282
|
-
where_statement = f"WHERE {self._id} = :{self._id}"
|
|
283
|
-
if self.parent_key is not None:
|
|
284
|
-
where_statement += " AND " + self.parent_key + " = :" + self.parent_key
|
|
285
|
-
|
|
286
203
|
updates = ", ".join(
|
|
287
204
|
[
|
|
288
205
|
f"{field.name} = :{field.name}"
|
|
289
206
|
for field in self.fields
|
|
290
|
-
if not field.is_id and field.
|
|
207
|
+
if not field.is_id and not field.is_parent
|
|
291
208
|
]
|
|
292
209
|
)
|
|
293
210
|
|
|
294
211
|
return DatabaseCommand(f"""
|
|
295
|
-
UPDATE {self.table_name.
|
|
212
|
+
UPDATE {self.table_name.upper()}
|
|
296
213
|
SET
|
|
297
214
|
{updates}
|
|
298
|
-
{
|
|
299
|
-
""").with_data(
|
|
215
|
+
{self._where_statement(include_id=True)};
|
|
216
|
+
""").with_data(self._data_with_fixed(self.formatter.dump(item)))
|
|
300
217
|
|
|
301
218
|
def delete(self, item_id: str) -> DatabaseCommand:
|
|
302
|
-
raw: dict[str, Any] = {self._id: item_id}
|
|
303
|
-
where_statement = f"WHERE {self._id} = :{self._id}"
|
|
304
|
-
if self.parent_key is not None:
|
|
305
|
-
raw[self.parent_key] = self.parent_value
|
|
306
|
-
where_statement += " AND " + self.parent_key + " = :" + self.parent_key
|
|
307
|
-
|
|
308
219
|
return DatabaseCommand(f"""
|
|
309
220
|
DELETE
|
|
310
|
-
FROM {self.table_name.
|
|
311
|
-
{
|
|
312
|
-
""").with_data(
|
|
221
|
+
FROM {self.table_name.upper()}
|
|
222
|
+
{self._where_statement(include_id=True)};
|
|
223
|
+
""").with_data(self._data_with_fixed({self._id: item_id}))
|
|
313
224
|
|
|
314
225
|
def delete_all(self) -> DatabaseCommand:
|
|
315
|
-
where_statement = ""
|
|
316
|
-
if self.parent_key is not None:
|
|
317
|
-
where_statement += (
|
|
318
|
-
"WHERE " + self.parent_key + " = " + self._parent_value_sql
|
|
319
|
-
)
|
|
320
|
-
|
|
321
226
|
return DatabaseCommand(f"""
|
|
322
227
|
DELETE
|
|
323
|
-
FROM {self.table_name.
|
|
324
|
-
{
|
|
325
|
-
""")
|
|
228
|
+
FROM {self.table_name.upper()}
|
|
229
|
+
{self._where_statement(include_id=False)};
|
|
230
|
+
""").with_data(self._data_with_fixed({}))
|
|
326
231
|
|
|
327
232
|
def load(self, data: dict[str, Any]) -> ItemT:
|
|
328
233
|
return self.formatter.load(data)
|
|
@@ -335,6 +240,22 @@ class _DefaultSqlTable(SqlTable[ItemT]):
|
|
|
335
240
|
)
|
|
336
241
|
)
|
|
337
242
|
|
|
243
|
+
def _where_statement(self, include_id: bool = False) -> str:
|
|
244
|
+
result = next((field for field in self.fields if field.is_parent), None)
|
|
245
|
+
if result is None:
|
|
246
|
+
return f"WHERE {self._id} = :{self._id}" if include_id else ""
|
|
247
|
+
else:
|
|
248
|
+
statement = "WHERE " + result.name + " = :" + result.name
|
|
249
|
+
if include_id:
|
|
250
|
+
statement += f" AND {self._id} = :{self._id}"
|
|
251
|
+
return statement
|
|
252
|
+
|
|
253
|
+
def _data_with_fixed(self, data: dict[str, Any]) -> dict[str, Any]:
|
|
254
|
+
for field in self.fields:
|
|
255
|
+
if field.is_parent or field.is_fixed:
|
|
256
|
+
data[field.name] = field.fixed_value
|
|
257
|
+
return data
|
|
258
|
+
|
|
338
259
|
@property
|
|
339
260
|
def _id(self) -> str:
|
|
340
261
|
result = next((field for field in self.fields if field.is_id), None)
|
|
@@ -347,16 +268,15 @@ class _DefaultSqlTable(SqlTable[ItemT]):
|
|
|
347
268
|
names = [field.name for field in self.fields if field.is_composite]
|
|
348
269
|
return [self._id] if len(names) == 0 else names
|
|
349
270
|
|
|
350
|
-
@property
|
|
351
|
-
def _parent_value_sql(self) -> str:
|
|
352
|
-
if isinstance(self.parent_value, str):
|
|
353
|
-
return "'" + self.parent_value + "'"
|
|
354
|
-
else:
|
|
355
|
-
return str(self.parent_value)
|
|
356
|
-
|
|
357
271
|
|
|
358
272
|
@dataclass(frozen=True)
|
|
359
273
|
class SqliteField:
|
|
360
274
|
name: str
|
|
361
|
-
is_id: bool
|
|
362
|
-
is_composite: bool
|
|
275
|
+
is_id: bool = False
|
|
276
|
+
is_composite: bool = False
|
|
277
|
+
include_in_insert: bool = True
|
|
278
|
+
|
|
279
|
+
is_parent: bool = False
|
|
280
|
+
|
|
281
|
+
is_fixed: bool = False
|
|
282
|
+
fixed_value: Any | None = None
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|