database-wrapper-pgsql 0.2.7__py3-none-any.whl → 0.2.9__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.
- database_wrapper_pgsql/__init__.py +2 -0
- database_wrapper_pgsql/pg_introspector.py +72 -0
- database_wrapper_pgsql/type_mapping.py +54 -0
- {database_wrapper_pgsql-0.2.7.dist-info → database_wrapper_pgsql-0.2.9.dist-info}/METADATA +2 -2
- {database_wrapper_pgsql-0.2.7.dist-info → database_wrapper_pgsql-0.2.9.dist-info}/RECORD +7 -5
- {database_wrapper_pgsql-0.2.7.dist-info → database_wrapper_pgsql-0.2.9.dist-info}/WHEEL +0 -0
- {database_wrapper_pgsql-0.2.7.dist-info → database_wrapper_pgsql-0.2.9.dist-info}/top_level.txt +0 -0
|
@@ -24,6 +24,7 @@ from .connector import (
|
|
|
24
24
|
PgConnectionTypeAsync,
|
|
25
25
|
PgCursorTypeAsync,
|
|
26
26
|
)
|
|
27
|
+
from .pg_introspector import PostgresIntrospector
|
|
27
28
|
|
|
28
29
|
# Set the logger to a quiet default, can be enabled if needed
|
|
29
30
|
logger = logging.getLogger("database_wrapper_pgsql")
|
|
@@ -47,4 +48,5 @@ __all__ = [
|
|
|
47
48
|
"PgCursorTypeAsync",
|
|
48
49
|
# Helpers
|
|
49
50
|
"PgConfig",
|
|
51
|
+
"PostgresIntrospector",
|
|
50
52
|
]
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import psycopg
|
|
2
|
+
|
|
3
|
+
from database_wrapper import ColumnMetaIntrospector, DBIntrospector
|
|
4
|
+
from .type_mapping import map_db_type
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class PostgresIntrospector(DBIntrospector):
|
|
8
|
+
conn: psycopg.Connection
|
|
9
|
+
|
|
10
|
+
def map_db_type(self, db_type: str) -> str:
|
|
11
|
+
return map_db_type(db_type)
|
|
12
|
+
|
|
13
|
+
def get_table_columns(self, schema: str, table: str) -> list[ColumnMetaIntrospector]:
|
|
14
|
+
"""
|
|
15
|
+
Returns ColumnMeta including enum labels if column type is enum.
|
|
16
|
+
"""
|
|
17
|
+
q = """
|
|
18
|
+
WITH cols AS (
|
|
19
|
+
SELECT
|
|
20
|
+
a.attname AS col_name,
|
|
21
|
+
a.attnotnull AS not_null,
|
|
22
|
+
pg_catalog.format_type(a.atttypid, a.atttypmod) AS fmt_type,
|
|
23
|
+
t.typname AS typname,
|
|
24
|
+
t.typcategory AS typcategory,
|
|
25
|
+
a.atttypid AS typid,
|
|
26
|
+
pg_catalog.pg_get_expr(ad.adbin, ad.adrelid) AS default_expr
|
|
27
|
+
FROM pg_attribute a
|
|
28
|
+
JOIN pg_class c ON c.oid = a.attrelid
|
|
29
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
30
|
+
JOIN pg_type t ON t.oid = a.atttypid
|
|
31
|
+
LEFT JOIN pg_attrdef ad
|
|
32
|
+
ON ad.adrelid = a.attrelid
|
|
33
|
+
AND ad.adnum = a.attnum
|
|
34
|
+
WHERE n.nspname = %s
|
|
35
|
+
AND c.relname = %s
|
|
36
|
+
AND a.attnum > 0
|
|
37
|
+
AND NOT a.attisdropped
|
|
38
|
+
ORDER BY a.attnum
|
|
39
|
+
)
|
|
40
|
+
SELECT
|
|
41
|
+
cols.col_name,
|
|
42
|
+
cols.typname,
|
|
43
|
+
cols.fmt_type,
|
|
44
|
+
NOT not_null AS is_nullable,
|
|
45
|
+
default_expr,
|
|
46
|
+
CASE WHEN typcategory = 'E' THEN (
|
|
47
|
+
SELECT array_agg(e.enumlabel ORDER BY e.enumsortorder)
|
|
48
|
+
FROM pg_enum e
|
|
49
|
+
WHERE e.enumtypid = cols.typid
|
|
50
|
+
)
|
|
51
|
+
ELSE NULL
|
|
52
|
+
END AS enum_labels
|
|
53
|
+
FROM cols;
|
|
54
|
+
"""
|
|
55
|
+
with self.conn.cursor() as cur:
|
|
56
|
+
cur.execute(q, (schema, table))
|
|
57
|
+
rows = cur.fetchall()
|
|
58
|
+
|
|
59
|
+
out: list[ColumnMetaIntrospector] = []
|
|
60
|
+
for row in rows:
|
|
61
|
+
out.append(
|
|
62
|
+
ColumnMetaIntrospector(
|
|
63
|
+
col_name=row["col_name"],
|
|
64
|
+
db_type=row["typname"],
|
|
65
|
+
is_nullable=bool(row["is_nullable"]),
|
|
66
|
+
has_default=(row["default_expr"] is not None),
|
|
67
|
+
default_expr=row["default_expr"],
|
|
68
|
+
# enum_labels=list(row["enum_labels"]) if row["enum_labels"] else None,
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
return out
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# type_mapping_pg.py
|
|
2
|
+
from typing import Any, Optional, Tuple
|
|
3
|
+
from decimal import Decimal
|
|
4
|
+
import datetime
|
|
5
|
+
from database_wrapper import SerializeType
|
|
6
|
+
|
|
7
|
+
# Flip this if you want lossless decimals
|
|
8
|
+
USE_DECIMAL = False
|
|
9
|
+
|
|
10
|
+
_PG_TO_PY_BASE: dict[str, Tuple[type, Optional[SerializeType]]] = {
|
|
11
|
+
# integers
|
|
12
|
+
"int2": (int, None),
|
|
13
|
+
"int4": (int, None),
|
|
14
|
+
"int8": (int, None),
|
|
15
|
+
# floats
|
|
16
|
+
"float4": (float, None),
|
|
17
|
+
"float8": (float, None),
|
|
18
|
+
# bool
|
|
19
|
+
"bool": (bool, None),
|
|
20
|
+
"boolean": (bool, None),
|
|
21
|
+
# text
|
|
22
|
+
"text": (str, None),
|
|
23
|
+
"varchar": (str, None),
|
|
24
|
+
"bpchar": (str, None),
|
|
25
|
+
"citext": (str, None),
|
|
26
|
+
# json
|
|
27
|
+
"json": (dict[str, Any], SerializeType.JSON),
|
|
28
|
+
"jsonb": (dict[str, Any], SerializeType.JSON),
|
|
29
|
+
# temporal
|
|
30
|
+
"timestamptz": (datetime.datetime, SerializeType.DATETIME),
|
|
31
|
+
"timestamp": (datetime.datetime, SerializeType.DATETIME),
|
|
32
|
+
"date": (datetime.date, SerializeType.DATE),
|
|
33
|
+
"time": (datetime.time, SerializeType.TIME),
|
|
34
|
+
"timetz": (datetime.time, SerializeType.TIME),
|
|
35
|
+
# UUID
|
|
36
|
+
"uuid": (str, None), # or python's uuid.UUID if you prefer
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def map_db_type(
|
|
41
|
+
db_type: str, *, length: int | None = None, precision: int | None = None, scale: int | None = None
|
|
42
|
+
) -> tuple[type, Optional[SerializeType]]:
|
|
43
|
+
t = db_type.lower()
|
|
44
|
+
if t == "numeric":
|
|
45
|
+
if USE_DECIMAL:
|
|
46
|
+
return (Decimal, SerializeType.DECIMAL)
|
|
47
|
+
return (float, None)
|
|
48
|
+
|
|
49
|
+
# money: tends to need Decimal
|
|
50
|
+
if t in ("money", "smallmoney"):
|
|
51
|
+
return (Decimal, SerializeType.DECIMAL) if USE_DECIMAL else (float, None)
|
|
52
|
+
|
|
53
|
+
# fall back to base
|
|
54
|
+
return _PG_TO_PY_BASE.get(t, (str, None))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: database_wrapper_pgsql
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.9
|
|
4
4
|
Summary: database_wrapper for PostgreSQL database
|
|
5
5
|
Author-email: Gints Murans <gm@gm.lv>
|
|
6
6
|
License: GNU General Public License v3.0 (GPL-3.0)
|
|
@@ -32,7 +32,7 @@ Classifier: Topic :: Software Development
|
|
|
32
32
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
33
33
|
Requires-Python: >=3.8
|
|
34
34
|
Description-Content-Type: text/markdown
|
|
35
|
-
Requires-Dist: database_wrapper==0.2.
|
|
35
|
+
Requires-Dist: database_wrapper==0.2.9
|
|
36
36
|
Requires-Dist: psycopg[binary]>=3.2.0
|
|
37
37
|
Requires-Dist: psycopg[pool]>=3.2.0
|
|
38
38
|
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
database_wrapper_pgsql/__init__.py,sha256=
|
|
1
|
+
database_wrapper_pgsql/__init__.py,sha256=MKa2gKPeRh-nQxp_Jd1BxbmZtcow_M3LBtBe7hQhrWQ,1136
|
|
2
2
|
database_wrapper_pgsql/connector.py,sha256=Hicf9DHxOjv6H77ySdTi26YmKjlSTzOIWQrjETq3LRg,25027
|
|
3
3
|
database_wrapper_pgsql/db_wrapper_pgsql.py,sha256=Tm18dzSOINz4Z8xHWynLCPf-HmD_SFP0PYVE8ZPd_A4,1921
|
|
4
4
|
database_wrapper_pgsql/db_wrapper_pgsql_async.py,sha256=d4AZp_dHdmob7oJlEst2DnhMqpeXeG6WOzI8k5OldKg,2024
|
|
5
5
|
database_wrapper_pgsql/db_wrapper_pgsql_mixin.py,sha256=b4m7YSk5OjukuCMky_VwFT8TYCqjU2goNnSC2HOM0HA,5452
|
|
6
|
+
database_wrapper_pgsql/pg_introspector.py,sha256=MIhDFsvQ4a1bLQaCADOmvyV-Kr1cddlKFb9novf7bhw,2556
|
|
6
7
|
database_wrapper_pgsql/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
database_wrapper_pgsql
|
|
8
|
-
database_wrapper_pgsql-0.2.
|
|
9
|
-
database_wrapper_pgsql-0.2.
|
|
10
|
-
database_wrapper_pgsql-0.2.
|
|
8
|
+
database_wrapper_pgsql/type_mapping.py,sha256=TD1gEPNEidFfbofTYKRuuNNqHqPG0eiijoE9ICvV6SQ,1647
|
|
9
|
+
database_wrapper_pgsql-0.2.9.dist-info/METADATA,sha256=J0u0g_HR9YgRB2eTsgllHqsKVA6kE01vLXawmuI81Z0,3229
|
|
10
|
+
database_wrapper_pgsql-0.2.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
11
|
+
database_wrapper_pgsql-0.2.9.dist-info/top_level.txt,sha256=EQhZLk12wRdsSp-Lo3Jc4cXmNfG8y5EouNv_7OBCSGo,23
|
|
12
|
+
database_wrapper_pgsql-0.2.9.dist-info/RECORD,,
|
|
File without changes
|
{database_wrapper_pgsql-0.2.7.dist-info → database_wrapper_pgsql-0.2.9.dist-info}/top_level.txt
RENAMED
|
File without changes
|