Exemplo n.º 1
0
char *oph_predicate2(UDF_INIT * initid, UDF_ARGS * args, char *result, unsigned long *length, char *is_null, char *error)
{
	oph_string measure;
	char *buffer;
	char **names;
	int count;
	oph_predicate2_param *param;

	int i = 0;

	if (core_set_type(&(measure), args->args[0], &(args->lengths[0]))) {
		pmesg(1, __FILE__, __LINE__, "Type not recognized\n");
		*length = 0;
		*is_null = 0;
		*error = 1;
		return NULL;
	}

	measure.content = args->args[2];
	measure.length = &(args->lengths[2]);
	measure.missingvalue = NULL;

	core_set_elemsize(&(measure));

	if (core_set_numelem(&(measure))) {
		pmesg(1, __FILE__, __LINE__, "Error on counting elements\n");
		*length = 0;
		*is_null = 0;
		*error = 1;
		return NULL;
	}

	if (!initid->ptr) {
		initid->ptr = (char *) malloc(sizeof(oph_predicate2_param));
		if (!initid->ptr) {
			pmesg(1, __FILE__, __LINE__, "Error allocating result string\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		param = (oph_predicate2_param *) initid->ptr;

		for (i = 0; i < 4; ++i)
			param->f[i] = NULL;
		param->occurrence = 0;	// ALL

		buffer = (char *) malloc(1 + args->lengths[3]);
		strncpy(buffer, args->args[3], args->lengths[3]);
		buffer[args->lengths[3]] = '\0';
		pthread_rwlock_wrlock(&lock);
		param->f[1] = evaluator_create(buffer);
		pthread_rwlock_unlock(&lock);
		free(buffer);
		if (!param->f[1]) {
			pmesg(1, __FILE__, __LINE__, "Error allocating evaluator\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		evaluator_get_variables(param->f[1], &names, &count);
		if (count > 1) {
			pmesg(1, __FILE__, __LINE__, "Too variables in expression\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		// Comparison operator
		if (core_set_comp(&param->op, args->args[4], &(args->lengths[4]))) {
			pmesg(1, __FILE__, __LINE__, "Comparison operator not recognized\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		if (args->args[5] && args->lengths[5]) {
			buffer = (char *) malloc(1 + args->lengths[5]);
			core_strncpy(buffer, args->args[5], &(args->lengths[5]));
			if (!strcasecmp(buffer, "nan"))
				sprintf(buffer, "0/0");
		} else
			buffer = strdup("0/0");
		pthread_rwlock_wrlock(&lock);
		param->f[2] = evaluator_create(buffer);
		pthread_rwlock_unlock(&lock);
		free(buffer);
		if (!param->f[2]) {
			pmesg(1, __FILE__, __LINE__, "Error allocating evaluator\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		evaluator_get_variables(param->f[2], &names, &count);
		if (count > 1) {
			pmesg(1, __FILE__, __LINE__, "Too variables in expression\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		if (args->args[6] && args->lengths[6]) {
			buffer = (char *) malloc(1 + args->lengths[6]);
			core_strncpy(buffer, args->args[6], &(args->lengths[6]));
			if (!strcasecmp(buffer, "nan"))
				sprintf(buffer, "0/0");
		} else
			buffer = strdup("0/0");
		pthread_rwlock_wrlock(&lock);
		param->f[3] = evaluator_create(buffer);
		pthread_rwlock_unlock(&lock);
		free(buffer);
		if (!param->f[3]) {
			pmesg(1, __FILE__, __LINE__, "Error allocating evaluator\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}
		evaluator_get_variables(param->f[3], &names, &count);
		if (count > 1) {
			pmesg(1, __FILE__, __LINE__, "Too variables in expression\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		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;
		}
		param->result_type = output_array.type;
		param->result_elemsize = output_array.elemsize;

		param->length = output_array.elemsize * measure.numelem;
		param->f[0] = malloc(param->length);
		if (!param->f[0]) {
			pmesg(1, __FILE__, __LINE__, "Error allocating result string\n");
			*length = 0;
			*is_null = 0;
			*error = 1;
			return NULL;
		}

		if (args->arg_count > 7) {
			buffer = (char *) malloc(1 + args->lengths[7]);
			core_strncpy(buffer, args->args[7], &(args->lengths[7]));
			if (strcasecmp(buffer, OPH_PREDICATE2_ALL_OCCURRENCE)) {
				if (!strcasecmp(buffer, OPH_PREDICATE2_FIRST_OCCURRENCE) || !strcasecmp(buffer, OPH_PREDICATE2_BEGIN_OCCURRENCE))
					param->occurrence = 1;
				else if (!strcasecmp(buffer, OPH_PREDICATE2_LAST_OCCURRENCE) || !strcasecmp(buffer, OPH_PREDICATE2_END_OCCURRENCE))
					param->occurrence = -1;
				else {
					if (args->arg_type[7] == STRING_RESULT)
						param->occurrence = (long) strtol(buffer, NULL, 10);
					else
						param->occurrence = *((long long *) args->args[7]);
					if (param->occurrence < 1) {
						free(buffer);
						pmesg(1, __FILE__, __LINE__, "Unable to read occurrence\n");
						*length = 0;
						*is_null = 0;
						*error = 1;
						return NULL;
					}
				}
			}
			free(buffer);
		}
	} else
		param = (oph_predicate2_param *) initid->ptr;

	i = core_oph_predicate2(&measure, initid->ptr);
	if (i) {
		pmesg(1, __FILE__, __LINE__, "Unable to compute result\n");
		*length = 0;
		*is_null = 0;
		*error = 1;
		return NULL;
	}
	*length = param->length;
	*error = 0;
	*is_null = 0;
	return (char *) param->f[0];

}
void oph_aggregate_stats_partial_add(UDF_INIT * initid, UDF_ARGS * args, char *is_null, char *error)
{
	if (*error != 0)
		return;
	if (args->args[2]) {
		oph_agg_stats_partial_data *dat = (oph_agg_stats_partial_data *) initid->ptr;

		/* Setting of the aggregate result */
		if (!dat->result.content) {
			//It's the first row

			// default values
			unsigned long def_mask_len = MASK_LEN;
			dat->mask.content = (char *) calloc(MASK_LEN + 1, sizeof(char));
			if (!dat->mask.content) {
				pmesg(1, __FILE__, __LINE__, "Error allocating mask content\n");
				*error = 1;
				return;
			}
			core_strncpy(dat->mask.content, DEFAULT_MASK, &def_mask_len);

			dat->mask.length = (unsigned long *) calloc(1, sizeof(unsigned long));
			if (!dat->mask.length) {
				pmesg(1, __FILE__, __LINE__, "Error allocating mask length\n");
				*error = 1;
				return;
			}
			*(dat->mask.length) = def_mask_len;

			core_set_type(&(dat->measure), NULL, 0);
			dat->measure.length = (unsigned long *) calloc(1, sizeof(unsigned long));
			if (!dat->measure.length) {
				pmesg(1, __FILE__, __LINE__, "Error allocating measure length\n");
				*error = 1;
				return;
			}
			*(dat->measure.length) = args->lengths[2];

			core_set_type(&(dat->measure), args->args[0], &(args->lengths[0]));
			if (dat->measure.type != OPH_SHORT && dat->measure.type != OPH_BYTE && dat->measure.type != OPH_INT && dat->measure.type != OPH_LONG && dat->measure.type != OPH_FLOAT
			    && dat->measure.type != OPH_DOUBLE) {
				pmesg(1, __FILE__, __LINE__, "Invalid type\n");
				*error = 1;
				return;
			}
			if (args->arg_count > 3) {
				core_strncpy(dat->mask.content, args->args[3], &(args->lengths[3]));
				*(dat->mask.length) = args->lengths[3];
			}

			if (core_set_elemsize(&(dat->measure))) {
				pmesg(1, __FILE__, __LINE__, "Error on setting measure elements size\n");
				*error = 1;
				return;
			}
			if (core_set_numelem(&(dat->measure))) {
				pmesg(1, __FILE__, __LINE__, "Error on counting measure elements\n");
				*error = 1;
				return;
			}

			core_set_type(&dat->result, args->args[1], &(args->lengths[1]));
			if (!dat->result.type) {
				pmesg(1, __FILE__, __LINE__, "Unable to recognize measures type\n");
				*error = 1;
				return;
			}
			if (core_set_elemsize(&dat->result)) {
				pmesg(1, __FILE__, __LINE__, "Unable to recognize measures type\n");
				*error = 1;
				return;
			}
			// mask processing
			int i;
			for (i = 0; i < *(dat->mask.length); i++) {
				if (dat->mask.content[i] == '1') {
					(dat->mask.numelem)++;	// count 1s
					switch (i) {
						case 0:	// mean
							dat->sum1 = 1;	// sum{x_i} needed
							break;
						case 1:	// variance
							dat->sum1 = 1;
							dat->sum2 = 1;	// sum{(x_i)^2} needed
							break;
						case 2:	// std dev
							dat->sum1 = 1;
							dat->sum2 = 1;
							break;
						case 3:	// skew
							dat->sum1 = 1;
							dat->sum2 = 1;
							dat->sum3 = 1;	// sum{(x_i)^3} needed
							break;
						case 4:	// kurtosis
							dat->sum1 = 1;
							dat->sum2 = 1;
							dat->sum3 = 1;
							dat->sum4 = 1;	// sum{(x_i)^4} needed
							break;
						case 5:	// max
							dat->max = 1;	// array with max values needed
							break;
						case 6:	// min
							dat->min = 1;	// array with min values needed
					}
				}
			}
			if (dat->mask.numelem == 0) {
				pmesg(1, __FILE__, __LINE__, "Invalid mask\n");
				*error = 1;
				return;
			}

			int size = 1;
			if (dat->sum1)
				size++;
			if (dat->sum2)
				size++;
			if (dat->sum3)
				size++;
			if (dat->sum4)
				size++;
			if (dat->max)
				size++;
			if (dat->min)
				size++;

			// output array allocation
			dat->result.numelem = size * dat->measure.numelem;	// In future use a structed type of 'size' fields
			unsigned long outlen = dat->result.numelem * dat->result.elemsize;
			dat->result.length = (unsigned long *) calloc(1, sizeof(unsigned long));
			if (!dat->result.length) {
				pmesg(1, __FILE__, __LINE__, "Error allocating result length\n");
				*error = 1;
				return;
			}
			*(dat->result.length) = outlen;
			dat->result.content = (char *) calloc(1, *(dat->result.length));
			if (!dat->result.content) {
				pmesg(1, __FILE__, __LINE__, "Error allocating output array\n");
				*error = 1;
				return;
			}
			// partial results array allocation
			dat->partials = (oph_stringPtr) calloc((size - 1), sizeof(oph_string));
			if (!dat->partials) {
				pmesg(1, __FILE__, __LINE__, "Error allocating intermediate arrays\n");
				*error = 1;
				return;
			}
			for (i = 0; i < (size - 1); i++) {
				dat->partials[i].type = dat->measure.type;
				dat->partials[i].elemsize = dat->measure.elemsize;
				dat->partials[i].numelem = dat->measure.numelem;
				dat->partials[i].length = dat->measure.length;
				dat->partials[i].content = (char *) calloc(1, *(dat->partials[i].length));
				if (!dat->partials[i].content) {
					pmesg(1, __FILE__, __LINE__, "Error allocating intermediate array\n");
					*error = 1;
					return;
				}
			}
		}

		if (!dat->count) {
			//It's the first row or the first row in the group of the GROUP BY clause

			int i = 0;
			int j;
			// copy input values
			if (dat->sum1) {
				memcpy((void *) (dat->partials[i].content), (void *) (args->args[2]), *(dat->partials[i].length));
				i++;
			}
			// copy input values squared
			if (dat->sum2) {
				switch (dat->measure.type) {
					case OPH_INT:
						{
							int val_i;
							for (j = 0; j < dat->measure.numelem; j++) {
								val_i = ((int *) (args->args[2]))[j];
								((int *) (dat->partials[i].content))[j] = val_i * val_i;
							}
							break;
						}
					case OPH_SHORT:
						{
							int val_i;
							for (j = 0; j < dat->measure.numelem; j++) {
								val_i = ((short *) (args->args[2]))[j];
								((short *) (dat->partials[i].content))[j] = val_i * val_i;
							}
							break;
						}
					case OPH_BYTE:
						{
							int val_i;
							for (j = 0; j < dat->measure.numelem; j++) {
								val_i = ((char *) (args->args[2]))[j];
								((char *) (dat->partials[i].content))[j] = val_i * val_i;
							}
							break;
						}
					case OPH_LONG:
						{
							long long val_l;
							for (j = 0; j < dat->measure.numelem; j++) {
								val_l = ((long long *) (args->args[2]))[j];
								((long long *) (dat->partials[i].content))[j] = val_l * val_l;
							}
							break;
						}
					case OPH_FLOAT:
						{
							float val_f;
							for (j = 0; j < dat->measure.numelem; j++) {
								val_f = ((float *) (args->args[2]))[j];
								((float *) (dat->partials[i].content))[j] = val_f * val_f;
							}
							break;
						}
					case OPH_DOUBLE:
						{
							double val_d;
							for (j = 0; j < dat->measure.numelem; j++) {
								val_d = ((double *) (args->args[2]))[j];
								((double *) (dat->partials[i].content))[j] = val_d * val_d;
							}
						}
					case OPH_COMPLEX_INT:
					case OPH_COMPLEX_LONG:
					case OPH_COMPLEX_FLOAT:
					case OPH_COMPLEX_DOUBLE:
					case INVALID_TYPE:
						break;
				}
				i++;
			}
			// copy input values raised to 3
			if (dat->sum3) {
				switch (dat->measure.type) {
					case OPH_INT:
						{
							int val_i;
							for (j = 0; j < dat->measure.numelem; j++) {
								val_i = ((int *) (args->args[2]))[j];
								((int *) (dat->partials[i].content))[j] = val_i * val_i * val_i;
							}
							break;
						}
					case OPH_SHORT:
						{
							short val_i;
							for (j = 0; j < dat->measure.numelem; j++) {
								val_i = ((short *) (args->args[2]))[j];
								((short *) (dat->partials[i].content))[j] = val_i * val_i * val_i;
							}
							break;
						}
					case OPH_BYTE:
						{
							char val_i;
							for (j = 0; j < dat->measure.numelem; j++) {
								val_i = ((char *) (args->args[2]))[j];
								((char *) (dat->partials[i].content))[j] = val_i * val_i * val_i;
							}
							break;
						}
					case OPH_LONG:
						{
							long long val_l;
							for (j = 0; j < dat->measure.numelem; j++) {
								val_l = ((long long *) (args->args[2]))[j];
								((long long *) (dat->partials[i].content))[j] = val_l * val_l * val_l;
							}
							break;
						}
					case OPH_FLOAT:
						{
							float val_f;
							for (j = 0; j < dat->measure.numelem; j++) {
								val_f = ((float *) (args->args[2]))[j];
								((float *) (dat->partials[i].content))[j] = val_f * val_f * val_f;
							}
							break;
						}
					case OPH_DOUBLE:
						{
							double val_d;
							for (j = 0; j < dat->measure.numelem; j++) {
								val_d = ((double *) (args->args[2]))[j];
								((double *) (dat->partials[i].content))[j] = val_d * val_d * val_d;
							}
						}
					case OPH_COMPLEX_INT:
					case OPH_COMPLEX_LONG:
					case OPH_COMPLEX_FLOAT:
					case OPH_COMPLEX_DOUBLE:
					case INVALID_TYPE:
						break;
				}
				i++;
			}
			// copy input values raised to 4
			if (dat->sum4) {
				switch (dat->measure.type) {
					case OPH_INT:
						{
							int val_i;
							for (j = 0; j < dat->measure.numelem; j++) {
								val_i = ((int *) (args->args[2]))[j];
								((int *) (dat->partials[i].content))[j] = val_i * val_i * val_i * val_i;
							}
							break;
						}
					case OPH_SHORT:
						{
							short val_i;
							for (j = 0; j < dat->measure.numelem; j++) {
								val_i = ((short *) (args->args[2]))[j];
								((short *) (dat->partials[i].content))[j] = val_i * val_i * val_i * val_i;
							}
							break;
						}
					case OPH_BYTE:
						{
							char val_i;
							for (j = 0; j < dat->measure.numelem; j++) {
								val_i = ((char *) (args->args[2]))[j];
								((char *) (dat->partials[i].content))[j] = val_i * val_i * val_i * val_i;
							}
							break;
						}
					case OPH_LONG:
						{
							long long val_l;
							for (j = 0; j < dat->measure.numelem; j++) {
								val_l = ((long long *) (args->args[2]))[j];
								((long long *) (dat->partials[i].content))[j] = val_l * val_l * val_l * val_l;
							}
							break;
						}
					case OPH_FLOAT:
						{
							float val_f;
							for (j = 0; j < dat->measure.numelem; j++) {
								val_f = ((float *) (args->args[2]))[j];
								((float *) (dat->partials[i].content))[j] = val_f * val_f * val_f * val_f;
							}
							break;
						}
					case OPH_DOUBLE:
						{
							double val_d;
							for (j = 0; j < dat->measure.numelem; j++) {
								val_d = ((double *) (args->args[2]))[j];
								((double *) (dat->partials[i].content))[j] = val_d * val_d * val_d * val_d;
							}
						}
					case OPH_COMPLEX_INT:
					case OPH_COMPLEX_LONG:
					case OPH_COMPLEX_FLOAT:
					case OPH_COMPLEX_DOUBLE:
					case INVALID_TYPE:
						break;
				}
				i++;
			}
			// copy input values
			if (dat->max) {
				memcpy(dat->partials[i].content, (void *) (args->args[2]), *(dat->partials[i].length));
				i++;
			}
			// copy input values
			if (dat->min) {
				memcpy(dat->partials[i].content, (void *) (args->args[2]), *(dat->partials[i].length));
				i++;
			}
		} else {
			// Not the first row in the group => execute next aggregation step

			dat->measure.content = args->args[2];

			int i = 0;
			if (dat->sum1) {
				if (core_oph_sum_array(&(dat->measure), &(dat->partials[i]), dat->partials[i].content)) {
					pmesg(1, __FILE__, __LINE__, "Unable to compute result\n");
					*error = 1;
					return;
				}
				i++;
			}
			if (dat->sum2) {
				if (core_oph_sum2_array(&(dat->measure), &(dat->partials[i]), dat->partials[i].content)) {
					pmesg(1, __FILE__, __LINE__, "Unable to compute result\n");
					*error = 1;
					return;
				}
				i++;
			}
			if (dat->sum3) {
				if (core_oph_sum3_array(&(dat->measure), &(dat->partials[i]), dat->partials[i].content)) {
					pmesg(1, __FILE__, __LINE__, "Unable to compute result\n");
					*error = 1;
					return;
				}
				i++;
			}
			if (dat->sum4) {
				if (core_oph_sum4_array(&(dat->measure), &(dat->partials[i]), dat->partials[i].content)) {
					pmesg(1, __FILE__, __LINE__, "Unable to compute result\n");
					*error = 1;
					return;
				}
				i++;
			}
			if (dat->max) {
				if (core_oph_max_array(&(dat->measure), &(dat->partials[i]), dat->partials[i].content)) {
					pmesg(1, __FILE__, __LINE__, "Unable to compute result\n");
					*error = 1;
					return;
				}
				i++;
			}
			if (dat->min) {
				if (core_oph_min_array(&(dat->measure), &(dat->partials[i]), dat->partials[i].content)) {
					pmesg(1, __FILE__, __LINE__, "Unable to compute result\n");
					*error = 1;
					return;
				}
				i++;
			}
		}
		dat->count++;
	}
}