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  }