cmd_generic.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // Author: simon (ynwdlxm@163.com)
  2. // Date: 2025/9/16 16:56
  3. // Desc:
  4. package database
  5. import (
  6. "github.com/runningwater/go-redis/interface/resp"
  7. "github.com/runningwater/go-redis/lib/utils"
  8. "github.com/runningwater/go-redis/lib/wildcard"
  9. "github.com/runningwater/go-redis/resp/reply"
  10. )
  11. // 语法:
  12. //
  13. // DEL key [key ...]
  14. //
  15. // 返回:
  16. //
  17. // Integer reply: the number of keys that were removed.
  18. func execDel(db *DB, args [][]byte) resp.Reply {
  19. keys := make([]string, len(args))
  20. for i, v := range args {
  21. keys[i] = string(v)
  22. }
  23. deleted := db.Removes(keys...)
  24. if deleted > 0 {
  25. db.addAof(utils.ToCmdLine2("DEL", args...))
  26. }
  27. return reply.NewIntReply(int64(deleted))
  28. }
  29. // 语法:
  30. //
  31. // EXISTS key [key ...]
  32. //
  33. // 返回:
  34. //
  35. // Integer reply: the number of keys that exists.
  36. func execExists(db *DB, args [][]byte) resp.Reply {
  37. result := int64(0)
  38. for _, key := range args {
  39. if _, exists := db.GetEntity(string(key)); exists {
  40. result++
  41. }
  42. }
  43. return reply.NewIntReply(result)
  44. }
  45. // 语法:
  46. //
  47. // FLUSHDB [ASYNC | SYNC]
  48. //
  49. // 返回:
  50. //
  51. // Simple string reply: OK.
  52. func execFlushDb(db *DB, args [][]byte) resp.Reply {
  53. db.Flush()
  54. db.addAof(utils.ToCmdLine2("FLUSHDB", args...))
  55. return reply.NewOkReply()
  56. }
  57. // 语法:
  58. //
  59. // KEYS pattern
  60. //
  61. // Supported glob-style patterns:
  62. //
  63. // h?llo matches hello, hallo and hxllo
  64. // h*llo matches hllo and heeeello
  65. // h[ae]llo matches hello and hallo, but not hillo
  66. // h[^e]llo matches hallo, hbllo, ... but not hello
  67. // h[a-b]llo matches hallo and hbllo
  68. //
  69. // Use \ to escape special characters if you want to match them verbatim.
  70. //
  71. // 返回:
  72. //
  73. // Array reply: a list of keys matching pattern.
  74. func execKeys(db *DB, args [][]byte) resp.Reply {
  75. pattern := string(args[0])
  76. compilePattern := wildcard.CompilePattern(pattern)
  77. result := make([][]byte, 0)
  78. db.data.ForEach(func(key string, value any) bool {
  79. if compilePattern.IsMatch(key) {
  80. result = append(result, []byte(key))
  81. }
  82. return true
  83. })
  84. return reply.NewMultiBulkReply(result)
  85. }
  86. // 语法:
  87. //
  88. // TYPE key
  89. //
  90. // 返回:
  91. //
  92. // Returns the string representation of the type of the value stored at key.
  93. // The different types that can be returned are: string, list, set, zset, hash, stream, and vectorset.
  94. func execType(db *DB, args [][]byte) resp.Reply {
  95. key := string(args[0])
  96. entity, exists := db.GetEntity(key)
  97. if !exists {
  98. return reply.NewStatusReply("none")
  99. }
  100. switch entity.Data.(type) {
  101. case []byte:
  102. return reply.NewStatusReply("string")
  103. // : TODO 类型判断: 只实现了 string 类型, 其他类型未实现
  104. default:
  105. return reply.NewUnknownErrReply("don't know the type")
  106. }
  107. }
  108. // 语法:
  109. //
  110. // RENAME key newkey
  111. //
  112. // 返回:
  113. //
  114. // returns an error when key does not exist.
  115. // If newkey already exists it is overwritten,
  116. // when this happens RENAME executes an implicit DEL operation,
  117. // so if the deleted key contains a very big value it may cause
  118. // high latency even if RENAME itself is usually a constant-time operation.
  119. func execRename(db *DB, args [][]byte) resp.Reply {
  120. src := string(args[0])
  121. dest := string(args[1])
  122. entity, exists := db.GetEntity(src)
  123. if !exists {
  124. return reply.NewErrReply("no such key")
  125. }
  126. db.PutEntity(dest, entity)
  127. db.Remove(src)
  128. db.addAof(utils.ToCmdLine2("RENAME", args...))
  129. return reply.NewOkReply()
  130. }
  131. // 语法:
  132. //
  133. // RENAMENX key newkey
  134. //
  135. // 返回:
  136. //
  137. // Integer reply: 1 if key was renamed to newkey.
  138. // Integer reply: 0 if newkey already exists.
  139. func execRenamenx(db *DB, args [][]byte) resp.Reply {
  140. src := string(args[0])
  141. dest := string(args[1])
  142. _, ok := db.GetEntity(dest)
  143. if ok {
  144. return reply.NewIntReply(0)
  145. }
  146. entity, exists := db.GetEntity(src)
  147. if !exists {
  148. return reply.NewErrReply("no such key")
  149. }
  150. db.PutEntity(dest, entity)
  151. db.Remove(src)
  152. db.addAof(utils.ToCmdLine2("RENAMENX", args...))
  153. return reply.NewIntReply(1)
  154. }
  155. // init 将键相关命令注册到命令表中
  156. // 此函数在包初始化期间自动调用
  157. func init() {
  158. // 注册 DEL 命令,至少需要 2 个参数(命令名称 + 至少 1 个键)
  159. RegisterCommand("DEL", execDel, -2)
  160. // 注册 EXISTS 命令,至少需要 2 个参数(命令名称 + 至少 1 个键)
  161. RegisterCommand("EXISTS", execExists, -2)
  162. // 注册 FLUSHDB 命令,至少需要 1 个参数(命令名称)
  163. RegisterCommand("FLUSHDB", execFlushDb, -1)
  164. // 注册 RENAME 命令,需要 2 个参数(命令名称 + 源键 + 目标键)
  165. RegisterCommand("KEYS", execKeys, 2)
  166. // 注册 TYPE 命令,需要 2 个参数(命令名称 + 键)
  167. RegisterCommand("TYPE", execType, 2)
  168. // 注册 TYPE 命令,需要 3 个参数(命令名称 + 键)
  169. RegisterCommand("RENAME", execRename, 3)
  170. // 注册 RENAMENX 命令,需要 3 个参数(命令名称 + 源键 + 目标键)
  171. RegisterCommand("RENAMENX", execRenamenx, 3)
  172. }