code: func decorrelate(p LogicalPlan) LogicalPlan {
  	if apply, ok := p.(*Apply); ok {
  		outerPlan := apply.children[0]
  		innerPlan := apply.children[1].(LogicalPlan)
  		apply.extractCorColumnsBySchema()
  		if len(apply.corCols) == 0 {
  			// If the inner plan is non-correlated, the apply will be simplified to join.
  			join := &apply.Join
  			innerPlan.SetParents(join)
  			outerPlan.SetParents(join)
  			p = join
  		} else if sel, ok := innerPlan.(*Selection); ok {
  			// If the inner plan is a selection, we add this condition to join predicates.
  			// Notice that no matter what kind of join is, it's always right.
  			newConds := make([]expression.Expression, 0, len(sel.Conditions))
  			for _, cond := range sel.Conditions {
  				newConds = append(newConds, cond.Decorrelate(outerPlan.GetSchema()))
  			}
  			apply.attachOnConds(newConds)
  			innerPlan = sel.children[0].(LogicalPlan)
  			apply.SetChildren(outerPlan, innerPlan)
  			innerPlan.SetParents(apply)
  			return decorrelate(p)
  		}
  		// TODO: Deal with aggregation and projection.
  	}
  	newChildren := make([]Plan, 0, len(p.GetChildren()))
  	for _, child := range p.GetChildren() {
  		newChildren = append(newChildren, decorrelate(child.(LogicalPlan)))
  		child.SetParents(p)
  	}
  	p.SetChildren(newChildren...)
  	return p
  }
docs: // decorrelate function tries to convert apply plan to join plan.