]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Support normal /materialized views in PG separately
authorSebastian Bank <sebastian.bank@uni-leipzig.de>
Tue, 12 Apr 2016 03:16:39 +0000 (23:16 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 6 Jun 2016 22:57:10 +0000 (18:57 -0400)
Fixes: #3588
Change-Id: Ifbfcab67375f289ddb5c4522f4b803cb8b7c34de
Pull-request: https://github.com/zzzeek/sqlalchemy/pull/250

doc/build/changelog/changelog_11.rst
doc/build/changelog/migration_11.rst
lib/sqlalchemy/dialects/postgresql/base.py
test/dialect/postgresql/test_reflection.py

index 297be5d2d20677ecbcd572b92343ab5da7a4fa84..637d212b12bc0b6396732332c4ef1d7818da6ec5 100644 (file)
         to be formed with the same set of columns, allowing them to be
         batched.  Pull request courtesy Tobias Sauerwein.
 
+    .. change::
+        :tags: feature, postgresql
+        :tickets: 3588
+
+        Added new parameter :paramref:`.PGInspector.get_view_names.include`,
+        allowing specification for what kinds of views should be returned.
+        Currently "plain" and "materialized" views are included.  Pull
+        request courtesy Sebastian Bank.
+
     .. change::
         :tags: feature, mssql
 
index d9f48fcb1dbdbcea790ca3941cac969ed3c33a2e..723d076639e7f3a2890c13542175e214e4c1fe59 100644 (file)
@@ -2090,6 +2090,21 @@ both within the method :meth:`.Inspector.get_check_constraints` as well
 as within :class:`.Table` reflection within the :attr:`.Table.constraints`
 collection.
 
+"Plain" and "Materialized" views can be inspected separately
+------------------------------------------------------------
+
+The new argument :paramref:`.PGInspector.get_view_names.include`
+allows specification of which sub-types of views should be returned::
+
+    from sqlalchemy import inspect
+    insp = inspect(engine)
+
+    plain_views = insp.get_view_names(include='plain')
+    all_views = insp.get_view_names(include=('plain', 'materialized'))
+
+:ticket:`3588`
+
+
 Added tablespace option to Index
 --------------------------------
 
index 2356458b962500821111852f7753d623a001e9de..924c8d90250355981802fe3030af3aac12926324 100644 (file)
@@ -1552,6 +1552,24 @@ class PGInspector(reflection.Inspector):
         schema = schema or self.default_schema_name
         return self.dialect._get_foreign_table_names(self.bind, schema)
 
+    def get_view_names(self, schema=None, include=('plain', 'materialized')):
+        """Return all view names in `schema`.
+
+        :param schema: Optional, retrieve names from a non-default schema.
+         For special quoting, use :class:`.quoted_name`.
+
+        :param include: specify which types of views to return.  Passed
+         as a string value (for a single type) or a tuple (for any number
+         of types).  Defaults to ``('plain', 'materialized')``.
+
+         .. versionadded:: 1.1
+
+        """
+
+        return self.dialect.get_view_names(self.bind, schema,
+                                           info_cache=self.info_cache,
+                                           include=include)
+
 
 class CreateEnumType(schema._CreateDropBase):
     __visit_name__ = "create_enum_type"
@@ -1953,11 +1971,27 @@ class PGDialect(default.DefaultDialect):
         return [name for name, in result]
 
     @reflection.cache
-    def get_view_names(self, connection, schema=None, **kw):
+    def get_view_names(
+            self, connection, schema=None,
+            include=('plain', 'materialized'), **kw):
+
+        include_kind = {'plain': 'v', 'materialized': 'm'}
+        try:
+            kinds = [include_kind[i] for i in util.to_list(include)]
+        except KeyError:
+            raise ValueError(
+                "include %r unknown, needs to be a sequence containing "
+                "one or both of 'plain' and 'materialized'" % (include,))
+        if not kinds:
+            raise ValueError(
+                "empty include, needs to be a sequence containing "
+                "one or both of 'plain' and 'materialized'")
+
         result = connection.execute(
             sql.text("SELECT c.relname FROM pg_class c "
                      "JOIN pg_namespace n ON n.oid = c.relnamespace "
-                     "WHERE n.nspname = :schema AND c.relkind IN ('v', 'm')"
+                     "WHERE n.nspname = :schema AND c.relkind IN (%s)" %
+                     (", ".join("'%s'" % elem for elem in kinds))
                      ).columns(relname=sqltypes.Unicode),
             schema=schema if schema is not None else self.default_schema_name)
         return [name for name, in result]
index a0f9dcd49ac0f2072bc8173d3fde4eb622259e09..84aeef130bced5aab0deb0e63ab22916d9336307 100644 (file)
@@ -130,7 +130,27 @@ class MaterializedViewReflectionTest(
 
     def test_get_view_names(self):
         insp = inspect(testing.db)
-        eq_(set(insp.get_view_names()), set(['test_mview', 'test_regview']))
+        eq_(set(insp.get_view_names()), set(['test_regview', 'test_mview']))
+
+    def test_get_view_names_plain(self):
+        insp = inspect(testing.db)
+        eq_(
+            set(insp.get_view_names(include=('plain',))),
+            set(['test_regview']))
+
+    def test_get_view_names_plain_string(self):
+        insp = inspect(testing.db)
+        eq_(set(insp.get_view_names(include='plain')), set(['test_regview']))
+
+    def test_get_view_names_materialized(self):
+        insp = inspect(testing.db)
+        eq_(
+            set(insp.get_view_names(include=('materialized',))),
+            set(['test_mview']))
+
+    def test_get_view_names_empty(self):
+        insp = inspect(testing.db)
+        assert_raises(ValueError, insp.get_view_names, include=())
 
     def test_get_view_definition(self):
         insp = inspect(testing.db)