diff --git a/db/handler/db.go b/db/handler/db.go index b85d310..2c84c86 100644 --- a/db/handler/db.go +++ b/db/handler/db.go @@ -23,6 +23,7 @@ import ( const idKey = "id" const stmt = "create table if not exists %v(id text not null, data jsonb, primary key(id)); alter table %v add created_at timestamptz; alter table %v add updated_at timestamptz" const truncateStmt = `truncate table "%v"` +const renameTableStmt = `ALTER TABLE "%v" RENAME TO "%v"` var re = regexp.MustCompile("^[a-zA-Z0-9_]*$") var c = cache.New(5*time.Minute, 10*time.Minute) @@ -40,19 +41,28 @@ type Db struct { gorm2.Helper } -func correctFieldName(s string) string { +func correctFieldName(s string, isText bool) string { + operator := "->" + if isText { + // https: //stackoverflow.com/questions/27215216/postgres-how-to-convert-a-json-string-to-text + operator = "->>" + } switch s { // top level fields can stay top level case "id": // "created_at", "updated_at", <-- these are not special fields for now return s } if !strings.Contains(s, ".") { - return fmt.Sprintf("data ->> '%v'", s) + return fmt.Sprintf("data %v '%v'", operator, s) } paths := strings.Split(s, ".") ret := "data" - for _, path := range paths { - ret += fmt.Sprintf(" ->> '%v'", path) + for i, path := range paths { + if i == len(paths)-1 && isText { + ret += fmt.Sprintf(" ->> '%v'", path) + break + } + ret += fmt.Sprintf(" -> '%v'", path) } return ret } @@ -213,7 +223,7 @@ func (e *Db) Read(ctx context.Context, req *db.ReadRequest, rsp *db.ReadResponse db = db.Where("id = ?", req.Id) } else { for _, query := range queries { - logger.Infof("Query field: %v, op: %v, type: %v", query.Field, query.Op, query.Value) + logger.Infof("Query field: %v, op: %v, value: %v", query.Field, query.Op, query.Value) typ := "text" switch query.Value.(type) { case int64: @@ -236,7 +246,7 @@ func (e *Db) Read(ctx context.Context, req *db.ReadRequest, rsp *db.ReadResponse case itemNotEquals: op = "!=" } - queryField := correctFieldName(query.Field) + queryField := correctFieldName(query.Field, typ == "text") db = db.Where(fmt.Sprintf("(%v)::%v %v ?", queryField, typ, op), query.Value) } } @@ -245,7 +255,7 @@ func (e *Db) Read(ctx context.Context, req *db.ReadRequest, rsp *db.ReadResponse if req.OrderBy != "" { orderField = req.OrderBy } - orderField = correctFieldName(orderField) + orderField = correctFieldName(orderField, false) ordering := "asc" if req.Order != "" { @@ -260,7 +270,7 @@ func (e *Db) Read(ctx context.Context, req *db.ReadRequest, rsp *db.ReadResponse } db = db.Order(orderField + " " + ordering).Offset(int(req.Offset)).Limit(int(req.Limit)) - err = db.Find(&recs).Error + err = db.Debug().Find(&recs).Error if err != nil { return err } @@ -343,3 +353,53 @@ func (e *Db) Count(ctx context.Context, req *db.CountRequest, rsp *db.CountRespo rsp.Count = int32(a) return nil } + +func (e *Db) RenameTable(ctx context.Context, req *db.RenameTableRequest, rsp *db.RenameTableResponse) error { + if req.From == "" || req.To == "" { + return errors.BadRequest("db.renameTable", "must provide table names") + } + + oldtableName, err := e.tableName(ctx, req.From) + if err != nil { + return err + } + + newtableName, err := e.tableName(ctx, req.To) + if err != nil { + return err + } + + db, err := e.GetDBConn(ctx) + if err != nil { + return err + } + + stmt := fmt.Sprintf(renameTableStmt, oldtableName, newtableName) + logger.Info(stmt) + return db.Debug().Exec(stmt).Error +} + +func (e *Db) ListTables(ctx context.Context, req *db.ListTablesRequest, rsp *db.ListTablesResponse) error { + tenantId, ok := tenant.FromContext(ctx) + if !ok { + tenantId = "micro" + } + tenantId = strings.Replace(strings.Replace(tenantId, "/", "_", -1), "-", "_", -1) + + db, err := e.GetDBConn(ctx) + if err != nil { + return err + } + + var tables []string + if err := db.Table("information_schema.tables").Select("table_name").Where("table_schema = ?", "public").Find(&tables).Error; err != nil { + return err + } + rsp.Tables = []string{} + for _, v := range tables { + if strings.HasPrefix(v, tenantId) { + rsp.Tables = append(rsp.Tables, strings.Replace(v, tenantId+"_", "", -1)) + } + } + return nil +} diff --git a/db/handler/integration_test.go b/db/handler/integration_test.go new file mode 100644 index 0000000..bce68ce --- /dev/null +++ b/db/handler/integration_test.go @@ -0,0 +1,234 @@ +package handler + +import ( + "context" + "encoding/json" + "testing" + + "database/sql" + + "github.com/micro/micro/v3/service/auth" + db "github.com/micro/services/db/proto" + "google.golang.org/protobuf/types/known/structpb" +) + +const dbAddr = "postgresql://postgres:postgres@postgres:5432/postgres?sslmode=disable" + +func getHandler(t *testing.T) *Db { + sqlDB, err := sql.Open("pgx", dbAddr) + if err != nil { + t.Fatalf("Failed to open connection to DB %s", err) + } + h := &Db{} + h.DBConn(sqlDB) + return h +} + +func TestBasic(t *testing.T) { + h := getHandler(t) + ctx := auth.ContextWithAccount(context.Background(), &auth.Account{Issuer: "basic_test", ID: "test"}) + rs := []map[string]interface{}{ + { + "name": "Jane", + "age": 42, + "isActive": true, + "id": "1", + }, + { + "name": "Joe", + "age": 112, + "isActive": false, + "id": "2", + }, + } + for _, v := range rs { + record, _ := json.Marshal(v) + rec := &structpb.Struct{} + err := rec.UnmarshalJSON(record) + if err != nil { + t.Fatal(err) + } + err = h.Create(ctx, &db.CreateRequest{ + Table: "users", + Record: rec, + }, &db.CreateResponse{}) + if err != nil { + t.Fatal(err) + } + } + + t.Run("number ==", func(t *testing.T) { + readRsp := &db.ReadResponse{} + err := h.Read(ctx, &db.ReadRequest{ + Table: "users", + Query: "age == 112", + }, readRsp) + if err != nil { + t.Fatal(err) + } + if len(readRsp.Records) != 1 || readRsp.Records[0].AsMap()["id"].(string) != "2" { + t.Fatal(readRsp) + } + }) + + t.Run("number <", func(t *testing.T) { + readRsp := &db.ReadResponse{} + err := h.Read(ctx, &db.ReadRequest{ + Table: "users", + Query: "age < 100", + }, readRsp) + if err != nil { + t.Fatal(err) + } + if len(readRsp.Records) != 1 || readRsp.Records[0].AsMap()["id"].(string) != "1" { + t.Fatal(readRsp) + } + }) + + t.Run("number >", func(t *testing.T) { + readRsp := &db.ReadResponse{} + err := h.Read(ctx, &db.ReadRequest{ + Table: "users", + Query: "age > 100", + }, readRsp) + if err != nil { + t.Fatal(err) + } + if len(readRsp.Records) != 1 || readRsp.Records[0].AsMap()["id"].(string) != "2" { + t.Fatal(readRsp) + } + }) + + t.Run("number !=", func(t *testing.T) { + readRsp := &db.ReadResponse{} + err := h.Read(ctx, &db.ReadRequest{ + Table: "users", + Query: "age != 42", + }, readRsp) + if err != nil { + t.Fatal(err) + } + if len(readRsp.Records) != 1 || readRsp.Records[0].AsMap()["id"].(string) != "2" { + t.Fatal(readRsp) + } + }) + + t.Run("bool ==", func(t *testing.T) { + readRsp := &db.ReadResponse{} + err := h.Read(ctx, &db.ReadRequest{ + Table: "users", + Query: "isActive == false", + }, readRsp) + if err != nil { + t.Fatal(err) + } + if len(readRsp.Records) != 1 || readRsp.Records[0].AsMap()["id"].(string) != "2" { + t.Fatal(readRsp) + } + }) + + t.Run("bool !=", func(t *testing.T) { + readRsp := &db.ReadResponse{} + err := h.Read(ctx, &db.ReadRequest{ + Table: "users", + Query: "isActive != false", + }, readRsp) + if err != nil { + t.Fatal(err) + } + if len(readRsp.Records) != 1 || readRsp.Records[0].AsMap()["id"].(string) != "1" { + t.Fatal(readRsp) + } + }) + + t.Run("string ==", func(t *testing.T) { + readRsp := &db.ReadResponse{} + err := h.Read(ctx, &db.ReadRequest{ + Table: "users", + Query: "name == 'Jane'", + }, readRsp) + if err != nil { + t.Fatal(err) + } + if len(readRsp.Records) != 1 || readRsp.Records[0].AsMap()["id"].(string) != "1" { + t.Fatal(readRsp) + } + }) + + t.Run("string !=", func(t *testing.T) { + readRsp := &db.ReadResponse{} + err := h.Read(ctx, &db.ReadRequest{ + Table: "users", + Query: "name != 'Jane'", + }, readRsp) + if err != nil { + t.Fatal(err) + } + if len(readRsp.Records) != 1 || readRsp.Records[0].AsMap()["id"].(string) != "2" { + t.Fatal(readRsp) + } + }) + + t.Run("order number asc", func(t *testing.T) { + readRsp := &db.ReadResponse{} + err := h.Read(ctx, &db.ReadRequest{ + Table: "users", + OrderBy: "age", + Order: "asc", + }, readRsp) + if err != nil { + t.Fatal(err) + } + if len(readRsp.Records) != 2 || readRsp.Records[0].AsMap()["id"].(string) != "1" || readRsp.Records[1].AsMap()["id"].(string) != "2" { + t.Fatal(readRsp) + } + }) + + t.Run("order number desc", func(t *testing.T) { + readRsp := &db.ReadResponse{} + err := h.Read(ctx, &db.ReadRequest{ + Table: "users", + OrderBy: "age", + Order: "desc", + }, readRsp) + if err != nil { + t.Fatal(err) + } + if len(readRsp.Records) != 2 || readRsp.Records[0].AsMap()["id"].(string) != "2" || readRsp.Records[1].AsMap()["id"].(string) != "1" { + t.Fatal(readRsp) + } + }) + + t.Run("order number desc, limit", func(t *testing.T) { + readRsp := &db.ReadResponse{} + err := h.Read(ctx, &db.ReadRequest{ + Table: "users", + OrderBy: "age", + Order: "desc", + Limit: 1, + }, readRsp) + if err != nil { + t.Fatal(err) + } + if len(readRsp.Records) != 1 || readRsp.Records[0].AsMap()["id"].(string) != "2" { + t.Fatal(readRsp) + } + }) + + t.Run("order number desc, limit, offset", func(t *testing.T) { + readRsp := &db.ReadResponse{} + err := h.Read(ctx, &db.ReadRequest{ + Table: "users", + OrderBy: "age", + Order: "desc", + Limit: 1, + Offset: 1, + }, readRsp) + if err != nil { + t.Fatal(err) + } + if len(readRsp.Records) != 1 || readRsp.Records[0].AsMap()["id"].(string) != "1" { + t.Fatal(readRsp) + } + }) +} diff --git a/db/handler/parse_test.go b/db/handler/parse_test.go index bc771ae..fd0119e 100644 --- a/db/handler/parse_test.go +++ b/db/handler/parse_test.go @@ -9,8 +9,8 @@ import ( ) func TestCorrectFieldName(t *testing.T) { - f := correctFieldName("a.b.c") - if f != "data ->> 'a' ->> 'b' ->> 'c'" { + f := correctFieldName("a.b.c", true) + if f != "data -> 'a' -> 'b' ->> 'c'" { t.Fatal(f) } } diff --git a/db/proto/db.pb.go b/db/proto/db.pb.go index 3cc5f54..b8f4447 100644 --- a/db/proto/db.pb.go +++ b/db/proto/db.pb.go @@ -580,11 +580,13 @@ func (x *TruncateResponse) GetTable() string { return "" } +// Count records in a table type CountRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // specify the table name Table string `protobuf:"bytes,1,opt,name=table,proto3" json:"table,omitempty"` } @@ -632,6 +634,7 @@ type CountResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // the number of records in the table Count int32 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` } @@ -674,6 +677,184 @@ func (x *CountResponse) GetCount() int32 { return 0 } +type RenameTableRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + From string `protobuf:"bytes,1,opt,name=from,proto3" json:"from,omitempty"` + To string `protobuf:"bytes,2,opt,name=to,proto3" json:"to,omitempty"` +} + +func (x *RenameTableRequest) Reset() { + *x = RenameTableRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_db_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RenameTableRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RenameTableRequest) ProtoMessage() {} + +func (x *RenameTableRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_db_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RenameTableRequest.ProtoReflect.Descriptor instead. +func (*RenameTableRequest) Descriptor() ([]byte, []int) { + return file_proto_db_proto_rawDescGZIP(), []int{12} +} + +func (x *RenameTableRequest) GetFrom() string { + if x != nil { + return x.From + } + return "" +} + +func (x *RenameTableRequest) GetTo() string { + if x != nil { + return x.To + } + return "" +} + +type RenameTableResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *RenameTableResponse) Reset() { + *x = RenameTableResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_db_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RenameTableResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RenameTableResponse) ProtoMessage() {} + +func (x *RenameTableResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_db_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RenameTableResponse.ProtoReflect.Descriptor instead. +func (*RenameTableResponse) Descriptor() ([]byte, []int) { + return file_proto_db_proto_rawDescGZIP(), []int{13} +} + +type ListTablesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ListTablesRequest) Reset() { + *x = ListTablesRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_db_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListTablesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListTablesRequest) ProtoMessage() {} + +func (x *ListTablesRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_db_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListTablesRequest.ProtoReflect.Descriptor instead. +func (*ListTablesRequest) Descriptor() ([]byte, []int) { + return file_proto_db_proto_rawDescGZIP(), []int{14} +} + +type ListTablesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Tables []string `protobuf:"bytes,1,rep,name=tables,proto3" json:"tables,omitempty"` +} + +func (x *ListTablesResponse) Reset() { + *x = ListTablesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_db_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListTablesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListTablesResponse) ProtoMessage() {} + +func (x *ListTablesResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_db_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListTablesResponse.ProtoReflect.Descriptor instead. +func (*ListTablesResponse) Descriptor() ([]byte, []int) { + return file_proto_db_proto_rawDescGZIP(), []int{15} +} + +func (x *ListTablesResponse) GetTables() []string { + if x != nil { + return x.Tables + } + return nil +} + var File_proto_db_proto protoreflect.FileDescriptor var file_proto_db_proto_rawDesc = []byte{ @@ -724,28 +905,45 @@ var file_proto_db_proto_rawDesc = []byte{ 0x14, 0x0a, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x25, 0x0a, 0x0d, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x32, 0xb3, 0x02, 0x0a, - 0x02, 0x44, 0x62, 0x12, 0x31, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x11, 0x2e, - 0x64, 0x62, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x12, 0x2e, 0x64, 0x62, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x2b, 0x0a, 0x04, 0x52, 0x65, 0x61, 0x64, 0x12, 0x0f, - 0x2e, 0x64, 0x62, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x10, 0x2e, 0x64, 0x62, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x31, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x11, 0x2e, - 0x64, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x12, 0x2e, 0x64, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x31, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x12, 0x11, 0x2e, 0x64, 0x62, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x64, 0x62, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x37, 0x0a, 0x08, 0x54, 0x72, 0x75, - 0x6e, 0x63, 0x61, 0x74, 0x65, 0x12, 0x13, 0x2e, 0x64, 0x62, 0x2e, 0x54, 0x72, 0x75, 0x6e, 0x63, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x64, 0x62, 0x2e, - 0x54, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x2e, 0x0a, 0x05, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x10, 0x2e, 0x64, 0x62, - 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, - 0x64, 0x62, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x42, 0x0c, 0x5a, 0x0a, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x64, 0x62, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x38, 0x0a, 0x12, + 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x74, 0x6f, 0x22, 0x15, 0x0a, 0x13, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, + 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13, 0x0a, + 0x11, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x22, 0x2c, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, + 0x32, 0xb4, 0x03, 0x0a, 0x02, 0x44, 0x62, 0x12, 0x31, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x12, 0x11, 0x2e, 0x64, 0x62, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x64, 0x62, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x2b, 0x0a, 0x04, 0x52, 0x65, + 0x61, 0x64, 0x12, 0x0f, 0x2e, 0x64, 0x62, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x64, 0x62, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x31, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x12, 0x11, 0x2e, 0x64, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x64, 0x62, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x31, 0x0a, 0x06, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x12, 0x11, 0x2e, 0x64, 0x62, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x64, 0x62, 0x2e, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x37, 0x0a, + 0x08, 0x54, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x12, 0x13, 0x2e, 0x64, 0x62, 0x2e, 0x54, + 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, + 0x2e, 0x64, 0x62, 0x2e, 0x54, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x2e, 0x0a, 0x05, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, + 0x10, 0x2e, 0x64, 0x62, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x11, 0x2e, 0x64, 0x62, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x0b, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, + 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x16, 0x2e, 0x64, 0x62, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, + 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, + 0x64, 0x62, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, + 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x15, 0x2e, 0x64, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x64, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x0c, 0x5a, 0x0a, 0x2e, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x3b, 0x64, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -760,40 +958,48 @@ func file_proto_db_proto_rawDescGZIP() []byte { return file_proto_db_proto_rawDescData } -var file_proto_db_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_proto_db_proto_msgTypes = make([]protoimpl.MessageInfo, 16) var file_proto_db_proto_goTypes = []interface{}{ - (*ReadRequest)(nil), // 0: db.ReadRequest - (*ReadResponse)(nil), // 1: db.ReadResponse - (*CreateRequest)(nil), // 2: db.CreateRequest - (*CreateResponse)(nil), // 3: db.CreateResponse - (*UpdateRequest)(nil), // 4: db.UpdateRequest - (*UpdateResponse)(nil), // 5: db.UpdateResponse - (*DeleteRequest)(nil), // 6: db.DeleteRequest - (*DeleteResponse)(nil), // 7: db.DeleteResponse - (*TruncateRequest)(nil), // 8: db.TruncateRequest - (*TruncateResponse)(nil), // 9: db.TruncateResponse - (*CountRequest)(nil), // 10: db.CountRequest - (*CountResponse)(nil), // 11: db.CountResponse - (*_struct.Struct)(nil), // 12: google.protobuf.Struct + (*ReadRequest)(nil), // 0: db.ReadRequest + (*ReadResponse)(nil), // 1: db.ReadResponse + (*CreateRequest)(nil), // 2: db.CreateRequest + (*CreateResponse)(nil), // 3: db.CreateResponse + (*UpdateRequest)(nil), // 4: db.UpdateRequest + (*UpdateResponse)(nil), // 5: db.UpdateResponse + (*DeleteRequest)(nil), // 6: db.DeleteRequest + (*DeleteResponse)(nil), // 7: db.DeleteResponse + (*TruncateRequest)(nil), // 8: db.TruncateRequest + (*TruncateResponse)(nil), // 9: db.TruncateResponse + (*CountRequest)(nil), // 10: db.CountRequest + (*CountResponse)(nil), // 11: db.CountResponse + (*RenameTableRequest)(nil), // 12: db.RenameTableRequest + (*RenameTableResponse)(nil), // 13: db.RenameTableResponse + (*ListTablesRequest)(nil), // 14: db.ListTablesRequest + (*ListTablesResponse)(nil), // 15: db.ListTablesResponse + (*_struct.Struct)(nil), // 16: google.protobuf.Struct } var file_proto_db_proto_depIdxs = []int32{ - 12, // 0: db.ReadResponse.records:type_name -> google.protobuf.Struct - 12, // 1: db.CreateRequest.record:type_name -> google.protobuf.Struct - 12, // 2: db.UpdateRequest.record:type_name -> google.protobuf.Struct + 16, // 0: db.ReadResponse.records:type_name -> google.protobuf.Struct + 16, // 1: db.CreateRequest.record:type_name -> google.protobuf.Struct + 16, // 2: db.UpdateRequest.record:type_name -> google.protobuf.Struct 2, // 3: db.Db.Create:input_type -> db.CreateRequest 0, // 4: db.Db.Read:input_type -> db.ReadRequest 4, // 5: db.Db.Update:input_type -> db.UpdateRequest 6, // 6: db.Db.Delete:input_type -> db.DeleteRequest 8, // 7: db.Db.Truncate:input_type -> db.TruncateRequest 10, // 8: db.Db.Count:input_type -> db.CountRequest - 3, // 9: db.Db.Create:output_type -> db.CreateResponse - 1, // 10: db.Db.Read:output_type -> db.ReadResponse - 5, // 11: db.Db.Update:output_type -> db.UpdateResponse - 7, // 12: db.Db.Delete:output_type -> db.DeleteResponse - 9, // 13: db.Db.Truncate:output_type -> db.TruncateResponse - 11, // 14: db.Db.Count:output_type -> db.CountResponse - 9, // [9:15] is the sub-list for method output_type - 3, // [3:9] is the sub-list for method input_type + 12, // 9: db.Db.RenameTable:input_type -> db.RenameTableRequest + 14, // 10: db.Db.ListTables:input_type -> db.ListTablesRequest + 3, // 11: db.Db.Create:output_type -> db.CreateResponse + 1, // 12: db.Db.Read:output_type -> db.ReadResponse + 5, // 13: db.Db.Update:output_type -> db.UpdateResponse + 7, // 14: db.Db.Delete:output_type -> db.DeleteResponse + 9, // 15: db.Db.Truncate:output_type -> db.TruncateResponse + 11, // 16: db.Db.Count:output_type -> db.CountResponse + 13, // 17: db.Db.RenameTable:output_type -> db.RenameTableResponse + 15, // 18: db.Db.ListTables:output_type -> db.ListTablesResponse + 11, // [11:19] is the sub-list for method output_type + 3, // [3:11] is the sub-list for method input_type 3, // [3:3] is the sub-list for extension type_name 3, // [3:3] is the sub-list for extension extendee 0, // [0:3] is the sub-list for field type_name @@ -949,6 +1155,54 @@ func file_proto_db_proto_init() { return nil } } + file_proto_db_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RenameTableRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_db_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RenameTableResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_db_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListTablesRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_db_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListTablesResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -956,7 +1210,7 @@ func file_proto_db_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_db_proto_rawDesc, NumEnums: 0, - NumMessages: 12, + NumMessages: 16, NumExtensions: 0, NumServices: 1, }, diff --git a/db/proto/db.pb.micro.go b/db/proto/db.pb.micro.go index 37a9a6d..ce6e655 100644 --- a/db/proto/db.pb.micro.go +++ b/db/proto/db.pb.micro.go @@ -49,6 +49,8 @@ type DbService interface { Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) Truncate(ctx context.Context, in *TruncateRequest, opts ...client.CallOption) (*TruncateResponse, error) Count(ctx context.Context, in *CountRequest, opts ...client.CallOption) (*CountResponse, error) + RenameTable(ctx context.Context, in *RenameTableRequest, opts ...client.CallOption) (*RenameTableResponse, error) + ListTables(ctx context.Context, in *ListTablesRequest, opts ...client.CallOption) (*ListTablesResponse, error) } type dbService struct { @@ -123,6 +125,26 @@ func (c *dbService) Count(ctx context.Context, in *CountRequest, opts ...client. return out, nil } +func (c *dbService) RenameTable(ctx context.Context, in *RenameTableRequest, opts ...client.CallOption) (*RenameTableResponse, error) { + req := c.c.NewRequest(c.name, "Db.RenameTable", in) + out := new(RenameTableResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dbService) ListTables(ctx context.Context, in *ListTablesRequest, opts ...client.CallOption) (*ListTablesResponse, error) { + req := c.c.NewRequest(c.name, "Db.ListTables", in) + out := new(ListTablesResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for Db service type DbHandler interface { @@ -132,6 +154,8 @@ type DbHandler interface { Delete(context.Context, *DeleteRequest, *DeleteResponse) error Truncate(context.Context, *TruncateRequest, *TruncateResponse) error Count(context.Context, *CountRequest, *CountResponse) error + RenameTable(context.Context, *RenameTableRequest, *RenameTableResponse) error + ListTables(context.Context, *ListTablesRequest, *ListTablesResponse) error } func RegisterDbHandler(s server.Server, hdlr DbHandler, opts ...server.HandlerOption) error { @@ -142,6 +166,8 @@ func RegisterDbHandler(s server.Server, hdlr DbHandler, opts ...server.HandlerOp Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error Truncate(ctx context.Context, in *TruncateRequest, out *TruncateResponse) error Count(ctx context.Context, in *CountRequest, out *CountResponse) error + RenameTable(ctx context.Context, in *RenameTableRequest, out *RenameTableResponse) error + ListTables(ctx context.Context, in *ListTablesRequest, out *ListTablesResponse) error } type Db struct { db @@ -177,3 +203,11 @@ func (h *dbHandler) Truncate(ctx context.Context, in *TruncateRequest, out *Trun func (h *dbHandler) Count(ctx context.Context, in *CountRequest, out *CountResponse) error { return h.DbHandler.Count(ctx, in, out) } + +func (h *dbHandler) RenameTable(ctx context.Context, in *RenameTableRequest, out *RenameTableResponse) error { + return h.DbHandler.RenameTable(ctx, in, out) +} + +func (h *dbHandler) ListTables(ctx context.Context, in *ListTablesRequest, out *ListTablesResponse) error { + return h.DbHandler.ListTables(ctx, in, out) +} diff --git a/db/proto/db.proto b/db/proto/db.proto index ac485df..eb2c7e4 100644 --- a/db/proto/db.proto +++ b/db/proto/db.proto @@ -12,6 +12,8 @@ service Db { rpc Delete(DeleteRequest) returns (DeleteResponse) {} rpc Truncate(TruncateRequest) returns (TruncateResponse) {} rpc Count(CountRequest) returns (CountResponse) {} + rpc RenameTable(RenameTableRequest) returns (RenameTableResponse) {} + rpc ListTables(ListTablesRequest) returns (ListTablesResponse) {} } @@ -100,3 +102,20 @@ message CountResponse { // the number of records in the table int32 count = 1; } + +message RenameTableRequest { + string from = 1; + string to = 2; +} + +message RenameTableResponse { + +} + +message ListTablesRequest { + +} + +message ListTablesResponse { + repeated string tables = 1; +} \ No newline at end of file