mirror of
https://github.com/kevin-DL/services.git
synced 2026-01-16 21:14:36 +00:00
Recursive record type for DB (#144)
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
||||
gorm2 "github.com/micro/services/pkg/gorm"
|
||||
"github.com/micro/services/pkg/tenant"
|
||||
"github.com/patrickmn/go-cache"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
"gorm.io/datatypes"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@@ -37,7 +38,7 @@ type Db struct {
|
||||
|
||||
// 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) == 0 {
|
||||
if len(req.Record.AsMap()) == 0 {
|
||||
return errors.BadRequest("db.create", "missing record")
|
||||
}
|
||||
tenantId, ok := tenant.FromContext(ctx)
|
||||
@@ -60,11 +61,7 @@ func (e *Db) Create(ctx context.Context, req *db.CreateRequest, rsp *db.CreateRe
|
||||
c.Set(req.Table, true, 0)
|
||||
}
|
||||
|
||||
m := map[string]interface{}{}
|
||||
err = json.Unmarshal([]byte(req.Record), &m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m := req.Record.AsMap()
|
||||
if _, ok := m[idKey].(string); !ok {
|
||||
m[idKey] = uuid.New().String()
|
||||
}
|
||||
@@ -85,7 +82,7 @@ func (e *Db) Create(ctx context.Context, req *db.CreateRequest, rsp *db.CreateRe
|
||||
}
|
||||
|
||||
func (e *Db) Update(ctx context.Context, req *db.UpdateRequest, rsp *db.UpdateResponse) error {
|
||||
if len(req.Record) == 0 {
|
||||
if len(req.Record.AsMap()) == 0 {
|
||||
return errors.BadRequest("db.update", "missing record")
|
||||
}
|
||||
tenantId, ok := tenant.FromContext(ctx)
|
||||
@@ -98,11 +95,7 @@ func (e *Db) Update(ctx context.Context, req *db.UpdateRequest, rsp *db.UpdateRe
|
||||
return err
|
||||
}
|
||||
|
||||
m := map[string]interface{}{}
|
||||
err = json.Unmarshal([]byte(req.Record), &m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m := req.Record.AsMap()
|
||||
|
||||
// where ID is specified do a single update record update
|
||||
id, ok := m[idKey].(string)
|
||||
@@ -182,7 +175,8 @@ func (e *Db) Read(ctx context.Context, req *db.ReadRequest, rsp *db.ReadResponse
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ret := []map[string]interface{}{}
|
||||
|
||||
rsp.Records = []*structpb.Struct{}
|
||||
for _, rec := range recs {
|
||||
m, err := rec.Data.MarshalJSON()
|
||||
if err != nil {
|
||||
@@ -191,10 +185,15 @@ func (e *Db) Read(ctx context.Context, req *db.ReadRequest, rsp *db.ReadResponse
|
||||
ma := map[string]interface{}{}
|
||||
json.Unmarshal(m, &ma)
|
||||
ma[idKey] = rec.ID
|
||||
ret = append(ret, ma)
|
||||
m, _ = json.Marshal(ma)
|
||||
s := &structpb.Struct{}
|
||||
err = s.UnmarshalJSON(m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rsp.Records = append(rsp.Records, s)
|
||||
}
|
||||
bs, _ := json.Marshal(ret)
|
||||
rsp.Records = string(bs)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
)
|
||||
|
||||
var quoteEscape = fmt.Sprint(0x10FFFF)
|
||||
var singleQuoteEscape = fmt.Sprint(0x10FFFE)
|
||||
var backtickEscape = fmt.Sprint(0x10FFFD)
|
||||
|
||||
const (
|
||||
itemIgnore = iota
|
||||
@@ -53,6 +55,8 @@ var expressions = []lexer.TokenExpr{
|
||||
{`>`, itemGreaterThan},
|
||||
{`[0-9]+`, itemInt},
|
||||
{`"(?:[^"\\]|\\.)*"`, itemString},
|
||||
{"`" + `(?:[^"\\]|\\.)*` + "`", itemString},
|
||||
{`'(?:[^"\\]|\\.)*'`, itemString},
|
||||
{`[\<\>\!\=\+\-\|\&\*\/A-Za-z][A-Za-z0-9_]*`, itemFieldName},
|
||||
}
|
||||
|
||||
@@ -67,6 +71,9 @@ func Parse(q string) ([]Query, error) {
|
||||
return nil, errors.New("query contains illegal max rune")
|
||||
}
|
||||
q = strings.Replace(q, `""`, quoteEscape, -1)
|
||||
q = strings.Replace(q, "``", singleQuoteEscape, -1)
|
||||
q = strings.Replace(q, "''", backtickEscape, -1)
|
||||
|
||||
tokens, err := lexer.Lex(q, expressions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -102,7 +109,11 @@ func Parse(q string) ([]Query, error) {
|
||||
if len(token.Text) < 2 {
|
||||
return nil, fmt.Errorf("string literal too short: '%v'", token.Text)
|
||||
}
|
||||
current.Value = strings.Replace(token.Text[1:len(token.Text)-1], quoteEscape, `"`, -1)
|
||||
to := token.Text[1 : len(token.Text)-1]
|
||||
to = strings.Replace(to, quoteEscape, `"`, -1)
|
||||
to = strings.Replace(to, singleQuoteEscape, `'`, -1)
|
||||
to = strings.Replace(to, backtickEscape, "`", -1)
|
||||
current.Value = to
|
||||
case itemBoolTrue:
|
||||
switch current.Op {
|
||||
case itemEquals, itemNotEquals:
|
||||
|
||||
@@ -20,7 +20,7 @@ func TestLexing(t *testing.T) {
|
||||
t.Fatal(tokens)
|
||||
}
|
||||
|
||||
tokens, err = lexer.Lex(`a == 12 and name != "nandos"`, expressions)
|
||||
tokens, err = lexer.Lex(`a == 12 and name != 'nandos'`, expressions)
|
||||
if tokens[0].Typ != itemFieldName ||
|
||||
tokens[1].Typ != itemEquals ||
|
||||
tokens[2].Typ != itemInt ||
|
||||
@@ -55,9 +55,54 @@ func TestParsing(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
tCase{
|
||||
Q: `a == 12 and name != "nan'dos"`,
|
||||
E: []Query{
|
||||
Query{
|
||||
Field: "a",
|
||||
Value: int64(12),
|
||||
Op: itemEquals,
|
||||
},
|
||||
Query{
|
||||
Field: "name",
|
||||
Value: "nan'dos",
|
||||
Op: itemNotEquals,
|
||||
},
|
||||
},
|
||||
},
|
||||
tCase{
|
||||
Q: `a == 12 and name != 'nandos'`,
|
||||
E: []Query{
|
||||
Query{
|
||||
Field: "a",
|
||||
Value: int64(12),
|
||||
Op: itemEquals,
|
||||
},
|
||||
Query{
|
||||
Field: "name",
|
||||
Value: "nandos",
|
||||
Op: itemNotEquals,
|
||||
},
|
||||
},
|
||||
},
|
||||
tCase{
|
||||
Q: "a == 12 and name != `nandos`",
|
||||
E: []Query{
|
||||
Query{
|
||||
Field: "a",
|
||||
Value: int64(12),
|
||||
Op: itemEquals,
|
||||
},
|
||||
Query{
|
||||
Field: "name",
|
||||
Value: "nandos",
|
||||
Op: itemNotEquals,
|
||||
},
|
||||
},
|
||||
},
|
||||
// test escaping quotes
|
||||
tCase{
|
||||
Q: `a == 12 and name != "He said ""yes""!"`,
|
||||
Q: `a == 12 and name != 'He said ""yes""!'`,
|
||||
E: []Query{
|
||||
Query{
|
||||
Field: "a",
|
||||
|
||||
Reference in New Issue
Block a user