github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/processors/query/operator-result-fields-impl.go (about) 1 /* 2 * Copyright (c) 2021-present unTill Pro, Ltd. 3 */ 4 5 package queryprocessor 6 7 import ( 8 "context" 9 "time" 10 11 "github.com/voedger/voedger/pkg/istructs" 12 "github.com/voedger/voedger/pkg/pipeline" 13 coreutils "github.com/voedger/voedger/pkg/utils" 14 ) 15 16 type ResultFieldsOperator struct { 17 pipeline.AsyncNOOP 18 elements []IElement 19 rootFields FieldsKinds 20 fieldsDefs *fieldsDefs 21 metrics IMetrics 22 } 23 24 func (o ResultFieldsOperator) DoAsync(ctx context.Context, work pipeline.IWorkpiece) (outWork pipeline.IWorkpiece, err error) { 25 begin := time.Now() 26 defer func() { 27 o.metrics.Increase(execFieldsSeconds, time.Since(begin).Seconds()) 28 }() 29 outputRow := work.(IWorkpiece).OutputRow() 30 object := work.(IWorkpiece).Object() 31 for _, element := range o.elements { 32 outputRow.Set(element.Path().Name(), make([]IOutputRow, 0)) 33 if element.Path().IsRoot() { 34 err = o.fillRow(ctx, outputRow, element, object, o.rootFields) 35 if err != nil { 36 return work, err 37 } 38 continue 39 } 40 var findElements func(parent istructs.IObject, pathEntries []string, pathEntryIndex int) 41 findElements = func(parent istructs.IObject, pathEntries []string, pathEntryIndex int) { 42 parent.Children(pathEntries[pathEntryIndex], func(c istructs.IObject) { 43 if pathEntryIndex == len(pathEntries)-1 { 44 err = o.fillRow(ctx, outputRow, element, c, o.fieldsDefs.get(c.QName())) 45 if err != nil { 46 return 47 } 48 } else { 49 findElements(c, pathEntries, pathEntryIndex+1) 50 } 51 }) 52 } 53 findElements(object, element.Path().AsArray(), 0) 54 } 55 return work, err 56 } 57 58 func (o ResultFieldsOperator) fillRow(ctx context.Context, outputRow IOutputRow, element IElement, object istructs.IObject, fk FieldsKinds) (err error) { 59 row := element.NewOutputRow() 60 for _, field := range element.ResultFields() { 61 if ctx.Err() != nil { 62 return ctx.Err() 63 } 64 value := coreutils.ReadByKind(field.Field(), fk[field.Field()], object) 65 row.Set(field.Field(), value) 66 } 67 for _, field := range element.RefFields() { 68 if ctx.Err() != nil { 69 err = ctx.Err() 70 return 71 } 72 row.Set(field.Key(), object.AsRecordID(field.Field())) 73 } 74 outputRow.Set(element.Path().Name(), append(outputRow.Value(element.Path().Name()).([]IOutputRow), row)) 75 return nil 76 }