code: func ProduceDecWithSpecifiedTp(dec *MyDecimal, tp *FieldType, sc *stmtctx.StatementContext) (_ *MyDecimal, err error) {
  	flen, decimal := tp.Flen, tp.Decimal
  	if flen != UnspecifiedLength && decimal != UnspecifiedLength {
  		if flen < decimal {
  			return nil, ErrMBiggerThanD.GenWithStackByArgs("")
  		}
  		prec, frac := dec.PrecisionAndFrac()
  		if !dec.IsZero() && prec-frac > flen-decimal {
  			dec = NewMaxOrMinDec(dec.IsNegative(), flen, decimal)
  			// select (cast 111 as decimal(1)) causes a warning in MySQL.
  			err = ErrOverflow.GenWithStackByArgs("DECIMAL", fmt.Sprintf("(%d, %d)", flen, decimal))
  		} else if frac != decimal {
  			old := *dec
  			err = dec.Round(dec, decimal, ModeHalfEven)
  			if err != nil {
  				return nil, err
  			}
  			if !dec.IsZero() && frac > decimal && dec.Compare(&old) != 0 {
  				if sc.InInsertStmt || sc.InUpdateStmt || sc.InDeleteStmt {
  					// fix https://github.com/pingcap/tidb/issues/3895
  					// fix https://github.com/pingcap/tidb/issues/5532
  					sc.AppendWarning(ErrTruncated)
  					err = nil
  				} else {
  					err = sc.HandleTruncate(ErrTruncated)
  				}
  			}
  		}
  	}
  
  	if ErrOverflow.Equal(err) {
  		// TODO: warnErr need to be ErrWarnDataOutOfRange
  		err = sc.HandleOverflow(err, err)
  	}
  	unsigned := mysql.HasUnsignedFlag(tp.Flag)
  	if unsigned && dec.IsNegative() {
  		dec = dec.FromUint(0)
  	}
  	return dec, err
  }
docs: // ProduceDecWithSpecifiedTp produces a new decimal according to `flen` and `decimal`.