/* lib_mysqludf_str - string functions Copyright (C) 2007 Roland Bouman web: http://www.xcdsql.org/MySQL/UDF/ email: mysqludfs@gmail.com This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) #define DLLEXP __declspec(dllexport) #else #define DLLEXP #endif #ifdef STANDARD #include #include #include #ifdef __WIN__ typedef unsigned __int64 ulonglong; typedef __int64 longlong; #else typedef unsigned long long ulonglong; typedef long long longlong; #endif /*__WIN__*/ #else #include #include #endif #include #include #include #include #include #ifdef HAVE_DLOPEN #define LIBVERSION "lib_mysqludf_str version 0.0.1" #ifdef __cplusplus extern "C" { #endif /** * lib_mysqludf_statistics_info */ DLLEXP my_bool lib_mysqludf_str_info_init( UDF_INIT *initid , UDF_ARGS *args , char *message ); DLLEXP void lib_mysqludf_str_info_deinit( UDF_INIT *initid ); DLLEXP char* lib_mysqludf_str_info( UDF_INIT *initid , UDF_ARGS *args , char* result , unsigned long* length , char *is_null , char *error ); /** * lib_mysqludf_str_agg */ DLLEXP my_bool str_agg_init( UDF_INIT *initid , UDF_ARGS *args , char *message ); DLLEXP void str_agg_deinit( UDF_INIT *initid ); DLLEXP char* str_agg( UDF_INIT *initid , UDF_ARGS *args , char *result , unsigned long *length , char *is_null , char *error ); DLLEXP char* str_agg_reset( UDF_INIT *initid , UDF_ARGS *args , char *is_null , char *error ); DLLEXP char* str_agg_clear( UDF_INIT *initid , char *is_null , char *error ); DLLEXP char* str_agg_add( UDF_INIT *initid , UDF_ARGS *args , char *is_null , char *error ); #ifdef __cplusplus } #endif /** * lib_mysqludf_stat_info */ my_bool lib_mysqludf_str_info_init( UDF_INIT *initid , UDF_ARGS *args , char *message ){ my_bool status; if(args->arg_count!=0){ strcpy( message , "No arguments allowed (udf: lib_mysqludf_str_info)" ); status = 1; } else { status = 0; } initid->const_item = 1; return status; } void lib_mysqludf_str_info_deinit( UDF_INIT *initid ){ //intentionally empty } char* lib_mysqludf_str_info( UDF_INIT *initid , UDF_ARGS *args , char* result , unsigned long* length , char *is_null , char *error ){ strcpy(result,LIBVERSION); *length = strlen(LIBVERSION); return result; } /** * lib_mysqludf_str_agg */ typedef struct st_str_agg { unsigned long chunk_length; //the allocation unit unsigned long result_length; //the length of the contents in the buffer unsigned long result_max_length; //the length of the buffer char * result; //the buffer } STR_AGG; my_bool str_agg_init( UDF_INIT *initid , UDF_ARGS *args , char *message ){ int unsigned i; if(args->arg_count==0){ strcpy( message , "Expected one or more string arguments (udf: lib_mysqludf_str_agg)" ); return 1; } if((initid->ptr = malloc(65535))==NULL){ strcpy( message , "Could not allocate memory (udf: str_agg_init)" ); return 1; } initid->max_length = 65535 - sizeof(unsigned long) + 1; for (i=0; iarg_count; i++){ args->arg_type[i] = STRING_RESULT; } return 0; } void str_agg_deinit( UDF_INIT *initid ){ if(initid->ptr!=NULL){ free(initid->ptr); } } char* str_agg_reset( UDF_INIT *initid , UDF_ARGS *args , char *is_null , char *error ){ str_agg_clear( initid , is_null , error ); str_agg_add( initid , args , is_null , error ); return NULL; //I hope this is what should be returned... } char* str_agg_clear( UDF_INIT *initid , char *is_null , char *error ){ *initid->ptr = (char)0; unsigned long *result_length_ptr = (unsigned long*)(initid->ptr+1); *result_length_ptr = 0; return NULL; } char* str_agg_add( UDF_INIT *initid , UDF_ARGS *args , char *is_null , char *error ){ if(*initid->ptr==0){ unsigned long *result_length_ptr = (unsigned long*)(initid->ptr + 1); char * buffer = initid->ptr + 1 + sizeof(unsigned long) + *result_length_ptr; int unsigned i; unsigned long arg_length; for(i=0 ; iarg_count ; i++ ){ arg_length = args->lengths[i]; if((*result_length_ptr += arg_length)max_length){ memcpy(buffer,args->args[i],arg_length); buffer += arg_length; } else { *initid->ptr = (char)1; *result_length_ptr -= arg_length; } } } return NULL; } char* str_agg( UDF_INIT *initid , UDF_ARGS *args , char *result , unsigned long *length , char *is_null , char *error ){ *length = *((unsigned long*)(initid->ptr+1)); return initid->ptr + 1 + sizeof(unsigned long); } #endif /* HAVE_DLOPEN */