github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/store/types/json.go (about)

     1  // Copyright 2021 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package types
    16  
    17  import (
    18  	"context"
    19  	"errors"
    20  	"fmt"
    21  	"strings"
    22  
    23  	"github.com/dolthub/dolt/go/store/d"
    24  )
    25  
    26  type JSON struct {
    27  	valueImpl
    28  }
    29  
    30  // NewJSONDoc wraps |value| in a JSON value.
    31  func NewJSONDoc(nbf *NomsBinFormat, vrw ValueReadWriter, value Value) (JSON, error) {
    32  	w := newBinaryNomsWriter()
    33  	if err := JSONKind.writeTo(&w, nbf); err != nil {
    34  		return EmptyJSONDoc(nbf), err
    35  	}
    36  
    37  	if err := value.writeTo(&w, nbf); err != nil {
    38  		return EmptyJSONDoc(nbf), err
    39  	}
    40  
    41  	return JSON{valueImpl{vrw, nbf, w.data(), nil}}, nil
    42  }
    43  
    44  // EmptyJSONDoc creates and empty JSON value.
    45  func EmptyJSONDoc(nbf *NomsBinFormat) JSON {
    46  	w := newBinaryNomsWriter()
    47  	if err := JSONKind.writeTo(&w, nbf); err != nil {
    48  		d.PanicIfError(err)
    49  	}
    50  
    51  	return JSON{valueImpl{nil, nbf, w.data(), nil}}
    52  }
    53  
    54  // readJSON reads the data provided by a decoder and moves the decoder forward.
    55  func readJSON(nbf *NomsBinFormat, dec *valueDecoder) (JSON, error) {
    56  	start := dec.pos()
    57  
    58  	k := dec.PeekKind()
    59  	if k == NullKind {
    60  		dec.skipKind()
    61  		return EmptyJSONDoc(nbf), nil
    62  	}
    63  	if k != JSONKind {
    64  		return JSON{}, errors.New("current value is not a JSON")
    65  	}
    66  
    67  	if err := skipJSON(nbf, dec); err != nil {
    68  		return JSON{}, err
    69  	}
    70  
    71  	end := dec.pos()
    72  	return JSON{valueImpl{dec.vrw, nbf, dec.byteSlice(start, end), nil}}, nil
    73  }
    74  
    75  func skipJSON(nbf *NomsBinFormat, dec *valueDecoder) error {
    76  	dec.skipKind()
    77  	return dec.SkipValue(nbf)
    78  }
    79  
    80  func walkJSON(nbf *NomsBinFormat, r *refWalker, cb RefCallback) error {
    81  	r.skipKind()
    82  	return r.walkValue(nbf, cb)
    83  }
    84  
    85  // CopyOf creates a copy of a JSON.  This is necessary in cases where keeping a reference to the original JSON is
    86  // preventing larger objects from being collected.
    87  func (t JSON) CopyOf(vrw ValueReadWriter) JSON {
    88  	buff := make([]byte, len(t.buff))
    89  	offsets := make([]uint32, len(t.offsets))
    90  
    91  	copy(buff, t.buff)
    92  	copy(offsets, t.offsets)
    93  
    94  	return JSON{
    95  		valueImpl{
    96  			buff:    buff,
    97  			offsets: offsets,
    98  			vrw:     vrw,
    99  			nbf:     t.nbf,
   100  		},
   101  	}
   102  }
   103  
   104  // Empty implements the Emptyable interface.
   105  func (t JSON) Empty() bool {
   106  	return t.Len() == 0
   107  }
   108  
   109  // Format returns this values NomsBinFormat.
   110  func (t JSON) Format() *NomsBinFormat {
   111  	return t.format()
   112  }
   113  
   114  // Value implements the Value interface.
   115  func (t JSON) Value(ctx context.Context) (Value, error) {
   116  	return t, nil
   117  }
   118  
   119  // Inner returns the JSON value's inner value.
   120  func (t JSON) Inner() (Value, error) {
   121  	dec := newValueDecoder(t.buff, t.vrw)
   122  	dec.skipKind()
   123  	return dec.readValue(t.nbf)
   124  }
   125  
   126  // WalkValues implements the Value interface.
   127  func (t JSON) WalkValues(ctx context.Context, cb ValueCallback) error {
   128  	val, err := t.Inner()
   129  	if err != nil {
   130  		return err
   131  	}
   132  	return val.WalkValues(ctx, cb)
   133  }
   134  
   135  // typeOf implements the Value interface.
   136  func (t JSON) typeOf() (*Type, error) {
   137  	val, err := t.Inner()
   138  	if err != nil {
   139  		return nil, err
   140  	}
   141  	return val.typeOf()
   142  }
   143  
   144  // Kind implements the Valuable interface.
   145  func (t JSON) Kind() NomsKind {
   146  	return JSONKind
   147  }
   148  
   149  func (t JSON) decoderSkipToFields() (valueDecoder, uint64) {
   150  	dec := t.decoder()
   151  	dec.skipKind()
   152  	return dec, uint64(1)
   153  }
   154  
   155  // Len implements the Value interface.
   156  func (t JSON) Len() uint64 {
   157  	// TODO(andy): is this ever 0?
   158  	return 1
   159  }
   160  
   161  func (t JSON) isPrimitive() bool {
   162  	return false
   163  }
   164  
   165  // Less implements the LesserValuable interface.
   166  func (t JSON) Less(nbf *NomsBinFormat, other LesserValuable) (bool, error) {
   167  	otherJSONDoc, ok := other.(JSON)
   168  	if !ok {
   169  		return JSONKind < other.Kind(), nil
   170  	}
   171  
   172  	cmp, err := t.Compare(otherJSONDoc)
   173  	if err != nil {
   174  		return false, err
   175  	}
   176  
   177  	return cmp == -1, nil
   178  }
   179  
   180  // Compare implements MySQL JSON type compare semantics.
   181  func (t JSON) Compare(other JSON) (int, error) {
   182  	left, err := t.Inner()
   183  	if err != nil {
   184  		return 0, err
   185  	}
   186  
   187  	right, err := other.Inner()
   188  	if err != nil {
   189  		return 0, err
   190  	}
   191  
   192  	return compareJSON(left, right)
   193  }
   194  
   195  func (t JSON) readFrom(nbf *NomsBinFormat, b *binaryNomsReader) (Value, error) {
   196  	panic("unreachable")
   197  }
   198  
   199  func (t JSON) skip(nbf *NomsBinFormat, b *binaryNomsReader) {
   200  	panic("unreachable")
   201  }
   202  
   203  // HumanReadableString implements the Value interface.
   204  func (t JSON) HumanReadableString() string {
   205  	val, err := t.Inner()
   206  	if err != nil {
   207  		d.PanicIfError(err)
   208  	}
   209  	h, err := val.Hash(t.nbf)
   210  	if err != nil {
   211  		d.PanicIfError(err)
   212  	}
   213  	return fmt.Sprintf("JSON(%s)", h.String())
   214  }
   215  
   216  func compareJSON(a, b Value) (int, error) {
   217  	aNull := a.Kind() == NullKind
   218  	bNull := b.Kind() == NullKind
   219  	if aNull && bNull {
   220  		return 0, nil
   221  	} else if aNull && !bNull {
   222  		return -1, nil
   223  	} else if !aNull && bNull {
   224  		return 1, nil
   225  	}
   226  
   227  	switch a := a.(type) {
   228  	case Bool:
   229  		return compareJSONBool(a, b)
   230  	case List:
   231  		return compareJSONArray(a, b)
   232  	case Map:
   233  		return compareJSONObject(a, b)
   234  	case String:
   235  		return compareJSONString(a, b)
   236  	case Float:
   237  		return compareJSONNumber(a, b)
   238  	default:
   239  		return 0, fmt.Errorf("unexpected type: %v", a)
   240  	}
   241  }
   242  
   243  func compareJSONBool(a Bool, b Value) (int, error) {
   244  	switch b := b.(type) {
   245  	case Bool:
   246  		// The JSON false literal is less than the JSON true literal.
   247  		if a == b {
   248  			return 0, nil
   249  		}
   250  		if a {
   251  			// a > b
   252  			return 1, nil
   253  		} else {
   254  			// a < b
   255  			return -1, nil
   256  		}
   257  
   258  	default:
   259  		// a is higher precedence
   260  		return 1, nil
   261  	}
   262  }
   263  
   264  func compareJSONArray(a List, b Value) (int, error) {
   265  	switch b := b.(type) {
   266  	case Bool:
   267  		// a is lower precedence
   268  		return -1, nil
   269  
   270  	case List:
   271  		// Two JSON arrays are equal if they have the same length and values in corresponding positions in the arrays
   272  		// are equal. If the arrays are not equal, their order is determined by the elements in the first position
   273  		// where there is a difference. The array with the smaller value in that position is ordered first.
   274  
   275  		// TODO(andy): this diverges from GMS
   276  		aLess, err := a.Less(a.format(), b)
   277  		if err != nil {
   278  			return 0, err
   279  		}
   280  		if aLess {
   281  			return -1, nil
   282  		}
   283  
   284  		bLess, err := b.Less(b.format(), a)
   285  		if err != nil {
   286  			return 0, err
   287  		}
   288  		if bLess {
   289  			return 1, nil
   290  		}
   291  
   292  		return 0, nil
   293  
   294  	default:
   295  		// a is higher precedence
   296  		return 1, nil
   297  	}
   298  }
   299  
   300  func compareJSONObject(a Map, b Value) (int, error) {
   301  	switch b := b.(type) {
   302  	case
   303  		Bool,
   304  		List:
   305  		// a is lower precedence
   306  		return -1, nil
   307  
   308  	case Map:
   309  		// Two JSON objects are equal if they have the same set of keys, and each key has the same value in both
   310  		// objects. The order of two objects that are not equal is unspecified but deterministic.
   311  
   312  		// TODO(andy): this diverges from GMS
   313  		aLess, err := a.Less(a.format(), b)
   314  		if err != nil {
   315  			return 0, err
   316  		}
   317  		if aLess {
   318  			return -1, nil
   319  		}
   320  
   321  		bLess, err := b.Less(b.format(), a)
   322  		if err != nil {
   323  			return 0, err
   324  		}
   325  		if bLess {
   326  			return 1, nil
   327  		}
   328  
   329  		return 0, nil
   330  
   331  	default:
   332  		// a is higher precedence
   333  		return 1, nil
   334  	}
   335  }
   336  
   337  func compareJSONString(a String, b Value) (int, error) {
   338  	switch b := b.(type) {
   339  	case
   340  		Bool,
   341  		List,
   342  		Map:
   343  		// a is lower precedence
   344  		return -1, nil
   345  
   346  	case String:
   347  		return strings.Compare(string(a), string(b)), nil
   348  
   349  	default:
   350  		// a is higher precedence
   351  		return 1, nil
   352  	}
   353  }
   354  
   355  func compareJSONNumber(a Float, b Value) (int, error) {
   356  	switch b := b.(type) {
   357  	case
   358  		Bool,
   359  		List,
   360  		Map,
   361  		String:
   362  		// a is lower precedence
   363  		return -1, nil
   364  
   365  	case Float:
   366  		if a > b {
   367  			return 1, nil
   368  		} else if a < b {
   369  			return -1, nil
   370  		}
   371  		return 0, nil
   372  
   373  	default:
   374  		// a is higher precedence
   375  		return 1, nil
   376  	}
   377  }