Example #1
0
    def checkout(self):
        if self.connection is None:
            raise exc.InvalidRequestError("This connection is closed")
        self.__counter += 1

        if not self._pool.dispatch.checkout or self.__counter != 1:
            return self

        # Pool listeners can trigger a reconnection on checkout
        attempts = 2
        while attempts > 0:
            try:
                self._pool.dispatch.checkout(self.connection,
                                            self._connection_record,
                                            self)
                return self
            except exc.DisconnectionError as e:
                self._pool.logger.info(
                "Disconnection detected on checkout: %s", e)
                self._connection_record.invalidate(e)
                self.connection = self._connection_record.get_connection()
                attempts -= 1

        self._pool.logger.info("Reconnection attempts exhausted on checkout")
        self.invalidate()
        raise exc.InvalidRequestError("This connection is closed")
    def pre_exec(self):
        if self.isinsert:
            tbl = self.compiled.statement.table
            seq_column = tbl._autoincrement_column
            insert_has_sequence = seq_column is not None

            if insert_has_sequence:
                self._enable_identity_insert = \
                                seq_column.key in self.compiled_parameters[0]
            else:
                self._enable_identity_insert = False

            if self._enable_identity_insert:
                self.cursor.execute(
                    "SET IDENTITY_INSERT %s ON" %
                    self.dialect.identifier_preparer.format_table(tbl))

        if self.isddl:
            # TODO: to enhance this, we can detect "ddl in tran" on the
            # database settings.  this error message should be improved to
            # include a note about that.
            if not self.should_autocommit:
                raise exc.InvalidRequestError(
                    "The Sybase dialect only supports "
                    "DDL in 'autocommit' mode at this time.")

            self.root_connection.engine.logger.info(
                "AUTOCOMMIT (Assuming no Sybase 'ddl in tran')")

            self.set_ddl_autocommit(self.root_connection.connection.connection,
                                    True)
Example #3
0
    def contains(self, obj):
        """Produce a proxied 'contains' expression using EXISTS.
        This expression will be a composed product
        using the :meth:`.RelationshipProperty.Comparator.any`
        , :meth:`.RelationshipProperty.Comparator.has`,
        and/or :meth:`.RelationshipProperty.Comparator.contains`
        operators of the underlying proxied attributes.
        """

        target_assoc = self._unwrap_target_assoc_proxy
        if target_assoc is not None:
            return self._comparator._criterion_exists(
                target_assoc.contains(obj)
                if not target_assoc.scalar else target_assoc == obj)
        elif self._target_is_object and self.scalar and \
                not self._value_is_scalar:
            return self._comparator.has(
                getattr(self.target_class, self.value_attr).contains(obj))
        elif self._target_is_object and self.scalar and \
                self._value_is_scalar:
            raise exc.InvalidRequestError(
                "contains() doesn't apply to a scalar object endpoint; use ==")
        else:

            return self._comparator._criterion_exists(**{self.value_attr: obj})
Example #4
0
def listen(target, identifier, fn, *args, **kw):
    """Register a listener function for the given target.
    
    e.g.::
    
        from sqlalchemy import event
        from sqlalchemy.schema import UniqueConstraint
        
        def unique_constraint_name(const, table):
            const.name = "uq_%s_%s" % (
                table.name,
                list(const.columns)[0].name
            )
        event.listen(
                UniqueConstraint, 
                "after_parent_attach", 
                unique_constraint_name)

    """

    for evt_cls in _registrars[identifier]:
        tgt = evt_cls._accept_with(target)
        if tgt is not None:
            tgt.dispatch._listen(tgt, identifier, fn, *args, **kw)
            return
    raise exc.InvalidRequestError("No such event '%s' for target '%s'" %
                                  (identifier, target))
Example #5
0
    def visit_select(self, select, **kwargs):
        """Look for ``LIMIT`` and OFFSET in a select statement, and if
        so tries to wrap it in a subquery with ``row_number()`` criterion.

        """
        if not getattr(select, '_mssql_visit', None) and select._offset:
            # to use ROW_NUMBER(), an ORDER BY is required.
            orderby = self.process(select._order_by_clause)
            if not orderby:
                raise exc.InvalidRequestError(
                    'MSSQL requires an order_by when '
                    'using an offset.')

            _offset = select._offset
            _limit = select._limit
            select._mssql_visit = True
            select = select.column(
                sql.literal_column("ROW_NUMBER() OVER (ORDER BY %s)" \
                % orderby).label("mssql_rn")
                                   ).order_by(None).alias()

            limitselect = sql.select(
                [c for c in select.c if c.key != 'mssql_rn'])
            limitselect.append_whereclause("mssql_rn>%d" % _offset)
            if _limit is not None:
                limitselect.append_whereclause("mssql_rn<=%d" %
                                               (_limit + _offset))
            return self.process(limitselect, iswrapper=True, **kwargs)
        else:
            return compiler.SQLCompiler.visit_select(self, select, **kwargs)
Example #6
0
    def __init__(self,
                 auto_convert_lobs=True,
                 threaded=True,
                 coerce_to_unicode=True,
                 coerce_to_decimal=True,
                 arraysize=50,
                 **kwargs):

        self._pop_deprecated_kwargs(kwargs)

        OracleDialect.__init__(self, **kwargs)
        self.threaded = threaded
        self.arraysize = arraysize
        self.auto_convert_lobs = auto_convert_lobs
        self.coerce_to_unicode = coerce_to_unicode
        self.coerce_to_decimal = coerce_to_decimal
        if self._use_nchar_for_unicode:
            self.colspecs = self.colspecs.copy()
            self.colspecs[sqltypes.Unicode] = _OracleUnicodeStringNCHAR
            self.colspecs[sqltypes.UnicodeText] = _OracleUnicodeTextNCLOB

        cx_Oracle = self.dbapi

        if cx_Oracle is None:
            self._include_setinputsizes = {}
            self.cx_oracle_ver = (0, 0, 0)
        else:
            self.cx_oracle_ver = self._parse_cx_oracle_ver(cx_Oracle.version)
            if self.cx_oracle_ver < (5, 2) and self.cx_oracle_ver > (0, 0, 0):
                raise exc.InvalidRequestError(
                    "cx_Oracle version 5.2 and above are supported")

            self._has_native_int = hasattr(cx_Oracle, "NATIVE_INT")

            self._include_setinputsizes = {
                cx_Oracle.NCLOB, cx_Oracle.CLOB, cx_Oracle.LOB,
                cx_Oracle.NCHAR, cx_Oracle.FIXED_NCHAR, cx_Oracle.BLOB,
                cx_Oracle.FIXED_CHAR, cx_Oracle.TIMESTAMP, _OracleInteger,
                _OracleBINARY_FLOAT, _OracleBINARY_DOUBLE
            }

            self._paramval = lambda value: value.getvalue()

            # https://github.com/oracle/python-cx_Oracle/issues/176#issuecomment-386821291
            # https://github.com/oracle/python-cx_Oracle/issues/224
            self._values_are_lists = self.cx_oracle_ver >= (6, 3)
            if self._values_are_lists:
                cx_Oracle.__future__.dml_ret_array_val = True

                def _returningval(value):
                    try:
                        return value.values[0][0]
                    except IndexError:
                        return None

                self._returningval = _returningval
            else:
                self._returningval = self._paramval

        self._is_cx_oracle_6 = self.cx_oracle_ver >= (6, )
Example #7
0
    def result_processor(self, dialect, coltype):
        if dialect.datetimeformat == 'internal':

            def process(value):
                if value is None:
                    return None
                else:
                    return datetime.datetime(*[
                        int(v) for v in (value[0:4], value[4:6], value[6:8],
                                         value[8:10], value[10:12],
                                         value[12:14], value[14:])
                    ])
        elif dialect.datetimeformat == 'iso':

            def process(value):
                if value is None:
                    return None
                else:
                    return datetime.datetime(*[
                        int(v) for v in (value[0:4], value[5:7], value[8:10],
                                         value[11:13], value[14:16],
                                         value[17:19], value[20:])
                    ])
        else:
            raise exc.InvalidRequestError(
                "datetimeformat '%s' is not supported." %
                dialect.datetimeformat)
        return process
Example #8
0
    def get_column_specification(self, column, **kwargs):
        colspec = (self.preparer.format_column(column) + " " +
                   self.dialect.type_compiler.process(column.type))

        if column.nullable is not None:
            if not column.nullable or column.primary_key:
                colspec += " NOT NULL"
            else:
                colspec += " NULL"

        if column.table is None:
            raise exc.InvalidRequestError("mssql requires Table-bound columns "
                                          "in order to generate DDL")

        seq_col = column.table._autoincrement_column

        # install a IDENTITY Sequence if we have an implicit IDENTITY column
        if seq_col is column:
            sequence = isinstance(column.default, sa_schema.Sequence) and \
                            column.default
            if sequence:
                start, increment = sequence.start or 1, \
                                    sequence.increment or 1
            else:
                start, increment = 1, 1
            colspec += " IDENTITY(%s,%s)" % (start, increment)
        else:
            default = self.get_column_default_string(column)
            if default is not None:
                colspec += " DEFAULT " + default

        return colspec
    def with_totals(self):
        if not self._group_by:
            raise exc.InvalidRequestError(
                "Query.with_totals() can be used only with specified "
                "GROUP BY, call group_by()")

        self._with_totals = True
Example #10
0
    def create_row_processor(self, context, path, mapper, row, adapter):
        if not self.parent.class_manager[self.key].impl.supports_population:
            raise sa_exc.InvalidRequestError(
                "'%s' does not support object "
                "population - eager loading cannot be applied." % self)

        path = path[self.key]

        our_col = path.get(context, "nested_result")
        if our_col in row:
            _instance = loading.instance_processor(self.mapper, context,
                                                   path[self.mapper], None)

            if not self.uselist:
                return self._create_scalar_loader(context, self.key, our_col,
                                                  _instance)
            else:
                return self._create_collection_loader(context, self.key,
                                                      our_col, _instance)

        else:
            return self.parent_property.\
                            _get_strategy(LazyLoader).\
                            create_row_processor(
                                            context, path,
                                            mapper, row, adapter)
Example #11
0
 def last_inserted_ids(self):
     if self.context.last_inserted_ids is None:
         raise exc.InvalidRequestError(
             "no INSERT executed, or can't use cursor.lastrowid without Postgres OIDs enabled"
         )
     else:
         return self.context.last_inserted_ids
Example #12
0
    def order_by_clause(self, select, **kw):
        order_by = self.process(select._order_by_clause, **kw)

        # ORDER BY clauses in DISTINCT queries must reference aliased
        # inner columns by alias name, not true column name.
        if order_by and getattr(select, '_distinct', False):
            labels = self._find_labeled_columns(select.inner_columns,
                                                select.use_labels)
            if labels:
                for needs_alias in labels.keys():
                    r = re.compile(r'(^| )(%s)(,| |$)' %
                                   re.escape(needs_alias))
                    order_by = r.sub((r'\1%s\3' % labels[needs_alias]),
                                     order_by)

        # No ORDER BY in subqueries.
        if order_by:
            if self.is_subquery():
                # It's safe to simply drop the ORDER BY if there is no
                # LIMIT.  Right?  Other dialects seem to get away with
                # dropping order.
                if select._limit:
                    raise exc.InvalidRequestError(
                        "MaxDB does not support ORDER BY in subqueries")
                else:
                    return ""
            return " ORDER BY " + order_by
        else:
            return ""
Example #13
0
 def result_processor(self, dialect, coltype):
     if self.asdecimal:
         if coltype in _FLOAT_TYPES:
             return processors.to_decimal_processor_factory(decimal.Decimal)
         elif coltype in _DECIMAL_TYPES:
             # pg8000 returns Decimal natively for 1700
             return None
         else:
             raise exc.InvalidRequestError("Unknown PG numeric type: %d" % coltype)
     else:
         if coltype in _FLOAT_TYPES:
             # pg8000 returns float natively for 701
             return None
         elif coltype in _DECIMAL_TYPES:
             return processors.to_float
         else:
             raise exc.InvalidRequestError("Unknown PG numeric type: %d" % coltype)
Example #14
0
 def visit_select_precolumns(self, select):
     """Access puts TOP, it's version of LIMIT here """
     s = select.distinct and "DISTINCT " or ""
     if select.limit:
         s += "TOP %s " % (select.limit)
     if select.offset:
         raise exc.InvalidRequestError('Access does not support LIMIT with an offset')
     return s
Example #15
0
    def create_connect_args(self, url):
        dialect_opts = dict(url.query)

        for opt in (
                "use_ansi",
                "auto_setinputsizes",
                "auto_convert_lobs",
                "threaded",
                "allow_twophase",
        ):
            if opt in dialect_opts:
                util.coerce_kw_type(dialect_opts, opt, bool)
                setattr(self, opt, dialect_opts[opt])

        database = url.database
        service_name = dialect_opts.get("service_name", None)
        if database or service_name:
            # if we have a database, then we have a remote host
            port = url.port
            if port:
                port = int(port)
            else:
                port = 1521

            if database and service_name:
                raise exc.InvalidRequestError(
                    '"service_name" option shouldn\'t '
                    'be used with a "database" part of the url')
            if database:
                makedsn_kwargs = {"sid": database}
            if service_name:
                makedsn_kwargs = {"service_name": service_name}

            dsn = self.dbapi.makedsn(url.host, port, **makedsn_kwargs)
        else:
            # we have a local tnsname
            dsn = url.host

        opts = dict(threaded=self.threaded)

        if dsn is not None:
            opts["dsn"] = dsn
        if url.password is not None:
            opts["password"] = url.password
        if url.username is not None:
            opts["user"] = url.username

        if "mode" in url.query:
            opts["mode"] = url.query["mode"]
            if isinstance(opts["mode"], util.string_types):
                mode = opts["mode"].upper()
                if mode == "SYSDBA":
                    opts["mode"] = self.dbapi.SYSDBA
                elif mode == "SYSOPER":
                    opts["mode"] = self.dbapi.SYSOPER
                else:
                    util.coerce_kw_type(opts, "mode", int)
        return ([], opts)
Example #16
0
 def get_select_precolumns(self, select):
     # Convert a subquery's LIMIT to TOP
     sql = select._distinct and 'DISTINCT ' or ''
     if self.is_subquery() and select._limit:
         if select._offset:
             raise exc.InvalidRequestError(
                 'MaxDB does not support LIMIT with an offset.')
         sql += 'TOP %s ' % select._limit
     return sql
Example #17
0
    def create_connect_args(self, url):
        dialect_opts = dict(url.query)

        for opt in ('use_ansi', 'auto_setinputsizes', 'auto_convert_lobs',
                    'threaded', 'allow_twophase'):
            if opt in dialect_opts:
                util.coerce_kw_type(dialect_opts, opt, bool)
                setattr(self, opt, dialect_opts[opt])

        database = url.database
        service_name = dialect_opts.get('service_name', None)
        if database.endswith(':timesten_direct') or database.endswith(
                ':timesten_client'):
            dsn = url.host + '/' + database
            self.is_timesten = True
        elif database or service_name:
            # if we have a database, then we have a remote host
            port = url.port
            if port:
                port = int(port)
            else:
                port = 1521

            if database and service_name:
                raise exc.InvalidRequestError(
                    '"service_name" option shouldn\'t '
                    'be used with a "database" part of the url')
            if database:
                makedsn_kwargs = {'sid': database}
            if service_name:
                makedsn_kwargs = {'service_name': service_name}

            dsn = self.dbapi.makedsn(url.host, port, **makedsn_kwargs)
        else:
            # we have a local tnsname
            dsn = url.host

        opts = dict(threaded=self.threaded, )

        if dsn is not None:
            opts['dsn'] = dsn
        if url.password is not None:
            opts['password'] = url.password
        if url.username is not None:
            opts['user'] = url.username

        if 'mode' in url.query:
            opts['mode'] = url.query['mode']
            if isinstance(opts['mode'], util.string_types):
                mode = opts['mode'].upper()
                if mode == 'SYSDBA':
                    opts['mode'] = self.dbapi.SYSDBA
                elif mode == 'SYSOPER':
                    opts['mode'] = self.dbapi.SYSOPER
                else:
                    util.coerce_kw_type(opts, 'mode', int)
        return ([], opts)
Example #18
0
 def _do_check(state, value, oldvalue, initiator):
     if value is not None:
         hasparent = initiator.hasparent(attributes.instance_state(value))
         if hasparent and oldvalue is not value:
             raise sa_exc.InvalidRequestError(
                 "Instance %s is already associated with an instance "
                 "of %s via its %s attribute, and is only allowed a "
                 "single parent." %
                 (mapperutil.instance_str(value), state.class_, prop))
     return value
Example #19
0
    def pre_exec(self):
        self._enable_identity_insert = False
        self._select_lastrowid = False
        self._lastrowid = None

        if self.isinsert:
            tbl = self.compiled.statement.table
            seq_column = tbl._autoincrement_column
            insert_has_sequence = seq_column is not None

            if insert_has_sequence:
                self._enable_identity_insert = (
                    seq_column.key in self.compiled_parameters[0]
                )
            else:
                self._enable_identity_insert = False

            # _select_lastrowid logic
            # based on: https://github.com/sqlalchemy/sqlalchemy/
            # blob/3ab2364e78641c4f0e4b6456afc2cbed39b0d0e6/lib/sqlalchemy/
            # dialects/mssql/base.py#L1506-L1512
            self._select_lastrowid = (
                not self.compiled.inline
                and insert_has_sequence
                and not self.compiled.returning
                and not self._enable_identity_insert
                and not self.executemany
            )
            if self._select_lastrowid:
                # https://github.com/FreeTDS/freetds/issues/337#issuecomment-640070962
                self.statement += "\n SELECT @@identity"

            if self._enable_identity_insert:
                self.cursor.execute(
                    "SET IDENTITY_INSERT %s ON"
                    % self.dialect.identifier_preparer.format_table(tbl)
                )

        if self.isddl:
            # TODO: to enhance this, we can detect "ddl in tran" on the
            #       database settings.  this error message should be improved
            #       to include a note about that.
            if not self.should_autocommit:
                raise exc.InvalidRequestError(
                    "The Sybase dialect only supports "
                    "DDL in 'autocommit' mode at this time."
                )

            self.root_connection.engine.logger.info(
                "AUTOCOMMIT (Assuming no Sybase 'ddl in tran')"
            )

            self.set_ddl_autocommit(
                self.root_connection.connection.connection, True
            )
Example #20
0
 def limit_clause(self, select):
     # The docs say offsets are supported with LIMIT.  But they're not.
     # TODO: maybe emulate by adding a ROWNO/ROWNUM predicate?
     if self.is_subquery():
         # sub queries need TOP
         return ''
     elif select._offset:
         raise exc.InvalidRequestError(
             'MaxDB does not support LIMIT with an offset.')
     else:
         return ' \n LIMIT %s' % (select._limit, )
Example #21
0
 def _revalidate_connection(self):
     if self._Connection__can_reconnect and self._Connection__invalid:
         if self._Connection__transaction is not None:
             raise sqla_exc.InvalidRequestError(
                 "Can't reconnect until invalid "
                 "transaction is rolled back")
         self._Connection__connection = self.engine.raw_connection(
             _connection=self)
         self._Connection__invalid = False
         return self._Connection__connection
     raise sqla_exc.ResourceClosedError("This Connection is closed")
Example #22
0
    def get_select_precolumns(self, select, **kwargs):
        """Teradata uses TOP instead of LIMIT """

        if select._distinct or select._limit is not None:
            s = select._distinct and "DISTINCT " or ""
            if select._limit is not None:
                s += "TOP %d " % (select._limit)
            if select._offset is not None:
                raise exc.InvalidRequestError('Teradata does not support LIMIT with an offset')
            return s
        return compiler.SQLCompiler.get_select_precolumns(self, select)
 def test_statement_error_no_code(self):
     try:
         raise sa_exceptions.DBAPIError.instance(
             'select * from table', [{
                 "x": 1
             }], sa_exceptions.InvalidRequestError("hello"), DatabaseError)
     except sa_exceptions.StatementError as err:
         eq_(
             str(err), "(sqlalchemy.exc.InvalidRequestError) hello "
             "[SQL: 'select * from table'] [parameters: [{'x': 1}]]")
         eq_(err.args, ("(sqlalchemy.exc.InvalidRequestError) hello", ))
Example #24
0
def make_transient_to_detached(instance):
    '''
    Moved from sqlalchemy newer version
    '''
    state = attributes.instance_state(instance)
    if state.session_id or state.key:
        raise sa_exc.InvalidRequestError("Given object must be transient")
    state.key = state.mapper._identity_key_from_state(state)
    if state.deleted:
        del state.deleted
    state._commit_all(state.dict)
    state._expire_attributes(state.dict, state.unloaded)
Example #25
0
 def process(value):
     if not isinstance(value, (unicode, NoneType)):
         if assert_unicode == 'warn':
             util.warn("Unicode type received non-unicode bind "
                       "param value %r" % value)
             return value
         else:
             raise exc.InvalidRequestError(
                 "Unicode type received non-unicode bind param value %r"
                 % value)
     else:
         return value
    def remove(self, value, _sa_initiator=None):
        """Remove an item by value, consulting the keyfunc for the key."""

        key = self.keyfunc(value)
        # Let self[key] raise if key is not in this collection
        # testlib.pragma exempt:__ne__
        if not self.__contains__(key) or value not in self[key]:
            raise sa_exc.InvalidRequestError(
                "Can not remove '%s': collection holds '%s' for key '%s'. "
                "Possible cause: is the MappedCollection key function "
                "based on mutable properties or properties that only obtain "
                "values after flush?" % (value, self[key], key))
        self.__getitem__(key, _sa_initiator).remove(value)
Example #27
0
 def process(value):
     if value is None:
         return None
     elif dialect.datetimeformat == 'internal':
         return datetime.date(
             *[int(v) for v in (value[0:4], value[4:6], value[6:8])])
     elif dialect.datetimeformat == 'iso':
         return datetime.date(
             *[int(v) for v in (value[0:4], value[5:7], value[8:10])])
     else:
         raise exc.InvalidRequestError(
             "datetimeformat '%s' is not supported." %
             (dialect.datetimeformat, ))
Example #28
0
    def invalidate(self, e=None):
        """Mark this connection as invalidated.

        The connection will be immediately closed.  The containing
        ConnectionRecord will create a new connection when next used.
        """

        if self.connection is None:
            raise exc.InvalidRequestError("This connection is closed")
        if self._connection_record is not None:
            self._connection_record.invalidate(e=e)
        self.connection = None
        self._close()
Example #29
0
    def info(self):
        """An info collection unique to this DB-API connection."""

        try:
            return self._connection_record.info
        except AttributeError:
            if self.connection is None:
                raise exc.InvalidRequestError("This connection is closed")
            try:
                return self._detached_info
            except AttributeError:
                self._detached_info = value = {}
                return value
Example #30
0
 def process(value):
     if value is None:
         return None
     elif isinstance(value, basestring):
         return value
     elif dialect.datetimeformat == 'internal':
         return value.strftime("%H%M%S")
     elif dialect.datetimeformat == 'iso':
         return value.strftime("%H-%M-%S")
     else:
         raise exc.InvalidRequestError(
             "datetimeformat '%s' is not supported." %
             (dialect.datetimeformat, ))