/
VirusVK
/
ServerIT
Обзор
Документация
Войти
/
VirusVK
/
ServerIT
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
armdb/src/query/filter.c
272 строки
9 KB
VirusVK
upload files
13 дек 2025, 14:28
13 дек 2025, 14:28
a626524
Код
Авторство
О чём код?
#include <stdlib.h> #include <string.h> #include <ctype.h> #include "query.h" #include "models.h" /* Вспомогательные функции */ static int compare_strings(const char *str1, const char *str2) { return strcmp(str1, str2); } static int compare_strings_ci(const char *str1, const char *str2) { while (*str1 && *str2) { int diff = tolower((unsigned char)*str1) - tolower((unsigned char)*str2); if (diff != 0) return diff; str1++; str2++; } return tolower((unsigned char)*str1) - tolower((unsigned char)*str2); } static int compare_numbers(uint64_t num1, uint64_t num2) { if (num1 < num2) return -1; if (num1 > num2) return 1; return 0; } static int compare_timestamps(Timestamp ts1, Timestamp ts2) { if (ts1.seconds < ts2.seconds) return -1; if (ts1.seconds > ts2.seconds) return 1; if (ts1.nanoseconds < ts2.nanoseconds) return -1; if (ts1.nanoseconds > ts2.nanoseconds) return 1; return 0; } /* Создание запроса */ Query *create_query(ObjectType type) { Query *query = calloc(1, sizeof(Query)); if (!query) return NULL; query->object_type = type; query->filters = NULL; query->filter_count = 0; query->sort_ascending = true; query->limit = -1; // без ограничения query->offset = 0; return query; } void free_query(Query *query) { if (!query) return; if (query->filters) { for (int i = 0; i < query->filter_count; i++) { if (query->filters[i].value1) free(query->filters[i].value1); if (query->filters[i].value2) free(query->filters[i].value2); } free(query->filters); } free(query); } void add_filter(Query *query, const char *field, FilterType type, void *value1, void *value2) { if (!query || !field) return; // Увеличиваем массив фильтров Filter *new_filters = realloc(query->filters, (query->filter_count + 1) * sizeof(Filter)); if (!new_filters) return; query->filters = new_filters; // Заполняем новый фильтр Filter *filter = &query->filters[query->filter_count]; strncpy(filter->field_name, field, sizeof(filter->field_name) - 1); filter->type = type; // Копируем значения // TODO: копирование в зависимости от типа поля query->filter_count++; } void set_sorting(Query *query, const char *field, bool ascending) { if (!query || !field) return; strncpy(query->sort_field, field, sizeof(query->sort_field) - 1); query->sort_ascending = ascending; } void set_pagination(Query *query, int limit, int offset) { if (!query) return; query->limit = limit; query->offset = offset; } /* Применение фильтров к записям АРМ */ static bool apply_filters_to_arm(const ArmRecord *arm, const Query *query) { if (!arm || !query) return false; for (int i = 0; i < query->filter_count; i++) { const Filter *filter = &query->filters[i]; if (strcmp(filter->field_name, "inventory_number") == 0) { const char *value = (const char *)filter->value1; switch (filter->type) { case FILTER_EQUALS: if (strcmp(arm->inventory_number, value) != 0) return false; break; case FILTER_NOT_EQUALS: if (strcmp(arm->inventory_number, value) == 0) return false; break; case FILTER_CONTAINS: if (strstr(arm->inventory_number, value) == NULL) return false; break; default: break; } } else if (strcmp(filter->field_name, "name") == 0) { const char *value = (const char *)filter->value1; switch (filter->type) { case FILTER_CONTAINS: if (strstr(arm->name, value) == NULL) return false; break; default: break; } } else if (strcmp(filter->field_name, "ip_address") == 0) { const char *value = (const char *)filter->value1; switch (filter->type) { case FILTER_EQUALS: if (strcmp(arm->ip_address, value) != 0) return false; break; default: break; } } // TODO: добавить другие поля } return true; } /* Применение фильтров к пользователям */ static bool apply_filters_to_user(const UserRecord *user, const Query *query) { if (!user || !query) return false; for (int i = 0; i < query->filter_count; i++) { const Filter *filter = &query->filters[i]; if (strcmp(filter->field_name, "username") == 0) { const char *value = (const char *)filter->value1; switch (filter->type) { case FILTER_EQUALS: if (strcmp(user->username, value) != 0) return false; break; case FILTER_CONTAINS: if (strstr(user->username, value) == NULL) return false; break; default: break; } } else if (strcmp(filter->field_name, "full_name") == 0) { const char *value = (const char *)filter->value1; switch (filter->type) { case FILTER_CONTAINS: if (strstr(user->full_name, value) == NULL) return false; break; default: break; } } // TODO: добавить другие поля } return true; } /* Выполнение запроса для АРМ (пока что просто фильтрация в памяти) */ int execute_arm_query(Database *db, Query *query, ArmRecord **results, int *count) { if (!db || !query || !results || !count) return -1; // TODO: использовать индексы для оптимизации // Получаем все записи АРМ ArmRecord *all_arms = NULL; int all_count = 0; if (arm_list_all(db, &all_arms, &all_count) != 0) { return -1; } // Применяем фильтры ArmRecord *filtered = malloc(all_count * sizeof(ArmRecord)); if (!filtered) { free(all_arms); return -1; } int filtered_count = 0; for (int i = 0; i < all_count; i++) { if (apply_filters_to_arm(&all_arms[i], query)) { filtered[filtered_count++] = all_arms[i]; } } // Применяем сортировку if (strlen(query->sort_field) > 0) { // TODO: реализовать сортировку } // Применяем пагинацию int start = query->offset; int end = (query->limit == -1) ? filtered_count : (query->offset + query->limit); if (end > filtered_count) end = filtered_count; if (start > filtered_count) start = filtered_count; *count = end - start; *results = malloc(*count * sizeof(ArmRecord)); if (!*results) { free(all_arms); free(filtered); *count = 0; return -1; } for (int i = start; i < end; i++) { (*results)[i - start] = filtered[i]; } free(all_arms); free(filtered); return 0; } /* Выполнение запроса для пользователей */ int execute_user_query(Database *db, Query *query, UserRecord **results, int *count) { if (!db || !query || !results || !count) return -1; // TODO: реализовать с использованием индексов *count = 0; *results = NULL; return 0; } /* Выполнение запроса для подразделений */ int execute_department_query(Database *db, Query *query, DepartmentRecord **results, int *count) { if (!db || !query || !results || !count) return -1; // TODO: реализовать *count = 0; *results = NULL; return 0; }