This repository has been archived on 2024-01-15. You can view files and clone it, but cannot push or open issues or pull requests.
vn-mysql/udfs/minacum.cc

109 lines
2.2 KiB
C++

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <mysql/mysql.h>
#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);
}
}