code: func (s *propConstSolver) propagateConstantEQ() {
  	s.eqList = make([]*Constant, len(s.columns))
  	visited := make([]bool, len(s.conditions))
  	for i := 0; i < MaxPropagateColsCnt; i++ {
  		mapper := s.pickNewEQConds(visited)
  		if len(mapper) == 0 {
  			return
  		}
  		cols := make([]*Column, 0, len(mapper))
  		cons := make([]Expression, 0, len(mapper))
  		for id, con := range mapper {
  			cols = append(cols, s.columns[id])
  			cons = append(cons, con)
  		}
  		for i, cond := range s.conditions {
  			if !visited[i] {
  				s.conditions[i] = ColumnSubstitute(cond, NewSchema(cols...), cons)
  			}
  		}
  	}
  }
docs: // propagateConstantEQ propagates expressions like 'column = constant' by substituting the constant for column, the
  // procedure repeats multiple times. An example runs as following:
  // a = d & b * 2 = c & c = d + 2 & b = 1 & a = 4, we pick eq cond b = 1 and a = 4
  // d = 4 & 2 = c & c = d + 2 & b = 1 & a = 4, we propagate b = 1 and a = 4 and pick eq cond c = 2 and d = 4
  // d = 4 & 2 = c & false & b = 1 & a = 4, we propagate c = 2 and d = 4, and do constant folding: c = d + 2 will be folded as false.