github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/sqlbase/encoded_datum_test.go (about)

     1  // Copyright 2016 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package sqlbase
    12  
    13  import (
    14  	"context"
    15  	"testing"
    16  	"time"
    17  	"unsafe"
    18  
    19  	"github.com/cockroachdb/apd"
    20  	"github.com/cockroachdb/cockroach/pkg/settings/cluster"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    22  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    23  	"github.com/cockroachdb/cockroach/pkg/util/encoding"
    24  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    25  	"github.com/cockroachdb/cockroach/pkg/util/randutil"
    26  )
    27  
    28  func TestEncDatum(t *testing.T) {
    29  	defer leaktest.AfterTest(t)()
    30  
    31  	a := &DatumAlloc{}
    32  	evalCtx := tree.NewTestingEvalContext(cluster.MakeTestingClusterSettings())
    33  	defer evalCtx.Stop(context.Background())
    34  	v := EncDatum{}
    35  	if !v.IsUnset() {
    36  		t.Errorf("empty EncDatum should be unset")
    37  	}
    38  
    39  	if _, ok := v.Encoding(); ok {
    40  		t.Errorf("empty EncDatum has an encoding")
    41  	}
    42  
    43  	x := DatumToEncDatum(types.Int, tree.NewDInt(5))
    44  
    45  	check := func(x EncDatum) {
    46  		if x.IsUnset() {
    47  			t.Errorf("unset after DatumToEncDatum()")
    48  		}
    49  		if x.IsNull() {
    50  			t.Errorf("null after DatumToEncDatum()")
    51  		}
    52  		if val, err := x.GetInt(); err != nil {
    53  			t.Fatal(err)
    54  		} else if val != 5 {
    55  			t.Errorf("GetInt returned %d", val)
    56  		}
    57  	}
    58  	check(x)
    59  
    60  	encoded, err := x.Encode(types.Int, a, DatumEncoding_ASCENDING_KEY, nil)
    61  	if err != nil {
    62  		t.Fatal(err)
    63  	}
    64  
    65  	y := EncDatumFromEncoded(DatumEncoding_ASCENDING_KEY, encoded)
    66  	check(y)
    67  
    68  	if enc, ok := y.Encoding(); !ok {
    69  		t.Error("no encoding after EncDatumFromEncoded")
    70  	} else if enc != DatumEncoding_ASCENDING_KEY {
    71  		t.Errorf("invalid encoding %d", enc)
    72  	}
    73  	err = y.EnsureDecoded(types.Int, a)
    74  	if err != nil {
    75  		t.Fatal(err)
    76  	}
    77  	if cmp := y.Datum.Compare(evalCtx, x.Datum); cmp != 0 {
    78  		t.Errorf("Datums should be equal, cmp = %d", cmp)
    79  	}
    80  
    81  	enc2, err := y.Encode(types.Int, a, DatumEncoding_DESCENDING_KEY, nil)
    82  	if err != nil {
    83  		t.Fatal(err)
    84  	}
    85  	// y's encoding should not change.
    86  	if enc, ok := y.Encoding(); !ok {
    87  		t.Error("no encoding")
    88  	} else if enc != DatumEncoding_ASCENDING_KEY {
    89  		t.Errorf("invalid encoding %d", enc)
    90  	}
    91  	z := EncDatumFromEncoded(DatumEncoding_DESCENDING_KEY, enc2)
    92  	if enc, ok := z.Encoding(); !ok {
    93  		t.Error("no encoding")
    94  	} else if enc != DatumEncoding_DESCENDING_KEY {
    95  		t.Errorf("invalid encoding %d", enc)
    96  	}
    97  	check(z)
    98  
    99  	err = z.EnsureDecoded(types.Int, a)
   100  	if err != nil {
   101  		t.Fatal(err)
   102  	}
   103  	if cmp := y.Datum.Compare(evalCtx, z.Datum); cmp != 0 {
   104  		t.Errorf("Datums should be equal, cmp = %d", cmp)
   105  	}
   106  	y.UnsetDatum()
   107  	if !y.IsUnset() {
   108  		t.Error("not unset after UnsetDatum()")
   109  	}
   110  }
   111  
   112  func columnTypeCompatibleWithEncoding(typ *types.T, enc DatumEncoding) bool {
   113  	return enc == DatumEncoding_VALUE || ColumnTypeIsIndexable(typ)
   114  }
   115  
   116  func TestEncDatumNull(t *testing.T) {
   117  	defer leaktest.AfterTest(t)()
   118  
   119  	// Verify DNull is null.
   120  	n := DatumToEncDatum(types.Int, tree.DNull)
   121  	if !n.IsNull() {
   122  		t.Error("DNull not null")
   123  	}
   124  
   125  	var alloc DatumAlloc
   126  	rng, _ := randutil.NewPseudoRand()
   127  
   128  	// Generate random EncDatums (some of which are null), and verify that a datum
   129  	// created from its encoding has the same IsNull() value.
   130  	for cases := 0; cases < 100; cases++ {
   131  		a, typ := RandEncDatum(rng)
   132  		for enc := range DatumEncoding_name {
   133  			if !columnTypeCompatibleWithEncoding(typ, DatumEncoding(enc)) {
   134  				continue
   135  			}
   136  			encoded, err := a.Encode(typ, &alloc, DatumEncoding(enc), nil)
   137  			if err != nil {
   138  				t.Fatal(err)
   139  			}
   140  			b := EncDatumFromEncoded(DatumEncoding(enc), encoded)
   141  			if a.IsNull() != b.IsNull() {
   142  				t.Errorf("before: %s (null=%t) after: %s (null=%t)",
   143  					a.String(types.Int), a.IsNull(), b.String(types.Int), b.IsNull())
   144  			}
   145  		}
   146  	}
   147  
   148  }
   149  
   150  // checkEncDatumCmp encodes the given values using the given encodings,
   151  // creates EncDatums from those encodings and verifies the Compare result on
   152  // those encodings. It also checks if the Compare resulted in decoding or not.
   153  func checkEncDatumCmp(
   154  	t *testing.T,
   155  	a *DatumAlloc,
   156  	typ *types.T,
   157  	v1, v2 *EncDatum,
   158  	enc1, enc2 DatumEncoding,
   159  	expectedCmp int,
   160  	requiresDecode bool,
   161  ) {
   162  	buf1, err := v1.Encode(typ, a, enc1, nil)
   163  	if err != nil {
   164  		t.Fatal(err)
   165  	}
   166  	buf2, err := v2.Encode(typ, a, enc2, nil)
   167  	if err != nil {
   168  		t.Fatal(err)
   169  	}
   170  	dec1 := EncDatumFromEncoded(enc1, buf1)
   171  
   172  	dec2 := EncDatumFromEncoded(enc2, buf2)
   173  
   174  	evalCtx := tree.NewTestingEvalContext(cluster.MakeTestingClusterSettings())
   175  	defer evalCtx.Stop(context.Background())
   176  	if val, err := dec1.Compare(typ, a, evalCtx, &dec2); err != nil {
   177  		t.Fatal(err)
   178  	} else if val != expectedCmp {
   179  		t.Errorf("comparing %s (%s), %s (%s) resulted in %d, expected %d",
   180  			v1.String(typ), enc1, v2.String(typ), enc2, val, expectedCmp,
   181  		)
   182  	}
   183  
   184  	if requiresDecode {
   185  		if dec1.Datum == nil || dec2.Datum == nil {
   186  			t.Errorf(
   187  				"comparing %s (%s), %s (%s) did not require decoding",
   188  				v1.String(typ), enc1, v2.String(typ), enc2,
   189  			)
   190  		}
   191  	} else {
   192  		if dec1.Datum != nil || dec2.Datum != nil {
   193  			t.Errorf(
   194  				"comparing %s (%s), %s (%s) required decoding",
   195  				v1.String(typ), enc1, v2.String(typ), enc2,
   196  			)
   197  		}
   198  	}
   199  }
   200  
   201  func TestEncDatumCompare(t *testing.T) {
   202  	defer leaktest.AfterTest(t)()
   203  
   204  	a := &DatumAlloc{}
   205  	evalCtx := tree.NewTestingEvalContext(cluster.MakeTestingClusterSettings())
   206  	defer evalCtx.Stop(context.Background())
   207  	rng, _ := randutil.NewPseudoRand()
   208  
   209  	for _, typ := range types.OidToType {
   210  		switch typ.Family() {
   211  		case types.AnyFamily, types.UnknownFamily, types.ArrayFamily, types.JsonFamily, types.TupleFamily, types.GeometryFamily, types.GeographyFamily:
   212  			continue
   213  		case types.CollatedStringFamily:
   214  			typ = types.MakeCollatedString(types.String, *RandCollationLocale(rng))
   215  		}
   216  
   217  		// Generate two datums d1 < d2
   218  		var d1, d2 tree.Datum
   219  		for {
   220  			d1 = RandDatum(rng, typ, false)
   221  			d2 = RandDatum(rng, typ, false)
   222  			if cmp := d1.Compare(evalCtx, d2); cmp < 0 {
   223  				break
   224  			}
   225  		}
   226  		v1 := DatumToEncDatum(typ, d1)
   227  		v2 := DatumToEncDatum(typ, d2)
   228  
   229  		if val, err := v1.Compare(typ, a, evalCtx, &v2); err != nil {
   230  			t.Fatal(err)
   231  		} else if val != -1 {
   232  			t.Errorf("compare(1, 2) = %d", val)
   233  		}
   234  
   235  		asc := DatumEncoding_ASCENDING_KEY
   236  		desc := DatumEncoding_DESCENDING_KEY
   237  		noncmp := DatumEncoding_VALUE
   238  
   239  		checkEncDatumCmp(t, a, typ, &v1, &v2, asc, asc, -1, false)
   240  		checkEncDatumCmp(t, a, typ, &v2, &v1, asc, asc, +1, false)
   241  		checkEncDatumCmp(t, a, typ, &v1, &v1, asc, asc, 0, false)
   242  		checkEncDatumCmp(t, a, typ, &v2, &v2, asc, asc, 0, false)
   243  
   244  		checkEncDatumCmp(t, a, typ, &v1, &v2, desc, desc, -1, false)
   245  		checkEncDatumCmp(t, a, typ, &v2, &v1, desc, desc, +1, false)
   246  		checkEncDatumCmp(t, a, typ, &v1, &v1, desc, desc, 0, false)
   247  		checkEncDatumCmp(t, a, typ, &v2, &v2, desc, desc, 0, false)
   248  
   249  		// These cases require decoding. Data with a composite key encoding cannot
   250  		// be decoded from their key part alone.
   251  		if !HasCompositeKeyEncoding(typ) {
   252  			checkEncDatumCmp(t, a, typ, &v1, &v2, noncmp, noncmp, -1, true)
   253  			checkEncDatumCmp(t, a, typ, &v2, &v1, desc, noncmp, +1, true)
   254  			checkEncDatumCmp(t, a, typ, &v1, &v1, asc, desc, 0, true)
   255  			checkEncDatumCmp(t, a, typ, &v2, &v2, desc, asc, 0, true)
   256  		}
   257  	}
   258  }
   259  
   260  func TestEncDatumFromBuffer(t *testing.T) {
   261  	defer leaktest.AfterTest(t)()
   262  
   263  	var alloc DatumAlloc
   264  	evalCtx := tree.NewTestingEvalContext(cluster.MakeTestingClusterSettings())
   265  	defer evalCtx.Stop(context.Background())
   266  	rng, _ := randutil.NewPseudoRand()
   267  	for test := 0; test < 20; test++ {
   268  		var err error
   269  		// Generate a set of random datums.
   270  		ed := make([]EncDatum, 1+rng.Intn(10))
   271  		typs := make([]*types.T, len(ed))
   272  		for i := range ed {
   273  			d, t := RandEncDatum(rng)
   274  			ed[i], typs[i] = d, t
   275  		}
   276  		// Encode them in a single buffer.
   277  		var buf []byte
   278  		enc := make([]DatumEncoding, len(ed))
   279  		for i := range ed {
   280  			if HasCompositeKeyEncoding(typs[i]) {
   281  				// There's no way to reconstruct data from the key part of a composite
   282  				// encoding.
   283  				enc[i] = DatumEncoding_VALUE
   284  			} else {
   285  				enc[i] = RandDatumEncoding(rng)
   286  				for !columnTypeCompatibleWithEncoding(typs[i], enc[i]) {
   287  					enc[i] = RandDatumEncoding(rng)
   288  				}
   289  			}
   290  			buf, err = ed[i].Encode(typs[i], &alloc, enc[i], buf)
   291  			if err != nil {
   292  				t.Fatalf("Failed to encode type %v: %s", typs[i], err)
   293  			}
   294  		}
   295  		// Decode the buffer.
   296  		b := buf
   297  		for i := range ed {
   298  			if len(b) == 0 {
   299  				t.Fatal("buffer ended early")
   300  			}
   301  			var decoded EncDatum
   302  			decoded, b, err = EncDatumFromBuffer(typs[i], enc[i], b)
   303  			if err != nil {
   304  				t.Fatalf("%+v: encdatum from %+v: %+v (%+v)", ed[i].Datum, enc[i], err, typs[i])
   305  			}
   306  			err = decoded.EnsureDecoded(typs[i], &alloc)
   307  			if err != nil {
   308  				t.Fatalf("%+v: ensuredecoded: %v (%+v)", ed[i], err, typs[i])
   309  			}
   310  			if decoded.Datum.Compare(evalCtx, ed[i].Datum) != 0 {
   311  				t.Errorf("decoded datum %+v doesn't equal original %+v", decoded.Datum, ed[i].Datum)
   312  			}
   313  		}
   314  		if len(b) != 0 {
   315  			t.Errorf("%d leftover bytes", len(b))
   316  		}
   317  	}
   318  }
   319  
   320  func TestEncDatumRowCompare(t *testing.T) {
   321  	defer leaktest.AfterTest(t)()
   322  
   323  	v := [5]EncDatum{}
   324  	for i := range v {
   325  		v[i] = DatumToEncDatum(types.Int, tree.NewDInt(tree.DInt(i)))
   326  	}
   327  
   328  	asc := encoding.Ascending
   329  	desc := encoding.Descending
   330  
   331  	testCases := []struct {
   332  		row1, row2 EncDatumRow
   333  		ord        ColumnOrdering
   334  		cmp        int
   335  	}{
   336  		{
   337  			row1: EncDatumRow{v[0], v[1], v[2]},
   338  			row2: EncDatumRow{v[0], v[1], v[3]},
   339  			ord:  ColumnOrdering{},
   340  			cmp:  0,
   341  		},
   342  		{
   343  			row1: EncDatumRow{v[0], v[1], v[2]},
   344  			row2: EncDatumRow{v[0], v[1], v[3]},
   345  			ord:  ColumnOrdering{{1, desc}},
   346  			cmp:  0,
   347  		},
   348  		{
   349  			row1: EncDatumRow{v[0], v[1], v[2]},
   350  			row2: EncDatumRow{v[0], v[1], v[3]},
   351  			ord:  ColumnOrdering{{0, asc}, {1, desc}},
   352  			cmp:  0,
   353  		},
   354  		{
   355  			row1: EncDatumRow{v[0], v[1], v[2]},
   356  			row2: EncDatumRow{v[0], v[1], v[3]},
   357  			ord:  ColumnOrdering{{2, asc}},
   358  			cmp:  -1,
   359  		},
   360  		{
   361  			row1: EncDatumRow{v[0], v[1], v[3]},
   362  			row2: EncDatumRow{v[0], v[1], v[2]},
   363  			ord:  ColumnOrdering{{2, asc}},
   364  			cmp:  1,
   365  		},
   366  		{
   367  			row1: EncDatumRow{v[0], v[1], v[2]},
   368  			row2: EncDatumRow{v[0], v[1], v[3]},
   369  			ord:  ColumnOrdering{{2, asc}, {0, asc}, {1, asc}},
   370  			cmp:  -1,
   371  		},
   372  		{
   373  			row1: EncDatumRow{v[0], v[1], v[2]},
   374  			row2: EncDatumRow{v[0], v[1], v[3]},
   375  			ord:  ColumnOrdering{{0, asc}, {2, desc}},
   376  			cmp:  1,
   377  		},
   378  		{
   379  			row1: EncDatumRow{v[0], v[1], v[2]},
   380  			row2: EncDatumRow{v[0], v[1], v[3]},
   381  			ord:  ColumnOrdering{{1, desc}, {0, asc}, {2, desc}},
   382  			cmp:  1,
   383  		},
   384  		{
   385  			row1: EncDatumRow{v[2], v[3], v[4]},
   386  			row2: EncDatumRow{v[1], v[3], v[0]},
   387  			ord:  ColumnOrdering{{0, asc}},
   388  			cmp:  1,
   389  		},
   390  		{
   391  			row1: EncDatumRow{v[2], v[3], v[4]},
   392  			row2: EncDatumRow{v[1], v[3], v[0]},
   393  			ord:  ColumnOrdering{{1, desc}, {0, asc}},
   394  			cmp:  1,
   395  		},
   396  		{
   397  			row1: EncDatumRow{v[2], v[3], v[4]},
   398  			row2: EncDatumRow{v[1], v[3], v[0]},
   399  			ord:  ColumnOrdering{{1, asc}, {0, asc}},
   400  			cmp:  1,
   401  		},
   402  		{
   403  			row1: EncDatumRow{v[2], v[3], v[4]},
   404  			row2: EncDatumRow{v[1], v[3], v[0]},
   405  			ord:  ColumnOrdering{{1, asc}, {0, desc}},
   406  			cmp:  -1,
   407  		},
   408  		{
   409  			row1: EncDatumRow{v[2], v[3], v[4]},
   410  			row2: EncDatumRow{v[1], v[3], v[0]},
   411  			ord:  ColumnOrdering{{0, desc}, {1, asc}},
   412  			cmp:  -1,
   413  		},
   414  	}
   415  
   416  	a := &DatumAlloc{}
   417  	evalCtx := tree.NewTestingEvalContext(cluster.MakeTestingClusterSettings())
   418  	defer evalCtx.Stop(context.Background())
   419  	for _, c := range testCases {
   420  		typs := make([]*types.T, len(c.row1))
   421  		for i := range typs {
   422  			typs[i] = types.Int
   423  		}
   424  		cmp, err := c.row1.Compare(typs, a, c.ord, evalCtx, c.row2)
   425  		if err != nil {
   426  			t.Error(err)
   427  		} else if cmp != c.cmp {
   428  			t.Errorf(
   429  				"%s cmp %s ordering %v got %d, expected %d",
   430  				c.row1.String(typs), c.row2.String(typs), c.ord, cmp, c.cmp,
   431  			)
   432  		}
   433  	}
   434  }
   435  
   436  func TestEncDatumRowAlloc(t *testing.T) {
   437  	defer leaktest.AfterTest(t)()
   438  
   439  	evalCtx := tree.NewTestingEvalContext(cluster.MakeTestingClusterSettings())
   440  	defer evalCtx.Stop(context.Background())
   441  	rng, _ := randutil.NewPseudoRand()
   442  	for _, cols := range []int{1, 2, 4, 10, 40, 100} {
   443  		for _, rows := range []int{1, 2, 3, 5, 10, 20} {
   444  			colTypes := RandColumnTypes(rng, cols)
   445  			in := make(EncDatumRows, rows)
   446  			for i := 0; i < rows; i++ {
   447  				in[i] = make(EncDatumRow, cols)
   448  				for j := 0; j < cols; j++ {
   449  					datum := RandDatum(rng, colTypes[j], true /* nullOk */)
   450  					in[i][j] = DatumToEncDatum(colTypes[j], datum)
   451  				}
   452  			}
   453  			var alloc EncDatumRowAlloc
   454  			out := make(EncDatumRows, rows)
   455  			for i := 0; i < rows; i++ {
   456  				out[i] = alloc.CopyRow(in[i])
   457  				if len(out[i]) != cols {
   458  					t.Fatalf("allocated row has invalid length %d (expected %d)", len(out[i]), cols)
   459  				}
   460  			}
   461  			// Do some random appends to make sure the buffers never overlap.
   462  			for x := 0; x < 10; x++ {
   463  				i := rng.Intn(rows)
   464  				j := rng.Intn(rows)
   465  				out[i] = append(out[i], out[j]...)
   466  				out[i] = out[i][:cols]
   467  			}
   468  			for i := 0; i < rows; i++ {
   469  				for j := 0; j < cols; j++ {
   470  					if a, b := in[i][j].Datum, out[i][j].Datum; a.Compare(evalCtx, b) != 0 {
   471  						t.Errorf("copied datum %s doesn't equal original %s", b, a)
   472  					}
   473  				}
   474  			}
   475  		}
   476  	}
   477  }
   478  
   479  func TestValueEncodeDecodeTuple(t *testing.T) {
   480  	rng, seed := randutil.NewPseudoRand()
   481  	tests := make([]tree.Datum, 1000)
   482  	colTypes := make([]*types.T, 1000)
   483  	evalCtx := tree.NewTestingEvalContext(cluster.MakeTestingClusterSettings())
   484  
   485  	for i := range tests {
   486  		len := rng.Intn(5)
   487  		contents := make([]*types.T, len)
   488  		for j := range contents {
   489  			contents[j] = RandEncodableType(rng)
   490  		}
   491  		colTypes[i] = types.MakeTuple(contents)
   492  		tests[i] = RandDatum(rng, colTypes[i], true)
   493  	}
   494  
   495  	for i, test := range tests {
   496  
   497  		switch typedTest := test.(type) {
   498  		case *tree.DTuple:
   499  
   500  			buf, err := EncodeTableValue(nil, ColumnID(encoding.NoColumnID), typedTest, nil)
   501  			if err != nil {
   502  				t.Fatalf("seed %d: encoding tuple %v with types %v failed with error: %v",
   503  					seed, test, colTypes[i], err)
   504  			}
   505  			var decodedTuple tree.Datum
   506  			testTyp := test.ResolvedType()
   507  
   508  			decodedTuple, buf, err = DecodeTableValue(&DatumAlloc{}, testTyp, buf)
   509  			if err != nil {
   510  				t.Fatalf("seed %d: decoding tuple %v with type (%+v, %+v) failed with error: %v",
   511  					seed, test, colTypes[i], testTyp, err)
   512  			}
   513  			if len(buf) != 0 {
   514  				t.Fatalf("seed %d: decoding tuple %v with type (%+v, %+v) left %d remaining bytes",
   515  					seed, test, colTypes[i], testTyp, len(buf))
   516  			}
   517  
   518  			if cmp := decodedTuple.Compare(evalCtx, test); cmp != 0 {
   519  				t.Fatalf("seed %d: encoded %+v, decoded %+v, expected equal, received comparison: %d", seed, test, decodedTuple, cmp)
   520  			}
   521  		default:
   522  			if test == tree.DNull {
   523  				continue
   524  			}
   525  			t.Fatalf("seed %d: non-null test case %v is not a tuple", seed, test)
   526  		}
   527  	}
   528  
   529  }
   530  
   531  func TestEncDatumSize(t *testing.T) {
   532  	defer leaktest.AfterTest(t)()
   533  
   534  	const (
   535  		asc  = DatumEncoding_ASCENDING_KEY
   536  		desc = DatumEncoding_DESCENDING_KEY
   537  
   538  		DIntSize    = unsafe.Sizeof(tree.DInt(0))
   539  		DFloatSize  = unsafe.Sizeof(tree.DFloat(0))
   540  		DStringSize = unsafe.Sizeof(*tree.NewDString(""))
   541  	)
   542  
   543  	dec12300 := &tree.DDecimal{Decimal: *apd.New(123, 2)}
   544  	decimalSize := dec12300.Size()
   545  
   546  	testCases := []struct {
   547  		encDatum     EncDatum
   548  		expectedSize uintptr
   549  	}{
   550  		{
   551  			encDatum:     EncDatumFromEncoded(asc, encoding.EncodeVarintAscending(nil, 0)),
   552  			expectedSize: EncDatumOverhead + 1, // 1 is encoded with length 1 byte array
   553  		},
   554  		{
   555  			encDatum:     EncDatumFromEncoded(desc, encoding.EncodeVarintDescending(nil, 123)),
   556  			expectedSize: EncDatumOverhead + 2, // 123 is encoded with length 2 byte array
   557  		},
   558  		{
   559  			encDatum:     EncDatumFromEncoded(asc, encoding.EncodeVarintAscending(nil, 12345)),
   560  			expectedSize: EncDatumOverhead + 3, // 12345 is encoded with length 3 byte array
   561  		},
   562  		{
   563  			encDatum:     DatumToEncDatum(types.Int, tree.NewDInt(123)),
   564  			expectedSize: EncDatumOverhead + DIntSize,
   565  		},
   566  		{
   567  			encDatum: EncDatum{
   568  				encoding: asc,
   569  				encoded:  encoding.EncodeVarintAscending(nil, 123),
   570  				Datum:    tree.NewDInt(123),
   571  			},
   572  			expectedSize: EncDatumOverhead + 2 + DIntSize, // 123 is encoded with length 2 byte array
   573  		},
   574  		{
   575  			encDatum:     EncDatumFromEncoded(asc, encoding.EncodeFloatAscending(nil, 0)),
   576  			expectedSize: EncDatumOverhead + 1, // 0.0 is encoded with length 1 byte array
   577  		},
   578  		{
   579  			encDatum:     EncDatumFromEncoded(desc, encoding.EncodeFloatDescending(nil, 123)),
   580  			expectedSize: EncDatumOverhead + 9, // 123.0 is encoded with length 9 byte array
   581  		},
   582  		{
   583  			encDatum:     DatumToEncDatum(types.Float, tree.NewDFloat(123)),
   584  			expectedSize: EncDatumOverhead + DFloatSize,
   585  		},
   586  		{
   587  			encDatum: EncDatum{
   588  				encoding: asc,
   589  				encoded:  encoding.EncodeFloatAscending(nil, 123),
   590  				Datum:    tree.NewDFloat(123),
   591  			},
   592  			expectedSize: EncDatumOverhead + 9 + DFloatSize, // 123.0 is encoded with length 9 byte array
   593  		},
   594  		{
   595  			encDatum:     EncDatumFromEncoded(asc, encoding.EncodeDecimalAscending(nil, apd.New(0, 0))),
   596  			expectedSize: EncDatumOverhead + 1, // 0.0 is encoded with length 1 byte array
   597  		},
   598  		{
   599  			encDatum:     EncDatumFromEncoded(desc, encoding.EncodeDecimalDescending(nil, apd.New(123, 2))),
   600  			expectedSize: EncDatumOverhead + 4, // 123.0 is encoded with length 4 byte array
   601  		},
   602  		{
   603  			encDatum:     DatumToEncDatum(types.Decimal, dec12300),
   604  			expectedSize: EncDatumOverhead + decimalSize,
   605  		},
   606  		{
   607  			encDatum: EncDatum{
   608  				encoding: asc,
   609  				encoded:  encoding.EncodeDecimalAscending(nil, &dec12300.Decimal),
   610  				Datum:    dec12300,
   611  			},
   612  			expectedSize: EncDatumOverhead + 4 + decimalSize,
   613  		},
   614  		{
   615  			encDatum:     EncDatumFromEncoded(asc, encoding.EncodeStringAscending(nil, "")),
   616  			expectedSize: EncDatumOverhead + 3, // "" is encoded with length 3 byte array
   617  		},
   618  		{
   619  			encDatum:     EncDatumFromEncoded(desc, encoding.EncodeStringDescending(nil, "123⌘")),
   620  			expectedSize: EncDatumOverhead + 9, // "123⌘" is encoded with length 9 byte array
   621  		},
   622  		{
   623  			encDatum:     DatumToEncDatum(types.String, tree.NewDString("12")),
   624  			expectedSize: EncDatumOverhead + DStringSize + 2,
   625  		},
   626  		{
   627  			encDatum: EncDatum{
   628  				encoding: asc,
   629  				encoded:  encoding.EncodeStringAscending(nil, "1234"),
   630  				Datum:    tree.NewDString("12345"),
   631  			},
   632  			expectedSize: EncDatumOverhead + 7 + DStringSize + 5, // "1234" is encoded with length 7 byte array
   633  		},
   634  		{
   635  			encDatum:     EncDatumFromEncoded(asc, encoding.EncodeTimeAscending(nil, time.Date(2018, time.June, 26, 11, 50, 0, 0, time.FixedZone("EDT", 0)))),
   636  			expectedSize: EncDatumOverhead + 7, // This time is encoded with length 7 byte array
   637  		},
   638  		{
   639  			encDatum:     EncDatumFromEncoded(asc, encoding.EncodeTimeAscending(nil, time.Date(2018, time.June, 26, 11, 50, 12, 3456789, time.FixedZone("EDT", 0)))),
   640  			expectedSize: EncDatumOverhead + 10, // This time is encoded with length 10 byte array
   641  		},
   642  	}
   643  
   644  	for _, c := range testCases {
   645  		receivedSize := c.encDatum.Size()
   646  		if receivedSize != c.expectedSize {
   647  			t.Errorf("on %v\treceived %d, expected %d", c.encDatum, receivedSize, c.expectedSize)
   648  		}
   649  	}
   650  
   651  	testRow := make(EncDatumRow, len(testCases))
   652  	expectedTotalSize := EncDatumRowOverhead
   653  	for idx, c := range testCases {
   654  		testRow[idx] = c.encDatum
   655  		expectedTotalSize += c.expectedSize
   656  	}
   657  	receivedTotalSize := testRow.Size()
   658  	if receivedTotalSize != expectedTotalSize {
   659  		t.Errorf("on %v\treceived %d, expected %d", testRow, receivedTotalSize, expectedTotalSize)
   660  	}
   661  }