The SORT command is the most complex command in Redis. Warning: this code * is optimized for speed and a bit less for readability */
| 191 | /* The SORT command is the most complex command in Redis. Warning: this code |
| 192 | * is optimized for speed and a bit less for readability */ |
| 193 | void sortCommand(client *c) { |
| 194 | list *operations; |
| 195 | unsigned int outputlen = 0; |
| 196 | int desc = 0, alpha = 0; |
| 197 | long limit_start = 0, limit_count = -1, start, end, vectorlen; |
| 198 | int j, dontsort = 0; |
| 199 | int getop = 0; /* GET operation counter */ |
| 200 | int int_conversion_error = 0; |
| 201 | int syntax_error = 0; |
| 202 | robj *sortval, *sortby = NULL, *storekey = NULL; |
| 203 | redisSortObject *vector; /* Resulting vector to sort */ |
| 204 | |
| 205 | /* Create a list of operations to perform for every sorted element. |
| 206 | * Operations can be GET */ |
| 207 | operations = listCreate(); |
| 208 | listSetFreeMethod(operations,zfree); |
| 209 | j = 2; /* options start at argv[2] */ |
| 210 | |
| 211 | /* The SORT command has an SQL-alike syntax, parse it */ |
| 212 | while(j < c->argc) { |
| 213 | int leftargs = c->argc-j-1; |
| 214 | if (!strcasecmp(szFromObj(c->argv[j]),"asc")) { |
| 215 | desc = 0; |
| 216 | } else if (!strcasecmp(szFromObj(c->argv[j]),"desc")) { |
| 217 | desc = 1; |
| 218 | } else if (!strcasecmp(szFromObj(c->argv[j]),"alpha")) { |
| 219 | alpha = 1; |
| 220 | } else if (!strcasecmp(szFromObj(c->argv[j]),"limit") && leftargs >= 2) { |
| 221 | if ((getLongFromObjectOrReply(c, c->argv[j+1], &limit_start, NULL) |
| 222 | != C_OK) || |
| 223 | (getLongFromObjectOrReply(c, c->argv[j+2], &limit_count, NULL) |
| 224 | != C_OK)) |
| 225 | { |
| 226 | syntax_error++; |
| 227 | break; |
| 228 | } |
| 229 | j+=2; |
| 230 | } else if (!strcasecmp(szFromObj(c->argv[j]),"store") && leftargs >= 1) { |
| 231 | storekey = c->argv[j+1]; |
| 232 | j++; |
| 233 | } else if (!strcasecmp(szFromObj(c->argv[j]),"by") && leftargs >= 1) { |
| 234 | sortby = c->argv[j+1]; |
| 235 | /* If the BY pattern does not contain '*', i.e. it is constant, |
| 236 | * we don't need to sort nor to lookup the weight keys. */ |
| 237 | if (strchr(szFromObj(c->argv[j+1]),'*') == NULL) { |
| 238 | dontsort = 1; |
| 239 | } else { |
| 240 | /* If BY is specified with a real patter, we can't accept |
| 241 | * it in cluster mode. */ |
| 242 | if (g_pserver->cluster_enabled) { |
| 243 | addReplyError(c,"BY option of SORT denied in Cluster mode."); |
| 244 | syntax_error++; |
| 245 | break; |
| 246 | } |
| 247 | } |
| 248 | j++; |
| 249 | } else if (!strcasecmp(szFromObj(c->argv[j]),"get") && leftargs >= 1) { |
| 250 | if (g_pserver->cluster_enabled) { |
nothing calls this directly
no test coverage detected