postgresdb3 0.6.0__tar.gz → 0.7.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.
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/PKG-INFO +1 -1
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/postgresdb3/core/async_db.py +116 -179
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/postgresdb3/core/sync_db.py +114 -227
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/postgresdb3/orm/fields/__init__.py +1 -1
- postgresdb3-0.7.0/postgresdb3/orm/fields/foreign.py +31 -0
- postgresdb3-0.7.0/postgresdb3/orm/meta.py +61 -0
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/postgresdb3/orm/models.py +45 -19
- postgresdb3-0.7.0/postgresdb3/orm/query.py +473 -0
- postgresdb3-0.7.0/postgresdb3/orm/relations.py +44 -0
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/postgresdb3.egg-info/PKG-INFO +1 -1
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/postgresdb3.egg-info/SOURCES.txt +2 -1
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/setup.py +1 -1
- postgresdb3-0.6.0/postgresdb3/orm/fields/relations.py +0 -16
- postgresdb3-0.6.0/postgresdb3/orm/meta.py +0 -41
- postgresdb3-0.6.0/postgresdb3/orm/query.py +0 -283
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/README.md +0 -0
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/postgresdb3/__init__.py +0 -0
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/postgresdb3/core/__init__.py +0 -0
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/postgresdb3/orm/__init__.py +0 -0
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/postgresdb3/orm/base.py +0 -0
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/postgresdb3/orm/fields/base.py +0 -0
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/postgresdb3/orm/fields/datetime.py +0 -0
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/postgresdb3/orm/fields/misc.py +0 -0
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/postgresdb3/orm/fields/numeric.py +0 -0
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/postgresdb3/orm/fields/text.py +0 -0
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/postgresdb3.egg-info/dependency_links.txt +0 -0
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/postgresdb3.egg-info/requires.txt +0 -0
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/postgresdb3.egg-info/top_level.txt +0 -0
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/pyproject.toml +0 -0
- {postgresdb3-0.6.0 → postgresdb3-0.7.0}/setup.cfg +0 -0
|
@@ -3,25 +3,7 @@ from typing import Any, List, Optional
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class AsyncPostgresDB:
|
|
6
|
-
"""
|
|
7
|
-
Async PostgreSQL helper class for CRUD operations and schema management.
|
|
8
|
-
|
|
9
|
-
Ushbu class `asyncpg` kutubxonasidan foydalanib,
|
|
10
|
-
PostgreSQL bilan asynchronous CRUD va schema operatsiyalarini bajaradi.
|
|
11
|
-
Aiogram kabi async frameworklar bilan to‘g‘ridan-to‘g‘ri ishlash uchun mos.
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
6
|
def __init__(self, database: str, user: str, password: str, host: str = "localhost", port: int = 5432) -> None:
|
|
15
|
-
"""
|
|
16
|
-
PostgreSQL bazasiga ulanishni tayyorlaydi.
|
|
17
|
-
|
|
18
|
-
Args:
|
|
19
|
-
database (str): Bazaning nomi.
|
|
20
|
-
user (str): Foydalanuvchi nomi.
|
|
21
|
-
password (str): Parol.
|
|
22
|
-
host (str): Server manzili (default: "localhost").
|
|
23
|
-
port (int): Port (default: 5432).
|
|
24
|
-
"""
|
|
25
7
|
self.database = database
|
|
26
8
|
self.user = user
|
|
27
9
|
self.password = password
|
|
@@ -30,21 +12,6 @@ class AsyncPostgresDB:
|
|
|
30
12
|
self.pool: Optional[asyncpg.pool.Pool] = None
|
|
31
13
|
|
|
32
14
|
async def _manager(self, sql: str, *params, fetchone=False, fetchall=False, commit=False) -> Any:
|
|
33
|
-
"""
|
|
34
|
-
Markaziy metod: barcha SQL so‘rovlarni bajaradi.
|
|
35
|
-
|
|
36
|
-
Args:
|
|
37
|
-
sql (str): Bajariladigan SQL so‘rov.
|
|
38
|
-
*params: SQL parametrlarini berish.
|
|
39
|
-
fetchone (bool): True bo‘lsa, faqat bitta qator qaytaradi.
|
|
40
|
-
fetchall (bool): True bo‘lsa, barcha natijalarni qaytaradi.
|
|
41
|
-
commit (bool): True bo‘lsa, tranzaksiya commit qilinadi.
|
|
42
|
-
|
|
43
|
-
Returns:
|
|
44
|
-
fetchone=True bo‘lsa: asyncpg.Record
|
|
45
|
-
fetchall=True bo‘lsa: list[asyncpg.Record]
|
|
46
|
-
commit=True bo‘lsa: None
|
|
47
|
-
"""
|
|
48
15
|
if not self.pool:
|
|
49
16
|
self.pool = await asyncpg.create_pool(
|
|
50
17
|
database=self.database,
|
|
@@ -56,39 +23,21 @@ class AsyncPostgresDB:
|
|
|
56
23
|
|
|
57
24
|
async with self.pool.acquire() as conn:
|
|
58
25
|
if commit:
|
|
59
|
-
await conn.execute(sql, *params)
|
|
60
|
-
return
|
|
26
|
+
return await conn.execute(sql, *params)
|
|
61
27
|
if fetchone:
|
|
62
28
|
return await conn.fetchrow(sql, *params)
|
|
63
29
|
if fetchall:
|
|
64
30
|
return await conn.fetch(sql, *params)
|
|
65
31
|
|
|
66
32
|
async def close_pool(self) -> None:
|
|
67
|
-
"""
|
|
68
|
-
Connection poolni yopadi.
|
|
69
|
-
"""
|
|
70
33
|
if self.pool:
|
|
71
34
|
await self.pool.close()
|
|
72
35
|
self.pool = None
|
|
73
36
|
|
|
74
37
|
async def create(self, table: str, columns: str) -> None:
|
|
75
|
-
"""
|
|
76
|
-
Jadval yaratadi (agar mavjud bo‘lsa o‘tkazib yuboradi).
|
|
77
|
-
|
|
78
|
-
Args:
|
|
79
|
-
table (str): Jadval nomi.
|
|
80
|
-
columns (str): Ustunlar va turlari, misol: "id SERIAL PRIMARY KEY, name TEXT".
|
|
81
|
-
"""
|
|
82
38
|
await self._manager(f"CREATE TABLE IF NOT EXISTS {table} ({columns})", commit=True)
|
|
83
39
|
|
|
84
40
|
async def drop(self, table: str, cascade: bool = False) -> None:
|
|
85
|
-
"""
|
|
86
|
-
Jadvalni o‘chiradi (agar mavjud bo‘lsa).
|
|
87
|
-
|
|
88
|
-
Args:
|
|
89
|
-
table (str): Jadval nomi.
|
|
90
|
-
cascade (bool): Agar True bo‘lsa, jadval bilan bog‘liq barcha obyektlar ham o‘chiradi. Default: True
|
|
91
|
-
"""
|
|
92
41
|
sql = f"DROP TABLE IF EXISTS {table}"
|
|
93
42
|
if cascade:
|
|
94
43
|
sql += " CASCADE"
|
|
@@ -96,10 +45,6 @@ class AsyncPostgresDB:
|
|
|
96
45
|
await self._manager(sql, commit=True)
|
|
97
46
|
|
|
98
47
|
def _validate_identifier(self, value: str, name: str = "identifier") -> str:
|
|
99
|
-
"""
|
|
100
|
-
Jadval yoki ustun nomi uchun minimal tekshiruv.
|
|
101
|
-
Faqat harf, raqam, underscore va nuqtaga ruxsat beradi.
|
|
102
|
-
"""
|
|
103
48
|
if not isinstance(value, str) or not value.strip():
|
|
104
49
|
raise ValueError(f"{name} bo'sh bo'lmasligi kerak")
|
|
105
50
|
|
|
@@ -110,11 +55,6 @@ class AsyncPostgresDB:
|
|
|
110
55
|
return value
|
|
111
56
|
|
|
112
57
|
def _normalize_columns(self, columns: str | list[str]) -> str:
|
|
113
|
-
"""
|
|
114
|
-
columns list bo'lsa stringga aylantiradi.
|
|
115
|
-
list bo'lsa har bir column validate qilinadi.
|
|
116
|
-
str bo'lsa SQL expression bo'lishi mumkinligi uchun o'z holicha qaytariladi.
|
|
117
|
-
"""
|
|
118
58
|
if isinstance(columns, list):
|
|
119
59
|
if not columns:
|
|
120
60
|
raise ValueError("columns bo'sh list bo'lmasligi kerak")
|
|
@@ -128,28 +68,6 @@ class AsyncPostgresDB:
|
|
|
128
68
|
return columns
|
|
129
69
|
|
|
130
70
|
def _build_where(self, where: Any, start_index: int = 1) -> tuple[str, list]:
|
|
131
|
-
"""
|
|
132
|
-
Qo'llab-quvvatlanadi:
|
|
133
|
-
|
|
134
|
-
1) tuple:
|
|
135
|
-
("age > $1", [18])
|
|
136
|
-
|
|
137
|
-
2) dict:
|
|
138
|
-
{
|
|
139
|
-
"age__gt": 18,
|
|
140
|
-
"name__ilike": "%ali%",
|
|
141
|
-
"status": "active",
|
|
142
|
-
"id__in": [1, 2, 3],
|
|
143
|
-
"deleted_at__isnull": True
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
3) list[tuple]:
|
|
147
|
-
[
|
|
148
|
-
("age", ">", 18),
|
|
149
|
-
("name", "ILIKE", "%ali%"),
|
|
150
|
-
("status", "=", "active")
|
|
151
|
-
]
|
|
152
|
-
"""
|
|
153
71
|
if where is None:
|
|
154
72
|
return "", []
|
|
155
73
|
|
|
@@ -268,26 +186,6 @@ class AsyncPostgresDB:
|
|
|
268
186
|
offset: Optional[int] = None,
|
|
269
187
|
fetchone: bool = False
|
|
270
188
|
) -> Any:
|
|
271
|
-
"""
|
|
272
|
-
Jadvaldan ma'lumotlarni tanlash.
|
|
273
|
-
|
|
274
|
-
Args:
|
|
275
|
-
table (str): Asosiy jadval nomi.
|
|
276
|
-
columns (str | list[str]): Tanlanadigan ustunlar.
|
|
277
|
-
where:
|
|
278
|
-
tuple — ("age > $1", [18])
|
|
279
|
-
dict — {"age__gt": 18, "name__ilike": "%ali%"}
|
|
280
|
-
list — [("age", ">", 18), ("name", "ILIKE", "%ali%")]
|
|
281
|
-
join (Optional[List[tuple]]): [("INNER JOIN", "orders", "users.id = orders.user_id")]
|
|
282
|
-
group_by (Optional[str]): GROUP BY ustuni.
|
|
283
|
-
order_by (Optional[str]): ORDER BY qoidasi.
|
|
284
|
-
limit (Optional[int]): LIMIT qiymati.
|
|
285
|
-
offset (Optional[int]): OFFSET qiymati.
|
|
286
|
-
fetchone (bool): True bo‘lsa faqat bitta qator qaytaradi.
|
|
287
|
-
|
|
288
|
-
Returns:
|
|
289
|
-
asyncpg.Record yoki list[asyncpg.Record]
|
|
290
|
-
"""
|
|
291
189
|
table = self._validate_identifier(table, "table")
|
|
292
190
|
columns = self._normalize_columns(columns)
|
|
293
191
|
|
|
@@ -321,44 +219,17 @@ class AsyncPostgresDB:
|
|
|
321
219
|
|
|
322
220
|
return await self._manager(sql, *params, fetchone=fetchone, fetchall=not fetchone)
|
|
323
221
|
|
|
324
|
-
async def insert(self, table: str, columns: str, values:
|
|
325
|
-
"""
|
|
326
|
-
Jadvalga yangi qator qo‘shadi.
|
|
327
|
-
|
|
328
|
-
Args:
|
|
329
|
-
table (str): Jadval nomi.
|
|
330
|
-
columns (str): Ustunlar nomi, misol: "name, age".
|
|
331
|
-
values (List[Any]): Qiymatlar, misol: ["Ali", 25].
|
|
332
|
-
"""
|
|
222
|
+
async def insert(self, table: str, columns: str, values: list, returning: str | None = None):
|
|
333
223
|
placeholders = ", ".join(f"${i + 1}" for i in range(len(values)))
|
|
334
224
|
sql = f"INSERT INTO {table} ({columns}) VALUES ({placeholders})"
|
|
225
|
+
|
|
226
|
+
if returning:
|
|
227
|
+
sql += f" RETURNING {returning}"
|
|
228
|
+
return await self._manager(sql, *values, fetchone=True)
|
|
229
|
+
|
|
335
230
|
await self._manager(sql, *values, commit=True)
|
|
336
231
|
|
|
337
232
|
async def insert_many(self, table: str, columns: str, values_list: List[List[Any]]) -> None:
|
|
338
|
-
"""
|
|
339
|
-
Jadvalga bir nechta qator qo‘shish (bulk insert).
|
|
340
|
-
|
|
341
|
-
Args:
|
|
342
|
-
table (str): Jadval nomi.
|
|
343
|
-
columns (str): Ustunlar nomi, misol: "name, age".
|
|
344
|
-
values_list (List[List[Any]]): Qiymatlar ro‘yxati, misol: [["Ali", 25], ["Vali", 30]].
|
|
345
|
-
|
|
346
|
-
Raises:
|
|
347
|
-
ValueError: Agar `values_list` bo‘sh bo‘lsa.
|
|
348
|
-
|
|
349
|
-
Notes:
|
|
350
|
-
- `asyncpg` kutubxonasida har bir parametr uchun unikal `$n` indekslari kerak,
|
|
351
|
-
shuning uchun har bir qator uchun ketma-ket `$1, $2, ...` ishlatiladi.
|
|
352
|
-
- Metod barcha qatorlarni bir so‘rovda qo‘shadi.
|
|
353
|
-
- `fetchmany` kerak emas, chunki bu insert operatsiyasi natija qaytarmaydi.
|
|
354
|
-
|
|
355
|
-
Example:
|
|
356
|
-
await db.insert_many(
|
|
357
|
-
"users",
|
|
358
|
-
"name, age",
|
|
359
|
-
[["Ali", 25], ["Vali", 30], ["Guli", 22]]
|
|
360
|
-
)
|
|
361
|
-
"""
|
|
362
233
|
if not values_list:
|
|
363
234
|
raise ValueError("values_list bo'sh bo'lishi mumkin emas")
|
|
364
235
|
|
|
@@ -376,41 +247,124 @@ class AsyncPostgresDB:
|
|
|
376
247
|
await self._manager(sql, *flat_values, commit=True)
|
|
377
248
|
|
|
378
249
|
async def update(self, table: str, set_column: str, set_value: Any, where_column: str, where_value: Any) -> None:
|
|
379
|
-
"""
|
|
380
|
-
Jadvaldagi qatorni yangilaydi.
|
|
381
|
-
|
|
382
|
-
Args:
|
|
383
|
-
table (str): Jadval nomi.
|
|
384
|
-
set_column (str): O‘zgartiriladigan ustun.
|
|
385
|
-
set_value (Any): Yangi qiymat.
|
|
386
|
-
where_column (str): Filtrlash ustuni.
|
|
387
|
-
where_value (Any): Filtrlash qiymati.
|
|
388
|
-
"""
|
|
389
250
|
sql = f"UPDATE {table} SET {set_column} = $1 WHERE {where_column} = $2"
|
|
390
251
|
await self._manager(sql, set_value, where_value, commit=True)
|
|
391
252
|
|
|
253
|
+
async def update_fields(self, table: str, data: dict, where_column: str, where_value: Any) -> int:
|
|
254
|
+
table = self._validate_identifier(table, "table")
|
|
255
|
+
where_column = self._validate_identifier(where_column, "where column")
|
|
256
|
+
|
|
257
|
+
if not data:
|
|
258
|
+
raise ValueError("Yangilash uchun data bo'sh bo'lmasligi kerak")
|
|
259
|
+
|
|
260
|
+
set_parts = []
|
|
261
|
+
params = []
|
|
262
|
+
index = 1
|
|
263
|
+
|
|
264
|
+
for key, value in data.items():
|
|
265
|
+
key = self._validate_identifier(key, "column")
|
|
266
|
+
set_parts.append(f"{key} = ${index}")
|
|
267
|
+
params.append(value)
|
|
268
|
+
index += 1
|
|
269
|
+
|
|
270
|
+
sql = f"UPDATE {table} SET {', '.join(set_parts)} WHERE {where_column} = ${index}"
|
|
271
|
+
params.append(where_value)
|
|
272
|
+
|
|
273
|
+
result = await self._manager(sql, *params, commit=True)
|
|
274
|
+
return int(result.split()[-1])
|
|
275
|
+
|
|
276
|
+
async def update_where(self, table: str, data: dict, where: tuple | dict | list) -> int:
|
|
277
|
+
table = self._validate_identifier(table, "table")
|
|
278
|
+
|
|
279
|
+
if not data:
|
|
280
|
+
raise ValueError("Yangilash uchun data bo'sh bo'lmasligi kerak")
|
|
281
|
+
|
|
282
|
+
if not where:
|
|
283
|
+
raise ValueError("update_where uchun where bo'sh bo'lmasligi kerak")
|
|
284
|
+
|
|
285
|
+
set_parts = []
|
|
286
|
+
params = []
|
|
287
|
+
index = 1
|
|
288
|
+
|
|
289
|
+
for key, value in data.items():
|
|
290
|
+
key = self._validate_identifier(key, "column")
|
|
291
|
+
set_parts.append(f"{key} = ${index}")
|
|
292
|
+
params.append(value)
|
|
293
|
+
index += 1
|
|
294
|
+
|
|
295
|
+
where_sql, where_params = self._build_where(where, start_index=index)
|
|
296
|
+
|
|
297
|
+
if not where_sql:
|
|
298
|
+
raise ValueError("WHERE sharti noto'g'ri")
|
|
299
|
+
|
|
300
|
+
sql = f"UPDATE {table} SET {', '.join(set_parts)} WHERE {where_sql}"
|
|
301
|
+
|
|
302
|
+
result = await self._manager(
|
|
303
|
+
sql,
|
|
304
|
+
*(params + where_params),
|
|
305
|
+
commit=True
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
return int(result.split()[-1])
|
|
309
|
+
|
|
392
310
|
async def delete(self, table: str, where_column: str, where_value: Any) -> None:
|
|
393
|
-
"""
|
|
394
|
-
Jadvaldan qator o‘chiradi.
|
|
395
|
-
|
|
396
|
-
Args:
|
|
397
|
-
table (str): Jadval nomi.
|
|
398
|
-
where_column (str): Filtrlash ustuni.
|
|
399
|
-
where_value (Any): Filtrlash qiymati.
|
|
400
|
-
"""
|
|
401
311
|
sql = f"DELETE FROM {table} WHERE {where_column} = $1"
|
|
402
312
|
await self._manager(sql, where_value, commit=True)
|
|
403
313
|
|
|
404
|
-
async def
|
|
405
|
-
""
|
|
406
|
-
|
|
314
|
+
async def delete_where(self, table: str, where: tuple | dict | list) -> int:
|
|
315
|
+
table = self._validate_identifier(table, "table")
|
|
316
|
+
|
|
317
|
+
if not where:
|
|
318
|
+
raise ValueError("delete_where uchun where bo'sh bo'lmasligi kerak")
|
|
319
|
+
|
|
320
|
+
where_sql, where_params = self._build_where(where, start_index=1)
|
|
407
321
|
|
|
408
|
-
|
|
409
|
-
|
|
322
|
+
if not where_sql:
|
|
323
|
+
raise ValueError("WHERE sharti noto'g'ri")
|
|
410
324
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
325
|
+
sql = f"DELETE FROM {table} WHERE {where_sql}"
|
|
326
|
+
|
|
327
|
+
result = await self._manager(
|
|
328
|
+
sql,
|
|
329
|
+
*where_params,
|
|
330
|
+
commit=True
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
return int(result.split()[-1])
|
|
334
|
+
|
|
335
|
+
async def exists_where(
|
|
336
|
+
self,
|
|
337
|
+
table: str,
|
|
338
|
+
where: tuple | dict | list | None = None,
|
|
339
|
+
join: list[tuple] | None = None,
|
|
340
|
+
group_by: str | None = None,
|
|
341
|
+
) -> bool:
|
|
342
|
+
table = self._validate_identifier(table, "table")
|
|
343
|
+
|
|
344
|
+
sql = f"SELECT 1 FROM {table}"
|
|
345
|
+
params = []
|
|
346
|
+
|
|
347
|
+
if join:
|
|
348
|
+
for join_type, join_table, on_condition in join:
|
|
349
|
+
join_table = self._validate_identifier(join_table, "join table")
|
|
350
|
+
sql += f" {join_type} {join_table} ON {on_condition}"
|
|
351
|
+
|
|
352
|
+
if where:
|
|
353
|
+
condition, values = self._build_where(where, start_index=1)
|
|
354
|
+
if condition:
|
|
355
|
+
sql += f" WHERE {condition}"
|
|
356
|
+
params.extend(values)
|
|
357
|
+
|
|
358
|
+
if group_by:
|
|
359
|
+
sql += f" GROUP BY {group_by}"
|
|
360
|
+
|
|
361
|
+
sql += f" LIMIT ${len(params) + 1}"
|
|
362
|
+
params.append(1)
|
|
363
|
+
|
|
364
|
+
record = await self._manager(sql, *params, fetchone=True)
|
|
365
|
+
return record is not None
|
|
366
|
+
|
|
367
|
+
async def list_tables(self, schema: str = "public") -> List[str]:
|
|
414
368
|
sql = """
|
|
415
369
|
SELECT table_name
|
|
416
370
|
FROM information_schema.tables
|
|
@@ -421,16 +375,6 @@ class AsyncPostgresDB:
|
|
|
421
375
|
return [r["table_name"] for r in result]
|
|
422
376
|
|
|
423
377
|
async def describe_table(self, table: str, schema: str = "public") -> List[str]:
|
|
424
|
-
"""
|
|
425
|
-
Jadval ustunlari haqida ma'lumot beradi.
|
|
426
|
-
|
|
427
|
-
Args:
|
|
428
|
-
table (str): Jadval nomi.
|
|
429
|
-
schema (str): Schema nomi, default "public".
|
|
430
|
-
|
|
431
|
-
Returns:
|
|
432
|
-
list[asyncpg.Record]: Har bir ustun bo‘yicha ma’lumot
|
|
433
|
-
"""
|
|
434
378
|
sql = """
|
|
435
379
|
SELECT column_name, data_type, is_nullable, column_default
|
|
436
380
|
FROM information_schema.columns
|
|
@@ -441,12 +385,5 @@ class AsyncPostgresDB:
|
|
|
441
385
|
return await self._manager(sql, schema, table, fetchall=True)
|
|
442
386
|
|
|
443
387
|
async def alter(self, table: str, action: str) -> None:
|
|
444
|
-
"""
|
|
445
|
-
Jadval strukturasi o‘zgartirish (ALTER TABLE).
|
|
446
|
-
|
|
447
|
-
Args:
|
|
448
|
-
table (str): Jadval nomi.
|
|
449
|
-
action (str): ALTER TABLE dan keyingi SQL qismi, misol: "ADD COLUMN age INT".
|
|
450
|
-
"""
|
|
451
388
|
sql = f"ALTER TABLE {table} {action}"
|
|
452
389
|
await self._manager(sql, commit=True)
|