generic.go 4.4 KB

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