postgresdb3 0.2.2__tar.gz → 0.3.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.2.2 → postgresdb3-0.3.0}/PKG-INFO +4 -4
- {postgresdb3-0.2.2 → postgresdb3-0.3.0}/README.md +1 -1
- {postgresdb3-0.2.2 → postgresdb3-0.3.0}/postgresdb3/async_db.py +81 -39
- postgresdb3-0.3.0/postgresdb3/sync_db.py +344 -0
- {postgresdb3-0.2.2 → postgresdb3-0.3.0}/postgresdb3.egg-info/PKG-INFO +4 -4
- {postgresdb3-0.2.2 → postgresdb3-0.3.0}/setup.py +4 -2
- postgresdb3-0.2.2/postgresdb3/sync_db.py +0 -189
- {postgresdb3-0.2.2 → postgresdb3-0.3.0}/postgresdb3/__init__.py +0 -0
- {postgresdb3-0.2.2 → postgresdb3-0.3.0}/postgresdb3.egg-info/SOURCES.txt +0 -0
- {postgresdb3-0.2.2 → postgresdb3-0.3.0}/postgresdb3.egg-info/dependency_links.txt +0 -0
- {postgresdb3-0.2.2 → postgresdb3-0.3.0}/postgresdb3.egg-info/requires.txt +0 -0
- {postgresdb3-0.2.2 → postgresdb3-0.3.0}/postgresdb3.egg-info/top_level.txt +0 -0
- {postgresdb3-0.2.2 → postgresdb3-0.3.0}/pyproject.toml +0 -0
- {postgresdb3-0.2.2 → postgresdb3-0.3.0}/setup.cfg +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: postgresdb3
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Python uchun oddiy PostgreSQL wrapper
|
|
5
|
-
Home-page: https://github.com/AlijonovUz/PostgresDB
|
|
6
5
|
Author: Abdulbosit Alijonov
|
|
6
|
+
Project-URL: Source Code, https://github.com/AlijonovUz/PostgresDB
|
|
7
7
|
Classifier: Programming Language :: Python :: 3
|
|
8
8
|
Classifier: License :: OSI Approved :: MIT License
|
|
9
9
|
Classifier: Operating System :: OS Independent
|
|
@@ -15,7 +15,7 @@ Dynamic: author
|
|
|
15
15
|
Dynamic: classifier
|
|
16
16
|
Dynamic: description
|
|
17
17
|
Dynamic: description-content-type
|
|
18
|
-
Dynamic:
|
|
18
|
+
Dynamic: project-url
|
|
19
19
|
Dynamic: requires-dist
|
|
20
20
|
Dynamic: requires-python
|
|
21
21
|
Dynamic: summary
|
|
@@ -31,7 +31,7 @@ Oddiy va qulay Python wrapper PostgreSQL bazasi bilan ishlash uchun.
|
|
|
31
31
|
## O'rnatish
|
|
32
32
|
|
|
33
33
|
``` bash
|
|
34
|
-
|
|
34
|
+
pip install postgresdb3
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
## Foydalanish (Sync)
|
|
@@ -11,7 +11,7 @@ class AsyncPostgresDB:
|
|
|
11
11
|
Aiogram kabi async frameworklar bilan to‘g‘ridan-to‘g‘ri ishlash uchun mos.
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
|
-
def __init__(self, database: str, user: str, password: str, host: str = "localhost", port: int = 5432):
|
|
14
|
+
def __init__(self, database: str, user: str, password: str, host: str = "localhost", port: int = 5432) -> None:
|
|
15
15
|
"""
|
|
16
16
|
PostgreSQL bazasiga ulanishni tayyorlaydi.
|
|
17
17
|
|
|
@@ -29,7 +29,7 @@ class AsyncPostgresDB:
|
|
|
29
29
|
self.port = port
|
|
30
30
|
self.pool: Optional[asyncpg.pool.Pool] = None
|
|
31
31
|
|
|
32
|
-
async def
|
|
32
|
+
async def _manager(self, sql: str, *params, fetchone=False, fetchall=False, commit=False) -> Any:
|
|
33
33
|
"""
|
|
34
34
|
Markaziy metod: barcha SQL so‘rovlarni bajaradi.
|
|
35
35
|
|
|
@@ -63,7 +63,7 @@ class AsyncPostgresDB:
|
|
|
63
63
|
if fetchall:
|
|
64
64
|
return await conn.fetch(sql, *params)
|
|
65
65
|
|
|
66
|
-
async def close_pool(self):
|
|
66
|
+
async def close_pool(self) -> None:
|
|
67
67
|
"""
|
|
68
68
|
Connection poolni yopadi.
|
|
69
69
|
"""
|
|
@@ -71,7 +71,7 @@ class AsyncPostgresDB:
|
|
|
71
71
|
await self.pool.close()
|
|
72
72
|
self.pool = None
|
|
73
73
|
|
|
74
|
-
async def create(self, table: str, columns: str):
|
|
74
|
+
async def create(self, table: str, columns: str) -> None:
|
|
75
75
|
"""
|
|
76
76
|
Jadval yaratadi (agar mavjud bo‘lsa o‘tkazib yuboradi).
|
|
77
77
|
|
|
@@ -79,26 +79,26 @@ class AsyncPostgresDB:
|
|
|
79
79
|
table (str): Jadval nomi.
|
|
80
80
|
columns (str): Ustunlar va turlari, misol: "id SERIAL PRIMARY KEY, name TEXT".
|
|
81
81
|
"""
|
|
82
|
-
await self.
|
|
82
|
+
await self._manager(f"CREATE TABLE IF NOT EXISTS {table} ({columns})", commit=True)
|
|
83
83
|
|
|
84
|
-
async def drop(self, table: str):
|
|
84
|
+
async def drop(self, table: str) -> None:
|
|
85
85
|
"""
|
|
86
86
|
Jadvalni o‘chiradi (agar mavjud bo‘lsa).
|
|
87
87
|
|
|
88
88
|
Args:
|
|
89
89
|
table (str): Jadval nomi.
|
|
90
90
|
"""
|
|
91
|
-
await self.
|
|
91
|
+
await self._manager(f"DROP TABLE IF EXISTS {table} CASCADE", commit=True)
|
|
92
92
|
|
|
93
93
|
async def select(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
):
|
|
94
|
+
self, table: str, columns: str = "*",
|
|
95
|
+
where: Optional[List[Any]] = None,
|
|
96
|
+
join: Optional[List[tuple]] = None,
|
|
97
|
+
group_by: Optional[str] = None,
|
|
98
|
+
order_by: Optional[str] = None,
|
|
99
|
+
limit: Optional[int] = None,
|
|
100
|
+
fetchone: bool = False
|
|
101
|
+
) -> Any:
|
|
102
102
|
"""
|
|
103
103
|
Jadvaldan ma'lumotlarni tanlash.
|
|
104
104
|
|
|
@@ -137,9 +137,9 @@ class AsyncPostgresDB:
|
|
|
137
137
|
sql += f" LIMIT $%d" % (len(params) + 1)
|
|
138
138
|
params.append(limit)
|
|
139
139
|
|
|
140
|
-
return await self.
|
|
140
|
+
return await self._manager(sql, *params, fetchone=fetchone, fetchall=not fetchone)
|
|
141
141
|
|
|
142
|
-
async def insert(self, table: str, columns: str, values: List[Any]):
|
|
142
|
+
async def insert(self, table: str, columns: str, values: List[Any]) -> None:
|
|
143
143
|
"""
|
|
144
144
|
Jadvalga yangi qator qo‘shadi.
|
|
145
145
|
|
|
@@ -148,11 +148,52 @@ class AsyncPostgresDB:
|
|
|
148
148
|
columns (str): Ustunlar nomi, misol: "name, age".
|
|
149
149
|
values (List[Any]): Qiymatlar, misol: ["Ali", 25].
|
|
150
150
|
"""
|
|
151
|
-
placeholders = ", ".join(f"${i+1}" for i in range(len(values)))
|
|
151
|
+
placeholders = ", ".join(f"${i + 1}" for i in range(len(values)))
|
|
152
152
|
sql = f"INSERT INTO {table} ({columns}) VALUES ({placeholders})"
|
|
153
|
-
await self.
|
|
153
|
+
await self._manager(sql, *values, commit=True)
|
|
154
154
|
|
|
155
|
-
async def
|
|
155
|
+
async def insert_many(self, table: str, columns: str, values_list: List[List[Any]]) -> None:
|
|
156
|
+
"""
|
|
157
|
+
Jadvalga bir nechta qator qo‘shish (bulk insert).
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
table (str): Jadval nomi.
|
|
161
|
+
columns (str): Ustunlar nomi, misol: "name, age".
|
|
162
|
+
values_list (List[List[Any]]): Qiymatlar ro‘yxati, misol: [["Ali", 25], ["Vali", 30]].
|
|
163
|
+
|
|
164
|
+
Raises:
|
|
165
|
+
ValueError: Agar `values_list` bo‘sh bo‘lsa.
|
|
166
|
+
|
|
167
|
+
Notes:
|
|
168
|
+
- `asyncpg` kutubxonasida har bir parametr uchun unikal `$n` indekslari kerak,
|
|
169
|
+
shuning uchun har bir qator uchun ketma-ket `$1, $2, ...` ishlatiladi.
|
|
170
|
+
- Metod barcha qatorlarni bir so‘rovda qo‘shadi.
|
|
171
|
+
- `fetchmany` kerak emas, chunki bu insert operatsiyasi natija qaytarmaydi.
|
|
172
|
+
|
|
173
|
+
Example:
|
|
174
|
+
await db.insert_many(
|
|
175
|
+
"users",
|
|
176
|
+
"name, age",
|
|
177
|
+
[["Ali", 25], ["Vali", 30], ["Guli", 22]]
|
|
178
|
+
)
|
|
179
|
+
"""
|
|
180
|
+
if not values_list:
|
|
181
|
+
raise ValueError("values_list bo'sh bo'lishi mumkin emas")
|
|
182
|
+
|
|
183
|
+
placeholders_list = []
|
|
184
|
+
flat_values = []
|
|
185
|
+
counter = 1
|
|
186
|
+
|
|
187
|
+
for values in values_list:
|
|
188
|
+
placeholders = ", ".join(f"${i}" for i in range(counter, counter + len(values)))
|
|
189
|
+
placeholders_list.append(f"({placeholders})")
|
|
190
|
+
flat_values.extend(values)
|
|
191
|
+
counter += len(values)
|
|
192
|
+
|
|
193
|
+
sql = f"INSERT INTO {table} ({columns}) VALUES {', '.join(placeholders_list)}"
|
|
194
|
+
await self._manager(sql, *flat_values, commit=True)
|
|
195
|
+
|
|
196
|
+
async def update(self, table: str, set_column: str, set_value: Any, where_column: str, where_value: Any) -> None:
|
|
156
197
|
"""
|
|
157
198
|
Jadvaldagi qatorni yangilaydi.
|
|
158
199
|
|
|
@@ -164,9 +205,9 @@ class AsyncPostgresDB:
|
|
|
164
205
|
where_value (Any): Filtrlash qiymati.
|
|
165
206
|
"""
|
|
166
207
|
sql = f"UPDATE {table} SET {set_column} = $1 WHERE {where_column} = $2"
|
|
167
|
-
await self.
|
|
208
|
+
await self._manager(sql, set_value, where_value, commit=True)
|
|
168
209
|
|
|
169
|
-
async def delete(self, table: str, where_column: str, where_value: Any):
|
|
210
|
+
async def delete(self, table: str, where_column: str, where_value: Any) -> None:
|
|
170
211
|
"""
|
|
171
212
|
Jadvaldan qator o‘chiradi.
|
|
172
213
|
|
|
@@ -176,7 +217,7 @@ class AsyncPostgresDB:
|
|
|
176
217
|
where_value (Any): Filtrlash qiymati.
|
|
177
218
|
"""
|
|
178
219
|
sql = f"DELETE FROM {table} WHERE {where_column} = $1"
|
|
179
|
-
await self.
|
|
220
|
+
await self._manager(sql, where_value, commit=True)
|
|
180
221
|
|
|
181
222
|
async def list_tables(self, schema: str = "public") -> List[str]:
|
|
182
223
|
"""
|
|
@@ -189,15 +230,15 @@ class AsyncPostgresDB:
|
|
|
189
230
|
List[str]: Jadval nomlari
|
|
190
231
|
"""
|
|
191
232
|
sql = """
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
result = await self.
|
|
233
|
+
SELECT table_name
|
|
234
|
+
FROM information_schema.tables
|
|
235
|
+
WHERE table_schema = $1
|
|
236
|
+
ORDER BY table_name \
|
|
237
|
+
"""
|
|
238
|
+
result = await self._manager(sql, schema, fetchall=True)
|
|
198
239
|
return [r["table_name"] for r in result]
|
|
199
240
|
|
|
200
|
-
async def describe_table(self, table: str, schema: str = "public"):
|
|
241
|
+
async def describe_table(self, table: str, schema: str = "public") -> List[str]:
|
|
201
242
|
"""
|
|
202
243
|
Jadval ustunlari haqida ma'lumot beradi.
|
|
203
244
|
|
|
@@ -209,14 +250,15 @@ class AsyncPostgresDB:
|
|
|
209
250
|
list[asyncpg.Record]: Har bir ustun bo‘yicha ma’lumot
|
|
210
251
|
"""
|
|
211
252
|
sql = """
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
253
|
+
SELECT column_name, data_type, is_nullable, column_default
|
|
254
|
+
FROM information_schema.columns
|
|
255
|
+
WHERE table_schema = $1
|
|
256
|
+
AND table_name = $2
|
|
257
|
+
ORDER BY ordinal_position \
|
|
258
|
+
"""
|
|
259
|
+
return await self._manager(sql, schema, table, fetchall=True)
|
|
260
|
+
|
|
261
|
+
async def alter(self, table: str, action: str) -> None:
|
|
220
262
|
"""
|
|
221
263
|
Jadval strukturasi o‘zgartirish (ALTER TABLE).
|
|
222
264
|
|
|
@@ -225,4 +267,4 @@ class AsyncPostgresDB:
|
|
|
225
267
|
action (str): ALTER TABLE dan keyingi SQL qismi, misol: "ADD COLUMN age INT".
|
|
226
268
|
"""
|
|
227
269
|
sql = f"ALTER TABLE {table} {action}"
|
|
228
|
-
await self.
|
|
270
|
+
await self._manager(sql, commit=True)
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
import psycopg2
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class PostgresDB:
|
|
6
|
+
|
|
7
|
+
def __init__(self, database: str, user: str, password: str, host: str = "localhost", port: int = 5432) -> None:
|
|
8
|
+
"""
|
|
9
|
+
PostgreSQL bazasiga ulanish.
|
|
10
|
+
|
|
11
|
+
Parametrlar:
|
|
12
|
+
database (str): Bazaning nomi
|
|
13
|
+
user (str): Foydalanuvchi
|
|
14
|
+
password (str): Parol
|
|
15
|
+
host (str): Server manzili (standart = localhost)
|
|
16
|
+
port (int): Port (standart = 5432)
|
|
17
|
+
"""
|
|
18
|
+
self.connection = psycopg2.connect(
|
|
19
|
+
database=database, user=user, password=password, host=host, port=port
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
def _manager(
|
|
23
|
+
self,
|
|
24
|
+
sql: str,
|
|
25
|
+
params: list | tuple | None = None,
|
|
26
|
+
*,
|
|
27
|
+
commit: bool = False,
|
|
28
|
+
many: bool = False,
|
|
29
|
+
fetchone: bool = False,
|
|
30
|
+
fetchall: bool = False,
|
|
31
|
+
fetchmany: int | None = None
|
|
32
|
+
) -> Any:
|
|
33
|
+
"""
|
|
34
|
+
SQL so'rovlarini xavfsiz bajaruvchi yagona, ichki metod.
|
|
35
|
+
|
|
36
|
+
Bu metod **protected** bo‘lib, tashqaridan ishlatish tavsiya etilmaydi.
|
|
37
|
+
Public uchun `raw()` metodini ishlatish yaxshiroq.
|
|
38
|
+
|
|
39
|
+
Parametrlar
|
|
40
|
+
----------
|
|
41
|
+
sql : str
|
|
42
|
+
Bajariladigan SQL so'rov. Majburiy.
|
|
43
|
+
params : tuple, list yoki None, ixtiyoriy
|
|
44
|
+
SQL so‘rovga parametrlarni bog‘lash uchun ishlatiladi. Default: None.
|
|
45
|
+
Agar `many=True` bo‘lsa, bu **tuple lar ro‘yxati** bo‘lishi kerak.
|
|
46
|
+
commit : bool, ixtiyoriy
|
|
47
|
+
Agar True bo‘lsa, tranzaksiya bajarilgandan keyin commit qilinadi.
|
|
48
|
+
Default: False. INSERT, UPDATE, DELETE kabi so‘rovlar uchun kerak.
|
|
49
|
+
many : bool, ixtiyoriy
|
|
50
|
+
Agar True bo‘lsa, so‘rovni bir nechta parametrlar bilan qayta bajaradi
|
|
51
|
+
(`cursor.executemany()` ishlatiladi). Default: False.
|
|
52
|
+
`fetchone`, `fetchall` yoki `fetchmany` bilan birga ishlatilmaydi.
|
|
53
|
+
fetchone : bool, ixtiyoriy
|
|
54
|
+
Agar True bo‘lsa, so‘rov natijasidan faqat bitta qator qaytariladi.
|
|
55
|
+
Default: False. `fetchall`, `fetchmany` yoki `many=True` bilan ishlamaydi.
|
|
56
|
+
fetchall : bool, ixtiyoriy
|
|
57
|
+
Agar True bo‘lsa, so‘rov natijasidagi barcha qatorlar qaytariladi.
|
|
58
|
+
Default: False. `fetchone`, `fetchmany` yoki `many=True` bilan ishlamaydi.
|
|
59
|
+
fetchmany : int yoki None, ixtiyoriy
|
|
60
|
+
Agar butun son N berilsa, so‘rov natijasidan N ta qator qaytariladi.
|
|
61
|
+
Default: None. `fetchone`, `fetchall` yoki `many=True` bilan ishlamaydi.
|
|
62
|
+
|
|
63
|
+
Returns
|
|
64
|
+
-------
|
|
65
|
+
result : any
|
|
66
|
+
So‘rov natijasi fetch parametriga bog‘liq:
|
|
67
|
+
- `fetchone=True` → bitta qator (tuple)
|
|
68
|
+
- `fetchall=True` → barcha qatorlar ro‘yxati
|
|
69
|
+
- `fetchmany=N` → N ta qator ro‘yxati
|
|
70
|
+
- `many=True` → None
|
|
71
|
+
- Fetch parametri ishlatilmasa → None
|
|
72
|
+
|
|
73
|
+
Raises
|
|
74
|
+
------
|
|
75
|
+
ValueError
|
|
76
|
+
- Agar `sql` bo‘sh yoki None bo‘lsa.
|
|
77
|
+
- Agar bir vaqtda `fetchone` va `fetchall` True bo‘lsa.
|
|
78
|
+
- Agar `many=True` fetch parametrlar bilan birga ishlatilsa.
|
|
79
|
+
|
|
80
|
+
Izohlar
|
|
81
|
+
--------
|
|
82
|
+
- Bu metod connection va cursor ni context manager orqali avtomatik boshqaradi.
|
|
83
|
+
- Exceptionlar va tranzaksiya nazorati psycopg2 tomonidan amalga oshiriladi.
|
|
84
|
+
- Tashqarida ishlatishda `raw()` yoki yuqori darajadagi metodlar (`insert()`, `select()`, `insert_many()`) ishlatilishi tavsiya etiladi.
|
|
85
|
+
- Tashqaridan bevosita chaqirish tavsiya etilmaydi.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
if fetchone and fetchall:
|
|
89
|
+
raise ValueError("fetchone and fetchall cannot be True at the same time")
|
|
90
|
+
if many and (fetchone or fetchall or fetchmany):
|
|
91
|
+
raise ValueError("cannot use fetchone/fetchall/fetchmany with many=True")
|
|
92
|
+
|
|
93
|
+
with self.connection.cursor() as cursor:
|
|
94
|
+
if many:
|
|
95
|
+
cursor.executemany(sql, params)
|
|
96
|
+
result = None
|
|
97
|
+
else:
|
|
98
|
+
cursor.execute(sql, params)
|
|
99
|
+
if fetchone:
|
|
100
|
+
result = cursor.fetchone()
|
|
101
|
+
elif fetchall:
|
|
102
|
+
result = cursor.fetchall()
|
|
103
|
+
elif fetchmany is not None:
|
|
104
|
+
result = cursor.fetchmany(fetchmany)
|
|
105
|
+
else:
|
|
106
|
+
result = None
|
|
107
|
+
|
|
108
|
+
if commit:
|
|
109
|
+
self.connection.commit()
|
|
110
|
+
|
|
111
|
+
return result
|
|
112
|
+
|
|
113
|
+
def close(self) -> None:
|
|
114
|
+
self.connection.close()
|
|
115
|
+
|
|
116
|
+
def raw(
|
|
117
|
+
self,
|
|
118
|
+
sql: str,
|
|
119
|
+
params: list | tuple | None = None,
|
|
120
|
+
*,
|
|
121
|
+
commit: bool = False,
|
|
122
|
+
many: bool = False,
|
|
123
|
+
fetchone: bool = False,
|
|
124
|
+
fetchall: bool = False,
|
|
125
|
+
fetchmany: int | None = None
|
|
126
|
+
) -> Any:
|
|
127
|
+
"""
|
|
128
|
+
SQL so'rovini bevosita bajarish (raw execution).
|
|
129
|
+
|
|
130
|
+
Faqat ilg'or foydalanish uchun. Bu metod ichki `_manager` metodini chaqiradi.
|
|
131
|
+
Tashqaridan oddiy foydalanuvchilar uchun `select()`, `insert()`, `update()`,
|
|
132
|
+
`delete()` yoki `insert_many()` metodlarini ishlatish tavsiya etiladi.
|
|
133
|
+
|
|
134
|
+
Parametrlar
|
|
135
|
+
----------
|
|
136
|
+
sql : str
|
|
137
|
+
Bajariladigan SQL so'rov. Majburiy.
|
|
138
|
+
params : tuple, list yoki None, ixtiyoriy
|
|
139
|
+
SQL so‘rovga parametrlarni bog‘lash uchun ishlatiladi. Default: None.
|
|
140
|
+
commit : bool, ixtiyoriy
|
|
141
|
+
Agar True bo‘lsa, tranzaksiya bajarilgandan keyin commit qilinadi.
|
|
142
|
+
Default: False.
|
|
143
|
+
fetchone : bool, ixtiyoriy
|
|
144
|
+
Agar True bo‘lsa, so‘rov natijasidan faqat bitta qator qaytariladi.
|
|
145
|
+
Default: False. `fetchall` bilan birga ishlatilmaydi.
|
|
146
|
+
fetchall : bool, ixtiyoriy
|
|
147
|
+
Agar True bo‘lsa, so‘rov natijasidagi barcha qatorlar qaytariladi.
|
|
148
|
+
Default: False. `fetchone` bilan birga ishlatilmaydi.
|
|
149
|
+
|
|
150
|
+
Returns
|
|
151
|
+
-------
|
|
152
|
+
result : any
|
|
153
|
+
So‘rov natijasi fetch parametriga bog‘liq:
|
|
154
|
+
- `fetchone=True` → bitta qator (tuple)
|
|
155
|
+
- `fetchall=True` → barcha qatorlar ro‘yxati
|
|
156
|
+
- Hech qaysi fetch parametr ishlatilmasa → None
|
|
157
|
+
|
|
158
|
+
Raises
|
|
159
|
+
------
|
|
160
|
+
ValueError
|
|
161
|
+
- Agar bir vaqtda `fetchone` va `fetchall` True bo‘lsa.
|
|
162
|
+
|
|
163
|
+
Misol
|
|
164
|
+
------
|
|
165
|
+
>>> db.raw("SELECT * FROM users WHERE age > %s", (18,), fetchall=True)
|
|
166
|
+
"""
|
|
167
|
+
if fetchone and fetchall:
|
|
168
|
+
raise ValueError("fetchone va fetchall bir vaqtda True bo‘la olmaydi")
|
|
169
|
+
|
|
170
|
+
return self._manager(
|
|
171
|
+
sql,
|
|
172
|
+
params,
|
|
173
|
+
commit=commit,
|
|
174
|
+
many=many,
|
|
175
|
+
fetchone=fetchone,
|
|
176
|
+
fetchall=fetchall,
|
|
177
|
+
fetchmany=fetchmany,
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
def create(self, table: str, columns: str) -> None:
|
|
181
|
+
"""
|
|
182
|
+
table: str - jadval nomi
|
|
183
|
+
columns: str - ustunlar va turlari, misol: "id SERIAL PRIMARY KEY, name VARCHAR(100)"
|
|
184
|
+
"""
|
|
185
|
+
sql = f"CREATE TABLE IF NOT EXISTS {table} ({columns})"
|
|
186
|
+
self._manager(sql, commit=True)
|
|
187
|
+
|
|
188
|
+
def drop(self, table: str) -> None:
|
|
189
|
+
"""
|
|
190
|
+
table: str - o'chiriladigan jadval nomi
|
|
191
|
+
"""
|
|
192
|
+
sql = f"DROP TABLE IF EXISTS {table} CASCADE"
|
|
193
|
+
self._manager(sql, commit=True)
|
|
194
|
+
|
|
195
|
+
def select(
|
|
196
|
+
self,
|
|
197
|
+
table: str,
|
|
198
|
+
columns: str = "*",
|
|
199
|
+
where: tuple | None = None,
|
|
200
|
+
join: list[tuple] | None = None,
|
|
201
|
+
group_by: str | None = None,
|
|
202
|
+
order_by: str | None = None,
|
|
203
|
+
limit: int | None = None,
|
|
204
|
+
fetchone: bool = False
|
|
205
|
+
) -> Any:
|
|
206
|
+
"""
|
|
207
|
+
table: str — asosiy jadval
|
|
208
|
+
columns: str — tanlanadigan ustunlar ("id, name")
|
|
209
|
+
where: tuple | None — ("age > %s", [18])
|
|
210
|
+
join: list | None — [("INNER JOIN", "orders", "users.id = orders.user_id")]
|
|
211
|
+
group_by: str | None — "age"
|
|
212
|
+
order_by: str | None — "age DESC"
|
|
213
|
+
limit: int | None
|
|
214
|
+
"""
|
|
215
|
+
|
|
216
|
+
sql = f"SELECT {columns} FROM {table}"
|
|
217
|
+
params = []
|
|
218
|
+
|
|
219
|
+
if join:
|
|
220
|
+
for join_type, join_table, on_condition in join:
|
|
221
|
+
sql += f" {join_type} {join_table} ON {on_condition}"
|
|
222
|
+
|
|
223
|
+
if where:
|
|
224
|
+
condition, values = where
|
|
225
|
+
sql += f" WHERE {condition}"
|
|
226
|
+
params.extend(values)
|
|
227
|
+
|
|
228
|
+
if group_by:
|
|
229
|
+
sql += f" GROUP BY {group_by}"
|
|
230
|
+
|
|
231
|
+
if order_by:
|
|
232
|
+
sql += f" ORDER BY {order_by}"
|
|
233
|
+
|
|
234
|
+
if limit:
|
|
235
|
+
sql += f" LIMIT %s"
|
|
236
|
+
params.append(limit)
|
|
237
|
+
|
|
238
|
+
if fetchone:
|
|
239
|
+
return self._manager(sql, params, fetchone=True)
|
|
240
|
+
return self._manager(sql, params, fetchall=True)
|
|
241
|
+
|
|
242
|
+
def insert(self, table: str, columns: str, values: tuple | list) -> None:
|
|
243
|
+
"""
|
|
244
|
+
table: str - jadval nomi
|
|
245
|
+
columns: str - ustunlar, misol: "name, email, age"
|
|
246
|
+
values: tuple yoki list - ustun qiymatlari, misol: ("Ali", "ali@mail.com", 25)
|
|
247
|
+
"""
|
|
248
|
+
placeholders = ", ".join(["%s"] * len(values))
|
|
249
|
+
sql = f"INSERT INTO {table} ({columns}) VALUES ({placeholders})"
|
|
250
|
+
self._manager(sql, values, commit=True)
|
|
251
|
+
|
|
252
|
+
def insert_many(self, table: str, columns: str, values_list: list[tuple]) -> None:
|
|
253
|
+
"""
|
|
254
|
+
Jadvalga bir nechta qatorni qo'shish (bulk insert).
|
|
255
|
+
|
|
256
|
+
Parametrlar
|
|
257
|
+
----------
|
|
258
|
+
table : str
|
|
259
|
+
Jadval nomi.
|
|
260
|
+
columns : str
|
|
261
|
+
Ustunlar, misol: "name, email, age".
|
|
262
|
+
values_list : list of tuples
|
|
263
|
+
Har tuple bitta qator qiymatlari, misol:
|
|
264
|
+
[("Ali", "ali@mail.com", 25), ("Vali", "vali@mail.com", 30)]
|
|
265
|
+
|
|
266
|
+
Misol
|
|
267
|
+
------
|
|
268
|
+
>>> db.insert_many(
|
|
269
|
+
... "users",
|
|
270
|
+
... "name, email, age",
|
|
271
|
+
... [("Ali", "ali@mail.com", 25), ("Vali", "vali@mail.com", 30)]
|
|
272
|
+
... )
|
|
273
|
+
"""
|
|
274
|
+
if not values_list:
|
|
275
|
+
raise ValueError("values_list bo'sh bo'lishi mumkin emas")
|
|
276
|
+
|
|
277
|
+
placeholders = ", ".join(["%s"] * len(values_list[0]))
|
|
278
|
+
sql = f"INSERT INTO {table} ({columns}) VALUES ({placeholders})"
|
|
279
|
+
|
|
280
|
+
self._manager(sql, values_list, commit=True, many=True)
|
|
281
|
+
|
|
282
|
+
def update(self, table: str, set_column: str, set_value: Any, where_column: str, where_value: Any) -> None:
|
|
283
|
+
"""
|
|
284
|
+
Jadvaldagi ma'lumotni yangilash.
|
|
285
|
+
|
|
286
|
+
Parametrlar:
|
|
287
|
+
table (str): Jadval nomi.
|
|
288
|
+
set_column (str): O'zgartiriladigan ustun.
|
|
289
|
+
set_value (Any): Yangi qiymat.
|
|
290
|
+
where_column (str): Filtrlash ustuni.
|
|
291
|
+
where_value (Any): Qaysi qatorda o'zgarish bo'lishi.
|
|
292
|
+
|
|
293
|
+
Izoh:
|
|
294
|
+
Faqat WHERE shartiga mos kelgan qatorlar yangilanadi.
|
|
295
|
+
"""
|
|
296
|
+
sql = f"UPDATE {table} SET {set_column} = %s WHERE {where_column} = %s"
|
|
297
|
+
self._manager(sql, (set_value, where_value), commit=True)
|
|
298
|
+
|
|
299
|
+
def delete(self, table: str, where_column: str, where_value: Any) -> None:
|
|
300
|
+
"""
|
|
301
|
+
Jadvaldan qator o'chirish.
|
|
302
|
+
"""
|
|
303
|
+
sql = f"DELETE FROM {table} WHERE {where_column} = %s"
|
|
304
|
+
self._manager(sql, (where_value,), commit=True)
|
|
305
|
+
|
|
306
|
+
def list_tables(self, schema="public") -> list[tuple]:
|
|
307
|
+
"""
|
|
308
|
+
Bazadagi mavjud jadvallar ro'yxatini qaytaradi.
|
|
309
|
+
|
|
310
|
+
schema: str — schema nomi (standart: public)
|
|
311
|
+
"""
|
|
312
|
+
sql = """
|
|
313
|
+
SELECT table_name
|
|
314
|
+
FROM information_schema.tables
|
|
315
|
+
WHERE table_schema = %s
|
|
316
|
+
ORDER BY table_name; \
|
|
317
|
+
"""
|
|
318
|
+
return self._manager(sql, (schema,), fetchall=True)
|
|
319
|
+
|
|
320
|
+
def describe_table(self, table: str, schema: str = "public") -> list[tuple]:
|
|
321
|
+
"""
|
|
322
|
+
Jadval ustunlari haqida ma'lumot beradi.
|
|
323
|
+
"""
|
|
324
|
+
sql = """
|
|
325
|
+
SELECT column_name,
|
|
326
|
+
data_type,
|
|
327
|
+
is_nullable,
|
|
328
|
+
column_default
|
|
329
|
+
FROM information_schema.columns
|
|
330
|
+
WHERE table_schema = %s
|
|
331
|
+
AND table_name = %s
|
|
332
|
+
ORDER BY ordinal_position; \
|
|
333
|
+
"""
|
|
334
|
+
return self._manager(sql, (schema, table), fetchall=True)
|
|
335
|
+
|
|
336
|
+
def alter(self, table: str, action: str) -> Any:
|
|
337
|
+
"""
|
|
338
|
+
Universal ALTER TABLE metodi.
|
|
339
|
+
|
|
340
|
+
table: str — jadval nomi
|
|
341
|
+
action: str — ALTER TABLE dan keyingi qism
|
|
342
|
+
"""
|
|
343
|
+
sql = f"ALTER TABLE {table} {action}"
|
|
344
|
+
return self._manager(sql, commit=True)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: postgresdb3
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Python uchun oddiy PostgreSQL wrapper
|
|
5
|
-
Home-page: https://github.com/AlijonovUz/PostgresDB
|
|
6
5
|
Author: Abdulbosit Alijonov
|
|
6
|
+
Project-URL: Source Code, https://github.com/AlijonovUz/PostgresDB
|
|
7
7
|
Classifier: Programming Language :: Python :: 3
|
|
8
8
|
Classifier: License :: OSI Approved :: MIT License
|
|
9
9
|
Classifier: Operating System :: OS Independent
|
|
@@ -15,7 +15,7 @@ Dynamic: author
|
|
|
15
15
|
Dynamic: classifier
|
|
16
16
|
Dynamic: description
|
|
17
17
|
Dynamic: description-content-type
|
|
18
|
-
Dynamic:
|
|
18
|
+
Dynamic: project-url
|
|
19
19
|
Dynamic: requires-dist
|
|
20
20
|
Dynamic: requires-python
|
|
21
21
|
Dynamic: summary
|
|
@@ -31,7 +31,7 @@ Oddiy va qulay Python wrapper PostgreSQL bazasi bilan ishlash uchun.
|
|
|
31
31
|
## O'rnatish
|
|
32
32
|
|
|
33
33
|
``` bash
|
|
34
|
-
|
|
34
|
+
pip install postgresdb3
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
## Foydalanish (Sync)
|
|
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as f:
|
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name="postgresdb3",
|
|
8
|
-
version="0.
|
|
8
|
+
version="0.3.0",
|
|
9
9
|
packages=find_packages(),
|
|
10
10
|
install_requires=[
|
|
11
11
|
"psycopg2>=2.9",
|
|
@@ -15,7 +15,9 @@ setup(
|
|
|
15
15
|
description="Python uchun oddiy PostgreSQL wrapper",
|
|
16
16
|
long_description=long_description,
|
|
17
17
|
long_description_content_type="text/markdown",
|
|
18
|
-
|
|
18
|
+
project_urls={
|
|
19
|
+
"Source Code": "https://github.com/AlijonovUz/PostgresDB",
|
|
20
|
+
},
|
|
19
21
|
classifiers=[
|
|
20
22
|
"Programming Language :: Python :: 3",
|
|
21
23
|
"License :: OSI Approved :: MIT License",
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
import psycopg2
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class PostgresDB:
|
|
5
|
-
|
|
6
|
-
def __init__(self, database, user, password, host="localhost", port=5432):
|
|
7
|
-
"""
|
|
8
|
-
PostgreSQL bazasiga ulanish.
|
|
9
|
-
|
|
10
|
-
Parametrlar:
|
|
11
|
-
database (str): Bazaning nomi
|
|
12
|
-
user (str): Foydalanuvchi
|
|
13
|
-
password (str): Parol
|
|
14
|
-
host (str): Server manzili (standart = localhost)
|
|
15
|
-
port (int): Port (standart = 5432)
|
|
16
|
-
"""
|
|
17
|
-
self.connect = psycopg2.connect(
|
|
18
|
-
database=database, user=user, password=password, host=host, port=port
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
def manager(
|
|
22
|
-
self,
|
|
23
|
-
sql=None,
|
|
24
|
-
params=None,
|
|
25
|
-
*,
|
|
26
|
-
commit=False,
|
|
27
|
-
fetchall=False,
|
|
28
|
-
fetchone=False,
|
|
29
|
-
):
|
|
30
|
-
"""
|
|
31
|
-
Barcha SQL amallarni boshqaruvchi yagona metod.
|
|
32
|
-
|
|
33
|
-
Parametrlar:
|
|
34
|
-
sql (str | None): Bajariladigan SQL so'rov.
|
|
35
|
-
params (tuple | list | None): Parametrlar.
|
|
36
|
-
commit (bool): Tranzaksiyani tasdiqlash.
|
|
37
|
-
fetchall (bool): Barcha natijalarni olish.
|
|
38
|
-
fetchone (bool): Bitta natija olish.
|
|
39
|
-
"""
|
|
40
|
-
|
|
41
|
-
with self.connect as connect:
|
|
42
|
-
result = None
|
|
43
|
-
with connect.cursor() as cursor:
|
|
44
|
-
cursor.execute(sql, params)
|
|
45
|
-
|
|
46
|
-
if commit:
|
|
47
|
-
connect.commit()
|
|
48
|
-
elif fetchall:
|
|
49
|
-
result = cursor.fetchall()
|
|
50
|
-
elif fetchone:
|
|
51
|
-
result = cursor.fetchone()
|
|
52
|
-
|
|
53
|
-
return result
|
|
54
|
-
|
|
55
|
-
def create(self, table, columns):
|
|
56
|
-
"""
|
|
57
|
-
table: str - jadval nomi
|
|
58
|
-
columns: str - ustunlar va turlari, misol: "id SERIAL PRIMARY KEY, name VARCHAR(100)"
|
|
59
|
-
"""
|
|
60
|
-
sql = f"CREATE TABLE IF NOT EXISTS {table} ({columns})"
|
|
61
|
-
self.manager(sql, commit=True)
|
|
62
|
-
|
|
63
|
-
def drop(self, table):
|
|
64
|
-
"""
|
|
65
|
-
table: str - o'chiriladigan jadval nomi
|
|
66
|
-
"""
|
|
67
|
-
sql = f"DROP TABLE IF EXISTS {table} CASCADE"
|
|
68
|
-
self.manager(sql, commit=True)
|
|
69
|
-
|
|
70
|
-
def select(
|
|
71
|
-
self,
|
|
72
|
-
table,
|
|
73
|
-
columns="*",
|
|
74
|
-
where=None,
|
|
75
|
-
join=None,
|
|
76
|
-
group_by=None,
|
|
77
|
-
order_by=None,
|
|
78
|
-
limit=None,
|
|
79
|
-
fetchone=False,
|
|
80
|
-
):
|
|
81
|
-
"""
|
|
82
|
-
table: str — asosiy jadval
|
|
83
|
-
columns: str — tanlanadigan ustunlar ("id, name")
|
|
84
|
-
where: tuple | None — ("age > %s", [18])
|
|
85
|
-
join: list | None — [("INNER JOIN", "orders", "users.id = orders.user_id")]
|
|
86
|
-
group_by: str | None — "age"
|
|
87
|
-
order_by: str | None — "age DESC"
|
|
88
|
-
limit: int | None
|
|
89
|
-
"""
|
|
90
|
-
|
|
91
|
-
sql = f"SELECT {columns} FROM {table}"
|
|
92
|
-
params = []
|
|
93
|
-
|
|
94
|
-
if join:
|
|
95
|
-
for join_type, join_table, on_condition in join:
|
|
96
|
-
sql += f" {join_type} {join_table} ON {on_condition}"
|
|
97
|
-
|
|
98
|
-
if where:
|
|
99
|
-
condition, values = where
|
|
100
|
-
sql += f" WHERE {condition}"
|
|
101
|
-
params.extend(values)
|
|
102
|
-
|
|
103
|
-
if group_by:
|
|
104
|
-
sql += f" GROUP BY {group_by}"
|
|
105
|
-
|
|
106
|
-
if order_by:
|
|
107
|
-
sql += f" ORDER BY {order_by}"
|
|
108
|
-
|
|
109
|
-
if limit:
|
|
110
|
-
sql += f" LIMIT %s"
|
|
111
|
-
params.append(limit)
|
|
112
|
-
|
|
113
|
-
if fetchone:
|
|
114
|
-
return self.manager(sql, params, fetchone=True)
|
|
115
|
-
return self.manager(sql, params, fetchall=True)
|
|
116
|
-
|
|
117
|
-
def insert(self, table, columns, values):
|
|
118
|
-
"""
|
|
119
|
-
table: str - jadval nomi
|
|
120
|
-
columns: str - ustunlar, misol: "name, email, age"
|
|
121
|
-
values: tuple yoki list - ustun qiymatlari, misol: ("Ali", "ali@mail.com", 25)
|
|
122
|
-
"""
|
|
123
|
-
placeholders = ", ".join(["%s"] * len(values))
|
|
124
|
-
sql = f"INSERT INTO {table} ({columns}) VALUES ({placeholders})"
|
|
125
|
-
self.manager(sql, values, commit=True)
|
|
126
|
-
|
|
127
|
-
def update(self, table, set_column, set_value, where_column, where_value):
|
|
128
|
-
"""
|
|
129
|
-
Jadvaldagi ma'lumotni yangilash.
|
|
130
|
-
|
|
131
|
-
Parametrlar:
|
|
132
|
-
table (str): Jadval nomi.
|
|
133
|
-
set_column (str): O'zgartiriladigan ustun.
|
|
134
|
-
set_value (Any): Yangi qiymat.
|
|
135
|
-
where_column (str): Filtrlash ustuni.
|
|
136
|
-
where_value (Any): Qaysi qatorda o'zgarish bo'lishi.
|
|
137
|
-
|
|
138
|
-
Izoh:
|
|
139
|
-
Faqat WHERE shartiga mos kelgan qatorlar yangilanadi.
|
|
140
|
-
"""
|
|
141
|
-
sql = f"UPDATE {table} SET {set_column} = %s WHERE {where_column} = %s"
|
|
142
|
-
return self.manager(sql, (set_value, where_value), commit=True)
|
|
143
|
-
|
|
144
|
-
def delete(self, table, where_column, where_value):
|
|
145
|
-
"""
|
|
146
|
-
Jadvaldan qator o'chirish.
|
|
147
|
-
"""
|
|
148
|
-
sql = f"DELETE FROM {table} WHERE {where_column} = %s"
|
|
149
|
-
return self.manager(sql, (where_value,), commit=True)
|
|
150
|
-
|
|
151
|
-
def list_tables(self, schema="public"):
|
|
152
|
-
"""
|
|
153
|
-
Bazadagi mavjud jadvallar ro'yxatini qaytaradi.
|
|
154
|
-
|
|
155
|
-
schema: str — schema nomi (standart: public)
|
|
156
|
-
"""
|
|
157
|
-
sql = """
|
|
158
|
-
SELECT table_name
|
|
159
|
-
FROM information_schema.tables
|
|
160
|
-
WHERE table_schema = %s
|
|
161
|
-
ORDER BY table_name; \
|
|
162
|
-
"""
|
|
163
|
-
return self.manager(sql, (schema,), fetchall=True)
|
|
164
|
-
|
|
165
|
-
def describe_table(self, table, schema="public"):
|
|
166
|
-
"""
|
|
167
|
-
Jadval ustunlari haqida ma'lumot beradi.
|
|
168
|
-
"""
|
|
169
|
-
sql = """
|
|
170
|
-
SELECT column_name,
|
|
171
|
-
data_type,
|
|
172
|
-
is_nullable,
|
|
173
|
-
column_default
|
|
174
|
-
FROM information_schema.columns
|
|
175
|
-
WHERE table_schema = %s
|
|
176
|
-
AND table_name = %s
|
|
177
|
-
ORDER BY ordinal_position; \
|
|
178
|
-
"""
|
|
179
|
-
return self.manager(sql, (schema, table), fetchall=True)
|
|
180
|
-
|
|
181
|
-
def alter(self, table, action):
|
|
182
|
-
"""
|
|
183
|
-
Universal ALTER TABLE metodi.
|
|
184
|
-
|
|
185
|
-
table: str — jadval nomi
|
|
186
|
-
action: str — ALTER TABLE dan keyingi qism
|
|
187
|
-
"""
|
|
188
|
-
sql = f"ALTER TABLE {table} {action}"
|
|
189
|
-
return self.manager(sql, commit=True)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|