#28451: Change in Oracle sequence name truncation causes regression when 
updating
existing database
-------------------------------------+-------------------------------------
               Reporter:  Kevin      |          Owner:  nobody
  Grinberg                           |
                   Type:  Bug        |         Status:  new
              Component:  Database   |        Version:  1.11
  layer (models, ORM)                |
               Severity:  Normal     |       Keywords:  oracle
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 **Summary**: a change introduced in 1.11 in how the Oracle backend
 truncates sequence names introduces persistent "ORA-02289: sequence does
 not exist" errors after upgrading to 1.11.

 **Explanation** (as far best as I can tell): In the Oracle backend,
 sequence names are truncated to 30 characters.

 In 1.10.7 (and 1.9.13 & 1.8.17) the method to do that in
 `django.db.backends.oracle.operations` is as follows:
 {{{
 def _get_sequence_name(self, table):
     name_length = self.max_name_length() - 3
     return '%s_SQ' % truncate_name(table, name_length).upper()
 }}}
 In 1.11.3 it's:
 {{{
 def _get_sequence_name(self, table):
     name_length = self.max_name_length() - 3
     sequence_name = '%s_SQ' % strip_quotes(table)
     return truncate_name(sequence_name, name_length).upper()
 }}}
 Note the subtle change - in 1.10.7 the return value always ends with
 '_SQ'; in 1.11.3 the '_SQ' is part of what gets truncated. (For context,
 truncate_name basically takes a hash of the string and appends the last
 few digits to the name of the table - so you end up with e.g.
 'PATIENTS_PATIENTDOCTORRELA8026', to fit in the 30-character limit).

 The consequence of this is that after upgrading an Oracle-backed app to
 1.11, inserts start failing (because `last_insert_id` is looking for the
 sequence name 'PATIENTS_PATIENTDOCTORR36D1', whereas the actual sequence
 name is 'PATIENTS_PATIENTDOCTORRC0BD_SQ' - because that's what was
 generated in the prior version; or, to be precise, whenever the table was
 created, several versions before that).

 As far as I can tell (though I can't be sure) this change was an
 inadvertent side effect of
 [changeset:"69b7d4b116e3b70b250c77829e11038d5d55c2a8" 69b7d4b1], which was
 the fix for #27458. I say 'inadvertent' because it doesn't appear to be
 the focus of the change, and the tests don't appear to be taking that into
 account. In general, most tests wouldn't pick up the problem because it
 only manifests if you have existing sequences - for a fresh database, it's
 fine (since the sequences will be created with the new naming scheme and
 everything is hunky-dory).

 (NB: the same thing appears to have happened for triggers, though this
 particular database isn't using triggers so I didn't hit that particular
 error).

 As a quick test, patching Django to use the pre-1.11 version of
 `_get_sequence_name` worked correctly, so I'm fairly confident that's the
 issue (there was another change in it, the strip_quotes bit, so if we go
 that way for the ultimate fix we'll probably want to keep that rather than
 just reverting).

 I'd be glad to work on a patch but to be honest I'm not clear what
 direction to take... as I see it, the options are:

 1) Revert the behavior - make `_get_sequence_name` return '%s_SQ' like it
 did pre-1.11 (but with the strip_quotes fix). This has a bad backcompat
 issue in that it'll introduce essentially the same problem for sequences
 created with 1.11.x... so that doesn't really seem like a good idea.

 2) Create a helper to rename sequences when a change like this is
 introduced. In theory this is an implementation detail and Django should
 be able to tweak the way the truncated names are generated, as long as
 there's a transition path (though I say that as someone who doesn't use
 custom sequences much - others may have a different opinion).

 So I can imagine a utility of some sort to cross-check sequence names (for
 autonumber fields and such) with what Django expects, and either
 interactively or automatically rename them. Perhaps call it out in the
 release notes?

 For completeness, this feels related to #23577 but feels a bit different,
 and IMO is more dire because it's less obvious and less likely to get
 noticed right away.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/28451>
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/052.72f313e2d9edb3d93f969bc136b0a49e%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to