Repository: modin-project/modin

Issue:
[omnisci] fillna on datetime[ns] column produces AssertionError
### System information
- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**:

Ubuntu 20.04.1 LTS

- **Modin version** (`modin.__version__`):

0.10.2+39.g15f168ca

- **Python version**:

Python 3.9.7

- **Code we can use to reproduce**:

```python
import numpy as np
import modin.pandas as pd

MULTIPLIER = 1000_000

df = pd.DataFrame({
    "a": [np.float(1)] * MULTIPLIER,
    "s": ["abc"] * MULTIPLIER,
    "i": [10] * MULTIPLIER,
    "t": [pd.to_datetime("2021")] * MULTIPLIER
})

s = df["a"].fillna(-1)
print(s)
s = df["i"].fillna(-1)
print(s)
s = df["t"].fillna(-1)
print(s)
```

<!--
You can obtain the Modin version with

python -c "import modin; print(modin.__version__)"
-->

### Describe the problem
<!-- Describe the problem clearly here. -->

Code above raises `AssertionError` on omnisci and works with no exceptions on Ray and Pandas.

### 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/omnisci_on_native/frame/data.py b/modin/experimental/engines/omnisci_on_native/frame/data.py
--- a/modin/experimental/engines/omnisci_on_native/frame/data.py
+++ b/modin/experimental/engines/omnisci_on_native/frame/data.py
@@ -603,28 +603,33 @@ def fillna(self, value=None, method=None, axis=None, limit=None, downcast=None):
         if method is not None:
             raise NotImplementedError("fillna doesn't support method yet")
 
-        exprs = self._index_exprs()
-        if isinstance(value, dict):
-            for col in self.columns:
-                col_expr = self.ref(col)
-                if col in value:
-                    value_expr = LiteralExpr(value[col])
+        try:
+            exprs = self._index_exprs()
+            if isinstance(value, dict):
+                for col in self.columns:
+                    col_expr = self.ref(col)
+                    if col in value:
+                        value_expr = LiteralExpr(value[col])
+                        res_type = _get_common_dtype(value_expr._dtype, col_expr._dtype)
+                        exprs[col] = build_if_then_else(
+                            col_expr.is_null(), value_expr, col_expr, res_type
+                        )
+                    else:
+                        exprs[col] = col_expr
+            elif np.isscalar(value):
+                value_expr = LiteralExpr(value)
+                for col in self.columns:
+                    col_expr = self.ref(col)
                     res_type = _get_common_dtype(value_expr._dtype, col_expr._dtype)
                     exprs[col] = build_if_then_else(
                         col_expr.is_null(), value_expr, col_expr, res_type
                     )
-                else:
-                    exprs[col] = col_expr
-        elif np.isscalar(value):
-            value_expr = LiteralExpr(value)
-            for col in self.columns:
-                col_expr = self.ref(col)
-                res_type = _get_common_dtype(value_expr._dtype, col_expr._dtype)
-                exprs[col] = build_if_then_else(
-                    col_expr.is_null(), value_expr, col_expr, res_type
-                )
-        else:
-            raise NotImplementedError("unsupported value for fillna")
+            else:
+                raise NotImplementedError("unsupported value for fillna")
+        except TypeError:
+            raise NotImplementedError(
+                "Heterogenous data is not supported in OmniSci backend"
+            )
 
         new_op = TransformNode(self, exprs)
         dtypes = self._dtypes_for_exprs(exprs)
diff --git a/modin/experimental/engines/omnisci_on_native/frame/expr.py b/modin/experimental/engines/omnisci_on_native/frame/expr.py
--- a/modin/experimental/engines/omnisci_on_native/frame/expr.py
+++ b/modin/experimental/engines/omnisci_on_native/frame/expr.py
@@ -46,10 +46,17 @@ def _get_common_dtype(lhs_dtype, rhs_dtype):
     """
     if lhs_dtype == rhs_dtype:
         return lhs_dtype
-    if is_float_dtype(lhs_dtype) or is_float_dtype(rhs_dtype):
+    if is_float_dtype(lhs_dtype) and (
+        is_float_dtype(rhs_dtype) or is_integer_dtype(rhs_dtype)
+    ):
         return get_dtype(float)
-    assert is_integer_dtype(lhs_dtype) and is_integer_dtype(rhs_dtype)
-    return get_dtype(int)
+    if is_float_dtype(rhs_dtype) and (
+        is_float_dtype(lhs_dtype) or is_integer_dtype(lhs_dtype)
+    ):
+        return get_dtype(float)
+    if is_integer_dtype(lhs_dtype) and is_integer_dtype(rhs_dtype):
+        return get_dtype(int)
+    raise TypeError(f"Cannot perform operation on types: {lhs_dtype}, {rhs_dtype}")
 
 
 _aggs_preserving_numeric_type = {"sum", "min", "max"}


Test patch:
diff --git a/modin/experimental/engines/omnisci_on_native/test/test_dataframe.py b/modin/experimental/engines/omnisci_on_native/test/test_dataframe.py
--- a/modin/experimental/engines/omnisci_on_native/test/test_dataframe.py
+++ b/modin/experimental/engines/omnisci_on_native/test/test_dataframe.py
@@ -1864,6 +1864,12 @@ def applier(df1, df2, *args, **kwargs):
             applier, data=self.bad_for_omnisci, data2=self.ok_data, force_lazy=False
         )
 
+    def test_heterogenous_fillna(self):
+        def fillna(df, **kwargs):
+            return df["d"].fillna("a")
+
+        run_and_compare(fillna, data=self.ok_data, force_lazy=False)
+
 
 class TestDropna:
     data = {