1
0
mirror of https://github.com/django/django.git synced 2025-07-06 02:39:12 +00:00

queryset-refactor: Added support for munging of insert columns.

Needed to support cases like GIS fields. Patch from Justin Bronn.


git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@7318 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2008-03-19 14:24:23 +00:00
parent d20996b58d
commit 9ee77a7501

View File

@ -126,9 +126,9 @@ class UpdateQuery(Query):
result = ['UPDATE %s' % qn(table)] result = ['UPDATE %s' % qn(table)]
result.append('SET') result.append('SET')
values, update_params = [], [] values, update_params = [], []
for name, val in self.values: for name, val, placeholder in self.values:
if val is not None: if val is not None:
values.append('%s = %%s' % qn(name)) values.append('%s = %s' % (qn(name), placeholder))
update_params.append(val) update_params.append(val)
else: else:
values.append('%s = NULL' % qn(name)) values.append('%s = NULL' % qn(name))
@ -190,33 +190,40 @@ class UpdateQuery(Query):
self.where.add((None, f.column, f, 'in', self.where.add((None, f.column, f, 'in',
pk_list[offset : offset + GET_ITERATOR_CHUNK_SIZE]), pk_list[offset : offset + GET_ITERATOR_CHUNK_SIZE]),
AND) AND)
self.values = [(related_field.column, None)] self.values = [(related_field.column, None, '%s')]
self.execute_sql(None) self.execute_sql(None)
def add_update_values(self, values): def add_update_values(self, values):
from django.db.models.base import Model from django.db.models.base import Model
for name, val in values.items(): for name, val in values.iteritems():
field, model, direct, m2m = self.model._meta.get_field_by_name(name) field, model, direct, m2m = self.model._meta.get_field_by_name(name)
if not direct or m2m: if not direct or m2m:
raise FieldError('Cannot update model field %r (only non-relations and foreign keys permitted).' % field) raise FieldError('Cannot update model field %r (only non-relations and foreign keys permitted).' % field)
# FIXME: Some sort of db_prep_* is probably more appropriate here. # FIXME: Some sort of db_prep_* is probably more appropriate here.
if field.rel and isinstance(val, Model): if field.rel and isinstance(val, Model):
val = val.pk val = val.pk
if model:
self.add_related_update(model, field.column, val)
else:
self.values.append((field.column, val))
def add_related_update(self, model, column, value): # Getting the placeholder for the field.
if hasattr(field, 'get_placeholder'):
placeholder = field.get_placeholder(val)
else:
placeholder = '%s'
if model:
self.add_related_update(model, field.column, val, placeholder)
else:
self.values.append((field.column, val, placeholder))
def add_related_update(self, model, column, value, placeholder):
""" """
Adds (name, value) to an update query for an ancestor model. Adds (name, value) to an update query for an ancestor model.
Updates are coalesced so that we only run one update query per ancestor. Updates are coalesced so that we only run one update query per ancestor.
""" """
try: try:
self.related_updates[model].append((column, value)) self.related_updates[model].append((column, value, placeholder))
except KeyError: except KeyError:
self.related_updates[model] = [(column, value)] self.related_updates[model] = [(column, value, placeholder)]
def get_related_updates(self): def get_related_updates(self):
""" """
@ -227,7 +234,7 @@ class UpdateQuery(Query):
if not self.related_updates: if not self.related_updates:
return [] return []
result = [] result = []
for model, values in self.related_updates.items(): for model, values in self.related_updates.iteritems():
query = UpdateQuery(model, self.connection) query = UpdateQuery(model, self.connection)
query.values = values query.values = values
if self.related_ids: if self.related_ids:
@ -272,20 +279,31 @@ class InsertQuery(Query):
parameters. This provides a way to insert NULL and DEFAULT keywords parameters. This provides a way to insert NULL and DEFAULT keywords
into the query, for example. into the query, for example.
""" """
func = lambda x: self.model._meta.get_field_by_name(x)[0].column func = lambda x: self.model._meta.get_field_by_name(x)[0]
# keys() and values() return items in the same order, providing the # keys() and values() return items in the same order, providing the
# dictionary hasn't changed between calls. So the dual iteration here # dictionary hasn't changed between calls. So the dual iteration here
# works as intended. # works as intended.
for name in insert_values: placeholders, values = [], []
for name, val in insert_values.iteritems():
if name == 'pk': if name == 'pk':
name = self.model._meta.pk.name name = self.model._meta.pk.name
self.columns.append(func(name)) # Getting the Field associated w/the name.
if raw_values: field = func(name)
self.values.extend(insert_values.values())
if hasattr(field, 'get_placeholder'):
# Some fields (e.g. geo fields) need special munging before
# they can be inserted.
placeholders.append(field.get_placeholder(val))
else:
placeholders.append('%s')
self.columns.append(field.column)
values.append(val)
if raw_values:
self.values.extend(values)
else: else:
values = insert_values.values()
self.params += tuple(values) self.params += tuple(values)
self.values.extend(['%s'] * len(values)) self.values.extend(placeholders)
class DateQuery(Query): class DateQuery(Query):
""" """