mirror of
https://github.com/django/django.git
synced 2024-12-22 17:16:24 +00:00
Fixed #34671 -- Fixed collation introspection for views and materialized views on Oracle.
Thanks Philipp Maino for the report.
This commit is contained in:
parent
c4a09499aa
commit
a6d30f5012
@ -110,6 +110,31 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||
Return a description of the table with the DB-API cursor.description
|
||||
interface.
|
||||
"""
|
||||
# A default collation for the given table/view/materialized view.
|
||||
cursor.execute(
|
||||
"""
|
||||
SELECT user_tables.default_collation
|
||||
FROM user_tables
|
||||
WHERE
|
||||
user_tables.table_name = UPPER(%s) AND
|
||||
NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM user_mviews
|
||||
WHERE user_mviews.mview_name = user_tables.table_name
|
||||
)
|
||||
UNION ALL
|
||||
SELECT user_views.default_collation
|
||||
FROM user_views
|
||||
WHERE user_views.view_name = UPPER(%s)
|
||||
UNION ALL
|
||||
SELECT user_mviews.default_collation
|
||||
FROM user_mviews
|
||||
WHERE user_mviews.mview_name = UPPER(%s)
|
||||
""",
|
||||
[table_name, table_name, table_name],
|
||||
)
|
||||
row = cursor.fetchone()
|
||||
default_table_collation = row[0] if row else ""
|
||||
# user_tab_columns gives data default for columns
|
||||
cursor.execute(
|
||||
"""
|
||||
@ -117,7 +142,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||
user_tab_cols.column_name,
|
||||
user_tab_cols.data_default,
|
||||
CASE
|
||||
WHEN user_tab_cols.collation = user_tables.default_collation
|
||||
WHEN user_tab_cols.collation = %s
|
||||
THEN NULL
|
||||
ELSE user_tab_cols.collation
|
||||
END collation,
|
||||
@ -143,15 +168,13 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
|
||||
END as is_json,
|
||||
user_col_comments.comments as col_comment
|
||||
FROM user_tab_cols
|
||||
LEFT OUTER JOIN
|
||||
user_tables ON user_tables.table_name = user_tab_cols.table_name
|
||||
LEFT OUTER JOIN
|
||||
user_col_comments ON
|
||||
user_col_comments.column_name = user_tab_cols.column_name AND
|
||||
user_col_comments.table_name = user_tab_cols.table_name
|
||||
WHERE user_tab_cols.table_name = UPPER(%s)
|
||||
""",
|
||||
[table_name],
|
||||
[default_table_collation, table_name],
|
||||
)
|
||||
field_map = {
|
||||
column: (
|
||||
|
@ -1,9 +1,9 @@
|
||||
import unittest
|
||||
|
||||
from django.db import connection
|
||||
from django.test import TransactionTestCase
|
||||
from django.test import TransactionTestCase, skipUnlessDBFeature
|
||||
|
||||
from ..models import Square
|
||||
from ..models import Person, Square
|
||||
|
||||
|
||||
@unittest.skipUnless(connection.vendor == "oracle", "Oracle tests")
|
||||
@ -33,3 +33,54 @@ class DatabaseSequenceTests(TransactionTestCase):
|
||||
# Recreate model, because adding identity is impossible.
|
||||
editor.delete_model(Square)
|
||||
editor.create_model(Square)
|
||||
|
||||
@skipUnlessDBFeature("supports_collation_on_charfield")
|
||||
def test_get_table_description_view_default_collation(self):
|
||||
person_table = connection.introspection.identifier_converter(
|
||||
Person._meta.db_table
|
||||
)
|
||||
first_name_column = connection.ops.quote_name(
|
||||
Person._meta.get_field("first_name").column
|
||||
)
|
||||
person_view = connection.introspection.identifier_converter("TEST_PERSON_VIEW")
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(
|
||||
f"CREATE VIEW {person_view} "
|
||||
f"AS SELECT {first_name_column} FROM {person_table}"
|
||||
)
|
||||
try:
|
||||
columns = connection.introspection.get_table_description(
|
||||
cursor, person_view
|
||||
)
|
||||
self.assertEqual(len(columns), 1)
|
||||
self.assertIsNone(columns[0].collation)
|
||||
finally:
|
||||
cursor.execute(f"DROP VIEW {person_view}")
|
||||
|
||||
@skipUnlessDBFeature("supports_collation_on_charfield")
|
||||
def test_get_table_description_materialized_view_non_default_collation(self):
|
||||
person_table = connection.introspection.identifier_converter(
|
||||
Person._meta.db_table
|
||||
)
|
||||
first_name_column = connection.ops.quote_name(
|
||||
Person._meta.get_field("first_name").column
|
||||
)
|
||||
person_mview = connection.introspection.identifier_converter(
|
||||
"TEST_PERSON_MVIEW"
|
||||
)
|
||||
collation = connection.features.test_collations.get("ci")
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(
|
||||
f"CREATE MATERIALIZED VIEW {person_mview} "
|
||||
f"DEFAULT COLLATION {collation} "
|
||||
f"AS SELECT {first_name_column} FROM {person_table}"
|
||||
)
|
||||
try:
|
||||
columns = connection.introspection.get_table_description(
|
||||
cursor, person_mview
|
||||
)
|
||||
self.assertEqual(len(columns), 1)
|
||||
self.assertIsNotNone(columns[0].collation)
|
||||
self.assertNotEqual(columns[0].collation, collation)
|
||||
finally:
|
||||
cursor.execute(f"DROP MATERIALIZED VIEW {person_mview}")
|
||||
|
Loading…
Reference in New Issue
Block a user