async def callproc(self, procname, args=()):
        """Execute stored procedure procname with args

        Compatibility warning: PEP-249 specifies that any modified
        parameters must be returned. This is currently impossible
        as they are only available by storing them in a server
        variable and then retrieved by a query. Since stored
        procedures return zero or more result sets, there is no
        reliable way to get at OUT or INOUT parameters via callproc.
        The server variables are named @_procname_n, where procname
        is the parameter above and n is the position of the parameter
        (from zero). Once all result sets generated by the procedure
        have been fetched, you can issue a SELECT @_procname_0, ...
        query using .execute() to get any OUT or INOUT values.

        Compatibility warning: The act of calling a stored procedure
        itself creates an empty result set. This appears after any
        result sets generated by the procedure. This is non-standard
        behavior with respect to the DB-API. Be sure to use nextset()
        to advance through all result sets; otherwise you may get
        disconnected.

        :param procname: ``str``, name of procedure to execute on server
        :param args: `sequence of parameters to use with procedure
        :returns: the original args.
        """
        conn = self._get_db()
        if self._echo:
            logger.info("CALL %s", procname)
            logger.info("%r", args)

        for index, arg in enumerate(args):
            q = "SET @_%s_%d=%s" % (procname, index, conn.escape(arg))
            await self._query(q)
            await self.nextset()

        _args = ','.join('@_%s_%d' % (procname, i) for i in range(len(args)))
        q = "CALL %s(%s)" % (procname, _args)
        await self._query(q)
        self._executed = q
        return args