Hi all,

I've been looking at #14799, and trying to work out the best approach
for a solution. I can see three options, none of which are are
particularly attractive. I'm looking for feedback on which one smells
the least.

First off - the problem:

 * The test framework needs to create test databases
 * The DB backend call to create the test database implies a call to
syncdb on that database
 * But a post_syncdb handler can invoke a query on *any* database
 * If the database required by the code in a post_syncdb handler
hasn't been created yet, the test system falls over during database
setup.
 * The test databases are specified as a dictionary, so there's no
guarantee on the order in which tests databases are created.

There is one obvious manifestation of this bug. If you run Django's
own test suite, and the 'other' alias is created before the 'default'
alias, the test suite fails to initialize, because the post_syncdb
handler for contenttypes tries to run ContentTypes.objects.get() on
the 'default' database, but that database doesn't exist yet.

Jacob has committed an interim fix for this problem, which involves
simply ensuring that the 'default' database is created first. This
works for Django's own test suite, but doesn't work in the general
case -- if you have a router that directs contenttypes read queries to
'other', the suite will fail for exactly the same reason. Similarly,
if you have some other post_syncdb handler with dependency on
something other than default,

So - how can this be fixed?

Option 1: The documentation approach: "You may only assume that the
default database exists when post_syncdb runs on a non-default
database". This is the non-solution; the current code on trunk will be
sufficient, but it will leave some users high and dry.

Option 2: Force the use of SortedDict when defining DATABASES. This
removes the non-deterministic database creation order, but requires
imports in the settings file, and requires action on the part of every
person that has migrated to using the DATABASES format.

Option 3: Split syncdb into two parts -- phase 1: create tables, and
phase 2: post_syncdb, custom SQL, index creation and initial data.

I haven't implemented this -- but I've taken a look at what will be
needed, and it will be messy. The current syncdb command and
backend.create_test_db() API guarantees a full syncdb cycle, so
implementing this in a way that preserves backwards compatibility will
involve introducing a bunch of flags that only do partial syncdb runs
(either phase 1 or phase 2). There's also the question of whether this
will violate any existing expectations -- after all, we will be
effectively changing the order in which syncdb will be invoked in a
non-configurable way.

Option 4: Introduce a per-database setting -- TEST_DEPENDENCIES --
that allows the developer to explicitly encode the dependency between
databases. This means the developer can explicitly encode the
dependencies that exists in database creation order. We can default to
assuming 'everything depends on default' (which is what the current
trunk implements); but this gives end users the flexibility to define
any dependency they need. The patch on #14799 implements this solution
(although it needs some tests for the dependency resolution code and
documentation for the setting itself)

My personal preference is for (4). I don't like the addition of a
setting, but it's a setting that most users will be able to ignore
(since there is a reasonably sensible default), and it is the most
explicit and configurable option available.

Opinions? Alternatives?

Yours,
Russ Magee %-)

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-develop...@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.

Reply via email to