Repository: valkey-io/valkey
File: src/t_hash.c (C)

Code before:
    value += incr;
    new = sdsfromlonglong(value);
    bool has_volatile_fields = hashTypeHasVolatileFields(o);
    bool expired_overitten = false;
    hashTypeSet(o, objectGetVal(c->argv[2]), new, expiry, HASH_SET_TAKE_VALUE, &expired_overitten);
    if (has_volatile_fields != hashTypeHasVolatileFields(o)) {
        dbUpdateObjectWithVolatileItemsTracking(c->db, o);
    }
    signalModifiedKey(c, c->db, c->argv[1]);
    /* In case we overitten an expired field, we need to act as if it was just expired */
    if (expired_overitten) {
        server.stat_expiredfields++;
        notifyKeyspaceEvent(NOTIFY_HASH, "hexpired", c->argv[1], c->db->id);
    }
    notifyKeyspaceEvent(NOTIFY_HASH, "hincrby", c->argv[1], c->db->id);
    server.dirty++;
    addReplyLongLong(c, value);

    /* Always replicate HINCRBY as an HSET or HSETEX command with the final value
     * when hash has volatile item, since we do not know what will the field state be when the command reach the replica.
     * HSET is used to override the resulting value and HSETEX is used in order to maintain the expiration time on the target. */
    if (has_volatile_fields) {
        char buf[MAX_LONG_DOUBLE_CHARS];
        int len = ld2string(buf, sizeof(buf), value, LD_STR_HUMAN);
        robj *newobj;
        newobj = createRawStringObject(buf, len);
        if (expiry == EXPIRY_NONE) {
            rewriteClientCommandArgument(c, 0, shared.hset);
            rewriteClientCommandArgument(c, 3, newobj);
            decrRefCount(newobj);
        } else {
            int new_argc = 8; /* HSETEX(1) + key(2) + PXAT(3) + unix-time-milliseconds(4) + FIELDS(5) + numfields(6) + field(7) + value(8) */
            robj **new_argv = zmalloc(sizeof(robj *) * (8));
            robj *milliseconds_obj = createStringObjectFromLongLong(expiry);
            new_argv[0] = shared.hsetex;
            new_argv[1] = c->argv[1];
            incrRefCount(c->argv[1]);
            new_argv[2] = shared.pxat;
            new_argv[3] = milliseconds_obj;
            new_argv[4] = shared.fields;
            new_argv[5] = shared.integers[1];
            new_argv[6] = c->argv[2];
            incrRefCount(c->argv[2]);
            new_argv[7] = newobj;
            replaceClientCommandVector(c, new_argc, new_argv);
        }
    }
}

void hincrbyfloatCommand(client *c) {
    long double value, incr;

Review comment (suggestion):
```suggestion
        robj *newobj = createRawStringObject(buf, len);
```

Code after:
    value += incr;
    new = sdsfromlonglong(value);
    bool has_volatile_fields = hashTypeHasVolatileFields(o);
    bool expired_overwritten = false;
    hashTypeSet(o, objectGetVal(c->argv[2]), new, expiry, HASH_SET_TAKE_VALUE, &expired_overwritten);
    if (has_volatile_fields != hashTypeHasVolatileFields(o)) {
        dbUpdateObjectWithVolatileItemsTracking(c->db, o);
    }
    signalModifiedKey(c, c->db, c->argv[1]);
    /* In case we overitten an expired field, we need to act as if it was just expired */
    if (expired_overwritten) {
        server.stat_expiredfields++;
        notifyKeyspaceEvent(NOTIFY_HASH, "hexpired", c->argv[1], c->db->id);
    }
    notifyKeyspaceEvent(NOTIFY_HASH, "hincrby", c->argv[1], c->db->id);
    server.dirty++;
    addReplyLongLong(c, value);

    /* Always replicate HINCRBY as an HSET or HSETEX command with the final value
     * when hash has volatile item, since we do not know what will the field state be when the command reach the replica.
     * HSET is used to override the resulting value and HSETEX is used in order to maintain the expiration time on the target. */
    if (has_volatile_fields) {
        char buf[MAX_LONG_DOUBLE_CHARS];
        int len = ld2string(buf, sizeof(buf), value, LD_STR_HUMAN);
        robj *newobj = createRawStringObject(buf, len);
        if (expiry == EXPIRY_NONE) {
            rewriteClientCommandArgument(c, 0, shared.hset);
            rewriteClientCommandArgument(c, 3, newobj);
            decrRefCount(newobj);
        } else {
            int new_argc = 8; /* HSETEX(1) + key(2) + PXAT(3) + unix-time-milliseconds(4) + FIELDS(5) + numfields(6) + field(7) + value(8) */
            robj **new_argv = zmalloc(sizeof(robj *) * (8));
            robj *milliseconds_obj = createStringObjectFromLongLong(expiry);
            new_argv[0] = shared.hsetex;
            new_argv[1] = c->argv[1];
            incrRefCount(c->argv[1]);
            new_argv[2] = shared.pxat;
            new_argv[3] = milliseconds_obj;
            new_argv[4] = shared.fields;
            new_argv[5] = shared.integers[1];
            new_argv[6] = c->argv[2];
            incrRefCount(c->argv[2]);
            new_argv[7] = newobj;
            replaceClientCommandVector(c, new_argc, new_argv);
        }
    }
}

void hincrbyfloatCommand(client *c) {
    long double value, incr;
    long long ll;