Refs #29722 -- Added introspection of materialized views for Oracle.
Thanks Tim Graham for the review.
This commit is contained in:
parent
26c2a6ff88
commit
f091ea3515
|
@ -151,6 +151,9 @@ class BaseDatabaseFeatures:
|
|||
# Can the backend introspect the column order (ASC/DESC) for indexes?
|
||||
supports_index_column_ordering = True
|
||||
|
||||
# Does the backend support introspection of materialized views?
|
||||
can_introspect_materialized_views = False
|
||||
|
||||
# Support for the DISTINCT ON clause
|
||||
can_distinct_on_fields = False
|
||||
|
||||
|
|
|
@ -241,11 +241,14 @@ class DatabaseCreation(BaseDatabaseCreation):
|
|||
if not success and self._test_settings_get('PASSWORD') is None:
|
||||
set_password = 'ALTER USER %(user)s IDENTIFIED BY "%(password)s"'
|
||||
self._execute_statements(cursor, [set_password], parameters, verbosity)
|
||||
# Most test-suites can be run without the create-view privilege. But some need it.
|
||||
extra = "GRANT CREATE VIEW TO %(user)s"
|
||||
success = self._execute_allow_fail_statements(cursor, [extra], parameters, verbosity, 'ORA-01031')
|
||||
if not success and verbosity >= 2:
|
||||
self.log('Failed to grant CREATE VIEW permission to test user. This may be ok.')
|
||||
# Most test suites can be run without "create view" and
|
||||
# "create materialized view" privileges. But some need it.
|
||||
for object_type in ('VIEW', 'MATERIALIZED VIEW'):
|
||||
extra = 'GRANT CREATE %(object_type)s TO %(user)s'
|
||||
parameters['object_type'] = object_type
|
||||
success = self._execute_allow_fail_statements(cursor, [extra], parameters, verbosity, 'ORA-01031')
|
||||
if not success and verbosity >= 2:
|
||||
self.log('Failed to grant CREATE %s permission to test user. This may be ok.' % object_type)
|
||||
|
||||
def _execute_test_db_destruction(self, cursor, parameters, verbosity):
|
||||
if verbosity >= 2:
|
||||
|
|
|
@ -21,6 +21,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
|||
truncates_names = True
|
||||
supports_tablespaces = True
|
||||
supports_sequence_reset = False
|
||||
can_introspect_materialized_views = True
|
||||
can_introspect_time_field = False
|
||||
atomic_transactions = False
|
||||
supports_combined_alters = False
|
||||
|
|
|
@ -48,8 +48,20 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
|||
|
||||
def get_table_list(self, cursor):
|
||||
"""Return a list of table and view names in the current database."""
|
||||
cursor.execute("SELECT TABLE_NAME, 't' FROM USER_TABLES UNION ALL "
|
||||
"SELECT VIEW_NAME, 'v' FROM USER_VIEWS")
|
||||
cursor.execute("""
|
||||
SELECT table_name, 't'
|
||||
FROM user_tables
|
||||
WHERE
|
||||
NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM user_mviews
|
||||
WHERE user_mviews.mview_name = user_tables.table_name
|
||||
)
|
||||
UNION ALL
|
||||
SELECT view_name, 'v' FROM user_views
|
||||
UNION ALL
|
||||
SELECT mview_name, 'v' FROM user_mviews
|
||||
""")
|
||||
return [TableInfo(self.identifier_converter(row[0]), row[1]) for row in cursor.fetchall()]
|
||||
|
||||
def get_table_description(self, cursor, table_name):
|
||||
|
|
|
@ -21,6 +21,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
|||
supports_transactions = True
|
||||
can_introspect_autofield = True
|
||||
can_introspect_ip_address_field = True
|
||||
can_introspect_materialized_views = True
|
||||
can_introspect_small_integer_field = True
|
||||
can_distinct_on_fields = True
|
||||
can_rollback_ddl = True
|
||||
|
|
|
@ -764,9 +764,10 @@ and a user granted ``RESOURCE WITH ADMIN OPTION`` can grant ``RESOURCE``, such
|
|||
a user cannot grant the individual privileges (e.g. ``CREATE TABLE``), and thus
|
||||
``RESOURCE WITH ADMIN OPTION`` is not usually sufficient for running tests.
|
||||
|
||||
Some test suites also create views; to run these, the user also needs
|
||||
the ``CREATE VIEW WITH ADMIN OPTION`` privilege. In particular, this is needed
|
||||
for Django's own test suite.
|
||||
Some test suites also create views or materialized views; to run these, the
|
||||
user also needs ``CREATE VIEW WITH ADMIN OPTION`` and
|
||||
``CREATE MATERIALIZED VIEW WITH ADMIN OPTION`` privileges. In particular, this
|
||||
is needed for Django's own test suite.
|
||||
|
||||
All of these privileges are included in the DBA role, which is appropriate
|
||||
for use on a private developer's database.
|
||||
|
|
|
@ -399,6 +399,12 @@ it because ``True`` is its default value).
|
|||
Database-specific notes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Oracle
|
||||
^^^^^^
|
||||
|
||||
* Models are created for materialized views if :option:`--include-views` is
|
||||
used.
|
||||
|
||||
PostgreSQL
|
||||
^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -182,7 +182,7 @@ Management Commands
|
|||
* :djadmin:`inspectdb` now creates models for foreign tables on PostgreSQL.
|
||||
|
||||
* :option:`inspectdb --include-views` now creates models for materialized views
|
||||
on PostgreSQL.
|
||||
on Oracle and PostgreSQL.
|
||||
|
||||
* The new :option:`inspectdb --include-partitions` option allows creating
|
||||
models for partition tables on PostgreSQL. In older versions, models are
|
||||
|
|
|
@ -310,16 +310,16 @@ class InspectDBTransactionalTests(TransactionTestCase):
|
|||
with connection.cursor() as cursor:
|
||||
cursor.execute('DROP VIEW inspectdb_people_view')
|
||||
|
||||
@skipUnless(connection.vendor == 'postgresql', 'PostgreSQL specific SQL')
|
||||
@skipUnlessDBFeature('can_introspect_materialized_views')
|
||||
def test_include_materialized_views(self):
|
||||
"""inspectdb --include-views creates models for database materialized views."""
|
||||
"""inspectdb --include-views creates models for materialized views."""
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(
|
||||
'CREATE MATERIALIZED VIEW inspectdb_people_materialized_view AS '
|
||||
'CREATE MATERIALIZED VIEW inspectdb_people_materialized AS '
|
||||
'SELECT id, name FROM inspectdb_people'
|
||||
)
|
||||
out = StringIO()
|
||||
view_model = 'class InspectdbPeopleMaterializedView(models.Model):'
|
||||
view_model = 'class InspectdbPeopleMaterialized(models.Model):'
|
||||
view_managed = 'managed = False # Created from a view.'
|
||||
try:
|
||||
call_command('inspectdb', table_name_filter=inspectdb_tables_only, stdout=out)
|
||||
|
@ -332,7 +332,7 @@ class InspectDBTransactionalTests(TransactionTestCase):
|
|||
self.assertIn(view_managed, with_views_output)
|
||||
finally:
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute('DROP MATERIALIZED VIEW IF EXISTS inspectdb_people_materialized_view')
|
||||
cursor.execute('DROP MATERIALIZED VIEW inspectdb_people_materialized')
|
||||
|
||||
@skipUnless(connection.vendor == 'postgresql', 'PostgreSQL specific SQL')
|
||||
@skipUnlessDBFeature('supports_table_partitions')
|
||||
|
|
Loading…
Reference in New Issue