diff --git a/clients/go/db/db.go b/clients/go/db/db.go index 1cea496..47d7959 100755 --- a/clients/go/db/db.go +++ b/clients/go/db/db.go @@ -16,6 +16,12 @@ type DbService struct { client *client.Client } +// Count records in a table +func (t *DbService) Count(request *CountRequest) (*CountResponse, error) { + rsp := &CountResponse{} + return rsp, t.client.Call("db", "Count", request, rsp) +} + // Create a record in the database. Optionally include an "id" field otherwise it's set automatically. func (t *DbService) Create(request *CreateRequest) (*CreateResponse, error) { rsp := &CreateResponse{} @@ -46,6 +52,14 @@ func (t *DbService) Update(request *UpdateRequest) (*UpdateResponse, error) { return rsp, t.client.Call("db", "Update", request, rsp) } +type CountRequest struct { + Table string `json:"table"` +} + +type CountResponse struct { + Count int32 `json:"count"` +} + type CreateRequest struct { // JSON encoded record or records (can be array or object) Record map[string]interface{} `json:"record"` diff --git a/clients/ts/db/index.ts b/clients/ts/db/index.ts index f23acf2..e45daa7 100755 --- a/clients/ts/db/index.ts +++ b/clients/ts/db/index.ts @@ -6,6 +6,10 @@ export class DbService { constructor(token: string) { this.client = new m3o.Client({ token: token }); } + // Count records in a table + count(request: CountRequest): Promise { + return this.client.call("db", "Count", request) as Promise; + } // Create a record in the database. Optionally include an "id" field otherwise it's set automatically. create(request: CreateRequest): Promise { return this.client.call("db", "Create", request) as Promise; @@ -32,6 +36,14 @@ export class DbService { } } +export interface CountRequest { + table?: string; +} + +export interface CountResponse { + count?: number; +} + export interface CreateRequest { // JSON encoded record or records (can be array or object) record?: { [key: string]: any }; diff --git a/clients/ts/package.json b/clients/ts/package.json index 8a461c5..06455d4 100644 --- a/clients/ts/package.json +++ b/clients/ts/package.json @@ -66,5 +66,5 @@ }, "type": "module", "types": "dist/index.d.ts", - "version": "1.0.554" + "version": "1.0.555" } \ No newline at end of file diff --git a/db/examples.json b/db/examples.json index ade3712..d7642f0 100644 --- a/db/examples.json +++ b/db/examples.json @@ -1,66 +1,87 @@ { - "create": [{ - "title": "Create a record", - "run_check": true, - "request": { - "table": "users", - "record": { - "id": "1", - "name": "Jane", - "age": 42, - "isActive":true - } - }, - "response": { - "id": "1" + "create": [ + { + "title": "Create a record", + "run_check": true, + "request": { + "table": "users", + "record": { + "id": "1", + "name": "Jane", + "age": 42, + "isActive": true } - }], - "update": [{ - "title": "Update a record", - "run_check": true, - "request": { - "table": "users", - "record": { - "id": "1", - "age": 43 - } - }, - "response": { + }, + "response": { + "id": "1" + } + } + ], + "update": [ + { + "title": "Update a record", + "run_check": true, + "request": { + "table": "users", + "record": { + "id": "1", + "age": 43 } - }], - "read": [{ - "title": "Read records", - "run_check": true, - "request": { - "table": "users", - "query": "age == 43" - }, - "response": { - "records": [{ - "id": "1", - "name": "Jane", - "age": 43, - "isActive":true - }] - } - }], - "delete": [{ - "title": "Delete a record", - "run_check": true, - "request": { - "table": "users", - "id": "1" - }, - "response": {} - }], - "truncate": [{ - "title": "Truncate table", - "run_check": false, - "request": { - "table": "users" - }, - "response": { - - } - }] + }, + "response": {} + } + ], + "read": [ + { + "title": "Read records", + "run_check": true, + "request": { + "table": "users", + "query": "age == 43" + }, + "response": { + "records": [ + { + "id": "1", + "name": "Jane", + "age": 43, + "isActive": true + } + ] + } + } + ], + "delete": [ + { + "title": "Delete a record", + "run_check": true, + "request": { + "table": "users", + "id": "1" + }, + "response": {} + } + ], + "truncate": [ + { + "title": "Truncate table", + "run_check": false, + "request": { + "table": "users" + }, + "response": {} + } + ], + "count": [ + { + "title": "Count entries in a table", + "run_check": false, + "request": { + "table": "users" + }, + "response": { + "count": 31 + } + } + ] } diff --git a/db/handler/db.go b/db/handler/db.go index 2a63a5b..bbc9d18 100644 --- a/db/handler/db.go +++ b/db/handler/db.go @@ -121,7 +121,7 @@ func (e *Db) Update(ctx context.Context, req *db.UpdateRequest, rsp *db.UpdateRe 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)) + return errors.BadRequest("db.update", fmt.Sprintf("table name %v is invalid", req.Table)) } logger.Infof("Updating table '%v'", tableName) @@ -306,7 +306,7 @@ func (e *Db) Delete(ctx context.Context, req *db.DeleteRequest, rsp *db.DeleteRe 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)) + return errors.BadRequest("db.delete", fmt.Sprintf("table name %v is invalid", req.Table)) } logger.Infof("Deleting from table '%v'", tableName) @@ -331,7 +331,7 @@ func (e *Db) Truncate(ctx context.Context, req *db.TruncateRequest, rsp *db.Trun 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)) + return errors.BadRequest("db.truncate", fmt.Sprintf("table name %v is invalid", req.Table)) } logger.Infof("Truncating table '%v'", tableName) @@ -341,3 +341,31 @@ func (e *Db) Truncate(ctx context.Context, req *db.TruncateRequest, rsp *db.Trun } return db.Exec(fmt.Sprintf(truncateStmt, tableName)).Error } + +func (e *Db) Count(ctx context.Context, req *db.CountRequest, rsp *db.CountResponse) 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.count", fmt.Sprintf("table name %v is invalid", req.Table)) + } + + db, err := e.GetDBConn(ctx) + if err != nil { + return err + } + + var a int64 + err = db.Table(tableName).Model(Record{}).Count(&a).Error + if err != nil { + return err + } + rsp.Count = int32(a) + return nil +} diff --git a/db/proto/db.pb.go b/db/proto/db.pb.go index 90c3305..3cc5f54 100644 --- a/db/proto/db.pb.go +++ b/db/proto/db.pb.go @@ -1,15 +1,15 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.15.6 +// protoc v3.6.1 // source: proto/db.proto package db import ( + _struct "github.com/golang/protobuf/ptypes/struct" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - structpb "google.golang.org/protobuf/types/known/structpb" reflect "reflect" sync "sync" ) @@ -27,7 +27,7 @@ type ReadRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Table name is optional + // Optional table name. Defaults to 'default' Table string `protobuf:"bytes,1,opt,name=table,proto3" json:"table,omitempty"` // Read by id. Equivalent to 'id == "your-id"' Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` @@ -38,7 +38,7 @@ type ReadRequest struct { // 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 number of records to return. 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 @@ -134,7 +134,7 @@ type ReadResponse struct { unknownFields protoimpl.UnknownFields // JSON encoded records - Records []*structpb.Struct `protobuf:"bytes,1,rep,name=records,proto3" json:"records,omitempty"` + Records []*_struct.Struct `protobuf:"bytes,1,rep,name=records,proto3" json:"records,omitempty"` } func (x *ReadResponse) Reset() { @@ -169,23 +169,23 @@ func (*ReadResponse) Descriptor() ([]byte, []int) { return file_proto_db_proto_rawDescGZIP(), []int{1} } -func (x *ReadResponse) GetRecords() []*structpb.Struct { +func (x *ReadResponse) GetRecords() []*_struct.Struct { if x != nil { return x.Records } return nil } -// Create a record in the database. Optionally include an "id" field otherwise its set automatically. +// Create a record in the database. Optionally include an "id" field otherwise it's set automatically. type CreateRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Table name is optional + // Optional table name. Defaults to 'default' Table string `protobuf:"bytes,1,opt,name=table,proto3" json:"table,omitempty"` // JSON encoded record or records (can be array or object) - Record *structpb.Struct `protobuf:"bytes,2,opt,name=record,proto3" json:"record,omitempty"` + Record *_struct.Struct `protobuf:"bytes,2,opt,name=record,proto3" json:"record,omitempty"` } func (x *CreateRequest) Reset() { @@ -227,7 +227,7 @@ func (x *CreateRequest) GetTable() string { return "" } -func (x *CreateRequest) GetRecord() *structpb.Struct { +func (x *CreateRequest) GetRecord() *_struct.Struct { if x != nil { return x.Record } @@ -288,12 +288,12 @@ type UpdateRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Table name is optional + // Optional table name. Defaults to 'default' Table string `protobuf:"bytes,1,opt,name=table,proto3" json:"table,omitempty"` - // The id of the record + // The id of the record. If not specified it is inferred from the 'id' field of the record Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` // record, JSON object - Record *structpb.Struct `protobuf:"bytes,3,opt,name=record,proto3" json:"record,omitempty"` + Record *_struct.Struct `protobuf:"bytes,3,opt,name=record,proto3" json:"record,omitempty"` } func (x *UpdateRequest) Reset() { @@ -342,7 +342,7 @@ func (x *UpdateRequest) GetId() string { return "" } -func (x *UpdateRequest) GetRecord() *structpb.Struct { +func (x *UpdateRequest) GetRecord() *_struct.Struct { if x != nil { return x.Record } @@ -393,9 +393,9 @@ type DeleteRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Table name is optional + // Optional table name. Defaults to 'default' Table string `protobuf:"bytes,1,opt,name=table,proto3" json:"table,omitempty"` - // id or ids, eg. 'user-1', or comma separated ids 'user-1,user-2' + // id of the record Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` } @@ -489,7 +489,7 @@ type TruncateRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Table name is optional + // Optional table name. Defaults to 'default' Table string `protobuf:"bytes,1,opt,name=table,proto3" json:"table,omitempty"` } @@ -580,6 +580,100 @@ func (x *TruncateResponse) GetTable() string { return "" } +type CountRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Table string `protobuf:"bytes,1,opt,name=table,proto3" json:"table,omitempty"` +} + +func (x *CountRequest) Reset() { + *x = CountRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_db_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CountRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CountRequest) ProtoMessage() {} + +func (x *CountRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_db_proto_msgTypes[10] + 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 CountRequest.ProtoReflect.Descriptor instead. +func (*CountRequest) Descriptor() ([]byte, []int) { + return file_proto_db_proto_rawDescGZIP(), []int{10} +} + +func (x *CountRequest) GetTable() string { + if x != nil { + return x.Table + } + return "" +} + +type CountResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Count int32 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` +} + +func (x *CountResponse) Reset() { + *x = CountResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_db_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CountResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CountResponse) ProtoMessage() {} + +func (x *CountResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_db_proto_msgTypes[11] + 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 CountResponse.ProtoReflect.Descriptor instead. +func (*CountResponse) Descriptor() ([]byte, []int) { + return file_proto_db_proto_rawDescGZIP(), []int{11} +} + +func (x *CountResponse) GetCount() int32 { + if x != nil { + return x.Count + } + return 0 +} + var File_proto_db_proto protoreflect.FileDescriptor var file_proto_db_proto_rawDesc = []byte{ @@ -625,25 +719,33 @@ 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, 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, + 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, + 0x24, 0x0a, 0x0c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 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, 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, } var ( @@ -658,7 +760,7 @@ func file_proto_db_proto_rawDescGZIP() []byte { return file_proto_db_proto_rawDescData } -var file_proto_db_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_proto_db_proto_msgTypes = make([]protoimpl.MessageInfo, 12) var file_proto_db_proto_goTypes = []interface{}{ (*ReadRequest)(nil), // 0: db.ReadRequest (*ReadResponse)(nil), // 1: db.ReadResponse @@ -670,24 +772,28 @@ var file_proto_db_proto_goTypes = []interface{}{ (*DeleteResponse)(nil), // 7: db.DeleteResponse (*TruncateRequest)(nil), // 8: db.TruncateRequest (*TruncateResponse)(nil), // 9: db.TruncateResponse - (*structpb.Struct)(nil), // 10: google.protobuf.Struct + (*CountRequest)(nil), // 10: db.CountRequest + (*CountResponse)(nil), // 11: db.CountResponse + (*_struct.Struct)(nil), // 12: google.protobuf.Struct } var file_proto_db_proto_depIdxs = []int32{ - 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 + 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 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 + 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 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 @@ -819,6 +925,30 @@ func file_proto_db_proto_init() { return nil } } + file_proto_db_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CountRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_db_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CountResponse); 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{ @@ -826,7 +956,7 @@ func file_proto_db_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_db_proto_rawDesc, NumEnums: 0, - NumMessages: 10, + NumMessages: 12, NumExtensions: 0, NumServices: 1, }, diff --git a/db/proto/db.pb.micro.go b/db/proto/db.pb.micro.go index fb4126e..37a9a6d 100644 --- a/db/proto/db.pb.micro.go +++ b/db/proto/db.pb.micro.go @@ -6,7 +6,7 @@ package db import ( fmt "fmt" proto "github.com/golang/protobuf/proto" - _ "google.golang.org/protobuf/types/known/structpb" + _ "github.com/golang/protobuf/ptypes/struct" math "math" ) @@ -48,6 +48,7 @@ type DbService interface { 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) + Count(ctx context.Context, in *CountRequest, opts ...client.CallOption) (*CountResponse, error) } type dbService struct { @@ -112,6 +113,16 @@ func (c *dbService) Truncate(ctx context.Context, in *TruncateRequest, opts ...c return out, nil } +func (c *dbService) Count(ctx context.Context, in *CountRequest, opts ...client.CallOption) (*CountResponse, error) { + req := c.c.NewRequest(c.name, "Db.Count", in) + out := new(CountResponse) + 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 { @@ -120,6 +131,7 @@ type DbHandler interface { Update(context.Context, *UpdateRequest, *UpdateResponse) error Delete(context.Context, *DeleteRequest, *DeleteResponse) error Truncate(context.Context, *TruncateRequest, *TruncateResponse) error + Count(context.Context, *CountRequest, *CountResponse) error } func RegisterDbHandler(s server.Server, hdlr DbHandler, opts ...server.HandlerOption) error { @@ -129,6 +141,7 @@ func RegisterDbHandler(s server.Server, hdlr DbHandler, opts ...server.HandlerOp 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 + Count(ctx context.Context, in *CountRequest, out *CountResponse) error } type Db struct { db @@ -160,3 +173,7 @@ func (h *dbHandler) Delete(ctx context.Context, in *DeleteRequest, out *DeleteRe func (h *dbHandler) Truncate(ctx context.Context, in *TruncateRequest, out *TruncateResponse) error { return h.DbHandler.Truncate(ctx, in, out) } + +func (h *dbHandler) Count(ctx context.Context, in *CountRequest, out *CountResponse) error { + return h.DbHandler.Count(ctx, in, out) +} diff --git a/db/proto/db.proto b/db/proto/db.proto index 06d7b62..51d8cc0 100644 --- a/db/proto/db.proto +++ b/db/proto/db.proto @@ -11,6 +11,7 @@ service Db { rpc Update(UpdateRequest) returns (UpdateResponse) {} rpc Delete(DeleteRequest) returns (DeleteResponse) {} rpc Truncate(TruncateRequest) returns (TruncateResponse) {} + rpc Count(CountRequest) returns (CountResponse) {} } @@ -88,3 +89,12 @@ message TruncateResponse { // The table truncated string table = 1; } + +// Count records in a table +message CountRequest { + string table = 1; +} + +message CountResponse { + int32 count = 1; +} \ No newline at end of file diff --git a/examples/db/count/curl/countEntriesInATable.sh b/examples/db/count/curl/countEntriesInATable.sh new file mode 100755 index 0000000..049d6e2 --- /dev/null +++ b/examples/db/count/curl/countEntriesInATable.sh @@ -0,0 +1,6 @@ +curl "https://api.m3o.com/v1/db/Count" \ +-H "Content-Type: application/json" \ +-H "Authorization: Bearer $MICRO_API_TOKEN" \ +-d '{ + "table": "users" +}' \ No newline at end of file diff --git a/examples/db/count/go/countEntriesInATable.go b/examples/db/count/go/countEntriesInATable.go new file mode 100755 index 0000000..99d2180 --- /dev/null +++ b/examples/db/count/go/countEntriesInATable.go @@ -0,0 +1,16 @@ +package example + +import ( + "fmt" + "github.com/micro/services/clients/go/db" + "os" +) + +// Count records in a table +func CountEntriesInAtable() { + dbService := db.NewDbService(os.Getenv("MICRO_API_TOKEN")) + rsp, err := dbService.Count(&db.CountRequest{ + Table: "users", + }) + fmt.Println(rsp, err) +} diff --git a/examples/db/count/node/countEntriesInATable.js b/examples/db/count/node/countEntriesInATable.js new file mode 100755 index 0000000..a979b55 --- /dev/null +++ b/examples/db/count/node/countEntriesInATable.js @@ -0,0 +1,12 @@ +import * as db from "m3o/db"; + +// Count records in a table +async function CountEntriesInAtable() { + let dbService = new db.DbService(process.env.MICRO_API_TOKEN); + let rsp = await dbService.count({ + table: "users", + }); + console.log(rsp); +} + +await CountEntriesInAtable(); diff --git a/examples/db/create/go/createARecord.go b/examples/db/create/go/createARecord.go index ed2b1c4..c582849 100755 --- a/examples/db/create/go/createARecord.go +++ b/examples/db/create/go/createARecord.go @@ -11,10 +11,10 @@ func CreateArecord() { dbService := db.NewDbService(os.Getenv("MICRO_API_TOKEN")) rsp, err := dbService.Create(&db.CreateRequest{ Record: map[string]interface{}{ - "id": "1", "name": "Jane", "age": 42, "isActive": true, + "id": "1", }, Table: "users", }) diff --git a/examples/stream/publish/go/publishAMessage.go b/examples/stream/publish/go/publishAMessage.go index af88ee1..0f33eac 100755 --- a/examples/stream/publish/go/publishAMessage.go +++ b/examples/stream/publish/go/publishAMessage.go @@ -11,9 +11,9 @@ func PublishAmessage() { streamService := stream.NewStreamService(os.Getenv("MICRO_API_TOKEN")) rsp, err := streamService.Publish(&stream.PublishRequest{ Message: map[string]interface{}{ + "user": "john", "id": "1", "type": "signup", - "user": "john", }, Topic: "events", })