github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/sys/sqlquery/impl_viewrecords.go (about) 1 /* 2 * Copyright (c) 2022-present unTill Pro, Ltd. 3 */ 4 5 package sqlquery 6 7 import ( 8 "context" 9 "encoding/json" 10 "fmt" 11 "strconv" 12 13 "github.com/blastrain/vitess-sqlparser/sqlparser" 14 15 "github.com/voedger/voedger/pkg/appdef" 16 "github.com/voedger/voedger/pkg/istructs" 17 coreutils "github.com/voedger/voedger/pkg/utils" 18 ) 19 20 func readViewRecords(ctx context.Context, wsid istructs.WSID, viewRecordQName appdef.QName, expr sqlparser.Expr, appStructs istructs.IAppStructs, f *filter, callback istructs.ExecQueryCallback) error { 21 view := appStructs.AppDef().View(viewRecordQName) 22 23 if !f.acceptAll { 24 allowedFields := make(map[string]bool, view.Key().FieldCount()+view.Value().FieldCount()) 25 for _, f := range view.Key().Fields() { 26 allowedFields[f.Name()] = true 27 } 28 for _, f := range view.Value().Fields() { 29 allowedFields[f.Name()] = true 30 } 31 for field := range f.fields { 32 if !allowedFields[field] { 33 return fmt.Errorf("field '%s' does not exist in '%s' value def", field, viewRecordQName) 34 } 35 } 36 } 37 38 kk := make([]keyPart, 0) 39 var keyParts func(expr sqlparser.Expr) error 40 keyParts = func(expr sqlparser.Expr) error { 41 switch r := expr.(type) { 42 case *sqlparser.ComparisonExpr: 43 if r.Operator != sqlparser.EqualStr { 44 return fmt.Errorf("unsupported operator: %s", r.Operator) 45 } 46 47 cn := r.Left.(*sqlparser.ColName) 48 49 var name string 50 if !cn.Qualifier.IsEmpty() { 51 name = fmt.Sprintf("%s.%s", cn.Qualifier.Name, cn.Name) 52 } else { 53 name = cn.Name.String() 54 } 55 56 kk = append(kk, keyPart{ 57 name: name, 58 value: r.Right.(*sqlparser.SQLVal).Val, 59 }) 60 case *sqlparser.AndExpr: 61 e := keyParts(r.Left) 62 if e != nil { 63 return e 64 } 65 e = keyParts(r.Right) 66 if e != nil { 67 return e 68 } 69 case nil: 70 default: 71 return fmt.Errorf("unsupported expression: %T", r) 72 } 73 return nil 74 } 75 err := keyParts(expr) 76 if err != nil { 77 return err 78 } 79 80 kb := appStructs.ViewRecords().KeyBuilder(viewRecordQName) 81 82 for _, k := range kk { 83 f := view.Key().Field(k.name) 84 if f == nil { 85 return fmt.Errorf("field '%s' does not exist in '%s' key def", k.name, viewRecordQName) 86 } 87 switch f.DataKind() { 88 case appdef.DataKind_int32: 89 fallthrough 90 case appdef.DataKind_int64: 91 fallthrough 92 case appdef.DataKind_float32: 93 fallthrough 94 case appdef.DataKind_float64: 95 fallthrough 96 case appdef.DataKind_RecordID: 97 v, e := strconv.ParseFloat(string(k.value), bitSize64) 98 if e != nil { 99 return e 100 } 101 kb.PutNumber(k.name, v) 102 case appdef.DataKind_bytes, appdef.DataKind_string: 103 fallthrough 104 case appdef.DataKind_QName: 105 kb.PutChars(k.name, string(k.value)) 106 default: 107 return errUnsupportedDataKind 108 } 109 } 110 111 return appStructs.ViewRecords().Read(ctx, wsid, kb, func(key istructs.IKey, value istructs.IValue) (err error) { 112 data := coreutils.FieldsToMap(key, appStructs.AppDef(), getFilter(f.filter), coreutils.WithNonNilsOnly()) 113 for k, v := range coreutils.FieldsToMap(value, appStructs.AppDef(), getFilter(f.filter), coreutils.WithNonNilsOnly()) { 114 data[k] = v 115 } 116 bb, err := json.Marshal(data) 117 if err != nil { 118 return err 119 } 120 121 return callback(&result{value: string(bb)}) 122 }) 123 }