code: func refine4NeighbourProj(p, childProj *PhysicalProjection) {
  	inputIdx2OutputIdxes := make(map[int][]int)
  	for i, expr := range childProj.Exprs {
  		col, isCol := expr.(*expression.Column)
  		if !isCol {
  			continue
  		}
  		inputIdx2OutputIdxes[col.Index] = append(inputIdx2OutputIdxes[col.Index], i)
  	}
  	childSchemaUnionSet := disjointset.NewIntSet(childProj.schema.Len())
  	for _, outputIdxes := range inputIdx2OutputIdxes {
  		if len(outputIdxes) <= 1 {
  			continue
  		}
  		for i := 1; i < len(outputIdxes); i++ {
  			childSchemaUnionSet.Union(outputIdxes[0], outputIdxes[i])
  		}
  	}
  
  	for _, expr := range p.Exprs {
  		col, isCol := expr.(*expression.Column)
  		if !isCol {
  			continue
  		}
  		col.Index = childSchemaUnionSet.FindRoot(col.Index)
  	}
  }
docs: // refine4NeighbourProj refines the index for p.Exprs whose type is *Column when
  // there is two neighbouring Projections.
  // This function is introduced because that different childProj.Expr may refer
  // to the same index of childProj.Schema, so we need to keep this relation
  // between the specified expressions in the parent Projection.