Repository: modin-project/modin

Issue:
Distributed read_sql in experimental Pandas on Ray is broken
### System information
- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**: any
- **Modin version** (`modin.__version__`): 0.8.1.1
- **Python version**: any
- **Code we can use to reproduce**:

<!--
You can obtain the Modin version with

python -c "import modin; print(modin.__version__)"
-->

### Describe the problem
<!-- Describe the problem clearly here. -->
There is no member `ExperimentalPandasOnRayIO.frame_mgr_cls` at

https://github.com/modin-project/modin/blob/0e200c6219547ec20aad43718d5ec6d3ea501a3b/modin/experimental/engines/pandas_on_ray/io_exp.py#L120

which leads to `AttributeError` when trying to perform distributed `pd.read_sql` in experimental mode when running Pandas on Ray.

### 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:

Resolving patch:
diff --git a/modin/experimental/engines/pandas_on_ray/io_exp.py b/modin/experimental/engines/pandas_on_ray/io_exp.py
--- a/modin/experimental/engines/pandas_on_ray/io_exp.py
+++ b/modin/experimental/engines/pandas_on_ray/io_exp.py
@@ -130,7 +130,7 @@ def read_sql(
             )
         #  starts the distributed alternative
         cols_names, query = get_query_info(sql, con, partition_column)
-        num_parts = min(NPartitions.get(), max_sessions)
+        num_parts = min(NPartitions.get(), max_sessions if max_sessions else 1)
         num_splits = min(len(cols_names), num_parts)
         diff = (upper_bound - lower_bound) + 1
         min_size = diff // num_parts
@@ -168,9 +168,11 @@ def read_sql(
             )
             index_ids.append(partition_id[-1])
         new_index = pandas.RangeIndex(sum(ray.get(index_ids)))
-        return cls.query_compiler_cls(
+        new_query_compiler = cls.query_compiler_cls(
             cls.frame_cls(np.array(partition_ids), new_index, cols_names)
         )
+        new_query_compiler._modin_frame._apply_index_objs(axis=0)
+        return new_query_compiler
 
 
 @ray.remote
diff --git a/modin/experimental/engines/pandas_on_ray/sql.py b/modin/experimental/engines/pandas_on_ray/sql.py
--- a/modin/experimental/engines/pandas_on_ray/sql.py
+++ b/modin/experimental/engines/pandas_on_ray/sql.py
@@ -12,7 +12,7 @@
 # governing permissions and limitations under the License.
 
 from collections import OrderedDict
-from sqlalchemy import MetaData, Table, create_engine
+from sqlalchemy import MetaData, Table, create_engine, inspect
 
 
 def is_distributed(partition_column, lower_bound, upper_bound):
@@ -54,7 +54,7 @@ def is_table(engine, sql):
     Returns:
         True for table or False if not
     """
-    if engine.dialect.has_table(engine, sql):
+    if inspect(engine).has_table(sql):
         return True
     return False
 
@@ -132,7 +132,7 @@ def get_query_columns(engine, query):
     con = engine.connect()
     result = con.execute(query).fetchone()
     values = list(result)
-    cols_names = result.keys()
+    cols_names = list(result.keys())
     cols = OrderedDict()
     for i in range(len(cols_names)):
         cols[cols_names[i]] = type(values[i]).__name__


Test patch:
diff --git a/modin/experimental/pandas/test/test_io_exp.py b/modin/experimental/pandas/test/test_io_exp.py
--- a/modin/experimental/pandas/test/test_io_exp.py
+++ b/modin/experimental/pandas/test/test_io_exp.py
@@ -24,7 +24,6 @@
 )
 def test_from_sql_distributed(make_sql_connection):  # noqa: F811
     if Engine.get() == "Ray":
-        pytest.xfail("Distributed read_sql is broken, see GH#2194")
         filename = "test_from_sql_distributed.db"
         table = "test_from_sql_distributed"
         conn = make_sql_connection(filename, table)
@@ -32,10 +31,20 @@ def test_from_sql_distributed(make_sql_connection):  # noqa: F811
 
         pandas_df = pandas.read_sql(query, conn)
         modin_df_from_query = pd.read_sql(
-            query, conn, partition_column="col1", lower_bound=0, upper_bound=6
+            query,
+            conn,
+            partition_column="col1",
+            lower_bound=0,
+            upper_bound=6,
+            max_sessions=2,
         )
         modin_df_from_table = pd.read_sql(
-            table, conn, partition_column="col1", lower_bound=0, upper_bound=6
+            table,
+            conn,
+            partition_column="col1",
+            lower_bound=0,
+            upper_bound=6,
+            max_sessions=2,
         )
 
         df_equals(modin_df_from_query, pandas_df)