/* * User defined function for MySQL. */ #include #include #include #include #include #include #include #include using namespace boost::gregorian; using namespace std; static void udf_init(UDF_INIT *initid) { initid->maybe_null = false; /* 1 if function can return NULL */ initid->const_item = false; initid->decimals = 0; /* for real functions */ initid->max_length = 0; //initid->ptr = NULL; //initid->extension = NULL; } extern "C" my_bool CF_convert_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { udf_init (initid); initid->max_length = 26; initid->maybe_null = true; if (args->arg_count != 5){ strcpy(message,"Wrong argument count to CF_convert, expect 5"); return 1; }else if (args->arg_type[0] != STRING_RESULT || args->arg_type[1] != INT_RESULT || args->arg_type[2] != INT_RESULT || args->arg_type[4] != INT_RESULT){ strcpy(message,"Wrong arguments type to CF_convert, expect \"type\",number,number, string or number, number"); return 1; } return false; } extern "C" void CF_convert_deinit(UDF_INIT *initid) { } extern "C" char *CF_convert( UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error) { char *ret = NULL; memset(result,0,initid->max_length); if (args->arg_count == 5){ const char *type = args->args[0]; int size = *(int*)(args->args[1]); int format = *(int*)(args->args[4]); bool is_datetime = strcasecmp(type,"datetime")==0; if (strcasecmp(type,"int")==0){ if (args->args[3] == NULL){ *error = 1; return NULL; }else{ if (size == 0) size = 10; int val = 0; if(args->arg_type[3] == STRING_RESULT){ val = atoi(args->args[3]); }else if(args->arg_type[3] == DECIMAL_RESULT){ val = atoi(args->args[3]); } size = snprintf (result,size+1,"%d",val); } }else if (strcasecmp(type,"numeric")==0 || strcasecmp(type,"float")==0){ if (args->args[3] == NULL){ *error = 1; return NULL; }else{ if (size == 0) size = 10; double val = 0; if(args->arg_type[3] == STRING_RESULT){ val = atof(args->args[3]); }else if(args->arg_type[3] == DECIMAL_RESULT){ val = atof(args->args[3]); } int size2 = *(int*)(args->args[2]); size = snprintf (result,size+1,"%*.*lf",size,size2,val); } }else if ((strcasecmp(type,"char")==0 || strcasecmp(type,"varchar")==0 || is_datetime) && args->arg_type[3] == STRING_RESULT){ if (args->args[3] == NULL){ *error = 1; return NULL; }else{ if (is_datetime) size=20; if (size == 0) size = 1; const char *val = args->args[3]; int lenval = strlen(val); if (format == 109){ if (lenval == 10 || lenval == 19){ int year = atoi(val); int month = atoi(val+5); int day = atoi(val+8); const char *hour = "12:00:00:000AM"; char tmphour[8+4+2+1]; if (lenval == 19){ hour = val+11; if (strlen(hour)==8){ int n = atoi(hour); const char *suffix = ":000AM"; if (n > 12){ suffix = ":000PM"; n -= 12; }else if (n == 0){ n = 12; } snprintf (tmphour,sizeof(tmphour),"%2d%s%s",n,hour+2,suffix); hour = tmphour; } } static const char *tbmonth[]={ "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" }; size = snprintf (result,size+1,"%s %2d %d %s",tbmonth[month-1],day,year,hour); }else{ *error = 1; size = sprintf (result,"%*.*s",size,size,"Invalid date"); } }else if (format == 101){ if (lenval == 10 || lenval == 19){ int year = atoi(val); int month = atoi(val+5); int day = atoi(val+8); size = snprintf (result,size-1,"%02d/%02d/%04d",month,day,year); }else{ *error = 1; size = sprintf (result,"%*.*s",size,size,"Invalid date"); } }else if (format == 102){ if (lenval == 10 || lenval == 19){ int year = atoi(val); int month = atoi(val+5); int day = atoi(val+8); size = snprintf (result,size-1,"%04d.%02d.%02d",year,month,day); }else{ *error = 1; size = sprintf (result,"%*.*s",size,size,"Invalid date"); } }else if (format == 103){ if (lenval == 10 || lenval == 19){ int year = atoi(val); int month = atoi(val+5); int day = atoi(val+8); size = snprintf (result,size-1,"%02d/%02d/%04d",day,month,year); }else{ *error = 1; size = sprintf (result,"%*.*s",size,size,"Invalid date"); } }else if (format == 104){ if (lenval == 10 || lenval == 19){ int year = atoi(val); int month = atoi(val+5); int day = atoi(val+8); size = snprintf (result,size-1,"%02d.%02d.%04d",day,month,year); }else{ *error = 1; size = sprintf (result,"%*.*s",size,size,"Invalid date"); } }else if (format == 105){ if (lenval == 10 || lenval == 19){ int year = atoi(val); int month = atoi(val+5); int day = atoi(val+8); size = snprintf (result,size-1,"%02d-%02d-%04d",day,month,year); }else{ *error = 1; size = sprintf (result,"%*.*s",size,size,"Invalid date"); } }else{ size = sprintf (result,"ERROR convert ??? format %d",format); *error = 1; size = 0; } } }else{ size = sprintf (result,"ERROR convert ??? type %s",type); *error = 1; } *length=size; ret = result; } return ret; } extern "C" my_bool CF_textptr_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { udf_init (initid); initid->max_length = 26; return false; } extern "C" void CF_textptr_deinit(UDF_INIT *initid) { } extern "C" char *CF_textptr( UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error) { #if 0 strcpy (result,"0xabc"); *length = strlen(result); #else result[0] = 0xab; result[1] = 0xcd; *length = 2; #endif return result; } static map id2name; static map name2id; extern "C" my_bool CF_object_name_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { static bool is_init = false; if (!is_init){ #include "id2name.h" is_init = true; } udf_init (initid); initid->max_length = 255; initid->maybe_null = true; if (args->arg_count != 1){ strcpy(message,"Wrong arguments to CF_object_name, expect 1"); return 1; }else if (args->arg_type[0] != INT_RESULT){ strcpy(message,"Wrong arguments to CF_object_name, expect numeric"); return 1; } return false; } extern "C" void CF_object_name_deinit(UDF_INIT *initid) { } extern "C" char *CF_object_name( UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error) { char *ret = NULL; if (args->arg_count == 1 && args->args[0] != NULL){ int id = *(int*)(args->args[0]); map::iterator it = id2name.find(id); if (it != id2name.end()){ string &x = it->second; *length = x.size(); strcpy (result,x.c_str()); ret = result; } } return ret; } extern "C" my_bool CF_object_id_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { static bool is_init = false; if (!is_init){ #include "id2name.h" is_init = true; } udf_init (initid); initid->max_length = 255; initid->maybe_null = true; if (args->arg_count != 1){ strcpy(message,"Wrong arguments to CF_object_id, expect 1"); return 1; }else if (args->arg_type[0] != STRING_RESULT){ strcpy(message,"Wrong arguments to CF_object_id, expect string"); return 1; } return false; } extern "C" void CF_object_id_deinit(UDF_INIT *initid) { } static string toupper(const char *s) { string ret; while (*s != '\0'){ ret += toupper(*s); s++; } return ret; } extern "C" char *CF_object_id( UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error) { char *ret = NULL; if (args->arg_count == 1){ string sup = toupper(args->args[0]); map::iterator it = name2id.find(sup); if (it != name2id.end()){ int id = it->second; int n = sprintf (result,"%d",id); *length = n; ret = result; } } return ret; } extern "C" my_bool CF_identity_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { udf_init (initid); initid->max_length = 15; if (args->arg_count != 1){ // The identity function requires one argument, but does nothing with it. strcpy(message,"Wrong argument number to CF_identity, expect 1"); return 1; } if (initid->ptr == NULL){ initid->ptr = (char*)malloc(sizeof(int)); // This will be the counter for this session *(int*)(initid->ptr) = 1; } return false; } extern "C" void CF_identity_deinit(UDF_INIT *initid) { free (initid->ptr); } extern "C" long long CF_identity( UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) { long long ret = -1; if (args->arg_count == 1){ ret = *(int*)(initid->ptr); *(int*)(initid->ptr) = ret+1; } return ret; } extern "C" my_bool CF_datediff_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { udf_init (initid); initid->max_length = 15; initid->maybe_null = true; if (args->arg_count != 3){ strcpy(message,"Wrong argument number to CF_datediff, expect 3"); return 1; }else if (args->arg_type[0] != INT_RESULT || args->arg_type[1] != STRING_RESULT || args->arg_type[2] != STRING_RESULT){ strcpy(message,"Wrong argument types to CF_datediff, expect number,string,string"); return 1; } return false; } extern "C" void CF_datediff_deinit(UDF_INIT *initid) { } extern "C" long long CF_datediff( UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) { long long ret = 0; if (args->arg_count == 3){ int *typep = (int*)args->args[0]; const char *date1 = args->args[1]; const char *date2 = args->args[2]; if (typep == NULL || date1 == NULL || date2 == NULL){ *is_null = 1; }else if (strlen(date1)<10 || strlen(date2)<10){ *is_null = 1; }else{ int type = *typep; int year1 = atoi(date1); int month1 = atoi(date1+5); int year2 = atoi(date2); int month2 = atoi(date2+5); if (type == 0){ // day date d1(from_simple_string(date1)); date d2(from_simple_string(date2)); ret = (long long) d2.julian_day()-d1.julian_day(); }else if (type == 1){ // Week date d1(from_simple_string(date1)); date d2(from_simple_string(date2)); ret = (long long)(d2.year()*52+d2.week_number())-(d1.year()*52+d1.week_number()); }else if (type == 2){ // Month ret = (year2*12+month2)-(year1*12+month1); }else if (type == 3){ // year ret = year2-year1; }else{ *is_null = 1; } } }else{ *is_null = 1; } return ret; }