azkustodata/query/from_kusto.go (60 lines of code) (raw):

package query import ( kustoErrors "github.com/Azure/azure-kusto-go/azkustodata/errors" "github.com/Azure/azure-kusto-go/azkustodata/value" "reflect" "strings" "sync" ) type fieldMap struct { colNameToFieldName map[string]string } var typeMapper = map[reflect.Type]fieldMap{} var typeMapperLock = sync.RWMutex{} // decodeToStruct takes a list of columns and a row to decode into "p" which will be a pointer // to a struct (enforce in the decoder). func decodeToStruct(cols []Column, row value.Values, p interface{}) error { t := reflect.TypeOf(p) v := reflect.ValueOf(p) fields := newFields(t) for i, col := range cols { if err := fields.convert(col, row[i], v); err != nil { return err } } return nil } // newFields takes in the Columns from our row and the reflect.Type of our *struct. func newFields(ptr reflect.Type) fieldMap { typeMapperLock.RLock() f, ok := typeMapper[ptr] typeMapperLock.RUnlock() if ok { return f } else { typeMapperLock.Lock() defer typeMapperLock.Unlock() nFields := fieldMap{colNameToFieldName: make(map[string]string, ptr.Elem().NumField())} for i := 0; i < ptr.Elem().NumField(); i++ { field := ptr.Elem().Field(i) if tag := field.Tag.Get("kusto"); strings.TrimSpace(tag) != "" { nFields.colNameToFieldName[tag] = field.Name } else { nFields.colNameToFieldName[field.Name] = field.Name } } typeMapper[ptr] = nFields return nFields } } // convert converts a KustoValue that is for Column col into "v" reflect.Value with reflect.Type "t". func (f fieldMap) convert(col Column, k value.Kusto, v reflect.Value) error { fieldName, ok := f.colNameToFieldName[col.Name()] if !ok { return nil } if fieldName == "-" { return nil } err := k.Convert(v.Elem().FieldByName(fieldName)) if err != nil { return kustoErrors.ES(kustoErrors.OpTableAccess, kustoErrors.KWrongColumnType, "column %s could not store in struct.%s: %s", col.Name(), fieldName, err.Error()) } return nil }