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

Code before:
	}

	if err := assertEncoding(obj.TypeEncoding, OBJ_ENCODING_QREF); err != nil {
		return Encode(err, false)
	}

	q := obj.Value.(*QueueRef)
	return Encode(q.Iterate(int(num)), false)
}

// evalSTACKREFPEEK peeks into the STACKREF and returns 5 elements without popping them
// returns the array of resp encoded values as the response.
// if the key does not exist, then we return an empty array
func evalSTACKREFPEEK(args []string) []byte {
	var num int64 = 5
	var err error

	if len(args) == 0 {
		return Encode(errors.New("ERR invalid number of arguments for `STACKREFPEEK` command"), false)
	}

	if len(args) == 2 {
		num, err = strconv.ParseInt(args[1], 10, 32)
		if err != nil || num <= 0 || num > 100 {
			return Encode(errors.New("ERR number of elements to peek should be a positive number less than 100"), false)
		}
	}

	obj := Get(args[0])
	if obj == nil {
		return RESP_EMPTY_ARRAY
	}

	if err := assertType(obj.TypeEncoding, OBJ_TYPE_BYTELIST); err != nil {
		return Encode(err, false)
	}

	if err := assertEncoding(obj.TypeEncoding, OBJ_ENCODING_STACKREF); err != nil {
		return Encode(err, false)
	}

	s := obj.Value.(*StackRef)
	return Encode(s.Iterate(int(num)), false)
}

// evalQWATCH adds the specified key to the watch list for the caller client.
// Every time a key in the watch list is modified, the client will be sent a response
// containing the new value of the key along with the operation that was performed on it.
// Contains only one argument, the key to be watched.
func evalQWATCH(args []string, c *Client) []byte {
	if len(args) != 1 {

Review comment (suggestion):
nit: we could use errors.New() instead of fmt.Errorf().

There's not much difference, but since there are no custom args for this string we probably don't need fmt.Errorf

Code after:
	if len(args) != 1 {
		return Encode(errors.New("ERR invalid number of arguments for `QWATCH` command (expected 1)"), false)
	}

	// Parse and get the selection from the query.
	query, error := ParseQuery( /*sql=*/ args[0])

	if error != nil {
		return Encode(error, false)
	}

	AddWatcher(query, c.Fd)

	return RESP_OK
}

// evalCommand evaluates COMMAND <subcommand> command based on subcommand
// COUNT: return total count of commands in Dice.
func evalCommand(args []string) []byte {
	if len(args) == 0 {
		return Encode(errors.New("(error) ERR wrong number of arguments for 'command' command"), false)
	}
	subcommand := strings.ToUpper(args[0])
	switch subcommand {
	case "COUNT":
		return evalCommandCount(nil)
	default:
		return Encode(fmt.Errorf("ERR unknown subcommand '%s'. Try COMMAND HELP", subcommand), false)
	}
}

// evalCommandCount returns an number of commands supported by DiceDB
func evalCommandCount(args []string) []byte {
	return Encode(diceCommandsCount, false)
}

func executeCommand(cmd *RedisCmd, c *Client) []byte {
	diceCmd, ok := diceCmds[cmd.Cmd]
	if !ok {
		return Encode(fmt.Errorf("ERR unknown command '%s', with args beginning with: %s", cmd.Cmd, strings.Join(cmd.Args, " ")), false)
	}

	if diceCmd.Name == "SUBSCRIBE" || diceCmd.Name == "QWATCH" {
		return evalQWATCH(cmd.Args, c)
	}
	if diceCmd.Name == "MULTI" {
		c.TxnBegin()
		return diceCmd.Eval(cmd.Args)
	}
	if diceCmd.Name == "EXEC" {
		if !c.isTxn {