On Fri, Jan 15, 2010 at 3:55 AM, Russell Keith-Magee
<[email protected]> wrote:
> And to be clear - a solid proposal isn't just "merge this branch". A
> patch/branch is one way to prove that you have thought about the
> problem in detail, but you also need to provide the discussion and
> description necessary to explain the nature of and reasoning behind
> the changes you want to make.

OK, I think I've found a better way to get very non-relational backend
support integrated with minimal changes to Django. The current patch
is very simple and it's not based on QueryData, but it already
supports the same feature set as our previous port. It's not yet
sufficient for emulating JOINs and maybe a few other "advanced"
features, but it looks like sql.Query and SQLCompiler would only need
minor modifications to be abstract enough for emulating advanced
features with nonrel DBs. Anyway, this can be added once we've
discussed whether the current solution is good enough.

The idea is to just use the SQLCompiler backend API and let the nonrel
backends interpret sql.Query.where and the other query attributes.
This required a few small changes to sql.Query and SQLCompiler.

The patch is this commit:
http://bitbucket.org/wkornewald/django-nonrel/changeset/71117e43ae33/

My reasoning behind the patch is the following:

1. Nonrel DBs don't distinguish between INSERT and UPDATE
On such DBs Model.save_base() shouldn't check if an entity already
exists. Instead, it should just always INSERT. For this I added
connection.features.distinguishes_insert_from_update.

2. Deleting related objects can be too costly on non-relational DBs
For this I added
connection.features.supports_deleting_related_objects. If it's False
no related objects will be deleted. Ideally, the backend should be
able to delegate this job to a background task. This is planned.

3. Multi-table inheritance needs JOINs
For this I added connection.features.supports_multi_table_inheritance.
If it's False Django will reject to save this model or run queries on
this model using that connection.
In the future, at least single inheritance could be emulated with a
ListField type. On App Engine multiple inheritance support would
require lots of custom datastore indexes and could lead to exploding
indexes. We can discuss this later.

4. sql.Query.has_results() used a trick that only works with SQL
I moved some of the code to SQLCompiler, so the backend can override it.

5. We need transactions which lock rows
I added a GAE-specific @commit_locked transaction decorator. This
should be moved into the backend layer, of course. I'd just like to
know if this is an option for 1.3 or not. On SQL this would be SELECT
... FOR UPDATE, but I don't know if all SQL DBs support it. Such a
decorator would be important to make get_or_create() and a few other
functions work 100% correctly, so it would also benefit the SQL layer.
I couldn't provide the respective SQL implementations, though.

Planned changes:

Delegate deletion of related objects to background task.

Maybe emulate multi-table inheritance with a ListField.

Nonrel DBs need special handling for primary key fields.
MongoDB and CouchDB store them in '_id' and App Engine uses a special
property which is not part of the field values dictionary. In order to
emulate JOINs we must store the column names of the primary keys used
in the sql.Query instance.

So, do you think this is a good path to take?

Bye,
Waldemar Kornewald

--
http://twitter.com/wkornewald
http://bitbucket.org/wkornewald/
http://allbuttonspressed.blogspot.com/
-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.


Reply via email to