class_docstr: Perform a database (SQL) merge operation between two DataFrame objects
  using either columns as keys or their row indexes
class_docstr_tok: ["Perform","a","database","(","SQL",")","merge","operation","between","two","DataFrame","objects","using","either","columns","as","keys","or","their","row","indexes"]
code: def _validate_specification(self):
      # Hm, any way to make this logic less complicated??
      if (
          self.on is None
          and self.left_on is None
          and self.right_on is None
      ):
          if self.left_index and self.right_index:
              self.left_on, self.right_on = (), ()
          elif self.left_index:
              if self.right_on is None:
                  raise MergeError(
                      "Must pass right_on or right_index=True"
                  )
          elif self.right_index:
              if self.left_on is None:
                  raise MergeError(
                      "Must pass left_on or left_index=True"
                  )
          else:
              # use the common columns
              common_cols = self.left.columns.intersection(
                  self.right.columns
              )
              if len(common_cols) == 0:
                  raise MergeError(
                      "No common columns to perform merge on. "
                      "Merge options: left_on={lon}, right_on={ron}, "
                      "left_index={lidx}, right_index={ridx}".format(
                          lon=self.left_on,
                          ron=self.right_on,
                          lidx=self.left_index,
                          ridx=self.right_index,
                      )
                  )
              if not common_cols.is_unique:
                  raise MergeError(
                      "Data columns not unique: {common!r}".format(
                          common=common_cols
                      )
                  )
              self.left_on = self.right_on = common_cols
      elif self.on is not None:
          if self.left_on is not None or self.right_on is not None:
              raise MergeError(
                  'Can only pass argument "on" OR "left_on" '
                  'and "right_on", not a combination of both.'
              )
          self.left_on = self.right_on = self.on
      elif self.left_on is not None:
          n = len(self.left_on)
          if self.right_index:
              if len(self.left_on) != self.right.index.nlevels:
                  raise ValueError(
                      "len(left_on) must equal the number "
                      'of levels in the index of "right"'
                  )
              self.right_on = [None] * n
      elif self.right_on is not None:
          n = len(self.right_on)
          if self.left_index:
              if len(self.right_on) != self.left.index.nlevels:
                  raise ValueError(
                      "len(right_on) must equal the number "
                      'of levels in the index of "left"'
                  )
              self.left_on = [None] * n
      if len(self.right_on) != len(self.left_on):
          raise ValueError("len(right_on) must equal len(left_on)")
  
imports: import copy
  import string
  import warnings
  import numpy
  from pandas._libs import hashtable, join, lib
  import pandas.compat
  from pandas.compat import filter, lzip, map, range, zip
  from pandas.errors import MergeError
  from pandas.util._decorators import Appender, Substitution
  from pandas.core.dtypes.common import ensure_float64, ensure_int64, ensure_object, is_array_like, is_bool, is_bool_dtype, is_categorical_dtype, is_datetime64_dtype, is_datetime64tz_dtype, is_datetimelike, is_dtype_equal, is_extension_array_dtype, is_float_dtype, is_int64_dtype, is_integer, is_integer_dtype, is_list_like, is_number, is_numeric_dtype, is_object_dtype, needs_i8_conversion
  from pandas.core.dtypes.missing import isnull, na_value_for_dtype
  from pandas import Categorical, DataFrame, Index, MultiIndex, Series, Timedelta
  import pandas.core.algorithms
  from pandas.core.arrays.categorical import _recode_for_categories
  import pandas.core.common
  from pandas.core.frame import _merge_doc
  from pandas.core.internals import concatenate_block_managers, items_overlap_with_suffix
  import pandas.core.sorting
  from pandas.core.sorting import is_int64_overflow_possible
label_desc: Use image node_id 11 for calling the _MergeOperation obj's underlying member method code with example usage: obj._validate_specification() without return types