pgconnect 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pgconnect/Column.py +25 -0
- pgconnect/Connection.py +98 -0
- pgconnect/DataType.py +234 -0
- pgconnect/Table.py +766 -0
- pgconnect/__init__.py +4 -0
- pgconnect/examples.py +55 -0
- pgconnect-0.0.1.dist-info/LICENSE +21 -0
- pgconnect-0.0.1.dist-info/METADATA +271 -0
- pgconnect-0.0.1.dist-info/RECORD +11 -0
- pgconnect-0.0.1.dist-info/WHEEL +5 -0
- pgconnect-0.0.1.dist-info/top_level.txt +1 -0
pgconnect/Column.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import asyncpg
|
|
2
|
+
import pgconnect
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Column:
|
|
6
|
+
def __init__(
|
|
7
|
+
self,
|
|
8
|
+
name: str,
|
|
9
|
+
type: pgconnect.DataType
|
|
10
|
+
) -> None:
|
|
11
|
+
"""
|
|
12
|
+
Initializes the column with specified properties.
|
|
13
|
+
|
|
14
|
+
Notes:
|
|
15
|
+
- Length should only be set for VARCHAR and CHAR types.
|
|
16
|
+
- Default values will be applied if provided.
|
|
17
|
+
"""
|
|
18
|
+
self.name = name
|
|
19
|
+
self.type = type
|
|
20
|
+
|
|
21
|
+
def __repr__(self) -> str:
|
|
22
|
+
return f"<Column {self.name}>"
|
|
23
|
+
|
|
24
|
+
def __str__(self) -> str:
|
|
25
|
+
return f"<Column {self.name}>"
|
pgconnect/Connection.py
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import asyncpg
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Connection:
|
|
6
|
+
connection:asyncpg.Connection = None
|
|
7
|
+
def __init__(
|
|
8
|
+
self,
|
|
9
|
+
host: str,
|
|
10
|
+
port: int,
|
|
11
|
+
user: str,
|
|
12
|
+
password: str,
|
|
13
|
+
database: str,
|
|
14
|
+
ssl: bool = False,
|
|
15
|
+
pool: int = None,
|
|
16
|
+
reconnect: bool = False
|
|
17
|
+
) -> None:
|
|
18
|
+
self.host = host
|
|
19
|
+
self.port = port
|
|
20
|
+
self.user = user
|
|
21
|
+
self.password = password
|
|
22
|
+
self.database = database
|
|
23
|
+
self.ssl = ssl
|
|
24
|
+
self.pool = pool
|
|
25
|
+
self.reconnect = reconnect
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
async def get_connection(self):
|
|
29
|
+
if not self.connection:
|
|
30
|
+
await self.connect()
|
|
31
|
+
if isinstance(self.connection, asyncpg.pool.Pool):
|
|
32
|
+
return await self.connection.acquire()
|
|
33
|
+
else:
|
|
34
|
+
return self.connection
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
async def ping(self) -> float:
|
|
38
|
+
"""
|
|
39
|
+
Check the connection to the database
|
|
40
|
+
:return: The time taken to ping the database in milliseconds
|
|
41
|
+
"""
|
|
42
|
+
start_time = time.time_ns()
|
|
43
|
+
connection = await self.get_connection()
|
|
44
|
+
await connection.fetchval("SELECT 1")
|
|
45
|
+
if isinstance(self.connection, asyncpg.pool.Pool):
|
|
46
|
+
await connection.close()
|
|
47
|
+
end_time = time.time_ns()
|
|
48
|
+
return (end_time - start_time) / 1000000
|
|
49
|
+
|
|
50
|
+
async def connect(self):
|
|
51
|
+
try:
|
|
52
|
+
if self.pool:
|
|
53
|
+
connection = await asyncpg.create_pool(
|
|
54
|
+
host=self.host,
|
|
55
|
+
port=self.port,
|
|
56
|
+
user=self.user,
|
|
57
|
+
password=self.password,
|
|
58
|
+
database=self.database,
|
|
59
|
+
ssl=self.ssl,
|
|
60
|
+
max_size=self.pool
|
|
61
|
+
)
|
|
62
|
+
else:
|
|
63
|
+
connection = await asyncpg.connect(
|
|
64
|
+
host=self.host,
|
|
65
|
+
port=self.port,
|
|
66
|
+
user=self.user,
|
|
67
|
+
password=self.password,
|
|
68
|
+
database=self.database,
|
|
69
|
+
ssl=self.ssl
|
|
70
|
+
)
|
|
71
|
+
self.connection = connection
|
|
72
|
+
except Exception as e:
|
|
73
|
+
raise ConnectionError("Could not connect to the database") from e
|
|
74
|
+
|
|
75
|
+
async def acquire(self):
|
|
76
|
+
if isinstance(self.connection, asyncpg.pool.Pool):
|
|
77
|
+
return self.connection.acquire()
|
|
78
|
+
else:
|
|
79
|
+
return self.connection
|
|
80
|
+
|
|
81
|
+
async def release(self, connection):
|
|
82
|
+
"""
|
|
83
|
+
Release a connection back to the pool
|
|
84
|
+
"""
|
|
85
|
+
if isinstance(self.connection, asyncpg.pool.Pool):
|
|
86
|
+
await connection.close()
|
|
87
|
+
|
|
88
|
+
async def close(self):
|
|
89
|
+
"""
|
|
90
|
+
Close the connection to the database
|
|
91
|
+
"""
|
|
92
|
+
if isinstance(self.connection, asyncpg.pool.Pool):
|
|
93
|
+
await self.connection.close()
|
|
94
|
+
else:
|
|
95
|
+
await self.connection.close()
|
|
96
|
+
self.connection = None
|
|
97
|
+
return True
|
|
98
|
+
|
pgconnect/DataType.py
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
class DataType:
|
|
5
|
+
"""
|
|
6
|
+
A class to represent PostgreSQL data types.
|
|
7
|
+
"""
|
|
8
|
+
def __init__(self, type_name: str):
|
|
9
|
+
self.type_name = type_name
|
|
10
|
+
self.constraints = []
|
|
11
|
+
self.length = None
|
|
12
|
+
|
|
13
|
+
def primary_key(self):
|
|
14
|
+
if self.type_name in ["TEXT", "BYTEA", "JSON", "JSONB", "ARRAY"]:
|
|
15
|
+
raise ValueError(f"{self.type_name} cannot be a primary key")
|
|
16
|
+
self.constraints.append("PRIMARY KEY")
|
|
17
|
+
return self
|
|
18
|
+
|
|
19
|
+
def not_null(self):
|
|
20
|
+
self.constraints.append("NOT NULL")
|
|
21
|
+
return self
|
|
22
|
+
|
|
23
|
+
def unique(self):
|
|
24
|
+
if self.type_name in ["TEXT", "BYTEA", "JSON", "JSONB", "ARRAY"]:
|
|
25
|
+
raise ValueError(f"{self.type_name} cannot be unique")
|
|
26
|
+
self.constraints.append("UNIQUE")
|
|
27
|
+
return self
|
|
28
|
+
|
|
29
|
+
def default(self, value: Any):
|
|
30
|
+
if self.type_name in ["BYTEA", "ARRAY"]:
|
|
31
|
+
raise ValueError(f"{self.type_name} cannot have a default value")
|
|
32
|
+
if self.type_name in ["JSON", "JSONB"]:
|
|
33
|
+
value = json.dumps(value)
|
|
34
|
+
self.constraints.append(f"DEFAULT '{value}'")
|
|
35
|
+
return self
|
|
36
|
+
|
|
37
|
+
def check(self, condition: str):
|
|
38
|
+
self.constraints.append(f"CHECK ({condition})")
|
|
39
|
+
return self
|
|
40
|
+
|
|
41
|
+
def references(self, table: str, column: str):
|
|
42
|
+
if self.type_name in ["TEXT", "BYTEA", "JSON", "JSONB", "ARRAY"]:
|
|
43
|
+
raise ValueError(f"{self.type_name} cannot reference another table")
|
|
44
|
+
self.constraints.append(f"REFERENCES {table}({column})")
|
|
45
|
+
return self
|
|
46
|
+
|
|
47
|
+
def length(self, length: int):
|
|
48
|
+
if self.type_name not in ["VARCHAR", "CHAR"]:
|
|
49
|
+
raise ValueError(f"Length can only be set for VARCHAR and CHAR types")
|
|
50
|
+
self.type_name = f"{self.type_name}({length})"
|
|
51
|
+
return self
|
|
52
|
+
|
|
53
|
+
def __str__(self):
|
|
54
|
+
return f"{self.type_name} {' '.join(self.constraints)}"
|
|
55
|
+
|
|
56
|
+
@classmethod
|
|
57
|
+
def INT(cls):
|
|
58
|
+
return cls("INTEGER")
|
|
59
|
+
|
|
60
|
+
@classmethod
|
|
61
|
+
def SMALLINT(cls):
|
|
62
|
+
return cls("SMALLINT")
|
|
63
|
+
|
|
64
|
+
@classmethod
|
|
65
|
+
def BIGINT(cls):
|
|
66
|
+
return cls("BIGINT")
|
|
67
|
+
|
|
68
|
+
@classmethod
|
|
69
|
+
def SERIAL(cls):
|
|
70
|
+
return cls("SERIAL")
|
|
71
|
+
|
|
72
|
+
@classmethod
|
|
73
|
+
def BIGSERIAL(cls):
|
|
74
|
+
return cls("BIGSERIAL")
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def REAL(cls):
|
|
78
|
+
return cls("REAL")
|
|
79
|
+
|
|
80
|
+
@classmethod
|
|
81
|
+
def DOUBLE_PRECISION(cls):
|
|
82
|
+
return cls("DOUBLE PRECISION")
|
|
83
|
+
|
|
84
|
+
@classmethod
|
|
85
|
+
def NUMERIC(cls, precision: int = 10, scale: int = 0):
|
|
86
|
+
return cls(f"NUMERIC({precision}, {scale})")
|
|
87
|
+
|
|
88
|
+
@classmethod
|
|
89
|
+
def DECIMAL(cls, precision: int = 10, scale: int = 0):
|
|
90
|
+
return cls(f"DECIMAL({precision}, {scale})")
|
|
91
|
+
|
|
92
|
+
@classmethod
|
|
93
|
+
def MONEY(cls):
|
|
94
|
+
return cls("MONEY")
|
|
95
|
+
|
|
96
|
+
@classmethod
|
|
97
|
+
def TEXT(cls):
|
|
98
|
+
return cls("TEXT")
|
|
99
|
+
|
|
100
|
+
@classmethod
|
|
101
|
+
def VARCHAR(cls, length: int = 255):
|
|
102
|
+
return cls(f"VARCHAR({length})")
|
|
103
|
+
|
|
104
|
+
@classmethod
|
|
105
|
+
def CHAR(cls, length: int = 1):
|
|
106
|
+
return cls(f"CHAR({length})")
|
|
107
|
+
|
|
108
|
+
@classmethod
|
|
109
|
+
def BYTEA(cls):
|
|
110
|
+
return cls("BYTEA")
|
|
111
|
+
|
|
112
|
+
@classmethod
|
|
113
|
+
def TIMESTAMP(cls):
|
|
114
|
+
return cls("TIMESTAMP")
|
|
115
|
+
|
|
116
|
+
@classmethod
|
|
117
|
+
def TIMESTAMPTZ(cls):
|
|
118
|
+
return cls("TIMESTAMPTZ")
|
|
119
|
+
|
|
120
|
+
@classmethod
|
|
121
|
+
def DATE(cls):
|
|
122
|
+
return cls("DATE")
|
|
123
|
+
|
|
124
|
+
@classmethod
|
|
125
|
+
def TIME(cls):
|
|
126
|
+
return cls("TIME")
|
|
127
|
+
|
|
128
|
+
@classmethod
|
|
129
|
+
def TIMETZ(cls):
|
|
130
|
+
return cls("TIMETZ")
|
|
131
|
+
|
|
132
|
+
@classmethod
|
|
133
|
+
def INTERVAL(cls):
|
|
134
|
+
return cls("INTERVAL")
|
|
135
|
+
|
|
136
|
+
@classmethod
|
|
137
|
+
def BOOLEAN(cls):
|
|
138
|
+
return cls("BOOLEAN")
|
|
139
|
+
|
|
140
|
+
@classmethod
|
|
141
|
+
def UUID(cls):
|
|
142
|
+
return cls("UUID")
|
|
143
|
+
|
|
144
|
+
@classmethod
|
|
145
|
+
def JSON(cls):
|
|
146
|
+
return cls("JSON")
|
|
147
|
+
|
|
148
|
+
@classmethod
|
|
149
|
+
def JSONB(cls):
|
|
150
|
+
return cls("JSONB")
|
|
151
|
+
|
|
152
|
+
@classmethod
|
|
153
|
+
def CIDR(cls):
|
|
154
|
+
return cls("CIDR")
|
|
155
|
+
|
|
156
|
+
@classmethod
|
|
157
|
+
def INET(cls):
|
|
158
|
+
return cls("INET")
|
|
159
|
+
|
|
160
|
+
@classmethod
|
|
161
|
+
def MACADDR(cls):
|
|
162
|
+
return cls("MACADDR")
|
|
163
|
+
|
|
164
|
+
@classmethod
|
|
165
|
+
def POINT(cls):
|
|
166
|
+
return cls("POINT")
|
|
167
|
+
|
|
168
|
+
@classmethod
|
|
169
|
+
def LINE(cls):
|
|
170
|
+
return cls("LINE")
|
|
171
|
+
|
|
172
|
+
@classmethod
|
|
173
|
+
def LSEG(cls):
|
|
174
|
+
return cls("LSEG")
|
|
175
|
+
|
|
176
|
+
@classmethod
|
|
177
|
+
def BOX(cls):
|
|
178
|
+
return cls("BOX")
|
|
179
|
+
|
|
180
|
+
@classmethod
|
|
181
|
+
def PATH(cls):
|
|
182
|
+
return cls("PATH")
|
|
183
|
+
|
|
184
|
+
@classmethod
|
|
185
|
+
def POLYGON(cls):
|
|
186
|
+
return cls("POLYGON")
|
|
187
|
+
|
|
188
|
+
@classmethod
|
|
189
|
+
def CIRCLE(cls):
|
|
190
|
+
return cls("CIRCLE")
|
|
191
|
+
|
|
192
|
+
@classmethod
|
|
193
|
+
def ARRAY(cls, base_type: str):
|
|
194
|
+
return cls(f"{base_type}[]")
|
|
195
|
+
|
|
196
|
+
@classmethod
|
|
197
|
+
def INT4RANGE(cls):
|
|
198
|
+
return cls("INT4RANGE")
|
|
199
|
+
|
|
200
|
+
@classmethod
|
|
201
|
+
def INT8RANGE(cls):
|
|
202
|
+
return cls("INT8RANGE")
|
|
203
|
+
|
|
204
|
+
@classmethod
|
|
205
|
+
def NUMRANGE(cls):
|
|
206
|
+
return cls("NUMRANGE")
|
|
207
|
+
|
|
208
|
+
@classmethod
|
|
209
|
+
def TSRANGE(cls):
|
|
210
|
+
return cls("TSRANGE")
|
|
211
|
+
|
|
212
|
+
@classmethod
|
|
213
|
+
def TSTZRANGE(cls):
|
|
214
|
+
return cls("TSTZRANGE")
|
|
215
|
+
|
|
216
|
+
@classmethod
|
|
217
|
+
def DATERANGE(cls):
|
|
218
|
+
return cls("DATERANGE")
|
|
219
|
+
|
|
220
|
+
@classmethod
|
|
221
|
+
def HSTORE(cls):
|
|
222
|
+
return cls("HSTORE")
|
|
223
|
+
|
|
224
|
+
@classmethod
|
|
225
|
+
def XML(cls):
|
|
226
|
+
return cls("XML")
|
|
227
|
+
|
|
228
|
+
@classmethod
|
|
229
|
+
def TSQUERY(cls):
|
|
230
|
+
return cls("TSQUERY")
|
|
231
|
+
|
|
232
|
+
@classmethod
|
|
233
|
+
def TSVECTOR(cls):
|
|
234
|
+
return cls("TSVECTOR")
|