LINSERT (BEFORE|AFTER) */
| 281 | |
| 282 | /* LINSERT <key> (BEFORE|AFTER) <pivot> <element> */ |
| 283 | void linsertCommand(client *c) { |
| 284 | int where; |
| 285 | robj *subject; |
| 286 | listTypeIterator *iter; |
| 287 | listTypeEntry entry; |
| 288 | int inserted = 0; |
| 289 | |
| 290 | if (strcasecmp(c->argv[2]->ptr,"after") == 0) { |
| 291 | where = LIST_TAIL; |
| 292 | } else if (strcasecmp(c->argv[2]->ptr,"before") == 0) { |
| 293 | where = LIST_HEAD; |
| 294 | } else { |
| 295 | addReplyErrorObject(c,shared.syntaxerr); |
| 296 | return; |
| 297 | } |
| 298 | |
| 299 | if (sdslen(c->argv[4]->ptr) > LIST_MAX_ITEM_SIZE) { |
| 300 | addReplyError(c, "Element too large"); |
| 301 | return; |
| 302 | } |
| 303 | |
| 304 | if ((subject = lookupKeyWriteOrReply(c,c->argv[1],shared.czero)) == NULL || |
| 305 | checkType(c,subject,OBJ_LIST)) return; |
| 306 | |
| 307 | /* Seek pivot from head to tail */ |
| 308 | iter = listTypeInitIterator(subject,0,LIST_TAIL); |
| 309 | while (listTypeNext(iter,&entry)) { |
| 310 | if (listTypeEqual(&entry,c->argv[3])) { |
| 311 | listTypeInsert(&entry,c->argv[4],where); |
| 312 | inserted = 1; |
| 313 | break; |
| 314 | } |
| 315 | } |
| 316 | listTypeReleaseIterator(iter); |
| 317 | |
| 318 | if (inserted) { |
| 319 | signalModifiedKey(c,c->db,c->argv[1]); |
| 320 | notifyKeyspaceEvent(NOTIFY_LIST,"linsert", |
| 321 | c->argv[1],c->db->id); |
| 322 | server.dirty++; |
| 323 | } else { |
| 324 | /* Notify client of a failed insert */ |
| 325 | addReplyLongLong(c,-1); |
| 326 | return; |
| 327 | } |
| 328 | |
| 329 | addReplyLongLong(c,listTypeLength(subject)); |
| 330 | } |
| 331 | |
| 332 | /* LLEN <key> */ |
| 333 | void llenCommand(client *c) { |
nothing calls this directly
no test coverage detected