From: Mike Bayer Date: Tue, 3 Jan 2006 00:40:40 +0000 (+0000) Subject: cleanup to mapper/relation order_by parameter to be more consistently picked up X-Git-Tag: rel_0_1_0~173 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cc1cd920e0ca8957c6edeae6ff5b9ef8fb85a412;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git cleanup to mapper/relation order_by parameter to be more consistently picked up down the chain of engine->mapper->select() documented mapperoption methods --- diff --git a/lib/sqlalchemy/mapping/mapper.py b/lib/sqlalchemy/mapping/mapper.py index 9108c0308c..2437cdc371 100644 --- a/lib/sqlalchemy/mapping/mapper.py +++ b/lib/sqlalchemy/mapping/mapper.py @@ -598,41 +598,33 @@ class Mapper(object): ) def _compile(self, whereclause = None, **kwargs): - no_sort = kwargs.pop('no_sort', False) or (self.order_by is None) - if not no_sort: - if self.order_by: - order_by = self.order_by - elif self.table.default_order_by() is not None: + order_by = kwargs.pop('order_by', False) + if order_by is False: + order_by = self.order_by + if order_by is False: + if self.table.default_order_by() is not None: order_by = self.table.default_order_by() - else: - order_by = None - else: - order_by = None - + if self._should_nest(**kwargs): s2 = sql.select(self.table.primary_key, whereclause, use_labels=True, **kwargs) - if not kwargs.get('distinct', False) and self.table.default_order_by() is not None: - s2.order_by(*self.table.default_order_by()) + if not kwargs.get('distinct', False) and order_by: + s2.order_by(*util.to_list(order_by)) s3 = s2.alias('rowcount') crit = [] for i in range(0, len(self.table.primary_key)): crit.append(s3.primary_key[i] == self.table.primary_key[i]) statement = sql.select([], sql.and_(*crit), from_obj=[self.table], use_labels=True) - if kwargs.has_key('order_by'): - statement.order_by(*kwargs['order_by']) - else: - statement.order_by(*order_by) + if order_by: + statement.order_by(*util.to_list(order_by)) else: statement = sql.select([], whereclause, from_obj=[self.table], use_labels=True, **kwargs) - if order_by is not None and kwargs.get('order_by', None) is None: - statement.order_by(*order_by) + if order_by: + statement.order_by(*util.to_list(order_by)) # for a DISTINCT query, you need the columns explicitly specified in order - # to use it in "order_by" - in the case we added the oid column in, - # add that to the column list - # TODO: this idea should be handled by the SELECT statement itself, insuring - # that order_by cols are in the select list if DISTINCT is selected - if kwargs.get('distinct', False) and self.table.default_order_by() is not None and order_by == [self.table.default_order_by()]: - statement.append_column(*self.table.default_order_by()) + # to use it in "order_by". insure they are in the column criterion (particularly oid). + # TODO: this should be done at the SQL level not the mapper level + if kwargs.get('distinct', False) and order_by: + statement.append_column(*util.to_list(order_by)) # plugin point @@ -762,22 +754,64 @@ class MapperExtension(object): def __init__(self): self.next = None def create_instance(self, mapper, row, imap, class_): + """called when a new object instance is about to be created from a row. + the method can choose to create the instance itself, or it can return + None to indicate normal object creation should take place. + + mapper - the mapper doing the operation + + row - the result row from the database + + imap - a dictionary that is storing the running set of objects collected from the + current result set + + class_ - the class we are mapping. + """ if self.next is None: return None else: return self.next.create_instance(mapper, row, imap, class_) def append_result(self, mapper, row, imap, result, instance, isnew, populate_existing=False): + """called when an object instance is being appended to a result list. + + If it returns True, it is assumed that this method handled the appending itself. + + mapper - the mapper doing the operation + + row - the result row from the database + + imap - a dictionary that is storing the running set of objects collected from the + current result set + + result - an instance of util.HistoryArraySet(), which may be an attribute on an + object if this is a related object load (lazy or eager). use result.append_nohistory(value) + to append objects to this list. + + instance - the object instance to be appended to the result + + isnew - indicates if this is the first time we have seen this object instance in the current result + set. if you are selecting from a join, such as an eager load, you might see the same object instance + many times in the same result set. + + populate_existing - usually False, indicates if object instances that were already in the main + identity map, i.e. were loaded by a previous select(), get their attributes overwritten + """ if self.next is None: return True else: return self.next.append_result(mapper, row, imap, result, instance, isnew, populate_existing) def before_insert(self, mapper, instance): + """called before an object instance is INSERTed into its table. + + this is a good place to set up primary key values and such that arent handled otherwise.""" if self.next is not None: self.next.before_insert(mapper, instance) def after_insert(self, mapper, instance): + """called after an object instance has been INSERTed""" if self.next is not None: self.next.after_insert(mapper, instance) def before_delete(self, mapper, instance): + """called before an object instance is DELETEed""" if self.next is not None: self.next.before_delete(mapper, instance) diff --git a/lib/sqlalchemy/mapping/properties.py b/lib/sqlalchemy/mapping/properties.py index 3f9578372e..502fd794df 100644 --- a/lib/sqlalchemy/mapping/properties.py +++ b/lib/sqlalchemy/mapping/properties.py @@ -121,7 +121,7 @@ class PropertyLoader(MapperProperty): """describes an object property that holds a single item or list of items that correspond to a related database table.""" - def __init__(self, argument, secondary, primaryjoin, secondaryjoin, foreignkey=None, uselist=None, private=False, live=False, association=None, selectalias=None, order_by=None, attributeext=None, backref=None, is_backref=False): + def __init__(self, argument, secondary, primaryjoin, secondaryjoin, foreignkey=None, uselist=None, private=False, live=False, association=None, selectalias=None, order_by=False, attributeext=None, backref=None, is_backref=False): self.uselist = uselist self.argument = argument self.secondary = secondary @@ -132,7 +132,7 @@ class PropertyLoader(MapperProperty): self.live = live self.association = association self.selectalias = selectalias - self.order_by=util.to_list(order_by) + self.order_by = order_by self.attributeext=attributeext self.backref = backref self.is_backref = is_backref @@ -590,12 +590,12 @@ class LazyLoader(PropertyLoader): allparams = False break if allparams: - if self.order_by is not None: + if self.order_by is not False: order_by = self.order_by elif self.secondary is not None and self.secondary.default_order_by() is not None: order_by = self.secondary.default_order_by() else: - order_by = None + order_by = False result = self.mapper.select(self.lazywhere, order_by=order_by, params=params) else: result = [] @@ -677,15 +677,15 @@ class EagerLoader(PropertyLoader): else: self.eagerprimary = self.primaryjoin.copy_container() self.eagerprimary.accept_visitor(aliasizer) - if self.order_by is not None: - self.eager_order_by = [o.copy_container() for o in self.order_by] + if self.order_by: + self.eager_order_by = [o.copy_container() for o in util.to_list(self.order_by)] for i in range(0, len(self.eager_order_by)): if isinstance(self.eager_order_by[i], schema.Column): self.eager_order_by[i] = self.eagertarget._get_col_by_original(self.eager_order_by[i]) else: self.eager_order_by[i].accept_visitor(aliasizer) else: - self.eager_order_by = None + self.eager_order_by = self.order_by else: self.eagertarget = self.target self.eagerprimary = self.primaryjoin @@ -714,15 +714,15 @@ class EagerLoader(PropertyLoader): if self.secondaryjoin is not None: statement._outerjoin = sql.outerjoin(towrap, self.secondary, self.primaryjoin).outerjoin(self.eagertarget, self.eagersecondary) - if self.order_by is None and self.secondary.default_order_by() is not None: + if self.order_by is False and self.secondary.default_order_by() is not None: statement.order_by(*self.secondary.default_order_by()) else: statement._outerjoin = towrap.outerjoin(self.eagertarget, self.eagerprimary) - if self.order_by is None and self.eagertarget.default_order_by() is not None: + if self.order_by is False and self.eagertarget.default_order_by() is not None: statement.order_by(*self.eagertarget.default_order_by()) - if self.eager_order_by is not None: - statement.order_by(*self.eager_order_by) + if self.eager_order_by: + statement.order_by(*util.to_list(self.eager_order_by)) statement.append_from(statement._outerjoin) #statement.append_column(self.eagertarget)