// // $Id$ // // // Sphinx UDF function example // // Linux // gcc -fPIC -shared -o udfexample.so udfexample.c // CREATE FUNCTION sequence RETURNS INT SONAME 'udfexample.so'; // CREATE FUNCTION strtoint RETURNS INT SONAME 'udfexample.so'; // CREATE FUNCTION avgmva RETURNS FLOAT SONAME 'udfexample.so'; // // Windows // cl /MTd /LD udfexample.c // CREATE FUNCTION sequence RETURNS INT SONAME 'udfexample.dll'; // CREATE FUNCTION strtoint RETURNS INT SONAME 'udfexample.dll'; // CREATE FUNCTION avgmva RETURNS FLOAT SONAME 'udfexample.dll'; // #include "sphinxudf.h" #include #include #include #ifdef _MSC_VER #define snprintf _snprintf #define DLLEXPORT __declspec(dllexport) #else #define DLLEXPORT #endif /// UDF initialization /// gets called on every query, when query begins /// args are filled with values for a particular query DLLEXPORT int sequence_init ( SPH_UDF_INIT * init, SPH_UDF_ARGS * args, char * error_message ) { // check argument count if ( args->arg_count > 1 ) { snprintf ( error_message, SPH_UDF_ERROR_LEN, "SEQUENCE() takes either 0 or 1 arguments" ); return 1; } // check argument type if ( args->arg_count && args->arg_types[0]!=SPH_UDF_TYPE_UINT32 ) { snprintf ( error_message, SPH_UDF_ERROR_LEN, "SEQUENCE() requires 1st argument to be uint" ); return 1; } // allocate and init counter storage init->func_data = (void*) malloc ( sizeof(int) ); if ( !init->func_data ) { snprintf ( error_message, SPH_UDF_ERROR_LEN, "malloc() failed" ); return 1; } *(int*)init->func_data = 1; // all done return 0; } /// UDF deinitialization /// gets called on every query, when query ends DLLEXPORT void sequence_deinit ( SPH_UDF_INIT * init ) { // deallocate storage if ( init->func_data ) { free ( init->func_data ); init->func_data = NULL; } } /// UDF implementation /// gets called for every row, unless optimized away DLLEXPORT sphinx_int64_t sequence ( SPH_UDF_INIT * init, SPH_UDF_ARGS * args, char * error_flag ) { int res = (*(int*)init->func_data)++; if ( args->arg_count ) res += *(int*)args->arg_values[0]; return res; } ////////////////////////////////////////////////////////////////////////// DLLEXPORT int strtoint_init ( SPH_UDF_INIT * init, SPH_UDF_ARGS * args, char * error_message ) { if ( args->arg_count!=1 || args->arg_types[0]!=SPH_UDF_TYPE_STRING ) { snprintf ( error_message, SPH_UDF_ERROR_LEN, "STRTOINT() requires 1 string argument" ); return 1; } return 0; } DLLEXPORT sphinx_int64_t strtoint ( SPH_UDF_INIT * init, SPH_UDF_ARGS * args, char * error_flag ) { const char * s = args->arg_values[0]; int len = args->str_lengths[0], res = 0; while ( len>0 && *s>='0' && *s<='9' ) { res += *s - '0'; len--; } return res; } ////////////////////////////////////////////////////////////////////////// DLLEXPORT int avgmva_init ( SPH_UDF_INIT * init, SPH_UDF_ARGS * args, char * error_message ) { if ( args->arg_count!=1 || args->arg_types[0]!=SPH_UDF_TYPE_UINT32SET ) { snprintf ( error_message, SPH_UDF_ERROR_LEN, "STRTOINT() requires 1 MVA argument" ); return 1; } return 0; } DLLEXPORT double avgmva ( SPH_UDF_INIT * init, SPH_UDF_ARGS * args, char * error_flag ) { unsigned int * mva = (unsigned int *) args->arg_values[0]; double res = 0; int i, n; if ( !mva ) return res; n = *mva++; for ( i=0; i