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

Code before:
        addReplyError(c, "numfields should be greater than 0 and match the provided number of fields");
        return;
    }

    if (convertExpireArgumentToUnixTime(c, param, basetime, unit, &when) == C_ERR)
        return;

    if (checkAlreadyExpired(when))
        set_expired = 1;

    robj *obj = lookupKeyWrite(c->db, key);

    /* Non HASH type return simple error */
    if (checkType(c, obj, OBJ_HASH)) {
        return;
    }

    bool has_volatile_fields = hashTypeHasVolatileFields(obj);

    /* From this point we would return array reply */
    addReplyArrayLen(c, num_fields);

    for (i = 0; i < num_fields; i++) {
        expiryModificationResult result = EXPIRATION_MODIFICATION_NOT_EXIST;
        /* If the flags included the GT flag, we cannot delete the entries since existing entries
         * MUST have expiration time bigger than a past time.*/
        if (set_expired && !(flag & EXPIRE_GT)) {
            /* In case the expiration time is past, we have no items to apply this change. */
            if (obj && hashTypeDelete(obj, objectGetVal(c->argv[fields_index + i]))) {
                /* In case we are expiring all the elements prepare a new argv since we are going to delete all the expired fields. */
                if (new_argv == NULL) {
                    new_argv = zmalloc(sizeof(robj *) * (num_fields + 3));
                    new_argv[new_argc++] = shared.hdel;
                    incrRefCount(shared.hdel);
                    new_argv[new_argc++] = c->argv[1];
                    incrRefCount(c->argv[1]);
                }
                /* In case we deleted the field, add it to the new hdel command vector. */
                new_argv[new_argc++] = c->argv[fields_index + i];
                incrRefCount(c->argv[fields_index + i]);
                result = EXPIRATION_MODIFICATION_EXPIRE_ASAP;
                /* we treat this case exactly as active expiration. */
                server.stat_expiredfields++;
                expired++;
            }
        } else {
            result = hashTypeSetExpire(obj, objectGetVal(c->argv[fields_index + i]), when, flag);
            if (result == EXPIRATION_MODIFICATION_SUCCESSFUL) updated++;
        }
        addReplyLongLong(c, result);
    }

Review comment (suggestion):
```suggestion
         * MUST have expiration time bigger than a past time. */
```

Code after:
        addReplyError(c, "numfields should be greater than 0 and match the provided number of fields");
        return;
    }

    if (convertExpireArgumentToUnixTime(c, param, basetime, unit, &when) == C_ERR)
        return;

    if (checkAlreadyExpired(when))
        set_expired = 1;

    robj *obj = lookupKeyWrite(c->db, key);

    /* Non HASH type return simple error */
    if (checkType(c, obj, OBJ_HASH)) {
        return;
    }

    bool has_volatile_fields = hashTypeHasVolatileFields(obj);

    /* From this point we would return array reply */
    addReplyArrayLen(c, num_fields);

    for (i = 0; i < num_fields; i++) {
        expiryModificationResult result = EXPIRATION_MODIFICATION_NOT_EXIST;
        /* If the flags included the GT flag, we cannot delete the entries since existing entries
         * MUST have expiration time bigger than a past time. */
        if (set_expired && !(flag & EXPIRE_GT)) {
            if (obj && hashTypeDelete(obj, objectGetVal(c->argv[fields_index + i]))) {
                /* In case we are expiring all the elements prepare a new argv since we are going to delete all the expired fields. */
                if (new_argv == NULL) {
                    new_argv = zmalloc(sizeof(robj *) * (num_fields + 3));
                    new_argv[new_argc++] = shared.hdel;
                    incrRefCount(shared.hdel);
                    new_argv[new_argc++] = c->argv[1];
                    incrRefCount(c->argv[1]);
                }
                /* In case we deleted the field, add it to the new hdel command vector. */
                new_argv[new_argc++] = c->argv[fields_index + i];
                incrRefCount(c->argv[fields_index + i]);
                result = EXPIRATION_MODIFICATION_EXPIRE_ASAP;
                /* we treat this case exactly as active expiration. */
                server.stat_expiredfields++;
                expired++;
            }
        } else {
            result = hashTypeSetExpire(obj, objectGetVal(c->argv[fields_index + i]), when, flag);
            if (result == EXPIRATION_MODIFICATION_SUCCESSFUL) updated++;
        }
        addReplyLongLong(c, result);
    }