| 1593 | } |
| 1594 | |
| 1595 | void copyCommand(client *c) { |
| 1596 | robj *o; |
| 1597 | redisDb *src, *dst; |
| 1598 | int srcid, dbid; |
| 1599 | expireEntry *expire = nullptr; |
| 1600 | int j, replace = 0, fdelete = 0; |
| 1601 | |
| 1602 | /* Obtain source and target DB pointers |
| 1603 | * Default target DB is the same as the source DB |
| 1604 | * Parse the REPLACE option and targetDB option. */ |
| 1605 | src = c->db; |
| 1606 | dst = c->db; |
| 1607 | srcid = c->db->id; |
| 1608 | dbid = c->db->id; |
| 1609 | for (j = 3; j < c->argc; j++) { |
| 1610 | int additional = c->argc - j - 1; |
| 1611 | if (!strcasecmp(szFromObj(c->argv[j]),"replace")) { |
| 1612 | replace = 1; |
| 1613 | } else if (!strcasecmp(szFromObj(c->argv[j]), "db") && additional >= 1) { |
| 1614 | if (getIntFromObjectOrReply(c, c->argv[j+1], &dbid, NULL) != C_OK) |
| 1615 | return; |
| 1616 | |
| 1617 | if (selectDb(c, dbid) == C_ERR) { |
| 1618 | addReplyError(c,"DB index is out of range"); |
| 1619 | return; |
| 1620 | } |
| 1621 | dst = c->db; |
| 1622 | selectDb(c,srcid); /* Back to the source DB */ |
| 1623 | j++; /* Consume additional arg. */ |
| 1624 | } else { |
| 1625 | addReplyErrorObject(c,shared.syntaxerr); |
| 1626 | return; |
| 1627 | } |
| 1628 | } |
| 1629 | |
| 1630 | if ((g_pserver->cluster_enabled == 1) && (srcid != 0 || dbid != 0)) { |
| 1631 | addReplyError(c,"Copying to another database is not allowed in cluster mode"); |
| 1632 | return; |
| 1633 | } |
| 1634 | |
| 1635 | /* If the user select the same DB as |
| 1636 | * the source DB and using newkey as the same key |
| 1637 | * it is probably an error. */ |
| 1638 | robj *key = c->argv[1]; |
| 1639 | robj *newkey = c->argv[2]; |
| 1640 | if (src == dst && (sdscmp(szFromObj(key), szFromObj(newkey)) == 0)) { |
| 1641 | addReplyErrorObject(c,shared.sameobjecterr); |
| 1642 | return; |
| 1643 | } |
| 1644 | |
| 1645 | /* Check if the element exists and get a reference */ |
| 1646 | o = lookupKeyWrite(c->db, key); |
| 1647 | if (!o) { |
| 1648 | addReply(c,shared.czero); |
| 1649 | return; |
| 1650 | } |
| 1651 | expire = o->FExpires() ? &o->expire : nullptr; |
| 1652 |
nothing calls this directly
no test coverage detected