code: func (p *LogicalJoin) outerJoinPropConst(predicates []expression.Expression) []expression.Expression {
  	outerTable := p.children[0]
  	innerTable := p.children[1]
  	if p.JoinType == RightOuterJoin {
  		innerTable, outerTable = outerTable, innerTable
  	}
  	lenJoinConds := len(p.EqualConditions) + len(p.LeftConditions) + len(p.RightConditions) + len(p.OtherConditions)
  	joinConds := make([]expression.Expression, 0, lenJoinConds)
  	for _, equalCond := range p.EqualConditions {
  		joinConds = append(joinConds, equalCond)
  	}
  	joinConds = append(joinConds, p.LeftConditions...)
  	joinConds = append(joinConds, p.RightConditions...)
  	joinConds = append(joinConds, p.OtherConditions...)
  	p.EqualConditions = nil
  	p.LeftConditions = nil
  	p.RightConditions = nil
  	p.OtherConditions = nil
  	nullSensitive := (p.JoinType == AntiLeftOuterSemiJoin || p.JoinType == LeftOuterSemiJoin)
  	joinConds, predicates = expression.PropConstOverOuterJoin(p.ctx, joinConds, predicates, outerTable.Schema(), innerTable.Schema(), nullSensitive)
  	p.attachOnConds(joinConds)
  	return predicates
  }
docs: // outerJoinPropConst propagates constant equal and column equal conditions over outer join.