Changeset 7253
- Timestamp:
- 03/16/08 11:18:39 (8 months ago)
- Files:
-
- django/branches/queryset-refactor/django/db/models/fields/__init__.py (modified) (1 diff)
- django/branches/queryset-refactor/django/db/models/options.py (modified) (3 diffs)
- django/branches/queryset-refactor/django/db/models/query.py (modified) (2 diffs)
- django/branches/queryset-refactor/django/db/models/sql/query.py (modified) (9 diffs)
- django/branches/queryset-refactor/django/db/models/sql/subqueries.py (modified) (3 diffs)
- django/branches/queryset-refactor/tests/modeltests/model_inheritance/models.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/queryset-refactor/django/db/models/fields/__init__.py
r7152 r7253 161 161 # can implement db_type() instead of get_internal_type() to specify 162 162 # exactly which wacky database column type you want to use. 163 data_types = get_creation_module().DATA_TYPES164 internal_type = self.get_internal_type()165 if internal_type not in data_types:163 try: 164 return get_creation_module().DATA_TYPES[self.get_internal_type()] % self.__dict__ 165 except KeyError: 166 166 return None 167 return data_types[internal_type] % self.__dict__168 167 169 168 def validate_full(self, field_data, all_data): django/branches/queryset-refactor/django/db/models/options.py
r7143 r7253 124 124 if hasattr(self, '_field_cache'): 125 125 del self._field_cache 126 del self._field_name_cache 126 127 127 128 if hasattr(self, '_name_map'): … … 156 157 The getter for self.fields. This returns the list of field objects 157 158 available to this model (including through parent models). 158 """ 159 try: 160 self._field_cache 159 160 Callers are not permitted to modify this list, since it's a reference 161 to this instance (not a copy). 162 """ 163 try: 164 self._field_name_cache 161 165 except AttributeError: 162 166 self._fill_fields_cache() 163 return self._field_ cache.keys()167 return self._field_name_cache 164 168 fields = property(_fields) 165 169 166 170 def get_fields_with_model(self): 167 171 """ 168 Returns a listof (field, model) pairs for all fields. The "model"172 Returns a sequence of (field, model) pairs for all fields. The "model" 169 173 element is None for fields on the current model. Mostly of use when 170 174 constructing queries so that we know which model a field belongs to. … … 174 178 except AttributeError: 175 179 self._fill_fields_cache() 176 return self._field_cache .items()180 return self._field_cache 177 181 178 182 def _fill_fields_cache(self): 179 cache = SortedDict()183 cache = [] 180 184 for parent in self.parents: 181 185 for field, model in parent._meta.get_fields_with_model(): 182 186 if model: 183 cache [field] = model187 cache.append((field, model)) 184 188 else: 185 cache [field] = parent186 for field in self.local_fields:187 cache[field] = None188 self._field_ cache = cache189 cache.append((field, parent)) 190 cache.extend([(f, None) for f in self.local_fields]) 191 self._field_cache = tuple(cache) 192 self._field_name_cache = [x for x, _ in cache] 189 193 190 194 def _many_to_many(self): django/branches/queryset-refactor/django/db/models/query.py
r7250 r7253 32 32 33 33 def __len__(self): 34 # Since __len__ is called quite frequently (as part of list(qs), which 35 # means as part of qs.get(), for example), we make some effort here to 36 # be as efficient as possible whilst not messing up any existing 37 # iterators against the queryset. 34 # Since __len__ is called quite frequently (for example, as part of 35 # list(qs), we make some effort here to be as efficient as possible 36 # whilst not messing up any existing iterators against the queryset. 38 37 if self._result_cache is None: 39 38 if self._iter: … … 51 50 if self._iter: 52 51 return self._result_iter() 52 # Python's list iterator is better than our version when we're just 53 # iterating over the cache. 53 54 return iter(self._result_cache) 54 55 django/branches/queryset-refactor/django/db/models/sql/query.py
r7247 r7253 8 8 """ 9 9 10 import itertools 10 11 from copy import deepcopy 11 12 … … 224 225 if where: 225 226 result.append('WHERE %s' % where) 227 params.extend(w_params) 226 228 if self.extra_where: 227 229 if not where: … … 230 232 result.append('AND') 231 233 result.append(' AND'.join(self.extra_where)) 232 params.extend(w_params)233 234 234 235 if self.group_by: … … 362 363 aliases.append(col.alias) 363 364 elif self.default_cols: 364 result = self.get_default_columns( lambda x, y: "%s.%s" % (qn(x), qn(y)))365 result = self.get_default_columns(True) 365 366 aliases = result[:] 366 367 … … 369 370 aliases.extend(self.extra_select.keys()) 370 371 371 self._select_aliases = dict.fromkeys(aliases)372 self._select_aliases = set(aliases) 372 373 return result 373 374 374 def get_default_columns(self, combine_func=None):375 def get_default_columns(self, as_str=False): 375 376 """ 376 377 Computes the default columns for selecting every field in the base 377 378 model. Returns a list of default (alias, column) pairs suitable for 378 direct inclusion as the select columns. The 'combine_func' can be 379 passed in to change the returned data set to a list of some other 380 structure. 381 """ 382 # Note: We allow 'combine_func' here because this method is called a 383 # lot. The extra overhead from returning a list and then transforming 384 # it in get_columns() hurt performance in a measurable way. 379 inclusion as the select columns. If 'as_str' is True, returns a list of 380 strings, quoted appropriately for use in SQL directly. 381 """ 385 382 result = [] 386 383 table_alias = self.tables[0] 387 384 root_pk = self.model._meta.pk.column 388 385 seen = {None: table_alias} 386 qn = self.quote_name_unless_alias 387 qn2 = self.connection.ops.quote_name 389 388 for field, model in self.model._meta.get_fields_with_model(): 390 if model not in seen: 391 seen[model] = self.join((table_alias, model._meta.db_table, 389 try: 390 alias = seen[model] 391 except KeyError: 392 alias = self.join((table_alias, model._meta.db_table, 392 393 root_pk, model._meta.pk.column)) 393 if combine_func: 394 result.append(combine_func(seen[model], field.column)) 395 else: 396 result.append((seen[model], field.column)) 394 seen[model] = alias 395 if as_str: 396 result.append('%s.%s' % (qn(alias), qn2(field.column))) 397 else: 398 result.append((alias, field.column)) 397 399 return result 398 400 … … 898 900 # make the new additions (and any existing ones not used in the new 899 901 # join list) an outer join. 900 join_it = nested_iter(join_list)902 join_it = itertools.chain(*join_list) 901 903 table_it = iter(self.tables) 902 904 join_it.next(), table_it.next() … … 1326 1328 except EmptyResultSet: 1327 1329 if result_type == MULTI: 1328 r aise StopIteration1330 return empty_iter() 1329 1331 else: 1330 1332 return … … 1333 1335 cursor.execute(sql, params) 1334 1336 1335 if result_type is None:1337 if not result_type: 1336 1338 return cursor 1337 1338 1339 if result_type == SINGLE: 1339 1340 return cursor.fetchone() 1340 1341 1341 # The MULTI case. 1342 return results_iter(cursor)1342 return iter((lambda: cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE)), []) 1343 1343 1344 1344 def get_order_dir(field, default='ASC'): … … 1355 1355 return field, dirn[0] 1356 1356 1357 def results_iter(cursor):1357 def empty_iter(): 1358 1358 """ 1359 An iterator over the result set that returns a chunk of rows at a time.1359 Returns an iterator containing no results. 1360 1360 """ 1361 while 1: 1362 rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE) 1363 if not rows: 1364 raise StopIteration 1365 yield rows 1366 1367 def nested_iter(nested): 1368 """ 1369 An iterator over a sequence of sequences. Each element is returned in turn. 1370 Only handles one level of nesting, since that's all we need here. 1371 """ 1372 for seq in nested: 1373 for elt in seq: 1374 yield elt 1361 yield iter([]).next() 1375 1362 1376 1363 def setup_join_cache(sender): django/branches/queryset-refactor/django/db/models/sql/subqueries.py
r7247 r7253 239 239 def __init__(self, *args, **kwargs): 240 240 super(InsertQuery, self).__init__(*args, **kwargs) 241 self._setup_query()242 243 def _setup_query(self):244 """245 Run on initialisation and after cloning.246 """247 241 self.columns = [] 248 242 self.values = [] 243 self.params = () 244 245 def clone(self, klass=None, **kwargs): 246 extras = {'columns': self.columns[:], 'values': self.values[:], 247 'params': self.params} 248 return super(InsertQuery, self).clone(klass, extras) 249 249 250 250 def as_sql(self): 251 self.select_related = False252 self.pre_sql_setup()253 qn = self. quote_name_unless_alias254 result = ['INSERT INTO %s' % qn(self. tables[0])]251 # We don't need quote_name_unless_alias() here, since these are all 252 # going to be column names (so we can avoid the extra overhead). 253 qn = self.connection.ops.quote_name 254 result = ['INSERT INTO %s' % qn(self.model._meta.db_table)] 255 255 result.append('(%s)' % ', '.join([qn(c) for c in self.columns])) 256 result.append('VALUES (') 257 params = [] 258 first = True 259 for value in self.values: 260 prefix = not first and ', ' or '' 261 if isinstance(value, RawValue): 262 result.append('%s%s' % (prefix, value.value)) 263 else: 264 result.append('%s%%s' % prefix) 265 params.append(value) 266 first = False 267 result.append(')') 268 return ' '.join(result), tuple(params) 256 result.append('VALUES (%s)' % ', '.join(self.values)) 257 return ' '.join(result), self.params 269 258 270 259 def execute_sql(self, return_id=False): 271 260 cursor = super(InsertQuery, self).execute_sql(None) 272 261 if return_id: 273 return self.connection.ops.last_insert_id(cursor, self.tables[0],274 self.model._meta. pk.column)262 return self.connection.ops.last_insert_id(cursor, 263 self.model._meta.db_table, self.model._meta.pk.column) 275 264 276 265 def insert_values(self, insert_values, raw_values=False): … … 286 275 func = lambda x: self.model._meta.get_field_by_name(x)[0].column 287 276 # keys() and values() return items in the same order, providing the 288 # dictionary hasn't changed between calls. So the se lines work as289 # intended.277 # dictionary hasn't changed between calls. So the dual iteration here 278 # works as intended. 290 279 for name in insert_values: 291 280 if name == 'pk': … … 293 282 self.columns.append(func(name)) 294 283 if raw_values: 295 self.values.extend( [RawValue(v) for v in insert_values.values()])284 self.values.extend(insert_values.values()) 296 285 else: 297 self.values.extend(insert_values.values()) 286 values = insert_values.values() 287 self.params += tuple(values) 288 self.values.extend(['%s'] * len(values)) 298 289 299 290 class DateQuery(Query): django/branches/queryset-refactor/tests/modeltests/model_inheritance/models.py
r7241 r7253 264 264 >>> len(db.connection.queries) 265 265 3 266 >>> settings.DEBUG = False 266 267 267 268 """}
