* keywords: syncdb oracle => syncdb oracle inspectdb
* ui_ux: => 0
* easy: => 0
--
Ticket URL: <https://code.djangoproject.com/ticket/12529#comment:6>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
Comment (by manelclos@…):
Hi, I've fixed this by changing django.db.backends.oracle.introspection.py
from:
{{{
def table_name_converter(self, name):
"Table name comparison is case insensitive under Oracle"
return name.lower()
}}}
to:
{{{
from django.db.backends import util
}}}
{{{
def table_name_converter(self, name):
"Table name comparison is case insensitive under Oracle"
max_length = self.connection.ops.max_name_length()
truncated = util.truncate_name(name.upper(), max_length)
return truncated.lower()
}}}
Is there any problem in this solution?
--
Ticket URL: <https://code.djangoproject.com/ticket/12529#comment:7>
* status: new => closed
* resolution: => fixed
Comment:
With the introduction of the new migrations framework in Django 1.7, this
issue doesn't exist anymore.
--
Ticket URL: <https://code.djangoproject.com/ticket/12529#comment:8>
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>
* status: closed => new
* resolution: fixed =>
--
Ticket URL: <https://code.djangoproject.com/ticket/12529#comment:10>