DecimalToHLC performs the conversion from an inputted DECIMAL datum for an AS OF SYSTEM TIME query to an HLC timestamp.
(d *apd.Decimal)
| 136 | // DecimalToHLC performs the conversion from an inputted DECIMAL datum for an |
| 137 | // AS OF SYSTEM TIME query to an HLC timestamp. |
| 138 | func DecimalToHLC(d *apd.Decimal) (hlc.Timestamp, error) { |
| 139 | // Format the decimal into a string and split on `.` to extract the nanosecond |
| 140 | // walltime and logical tick parts. |
| 141 | // TODO(mjibson): use d.Modf() instead of converting to a string. |
| 142 | s := d.Text('f') |
| 143 | parts := strings.SplitN(s, ".", 2) |
| 144 | nanos, err := strconv.ParseInt(parts[0], 10, 64) |
| 145 | if err != nil { |
| 146 | return hlc.Timestamp{}, pgerror.Wrapf(err, pgcode.Syntax, "parsing argument") |
| 147 | } |
| 148 | var logical int64 |
| 149 | if len(parts) > 1 { |
| 150 | // logicalLength is the number of decimal digits expected in the |
| 151 | // logical part to the right of the decimal. See the implementation of |
| 152 | // cluster_logical_timestamp(). |
| 153 | const logicalLength = 10 |
| 154 | p := parts[1] |
| 155 | if lp := len(p); lp > logicalLength { |
| 156 | return hlc.Timestamp{}, pgerror.Newf(pgcode.Syntax, "logical part has too many digits") |
| 157 | } else if lp < logicalLength { |
| 158 | p += strings.Repeat("0", logicalLength-lp) |
| 159 | } |
| 160 | logical, err = strconv.ParseInt(p, 10, 32) |
| 161 | if err != nil { |
| 162 | return hlc.Timestamp{}, pgerror.Wrapf(err, pgcode.Syntax, "parsing argument") |
| 163 | } |
| 164 | } |
| 165 | return hlc.Timestamp{ |
| 166 | WallTime: nanos, |
| 167 | Logical: int32(logical), |
| 168 | }, nil |
| 169 | } |
no test coverage detected
searching dependent graphs…