code: func EncodeRow(sc *stmtctx.StatementContext, row []types.Datum, colIDs []int64, valBuf []byte, values []types.Datum) ([]byte, error) {
  	if len(row) != len(colIDs) {
  		return nil, errors.Errorf("EncodeRow error: data and columnID count not match %d vs %d", len(row), len(colIDs))
  	}
  	valBuf = valBuf[:0]
  	if values == nil {
  		values = make([]types.Datum, len(row)*2)
  	}
  	for i, c := range row {
  		id := colIDs[i]
  		values[2*i].SetInt64(id)
  		err := flatten(sc, c, &values[2*i+1])
  		if err != nil {
  			return nil, errors.Trace(err)
  		}
  	}
  	if len(values) == 0 {
  		// We could not set nil value into kv.
  		return []byte{codec.NilFlag}, nil
  	}
  	return codec.EncodeValue(sc, valBuf, values...)
  }
docs: // EncodeRow encode row data and column ids into a slice of byte.
  // Row layout: colID1, value1, colID2, value2, .....
  // valBuf and values pass by caller, for reducing EncodeRow allocates temporary bufs. If you pass valBuf and values as nil,
  // EncodeRow will allocate it.