void oph_aggregate_operator_add(UDF_INIT * initid, UDF_ARGS * args, char *is_null, char *error) { if (*error || !args->args[2]) return; //Assume that: //1. Type of each element is the same //2. Length of each array is the same oph_string measure; oph_agg_oper_data *dat = (oph_agg_oper_data *) initid->ptr; oph_requestPtr res = (oph_requestPtr) & (dat->result); /* Setting of the aggregate result */ if (!res->measure.content) { //It's the first row core_set_type(&(res->measure), args->args[0], &(args->lengths[0])); if (args->arg_count < 4) { core_set_oper(res, NULL, 0); } else { core_set_oper(res, args->args[3], &(args->lengths[3])); } if (!res->oper) { pmesg(1, __FILE__, __LINE__, "Operator not recognized\n"); *is_null = 0; *error = 1; return; } core_set_hier(res, NULL, 0); res->measure.length = malloc(sizeof(unsigned long)); if (!res->measure.length) { pmesg(1, __FILE__, __LINE__, "Error allocating result string\n"); *is_null = 0; *error = 1; return; } *(res->measure.length) = args->lengths[2]; core_set_elemsize(&(res->measure)); if (core_set_numelem(&(res->measure))) { pmesg(1, __FILE__, __LINE__, "Error on counting elements\n"); *is_null = 0; *error = 1; return; } res->measure.content = (char *) malloc(*(res->measure.length)); if (!res->measure.content) { pmesg(1, __FILE__, __LINE__, "Error allocating result string\n"); *is_null = 0; *error = 1; return; } switch (res->oper) { case OPH_COUNT: dat->core_oph_oper = core_oph_count_array; break; case OPH_MAX: dat->core_oph_oper = core_oph_max_array; break; case OPH_MIN: dat->core_oph_oper = core_oph_min_array; break; case OPH_SUM: dat->core_oph_oper = core_oph_sum_array; break; case OPH_AVG: dat->core_oph_oper = NULL; break; default: pmesg(1, __FILE__, __LINE__, "Unable to recognize operator\n"); *is_null = 0; *error = 1; return; } oph_string output_array; core_set_type(&output_array, args->args[1], &(args->lengths[1])); if (!output_array.type) { pmesg(1, __FILE__, __LINE__, "Unable to recognize measures type\n"); *is_null = 0; *error = 1; return; } if (core_set_elemsize(&output_array)) { pmesg(1, __FILE__, __LINE__, "Unable to recognize measures type\n"); *is_null = 0; *error = 1; return; } dat->result_size = output_array.elemsize; dat->result_type = output_array.type; dat->result_length = res->measure.numelem * dat->result_size; dat->result_data = (char *) malloc(dat->result_length); if (!dat->result_data) { pmesg(1, __FILE__, __LINE__, "Error allocating result string\n"); *is_null = 0; *error = 1; return; } } if (!dat->count && (res->oper == OPH_AVG)) { dat->count = (int *) malloc(res->measure.numelem * sizeof(int)); if (!dat->count) { pmesg(1, __FILE__, __LINE__, "Error allocating result string\n"); *is_null = 0; *error = 1; return; } size_t i; for (i = 0; i < res->measure.numelem; ++i) dat->count[i] = 0; } measure.type = res->measure.type; measure.content = args->args[2]; measure.length = res->measure.length; measure.elemsize = res->measure.elemsize; measure.numelem = res->measure.numelem; double missingvalue; if ((args->arg_count > 4) && args->args[4]) { missingvalue = *((double *) (args->args[4])); measure.missingvalue = &missingvalue; } else measure.missingvalue = NULL; if (res->oper == OPH_AVG) { if (core_oph_sum_array2(&measure, dat->first ? NULL : &(res->measure), res->measure.content, dat->count)) { pmesg(1, __FILE__, __LINE__, "Unable to compute result\n"); *is_null = 0; *error = 1; return; } } else if (dat->first && (res->oper != OPH_COUNT)) { //It's the first row or the first row in the group of the GRUOP BY clause //Only perform the copy of the tuple memcpy(res->measure.content, args->args[2], *(res->measure.length)); } else if (dat->core_oph_oper(&measure, dat->first ? NULL : &(res->measure), res->measure.content)) { pmesg(1, __FILE__, __LINE__, "Unable to compute result\n"); *is_null = 0; *error = 1; return; } dat->first = 0; }
char* oph_reduce2(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error) { oph_request inp_req; long long hierarchy_set = 0; long long result_length = 0; long long block_size = 1, numelement_to_reduce, max_size = 0; int i = 0, j; unsigned long lll, olll, k; int (*core_oph_oper) (oph_stringPtr byte_array, char *res); if (args->arg_count > 5) { block_size = *((long long*)(args->args[5])); if(block_size<=0) { pmesg(1, __FILE__, __LINE__, "Wrong arguments to oph_reduce2 function\n"); *length=0; *is_null=0; *error=1; return NULL; } } core_set_type(&(inp_req.measure), args->args[0], &(args->lengths[0])); if(!inp_req.measure.type){ pmesg(1, __FILE__, __LINE__, "Unable to recognize measures type\n"); *length=0; *is_null=0; *error=1; return NULL; } if(args->arg_count < 4){ core_set_oper(&inp_req, NULL, 0); } else{ core_set_oper(&inp_req, args->args[3], &(args->lengths[3])); } if(!inp_req.oper){ pmesg(1, __FILE__, __LINE__, "Operator not recognized\n"); *length=0; *is_null=0; *error=1; return NULL; } core_set_hier(&inp_req, NULL, 0); if(!inp_req.hier){ pmesg(1, __FILE__, __LINE__, "Hierarchy not recognized\n"); *length=0; *is_null=0; *error=1; return NULL; } inp_req.measure.content = args->args[2]; inp_req.measure.length = &(args->lengths[2]); if(core_set_elemsize(&(inp_req.measure))){ pmesg(1, __FILE__, __LINE__, "Unable to recognize measures type\n"); *length=0; *is_null=0; *error=1; return NULL; } if(core_set_numelem(&(inp_req.measure))){ pmesg(1, __FILE__, __LINE__, "Error on counting elements\n"); *length=0; *is_null=0; *error=1; return NULL; } if (args->arg_count < 6) numelement_to_reduce = (long long)inp_req.measure.numelem; else { if(((long long)inp_req.measure.numelem) % block_size) { pmesg(1, __FILE__, __LINE__, "Error: 'block_size' %lld not applicable on %ld elements\n", block_size, inp_req.measure.numelem); *length=0; *is_null=0; *error=1; return NULL; } numelement_to_reduce = (long long)inp_req.measure.numelem / block_size; } if (args->arg_count > 6) max_size = *((long long*)(args->args[6])); if (!max_size) max_size = numelement_to_reduce; if((args->arg_count < 5) || !args->args[4]) hierarchy_set = (long long) (inp_req.measure.numelem); else { hierarchy_set = *((long long*)(args->args[4])); if (!hierarchy_set || (hierarchy_set>max_size)) hierarchy_set = max_size; else if ((hierarchy_set<0) || (max_size%hierarchy_set)) { pmesg(1, __FILE__, __LINE__, "Wrong parameter value 'count' %lld\n",hierarchy_set); *length=0; *is_null=0; *error=1; return NULL; } } /* Check if I can apply the hierarchy */ if(numelement_to_reduce%hierarchy_set) { pmesg(1, __FILE__, __LINE__, "Error: hierarchy_set %lld not applicable on %ld elements\n", hierarchy_set, inp_req.measure.numelem); *length=0; *is_null=0; *error=1; return NULL; } result_length = inp_req.measure.numelem/hierarchy_set; oph_type result_type = inp_req.measure.type; size_t result_size = inp_req.measure.elemsize; switch(inp_req.oper) { case OPH_COUNT: core_oph_oper = core_oph_count; break; case OPH_MAX: core_oph_oper = core_oph_max; break; case OPH_MIN: core_oph_oper = core_oph_min; break; case OPH_SUM: core_oph_oper = core_oph_sum; break; case OPH_AVG: core_oph_oper = core_oph_avg; break; case OPH_STD: core_oph_oper = core_oph_std; break; case OPH_VAR: core_oph_oper = core_oph_var; break; case OPH_CMOMENT: core_oph_oper = core_oph_cmoment; break; case OPH_ACMOMENT: core_oph_oper = core_oph_acmoment; break; case OPH_RMOMENT: core_oph_oper = core_oph_rmoment; break; case OPH_ARMOMENT: core_oph_oper = core_oph_armoment; break; case OPH_QUANTILE: core_oph_oper = core_oph_quantile; break; default: pmesg(1, __FILE__, __LINE__, "Unable to recognize operator\n"); *length=0; *is_null=0; *error=1; return NULL; } switch(inp_req.oper) { case OPH_COUNT: result_type = OPH_LONG; result_size = core_sizeof(OPH_LONG); break; case OPH_AVG: case OPH_STD: case OPH_VAR: case OPH_CMOMENT: case OPH_ACMOMENT: case OPH_RMOMENT: case OPH_ARMOMENT: case OPH_QUANTILE: if(inp_req.measure.type == OPH_BYTE || inp_req.measure.type == OPH_SHORT || inp_req.measure.type == OPH_INT) { result_type = OPH_FLOAT; result_size = core_sizeof(OPH_FLOAT); } else if(inp_req.measure.type == OPH_LONG) { result_type = OPH_DOUBLE; result_size = core_sizeof(OPH_DOUBLE); } break; default:; } oph_string output_array; core_set_type(&output_array, args->args[1], &(args->lengths[1])); if(!output_array.type){ pmesg(1, __FILE__, __LINE__, "Unable to recognize measures type\n"); *length=0; *is_null=0; *error=1; return NULL; } if(core_set_elemsize(&output_array)){ pmesg(1, __FILE__, __LINE__, "Unable to recognize measures type\n"); *length=0; *is_null=0; *error=1; return NULL; } olll = result_length*output_array.elemsize; /* Allocate the right space for the result set */ oph_reduce2_param* tmp; if(!initid->ptr) { tmp = (oph_reduce2_param*)malloc(sizeof(oph_reduce2_param)); initid->ptr = (char*)tmp; if(!initid->ptr) { pmesg(1, __FILE__, __LINE__, "Error allocating measures string\n"); *length=0; *is_null=0; *error=1; return NULL; } tmp->result = (char *)malloc(olll); if(!tmp->result) { pmesg(1, __FILE__, __LINE__, "Error allocating measures string\n"); *length=0; *is_null=0; *error=1; return NULL; } if (block_size>1) { tmp->temp = (char *)malloc(hierarchy_set*inp_req.measure.elemsize); if(!tmp->temp) { pmesg(1, __FILE__, __LINE__, "Error allocating measures string\n"); *length=0; *is_null=0; *error=1; return NULL; } } else tmp->temp = NULL; if (inp_req.oper == OPH_QUANTILE) { tmp->temp2 = (char *)malloc(*inp_req.measure.length); if(!tmp->temp2) { pmesg(1, __FILE__, __LINE__, "Error allocating measures string\n"); *length=0; *is_null=0; *error=1; return NULL; } } else tmp->temp2 = NULL; } else tmp = (oph_reduce2_param*)initid->ptr; oph_string curr_array; curr_array.type = inp_req.measure.type; curr_array.elemsize = inp_req.measure.elemsize; curr_array.numelem = hierarchy_set; curr_array.length = &lll; *curr_array.length = (unsigned long)(hierarchy_set*curr_array.elemsize); if(args->arg_count > 7) { curr_array.param = *((double*)(args->args[7])); if (curr_array.param<0) { pmesg(1, __FILE__, __LINE__, "Wrong parameter value 'order' %f\n",curr_array.param); *length=0; *is_null=0; *error=1; return NULL; } } else curr_array.param = 2.0; curr_array.extend = (void*)tmp->temp2; char temporary[result_size]; for(i=0; i < result_length; i++) { if (block_size==1) curr_array.content = inp_req.measure.content+(i*(*curr_array.length)); else { for (j=0, k=0; k<inp_req.measure.numelem; ++k) // Loop on the input array if (k%block_size + (k/(block_size*hierarchy_set))*block_size == i) { memcpy(tmp->temp+j*inp_req.measure.elemsize,inp_req.measure.content+k*inp_req.measure.elemsize,inp_req.measure.elemsize); ++j; if (j>=hierarchy_set) break; // Found all the elements to be reduced } if (k>=inp_req.measure.numelem) { pmesg(1, __FILE__, __LINE__, "Unable to find an element to be aggregated\n"); *length=0; *is_null=0; *error=1; return NULL; } curr_array.content = tmp->temp; } if(core_oph_oper(&curr_array, temporary)) { pmesg(1, __FILE__, __LINE__, "Unable to find result\n"); *length=0; *is_null=0; *error=1; return NULL; } if(core_oph_type_cast(temporary, tmp->result+i*output_array.elemsize, result_type, output_array.type)) { pmesg(1, __FILE__, __LINE__, "Unable to find result\n"); *length=0; *is_null=0; *error=1; return NULL; } pmesg(3, __FILE__, __LINE__, "RES: %f\n", *(double*)(tmp->result)); } *length = (unsigned long) (olll); *is_null=0; *error=0; return tmp->result; }
char *oph_operator(UDF_INIT * initid, UDF_ARGS * args, char *result, unsigned long *length, char *is_null, char *error) { if (*error) { *length = 0; *is_null = 0; *error = 1; return NULL; } if (*is_null || !args->lengths[2]) { *length = 0; *is_null = 1; *error = 0; return NULL; } oph_generic_param_multi *param; if (!initid->ptr) { param = (oph_generic_param_multi *) malloc(sizeof(oph_generic_param_multi)); if (!param) { pmesg(1, __FILE__, __LINE__, "Error in allocating parameters\n"); *length = 0; *is_null = 0; *error = 1; return NULL; } param->measure = NULL; param->result = NULL; param->error = 0; param->extend = NULL; initid->ptr = (char *) param; } else param = (oph_generic_param_multi *) initid->ptr; if (param->error) { *length = 0; *is_null = 0; *error = 1; return NULL; } oph_multistring *measure; if (!param->error && !param->measure) { if (core_set_oph_multistring(&measure, args->args[0], &(args->lengths[0]))) { param->error = 1; pmesg(1, __FILE__, __LINE__, "Error setting measure structure\n"); *length = 0; *is_null = 0; *error = 1; return NULL; } if (!measure->islast) { param->error = 1; pmesg(1, __FILE__, __LINE__, "Wrong number of input measure\n"); *length = 0; *is_null = 0; *error = 1; return NULL; } measure->length = args->lengths[2]; if (measure->length % measure->blocksize) { param->error = 1; pmesg(1, __FILE__, __LINE__, "Wrong input type or data corrupted\n"); *length = 0; *is_null = 0; *error = 1; return NULL; } measure->numelem = measure->length / measure->blocksize; oph_request req; if (args->arg_count < 4) core_set_oper(&req, NULL, 0); else core_set_oper(&req, args->args[3], &(args->lengths[3])); if (!req.oper) { param->error = 1; pmesg(1, __FILE__, __LINE__, "Operator not recognized\n"); *length = 0; *is_null = 0; *error = 1; return NULL; } switch (req.oper) { case OPH_COUNT: param->core_oph_oper_multi = core_oph_count_multi; break; case OPH_MAX: param->core_oph_oper_multi = core_oph_max_multi; break; case OPH_MIN: param->core_oph_oper_multi = core_oph_min_multi; break; case OPH_SUM: param->core_oph_oper_multi = core_oph_sum_multi; break; case OPH_AVG: param->core_oph_oper_multi = core_oph_avg_multi; break; case OPH_STD: param->core_oph_oper_multi = core_oph_std_multi; break; case OPH_CMOMENT: param->core_oph_oper_multi = core_oph_cmoment_multi; break; case OPH_ACMOMENT: param->core_oph_oper_multi = core_oph_acmoment_multi; break; case OPH_RMOMENT: param->core_oph_oper_multi = core_oph_rmoment_multi; break; case OPH_ARMOMENT: param->core_oph_oper_multi = core_oph_armoment_multi; break; default: param->error = 1; pmesg(1, __FILE__, __LINE__, "Unable to recognize operator\n"); *length = 0; *is_null = 0; *error = 1; return NULL; } if (args->arg_count < 5) core_set_hier(&req, NULL, 0); else core_set_hier(&req, args->args[4], &(args->lengths[4])); if (!req.hier) { param->error = 1; pmesg(1, __FILE__, __LINE__, "Hierarchy not recognized\n"); *length = 0; *is_null = 0; *error = 1; return NULL; } switch (req.hier) { case OPH_ALL: param->extend = (void *) 1; break; default: param->error = 1; pmesg(1, __FILE__, __LINE__, "Unable to recognize hierarchy\n"); *length = 0; *is_null = 0; *error = 1; return NULL; } if (args->arg_count > 5) { measure->param = *((double *) (args->args[5])); if (measure->param < 0) { param->error = 1; pmesg(1, __FILE__, __LINE__, "Wrong parameter value 'order' %f\n", measure->param); *length = 0; *is_null = 0; *error = 1; return NULL; } } else measure->param = 2.0; param->measure = measure; } else measure = param->measure; double missingvalue; if ((args->arg_count > 6) && args->args[6]) { missingvalue = *((double *) (args->args[6])); measure->missingvalue = &missingvalue; } else measure->missingvalue = NULL; measure->content = args->args[2]; oph_multistring *output; if (!param->error && !param->result) { if (core_set_oph_multistring(&output, args->args[1], &(args->lengths[1]))) { param->error = 1; pmesg(1, __FILE__, __LINE__, "Error setting measure structure\n"); *length = 0; *is_null = 0; *error = 1; return NULL; } if (output->num_measure != measure->num_measure) { param->error = 1; pmesg(1, __FILE__, __LINE__, "Wrong number of output data type\n"); *length = 0; *is_null = 0; *error = 1; return NULL; } output->numelem = param->extend ? 1 : 0; output->length = output->numelem * output->blocksize; if (!output->length) { *length = 0; *is_null = 1; *error = 0; return NULL; } output->content = (char *) malloc(output->length); if (!output->content) { param->error = 1; pmesg(1, __FILE__, __LINE__, "Error allocating measures string\n"); *length = 0; *is_null = 0; *error = 1; return NULL; } param->result = output; } else output = param->result; if (!param->error && param->core_oph_oper_multi(param->measure, param->result)) { param->error = 1; pmesg(1, __FILE__, __LINE__, "Unable to compute result\n"); *length = 0; *is_null = 0; *error = 1; return NULL; } *length = output->length; *error = 0; *is_null = 0; return (result = output->content); }