MCPcopy Create free account
hub / github.com/brimdata/super / NewRecordBuilder

Function NewRecordBuilder

recordbuilder.go:60–124  ·  view source on GitHub ↗

NewRecordBuilder constructs the scode.Bytes representation for records built from an array of input field selectors expressed as field.Path. Append should be called to enter field values in the left to right order of the provided fields and Encode is called to retrieve the nested scode.Bytes value.

(sctx *Context, fields field.List)

Source from the content-addressed store, hash-verified

58// value. Reset should be called before encoding the next record. This mechanism
59// never builds records with optional fields.
60func NewRecordBuilder(sctx *Context, fields field.List) (*RecordBuilder, error) {
61 seenRecords := make(map[string]bool)
62 fieldInfos := make([]fieldInfo, 0, len(fields))
63 var currentRecord []string
64 for i, field := range fields {
65 if field.IsEmpty() {
66 return nil, errors.New("empty field path")
67 }
68 names := field
69 // Grab everything except the leaf field name and see if
70 // it has changed from the previous field. If it hasn't,
71 // things are simple but if it has, we need to carefully
72 // figure out which records we are stepping in and out of.
73 record := names[:len(names)-1]
74 var containerBegins []string
75 if !slices.Equal(record, currentRecord) {
76 // currentRecord is what nested record the scode.Builder
77 // is currently working on, record is the nested
78 // record for the current field. First figure out
79 // what (if any) common parents are shared.
80 l := min(len(currentRecord), len(record))
81 pos := 0
82 for pos < l {
83 if record[pos] != currentRecord[pos] {
84 break
85 }
86 pos += 1
87 }
88
89 // Note any previously encoded records that are
90 // now finished.
91 if i > 0 {
92 fieldInfos[i-1].containerEnds = len(currentRecord) - pos
93 }
94
95 // Validate any new records that we're starting
96 // (i.e., ensure that we didn't handle fields from
97 // the same record previously), then record the names
98 // of all these records.
99 for pos2 := pos; pos2 < len(record); pos2++ {
100 recname := strings.Join(record[:pos2+1], ".")
101 _, seen := seenRecords[recname]
102 if seen {
103 return nil, fmt.Errorf("fields in record %s must be adjacent", recname)
104 }
105 seenRecords[recname] = true
106 containerBegins = append(containerBegins, record[pos2])
107 }
108 currentRecord = record
109 }
110 if isIn(field, fieldInfos) {
111 return nil, &DuplicateFieldError{strings.Join(field, ".")}
112 }
113 fieldInfos = append(fieldInfos, fieldInfo{field, containerBegins, 0})
114 }
115 if len(fieldInfos) > 0 {
116 fieldInfos[len(fieldInfos)-1].containerEnds = len(currentRecord)
117 }

Callers 5

semOpMethod · 0.92
lookupBuilderAndTypeMethod · 0.92
NewScalarFunction · 0.92
NewFunction · 0.92
buildMetadataValueFunction · 0.92

Calls 5

NewBuilderFunction · 0.92
isInFunction · 0.85
IsEmptyMethod · 0.80
NewMethod · 0.80
EqualMethod · 0.45

Tested by

no test coverage detected