DatumPrev returns a datum that is "previous" to the given one. For many types it just delegates to Datum.Prev, but for some types that don't have an implementation of that function this method makes the best effort to come up with a reasonable previous datum that is smaller than the given one. The
( ctx context.Context, datum Datum, cmpCtx CompareContext, collationEnv *CollationEnvironment, )
| 6581 | // The return value is undefined if Datum.IsMin returns true or if the value is |
| 6582 | // NaN or an infinity (for floats and decimals). |
| 6583 | func DatumPrev( |
| 6584 | ctx context.Context, datum Datum, cmpCtx CompareContext, collationEnv *CollationEnvironment, |
| 6585 | ) (Datum, bool) { |
| 6586 | datum = UnwrapDOidWrapper(datum) |
| 6587 | prevString := func(s string) (string, bool) { |
| 6588 | // In order to obtain a previous string we subtract 1 from the last |
| 6589 | // non-zero byte. |
| 6590 | b := []byte(s) |
| 6591 | lastNonZeroByteIdx := len(b) - 1 |
| 6592 | for ; lastNonZeroByteIdx >= 0 && b[lastNonZeroByteIdx] == 0; lastNonZeroByteIdx-- { |
| 6593 | } |
| 6594 | if lastNonZeroByteIdx < 0 { |
| 6595 | return "", false |
| 6596 | } |
| 6597 | b[lastNonZeroByteIdx]-- |
| 6598 | return string(b), true |
| 6599 | } |
| 6600 | switch d := datum.(type) { |
| 6601 | case *DDecimal: |
| 6602 | var prev DDecimal |
| 6603 | var sub apd.Decimal |
| 6604 | _, err := sub.SetFloat64(1e-6) |
| 6605 | if err != nil { |
| 6606 | return nil, false |
| 6607 | } |
| 6608 | _, err = ExactCtx.Sub(&prev.Decimal, &d.Decimal, &sub) |
| 6609 | if err != nil { |
| 6610 | return nil, false |
| 6611 | } |
| 6612 | return &prev, true |
| 6613 | case *DString: |
| 6614 | prev, ok := prevString(string(*d)) |
| 6615 | if !ok { |
| 6616 | return nil, false |
| 6617 | } |
| 6618 | return NewDString(prev), true |
| 6619 | case *DBytes: |
| 6620 | prev, ok := prevString(string(*d)) |
| 6621 | if !ok { |
| 6622 | return nil, false |
| 6623 | } |
| 6624 | return NewDBytes(DBytes(prev)), true |
| 6625 | case *DInterval: |
| 6626 | // Subtract 1ms. |
| 6627 | prev := d.Sub(duration.MakeDuration(1000000 /* nanos */, 0 /* days */, 0 /* months */)) |
| 6628 | return NewDInterval(prev, types.DefaultIntervalTypeMetadata), true |
| 6629 | default: |
| 6630 | // TODO(yuzefovich): consider adding support for other datums that don't |
| 6631 | // have Datum.Prev implementation (DCollatedString, DBitArray, |
| 6632 | // DGeography, DGeometry, DBox2D, DJSON, DArray). |
| 6633 | return datum.Prev(ctx, cmpCtx) |
| 6634 | } |
| 6635 | } |
| 6636 | |
| 6637 | // DatumNext returns a datum that is "next" to the given one. For many types it |
| 6638 | // just delegates to Datum.Next, but for some types that don't have an |
nothing calls this directly
no test coverage detected
searching dependent graphs…