aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralex <[email protected]>2026-07-06 19:21:44 +0200
committeralex <[email protected]>2026-07-06 19:21:44 +0200
commit291a6c9044723fcbcce18a3cd12509d5fdac4702 (patch)
tree6c21f5e00a53667010e3eb556fdd882fac4e52ab
parent316b443addb7ec55e27f571ef489f2c19afb3a82 (diff)
downloadredis-clone-291a6c9044723fcbcce18a3cd12509d5fdac4702.tar.xz
redis-clone-291a6c9044723fcbcce18a3cd12509d5fdac4702.zip
added hash support
-rw-r--r--handlers.go91
-rw-r--r--main.go3
-rw-r--r--redisDB.go8
3 files changed, 102 insertions, 0 deletions
diff --git a/handlers.go b/handlers.go
index 244d332..a6ae6ef 100644
--- a/handlers.go
+++ b/handlers.go
@@ -396,4 +396,95 @@ func handleExpire(conn net.Conn, args []string){
item.ExpiresAt = &expiry
db.data[key] = item
conn.Write(serializeRESP(1))
+}
+
+func handleHset(conn net.Conn, args []string){
+
+ if len(args) < 4 || (len(args)-2)%2 != 0 {
+ err := errors.New("wrong number of arguments for 'HSET'")
+ conn.Write(serializeRESP(err))
+ return
+ }
+ key := args[1]
+ db.mu.Lock()
+ defer db.mu.Unlock()
+
+ item, exists := db.data[key]
+
+ var hash map[string]string
+
+ if exists {
+ var ok bool
+ hash, ok = item.Value.(map[string]string)
+ if !ok {
+ conn.Write(serializeRESP(errors.New("WRONGTYPE Operation against a key holding the wrong kind of value")))
+ return
+ }
+ } else {
+ hash = make(map[string]string)
+ }
+ count := 0
+ for i := 2; i < len(args); i += 2 {
+ hash[args[i]] = args[i+1]
+ count += 1
+ }
+ db.data[key] = Item{Value: hash}
+ conn.Write(serializeRESP(count))
+}
+
+func handleHget(conn net.Conn, args []string) {
+ if len(args) != 3 {
+ conn.Write(serializeRESP(errors.New("ERR wrong number of arguments for 'HGET'")))
+ return
+ }
+
+ key := args[1]
+ field := args[2]
+
+ db.mu.Lock()
+ defer db.mu.Unlock()
+
+ item, exists := db.data[key]
+ if !exists {
+ conn.Write(serializeRESP(nil))
+ return
+ }
+
+ hash, ok := item.Value.(map[string]string)
+ if !ok {
+ conn.Write(serializeRESP(errors.New("WRONGTYPE Operation against a key holding the wrong kind of value")))
+ return
+ }
+
+ val, found := hash[field]
+ if !found {
+ conn.Write(serializeRESP(nil))
+ return
+ }
+
+ conn.Write(serializeRESP(val))
+}
+
+func handleHgetall(conn net.Conn, args []string){
+ if len(args) != 2 {
+ conn.Write(serializeRESP(errors.New("ERR wrong number of arguments for 'HGETALL'")))
+ return
+ }
+ key := args[1]
+
+ db.mu.Lock()
+ defer db.mu.Unlock()
+
+ item, exists := db.data[key]
+ if !exists {
+ conn.Write(serializeRESP(nil))
+ return
+ }
+
+ hash, ok := item.Value.(map[string]string)
+ if !ok {
+ conn.Write(serializeRESP(errors.New("WRONGTYPE Operation against a key holding the wrong kind of value")))
+ return
+ }
+ conn.Write(serializeRESP(hash))
} \ No newline at end of file
diff --git a/main.go b/main.go
index ade1b76..a20db6a 100644
--- a/main.go
+++ b/main.go
@@ -29,6 +29,9 @@ var commandRegistry = map[string]handlerFunc{
"LPOP": handleLpop,
"RPOP": handleRpop,
"EXPIRE": handleExpire,
+ "HSET": handleHset,
+ "HGET": handleHget,
+ "HGETALL": handleHgetall,
}
func main() {
diff --git a/redisDB.go b/redisDB.go
index 9138971..74a7de6 100644
--- a/redisDB.go
+++ b/redisDB.go
@@ -36,6 +36,14 @@ func serializeRESP(v any) []byte {
result = append(result, serializeRESP(val[i])...)
}
return result
+ case map[string]string:
+ size := len(val)
+ result := []byte(fmt.Sprintf("*%d\r\n", size*2))
+ for key, value := range val {
+ result = append(result, serializeRESP(key)...)
+ result = append(result, serializeRESP(value)...)
+ }
+ return result
case SimpleString:
simpleStr := fmt.Sprintf("+%s\r\n", val)
return []byte(simpleStr)