#12529: manage.py syncdb doesn't check tables by using mangled names with Oracle
backend
-------------------------------------+-------------------------------------
Reporter: jtiai | Owner: nobody
Type: Bug | Status: closed
Component: Database layer | Version: master
(models, ORM) | Resolution: fixed
Severity: Normal | Triage Stage: Accepted
Keywords: syncdb oracle | Needs documentation: 0
inspectdb | Patch needs improvement: 0
Has patch: 0 | UI/UX: 0
Needs tests: 0 |
Easy pickings: 0 |
-------------------------------------+-------------------------------------
Comment (by manelclos):
Hi, I can still reproduce this using Django 1.7 and 1.7.1.
As an example, let's use django-cas' table
"django_cas_session_service_ticket". This also happens with
easy_thumbails' table "easy_thumbnails_thumbnaildimensions".
The flow is like this:
- migrate command is called, eventually migrate.py:model_installed() is
called:
{{{
def model_installed(model):
opts = model._meta
converter = connection.introspection.table_name_converter
# Note that if a model is unmanaged we short-circuit and
never try to install it
return not ((converter(opts.db_table) in tables) or
(opts.auto_created and
converter(opts.auto_created._meta.db_table) in tables))
}}}
- here, the table name converter will just return name.lower(), which is
clearly NOT the name that was used to create the table.
- at creation time, the Oracle DatabaseOperations (oracle/base.py) class
will truncate the name:
{{{
def quote_name(self, name):
# SQL92 requires delimited (quoted) names to be case-sensitive.
When
# not quoted, Oracle has case-insensitive behavior for
identifiers, but
# always defaults to uppercase.
# We simplify things by making Oracle identifiers always
uppercase.
if not name.startswith('"') and not name.endswith('"'):
name = '"%s"' % backend_utils.truncate_name(name.upper(),
self.max_name_length())
# Oracle puts the query text into a (query % args) construct, so %
signs
# in names need to be escaped. The '%%' will be collapsed back to
'%' at
# that stage so we aren't really making the name longer here.
name = name.replace('%', '%%')
return name.upper()
}}}
- the check for table existance "(converter(opts.db_table) in tables)"
will fail, as tables array contains "django_cas_session_service1144" and
not "django_cas_session_service_ticket"
- with these changes in oracle/introspection.py everything works as
expected. imports included in function for easier testing:
{{{
def table_name_converter(self, name):
"Table name comparison is case insensitive under Oracle"
from django.db.backends import utils as backend_utils
from django.db.backends.oracle.base import DatabaseOperations
self.ops = DatabaseOperations(self)
name = backend_utils.truncate_name(name.upper(),
self.ops.max_name_length())
return name.lower()
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/12529#comment:9>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/063.67130252acf547b9af39b6faaebbd29d%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.