Fixed #27458 -- Fixed invalid sequence/index names when using "USER"."TABLE" db_table on Oracle.
This commit is contained in:
parent
398a859642
commit
69b7d4b116
|
@ -1,6 +1,6 @@
|
|||
from django.contrib.gis.db.models.fields import GeometryField
|
||||
from django.db.backends.oracle.schema import DatabaseSchemaEditor
|
||||
from django.db.backends.utils import truncate_name
|
||||
from django.db.backends.utils import strip_quotes, truncate_name
|
||||
|
||||
|
||||
class OracleGISSchemaEditor(DatabaseSchemaEditor):
|
||||
|
@ -91,4 +91,4 @@ class OracleGISSchemaEditor(DatabaseSchemaEditor):
|
|||
def _create_spatial_index_name(self, model, field):
|
||||
# Oracle doesn't allow object names > 30 characters. Use this scheme
|
||||
# instead of self._create_index_name() for backwards compatibility.
|
||||
return truncate_name('%s_%s_id' % (model._meta.db_table, field.column), 30)
|
||||
return truncate_name('%s_%s_id' % (strip_quotes(model._meta.db_table), field.column), 30)
|
||||
|
|
|
@ -2,6 +2,7 @@ import hashlib
|
|||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
from django.db.backends.utils import strip_quotes
|
||||
from django.db.transaction import TransactionManagementError, atomic
|
||||
from django.utils import six, timezone
|
||||
from django.utils.encoding import force_bytes
|
||||
|
@ -841,7 +842,7 @@ class BaseDatabaseSchemaEditor(object):
|
|||
The name is divided into 3 parts: the table name, the column names,
|
||||
and a unique digest and suffix.
|
||||
"""
|
||||
table_name = model._meta.db_table
|
||||
table_name = strip_quotes(model._meta.db_table)
|
||||
hash_data = [table_name] + list(column_names)
|
||||
hash_suffix_part = '%s%s' % (self._digest(*hash_data), suffix)
|
||||
max_length = self.connection.ops.max_name_length() or 200
|
||||
|
|
|
@ -6,7 +6,7 @@ import uuid
|
|||
|
||||
from django.conf import settings
|
||||
from django.db.backends.base.operations import BaseDatabaseOperations
|
||||
from django.db.backends.utils import truncate_name
|
||||
from django.db.backends.utils import strip_quotes, truncate_name
|
||||
from django.utils import six, timezone
|
||||
from django.utils.encoding import force_bytes, force_text
|
||||
|
||||
|
@ -450,11 +450,13 @@ WHEN (new.%(col_name)s IS NULL)
|
|||
|
||||
def _get_sequence_name(self, table):
|
||||
name_length = self.max_name_length() - 3
|
||||
return '%s_SQ' % truncate_name(table, name_length).upper()
|
||||
sequence_name = '%s_SQ' % strip_quotes(table)
|
||||
return truncate_name(sequence_name, name_length).upper()
|
||||
|
||||
def _get_trigger_name(self, table):
|
||||
name_length = self.max_name_length() - 3
|
||||
return '%s_TR' % truncate_name(table, name_length).upper()
|
||||
trigger_name = '%s_TR' % strip_quotes(table)
|
||||
return truncate_name(trigger_name, name_length).upper()
|
||||
|
||||
def bulk_insert_sql(self, fields, placeholder_rows):
|
||||
return " UNION ALL ".join(
|
||||
|
|
|
@ -209,3 +209,13 @@ def format_number(value, max_digits, decimal_places):
|
|||
if decimal_places is not None:
|
||||
return "%.*f" % (decimal_places, value)
|
||||
return "{:f}".format(value)
|
||||
|
||||
|
||||
def strip_quotes(table_name):
|
||||
"""
|
||||
Strip quotes off of quoted table names to make them safe for use in index
|
||||
names, sequence names, etc. For example '"USER"."TABLE"' (an Oracle naming
|
||||
scheme) becomes 'USER"."TABLE'.
|
||||
"""
|
||||
has_quotes = table_name.startswith('"') and table_name.endswith('"')
|
||||
return table_name[1:-1] if has_quotes else table_name
|
||||
|
|
|
@ -1565,7 +1565,8 @@ class ManyToManyField(RelatedField):
|
|||
elif self.db_table:
|
||||
return self.db_table
|
||||
else:
|
||||
return utils.truncate_name('%s_%s' % (opts.db_table, self.name), connection.ops.max_name_length())
|
||||
m2m_table_name = '%s_%s' % (utils.strip_quotes(opts.db_table), self.name)
|
||||
return utils.truncate_name(m2m_table_name, connection.ops.max_name_length())
|
||||
|
||||
def _get_m2m_attr(self, related, attr):
|
||||
"""
|
||||
|
|
|
@ -2266,3 +2266,34 @@ class SchemaTests(TransactionTestCase):
|
|||
editor, Author, tob_auto_now_add, 'tob_auto_now_add', now.time(),
|
||||
cast_function=lambda x: x.time(),
|
||||
)
|
||||
|
||||
@unittest.skipUnless(connection.vendor == 'oracle', 'Oracle specific db_table syntax')
|
||||
def test_creation_with_db_table_double_quotes(self):
|
||||
oracle_user = connection.creation._test_database_user()
|
||||
|
||||
class Student(Model):
|
||||
name = CharField(max_length=30)
|
||||
|
||||
class Meta:
|
||||
app_label = 'schema'
|
||||
apps = new_apps
|
||||
db_table = '"%s"."DJANGO_STUDENT_TABLE"' % oracle_user
|
||||
|
||||
class Document(Model):
|
||||
name = CharField(max_length=30)
|
||||
students = ManyToManyField(Student)
|
||||
|
||||
class Meta:
|
||||
app_label = 'schema'
|
||||
apps = new_apps
|
||||
db_table = '"%s"."DJANGO_DOCUMENT_TABLE"' % oracle_user
|
||||
|
||||
self.local_models = [Student, Document]
|
||||
|
||||
with connection.schema_editor() as editor:
|
||||
editor.create_model(Student)
|
||||
editor.create_model(Document)
|
||||
|
||||
doc = Document.objects.create(name='Test Name')
|
||||
student = Student.objects.create(name='Some man')
|
||||
doc.students.add(student)
|
||||
|
|
Loading…
Reference in New Issue