code: def test_join_on(setup):
      df1 = pd.DataFrame(
          [[1, 3, 3], [4, 2, 6], [7, 8, 9]], columns=["a1", "a2", "a3"]
      )
      df2 = (
          pd.DataFrame(
              [[1, 2, 3], [1, 5, 6], [7, 8, 9]],
              columns=["a1", "b2", "b3"],
          )
          + 1
      )
      df2 = pd.concat([df2, df2 + 1])
  
      mdf1 = from_pandas(df1, chunk_size=2)
      mdf2 = from_pandas(df2, chunk_size=2)
  
      expected0 = df1.join(df2, on=None, lsuffix="_l", rsuffix="_r")
      jdf0 = mdf1.join(
          mdf2, on=None, lsuffix="_l", rsuffix="_r", auto_merge="none"
      )
      result0 = jdf0.execute().fetch()
      pd.testing.assert_frame_equal(
          sort_dataframe_inplace(expected0, 0),
          sort_dataframe_inplace(result0, 0),
      )
  
      expected1 = df1.join(
          df2, how="left", on="a1", lsuffix="_l", rsuffix="_r"
      )
      jdf1 = mdf1.join(
          mdf2,
          how="left",
          on="a1",
          lsuffix="_l",
          rsuffix="_r",
          auto_merge="none",
      )
      result1 = jdf1.execute().fetch()
  
      # Note [Columns of Left Join]
      #
      # I believe we have no chance to obtain the entirely same result with pandas here:
      #
      # Look at the following example:
      #
      # >>> df1
      #     a1  a2  a3
      # 0   1   3   3
      # >>> df2
      #     a1  b2  b3
      # 1   2   6   7
      # >>> df3
      #     a1  b2  b3
      # 1   2   6   7
      # 1   2   6   7
      #
      # >>> df1.merge(df2, how='left', left_on='a1', left_index=False, right_index=True)
      #     a1_x  a2  a3  a1_y  b2  b3
      # 0   1   3   3     2   6   7
      # >>> df1.merge(df3, how='left', left_on='a1', left_index=False, right_index=True)
      #     a1  a1_x  a2  a3  a1_y  b2  b3
      # 0   1     1   3   3     2   6   7
      # 0   1     1   3   3     2   6   7
      #
      # Note that the result of `df1.merge(df3)` has an extra column `a` compared to `df1.merge(df2)`.
      # The value of column `a` is the same of `a1_x`, just because `1` occurs twice in index of `df3`.
      # I haven't invistagated why pandas has such behaviour...
      #
      # We cannot yield the same result with pandas, because, the `df3` is chunked, then some of the
      # result chunk has 6 columns, others may have 7 columns, when concatenated into one DataFrame
      # some cells of column `a` will have value `NaN`, which is different from the result of pandas.
      #
      # But we can guarantee that other effective columns have absolutely same value with pandas.
  
      columns_to_compare = jdf1.columns_value.to_pandas()
  
      pd.testing.assert_frame_equal(
          sort_dataframe_inplace(expected1[columns_to_compare], 0, 1),
          sort_dataframe_inplace(result1[columns_to_compare], 0, 1),
      )
  
      # Note [Index of Join on EmptyDataFrame]
      #
      # It is tricky that it is non-trivial to get the same `index` result with pandas.
      #
      # Look at the following example:
      #
      # >>> df1
      #    a1  a2  a3
      # 1   4   2   6
      # >>> df2
      #    a1  b2  b3
      # 1   2   6   7
      # 2   8   9  10
      # >>> df3
      # Empty DataFrame
      # Columns: [a1, a2, a3]
      # Index: []
      # >>> df1.join(df2, how='right', on='a2', lsuffix='_l', rsuffix='_r')
      #       a1_l  a2   a3  a1_r  b2  b3
      # 1.0   4.0   2  6.0     8   9  10
      # NaN   NaN   1  NaN     2   6   7
      # >>> df3.join(df2, how='right', on='a2', lsuffix='_l', rsuffix='_r')
      #     a1_l  a2  a3  a1_r  b2  b3
      # 1   NaN   1 NaN     2   6   7
      # 2   NaN   2 NaN     8   9  10
      #
      # When the `left` dataframe is not empty, the mismatched rows in `right` will have index value `NaN`,
      # and the matched rows have index value from `right`. When the `left` dataframe is empty, the mismatched
      # rows have index value from `right`.
      #
      # Since we chunked the `left` dataframe, it is uneasy to obtain the same index value with pandas in the
      # final result dataframe, but we guaranteed that the dataframe content is correctly.
  
      expected2 = df1.join(
          df2, how="right", on="a2", lsuffix="_l", rsuffix="_r"
      )
      jdf2 = mdf1.join(
          mdf2,
          how="right",
          on="a2",
          lsuffix="_l",
          rsuffix="_r",
          auto_merge="none",
      )
      result2 = jdf2.execute().fetch()
  
      expected2.set_index("a2", inplace=True)
      result2.set_index("a2", inplace=True)
      pd.testing.assert_frame_equal(
          sort_dataframe_inplace(expected2, 0),
          sort_dataframe_inplace(result2, 0),
      )
  
      expected3 = df1.join(
          df2, how="inner", on="a2", lsuffix="_l", rsuffix="_r"
      )
      jdf3 = mdf1.join(
          mdf2,
          how="inner",
          on="a2",
          lsuffix="_l",
          rsuffix="_r",
          auto_merge="none",
      )
      result3 = jdf3.execute().fetch()
      pd.testing.assert_frame_equal(
          sort_dataframe_inplace(expected3, 0),
          sort_dataframe_inplace(result3, 0),
      )
  
      expected4 = df1.join(
          df2, how="outer", on="a2", lsuffix="_l", rsuffix="_r"
      )
      jdf4 = mdf1.join(
          mdf2,
          how="outer",
          on="a2",
          lsuffix="_l",
          rsuffix="_r",
          auto_merge="none",
      )
      result4 = jdf4.execute().fetch()
  
      expected4.set_index("a2", inplace=True)
      result4.set_index("a2", inplace=True)
      pd.testing.assert_frame_equal(
          sort_dataframe_inplace(expected4, 0, kind="mergesort"),
          sort_dataframe_inplace(result4, 0, kind="mergesort"),
      )
  
file_path: mars/mars/dataframe/merge/tests/test_merge_execution.py
imports: import numpy
  import pandas
  import pytest
  from ....core.graph.builder.utils import build_graph
  from ...datasource.dataframe import from_pandas
  from ...datasource.series import from_pandas
  from ...utils import sort_dataframe_inplace
  from ..None import concat, DataFrameConcat, DataFrameMergeAlign
label_desc: Use image node_id 3 for calling a global function with example usage: test_join_on(setup) without return types