diff --git a/db/handler/db.go b/db/handler/db.go index 2267648..6039ec5 100644 --- a/db/handler/db.go +++ b/db/handler/db.go @@ -22,6 +22,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"` var re = regexp.MustCompile("^[a-zA-Z0-9_]*$") var c = cache.New(5*time.Minute, 10*time.Minute) @@ -39,6 +40,23 @@ type Db struct { gorm2.Helper } +func correctFieldName(s string) string { + 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) + } + paths := strings.Split(s, ".") + ret := "data" + for _, path := range paths { + ret += fmt.Sprintf(" ->> '%v'", path) + } + return ret +} + // Call is a single request handler called via client.Call or the generated client code func (e *Db) Create(ctx context.Context, req *db.CreateRequest, rsp *db.CreateResponse) error { if len(req.Record.AsMap()) == 0 { @@ -208,13 +226,28 @@ func (e *Db) Read(ctx context.Context, req *db.ReadRequest, rsp *db.ReadResponse case itemNotEquals: op = "!=" } - db = db.Where(fmt.Sprintf("(data ->> '%v')::%v %v ?", query.Field, typ, op), query.Value) + queryField := correctFieldName(query.Field) + db = db.Where(fmt.Sprintf("(%v)::%v %v ?", queryField, typ, op), query.Value) } - orderField := "created_at DESC" + orderField := "created_at" if req.OrderBy != "" { - orderField = req.OrderBy + " " + req.Order + orderField = req.OrderBy } - db = db.Order(orderField).Offset(int(req.Offset)).Limit(int(req.Limit)) + orderField = correctFieldName(orderField) + + ordering := "asc" + if req.Order != "" { + switch strings.ToLower(req.Order) { + case "asc": + ordering = "asc" + case "", "desc": + ordering = "desc" + default: + return errors.BadRequest("db.read", "invalid ordering: "+req.Order) + } + } + + db = db.Order(orderField + " " + ordering).Offset(int(req.Offset)).Limit(int(req.Limit)) err = db.Find(&recs).Error if err != nil { return err @@ -269,3 +302,25 @@ func (e *Db) Delete(ctx context.Context, req *db.DeleteRequest, rsp *db.DeleteRe ID: req.Id, }).Error } + +func (e *Db) Truncate(ctx context.Context, req *db.TruncateRequest, rsp *db.TruncateResponse) error { + tenantId, ok := tenant.FromContext(ctx) + if !ok { + tenantId = "micro" + } + if req.Table == "" { + req.Table = "default" + } + tenantId = strings.Replace(strings.Replace(tenantId, "/", "_", -1), "-", "_", -1) + tableName := tenantId + "_" + req.Table + if !re.Match([]byte(tableName)) { + return errors.BadRequest("db.create", fmt.Sprintf("table name %v is invalid", req.Table)) + } + logger.Infof("Truncating table '%v'", tableName) + + db, err := e.GetDBConn(ctx) + if err != nil { + return err + } + return db.Exec(fmt.Sprintf(truncateStmt, tableName)).Error +} diff --git a/db/handler/parse.go b/db/handler/parse.go index 6f0e03d..a32c86e 100644 --- a/db/handler/parse.go +++ b/db/handler/parse.go @@ -57,7 +57,7 @@ var expressions = []lexer.TokenExpr{ {`"(?:[^"\\]|\\.)*"`, itemString}, {"`" + `(?:[^"\\]|\\.)*` + "`", itemString}, {`'(?:[^"\\]|\\.)*'`, itemString}, - {`[\<\>\!\=\+\-\|\&\*\/A-Za-z][A-Za-z0-9_]*`, itemFieldName}, + {`[\<\>\!\=\+\-\|\&\*\/A-Za-z][A-Za-z0-9_\.]*`, itemFieldName}, } type Query struct { diff --git a/db/handler/parse_test.go b/db/handler/parse_test.go index 72c0d65..a0f80c9 100644 --- a/db/handler/parse_test.go +++ b/db/handler/parse_test.go @@ -8,6 +8,13 @@ import ( "github.com/crufter/lexer" ) +func TestCorrectFieldName(t *testing.T) { + f := correctFieldName("a.b.c") + if f != "data ->> 'a' ->> 'b' ->> 'c'" { + t.Fatal(f) + } +} + func TestLexing(t *testing.T) { tokens, err := lexer.Lex("a == 12", expressions) if err != nil { @@ -55,6 +62,21 @@ func TestParsing(t *testing.T) { }, }, }, + tCase{ + Q: `a.b.c == 12 and name != "nandos"`, + E: []Query{ + Query{ + Field: "a.b.c", + Value: int64(12), + Op: itemEquals, + }, + Query{ + Field: "name", + Value: "nandos", + Op: itemNotEquals, + }, + }, + }, tCase{ Q: `a == 12 and name != "nan'dos"`, E: []Query{ diff --git a/db/proto/db.pb.go b/db/proto/db.pb.go index 0b26a6b..3b7efd6 100644 --- a/db/proto/db.pb.go +++ b/db/proto/db.pb.go @@ -27,16 +27,22 @@ type ReadRequest struct { unknownFields protoimpl.UnknownFields Table string `protobuf:"bytes,1,opt,name=table,proto3" json:"table,omitempty"` - // eg. 'age >= 18', 'age >= 18 and verified == true' - // comparison operators: '==', '!=', '<', '>', '<=', '>=' - // logical operator: 'and' - Query string `protobuf:"bytes,2,opt,name=query,proto3" json:"query,omitempty"` - Offset int32 `protobuf:"varint,3,opt,name=offset,proto3" json:"offset,omitempty"` - Limit int32 `protobuf:"varint,4,opt,name=limit,proto3" json:"limit,omitempty"` + // Read by id. Equivalent to 'id == "your-id"' + Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` + // Examples: 'age >= 18', 'age >= 18 and verified == true' + // Comparison operators: '==', '!=', '<', '>', '<=', '>=' + // Logical operator: 'and' + // Dot access is supported, eg: 'user.age == 11' + // Accessing list elements is not supported yet. + Query string `protobuf:"bytes,3,opt,name=query,proto3" json:"query,omitempty"` + Offset int32 `protobuf:"varint,4,opt,name=offset,proto3" json:"offset,omitempty"` + // Default limit is 25. + // Maximum limit is 1000. Anything higher will return an error. + Limit int32 `protobuf:"varint,5,opt,name=limit,proto3" json:"limit,omitempty"` // field name to order by - OrderBy string `protobuf:"bytes,5,opt,name=orderBy,proto3" json:"orderBy,omitempty"` + OrderBy string `protobuf:"bytes,6,opt,name=orderBy,proto3" json:"orderBy,omitempty"` // 'asc' (default), 'desc' - Order string `protobuf:"bytes,6,opt,name=order,proto3" json:"order,omitempty"` + Order string `protobuf:"bytes,7,opt,name=order,proto3" json:"order,omitempty"` } func (x *ReadRequest) Reset() { @@ -78,6 +84,13 @@ func (x *ReadRequest) GetTable() string { return "" } +func (x *ReadRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + func (x *ReadRequest) GetQuery() string { if x != nil { return x.Query @@ -453,22 +466,117 @@ func (*DeleteResponse) Descriptor() ([]byte, []int) { return file_proto_db_proto_rawDescGZIP(), []int{7} } +type TruncateRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Table string `protobuf:"bytes,1,opt,name=table,proto3" json:"table,omitempty"` +} + +func (x *TruncateRequest) Reset() { + *x = TruncateRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_db_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TruncateRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TruncateRequest) ProtoMessage() {} + +func (x *TruncateRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_db_proto_msgTypes[8] + 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 TruncateRequest.ProtoReflect.Descriptor instead. +func (*TruncateRequest) Descriptor() ([]byte, []int) { + return file_proto_db_proto_rawDescGZIP(), []int{8} +} + +func (x *TruncateRequest) GetTable() string { + if x != nil { + return x.Table + } + return "" +} + +type TruncateResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Table string `protobuf:"bytes,1,opt,name=table,proto3" json:"table,omitempty"` +} + +func (x *TruncateResponse) Reset() { + *x = TruncateResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_db_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TruncateResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TruncateResponse) ProtoMessage() {} + +func (x *TruncateResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_db_proto_msgTypes[9] + 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 TruncateResponse.ProtoReflect.Descriptor instead. +func (*TruncateResponse) Descriptor() ([]byte, []int) { + return file_proto_db_proto_rawDescGZIP(), []int{9} +} + +func (x *TruncateResponse) GetTable() string { + if x != nil { + return x.Table + } + return "" +} + var File_proto_db_proto protoreflect.FileDescriptor var file_proto_db_proto_rawDesc = []byte{ 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x62, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x64, 0x62, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x22, 0x97, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x74, 0x6f, 0x22, 0xa7, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, - 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x16, - 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, + 0x09, 0x52, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x16, + 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x18, 0x0a, 0x07, - 0x6f, 0x72, 0x64, 0x65, 0x72, 0x42, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, + 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x18, 0x0a, 0x07, + 0x6f, 0x72, 0x64, 0x65, 0x72, 0x42, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x42, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x41, 0x0a, 0x0c, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x41, 0x0a, 0x0c, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x07, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, @@ -491,21 +599,30 @@ var file_proto_db_proto_rawDesc = []byte{ 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x10, 0x0a, 0x0e, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xca, 0x01, 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, 0x42, 0x0c, 0x5a, 0x0a, 0x2e, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x64, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x0a, 0x0f, + 0x54, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x14, 0x0a, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x28, 0x0a, 0x10, 0x54, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x32, + 0x83, 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, 0x42, 0x0c, 0x5a, 0x0a, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x3b, 0x64, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -520,35 +637,39 @@ func file_proto_db_proto_rawDescGZIP() []byte { return file_proto_db_proto_rawDescData } -var file_proto_db_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_proto_db_proto_msgTypes = make([]protoimpl.MessageInfo, 10) 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 - (*_struct.Struct)(nil), // 8: 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 + (*_struct.Struct)(nil), // 10: google.protobuf.Struct } var file_proto_db_proto_depIdxs = []int32{ - 8, // 0: db.ReadResponse.records:type_name -> google.protobuf.Struct - 8, // 1: db.CreateRequest.record:type_name -> google.protobuf.Struct - 8, // 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 - 3, // 7: db.Db.Create:output_type -> db.CreateResponse - 1, // 8: db.Db.Read:output_type -> db.ReadResponse - 5, // 9: db.Db.Update:output_type -> db.UpdateResponse - 7, // 10: db.Db.Delete:output_type -> db.DeleteResponse - 7, // [7:11] is the sub-list for method output_type - 3, // [3:7] 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 + 10, // 0: db.ReadResponse.records:type_name -> google.protobuf.Struct + 10, // 1: db.CreateRequest.record:type_name -> google.protobuf.Struct + 10, // 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 + 3, // 8: db.Db.Create:output_type -> db.CreateResponse + 1, // 9: db.Db.Read:output_type -> db.ReadResponse + 5, // 10: db.Db.Update:output_type -> db.UpdateResponse + 7, // 11: db.Db.Delete:output_type -> db.DeleteResponse + 9, // 12: db.Db.Truncate:output_type -> db.TruncateResponse + 8, // [8:13] is the sub-list for method output_type + 3, // [3:8] 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 } func init() { file_proto_db_proto_init() } @@ -653,6 +774,30 @@ func file_proto_db_proto_init() { return nil } } + file_proto_db_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TruncateRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_db_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TruncateResponse); 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{ @@ -660,7 +805,7 @@ func file_proto_db_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_db_proto_rawDesc, NumEnums: 0, - NumMessages: 8, + NumMessages: 10, NumExtensions: 0, NumServices: 1, }, diff --git a/db/proto/db.pb.micro.go b/db/proto/db.pb.micro.go index ddff33f..49e40bb 100644 --- a/db/proto/db.pb.micro.go +++ b/db/proto/db.pb.micro.go @@ -47,6 +47,7 @@ type DbService interface { Read(ctx context.Context, in *ReadRequest, opts ...client.CallOption) (*ReadResponse, error) Update(ctx context.Context, in *UpdateRequest, opts ...client.CallOption) (*UpdateResponse, error) Delete(ctx context.Context, in *DeleteRequest, opts ...client.CallOption) (*DeleteResponse, error) + Truncate(ctx context.Context, in *TruncateRequest, opts ...client.CallOption) (*TruncateResponse, error) } type dbService struct { @@ -101,6 +102,16 @@ func (c *dbService) Delete(ctx context.Context, in *DeleteRequest, opts ...clien return out, nil } +func (c *dbService) Truncate(ctx context.Context, in *TruncateRequest, opts ...client.CallOption) (*TruncateResponse, error) { + req := c.c.NewRequest(c.name, "Db.Truncate", in) + out := new(TruncateResponse) + 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 { @@ -108,6 +119,7 @@ type DbHandler interface { Read(context.Context, *ReadRequest, *ReadResponse) error Update(context.Context, *UpdateRequest, *UpdateResponse) error Delete(context.Context, *DeleteRequest, *DeleteResponse) error + Truncate(context.Context, *TruncateRequest, *TruncateResponse) error } func RegisterDbHandler(s server.Server, hdlr DbHandler, opts ...server.HandlerOption) error { @@ -116,6 +128,7 @@ func RegisterDbHandler(s server.Server, hdlr DbHandler, opts ...server.HandlerOp Read(ctx context.Context, in *ReadRequest, out *ReadResponse) error Update(ctx context.Context, in *UpdateRequest, out *UpdateResponse) error Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error + Truncate(ctx context.Context, in *TruncateRequest, out *TruncateResponse) error } type Db struct { db @@ -143,3 +156,7 @@ func (h *dbHandler) Update(ctx context.Context, in *UpdateRequest, out *UpdateRe func (h *dbHandler) Delete(ctx context.Context, in *DeleteRequest, out *DeleteResponse) error { return h.DbHandler.Delete(ctx, in, out) } + +func (h *dbHandler) Truncate(ctx context.Context, in *TruncateRequest, out *TruncateResponse) error { + return h.DbHandler.Truncate(ctx, in, out) +} diff --git a/db/proto/db.proto b/db/proto/db.proto index 54b12bb..e40c3b9 100644 --- a/db/proto/db.proto +++ b/db/proto/db.proto @@ -10,21 +10,28 @@ service Db { rpc Read(ReadRequest) returns (ReadResponse) {} rpc Update(UpdateRequest) returns (UpdateResponse) {} rpc Delete(DeleteRequest) returns (DeleteResponse) {} + rpc Truncate(TruncateRequest) returns (TruncateResponse) {} } message ReadRequest { string table = 1; - // eg. 'age >= 18', 'age >= 18 and verified == true' - // comparison operators: '==', '!=', '<', '>', '<=', '>=' - // logical operator: 'and' - string query = 2; - int32 offset = 3; - int32 limit = 4; + // Read by id. Equivalent to 'id == "your-id"' + string id = 2; + // Examples: 'age >= 18', 'age >= 18 and verified == true' + // Comparison operators: '==', '!=', '<', '>', '<=', '>=' + // Logical operator: 'and' + // Dot access is supported, eg: 'user.age == 11' + // Accessing list elements is not supported yet. + string query = 3; + int32 offset = 4; + // Default limit is 25. + // Maximum limit is 1000. Anything higher will return an error. + int32 limit = 5; // field name to order by - string orderBy = 5; + string orderBy = 6; // 'asc' (default), 'desc' - string order = 6; + string order = 7; } message ReadResponse { @@ -62,3 +69,11 @@ message DeleteRequest { message DeleteResponse { } + +message TruncateRequest { + string table = 1; +} + +message TruncateResponse { + string table = 1; +} \ No newline at end of file