On Tuesday 11 December 2012, Ian Kelly wrote: > On Tue, Dec 11, 2012 at 6:31 AM, Shai Berger <s...@platonix.com> wrote: > > Hi all, > > > > I've just been hit by a very simple and annoying bug on Oracle, on Django > > 1.3.4. Without testing, it seems to no longer be as bad on master, but a > > shade of it still remains. > > > > The bug is this: The DatabaseFeatures for the Oracle backend do not > > specify that it supports transactions. > > > > On 1.3.4, this means the value is only set if confirm() is called, and > > when it is, it only affects a single connection; it does not appear to > > be called whenever a connection is created -- while database test > > creation calls it, by the time the tests use it it is all forgotten and > > testing is relegated to the old behavior of flush for every test. > > > > On master, where the generic supports_transactions is a cached property, > > this means that for every connection opened, 4 statements are being > > executed to check if the database (still) supports transactions. > > While connections come and go, the DatabaseWrapper objects are stored > in the ConnectionHandler on a per-thread basis and should be reused > for subsequent connections. So these tests *should* run only once per > configured connection per thread. Can you demonstrate that they are > actually being run on every connection? >
As I noted above, I haven't actually tested on master, so I can't be sure; this was just my reading of the code. As far as I'm aware, though, the basic management of database wrappers and connections hasn't changed much since 1.3, and I can demonstrate that on 1.3.4, a new connection uses a new DatabaseFeatures object. I found this issue not by optimizing for speed, but by using a test-runner which installs some objects in the DB before running the test-suite; to my surprise, the objects weren't available, because the test framework, thinking the backend didn't support transactions, flushed the DB (as mentioned, on 1.3.4 the setting of supports_transactions takes a call to confirm(), but one is made, and running tests is single-threaded). > > 1. Oracle supports transactions. is there a reason not to just add the > > line > > > > supports_transactions = True > > > > to its DatabaseFeatures class? > > I see no harm in it, although per the above I don't think it will help > as much as you hope. Since the test involves a CREATE TABLE though, > and since DDL is slow in Oracle, and since there's really no guarantee > that the user even has the necessary permissions to create the table > in the first place, I think it's a good idea to add this in any case. > Should I open a ticket for it? It is a one-line patch... > > 2. Database features, typically, do not change between opening of > > connections within a single server run. Shouldn't we consider saving > > these features -- even the dynamic ones -- on the DatabaseFeatures > > class, instead of its instances? > > This would lead to bugs in multi-DB setups where the user has > configured connections to multiple databases of the same type but > different versions (and different feature sets). I don't know how > common that is, but it is better to be correct and slow than fast and > buggy. While I doubt that such setups are common enough to justify a price paid by the whole community, I can accept this answer as "we considered it and decided against". But then, I would ask for backends to rely as little as possible on dynamic features. A user can easily monkey-patch sense into the backend DatabaseFeatures, but that's no replacement for sensible defaults. Thanks, Shai. -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.