[Django] #32653: Issue with multiple database backends sharing a model with a very long name

4 views
Skip to first unread message

Django

unread,
Apr 14, 2021, 11:05:09 AM4/14/21
to django-...@googlegroups.com
#32653: Issue with multiple database backends sharing a model with a very long name
-------------------------------------+-------------------------------------
Reporter: Javier | Owner: nobody
Buzzi |
Type: Bug | Status: new
Component: Database | Version: 2.2
layer (models, ORM) |
Severity: Normal | Keywords:
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
''Original discussion can be found here: https://groups.google.com/g
/django-developers/c/f3Z0AchkdyU/m/q0puWHYOCgAJ''

I have a model with a really long name think
`ThisIsAReallyLongModelNameThatIsAlsoVeryOld`. To complicate things
further I have a Oracle instance with archival data designated with
connection name `old` and a new postgres instance with the connection name
`default`.

Issue i've found is that if i try and call the model
`ThisIsAReallyLongModelNameThatIsAlsoVeryOld.objects.using('old').count()`
i get an error saying that the table `APP_THISISAREALLYLONGMODEL5300` does
not exist, when it should be using `APP_THISISAREALLYLONGMODEL5BD6`
instead. When postgres is used it works as expected:
`ThisIsAReallyLongModelNameThatIsAlsoVeryOld.objects.using('default').count()`

This is because the default connection is used when the model is
instantiated, and then its used from that moment on.

https://github.com/django/django/blob/stable/3.2.x/django/db/models/options.py#L207

This is an issue that seems to go back to the beginning of Django.

--
Ticket URL: <https://code.djangoproject.com/ticket/32653>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Apr 14, 2021, 12:51:17 PM4/14/21
to django-...@googlegroups.com
#32653: Issue with multiple database backends sharing a model with a very long name
-------------------------------------+-------------------------------------
Reporter: Javier Buzzi | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 2.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Simon Charette):

This is kind of have some overlap with
[https://code.djangoproject.com/ticket/6148#comment:165 the solution
proposed by Anssi] for #6148.

If `db_table` was a compilable object (it follows the `as_sql(connection,
compile)` protocol) then the default implementation could be


{{{#!python
class Table:
def __init__(self, name):
self.name = name

def __str__(self):
returns self.name

def as_sql(self, connection, compiler):
return connection.quote_name(
truncate_name(name, connection.ops.max_name_length())
)
}}}

And be used by `Options.contribute_to_class` as

{{{
db_table = self.db_table
if not db_table:
db_table = "%s_%s" % (self.app_label, self.model_name)
self.db_table = Table(db_table)
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/32653#comment:1>

Django

unread,
Apr 14, 2021, 1:27:51 PM4/14/21
to django-...@googlegroups.com
#32653: Issue with multiple database backends sharing a model with a very long name
-------------------------------------+-------------------------------------
Reporter: Javier Buzzi | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: 2.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Adam Johnson):

* cc: Adam Johnson (added)


--
Ticket URL: <https://code.djangoproject.com/ticket/32653#comment:2>

Django

unread,
Apr 15, 2021, 4:17:26 AM4/15/21
to django-...@googlegroups.com
#32653: Issue with multiple database backends sharing a model with a very long name
-------------------------------------+-------------------------------------
Reporter: Javier Buzzi | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: 2.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Javier Buzzi):

@Simon YES! What you pasted is clear, concise, it's amazing. That looks
like it should work. Whats the hold up?

--
Ticket URL: <https://code.djangoproject.com/ticket/32653#comment:3>

Django

unread,
Apr 15, 2021, 4:32:06 AM4/15/21
to django-...@googlegroups.com
#32653: Quoting names in the Oracle backend is not consistent with the db_table
generation.

-------------------------------------+-------------------------------------
Reporter: Javier Buzzi | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: 2.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: oracle | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak):

* keywords: => oracle
* stage: Unreviewed => Accepted


Comment:

I agree with Shai's [https://groups.google.com/g/django-
developers/c/f3Z0AchkdyU/m/p7D4c78QCgAJ comment]. It's related with
quoting names in the Oracle backend and can be fixed by:
{{{
diff --git a/django/db/backends/oracle/operations.py
b/django/db/backends/oracle/operations.py
index ae6bd432fb..d48c8dd868 100644
--- a/django/db/backends/oracle/operations.py
+++ b/django/db/backends/oracle/operations.py
@@ -334,7 +334,7 @@ END;
# always defaults to uppercase.
# We simplify things by making Oracle identifiers always
uppercase.
if not name.startswith('"') and not name.endswith('"'):
- name = '"%s"' % truncate_name(name.upper(),
self.max_name_length())
+ name = '"%s"' % truncate_name(name, 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.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/32653#comment:4>

Django

unread,
Apr 15, 2021, 4:45:04 AM4/15/21
to django-...@googlegroups.com
#32653: Quoting names in the Oracle backend is not consistent with the db_table
generation.
-------------------------------------+-------------------------------------
Reporter: Javier Buzzi | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: 2.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: oracle | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak):

* Attachment "test-32653.diff" added.

Django

unread,
Apr 15, 2021, 4:50:27 AM4/15/21
to django-...@googlegroups.com
#32653: Quoting names in the Oracle backend is not consistent with the db_table
generation.
-------------------------------------+-------------------------------------
Reporter: Javier Buzzi | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: 2.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: oracle | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Javier Buzzi):

@Mariusz the issue is see with your solution is that it will work from my
current case Postgres as `default`, Oracle as `old`. Where Postgres wont
change the db_table as long as its under 63 chars??? But if we have the
inverse, Oracle as `default` and Postgres as `new`; it will break Postgres
since the `db_table` would be something like
`backends_verylongmodelnamezzz1234` and Postgres would want the whole
string
`backends_verylongmodelnamezzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz`.
The solution @Simon suggested would work on both cases.

--
Ticket URL: <https://code.djangoproject.com/ticket/32653#comment:5>

Django

unread,
Apr 15, 2021, 5:02:21 AM4/15/21
to django-...@googlegroups.com
#32653: Quoting names in the Oracle backend is not consistent with the db_table
generation.
-------------------------------------+-------------------------------------
Reporter: Javier Buzzi | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: 2.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: oracle | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Mariusz Felisiak):

Personally I would recommend specifying `db_table` for such a complicated
setup with different vendors. Database backends (even builtin) will never
be fully swappable. `quote_name()` on Oracle should be fixed regardless of
whether we decide to move forward with Simon's proposition or not.

--
Ticket URL: <https://code.djangoproject.com/ticket/32653#comment:6>

Django

unread,
Apr 30, 2021, 5:21:43 AM4/30/21
to django-...@googlegroups.com
#32653: Quoting names in the Oracle backend is not consistent with the db_table
generation.
-------------------------------------+-------------------------------------
Reporter: Javier Buzzi | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: 2.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: oracle | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Mariusz Felisiak):

> Ideally, the line self.db_table = truncate_name(self.db_table,
connection.ops.max_name_length()) would be removed, and the aliases that
is done in the SQLCompiler be moved to the individual backend, and that
way you can cache the table names for later use.

This is tracked in #13528.

--
Ticket URL: <https://code.djangoproject.com/ticket/32653#comment:7>

Django

unread,
Apr 30, 2021, 5:34:10 AM4/30/21
to django-...@googlegroups.com
#32653: Quoting names in the Oracle backend is not consistent with the db_table
generation.
-------------------------------------+-------------------------------------
Reporter: Javier Buzzi | Owner: Mariusz
| Felisiak
Type: Bug | Status: assigned

Component: Database layer | Version: 2.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: oracle | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak):

* owner: nobody => Mariusz Felisiak
* status: new => assigned
* has_patch: 0 => 1


Comment:

[https://github.com/django/django/pull/14335 PR]

--
Ticket URL: <https://code.djangoproject.com/ticket/32653#comment:8>

Django

unread,
Apr 30, 2021, 6:59:17 AM4/30/21
to django-...@googlegroups.com
#32653: Quoting names in the Oracle backend is not consistent with the db_table
generation.
-------------------------------------+-------------------------------------
Reporter: Javier Buzzi | Owner: Mariusz
| Felisiak
Type: Bug | Status: closed

Component: Database layer | Version: 2.2
(models, ORM) |
Severity: Normal | Resolution: fixed

Keywords: oracle | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by GitHub <noreply@…>):

* status: assigned => closed
* resolution: => fixed


Comment:

In [changeset:"1f643c28b5f2b039c47155692844dbae1cb091cd" 1f643c2]:
{{{
#!CommitTicketReference repository=""
revision="1f643c28b5f2b039c47155692844dbae1cb091cd"
Fixed #32653 -- Made quoting names in the Oracle backend consistent with
db_table.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/32653#comment:9>

Reply all
Reply to author
Forward
0 new messages