Example #1
0
 def process_query_property(self, query, paths, mappers):
     if self.alias:
         if isinstance(self.alias, basestring):
             mapper = mappers[-1]
             (root_mapper, propname) = paths[-1][-2:]
             prop = mapper.get_property(propname, resolve_synonyms=True)
             self.alias = prop.target.alias(self.alias)
         query._attributes[("user_defined_eager_row_processor", paths[-1])] = sql_util.ColumnAdapter(self.alias)
     else:
         (root_mapper, propname) = paths[-1][-2:]
         mapper = mappers[-1]
         prop = mapper.get_property(propname, resolve_synonyms=True)
         adapter = query._polymorphic_adapters.get(prop.mapper, None)
         query._attributes[("user_defined_eager_row_processor", paths[-1])] = adapter
Example #2
0
 def process_query_property(self, query, paths, mappers):
     if self.alias:
         if isinstance(self.alias, basestring):
             mapper = mappers[-1]
             (root_mapper, propname) = paths[-1][-2:]
             prop = mapper.get_property(propname, resolve_synonyms=True)
             self.alias = prop.target.alias(self.alias)
         query._attributes[("user_defined_eager_row_processor",
                            paths[-1])] = sql_util.ColumnAdapter(self.alias)
     else:
         (root_mapper, propname) = paths[-1][-2:]
         mapper = mappers[-1]
         prop = mapper.get_property(propname, resolve_synonyms=True)
         adapter = query._polymorphic_adapters.get(prop.mapper, None)
         query._attributes[("user_defined_eager_row_processor",
                            paths[-1])] = adapter
Example #3
0
    def with_parent(self, instance, property=None):
        """add a join criterion corresponding to a relationship to the given parent instance.

            instance
                a persistent or detached instance which is related to class represented
                by this query.

            property
                string name of the property which relates this query's class to the 
                instance.  if None, the method will attempt to find a suitable property.

        currently, this method only works with immediate parent relationships, but in the
        future may be enhanced to work across a chain of parent mappers.    
        """

        from sqlalchemy.orm import properties
        mapper = object_mapper(instance)
        if property is None:
            for prop in mapper.iterate_properties:
                if isinstance(prop, properties.PropertyLoader) and prop.mapper is self.mapper:
                    break
            else:
                raise exceptions.InvalidRequestError("Could not locate a property which relates instances of class '%s' to instances of class '%s'" % (self.mapper.class_.__name__, instance.__class__.__name__))
        else:
            prop = mapper.get_property(property, resolve_synonyms=True)
        return self.filter(Query._with_lazy_criterion(instance, prop))
Example #4
0
 def __init__(self, **kwargs):
     for key, value in kwargs.items():
         if ext.validate:
             if not mapper.get_property(key, resolve_synonyms=False,
                                        raiseerr=False):
                 raise sa_exc.ArgumentError(
                     "Invalid __init__ argument: '%s'" % key)
         setattr(self, key, value)
Example #5
0
 def __init__(self, **kwargs):
     for key, value in kwargs.items():
         if ext.validate:
             if not mapper.get_property(key, resolve_synonyms=False,
                                        raiseerr=False):
                 raise sa_exc.ArgumentError(
                     "Invalid __init__ argument: '%s'" % key)
         setattr(self, key, value)
Example #6
0
 def __getattr__(self, key):
     mapper = class_mapper(self.cls, compile=False)
     if not mapper:
         return getattr(self.cls, key)
     else:
         prop = mapper.get_property(key)
         if not isinstance(prop, ColumnProperty):
             raise exceptions.InvalidRequestError("Property %r is not an instance of ColumnProperty (i.e. does not correspnd directly to a Column)." % key)
         return prop.columns[0]
 def __getattr__(self, key):
     mapper = class_mapper(self.cls, compile=False)
     if not mapper:
         return getattr(self.cls, key)
     else:
         prop = mapper.get_property(key)
         if not isinstance(prop, ColumnProperty):
             raise exceptions.InvalidRequestError("Property %r is not an instance of ColumnProperty (i.e. does not correspnd directly to a Column)." % key)
         return prop.columns[0]
Example #8
0
    def process_query_property(self, query, paths):
        if self.alias is not None and self.decorator is None:
            (mapper, propname) = paths[-1][-2:]

            prop = mapper.get_property(propname, resolve_synonyms=True)
            if isinstance(self.alias, basestring):
                self.alias = prop.target.alias(self.alias)

            self.decorator = mapperutil.create_row_adapter(self.alias)
        query._attributes[("eager_row_processor", paths[-1])] = self.decorator
Example #9
0
    def process_query_property(self, query, paths):
        if self.alias:
            if isinstance(self.alias, basestring):
                (mapper, propname) = paths[-1][-2:]

                prop = mapper.get_property(propname, resolve_synonyms=True)
                self.alias = prop.target.alias(self.alias)
            query._attributes[("user_defined_eager_row_processor", paths[-1])] = sql_util.ColumnAdapter(self.alias)
        else:
            query._attributes[("user_defined_eager_row_processor", paths[-1])] = None
Example #10
0
    def process_query_property(self, query, paths):
        if self.alias is not None and self.decorator is None:
            (mapper, propname) = paths[-1][-2:]

            prop = mapper.get_property(propname, resolve_synonyms=True)
            if isinstance(self.alias, basestring):
                self.alias = prop.target.alias(self.alias)

            self.decorator = mapperutil.create_row_adapter(self.alias)
        query._attributes[("eager_row_processor", paths[-1])] = self.decorator
Example #11
0
 def init_instance(self, mapper, class_, oldinit, instance, args, kwargs):
     session = kwargs.pop('_sa_session', self.context.registry())
     if not isinstance(oldinit, types.MethodType):
         for key, value in kwargs.items():
             if self.validate:
                 if not mapper.get_property(key, resolve_synonyms=False, raiseerr=False):
                     raise exceptions.ArgumentError("Invalid __init__ argument: '%s'" % key)
             setattr(instance, key, value)
     if self.save_on_init:
         session._save_impl(instance, entity_name=kwargs.pop('_sa_entity_name', None))
     return EXT_CONTINUE
Example #12
0
    def process_query_property(self, query, paths):
        if self.alias:
            if isinstance(self.alias, basestring):
                (mapper, propname) = paths[-1][-2:]

                prop = mapper.get_property(propname, resolve_synonyms=True)
                self.alias = prop.target.alias(self.alias)
            query._attributes[("user_defined_eager_row_processor",
                               paths[-1])] = sql_util.ColumnAdapter(self.alias)
        else:
            query._attributes[("user_defined_eager_row_processor",
                               paths[-1])] = None
Example #13
0
    def from_dict(self, data):
        """
        Update a mapped class with data from a JSON-style nested dict/list
        structure.
        """
        # surrogate can be guessed from autoincrement/sequence but I guess
        # that's not 100% reliable, so we'll need an override

        mapper = sqlalchemy.orm.object_mapper(self)

        for key, value in data.iteritems():
            if isinstance(value, dict):
                dbvalue = getattr(self, key)
                rel_class = mapper.get_property(key).mapper.class_
                pk_props = rel_class._descriptor.primary_key_properties

                # If the data doesn't contain any pk, and the relationship
                # already has a value, update that record.
                if not [1 for p in pk_props if p.key in data] and \
                   dbvalue is not None:
                    dbvalue.from_dict(value)
                else:
                    record = rel_class.update_or_create(value)
                    setattr(self, key, record)
            elif isinstance(value, list) and \
                 value and isinstance(value[0], dict):

                rel_class = mapper.get_property(key).mapper.class_
                new_attr_value = []
                for row in value:
                    if not isinstance(row, dict):
                        raise Exception(
                                'Cannot send mixed (dict/non dict) data '
                                'to list relationships in from_dict data.')
                    record = rel_class.update_or_create(row)
                    new_attr_value.append(record)
                setattr(self, key, new_attr_value)
            else:
                setattr(self, key, value)
Example #14
0
    def from_dict(self, data):
        """
        Update a mapped class with data from a JSON-style nested dict/list
        structure.
        """
        # surrogate can be guessed from autoincrement/sequence but I guess
        # that's not 100% reliable, so we'll need an override

        mapper = sqlalchemy.orm.object_mapper(self)

        for key, value in data.iteritems():
            if isinstance(value, dict):
                dbvalue = getattr(self, key)
                rel_class = mapper.get_property(key).mapper.class_
                pk_props = rel_class._descriptor.primary_key_properties

                # If the data doesn't contain any pk, and the relationship
                # already has a value, update that record.
                if not [1 for p in pk_props if p.key in data] and \
                   dbvalue is not None:
                    dbvalue.from_dict(value)
                else:
                    record = rel_class.update_or_create(value)
                    setattr(self, key, record)
            elif isinstance(value, list) and \
                 value and isinstance(value[0], dict):

                rel_class = mapper.get_property(key).mapper.class_
                new_attr_value = []
                for row in value:
                    if not isinstance(row, dict):
                        raise Exception(
                                'Cannot send mixed (dict/non dict) data '
                                'to list relationships in from_dict data.')
                    record = rel_class.update_or_create(row)
                    new_attr_value.append(record)
                setattr(self, key, new_attr_value)
            else:
                setattr(self, key, value)
Example #15
0
 def init_instance(self, mapper, class_, oldinit, instance, args, kwargs):
     if self.save_on_init:
         entity_name = kwargs.pop("_sa_entity_name", None)
         session = kwargs.pop("_sa_session", None)
     if not isinstance(oldinit, types.MethodType):
         for key, value in kwargs.items():
             if self.validate:
                 if not mapper.get_property(key, resolve_synonyms=False, raiseerr=False):
                     raise exceptions.ArgumentError("Invalid __init__ argument: '%s'" % key)
             setattr(instance, key, value)
         kwargs.clear()
     if self.save_on_init:
         session = session or self.context.registry()
         session._save_impl(instance, entity_name=entity_name)
     return EXT_CONTINUE
Example #16
0
 def __getattr__(self, key):
     
     mapper = class_mapper(self.cls, compile=False)
     if mapper:
         prop = mapper.get_property(key, raiseerr=False)
         if prop is None:
             raise exceptions.InvalidRequestError(
                         "Class %r does not have a mapped column named %r"
                         % (self.cls, key))
         elif not isinstance(prop, ColumnProperty):
             raise exceptions.InvalidRequestError(
                         "Property %r is not an instance of"
                         " ColumnProperty (i.e. does not correspond"
                         " directly to a Column)." % key)
     return getattr(self.cls, key)
Example #17
0
    def _join_to(self, prop, outerjoin=False, start=None):
        if start is None:
            start = self._joinpoint

        if isinstance(prop, list):
            keys = prop
        else:
            [keys,p] = self._locate_prop(prop, start=start)

        clause = self._from_obj[-1]

        currenttables = [clause]
        class FindJoinedTables(sql.NoColumnVisitor):
            def visit_join(self, join):
                currenttables.append(join.left)
                currenttables.append(join.right)
        FindJoinedTables().traverse(clause)
            
        mapper = start
        for key in keys:
            prop = mapper.get_property(key, resolve_synonyms=True)
            if prop._is_self_referential():
                raise exceptions.InvalidRequestError("Self-referential query on '%s' property must be constructed manually using an Alias object for the related table." % str(prop))
            # dont re-join to a table already in our from objects
            if prop.select_table not in currenttables:
                if outerjoin:
                    if prop.secondary:
                        clause = clause.outerjoin(prop.secondary, prop.get_join(mapper, primary=True, secondary=False))
                        clause = clause.outerjoin(prop.select_table, prop.get_join(mapper, primary=False))
                    else:
                        clause = clause.outerjoin(prop.select_table, prop.get_join(mapper))
                else:
                    if prop.secondary:
                        clause = clause.join(prop.secondary, prop.get_join(mapper, primary=True, secondary=False))
                        clause = clause.join(prop.select_table, prop.get_join(mapper, primary=False))
                    else:
                        clause = clause.join(prop.select_table, prop.get_join(mapper))
            elif prop.secondary is not None and prop.secondary not in currenttables:
                # TODO: this check is not strong enough for different paths to the same endpoint which
                # does not use secondary tables
                raise exceptions.InvalidRequestError("Can't join to property '%s'; a path to this table along a different secondary table already exists.  Use explicit `Alias` objects." % prop.key)
                
            mapper = prop.mapper
            
        return (clause, mapper)
Example #18
0
    def compile(self, prop):
        """Called by the owning PropertyLoader to set up a
        backreference on the PropertyLoader's mapper.
        """

        # try to set a LazyLoader on our mapper referencing the parent mapper
        mapper = prop.mapper.primary_mapper()
        if not mapper.get_property(self.key, raiseerr=False) is not None:
            pj = self.kwargs.pop('primaryjoin', None)
            sj = self.kwargs.pop('secondaryjoin', None)
            # the backref property is set on the primary mapper
            parent = prop.parent.primary_mapper()
            self.kwargs.setdefault('viewonly', prop.viewonly)
            self.kwargs.setdefault('post_update', prop.post_update)
            relation = PropertyLoader(parent,
                                      prop.secondary,
                                      pj,
                                      sj,
                                      backref=prop.key,
                                      is_backref=True,
                                      **self.kwargs)
            mapper._compile_property(self.key, relation)
        elif not isinstance(mapper.get_property(self.key), PropertyLoader):
            raise exceptions.ArgumentError(
                "Can't create backref '%s' on mapper '%s'; an incompatible "
                "property of that name already exists" %
                (self.key, str(mapper)))
        else:
            # else set one of us as the "backreference"
            parent = prop.parent.primary_mapper()
            if parent.class_ is not mapper.get_property(
                    self.key)._get_target_class():
                raise exceptions.ArgumentError(
                    "Backrefs do not match:  backref '%s' expects to connect to %s, "
                    "but found a backref already connected to %s" %
                    (self.key, str(parent.class_),
                     str(mapper.get_property(self.key).mapper.class_)))
            if not mapper.get_property(self.key).is_backref:
                prop.is_backref = True
                if not prop.viewonly:
                    prop._dependency_processor.is_backref = True
                    # reverse_property used by dependencies.ManyToManyDP to check
                    # association table operations
                    prop.reverse_property = mapper.get_property(self.key)
                    mapper.get_property(self.key).reverse_property = prop
Example #19
0
    def join_via(self, keys):
        """Given a list of keys that represents a path from this
        Query's mapper to a related mapper based on names of relations
        from one mapper to the next, return a ClauseElement
        representing a join from this Query's mapper to the endmost
        mapper.

        this method is deprecated in 0.4.
        """

        mapper = self.mapper
        clause = None
        for key in keys:
            prop = mapper.get_property(key, resolve_synonyms=True)
            if clause is None:
                clause = prop.get_join(mapper)
            else:
                clause &= prop.get_join(mapper)
            mapper = prop.mapper

        return clause
Example #20
0
    def query_from_parent(cls, instance, property, **kwargs):
        """return a newly constructed Query object, with criterion corresponding to 
        a relationship to the given parent instance.

            instance
                a persistent or detached instance which is related to class represented
                by this query.

            property
                string name of the property which relates this query's class to the 
                instance. 
                
            \**kwargs
                all extra keyword arguments are propigated to the constructor of
                Query.
                
        """
        
        mapper = object_mapper(instance)
        prop = mapper.get_property(property, resolve_synonyms=True)
        target = prop.mapper
        criterion = cls._with_lazy_criterion(instance, prop)
        return Query(target, **kwargs).filter(criterion)