code: func (p *Projection) convert2PhysicalPlan(prop *requiredProperty) (*physicalPlanInfo, error) {
  	info, err := p.getPlanInfo(prop)
  	if err != nil {
  		return nil, errors.Trace(err)
  	}
  	if info != nil {
  		return info, nil
  	}
  	newProp := &requiredProperty{
  		props:      make([]*columnProp, 0, len(prop.props)),
  		sortKeyLen: prop.sortKeyLen,
  		limit:      prop.limit}
  	childSchema := p.GetChildByIndex(0).GetSchema()
  	usedCols := make([]bool, childSchema.Len())
  	canPassSort := true
  loop:
  	for _, c := range prop.props {
  		idx := p.schema.GetColumnIndex(c.col)
  		switch v := p.Exprs[idx].(type) {
  		case *expression.Column:
  			childIdx := childSchema.GetColumnIndex(v)
  			if !usedCols[childIdx] {
  				usedCols[childIdx] = true
  				newProp.props = append(newProp.props, &columnProp{col: v, desc: c.desc})
  			}
  		case *expression.ScalarFunction:
  			newProp = nil
  			canPassSort = false
  			break loop
  		default:
  			newProp.sortKeyLen--
  		}
  	}
  	if !canPassSort {
  		return &physicalPlanInfo{cost: math.MaxFloat64}, nil
  	}
  	info, err = p.GetChildByIndex(0).(LogicalPlan).convert2PhysicalPlan(newProp)
  	if err != nil {
  		return nil, errors.Trace(err)
  	}
  	info = addPlanToResponse(p, info)
  	p.storePlanInfo(prop, info)
  	return info, nil
  }
docs: // convert2PhysicalPlan implements the LogicalPlan convert2PhysicalPlan interface.