github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/sys/uniques/utils.go (about) 1 /* 2 * Copyright (c) 2024-present unTill Software Development Group B.V. 3 * @author Denis Gribanov 4 */ 5 6 package uniques 7 8 import ( 9 "errors" 10 "fmt" 11 12 "github.com/voedger/voedger/pkg/appdef" 13 "github.com/voedger/voedger/pkg/istructs" 14 "github.com/voedger/voedger/pkg/istructsmem" 15 ) 16 17 // returns ID of the record identified by the the provided unique combination 18 // returns NullRecordID if there is no record by the provided unique combination or if the record is inactive 19 func GetRecordIDByUniqueCombination(wsid istructs.WSID, tableQName appdef.QName, as istructs.IAppStructs, values map[string]interface{}) (istructs.RecordID, error) { 20 tableType := as.AppDef().Type(tableQName) 21 if tableType.Kind() == appdef.TypeKind_null { 22 return 0, appdef.ErrNotFound("type %q", tableQName) 23 } 24 table, ok := tableType.(appdef.IDoc) //nnv: why IDoc but not IRecord ?? 25 if !ok { 26 return 0, fmt.Errorf("%q is not a table: %w", tableQName, appdef.ErrInvalidError) 27 } 28 // let's find the unique by set of field names 29 // matchedIUnique := appdef.IUnique(nil) 30 matchedUniqueQName := appdef.NullQName 31 matchedUniqueFields := []appdef.IField{} 32 for _, iUnique := range table.Uniques() { 33 if len(values) != len(iUnique.Fields()) { 34 continue 35 } 36 matchedFieldsCount := 0 37 for providedFieldName := range values { 38 for _, uniqueField := range iUnique.Fields() { 39 if uniqueField.Name() == providedFieldName { 40 matchedFieldsCount++ 41 break 42 } 43 } 44 } 45 if matchedFieldsCount == len(iUnique.Fields()) { 46 matchedUniqueQName = iUnique.Name() 47 matchedUniqueFields = iUnique.Fields() 48 break 49 } 50 } 51 if matchedUniqueQName == appdef.NullQName && table.UniqueField() != nil && len(values) == 1 { 52 providedUniqueFieldName := "" 53 for n := range values { 54 providedUniqueFieldName = n 55 } 56 if table.UniqueField().Name() == providedUniqueFieldName { 57 matchedUniqueQName = table.QName() 58 matchedUniqueFields = append(matchedUniqueFields, table.UniqueField()) 59 } 60 } 61 if matchedUniqueQName == appdef.NullQName { 62 return 0, fmt.Errorf("provided set of fields does not match any known unique of %s: %w", tableType.QName(), ErrUniqueNotExist) 63 } 64 65 // build unique field values stream 66 uniqueKeyValues, err := getUniqueKeyValuesFromMap(values, matchedUniqueFields, matchedUniqueQName) 67 if err != nil { 68 return 0, err 69 } 70 71 uniqueViewRecordBuilder := as.ViewRecords().KeyBuilder(qNameViewUniques) 72 buildUniqueViewKeyByValues(uniqueViewRecordBuilder, matchedUniqueQName, uniqueKeyValues) 73 uniqueViewRecord, err := as.ViewRecords().Get(wsid, uniqueViewRecordBuilder) 74 if err != nil { 75 if errors.Is(err, istructsmem.ErrRecordNotFound) { 76 return 0, nil 77 } 78 // notest 79 return 0, err 80 } 81 return uniqueViewRecord.AsRecordID(field_ID), nil 82 }