Encode decimals as floats without precision loss
This commit is contained in:
		
							parent
							
								
									68567fad6e
								
							
						
					
					
						commit
						c0a153a532
					
				
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @ -2,4 +2,4 @@ install: | |||||||
| 	dep ensure | 	dep ensure | ||||||
| 
 | 
 | ||||||
| test: | test: | ||||||
| 	go test -v ./tests | 	go test -v ./{mysql,tests} | ||||||
|  | |||||||
| @ -2,13 +2,23 @@ package mysql | |||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
|  | 	"database/sql/driver" | ||||||
| 	"encoding/binary" | 	"encoding/binary" | ||||||
|  | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"strconv" | ||||||
|  | 	"strings" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | // Decimal represents a decimal type that retains precision until converted to | ||||||
|  | // a float. It is designed to be marshaled into JSON without losing precision. | ||||||
|  | type Decimal struct { | ||||||
|  | 	str string | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // DecodeDecimal decodes a decimal value. | // DecodeDecimal decodes a decimal value. | ||||||
| // Implementation borrowed from https://github.com/siddontang/go-mysql/ | // Implementation borrowed from https://github.com/siddontang/go-mysql/ | ||||||
| func DecodeDecimal(data []byte, precision int, decimals int) (string, int) { | func DecodeDecimal(data []byte, precision int, decimals int) (Decimal, int) { | ||||||
| 	const digitsPerInteger int = 9 | 	const digitsPerInteger int = 9 | ||||||
| 	var compressedBytes = [...]int{0, 1, 1, 2, 2, 3, 3, 4, 4, 4} | 	var compressedBytes = [...]int{0, 1, 1, 2, 2, 3, 3, 4, 4, 4} | ||||||
| 
 | 
 | ||||||
| @ -21,6 +31,7 @@ func DecodeDecimal(data []byte, precision int, decimals int) (string, int) { | |||||||
| 		value = uint32(DecodeVarLen64BigEndian(databuff)) | 		value = uint32(DecodeVarLen64BigEndian(databuff)) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| 	// See python mysql replication and https://github.com/jeremycole/mysql_binlog | 	// See python mysql replication and https://github.com/jeremycole/mysql_binlog | ||||||
| 	integral := (precision - decimals) | 	integral := (precision - decimals) | ||||||
| 	uncompIntegral := int(integral / digitsPerInteger) | 	uncompIntegral := int(integral / digitsPerInteger) | ||||||
| @ -73,5 +84,49 @@ func DecodeDecimal(data []byte, precision int, decimals int) (string, int) { | |||||||
| 		pos += size | 		pos += size | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return res.String(), pos | 	return NewDecimal(res.String()), pos | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NewDecimal creates a new decimal with given value. | ||||||
|  | func NewDecimal(str string) Decimal { | ||||||
|  | 	var sign string | ||||||
|  | 	if str[0] == '-' { | ||||||
|  | 		str = str[1:] | ||||||
|  | 		sign = "-" | ||||||
|  | 	} | ||||||
|  | 	str = strings.Trim(str, "0") | ||||||
|  | 	if str[0] == '.' { | ||||||
|  | 		str = "0" + str | ||||||
|  | 	} | ||||||
|  | 	if str[len(str)-1] == '.' { | ||||||
|  | 		str += "0" | ||||||
|  | 	} | ||||||
|  | 	return Decimal{sign + str} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Float64 returns a float representation of the decimal. Precision could be | ||||||
|  | // lost. | ||||||
|  | func (d Decimal) Float64() float64 { | ||||||
|  | 	f, _ := strconv.ParseFloat(d.str, 64) | ||||||
|  | 	return f | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var _ json.Marshaler = Decimal{} | ||||||
|  | 
 | ||||||
|  | // MarshalJSON returns the JSON encoding of the decimal. | ||||||
|  | func (d Decimal) MarshalJSON() ([]byte, error) { | ||||||
|  | 	return []byte(d.str), nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var _ fmt.Stringer = Decimal{} | ||||||
|  | 
 | ||||||
|  | func (d Decimal) String() string { | ||||||
|  | 	return d.str | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var _ driver.Valuer = Decimal{} | ||||||
|  | 
 | ||||||
|  | // Value returns a driver Value. | ||||||
|  | func (d Decimal) Value() (driver.Value, error) { | ||||||
|  | 	return d.str, nil | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										231
									
								
								mysql/decimal_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								mysql/decimal_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,231 @@ | |||||||
|  | package mysql | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"testing" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func BenchmarkDecodeDecimal(b *testing.B) { | ||||||
|  | 	data := []byte{129, 134, 159, 59, 154, 201, 255, 59, 154, 201, 255, 0, 152, 150, 127, 10, 0} | ||||||
|  | 	precision := 30 | ||||||
|  | 	decimals := 25 | ||||||
|  | 
 | ||||||
|  | 	b.ReportAllocs() | ||||||
|  | 	for i := 0; i < b.N; i++ { | ||||||
|  | 		DecodeDecimal(data, precision, decimals) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestDecodeDecimalOrig(t *testing.T) { | ||||||
|  | 	testcases := []struct { | ||||||
|  | 		Data        []byte | ||||||
|  | 		Precision   int | ||||||
|  | 		Decimals    int | ||||||
|  | 		Expected    string | ||||||
|  | 		ExpectedPos int | ||||||
|  | 	}{ | ||||||
|  | 		{[]byte{117, 200, 127, 255}, 4, 2, "-10.55", 2}, | ||||||
|  | 		{[]byte{127, 255, 244, 127, 245}, 5, 0, "-11.0", 3}, | ||||||
|  | 		{[]byte{127, 245, 253, 217, 127, 255}, 7, 3, "-10.55", 4}, | ||||||
|  | 		{[]byte{127, 255, 255, 245, 200, 127, 255}, 10, 2, "-10.55", 5}, | ||||||
|  | 		{[]byte{127, 255, 255, 245, 253, 217, 127, 255}, 10, 3, "-10.55", 6}, | ||||||
|  | 		{[]byte{127, 255, 255, 255, 245, 200, 118, 196}, 13, 2, "-10.55", 6}, | ||||||
|  | 		{[]byte{118, 196, 101, 54, 0, 254, 121, 96, 127, 255}, 15, 14, "-9.99999999999999", 8}, | ||||||
|  | 		{[]byte{127, 255, 255, 255, 245, 223, 55, 170, 127, 255, 127, 255}, 20, 10, "-10.55", 10}, | ||||||
|  | 		{[]byte{127, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 245, 255, 41, 39, 127, 255}, 30, 5, "-10.55", 15}, | ||||||
|  | 		{[]byte{127, 255, 255, 255, 245, 223, 55, 170, 127, 255, 255, 255, 255, 255, 127, 255}, 30, 20, "-10.55", 14}, | ||||||
|  | 		{[]byte{127, 255, 245, 223, 55, 170, 127, 255, 255, 255, 255, 255, 255, 255, 255, 4, 0}, 30, 25, "-10.55", 15}, | ||||||
|  | 		{[]byte{128, 1, 128, 0}, 4, 2, "0.01", 2}, | ||||||
|  | 		{[]byte{128, 0, 0, 128, 0}, 5, 0, "0.0", 3}, | ||||||
|  | 		{[]byte{128, 0, 0, 12, 128, 0}, 7, 3, "0.012", 4}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 1, 128, 0}, 10, 2, "0.01", 5}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 12, 128, 0}, 10, 3, "0.012", 6}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 1, 128, 0}, 13, 2, "0.01", 6}, | ||||||
|  | 		{[]byte{128, 0, 188, 97, 78, 1, 96, 11, 128, 0}, 15, 14, "0.01234567890123", 8}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 188, 97, 78, 9, 128, 0}, 20, 10, "0.0123456789", 10}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 211, 128, 0}, 30, 5, "0.01235", 15}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 188, 97, 78, 53, 183, 191, 135, 89, 128, 0}, 30, 20, "0.01234567890123456789", 14}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 188, 97, 78, 53, 183, 191, 135, 0, 135, 253, 217, 30, 0}, 30, 25, "0.0123456789012345678912345", 15}, | ||||||
|  | 		{[]byte{227, 99, 128, 48}, 4, 2, "99.99", 2}, | ||||||
|  | 		{[]byte{128, 48, 57, 167, 15}, 5, 0, "12345.0", 3}, | ||||||
|  | 		{[]byte{167, 15, 3, 231, 128, 0}, 7, 3, "9999.999", 4}, | ||||||
|  | 		{[]byte{128, 0, 48, 57, 0, 128, 0}, 10, 2, "12345.0", 5}, | ||||||
|  | 		{[]byte{128, 0, 48, 57, 0, 0, 128, 0}, 10, 3, "12345.0", 6}, | ||||||
|  | 		{[]byte{128, 0, 0, 48, 57, 0, 137, 59}, 13, 2, "12345.0", 6}, | ||||||
|  | 		{[]byte{137, 59, 154, 201, 255, 1, 134, 159, 128, 0}, 15, 14, "9.99999999999999", 8}, | ||||||
|  | 		{[]byte{128, 0, 0, 48, 57, 0, 0, 0, 0, 0, 128, 0}, 20, 10, "12345.0", 10}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 57, 0, 0, 0, 128, 0}, 30, 5, "12345.0", 15}, | ||||||
|  | 		{[]byte{128, 0, 0, 48, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 48}, 30, 20, "12345.0", 14}, | ||||||
|  | 		{[]byte{128, 48, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0}, 30, 25, "12345.0", 15}, | ||||||
|  | 		{[]byte{227, 99, 128, 48}, 4, 2, "99.99", 2}, | ||||||
|  | 		{[]byte{128, 48, 57, 167, 15}, 5, 0, "12345.0", 3}, | ||||||
|  | 		{[]byte{167, 15, 3, 231, 128, 0}, 7, 3, "9999.999", 4}, | ||||||
|  | 		{[]byte{128, 0, 48, 57, 0, 128, 0}, 10, 2, "12345.0", 5}, | ||||||
|  | 		{[]byte{128, 0, 48, 57, 0, 0, 128, 0}, 10, 3, "12345.0", 6}, | ||||||
|  | 		{[]byte{128, 0, 0, 48, 57, 0, 137, 59}, 13, 2, "12345.0", 6}, | ||||||
|  | 		{[]byte{137, 59, 154, 201, 255, 1, 134, 159, 128, 0}, 15, 14, "9.99999999999999", 8}, | ||||||
|  | 		{[]byte{128, 0, 0, 48, 57, 0, 0, 0, 0, 0, 128, 0}, 20, 10, "12345.0", 10}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 57, 0, 0, 0, 128, 0}, 30, 5, "12345.0", 15}, | ||||||
|  | 		{[]byte{128, 0, 0, 48, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 48}, 30, 20, "12345.0", 14}, | ||||||
|  | 		{[]byte{128, 48, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0}, 30, 25, "12345.0", 15}, | ||||||
|  | 		{[]byte{227, 99, 128, 0}, 4, 2, "99.99", 2}, | ||||||
|  | 		{[]byte{128, 0, 123, 128, 123}, 5, 0, "123.0", 3}, | ||||||
|  | 		{[]byte{128, 123, 1, 194, 128, 0}, 7, 3, "123.45", 4}, | ||||||
|  | 		{[]byte{128, 0, 0, 123, 45, 128, 0}, 10, 2, "123.45", 5}, | ||||||
|  | 		{[]byte{128, 0, 0, 123, 1, 194, 128, 0}, 10, 3, "123.45", 6}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 123, 45, 137, 59}, 13, 2, "123.45", 6}, | ||||||
|  | 		{[]byte{137, 59, 154, 201, 255, 1, 134, 159, 128, 0}, 15, 14, "9.99999999999999", 8}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 123, 26, 210, 116, 128, 0, 128, 0}, 20, 10, "123.45", 10}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 175, 200, 128, 0}, 30, 5, "123.45", 15}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 123, 26, 210, 116, 128, 0, 0, 0, 0, 0, 128, 0}, 30, 20, "123.45", 14}, | ||||||
|  | 		{[]byte{128, 0, 123, 26, 210, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0}, 30, 25, "123.45", 15}, | ||||||
|  | 		{[]byte{28, 156, 127, 255}, 4, 2, "-99.99", 2}, | ||||||
|  | 		{[]byte{127, 255, 132, 127, 132}, 5, 0, "-123.0", 3}, | ||||||
|  | 		{[]byte{127, 132, 254, 61, 127, 255}, 7, 3, "-123.45", 4}, | ||||||
|  | 		{[]byte{127, 255, 255, 132, 210, 127, 255}, 10, 2, "-123.45", 5}, | ||||||
|  | 		{[]byte{127, 255, 255, 132, 254, 61, 127, 255}, 10, 3, "-123.45", 6}, | ||||||
|  | 		{[]byte{127, 255, 255, 255, 132, 210, 118, 196}, 13, 2, "-123.45", 6}, | ||||||
|  | 		{[]byte{118, 196, 101, 54, 0, 254, 121, 96, 127, 255}, 15, 14, "-9.99999999999999", 8}, | ||||||
|  | 		{[]byte{127, 255, 255, 255, 132, 229, 45, 139, 127, 255, 127, 255}, 20, 10, "-123.45", 10}, | ||||||
|  | 		{[]byte{127, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 132, 255, 80, 55, 127, 255}, 30, 5, "-123.45", 15}, | ||||||
|  | 		{[]byte{127, 255, 255, 255, 132, 229, 45, 139, 127, 255, 255, 255, 255, 255, 127, 255}, 30, 20, "-123.45", 14}, | ||||||
|  | 		{[]byte{127, 255, 132, 229, 45, 139, 127, 255, 255, 255, 255, 255, 255, 255, 255, 20, 0}, 30, 25, "-123.45", 15}, | ||||||
|  | 		{[]byte{128, 0, 128, 0}, 4, 2, "0.0", 2}, | ||||||
|  | 		{[]byte{128, 0, 0, 128, 0}, 5, 0, "0.0", 3}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 128, 0}, 7, 3, "0.0", 4}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 128, 0}, 10, 2, "0.0", 5}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 128, 0}, 10, 3, "0.0", 6}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 128, 0}, 13, 2, "0.0", 6}, | ||||||
|  | 		{[]byte{128, 0, 1, 226, 58, 0, 0, 99, 128, 0}, 15, 14, "0.00012345000099", 8}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 1, 226, 58, 0, 128, 0}, 20, 10, "0.00012345", 10}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 128, 0}, 30, 5, "0.00012", 15}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 1, 226, 58, 0, 15, 18, 2, 0, 128, 0}, 30, 20, "0.00012345000098765", 14}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 1, 226, 58, 0, 15, 18, 2, 0, 0, 0, 0, 15, 0}, 30, 25, "0.00012345000098765", 15}, | ||||||
|  | 		{[]byte{128, 0, 128, 0}, 4, 2, "0.0", 2}, | ||||||
|  | 		{[]byte{128, 0, 0, 128, 0}, 5, 0, "0.0", 3}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 128, 0}, 7, 3, "0.0", 4}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 128, 0}, 10, 2, "0.0", 5}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 128, 0}, 10, 3, "0.0", 6}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 128, 0}, 13, 2, "0.0", 6}, | ||||||
|  | 		{[]byte{128, 0, 1, 226, 58, 0, 0, 99, 128, 0}, 15, 14, "0.00012345000099", 8}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 1, 226, 58, 0, 128, 0}, 20, 10, "0.00012345", 10}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 128, 0}, 30, 5, "0.00012", 15}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 1, 226, 58, 0, 15, 18, 2, 0, 128, 0}, 30, 20, "0.00012345000098765", 14}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 1, 226, 58, 0, 15, 18, 2, 0, 0, 0, 0, 22, 0}, 30, 25, "0.00012345000098765", 15}, | ||||||
|  | 		{[]byte{128, 12, 128, 0}, 4, 2, "0.12", 2}, | ||||||
|  | 		{[]byte{128, 0, 0, 128, 0}, 5, 0, "0.0", 3}, | ||||||
|  | 		{[]byte{128, 0, 0, 123, 128, 0}, 7, 3, "0.123", 4}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 12, 128, 0}, 10, 2, "0.12", 5}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 123, 128, 0}, 10, 3, "0.123", 6}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 12, 128, 7}, 13, 2, "0.12", 6}, | ||||||
|  | 		{[]byte{128, 7, 91, 178, 144, 1, 129, 205, 128, 0}, 15, 14, "0.12345000098765", 8}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 7, 91, 178, 145, 0, 128, 0}, 20, 10, "0.123450001", 10}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 57, 128, 0}, 30, 5, "0.12345", 15}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 7, 91, 178, 144, 58, 222, 87, 208, 0, 128, 0}, 30, 20, "0.12345000098765", 14}, | ||||||
|  | 		{[]byte{128, 0, 0, 7, 91, 178, 144, 58, 222, 87, 208, 0, 0, 0, 0, 30, 0}, 30, 25, "0.12345000098765", 15}, | ||||||
|  | 		{[]byte{128, 0, 128, 0}, 4, 2, "0.0", 2}, | ||||||
|  | 		{[]byte{128, 0, 0, 128, 0}, 5, 0, "0.0", 3}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 128, 0}, 7, 3, "0.0", 4}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 128, 0}, 10, 2, "0.0", 5}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 128, 0}, 10, 3, "0.0", 6}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 127, 255}, 13, 2, "0.0", 6}, | ||||||
|  | 		{[]byte{127, 255, 255, 255, 243, 255, 121, 59, 127, 255}, 15, 14, "-0.000000012345", 8}, | ||||||
|  | 		{[]byte{127, 255, 255, 255, 255, 255, 255, 255, 243, 252, 128, 0}, 20, 10, "-0.0000000123", 10}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255}, 30, 5, "0.0", 15}, | ||||||
|  | 		{[]byte{127, 255, 255, 255, 255, 255, 255, 255, 243, 235, 111, 183, 93, 178, 127, 255}, 30, 20, "-0.00000001234500009877", 14}, | ||||||
|  | 		{[]byte{127, 255, 255, 255, 255, 255, 243, 235, 111, 183, 93, 255, 139, 69, 47, 30, 0}, 30, 25, "-0.000000012345000098765", 15}, | ||||||
|  | 		{[]byte{227, 99, 129, 134}, 4, 2, "99.99", 2}, | ||||||
|  | 		{[]byte{129, 134, 159, 167, 15}, 5, 0, "99999.0", 3}, | ||||||
|  | 		{[]byte{167, 15, 3, 231, 133, 245}, 7, 3, "9999.999", 4}, | ||||||
|  | 		{[]byte{133, 245, 224, 255, 99, 128, 152}, 10, 2, "99999999.99", 5}, | ||||||
|  | 		{[]byte{128, 152, 150, 127, 3, 231, 227, 59}, 10, 3, "9999999.999", 6}, | ||||||
|  | 		{[]byte{227, 59, 154, 201, 255, 99, 137, 59}, 13, 2, "99999999999.99", 6}, | ||||||
|  | 		{[]byte{137, 59, 154, 201, 255, 1, 134, 159, 137, 59}, 15, 14, "9.99999999999999", 8}, | ||||||
|  | 		{[]byte{137, 59, 154, 201, 255, 59, 154, 201, 255, 9, 128, 0}, 20, 10, "9999999999.9999999999", 10}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 4, 210, 29, 205, 139, 148, 0, 195, 80, 137, 59}, 30, 5, "1234500009876.5", 15}, | ||||||
|  | 		{[]byte{137, 59, 154, 201, 255, 59, 154, 201, 255, 59, 154, 201, 255, 99, 129, 134}, 30, 20, "9999999999.99999999999999999999", 14}, | ||||||
|  | 		{[]byte{129, 134, 159, 59, 154, 201, 255, 59, 154, 201, 255, 0, 152, 150, 127, 30, 0}, 30, 25, "99999.9999999999999999999999999", 15}, | ||||||
|  | 		{[]byte{227, 99, 129, 134}, 4, 2, "99.99", 2}, | ||||||
|  | 		{[]byte{129, 134, 159, 167, 15}, 5, 0, "99999.0", 3}, | ||||||
|  | 		{[]byte{167, 15, 3, 231, 133, 245}, 7, 3, "9999.999", 4}, | ||||||
|  | 		{[]byte{133, 245, 224, 255, 99, 128, 152}, 10, 2, "99999999.99", 5}, | ||||||
|  | 		{[]byte{128, 152, 150, 127, 3, 231, 128, 6}, 10, 3, "9999999.999", 6}, | ||||||
|  | 		{[]byte{128, 6, 159, 107, 199, 11, 137, 59}, 13, 2, "111111111.11", 6}, | ||||||
|  | 		{[]byte{137, 59, 154, 201, 255, 1, 134, 159, 128, 6}, 15, 14, "9.99999999999999", 8}, | ||||||
|  | 		{[]byte{128, 6, 159, 107, 199, 6, 142, 119, 128, 0, 128, 0}, 20, 10, "111111111.11", 10}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 0, 0, 6, 159, 107, 199, 0, 42, 248, 128, 6}, 30, 5, "111111111.11", 15}, | ||||||
|  | 		{[]byte{128, 6, 159, 107, 199, 6, 142, 119, 128, 0, 0, 0, 0, 0, 129, 134}, 30, 20, "111111111.11", 14}, | ||||||
|  | 		{[]byte{129, 134, 159, 59, 154, 201, 255, 59, 154, 201, 255, 0, 152, 150, 127, 10, 0}, 30, 25, "99999.9999999999999999999999999", 15}, | ||||||
|  | 		{[]byte{128, 1, 128, 0}, 4, 2, "0.01", 2}, | ||||||
|  | 		{[]byte{128, 0, 0, 128, 0}, 5, 0, "0.0", 3}, | ||||||
|  | 		{[]byte{128, 0, 0, 10, 128, 0}, 7, 3, "0.01", 4}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 1, 128, 0}, 10, 2, "0.01", 5}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 10, 128, 0}, 10, 3, "0.01", 6}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 1, 128, 0}, 13, 2, "0.01", 6}, | ||||||
|  | 		{[]byte{128, 0, 152, 150, 128, 0, 0, 0, 128, 0}, 15, 14, "0.01", 8}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 152, 150, 128, 0, 128, 0}, 20, 10, "0.01", 10}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 232, 128, 0}, 30, 5, "0.01", 15}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 152, 150, 128, 0, 0, 0, 0, 0, 128, 0}, 30, 20, "0.01", 14}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 152, 150, 128, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0}, 30, 25, "0.01", 15}, | ||||||
|  | 		{[]byte{227, 99, 128, 0}, 4, 2, "99.99", 2}, | ||||||
|  | 		{[]byte{128, 0, 123, 128, 123}, 5, 0, "123.0", 3}, | ||||||
|  | 		{[]byte{128, 123, 1, 144, 128, 0}, 7, 3, "123.4", 4}, | ||||||
|  | 		{[]byte{128, 0, 0, 123, 40, 128, 0}, 10, 2, "123.4", 5}, | ||||||
|  | 		{[]byte{128, 0, 0, 123, 1, 144, 128, 0}, 10, 3, "123.4", 6}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 123, 40, 137, 59}, 13, 2, "123.4", 6}, | ||||||
|  | 		{[]byte{137, 59, 154, 201, 255, 1, 134, 159, 128, 0}, 15, 14, "9.99999999999999", 8}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 123, 23, 215, 132, 0, 0, 128, 0}, 20, 10, "123.4", 10}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 156, 64, 128, 0}, 30, 5, "123.4", 15}, | ||||||
|  | 		{[]byte{128, 0, 0, 0, 123, 23, 215, 132, 0, 0, 0, 0, 0, 0, 128, 0}, 30, 20, "123.4", 14}, | ||||||
|  | 		{[]byte{128, 0, 123, 23, 215, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0}, 30, 25, "123.4", 15}, | ||||||
|  | 		{[]byte{28, 156, 127, 253}, 4, 2, "-99.99", 2}, | ||||||
|  | 		{[]byte{127, 253, 204, 125, 205}, 5, 0, "-563.0", 3}, | ||||||
|  | 		{[]byte{125, 205, 253, 187, 127, 255}, 7, 3, "-562.58", 4}, | ||||||
|  | 		{[]byte{127, 255, 253, 205, 197, 127, 255}, 10, 2, "-562.58", 5}, | ||||||
|  | 		{[]byte{127, 255, 253, 205, 253, 187, 127, 255}, 10, 3, "-562.58", 6}, | ||||||
|  | 		{[]byte{127, 255, 255, 253, 205, 197, 118, 196}, 13, 2, "-562.58", 6}, | ||||||
|  | 		{[]byte{118, 196, 101, 54, 0, 254, 121, 96, 127, 255}, 15, 14, "-9.99999999999999", 8}, | ||||||
|  | 		{[]byte{127, 255, 255, 253, 205, 221, 109, 230, 255, 255, 127, 255}, 20, 10, "-562.58", 10}, | ||||||
|  | 		{[]byte{127, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 205, 255, 29, 111, 127, 255}, 30, 5, "-562.58", 15}, | ||||||
|  | 		{[]byte{127, 255, 255, 253, 205, 221, 109, 230, 255, 255, 255, 255, 255, 255, 127, 253}, 30, 20, "-562.58", 14}, | ||||||
|  | 		{[]byte{127, 253, 205, 221, 109, 230, 255, 255, 255, 255, 255, 255, 255, 255, 255, 13, 0}, 30, 25, "-562.58", 15}, | ||||||
|  | 		{[]byte{28, 156, 127, 241}, 4, 2, "-99.99", 2}, | ||||||
|  | 		{[]byte{127, 241, 140, 113, 140}, 5, 0, "-3699.0", 3}, | ||||||
|  | 		{[]byte{113, 140, 255, 245, 127, 255}, 7, 3, "-3699.01", 4}, | ||||||
|  | 		{[]byte{127, 255, 241, 140, 254, 127, 255}, 10, 2, "-3699.01", 5}, | ||||||
|  | 		{[]byte{127, 255, 241, 140, 255, 245, 127, 255}, 10, 3, "-3699.01", 6}, | ||||||
|  | 		{[]byte{127, 255, 255, 241, 140, 254, 118, 196}, 13, 2, "-3699.01", 6}, | ||||||
|  | 		{[]byte{118, 196, 101, 54, 0, 254, 121, 96, 127, 255}, 15, 14, "-9.99999999999999", 8}, | ||||||
|  | 		{[]byte{127, 255, 255, 241, 140, 255, 103, 105, 127, 255, 127, 255}, 20, 10, "-3699.01", 10}, | ||||||
|  | 		{[]byte{127, 255, 255, 255, 255, 255, 255, 255, 255, 255, 241, 140, 255, 252, 23, 127, 255}, 30, 5, "-3699.01", 15}, | ||||||
|  | 		{[]byte{127, 255, 255, 241, 140, 255, 103, 105, 127, 255, 255, 255, 255, 255, 127, 241}, 30, 20, "-3699.01", 14}, | ||||||
|  | 		{[]byte{127, 241, 140, 255, 103, 105, 127, 255, 255, 255, 255, 255, 255, 255, 255, 13, 0}, 30, 25, "-3699.01", 15}, | ||||||
|  | 		{[]byte{28, 156, 127, 248}, 4, 2, "-99.99", 2}, | ||||||
|  | 		{[]byte{127, 248, 99, 120, 99}, 5, 0, "-1948.0", 3}, | ||||||
|  | 		{[]byte{120, 99, 255, 115, 127, 255}, 7, 3, "-1948.14", 4}, | ||||||
|  | 		{[]byte{127, 255, 248, 99, 241, 127, 255}, 10, 2, "-1948.14", 5}, | ||||||
|  | 		{[]byte{127, 255, 248, 99, 255, 115, 127, 255}, 10, 3, "-1948.14", 6}, | ||||||
|  | 		{[]byte{127, 255, 255, 248, 99, 241, 118, 196}, 13, 2, "-1948.14", 6}, | ||||||
|  | 		{[]byte{118, 196, 101, 54, 0, 254, 121, 96, 127, 255}, 15, 14, "-9.99999999999999", 8}, | ||||||
|  | 		{[]byte{127, 255, 255, 248, 99, 247, 167, 196, 255, 255, 127, 255}, 20, 10, "-1948.14", 10}, | ||||||
|  | 		{[]byte{127, 255, 255, 255, 255, 255, 255, 255, 255, 255, 248, 99, 255, 201, 79, 127, 255}, 30, 5, "-1948.14", 15}, | ||||||
|  | 		{[]byte{127, 255, 255, 248, 99, 247, 167, 196, 255, 255, 255, 255, 255, 255, 127, 248}, 30, 20, "-1948.14", 14}, | ||||||
|  | 		{[]byte{127, 248, 99, 247, 167, 196, 255, 255, 255, 255, 255, 255, 255, 255, 255, 13, 0}, 30, 25, "-1948.14", 15}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, tc := range testcases { | ||||||
|  | 		d, size := DecodeDecimal(tc.Data, tc.Precision, tc.Decimals) | ||||||
|  | 		b, err := json.Marshal(d) | ||||||
|  | 		if err != nil { | ||||||
|  | 			t.Fatalf("Unexpected error (exp: %q): %v", tc.Expected, err) | ||||||
|  | 		} | ||||||
|  | 		out := string(b) | ||||||
|  | 		if tc.Expected != out { | ||||||
|  | 			t.Errorf("Expected %s, got %s", tc.Expected, out) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if tc.ExpectedPos != size { | ||||||
|  | 			t.Errorf("Expected %d bytes, got %d", tc.ExpectedPos, size) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -19,8 +19,8 @@ func TestDecimal(t *testing.T) { | |||||||
| 			"99.9", | 			"99.9", | ||||||
| 		}, | 		}, | ||||||
| 		"6,2": { | 		"6,2": { | ||||||
| 			"0.00", | 			"0.0", | ||||||
| 			"1.00", | 			"1.0", | ||||||
| 			"1.33", | 			"1.33", | ||||||
| 			"10.16", | 			"10.16", | ||||||
| 			"620.99", | 			"620.99", | ||||||
| @ -28,18 +28,17 @@ func TestDecimal(t *testing.T) { | |||||||
| 			"9999.99", | 			"9999.99", | ||||||
| 		}, | 		}, | ||||||
| 		"10,4": { | 		"10,4": { | ||||||
| 			"0.0000", | 			"0.0", | ||||||
| 			"1.0001", | 			"1.0001", | ||||||
| 			"1.3301", | 			"1.3301", | ||||||
| 			"10.1600", | 			"10.16", | ||||||
| 			"620.9999", | 			"620.9999", | ||||||
| 			"500000.0001", | 			"500000.0001", | ||||||
| 			"999999.9999", | 			"999999.9999", | ||||||
| 		}, | 		}, | ||||||
| 		"30,10": { | 		"30,10": { | ||||||
| 			// NOTE: At certain length there's undesired zero fill :/ | 			"0.0", | ||||||
| 			"0000000000000000000.0000000000", | 			"1.0000000001", | ||||||
| 			"0000000000000000001.0000000001", |  | ||||||
| 			"99999999999999999999.9999999999", | 			"99999999999999999999.9999999999", | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| @ -51,11 +50,11 @@ func TestDecimal(t *testing.T) { | |||||||
| 
 | 
 | ||||||
| 			for _, v := range vals { | 			for _, v := range vals { | ||||||
| 				t.Run(v, func(t *testing.T) { | 				t.Run(v, func(t *testing.T) { | ||||||
| 					suite.insertAndCompare(t, tbl, v) | 					suite.insertAndCompare(t, tbl, mysql.NewDecimal(v)) | ||||||
| 				}) | 				}) | ||||||
| 				if !strings.HasPrefix(v, "0") { | 				if !strings.HasPrefix(v, "0") { | ||||||
| 					t.Run("-"+v, func(t *testing.T) { | 					t.Run("-"+v, func(t *testing.T) { | ||||||
| 						suite.insertAndCompare(t, tbl, "-"+v) | 						suite.insertAndCompare(t, tbl, mysql.NewDecimal("-"+v)) | ||||||
| 					}) | 					}) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ package tests | |||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
|  | 	"context" | ||||||
| 	"database/sql" | 	"database/sql" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| @ -201,9 +202,10 @@ func (s *testSuite) insertAndCompareExp(t *testing.T, tbl *table, vals, exps []i | |||||||
| func (s *testSuite) expectValue(t *testing.T, tbl *table, exp []interface{}) { | func (s *testSuite) expectValue(t *testing.T, tbl *table, exp []interface{}) { | ||||||
| 	t.Helper() | 	t.Helper() | ||||||
| 	out := make(chan []interface{}) | 	out := make(chan []interface{}) | ||||||
|  | 	ctx := context.Background() | ||||||
| 	go func() { | 	go func() { | ||||||
| 		for { | 		for { | ||||||
| 			evt, err := suite.reader.ReadEvent() | 			evt, err := suite.reader.ReadEvent(ctx) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				t.Errorf("Failed to read event: %v", err) | 				t.Errorf("Failed to read event: %v", err) | ||||||
| 				return | 				return | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user