Repository: DiceDB/dice
File: core/eval.go (Go)

Code before:
// args must contain at least the key;  (path unused in this implementation)
// Returns encoded error if key is expired or it does not exist
// Returns encoded error response if incorrect number of arguments
// Returns an integer reply specifying the number of matching JSON arrays
// and objects cleared + number of matching JSON numerical values zeroed.
func evalJSONCLEAR(args []string, store *Store) []byte {
	if len(args) < 1 {
		return diceerrors.NewErrArity("JSON.CLEAR")
	}
	key := args[0]

	// Default path is root if not specified
	path := defaultRootPath
	if len(args) > 1 {
		path = args[1]
	}

	// Retrieve the object from the database
	obj := store.Get(key)
	if obj == nil {
		return diceerrors.NewErrWithMessage("could not perform this operation on a key that doesn't exist")
	}

	err := assertType(obj.TypeEncoding, ObjTypeJSON)
	if err != nil {
		return Encode(err, false)
	}
	err = assertEncoding(obj.TypeEncoding, ObjEncodingJSON)
	if err != nil {
		return Encode(err, false)
	}

	jsonData := obj.Value

	_, err = sonic.Marshal(jsonData)
	if err != nil {
		return diceerrors.NewErrWithMessage("could not serialize result")
	}

	var countClear uint64 = 0
	if len(args) == 1 || path == defaultRootPath {
		if jsonData != struct{}{} {
			// If path is root and len(args) == 1, return it instantly
			newObj := store.NewObj(struct{}{}, -1, ObjTypeJSON, ObjEncodingJSON)
			store.Put(key, newObj)
			countClear++
			return Encode(countClear, false)
		}
	}

	expr, err := jp.ParseString(path)

Review comment (bug):
To be consistent with Redis, should we return error message "Existing key has wrong Redis type"?
```
redis:6379> SET doc '{"obj":{"a":1, "b":2}, "arr":[1,2,3], "str": "foo", "bool": true, "int": 42, "float": 3.14}'
OK
redis:6379> JSON.GET doc $
(error) Existing key has wrong Redis type
```

Code after:
// args must contain at least the key;  (path unused in this implementation)
// Returns encoded error if key is expired or it does not exist
// Returns encoded error response if incorrect number of arguments
// Returns an integer reply specifying the number of matching JSON arrays
// and objects cleared + number of matching JSON numerical values zeroed.
func evalJSONCLEAR(args []string, store *Store) []byte {
	if len(args) < 1 {
		return diceerrors.NewErrArity("JSON.CLEAR")
	}
	key := args[0]

	// Default path is root if not specified
	path := defaultRootPath
	if len(args) > 1 {
		path = args[1]
	}

	// Retrieve the object from the database
	obj := store.Get(key)
	if obj == nil {
		return diceerrors.NewErrWithMessage("could not perform this operation on a key that doesn't exist")
	}

	err := assertType(obj.TypeEncoding, ObjTypeJSON)
	if err != nil {
		return diceerrors.NewErrWithMessage("Existing key has wrong Dice type")
	}
	err = assertEncoding(obj.TypeEncoding, ObjEncodingJSON)
	if err != nil {
		return diceerrors.NewErrWithMessage("Existing key has wrong Dice type")
	}

	jsonData := obj.Value

	_, err = sonic.Marshal(jsonData)
	if err != nil {
		return diceerrors.NewErrWithMessage("Existing key has wrong Dice type")
	}

	var countClear uint64 = 0
	if len(args) == 1 || path == defaultRootPath {
		if jsonData != struct{}{} {
			// If path is root and len(args) == 1, return it instantly
			newObj := store.NewObj(struct{}{}, -1, ObjTypeJSON, ObjEncodingJSON)
			store.Put(key, newObj)
			countClear++
			return Encode(countClear, false)
		}
	}

	expr, err := jp.ParseString(path)