Exemple #1
0
 def selectone_by(self, *args, **params):
     """works like selectfirst_by(), but throws an error if not exactly one result was returned."""
     ret = self.select_whereclause(self.join_by(*args, **params), limit=2)
     if len(ret) == 1:
         return ret[0]
     elif len(ret) == 0:
         raise exceptions.InvalidRequestError(
             'No rows returned for selectone_by')
     else:
         raise exceptions.InvalidRequestError(
             'Multiple rows returned for selectone_by')
Exemple #2
0
 def selectone(self, *args, **params):
     """works like selectfirst(), but throws an error if not exactly one result was returned."""
     ret = list(self.select(*args, **params)[0:2])
     if len(ret) == 1:
         return ret[0]
     elif len(ret) == 0:
         raise exceptions.InvalidRequestError(
             'No rows returned for selectone_by')
     else:
         raise exceptions.InvalidRequestError(
             'Multiple rows returned for selectone')
Exemple #3
0
 def refresh(self, obj):
     """reload the attributes for the given object from the database, clear any changes made."""
     self._validate_persistent(obj)
     if self.query(obj.__class__)._get(obj._instance_key,
                                       reload=True) is None:
         raise exceptions.InvalidRequestError(
             "Could not refresh instance '%s'" % repr(obj))
Exemple #4
0
 def _update_impl(self, object, **kwargs):
     if self._is_attached(object) and object not in self.deleted:
         return
     if not hasattr(object, '_instance_key'):
         raise exceptions.InvalidRequestError(
             "Instance '%s' is not persisted" % repr(object))
     self._attach(object)
Exemple #5
0
 def invalidate(self):
     if self.connection is None:
         raise exceptions.InvalidRequestError("This connection is closed")
     self._connection_record.invalidate()
     self.connection = None
     self._cursors = None
     self._close()
Exemple #6
0
 def get_bind(self, mapper):
     """return the Engine or Connection which is used to execute statements on behalf of the given Mapper.
     
     Calling connect() on the return result will always result in a Connection object.  This method 
     disregards any SessionTransaction that may be in progress.
     
     The order of searching is as follows:
     
     if an Engine or Connection was bound to this Mapper specifically within this Session, returns that 
     Engine or Connection.
     
     if an Engine or Connection was bound to this Mapper's underlying Table within this Session
     (i.e. not to the Table directly), returns that Engine or Conneciton.
     
     if an Engine or Connection was bound to this Session, returns that Engine or Connection.
     
     finally, returns the Engine which was bound directly to the Table's MetaData object.  
     
     If no Engine is bound to the Table, an exception is raised.
     """
     if mapper is None:
         return self.bind_to
     elif self.binds.has_key(mapper):
         return self.binds[mapper]
     elif self.binds.has_key(mapper.mapped_table):
         return self.binds[mapper.mapped_table]
     elif self.bind_to is not None:
         return self.bind_to
     else:
         e = mapper.mapped_table.engine
         if e is None:
             raise exceptions.InvalidRequestError(
                 "Could not locate any Engine bound to mapper '%s'" %
                 str(mapper))
         return e
Exemple #7
0
    def _locate_prop(self, key, start=None):
        import properties
        keys = []
        seen = util.Set()

        def search_for_prop(mapper_):
            if mapper_ in seen:
                return None
            seen.add(mapper_)
            if mapper_.props.has_key(key):
                prop = mapper_.props[key]
                if isinstance(prop, properties.SynonymProperty):
                    prop = mapper_.props[prop.name]
                if isinstance(prop, properties.PropertyLoader):
                    keys.insert(0, prop.key)
                return prop
            else:
                for prop in mapper_.props.values():
                    if not isinstance(prop, properties.PropertyLoader):
                        continue
                    x = search_for_prop(prop.mapper)
                    if x:
                        keys.insert(0, prop.key)
                        return x
                else:
                    return None

        p = search_for_prop(start or self.mapper)
        if p is None:
            raise exceptions.InvalidRequestError(
                "Cant locate property named '%s'" % key)
        return [keys, p]
Exemple #8
0
        def lazyload():
            if self._should_log_debug:
                self.logger.debug("deferred load %s group %s" %
                                  (mapperutil.attribute_str(
                                      instance, self.key), str(self.group)))
            try:
                pk = self.parent.pks_by_table[self.columns[0].table]
            except KeyError:
                pk = self.columns[0].table.primary_key

            clause = sql.and_()
            for primary_key in pk:
                attr = self.parent.get_attr_by_column(instance, primary_key)
                if not attr:
                    return None
                clause.clauses.append(primary_key == attr)

            session = sessionlib.object_session(instance)
            if session is None:
                raise exceptions.InvalidRequestError(
                    "Parent instance %s is not bound to a Session; deferred load operation of attribute '%s' cannot proceed"
                    % (instance.__class__, self.key))

            localparent = mapper.object_mapper(instance)
            if self.group is not None:
                groupcols = [
                    p for p in localparent.props.values()
                    if isinstance(p.strategy, DeferredColumnLoader)
                    and p.group == self.group
                ]
                result = session.execute(
                    localparent,
                    sql.select([g.columns[0] for g in groupcols],
                               clause,
                               use_labels=True), None)
                try:
                    row = result.fetchone()
                    for prop in groupcols:
                        if prop is self:
                            continue
                        # set a scalar object instance directly on the object,
                        # bypassing SmartProperty event handlers.
                        sessionlib.attribute_manager.init_instance_attribute(
                            instance, prop.key, uselist=False)
                        instance.__dict__[prop.key] = row[prop.columns[0]]
                    return row[self.columns[0]]
                finally:
                    result.close()
            else:
                return session.scalar(
                    localparent,
                    sql.select([self.columns[0]], clause, use_labels=True),
                    None)
Exemple #9
0
    def create(self, name_or_url, **kwargs):
        # create url.URL object
        u = url.make_url(name_or_url)

        # get module from sqlalchemy.databases
        module = u.get_module()

        dialect_args = {}
        # consume dialect arguments from kwargs
        for k in util.get_cls_kwargs(module.dialect):
            if k in kwargs:
                dialect_args[k] = kwargs.pop(k)

        # create dialect
        dialect = module.dialect(**dialect_args)

        # assemble connection arguments
        (cargs, cparams) = dialect.create_connect_args(u)
        cparams.update(kwargs.pop('connect_args', {}))

        # look for existing pool or create
        pool = kwargs.pop('pool', None)
        if pool is None:
            dbapi = kwargs.pop('module', dialect.dbapi())
            if dbapi is None:
                raise exceptions.InvalidRequestError(
                    "Cant get DBAPI module for dialect '%s'" % dialect)

            def connect():
                try:
                    return dbapi.connect(*cargs, **cparams)
                except Exception, e:
                    raise exceptions.DBAPIError("Connection failed", e)

            creator = kwargs.pop('creator', connect)

            poolclass = kwargs.pop(
                'poolclass', getattr(module, 'poolclass', poollib.QueuePool))
            pool_args = {}
            # consume pool arguments from kwargs, translating a few of the arguments
            for k in util.get_cls_kwargs(poolclass):
                tk = {
                    'echo': 'echo_pool',
                    'timeout': 'pool_timeout',
                    'recycle': 'pool_recycle'
                }.get(k, k)
                if tk in kwargs:
                    pool_args[k] = kwargs.pop(tk)
            pool_args['use_threadlocal'] = self.pool_threadlocal()
            pool = poolclass(creator, **pool_args)
Exemple #10
0
 def load(self, ident, **kwargs):
     """return an instance of the object based on the given identifier. 
     
     If not found, raises an exception.  The method will *remove all pending changes* to the object
     already existing in the Session.  The ident argument is a scalar or tuple of primary
     key column values in the order of the table def's primary key columns."""
     ret = self.extension.load(self, ident, **kwargs)
     if ret is not mapper.EXT_PASS:
         return ret
     key = self.mapper.identity_key(ident)
     instance = self._get(key, ident, reload=True, **kwargs)
     if instance is None:
         raise exceptions.InvalidRequestError(
             "No instance found for identity %s" % repr(ident))
     return instance
Exemple #11
0
    def _save_impl(self, object, **kwargs):
        if hasattr(object, '_instance_key'):
            if not self.identity_map.has_key(object._instance_key):
                raise exceptions.InvalidRequestError(
                    "Instance '%s' is a detached instance or is already persistent in a different Session"
                    % repr(object))
        else:
            m = _class_mapper(object.__class__,
                              entity_name=kwargs.get('entity_name', None))

            # this would be a nice exception to raise...however this is incompatible with a contextual
            # session which puts all objects into the session upon construction.
            #if m._is_orphan(object):
            #    raise exceptions.InvalidRequestError("Instance '%s' is an orphan, and must be attached to a parent object to be saved" % (repr(object)))

            m._assign_entity_name(object)
            self._register_pending(object)
Exemple #12
0
    def _attach(self, obj):
        """Attach the given object to this Session."""
        if getattr(obj, '_sa_session_id', None) != self.hash_key:
            old = getattr(obj, '_sa_session_id', None)
            if old is not None and _sessions.has_key(old):
                raise exceptions.InvalidRequestError(
                    "Object '%s' is already attached to session '%s' (this is '%s')"
                    % (repr(obj), old, id(self)))

                # auto-removal from the old session is disabled.  but if we decide to
                # turn it back on, do it as below: gingerly since _sessions is a WeakValueDict
                # and it might be affected by other threads
                #try:
                #    sess = _sessions[old]
                #except KeyError:
                #    sess = None
                #if sess is not None:
                #    sess.expunge(old)
            key = getattr(obj, '_instance_key', None)
            if key is not None:
                self.identity_map[key] = obj
            obj._sa_session_id = self.hash_key
Exemple #13
0
 def _close(self):
     if self._cursors is not None:
         # cursors should be closed before connection is returned to the pool.  some dbapis like
         # mysql have real issues if they are not.
         if self.__pool.auto_close_cursors:
             self.close_open_cursors()
         elif self.__pool.disallow_open_cursors:
             if len(self._cursors):
                 raise exceptions.InvalidRequestError("This connection still has %d open cursors" % len(self._cursors))
     if self.connection is not None:
         try:
             self.connection.rollback()
         except:
             if self._connection_record is not None:
                 self._connection_record.invalidate()
     if self._connection_record is not None:
         if self.__pool.echo:
             self.__pool.log("Connection %s being returned to pool" % repr(self.connection))
         self.__pool.return_conn(self)
     self.connection = None
     self._connection_record = None
     self._threadfairy = None
     self._cursors = None
Exemple #14
0
 def _executioncontext(self):
     try:
         return self.__executioncontext
     except AttributeError:
         raise exceptions.InvalidRequestError("This ResultProxy does not have an execution context with which to complete this operation.  Execution contexts are not generated for literal SQL execution.")
Exemple #15
0
        def lazyload():
            self.logger.debug("lazy load attribute %s on instance %s" %
                              (self.key, mapperutil.instance_str(instance)))
            params = {}
            allparams = True
            # if the instance wasnt loaded from the database, then it cannot lazy load
            # child items.  one reason for this is that a bi-directional relationship
            # will not update properly, since bi-directional uses lazy loading functions
            # in both directions, and this instance will not be present in the lazily-loaded
            # results of the other objects since its not in the database
            if not mapper.has_identity(instance):
                return None
            #print "setting up loader, lazywhere", str(self.lazywhere), "binds", self.lazybinds
            for col, bind in self.lazybinds.iteritems():
                params[bind.key] = self.parent.get_attr_by_column(
                    instance, col)
                if params[bind.key] is None:
                    allparams = False
                    break

            if not allparams:
                return None

            session = sessionlib.object_session(instance)
            if session is None:
                try:
                    session = mapper.object_mapper(instance).get_session()
                except exceptions.InvalidRequestError:
                    raise exceptions.InvalidRequestError(
                        "Parent instance %s is not bound to a Session, and no contextual session is established; lazy load operation of attribute '%s' cannot proceed"
                        % (instance.__class__, self.key))

            # if we have a simple straight-primary key load, use mapper.get()
            # to possibly save a DB round trip
            if self.use_get:
                ident = []
                for primary_key in self.mapper.pks_by_table[
                        self.mapper.mapped_table]:
                    bind = self.lazyreverse[primary_key]
                    ident.append(params[bind.key])
                return session.query(self.mapper).get(ident)
            elif 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 = False
            result = session.query(self.mapper,
                                   with_options=options).select_whereclause(
                                       self.lazywhere,
                                       order_by=order_by,
                                       params=params)

            if self.uselist:
                return result
            else:
                if len(result):
                    return result[0]
                else:
                    return None
Exemple #16
0
 def checkout(self):
     if self.connection is None:
         raise exceptions.InvalidRequestError("This connection is closed")
     self.__counter +=1
     return self
Exemple #17
0
    def setup_query(self,
                    context,
                    eagertable=None,
                    parentclauses=None,
                    parentmapper=None,
                    **kwargs):
        """add a left outer join to the statement thats being constructed"""
        if parentmapper is None:
            localparent = context.mapper
        else:
            localparent = parentmapper

        if self.mapper in context.recursion_stack:
            return
        else:
            context.recursion_stack.add(self.parent)

        statement = context.statement

        if hasattr(statement, '_outerjoin'):
            towrap = statement._outerjoin
        elif isinstance(localparent.mapped_table, schema.Table):
            # if the mapper is against a plain Table, look in the from_obj of the select statement
            # to join against whats already there.
            for (fromclause, finder) in [(x, sql_util.TableFinder(x))
                                         for x in statement.froms]:
                # dont join against an Alias'ed Select.  we are really looking either for the
                # table itself or a Join that contains the table.  this logic still might need
                # adjustments for scenarios not thought of yet.
                if not isinstance(
                        fromclause,
                        sql.Alias) and localparent.mapped_table in finder:
                    towrap = fromclause
                    break
            else:
                raise exceptions.InvalidRequestError(
                    "EagerLoader cannot locate a clause with which to outer join to, in query '%s' %s"
                    % (str(statement), self.localparent.mapped_table))
        else:
            # if the mapper is against a select statement or something, we cant handle that at the
            # same time as a custom FROM clause right now.
            towrap = localparent.mapped_table

        try:
            clauses = self.clauses[parentclauses]
        except KeyError:
            clauses = EagerLoader.AliasedClauses(self, parentclauses)
            self.clauses[parentclauses] = clauses
            self.clauses_by_lead_mapper[context.mapper] = clauses

        if self.secondaryjoin is not None:
            statement._outerjoin = sql.outerjoin(
                towrap, clauses.eagersecondary,
                clauses.eagerprimary).outerjoin(clauses.eagertarget,
                                                clauses.eagersecondaryjoin)
            if self.order_by is False and self.secondary.default_order_by(
            ) is not None:
                statement.order_by(*clauses.eagersecondary.default_order_by())
        else:
            statement._outerjoin = towrap.outerjoin(clauses.eagertarget,
                                                    clauses.eagerprimary)
            if self.order_by is False and clauses.eagertarget.default_order_by(
            ) is not None:
                statement.order_by(*clauses.eagertarget.default_order_by())

        if clauses.eager_order_by:
            statement.order_by(*util.to_list(clauses.eager_order_by))
        elif getattr(statement, 'order_by_clause', None):
            clauses._aliasize_orderby(statement.order_by_clause, False)

        statement.append_from(statement._outerjoin)
        for value in self.select_mapper.props.values():
            value.setup(context,
                        eagertable=clauses.eagertarget,
                        parentclauses=clauses,
                        parentmapper=self.select_mapper)
Exemple #18
0
 def _validate_attached(self, obj):
     """validate that the given object is either pending or persistent within this Session."""
     if not self._is_attached(obj):
         raise exceptions.InvalidRequestError(
             "Instance '%s' not attached to this Session" % repr(obj))
Exemple #19
0
 def _get_connection(self):
     try:
         return self.__connection
     except AttributeError:
         raise exceptions.InvalidRequestError("This Connection is closed")
Exemple #20
0
 def commit(self):
     if not self.__parent.__is_active:
         raise exceptions.InvalidRequestError("This transaction is inactive")
     if self.__parent is self:
         self.__connection._commit_impl()
         self.__is_active = False
Exemple #21
0
 def add(self, connectable):
     if self.connections.has_key(connectable.engine):
         raise exceptions.InvalidRequestError(
             "Session already has a Connection associated for the given Connection's Engine"
         )
     return self.get_or_add(connectable)
Exemple #22
0
 def exp():
     if self.query(obj.__class__)._get(obj._instance_key,
                                       reload=True) is None:
         raise exceptions.InvalidRequestError(
             "Could not refresh instance '%s'" % repr(obj))
Exemple #23
0
 def convert_result_value(self, arg, engine):
     raise exceptions.InvalidRequestError("Ambiguous column name '%s' in result set! try 'use_labels' option on select statement." % (self.key))