Repository: modin-project/modin

Issue:
BUG: Empty frames concatenation with inner join is not valid
### Modin version checks

- [X] I have checked that this issue has not already been reported.

- [X] I have confirmed this bug exists on the latest released version of Modin.

- [X] I have confirmed this bug exists on the main branch of Modin. (In order to do this you can follow [this guide](https://modin.readthedocs.io/en/stable/getting_started/installation.html#installing-from-the-github-master-branch).)


### Reproducible Example

```python
@pytest.mark.parametrize(
    "data1, index1, data2, index2",
    [
        (None, None, None, None),
        (None, None, {"A": [1, 2, 3]}, pandas.Index([1, 2, 3], name="Test")),
        ({"A": [1, 2, 3]}, pandas.Index([1, 2, 3], name="Test"), None, None),
        ({"A": [1, 2, 3]}, None, None, None),
        (None, None, {"A": [1, 2, 3]}, None),
        (None, pandas.Index([1, 2, 3], name="Test"), None, None),
        (None, None, None, pandas.Index([1, 2, 3], name="Test")),
    ],
)
@pytest.mark.parametrize("axis", [0, 1])
def test_concat_inner_empty(data1, index1, data2, index2, axis):
    pdf1 = pandas.DataFrame(data1, index=index1)
    pdf2 = pandas.DataFrame(data2, index=index2)
    pdf = pandas.concat((pdf1, pdf2), axis=axis, join="inner")
    mdf1 = pd.DataFrame(data1, index=index1)
    mdf2 = pd.DataFrame(data2, index=index2)
    mdf = pd.concat((mdf1, mdf2), axis=axis, join="inner")
    df_equals(pdf, mdf)
```


### Issue Description

The above test fails on all backends.

### Expected Behavior

If at least one frame is empty, the result should be an empty frame with merged index.

### Error Logs

<details>

```python-traceback

Replace this line with the error backtrace (if applicable).

```

</details>


### Installed Versions

<details>

Replace this line with the output of pd.show_versions()

</details>



Discussion:

Resolving patch:
diff --git a/modin/pandas/general.py b/modin/pandas/general.py
--- a/modin/pandas/general.py
+++ b/modin/pandas/general.py
@@ -361,13 +361,13 @@ def concat(
         )
     axis = pandas.DataFrame()._get_axis_number(axis)
     if isinstance(objs, dict):
-        list_of_objs = list(objs.values())
+        input_list_of_objs = list(objs.values())
     else:
-        list_of_objs = list(objs)
-    if len(list_of_objs) == 0:
+        input_list_of_objs = list(objs)
+    if len(input_list_of_objs) == 0:
         raise ValueError("No objects to concatenate")
 
-    list_of_objs = [obj for obj in list_of_objs if obj is not None]
+    list_of_objs = [obj for obj in input_list_of_objs if obj is not None]
 
     if len(list_of_objs) == 0:
         raise ValueError("All objects passed were None")
@@ -404,7 +404,18 @@ def concat(
                 sort=sort,
             )
         )
-    if join not in ["inner", "outer"]:
+    if join == "outer":
+        # Filter out empties
+        list_of_objs = [
+            obj
+            for obj in list_of_objs
+            if (
+                isinstance(obj, (Series, pandas.Series))
+                or (isinstance(obj, DataFrame) and obj._query_compiler.lazy_execution)
+                or sum(obj.shape) > 0
+            )
+        ]
+    elif join != "inner":
         raise ValueError(
             "Only can inner (intersect) or outer (union) join the other axis"
         )
@@ -412,19 +423,13 @@ def concat(
     # dataframe to a series on axis=0, pandas ignores the name of the series,
     # and this check aims to mirror that (possibly buggy) functionality
     list_of_objs = [
-        obj
+        obj._query_compiler
         if isinstance(obj, DataFrame)
-        else DataFrame(obj.rename())
+        else DataFrame(obj.rename())._query_compiler
         if isinstance(obj, (pandas.Series, Series)) and axis == 0
-        else DataFrame(obj)
+        else DataFrame(obj)._query_compiler
         for obj in list_of_objs
     ]
-    list_of_objs = [
-        obj._query_compiler
-        for obj in list_of_objs
-        if (not obj._query_compiler.lazy_execution and len(obj.index))
-        or len(obj.columns)
-    ]
     if keys is not None:
         if all_series:
             new_idx = keys
@@ -454,6 +459,14 @@ def concat(
         ).index
     else:
         new_idx = None
+
+    if len(list_of_objs) == 0:
+        return DataFrame(
+            index=input_list_of_objs[0].index.append(
+                [f.index for f in input_list_of_objs[1:]]
+            )
+        )
+
     new_query_compiler = list_of_objs[0].concat(
         axis,
         list_of_objs[1:],


Test patch:
diff --git a/modin/pandas/test/test_concat.py b/modin/pandas/test/test_concat.py
--- a/modin/pandas/test/test_concat.py
+++ b/modin/pandas/test/test_concat.py
@@ -23,11 +23,14 @@
     generate_multiindex_dfs,
     generate_none_dfs,
     create_test_dfs,
+    default_to_pandas_ignore_string,
 )
 from modin.config import NPartitions
 
 NPartitions.put(4)
 
+pytestmark = pytest.mark.filterwarnings(default_to_pandas_ignore_string)
+
 
 def test_df_concat():
     df, df2 = generate_dfs()
@@ -236,3 +239,36 @@ def test_sort_order(sort, join, axis):
         modin_concat,
     )
     assert list(pandas_concat.columns) == list(modin_concat.columns)
+
+
+@pytest.mark.parametrize(
+    "data1, index1, data2, index2",
+    [
+        (None, None, None, None),
+        (None, None, {"A": [1, 2, 3]}, pandas.Index([1, 2, 3], name="Test")),
+        ({"A": [1, 2, 3]}, pandas.Index([1, 2, 3], name="Test"), None, None),
+        ({"A": [1, 2, 3]}, None, None, None),
+        (None, None, {"A": [1, 2, 3]}, None),
+        (None, pandas.Index([1, 2, 3], name="Test"), None, None),
+        (None, None, None, pandas.Index([1, 2, 3], name="Test")),
+    ],
+)
+@pytest.mark.parametrize("axis", [0, 1])
+@pytest.mark.parametrize("join", ["inner", "outer"])
+def test_concat_empty(data1, index1, data2, index2, axis, join):
+    pdf1 = pandas.DataFrame(data1, index=index1)
+    pdf2 = pandas.DataFrame(data2, index=index2)
+    pdf = pandas.concat((pdf1, pdf2), axis=axis, join=join)
+    mdf1 = pd.DataFrame(data1, index=index1)
+    mdf2 = pd.DataFrame(data2, index=index2)
+    mdf = pd.concat((mdf1, mdf2), axis=axis, join=join)
+    df_equals(pdf, mdf)
+
+
+def test_concat_empty_df_series():
+    pdf = pandas.concat((pandas.DataFrame({"A": [1, 2, 3]}), pandas.Series()))
+    mdf = pd.concat((pd.DataFrame({"A": [1, 2, 3]}), pd.Series()))
+    df_equals(pdf, mdf)
+    pdf = pandas.concat((pandas.DataFrame(), pandas.Series([1, 2, 3])))
+    mdf = pd.concat((pd.DataFrame(), pd.Series([1, 2, 3])))
+    df_equals(pdf, mdf)