Repository: modin-project/modin

Issue:
Replace raising `NotImplementedError` methods to calling BaseQueryCompiler methods in OmniSci query compiler
Currently `DFAlgQueryCompiler` raising `NotImplementedError` when obtain parameters, implementation of which is not ready yet. It's needed to replace all this raisings to
```python
super().method(*args, **kwargs)
```


Discussion:

Resolving patch:
diff --git a/modin/experimental/backends/omnisci/query_compiler.py b/modin/experimental/backends/omnisci/query_compiler.py
--- a/modin/experimental/backends/omnisci/query_compiler.py
+++ b/modin/experimental/backends/omnisci/query_compiler.py
@@ -11,7 +11,10 @@
 # ANY KIND, either express or implied. See the License for the specific language
 # governing permissions and limitations under the License.
 
-from modin.backends.base.query_compiler import BaseQueryCompiler
+from modin.backends.base.query_compiler import (
+    BaseQueryCompiler,
+    _set_axis as default_axis_setter,
+)
 from modin.backends.pandas.query_compiler import PandasQueryCompiler
 
 import pandas
@@ -219,7 +222,7 @@ def groupby_dict_agg(self, by, func_dict, groupby_args, agg_args, drop=False):
 
         Parameters
         ----------
-        by : PandasQueryCompiler
+        by : DFAlgQueryCompiler
             The column to group by
         func_dict : dict of str, callable/string
             The dictionary mapping of column to function
@@ -232,7 +235,7 @@ def groupby_dict_agg(self, by, func_dict, groupby_args, agg_args, drop=False):
 
         Returns
         -------
-        PandasQueryCompiler
+        DFAlgQueryCompiler
             The result of the per-column aggregations on the grouped dataframe.
         """
         # TODO: handle drop arg
@@ -248,7 +251,9 @@ def _get_index(self):
         return self._modin_frame.index
 
     def _set_index(self, index):
-        self._modin_frame.index = index
+        default_axis_setter(0)(self, index)
+        # NotImplementedError: OmnisciOnRayFrame._set_index is not yet suported
+        # self._modin_frame.index = index
 
     def _get_columns(self):
         return self._modin_frame.columns
@@ -342,7 +347,7 @@ def dt_month(self):
     def _bin_op(self, other, op_name, **kwargs):
         level = kwargs.get("level", None)
         if level is not None:
-            raise NotImplementedError(f"{op_name} doesn't support levels")
+            return getattr(super(), op_name)(other=other, op_name=op_name, **kwargs)
 
         if isinstance(other, DFAlgQueryCompiler):
             shape_hint = (
@@ -391,7 +396,7 @@ def ne(self, other, **kwargs):
     def reset_index(self, **kwargs):
         level = kwargs.get("level", None)
         if level is not None:
-            raise NotImplementedError("reset_index doesn't support level arg yet")
+            return super().reset_index(**kwargs)
 
         drop = kwargs.get("drop", False)
         shape_hint = self._shape_hint if drop else None
@@ -424,11 +429,8 @@ def setitem(self, axis, key, value):
         Returns:
              A new QueryCompiler
         """
-        if axis == 1:
-            raise NotImplementedError("setitem doesn't support axis 1")
-
-        if not isinstance(value, type(self)):
-            raise NotImplementedError("unsupported value for setitem")
+        if axis == 1 or not isinstance(value, type(self)):
+            return super().setitem(axis=axis, key=key, value=value)
 
         return self._setitem(axis, key, value)
 
@@ -443,12 +445,10 @@ def insert(self, loc, column, value):
             value: Dtype object values to insert.
 
         Returns:
-            A new PandasQueryCompiler with new data inserted.
+            A new DFAlgQueryCompiler with new data inserted.
         """
         if is_list_like(value):
-            raise NotImplementedError(
-                "non-scalar values are not supported by insert yet"
-            )
+            return super().insert(loc=loc, column=column, value=value)
 
         return self.__constructor__(self._modin_frame.insert(loc, column, value))
 
@@ -464,7 +464,7 @@ def sort_rows_by_column_values(self, columns, ascending=True, **kwargs):
 
         Returns
         -------
-        PandasQueryCompiler
+        DFAlgQueryCompiler
             A new query compiler that contains result of the sort
         """
         ignore_index = kwargs.get("ignore_index", False)
@@ -474,25 +474,6 @@ def sort_rows_by_column_values(self, columns, ascending=True, **kwargs):
             self._shape_hint,
         )
 
-    def sort_columns_by_row_values(self, rows, ascending=True, **kwargs):
-        """Reorder the columns based on the lexicographic order of the given rows.
-
-        Parameters
-        ----------
-        rows : scalar or list of scalar
-            The row or rows to sort by
-        ascending : bool
-            Sort in ascending order (True) or descending order (False)
-
-        Returns
-        -------
-        PandasQueryCompiler
-            A new query compiler that contains result of the sort
-        """
-        raise NotImplementedError(
-            "column sorting is not yet suported in DFAlgQueryCompiler"
-        )
-
     def columnarize(self):
         """
         Transposes this QueryCompiler if it has a single row but multiple columns.


Test patch:
diff --git a/modin/experimental/engines/omnisci_on_ray/test/test_dataframe.py b/modin/experimental/engines/omnisci_on_ray/test/test_dataframe.py
--- a/modin/experimental/engines/omnisci_on_ray/test/test_dataframe.py
+++ b/modin/experimental/engines/omnisci_on_ray/test/test_dataframe.py
@@ -27,6 +27,7 @@
     to_pandas,
     test_data_values,
     test_data_keys,
+    generate_multiindex,
 )
 
 
@@ -387,8 +388,8 @@ def concat(df, **kwargs):
 
         run_and_compare(concat, data=self.data)
 
-    def test_insert(self):
-        def insert(df, **kwargs):
+    def test_setitem(self):
+        def applier(df, **kwargs):
             df["new_int8"] = np.int8(10)
             df["new_int16"] = np.int16(10)
             df["new_int32"] = np.int32(10)
@@ -398,7 +399,19 @@ def insert(df, **kwargs):
             df["new_float64"] = np.float64(10.1)
             return df
 
-        run_and_compare(insert, data=self.data)
+        run_and_compare(applier, data=self.data)
+
+    def test_insert(self):
+        def applier(df, **kwargs):
+            df.insert(0, "new_int", 10)
+            df.insert(0, "new_float", 5.5)
+            df.insert(0, "new_list_like", np.arange(len(df)))
+            df.insert(0, "qc_column", df["new_int"])
+            return df
+
+        # setting `force_lazy=False`, because we're expecting to fallback
+        # to pandas in that case, which is not supported in lazy mode
+        run_and_compare(applier, data=self.data, force_lazy=False)
 
     def test_concat_many(self):
         def concat(df1, df2, lib, **kwargs):
@@ -934,6 +947,15 @@ class TestBinaryOp:
     }
     fill_values = [None, 1]
 
+    def test_binary_level(self):
+        def applier(df1, df2, **kwargs):
+            df2.index = generate_multiindex(len(df2))
+            return df1.add(df2, level=1)
+
+        # setting `force_lazy=False`, because we're expecting to fallback
+        # to pandas in that case, which is not supported in lazy mode
+        run_and_compare(applier, data=self.data, data2=self.data, force_lazy=False)
+
     def test_add_cst(self):
         def add(lib, df):
             return df + 1
@@ -1185,9 +1207,7 @@ class TestSort:
         "c": [None, 4, 2, None, 1, 1, 4, 5, 6],
     }
     cols_values = ["a", ["a", "b"], ["b", "a"], ["c", "a", "b"]]
-    # Issue #1766 - support set_index for OmniSci backend
-    # index_cols_values = [None, "a", ["a", "b"]]
-    index_cols_values = [None]
+    index_cols_values = [None, "a", ["a", "b"]]
     ascending_values = [True, False]
     ascending_list_values = [[True, False], [False, True]]
     na_position_values = ["first", "last"]
@@ -1209,6 +1229,9 @@ def sort(df, cols, ignore_index, index_cols, ascending, **kwargs):
             ignore_index=ignore_index,
             index_cols=index_cols,
             ascending=ascending,
+            # we're expecting to fallback to pandas in that case,
+            # which is not supported in lazy mode
+            force_lazy=(index_cols is None),
         )
 
     @pytest.mark.parametrize("ascending", ascending_list_values)
diff --git a/modin/pandas/test/utils.py b/modin/pandas/test/utils.py
--- a/modin/pandas/test/utils.py
+++ b/modin/pandas/test/utils.py
@@ -727,9 +727,9 @@ def generate_level(length, nlevel):
             )
         return result.sort_values()
     else:
-        base_level = ["first"] * (elements_number // 2) + ["second"] * (
-            elements_number // 2
-        )
+        base_level = ["first"] * (elements_number // 2 + elements_number % 2) + [
+            "second"
+        ] * (elements_number // 2)
         primary_levels = [generate_level(elements_number, i) for i in range(1, nlevels)]
         arrays = [base_level] + primary_levels
         return pd.MultiIndex.from_tuples(