github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/col/coldata/json.go (about) 1 // Copyright 2021 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package coldata 12 13 import ( 14 "fmt" 15 "strings" 16 17 "github.com/cockroachdb/cockroachdb-parser/pkg/sql/colexecerror" 18 "github.com/cockroachdb/cockroachdb-parser/pkg/util/json" 19 ) 20 21 // JSONs is a representation of columnar JSON data. It's simply a wrapper around 22 // the flat Bytes structure. To pull a JSON out of the structure, we construct 23 // a new "encodedJSON" object from scratch on demand. 24 type JSONs struct { 25 Bytes 26 // scratch is a scratch space for encoding a JSON object on demand. 27 scratch []byte 28 } 29 30 // NewJSONs returns a new JSONs presized to n elements. 31 func NewJSONs(n int) *JSONs { 32 return &JSONs{ 33 Bytes: *NewBytes(n), 34 } 35 } 36 37 // Get returns the ith JSON in JSONs. Note that the returned JSON is 38 // unsafe for reuse if any write operation happens. 39 // NOTE: if ith element was never set in any way, the behavior of Get is 40 // undefined. 41 func (js *JSONs) Get(i int) json.JSON { 42 bytes := js.Bytes.Get(i) 43 if len(bytes) == 0 { 44 return json.NullJSONValue 45 } 46 ret, err := json.FromEncoding(bytes) 47 if err != nil { 48 colexecerror.ExpectedError(err) 49 } 50 return ret 51 } 52 53 // Set sets the ith JSON in JSONs. 54 func (js *JSONs) Set(i int, j json.JSON) { 55 var err error 56 js.scratch, err = json.EncodeJSON(js.scratch[:0], j) 57 if err != nil { 58 colexecerror.ExpectedError(err) 59 } 60 js.Bytes.Set(i, js.scratch) 61 } 62 63 // Window creates a "window" into the receiver. It behaves similarly to 64 // Golang's slice, but the returned object is *not* allowed to be modified - it 65 // is read-only. Window is a lightweight operation that doesn't involve copying 66 // the underlying data. 67 func (js *JSONs) Window(start, end int) *JSONs { 68 return &JSONs{ 69 Bytes: *js.Bytes.Window(start, end), 70 } 71 } 72 73 // Copy copies a single value from src at position srcIdx into position destIdx 74 // of the receiver. 75 func (js *JSONs) Copy(src *JSONs, destIdx, srcIdx int) { 76 js.Bytes.Copy(&src.Bytes, destIdx, srcIdx) 77 } 78 79 // CopySlice copies srcStartIdx inclusive and srcEndIdx exclusive []byte values 80 // from src into the receiver starting at destIdx. See Bytes.CopySlice. 81 func (js *JSONs) CopySlice(src *JSONs, destIdx, srcStartIdx, srcEndIdx int) { 82 js.Bytes.CopySlice(&src.Bytes, destIdx, srcStartIdx, srcEndIdx) 83 } 84 85 // AppendSlice appends srcStartIdx inclusive and srcEndIdx exclusive JSON 86 // values from src into the receiver starting at destIdx. 87 func (js *JSONs) AppendSlice(src *JSONs, destIdx, srcStartIdx, srcEndIdx int) { 88 js.Bytes.AppendSlice(&src.Bytes, destIdx, srcStartIdx, srcEndIdx) 89 } 90 91 // appendSliceWithSel appends all values specified in sel from the source into 92 // the receiver starting at position destIdx. 93 func (js *JSONs) appendSliceWithSel(src *JSONs, destIdx int, sel []int) { 94 js.Bytes.appendSliceWithSel(&src.Bytes, destIdx, sel) 95 } 96 97 // String is used for debugging purposes. 98 func (js *JSONs) String() string { 99 var builder strings.Builder 100 for i := 0; i < js.Len(); i++ { 101 builder.WriteString( 102 fmt.Sprintf("%d: %s\n", i, js.Get(i)), 103 ) 104 } 105 return builder.String() 106 }