]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Add postgresl.REGCLASS type for casting table names to OIDs and vice versa
authorSebastian Bank <sebastian.bank@uni-leipzig.de>
Mon, 2 Apr 2018 15:25:08 +0000 (11:25 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 3 Apr 2018 13:31:07 +0000 (09:31 -0400)
Fixes: #4160
Change-Id: Id0bdbad1be3a0950dc8f35895ee13d9264244722
Pull-request: https://github.com/zzzeek/sqlalchemy/pull/435

doc/build/changelog/unreleased_12/4160.rst [new file with mode: 0644]
lib/sqlalchemy/dialects/postgresql/__init__.py
lib/sqlalchemy/dialects/postgresql/base.py
test/dialect/postgresql/test_types.py

diff --git a/doc/build/changelog/unreleased_12/4160.rst b/doc/build/changelog/unreleased_12/4160.rst
new file mode 100644 (file)
index 0000000..859720c
--- /dev/null
@@ -0,0 +1,7 @@
+.. change::
+    :tags: feature, postgresql
+    :tickets: 4160
+    :versions: 1.3.0b1
+
+    Added new PG type :class:`.postgresql.REGCLASS` which assists in casting
+    table names to OID values.  Pull request courtesy Sebastian Bank.
index a985f06a9122a2ff2b41b57eb2ac10aa52b4ede0..d2f8057b6757d9e3c971ae49ac6499346cca9989 100644 (file)
@@ -10,7 +10,7 @@ from . import base, psycopg2, pg8000, pypostgresql, pygresql, \
 
 from .base import \
     INTEGER, BIGINT, SMALLINT, VARCHAR, CHAR, TEXT, NUMERIC, FLOAT, REAL, \
-    INET, CIDR, UUID, BIT, MACADDR, MONEY, OID, DOUBLE_PRECISION, \
+    INET, CIDR, UUID, BIT, MACADDR, MONEY, OID, REGCLASS, DOUBLE_PRECISION, \
     TIMESTAMP, TIME, DATE, BYTEA, BOOLEAN, INTERVAL, ENUM, TSVECTOR, \
     DropEnumType, CreateEnumType
 from .hstore import HSTORE, hstore
@@ -28,8 +28,8 @@ base.dialect = dialect = psycopg2.dialect
 __all__ = (
     'INTEGER', 'BIGINT', 'SMALLINT', 'VARCHAR', 'CHAR', 'TEXT', 'NUMERIC',
     'FLOAT', 'REAL', 'INET', 'CIDR', 'UUID', 'BIT', 'MACADDR', 'MONEY', 'OID',
-    'DOUBLE_PRECISION', 'TIMESTAMP', 'TIME', 'DATE', 'BYTEA', 'BOOLEAN',
-    'INTERVAL', 'ARRAY', 'ENUM', 'dialect', 'array', 'HSTORE',
+    'REGCLASS', 'DOUBLE_PRECISION', 'TIMESTAMP', 'TIME', 'DATE', 'BYTEA',
+    'BOOLEAN', 'INTERVAL', 'ARRAY', 'ENUM', 'dialect', 'array', 'HSTORE',
     'hstore', 'INT4RANGE', 'INT8RANGE', 'NUMRANGE', 'DATERANGE',
     'TSRANGE', 'TSTZRANGE', 'json', 'JSON', 'JSONB', 'Any', 'All',
     'DropEnumType', 'CreateEnumType', 'ExcludeConstraint',
index 1dffe8db93336b992f2c65e26d623852dbc4f9c3..c5b0db6ce5606a66182c25ea96c5db6acee558a6 100644 (file)
@@ -1000,6 +1000,16 @@ class OID(sqltypes.TypeEngine):
     __visit_name__ = "OID"
 
 
+class REGCLASS(sqltypes.TypeEngine):
+
+    """Provide the PostgreSQL REGCLASS type.
+
+    .. versionadded:: 1.2.7
+
+    """
+    __visit_name__ = "REGCLASS"
+
+
 class TIMESTAMP(sqltypes.TIMESTAMP):
 
     def __init__(self, timezone=False, precision=None):
@@ -1382,6 +1392,7 @@ ischema_names = {
     'macaddr': MACADDR,
     'money': MONEY,
     'oid': OID,
+    'regclass': REGCLASS,
     'double precision': DOUBLE_PRECISION,
     'timestamp': TIMESTAMP,
     'timestamp with time zone': TIMESTAMP,
@@ -1876,6 +1887,9 @@ class PGTypeCompiler(compiler.GenericTypeCompiler):
     def visit_OID(self, type_, **kw):
         return "OID"
 
+    def visit_REGCLASS(self, type_, **kw):
+        return "REGCLASS"
+
     def visit_FLOAT(self, type_, **kw):
         if not type_.precision:
             return "FLOAT"
index dea17bc2a9bb3e744492e4d291b9aaa68d887f3f..8aa9d1b1f59a5e902a6235e05b68d249ded6d7d5 100644 (file)
@@ -630,6 +630,46 @@ class OIDTest(fixtures.TestBase):
         assert isinstance(t2.c.y.type, postgresql.OID)
 
 
+class RegClassTest(fixtures.TestBase):
+    __only_on__ = 'postgresql'
+    __backend__ = True
+
+    @staticmethod
+    def _scalar(expression):
+        with testing.db.connect() as conn:
+            return conn.scalar(select([expression]))
+
+    def test_cast_name(self):
+        eq_(
+            self._scalar(cast('pg_class', postgresql.REGCLASS)),
+            'pg_class'
+        )
+
+    def test_cast_path(self):
+        eq_(
+            self._scalar(cast('pg_catalog.pg_class', postgresql.REGCLASS)),
+            'pg_class'
+        )
+
+    def test_cast_oid(self):
+        regclass = cast('pg_class', postgresql.REGCLASS)
+        oid = self._scalar(cast(regclass, postgresql.OID))
+        assert isinstance(oid, int)
+        eq_(self._scalar(cast(oid, postgresql.REGCLASS)), 'pg_class')
+
+    def test_cast_whereclause(self):
+        pga = Table('pg_attribute', MetaData(testing.db),
+                    Column('attrelid', postgresql.OID),
+                    Column('attname', String(64)))
+        with testing.db.connect() as conn:
+            oid = conn.scalar(
+                select([pga.c.attrelid]).where(
+                    pga.c.attrelid == cast('pg_class', postgresql.REGCLASS)
+                )
+            )
+        assert isinstance(oid, int)
+
+
 class NumericInterpretationTest(fixtures.TestBase):
     __only_on__ = 'postgresql'
     __backend__ = True