Skip to content

Commit

Permalink
feat(client): replace long256 string with big.Int (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
jammutkarsh authored Jan 6, 2023
1 parent 576423f commit bb06b09
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 18 deletions.
37 changes: 30 additions & 7 deletions sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,15 +325,28 @@ func (s *LineSender) Int64Column(name string, val int64) *LineSender {

// Long256Column adds a 256-bit unsigned integer (long256) column
// value to the ILP message.
//
// val should contain a hex encoded 256-bit unsigned integer value
// with "0x" prefix and "i" suffix. Any attempt to set a string which is
// not a hexadecimal will not be parsed and rejected by the database.
//
//
// Only non-negative numbers that fit into 256-bit unsigned integer are
// supported and any other input value would lead to an error.
//
// Column name cannot contain any of the following characters:
// '\n', '\r', '?', '.', ',', ”', '"', '\\', '/', ':', ')', '(', '+',
// '-', '*' '%%', '~', or a non-printable char.
func (s *LineSender) Long256Column(name, val string) *LineSender {
func (s *LineSender) Long256Column(name string, val *big.Int) *LineSender {
if val.Sign() < 0 {
if s.lastErr != nil {
return s
}
s.lastErr = fmt.Errorf("long256 cannot be negative: %s", val.String())
return s
}
if val.BitLen() > 256 {
if s.lastErr != nil {
return s
}
s.lastErr = fmt.Errorf("long256 cannot be larger than 256-bit: %v", val.BitLen())
return s
}
if !s.prepareForField(name) {
return s
}
Expand All @@ -342,7 +355,10 @@ func (s *LineSender) Long256Column(name, val string) *LineSender {
return s
}
s.buf.WriteByte('=')
s.lastErr = s.writeStrValue(val, false)
s.buf.WriteByte('0')
s.buf.WriteByte('x')
s.buf.WriteBigInt(val)
s.buf.WriteByte('i')
if s.lastErr != nil {
return s
}
Expand Down Expand Up @@ -828,3 +844,10 @@ func (b *buffer) WriteFloat(f float64) {
s := strconv.AppendFloat(a[0:0], f, 'G', -1, 64)
b.Write(s)
}

func (b *buffer) WriteBigInt(i *big.Int) {
// We need up to 64 bytes to fit an unsigned 256-bit number.
var a [64]byte
s := i.Append(a[0:0], 16)
b.Write(s)
}
14 changes: 9 additions & 5 deletions sender_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
"math/big"
"net/http"
"net/url"
"path/filepath"
Expand Down Expand Up @@ -231,12 +232,13 @@ func TestE2EValidWrites(t *testing.T) {
"all column types",
testTable,
func(s *qdb.LineSender) error {
val, _ := big.NewInt(0).SetString("123a4", 16)
err := s.
Table(testTable).
Symbol("sym_col", "test_ilp1").
Float64Column("double_col", 12.2).
Int64Column("long_col", 12).
Long256Column("long256_col", "0x123a4i").
Long256Column("long256_col", val).
StringColumn("str_col", "foobar").
BoolColumn("bool_col", true).
TimestampColumn("timestamp_col", 42).
Expand All @@ -245,12 +247,13 @@ func TestE2EValidWrites(t *testing.T) {
return err
}

val, _ = big.NewInt(0).SetString("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)
return s.
Table(testTable).
Symbol("sym_col", "test_ilp2").
Float64Column("double_col", 11.2).
Int64Column("long_col", 11).
Long256Column("long256_col", "0x123a3i").
Long256Column("long256_col", val).
StringColumn("str_col", "barbaz").
BoolColumn("bool_col", false).
TimestampColumn("timestamp_col", 43).
Expand All @@ -269,7 +272,7 @@ func TestE2EValidWrites(t *testing.T) {
},
Dataset: [][]interface{}{
{"test_ilp1", float64(12.2), float64(12), "0x0123a4", "foobar", true, "1970-01-01T00:00:00.000042Z", "1970-01-01T00:00:00.000001Z"},
{"test_ilp2", float64(11.2), float64(11), "0x0123a3", "barbaz", false, "1970-01-01T00:00:00.000043Z", "1970-01-01T00:00:00.000002Z"},
{"test_ilp2", float64(11.2), float64(11), "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "barbaz", false, "1970-01-01T00:00:00.000043Z", "1970-01-01T00:00:00.000002Z"},
},
Count: 2,
},
Expand Down Expand Up @@ -340,9 +343,10 @@ func TestE2EValidWrites(t *testing.T) {
"single column long256",
testTable,
func(s *qdb.LineSender) error {
val, _ := big.NewInt(0).SetString("7fffffffffffffff", 16)
return s.
Table(testTable).
Long256Column("foobar", "0x123a4i").
Long256Column("foobar", val).
At(ctx, 42000)
},
tableData{
Expand All @@ -351,7 +355,7 @@ func TestE2EValidWrites(t *testing.T) {
{"timestamp", "TIMESTAMP"},
},
Dataset: [][]interface{}{
{"0x0123a4", "1970-01-01T00:00:00.000042Z"},
{"0x7fffffffffffffff", "1970-01-01T00:00:00.000042Z"},
},
Count: 1,
},
Expand Down
49 changes: 43 additions & 6 deletions sender_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"io/ioutil"
"log"
"math"
"math/big"
"net"
"reflect"
"strconv"
Expand Down Expand Up @@ -192,11 +193,11 @@ func TestLong256Column(t *testing.T) {
val string
expected string
}{
{"random bits ", "0x0123a4i", "0x0123a4"},
{"8bit max", "0xffffffffi", "0xffffffff"},
{"16bit max", "0xffffffffffffffffi", "0xffffffffffffffff"},
{"32bit max", "0xffffffffffffffffffffffffffffffffi", "0xffffffffffffffffffffffffffffffff"},
{"64bit long", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffi", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
{"zero", "0", "0x0"},
{"one", "1", "0x1"},
{"32-bit max", strconv.FormatInt(math.MaxInt32, 16), "0x7fffffff"},
{"64-bit random", strconv.FormatInt(7423093023234231, 16), "0x1a5f4386c8d8b7"},
{"256-bit max", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
}

for _, tc := range testCases {
Expand All @@ -207,7 +208,8 @@ func TestLong256Column(t *testing.T) {
sender, err := qdb.NewLineSender(ctx, qdb.WithAddress(srv.addr))
assert.NoError(t, err)

err = sender.Table(testTable).Long256Column("a_col", tc.val).AtNow(ctx)
newVal, _ := big.NewInt(0).SetString(tc.val, 16)
err = sender.Table(testTable).Long256Column("a_col", newVal).AtNow(ctx)
assert.NoError(t, err)

err = sender.Flush(ctx)
Expand Down Expand Up @@ -424,6 +426,41 @@ func TestErrorOnNegativeTimestamp(t *testing.T) {
assert.Empty(t, sender.Messages())
}

func TestErrorOnNegativeLong256(t *testing.T) {
ctx := context.Background()

srv, err := newTestServer(readAndDiscard)
assert.NoError(t, err)
defer srv.close()

sender, err := qdb.NewLineSender(ctx, qdb.WithAddress(srv.addr))
assert.NoError(t, err)
defer sender.Close()

err = sender.Table(testTable).Long256Column("long256_col", big.NewInt(-42)).AtNow(ctx)

assert.ErrorContains(t, err, "long256 cannot be negative: -42")
assert.Empty(t, sender.Messages())
}

func TestErrorOnLargerLong256(t *testing.T) {
ctx := context.Background()

srv, err := newTestServer(readAndDiscard)
assert.NoError(t, err)
defer srv.close()

sender, err := qdb.NewLineSender(ctx, qdb.WithAddress(srv.addr))
assert.NoError(t, err)
defer sender.Close()

bigVal, _ := big.NewInt(0).SetString("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)
err = sender.Table(testTable).Long256Column("long256_col", bigVal).AtNow(ctx)

assert.ErrorContains(t, err, "long256 cannot be larger than 256-bit: 260")
assert.Empty(t, sender.Messages())
}

func TestErrorOnSymbolCallAfterColumn(t *testing.T) {
ctx := context.Background()

Expand Down

0 comments on commit bb06b09

Please sign in to comment.