#include #include #include #include #define NAME "minacum" #define N_ARGS 3 #define ARG_IVAL 0 #define ARG_NUM 1 #define ARG_BASE 2 #define INTERVAL(ptr) ((Interval *) ptr) #define GET_ARG(n) (args->args[n] == NULL ? 0 : *((long long*) args->args[n])) extern "C" { typedef struct _Interval Interval; struct _Interval { long long num; long long sum; Interval* next; }; void free_data(UDF_INIT *initid) { Interval* ival = INTERVAL(initid->ptr); Interval* cur; while (ival != NULL) { cur = ival; ival = ival->next; free(cur); } initid->ptr = NULL; } long long minacum(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) { Interval* ival = INTERVAL(initid->ptr); if (ival == NULL) return 0; long long min; long long base = GET_ARG(ARG_BASE); if (ival->num == base) { min = ival->sum; ival = ival->next; } else min = 0; long long acum = min; while (ival != NULL) { acum += ival->sum; if (acum < min) min = acum; ival = ival->next; } return min; } void minacum_add(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) { long long num = GET_ARG(ARG_IVAL); long long amount = GET_ARG(ARG_NUM); Interval* ival = INTERVAL(initid->ptr); Interval* prev = ival; while (ival != NULL && ival->num < num) { prev = ival; ival = ival->next; } if (ival == NULL || ival->num > num) { Interval* new_ival = INTERVAL(malloc(sizeof(Interval))); new_ival->num = num; new_ival->sum = amount; new_ival->next = ival; if (prev != ival) prev->next = new_ival; else initid->ptr = (char *) new_ival; } else ival->sum += amount; } void minacum_clear(UDF_INIT *initid, char *is_null, char *error) { free_data(initid); } bool minacum_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { if (args->arg_count == N_ARGS) { args->arg_type[ARG_IVAL] = INT_RESULT; args->arg_type[ARG_NUM] = INT_RESULT; args->arg_type[ARG_BASE] = INT_RESULT; initid->maybe_null = 0; initid->const_item = 0; initid->ptr = NULL; return 0; } else { sprintf(message, "%s must have %d parameters", NAME, N_ARGS); return 1; } } void minacum_deinit(UDF_INIT *initid) { free_data(initid); } }