summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/dialects/postgresql/base.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2022-02-11 04:54:45 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2022-06-01 11:40:56 -0400
commit349a7c5e0e2aeeac98fad789b0043a4bdfeed837 (patch)
tree20c314304023752e4cd7bc7894f042cc7b9d7064 /lib/sqlalchemy/dialects/postgresql/base.py
parent4fb6aca6cfc593c64cd7102cd70924d1b7caea05 (diff)
downloadsqlalchemy-349a7c5e0e2aeeac98fad789b0043a4bdfeed837.tar.gz
add backend agnostic UUID datatype
Added new backend-agnostic :class:`_types.Uuid` datatype generalized from the PostgreSQL dialects to now be a core type, as well as migrated :class:`_types.UUID` from the PostgreSQL dialect. Thanks to Trevor Gross for the help on this. also includes: * corrects some missing behaviors in the suite literal fixtures test where row round trips weren't being correctly asserted. * fixes some of the ISO literal date rendering added in 952383f9ee0 for #5052 to truncate datetime strings for date/time datatypes in the same way that drivers typically do for bound parameters; this was not working fully and wasn't caught by the broken test fixture Fixes: #7212 Change-Id: I981ac6d34d278c18281c144430a528764c241b04
Diffstat (limited to 'lib/sqlalchemy/dialects/postgresql/base.py')
-rw-r--r--lib/sqlalchemy/dialects/postgresql/base.py115
1 files changed, 14 insertions, 101 deletions
diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py
index 0aeeb806b..146e59c4d 100644
--- a/lib/sqlalchemy/dialects/postgresql/base.py
+++ b/lib/sqlalchemy/dialects/postgresql/base.py
@@ -1453,9 +1453,6 @@ from collections import defaultdict
import datetime as dt
import re
from typing import Any
-from typing import overload
-from typing import TypeVar
-from uuid import UUID as _python_UUID
from . import array as _array
from . import dml
@@ -1489,8 +1486,8 @@ from ...types import NUMERIC
from ...types import REAL
from ...types import SMALLINT
from ...types import TEXT
+from ...types import UUID as UUID
from ...types import VARCHAR
-from ...util.typing import Literal
IDX_USING = re.compile(r"^(?:btree|hash|gist|gin|[\w_]+)$", re.I)
@@ -1606,6 +1603,11 @@ _FLOAT_TYPES = (700, 701, 1021, 1022)
_INT_TYPES = (20, 21, 23, 26, 1005, 1007, 1016)
+class PGUuid(UUID):
+ render_bind_cast = True
+ render_literal_cast = True
+
+
class BYTEA(sqltypes.LargeBinary[bytes]):
__visit_name__ = "BYTEA"
@@ -1765,103 +1767,6 @@ class BIT(sqltypes.TypeEngine[int]):
PGBit = BIT
-_UUID_RETURN = TypeVar("_UUID_RETURN", str, _python_UUID)
-
-
-class UUID(sqltypes.TypeEngine[_UUID_RETURN]):
-
- """PostgreSQL UUID type.
-
- Represents the UUID column type, interpreting
- data either as natively returned by the DBAPI
- or as Python uuid objects.
-
- The UUID type is currently known to work within the prominent DBAPI
- drivers supported by SQLAlchemy including psycopg, psycopg2, pg8000 and
- asyncpg. Support for other DBAPI drivers may be incomplete or non-present.
-
- """
-
- __visit_name__ = "UUID"
-
- @overload
- def __init__(self: "UUID[_python_UUID]", as_uuid: Literal[True] = ...):
- ...
-
- @overload
- def __init__(self: "UUID[str]", as_uuid: Literal[False] = ...):
- ...
-
- def __init__(self, as_uuid: bool = True):
- """Construct a UUID type.
-
-
- :param as_uuid=True: if True, values will be interpreted
- as Python uuid objects, converting to/from string via the
- DBAPI.
-
- .. versionchanged: 2 ``as_uuid`` now defaults to ``True``.
-
- """
- self.as_uuid = as_uuid
-
- def coerce_compared_value(self, op, value):
- """See :meth:`.TypeEngine.coerce_compared_value` for a description."""
-
- if isinstance(value, str):
- return self
- else:
- return super(UUID, self).coerce_compared_value(op, value)
-
- def bind_processor(self, dialect):
- if self.as_uuid:
-
- def process(value):
- if value is not None:
- value = str(value)
- return value
-
- return process
- else:
- return None
-
- def result_processor(self, dialect, coltype):
- if self.as_uuid:
-
- def process(value):
- if value is not None:
- value = _python_UUID(value)
- return value
-
- return process
- else:
- return None
-
- def literal_processor(self, dialect):
- if self.as_uuid:
-
- def process(value):
- if value is not None:
- value = "'%s'::UUID" % value
- return value
-
- return process
- else:
-
- def process(value):
- if value is not None:
- value = "'%s'" % value
- return value
-
- return process
-
- @property
- def python_type(self):
- return _python_UUID if self.as_uuid else str
-
-
-PGUuid = UUID
-
class TSVECTOR(sqltypes.TypeEngine[Any]):
@@ -2162,6 +2067,7 @@ colspecs = {
sqltypes.Enum: ENUM,
sqltypes.JSON.JSONPathType: _json.JSONPathType,
sqltypes.JSON: _json.JSON,
+ UUID: PGUuid,
}
ischema_names = {
@@ -3043,6 +2949,12 @@ class PGTypeCompiler(compiler.GenericTypeCompiler):
compiled = "BIT(%d)" % type_.length
return compiled
+ def visit_uuid(self, type_, **kw):
+ if type_.native_uuid:
+ return self.visit_UUID(type_, **kw)
+ else:
+ return super().visit_uuid(type_, **kw)
+
def visit_UUID(self, type_, **kw):
return "UUID"
@@ -3267,6 +3179,7 @@ class PGDialect(default.DefaultDialect):
supports_native_enum = True
supports_native_boolean = True
+ supports_native_uuid = True
supports_smallserial = True
supports_sequences = True