Repository: modin-project/modin

Issue:
Modin causes read_sql to throw exception for PyMySQL
<!--
General questions should be asked on the mailing list modin-dev@googlegroups.com.

Before submitting an issue, please fill out the following form.
-->

### System information
- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**: Ubuntu 18.04.2 LTS
- **Modin installed from (source or binary)**: binary
- **Modin version**: 0.5.4
- **Python version**: 3.6.5
- **Pandas version**: 0.24.2
- **PyMySQL version**: 0.9.3
- **SQLAlchemy version**: 1.3.5
- **Exact command to reproduce**:
```python
import modin.pandas as pd
from sqlalchemy import create_engine
import dbconf
server = dbconf.server
name = dbconf.name
pw = dbconf.pw
engine = create_engine('mysql+pymysql://'+name+':'+pw+'@'+server+'/?charset=utf8')
sql = 'select user_id, market from testschema.allmarkets where marketplace=5'
df = pd.read_sql(sql,engine)
```
Error output:
```shell
ubuntu@hostname:~/workspace$ python dbm.py
Traceback (most recent call last):
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 2262, in _wrap_pool_connect
    return fn()
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/pool/base.py", line 363, in connect
    return _ConnectionFairy._checkout(self)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/pool/base.py", line 760, in _checkout
    fairy = _ConnectionRecord.checkout(pool)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/pool/base.py", line 492, in checkout
    rec = pool._do_get()
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/pool/impl.py", line 139, in _do_get
    self._dec_overflow()
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/util/langhelpers.py", line 68, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 154, in reraise
    raise value
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/pool/impl.py", line 136, in _do_get
    return self._create_connection()
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/pool/base.py", line 308, in _create_connection
    return _ConnectionRecord(self)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/pool/base.py", line 437, in __init__
    self.__connect(first_connect_check=True)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/pool/base.py", line 639, in __connect
    connection = pool._invoke_creator(self)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/engine/strategies.py", line 114, in connect
    return dialect.connect(*cargs, **cparams)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 451, in connect
    return self.dbapi.connect(*cargs, **cparams)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/pymysql/__init__.py", line 94, in Connect
    return Connection(*args, **kwargs)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/pymysql/connections.py", line 325, in __init__
    self.connect()
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/pymysql/connections.py", line 599, in connect
    self._request_authentication()
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/pymysql/connections.py", line 861, in _request_authentication
    auth_packet = self._read_packet()
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/pymysql/connections.py", line 684, in _read_packet
    packet.check_error()
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/pymysql/protocol.py", line 220, in check_error
    err.raise_mysql_exception(self._data)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/pymysql/err.py", line 109, in raise_mysql_exception
    raise errorclass(errno, errval)
pymysql.err.OperationalError: (1045, "Access denied for user 'username'@'123.123.123.123' (using password: YES)")

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "dbm.py", line 9, in <module>
    df = pd.read_sql(sql,engine)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/modin/pandas/io.py", line 324, in read_sql
    return DataFrame(query_compiler=BaseFactory.read_sql(**kwargs))
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/modin/data_management/factories.py", line 155, in read_sql
    return cls._determine_engine()._read_sql(**kwargs)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/modin/data_management/factories.py", line 159, in _read_sql
    return cls.io_cls.read_sql(**kwargs)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/modin/engines/ray/generic/io.py", line 941, in read_sql
    row_cnt = pandas.read_sql(row_cnt_query, con).squeeze()
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/pandas/io/sql.py", line 397, in read_sql
    chunksize=chunksize)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/pandas/io/sql.py", line 1099, in read_query
    result = self.execute(*args)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/pandas/io/sql.py", line 990, in execute
    return self.connectable.execute(*args, **kwargs)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 2165, in execute
    connection = self._contextual_connect(close_with_result=True)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 2226, in _contextual_connect
    self._wrap_pool_connect(self.pool.connect, None),
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 2266, in _wrap_pool_connect
    e, dialect, self
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1536, in _handle_dbapi_exception_noconnection
    util.raise_from_cause(sqlalchemy_exception, exc_info)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 399, in raise_from_cause
    reraise(type(exception), exception, tb=exc_tb, cause=cause)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 153, in reraise
    raise value.with_traceback(tb)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 2262, in _wrap_pool_connect
    return fn()
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/pool/base.py", line 363, in connect
    return _ConnectionFairy._checkout(self)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/pool/base.py", line 760, in _checkout
    fairy = _ConnectionRecord.checkout(pool)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/pool/base.py", line 492, in checkout
    rec = pool._do_get()
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/pool/impl.py", line 139, in _do_get
    self._dec_overflow()
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/util/langhelpers.py", line 68, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 154, in reraise
    raise value
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/pool/impl.py", line 136, in _do_get
    return self._create_connection()
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/pool/base.py", line 308, in _create_connection
    return _ConnectionRecord(self)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/pool/base.py", line 437, in __init__
    self.__connect(first_connect_check=True)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/pool/base.py", line 639, in __connect
    connection = pool._invoke_creator(self)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/engine/strategies.py", line 114, in connect
    return dialect.connect(*cargs, **cparams)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 451, in connect
    return self.dbapi.connect(*cargs, **cparams)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/pymysql/__init__.py", line 94, in Connect
    return Connection(*args, **kwargs)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/pymysql/connections.py", line 325, in __init__
    self.connect()
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/pymysql/connections.py", line 599, in connect
    self._request_authentication()
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/pymysql/connections.py", line 861, in _request_authentication
    auth_packet = self._read_packet()
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/pymysql/connections.py", line 684, in _read_packet
    packet.check_error()
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/pymysql/protocol.py", line 220, in check_error
    err.raise_mysql_exception(self._data)
  File "/home/ubuntu/miniconda3/lib/python3.6/site-packages/pymysql/err.py", line 109, in raise_mysql_exception
    raise errorclass(errno, errval)
sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (1045, "Access denied for user 'username'@'123.123.123.123' (using password: YES)")
(Background on this error at: http://sqlalche.me/e/e3q8)
```


<!--
You can obtain the Modin version with

python -c "import modin; print(modin.__version__)"
-->

### Describe the problem
Modin appears to cause PyMySQL to throw the above error.  There is no error with Pandas by itself.  A workaround appears to be:
```python
import ray
import pandas as pd
```
similar to the error & solution in https://github.com/modin-project/modin/issues/556

### Source code / logs
<!-- Include any logs or source code that would be helpful to diagnose the problem. If including tracebacks, please include the full traceback. Large logs and files should be attached. Try to provide a reproducible test case that is the bare minimum necessary to generate the problem. -->



Discussion:
Hi @Shellcat-Zero, thanks for the report! I think I see what is happening with the connection.

Does it work if you instead pass in the string and let the engine creation happen in Modin?

```python
import modin.pandas as pd
from sqlalchemy import create_engine
import dbconf
server = dbconf.server
name = dbconf.name
pw = dbconf.pw
engine = 'mysql+pymysql://'+name+':'+pw+'@'+server+'/?charset=utf8'
sql = 'select user_id, market from testschema.allmarkets where marketplace=5'
df = pd.read_sql(sql,engine)
```
@devin-petersohn Yes, it works just fine if I let engine creation happen within Modin.
I'm going to add a warning here because it shouldn't be breaking in this case.

Resolving patch:
diff --git a/modin/engines/ray/generic/io.py b/modin/engines/ray/generic/io.py
--- a/modin/engines/ray/generic/io.py
+++ b/modin/engines/ray/generic/io.py
@@ -11,6 +11,7 @@
 import sys
 import numpy as np
 import math
+import warnings
 
 from modin.error_message import ErrorMessage
 from modin.engines.base.io import BaseIO
@@ -1075,7 +1076,11 @@ def read_sql(cls, sql, con, index_col=None, **kwargs):
         # are not pickleable. We have to convert it to the URL string and connect from
         # each of the workers.
         if isinstance(con, (sa.engine.Engine, sa.engine.Connection)):
-            con = repr(con.engine.url)
+            warnings.warn(
+                "To use parallel implementation of `read_sql`, pass the "
+                "connection string instead of {}.".format(type(con))
+            )
+            return super(RayIO, cls).read_sql(sql, con, index_col=index_col, **kwargs)
         row_cnt_query = "SELECT COUNT(*) FROM ({}) as foo".format(sql)
         row_cnt = pandas.read_sql(row_cnt_query, con).squeeze()
         cols_names_df = pandas.read_sql(


Test patch: