diff --git a/inc/lektor/database.def b/inc/lektor/database.def
new file mode 100644
index 0000000000000000000000000000000000000000..dfbdce2461e203c2f17b0bd66bbb42652d7161f7
--- /dev/null
+++ b/inc/lektor/database.def
@@ -0,0 +1,31 @@
+/* Types available in the database */
+kara_type("OP")
+kara_type("ED")
+kara_type("AMV")
+kara_type("IS")
+kara_type("LIVE")
+kara_type("CDG")
+kara_type("PV")
+kara_type("MV")
+
+/* Categories available in the database */
+kara_category("vo")
+kara_category("va")
+kara_category("amv")
+kara_category("cdg")
+kara_category("autres")
+kara_category("vocaloid")
+
+/* Languages available in the database */
+kara_language("jp")
+kara_language("fr")
+kara_language("en")
+kara_language("ru")
+kara_language("sp")
+kara_language("it")
+kara_language("ch")
+kara_language("latin")
+kara_language("multi")
+kara_language("undefined")
+
+// vi:syntax=c
diff --git a/src/main/lkt.c b/src/main/lkt.c
index f6c0987ca2c0b8398f4edb2abee19296cb914196..f5ab077b08979487218fe39e37dd100f5c56e426 100644
--- a/src/main/lkt.c
+++ b/src/main/lkt.c
@@ -24,6 +24,7 @@
 #include <stdbool.h>
 #include <stdarg.h>
 #include <limits.h>
+#include <ctype.h>
 
 #define LKT_KEY_VALUE_SEP               ": \n\t\0"
 #define fail_if(cond, msg)              { if (cond) { LOG_ERROR("LKT", "%s", msg); exit(EXIT_FAILURE); } }
@@ -66,6 +67,136 @@ lkt_valid_type(const char *type)
             STR_MATCH(type, "playlist"));
 }
 
+enum lkt_query_type {
+    LKT_QUERY_TYPE_ERROR = 0,
+    LKT_QUERY_TYPE_ID,
+    LKT_QUERY_TYPE_LANG,
+    LKT_QUERY_TYPE_AUTHOR,
+    LKT_QUERY_TYPE_CAT,
+    LKT_QUERY_TYPE_TYPE,
+    LKT_QUERY_TYPE_PLAYLIST,
+    LKT_QUERY_TYPE_QUERY,
+};
+
+static inline int
+__string_is_lower(const char *str)
+{
+    while (*str != '\0') {
+        if (!islower(*str))
+            return 1;
+    }
+    return 0;
+}
+
+static inline int
+__string_is_upper(const char *str)
+{
+    while (*str != '\0') {
+        if (!isupper(*str))
+            return 1;
+    }
+    return 0;
+}
+
+static inline void
+__concat_strings(char *const res, size_t len, const char **tab, size_t count)
+{
+    size_t i;
+    for (i = 0; i < count - 1; ++i) {
+        strncat(res, tab[i], len - 1);
+        strncat(res, " ", len - 1);
+    }
+    strncat(res, tab[i], len - 1);
+}
+
+__attribute__((unused)) static int
+lkt_get_query_type(struct cmd_args *args, enum lkt_query_type *type,
+                   char *const regex, size_t regex_len)
+{
+    if (args->argc == 0) {
+        LOG_ERROR("LKT", "Invalid empty query");
+        *type = LKT_QUERY_TYPE_ERROR;
+        return 1;
+    }
+
+    /* id, type, lang, category */
+    if (args->argc == 1) {
+        /* Type ?== id */
+        long id = 0;
+        errno = 0;
+        id = strtol(args->argv[0], NULL, 10);
+        if (id != 0 && errno == 0) {
+            *type = LKT_QUERY_TYPE_ID;
+            safe_snprintf(regex, regex_len, "%ld", id);
+            return 0;
+        }
+
+        /* Type ?== type */
+        else if (__string_is_upper(args->argv[0])) {
+#define kara_category(unused)
+#define kara_language(unused)
+#define kara_type(tp)                                       \
+if (STR_MATCH(tp, args->argv[0])) {                         \
+    *type = LKT_QUERY_TYPE_TYPE;                            \
+    safe_snprintf(regex, regex_len, "%s", args->argv[0]);   \
+    return 0;                                               \
+}
+#include <lektor/database.def>
+#undef kara_category
+#undef kara_language
+#undef kara_type
+        }
+
+        /* Type ?== category OR Type ?== lang */
+        else if (__string_is_lower(args->argv[0])) {
+#define kara_type(unused)
+#define kara_category(ct)                                   \
+if (STR_MATCH(ct, args->argv[0])) {                         \
+    *type = LKT_QUERY_TYPE_CAT;                             \
+    safe_snprintf(regex, regex_len, "%s", args->argv[0]);   \
+    return 0;                                               \
+}
+#define kara_language(lg)                                   \
+if (STR_MATCH(lg, args->argv[0])) {                         \
+    *type = LKT_QUERY_TYPE_LANG;                            \
+    safe_snprintf(regex, regex_len, "%s", args->argv[0]);   \
+    return 0;                                               \
+}
+#include <lektor/database.def>
+#undef kara_category
+#undef kara_language
+#undef kara_type
+        }
+    }
+
+    memset(regex, 0, regex_len * sizeof(char));
+
+    /* author, playlist/plt */
+    if (args->argc >= 2) {
+        /* Type ?== author */
+        if (STR_MATCH("author", args->argv[0])) {
+            *type = LKT_QUERY_TYPE_AUTHOR;
+            __concat_strings(regex, regex_len, args->argv + 1, args->argc - 1);
+        }
+
+        /* Type ?== playlist */
+        else if (STR_MATCH("plt", args->argv[0]) || STR_MATCH("playlist", args->argv[0])) {
+            *type = LKT_QUERY_TYPE_PLAYLIST;
+            __concat_strings(regex, regex_len, args->argv + 1, args->argc - 1);
+        }
+
+        return 0;
+    }
+
+    /* If 'query' is specified, skip it */
+    int index = STR_MATCH("query", args->argv[0]) ? 1 : 0;
+    strncat(regex, "%", regex_len - 1);
+    __concat_strings(regex, regex_len, args->argv + index, args->argc - index);
+    strncat(regex, "%", regex_len - 1);
+    *type = LKT_QUERY_TYPE_QUERY;
+    return 0;
+}
+
 static int
 read_socket(FILE *sock, char *buff, size_t max_len)
 {
@@ -1133,10 +1264,9 @@ main(int argc, const char **argv)
 {
     __log_level = ERROR;
     executable_name = "lkt";
-    assert(NULL != setlocale(LC_ALL, "en_US.UTF-8"));   /* BECAUSE! */
-    if (signal(SIGPIPE, sigpipe__)) {
-        // LOG_ERROR("SYS", "%s", "Failed to install handler for SIGPIPE signal");
-    }
+    assert(NULL != setlocale(LC_ALL, "en_US.UTF-8")); /* BECAUSE! */
+    if (signal(SIGPIPE, sigpipe__))
+        LOG_ERROR("SYS", "Failed to install handler for SIGPIPE signal");
 
     args_t args = {
         .host = "localhost",