github.com/cockroachdb/apd/v3@v3.2.0/decimal.go (about) 1 // Copyright 2016 The Cockroach Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 // implied. See the License for the specific language governing 13 // permissions and limitations under the License. 14 15 package apd 16 17 import ( 18 "errors" 19 "fmt" 20 "strconv" 21 "strings" 22 "unsafe" 23 24 "database/sql/driver" 25 ) 26 27 // Decimal is an arbitrary-precision decimal. Its value is: 28 // 29 // Negative × Coeff × 10**Exponent 30 // 31 // Coeff must be positive. If it is negative results may be incorrect and 32 // apd may panic. 33 type Decimal struct { 34 Form Form 35 Negative bool 36 Exponent int32 37 Coeff BigInt 38 } 39 40 // Form specifies the form of a Decimal. 41 type Form int8 42 43 const ( 44 // These constants must be in the following order. CmpTotal assumes that 45 // the order of these constants reflects the total order on decimals. 46 47 // Finite is the finite form. 48 Finite Form = iota 49 // Infinite is the infinite form. 50 Infinite 51 // NaNSignaling is the signaling NaN form. It will always raise the 52 // InvalidOperation condition during an operation. 53 NaNSignaling 54 // NaN is the NaN form. 55 NaN 56 ) 57 58 var ( 59 decimalNaN = &Decimal{Form: NaN} 60 decimalInfinity = &Decimal{Form: Infinite} 61 ) 62 63 //go:generate stringer -type=Form 64 65 const ( 66 // TODO(mjibson): MaxExponent is set because both upscale and Round 67 // perform a calculation of 10^x, where x is an exponent. This is done by 68 // big.Int.Exp. This restriction could be lifted if better algorithms were 69 // determined during upscale and Round that don't need to perform Exp. 70 71 // MaxExponent is the highest exponent supported. Exponents near this range will 72 // perform very slowly (many seconds per operation). 73 MaxExponent = 100000 74 // MinExponent is the lowest exponent supported with the same limitations as 75 // MaxExponent. 76 MinExponent = -MaxExponent 77 ) 78 79 // New creates a new decimal with the given coefficient and exponent. 80 func New(coeff int64, exponent int32) *Decimal { 81 d := new(Decimal) 82 d.SetFinite(coeff, exponent) 83 return d 84 } 85 86 // NewWithBigInt creates a new decimal with the given coefficient and exponent. 87 func NewWithBigInt(coeff *BigInt, exponent int32) *Decimal { 88 d := new(Decimal) 89 d.Coeff.Set(coeff) 90 if d.Coeff.Sign() < 0 { 91 d.Negative = true 92 d.Coeff.Abs(&d.Coeff) 93 } 94 d.Exponent = exponent 95 return d 96 } 97 98 func consumePrefix(s, prefix string) (string, bool) { 99 if strings.HasPrefix(s, prefix) { 100 return s[len(prefix):], true 101 } 102 return s, false 103 } 104 105 func (d *Decimal) setString(c *Context, s string) (Condition, error) { 106 orig := s 107 s, d.Negative = consumePrefix(s, "-") 108 if !d.Negative { 109 s, _ = consumePrefix(s, "+") 110 } 111 s = strings.ToLower(s) 112 d.Exponent = 0 113 d.Coeff.SetInt64(0) 114 // Until there are no parse errors, leave as NaN. 115 d.Form = NaN 116 if strings.HasPrefix(s, "-") || strings.HasPrefix(s, "+") { 117 return 0, fmt.Errorf("could not parse: %s", orig) 118 } 119 switch s { 120 case "infinity", "inf": 121 d.Form = Infinite 122 return 0, nil 123 } 124 isNaN := false 125 s, consumed := consumePrefix(s, "nan") 126 if consumed { 127 isNaN = true 128 } 129 s, consumed = consumePrefix(s, "snan") 130 if consumed { 131 isNaN = true 132 d.Form = NaNSignaling 133 } 134 if isNaN { 135 if s != "" { 136 // We ignore these digits, but must verify them. 137 _, err := strconv.ParseUint(s, 10, 64) 138 if err != nil { 139 return 0, fmt.Errorf("parse payload: %s: %w", s, err) 140 } 141 } 142 return 0, nil 143 } 144 145 exps := make([]int64, 0, 2) 146 if i := strings.IndexByte(s, 'e'); i >= 0 { 147 exp, err := strconv.ParseInt(s[i+1:], 10, 32) 148 if err != nil { 149 return 0, fmt.Errorf("parse exponent: %s: %w", s[i+1:], err) 150 } 151 exps = append(exps, exp) 152 s = s[:i] 153 } 154 if i := strings.IndexByte(s, '.'); i >= 0 { 155 exp := int64(len(s) - i - 1) 156 exps = append(exps, -exp) 157 s = s[:i] + s[i+1:] 158 } 159 if _, ok := d.Coeff.SetString(s, 10); !ok { 160 return 0, fmt.Errorf("parse mantissa: %s", s) 161 } 162 // No parse errors, can now flag as finite. 163 d.Form = Finite 164 return c.goError(d.setExponent(c, unknownNumDigits, 0, exps...)) 165 } 166 167 // NewFromString creates a new decimal from s. It has no restrictions on 168 // exponents or precision. 169 func NewFromString(s string) (*Decimal, Condition, error) { 170 return BaseContext.NewFromString(s) 171 } 172 173 // SetString sets d to s and returns d. It has no restrictions on exponents 174 // or precision. 175 func (d *Decimal) SetString(s string) (*Decimal, Condition, error) { 176 return BaseContext.SetString(d, s) 177 } 178 179 // NewFromString creates a new decimal from s. The returned Decimal has its 180 // exponents restricted by the context and its value rounded if it contains more 181 // digits than the context's precision. 182 func (c *Context) NewFromString(s string) (*Decimal, Condition, error) { 183 d := new(Decimal) 184 return c.SetString(d, s) 185 } 186 187 // SetString sets d to s and returns d. The returned Decimal has its exponents 188 // restricted by the context and its value rounded if it contains more digits 189 // than the context's precision. 190 func (c *Context) SetString(d *Decimal, s string) (*Decimal, Condition, error) { 191 res, err := d.setString(c, s) 192 if err != nil { 193 return nil, 0, err 194 } 195 res |= c.round(d, d) 196 _, err = c.goError(res) 197 return d, res, err 198 } 199 200 // Set sets d's fields to the values of x and returns d. 201 //gcassert:inline 202 func (d *Decimal) Set(x *Decimal) *Decimal { 203 if d == x { 204 return d 205 } 206 return d.setSlow(x) 207 } 208 209 // setSlow is split from Set to allow the aliasing fast-path to be 210 // inlined in callers. 211 func (d *Decimal) setSlow(x *Decimal) *Decimal { 212 d.Form = x.Form 213 d.Negative = x.Negative 214 d.Exponent = x.Exponent 215 d.Coeff.Set(&x.Coeff) 216 return d 217 } 218 219 // SetInt64 sets d to x and returns d. 220 func (d *Decimal) SetInt64(x int64) *Decimal { 221 return d.SetFinite(x, 0) 222 } 223 224 // SetFinite sets d to x with exponent e and returns d. 225 func (d *Decimal) SetFinite(x int64, e int32) *Decimal { 226 d.setCoefficient(x) 227 d.Exponent = e 228 return d 229 } 230 231 // setCoefficient sets d's coefficient and negative value to x and its Form 232 // to Finite The exponent is not changed. Since the exponent is not changed 233 // (and this is thus easy to misuse), this is unexported for internal use only. 234 func (d *Decimal) setCoefficient(x int64) { 235 d.Negative = x < 0 236 d.Coeff.SetInt64(x) 237 d.Coeff.Abs(&d.Coeff) 238 d.Form = Finite 239 } 240 241 // SetFloat64 sets d's Coefficient and Exponent to x and returns d. d will 242 // hold the exact value of f. 243 func (d *Decimal) SetFloat64(f float64) (*Decimal, error) { 244 _, _, err := d.SetString(strconv.FormatFloat(f, 'E', -1, 64)) 245 return d, err 246 } 247 248 // Int64 returns the int64 representation of x. If x cannot be represented in an 249 // int64, an error is returned. 250 func (d *Decimal) Int64() (int64, error) { 251 if d.Form != Finite { 252 return 0, fmt.Errorf("%s is not finite", d.String()) 253 } 254 var integ, frac Decimal 255 d.Modf(&integ, &frac) 256 if !frac.IsZero() { 257 return 0, fmt.Errorf("%s: has fractional part", d.String()) 258 } 259 var ed ErrDecimal 260 if integ.Cmp(decimalMaxInt64) > 0 { 261 return 0, fmt.Errorf("%s: greater than max int64", d.String()) 262 } 263 if integ.Cmp(decimalMinInt64) < 0 { 264 return 0, fmt.Errorf("%s: less than min int64", d.String()) 265 } 266 if err := ed.Err(); err != nil { 267 return 0, err 268 } 269 v := integ.Coeff.Int64() 270 for i := int32(0); i < integ.Exponent; i++ { 271 v *= 10 272 } 273 if d.Negative { 274 v = -v 275 } 276 return v, nil 277 } 278 279 // Float64 returns the float64 representation of x. This conversion may lose 280 // data (see strconv.ParseFloat for caveats). 281 func (d *Decimal) Float64() (float64, error) { 282 return strconv.ParseFloat(d.String(), 64) 283 } 284 285 const ( 286 errExponentOutOfRangeStr = "exponent out of range" 287 288 unknownNumDigits = int64(-1) 289 ) 290 291 // setExponent sets d's Exponent to the sum of xs. Each value and the sum 292 // of xs must fit within an int32. An error occurs if the sum is outside of 293 // the MaxExponent or MinExponent range. nd is the number of digits in d, as 294 // computed by NumDigits. Callers can pass unknownNumDigits to indicate that 295 // they have not yet computed this digit count, in which case setExponent will 296 // do so. res is any Condition previously set for this operation, which can 297 // cause Underflow to be set if, for example, Inexact is already set. 298 func (d *Decimal) setExponent(c *Context, nd int64, res Condition, xs ...int64) Condition { 299 var sum int64 300 for _, x := range xs { 301 if x > MaxExponent { 302 return SystemOverflow | Overflow 303 } 304 if x < MinExponent { 305 return SystemUnderflow | Underflow 306 } 307 sum += x 308 } 309 r := int32(sum) 310 311 if nd == unknownNumDigits { 312 nd = d.NumDigits() 313 } 314 // adj is the adjusted exponent: exponent + clength - 1 315 adj := sum + nd - 1 316 // Make sure it is less than the system limits. 317 if adj > MaxExponent { 318 return SystemOverflow | Overflow 319 } 320 if adj < MinExponent { 321 return SystemUnderflow | Underflow 322 } 323 v := int32(adj) 324 325 // d is subnormal. 326 if v < c.MinExponent { 327 if !d.IsZero() { 328 res |= Subnormal 329 } 330 Etiny := c.MinExponent - (int32(c.Precision) - 1) 331 // Only need to round if exponent < Etiny. 332 if r < Etiny { 333 // We need to take off (r - Etiny) digits. Split up d.Coeff into integer and 334 // fractional parts and do operations similar Round. We avoid calling Round 335 // directly because it calls setExponent and modifies the result's exponent 336 // and coeff in ways that would be wrong here. 337 var tmp Decimal 338 tmp.Coeff.Set(&d.Coeff) 339 tmp.Exponent = r - Etiny 340 var integ, frac Decimal 341 tmp.Modf(&integ, &frac) 342 frac.Abs(&frac) 343 if !frac.IsZero() { 344 res |= Inexact 345 if c.Rounding.ShouldAddOne(&integ.Coeff, integ.Negative, frac.Cmp(decimalHalf)) { 346 integ.Coeff.Add(&integ.Coeff, bigOne) 347 } 348 } 349 if integ.IsZero() { 350 res |= Clamped 351 } 352 r = Etiny 353 d.Coeff.Set(&integ.Coeff) 354 res |= Rounded 355 } 356 } else if v > c.MaxExponent { 357 if d.IsZero() { 358 res |= Clamped 359 r = c.MaxExponent 360 } else { 361 res |= Overflow | Inexact 362 d.Form = Infinite 363 } 364 } 365 366 if res.Inexact() && res.Subnormal() { 367 res |= Underflow 368 } 369 370 d.Exponent = r 371 return res 372 } 373 374 // upscale converts a and b to BigInts with the same scaling. It returns 375 // them with this scaling, along with the scaling. An error can be produced 376 // if the resulting scale factor is out of range. The tmp argument must be 377 // provided and can be (but won't always be) one of the return values. 378 func upscale(a, b *Decimal, tmp *BigInt) (*BigInt, *BigInt, int32, error) { 379 if a.Exponent == b.Exponent { 380 return &a.Coeff, &b.Coeff, a.Exponent, nil 381 } 382 swapped := false 383 if a.Exponent < b.Exponent { 384 swapped = true 385 b, a = a, b 386 } 387 s := int64(a.Exponent) - int64(b.Exponent) 388 // TODO(mjibson): figure out a better way to upscale numbers with highly 389 // differing exponents. 390 if s > MaxExponent { 391 return nil, nil, 0, errors.New(errExponentOutOfRangeStr) 392 } 393 x := tmp 394 e := tableExp10(s, x) 395 x.Mul(&a.Coeff, e) 396 y := &b.Coeff 397 if swapped { 398 x, y = y, x 399 } 400 return x, y, b.Exponent, nil 401 } 402 403 // setBig sets b to d's coefficient with negative. 404 func (d *Decimal) setBig(b *BigInt) *BigInt { 405 b.Set(&d.Coeff) 406 if d.Negative { 407 b.Neg(b) 408 } 409 return b 410 } 411 412 // CmpTotal compares d and x using their abstract representation rather 413 // than their numerical value. A total ordering is defined for all possible 414 // abstract representations, as described below. If the first operand is 415 // lower in the total order than the second operand then the result is -1, 416 // if the operands have the same abstract representation then the result is 417 // 0, and if the first operand is higher in the total order than the second 418 // operand then the result is 1. 419 // 420 // Numbers (representations which are not NaNs) are ordered such that a 421 // larger numerical value is higher in the ordering. If two representations 422 // have the same numerical value then the exponent is taken into account; 423 // larger (more positive) exponents are higher in the ordering. 424 // 425 // For example, the following values are ordered from lowest to highest. Note 426 // the difference in ordering between 1.2300 and 1.23. 427 // 428 // -NaN 429 // -NaNSignaling 430 // -Infinity 431 // -127 432 // -1.00 433 // -1 434 // -0.000 435 // -0 436 // 0 437 // 1.2300 438 // 1.23 439 // 1E+9 440 // Infinity 441 // NaNSignaling 442 // NaN 443 // 444 func (d *Decimal) CmpTotal(x *Decimal) int { 445 do := d.cmpOrder() 446 xo := x.cmpOrder() 447 448 if do < xo { 449 return -1 450 } 451 if do > xo { 452 return 1 453 } 454 455 switch d.Form { 456 case Finite: 457 // d and x have the same sign and form, compare their value. 458 if c := d.Cmp(x); c != 0 { 459 return c 460 } 461 462 lt := -1 463 gt := 1 464 if d.Negative { 465 lt = 1 466 gt = -1 467 } 468 469 // Values are equal, compare exponents. 470 if d.Exponent < x.Exponent { 471 return lt 472 } 473 if d.Exponent > x.Exponent { 474 return gt 475 } 476 return 0 477 478 case Infinite: 479 return 0 480 481 default: 482 return d.Coeff.Cmp(&x.Coeff) 483 } 484 } 485 486 func (d *Decimal) cmpOrder() int { 487 v := int(d.Form) + 1 488 if d.Negative { 489 v = -v 490 } 491 return v 492 } 493 494 // Cmp compares x and y and sets d to: 495 // 496 // -1 if x < y 497 // 0 if x == y 498 // +1 if x > y 499 // 500 // This comparison respects the normal rules of special values (like NaN), 501 // and does not compare them. 502 func (c *Context) Cmp(d, x, y *Decimal) (Condition, error) { 503 if c.shouldSetAsNaN(x, y) { 504 return c.setAsNaN(d, x, y) 505 } 506 v := x.Cmp(y) 507 d.SetInt64(int64(v)) 508 return 0, nil 509 } 510 511 // Cmp compares d and x and returns: 512 // 513 // -1 if d < x 514 // 0 if d == x 515 // +1 if d > x 516 // undefined if d or x are NaN 517 // 518 func (d *Decimal) Cmp(x *Decimal) int { 519 ds := d.Sign() 520 xs := x.Sign() 521 522 // First compare signs. 523 if ds < xs { 524 return -1 525 } else if ds > xs { 526 return 1 527 } else if ds == 0 && xs == 0 { 528 return 0 529 } 530 531 // Use gt and lt here with flipped signs if d is negative. gt and lt then 532 // allow for simpler comparisons since we can ignore the sign of the decimals 533 // and only worry about the form and value. 534 gt := 1 535 lt := -1 536 if ds == -1 { 537 gt = -1 538 lt = 1 539 } 540 541 if d.Form == Infinite { 542 if x.Form == Infinite { 543 return 0 544 } 545 return gt 546 } else if x.Form == Infinite { 547 return lt 548 } 549 550 if d.Exponent == x.Exponent { 551 cmp := d.Coeff.Cmp(&x.Coeff) 552 if ds < 0 { 553 cmp = -cmp 554 } 555 return cmp 556 } 557 558 // Next compare adjusted exponents. 559 dn := d.NumDigits() + int64(d.Exponent) 560 xn := x.NumDigits() + int64(x.Exponent) 561 if dn < xn { 562 return lt 563 } else if dn > xn { 564 return gt 565 } 566 567 // Now have to use aligned BigInts. This function previously used upscale to 568 // align in all cases, but that requires an error in the return value. upscale 569 // does that so that it can fail if it needs to take the Exp of too-large a 570 // number, which is very slow. The only way for that to happen here is for d 571 // and x's coefficients to be of hugely differing values. That is practically 572 // more difficult, so we are assuming the user is already comfortable with 573 // slowness in those operations. 574 575 var cmp int 576 if d.Exponent < x.Exponent { 577 var xScaled, tmpE BigInt 578 xScaled.Set(&x.Coeff) 579 xScaled.Mul(&xScaled, tableExp10(int64(x.Exponent)-int64(d.Exponent), &tmpE)) 580 cmp = d.Coeff.Cmp(&xScaled) 581 } else { 582 var dScaled, tmpE BigInt 583 dScaled.Set(&d.Coeff) 584 dScaled.Mul(&dScaled, tableExp10(int64(d.Exponent)-int64(x.Exponent), &tmpE)) 585 cmp = dScaled.Cmp(&x.Coeff) 586 } 587 if ds < 0 { 588 cmp = -cmp 589 } 590 return cmp 591 } 592 593 // Sign returns, if d is Finite: 594 // 595 // -1 if d < 0 596 // 0 if d == 0 or -0 597 // +1 if d > 0 598 // 599 // Otherwise (if d is Infinite or NaN): 600 // 601 // -1 if d.Negative == true 602 // +1 if d.Negative == false 603 // 604 func (d *Decimal) Sign() int { 605 if d.Form == Finite && d.Coeff.Sign() == 0 { 606 return 0 607 } 608 if d.Negative { 609 return -1 610 } 611 return 1 612 } 613 614 // IsZero returns true if d == 0 or -0. 615 func (d *Decimal) IsZero() bool { 616 return d.Sign() == 0 617 } 618 619 // Modf sets integ to the integral part of d and frac to the fractional part 620 // such that d = integ+frac. If d is negative, both integ or frac will be either 621 // 0 or negative. integ.Exponent will be >= 0; frac.Exponent will be <= 0. 622 // Either argument can be nil, preventing it from being set. 623 func (d *Decimal) Modf(integ, frac *Decimal) { 624 if integ == nil && frac == nil { 625 return 626 } 627 628 neg := d.Negative 629 630 // No fractional part. 631 if d.Exponent > 0 { 632 if frac != nil { 633 frac.Negative = neg 634 frac.Exponent = 0 635 frac.Coeff.SetInt64(0) 636 } 637 if integ != nil { 638 integ.Set(d) 639 } 640 return 641 } 642 nd := d.NumDigits() 643 exp := -int64(d.Exponent) 644 // d < 0 because exponent is larger than number of digits. 645 if exp > nd { 646 if integ != nil { 647 integ.Negative = neg 648 integ.Exponent = 0 649 integ.Coeff.SetInt64(0) 650 } 651 if frac != nil { 652 frac.Set(d) 653 } 654 return 655 } 656 657 var tmpE BigInt 658 e := tableExp10(exp, &tmpE) 659 660 var icoeff *BigInt 661 if integ != nil { 662 icoeff = &integ.Coeff 663 integ.Exponent = 0 664 integ.Negative = neg 665 } else { 666 // This is the integ == nil branch, and we already checked if both integ and 667 // frac were nil above, so frac can never be nil in this branch. 668 icoeff = new(BigInt) 669 } 670 671 if frac != nil { 672 icoeff.QuoRem(&d.Coeff, e, &frac.Coeff) 673 frac.Exponent = d.Exponent 674 frac.Negative = neg 675 } else { 676 // This is the frac == nil, which means integ must not be nil since they both 677 // can't be due to the check above. 678 icoeff.Quo(&d.Coeff, e) 679 } 680 } 681 682 // Neg sets d to -x and returns d. 683 func (d *Decimal) Neg(x *Decimal) *Decimal { 684 d.Set(x) 685 if d.IsZero() { 686 d.Negative = false 687 } else { 688 d.Negative = !d.Negative 689 } 690 return d 691 } 692 693 // Abs sets d to |x| and returns d. 694 func (d *Decimal) Abs(x *Decimal) *Decimal { 695 d.Set(x) 696 d.Negative = false 697 return d 698 } 699 700 // Reduce sets d to x with all trailing zeros removed and returns d and the 701 // number of zeros removed. 702 func (d *Decimal) Reduce(x *Decimal) (*Decimal, int) { 703 if x.Form != Finite { 704 d.Set(x) 705 return d, 0 706 } 707 var nd int 708 neg := false 709 switch x.Sign() { 710 case 0: 711 nd = int(d.NumDigits()) 712 d.SetInt64(0) 713 return d, nd - 1 714 case -1: 715 neg = true 716 } 717 d.Set(x) 718 719 // Use a uint64 for the division if possible. 720 if d.Coeff.IsUint64() { 721 i := d.Coeff.Uint64() 722 for i >= 10000 && i%10000 == 0 { 723 i /= 10000 724 nd += 4 725 } 726 for i%10 == 0 { 727 i /= 10 728 nd++ 729 } 730 if nd != 0 { 731 d.Exponent += int32(nd) 732 d.Coeff.SetUint64(i) 733 d.Negative = neg 734 } 735 return d, nd 736 } 737 738 // Divide by 10 in a loop. In benchmarks of reduce0.decTest, this is 20% 739 // faster than converting to a string and trimming the 0s from the end. 740 var z, r BigInt 741 d.setBig(&z) 742 for { 743 z.QuoRem(&d.Coeff, bigTen, &r) 744 if r.Sign() == 0 { 745 d.Coeff.Set(&z) 746 nd++ 747 } else { 748 break 749 } 750 } 751 d.Exponent += int32(nd) 752 return d, nd 753 } 754 755 const decimalSize = unsafe.Sizeof(Decimal{}) 756 757 // Size returns the total memory footprint of d in bytes. 758 func (d *Decimal) Size() uintptr { 759 return decimalSize - bigIntSize + d.Coeff.Size() 760 } 761 762 // Value implements the database/sql/driver.Valuer interface. It converts d to a 763 // string. 764 func (d Decimal) Value() (driver.Value, error) { 765 return d.String(), nil 766 } 767 768 // Scan implements the database/sql.Scanner interface. It supports string, 769 // []byte, int64, float64. 770 func (d *Decimal) Scan(src interface{}) error { 771 switch src := src.(type) { 772 case []byte: 773 _, _, err := d.SetString(string(src)) 774 return err 775 case string: 776 _, _, err := d.SetString(src) 777 return err 778 case int64: 779 d.SetInt64(src) 780 return nil 781 case float64: 782 _, err := d.SetFloat64(src) 783 return err 784 default: 785 return fmt.Errorf("could not convert %T to Decimal", src) 786 } 787 } 788 789 // UnmarshalText implements the encoding.TextUnmarshaler interface. 790 func (d *Decimal) UnmarshalText(b []byte) error { 791 _, _, err := d.SetString(string(b)) 792 return err 793 } 794 795 // MarshalText implements the encoding.TextMarshaler interface. 796 func (d *Decimal) MarshalText() ([]byte, error) { 797 if d == nil { 798 return []byte("<nil>"), nil 799 } 800 return []byte(d.String()), nil 801 } 802 803 // NullDecimal represents a string that may be null. NullDecimal implements 804 // the database/sql.Scanner interface so it can be used as a scan destination: 805 // 806 // var d NullDecimal 807 // err := db.QueryRow("SELECT num FROM foo WHERE id=?", id).Scan(&d) 808 // ... 809 // if d.Valid { 810 // // use d.Decimal 811 // } else { 812 // // NULL value 813 // } 814 // 815 type NullDecimal struct { 816 Decimal Decimal 817 Valid bool // Valid is true if Decimal is not NULL 818 } 819 820 // Scan implements the database/sql.Scanner interface. 821 func (nd *NullDecimal) Scan(value interface{}) error { 822 if value == nil { 823 nd.Valid = false 824 return nil 825 } 826 nd.Valid = true 827 return nd.Decimal.Scan(value) 828 } 829 830 // Value implements the database/sql/driver.Valuer interface. 831 func (nd NullDecimal) Value() (driver.Value, error) { 832 if !nd.Valid { 833 return nil, nil 834 } 835 return nd.Decimal.Value() 836 }