Repository: modin-project/modin

Issue:
Error with Modin Pandas and pyodbc
Hi, I am trying to get information from a Netezza db with modin.pandas. 

When I try this with pandas works well.

This is mi code: 

import modin.pandas as pd
import numpy as np
import seaborn as sns
import matplotlib as pltt
import pyodbc
import os
from io import open

conn= pyodbc.connect("""
DRIVER={NetezzaSQL};
SERVER=XXX;
PORT=5480;
DATABASE=DATABASE; 
UID=USER:
PWD=PASS;
""")

df=pd.read_sql("SELECT * FROM TABLE ",conn)

**That return me this error:** 

ProgrammingError                          Traceback (most recent call last)
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\io\sql.py in execute(self, *args, **kwargs)
   1585         try:
-> 1586             cur.execute(*args, **kwargs)
   1587             return cur

ProgrammingError: ('42000', '[42000] Syntax error or access violation (27) (SQLExecDirectW)')

The above exception was the direct cause of the following exception:

DatabaseError                             Traceback (most recent call last)
 in ()
 
----> 3 df=pd.read_sql("SELECT * FROM TABLE",conn)

~\AppData\Local\Continuum\anaconda3\lib\site-packages\modin\pandas\io.py in read_sql(sql, con, index_col, coerce_float, params, parse_dates, columns, chunksize)
    381         df_gen = pandas.read_sql(**kwargs)
    382         return (DataFrame(query_compiler=BaseFactory.from_pandas(df)) for df in df_gen)
--> 383     return DataFrame(query_compiler=BaseFactory.read_sql(**kwargs))
    384 
    385 

~\AppData\Local\Continuum\anaconda3\lib\site-packages\modin\data_management\factories.py in read_sql(cls, **kwargs)
    151     @classmethod
    152     def read_sql(cls, **kwargs):
--> 153         return cls._determine_engine()._read_sql(**kwargs)
    154 
    155     @classmethod

~\AppData\Local\Continuum\anaconda3\lib\site-packages\modin\data_management\factories.py in _read_sql(cls, **kwargs)
    155     @classmethod
    156     def _read_sql(cls, **kwargs):
--> 157         return cls.io_cls.read_sql(**kwargs)
    158 
    159     @classmethod

~\AppData\Local\Continuum\anaconda3\lib\site-packages\modin\engines\base\io\sql\sql_reader.py in read(cls, sql, con, index_col, **kwargs)
     60             return cls.single_worker_read(sql, con=con, index_col=index_col, **kwargs)
     61         row_cnt_query = "SELECT COUNT(*) FROM ({}) as foo".format(sql)
---> 62         row_cnt = pandas.read_sql(row_cnt_query, con).squeeze()
     63         cols_names_df = pandas.read_sql(
     64             "SELECT * FROM ({}) as foo LIMIT 0".format(sql), con, index_col=index_col

~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\io\sql.py in read_sql(sql, con, index_col, coerce_float, params, parse_dates, columns, chunksize)
    410             coerce_float=coerce_float,
    411             parse_dates=parse_dates,
--> 412             chunksize=chunksize,
    413         )
    414 

~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\io\sql.py in read_query(self, sql, index_col, coerce_float, params, parse_dates, chunksize)
   1631 
   1632         args = _convert_params(sql, params)
-> 1633         cursor = self.execute(*args)
   1634         columns = [col_desc[0] for col_desc in cursor.description]
   1635 

~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\io\sql.py in execute(self, *args, **kwargs)
   1596 
   1597             ex = DatabaseError(f"Execution failed on sql '{args[0]}': {exc}")
-> 1598             raise ex from exc
   1599 
   1600     @staticmethod

DatabaseError: Execution failed on sql 'SELECT COUNT(*) FROM (SELECT * from TABLE;



SELECT  * FROM TBALE as nameAlias} ${WHERE condition}) as foo': ('42000', '[42000] Syntax error or access violation (27) (SQLExecDirectW)')


Thanks. 




Discussion:
Hi @jpchavezs, thanks for the report!

We can get this fixed, it is a matter of changing the check [here](https://github.com/modin-project/modin/blob/63cf839c09e02e23aff015b712c9c94c84f0a8f7/modin/engines/base/io/sql/sql_reader.py#L55) to check `if isinstance(con, str)`. 

We cannot use database connections in a distributed way. There is some state that is a part of that object that cannot be communicated across workers. 

Resolving patch:
diff --git a/modin/engines/base/io/sql/sql_reader.py b/modin/engines/base/io/sql/sql_reader.py
--- a/modin/engines/base/io/sql/sql_reader.py
+++ b/modin/engines/base/io/sql/sql_reader.py
@@ -32,8 +32,6 @@ def _read(cls, sql, con, index_col=None, **kwargs):
             index_col: Column(s) to set as index(MultiIndex).
             kwargs: Pass into pandas.read_sql function.
         """
-        import sqlalchemy as sa
-
         try:
             import psycopg2 as pg
 
@@ -52,9 +50,9 @@ def _read(cls, sql, con, index_col=None, **kwargs):
         # In the case that we are given a SQLAlchemy Connection or Engine, the objects
         # 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)):
+        if not isinstance(con, str):
             warnings.warn(
-                "To use parallel implementation of `read_sql`, pass the "
+                "To use parallel implementation of `read_sql`, pass the sqlalchemy"
                 "connection string instead of {}.".format(type(con))
             )
             return cls.single_worker_read(sql, con=con, index_col=index_col, **kwargs)


Test patch: