github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/state/impl_records_storage.go (about) 1 /* 2 * Copyright (c) 2022-present unTill Pro, Ltd. 3 */ 4 5 package state 6 7 import ( 8 "fmt" 9 10 "github.com/voedger/voedger/pkg/appdef" 11 "github.com/voedger/voedger/pkg/istructs" 12 ) 13 14 type recordsStorage struct { 15 recordsFunc recordsFunc 16 cudFunc CUDFunc 17 wsidFunc WSIDFunc 18 wsTypeVailidator wsTypeVailidator 19 } 20 21 func newRecordsStorage(appStructsFunc AppStructsFunc, wsidFunc WSIDFunc, cudFunc CUDFunc) *recordsStorage { 22 return &recordsStorage{ 23 recordsFunc: func() istructs.IRecords { return appStructsFunc().Records() }, 24 wsidFunc: wsidFunc, 25 cudFunc: cudFunc, 26 wsTypeVailidator: newWsTypeValidator(appStructsFunc), 27 } 28 } 29 30 func (s *recordsStorage) NewKeyBuilder(entity appdef.QName, _ istructs.IStateKeyBuilder) istructs.IStateKeyBuilder { 31 return &recordsKeyBuilder{ 32 id: istructs.NullRecordID, 33 singleton: appdef.NullQName, 34 wsid: s.wsidFunc(), 35 entity: entity, 36 } 37 } 38 39 func (s *recordsStorage) Get(key istructs.IStateKeyBuilder) (value istructs.IStateValue, err error) { 40 k := key.(*recordsKeyBuilder) 41 if k.singleton != appdef.NullQName { 42 err = s.wsTypeVailidator.validate(k.wsid, k.singleton) 43 if err != nil { 44 return nil, err 45 } 46 singleton, e := s.recordsFunc().GetSingleton(k.wsid, k.singleton) 47 if e != nil { 48 return nil, e 49 } 50 if singleton.QName() == appdef.NullQName { 51 return nil, nil 52 } 53 return &recordsValue{record: singleton}, nil 54 } 55 if k.id == istructs.NullRecordID { 56 // error message according to https://dev.untill.com/projects/#!637229 57 return nil, fmt.Errorf("value of one of RecordID fields is 0: %w", ErrNotFound) 58 } 59 record, err := s.recordsFunc().Get(k.wsid, true, k.id) 60 if err != nil { 61 return nil, err 62 } 63 if record.QName() == appdef.NullQName { 64 return nil, nil 65 } 66 return &recordsValue{record: record}, nil 67 } 68 69 func (s *recordsStorage) GetBatch(items []GetBatchItem) (err error) { 70 type getSingletonParams struct { 71 wsid istructs.WSID 72 qname appdef.QName 73 itemIdx int 74 } 75 wsidToItemIdx := make(map[istructs.WSID][]int) 76 batches := make(map[istructs.WSID][]istructs.RecordGetBatchItem) 77 gg := make([]getSingletonParams, 0) 78 for itemIdx, item := range items { 79 k := item.key.(*recordsKeyBuilder) 80 if k.singleton != appdef.NullQName { 81 err = s.wsTypeVailidator.validate(k.wsid, k.singleton) 82 if err != nil { 83 return err 84 } 85 gg = append(gg, getSingletonParams{ 86 wsid: k.wsid, 87 qname: k.singleton, 88 itemIdx: itemIdx, 89 }) 90 continue 91 } 92 if k.id == istructs.NullRecordID { 93 // error message according to https://dev.untill.com/projects/#!637229 94 return fmt.Errorf("value of one of RecordID fields is 0: %w", ErrNotFound) 95 } 96 wsidToItemIdx[k.wsid] = append(wsidToItemIdx[k.wsid], itemIdx) 97 batches[k.wsid] = append(batches[k.wsid], istructs.RecordGetBatchItem{ID: k.id}) 98 } 99 for wsid, batch := range batches { 100 err = s.recordsFunc().GetBatch(wsid, true, batch) 101 if err != nil { 102 return 103 } 104 for i, batchItem := range batch { 105 if batchItem.Record.QName() == appdef.NullQName { 106 continue 107 } 108 items[wsidToItemIdx[wsid][i]].value = &recordsValue{record: batchItem.Record} 109 } 110 } 111 for _, g := range gg { 112 singleton, e := s.recordsFunc().GetSingleton(g.wsid, g.qname) 113 if e != nil { 114 return e 115 } 116 if singleton.QName() == appdef.NullQName { 117 continue 118 } 119 items[g.itemIdx].value = &recordsValue{record: singleton} 120 } 121 return err 122 } 123 func (s *recordsStorage) Validate([]ApplyBatchItem) (err error) { return } 124 func (s *recordsStorage) ApplyBatch([]ApplyBatchItem) (err error) { return } 125 func (s *recordsStorage) ProvideValueBuilder(key istructs.IStateKeyBuilder, _ istructs.IStateValueBuilder) (istructs.IStateValueBuilder, error) { 126 kb := key.(*recordsKeyBuilder) 127 if kb.entity == appdef.NullQName { 128 return nil, errEntityRequiredForValueBuilder 129 } 130 err := s.wsTypeVailidator.validate(kb.wsid, kb.entity) 131 if err != nil { 132 return nil, err 133 } 134 rw := s.cudFunc().Create(kb.entity) 135 return &recordsValueBuilder{rw: rw}, nil 136 } 137 func (s *recordsStorage) ProvideValueBuilderForUpdate(_ istructs.IStateKeyBuilder, existingValue istructs.IStateValue, _ istructs.IStateValueBuilder) (istructs.IStateValueBuilder, error) { 138 return &recordsValueBuilder{rw: s.cudFunc().Update(existingValue.AsRecord(""))}, nil 139 }