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
=============================================
--- /dev/null
+.. 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`
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.
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]
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"""