All files / src/resp/command/hash hset-command.ts

94.73% Statements 36/38
50% Branches 3/6
100% Functions 2/2
94.59% Lines 35/37

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 1041x   1x   1x 1x 1x                               1x 8x   8x   8x   8x   8x     2x         2x         2x 2x 2x       2x 2x 2x       2x         2x 2x       2x 2x       2x 6x 6x 6x 6x 6x 6x       6x   2x                   2x             2x      
import { Logger } from "../../../logger";
import { IRequest } from "../../../server/request";
import { DataType } from "../../data/data-type";
import { Database } from "../../data/database";
import { DatabaseValue } from "../../data/database-value";
import { RedisToken } from "../../protocol/redis-token";
import { IRespCommand } from "../resp-command";
 
/**
 * Available since v2.0.0
 *
 * HSET key field value [field value ...]
 *
 * Sets field in the hash stored at key to value. If key does not exist,
 * a new key holding a hash is created. If field already exists in the hash,
 * it is overwritten.
 *
 * As of Redis 4.0.0, HSET is variadic and allows for multiple field/value pairs.
 *
 * Return value
 * Integer reply: The number of fields that were added.
 */
export class HsetCommand extends IRespCommand {
    public DbDataType = DataType.HASH
 
    public maxParams = -1
 
    public minParams = 3
 
    public name = "hset"
 
    private logger: Logger = new Logger(module.id);
 
    public execSync(request: IRequest, db: Database): RedisToken {
        this.logger.debug(
            `${request.getCommand()}.execute(%s)`,
            ...request.getParams()
        );
        // Params() must be an odd number
        Iif (request.getParams().length % 2 !== 1) {
            return RedisToken.error("ERR wrong number of arguments for hset");
        }
 
        // Get the original HASH
        this.logger.debug(`Getting database key ${request.getParam(0)}`);
        let item: DatabaseValue = db.get(request.getParam(0));
        this.logger.debug(
            `ITEM is ${item}`,
            `${item}`
        );
        let fieldsAdded: number = 0;
        Eif (!item) {
            item = new DatabaseValue(
                DataType.HASH,
                {}
            );
            this.logger.debug(
                "Instantiated new EMPTY_HASH",
                `${item}`
            );
        }
        const hash = item.getHash();
        this.logger.debug(
            "Hash is ",
            `${item}`
        );
        this.logger.debug(`Processing ${request.getParams().length} params`);
        this.logger.debug(
            `hash has ${Object.keys(hash).length} key(s)`,
            ...Object.keys(hash)
        );
        for (let index = 1; index < request.getParams().length; index += 2) {
            const field = request.getParam(index),
                value = request.getParam(index + 1);
            this.logger.debug(`Got field ${field} with value ${value}`);
            Eif (!hash[field]) {
                this.logger.debug(`Adding field ${field}`);
                ++fieldsAdded;
            } else {
                this.logger.debug(`Replacing field ${field} - was ${hash[field]}`);
            }
            hash[field] = value;
        }
        this.logger.debug(
            `NOW hash has ${Object.keys(hash).length} key(s)`,
            ...Object.keys(hash)
        );
 
        /*
         * If the has already had an expiredAt value it might have been replaced here
         * TODO: Create a special key (applicable to all DatabaseValue types) to
         * Segregate admin values from public scrutiny.  Until then ...
         */
        db.put(
            request.getParam(0),
            new DatabaseValue(
                DataType.HASH,
                hash
            )
        );
        return RedisToken.integer(fieldsAdded);
    }
}