From c8c41d7f8c1c7735f81893cc63e168b79f987ef7 Mon Sep 17 00:00:00 2001 From: reshke Date: Mon, 11 Mar 2024 21:22:00 +0000 Subject: [PATCH] Change yacc and protos for multidim key ranges. --- .gitignore | 4 +- Makefile | 2 +- balancer/provider/balancer.go | 21 +- cmd/mover/main.go | 24 +- cmd/spqrdump/main.go | 25 +- coordinator/provider/coordinator.go | 119 ++-- coordinator/provider/keyranges.go | 9 +- pkg/clientinteractor/interactor.go | 9 +- pkg/coord/adapter.go | 37 +- pkg/coord/local/clocal.go | 118 ++-- pkg/coord/local/clocal_test.go | 1 + pkg/datatransfers/data_transfers.go | 21 +- pkg/decode/spqrql.go | 5 +- pkg/decode/spqrql_test.go | 30 +- pkg/meta/meta.go | 13 +- pkg/models/hashfunction/hashfunction.go | 49 +- pkg/models/kr/keyrange.go | 276 +++++++-- pkg/models/kr/keyrangemgr.go | 2 +- pkg/protos/key_range.pb.go | 295 +++++----- protos/key_range.proto | 7 +- qdb/models.go | 7 +- qdb/ops/ops.go | 7 +- router/grpc/qrouter.go | 8 +- router/mock/qrouter/mock_qrouter.go | 2 +- router/qrouter/proxy_routing.go | 264 ++++++--- router/qrouter/proxy_routing_test.go | 392 +++++++++---- router/qrouter/qrouter.go | 3 +- router/relay/qstate.go | 7 +- test/feature/features/spqrdump.feature | 12 +- .../console/expected/delete_distribution.out | 6 +- .../tests/console/sql/delete_distribution.sql | 4 +- .../router/expected/alter_distribution.out | 6 +- .../tests/router/expected/copy_routing.out | 2 +- .../tests/router/sql/alter_distribution.sql | 7 +- .../regress/tests/router/sql/copy_routing.sql | 2 +- yacc/console/ast.go | 8 +- yacc/console/gram.go | 538 +++++++++--------- yacc/console/gram.y | 69 ++- yacc/console/yx_test.go | 38 +- 39 files changed, 1573 insertions(+), 876 deletions(-) create mode 100644 pkg/coord/local/clocal_test.go diff --git a/.gitignore b/.gitignore index 02bc408e8..0813ee5c3 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ spqr-worldmock spqr-balancer spqr-mover spqr-workloadreplay -spqrdump +spqr-dump y.output *.swp *.swo @@ -17,4 +17,4 @@ memqdb.json test/feature/generatedFeatures test/feature/logs yacc/console/gram.y.save -.DS_Store \ No newline at end of file +.DS_Store diff --git a/Makefile b/Makefile index b4d81ae5b..aae9b97a4 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ build_workloadreplay: go build -pgo=auto -o spqr-workloadreplay ./cmd/workloadreplay build_spqrdump: - go build -pgo=auto -o spqrdump ./cmd/spqrdump + go build -pgo=auto -o spqr-dump ./cmd/spqrdump build: build_balancer build_coordinator build_coorctl build_router build_mover build_worldmock build_workloadreplay build_spqrdump diff --git a/balancer/provider/balancer.go b/balancer/provider/balancer.go index e8b1d7fa6..a42a35a68 100644 --- a/balancer/provider/balancer.go +++ b/balancer/provider/balancer.go @@ -3,6 +3,9 @@ package provider import ( "context" "fmt" + "sort" + "strings" + "github.com/google/uuid" "github.com/jackc/pgx/v5" "github.com/pg-sharding/spqr/balancer" @@ -14,8 +17,6 @@ import ( "github.com/pg-sharding/spqr/pkg/spqrlog" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - "sort" - "strings" ) type BalancerImpl struct { @@ -346,10 +347,11 @@ func (b *BalancerImpl) getKRCondition(rel *distributions.DistributedRelation, kR } else { hashedCol = entry.Column } + // TODO: fix multidim case if nextKR != nil { - buf[i] = fmt.Sprintf("%s >= %s AND %s < %s", hashedCol, string(kRange.LowerBound), hashedCol, string(nextKR.LowerBound)) + buf[i] = fmt.Sprintf("%s >= %s AND %s < %s", hashedCol, kRange.SendRaw()[0], hashedCol, nextKR.SendRaw()[0]) } else { - buf[i] = fmt.Sprintf("%s >= %s", hashedCol, string(kRange.LowerBound)) + buf[i] = fmt.Sprintf("%s >= %s", hashedCol, kRange.SendRaw()[0]) } } return strings.Join(buf, " AND "), nil @@ -666,6 +668,7 @@ func (b *BalancerImpl) executeTasks(ctx context.Context, group *tasks.TaskGroup) func (b *BalancerImpl) updateKeyRanges(ctx context.Context) error { keyRangeService := protos.NewKeyRangeServiceClient(b.coordinatorConn) + distrService := protos.NewDistributionServiceClient(b.coordinatorConn) keyRangesProto, err := keyRangeService.ListAllKeyRanges(ctx, &protos.ListAllKeyRangesRequest{}) if err != nil { return err @@ -675,11 +678,17 @@ func (b *BalancerImpl) updateKeyRanges(ctx context.Context) error { if _, ok := keyRanges[krProto.DistributionId]; !ok { keyRanges[krProto.DistributionId] = make([]*kr.KeyRange, 0) } - keyRanges[krProto.DistributionId] = append(keyRanges[krProto.DistributionId], kr.KeyRangeFromProto(krProto)) + ds, err := distrService.GetDistribution(ctx, &protos.GetDistributionRequest{ + Id: krProto.DistributionId, + }) + if err != nil { + return err + } + keyRanges[krProto.DistributionId] = append(keyRanges[krProto.DistributionId], kr.KeyRangeFromProto(krProto, ds.Distribution.ColumnTypes)) } for _, krs := range keyRanges { sort.Slice(krs, func(i, j int) bool { - return kr.CmpRangesLess(krs[i].LowerBound, krs[j].LowerBound) + return kr.CmpRangesLess(krs[i].LowerBound, krs[j].LowerBound, krs[j].ColumnTypes) }) } diff --git a/cmd/mover/main.go b/cmd/mover/main.go index 59db82d80..80f1037a5 100644 --- a/cmd/mover/main.go +++ b/cmd/mover/main.go @@ -4,11 +4,12 @@ import ( "context" "flag" "fmt" - "github.com/pg-sharding/spqr/pkg/models/distributions" "io" "os" "strings" + "github.com/pg-sharding/spqr/pkg/models/distributions" + "github.com/jackc/pgx/v5" _ "github.com/lib/pq" "github.com/pg-sharding/spqr/pkg/models/kr" @@ -103,10 +104,10 @@ FROM information_schema.tables; // TODO: support multi-column move in SPQR2 if nextKeyRange == nil { qry = fmt.Sprintf("copy (delete from %s WHERE %s >= %s returning *) to stdout", rel.Name, - rel.DistributionKey[0].Column, keyRange.LowerBound) + rel.DistributionKey[0].Column, keyRange.SendRaw()[0]) } else { qry = fmt.Sprintf("copy (delete from %s WHERE %s >= %s and %s < %s returning *) to stdout", rel.Name, - rel.DistributionKey[0].Column, keyRange.LowerBound, rel.DistributionKey[0].Column, nextKeyRange.LowerBound) + rel.DistributionKey[0].Column, keyRange.SendRaw()[0], rel.DistributionKey[0].Column, nextKeyRange.SendRaw()[0]) } spqrlog.Zero.Debug(). @@ -132,6 +133,7 @@ FROM information_schema.tables; spqrlog.Zero.Debug().Msg("copy cmd executed") } + /* TODO: handle errors here */ _ = txTo.Commit(ctx) _ = txFrom.Commit(ctx) return nil @@ -165,7 +167,14 @@ func main() { spqrlog.Zero.Error().Err(err).Msg("") return } - keyRange := kr.KeyRangeFromDB(qdbKr) + + ds, err := db.GetDistribution(ctx, qdbKr.DistributionId) + if err != nil { + spqrlog.Zero.Error().Err(err).Msg("") + return + } + + keyRange := kr.KeyRangeFromDB(qdbKr, ds.ColTypes) krs, err := db.ListKeyRanges(ctx, keyRange.Distribution) if err != nil { @@ -176,9 +185,10 @@ func main() { var nextKeyRange *kr.KeyRange for _, currkr := range krs { - if kr.CmpRangesLess(keyRange.LowerBound, currkr.LowerBound) { - if nextKeyRange == nil || kr.CmpRangesLess(currkr.LowerBound, nextKeyRange.LowerBound) { - nextKeyRange = kr.KeyRangeFromDB(currkr) + typedKr := kr.KeyRangeFromDB(currkr, ds.ColTypes) + if kr.CmpRangesLess(keyRange.LowerBound, typedKr.LowerBound, ds.ColTypes) { + if nextKeyRange == nil || kr.CmpRangesLess(typedKr.LowerBound, nextKeyRange.LowerBound, ds.ColTypes) { + nextKeyRange = typedKr } } } diff --git a/cmd/spqrdump/main.go b/cmd/spqrdump/main.go index d736d1ccd..f0d5a866d 100644 --- a/cmd/spqrdump/main.go +++ b/cmd/spqrdump/main.go @@ -12,6 +12,7 @@ import ( "google.golang.org/grpc" "github.com/pg-sharding/spqr/pkg/conn" + "github.com/pg-sharding/spqr/pkg/models/kr" "github.com/pg-sharding/spqr/pkg/spqrlog" "github.com/pg-sharding/spqr/pkg/decode" @@ -25,7 +26,7 @@ func Dial(addr string) (*grpc.ClientConn, error) { } var rootCmd = &cobra.Command{ - Use: "spqrdump -e localhost:7003", + Use: "spqr-dump -e localhost:7003", CompletionOptions: cobra.CompletionOptions{ DisableDefaultCmd: true, }, @@ -116,14 +117,16 @@ func getconn() (*pgproto3.Frontend, error) { // TODO : unit tests func DumpKeyRangesPsql() error { return dumpPsql("SHOW key_ranges;", func(v *pgproto3.DataRow) (string, error) { - l := string(v.Values[2]) + l := v.Values[2] id := string(v.Values[0]) shard := string(v.Values[1]) return decode.KeyRange( - &protos.KeyRangeInfo{ - KeyRange: &protos.KeyRange{LowerBound: l}, - ShardId: shard, Krid: id}), nil + &kr.KeyRange{ + LowerBound: []interface{}{l}, + ID: id, + ShardID: shard, + }), nil }) } @@ -171,13 +174,21 @@ func DumpKeyRanges() error { } rCl := protos.NewKeyRangeServiceClient(cc) + dCl := protos.NewDistributionServiceClient(cc) if keys, err := rCl.ListAllKeyRanges(context.Background(), &protos.ListAllKeyRangesRequest{}); err != nil { spqrlog.Zero.Error(). Err(err). Msg("failed to dump endpoint rules") } else { for _, krg := range keys.KeyRangesInfo { - fmt.Println(decode.KeyRange(krg)) + ds, err := dCl.GetDistribution(context.Background(), &protos.GetDistributionRequest{ + Id: krg.DistributionId, + }) + if err != nil { + return err + } + krCurr := kr.KeyRangeFromProto(krg, ds.Distribution.ColumnTypes) + fmt.Println(decode.KeyRange(krCurr)) } } @@ -260,7 +271,7 @@ var dump = &cobra.Command{ } spqrlog.Zero.Debug(). Str("endpoint", endpoint). - Msg("dialing spqrdump on") + Msg("dialing spqr-dump on") switch proto { case "grpc": diff --git a/coordinator/provider/coordinator.go b/coordinator/provider/coordinator.go index c8d436c43..4502e7419 100644 --- a/coordinator/provider/coordinator.go +++ b/coordinator/provider/coordinator.go @@ -427,7 +427,7 @@ func (qc *qdbCoordinator) AddRouter(ctx context.Context, router *topology.Router func (qc *qdbCoordinator) CreateKeyRange(ctx context.Context, keyRange *kr.KeyRange) error { // add key range to metadb spqrlog.Zero.Debug(). - Bytes("lower-bound", keyRange.LowerBound). + Bytes("lower-bound", keyRange.Raw()[0]). Str("shard-id", keyRange.ShardID). Str("key-range-id", keyRange.ID). Msg("add key range") @@ -461,7 +461,11 @@ func (qc *qdbCoordinator) GetKeyRange(ctx context.Context, krId string) (*kr.Key if err != nil { return nil, err } - return kr.KeyRangeFromDB(krDb), nil + ds, err := qc.db.GetDistribution(ctx, krDb.DistributionId) + if err != nil { + return nil, err + } + return kr.KeyRangeFromDB(krDb, ds.ColTypes), nil } // TODO : unit tests @@ -473,7 +477,11 @@ func (qc *qdbCoordinator) ListKeyRanges(ctx context.Context, distribution string keyr := make([]*kr.KeyRange, 0, len(keyRanges)) for _, keyRange := range keyRanges { - keyr = append(keyr, kr.KeyRangeFromDB(keyRange)) + ds, err := qc.db.GetDistribution(ctx, keyRange.DistributionId) + if err != nil { + return nil, err + } + keyr = append(keyr, kr.KeyRangeFromDB(keyRange, ds.ColTypes)) } return keyr, nil @@ -488,7 +496,11 @@ func (qc *qdbCoordinator) ListAllKeyRanges(ctx context.Context) ([]*kr.KeyRange, keyr := make([]*kr.KeyRange, 0, len(keyRanges)) for _, keyRange := range keyRanges { - keyr = append(keyr, kr.KeyRangeFromDB(keyRange)) + ds, err := qc.db.GetDistribution(ctx, keyRange.DistributionId) + if err != nil { + return nil, err + } + keyr = append(keyr, kr.KeyRangeFromDB(keyRange, ds.ColTypes)) } return keyr, nil @@ -501,12 +513,18 @@ func (qc *qdbCoordinator) MoveKeyRange(ctx context.Context, keyRange *kr.KeyRang // TODO : unit tests func (qc *qdbCoordinator) LockKeyRange(ctx context.Context, keyRangeID string) (*kr.KeyRange, error) { - keyRangeDB, err := qc.db.LockKeyRange(ctx, keyRangeID) + + keyRangeDB, err := qc.QDB().LockKeyRange(ctx, keyRangeID) + if err != nil { + return nil, err + } + ds, err := qc.QDB().GetDistribution(ctx, keyRangeDB.DistributionId) if err != nil { + _ = qc.QDB().UnlockKeyRange(ctx, keyRangeID) return nil, err } - keyRange := kr.KeyRangeFromDB(keyRangeDB) + keyRange := kr.KeyRangeFromDB(keyRangeDB, ds.ColTypes) return keyRange, qc.traverseRouters(ctx, func(cc *grpc.ClientConn) error { cl := routerproto.NewKeyRangeServiceClient(cc) @@ -558,61 +576,68 @@ func (qc *qdbCoordinator) Split(ctx context.Context, req *kr.SplitKeyRange) erro return spqrerror.Newf(spqrerror.SPQR_KEYRANGE_ERROR, "key range %v already present in qdb", req.Krid) } - krOld, err := qc.db.LockKeyRange(ctx, req.SourceID) + krOld, err := qc.LockKeyRange(ctx, req.SourceID) if err != nil { return err } defer func() { - if err := qc.db.UnlockKeyRange(ctx, req.SourceID); err != nil { + if err := qc.UnlockKeyRange(ctx, req.SourceID); err != nil { spqrlog.Zero.Error().Err(err).Msg("") } }() - ds, err := qc.db.GetDistribution(ctx, krOld.DistributionId) + ds, err := qc.db.GetDistribution(ctx, krOld.Distribution) if err != nil { return err } - if kr.CmpRangesEqual(krOld.LowerBound, req.Bound) { + eph := kr.KeyRangeFromBytes(req.Bound, ds.ColTypes) + + if kr.CmpRangesEqual(krOld.LowerBound, eph.LowerBound, ds.ColTypes) { return spqrerror.New(spqrerror.SPQR_KEYRANGE_ERROR, "failed to split because bound equals lower of the key range") } - if kr.CmpRangesLess(req.Bound, krOld.LowerBound) { + if kr.CmpRangesLess(eph.LowerBound, krOld.LowerBound, ds.ColTypes) { return spqrerror.New(spqrerror.SPQR_KEYRANGE_ERROR, "failed to split because bound is out of key range") } - krs, err := qc.db.ListKeyRanges(ctx, ds.ID) + krs, err := qc.ListKeyRanges(ctx, ds.ID) if err != nil { return err } for _, kRange := range krs { - if kr.CmpRangesLess(krOld.LowerBound, kRange.LowerBound) && kr.CmpRangesLessEqual(kRange.LowerBound, req.Bound) { - return spqrerror.Newf(spqrerror.SPQR_KEYRANGE_ERROR, "failed to split because bound intersects with \"%s\" key range", kRange.KeyRangeID) + if kr.CmpRangesLess(krOld.LowerBound, kRange.LowerBound, ds.ColTypes) && kr.CmpRangesLessEqual(kRange.LowerBound, eph.LowerBound, ds.ColTypes) { + return spqrerror.Newf(spqrerror.SPQR_KEYRANGE_ERROR, "failed to split because bound intersects with \"%s\" key range", kRange.ID) } } - krNew := &kr.KeyRange{ - LowerBound: func() []byte { - if req.SplitLeft { - return krOld.LowerBound - } - return req.Bound - }(), - ID: req.Krid, - ShardID: krOld.ShardID, - Distribution: krOld.DistributionId, - } + krNew := kr.KeyRangeFromDB( + &qdb.KeyRange{ + // fix multidim case + LowerBound: func() []byte { + if req.SplitLeft { + return krOld.Raw()[0] + } + return req.Bound[0] + }(), + KeyRangeID: req.Krid, + ShardID: krOld.ShardID, + DistributionId: krOld.Distribution, + }, + ds.ColTypes, + ) spqrlog.Zero.Debug(). - Bytes("lower-bound", krNew.LowerBound). + Bytes("lower-bound", krNew.Raw()[0]). Str("shard-id", krNew.ShardID). Str("id", krNew.ID). Msg("new key range") if req.SplitLeft { - krOld.LowerBound = req.Bound + krOld.LowerBound = kr.KeyRangeFromBytes(req.Bound, ds.ColTypes).LowerBound } - if err := ops.ModifyKeyRangeWithChecks(ctx, qc.db, kr.KeyRangeFromDB(krOld)); err != nil { + + if err := ops.ModifyKeyRangeWithChecks(ctx, qc.db, krOld); err != nil { return err } @@ -623,7 +648,7 @@ func (qc *qdbCoordinator) Split(ctx context.Context, req *kr.SplitKeyRange) erro if err := qc.traverseRouters(ctx, func(cc *grpc.ClientConn) error { cl := routerproto.NewKeyRangeServiceClient(cc) resp, err := cl.SplitKeyRange(ctx, &routerproto.SplitKeyRangeRequest{ - Bound: req.Bound, + Bound: req.Bound[0], // fix multidim case SourceId: req.SourceID, NewId: krNew.ID, }) @@ -681,24 +706,24 @@ func (qc *qdbCoordinator) DropKeyRange(ctx context.Context, id string) error { // TODO : unit tests func (qc *qdbCoordinator) Unite(ctx context.Context, uniteKeyRange *kr.UniteKeyRange) error { - krBase, err := qc.db.LockKeyRange(ctx, uniteKeyRange.BaseKeyRangeId) + krBase, err := qc.LockKeyRange(ctx, uniteKeyRange.BaseKeyRangeId) if err != nil { return err } defer func() { - if err := qc.db.UnlockKeyRange(ctx, uniteKeyRange.BaseKeyRangeId); err != nil { + if err := qc.UnlockKeyRange(ctx, uniteKeyRange.BaseKeyRangeId); err != nil { spqrlog.Zero.Error().Err(err).Msg("") } }() - krAppendage, err := qc.db.LockKeyRange(ctx, uniteKeyRange.AppendageKeyRangeId) + krAppendage, err := qc.LockKeyRange(ctx, uniteKeyRange.AppendageKeyRangeId) if err != nil { return err } defer func() { - if err := qc.db.UnlockKeyRange(ctx, uniteKeyRange.AppendageKeyRangeId); err != nil { + if err := qc.UnlockKeyRange(ctx, uniteKeyRange.AppendageKeyRangeId); err != nil { spqrlog.Zero.Error().Err(err).Msg("") } }() @@ -706,41 +731,41 @@ func (qc *qdbCoordinator) Unite(ctx context.Context, uniteKeyRange *kr.UniteKeyR if krBase.ShardID != krAppendage.ShardID { return spqrerror.New(spqrerror.SPQR_KEYRANGE_ERROR, "failed to unite key ranges routing different shards") } - if krBase.DistributionId != krAppendage.DistributionId { + if krBase.Distribution != krAppendage.Distribution { return spqrerror.New(spqrerror.SPQR_KEYRANGE_ERROR, "failed to unite key ranges of different distributions") } - ds, err := qc.db.GetDistribution(ctx, krBase.DistributionId) + ds, err := qc.db.GetDistribution(ctx, krBase.Distribution) if err != nil { return err } // TODO: check all types when composite keys are supported krLeft, krRight := krBase, krAppendage - if kr.CmpRangesLess(krRight.LowerBound, krLeft.LowerBound) { + if kr.CmpRangesLess(krRight.LowerBound, krLeft.LowerBound, ds.ColTypes) { krLeft, krRight = krRight, krLeft } - krs, err := qc.db.ListKeyRanges(ctx, ds.ID) + krs, err := qc.ListKeyRanges(ctx, ds.ID) if err != nil { return err } for _, kRange := range krs { - if kRange.KeyRangeID != krLeft.KeyRangeID && - kRange.KeyRangeID != krRight.KeyRangeID && - kr.CmpRangesLessEqual(krLeft.LowerBound, kRange.LowerBound) && - kr.CmpRangesLessEqual(kRange.LowerBound, krRight.LowerBound) { + if kRange.ID != krLeft.ID && + kRange.ID != krRight.ID && + kr.CmpRangesLessEqual(krLeft.LowerBound, kRange.LowerBound, ds.ColTypes) && + kr.CmpRangesLessEqual(kRange.LowerBound, krRight.LowerBound, ds.ColTypes) { return spqrerror.New(spqrerror.SPQR_KEYRANGE_ERROR, "failed to unite non-adjacent key ranges") } } - if err := qc.db.DropKeyRange(ctx, krAppendage.KeyRangeID); err != nil { + if err := qc.db.DropKeyRange(ctx, krAppendage.ID); err != nil { return spqrerror.Newf(spqrerror.SPQR_KEYRANGE_ERROR, "failed to drop an old key range: %s", err.Error()) } - if krLeft.KeyRangeID != krBase.KeyRangeID { + if krLeft.ID != krBase.ID { krBase.LowerBound = krAppendage.LowerBound } - if err := ops.ModifyKeyRangeWithChecks(ctx, qc.db, kr.KeyRangeFromDB(krBase)); err != nil { + if err := ops.ModifyKeyRangeWithChecks(ctx, qc.db, krBase); err != nil { return spqrerror.Newf(spqrerror.SPQR_KEYRANGE_ERROR, "failed to update a new key range: %s", err.Error()) } @@ -927,8 +952,12 @@ func (qc *qdbCoordinator) SyncRouterMetadata(ctx context.Context, qRouter *topol } for _, keyRange := range keyRanges { + ds, err := qc.db.GetDistribution(ctx, keyRange.DistributionId) + if err != nil { + return err + } resp, err := krClient.CreateKeyRange(ctx, &routerproto.CreateKeyRangeRequest{ - KeyRangeInfo: kr.KeyRangeFromDB(keyRange).ToProto(), + KeyRangeInfo: kr.KeyRangeFromDB(keyRange, ds.ColTypes).ToProto(), }) if err != nil { diff --git a/coordinator/provider/keyranges.go b/coordinator/provider/keyranges.go index d81d7e1fd..059607441 100644 --- a/coordinator/provider/keyranges.go +++ b/coordinator/provider/keyranges.go @@ -18,7 +18,12 @@ type CoordinatorService struct { // TODO : unit tests func (c *CoordinatorService) CreateKeyRange(ctx context.Context, request *protos.CreateKeyRangeRequest) (*protos.ModifyReply, error) { - err := c.impl.CreateKeyRange(ctx, kr.KeyRangeFromProto(request.KeyRangeInfo)) + ds, err := c.impl.GetDistribution(ctx, request.KeyRangeInfo.DistributionId) + if err != nil { + return nil, err + } + + err = c.impl.CreateKeyRange(ctx, kr.KeyRangeFromProto(request.KeyRangeInfo, ds.ColTypes)) if err != nil { return nil, err } @@ -50,7 +55,7 @@ func (c *CoordinatorService) UnlockKeyRange(ctx context.Context, request *protos // TODO : unit tests func (c *CoordinatorService) SplitKeyRange(ctx context.Context, request *protos.SplitKeyRangeRequest) (*protos.ModifyReply, error) { splitKR := &kr.SplitKeyRange{ - Bound: request.Bound, + Bound: [][]byte{request.Bound}, // fix multidim case Krid: request.NewId, SourceID: request.SourceId, SplitLeft: request.SplitLeft, diff --git a/pkg/clientinteractor/interactor.go b/pkg/clientinteractor/interactor.go index 39c89b48e..4fc1cac34 100644 --- a/pkg/clientinteractor/interactor.go +++ b/pkg/clientinteractor/interactor.go @@ -211,8 +211,6 @@ func (pi *PSQLInteractor) DropShard(id string) error { // TODO : unit tests func (pi *PSQLInteractor) KeyRanges(krs []*kr.KeyRange) error { - spqrlog.Zero.Debug().Msg("listing key ranges") - for _, msg := range []pgproto3.BackendMessage{ &pgproto3.RowDescription{Fields: []pgproto3.FieldDescription{ TextOidFD("Key range ID"), @@ -234,7 +232,7 @@ func (pi *PSQLInteractor) KeyRanges(krs []*kr.KeyRange) error { []byte(keyRange.ID), []byte(keyRange.ShardID), []byte(keyRange.Distribution), - keyRange.LowerBound, + []byte(strings.Join(keyRange.SendRaw(), ",")), }, }); err != nil { spqrlog.Zero.Error().Err(err).Msg("") @@ -252,7 +250,7 @@ func (pi *PSQLInteractor) CreateKeyRange(ctx context.Context, keyRange *kr.KeyRa } for _, msg := range []pgproto3.BackendMessage{ - &pgproto3.DataRow{Values: [][]byte{[]byte(fmt.Sprintf("created key range with bound %s", keyRange.LowerBound))}}, + &pgproto3.DataRow{Values: [][]byte{[]byte(fmt.Sprintf("created key range with bound %s", keyRange.SendRaw()[0]))}}, } { if err := pi.cl.Send(msg); err != nil { spqrlog.Zero.Error().Err(err).Msg("") @@ -271,7 +269,8 @@ func (pi *PSQLInteractor) SplitKeyRange(ctx context.Context, split *kr.SplitKeyR } for _, msg := range []pgproto3.BackendMessage{ - &pgproto3.DataRow{Values: [][]byte{[]byte(fmt.Sprintf("split key range %v by %s", split.SourceID, string(split.Bound)))}}, + // fix multidim case + &pgproto3.DataRow{Values: [][]byte{[]byte(fmt.Sprintf("split key range %v by %s", split.SourceID, string(split.Bound[0])))}}, } { if err := pi.cl.Send(msg); err != nil { spqrlog.Zero.Error().Err(err).Msg("") diff --git a/pkg/coord/adapter.go b/pkg/coord/adapter.go index 0264a8712..ee027a7ce 100644 --- a/pkg/coord/adapter.go +++ b/pkg/coord/adapter.go @@ -44,16 +44,26 @@ func (a *Adapter) ShareKeyRange(id string) error { // TODO unit tests func (a *Adapter) GetKeyRange(ctx context.Context, krId string) (*kr.KeyRange, error) { c := proto.NewKeyRangeServiceClient(a.conn) + cdistr := proto.NewDistributionServiceClient(a.conn) reply, err := c.GetKeyRange(ctx, &proto.GetKeyRangeRequest{ Ids: []string{krId}, }) if err != nil { return nil, err } + // what if len > 1 ? if len(reply.KeyRangesInfo) == 0 { return nil, nil } - return kr.KeyRangeFromProto(reply.KeyRangesInfo[0]), nil + ds, err := cdistr.GetDistribution(ctx, &proto.GetDistributionRequest{ + Id: reply.KeyRangesInfo[0].DistributionId, + }) + + if err != nil { + return nil, err + } + + return kr.KeyRangeFromProto(reply.KeyRangesInfo[0], ds.Distribution.ColumnTypes), nil } // TODO : unit tests @@ -66,9 +76,14 @@ func (a *Adapter) ListKeyRanges(ctx context.Context, distribution string) ([]*kr return nil, err } + ds, err := a.QDB().GetDistribution(ctx, distribution) + if err != nil { + return nil, err + } + krs := make([]*kr.KeyRange, len(reply.KeyRangesInfo)) for i, keyRange := range reply.KeyRangesInfo { - krs[i] = kr.KeyRangeFromProto(keyRange) + krs[i] = kr.KeyRangeFromProto(keyRange, ds.ColTypes) } return krs, nil @@ -84,7 +99,11 @@ func (a *Adapter) ListAllKeyRanges(ctx context.Context) ([]*kr.KeyRange, error) krs := make([]*kr.KeyRange, len(reply.KeyRangesInfo)) for i, keyRange := range reply.KeyRangesInfo { - krs[i] = kr.KeyRangeFromProto(keyRange) + ds, err := a.QDB().GetDistribution(ctx, keyRange.DistributionId) + if err != nil { + return nil, err + } + krs[i] = kr.KeyRangeFromProto(keyRange, ds.ColTypes) } return krs, nil @@ -146,8 +165,12 @@ func (a *Adapter) Split(ctx context.Context, split *kr.SplitKeyRange) error { for _, keyRange := range krs { if keyRange.ID == split.SourceID { c := proto.NewKeyRangeServiceClient(a.conn) + + nkr := keyRange.ToProto() + nkr.Krid = split.Krid + _, err := c.SplitKeyRange(ctx, &proto.SplitKeyRangeRequest{ - Bound: split.Bound, + Bound: split.Bound[0], // fix multidim case SourceId: split.SourceID, NewId: split.Krid, SplitLeft: split.SplitLeft, @@ -179,7 +202,7 @@ func (a *Adapter) Unite(ctx context.Context, unite *kr.UniteKeyRange) error { } } - if kr.CmpRangesLess(right.LowerBound, left.LowerBound) { + if kr.CmpRangesLess(right.LowerBound, left.LowerBound, right.ColumnTypes) { left, right = right, left } @@ -187,12 +210,12 @@ func (a *Adapter) Unite(ctx context.Context, unite *kr.UniteKeyRange) error { if krCurr.ID == unite.BaseKeyRangeId || krCurr.ID == unite.AppendageKeyRangeId { continue } - if kr.CmpRangesLess(krCurr.LowerBound, right.LowerBound) && kr.CmpRangesLess(left.LowerBound, krCurr.LowerBound) { + if kr.CmpRangesLess(krCurr.LowerBound, right.LowerBound, krCurr.ColumnTypes) && kr.CmpRangesLess(left.LowerBound, krCurr.LowerBound, krCurr.ColumnTypes) { return spqrerror.New(spqrerror.SPQR_KEYRANGE_ERROR, "unvalid unite request") } } - if left == nil || right == nil || kr.CmpRangesLess(right.LowerBound, left.LowerBound) { + if left == nil || right == nil || kr.CmpRangesLess(right.LowerBound, left.LowerBound, right.ColumnTypes) { return spqrerror.New(spqrerror.SPQR_KEYRANGE_ERROR, "key range on left or right was not found") } diff --git a/pkg/coord/local/clocal.go b/pkg/coord/local/clocal.go index 693906f78..6d6e1520b 100644 --- a/pkg/coord/local/clocal.go +++ b/pkg/coord/local/clocal.go @@ -71,6 +71,9 @@ func (lc *LocalCoordinator) ListDistributions(ctx context.Context) ([]*distribut func (lc *LocalCoordinator) CreateDistribution(ctx context.Context, ds *distributions.Distribution) error { lc.mu.Lock() defer lc.mu.Unlock() + if len(ds.ColTypes) == 0 { + return fmt.Errorf("empty distributions are disallowed") + } return lc.qdb.CreateDistribution(ctx, distributions.DistributionToDB(ds)) } @@ -79,8 +82,16 @@ func (lc *LocalCoordinator) AlterDistributionAttach(ctx context.Context, id stri lc.mu.Lock() defer lc.mu.Unlock() + ds, err := lc.qdb.GetDistribution(ctx, id) + if err != nil { + return err + } + dRels := []*qdb.DistributedRelation{} for _, r := range rels { + if len(r.DistributionKey) != len(ds.ColTypes) { + return fmt.Errorf("cannot attach relation %v to this dataspace: number of column mismatch", r.Name) + } dRels = append(dRels, distributions.DistributedRelationToDB(r)) } @@ -254,6 +265,7 @@ func (lc *LocalCoordinator) WorldShards() []string { return ret } +// Caller should lock key range // TODO : unit tests func (qr *LocalCoordinator) Move(ctx context.Context, req *kr.MoveKeyRange) error { var krmv *qdb.KeyRange @@ -262,30 +274,33 @@ func (qr *LocalCoordinator) Move(ctx context.Context, req *kr.MoveKeyRange) erro return err } - var reqKr = kr.KeyRangeFromDB(krmv) + ds, err := qr.qdb.GetDistribution(ctx, krmv.DistributionId) + if err != nil { + return err + } + + var reqKr = kr.KeyRangeFromDB(krmv, ds.ColTypes) reqKr.ShardID = req.ShardId return ops.ModifyKeyRangeWithChecks(ctx, qr.qdb, reqKr) } +// Caller should lock both key ranges // TODO : unit tests func (qr *LocalCoordinator) Unite(ctx context.Context, req *kr.UniteKeyRange) error { var krBase *qdb.KeyRange var krAppendage *qdb.KeyRange var err error - if krBase, err = qr.qdb.LockKeyRange(ctx, req.BaseKeyRangeId); err != nil { //nolint:all TODO + if krBase, err = qr.qdb.CheckLockedKeyRange(ctx, req.BaseKeyRangeId); err != nil { //nolint:all TODO + return err + } + ds, err := qr.qdb.GetDistribution(ctx, krBase.DistributionId) + if err != nil { return err } - defer func(qdb qdb.QDB, ctx context.Context, keyRangeID string) { - err := qdb.UnlockKeyRange(ctx, keyRangeID) - if err != nil { - spqrlog.Zero.Error().Err(err).Msg("") - return - } - }(qr.qdb, ctx, req.BaseKeyRangeId) // TODO: krRight seems to be empty. - if krAppendage, err = qr.qdb.GetKeyRange(ctx, req.AppendageKeyRangeId); err != nil { + if krAppendage, err = qr.qdb.CheckLockedKeyRange(ctx, req.AppendageKeyRangeId); err != nil { return err } @@ -294,20 +309,18 @@ func (qr *LocalCoordinator) Unite(ctx context.Context, req *kr.UniteKeyRange) er } newBound := krBase.LowerBound - if kr.CmpRangesLess(krAppendage.LowerBound, krBase.LowerBound) { + if kr.CmpRangesLess(kr.KeyRangeFromDB(krAppendage, ds.ColTypes).LowerBound, kr.KeyRangeFromDB(krBase, ds.ColTypes).LowerBound, ds.ColTypes) { newBound = krAppendage.LowerBound } - united := &kr.KeyRange{ - LowerBound: newBound, - ShardID: krBase.ShardID, - Distribution: krBase.DistributionId, - ID: krBase.KeyRangeID, - } + krBaseCopy := krBase + krBaseCopy.LowerBound = newBound + united := kr.KeyRangeFromDB(krBaseCopy, ds.ColTypes) return ops.ModifyKeyRangeWithChecks(ctx, qr.qdb, united) } +// Caller should lock key range // TODO : unit tests func (qr *LocalCoordinator) Split(ctx context.Context, req *kr.SplitKeyRange) error { var krOld *qdb.KeyRange @@ -319,38 +332,41 @@ func (qr *LocalCoordinator) Split(ctx context.Context, req *kr.SplitKeyRange) er Str("source-id", req.SourceID). Msg("split request is") - if krOld, err = qr.qdb.LockKeyRange(ctx, req.SourceID); err != nil { + if krOld, err = qr.qdb.CheckLockedKeyRange(ctx, req.SourceID); err != nil { return err } - defer func() { - if err := qr.qdb.UnlockKeyRange(ctx, req.SourceID); err != nil { - spqrlog.Zero.Error().Err(err).Msg("") - } - }() - - krNew := &kr.KeyRange{ - LowerBound: func() []byte { - if req.SplitLeft { - return krOld.LowerBound - } - return req.Bound - }(), - ID: req.Krid, - ShardID: krOld.ShardID, - Distribution: krOld.DistributionId, + ds, err := qr.qdb.GetDistribution(ctx, krOld.DistributionId) + if err != nil { + return err } + krNew := kr.KeyRangeFromDB( + &qdb.KeyRange{ + LowerBound: func() []byte { + if req.SplitLeft { + return krOld.LowerBound + } + return req.Bound[0] // fix multidim case ! + }(), + KeyRangeID: req.Krid, + ShardID: krOld.ShardID, + DistributionId: krOld.DistributionId, + }, + ds.ColTypes, + ) + spqrlog.Zero.Debug(). - Bytes("lower-bound", krNew.LowerBound). + Bytes("lower-bound", krNew.Raw()[0]). Str("shard-id", krNew.ShardID). Str("id", krNew.ID). Msg("new key range") if req.SplitLeft { - krOld.LowerBound = req.Bound + krOld.LowerBound = req.Bound[0] // TODO: fix } - if err := ops.ModifyKeyRangeWithChecks(ctx, qr.qdb, kr.KeyRangeFromDB(krOld)); err != nil { + + if err := ops.ModifyKeyRangeWithChecks(ctx, qr.qdb, kr.KeyRangeFromDB(krOld, ds.ColTypes)); err != nil { return err } @@ -368,7 +384,12 @@ func (qr *LocalCoordinator) LockKeyRange(ctx context.Context, krid string) (*kr. return nil, err } - return kr.KeyRangeFromDB(keyRangeDB), nil + ds, err := qr.qdb.GetDistribution(ctx, keyRangeDB.DistributionId) + if err != nil { + return nil, err + } + + return kr.KeyRangeFromDB(keyRangeDB, ds.ColTypes), nil } // TODO : unit tests @@ -408,7 +429,11 @@ func (lc *LocalCoordinator) GetKeyRange(ctx context.Context, krId string) (*kr.K if err != nil { return nil, err } - return kr.KeyRangeFromDB(krDb), nil + ds, err := lc.qdb.GetDistribution(ctx, krDb.DistributionId) + if err != nil { + return nil, err + } + return kr.KeyRangeFromDB(krDb, ds.ColTypes), nil } // TODO : unit tests @@ -418,8 +443,13 @@ func (qr *LocalCoordinator) ListKeyRanges(ctx context.Context, distribution stri return nil, err } else { for _, keyRange := range krs { - ret = append(ret, kr.KeyRangeFromDB(keyRange)) + ds, err := qr.qdb.GetDistribution(ctx, keyRange.DistributionId) + + if err != nil { + return nil, err + } + ret = append(ret, kr.KeyRangeFromDB(keyRange, ds.ColTypes)) } } @@ -433,8 +463,14 @@ func (qr *LocalCoordinator) ListAllKeyRanges(ctx context.Context) ([]*kr.KeyRang return nil, err } else { for _, keyRange := range krs { - ret = append(ret, kr.KeyRangeFromDB(keyRange)) + ds, err := qr.qdb.GetDistribution(ctx, keyRange.DistributionId) + + if err != nil { + return nil, err + } + + ret = append(ret, kr.KeyRangeFromDB(keyRange, ds.ColTypes)) } } diff --git a/pkg/coord/local/clocal_test.go b/pkg/coord/local/clocal_test.go new file mode 100644 index 000000000..521b6287f --- /dev/null +++ b/pkg/coord/local/clocal_test.go @@ -0,0 +1 @@ +package local_test diff --git a/pkg/datatransfers/data_transfers.go b/pkg/datatransfers/data_transfers.go index 6a16d699c..073941186 100644 --- a/pkg/datatransfers/data_transfers.go +++ b/pkg/datatransfers/data_transfers.go @@ -3,12 +3,13 @@ package datatransfers import ( "context" "fmt" - "github.com/pg-sharding/spqr/pkg/models/distributions" "io" "os" "strings" "sync" + "github.com/pg-sharding/spqr/pkg/models/distributions" + pgx "github.com/jackc/pgx/v5" _ "github.com/lib/pq" "github.com/pg-sharding/spqr/pkg/config" @@ -115,21 +116,23 @@ func MoveKeys(ctx context.Context, fromId, toId string, keyr qdb.KeyRange, db qd } }(ctx) - var nextKeyRange *kr.KeyRange - moveKeyRange := kr.KeyRangeFromDB(&keyr) qdbDs, err := db.GetDistribution(ctx, keyr.DistributionId) if err != nil { return err } + + var nextKeyRange *kr.KeyRange + moveKeyRange := kr.KeyRangeFromDB(&keyr, qdbDs.ColTypes) ds := distributions.DistributionFromDB(qdbDs) if krs, err := db.ListKeyRanges(ctx, moveKeyRange.Distribution); err != nil { return err } else { for _, currkr := range krs { - if kr.CmpRangesLess(moveKeyRange.LowerBound, currkr.LowerBound) { - if nextKeyRange == nil || kr.CmpRangesLess(currkr.LowerBound, nextKeyRange.LowerBound) { - nextKeyRange = kr.KeyRangeFromDB(currkr) + typedKr := kr.KeyRangeFromDB(currkr, qdbDs.ColTypes) + if kr.CmpRangesLess(moveKeyRange.LowerBound, typedKr.LowerBound, qdbDs.ColTypes) { + if nextKeyRange == nil || kr.CmpRangesLess(typedKr.LowerBound, nextKeyRange.LowerBound, qdbDs.ColTypes) { + nextKeyRange = typedKr } } } @@ -256,6 +259,7 @@ func rollbackTransactions(ctx context.Context, txTo, txFrom pgx.Tx) error { } // TODO enhance for multi-column sharding rules +// TODO: unite this logic with spqr-mover func moveData(ctx context.Context, keyRange, nextKeyRange *kr.KeyRange, rels map[string]*distributions.DistributedRelation, txTo, txFrom pgx.Tx) error { // TODO: use whole RFQN rows, err := txFrom.Query(ctx, ` @@ -295,10 +299,10 @@ FROM information_schema.tables; var qry string if nextKeyRange == nil { qry = fmt.Sprintf("COPY (DELETE FROM %s WHERE %s >= %s RETURNING *) TO STDOUT", rel.Name, - rel.DistributionKey[0].Column, keyRange.LowerBound) + rel.DistributionKey[0].Column, keyRange.SendRaw()[0]) } else { qry = fmt.Sprintf("COPY (DELETE FROM %s WHERE %s >= %s and %s < %s RETURNING *) TO STDOUT", rel.Name, - rel.DistributionKey[0].Column, keyRange.LowerBound, rel.DistributionKey[0].Column, nextKeyRange.LowerBound) + rel.DistributionKey[0].Column, keyRange.SendRaw()[0], rel.DistributionKey[0].Column, nextKeyRange.SendRaw()[0]) } go func() { @@ -311,6 +315,7 @@ FROM information_schema.tables; spqrlog.Zero.Error().Err(err).Msg("error closing pipe") } }() + _, err = txTo.Conn().PgConn().CopyFrom(ctx, r, fmt.Sprintf("COPY %s FROM STDIN", rel.Name)) if err != nil { diff --git a/pkg/decode/spqrql.go b/pkg/decode/spqrql.go index 3e7fe920e..a72624227 100644 --- a/pkg/decode/spqrql.go +++ b/pkg/decode/spqrql.go @@ -4,13 +4,14 @@ import ( "fmt" "strings" + "github.com/pg-sharding/spqr/pkg/models/kr" protos "github.com/pg-sharding/spqr/pkg/protos" ) // KeyRange returns query to create given key range -func KeyRange(krg *protos.KeyRangeInfo) string { +func KeyRange(krg *kr.KeyRange) string { /* TODO: composite key support */ - return fmt.Sprintf("CREATE KEY RANGE %s FROM %s ROUTE TO %s FOR DISTRIBUTION %s;", krg.Krid, krg.KeyRange.LowerBound, krg.ShardId, krg.DistributionId) + return fmt.Sprintf("CREATE KEY RANGE %s FROM %s ROUTE TO %s FOR DISTRIBUTION %s;", krg.ID, krg.SendRaw()[0], krg.ShardID, krg.Distribution) } // Distribution returns query to create given distribution diff --git a/pkg/decode/spqrql_test.go b/pkg/decode/spqrql_test.go index 1140b55ab..aef4956e9 100644 --- a/pkg/decode/spqrql_test.go +++ b/pkg/decode/spqrql_test.go @@ -1,22 +1,36 @@ package decode import ( + "testing" + + "github.com/pg-sharding/spqr/pkg/models/kr" protos "github.com/pg-sharding/spqr/pkg/protos" + "github.com/pg-sharding/spqr/qdb" "github.com/stretchr/testify/assert" - "testing" ) func TestKeyRange(t *testing.T) { assert := assert.New(t) assert.Equal("CREATE KEY RANGE kr1 FROM 10 ROUTE TO sh1 FOR DISTRIBUTION ds1;", - KeyRange(&protos.KeyRangeInfo{ - Krid: "kr1", - ShardId: "sh1", - DistributionId: "ds1", - KeyRange: &protos.KeyRange{ - LowerBound: "10", - }, + KeyRange(&kr.KeyRange{ + ID: "kr1", + ShardID: "sh1", + Distribution: "ds1", + LowerBound: []interface{}{10}, + + ColumnTypes: []string{qdb.ColumnTypeInteger}, })) + // UpperBound is ignored + assert.Equal("CREATE KEY RANGE kr1 FROM 10 ROUTE TO sh1 FOR DISTRIBUTION ds1;", + KeyRange( + &kr.KeyRange{ + ID: "kr1", + ShardID: "sh1", + Distribution: "ds1", + LowerBound: []interface{}{10}, + + ColumnTypes: []string{qdb.ColumnTypeInteger}, + })) } func TestDistribution(t *testing.T) { diff --git a/pkg/meta/meta.go b/pkg/meta/meta.go index 879065370..c3db6dc9b 100644 --- a/pkg/meta/meta.go +++ b/pkg/meta/meta.go @@ -163,7 +163,16 @@ func processCreate(ctx context.Context, astmt spqrparser.Statement, mngr EntityM case *spqrparser.ShardingRuleDefinition: return cli.ReportError(spqrerror.ShardingKeysRemoved) case *spqrparser.KeyRangeDefinition: - req := kr.KeyRangeFromSQL(stmt) + ds, err := mngr.GetDistribution(ctx, stmt.Distribution) + if err != nil { + spqrlog.Zero.Error().Err(err).Msg("Error when adding key range") + return cli.ReportError(err) + } + req, err := kr.KeyRangeFromSQL(stmt, ds.ColTypes) + if err != nil { + spqrlog.Zero.Error().Err(err).Msg("Error when adding key range") + return cli.ReportError(err) + } if err := mngr.CreateKeyRange(ctx, req); err != nil { spqrlog.Zero.Error().Err(err).Msg("Error when adding key range") return cli.ReportError(err) @@ -285,7 +294,7 @@ func Proc(ctx context.Context, tstmt spqrparser.Statement, mgr EntityMgr, ci con return ProcessKill(ctx, stmt, mgr, ci, cli) case *spqrparser.SplitKeyRange: splitKeyRange := &kr.SplitKeyRange{ - Bound: stmt.Border, + Bound: stmt.Border.Pivots, SourceID: stmt.KeyRangeFromID, Krid: stmt.KeyRangeID, } diff --git a/pkg/models/hashfunction/hashfunction.go b/pkg/models/hashfunction/hashfunction.go index 19c906580..03ec20b18 100644 --- a/pkg/models/hashfunction/hashfunction.go +++ b/pkg/models/hashfunction/hashfunction.go @@ -1,10 +1,11 @@ package hashfunction import ( + "encoding/binary" "fmt" - "strconv" "github.com/go-faster/city" + "github.com/pg-sharding/spqr/qdb" "github.com/spaolacci/murmur3" ) @@ -21,16 +22,52 @@ var ( errNoSuchHashFunction = fmt.Errorf("no such hash function") ) -func ApplyHashFunction(inp []byte, hf HashFunctionType) ([]byte, error) { +func ApplyHashFunction(inp interface{}, ctype string, hf HashFunctionType) (interface{}, error) { switch hf { case HashFunctionIdent: return inp, nil case HashFunctionMurmur: - h := murmur3.Sum32(inp) - return []byte(strconv.FormatUint(uint64(h), 10)), nil + switch ctype { + case qdb.ColumnTypeInteger: + buf := make([]byte, 8) + binary.PutVarint(buf, inp.(int64)) + h := murmur3.Sum64(buf) + return h, nil + + case qdb.ColumnTypeUinteger: + buf := make([]byte, 8) + binary.PutUvarint(buf, inp.(uint64)) + h := murmur3.Sum64(buf) + return h, nil + case qdb.ColumnTypeVarcharDeprecated: + fallthrough + case qdb.ColumnTypeVarchar: + h := murmur3.Sum64(inp.([]byte)) + return h, nil + default: + return nil, errNoSuchHashFunction + } case HashFunctionCity: - h := city.Hash32(inp) - return []byte(strconv.FormatUint(uint64(h), 10)), nil + switch ctype { + case qdb.ColumnTypeInteger: + buf := make([]byte, 8) + binary.PutVarint(buf, inp.(int64)) + h := city.Hash64(buf) + return h, nil + + case qdb.ColumnTypeUinteger: + buf := make([]byte, 8) + binary.PutUvarint(buf, inp.(uint64)) + h := city.Hash64(buf) + return h, nil + case qdb.ColumnTypeVarcharDeprecated: + fallthrough + case qdb.ColumnTypeVarchar: + h := city.Hash64(inp.([]byte)) + return h, nil + default: + return nil, errNoSuchHashFunction + } default: return nil, errNoSuchHashFunction } diff --git a/pkg/models/kr/keyrange.go b/pkg/models/kr/keyrange.go index a32dfff6e..534224f11 100644 --- a/pkg/models/kr/keyrange.go +++ b/pkg/models/kr/keyrange.go @@ -1,106 +1,302 @@ package kr import ( + "encoding/binary" + "fmt" + proto "github.com/pg-sharding/spqr/pkg/protos" "github.com/pg-sharding/spqr/qdb" spqrparser "github.com/pg-sharding/spqr/yacc/console" ) -type KeyRangeBound []byte +type KeyRangeBound []interface{} type ShardKey struct { Name string RW bool } +// qdb KeyRange with its distibtion column types +// stored in case struct for fast convertion/access type KeyRange struct { LowerBound KeyRangeBound ShardID string ID string Distribution string + + ColumnTypes []string } -// TODO : unit tests -func CmpRangesLess(kr []byte, other []byte) bool { - if len(kr) == len(other) { - return string(kr) < string(other) +func CmpRangesLessStringsDeprecated(bound string, key string) bool { + if len(bound) == len(key) { + return bound < key } - return len(kr) < len(other) + return len(bound) < len(key) } -// TODO : unit tests -func CmpRangesLessEqual(kr []byte, other []byte) bool { - if len(kr) == len(other) { - return string(kr) <= string(other) +func (kr *KeyRange) InFunc(attribInd int, raw []byte) { + switch kr.ColumnTypes[attribInd] { + case qdb.ColumnTypeInteger: + n, _ := binary.Varint(raw) + kr.LowerBound[attribInd] = n + case qdb.ColumnTypeUinteger: + n, _ := binary.Uvarint(raw) + kr.LowerBound[attribInd] = n + case qdb.ColumnTypeVarcharDeprecated: + fallthrough + case qdb.ColumnTypeVarchar: + kr.LowerBound[attribInd] = string(raw) + } +} + +func (kr *KeyRange) OutFunc(attribInd int) []byte { + switch kr.ColumnTypes[attribInd] { + case qdb.ColumnTypeInteger: + raw := make([]byte, 8) + _ = binary.PutVarint(raw, kr.LowerBound[attribInd].(int64)) + return raw + case qdb.ColumnTypeUinteger: + raw := make([]byte, 8) + _ = binary.PutUvarint(raw, kr.LowerBound[attribInd].(uint64)) + return raw + case qdb.ColumnTypeVarcharDeprecated: + fallthrough + case qdb.ColumnTypeVarchar: + return []byte(kr.LowerBound[attribInd].(string)) + } + return nil +} + +func (kr *KeyRange) SendFunc(attribInd int) string { + return fmt.Sprintf("%v", kr.LowerBound[attribInd]) +} + +func (kr *KeyRange) Raw() [][]byte { + res := make([][]byte, len(kr.ColumnTypes)) + + for i := 0; i < len(kr.ColumnTypes); i++ { + res[i] = kr.OutFunc(i) + } + + return res +} + +func (kr *KeyRange) SendRaw() []string { + res := make([]string, len(kr.ColumnTypes)) + + for i := 0; i < len(kr.ColumnTypes); i++ { + res[i] = kr.SendFunc(i) } - return len(kr) < len(other) + return res } +// TODO: use it +var MissTypedKeyRange = fmt.Errorf("key range bound is mistyped") + // TODO : unit tests -func CmpRangesEqual(kr []byte, other []byte) bool { - if len(kr) == len(other) { - return string(kr) == string(other) +func CmpRangesLess(bound KeyRangeBound, key KeyRangeBound, types []string) bool { + // Here we panic if we failed to convert key range bound + // element to expected type. We consider panic as much better + // result that data corruption caused by erroreus routing logic. + // Big TODO here is to use and check specific error of types mismatch. + + for i := 0; i < len(bound); i++ { + switch types[i] { + case qdb.ColumnTypeInteger: + i1 := bound[i].(int64) + i2 := key[i].(int64) + if i1 == i2 { + // continue + } else if i1 < i2 { + return true + } else { + return false + } + case qdb.ColumnTypeVarchar: + i1 := bound[i].(string) + i2 := key[i].(string) + if i1 == i2 { + // continue + } else if i1 < i2 { + return true + } else { + return false + } + case qdb.ColumnTypeVarcharDeprecated: + i1 := bound[i].(string) + i2 := key[i].(string) + if i1 == i2 { + // continue + } else if CmpRangesLessStringsDeprecated(i1, i2) { + return true + } else { + return false + } + default: + // wtf? + panic(MissTypedKeyRange) + } } + // keys are actually equal. return false return false } +func CmpRangesEqual(bound KeyRangeBound, key KeyRangeBound, types []string) bool { + for i := 0; i < len(bound); i++ { + switch types[i] { + case qdb.ColumnTypeInteger: + i1 := bound[i].(int64) + i2 := key[i].(int64) + if i1 == i2 { + // continue + } else { + return false + } + case qdb.ColumnTypeVarchar: + i1 := bound[i].(string) + i2 := key[i].(string) + if i1 == i2 { + // continue + + } else { + return false + } + case qdb.ColumnTypeVarcharDeprecated: + i1 := bound[i].(string) + i2 := key[i].(string) + if i1 == i2 { + // continue + } else { + return false + } + default: + // wtf? + } + } + + // keys are actually equal. + return true +} + +func CmpRangesLessEqual(bound KeyRangeBound, key KeyRangeBound, types []string) bool { + return CmpRangesEqual(bound, key, types) || CmpRangesLess(bound, key, types) +} + // TODO : unit tests -func KeyRangeFromDB(kr *qdb.KeyRange) *KeyRange { - return &KeyRange{ - LowerBound: kr.LowerBound, - ShardID: kr.ShardID, - ID: kr.KeyRangeID, - Distribution: kr.DistributionId, +func KeyRangeFromDB(krdb *qdb.KeyRange, colTypes []string) *KeyRange { + kr := &KeyRange{ + ShardID: krdb.ShardID, + ID: krdb.KeyRangeID, + Distribution: krdb.DistributionId, + ColumnTypes: colTypes, + + LowerBound: make(KeyRangeBound, len(colTypes)), } + + // TODO: Fix this! (krdb.LowerBound -> krqb.LowerBound[i]) + // now this works only for unidim distributions + for i := 0; i < len(colTypes); i++ { + kr.InFunc(i, krdb.LowerBound) + } + + return kr } // TODO : unit tests -func KeyRangeFromSQL(kr *spqrparser.KeyRangeDefinition) *KeyRange { - if kr == nil { - return nil +func KeyRangeFromSQL(krsql *spqrparser.KeyRangeDefinition, colTypes []string) (*KeyRange, error) { + if krsql == nil { + return nil, nil + } + kr := &KeyRange{ + ShardID: krsql.ShardID, + ID: krsql.KeyRangeID, + Distribution: krsql.Distribution, + + ColumnTypes: colTypes, + + LowerBound: make(KeyRangeBound, len(colTypes)), } - return &KeyRange{ - LowerBound: kr.LowerBound, - ShardID: kr.ShardID, - ID: kr.KeyRangeID, - Distribution: kr.Distribution, + + if len(colTypes) != len(krsql.LowerBound.Pivots) { + return nil, fmt.Errorf("number of column mismatch with distribution") + } + + for i := 0; i < len(colTypes); i++ { + kr.InFunc(i, krsql.LowerBound.Pivots[i]) } + + return kr, nil +} + +func KeyRangeFromBytes(val [][]byte, colTypes []string) *KeyRange { + + kr := &KeyRange{ + ColumnTypes: colTypes, + + LowerBound: make(KeyRangeBound, len(colTypes)), + } + + for i := 0; i < len(colTypes); i++ { + kr.InFunc(i, val[i]) + } + + return kr } // TODO : unit tests -func KeyRangeFromProto(kr *proto.KeyRangeInfo) *KeyRange { - if kr == nil { +func KeyRangeFromProto(krproto *proto.KeyRangeInfo, colTypes []string) *KeyRange { + if krproto == nil { return nil } - return &KeyRange{ - LowerBound: KeyRangeBound(kr.KeyRange.LowerBound), - ShardID: kr.ShardId, - ID: kr.Krid, - Distribution: kr.DistributionId, + kr := &KeyRange{ + ShardID: krproto.ShardId, + ID: krproto.Krid, + Distribution: krproto.DistributionId, + ColumnTypes: colTypes, + + LowerBound: make(KeyRangeBound, len(colTypes)), } + + for i := 0; i < len(colTypes); i++ { + kr.InFunc(i, krproto.Bound.Values[i]) + } + + return kr } // TODO : unit tests func (kr *KeyRange) ToDB() *qdb.KeyRange { - return &qdb.KeyRange{ - LowerBound: kr.LowerBound, + krDb := &qdb.KeyRange{ + LowerBound: make([]byte, len(kr.ColumnTypes)), ShardID: kr.ShardID, KeyRangeID: kr.ID, DistributionId: kr.Distribution, } + // TODO: Fix this! (krqb.LowerBound -> krqb.LowerBound[i]) + // now this works only for unidim distributions + for i := 0; i < len(kr.ColumnTypes); i++ { + krDb.LowerBound = kr.OutFunc(i) + } + return krDb } // TODO : unit tests func (kr *KeyRange) ToProto() *proto.KeyRangeInfo { - return &proto.KeyRangeInfo{ - KeyRange: &proto.KeyRange{ - LowerBound: string(kr.LowerBound), + krProto := &proto.KeyRangeInfo{ + Bound: &proto.KeyRangeBound{ + Values: make([][]byte, len(kr.ColumnTypes)), }, ShardId: kr.ShardID, Krid: kr.ID, DistributionId: kr.Distribution, } + + for i := 0; i < len(kr.ColumnTypes); i++ { + krProto.Bound.Values[i] = kr.OutFunc(i) + } + + return krProto } diff --git a/pkg/models/kr/keyrangemgr.go b/pkg/models/kr/keyrangemgr.go index 4a4c5c644..8e1b2abe9 100644 --- a/pkg/models/kr/keyrangemgr.go +++ b/pkg/models/kr/keyrangemgr.go @@ -3,7 +3,7 @@ package kr import "context" type SplitKeyRange struct { - Bound KeyRangeBound + Bound [][]byte // KeyRangeBound raw SourceID string Krid string SplitLeft bool diff --git a/pkg/protos/key_range.pb.go b/pkg/protos/key_range.pb.go index b2a035fc5..9756d9fcf 100644 --- a/pkg/protos/key_range.pb.go +++ b/pkg/protos/key_range.pb.go @@ -66,16 +66,16 @@ func (KeyRangeStatus) EnumDescriptor() ([]byte, []int) { return file_protos_key_range_proto_rawDescGZIP(), []int{0} } -type KeyRange struct { +type KeyRangeBound struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - LowerBound string `protobuf:"bytes,1,opt,name=lower_bound,json=lowerBound,proto3" json:"lower_bound,omitempty"` + Values [][]byte `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` } -func (x *KeyRange) Reset() { - *x = KeyRange{} +func (x *KeyRangeBound) Reset() { + *x = KeyRangeBound{} if protoimpl.UnsafeEnabled { mi := &file_protos_key_range_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -83,13 +83,13 @@ func (x *KeyRange) Reset() { } } -func (x *KeyRange) String() string { +func (x *KeyRangeBound) String() string { return protoimpl.X.MessageStringOf(x) } -func (*KeyRange) ProtoMessage() {} +func (*KeyRangeBound) ProtoMessage() {} -func (x *KeyRange) ProtoReflect() protoreflect.Message { +func (x *KeyRangeBound) ProtoReflect() protoreflect.Message { mi := &file_protos_key_range_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -101,16 +101,16 @@ func (x *KeyRange) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use KeyRange.ProtoReflect.Descriptor instead. -func (*KeyRange) Descriptor() ([]byte, []int) { +// Deprecated: Use KeyRangeBound.ProtoReflect.Descriptor instead. +func (*KeyRangeBound) Descriptor() ([]byte, []int) { return file_protos_key_range_proto_rawDescGZIP(), []int{0} } -func (x *KeyRange) GetLowerBound() string { +func (x *KeyRangeBound) GetValues() [][]byte { if x != nil { - return x.LowerBound + return x.Values } - return "" + return nil } // key range info is mapped to shard @@ -119,10 +119,10 @@ type KeyRangeInfo struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - KeyRange *KeyRange `protobuf:"bytes,1,opt,name=key_range,json=keyRange,proto3" json:"key_range,omitempty"` - Krid string `protobuf:"bytes,2,opt,name=krid,proto3" json:"krid,omitempty"` - ShardId string `protobuf:"bytes,3,opt,name=shardId,proto3" json:"shardId,omitempty"` - DistributionId string `protobuf:"bytes,4,opt,name=distributionId,proto3" json:"distributionId,omitempty"` + Bound *KeyRangeBound `protobuf:"bytes,1,opt,name=bound,proto3" json:"bound,omitempty"` + Krid string `protobuf:"bytes,2,opt,name=krid,proto3" json:"krid,omitempty"` + ShardId string `protobuf:"bytes,3,opt,name=shardId,proto3" json:"shardId,omitempty"` + DistributionId string `protobuf:"bytes,4,opt,name=distributionId,proto3" json:"distributionId,omitempty"` } func (x *KeyRangeInfo) Reset() { @@ -157,9 +157,9 @@ func (*KeyRangeInfo) Descriptor() ([]byte, []int) { return file_protos_key_range_proto_rawDescGZIP(), []int{1} } -func (x *KeyRangeInfo) GetKeyRange() *KeyRange { +func (x *KeyRangeInfo) GetBound() *KeyRangeBound { if x != nil { - return x.KeyRange + return x.Bound } return nil } @@ -963,136 +963,135 @@ var File_protos_key_range_proto protoreflect.FileDescriptor var file_protos_key_range_proto_rawDesc = []byte{ 0x0a, 0x16, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x6b, 0x65, 0x79, 0x5f, 0x72, 0x61, 0x6e, - 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x73, 0x70, 0x71, 0x72, 0x22, 0x2b, - 0x0a, 0x08, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x6f, - 0x77, 0x65, 0x72, 0x5f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x91, 0x01, 0x0a, 0x0c, - 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2b, 0x0a, 0x09, - 0x6b, 0x65, 0x79, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0e, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, - 0x08, 0x6b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x72, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x72, 0x69, 0x64, 0x12, 0x18, 0x0a, - 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0e, 0x64, 0x69, 0x73, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0e, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, - 0x39, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x69, - 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x19, 0x0a, 0x17, 0x4c, 0x69, - 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x51, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, - 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, - 0x0a, 0x0e, 0x6b, 0x65, 0x79, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4b, 0x65, - 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0c, 0x6b, 0x65, 0x79, 0x52, - 0x61, 0x6e, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x7f, 0x0a, 0x14, 0x53, 0x70, 0x6c, 0x69, + 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x73, 0x70, 0x71, 0x72, 0x22, 0x27, + 0x0a, 0x0d, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x12, + 0x16, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, + 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x8f, 0x01, 0x0a, 0x0c, 0x4b, 0x65, 0x79, 0x52, + 0x61, 0x6e, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x29, 0x0a, 0x05, 0x62, 0x6f, 0x75, 0x6e, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4b, + 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x05, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x72, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6b, 0x72, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, + 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, + 0x64, 0x12, 0x26, 0x0a, 0x0e, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x64, 0x69, 0x73, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x39, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x65, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x6e, 0x65, 0x77, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x6f, 0x75, 0x6e, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x1b, 0x0a, - 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x70, - 0x6c, 0x69, 0x74, 0x5f, 0x6c, 0x65, 0x66, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, - 0x73, 0x70, 0x6c, 0x69, 0x74, 0x4c, 0x65, 0x66, 0x74, 0x22, 0x52, 0x0a, 0x14, 0x4d, 0x65, 0x72, - 0x67, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x17, 0x0a, 0x07, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x62, 0x61, 0x73, 0x65, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x70, - 0x70, 0x65, 0x6e, 0x64, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x67, 0x65, 0x49, 0x64, 0x22, 0x43, 0x0a, - 0x13, 0x4d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x6f, 0x53, 0x68, 0x61, 0x72, 0x64, 0x49, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x6f, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x49, 0x64, 0x22, 0x25, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, - 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x19, 0x0a, 0x17, 0x44, 0x72, 0x6f, - 0x70, 0x41, 0x6c, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x22, 0x4b, 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x41, 0x6c, 0x6c, 0x4b, - 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x2f, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x61, - 0x6e, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, - 0x65, 0x22, 0x25, 0x0a, 0x13, 0x4c, 0x6f, 0x63, 0x6b, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x27, 0x0a, 0x15, 0x55, 0x6e, 0x6c, 0x6f, - 0x63, 0x6b, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x02, 0x69, - 0x64, 0x22, 0x4b, 0x0a, 0x0d, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x70, - 0x6c, 0x79, 0x12, 0x3a, 0x0a, 0x0f, 0x6b, 0x65, 0x79, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, - 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x70, - 0x71, 0x72, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x0d, 0x6b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x30, - 0x0a, 0x0b, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x21, 0x0a, - 0x0c, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x22, 0x2e, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x61, - 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x6f, 0x75, 0x6e, 0x64, - 0x22, 0x36, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x61, - 0x6e, 0x67, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x1e, 0x0a, 0x0b, 0x6b, 0x65, 0x79, 0x5f, - 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6b, - 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x44, 0x22, 0x26, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4b, - 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, - 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x69, 0x64, 0x73, - 0x2a, 0x2b, 0x0a, 0x0e, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, - 0x0a, 0x09, 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x32, 0xcd, 0x06, - 0x0a, 0x0f, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, - 0x12, 0x18, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x61, - 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x73, 0x70, 0x71, - 0x72, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, - 0x00, 0x12, 0x40, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, - 0x65, 0x12, 0x19, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, - 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x73, - 0x70, 0x71, 0x72, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x70, 0x6c, - 0x79, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x4b, 0x65, - 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x1d, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, + 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x19, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x4b, + 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, + 0x51, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0e, 0x6b, 0x65, 0x79, 0x5f, + 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0c, 0x6b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x49, 0x6e, + 0x66, 0x6f, 0x22, 0x7f, 0x0a, 0x14, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x61, + 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x65, + 0x77, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x65, 0x77, 0x49, + 0x64, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x05, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x6c, 0x65, + 0x66, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x4c, + 0x65, 0x66, 0x74, 0x22, 0x52, 0x0a, 0x14, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x4b, 0x65, 0x79, 0x52, + 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x62, + 0x61, 0x73, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x61, + 0x73, 0x65, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x67, + 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x70, 0x70, 0x65, + 0x6e, 0x64, 0x61, 0x67, 0x65, 0x49, 0x64, 0x22, 0x43, 0x0a, 0x13, 0x4d, 0x6f, 0x76, 0x65, 0x4b, + 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1c, + 0x0a, 0x09, 0x74, 0x6f, 0x53, 0x68, 0x61, 0x72, 0x64, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x74, 0x6f, 0x53, 0x68, 0x61, 0x72, 0x64, 0x49, 0x64, 0x22, 0x25, 0x0a, 0x13, + 0x44, 0x72, 0x6f, 0x70, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x02, 0x69, 0x64, 0x22, 0x19, 0x0a, 0x17, 0x44, 0x72, 0x6f, 0x70, 0x41, 0x6c, 0x6c, 0x4b, 0x65, + 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x4b, + 0x0a, 0x18, 0x44, 0x72, 0x6f, 0x70, 0x41, 0x6c, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x09, 0x6b, 0x65, + 0x79, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x22, 0x25, 0x0a, 0x13, 0x4c, + 0x6f, 0x63, 0x6b, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x22, 0x27, 0x0a, 0x15, 0x55, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x4b, 0x65, 0x79, 0x52, + 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x4b, 0x0a, 0x0d, 0x4b, + 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x3a, 0x0a, 0x0f, + 0x6b, 0x65, 0x79, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4b, 0x65, 0x79, + 0x52, 0x61, 0x6e, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0d, 0x6b, 0x65, 0x79, 0x52, 0x61, + 0x6e, 0x67, 0x65, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x30, 0x0a, 0x0b, 0x4d, 0x6f, 0x64, 0x69, + 0x66, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x2e, 0x0a, 0x16, 0x52, 0x65, + 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x36, 0x0a, 0x14, 0x52, 0x65, + 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x70, + 0x6c, 0x79, 0x12, 0x1e, 0x0a, 0x0b, 0x6b, 0x65, 0x79, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5f, + 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, + 0x65, 0x44, 0x22, 0x26, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x69, 0x64, 0x73, 0x2a, 0x2b, 0x0a, 0x0e, 0x4b, 0x65, + 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0a, 0x0a, 0x06, + 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x41, 0x56, 0x41, 0x49, + 0x4c, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x32, 0xcd, 0x06, 0x0a, 0x0f, 0x4b, 0x65, 0x79, 0x52, + 0x61, 0x6e, 0x67, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x47, + 0x65, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x18, 0x2e, 0x73, 0x70, 0x71, + 0x72, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4b, 0x65, 0x79, 0x52, + 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x0c, 0x4c, + 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x70, + 0x71, 0x72, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4b, 0x65, - 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3e, 0x0a, - 0x0c, 0x4c, 0x6f, 0x63, 0x6b, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x19, 0x2e, - 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4c, 0x6f, 0x63, 0x6b, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, - 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x42, 0x0a, - 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, - 0x1b, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, - 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x73, - 0x70, 0x71, 0x72, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, - 0x00, 0x12, 0x3e, 0x0a, 0x0c, 0x44, 0x72, 0x6f, 0x70, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, - 0x65, 0x12, 0x19, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4b, 0x65, 0x79, - 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x73, - 0x70, 0x71, 0x72, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, - 0x00, 0x12, 0x53, 0x0a, 0x10, 0x44, 0x72, 0x6f, 0x70, 0x41, 0x6c, 0x6c, 0x4b, 0x65, 0x79, 0x52, - 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x1d, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x44, 0x72, 0x6f, - 0x70, 0x41, 0x6c, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x44, 0x72, 0x6f, 0x70, - 0x41, 0x6c, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0e, 0x55, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, - 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1b, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, - 0x55, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4d, 0x6f, 0x64, - 0x69, 0x66, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x0d, 0x53, 0x70, - 0x6c, 0x69, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1a, 0x2e, 0x73, 0x70, - 0x71, 0x72, 0x2e, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4d, - 0x6f, 0x64, 0x69, 0x66, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x0d, - 0x4d, 0x65, 0x72, 0x67, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1a, 0x2e, - 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, - 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x73, 0x70, 0x71, 0x72, - 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3e, - 0x0a, 0x0c, 0x4d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x19, - 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, - 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x73, 0x70, 0x71, 0x72, - 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x4d, - 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, - 0x65, 0x12, 0x1c, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, + 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x48, 0x0a, + 0x10, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, + 0x73, 0x12, 0x1d, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, + 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x13, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, + 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x0c, 0x4c, 0x6f, 0x63, 0x6b, 0x4b, + 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4c, + 0x6f, 0x63, 0x6b, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, + 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1b, 0x2e, 0x73, 0x70, 0x71, 0x72, + 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4d, 0x6f, + 0x64, 0x69, 0x66, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x0c, 0x44, + 0x72, 0x6f, 0x70, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x70, + 0x71, 0x72, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4d, 0x6f, + 0x64, 0x69, 0x66, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x53, 0x0a, 0x10, 0x44, + 0x72, 0x6f, 0x70, 0x41, 0x6c, 0x6c, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, + 0x1d, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x41, 0x6c, 0x6c, 0x4b, 0x65, + 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, + 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x41, 0x6c, 0x6c, 0x4b, 0x65, 0x79, + 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x12, 0x42, 0x0a, 0x0e, 0x55, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, + 0x67, 0x65, 0x12, 0x1b, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x55, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1a, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x4b, 0x65, - 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x0c, 0x5a, - 0x0a, 0x73, 0x70, 0x71, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x11, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x52, 0x65, 0x70, + 0x6c, 0x79, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x0d, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4b, 0x65, 0x79, + 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1a, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x53, 0x70, 0x6c, + 0x69, 0x74, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x11, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x52, + 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x0d, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x4b, + 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1a, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4d, + 0x65, 0x72, 0x67, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, + 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x0c, 0x4d, 0x6f, 0x76, 0x65, + 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, + 0x4d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x73, 0x70, 0x71, 0x72, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, + 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x4d, 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x6f, + 0x6c, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1c, 0x2e, 0x73, 0x70, + 0x71, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, + 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x73, 0x70, 0x71, 0x72, + 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x61, 0x6e, 0x67, 0x65, + 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x0c, 0x5a, 0x0a, 0x73, 0x70, 0x71, 0x72, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1111,7 +1110,7 @@ var file_protos_key_range_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_protos_key_range_proto_msgTypes = make([]protoimpl.MessageInfo, 18) var file_protos_key_range_proto_goTypes = []interface{}{ (KeyRangeStatus)(0), // 0: spqr.KeyRangeStatus - (*KeyRange)(nil), // 1: spqr.KeyRange + (*KeyRangeBound)(nil), // 1: spqr.KeyRangeBound (*KeyRangeInfo)(nil), // 2: spqr.KeyRangeInfo (*ListKeyRangeRequest)(nil), // 3: spqr.ListKeyRangeRequest (*ListAllKeyRangesRequest)(nil), // 4: spqr.ListAllKeyRangesRequest @@ -1131,7 +1130,7 @@ var file_protos_key_range_proto_goTypes = []interface{}{ (*GetKeyRangeRequest)(nil), // 18: spqr.GetKeyRangeRequest } var file_protos_key_range_proto_depIdxs = []int32{ - 1, // 0: spqr.KeyRangeInfo.key_range:type_name -> spqr.KeyRange + 1, // 0: spqr.KeyRangeInfo.bound:type_name -> spqr.KeyRangeBound 2, // 1: spqr.CreateKeyRangeRequest.key_range_info:type_name -> spqr.KeyRangeInfo 2, // 2: spqr.DropAllKeyRangesResponse.key_range:type_name -> spqr.KeyRangeInfo 2, // 3: spqr.KeyRangeReply.key_ranges_info:type_name -> spqr.KeyRangeInfo @@ -1173,7 +1172,7 @@ func file_protos_key_range_proto_init() { } if !protoimpl.UnsafeEnabled { file_protos_key_range_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*KeyRange); i { + switch v := v.(*KeyRangeBound); i { case 0: return &v.state case 1: diff --git a/protos/key_range.proto b/protos/key_range.proto index 93231786e..6b2ce666d 100644 --- a/protos/key_range.proto +++ b/protos/key_range.proto @@ -24,13 +24,14 @@ enum KeyRangeStatus { AVAILABLE = 1; } -message KeyRange { - string lower_bound = 1; +message KeyRangeBound { + repeated bytes values = 1; } // key range info is mapped to shard message KeyRangeInfo { - KeyRange key_range = 1; + KeyRangeBound bound = 1; + string krid = 2; string shardId = 3; string distributionId = 4; diff --git a/qdb/models.go b/qdb/models.go index 3f15c974f..80ab20984 100644 --- a/qdb/models.go +++ b/qdb/models.go @@ -69,9 +69,10 @@ func NewShard(ID string, hosts []string) *Shard { } var ( - ColumnTypeVarchar = "varchar" - ColumnTypeInteger = "integer" - ColumnTypeUinteger = "uinteger" + ColumnTypeVarchar = "varchar" + ColumnTypeVarcharDeprecated = "_varchar" + ColumnTypeInteger = "integer" + ColumnTypeUinteger = "uinteger" ) type DistributionKeyEntry struct { diff --git a/qdb/ops/ops.go b/qdb/ops/ops.go index ded72ae3d..905e6eb41 100644 --- a/qdb/ops/ops.go +++ b/qdb/ops/ops.go @@ -29,7 +29,8 @@ func CreateKeyRangeWithChecks(ctx context.Context, qdb qdb.QDB, keyRange *kr.Key } for _, v := range existsKrids { - if kr.CmpRangesEqual(keyRange.LowerBound, v.LowerBound) { + eph := kr.KeyRangeFromBytes([][]byte{v.LowerBound}, keyRange.ColumnTypes) + if kr.CmpRangesEqual(keyRange.LowerBound, eph.LowerBound, keyRange.ColumnTypes) { return spqrerror.Newf(spqrerror.SPQR_KEYRANGE_ERROR, "key range %v intersects with key range %v in QDB", keyRange.ID, v.KeyRangeID) } } @@ -58,7 +59,9 @@ func ModifyKeyRangeWithChecks(ctx context.Context, qdb qdb.QDB, keyRange *kr.Key // update req continue } - if kr.CmpRangesEqual(keyRange.LowerBound, v.LowerBound) { + + eph := kr.KeyRangeFromBytes([][]byte{v.LowerBound}, keyRange.ColumnTypes) + if kr.CmpRangesEqual(keyRange.LowerBound, eph.LowerBound, keyRange.ColumnTypes) { return spqrerror.Newf(spqrerror.SPQR_KEYRANGE_ERROR, "key range %v intersects with key range %v in QDB", keyRange.ID, v.KeyRangeID) } } diff --git a/router/grpc/qrouter.go b/router/grpc/qrouter.go index fa0d5b68d..bf0ae1627 100644 --- a/router/grpc/qrouter.go +++ b/router/grpc/qrouter.go @@ -231,7 +231,11 @@ func (l *LocalQrouterServer) DropShardingRules(ctx context.Context, request *pro // TODO : unit tests func (l *LocalQrouterServer) CreateKeyRange(ctx context.Context, request *protos.CreateKeyRangeRequest) (*protos.ModifyReply, error) { - err := l.mgr.CreateKeyRange(ctx, kr.KeyRangeFromProto(request.KeyRangeInfo)) + ds, err := l.mgr.GetDistribution(ctx, request.KeyRangeInfo.DistributionId) + if err != nil { + return nil, err + } + err = l.mgr.CreateKeyRange(ctx, kr.KeyRangeFromProto(request.KeyRangeInfo, ds.ColTypes)) if err != nil { return nil, err } @@ -314,7 +318,7 @@ func (l *LocalQrouterServer) SplitKeyRange(ctx context.Context, request *protos. if err := l.mgr.Split(ctx, &kr.SplitKeyRange{ Krid: request.NewId, SourceID: request.SourceId, - Bound: request.Bound, + Bound: [][]byte{request.Bound}, // TODO: fix SplitLeft: request.SplitLeft, }); err != nil { return nil, err diff --git a/router/mock/qrouter/mock_qrouter.go b/router/mock/qrouter/mock_qrouter.go index ad1218e89..fa28de1c6 100644 --- a/router/mock/qrouter/mock_qrouter.go +++ b/router/mock/qrouter/mock_qrouter.go @@ -54,7 +54,7 @@ func (mr *MockQueryRouterMockRecorder) DataShardsRoutes() *gomock.Call { } // DeparseKeyWithRangesInternal mocks base method. -func (m *MockQueryRouter) DeparseKeyWithRangesInternal(ctx context.Context, key string, krs []*kr.KeyRange) (*routingstate.DataShardRoute, error) { +func (m *MockQueryRouter) DeparseKeyWithRangesInternal(ctx context.Context, key []interface{}, krs []*kr.KeyRange) (*routingstate.DataShardRoute, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DeparseKeyWithRangesInternal", ctx, key, krs) ret0, _ := ret[0].(*routingstate.DataShardRoute) diff --git a/router/qrouter/proxy_routing.go b/router/qrouter/proxy_routing.go index 04ba59ae8..73d885b63 100644 --- a/router/qrouter/proxy_routing.go +++ b/router/qrouter/proxy_routing.go @@ -2,10 +2,15 @@ package qrouter import ( "context" + "encoding/binary" "fmt" - "github.com/pg-sharding/spqr/pkg/models/spqrerror" + "strconv" "strings" + "github.com/pg-sharding/spqr/pkg/meta" + "github.com/pg-sharding/spqr/pkg/models/distributions" + "github.com/pg-sharding/spqr/pkg/models/spqrerror" + "github.com/pg-sharding/spqr/pkg/config" "github.com/pg-sharding/spqr/pkg/models/hashfunction" "github.com/pg-sharding/spqr/pkg/models/kr" @@ -42,7 +47,7 @@ type RoutingMetadataContext struct { // SELECT * FROM a join b WHERE a.c1 = and a.c2 = // can be routed with different rules rels map[RelationFQN]struct{} - exprs map[RelationFQN]map[string]string + exprs map[RelationFQN]map[string]interface{} unparsed_columns map[string]struct{} @@ -51,6 +56,8 @@ type RoutingMetadataContext struct { // rarg:{range_var:{relname:"t2" inh:true relpersistence:"p" alias:{aliasname:"b"} tableAliases map[string]RelationFQN + distributions map[RelationFQN]*distributions.Distribution + params [][]byte paramsFormatCodes []int16 // TODO: include client ops and metadata here @@ -60,8 +67,9 @@ func NewRoutingMetadataContext(params [][]byte, paramsFormatCodes []int16) *Rout meta := &RoutingMetadataContext{ rels: map[RelationFQN]struct{}{}, tableAliases: map[string]RelationFQN{}, - exprs: map[RelationFQN]map[string]string{}, + exprs: map[RelationFQN]map[string]interface{}{}, unparsed_columns: map[string]struct{}{}, + distributions: map[RelationFQN]*distributions.Distribution{}, params: params, } // https://github.com/postgres/postgres/blob/master/src/backend/tcop/pquery.c#L635-L658 @@ -86,11 +94,24 @@ func NewRoutingMetadataContext(params [][]byte, paramsFormatCodes []int16) *Rout return meta } +func (m *RoutingMetadataContext) GetRelationDistribution(ctx context.Context, mgr meta.EntityMgr, resolvedRelation RelationFQN) (*distributions.Distribution, error) { + if res, ok := m.distributions[resolvedRelation]; ok { + return res, nil + } + ds, err := mgr.GetRelationDistribution(ctx, resolvedRelation.RelationName) + + if err != nil { + return nil, err + } + m.distributions[resolvedRelation] = ds + return ds, nil +} + // TODO : unit tests -func (meta *RoutingMetadataContext) RecordConstExpr(resolvedRelation RelationFQN, colname string, expr string) { +func (meta *RoutingMetadataContext) RecordConstExpr(resolvedRelation RelationFQN, colname string, expr interface{}) { meta.rels[resolvedRelation] = struct{}{} if _, ok := meta.exprs[resolvedRelation]; !ok { - meta.exprs[resolvedRelation] = map[string]string{} + meta.exprs[resolvedRelation] = map[string]interface{}{} } delete(meta.unparsed_columns, colname) meta.exprs[resolvedRelation][colname] = expr @@ -138,21 +159,21 @@ func (qr *ProxyQrouter) DeparseExprShardingEntries(expr lyx.Node, meta *RoutingM } // TODO : unit tests -func (qr *ProxyQrouter) DeparseKeyWithRangesInternal(_ context.Context, key string, krs []*kr.KeyRange) (*routingstate.DataShardRoute, error) { +func (qr *ProxyQrouter) DeparseKeyWithRangesInternal(_ context.Context, key []interface{}, krs []*kr.KeyRange) (*routingstate.DataShardRoute, error) { spqrlog.Zero.Debug(). - Str("key", key). + Interface("key", key[0]). Msg("checking key") spqrlog.Zero.Debug(). - Str("key", key). + Interface("key", key[0]). Int("key-ranges-count", len(krs)). Msg("checking key with key ranges") var matched_krkey *kr.KeyRange = nil for _, krkey := range krs { - if kr.CmpRangesLessEqual(krkey.LowerBound, []byte(key)) && - (matched_krkey == nil || kr.CmpRangesLessEqual(matched_krkey.LowerBound, krkey.LowerBound)) { + if kr.CmpRangesLessEqual(krkey.LowerBound, key, krkey.ColumnTypes) && + (matched_krkey == nil || kr.CmpRangesLessEqual(matched_krkey.LowerBound, krkey.LowerBound, krkey.ColumnTypes)) { matched_krkey = krkey } } @@ -171,77 +192,154 @@ func (qr *ProxyQrouter) DeparseKeyWithRangesInternal(_ context.Context, key stri return nil, FailedToFindKeyRange } -func (qr *ProxyQrouter) RecordDistributionKeyColumnValueOnRFQN(meta *RoutingMetadataContext, resolvedRelation RelationFQN, colname, value string) { +func (qr *ProxyQrouter) GetDistributionKeyOffsetType(meta *RoutingMetadataContext, resolvedRelation RelationFQN, colname string) (int, string) { + /* do not process non-distributed relations or columns not from relation distribution key */ + + ds, err := meta.GetRelationDistribution(context.TODO(), qr.Mgr(), resolvedRelation) + if err != nil { + return -1, "" + } + // TODO: optimize + for ind, c := range ds.Relations[resolvedRelation.RelationName].DistributionKey { + if c.Column == colname { + return ind, ds.ColTypes[ind] + } + } + return -1, "" +} +func (qr *ProxyQrouter) RecordDistributionKeyColumnValueOnRFQN(meta *RoutingMetadataContext, resolvedRelation RelationFQN, colname string, value interface{}) { /* do not process non-distributed relations or columns not from relation distribution key */ - if ds, err := qr.Mgr().GetRelationDistribution(context.TODO(), resolvedRelation.RelationName); err != nil { + + ds, err := meta.GetRelationDistribution(context.TODO(), qr.Mgr(), resolvedRelation) + if err != nil { return - } else { - // TODO: optimize - ok := false - for _, c := range ds.Relations[resolvedRelation.RelationName].DistributionKey { - if c.Column == colname { - ok = true - break - } - } - if !ok { - // some junk column - return + } + // TODO: optimize + ok := false + for _, c := range ds.Relations[resolvedRelation.RelationName].DistributionKey { + if c.Column == colname { + ok = true + break } } + if !ok { + // some junk column + return + } - // will not work not ints meta.RecordConstExpr(resolvedRelation, colname, value) } -// TODO : unit tests -func (qr *ProxyQrouter) RecordDistributionKeyExprOnRFQN(meta *RoutingMetadataContext, resolvedRelation RelationFQN, colname string, expr lyx.Node) error { - switch e := expr.(type) { - case *lyx.ParamRef: - if e.Number > len(meta.params) { - return ComplexQuery - } +func (qr *ProxyQrouter) processConstExpr(alias, colname string, expr lyx.Node, meta *RoutingMetadataContext) error { + resolvedRelation, err := meta.ResolveRelationByAlias(alias) + if err != nil { + // failed to resolve relation, skip column + meta.unparsed_columns[colname] = struct{}{} + return nil + } - // switch parameter format code and convert into proper representation + return qr.processConstExprOnRFQN(resolvedRelation, colname, expr, meta) +} - var routeParam []byte - fc := meta.paramsFormatCodes[e.Number-1] +func (qr *ProxyQrouter) processConstExprOnRFQN(resolvedRelation RelationFQN, colname string, expr lyx.Node, meta *RoutingMetadataContext) error { + off, tp := qr.GetDistributionKeyOffsetType(meta, resolvedRelation, colname) + if off == -1 { + // column not from distr key + return nil + } + + /* simple key-value pair */ + switch rght := expr.(type) { + case *lyx.ParamRef: + if rght.Number <= len(meta.params) { + // TODO: switch column type here + fc := meta.paramsFormatCodes[rght.Number-1] + + switch fc { + case xproto.FormatCodeBinary: + switch tp { + case qdb.ColumnTypeVarcharDeprecated: + fallthrough + case qdb.ColumnTypeVarchar: + meta.RecordConstExpr(resolvedRelation, colname, string(meta.params[rght.Number-1])) + case qdb.ColumnTypeInteger: + num, _ := binary.Varint(meta.params[rght.Number-1]) + meta.RecordConstExpr(resolvedRelation, colname, num) + case qdb.ColumnTypeUinteger: + num, _ := binary.Uvarint(meta.params[rght.Number-1]) + meta.RecordConstExpr(resolvedRelation, colname, num) + } + case xproto.FormatCodeText: + + switch tp { + case qdb.ColumnTypeVarcharDeprecated: + fallthrough + case qdb.ColumnTypeVarchar: + meta.RecordConstExpr(resolvedRelation, colname, string(meta.params[rght.Number-1])) + case qdb.ColumnTypeInteger: + num, err := strconv.ParseInt(string(meta.params[rght.Number-1]), 10, 64) + if err != nil { + return err + } + meta.RecordConstExpr(resolvedRelation, colname, num) + case qdb.ColumnTypeUinteger: + num, err := strconv.ParseUint(string(meta.params[rght.Number-1]), 10, 64) + if err != nil { + return err + } + meta.RecordConstExpr(resolvedRelation, colname, num) + } + default: + // ??? protoc violation + } - switch fc { - case xproto.FormatCodeBinary: - // TODO: here we need to invoke out function for convertion - // actually, we need to convert everything to binary format - case xproto.FormatCodeText: - routeParam = meta.params[e.Number-1] - default: - // ??? protoc violation } + // else error out? - qr.RecordDistributionKeyColumnValueOnRFQN(meta, resolvedRelation, colname, string(routeParam)) - return nil case *lyx.AExprSConst: - qr.RecordDistributionKeyColumnValueOnRFQN(meta, resolvedRelation, colname, string(e.Value)) - return nil + // TBD: postpone routing from here to root of parsing tree + switch tp { + case qdb.ColumnTypeVarcharDeprecated: + fallthrough + case qdb.ColumnTypeVarchar: + meta.RecordConstExpr(resolvedRelation, colname, rght.Value) + case qdb.ColumnTypeInteger: + num, err := strconv.ParseInt(rght.Value, 10, 64) + if err != nil { + return err + } + meta.RecordConstExpr(resolvedRelation, colname, num) + case qdb.ColumnTypeUinteger: + num, err := strconv.ParseUint(rght.Value, 10, 64) + if err != nil { + return err + } + meta.RecordConstExpr(resolvedRelation, colname, num) + } case *lyx.AExprIConst: - val := fmt.Sprintf("%d", e.Value) - qr.RecordDistributionKeyColumnValueOnRFQN(meta, resolvedRelation, colname, string(val)) - return nil + // TBD: postpone routing from here to root of parsing tree + // maybe expimely inefficient. Will be fixed in SPQR-2.0 + switch tp { + case qdb.ColumnTypeVarchar: + fallthrough + case qdb.ColumnTypeVarcharDeprecated: + return ComplexQuery + case qdb.ColumnTypeInteger: + meta.RecordConstExpr(resolvedRelation, colname, int64(rght.Value)) + case qdb.ColumnTypeUinteger: + meta.RecordConstExpr(resolvedRelation, colname, uint64(rght.Value)) + } + case *lyx.AExprList: + if len(rght.List) != 0 { + expr := rght.List[0] + return qr.processConstExprOnRFQN(resolvedRelation, colname, expr, meta) + } default: - return ComplexQuery - } -} - -func (qr *ProxyQrouter) RecordDistributionKeyColumnValue(meta *RoutingMetadataContext, alias, colname, value string) { - - resolvedRelation, err := meta.ResolveRelationByAlias(alias) - if err != nil { - // failed to resolve relation, skip column - meta.unparsed_columns[colname] = struct{}{} - return + return fmt.Errorf("expression is not const") } - qr.RecordDistributionKeyColumnValueOnRFQN(meta, resolvedRelation, colname, value) + return nil } // routeByClause de-parses sharding column-value pair from Where clause of the query @@ -265,30 +363,9 @@ func (qr *ProxyQrouter) routeByClause(ctx context.Context, expr lyx.Node, meta * /* simple key-value pair */ switch rght := texpr.Right.(type) { - case *lyx.ParamRef: - if rght.Number <= len(meta.params) { - qr.RecordDistributionKeyColumnValue(meta, alias, colname, string(meta.params[rght.Number-1])) - } - // else error out? - case *lyx.AExprSConst: - // TBD: postpone routing from here to root of parsing tree - qr.RecordDistributionKeyColumnValue(meta, alias, colname, rght.Value) - case *lyx.AExprIConst: - // TBD: postpone routing from here to root of parsing tree - // maybe expimely inefficient. Will be fixed in SPQR-2.0 - qr.RecordDistributionKeyColumnValue(meta, alias, colname, fmt.Sprintf("%d", rght.Value)) - case *lyx.AExprList: - if len(rght.List) != 0 { - expr := rght.List[0] - switch bexpr := expr.(type) { - case *lyx.AExprSConst: - // TBD: postpone routing from here to root of parsing tree - qr.RecordDistributionKeyColumnValue(meta, alias, colname, bexpr.Value) - case *lyx.AExprIConst: - // TBD: postpone routing from here to root of parsing tree - // maybe expimely inefficient. Will be fixed in SPQR-2.0 - qr.RecordDistributionKeyColumnValue(meta, alias, colname, fmt.Sprintf("%d", bexpr.Value)) - } + case *lyx.ParamRef, *lyx.AExprSConst, *lyx.AExprIConst, *lyx.AExprList: + if err := qr.processConstExpr(alias, colname, texpr.Right, meta); err != nil { + return err } case *lyx.FuncApplication: // there are several types of queries like DELETE FROM rel WHERE colref = func_applicion @@ -537,7 +614,7 @@ func (qr *ProxyQrouter) deparseShardingMapping( if tlUsable { for i := range offsets { - _ = qr.RecordDistributionKeyExprOnRFQN(meta, rfqn, insertCols[offsets[i]], targetList[offsets[i]]) + _ = qr.processConstExprOnRFQN(rfqn, insertCols[offsets[i]], targetList[offsets[i]], meta) } } @@ -562,7 +639,7 @@ func (qr *ProxyQrouter) deparseShardingMapping( if vlUsable { for i := range offsets { - _ = qr.RecordDistributionKeyExprOnRFQN(meta, rfqn, insertCols[offsets[i]], valList[offsets[i]]) + _ = qr.processConstExprOnRFQN(rfqn, insertCols[offsets[i]], valList[offsets[i]], meta) } } @@ -847,10 +924,11 @@ func (qr *ProxyQrouter) routeWithRules(ctx context.Context, stmt lyx.Node, sph s ok := true - var hashedKey []byte + var compositeKey []interface{} // TODO: multi-column routing. This works only for one-dim routing for i := 0; i < len(distrKey); i++ { + var hashedKey interface{} hf, err := hashfunction.HashFunctionByName(distrKey[i].HashFunction) if err != nil { ok = false @@ -866,15 +944,17 @@ func (qr *ProxyQrouter) routeWithRules(ctx context.Context, stmt lyx.Node, sph s break } - hashedKey, err = hashfunction.ApplyHashFunction([]byte(val), hf) + hashedKey, err = hashfunction.ApplyHashFunction(val, ds.ColTypes[i], hf) - spqrlog.Zero.Debug().Str("key", meta.exprs[rfqn][col]).Str("hashed key", string(hashedKey)).Msg("applying hash function on key") + spqrlog.Zero.Debug().Interface("key", meta.exprs[rfqn][col]).Interface("hashed key", hashedKey).Msg("applying hash function on key") if err != nil { spqrlog.Zero.Debug().Err(err).Msg("failed to apply hash function") ok = false break } + + compositeKey = append(compositeKey, hashedKey) } if !ok { @@ -882,7 +962,7 @@ func (qr *ProxyQrouter) routeWithRules(ctx context.Context, stmt lyx.Node, sph s continue } - currroute, err := qr.DeparseKeyWithRangesInternal(ctx, string(hashedKey), krs) + currroute, err := qr.DeparseKeyWithRangesInternal(ctx, compositeKey, krs) if err != nil { route_err = err spqrlog.Zero.Debug().Err(route_err).Msg("temporarily skip the route error") diff --git a/router/qrouter/proxy_routing_test.go b/router/qrouter/proxy_routing_test.go index d7208fbf0..ff4c4518c 100644 --- a/router/qrouter/proxy_routing_test.go +++ b/router/qrouter/proxy_routing_test.go @@ -131,6 +131,9 @@ func TestComment(t *testing.T) { _ = db.CreateDistribution(context.TODO(), &qdb.Distribution{ ID: distribution, + ColTypes: []string{ + qdb.ColumnTypeInteger, + }, Relations: map[string]*qdb.DistributedRelation{ "xx": { Name: "xx", @@ -143,21 +146,31 @@ func TestComment(t *testing.T) { }, }) - err := db.CreateKeyRange(context.TODO(), &qdb.KeyRange{ - ShardID: "sh1", - DistributionId: distribution, - KeyRangeID: "id1", - LowerBound: []byte("1"), - }) + err := db.CreateKeyRange(context.TODO(), (&kr.KeyRange{ + ShardID: "sh1", + Distribution: distribution, + ID: "id1", + LowerBound: kr.KeyRangeBound{ + int64(1), + }, + ColumnTypes: []string{ + qdb.ColumnTypeInteger, + }, + }).ToDB()) assert.NoError(err) - err = db.CreateKeyRange(context.TODO(), &qdb.KeyRange{ - ShardID: "sh2", - KeyRangeID: "id2", - DistributionId: distribution, - LowerBound: []byte("11"), - }) + err = db.CreateKeyRange(context.TODO(), (&kr.KeyRange{ + ShardID: "sh2", + Distribution: distribution, + ID: "id2", + LowerBound: kr.KeyRangeBound{ + int64(11), + }, + ColumnTypes: []string{ + qdb.ColumnTypeInteger, + }, + }).ToDB()) assert.NoError(err) @@ -188,7 +201,10 @@ func TestComment(t *testing.T) { ShardID: "sh1", ID: "id1", Distribution: distribution, - LowerBound: []byte("1"), + LowerBound: []interface{}{ + int64(1), + }, + ColumnTypes: []string{qdb.ColumnTypeInteger}, }, }, TargetSessionAttrs: "any", @@ -222,6 +238,9 @@ func TestSingleShard(t *testing.T) { _ = db.CreateDistribution(context.TODO(), &qdb.Distribution{ ID: distribution, + ColTypes: []string{ + qdb.ColumnTypeInteger, + }, Relations: map[string]*qdb.DistributedRelation{ "t": { Name: "t", @@ -266,21 +285,31 @@ func TestSingleShard(t *testing.T) { }, }) - err := db.CreateKeyRange(context.TODO(), &qdb.KeyRange{ - ShardID: "sh1", - DistributionId: distribution, - KeyRangeID: "id1", - LowerBound: []byte("1"), - }) + err := db.CreateKeyRange(context.TODO(), (&kr.KeyRange{ + ShardID: "sh1", + Distribution: distribution, + ID: "id1", + LowerBound: kr.KeyRangeBound{ + int64(1), + }, + ColumnTypes: []string{ + qdb.ColumnTypeInteger, + }, + }).ToDB()) assert.NoError(err) - err = db.CreateKeyRange(context.TODO(), &qdb.KeyRange{ - ShardID: "sh2", - DistributionId: distribution, - KeyRangeID: "id2", - LowerBound: []byte("11"), - }) + err = db.CreateKeyRange(context.TODO(), (&kr.KeyRange{ + ShardID: "sh2", + Distribution: distribution, + ID: "id2", + LowerBound: kr.KeyRangeBound{ + int64(11), + }, + ColumnTypes: []string{ + qdb.ColumnTypeInteger, + }, + }).ToDB()) assert.NoError(err) @@ -300,6 +329,55 @@ func TestSingleShard(t *testing.T) { assert.NoError(err) for _, tt := range []tcase{ + { + query: "SELECT * FROM xxtt1 a WHERE a.i = 21 and w_idj + w_idi != 0;", + exp: routingstate.ShardMatchState{ + Route: &routingstate.DataShardRoute{ + Shkey: kr.ShardKey{ + Name: "sh2", + }, + Matchedkr: &kr.KeyRange{ + ShardID: "sh2", + Distribution: distribution, + ID: "id2", + LowerBound: []interface{}{ + int64(11), + }, + + ColumnTypes: []string{ + qdb.ColumnTypeInteger, + }, + }, + }, + TargetSessionAttrs: "any", + }, + err: nil, + }, + + { + query: "SELECT * FROM xxtt1 a WHERE a.i = '21' and w_idj + w_idi != 0;", + exp: routingstate.ShardMatchState{ + Route: &routingstate.DataShardRoute{ + Shkey: kr.ShardKey{ + Name: "sh2", + }, + Matchedkr: &kr.KeyRange{ + ShardID: "sh2", + Distribution: distribution, + ID: "id2", + LowerBound: []interface{}{ + int64(11), + }, + + ColumnTypes: []string{ + qdb.ColumnTypeInteger, + }, + }, + }, + TargetSessionAttrs: "any", + }, + err: nil, + }, { query: ` @@ -320,7 +398,14 @@ func TestSingleShard(t *testing.T) { ShardID: "sh1", ID: "id1", Distribution: distribution, - LowerBound: []byte("1"), + LowerBound: []interface{}{ + + int64(1), + }, + + ColumnTypes: []string{ + qdb.ColumnTypeInteger, + }, }, }, TargetSessionAttrs: "any", @@ -346,7 +431,14 @@ func TestSingleShard(t *testing.T) { ShardID: "sh1", ID: "id1", Distribution: distribution, - LowerBound: []byte("1"), + LowerBound: []interface{}{ + + int64(1), + }, + + ColumnTypes: []string{ + qdb.ColumnTypeInteger, + }, }, }, TargetSessionAttrs: "any", @@ -363,7 +455,13 @@ func TestSingleShard(t *testing.T) { ShardID: "sh1", ID: "id1", Distribution: distribution, - LowerBound: []byte("1"), + LowerBound: []interface{}{ + int64(1), + }, + + ColumnTypes: []string{ + qdb.ColumnTypeInteger, + }, }, }, TargetSessionAttrs: "any", @@ -382,26 +480,13 @@ func TestSingleShard(t *testing.T) { ShardID: "sh2", ID: "id2", Distribution: distribution, - LowerBound: []byte("11"), - }, - }, - TargetSessionAttrs: "any", - }, - err: nil, - }, + LowerBound: []interface{}{ + int64(11), + }, - { - query: "SELECT * FROM xxtt1 a WHERE a.i = 21 and w_idj + w_idi != 0;", - exp: routingstate.ShardMatchState{ - Route: &routingstate.DataShardRoute{ - Shkey: kr.ShardKey{ - Name: "sh2", - }, - Matchedkr: &kr.KeyRange{ - ShardID: "sh2", - Distribution: distribution, - ID: "id2", - LowerBound: []byte("11"), + ColumnTypes: []string{ + qdb.ColumnTypeInteger, + }, }, }, TargetSessionAttrs: "any", @@ -419,7 +504,13 @@ func TestSingleShard(t *testing.T) { ShardID: "sh2", ID: "id2", Distribution: distribution, - LowerBound: []byte("11"), + LowerBound: []interface{}{ + int64(11), + }, + + ColumnTypes: []string{ + qdb.ColumnTypeInteger, + }, }, }, TargetSessionAttrs: "any", @@ -438,7 +529,13 @@ func TestSingleShard(t *testing.T) { ShardID: "sh1", ID: "id1", Distribution: distribution, - LowerBound: []byte("1"), + LowerBound: []interface{}{ + int64(1), + }, + + ColumnTypes: []string{ + qdb.ColumnTypeInteger, + }, }, }, TargetSessionAttrs: "any", @@ -460,7 +557,13 @@ func TestSingleShard(t *testing.T) { ShardID: "sh1", ID: "id1", Distribution: distribution, - LowerBound: []byte("1"), + LowerBound: []interface{}{ + int64(1), + }, + + ColumnTypes: []string{ + qdb.ColumnTypeInteger, + }, }, }, TargetSessionAttrs: "any", @@ -479,7 +582,13 @@ func TestSingleShard(t *testing.T) { ShardID: "sh2", ID: "id2", Distribution: distribution, - LowerBound: []byte("11"), + LowerBound: []interface{}{ + int64(11), + }, + + ColumnTypes: []string{ + qdb.ColumnTypeInteger, + }, }, }, TargetSessionAttrs: "any", @@ -512,7 +621,8 @@ func TestInsertOffsets(t *testing.T) { distribution := "dd" _ = db.CreateDistribution(context.TODO(), &qdb.Distribution{ - ID: distribution, + ID: distribution, + ColTypes: []string{qdb.ColumnTypeInteger}, Relations: map[string]*qdb.DistributedRelation{ "xx": { Name: "xx", @@ -541,21 +651,25 @@ func TestInsertOffsets(t *testing.T) { }, }) - err := db.CreateKeyRange(context.TODO(), &qdb.KeyRange{ - ShardID: "sh1", - KeyRangeID: "id1", - DistributionId: distribution, - LowerBound: []byte("1"), - }) + err := db.CreateKeyRange(context.TODO(), (&kr.KeyRange{ + LowerBound: []interface{}{int64(1)}, + + ShardID: "sh1", + Distribution: distribution, + ID: "id1", + ColumnTypes: []string{qdb.ColumnTypeInteger}, + }).ToDB()) assert.NoError(err) - err = db.CreateKeyRange(context.TODO(), &qdb.KeyRange{ - ShardID: "sh2", - DistributionId: distribution, - KeyRangeID: "id2", - LowerBound: []byte("11"), - }) + err = db.CreateKeyRange(context.TODO(), (&kr.KeyRange{ + LowerBound: []interface{}{int64(11)}, + + ShardID: "sh2", + Distribution: distribution, + ID: "id2", + ColumnTypes: []string{qdb.ColumnTypeInteger}, + }).ToDB()) assert.NoError(err) @@ -587,7 +701,11 @@ func TestInsertOffsets(t *testing.T) { ShardID: "sh2", ID: "id2", Distribution: distribution, - LowerBound: []byte("11"), + + ColumnTypes: []string{qdb.ColumnTypeInteger}, + LowerBound: []interface{}{ + int64(11), + }, }, }, TargetSessionAttrs: "any", @@ -597,7 +715,7 @@ func TestInsertOffsets(t *testing.T) { { query: ` - INSERT INTO xxtt1 (j, i, w_id) VALUES(2121221, -211212, '21'); + INSERT INTO xxtt1 (j, i, w_id) VALUES(2121221, -211212, 21); `, exp: routingstate.ShardMatchState{ Route: &routingstate.DataShardRoute{ @@ -608,7 +726,11 @@ func TestInsertOffsets(t *testing.T) { ShardID: "sh2", ID: "id2", Distribution: distribution, - LowerBound: []byte("11"), + + ColumnTypes: []string{qdb.ColumnTypeInteger}, + LowerBound: []interface{}{ + int64(11), + }, }, }, TargetSessionAttrs: "any", @@ -618,7 +740,7 @@ func TestInsertOffsets(t *testing.T) { { query: ` - INSERT INTO "people" ("first_name","last_name","email","id") VALUES ('John','Smith','','1') RETURNING "id"`, + INSERT INTO "people" ("first_name","last_name","email","id") VALUES ('John','Smith','',1) RETURNING "id"`, exp: routingstate.ShardMatchState{ Route: &routingstate.DataShardRoute{ Shkey: kr.ShardKey{ @@ -628,7 +750,11 @@ func TestInsertOffsets(t *testing.T) { ShardID: "sh1", ID: "id1", Distribution: distribution, - LowerBound: []byte("1"), + + ColumnTypes: []string{qdb.ColumnTypeInteger}, + LowerBound: []interface{}{ + int64(1), + }, }, }, TargetSessionAttrs: "any", @@ -648,7 +774,11 @@ func TestInsertOffsets(t *testing.T) { ShardID: "sh2", ID: "id2", Distribution: distribution, - LowerBound: []byte("11"), + + ColumnTypes: []string{qdb.ColumnTypeInteger}, + LowerBound: []interface{}{ + int64(11), + }, }, }, TargetSessionAttrs: "any", @@ -667,7 +797,11 @@ func TestInsertOffsets(t *testing.T) { ShardID: "sh1", ID: "id1", Distribution: distribution, - LowerBound: []byte("1"), + + ColumnTypes: []string{qdb.ColumnTypeInteger}, + LowerBound: []interface{}{ + int64(1), + }, }, }, TargetSessionAttrs: "any", @@ -701,7 +835,7 @@ func TestJoins(t *testing.T) { _ = db.CreateDistribution(context.TODO(), &qdb.Distribution{ ID: distribution, - ColTypes: []string{qdb.ColumnTypeVarchar}, + ColTypes: []string{qdb.ColumnTypeInteger}, Relations: map[string]*qdb.DistributedRelation{ "sshjt1": { Name: "sshjt1", @@ -730,21 +864,23 @@ func TestJoins(t *testing.T) { }, }) - err := db.CreateKeyRange(context.TODO(), &qdb.KeyRange{ - ShardID: "sh1", - KeyRangeID: "id1", - DistributionId: distribution, - LowerBound: []byte("1"), - }) + err := db.CreateKeyRange(context.TODO(), (&kr.KeyRange{ + ShardID: "sh1", + Distribution: distribution, + ID: "id1", + LowerBound: []interface{}{int64(11)}, + ColumnTypes: []string{qdb.ColumnTypeInteger}, + }).ToDB()) assert.NoError(err) - err = db.CreateKeyRange(context.TODO(), &qdb.KeyRange{ - ShardID: "sh2", - KeyRangeID: "id2", - DistributionId: distribution, - LowerBound: []byte("11"), - }) + err = db.CreateKeyRange(context.TODO(), (&kr.KeyRange{ + ShardID: "sh2", + Distribution: distribution, + ID: "id2", + LowerBound: []interface{}{int64(11)}, + ColumnTypes: []string{qdb.ColumnTypeInteger}, + }).ToDB()) assert.NoError(err) @@ -773,7 +909,10 @@ func TestJoins(t *testing.T) { ShardID: "sh2", ID: "id2", Distribution: distribution, - LowerBound: []byte("11"), + LowerBound: []interface{}{ + int64(11), + }, + ColumnTypes: []string{qdb.ColumnTypeInteger}, }, }, TargetSessionAttrs: "any", @@ -792,7 +931,10 @@ func TestJoins(t *testing.T) { ShardID: "sh2", ID: "id2", Distribution: distribution, - LowerBound: []byte("11"), + LowerBound: []interface{}{ + int64(11), + }, + ColumnTypes: []string{qdb.ColumnTypeInteger}, }, }, TargetSessionAttrs: "any", @@ -842,7 +984,8 @@ func TestUnnest(t *testing.T) { distribution := "dd" _ = db.CreateDistribution(context.TODO(), &qdb.Distribution{ - ID: distribution, + ID: distribution, + ColTypes: []string{qdb.ColumnTypeInteger}, Relations: map[string]*qdb.DistributedRelation{ "xxtt1": { Name: "xxtt1", @@ -855,21 +998,23 @@ func TestUnnest(t *testing.T) { }, }) - err := db.CreateKeyRange(context.TODO(), &qdb.KeyRange{ - ShardID: "sh1", - KeyRangeID: "id1", - DistributionId: distribution, - LowerBound: []byte("1"), - }) + err := db.CreateKeyRange(context.TODO(), (&kr.KeyRange{ + ShardID: "sh1", + Distribution: distribution, + ID: "id1", + LowerBound: []interface{}{int64(11)}, + ColumnTypes: []string{qdb.ColumnTypeInteger}, + }).ToDB()) assert.NoError(err) - err = db.CreateKeyRange(context.TODO(), &qdb.KeyRange{ - ShardID: "sh2", - DistributionId: distribution, - KeyRangeID: "id2", - LowerBound: []byte("11"), - }) + err = db.CreateKeyRange(context.TODO(), (&kr.KeyRange{ + ShardID: "sh2", + Distribution: distribution, + ID: "id2", + LowerBound: []interface{}{int64(11)}, + ColumnTypes: []string{qdb.ColumnTypeInteger}, + }).ToDB()) assert.NoError(err) @@ -901,7 +1046,11 @@ func TestUnnest(t *testing.T) { ShardID: "sh2", ID: "id2", Distribution: distribution, - LowerBound: []byte("11"), + LowerBound: []interface{}{ + int64(11), + }, + + ColumnTypes: []string{qdb.ColumnTypeInteger}, }, }, TargetSessionAttrs: "any", @@ -920,7 +1069,11 @@ func TestUnnest(t *testing.T) { ShardID: "sh2", ID: "id2", Distribution: distribution, - LowerBound: []byte("11"), + LowerBound: []interface{}{ + int64(11), + }, + + ColumnTypes: []string{qdb.ColumnTypeInteger}, }, }, TargetSessionAttrs: "any", @@ -953,7 +1106,8 @@ func TestCopySingleShard(t *testing.T) { distribution := "dd" _ = db.CreateDistribution(context.TODO(), &qdb.Distribution{ - ID: distribution, + ID: distribution, + ColTypes: []string{qdb.ColumnTypeInteger}, Relations: map[string]*qdb.DistributedRelation{ "xx": { Name: "xx", @@ -966,21 +1120,25 @@ func TestCopySingleShard(t *testing.T) { }, }) - err := db.CreateKeyRange(context.TODO(), &qdb.KeyRange{ - ShardID: "sh1", - DistributionId: distribution, - KeyRangeID: "id1", - LowerBound: []byte("1"), - }) + err := db.CreateKeyRange(context.TODO(), (&kr.KeyRange{ + ShardID: "sh1", + Distribution: distribution, + ID: "id1", + LowerBound: []interface{}{int64(1)}, + + ColumnTypes: []string{qdb.ColumnTypeInteger}, + }).ToDB()) assert.NoError(err) - err = db.CreateKeyRange(context.TODO(), &qdb.KeyRange{ - ShardID: "sh2", - DistributionId: distribution, - KeyRangeID: "id2", - LowerBound: []byte("11"), - }) + err = db.CreateKeyRange(context.TODO(), (&kr.KeyRange{ + ShardID: "sh2", + Distribution: distribution, + ID: "id2", + LowerBound: []interface{}{int64(11)}, + + ColumnTypes: []string{qdb.ColumnTypeInteger}, + }).ToDB()) assert.NoError(err) @@ -1011,7 +1169,11 @@ func TestCopySingleShard(t *testing.T) { ShardID: "sh1", ID: "id1", Distribution: distribution, - LowerBound: []byte("1"), + LowerBound: []interface{}{ + int64(1), + }, + + ColumnTypes: []string{qdb.ColumnTypeInteger}, }, }, TargetSessionAttrs: "any", diff --git a/router/qrouter/qrouter.go b/router/qrouter/qrouter.go index 29282162d..3fd33abad 100644 --- a/router/qrouter/qrouter.go +++ b/router/qrouter/qrouter.go @@ -3,6 +3,7 @@ package qrouter import ( "context" "fmt" + "github.com/pg-sharding/spqr/pkg/models/kr" "github.com/pg-sharding/spqr/pkg/config" @@ -22,7 +23,7 @@ type QueryRouter interface { WorldShardsRoutes() []*routingstate.DataShardRoute DataShardsRoutes() []*routingstate.DataShardRoute - DeparseKeyWithRangesInternal(ctx context.Context, key string, krs []*kr.KeyRange) (*routingstate.DataShardRoute, error) + DeparseKeyWithRangesInternal(ctx context.Context, key []interface{}, krs []*kr.KeyRange) (*routingstate.DataShardRoute, error) Initialized() bool Initialize() bool diff --git a/router/relay/qstate.go b/router/relay/qstate.go index a82b8e00d..80659fac9 100644 --- a/router/relay/qstate.go +++ b/router/relay/qstate.go @@ -41,7 +41,12 @@ func deparseRouteHint(rst RelayStateMgr, params map[string]string) (routehint.Ro return nil, err } - ds, err := rst.QueryRouter().DeparseKeyWithRangesInternal(context.TODO(), val, krs) + // TODO: fix this + compositeKey := []interface{}{ + val, + } + + ds, err := rst.QueryRouter().DeparseKeyWithRangesInternal(context.TODO(), compositeKey, krs) if err != nil { return nil, err } diff --git a/test/feature/features/spqrdump.feature b/test/feature/features/spqrdump.feature index cb2b0a321..897be7251 100644 --- a/test/feature/features/spqrdump.feature +++ b/test/feature/features/spqrdump.feature @@ -1,4 +1,4 @@ -Feature: spqrdump test +Feature: spqr-dump test Background: # # Make host "coordinator" take control @@ -25,7 +25,7 @@ Feature: spqrdump test When I run command on host "router" """ - /spqr/spqrdump dump -e regress_router:7000 + /spqr/spqr-dump dump -e regress_router:7000 """ Then command return code should be "0" And command output should match regexp @@ -48,15 +48,15 @@ Feature: spqrdump test When I run command on host "router" """ - /spqr/spqrdump dump -e regress_router:7000 + /spqr/spqr-dump dump -e regress_router:7000 """ Then command return code should be "0" And command output should match regexp """ CREATE DISTRIBUTION ds1 COLUMN TYPES integer, varchar; ALTER DISTRIBUTION ds1 ATTACH RELATION test DISTRIBUTION KEY id, id_2; - CREATE KEY RANGE krid1 FROM 0 ROUTE TO sh1 FOR DISTRIBUTION ds1; - CREATE KEY RANGE krid2 FROM 11 ROUTE TO sh2 FOR DISTRIBUTION ds1; + CREATE KEY RANGE krid1 FROM 0, 'a' ROUTE TO sh1 FOR DISTRIBUTION ds1; + CREATE KEY RANGE krid2 FROM 11, 'b' ROUTE TO sh2 FOR DISTRIBUTION ds1; """ Scenario: dump via GRPC works with hashed distribution key @@ -71,7 +71,7 @@ Feature: spqrdump test When I run command on host "router" """ - /spqr/spqrdump dump -e regress_router:7000 + /spqr/spqr-dump dump -e regress_router:7000 """ Then command return code should be "0" And command output should match regexp diff --git a/test/regress/tests/console/expected/delete_distribution.out b/test/regress/tests/console/expected/delete_distribution.out index 335ae579e..a254e0a82 100644 --- a/test/regress/tests/console/expected/delete_distribution.out +++ b/test/regress/tests/console/expected/delete_distribution.out @@ -5,13 +5,13 @@ You can find documentation here https://github.com/pg-sharding/spqr/tree/master/docs -CREATE DISTRIBUTION ds1; +CREATE DISTRIBUTION ds1 COLUMN TYPES int; add distribution ---------------------------------- created distribution with id ds1 (1 row) -CREATE DISTRIBUTION ds2; +CREATE DISTRIBUTION ds2 COLUMN TYPES int; add distribution ---------------------------------- created distribution with id ds2 @@ -74,7 +74,7 @@ DROP DISTRIBUTION ds1 CASCADE; SHOW distributions; Distribution ID | Column types -----------------+-------------- - ds2 | + ds2 | integer (1 row) DROP DISTRIBUTION ALL CASCADE; diff --git a/test/regress/tests/console/sql/delete_distribution.sql b/test/regress/tests/console/sql/delete_distribution.sql index 71fb6d57f..015d70ae7 100644 --- a/test/regress/tests/console/sql/delete_distribution.sql +++ b/test/regress/tests/console/sql/delete_distribution.sql @@ -1,5 +1,5 @@ -CREATE DISTRIBUTION ds1; -CREATE DISTRIBUTION ds2; +CREATE DISTRIBUTION ds1 COLUMN TYPES int; +CREATE DISTRIBUTION ds2 COLUMN TYPES int; CREATE KEY RANGE krid1 FROM 1 ROUTE TO sh1 FOR DISTRIBUTION ds1; CREATE KEY RANGE krid2 FROM 11 ROUTE TO sh2 FOR DISTRIBUTION ds1; diff --git a/test/regress/tests/router/expected/alter_distribution.out b/test/regress/tests/router/expected/alter_distribution.out index 45561545b..62e28bae6 100644 --- a/test/regress/tests/router/expected/alter_distribution.out +++ b/test/regress/tests/router/expected/alter_distribution.out @@ -6,13 +6,13 @@ You can find documentation here https://github.com/pg-sharding/spqr/tree/master/docs -CREATE DISTRIBUTION ds1; +CREATE DISTRIBUTION ds1 COLUMN TYPES int; add distribution ---------------------------------- created distribution with id ds1 (1 row) -CREATE DISTRIBUTION ds2; +CREATE DISTRIBUTION ds2 COLUMN TYPES int; add distribution ---------------------------------- created distribution with id ds2 @@ -55,7 +55,7 @@ ALTER DISTRIBUTION ds2 ATTACH RELATION yy DISTRIBUTION KEY w_id; (1 row) ALTER DISTRIBUTION ds3 ATTACH RELATION xx DISTRIBUTION KEY w_id; -ERROR: no such distribution. +ERROR: distribution "ds3" not found. ALTER DISTRIBUTION ds1 ATTACH RELATION xx DISTRIBUTION KEY w_id; ERROR: relation "xx" is already attached. \c regress diff --git a/test/regress/tests/router/expected/copy_routing.out b/test/regress/tests/router/expected/copy_routing.out index 673e4dc0e..5139f490b 100644 --- a/test/regress/tests/router/expected/copy_routing.out +++ b/test/regress/tests/router/expected/copy_routing.out @@ -6,7 +6,7 @@ You can find documentation here https://github.com/pg-sharding/spqr/tree/master/docs -CREATE DISTRIBUTION ds1; +CREATE DISTRIBUTION ds1 COLUMN TYPES int; add distribution ---------------------------------- created distribution with id ds1 diff --git a/test/regress/tests/router/sql/alter_distribution.sql b/test/regress/tests/router/sql/alter_distribution.sql index de0065851..914dc1923 100644 --- a/test/regress/tests/router/sql/alter_distribution.sql +++ b/test/regress/tests/router/sql/alter_distribution.sql @@ -1,7 +1,7 @@ \c spqr-console -CREATE DISTRIBUTION ds1; -CREATE DISTRIBUTION ds2; +CREATE DISTRIBUTION ds1 COLUMN TYPES int; +CREATE DISTRIBUTION ds2 COLUMN TYPES int; CREATE KEY RANGE krid1 FROM 1 ROUTE TO sh1 FOR DISTRIBUTION ds1; CREATE KEY RANGE krid2 FROM 11 ROUTE TO sh2 FOR DISTRIBUTION ds1; @@ -46,4 +46,5 @@ DROP TABLE yy; \c spqr-console DROP DISTRIBUTION ALL CASCADE; -DROP KEY RANGE ALL; \ No newline at end of file +DROP KEY RANGE ALL; + diff --git a/test/regress/tests/router/sql/copy_routing.sql b/test/regress/tests/router/sql/copy_routing.sql index b57fd9113..8e4010484 100644 --- a/test/regress/tests/router/sql/copy_routing.sql +++ b/test/regress/tests/router/sql/copy_routing.sql @@ -1,5 +1,5 @@ \c spqr-console -CREATE DISTRIBUTION ds1; +CREATE DISTRIBUTION ds1 COLUMN TYPES int; CREATE KEY RANGE krid1 FROM 1 ROUTE TO sh1 FOR DISTRIBUTION ds1; CREATE KEY RANGE krid2 FROM 30 ROUTE TO sh2 FOR DISTRIBUTION ds1; ALTER DISTRIBUTION ds1 ATTACH RELATION copy_test DISTRIBUTION KEY id; diff --git a/yacc/console/ast.go b/yacc/console/ast.go index 35285b270..10bf4afc8 100644 --- a/yacc/console/ast.go +++ b/yacc/console/ast.go @@ -87,8 +87,12 @@ type ShardingRuleEntry struct { HashFunction string } +type KeyRangeBound struct { + Pivots [][]byte +} + type KeyRangeDefinition struct { - LowerBound []byte + LowerBound *KeyRangeBound ShardID string KeyRangeID string Distribution string @@ -105,7 +109,7 @@ func (*DistributionDefinition) iCreate() {} func (*ShardingRuleDefinition) iCreate() {} type SplitKeyRange struct { - Border []byte + Border *KeyRangeBound KeyRangeFromID string KeyRangeID string } diff --git a/yacc/console/gram.go b/yacc/console/gram.go index 3f4177fe6..38a1d0723 100644 --- a/yacc/console/gram.go +++ b/yacc/console/gram.go @@ -9,6 +9,7 @@ import __yyfmt__ "fmt" import ( "crypto/rand" + "encoding/binary" "encoding/hex" "strconv" "strings" @@ -22,7 +23,7 @@ func randomHex(n int) (string, error) { return hex.EncodeToString(bytes), nil } -//line gram.y:24 +//line gram.y:25 type yySymType struct { yys int str string @@ -45,6 +46,8 @@ type yySymType struct { lock *Lock unlock *Unlock + krbound *KeyRangeBound + ds *DistributionDefinition kr *KeyRangeDefinition shard *ShardDefinition @@ -244,7 +247,7 @@ const yyEofCode = 1 const yyErrCode = 2 const yyInitialStackSize = 16 -//line gram.y:825 +//line gram.y:838 //line yacctab:1 var yyExca = [...]int8{ @@ -255,84 +258,83 @@ var yyExca = [...]int8{ const yyPrivate = 57344 -const yyLast = 243 +const yyLast = 241 var yyAct = [...]uint8{ - 130, 173, 212, 168, 176, 153, 142, 152, 127, 141, - 137, 114, 99, 91, 169, 170, 171, 120, 139, 27, - 28, 88, 52, 51, 204, 205, 206, 67, 175, 134, - 144, 30, 29, 34, 35, 68, 81, 21, 20, 24, - 25, 26, 31, 32, 80, 145, 86, 84, 36, 87, - 118, 81, 81, 81, 104, 175, 81, 208, 207, 94, - 95, 198, 197, 103, 81, 147, 102, 162, 90, 151, - 119, 144, 82, 33, 138, 135, 105, 106, 193, 101, - 94, 22, 23, 113, 116, 190, 145, 66, 79, 96, - 123, 125, 200, 124, 56, 194, 89, 123, 83, 54, - 121, 58, 177, 131, 132, 133, 59, 126, 122, 107, - 93, 85, 61, 115, 44, 57, 146, 117, 112, 45, - 81, 43, 110, 148, 109, 140, 46, 92, 196, 195, - 149, 183, 182, 76, 75, 42, 164, 158, 38, 166, - 163, 100, 41, 53, 40, 178, 179, 165, 174, 39, - 172, 218, 78, 180, 185, 115, 155, 50, 191, 184, - 181, 157, 156, 186, 49, 188, 48, 155, 189, 60, - 62, 47, 157, 156, 192, 72, 73, 74, 81, 174, - 187, 160, 81, 70, 98, 64, 37, 70, 161, 1, - 128, 199, 69, 71, 202, 201, 69, 150, 209, 210, - 18, 213, 17, 16, 15, 14, 12, 13, 214, 215, - 8, 216, 217, 9, 111, 167, 220, 221, 219, 213, - 136, 222, 108, 77, 19, 203, 143, 211, 6, 5, - 4, 3, 7, 11, 10, 65, 63, 55, 2, 129, - 159, 154, 97, + 130, 175, 210, 170, 178, 150, 149, 142, 148, 127, + 154, 141, 114, 137, 91, 171, 172, 173, 120, 151, + 139, 88, 52, 51, 204, 205, 206, 144, 86, 67, + 134, 87, 177, 81, 118, 68, 81, 81, 81, 81, + 104, 207, 145, 198, 80, 81, 103, 84, 147, 102, + 164, 153, 177, 119, 144, 90, 82, 138, 56, 94, + 95, 44, 135, 54, 194, 58, 45, 191, 43, 145, + 59, 79, 200, 46, 96, 81, 105, 106, 195, 89, + 94, 83, 61, 113, 116, 99, 101, 179, 85, 66, + 123, 125, 115, 124, 122, 107, 93, 123, 117, 27, + 28, 112, 92, 131, 132, 133, 57, 121, 126, 76, + 115, 30, 29, 34, 35, 42, 146, 21, 20, 24, + 25, 26, 31, 32, 183, 155, 140, 75, 36, 110, + 183, 109, 41, 40, 38, 196, 166, 50, 160, 168, + 165, 184, 100, 78, 214, 180, 181, 39, 81, 176, + 167, 53, 174, 33, 49, 48, 182, 183, 186, 155, + 128, 22, 23, 192, 185, 157, 187, 189, 162, 47, + 159, 158, 81, 190, 157, 163, 193, 60, 62, 159, + 158, 98, 176, 72, 73, 74, 64, 188, 70, 37, + 197, 1, 199, 70, 18, 202, 201, 69, 71, 208, + 17, 211, 69, 152, 16, 15, 14, 12, 212, 13, + 213, 8, 9, 111, 216, 211, 215, 217, 169, 136, + 108, 77, 19, 203, 143, 209, 6, 5, 4, 3, + 7, 11, 10, 65, 63, 55, 2, 129, 161, 156, + 97, } var yyPact = [...]int16{ - 13, -1000, 123, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 93, -1000, 119, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 77, 77, -47, -48, 57, 70, 70, 181, 23, 179, - -1000, 70, 70, 70, 112, 111, 44, -1000, -1000, -1000, - -1000, -1000, -1000, 178, 20, 55, 52, -1000, -1000, -1000, - -1000, -15, -50, -1000, 53, -1000, 16, 94, 49, 178, - -1000, 46, -1000, 176, -1000, 127, 127, -1000, -1000, -1000, - -1000, -1000, 9, 5, -5, 178, 48, -1000, 88, 178, - 80, -1000, 116, 60, -9, 15, -54, 127, -1000, 47, - 32, -1000, -1000, 94, -1000, -1000, 178, -1000, 174, -1000, - -1000, -1000, 178, 178, 178, -33, -1000, -1000, -1000, 30, - 29, -1000, -57, 74, 33, 178, 8, 183, 14, 179, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 152, 174, 177, - -1000, 11, -1000, -1000, 179, 178, 29, -1000, 178, -58, - 33, -8, -1000, 62, 178, 178, -1000, 183, 109, 108, - -1000, 179, 142, -1000, 174, -1000, -1000, -1000, 163, 179, - -1000, -1000, 179, -1000, -1000, -1000, 41, 146, -1000, -1000, - -1000, -1000, -8, -1000, -1000, 34, -1000, 54, -1000, -1000, - 106, 105, 4, 3, 142, 179, 152, -1000, -1000, -1000, - 50, -58, -1000, 178, -41, 0, -1, 178, 178, -1000, - 178, -1000, -1000, -1000, -1000, -1000, -1000, 178, 178, -35, - -35, 139, -1000, 62, -35, -35, -1000, -1000, 178, -1000, - -1000, -1000, -1000, + 24, 24, -47, -48, 21, 40, 40, 182, 25, 184, + -1000, 40, 40, 40, 105, 87, 27, -1000, -1000, -1000, + -1000, -1000, -1000, 168, 4, 38, 29, -1000, -1000, -1000, + -1000, -33, -50, -1000, 36, -1000, 3, 69, 35, 168, + -1000, 31, -1000, 173, -1000, 128, 128, -1000, -1000, -1000, + -1000, -1000, -8, -12, -19, 168, 34, -1000, 95, 168, + 63, -1000, 71, 41, -25, -2, -53, 128, -1000, 33, + 32, -1000, -1000, 69, -1000, -1000, 168, -1000, 144, -1000, + -1000, -1000, 168, 168, 168, -32, -1000, -1000, -1000, 17, + 12, -1000, -55, 53, 16, 168, -9, 189, -4, 184, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 161, 144, 164, + -1000, -6, -1000, -1000, 184, 168, 12, -1000, 168, -57, + 16, -11, -1000, 47, 168, 168, -1000, 189, 118, -1000, + -1000, -1000, -1000, 184, 146, -1000, 144, -1000, -1000, -1000, + 170, 184, -1000, -1000, 189, -1000, -1000, -1000, 23, 151, + -1000, -1000, -1000, -1000, -11, -1000, -1000, 20, -1000, 37, + -1000, -1000, 112, 189, -15, 146, 184, 161, -1000, -1000, + 145, 30, -57, -1000, 168, -41, -17, -1000, 168, -1000, + 168, -1000, -1000, -1000, -1000, -1000, -1000, 168, -31, 132, + -1000, 47, -31, -1000, 168, -1000, -1000, -1000, } var yyPgo = [...]uint8{ - 0, 242, 8, 241, 240, 239, 5, 0, 12, 238, - 237, 143, 115, 236, 235, 234, 233, 232, 231, 230, - 229, 228, 149, 144, 142, 135, 9, 227, 6, 2, - 11, 226, 4, 225, 1, 224, 223, 222, 220, 10, - 215, 214, 7, 3, 13, 213, 210, 207, 206, 205, - 204, 203, 202, 200, 189, 186, + 0, 240, 9, 6, 8, 239, 238, 237, 5, 0, + 19, 236, 235, 151, 106, 234, 233, 232, 231, 230, + 229, 228, 227, 226, 147, 133, 132, 115, 11, 225, + 7, 2, 12, 224, 4, 223, 1, 222, 221, 220, + 219, 13, 218, 213, 10, 3, 14, 212, 211, 209, + 207, 206, 205, 204, 200, 194, 191, 189, } var yyR1 = [...]int8{ - 0, 54, 55, 55, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 8, 6, 6, 6, 7, 3, 3, 3, 4, - 4, 5, 2, 2, 2, 1, 1, 13, 14, 44, - 44, 17, 17, 17, 17, 17, 17, 17, 18, 18, - 18, 18, 20, 20, 21, 35, 36, 36, 27, 27, - 29, 39, 38, 38, 37, 19, 19, 19, 19, 15, - 46, 22, 41, 41, 40, 40, 43, 43, 43, 23, - 23, 26, 26, 28, 30, 30, 31, 31, 33, 33, - 33, 32, 32, 34, 24, 24, 24, 24, 25, 25, - 42, 42, 45, 10, 11, 12, 49, 16, 16, 50, - 51, 48, 47, 52, 53, 53, + 0, 56, 57, 57, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 10, 8, 8, 8, 9, 5, 5, 5, 6, + 6, 7, 2, 2, 2, 1, 1, 15, 16, 46, + 46, 19, 19, 19, 19, 19, 19, 19, 20, 20, + 20, 20, 22, 22, 23, 37, 38, 38, 29, 29, + 31, 41, 40, 40, 39, 21, 21, 21, 21, 17, + 48, 24, 43, 43, 42, 42, 45, 45, 45, 25, + 25, 28, 28, 30, 32, 32, 33, 33, 35, 35, + 35, 34, 34, 36, 3, 3, 4, 4, 26, 26, + 27, 27, 44, 44, 47, 12, 13, 14, 51, 18, + 18, 52, 53, 50, 49, 54, 55, 55, } var yyR2 = [...]int8{ @@ -345,61 +347,59 @@ var yyR2 = [...]int8{ 2, 5, 1, 2, 2, 2, 2, 2, 2, 3, 2, 3, 3, 0, 3, 1, 1, 1, 1, 6, 5, 1, 2, 2, 2, 0, 2, 2, 1, 1, - 1, 3, 0, 3, 9, 9, 8, 8, 5, 4, - 1, 3, 2, 3, 3, 2, 6, 3, 3, 4, - 4, 2, 1, 5, 3, 3, + 1, 3, 0, 3, 1, 1, 1, 3, 9, 8, + 5, 4, 1, 3, 2, 3, 3, 2, 6, 3, + 3, 4, 4, 2, 1, 5, 3, 3, } var yyChk = [...]int16{ - -1000, -54, -9, -18, -19, -20, -21, -17, -46, -45, - -15, -16, -48, -47, -49, -50, -51, -52, -53, -35, + -1000, -56, -11, -20, -21, -22, -23, -19, -48, -47, + -17, -18, -50, -49, -51, -52, -53, -54, -55, -37, 25, 24, 68, 69, 26, 27, 28, 6, 7, 19, - 18, 29, 30, 60, 20, 21, 35, -55, 15, -22, - -23, -24, -25, 44, 37, 42, 49, -22, -23, -24, - -25, 70, 70, -11, 42, -10, 37, -12, 44, 49, - -11, 42, -11, -13, 4, -14, 64, 4, -6, 13, - 4, 14, -11, -11, -11, 22, 22, -36, -12, 44, - -7, 4, 52, 43, -7, 59, 61, 64, 71, 43, - 52, -44, 33, 61, -7, -7, 43, -1, 8, -8, - 14, -8, 57, 58, 59, -7, -7, 61, -37, 36, - 34, -41, 38, -7, -30, 39, -7, 57, 59, 55, - 71, -8, 61, -7, 61, -7, -44, -2, 16, -5, - -7, -7, -7, -7, 62, 45, -38, -39, 45, 75, - -30, -26, -28, -31, 38, 53, -7, 57, -6, -8, - 14, 55, -42, -6, -3, 4, 10, 9, -2, -4, - 4, 11, 56, -6, -7, -39, -7, -40, -43, 72, - 73, 74, -26, -34, -28, 63, -32, 40, -7, -7, - -6, -8, 23, 23, -42, 12, -2, 17, -6, -6, - 44, 12, -34, 44, 41, 23, 23, 58, 58, -6, - 42, -43, -7, -33, 65, 66, 67, 58, 58, -7, - -7, -27, -29, -7, -7, -7, -34, -34, 12, -32, - -34, -34, -29, + 18, 29, 30, 60, 20, 21, 35, -57, 15, -24, + -25, -26, -27, 44, 37, 42, 49, -24, -25, -26, + -27, 70, 70, -13, 42, -12, 37, -14, 44, 49, + -13, 42, -13, -15, 4, -16, 64, 4, -8, 13, + 4, 14, -13, -13, -13, 22, 22, -38, -14, 44, + -9, 4, 52, 43, -9, 59, 61, 64, 71, 43, + 52, -46, 33, 61, -9, -9, 43, -1, 8, -10, + 14, -10, 57, 58, 59, -9, -9, 61, -39, 36, + 34, -43, 38, -9, -32, 39, -9, 57, 59, 55, + 71, -10, 61, -9, 61, -9, -46, -2, 16, -7, + -9, -9, -9, -9, 62, 45, -40, -41, 45, 75, + -32, -28, -30, -33, 38, 53, -9, 57, -4, -3, + -8, -10, 14, 55, -44, -8, -5, 4, 10, 9, + -2, -6, 4, 11, 56, -8, -9, -41, -9, -42, + -45, 72, 73, 74, -28, -36, -30, 63, -34, 40, + -9, -9, -4, 12, 23, -44, 12, -2, 17, -8, + -4, 44, 12, -36, 44, 41, 23, -3, 58, -8, + 42, -45, -9, -35, 65, 66, 67, 58, -9, -29, + -31, -9, -9, -36, 12, -34, -36, -31, } var yyDef = [...]int8{ 0, -2, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 112, 0, 0, 0, 0, 0, 0, 1, 3, 48, + 114, 0, 0, 0, 0, 0, 0, 1, 3, 48, 49, 50, 51, 0, 0, 0, 0, 65, 66, 67, 68, 0, 0, 41, 0, 43, 0, 40, 0, 0, - 70, 0, 102, 35, 37, 0, 0, 38, 111, 22, + 70, 0, 104, 35, 37, 0, 0, 38, 113, 22, 23, 24, 0, 0, 0, 0, 0, 55, 0, 0, 73, 25, 85, 0, 0, 0, 0, 0, 54, 0, - 0, 45, 39, 40, 105, 47, 0, 69, 0, 107, - 21, 108, 0, 0, 0, 0, 114, 115, 56, 0, + 0, 45, 39, 40, 107, 47, 0, 69, 0, 109, + 21, 110, 0, 0, 0, 0, 116, 117, 56, 0, 0, 71, 0, 85, 0, 0, 0, 0, 0, 0, - 52, 53, 42, 104, 44, 103, 46, 36, 0, 0, - 31, 0, 109, 110, 0, 0, 64, 62, 0, 0, - 0, 0, 81, 92, 0, 0, 84, 0, 0, 0, - 21, 0, 99, 100, 0, 26, 27, 28, 0, 0, - 29, 30, 0, 113, 57, 63, 0, 72, 75, 76, - 77, 78, 0, 80, 82, 0, 83, 0, 86, 87, - 0, 0, 0, 0, 98, 0, 34, 32, 33, 106, - 0, 0, 79, 0, 0, 0, 0, 0, 0, 101, - 0, 74, 93, 91, 88, 89, 90, 0, 0, 0, - 0, 61, 59, 92, 0, 0, 96, 97, 0, 60, - 94, 95, 58, + 52, 53, 42, 106, 44, 105, 46, 36, 0, 0, + 31, 0, 111, 112, 0, 0, 64, 62, 0, 0, + 0, 0, 81, 92, 0, 0, 84, 0, 0, 96, + 94, 95, 21, 0, 101, 102, 0, 26, 27, 28, + 0, 0, 29, 30, 0, 115, 57, 63, 0, 72, + 75, 76, 77, 78, 0, 80, 82, 0, 83, 0, + 86, 87, 0, 0, 0, 100, 0, 34, 32, 33, + 108, 0, 0, 79, 0, 0, 0, 97, 0, 103, + 0, 74, 93, 91, 88, 89, 90, 0, 0, 61, + 59, 92, 0, 99, 0, 60, 98, 58, } var yyTok1 = [...]int8{ @@ -760,179 +760,179 @@ yydefault: case 2: yyDollar = yyS[yypt-0 : yypt+1] -//line gram.y:211 +//line gram.y:221 { } case 3: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:212 +//line gram.y:222 { } case 4: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:217 +//line gram.y:227 { setParseTree(yylex, yyDollar[1].create) } case 5: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:221 +//line gram.y:231 { setParseTree(yylex, yyDollar[1].create) } case 6: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:225 +//line gram.y:235 { setParseTree(yylex, yyDollar[1].trace) } case 7: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:229 +//line gram.y:239 { setParseTree(yylex, yyDollar[1].stoptrace) } case 8: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:233 +//line gram.y:243 { setParseTree(yylex, yyDollar[1].drop) } case 9: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:237 +//line gram.y:247 { setParseTree(yylex, yyDollar[1].lock) } case 10: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:241 +//line gram.y:251 { setParseTree(yylex, yyDollar[1].unlock) } case 11: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:245 +//line gram.y:255 { setParseTree(yylex, yyDollar[1].show) } case 12: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:249 +//line gram.y:259 { setParseTree(yylex, yyDollar[1].kill) } case 13: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:253 +//line gram.y:263 { setParseTree(yylex, yyDollar[1].listen) } case 14: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:257 +//line gram.y:267 { setParseTree(yylex, yyDollar[1].shutdown) } case 15: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:261 +//line gram.y:271 { setParseTree(yylex, yyDollar[1].split) } case 16: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:265 +//line gram.y:275 { setParseTree(yylex, yyDollar[1].move) } case 17: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:269 +//line gram.y:279 { setParseTree(yylex, yyDollar[1].unite) } case 18: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:273 +//line gram.y:283 { setParseTree(yylex, yyDollar[1].register_router) } case 19: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:277 +//line gram.y:287 { setParseTree(yylex, yyDollar[1].unregister_router) } case 20: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:281 +//line gram.y:291 { setParseTree(yylex, yyDollar[1].alter) } case 21: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:286 +//line gram.y:296 { yyVAL.uinteger = uint(yyDollar[1].uinteger) } case 22: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:291 +//line gram.y:301 { yyVAL.str = string(yyDollar[1].str) } case 23: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:295 +//line gram.y:305 { yyVAL.str = string(yyDollar[1].str) } case 24: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:297 +//line gram.y:307 { yyVAL.str = strconv.Itoa(int(yyDollar[1].uinteger)) } case 25: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:302 +//line gram.y:312 { yyVAL.str = string(yyDollar[1].str) } case 26: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:308 +//line gram.y:318 { yyVAL.str = yyDollar[1].str } case 27: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:310 +//line gram.y:320 { yyVAL.str = "AND" } case 28: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:312 +//line gram.y:322 { yyVAL.str = "OR" } case 29: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:317 +//line gram.y:327 { yyVAL.str = yyDollar[1].str } case 30: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:319 +//line gram.y:329 { yyVAL.str = "=" } case 31: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:325 +//line gram.y:335 { yyVAL.colref = ColumnRef{ ColName: yyDollar[1].str, @@ -940,13 +940,13 @@ yydefault: } case 32: yyDollar = yyS[yypt-3 : yypt+1] -//line gram.y:333 +//line gram.y:343 { yyVAL.where = yyDollar[2].where } case 33: yyDollar = yyS[yypt-3 : yypt+1] -//line gram.y:336 +//line gram.y:346 { yyVAL.where = WhereClauseLeaf{ ColRef: yyDollar[1].colref, @@ -956,7 +956,7 @@ yydefault: } case 34: yyDollar = yyS[yypt-3 : yypt+1] -//line gram.y:344 +//line gram.y:354 { yyVAL.where = WhereClauseOp{ Op: yyDollar[2].str, @@ -966,19 +966,19 @@ yydefault: } case 35: yyDollar = yyS[yypt-0 : yypt+1] -//line gram.y:354 +//line gram.y:364 { yyVAL.where = WhereClauseEmpty{} } case 36: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:358 +//line gram.y:368 { yyVAL.where = yyDollar[2].where } case 37: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:365 +//line gram.y:375 { switch v := strings.ToLower(string(yyDollar[1].str)); v { case DatabasesStr, RoutersStr, PoolsStr, ShardsStr, BackendConnectionsStr, KeyRangesStr, ShardingRules, ClientsStr, StatusStr, DistributionsStr, VersionStr, RelationsStr: @@ -989,7 +989,7 @@ yydefault: } case 38: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:376 +//line gram.y:386 { switch v := string(yyDollar[1].str); v { case ClientStr: @@ -1000,91 +1000,91 @@ yydefault: } case 39: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:386 +//line gram.y:396 { yyVAL.bool = true } case 40: yyDollar = yyS[yypt-0 : yypt+1] -//line gram.y:386 +//line gram.y:396 { yyVAL.bool = false } case 41: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:390 +//line gram.y:400 { yyVAL.drop = &Drop{Element: yyDollar[2].key_range_selector} } case 42: yyDollar = yyS[yypt-4 : yypt+1] -//line gram.y:394 +//line gram.y:404 { yyVAL.drop = &Drop{Element: &KeyRangeSelector{KeyRangeID: `*`}} } case 43: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:398 +//line gram.y:408 { yyVAL.drop = &Drop{Element: yyDollar[2].sharding_rule_selector} } case 44: yyDollar = yyS[yypt-4 : yypt+1] -//line gram.y:402 +//line gram.y:412 { yyVAL.drop = &Drop{Element: &ShardingRuleSelector{ID: `*`}} } case 45: yyDollar = yyS[yypt-3 : yypt+1] -//line gram.y:406 +//line gram.y:416 { yyVAL.drop = &Drop{Element: yyDollar[2].distribution_selector, CascadeDelete: yyDollar[3].bool} } case 46: yyDollar = yyS[yypt-4 : yypt+1] -//line gram.y:410 +//line gram.y:420 { yyVAL.drop = &Drop{Element: &DistributionSelector{ID: `*`}, CascadeDelete: yyDollar[4].bool} } case 47: yyDollar = yyS[yypt-3 : yypt+1] -//line gram.y:414 +//line gram.y:424 { yyVAL.drop = &Drop{Element: &ShardSelector{ID: yyDollar[3].str}} } case 48: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:421 +//line gram.y:431 { yyVAL.create = &Create{Element: yyDollar[2].ds} } case 49: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:426 +//line gram.y:436 { yyVAL.create = &Create{Element: yyDollar[2].sharding_rule} } case 50: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:431 +//line gram.y:441 { yyVAL.create = &Create{Element: yyDollar[2].kr} } case 51: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:435 +//line gram.y:445 { yyVAL.create = &Create{Element: yyDollar[2].shard} } case 52: yyDollar = yyS[yypt-4 : yypt+1] -//line gram.y:441 +//line gram.y:451 { yyVAL.trace = &TraceStmt{All: true} } case 53: yyDollar = yyS[yypt-4 : yypt+1] -//line gram.y:444 +//line gram.y:454 { yyVAL.trace = &TraceStmt{ Client: yyDollar[4].uinteger, @@ -1092,19 +1092,19 @@ yydefault: } case 54: yyDollar = yyS[yypt-3 : yypt+1] -//line gram.y:452 +//line gram.y:462 { yyVAL.stoptrace = &StopTraceStmt{} } case 55: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:458 +//line gram.y:468 { yyVAL.alter = &Alter{Element: yyDollar[2].alter_distribution} } case 56: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:464 +//line gram.y:474 { yyVAL.alter_distribution = &AlterDistribution{ Element: &AttachRelation{ @@ -1115,7 +1115,7 @@ yydefault: } case 57: yyDollar = yyS[yypt-4 : yypt+1] -//line gram.y:473 +//line gram.y:483 { yyVAL.alter_distribution = &AlterDistribution{ Element: &DetachRelation{ @@ -1126,13 +1126,13 @@ yydefault: } case 58: yyDollar = yyS[yypt-3 : yypt+1] -//line gram.y:485 +//line gram.y:495 { yyVAL.dEntrieslist = append(yyDollar[1].dEntrieslist, yyDollar[3].distrKeyEntry) } case 59: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:487 +//line gram.y:497 { yyVAL.dEntrieslist = []DistributionKeyEntry{ yyDollar[1].distrKeyEntry, @@ -1140,7 +1140,7 @@ yydefault: } case 60: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:497 +//line gram.y:507 { yyVAL.distrKeyEntry = DistributionKeyEntry{ Column: yyDollar[1].str, @@ -1149,7 +1149,7 @@ yydefault: } case 61: yyDollar = yyS[yypt-5 : yypt+1] -//line gram.y:506 +//line gram.y:516 { yyVAL.distributed_relation = &DistributedRelation{ Name: yyDollar[2].str, @@ -1158,61 +1158,61 @@ yydefault: } case 62: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:515 +//line gram.y:525 { yyVAL.relations = []*DistributedRelation{yyDollar[1].distributed_relation} } case 63: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:517 +//line gram.y:527 { yyVAL.relations = append(yyDollar[1].relations, yyDollar[2].distributed_relation) } case 64: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:522 +//line gram.y:532 { yyVAL.relations = yyDollar[2].relations } case 65: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:528 +//line gram.y:538 { yyVAL.create = &Create{Element: yyDollar[2].ds} } case 66: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:533 +//line gram.y:543 { yyVAL.create = &Create{Element: yyDollar[2].sharding_rule} } case 67: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:538 +//line gram.y:548 { yyVAL.create = &Create{Element: yyDollar[2].kr} } case 68: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:542 +//line gram.y:552 { yyVAL.create = &Create{Element: yyDollar[2].shard} } case 69: yyDollar = yyS[yypt-3 : yypt+1] -//line gram.y:549 +//line gram.y:559 { yyVAL.show = &Show{Cmd: yyDollar[2].str, Where: yyDollar[3].where} } case 70: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:555 +//line gram.y:565 { yyVAL.lock = &Lock{KeyRangeID: yyDollar[2].key_range_selector.KeyRangeID} } case 71: yyDollar = yyS[yypt-3 : yypt+1] -//line gram.y:563 +//line gram.y:573 { yyVAL.ds = &DistributionDefinition{ ID: yyDollar[2].str, @@ -1221,26 +1221,26 @@ yydefault: } case 72: yyDollar = yyS[yypt-3 : yypt+1] -//line gram.y:571 +//line gram.y:581 { yyVAL.strlist = yyDollar[3].strlist } case 73: yyDollar = yyS[yypt-0 : yypt+1] -//line gram.y:573 +//line gram.y:583 { /* empty column types should be prohibited */ yyVAL.strlist = nil } case 74: yyDollar = yyS[yypt-3 : yypt+1] -//line gram.y:579 +//line gram.y:589 { yyVAL.strlist = append(yyDollar[1].strlist, yyDollar[3].str) } case 75: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:581 +//line gram.y:591 { yyVAL.strlist = []string{ yyDollar[1].str, @@ -1248,31 +1248,31 @@ yydefault: } case 76: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:588 +//line gram.y:598 { yyVAL.str = "varchar" } case 77: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:590 +//line gram.y:600 { yyVAL.str = "integer" } case 78: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:592 +//line gram.y:602 { yyVAL.str = "integer" } case 79: yyDollar = yyS[yypt-6 : yypt+1] -//line gram.y:598 +//line gram.y:608 { yyVAL.sharding_rule = &ShardingRuleDefinition{ID: yyDollar[3].str, TableName: yyDollar[4].str, Entries: yyDollar[5].entrieslist, Distribution: yyDollar[6].str} } case 80: yyDollar = yyS[yypt-5 : yypt+1] -//line gram.y:603 +//line gram.y:613 { str, err := randomHex(6) if err != nil { @@ -1282,20 +1282,20 @@ yydefault: } case 81: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:612 +//line gram.y:622 { yyVAL.entrieslist = make([]ShardingRuleEntry, 0) yyVAL.entrieslist = append(yyVAL.entrieslist, yyDollar[1].shruleEntry) } case 82: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:618 +//line gram.y:628 { yyVAL.entrieslist = append(yyDollar[1].entrieslist, yyDollar[2].shruleEntry) } case 83: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:624 +//line gram.y:634 { yyVAL.shruleEntry = ShardingRuleEntry{ Column: yyDollar[1].str, @@ -1304,125 +1304,131 @@ yydefault: } case 84: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:633 +//line gram.y:643 { yyVAL.str = yyDollar[2].str } case 85: yyDollar = yyS[yypt-0 : yypt+1] -//line gram.y:636 +//line gram.y:646 { yyVAL.str = "" } case 86: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:640 +//line gram.y:650 { yyVAL.str = yyDollar[2].str } case 87: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:645 +//line gram.y:655 { yyVAL.str = yyDollar[2].str } case 88: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:651 +//line gram.y:661 { yyVAL.str = "identity" } case 89: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:653 +//line gram.y:663 { yyVAL.str = "murmur" } case 90: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:655 +//line gram.y:665 { yyVAL.str = "city" } case 91: yyDollar = yyS[yypt-3 : yypt+1] -//line gram.y:661 +//line gram.y:671 { yyVAL.str = yyDollar[3].str } case 92: yyDollar = yyS[yypt-0 : yypt+1] -//line gram.y:663 +//line gram.y:673 { yyVAL.str = "" } case 93: yyDollar = yyS[yypt-3 : yypt+1] -//line gram.y:668 +//line gram.y:678 { yyVAL.str = yyDollar[3].str } case 94: - yyDollar = yyS[yypt-9 : yypt+1] -//line gram.y:674 + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:683 { - yyVAL.kr = &KeyRangeDefinition{ - KeyRangeID: yyDollar[3].str, - LowerBound: []byte(yyDollar[5].str), - ShardID: yyDollar[8].str, - Distribution: yyDollar[9].str, - } + yyVAL.bytes = []byte(yyDollar[1].str) } case 95: - yyDollar = yyS[yypt-9 : yypt+1] -//line gram.y:683 + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:686 { - yyVAL.kr = &KeyRangeDefinition{ - KeyRangeID: yyDollar[3].str, - LowerBound: []byte(strconv.FormatUint(uint64(yyDollar[5].uinteger), 10)), - ShardID: yyDollar[8].str, - Distribution: yyDollar[9].str, - } + buf := make([]byte, 8) + binary.PutVarint(buf, int64(yyDollar[1].uinteger)) + yyVAL.bytes = buf } case 96: - yyDollar = yyS[yypt-8 : yypt+1] -//line gram.y:692 + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:693 { - str, err := randomHex(6) - if err != nil { - panic(err) + yyVAL.krbound = &KeyRangeBound{ + Pivots: [][]byte{ + yyDollar[1].bytes, + }, } + } + case 97: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:700 + { + yyVAL.krbound = &KeyRangeBound{ + Pivots: append(yyDollar[1].krbound.Pivots, yyDollar[3].bytes), + } + } + case 98: + yyDollar = yyS[yypt-9 : yypt+1] +//line gram.y:709 + { yyVAL.kr = &KeyRangeDefinition{ - LowerBound: []byte(yyDollar[4].str), - Distribution: yyDollar[6].str, - ShardID: yyDollar[7].str, - KeyRangeID: "kr" + str, + KeyRangeID: yyDollar[3].str, + LowerBound: yyDollar[5].krbound, + ShardID: yyDollar[8].str, + Distribution: yyDollar[9].str, } } - case 97: + case 99: yyDollar = yyS[yypt-8 : yypt+1] -//line gram.y:705 +//line gram.y:718 { str, err := randomHex(6) if err != nil { panic(err) } yyVAL.kr = &KeyRangeDefinition{ - LowerBound: []byte(strconv.FormatUint(uint64(yyDollar[4].uinteger), 10)), + LowerBound: yyDollar[4].krbound, ShardID: yyDollar[7].str, - KeyRangeID: "kr" + str, Distribution: yyDollar[8].str, + KeyRangeID: "kr" + str, } } - case 98: + case 100: yyDollar = yyS[yypt-5 : yypt+1] -//line gram.y:720 +//line gram.y:733 { yyVAL.shard = &ShardDefinition{Id: yyDollar[2].str, Hosts: yyDollar[5].strlist} } - case 99: + case 101: yyDollar = yyS[yypt-4 : yypt+1] -//line gram.y:725 +//line gram.y:738 { str, err := randomHex(6) if err != nil { @@ -1430,99 +1436,99 @@ yydefault: } yyVAL.shard = &ShardDefinition{Id: "shard" + str, Hosts: yyDollar[4].strlist} } - case 100: + case 102: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:735 +//line gram.y:748 { yyVAL.strlist = []string{yyDollar[1].str} } - case 101: + case 103: yyDollar = yyS[yypt-3 : yypt+1] -//line gram.y:740 +//line gram.y:753 { yyVAL.strlist = append(yyDollar[1].strlist, yyDollar[3].str) } - case 102: + case 104: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:746 +//line gram.y:759 { yyVAL.unlock = &Unlock{KeyRangeID: yyDollar[2].key_range_selector.KeyRangeID} } - case 103: + case 105: yyDollar = yyS[yypt-3 : yypt+1] -//line gram.y:752 +//line gram.y:765 { yyVAL.sharding_rule_selector = &ShardingRuleSelector{ID: yyDollar[3].str} } - case 104: + case 106: yyDollar = yyS[yypt-3 : yypt+1] -//line gram.y:758 +//line gram.y:771 { yyVAL.key_range_selector = &KeyRangeSelector{KeyRangeID: yyDollar[3].str} } - case 105: + case 107: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:764 +//line gram.y:777 { yyVAL.distribution_selector = &DistributionSelector{ID: yyDollar[2].str} } - case 106: + case 108: yyDollar = yyS[yypt-6 : yypt+1] -//line gram.y:770 +//line gram.y:783 { - yyVAL.split = &SplitKeyRange{KeyRangeID: yyDollar[2].key_range_selector.KeyRangeID, KeyRangeFromID: yyDollar[4].str, Border: []byte(yyDollar[6].str)} + yyVAL.split = &SplitKeyRange{KeyRangeID: yyDollar[2].key_range_selector.KeyRangeID, KeyRangeFromID: yyDollar[4].str, Border: yyDollar[6].krbound} } - case 107: + case 109: yyDollar = yyS[yypt-3 : yypt+1] -//line gram.y:776 +//line gram.y:789 { yyVAL.kill = &Kill{Cmd: yyDollar[2].str, Target: yyDollar[3].uinteger} } - case 108: + case 110: yyDollar = yyS[yypt-3 : yypt+1] -//line gram.y:779 +//line gram.y:792 { yyVAL.kill = &Kill{Cmd: "client", Target: yyDollar[3].uinteger} } - case 109: + case 111: yyDollar = yyS[yypt-4 : yypt+1] -//line gram.y:785 +//line gram.y:798 { yyVAL.move = &MoveKeyRange{KeyRangeID: yyDollar[2].key_range_selector.KeyRangeID, DestShardID: yyDollar[4].str} } - case 110: + case 112: yyDollar = yyS[yypt-4 : yypt+1] -//line gram.y:791 +//line gram.y:804 { yyVAL.unite = &UniteKeyRange{KeyRangeIDL: yyDollar[2].key_range_selector.KeyRangeID, KeyRangeIDR: yyDollar[4].str} } - case 111: + case 113: yyDollar = yyS[yypt-2 : yypt+1] -//line gram.y:797 +//line gram.y:810 { yyVAL.listen = &Listen{addr: yyDollar[2].str} } - case 112: + case 114: yyDollar = yyS[yypt-1 : yypt+1] -//line gram.y:803 +//line gram.y:816 { yyVAL.shutdown = &Shutdown{} } - case 113: + case 115: yyDollar = yyS[yypt-5 : yypt+1] -//line gram.y:811 +//line gram.y:824 { yyVAL.register_router = &RegisterRouter{ID: yyDollar[3].str, Addr: yyDollar[5].str} } - case 114: + case 116: yyDollar = yyS[yypt-3 : yypt+1] -//line gram.y:817 +//line gram.y:830 { yyVAL.unregister_router = &UnregisterRouter{ID: yyDollar[3].str} } - case 115: + case 117: yyDollar = yyS[yypt-3 : yypt+1] -//line gram.y:822 +//line gram.y:835 { yyVAL.unregister_router = &UnregisterRouter{ID: `*`} } diff --git a/yacc/console/gram.y b/yacc/console/gram.y index 2e532c6e3..6c087fd37 100644 --- a/yacc/console/gram.y +++ b/yacc/console/gram.y @@ -5,6 +5,7 @@ package spqrparser import ( "crypto/rand" "encoding/hex" + "encoding/binary" "strings" "strconv" ) @@ -42,6 +43,10 @@ func randomHex(n int) (string, error) { lock *Lock unlock *Unlock + + krbound *KeyRangeBound + + ds *DistributionDefinition kr *KeyRangeDefinition shard *ShardDefinition @@ -107,6 +112,11 @@ func randomHex(n int) (string, error) { %token ICONST + +%type key_range_bound_elem + +%type key_range_bound + // ';' %token TSEMICOLON @@ -669,49 +679,52 @@ distribution_membership: $$ = $3 } -key_range_define_stmt: - KEY RANGE any_id FROM any_val ROUTE TO any_id distribution_membership - { - $$ = &KeyRangeDefinition{ - KeyRangeID: $3, - LowerBound: []byte($5), - ShardID: $8, - Distribution: $9, +key_range_bound_elem: + any_val { + $$ = []byte($1) + } + | any_uint { + buf := make([]byte, 8) + binary.PutVarint(buf, int64($1)) + $$ = buf + } + +key_range_bound: + key_range_bound_elem { + $$ = &KeyRangeBound{ + Pivots: [][]byte{ + $1, + }, + } + } + | key_range_bound TCOMMA key_range_bound_elem { + $$ = &KeyRangeBound{ + Pivots: append($1.Pivots, $3), } } - | KEY RANGE any_id FROM any_uint ROUTE TO any_id distribution_membership + + +key_range_define_stmt: + KEY RANGE any_id FROM key_range_bound ROUTE TO any_id distribution_membership { $$ = &KeyRangeDefinition{ KeyRangeID: $3, - LowerBound: []byte(strconv.FormatUint(uint64($5), 10)), + LowerBound: $5, ShardID: $8, Distribution: $9, } } - | KEY RANGE FROM any_val ROUTE TO any_id distribution_membership - { - str, err := randomHex(6) - if err != nil { - panic(err) - } - $$ = &KeyRangeDefinition{ - LowerBound: []byte($4), - Distribution: $6, - ShardID: $7, - KeyRangeID: "kr"+str, - } - } - | KEY RANGE FROM any_uint ROUTE TO any_id distribution_membership + | KEY RANGE FROM key_range_bound ROUTE TO any_id distribution_membership { str, err := randomHex(6) if err != nil { panic(err) } $$ = &KeyRangeDefinition{ - LowerBound: []byte(strconv.FormatUint(uint64($4), 10)), + LowerBound: $4, ShardID: $7, - KeyRangeID: "kr"+str, Distribution: $8, + KeyRangeID: "kr"+str, } } @@ -766,9 +779,9 @@ distribution_select_stmt: } split_key_range_stmt: - SPLIT key_range_stmt FROM any_id BY any_val + SPLIT key_range_stmt FROM any_id BY key_range_bound { - $$ = &SplitKeyRange{KeyRangeID: $2.KeyRangeID, KeyRangeFromID: $4, Border: []byte($6)} + $$ = &SplitKeyRange{KeyRangeID: $2.KeyRangeID, KeyRangeFromID: $4, Border: $6} } kill_stmt: diff --git a/yacc/console/yx_test.go b/yacc/console/yx_test.go index 30f40dcdc..c24c1182c 100644 --- a/yacc/console/yx_test.go +++ b/yacc/console/yx_test.go @@ -220,7 +220,11 @@ func TestKeyRange(t *testing.T) { ShardID: "sh1", KeyRangeID: "krid1", Distribution: "ds1", - LowerBound: []byte("1"), + LowerBound: &spqrparser.KeyRangeBound{ + Pivots: [][]byte{ + []byte{2, 0, 0, 0, 0, 0, 0, 0}, + }, + }, }, }, err: nil, @@ -233,7 +237,31 @@ func TestKeyRange(t *testing.T) { ShardID: "sh2", KeyRangeID: "krid2", Distribution: "ds1", - LowerBound: []byte("88888888-8888-8888-8888-888888888889"), + LowerBound: &spqrparser.KeyRangeBound{ + Pivots: [][]byte{ + []byte("88888888-8888-8888-8888-888888888889"), + }, + }, + }, + }, + err: nil, + }, + + { + query: ` + CREATE KEY RANGE krid1 FROM 0, 'a' ROUTE TO sh1 FOR DISTRIBUTION ds1;`, + + exp: &spqrparser.Create{ + Element: &spqrparser.KeyRangeDefinition{ + ShardID: "sh1", + KeyRangeID: "krid1", + Distribution: "ds1", + LowerBound: &spqrparser.KeyRangeBound{ + Pivots: [][]byte{ + []byte{0, 0, 0, 0, 0, 0, 0, 0}, + []byte("a"), + }, + }, }, }, err: nil, @@ -309,7 +337,11 @@ func TestSplitKeyRange(t *testing.T) { { query: "SPLIT KEY RANGE krid3 FROM krid1 BY 5;", exp: &spqrparser.SplitKeyRange{ - Border: []byte("5"), + Border: &spqrparser.KeyRangeBound{ + Pivots: [][]byte{ + {10, 0, 0, 0, 0, 0, 0, 0}, + }, + }, KeyRangeFromID: "krid1", KeyRangeID: "krid3", },