Add reflection support for Postgresql partitioned tables

Added rudimental support for reflection of Postgresql
partitioned tables, e.g. that relkind='p' is added to reflection
queries that return table information.

Fixes: #4237
Change-Id: I66fd10b002e4ed21ea13b13a7e35a85f66bdea75
This commit is contained in:
Mike Bayer
2018-10-01 16:23:33 -04:00
parent 29d54ab69b
commit f1ca155cea
4 changed files with 95 additions and 2 deletions
+36
View File
@@ -409,6 +409,42 @@ Key Behavioral Changes - Core
Dialect Improvements and Changes - PostgreSQL
=============================================
.. _change_4237:
Added basic reflection support for Postgresql paritioned tables
---------------------------------------------------------------
SQLAlchemy can render the "PARTITION BY" sequnce within a Postgresql
CREATE TABLE statement using the flag ``postgresql_partition_by``, added in
version 1.2.6. However, the ``'p'`` type was not part of the reflection
queries used until now.
Given a schema such as::
dv = Table(
'data_values', metadata,
Column('modulus', Integer, nullable=False),
Column('data', String(30)),
postgresql_partition_by='range(modulus)')
sa.event.listen(
dv,
"after_create",
sa.DDL(
"CREATE TABLE data_values_4_10 PARTITION OF data_values "
"FOR VALUES FROM (4) TO (10)")
)
The two table names ``'data_values'`` and ``'data_values_4_10'`` will come
back from :meth:`.Inspector.get_table_names` and additionally the columns
will come back from ``Inspector.get_columns('data_values')`` as well
as ``Inspector.get_columns('data_values_4_10')``. This also extends to the
use of ``Table(..., autoload=True)`` with these tables.
:ticket:`4237`
Dialect Improvements and Changes - MySQL
=============================================
+11
View File
@@ -0,0 +1,11 @@
.. change::
:tags: feature, postgresql
:tickets: 4237
Added rudimental support for reflection of Postgresql
partitioned tables, e.g. that relkind='p' is added to reflection
queries that return table information.
.. seealso::
:ref:`change_4237`
+3 -2
View File
@@ -2460,7 +2460,8 @@ class PGDialect(default.DefaultDialect):
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE (%s)
AND c.relname = :table_name AND c.relkind in ('r', 'v', 'm', 'f')
AND c.relname = :table_name AND c.relkind in
('r', 'v', 'm', 'f', 'p')
""" % schema_where_clause
# Since we're binding to unicode, table_name and schema_name must be
# unicode.
@@ -2491,7 +2492,7 @@ class PGDialect(default.DefaultDialect):
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 = 'r'"
"WHERE n.nspname = :schema AND c.relkind in ('r', 'p')"
).columns(relname=sqltypes.Unicode),
schema=schema if schema is not None else self.default_schema_name)
return [name for name, in result]
@@ -74,6 +74,51 @@ class ForeignTableReflectionTest(fixtures.TablesTest, AssertsExecutionResults):
eq_(names, ['testtable'])
class PartitionedReflectionTest(
fixtures.TablesTest, AssertsExecutionResults):
# partitioned table reflection, issue #4237
__only_on__ = 'postgresql >= 10'
__backend__ = True
@classmethod
def define_tables(cls, metadata):
# the actual function isn't reflected yet
dv = Table(
'data_values', metadata,
Column('modulus', Integer, nullable=False),
Column('data', String(30)),
postgresql_partition_by='range(modulus)')
# looks like this is reflected prior to #4237
sa.event.listen(
dv,
"after_create",
sa.DDL(
"CREATE TABLE data_values_4_10 PARTITION OF data_values "
"FOR VALUES FROM (4) TO (10)")
)
def test_get_tablenames(self):
assert {'data_values', 'data_values_4_10'}.issubset(
inspect(testing.db).get_table_names()
)
def test_reflect_cols(self):
cols = inspect(testing.db).get_columns('data_values')
eq_(
[c['name'] for c in cols],
['modulus', 'data']
)
def test_reflect_cols_from_partition(self):
cols = inspect(testing.db).get_columns('data_values_4_10')
eq_(
[c['name'] for c in cols],
['modulus', 'data']
)
class MaterializedViewReflectionTest(
fixtures.TablesTest, AssertsExecutionResults):
"""Test reflection on materialized views"""