All files / src/resp/command/key keys-command.ts

40% Statements 8/20
0% Branches 0/4
33.33% Functions 1/3
42.1% Lines 8/19

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 761x       1x 1x                                                             1x 4x   4x   4x   4x                                                                
import { Logger } from "../../../logger";
import { IRequest } from "../../../server/request";
import { Database } from "../../data/database";
import { AbstractRedisToken } from "../../protocol/abstract-redis-token";
import { RedisToken } from "../../protocol/redis-token";
import { IRespCommand } from "../resp-command";
 
/**
 * Available since 1.0.0.
 *
 * KEYS pattern
 *
 * Returns all keys matching pattern.
 *
 * While the time complexity for this operation is O(N), the constant times are fairly low.
 * For example, Redis running on an entry level laptop can scan a 1 million key database in
 * 40 milliseconds.
 *
 * Warning: consider KEYS as a command that should only be used in production environments
 * with extreme care. It may ruin performance when it is executed against large databases.
 * This command is intended for debugging and special operations, such as changing your
 * keyspace layout. Don't use KEYS in your regular application code. If you're looking for
 * a way to find keys in a subset of your keyspace, consider using SCAN or sets.
 *
 * Supported glob-style patterns:
 *
 * - h?llo matches hello, hallo and hxllo
 * - h*llo matches hllo and heeeello
 * - h[ae]llo matches hello and hallo, but not hillo
 * - h[^e]llo matches hallo, hbllo, ... but not hello
 * - h[a-b]llo matches hallo and hbllo
 * - Use \ to escape special characters if you want to match them verbatim.
 *
 * <b>Return value</b><br>
 * Array reply: list of keys matching pattern.
 */
export class KeysCommand extends IRespCommand {
    public maxParams = 1
 
    public minParams = 1
 
    public name = "keys"
 
    private logger: Logger = new Logger(module.id);
 
    public execSync(request: IRequest, db: Database): RedisToken {
        this.logger.debug(
            `${request.getCommand()}.execute(%s)`,
            ...request.getParams()
        );
        const keys: any[] = [],
            pattern: string = request.getParam(0),
            re = new RegExp(`^${pattern.replace(
                /\?/gu,
                "."
            ).replace(
                /\*/gu,
                ".*?"
            )}$`);
        this.logger.debug(
            "Searching for keys matching pattern /%s/",
            `${re}`
        );
        for (const key of db.keys()) {
            if (re.test(key)) {
                this.logger.debug(`Accepting ${key}`);
                keys.push(RedisToken.string(key) as AbstractRedisToken<string>);
            } else {
                this.logger.debug(`Rejecting ${key}`);
            }
        }
        // Keys are sorted alphabetically in redis
        return RedisToken.array(keys.sort((a, b) => (a.getValue() < b.getValue() ? 0 : 1)));
    }
}