Esempio n. 1
0
 def test_serialize(self):
     d = util.frozendict({1: 2, 3: 4})
     for loads, dumps in picklers():
         print loads(dumps(d))
Esempio n. 2
0
class DefaultExecutionContext(base.ExecutionContext):
    execution_options = util.frozendict()
    isinsert = False
    isupdate = False
    isdelete = False
    isddl = False
    executemany = False
    result_map = None
    compiled = None
    statement = None
    
    def __init__(self, 
                    dialect, 
                    connection, 
                    compiled_sql=None, 
                    compiled_ddl=None, 
                    statement=None, 
                    parameters=None):
        
        self.dialect = dialect
        self._connection = self.root_connection = connection
        self.engine = connection.engine
        
        if compiled_ddl is not None:
            self.compiled = compiled = compiled_ddl
            self.isddl = True

            if compiled.statement._execution_options:
                self.execution_options = compiled.statement._execution_options
            if connection._execution_options:
                self.execution_options = self.execution_options.union(
                                                    connection._execution_options
                                                    )

            if not dialect.supports_unicode_statements:
                self.unicode_statement = unicode(compiled)
                self.statement = self.unicode_statement.encode(self.dialect.encoding)
            else:
                self.statement = self.unicode_statement = unicode(compiled)
                
            self.cursor = self.create_cursor()
            self.compiled_parameters = []
            self.parameters = [self._default_params]
            
        elif compiled_sql is not None:
            self.compiled = compiled = compiled_sql

            if not compiled.can_execute:
                raise exc.ArgumentError("Not an executable clause: %s" % compiled)

            if compiled.statement._execution_options:
                self.execution_options = compiled.statement._execution_options
            if connection._execution_options:
                self.execution_options = self.execution_options.union(
                                                        connection._execution_options
                                                        )

            # compiled clauseelement.  process bind params, process table defaults,
            # track collections used by ResultProxy to target and process results

            self.processors = dict(
                (key, value) for key, value in
                ( (compiled.bind_names[bindparam],
                   bindparam.bind_processor(self.dialect))
                  for bindparam in compiled.bind_names )
                if value is not None)

            self.result_map = compiled.result_map

            if not dialect.supports_unicode_statements:
                self.unicode_statement = unicode(compiled)
                self.statement = self.unicode_statement.encode(self.dialect.encoding)
            else:
                self.statement = self.unicode_statement = unicode(compiled)

            self.isinsert = compiled.isinsert
            self.isupdate = compiled.isupdate
            self.isdelete = compiled.isdelete

            if not parameters:
                self.compiled_parameters = [compiled.construct_params()]
            else:
                self.compiled_parameters = [compiled.construct_params(m, _group_number=grp) for
                                            grp,m in enumerate(parameters)]
                                            
                self.executemany = len(parameters) > 1

            self.cursor = self.create_cursor()
            if self.isinsert or self.isupdate:
                self.__process_defaults()
            self.parameters = self.__convert_compiled_params(self.compiled_parameters)
            
        elif statement is not None:
            # plain text statement
            if connection._execution_options:
                self.execution_options = self.execution_options.union(connection._execution_options)
            self.parameters = self.__encode_param_keys(parameters)
            self.executemany = len(parameters) > 1
            
            if isinstance(statement, unicode) and not dialect.supports_unicode_statements:
                self.unicode_statement = statement
                self.statement = statement.encode(self.dialect.encoding)
            else:
                self.statement = self.unicode_statement = statement
                
            self.cursor = self.create_cursor()
        else:
            # no statement. used for standalone ColumnDefault execution.
            if connection._execution_options:
                self.execution_options = self.execution_options.union(connection._execution_options)
            self.cursor = self.create_cursor()
        
    @util.memoized_property
    def is_crud(self):
        return self.isinsert or self.isupdate or self.isdelete
        
    @util.memoized_property
    def should_autocommit(self):
        autocommit = self.execution_options.get('autocommit', 
                                                not self.compiled and 
                                                self.statement and
                                                expression.PARSE_AUTOCOMMIT 
                                                or False)
                                                
        if autocommit is expression.PARSE_AUTOCOMMIT:
            return self.should_autocommit_text(self.unicode_statement)
        else:
            return autocommit
            
    @util.memoized_property
    def _is_explicit_returning(self):
        return self.compiled and \
            getattr(self.compiled.statement, '_returning', False)
    
    @util.memoized_property
    def _is_implicit_returning(self):
        return self.compiled and \
            bool(self.compiled.returning) and \
            not self.compiled.statement._returning
    
    @util.memoized_property
    def _default_params(self):
        if self.dialect.positional:
            return self.dialect.execute_sequence_format()
        else:
            return {}
        
    def _execute_scalar(self, stmt):
        """Execute a string statement on the current cursor, returning a
        scalar result.
        
        Used to fire off sequences, default phrases, and "select lastrowid"
        types of statements individually or in the context of a parent INSERT
        or UPDATE statement.
        
        """

        conn = self._connection
        if isinstance(stmt, unicode) and not self.dialect.supports_unicode_statements:
            stmt = stmt.encode(self.dialect.encoding)
        conn._cursor_execute(self.cursor, stmt, self._default_params)
        return self.cursor.fetchone()[0]
    
    @property
    def connection(self):
        return self._connection._branch()

    def __encode_param_keys(self, params):
        """Apply string encoding to the keys of dictionary-based bind parameters.

        This is only used executing textual, non-compiled SQL expressions.
        
        """
        
        if not params:
            return [self._default_params]
        elif isinstance(params[0], self.dialect.execute_sequence_format):
            return params
        elif isinstance(params[0], dict):
            if self.dialect.supports_unicode_statements:
                return params
            else:
                def proc(d):
                    return dict((k.encode(self.dialect.encoding), d[k]) for k in d)
                return [proc(d) for d in params] or [{}]
        else:
            return [self.dialect.execute_sequence_format(p) for p in params]
        

    def __convert_compiled_params(self, compiled_parameters):
        """Convert the dictionary of bind parameter values into a dict or list
        to be sent to the DBAPI's execute() or executemany() method.
        """

        processors = self.processors
        parameters = []
        if self.dialect.positional:
            for compiled_params in compiled_parameters:
                param = []
                for key in self.compiled.positiontup:
                    if key in processors:
                        param.append(processors[key](compiled_params[key]))
                    else:
                        param.append(compiled_params[key])
                parameters.append(self.dialect.execute_sequence_format(param))
        else:
            encode = not self.dialect.supports_unicode_statements
            for compiled_params in compiled_parameters:
                param = {}
                if encode:
                    encoding = self.dialect.encoding
                    for key in compiled_params:
                        if key in processors:
                            param[key.encode(encoding)] = processors[key](compiled_params[key])
                        else:
                            param[key.encode(encoding)] = compiled_params[key]
                else:
                    for key in compiled_params:
                        if key in processors:
                            param[key] = processors[key](compiled_params[key])
                        else:
                            param[key] = compiled_params[key]
                parameters.append(param)
        return self.dialect.execute_sequence_format(parameters)

    def should_autocommit_text(self, statement):
        return AUTOCOMMIT_REGEXP.match(statement)

    def create_cursor(self):
        return self._connection.connection.cursor()

    def pre_exec(self):
        pass

    def post_exec(self):
        pass
    
    def get_lastrowid(self):
        """return self.cursor.lastrowid, or equivalent, after an INSERT.
        
        This may involve calling special cursor functions,
        issuing a new SELECT on the cursor (or a new one),
        or returning a stored value that was
        calculated within post_exec().
        
        This function will only be called for dialects
        which support "implicit" primary key generation,
        keep preexecute_autoincrement_sequences set to False,
        and when no explicit id value was bound to the
        statement.
        
        The function is called once, directly after 
        post_exec() and before the transaction is committed
        or ResultProxy is generated.   If the post_exec()
        method assigns a value to `self._lastrowid`, the
        value is used in place of calling get_lastrowid().
        
        Note that this method is *not* equivalent to the
        ``lastrowid`` method on ``ResultProxy``, which is a
        direct proxy to the DBAPI ``lastrowid`` accessor
        in all cases.
        
        """
        
        return self.cursor.lastrowid

    def handle_dbapi_exception(self, e):
        pass

    def get_result_proxy(self):
        return base.ResultProxy(self)
    
    @property
    def rowcount(self):
        return self.cursor.rowcount

    def supports_sane_rowcount(self):
        return self.dialect.supports_sane_rowcount

    def supports_sane_multi_rowcount(self):
        return self.dialect.supports_sane_multi_rowcount
    
    def post_insert(self):
        if self.dialect.postfetch_lastrowid and \
            (not len(self._inserted_primary_key) or \
                        None in self._inserted_primary_key):
            
            table = self.compiled.statement.table
            lastrowid = self.get_lastrowid()
            self._inserted_primary_key = [c is table._autoincrement_column and lastrowid or v
                for c, v in zip(table.primary_key, self._inserted_primary_key)
            ]
            
    def _fetch_implicit_returning(self, resultproxy):
        table = self.compiled.statement.table
        row = resultproxy.fetchone()

        ipk = []
        for c, v in zip(table.primary_key, self._inserted_primary_key):
            if v is not None:
                ipk.append(v)
            else:
                ipk.append(row[c])
        
        self._inserted_primary_key = ipk

    def last_inserted_params(self):
        return self._last_inserted_params

    def last_updated_params(self):
        return self._last_updated_params

    def lastrow_has_defaults(self):
        return hasattr(self, 'postfetch_cols') and len(self.postfetch_cols)

    def set_input_sizes(self, translate=None, exclude_types=None):
        """Given a cursor and ClauseParameters, call the appropriate
        style of ``setinputsizes()`` on the cursor, using DB-API types
        from the bind parameter's ``TypeEngine`` objects.
        """

        if not hasattr(self.compiled, 'bind_names'):
            return

        types = dict(
                (self.compiled.bind_names[bindparam], bindparam.type)
                 for bindparam in self.compiled.bind_names)

        if self.dialect.positional:
            inputsizes = []
            for key in self.compiled.positiontup:
                typeengine = types[key]
                dbtype = typeengine.dialect_impl(self.dialect).get_dbapi_type(self.dialect.dbapi)
                if dbtype is not None and (not exclude_types or dbtype not in exclude_types):
                    inputsizes.append(dbtype)
            try:
                self.cursor.setinputsizes(*inputsizes)
            except Exception, e:
                self._connection._handle_dbapi_exception(e, None, None, None, self)
                raise
        else:
Esempio n. 3
0
    def map_to(self,
               attrname,
               tablename=None,
               selectable=None,
               schema=None,
               base=None,
               mapper_args=util.frozendict()):
        """Configure a mapping to the given attrname.

        This is the "master" method that can be used to create any 
        configuration.

        (new in 0.6.6)

        :param attrname: String attribute name which will be
          established as an attribute on this :class:.`.SqlSoup`
          instance.
        :param base: a Python class which will be used as the
          base for the mapped class. If ``None``, the "base"
          argument specified by this :class:`.SqlSoup`
          instance's constructor will be used, which defaults to
          ``object``.
        :param mapper_args: Dictionary of arguments which will
          be passed directly to :func:`.orm.mapper`.
        :param tablename: String name of a :class:`.Table` to be
          reflected. If a :class:`.Table` is already available,
          use the ``selectable`` argument. This argument is
          mutually exclusive versus the ``selectable`` argument.
        :param selectable: a :class:`.Table`, :class:`.Join`, or
          :class:`.Select` object which will be mapped. This
          argument is mutually exclusive versus the ``tablename``
          argument.
        :param schema: String schema name to use if the
          ``tablename`` argument is present.


        """
        if attrname in self._cache:
            raise InvalidRequestError(
                "Attribute '%s' is already mapped to '%s'" %
                (attrname, class_mapper(self._cache[attrname]).mapped_table))

        if tablename is not None:
            if not isinstance(tablename, basestring):
                raise ArgumentError("'tablename' argument must be a string.")
            if selectable is not None:
                raise ArgumentError("'tablename' and 'selectable' "
                                    "arguments are mutually exclusive")

            selectable = Table(tablename,
                               self._metadata,
                               autoload=True,
                               autoload_with=self.bind,
                               schema=schema or self.schema)
        elif schema:
            raise ArgumentError("'tablename' argument is required when "
                                "using 'schema'.")
        elif selectable is not None:
            if not isinstance(selectable, expression.FromClause):
                raise ArgumentError("'selectable' argument must be a "
                                    "table, select, join, or other "
                                    "selectable construct.")
        else:
            raise ArgumentError("'tablename' or 'selectable' argument is "
                                "required.")

        if not selectable.primary_key.columns:
            if tablename:
                raise PKNotFoundError("table '%s' does not have a primary "
                                      "key defined" % tablename)
            else:
                raise PKNotFoundError(
                    "selectable '%s' does not have a primary "
                    "key defined" % selectable)

        mapped_cls = _class_for_table(self.session, self.engine, selectable,
                                      base or self.base, mapper_args)
        self._cache[attrname] = mapped_cls
        return mapped_cls
Esempio n. 4
0
    def map_to(self, attrname, tablename=None, selectable=None, 
                    schema=None, base=None, mapper_args=util.frozendict()):
        """Configure a mapping to the given attrname.

        This is the "master" method that can be used to create any 
        configuration.

        (new in 0.6.6)

        :param attrname: String attribute name which will be
          established as an attribute on this :class:.`.SqlSoup`
          instance.
        :param base: a Python class which will be used as the
          base for the mapped class. If ``None``, the "base"
          argument specified by this :class:`.SqlSoup`
          instance's constructor will be used, which defaults to
          ``object``.
        :param mapper_args: Dictionary of arguments which will
          be passed directly to :func:`.orm.mapper`.
        :param tablename: String name of a :class:`.Table` to be
          reflected. If a :class:`.Table` is already available,
          use the ``selectable`` argument. This argument is
          mutually exclusive versus the ``selectable`` argument.
        :param selectable: a :class:`.Table`, :class:`.Join`, or
          :class:`.Select` object which will be mapped. This
          argument is mutually exclusive versus the ``tablename``
          argument.
        :param schema: String schema name to use if the
          ``tablename`` argument is present.


        """
        if attrname in self._cache:
            raise InvalidRequestError(
                "Attribute '%s' is already mapped to '%s'" % (
                attrname,
                class_mapper(self._cache[attrname]).mapped_table
            ))

        if tablename is not None:
            if not isinstance(tablename, basestring):
                raise ArgumentError("'tablename' argument must be a string."
                                    )
            if selectable is not None:
                raise ArgumentError("'tablename' and 'selectable' "
                                    "arguments are mutually exclusive")

            selectable = Table(tablename, 
                                        self._metadata, 
                                        autoload=True, 
                                        autoload_with=self.bind, 
                                        schema=schema or self.schema)
        elif schema:
            raise ArgumentError("'tablename' argument is required when "
                                "using 'schema'.")
        elif selectable is not None:
            if not isinstance(selectable, expression.FromClause):
                raise ArgumentError("'selectable' argument must be a "
                                    "table, select, join, or other "
                                    "selectable construct.")
        else:
            raise ArgumentError("'tablename' or 'selectable' argument is "
                                    "required.")

        if not selectable.primary_key.columns:
            if tablename:
                raise PKNotFoundError(
                            "table '%s' does not have a primary "
                            "key defined" % tablename)
            else:
                raise PKNotFoundError(
                            "selectable '%s' does not have a primary "
                            "key defined" % selectable)

        mapped_cls = _class_for_table(
            self.session,
            self.engine,
            selectable,
            base or self.base,
            mapper_args
        )
        self._cache[attrname] = mapped_cls
        return mapped_cls
Esempio n. 5
0
 def test_serialize(self):
     d = util.frozendict({1:2, 3:4})
     for loads, dumps in picklers():
         print loads(dumps(d))