Example #1
0
// MSET
func (m *Miniredis) cmdMset(out *redeo.Responder, r *redeo.Request) error {
	if len(r.Args) < 2 {
		setDirty(r.Client())
		return r.WrongNumberOfArgs()
	}
	if !m.handleAuth(r.Client(), out) {
		return nil
	}
	if len(r.Args)%2 != 0 {
		setDirty(r.Client())
		// non-default error message
		out.WriteErrorString("ERR wrong number of arguments for MSET")
		return nil
	}
	return withTx(m, out, r, func(out *redeo.Responder, ctx *connCtx) {
		db := m.db(ctx.selectedDB)

		for len(r.Args) > 0 {
			key := r.Args[0]
			value := r.Args[1]
			r.Args = r.Args[2:]

			db.del(key, true) // clear TTL
			db.stringSet(key, value)
		}
		out.WriteOK()
	})
}
Example #2
0
// MSETNX
func (m *Miniredis) cmdMsetnx(out *redeo.Responder, r *redeo.Request) error {
	if len(r.Args) < 2 {
		setDirty(r.Client())
		return r.WrongNumberOfArgs()
	}
	if !m.handleAuth(r.Client(), out) {
		return nil
	}
	if len(r.Args)%2 != 0 {
		setDirty(r.Client())
		// non-default error message (yes, with 'MSET').
		out.WriteErrorString("ERR wrong number of arguments for MSET")
		return nil
	}
	return withTx(m, out, r, func(out *redeo.Responder, ctx *connCtx) {
		db := m.db(ctx.selectedDB)

		keys := map[string]string{}
		existing := false
		for len(r.Args) > 0 {
			key := r.Args[0]
			value := r.Args[1]
			r.Args = r.Args[2:]
			keys[key] = value
			if _, ok := db.keys[key]; ok {
				existing = true
			}
		}

		res := 0
		if !existing {
			res = 1
			for k, v := range keys {
				// Nothing to delete. That's the whole point.
				db.stringSet(k, v)
			}
		}
		out.WriteInt(res)
	})
}
Example #3
0
// SET
func (m *Miniredis) cmdSet(out *redeo.Responder, r *redeo.Request) error {
	if len(r.Args) < 2 {
		setDirty(r.Client())
		return r.WrongNumberOfArgs()
	}
	if !m.handleAuth(r.Client(), out) {
		return nil
	}

	var (
		nx     = false // set iff not exists
		xx     = false // set iff exists
		expire = 0     // For seconds and milliseconds.
	)

	key := r.Args[0]
	value := r.Args[1]
	r.Args = r.Args[2:]
	for len(r.Args) > 0 {
		switch strings.ToUpper(r.Args[0]) {
		case "NX":
			nx = true
			r.Args = r.Args[1:]
			continue
		case "XX":
			xx = true
			r.Args = r.Args[1:]
			continue
		case "EX", "PX":
			if len(r.Args) < 2 {
				setDirty(r.Client())
				out.WriteErrorString(msgInvalidInt)
				return nil
			}
			var err error
			expire, err = strconv.Atoi(r.Args[1])
			if err != nil {
				setDirty(r.Client())
				out.WriteErrorString(msgInvalidInt)
				return nil
			}
			r.Args = r.Args[2:]
			continue
		default:
			setDirty(r.Client())
			out.WriteErrorString(msgSyntaxError)
			return nil
		}
	}

	return withTx(m, out, r, func(out *redeo.Responder, ctx *connCtx) {
		db := m.db(ctx.selectedDB)

		if nx {
			if db.exists(key) {
				out.WriteNil()
				return
			}
		}
		if xx {
			if !db.exists(key) {
				out.WriteNil()
				return
			}
		}

		db.del(key, true) // be sure to remove existing values of other type keys.
		// a vanilla SET clears the expire
		db.stringSet(key, value)
		if expire != 0 {
			db.expire[key] = expire
		}
		out.WriteOK()
	})
}