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  }