func TestPrettyPrintRange(t *testing.T) { tableKey := makeKey(MakeTablePrefix(61), encoding.EncodeVarintAscending(nil, 4)) tableKey2 := makeKey(MakeTablePrefix(61), encoding.EncodeVarintAscending(nil, 500)) testCases := []struct { start, end roachpb.Key maxChars int expected string }{ {MinKey, tableKey, 8, "/{M…-T…}"}, {MinKey, tableKey, 15, "/{Min-Tabl…}"}, {MinKey, tableKey, 20, "/{Min-Table/6…}"}, {MinKey, tableKey, 25, "/{Min-Table/61/4}"}, {tableKey, tableKey2, 8, "/Table/…"}, {tableKey, tableKey2, 15, "/Table/61/…"}, {tableKey, tableKey2, 20, "/Table/61/{4-500}"}, {tableKey, MaxKey, 10, "/{Ta…-Max}"}, {tableKey, MaxKey, 20, "/{Table/6…-Max}"}, {tableKey, MaxKey, 25, "/{Table/61/4-Max}"}, } for i, tc := range testCases { var buf bytes.Buffer PrettyPrintRange(&buf, tc.start, tc.end, tc.maxChars) if str := buf.String(); str != tc.expected { t.Errorf("%d: expected \"%s\", got \"%s\"", i, tc.expected, str) } } }
func (z *zeroSum) monkey(tableID uint32, d time.Duration) { r := newRand() zipf := z.accountDistribution(r) for { time.Sleep(time.Duration(rand.Float64() * float64(d))) key := keys.MakeTablePrefix(tableID) key = encoding.EncodeVarintAscending(key, int64(zipf.Uint64())) key = keys.MakeRowSentinelKey(key) switch r.Intn(2) { case 0: if err := z.Split(z.RandNode(r.Intn), key); err != nil { if strings.Contains(err.Error(), "range is already split at key") || strings.Contains(err.Error(), storage.ErrMsgConflictUpdatingRangeDesc) { continue } z.maybeLogError(err) } else { atomic.AddUint64(&z.stats.splits, 1) } case 1: if transferred, err := z.TransferLease(z.RandNode(r.Intn), r, key); err != nil { z.maybeLogError(err) } else if transferred { atomic.AddUint64(&z.stats.transfers, 1) } } } }
// MakeDataKey creates a time series data key for the given series name, source, // Resolution and timestamp. The timestamp is expressed in nanoseconds since the // epoch; it will be truncated to an exact multiple of the supplied // Resolution's KeyDuration. func MakeDataKey(name string, source string, r Resolution, timestamp int64) roachpb.Key { k := makeDataKeySeriesPrefix(name, r) // Normalize timestamp into a timeslot before recording. timeslot := timestamp / r.SlabDuration() k = encoding.EncodeVarintAscending(k, timeslot) k = append(k, source...) return k }
func BenchmarkMVCCPutDelete_RocksDB(b *testing.B) { rocksdb := setupMVCCInMemRocksDB(b, "put_delete") defer rocksdb.Close() r := rand.New(rand.NewSource(int64(timeutil.Now().UnixNano()))) value := roachpb.MakeValueFromBytes(randutil.RandBytes(r, 10)) zeroTS := hlc.ZeroTimestamp var blockNum int64 for i := 0; i < b.N; i++ { blockID := r.Int63() blockNum++ key := encoding.EncodeVarintAscending(nil, blockID) key = encoding.EncodeVarintAscending(key, blockNum) if err := MVCCPut(context.Background(), rocksdb, nil, key, zeroTS, value, nil /* txn */); err != nil { b.Fatal(err) } if err := MVCCDelete(context.Background(), rocksdb, nil, key, zeroTS, nil /* txn */); err != nil { b.Fatal(err) } } }
StoreIDGenerator = roachpb.Key(makeKey(SystemPrefix, roachpb.RKey("store-idgen"))) // StatusPrefix specifies the key prefix to store all status details. StatusPrefix = roachpb.Key(makeKey(SystemPrefix, roachpb.RKey("status-"))) // StatusNodePrefix stores all status info for nodes. StatusNodePrefix = roachpb.Key(makeKey(StatusPrefix, roachpb.RKey("node-"))) // TimeseriesPrefix is the key prefix for all timeseries data. TimeseriesPrefix = roachpb.Key(makeKey(SystemPrefix, roachpb.RKey("tsd"))) // UpdateCheckPrefix is the key prefix for all update check times. UpdateCheckPrefix = roachpb.Key(makeKey(SystemPrefix, roachpb.RKey("update-"))) UpdateCheckCluster = roachpb.Key(makeKey(UpdateCheckPrefix, roachpb.RKey("cluster"))) // TableDataMin is the start of the range of table data keys. TableDataMin = roachpb.Key(encoding.EncodeVarintAscending(nil, math.MinInt64)) // TableDataMin is the end of the range of table data keys. TableDataMax = roachpb.Key(encoding.EncodeVarintAscending(nil, math.MaxInt64)) // SystemConfigTableDataMax is the end key of system config structured data. SystemConfigTableDataMax = roachpb.Key(MakeTablePrefix(MaxSystemConfigDescID + 1)) // UserTableDataMin is the start key of user structured data. UserTableDataMin = roachpb.Key(MakeTablePrefix(MaxReservedDescID + 1)) // MaxKey is the infinity marker which is larger than any other key. MaxKey = roachpb.KeyMax // MinKey is a minimum key value which sorts before all other keys. MinKey = roachpb.KeyMin )
func TestTableReader(t *testing.T) { defer leaktest.AfterTest(t)() s, sqlDB, kvDB := serverutils.StartServer(t, base.TestServerArgs{}) defer s.Stopper().Stop() // Create a table where each row is: // // | a | b | sum | s | // |-----------------------------------------------------------------| // | rowId/10 | rowId%10 | rowId/10 + rowId%10 | IntToEnglish(rowId) | aFn := func(row int) parser.Datum { return parser.NewDInt(parser.DInt(row / 10)) } bFn := func(row int) parser.Datum { return parser.NewDInt(parser.DInt(row % 10)) } sumFn := func(row int) parser.Datum { return parser.NewDInt(parser.DInt(row/10 + row%10)) } sqlutils.CreateTable(t, sqlDB, "t", "a INT, b INT, sum INT, s STRING, PRIMARY KEY (a,b), INDEX bs (b,s)", 99, sqlutils.ToRowFn(aFn, bFn, sumFn, sqlutils.RowEnglishFn)) td := sqlbase.GetTableDescriptor(kvDB, "test", "t") makeIndexSpan := func(start, end int) TableReaderSpan { var span roachpb.Span prefix := roachpb.Key(sqlbase.MakeIndexKeyPrefix(td, td.Indexes[0].ID)) span.Key = append(prefix, encoding.EncodeVarintAscending(nil, int64(start))...) span.EndKey = append(span.EndKey, prefix...) span.EndKey = append(span.EndKey, encoding.EncodeVarintAscending(nil, int64(end))...) return TableReaderSpan{Span: span} } testCases := []struct { spec TableReaderSpec expected string }{ { spec: TableReaderSpec{ Filter: Expression{Expr: "@3 < 5 AND @2 != 3"}, // sum < 5 && b != 3 OutputColumns: []uint32{0, 1}, }, expected: "[[0 1] [0 2] [0 4] [1 0] [1 1] [1 2] [2 0] [2 1] [2 2] [3 0] [3 1] [4 0]]", }, { spec: TableReaderSpec{ Filter: Expression{Expr: "@3 < 5 AND @2 != 3"}, OutputColumns: []uint32{3}, // s HardLimit: 4, }, expected: "[['one'] ['two'] ['four'] ['one-zero']]", }, { spec: TableReaderSpec{ IndexIdx: 1, Reverse: true, Spans: []TableReaderSpan{makeIndexSpan(4, 6)}, Filter: Expression{Expr: "@1 < 3"}, // sum < 8 OutputColumns: []uint32{0, 1}, SoftLimit: 1, }, expected: "[[2 5] [1 5] [0 5] [2 4] [1 4] [0 4]]", }, } for _, c := range testCases { ts := c.spec ts.Table = *td flowCtx := FlowCtx{ Context: context.Background(), evalCtx: &parser.EvalContext{}, txnProto: &roachpb.Transaction{}, clientDB: kvDB, } out := &RowBuffer{} tr, err := newTableReader(&flowCtx, &ts, out) if err != nil { t.Fatal(err) } tr.Run(nil) if out.err != nil { t.Fatal(out.err) } if !out.closed { t.Fatalf("output RowReceiver not closed") } if result := out.rows.String(); result != c.expected { t.Errorf("invalid results: %s, expected %s'", result, c.expected) } } }
// EncodeTableKey encodes `val` into `b` and returns the new buffer. func EncodeTableKey(b []byte, val parser.Datum, dir encoding.Direction) ([]byte, error) { if (dir != encoding.Ascending) && (dir != encoding.Descending) { return nil, errors.Errorf("invalid direction: %d", dir) } if val == parser.DNull { if dir == encoding.Ascending { return encoding.EncodeNullAscending(b), nil } return encoding.EncodeNullDescending(b), nil } switch t := val.(type) { case *parser.DBool: var x int64 if *t { x = 1 } else { x = 0 } if dir == encoding.Ascending { return encoding.EncodeVarintAscending(b, x), nil } return encoding.EncodeVarintDescending(b, x), nil case *parser.DInt: if dir == encoding.Ascending { return encoding.EncodeVarintAscending(b, int64(*t)), nil } return encoding.EncodeVarintDescending(b, int64(*t)), nil case *parser.DFloat: if dir == encoding.Ascending { return encoding.EncodeFloatAscending(b, float64(*t)), nil } return encoding.EncodeFloatDescending(b, float64(*t)), nil case *parser.DDecimal: if dir == encoding.Ascending { return encoding.EncodeDecimalAscending(b, &t.Dec), nil } return encoding.EncodeDecimalDescending(b, &t.Dec), nil case *parser.DString: if dir == encoding.Ascending { return encoding.EncodeStringAscending(b, string(*t)), nil } return encoding.EncodeStringDescending(b, string(*t)), nil case *parser.DBytes: if dir == encoding.Ascending { return encoding.EncodeStringAscending(b, string(*t)), nil } return encoding.EncodeStringDescending(b, string(*t)), nil case *parser.DDate: if dir == encoding.Ascending { return encoding.EncodeVarintAscending(b, int64(*t)), nil } return encoding.EncodeVarintDescending(b, int64(*t)), nil case *parser.DTimestamp: if dir == encoding.Ascending { return encoding.EncodeTimeAscending(b, t.Time), nil } return encoding.EncodeTimeDescending(b, t.Time), nil case *parser.DTimestampTZ: if dir == encoding.Ascending { return encoding.EncodeTimeAscending(b, t.Time), nil } return encoding.EncodeTimeDescending(b, t.Time), nil case *parser.DInterval: if dir == encoding.Ascending { return encoding.EncodeDurationAscending(b, t.Duration) } return encoding.EncodeDurationDescending(b, t.Duration) case *parser.DTuple: for _, datum := range *t { var err error b, err = EncodeTableKey(b, datum, dir) if err != nil { return nil, err } } return b, nil } return nil, errors.Errorf("unable to encode table key: %T", val) }
func TestClusterFlow(t *testing.T) { defer leaktest.AfterTest(t)() const numRows = 100 args := base.TestClusterArgs{ReplicationMode: base.ReplicationManual} tc := serverutils.StartTestCluster(t, 3, args) defer tc.Stopper().Stop() sumDigitsFn := func(row int) parser.Datum { sum := 0 for row > 0 { sum += row % 10 row /= 10 } return parser.NewDInt(parser.DInt(sum)) } sqlutils.CreateTable(t, tc.ServerConn(0), "t", "num INT PRIMARY KEY, digitsum INT, numstr STRING, INDEX s (digitsum)", numRows, sqlutils.ToRowFn(sqlutils.RowIdxFn, sumDigitsFn, sqlutils.RowEnglishFn)) kvDB := tc.Server(0).KVClient().(*client.DB) desc := sqlbase.GetTableDescriptor(kvDB, "test", "t") makeIndexSpan := func(start, end int) TableReaderSpan { var span roachpb.Span prefix := roachpb.Key(sqlbase.MakeIndexKeyPrefix(desc, desc.Indexes[0].ID)) span.Key = append(prefix, encoding.EncodeVarintAscending(nil, int64(start))...) span.EndKey = append(span.EndKey, prefix...) span.EndKey = append(span.EndKey, encoding.EncodeVarintAscending(nil, int64(end))...) return TableReaderSpan{Span: span} } // Set up table readers on three hosts feeding data into a join reader on // the third host. This is a basic test for the distributed flow // infrastructure, including local and remote streams. // // Note that the ranges won't necessarily be local to the table readers, but // that doesn't matter for the purposes of this test. // Start a span (useful to look at spans using Lighstep). sp, err := tracing.JoinOrNew(tracing.NewTracer(), nil, "cluster test") if err != nil { t.Fatal(err) } ctx := opentracing.ContextWithSpan(context.Background(), sp) defer sp.Finish() tr1 := TableReaderSpec{ Table: *desc, IndexIdx: 1, OutputColumns: []uint32{0, 1}, Spans: []TableReaderSpan{makeIndexSpan(0, 8)}, } tr2 := TableReaderSpec{ Table: *desc, IndexIdx: 1, OutputColumns: []uint32{0, 1}, Spans: []TableReaderSpan{makeIndexSpan(8, 12)}, } tr3 := TableReaderSpec{ Table: *desc, IndexIdx: 1, OutputColumns: []uint32{0, 1}, Spans: []TableReaderSpan{makeIndexSpan(12, 100)}, } jr := JoinReaderSpec{ Table: *desc, OutputColumns: []uint32{2}, } txn := client.NewTxn(ctx, *kvDB) fid := FlowID{uuid.MakeV4()} req1 := &SetupFlowRequest{Txn: txn.Proto} req1.Flow = FlowSpec{ FlowID: fid, Processors: []ProcessorSpec{{ Core: ProcessorCoreUnion{TableReader: &tr1}, Output: []OutputRouterSpec{{ Type: OutputRouterSpec_MIRROR, Streams: []StreamEndpointSpec{ {StreamID: 0, Mailbox: &MailboxSpec{TargetAddr: tc.Server(2).ServingAddr()}}, }, }}, }}, } req2 := &SetupFlowRequest{Txn: txn.Proto} req2.Flow = FlowSpec{ FlowID: fid, Processors: []ProcessorSpec{{ Core: ProcessorCoreUnion{TableReader: &tr2}, Output: []OutputRouterSpec{{ Type: OutputRouterSpec_MIRROR, Streams: []StreamEndpointSpec{ {StreamID: 1, Mailbox: &MailboxSpec{TargetAddr: tc.Server(2).ServingAddr()}}, }, }}, }}, } req3 := &SetupFlowRequest{Txn: txn.Proto} req3.Flow = FlowSpec{ FlowID: fid, Processors: []ProcessorSpec{ { Core: ProcessorCoreUnion{TableReader: &tr3}, Output: []OutputRouterSpec{{ Type: OutputRouterSpec_MIRROR, Streams: []StreamEndpointSpec{ {StreamID: StreamID(2)}, }, }}, }, { Input: []InputSyncSpec{{ Type: InputSyncSpec_ORDERED, Ordering: Ordering{Columns: []Ordering_Column{{1, Ordering_Column_ASC}}}, Streams: []StreamEndpointSpec{ {StreamID: 0, Mailbox: &MailboxSpec{}}, {StreamID: 1, Mailbox: &MailboxSpec{}}, {StreamID: StreamID(2)}, }, }}, Core: ProcessorCoreUnion{JoinReader: &jr}, Output: []OutputRouterSpec{{ Type: OutputRouterSpec_MIRROR, Streams: []StreamEndpointSpec{{Mailbox: &MailboxSpec{SimpleResponse: true}}}, }}}, }, } if err := SetFlowRequestTrace(ctx, req1); err != nil { t.Fatal(err) } if err := SetFlowRequestTrace(ctx, req2); err != nil { t.Fatal(err) } if err := SetFlowRequestTrace(ctx, req3); err != nil { t.Fatal(err) } var clients []DistSQLClient for i := 0; i < 3; i++ { s := tc.Server(i) conn, err := s.RPCContext().GRPCDial(s.ServingAddr()) if err != nil { t.Fatal(err) } clients = append(clients, NewDistSQLClient(conn)) } if log.V(1) { log.Infof(ctx, "Setting up flow on 0") } if resp, err := clients[0].SetupFlow(ctx, req1); err != nil { t.Fatal(err) } else if resp.Error != nil { t.Fatal(resp.Error) } if log.V(1) { log.Infof(ctx, "Setting up flow on 1") } if resp, err := clients[1].SetupFlow(ctx, req2); err != nil { t.Fatal(err) } else if resp.Error != nil { t.Fatal(resp.Error) } if log.V(1) { log.Infof(ctx, "Running flow on 2") } stream, err := clients[2].RunSimpleFlow(ctx, req3) if err != nil { t.Fatal(err) } var decoder StreamDecoder var rows sqlbase.EncDatumRows for { msg, err := stream.Recv() if err != nil { if err == io.EOF { break } t.Fatal(err) } err = decoder.AddMessage(msg) if err != nil { t.Fatal(err) } rows = testGetDecodedRows(t, &decoder, rows) } if done, trailerErr := decoder.IsDone(); !done { t.Fatal("stream not done") } else if trailerErr != nil { t.Fatal("error in the stream trailer:", trailerErr) } // The result should be all the numbers in string form, ordered by the // digit sum (and then by number). var results []string for sum := 1; sum <= 50; sum++ { for i := 1; i <= numRows; i++ { if int(*sumDigitsFn(i).(*parser.DInt)) == sum { results = append(results, fmt.Sprintf("['%s']", sqlutils.IntToEnglish(i))) } } } expected := strings.Join(results, " ") expected = "[" + expected + "]" if rowStr := rows.String(); rowStr != expected { t.Errorf("Result: %s\n Expected: %s\n", rowStr, expected) } }
func TestPrettyPrint(t *testing.T) { tm, _ := time.Parse(time.RFC3339Nano, "2016-03-30T13:40:35.053725008Z") duration := duration.Duration{Months: 1, Days: 1, Nanos: 1 * time.Second.Nanoseconds()} durationAsc, _ := encoding.EncodeDurationAscending(nil, duration) durationDesc, _ := encoding.EncodeDurationDescending(nil, duration) txnID := uuid.MakeV4() // The following test cases encode keys with a mixture of ascending and descending direction, // but always decode keys in the ascending direction. This is why some of the decoded values // seem bizarre. testCases := []struct { key roachpb.Key exp string }{ // local {StoreIdentKey(), "/Local/Store/storeIdent"}, {StoreGossipKey(), "/Local/Store/gossipBootstrap"}, {AbortCacheKey(roachpb.RangeID(1000001), txnID), fmt.Sprintf(`/Local/RangeID/1000001/r/AbortCache/%q`, txnID)}, {RaftTombstoneKey(roachpb.RangeID(1000001)), "/Local/RangeID/1000001/r/RaftTombstone"}, {RaftAppliedIndexKey(roachpb.RangeID(1000001)), "/Local/RangeID/1000001/r/RaftAppliedIndex"}, {LeaseAppliedIndexKey(roachpb.RangeID(1000001)), "/Local/RangeID/1000001/r/LeaseAppliedIndex"}, {RaftTruncatedStateKey(roachpb.RangeID(1000001)), "/Local/RangeID/1000001/r/RaftTruncatedState"}, {RangeLeaseKey(roachpb.RangeID(1000001)), "/Local/RangeID/1000001/r/RangeLease"}, {RangeStatsKey(roachpb.RangeID(1000001)), "/Local/RangeID/1000001/r/RangeStats"}, {RangeTxnSpanGCThresholdKey(roachpb.RangeID(1000001)), `/Local/RangeID/1000001/r/RangeTxnSpanGCThreshold`}, {RangeFrozenStatusKey(roachpb.RangeID(1000001)), "/Local/RangeID/1000001/r/RangeFrozenStatus"}, {RangeLastGCKey(roachpb.RangeID(1000001)), "/Local/RangeID/1000001/r/RangeLastGC"}, {RaftHardStateKey(roachpb.RangeID(1000001)), "/Local/RangeID/1000001/u/RaftHardState"}, {RaftLastIndexKey(roachpb.RangeID(1000001)), "/Local/RangeID/1000001/u/RaftLastIndex"}, {RaftLogKey(roachpb.RangeID(1000001), uint64(200001)), "/Local/RangeID/1000001/u/RaftLog/logIndex:200001"}, {RangeLastReplicaGCTimestampKey(roachpb.RangeID(1000001)), "/Local/RangeID/1000001/u/RangeLastReplicaGCTimestamp"}, {RangeLastVerificationTimestampKeyDeprecated(roachpb.RangeID(1000001)), "/Local/RangeID/1000001/u/RangeLastVerificationTimestamp"}, {MakeRangeKeyPrefix(roachpb.RKey("ok")), `/Local/Range/"ok"`}, {RangeDescriptorKey(roachpb.RKey("111")), `/Local/Range/"111"/RangeDescriptor`}, {TransactionKey(roachpb.Key("111"), txnID), fmt.Sprintf(`/Local/Range/"111"/Transaction/addrKey:/id:%q`, txnID)}, {LocalMax, `/Meta1/""`}, // LocalMax == Meta1Prefix // system {makeKey(Meta2Prefix, roachpb.Key("foo")), `/Meta2/"foo"`}, {makeKey(Meta1Prefix, roachpb.Key("foo")), `/Meta1/"foo"`}, {RangeMetaKey(roachpb.RKey("f")), `/Meta2/"f"`}, {NodeLivenessKey(10033), "/System/NodeLiveness/10033"}, {NodeStatusKey(1111), "/System/StatusNode/1111"}, {SystemMax, "/System/Max"}, // key of key {RangeMetaKey(roachpb.RKey(MakeRangeKeyPrefix(roachpb.RKey("ok")))), `/Meta2/Local/Range/"ok"`}, {RangeMetaKey(roachpb.RKey(makeKey(MakeTablePrefix(42), roachpb.RKey("foo")))), `/Meta2/Table/42/"foo"`}, {RangeMetaKey(roachpb.RKey(makeKey(Meta2Prefix, roachpb.Key("foo")))), `/Meta1/"foo"`}, // table {UserTableDataMin, "/Table/50"}, {MakeTablePrefix(111), "/Table/111"}, {makeKey(MakeTablePrefix(42), roachpb.RKey("foo")), `/Table/42/"foo"`}, {makeKey(MakeTablePrefix(42), roachpb.RKey(encoding.EncodeFloatAscending(nil, float64(233.221112)))), "/Table/42/233.221112"}, {makeKey(MakeTablePrefix(42), roachpb.RKey(encoding.EncodeFloatDescending(nil, float64(-233.221112)))), "/Table/42/233.221112"}, {makeKey(MakeTablePrefix(42), roachpb.RKey(encoding.EncodeFloatAscending(nil, math.Inf(1)))), "/Table/42/+Inf"}, {makeKey(MakeTablePrefix(42), roachpb.RKey(encoding.EncodeFloatAscending(nil, math.NaN()))), "/Table/42/NaN"}, {makeKey(MakeTablePrefix(42), roachpb.RKey(encoding.EncodeVarintAscending(nil, 1222)), roachpb.RKey(encoding.EncodeStringAscending(nil, "handsome man"))), `/Table/42/1222/"handsome man"`}, {makeKey(MakeTablePrefix(42), roachpb.RKey(encoding.EncodeVarintAscending(nil, 1222))), `/Table/42/1222`}, {makeKey(MakeTablePrefix(42), roachpb.RKey(encoding.EncodeVarintDescending(nil, 1222))), `/Table/42/-1223`}, {makeKey(MakeTablePrefix(42), roachpb.RKey(encoding.EncodeBytesAscending(nil, []byte{1, 2, 8, 255}))), `/Table/42/"\x01\x02\b\xff"`}, {makeKey(MakeTablePrefix(42), roachpb.RKey(encoding.EncodeBytesAscending(nil, []byte{1, 2, 8, 255})), roachpb.RKey("bar")), `/Table/42/"\x01\x02\b\xff"/"bar"`}, {makeKey(MakeTablePrefix(42), roachpb.RKey(encoding.EncodeBytesDescending(nil, []byte{1, 2, 8, 255})), roachpb.RKey("bar")), `/Table/42/"\x01\x02\b\xff"/"bar"`}, {makeKey(MakeTablePrefix(42), roachpb.RKey(encoding.EncodeNullAscending(nil))), "/Table/42/NULL"}, {makeKey(MakeTablePrefix(42), roachpb.RKey(encoding.EncodeNotNullAscending(nil))), "/Table/42/#"}, {makeKey(MakeTablePrefix(42), roachpb.RKey(encoding.EncodeTimeAscending(nil, tm))), "/Table/42/2016-03-30T13:40:35.053725008Z"}, {makeKey(MakeTablePrefix(42), roachpb.RKey(encoding.EncodeTimeDescending(nil, tm))), "/Table/42/1923-10-04T10:19:23.946274991Z"}, {makeKey(MakeTablePrefix(42), roachpb.RKey(encoding.EncodeDecimalAscending(nil, inf.NewDec(1234, 2)))), "/Table/42/12.34"}, {makeKey(MakeTablePrefix(42), roachpb.RKey(encoding.EncodeDecimalDescending(nil, inf.NewDec(1234, 2)))), "/Table/42/-12.34"}, {makeKey(MakeTablePrefix(42), roachpb.RKey(durationAsc)), "/Table/42/1m1d1s"}, {makeKey(MakeTablePrefix(42), roachpb.RKey(durationDesc)), "/Table/42/-2m-2d743h59m58.999999999s"}, // others {makeKey([]byte("")), "/Min"}, {Meta1KeyMax, "/Meta1/Max"}, {Meta2KeyMax, "/Meta2/Max"}, {makeKey(MakeTablePrefix(42), roachpb.RKey([]byte{0x12, 'a', 0x00, 0x02})), "/Table/42/<unknown escape sequence: 0x0 0x2>"}, } for i, test := range testCases { keyInfo := MassagePrettyPrintedSpanForTest(PrettyPrint(test.key), nil) exp := MassagePrettyPrintedSpanForTest(test.exp, nil) if exp != keyInfo { t.Errorf("%d: expected %s, got %s", i, exp, keyInfo) } if exp != MassagePrettyPrintedSpanForTest(test.key.String(), nil) { t.Errorf("%d: expected %s, got %s", i, exp, test.key.String()) } parsed, err := UglyPrint(keyInfo) if err != nil { if _, ok := err.(*errUglifyUnsupported); !ok { t.Errorf("%d: %s: %s", i, keyInfo, err) } else { t.Logf("%d: skipping parsing of %s; key is unsupported: %v", i, keyInfo, err) } } else if exp, act := test.key, parsed; !bytes.Equal(exp, act) { t.Errorf("%d: expected %q, got %q", i, exp, act) } if t.Failed() { return } } }
// makeDataKeySeriesPrefix creates a key prefix for a time series at a specific // resolution. func makeDataKeySeriesPrefix(name string, r Resolution) roachpb.Key { k := append(roachpb.Key(nil), keys.TimeseriesPrefix...) k = encoding.EncodeBytesAscending(k, []byte(name)) k = encoding.EncodeVarintAscending(k, int64(r)) return k }