The zunionInterDiffGenericCommand() function is called in order to implement the * following commands: ZUNION, ZINTER, ZDIFF, ZUNIONSTORE, ZINTERSTORE, ZDIFFSTORE. * * 'numkeysIndex' parameter position of key number. for ZUNION/ZINTER/ZDIFF command, * this value is 1, for ZUNIONSTORE/ZINTERSTORE/ZDIFFSTORE command, this value is 2. * * 'op' SET_OP_INTER, SET_OP_UNION or SET_OP_DIFF. */
| 2572 | * 'op' SET_OP_INTER, SET_OP_UNION or SET_OP_DIFF. |
| 2573 | */ |
| 2574 | void zunionInterDiffGenericCommand(client *c, robj *dstkey, int numkeysIndex, int op) { |
| 2575 | int i, j; |
| 2576 | long setnum; |
| 2577 | int aggregate = REDIS_AGGR_SUM; |
| 2578 | zsetopsrc *src; |
| 2579 | zsetopval zval; |
| 2580 | sds tmp; |
| 2581 | size_t maxelelen = 0, totelelen = 0; |
| 2582 | robj *dstobj; |
| 2583 | zset *dstzset; |
| 2584 | zskiplistNode *znode; |
| 2585 | int withscores = 0; |
| 2586 | |
| 2587 | /* expect setnum input keys to be given */ |
| 2588 | if ((getLongFromObjectOrReply(c, c->argv[numkeysIndex], &setnum, NULL) != C_OK)) |
| 2589 | return; |
| 2590 | |
| 2591 | if (setnum < 1) { |
| 2592 | addReplyErrorFormat(c, |
| 2593 | "at least 1 input key is needed for %s", c->cmd->name); |
| 2594 | return; |
| 2595 | } |
| 2596 | |
| 2597 | /* test if the expected number of keys would overflow */ |
| 2598 | if (setnum > (c->argc-(numkeysIndex+1))) { |
| 2599 | addReplyErrorObject(c,shared.syntaxerr); |
| 2600 | return; |
| 2601 | } |
| 2602 | |
| 2603 | /* read keys to be used for input */ |
| 2604 | src = (zsetopsrc*)zcalloc(sizeof(zsetopsrc) * setnum); |
| 2605 | for (i = 0, j = numkeysIndex+1; i < setnum; i++, j++) { |
| 2606 | robj_roptr obj = dstkey ? |
| 2607 | lookupKeyWrite(c->db,c->argv[j]) : |
| 2608 | lookupKeyRead(c->db,c->argv[j]); |
| 2609 | if (obj != nullptr) { |
| 2610 | if (obj->type != OBJ_ZSET && obj->type != OBJ_SET) { |
| 2611 | zfree(src); |
| 2612 | addReplyErrorObject(c,shared.wrongtypeerr); |
| 2613 | return; |
| 2614 | } |
| 2615 | |
| 2616 | src[i].subject = obj.unsafe_robjcast(); |
| 2617 | src[i].type = obj->type; |
| 2618 | src[i].encoding = obj->encoding; |
| 2619 | } else { |
| 2620 | src[i].subject = NULL; |
| 2621 | } |
| 2622 | |
| 2623 | /* Default all weights to 1. */ |
| 2624 | src[i].weight = 1.0; |
| 2625 | } |
| 2626 | |
| 2627 | /* parse optional extra arguments */ |
| 2628 | if (j < c->argc) { |
| 2629 | int remaining = c->argc - j; |
| 2630 | |
| 2631 | while (remaining) { |
no test coverage detected