// Value handling functions #define INT(ptr) (*((long long *) ptr)) #define REAL(ptr) (*((double *) ptr)) #define min(a,b) (a < b ? a : b) typedef union { long long i; double d; char * s; } Val; typedef struct { Val val; int is_null; Item_result type; unsigned long len; int free; } Value; #define value_ptr(value) (value->is_null ? NULL : (char *) &value->val) void value_init(Value * value) { value->is_null = 1; value->free = 0; } void value_free_val(Value *value) { if (value->free) { free(value->val.s); value->free = 0; } } void value_set_null(Value *value) { value_free_val(value); value->is_null = 1; } void value_set(Value * value, UDF_ARGS *args, int arg_index, int copy) { char * arg = args->args[arg_index]; if (arg != NULL) { value->is_null = 0; value->type = args->arg_type[arg_index]; switch (value->type) { case INT_RESULT: value->val.i = INT(arg); break; case REAL_RESULT: value->val.d = REAL(arg); break; default: value->len = args->lengths[arg_index]; if (copy) { value->free = 1; value->val.s = (char *) malloc(value->len); memcpy(value->val.s, arg, value->len); } else value->val.s = arg; } } else value->is_null = 1; } void value_from_arg(Value * value, UDF_ARGS *args, int arg_index) { value->free = 0; value_set(value, args, arg_index, 0); } void value_copy_arg(Value * value, UDF_ARGS *args, int arg_index) { value_free_val(value); value_set(value, args, arg_index, 1); } int value_compare(Value *a, Value *b) { int cmp; double real_cmp; if (!a->is_null && !b->is_null && a->type == b->type) { switch (a->type) { case INT_RESULT: cmp = a->val.i - b->val.i; break; case REAL_RESULT: real_cmp = a->val.d - b->val.d; cmp = real_cmp == 0.0 ? 0 : (real_cmp > 0.0 ? 1 : -1); break; default: // STRING_RESULT & DECIMAL_RESULT cmp = strncmp(a->val.s, b->val.s, min(a->len, b->len)); if (cmp == 0) cmp = a->len - b->len; } } else cmp = b->is_null && a->is_null ? 0 : (a->is_null ? -1 : 1); return cmp; }