code: func (p *LogicalJoin) exhaustPhysicalPlans(prop *property.PhysicalProperty) []PhysicalPlan {
  	mergeJoins := p.getMergeJoin(prop)
  	if (p.preferJoinType & preferMergeJoin) > 0 {
  		return mergeJoins
  	}
  	joins := make([]PhysicalPlan, 0, 5)
  	joins = append(joins, mergeJoins...)
  
  	indexJoins, forced := p.tryToGetIndexJoin(prop)
  	if forced {
  		return indexJoins
  	}
  	joins = append(joins, indexJoins...)
  
  	hashJoins := p.getHashJoins(prop)
  	if (p.preferJoinType & preferHashJoin) > 0 {
  		return hashJoins
  	}
  	joins = append(joins, hashJoins...)
  	return joins
  }
docs: // LogicalJoin can generates hash join, index join and sort merge join.
  // Firstly we check the hint, if hint is figured by user, we force to choose the corresponding physical plan.
  // If the hint is not matched, it will get other candidates.
  // If the hint is not figured, we will pick all candidates.