# Buggy code
def estimate_size(cls, ctx, op):
    exec_size = 0
    outputs = op.outputs
    if all(
        not c.is_sparse() and hasattr(c, "nbytes") and not np.isnan(c.nbytes)
        for c in outputs
    ):
        for out in outputs:
            ctx[out.key] = (out.nbytes, out.nbytes)

    for inp in op.inputs or ():
        try:
            exec_size += ctx[inp.key][0]
        except KeyError:
            if not op.sparse:
                inp_size = calc_data_size(inp)
                if not np.isnan(inp_size):
                    exec_size += inp_size
    exec_size = int(exec_size)

    total_out_size = 0
    chunk_sizes = dict()
    for out in outputs:
        try:
            chunk_size = calc_data_size(out) if not out.is_sparse() else exec_size
            if np.isnan(chunk_size):
                raise TypeError
            chunk_sizes[out.key] = chunk_size
            total_out_size += chunk_size
        except (AttributeError, TypeError, ValueError):
            pass
    exec_size = max(exec_size, total_out_size)
    for out in outputs:
        if out.key in ctx:
            continue
        if out.key in chunk_sizes:
            store_size = chunk_sizes[out.key]
        else:
            store_size = max(
                exec_size // len(outputs), total_out_size // max(len(chunk_sizes), 1)
            )
        try:
            if out.is_sparse():
                max_sparse_size = (
                    out.nbytes
                    + np.dtype(np.int64).itemsize * np.prod(out.shape) * out.ndim
                )
            else:
                max_sparse_size = np.nan
        except TypeError:  # pragma: no cover
            max_sparse_size = np.nan
        if not np.isnan(max_sparse_size):
            store_size = min(store_size, max_sparse_size)
        ctx[out.key] = (store_size, exec_size // len(outputs))


# Traceback (mysql.connector.errors.ProgrammingError)
Traceback (most recent call last):
File "D:\Anaconda3\envs\py37\lib\site-packages\sqlalchemy\engine\base.py", line 1249, in _execute_context
cursor, statement, parameters, context
File "D:\Anaconda3\envs\py37\lib\site-packages\sqlalchemy\engine\default.py", line 580, in do_execute
cursor.execute(statement, parameters)
File "D:\Anaconda3\envs\py37\lib\site-packages\mysql\connector\cursor.py", line 551, in execute
self._handle_result(self._connection.cmd_query(stmt))
File "D:\Anaconda3\envs\py37\lib\site-packages\mysql\connector\connection.py", line 490, in cmd_query
result = self._handle_result(self._send_cmd(ServerCmd.QUERY, query))
File "D:\Anaconda3\envs\py37\lib\site-packages\mysql\connector\connection.py", line 395, in _handle_result
raise errors.get_exception(packet)
mysql.connector.errors.ProgrammingError: 1248 (42000): Every derived table must have its own alias

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "E:\mycodes\readdatabymars.py", line 17, in <module>
df = md.read_sql_query(sql1, con=engine)
File "D:\Anaconda3\envs\py37\lib\site-packages\mars\dataframe\datasource\read_sql.py", line 766, in read_sql_query
low_limit=low_limit, high_limit=high_limit)
File "D:\Anaconda3\envs\py37\lib\site-packages\mars\dataframe\datasource\read_sql.py", line 476, in _read_sql
return op(test_rows, chunk_size)
File "D:\Anaconda3\envs\py37\lib\site-packages\mars\dataframe\datasource\read_sql.py", line 250, in __call__
test_df, shape = self._collect_info(con, selectable, collect_cols, test_rows)
File "D:\Anaconda3\envs\py37\lib\site-packages\mars\dataframe\datasource\read_sql.py", line 196, in _collect_info
parse_dates=self._parse_dates)
File "D:\Anaconda3\envs\py37\lib\site-packages\pandas\io\sql.py", line 436, in read_sql
chunksize=chunksize,
File "D:\Anaconda3\envs\py37\lib\site-packages\pandas\io\sql.py", line 1218, in read_query
result = self.execute(*args)
File "D:\Anaconda3\envs\py37\lib\site-packages\pandas\io\sql.py", line 1087, in execute
return self.connectable.execute(*args, **kwargs)
File "D:\Anaconda3\envs\py37\lib\site-packages\sqlalchemy\engine\base.py", line 988, in execute
return meth(self, multiparams, params)
File "D:\Anaconda3\envs\py37\lib\site-packages\sqlalchemy\sql\elements.py", line 287, in _execute_on_connection
return connection._execute_clauseelement(self, multiparams, params)
File "D:\Anaconda3\envs\py37\lib\site-packages\sqlalchemy\engine\base.py", line 1107, in _execute_clauseelement
distilled_params,
File "D:\Anaconda3\envs\py37\lib\site-packages\sqlalchemy\engine\base.py", line 1253, in _execute_context
e, statement, parameters, cursor, context
File "D:\Anaconda3\envs\py37\lib\site-packages\sqlalchemy\engine\base.py", line 1473, in _handle_dbapi_exception
util.raise_from_cause(sqlalchemy_exception, exc_info)
File "D:\Anaconda3\envs\py37\lib\site-packages\sqlalchemy\util\compat.py", line 398, in raise_from_cause
reraise(type(exception), exception, tb=exc_tb, cause=cause)
File "D:\Anaconda3\envs\py37\lib\site-packages\sqlalchemy\util\compat.py", line 152, in reraise
raise value.with_traceback(tb)
File "D:\Anaconda3\envs\py37\lib\site-packages\sqlalchemy\engine\base.py", line 1249, in _execute_context
cursor, statement, parameters, context
File "D:\Anaconda3\envs\py37\lib\site-packages\sqlalchemy\engine\default.py", line 580, in do_execute
cursor.execute(statement, parameters)
File "D:\Anaconda3\envs\py37\lib\site-packages\mysql\connector\cursor.py", line 551, in execute
self._handle_result(self._connection.cmd_query(stmt))
File "D:\Anaconda3\envs\py37\lib\site-packages\mysql\connector\connection.py", line 490, in cmd_query
result = self._handle_result(self._send_cmd(ServerCmd.QUERY, query))
File "D:\Anaconda3\envs\py37\lib\site-packages\mysql\connector\connection.py", line 395, in _handle_result
raise errors.get_exception(packet)
sqlalchemy.exc.ProgrammingError: (mysql.connector.errors.ProgrammingError) 1248 (42000): Every derived table must have its own alias
[SQL: SELECT *
FROM (SELECT *
FROM (SELECT * FROM  table1) AS temp_6302b78c8a9347b8b02475d757cf17f7)
LIMIT %(param_1)s]
[parameters: {'param_1': 5}]
(Background on this error at: http://sqlalche.me/e/f405)

# Fixed code
def estimate_size(cls, ctx, op):
    from .dataframe.core import (
        DATAFRAME_CHUNK_TYPE,
        SERIES_CHUNK_TYPE,
        INDEX_CHUNK_TYPE,
    )

    exec_size = 0
    outputs = op.outputs
    if all(
        not c.is_sparse() and hasattr(c, "nbytes") and not np.isnan(c.nbytes)
        for c in outputs
    ):
        for out in outputs:
            ctx[out.key] = (out.nbytes, out.nbytes)

    for inp in op.inputs or ():
        try:
            # execution size of a specific data chunk may be
            # larger than stored type due to objects
            obj_overhead = n_strings = 0
            if getattr(inp, "shape", None) and not np.isnan(inp.shape[0]):
                if isinstance(inp, DATAFRAME_CHUNK_TYPE) and inp.dtypes is not None:
                    n_strings = len([dt for dt in inp.dtypes if is_object_dtype(dt)])
                elif (
                    isinstance(inp, (INDEX_CHUNK_TYPE, SERIES_CHUNK_TYPE))
                    and inp.dtype is not None
                ):
                    n_strings = 1 if is_object_dtype(inp.dtype) else 0
                obj_overhead += n_strings * inp.shape[0] * OBJECT_FIELD_OVERHEAD

            exec_size += ctx[inp.key][0] + obj_overhead
        except KeyError:
            if not op.sparse:
                inp_size = calc_data_size(inp)
                if not np.isnan(inp_size):
                    exec_size += inp_size
    exec_size = int(exec_size)

    total_out_size = 0
    chunk_sizes = dict()
    for out in outputs:
        try:
            chunk_size = calc_data_size(out) if not out.is_sparse() else exec_size
            if np.isnan(chunk_size):
                raise TypeError
            chunk_sizes[out.key] = chunk_size
            total_out_size += chunk_size
        except (AttributeError, TypeError, ValueError):
            pass

    exec_size = max(exec_size, total_out_size)
    for out in outputs:
        if out.key in ctx:
            continue
        if out.key in chunk_sizes:
            store_size = chunk_sizes[out.key]
        else:
            store_size = max(
                exec_size // len(outputs), total_out_size // max(len(chunk_sizes), 1)
            )
        try:
            if out.is_sparse():
                max_sparse_size = (
                    out.nbytes
                    + np.dtype(np.int64).itemsize * np.prod(out.shape) * out.ndim
                )
            else:
                max_sparse_size = np.nan
        except TypeError:  # pragma: no cover
            max_sparse_size = np.nan
        if not np.isnan(max_sparse_size):
            store_size = min(store_size, max_sparse_size)
        ctx[out.key] = (store_size, exec_size // len(outputs))