code: func (cf *concatFunction) Update(evalCtx *AggEvaluateContext, sc *stmtctx.StatementContext, row chunk.Row) error {
  	datumBuf := make([]types.Datum, 0, len(cf.Args))
  	if !cf.sepInited {
  		err := cf.initSeparator(sc, row)
  		if err != nil {
  			return err
  		}
  		cf.sepInited = true
  	}
  
  	// The last parameter is the concat separator, we only concat the first "len(cf.Args)-1" parameters.
  	for i, length := 0, len(cf.Args)-1; i < length; i++ {
  		value, err := cf.Args[i].Eval(row)
  		if err != nil {
  			return err
  		}
  		if value.IsNull() {
  			return nil
  		}
  		datumBuf = append(datumBuf, value)
  	}
  	if cf.HasDistinct {
  		d, err := evalCtx.DistinctChecker.Check(datumBuf)
  		if err != nil {
  			return err
  		}
  		if !d {
  			return nil
  		}
  	}
  	if evalCtx.Buffer == nil {
  		evalCtx.Buffer = &bytes.Buffer{}
  	} else {
  		evalCtx.Buffer.WriteString(cf.separator)
  	}
  	for _, val := range datumBuf {
  		cf.writeValue(evalCtx, val)
  	}
  	if cf.maxLen > 0 && uint64(evalCtx.Buffer.Len()) > cf.maxLen {
  		i := mathutil.MaxInt
  		if uint64(i) > cf.maxLen {
  			i = int(cf.maxLen)
  		}
  		evalCtx.Buffer.Truncate(i)
  		if !cf.truncated {
  			sc.AppendWarning(expression.ErrCutValueGroupConcat.GenWithStackByArgs(cf.Args[0].String()))
  		}
  		cf.truncated = true
  	}
  	return nil
  }
docs: // Update implements Aggregation interface.