code: func (p *Union) convert2PhysicalPlan(prop *requiredProperty) (*physicalPlanInfo, error) {
  	info, err := p.getPlanInfo(prop)
  	if err != nil {
  		return nil, errors.Trace(err)
  	}
  	if info != nil {
  		return info, nil
  	}
  	limit := prop.limit
  	childInfos := make([]*physicalPlanInfo, 0, len(p.children))
  	for _, child := range p.GetChildren() {
  		newProp := &requiredProperty{}
  		if limit != nil {
  			newProp = convertLimitOffsetToCount(prop)
  			newProp.props = make([]*columnProp, 0, len(prop.props))
  			for _, c := range prop.props {
  				idx := p.GetSchema().GetColumnIndex(c.col)
  				newProp.props = append(newProp.props, &columnProp{col: child.GetSchema().Columns[idx], desc: c.desc})
  			}
  		}
  		childInfo, err := child.(LogicalPlan).convert2PhysicalPlan(newProp)
  		if err != nil {
  			return nil, errors.Trace(err)
  		}
  		childInfos = append(childInfos, childInfo)
  	}
  	info = p.matchProperty(prop, childInfos...)
  	info = enforceProperty(prop, info)
  	p.storePlanInfo(prop, info)
  	return info, nil
  }
docs: // convert2PhysicalPlan implements the LogicalPlan convert2PhysicalPlan interface.