diff --git a/src/api/queries.c b/src/api/queries.c index eb16529f..1728048f 100644 --- a/src/api/queries.c +++ b/src/api/queries.c @@ -47,7 +47,7 @@ static int add_strings_to_array(struct ftl_conn *api, cJSON *array, const char * // Loop through returned rows int counter = 0; while((rc = sqlite3_step(stmt)) == SQLITE_ROW && - (max_count < 0 || ++counter < max_count)) + (max_count < 0 || ++counter <= max_count)) JSON_COPY_STR_TO_ARRAY(array, (const char*)sqlite3_column_text(stmt, 0)); // Acceptable return codes are either @@ -77,19 +77,24 @@ int api_queries_suggestions(struct ftl_conn *api) // Get domains cJSON *domain = JSON_NEW_ARRAY(); - rc = add_strings_to_array(api, domain, "SELECT domain FROM domain_by_id", count); + log_debug(DEBUG_API, "Reading top domains from database"); + rc = add_strings_to_array(api, domain, "WITH CTE AS (SELECT COUNT(*) cnt, domain FROM query_storage GROUP BY domain ORDER BY cnt DESC)"\ + "SELECT d.domain FROM CTE JOIN domain_by_id d ON CTE.domain = d.id", count); if(rc != 0) { log_err("Cannot read domains from database"); cJSON_Delete(domain); return rc; } + log_debug(DEBUG_API, "Read %d domains from database", cJSON_GetArraySize(domain)); // Get clients, both by IP and names // We have to call DISTINCT() here as multiple IPs can map to and name and // vice versa cJSON *client_ip = JSON_NEW_ARRAY(); - rc = add_strings_to_array(api, client_ip, "SELECT DISTINCT(ip) FROM client_by_id", count); + log_debug(DEBUG_API, "Reading top client IPs from database"); + rc = add_strings_to_array(api, client_ip, "WITH CTE AS (SELECT COUNT(*) cnt, client FROM query_storage GROUP BY client ORDER BY cnt DESC)"\ + "SELECT c.ip FROM CTE JOIN client_by_id c ON CTE.client = c.id", count); if(rc != 0) { log_err("Cannot read client IPs from database"); @@ -97,8 +102,12 @@ int api_queries_suggestions(struct ftl_conn *api) cJSON_Delete(client_ip); return rc; } + log_debug(DEBUG_API, "Read %d client IPs from database", cJSON_GetArraySize(client_ip)); + cJSON *client_name = JSON_NEW_ARRAY(); - rc = add_strings_to_array(api, client_name, "SELECT DISTINCT(name) FROM client_by_id", count); + log_debug(DEBUG_API, "Reading top client names from database"); + rc = add_strings_to_array(api, client_name, "WITH CTE AS (SELECT COUNT(*) cnt, client FROM query_storage GROUP BY client ORDER BY cnt DESC)"\ + "SELECT c.name FROM CTE JOIN client_by_id c ON CTE.client = c.id WHERE c.name IS NOT NULL", count); if(rc != 0) { log_err("Cannot read client names from database"); @@ -107,10 +116,13 @@ int api_queries_suggestions(struct ftl_conn *api) cJSON_Delete(client_name); return rc; } + log_debug(DEBUG_API, "Read %d client names from database", cJSON_GetArraySize(client_name)); // Get upstreams cJSON *upstream = JSON_NEW_ARRAY(); - rc = add_strings_to_array(api, upstream, "SELECT forward FROM forward_by_id", count); + log_debug(DEBUG_API, "Reading top upstreams from database"); + rc = add_strings_to_array(api, upstream, "WITH CTE AS (SELECT COUNT(*) cnt, forward FROM query_storage GROUP BY forward ORDER BY cnt DESC)"\ + "SELECT f.forward FROM CTE JOIN forward_by_id f ON CTE.forward = f.id", count); if(rc != 0) { log_err("Cannot read forward from database"); @@ -120,6 +132,7 @@ int api_queries_suggestions(struct ftl_conn *api) cJSON_Delete(upstream); return rc; } + log_debug(DEBUG_API, "Read %d upstreams from database", cJSON_GetArraySize(upstream)); // Get types cJSON *type = JSON_NEW_ARRAY();