From bd47f4f3be851c2eba9927a680d13c20b2470134 Mon Sep 17 00:00:00 2001 From: "kent@mysql.com/c-4b4072d5.010-2112-6f72651.cust.bredbandsbolaget.se" <> Date: Sat, 29 Jul 2006 04:41:50 +0200 Subject: udf_example.c, udf.test, Makefile.am: Converted "udf_example.cc" to C, avoids C++ runtime lib dependency (bug#21336) --- sql/udf_example.c | 1067 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1067 insertions(+) create mode 100644 sql/udf_example.c (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c new file mode 100644 index 00000000000..62995085599 --- /dev/null +++ b/sql/udf_example.c @@ -0,0 +1,1067 @@ +/* Copyright (C) 2002 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* +** example file of UDF (user definable functions) that are dynamicly loaded +** into the standard mysqld core. +** +** The functions name, type and shared library is saved in the new system +** table 'func'. To be able to create new functions one must have write +** privilege for the database 'mysql'. If one starts MySQL with +** --skip-grant, then UDF initialization will also be skipped. +** +** Syntax for the new commands are: +** create function returns {string|real|integer} +** soname +** drop function +** +** Each defined function may have a xxxx_init function and a xxxx_deinit +** function. The init function should alloc memory for the function +** and tell the main function about the max length of the result +** (for string functions), number of decimals (for double functions) and +** if the result may be a null value. +** +** If a function sets the 'error' argument to 1 the function will not be +** called anymore and mysqld will return NULL for all calls to this copy +** of the function. +** +** All strings arguments to functions are given as string pointer + length +** to allow handling of binary data. +** Remember that all functions must be thread safe. This means that one is not +** allowed to alloc any global or static variables that changes! +** If one needs memory one should alloc this in the init function and free +** this on the __deinit function. +** +** Note that the init and __deinit functions are only called once per +** SQL statement while the value function may be called many times +** +** Function 'metaphon' returns a metaphon string of the string argument. +** This is something like a soundex string, but it's more tuned for English. +** +** Function 'myfunc_double' returns summary of codes of all letters +** of arguments divided by summary length of all its arguments. +** +** Function 'myfunc_int' returns summary length of all its arguments. +** +** Function 'sequence' returns an sequence starting from a certain number. +** +** Function 'myfunc_argument_name' returns name of argument. +** +** On the end is a couple of functions that converts hostnames to ip and +** vice versa. +** +** A dynamicly loadable file should be compiled shared. +** (something like: gcc -shared -o my_func.so myfunc.cc). +** You can easily get all switches right by doing: +** cd sql ; make udf_example.o +** Take the compile line that make writes, remove the '-c' near the end of +** the line and add -shared -o udf_example.so to the end of the compile line. +** The resulting library (udf_example.so) should be copied to some dir +** searched by ld. (/usr/lib ?) +** If you are using gcc, then you should be able to create the udf_example.so +** by simply doing 'make udf_example.so'. +** +** After the library is made one must notify mysqld about the new +** functions with the commands: +** +** CREATE FUNCTION metaphon RETURNS STRING SONAME "udf_example.so"; +** CREATE FUNCTION myfunc_double RETURNS REAL SONAME "udf_example.so"; +** CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "udf_example.so"; +** CREATE FUNCTION sequence RETURNS INTEGER SONAME "udf_example.so"; +** CREATE FUNCTION lookup RETURNS STRING SONAME "udf_example.so"; +** CREATE FUNCTION reverse_lookup RETURNS STRING SONAME "udf_example.so"; +** CREATE AGGREGATE FUNCTION avgcost RETURNS REAL SONAME "udf_example.so"; +** CREATE FUNCTION myfunc_argument_name RETURNS STRING SONAME "udf_example.so"; +** +** After this the functions will work exactly like native MySQL functions. +** Functions should be created only once. +** +** The functions can be deleted by: +** +** DROP FUNCTION metaphon; +** DROP FUNCTION myfunc_double; +** DROP FUNCTION myfunc_int; +** DROP FUNCTION lookup; +** DROP FUNCTION reverse_lookup; +** DROP FUNCTION avgcost; +** DROP FUNCTION myfunc_argument_name; +** +** The CREATE FUNCTION and DROP FUNCTION update the func@mysql table. All +** Active function will be reloaded on every restart of server +** (if --skip-grant-tables is not given) +** +** If you ge problems with undefined symbols when loading the shared +** library, you should verify that mysqld is compiled with the -rdynamic +** option. +** +** If you can't get AGGREGATES to work, check that you have the column +** 'type' in the mysql.func table. If not, run 'mysql_fix_privilege_tables'. +** +*/ + +#ifdef STANDARD +/* STANDARD is defined, don't use any mysql functions */ +#include +#include +#include +#ifdef __WIN__ +typedef unsigned __int64 ulonglong; /* Microsofts 64 bit types */ +typedef __int64 longlong; +#else +typedef unsigned long long ulonglong; +typedef long long longlong; +#endif /*__WIN__*/ +#else +#include +#include +#include /* To get strmov() */ +#endif +#include +#include + +static pthread_mutex_t LOCK_hostname; + +#ifdef HAVE_DLOPEN + +/* These must be right or mysqld will not find the symbol! */ + +my_bool metaphon_init(UDF_INIT *initid, UDF_ARGS *args, char *message); +void metaphon_deinit(UDF_INIT *initid); +char *metaphon(UDF_INIT *initid, UDF_ARGS *args, char *result, + unsigned long *length, char *is_null, char *error); +my_bool myfunc_double_init(UDF_INIT *, UDF_ARGS *args, char *message); +double myfunc_double(UDF_INIT *initid, UDF_ARGS *args, char *is_null, + char *error); +my_bool myfunc_int_init(UDF_INIT *initid, UDF_ARGS *args, char *message); +longlong myfunc_int(UDF_INIT *initid, UDF_ARGS *args, char *is_null, + char *error); +my_bool sequence_init(UDF_INIT *initid, UDF_ARGS *args, char *message); + void sequence_deinit(UDF_INIT *initid); +longlong sequence(UDF_INIT *initid, UDF_ARGS *args, char *is_null, + char *error); +my_bool avgcost_init( UDF_INIT* initid, UDF_ARGS* args, char* message ); +void avgcost_deinit( UDF_INIT* initid ); +void avgcost_reset( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error ); +void avgcost_clear( UDF_INIT* initid, char* is_null, char *error ); +void avgcost_add( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error ); +double avgcost( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error ); + + +/************************************************************************* +** Example of init function +** Arguments: +** initid Points to a structure that the init function should fill. +** This argument is given to all other functions. +** my_bool maybe_null 1 if function can return NULL +** Default value is 1 if any of the arguments +** is declared maybe_null. +** unsigned int decimals Number of decimals. +** Default value is max decimals in any of the +** arguments. +** unsigned int max_length Length of string result. +** The default value for integer functions is 21 +** The default value for real functions is 13+ +** default number of decimals. +** The default value for string functions is +** the longest string argument. +** char *ptr; A pointer that the function can use. +** +** args Points to a structure which contains: +** unsigned int arg_count Number of arguments +** enum Item_result *arg_type Types for each argument. +** Types are STRING_RESULT, REAL_RESULT +** and INT_RESULT. +** char **args Pointer to constant arguments. +** Contains 0 for not constant argument. +** unsigned long *lengths; max string length for each argument +** char *maybe_null Information of which arguments +** may be NULL +** +** message Error message that should be passed to the user on fail. +** The message buffer is MYSQL_ERRMSG_SIZE big, but one should +** try to keep the error message less than 80 bytes long! +** +** This function should return 1 if something goes wrong. In this case +** message should contain something usefull! +**************************************************************************/ + +#define MAXMETAPH 8 + +my_bool metaphon_init(UDF_INIT *initid, UDF_ARGS *args, char *message) +{ + if (args->arg_count != 1 || args->arg_type[0] != STRING_RESULT) + { + strcpy(message,"Wrong arguments to metaphon; Use the source"); + return 1; + } + initid->max_length=MAXMETAPH; + return 0; +} + +/**************************************************************************** +** Deinit function. This should free all resources allocated by +** this function. +** Arguments: +** initid Return value from xxxx_init +****************************************************************************/ + + +void metaphon_deinit(UDF_INIT *initid __attribute__((unused))) +{ +} + +/*************************************************************************** +** UDF string function. +** Arguments: +** initid Structure filled by xxx_init +** args The same structure as to xxx_init. This structure +** contains values for all parameters. +** Note that the functions MUST check and convert all +** to the type it wants! Null values are represented by +** a NULL pointer +** result Possible buffer to save result. At least 255 byte long. +** length Pointer to length of the above buffer. In this the function +** should save the result length +** is_null If the result is null, one should store 1 here. +** error If something goes fatally wrong one should store 1 here. +** +** This function should return a pointer to the result string. +** Normally this is 'result' but may also be an alloced string. +***************************************************************************/ + +/* Character coding array */ +static char codes[26] = { + 1,16,4,16,9,2,4,16,9,2,0,2,2,2,1,4,0,2,4,4,1,0,0,0,8,0 + /* A B C D E F G H I J K L M N O P Q R S T U V W X Y Z*/ + }; + +/*--- Macros to access character coding array -------------*/ + +#define ISVOWEL(x) (codes[(x) - 'A'] & 1) /* AEIOU */ + + /* Following letters are not changed */ +#define NOCHANGE(x) (codes[(x) - 'A'] & 2) /* FJLMNR */ + + /* These form diphthongs when preceding H */ +#define AFFECTH(x) (codes[(x) - 'A'] & 4) /* CGPST */ + + /* These make C and G soft */ +#define MAKESOFT(x) (codes[(x) - 'A'] & 8) /* EIY */ + + /* These prevent GH from becoming F */ +#define NOGHTOF(x) (codes[(x) - 'A'] & 16) /* BDH */ + + +char *metaphon(UDF_INIT *initid __attribute__((unused)), + UDF_ARGS *args, char *result, unsigned long *length, + char *is_null, char *error __attribute__((unused))) +{ + const char *word=args->args[0]; + const char *w_end; + char *org_result; + char *n, *n_start, *n_end; /* pointers to string */ + char *metaph_end; /* pointers to end of metaph */ + char ntrans[32]; /* word with uppercase letters */ + int KSflag; /* state flag for X to KS */ + + if (!word) /* Null argument */ + { + *is_null=1; + return 0; + } + w_end=word+args->lengths[0]; + org_result=result; + + /*-------------------------------------------------------- + * Copy word to internal buffer, dropping non-alphabetic + * characters and converting to uppercase. + *-------------------------------------------------------*/ + + for (n = ntrans + 1, n_end = ntrans + sizeof(ntrans)-2; + word != w_end && n < n_end; word++ ) + if ( isalpha ( *word )) + *n++ = toupper ( *word ); + + if ( n == ntrans + 1 ) /* return empty string if 0 bytes */ + { + *length=0; + return result; + } + n_end = n; /* set n_end to end of string */ + ntrans[0] = 'Z'; /* ntrans[0] should be a neutral char */ + n[0]=n[1]=0; /* pad with nulls */ + n = ntrans + 1; /* assign pointer to start */ + + /*------------------------------------------------------------ + * check for all prefixes: + * PN KN GN AE WR WH and X at start. + *----------------------------------------------------------*/ + + switch ( *n ) { + case 'P': + case 'K': + case 'G': + if ( n[1] == 'N') + *n++ = 0; + break; + case 'A': + if ( n[1] == 'E') + *n++ = 0; + break; + case 'W': + if ( n[1] == 'R' ) + *n++ = 0; + else + if ( *(n + 1) == 'H') + { + n[1] = *n; + *n++ = 0; + } + break; + case 'X': + *n = 'S'; + break; + } + + /*------------------------------------------------------------ + * Now, loop step through string, stopping at end of string + * or when the computed metaph is MAXMETAPH characters long + *----------------------------------------------------------*/ + + KSflag = 0; /* state flag for KS translation */ + + for (metaph_end = result + MAXMETAPH, n_start = n; + n < n_end && result < metaph_end; n++ ) + { + + if ( KSflag ) + { + KSflag = 0; + *result++ = *n; + } + else + { + /* drop duplicates except for CC */ + if ( *( n - 1 ) == *n && *n != 'C' ) + continue; + + /* check for F J L M N R or first letter vowel */ + if ( NOCHANGE ( *n ) || + ( n == n_start && ISVOWEL ( *n ))) + *result++ = *n; + else + switch ( *n ) { + case 'B': /* check for -MB */ + if ( n < n_end || *( n - 1 ) != 'M' ) + *result++ = *n; + break; + + case 'C': /* C = X ("sh" sound) in CH and CIA */ + /* = S in CE CI and CY */ + /* dropped in SCI SCE SCY */ + /* else K */ + if ( *( n - 1 ) != 'S' || + !MAKESOFT ( n[1])) + { + if ( n[1] == 'I' && n[2] == 'A' ) + *result++ = 'X'; + else + if ( MAKESOFT ( n[1])) + *result++ = 'S'; + else + if ( n[1] == 'H' ) + *result++ = (( n == n_start && + !ISVOWEL ( n[2])) || + *( n - 1 ) == 'S' ) ? + (char)'K' : (char)'X'; + else + *result++ = 'K'; + } + break; + + case 'D': /* J before DGE, DGI, DGY, else T */ + *result++ = + ( n[1] == 'G' && + MAKESOFT ( n[2])) ? + (char)'J' : (char)'T'; + break; + + case 'G': /* complicated, see table in text */ + if (( n[1] != 'H' || ISVOWEL ( n[2])) + && ( + n[1] != 'N' || + ( + (n + 1) < n_end && + ( + n[2] != 'E' || + *( n + 3 ) != 'D' + ) + ) + ) + && ( + *( n - 1 ) != 'D' || + !MAKESOFT ( n[1]) + ) + ) + *result++ = + ( MAKESOFT ( *( n + 1 )) && + n[2] != 'G' ) ? + (char)'J' : (char)'K'; + else + if ( n[1] == 'H' && + !NOGHTOF( *( n - 3 )) && + *( n - 4 ) != 'H') + *result++ = 'F'; + break; + + case 'H': /* H if before a vowel and not after */ + /* C, G, P, S, T */ + + if ( !AFFECTH ( *( n - 1 )) && + ( !ISVOWEL ( *( n - 1 )) || + ISVOWEL ( n[1]))) + *result++ = 'H'; + break; + + case 'K': /* K = K, except dropped after C */ + if ( *( n - 1 ) != 'C') + *result++ = 'K'; + break; + + case 'P': /* PH = F, else P = P */ + *result++ = *( n + 1 ) == 'H' + ? (char)'F' : (char)'P'; + break; + case 'Q': /* Q = K (U after Q is already gone */ + *result++ = 'K'; + break; + + case 'S': /* SH, SIO, SIA = X ("sh" sound) */ + *result++ = ( n[1] == 'H' || + ( *(n + 1) == 'I' && + ( n[2] == 'O' || + n[2] == 'A'))) ? + (char)'X' : (char)'S'; + break; + + case 'T': /* TIO, TIA = X ("sh" sound) */ + /* TH = 0, ("th" sound ) */ + if ( *( n + 1 ) == 'I' && ( n[2] == 'O' + || n[2] == 'A') ) + *result++ = 'X'; + else + if ( n[1] == 'H' ) + *result++ = '0'; + else + if ( *( n + 1) != 'C' || n[2] != 'H') + *result++ = 'T'; + break; + + case 'V': /* V = F */ + *result++ = 'F'; + break; + + case 'W': /* only exist if a vowel follows */ + case 'Y': + if ( ISVOWEL ( n[1])) + *result++ = *n; + break; + + case 'X': /* X = KS, except at start */ + if ( n == n_start ) + *result++ = 'S'; + else + { + *result++ = 'K'; /* insert K, then S */ + KSflag = 1; /* this flag will cause S to be + inserted on next pass thru loop */ + } + break; + + case 'Z': + *result++ = 'S'; + break; + } + } + } + *length= (unsigned long) (result - org_result); + return org_result; +} + + +/*************************************************************************** +** UDF double function. +** Arguments: +** initid Structure filled by xxx_init +** args The same structure as to xxx_init. This structure +** contains values for all parameters. +** Note that the functions MUST check and convert all +** to the type it wants! Null values are represented by +** a NULL pointer +** is_null If the result is null, one should store 1 here. +** error If something goes fatally wrong one should store 1 here. +** +** This function should return the result. +***************************************************************************/ + +my_bool myfunc_double_init(UDF_INIT *initid, UDF_ARGS *args, char *message) +{ + uint i; + + if (!args->arg_count) + { + strcpy(message,"myfunc_double must have at least one argument"); + return 1; + } + /* + ** As this function wants to have everything as strings, force all arguments + ** to strings. + */ + for (i=0 ; i < args->arg_count; i++) + args->arg_type[i]=STRING_RESULT; + initid->maybe_null=1; /* The result may be null */ + initid->decimals=2; /* We want 2 decimals in the result */ + initid->max_length=6; /* 3 digits + . + 2 decimals */ + return 0; +} + + +double myfunc_double(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, + char *is_null, char *error __attribute__((unused))) +{ + unsigned long val = 0; + unsigned long v = 0; + uint i, j; + + for (i = 0; i < args->arg_count; i++) + { + if (args->args[i] == NULL) + continue; + val += args->lengths[i]; + for (j=args->lengths[i] ; j-- > 0 ;) + v += args->args[i][j]; + } + if (val) + return (double) v/ (double) val; + *is_null=1; + return 0.0; +} + + +/*************************************************************************** +** UDF long long function. +** Arguments: +** initid Return value from xxxx_init +** args The same structure as to xxx_init. This structure +** contains values for all parameters. +** Note that the functions MUST check and convert all +** to the type it wants! Null values are represented by +** a NULL pointer +** is_null If the result is null, one should store 1 here. +** error If something goes fatally wrong one should store 1 here. +** +** This function should return the result as a long long +***************************************************************************/ + +/* This function returns the sum of all arguments */ + +longlong myfunc_int(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, + char *is_null __attribute__((unused)), + char *error __attribute__((unused))) +{ + longlong val = 0; + uint i; + + for (i = 0; i < args->arg_count; i++) + { + if (args->args[i] == NULL) + continue; + switch (args->arg_type[i]) { + case STRING_RESULT: /* Add string lengths */ + val += args->lengths[i]; + break; + case INT_RESULT: /* Add numbers */ + val += *((longlong*) args->args[i]); + break; + case REAL_RESULT: /* Add numers as longlong */ + val += (longlong) *((double*) args->args[i]); + break; + default: + break; + } + } + return val; +} + +/* + At least one of _init/_deinit is needed unless the server is started + with --allow_suspicious_udfs. +*/ +my_bool myfunc_int_init(UDF_INIT *initid __attribute__((unused)), + UDF_ARGS *args __attribute__((unused)), + char *message __attribute__((unused))) +{ + return 0; +} + +/* + Simple example of how to get a sequences starting from the first argument + or 1 if no arguments have been given +*/ + +my_bool sequence_init(UDF_INIT *initid, UDF_ARGS *args, char *message) +{ + if (args->arg_count > 1) + { + strmov(message,"This function takes none or 1 argument"); + return 1; + } + if (args->arg_count) + args->arg_type[0]= INT_RESULT; /* Force argument to int */ + + if (!(initid->ptr=(char*) malloc(sizeof(longlong)))) + { + strmov(message,"Couldn't allocate memory"); + return 1; + } + bzero(initid->ptr,sizeof(longlong)); + /* + Fool MySQL to think that this function is a constant + This will ensure that MySQL only evalutes the function + when the rows are sent to the client and not before any ORDER BY + clauses + */ + initid->const_item=1; + return 0; +} + +void sequence_deinit(UDF_INIT *initid) +{ + if (initid->ptr) + free(initid->ptr); +} + +longlong sequence(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, + char *is_null __attribute__((unused)), + char *error __attribute__((unused))) +{ + ulonglong val=0; + if (args->arg_count) + val= *((longlong*) args->args[0]); + return ++*((longlong*) initid->ptr) + val; +} + + +/**************************************************************************** +** Some functions that handles IP and hostname conversions +** The orignal function was from Zeev Suraski. +** +** CREATE FUNCTION lookup RETURNS STRING SONAME "udf_example.so"; +** CREATE FUNCTION reverse_lookup RETURNS STRING SONAME "udf_example.so"; +** +****************************************************************************/ + +#include +#include +#include +#include + +my_bool lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message); +void lookup_deinit(UDF_INIT *initid); +char *lookup(UDF_INIT *initid, UDF_ARGS *args, char *result, + unsigned long *length, char *null_value, char *error); +my_bool reverse_lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message); +void reverse_lookup_deinit(UDF_INIT *initid); +char *reverse_lookup(UDF_INIT *initid, UDF_ARGS *args, char *result, + unsigned long *length, char *null_value, char *error); + + +/**************************************************************************** +** lookup IP for an hostname. +** +** This code assumes that gethostbyname_r exists and inet_ntoa() is thread +** safe (As it is in Solaris) +****************************************************************************/ + + +my_bool lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message) +{ + if (args->arg_count != 1 || args->arg_type[0] != STRING_RESULT) + { + strmov(message,"Wrong arguments to lookup; Use the source"); + return 1; + } + initid->max_length=11; + initid->maybe_null=1; +#if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_SOLARIS_STYLE_GETHOST) + (void) pthread_mutex_init(&LOCK_hostname,MY_MUTEX_INIT_SLOW); +#endif + return 0; +} + +void lookup_deinit(UDF_INIT *initid __attribute__((unused))) +{ +#if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_SOLARIS_STYLE_GETHOST) + (void) pthread_mutex_destroy(&LOCK_hostname); +#endif +} + +char *lookup(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, + char *result, unsigned long *res_length, char *null_value, + char *error __attribute__((unused))) +{ + uint length; + char name_buff[256]; + struct hostent *hostent; +#if defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST) + int tmp_errno; + char hostname_buff[2048]; + struct hostent tmp_hostent; +#endif + struct in_addr in; + + if (!args->args[0] || !(length=args->lengths[0])) + { + *null_value=1; + return 0; + } + if (length >= sizeof(name_buff)) + length=sizeof(name_buff)-1; + memcpy(name_buff,args->args[0],length); + name_buff[length]=0; +#if defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST) + if (!(hostent=gethostbyname_r(name_buff,&tmp_hostent,hostname_buff, + sizeof(hostname_buff), &tmp_errno))) + { + *null_value=1; + return 0; + } +#else + VOID(pthread_mutex_lock(&LOCK_hostname)); + if (!(hostent= gethostbyname((char*) name_buff))) + { + VOID(pthread_mutex_unlock(&LOCK_hostname)); + *null_value= 1; + return 0; + } + VOID(pthread_mutex_unlock(&LOCK_hostname)); +#endif + memcpy_fixed((char*) &in,(char*) *hostent->h_addr_list, sizeof(in.s_addr)); + *res_length= (ulong) (strmov(result, inet_ntoa(in)) - result); + return result; +} + + +/**************************************************************************** +** return hostname for an IP number. +** The functions can take as arguments a string "xxx.xxx.xxx.xxx" or +** four numbers. +****************************************************************************/ + +my_bool reverse_lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message) +{ + if (args->arg_count == 1) + args->arg_type[0]= STRING_RESULT; + else if (args->arg_count == 4) + args->arg_type[0]=args->arg_type[1]=args->arg_type[2]=args->arg_type[3]= + INT_RESULT; + else + { + strmov(message, + "Wrong number of arguments to reverse_lookup; Use the source"); + return 1; + } + initid->max_length=32; + initid->maybe_null=1; +#if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_SOLARIS_STYLE_GETHOST) + (void) pthread_mutex_init(&LOCK_hostname,MY_MUTEX_INIT_SLOW); +#endif + return 0; +} + +void reverse_lookup_deinit(UDF_INIT *initid __attribute__((unused))) +{ +#if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_SOLARIS_STYLE_GETHOST) + (void) pthread_mutex_destroy(&LOCK_hostname); +#endif +} + +char *reverse_lookup(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, + char *result, unsigned long *res_length, + char *null_value, char *error __attribute__((unused))) +{ +#if defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST) + char name_buff[256]; + struct hostent tmp_hostent; +#endif + struct hostent *hp; + unsigned long taddr; + uint length; + + if (args->arg_count == 4) + { + if (!args->args[0] || !args->args[1] ||!args->args[2] ||!args->args[3]) + { + *null_value=1; + return 0; + } + sprintf(result,"%d.%d.%d.%d", + (int) *((longlong*) args->args[0]), + (int) *((longlong*) args->args[1]), + (int) *((longlong*) args->args[2]), + (int) *((longlong*) args->args[3])); + } + else + { /* string argument */ + if (!args->args[0]) /* Return NULL for NULL values */ + { + *null_value=1; + return 0; + } + length=args->lengths[0]; + if (length >= (uint) *res_length-1) + length=(uint) *res_length; + memcpy(result,args->args[0],length); + result[length]=0; + } + + taddr = inet_addr(result); + if (taddr == (unsigned long) -1L) + { + *null_value=1; + return 0; + } +#if defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST) + int tmp_errno; + if (!(hp=gethostbyaddr_r((char*) &taddr,sizeof(taddr), AF_INET, + &tmp_hostent, name_buff,sizeof(name_buff), + &tmp_errno))) + { + *null_value=1; + return 0; + } +#else + VOID(pthread_mutex_lock(&LOCK_hostname)); + if (!(hp= gethostbyaddr((char*) &taddr, sizeof(taddr), AF_INET))) + { + VOID(pthread_mutex_unlock(&LOCK_hostname)); + *null_value= 1; + return 0; + } + VOID(pthread_mutex_unlock(&LOCK_hostname)); +#endif + *res_length=(ulong) (strmov(result,hp->h_name) - result); + return result; +} + +/* +** Syntax for the new aggregate commands are: +** create aggregate function returns {string|real|integer} +** soname +** +** Syntax for avgcost: avgcost( t.quantity, t.price ) +** with t.quantity=integer, t.price=double +** (this example is provided by Andreas F. Bobak ) +*/ + + +struct avgcost_data +{ + ulonglong count; + longlong totalquantity; + double totalprice; +}; + + +/* +** Average Cost Aggregate Function. +*/ +my_bool +avgcost_init( UDF_INIT* initid, UDF_ARGS* args, char* message ) +{ + struct avgcost_data* data; + + if (args->arg_count != 2) + { + strcpy( + message, + "wrong number of arguments: AVGCOST() requires two arguments" + ); + return 1; + } + + if ((args->arg_type[0] != INT_RESULT) || (args->arg_type[1] != REAL_RESULT) ) + { + strcpy( + message, + "wrong argument type: AVGCOST() requires an INT and a REAL" + ); + return 1; + } + + /* + ** force arguments to double. + */ + /*args->arg_type[0] = REAL_RESULT; + args->arg_type[1] = REAL_RESULT;*/ + + initid->maybe_null = 0; /* The result may be null */ + initid->decimals = 4; /* We want 4 decimals in the result */ + initid->max_length = 20; /* 6 digits + . + 10 decimals */ + + if (!(data = (struct avgcost_data*) malloc(sizeof(struct avgcost_data)))) + { + strmov(message,"Couldn't allocate memory"); + return 1; + } + data->totalquantity = 0; + data->totalprice = 0.0; + + initid->ptr = (char*)data; + + return 0; +} + +void +avgcost_deinit( UDF_INIT* initid ) +{ + free(initid->ptr); +} + + +/* This is only for MySQL 4.0 compability */ +void +avgcost_reset(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* message) +{ + avgcost_clear(initid, is_null, message); + avgcost_add(initid, args, is_null, message); +} + +/* This is needed to get things to work in MySQL 4.1.1 and above */ + +void +avgcost_clear(UDF_INIT* initid, char* is_null __attribute__((unused)), + char* message __attribute__((unused))) +{ + struct avgcost_data* data = (struct avgcost_data*)initid->ptr; + data->totalprice= 0.0; + data->totalquantity= 0; + data->count= 0; +} + + +void +avgcost_add(UDF_INIT* initid, UDF_ARGS* args, + char* is_null __attribute__((unused)), + char* message __attribute__((unused))) +{ + if (args->args[0] && args->args[1]) + { + struct avgcost_data* data = (struct avgcost_data*)initid->ptr; + longlong quantity = *((longlong*)args->args[0]); + longlong newquantity = data->totalquantity + quantity; + double price = *((double*)args->args[1]); + + data->count++; + + if ( ((data->totalquantity >= 0) && (quantity < 0)) + || ((data->totalquantity < 0) && (quantity > 0)) ) + { + /* + ** passing from + to - or from - to + + */ + if ( ((quantity < 0) && (newquantity < 0)) + || ((quantity > 0) && (newquantity > 0)) ) + { + data->totalprice = price * (double)newquantity; + } + /* + ** sub q if totalq > 0 + ** add q if totalq < 0 + */ + else + { + price = data->totalprice / (double)data->totalquantity; + data->totalprice = price * (double)newquantity; + } + data->totalquantity = newquantity; + } + else + { + data->totalquantity += quantity; + data->totalprice += price * (double)quantity; + } + + if (data->totalquantity == 0) + data->totalprice = 0.0; + } +} + + +double +avgcost( UDF_INIT* initid, UDF_ARGS* args __attribute__((unused)), + char* is_null, char* error __attribute__((unused))) +{ + struct avgcost_data* data = (struct avgcost_data*)initid->ptr; + if (!data->count || !data->totalquantity) + { + *is_null = 1; + return 0.0; + } + + *is_null = 0; + return data->totalprice/(double)data->totalquantity; +} + +my_bool myfunc_argument_name_init(UDF_INIT *initid, UDF_ARGS *args, + char *message); +char *myfunc_argument_name(UDF_INIT *initid, UDF_ARGS *args, char *result, + unsigned long *length, char *null_value, + char *error); + +my_bool myfunc_argument_name_init(UDF_INIT *initid, UDF_ARGS *args, + char *message) +{ + if (args->arg_count != 1) + { + strmov(message,"myfunc_argument_name_init accepts only one argument"); + return 1; + } + initid->max_length= args->attribute_lengths[0]; + initid->maybe_null= 1; + initid->const_item= 1; + return 0; +} + +char *myfunc_argument_name(UDF_INIT *initid __attribute__((unused)), + UDF_ARGS *args, char *result, + unsigned long *length, char *null_value, + char *error __attribute__((unused))) +{ + if (!args->attributes[0]) + { + null_value= 0; + return 0; + } + (*length)--; /* space for ending \0 (for debugging purposes) */ + if (*length > args->attribute_lengths[0]) + *length= args->attribute_lengths[0]; + memcpy(result, args->attributes[0], *length); + result[*length]= 0; + return result; +} + +#endif /* HAVE_DLOPEN */ -- cgit v1.2.1 From 607838488cffef3dbe5167e6d321d8c2ca704745 Mon Sep 17 00:00:00 2001 From: "kostja@bodhi.local" <> Date: Wed, 2 Aug 2006 13:25:13 +0400 Subject: Fix a compilation failiure on QNX --- sql/udf_example.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index 62995085599..a80fce81278 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -806,6 +806,7 @@ char *reverse_lookup(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, #if defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST) char name_buff[256]; struct hostent tmp_hostent; + int tmp_errno; #endif struct hostent *hp; unsigned long taddr; @@ -845,7 +846,6 @@ char *reverse_lookup(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, return 0; } #if defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST) - int tmp_errno; if (!(hp=gethostbyaddr_r((char*) &taddr,sizeof(taddr), AF_INET, &tmp_hostent, name_buff,sizeof(name_buff), &tmp_errno))) -- cgit v1.2.1 From 67a701003c5754ca87ff802ffed91e6276a89b4c Mon Sep 17 00:00:00 2001 From: "georg@lmy002.wdf.sap.corp" <> Date: Fri, 22 Sep 2006 14:42:43 +0200 Subject: Fix for bug #19121: Windows incompatible udf_example --- sql/udf_example.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index a80fce81278..2fa7474eb16 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -127,7 +127,14 @@ typedef long long longlong; #else #include #include +#if defined(MYSQL_SERVER) #include /* To get strmov() */ +#else +/* when compiled as standalone */ +#define strmov(a,b) strcpy(a,b) +#define bzero(a,b) memset(a,0,b) +#define memcpy_fixed(a,b,c) memcpy(a,b,c) +#endif #endif #include #include @@ -674,10 +681,14 @@ longlong sequence(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, ** ****************************************************************************/ +#ifdef __WIN__ +#include +#else #include #include #include #include +#endif my_bool lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message); void lookup_deinit(UDF_INIT *initid); -- cgit v1.2.1 From 8471897fbc01520bfdf93a7105019e17cdbca89e Mon Sep 17 00:00:00 2001 From: "cmiller@zippy.cornsilk.net" <> Date: Mon, 13 Nov 2006 13:13:44 -0500 Subject: Bug#18761: constant expression as UDF parameters not passed in as constant The code that set up data to be passed to user-defined functions was very old and analyzed the "Type" of the data that was passed into the UDF, when it really should analyze the "return_type", which is hard-coded for simple Items and works correctly for complex ones like functions. --- Added test at Sergei's behest. --- sql/udf_example.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index 2fa7474eb16..a4f7eddd302 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -165,6 +165,9 @@ void avgcost_reset( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error void avgcost_clear( UDF_INIT* initid, char* is_null, char *error ); void avgcost_add( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error ); double avgcost( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error ); +my_bool is_const_init(UDF_INIT *initid, UDF_ARGS *args, char *message); +char *is_const(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long + *length, char *is_null, char *error); /************************************************************************* @@ -1075,4 +1078,31 @@ char *myfunc_argument_name(UDF_INIT *initid __attribute__((unused)), return result; } + + +my_bool is_const_init(UDF_INIT *initid, UDF_ARGS *args, char *message) +{ + if (args->arg_count != 1) + { + strmov(message, "IS_CONST accepts only one argument"); + return 1; + } + initid->ptr= (args->args[0] != NULL) ? 1 : 0; + return 0; +} + +char * is_const(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long + *length, char *is_null, char *error) +{ + if (initid->ptr != 0) { + sprintf(result, "const"); + } else { + sprintf(result, "not const"); + } + *is_null= 0; + *length= strlen(result); + return result; +} + + #endif /* HAVE_DLOPEN */ -- cgit v1.2.1 From c99678df03090bb2e9672c374934d44ca9304860 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Thu, 23 Nov 2006 20:07:53 +0100 Subject: Fix netware compile failure Remove other warnings about unused variables --- sql/udf_example.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index a4f7eddd302..bbab47e253d 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -1087,12 +1087,13 @@ my_bool is_const_init(UDF_INIT *initid, UDF_ARGS *args, char *message) strmov(message, "IS_CONST accepts only one argument"); return 1; } - initid->ptr= (args->args[0] != NULL) ? 1 : 0; + initid->ptr= (char*)((args->args[0] != NULL) ? 1 : 0); return 0; } -char * is_const(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long - *length, char *is_null, char *error) +char * is_const(UDF_INIT *initid, UDF_ARGS *args __attribute__((unused)), + char *result, unsigned long *length, + char *is_null, char *error __attribute__((unused))) { if (initid->ptr != 0) { sprintf(result, "const"); -- cgit v1.2.1 From 7c82a06dcf0dbf4cff2e2001ae03cdb574e6105e Mon Sep 17 00:00:00 2001 From: "tsmith/tim@siva.hindu.god" <> Date: Tue, 19 Dec 2006 20:17:33 -0700 Subject: Remove warnings by casting --- sql/udf_example.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index bbab47e253d..f938cc9c1d3 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -1087,7 +1087,7 @@ my_bool is_const_init(UDF_INIT *initid, UDF_ARGS *args, char *message) strmov(message, "IS_CONST accepts only one argument"); return 1; } - initid->ptr= (char*)((args->args[0] != NULL) ? 1 : 0); + initid->ptr= (char*)((args->args[0] != NULL) ? 1UL : 0); return 0; } -- cgit v1.2.1 From 226a5c833f3084bc634996c70d47a1c0d9164e0d Mon Sep 17 00:00:00 2001 From: "kent@mysql.com/kent-amd64.(none)" <> Date: Sat, 23 Dec 2006 20:17:15 +0100 Subject: Many files: Changed header to GPL version 2 only --- sql/udf_example.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index f938cc9c1d3..2bb4fe92d2f 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -2,8 +2,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -- cgit v1.2.1 From 520d1b414455668e32e46e7b217257ebcb766bb2 Mon Sep 17 00:00:00 2001 From: "monty@mysql.com/narttu.mysql.fi" <> Date: Fri, 23 Feb 2007 22:48:15 +0200 Subject: Fixed compilations problems and warnings on windows --- sql/udf_example.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index 2bb4fe92d2f..d37c6505ced 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -684,7 +684,7 @@ longlong sequence(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, ****************************************************************************/ #ifdef __WIN__ -#include +#include #else #include #include -- cgit v1.2.1 From 3ee16518618ee73cc0d4e0b2e47124dc83adfe5d Mon Sep 17 00:00:00 2001 From: "mhansson@dl145s.mysql.com" <> Date: Thu, 31 May 2007 14:22:21 +0200 Subject: bug#27741: udf test fails on AIX < 5.3 problem #1: udf_example.so does not get built on AIX solution#1: build it yourself using cd sql; gcc -g -I ../include/ -I /usr/include/ -lpthread \ -shared -o udf_example.so udf_example.c; mv udf_example.so \ .libs/ problem#2 (the bug): udf_example fails because it does not recognize the variable LD_LIBRARY_PATH when doing dl_open(), it looks at LIBPATH solution#2: add the library path to LIBPATH problem#3: udf_example returns the wrong result length since it relies on strmov to return a pointer to the end of the string that it copies. On AIX builds, where m_string.h is not included (m_string defines a macro expanding strmov to stpcpy), there is a macro expanding strmov to strcpy, which returns a pointer to the first character. solution#3: define strmov as stpcpy. problem#4: #2 applies on hp-ux as well, but this platform looks at SHLIB_PATH solution#4: added the library path to SHLIB_PATH --- sql/udf_example.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index 2bb4fe92d2f..0f28c2a14b0 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -130,7 +130,8 @@ typedef long long longlong; #include /* To get strmov() */ #else /* when compiled as standalone */ -#define strmov(a,b) strcpy(a,b) +#include +#define strmov(a,b) stpcpy(a,b) #define bzero(a,b) memset(a,0,b) #define memcpy_fixed(a,b,c) memcpy(a,b,c) #endif -- cgit v1.2.1 From a933f28a937dd8e6b547a68c94b1baedd3a5ff2d Mon Sep 17 00:00:00 2001 From: "dkatz@damien-katzs-computer.local" <> Date: Sun, 5 Aug 2007 21:37:55 -0400 Subject: Bug #29804 UDF parameters don't contain correct string length Previously, UDF *_init functions were passed constant strings with erroneous lengths. The length came from the containing variable's size, not the length of the value itself. Now the *_init functions get the constant as a null terminated string with the correct length supplied. --- sql/udf_example.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index b603464568e..5165a577555 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -1106,4 +1106,39 @@ char * is_const(UDF_INIT *initid, UDF_ARGS *args __attribute__((unused)), } +my_bool check_const_len_init(UDF_INIT *initid, UDF_ARGS *args, char *message) +{ + if (args->arg_count != 1) + { + strmov(message, "IS_CONST accepts only one argument"); + return 1; + } + if (args->args[0] == 0) + { + initid->ptr= "Not constant"; + } + else if(strlen(args->args[0]) == args->lengths[0]) + { + initid->ptr= "Correct length"; + } + else + { + initid->ptr= "Wrong length"; + } + initid->max_length = 100; + return 0; +} + +char * check_const_len(UDF_INIT *initid, UDF_ARGS *args __attribute__((unused)), + char *result, unsigned long *length, + char *is_null, char *error __attribute__((unused))) +{ + strmov(result, initid->ptr); + *length= strlen(result); + *is_null= 0; + return result; +} + + + #endif /* HAVE_DLOPEN */ -- cgit v1.2.1 From 9d06483f72c0c46006db0a2b75b6813100679ae8 Mon Sep 17 00:00:00 2001 From: "msvensson@pilot.(none)" <> Date: Thu, 9 Aug 2007 10:21:28 +0200 Subject: Bug#29804 UDF parameters don't contain correct string length - Fix warnings - Export 'check_const_len' from udf_example.dll --- sql/udf_example.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index 5165a577555..6c07a929b04 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -1115,15 +1115,15 @@ my_bool check_const_len_init(UDF_INIT *initid, UDF_ARGS *args, char *message) } if (args->args[0] == 0) { - initid->ptr= "Not constant"; + initid->ptr= (char*)"Not constant"; } else if(strlen(args->args[0]) == args->lengths[0]) { - initid->ptr= "Correct length"; + initid->ptr= (char*)"Correct length"; } else { - initid->ptr= "Wrong length"; + initid->ptr= (char*)"Wrong length"; } initid->max_length = 100; return 0; -- cgit v1.2.1 From d8e67d455665e06e607fdd43f3e81e3668f76b2e Mon Sep 17 00:00:00 2001 From: "dkatz@damien-katzs-computer.local" <> Date: Wed, 5 Sep 2007 15:06:10 -0400 Subject: Bug #29804 UDF parameters don't contain correct string length Previously, UDF *_init functions were passed constant strings with erroneous lengths. The length came from the containing variable's size, not the length of the value itself. Now the *_init functions get the constant as a null terminated string with the correct length supplied too. --- sql/udf_example.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index 0f28c2a14b0..df3a69755ad 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -1106,4 +1106,39 @@ char * is_const(UDF_INIT *initid, UDF_ARGS *args __attribute__((unused)), } + +my_bool check_const_len_init(UDF_INIT *initid, UDF_ARGS *args, char *message) +{ + if (args->arg_count != 1) + { + strmov(message, "CHECK_CONST_LEN accepts only one argument"); + return 1; + } + if (args->args[0] == 0) + { + initid->ptr= (char*)"Not constant"; + } + else if(strlen(args->args[0]) == args->lengths[0]) + { + initid->ptr= (char*)"Correct length"; + } + else + { + initid->ptr= (char*)"Wrong length"; + } + initid->max_length = 100; + return 0; +} + +char * check_const_len(UDF_INIT *initid, UDF_ARGS *args __attribute__((unused)), + char *result, unsigned long *length, + char *is_null, char *error __attribute__((unused))) +{ + strmov(result, initid->ptr); + *length= strlen(result); + *is_null= 0; + return result; +} + + #endif /* HAVE_DLOPEN */ -- cgit v1.2.1 From 8c3d5135baeba8a418ded32a649ae6ca3f75be3e Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@magare.gmz" <> Date: Tue, 27 Nov 2007 17:16:52 +0200 Subject: Bug #30355: Incorrect ordering of UDF results There's currently no way of knowing the determinicity of an UDF. And the optimizer and the sequence() UDFs were making wrong assumptions about what the is_const member means. Plus there was no implementation of update_system_tables() causing the optimizer to overwrite the information returned by the _init function. Fixed by equating the assumptions about the semantics of is_const and providing a implementation of update_used_tables(). Added a TODO item for the UDF API change needed to make a better implementation. --- sql/udf_example.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index df3a69755ad..4ca6133da03 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -648,13 +648,11 @@ my_bool sequence_init(UDF_INIT *initid, UDF_ARGS *args, char *message) return 1; } bzero(initid->ptr,sizeof(longlong)); - /* - Fool MySQL to think that this function is a constant - This will ensure that MySQL only evalutes the function - when the rows are sent to the client and not before any ORDER BY - clauses + /* + sequence() is a non-deterministic function : it has different value + even if called with the same arguments. */ - initid->const_item=1; + initid->const_item=0; return 0; } -- cgit v1.2.1 From 2b85c64d65385297f4a90265ae47cb298891dd5f Mon Sep 17 00:00:00 2001 From: Ignacio Galarza Date: Tue, 10 Feb 2009 17:47:54 -0500 Subject: Bug#29125 Windows Server X64: so many compiler warnings - Remove bothersome warning messages. This change focuses on the warnings that are covered by the ignore file: support-files/compiler_warnings.supp. - Strings are guaranteed to be max uint in length --- sql/udf_example.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index 4ca6133da03..db48984eed8 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -1099,7 +1099,7 @@ char * is_const(UDF_INIT *initid, UDF_ARGS *args __attribute__((unused)), sprintf(result, "not const"); } *is_null= 0; - *length= strlen(result); + *length= (uint) strlen(result); return result; } @@ -1133,7 +1133,7 @@ char * check_const_len(UDF_INIT *initid, UDF_ARGS *args __attribute__((unused)), char *is_null, char *error __attribute__((unused))) { strmov(result, initid->ptr); - *length= strlen(result); + *length= (uint) strlen(result); *is_null= 0; return result; } -- cgit v1.2.1 From 38b6d49e826e1fde46c445d790eb7609b14c4220 Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Thu, 17 Sep 2009 17:10:30 +0200 Subject: Bug #43414 Parenthesis (and other) warnings compiling MySQL with gcc 4.3.2 This is the fifth patch cleaning up more GCC warnings about variables used before initialized using the new macro UNINIT_VAR(). --- sql/udf_example.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index db48984eed8..019d4d834dd 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -139,10 +139,10 @@ typedef long long longlong; #include #include -static pthread_mutex_t LOCK_hostname; - #ifdef HAVE_DLOPEN +static pthread_mutex_t LOCK_hostname; + /* These must be right or mysqld will not find the symbol! */ my_bool metaphon_init(UDF_INIT *initid, UDF_ARGS *args, char *message); -- cgit v1.2.1 From 46d04ebdefe05377b86e851d73df22c069d63246 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 30 Sep 2009 03:39:37 +0200 Subject: Backport of the patch http://lists.mysql.com/commits/57725 Vladislav Vaintroub 2008-11-03 Cleanup CMakeLists.txt(s) - remove winsock2 (ws2_32) from TARGET_LINK_LIBRARIES. Every exe or dll linked with mysys needs ws2_32, because mysys uses winsock function WSAStartup in my_init(). However, there is no need to explicitely add ws2_32 to the list of TARGET_LINK_LIBRARIES multiple times. Visual Studio comes with a handy pragma that tells linker to add library. So patch replaces bunch of ws2_32 in CMakeLists with single pragma comment(lib,"ws2_32") in my_init.c Additionally, reference to non-existing "debug" library has been removed from TARGET_LINK_LIBRARIES. The correct name of the library is "dbug". --- sql/udf_example.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index 30d85d95034..1d6a9828594 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -138,6 +138,11 @@ typedef long long longlong; #endif #include #include + +#ifdef _WIN32 +/* inet_aton needs winsock library */ +#pragma comment(lib, "ws2_32") +#endif static pthread_mutex_t LOCK_hostname; -- cgit v1.2.1 From 28015993235d3a1a56f08de5b86c4e1ef59d4723 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 30 Sep 2009 15:35:01 +0200 Subject: Backport http://lists.mysql.com/commits/57778 2677 Vladislav Vaintroub 2008-11-04 CMakeLists.txt files cleanup - remove SAFEMALLOC and SAFE_MUTEX definitions that were present in *each* CMakeLists.txt. Instead, put them into top level CMakeLists.txt, but disable on Windows, because a) SAFEMALLOC does not add any functionality that is not already present in Debug C runtime ( and 2 safe malloc one on top of the other only unnecessarily slows down the server) b)SAFE_MUTEX does not work on Windows and have been explicitely disabled on Windows with #undef previously. Fortunately, ntdll does pretty good job identifying l problems with CRITICAL_SECTIONs. DebugBreak()s on using uninited critical section, unlocking unowned critical section) -Also, remove occationally used -D_DEBUG (added by compiler anyway) --- sql/udf_example.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index 1d6a9828594..4b39a83d4ac 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -138,11 +138,11 @@ typedef long long longlong; #endif #include #include - -#ifdef _WIN32 -/* inet_aton needs winsock library */ -#pragma comment(lib, "ws2_32") -#endif + +#ifdef _WIN32 +/* inet_aton needs winsock library */ +#pragma comment(lib, "ws2_32") +#endif static pthread_mutex_t LOCK_hostname; -- cgit v1.2.1 From 04e99c10096e9cfe72f9823fc73b9f4eee80c1db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Bl=C3=A5udd?= Date: Wed, 7 Oct 2009 15:42:16 +0200 Subject: Bug#42589 mysql_fix_privilege_tables.sh to be deprecated - Remove remnants of "mysql_fix_privilege_tables.sh"(again) --- sql/udf_example.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index 30d85d95034..4e24735a93d 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -107,7 +107,7 @@ ** option. ** ** If you can't get AGGREGATES to work, check that you have the column -** 'type' in the mysql.func table. If not, run 'mysql_fix_privilege_tables'. +** 'type' in the mysql.func table. If not, run 'mysql_upgrade'. ** */ -- cgit v1.2.1 From 4cff617c2541279a53b92acbd4e4d8716dc54873 Mon Sep 17 00:00:00 2001 From: Konstantin Osipov Date: Tue, 24 Nov 2009 16:54:59 +0300 Subject: Backport of: ---------------------------------------------------------------------- ChangeSet@1.2571, 2008-04-08 12:30:06+02:00, vvaintroub@wva. +122 -0 Bug#32082 : definition of VOID in my_global.h conflicts with Windows SDK headers VOID macro is now removed. Its usage is replaced with void cast. In some cases, where cast does not make much sense (pthread_*, printf, hash_delete, my_seek), cast is ommited. --- sql/udf_example.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index 4e3dd82c467..73256bb5529 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -767,14 +767,14 @@ char *lookup(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, return 0; } #else - VOID(pthread_mutex_lock(&LOCK_hostname)); + pthread_mutex_lock(&LOCK_hostname); if (!(hostent= gethostbyname((char*) name_buff))) { - VOID(pthread_mutex_unlock(&LOCK_hostname)); + pthread_mutex_unlock(&LOCK_hostname); *null_value= 1; return 0; } - VOID(pthread_mutex_unlock(&LOCK_hostname)); + pthread_mutex_unlock(&LOCK_hostname); #endif memcpy_fixed((char*) &in,(char*) *hostent->h_addr_list, sizeof(in.s_addr)); *res_length= (ulong) (strmov(result, inet_ntoa(in)) - result); @@ -871,14 +871,14 @@ char *reverse_lookup(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, return 0; } #else - VOID(pthread_mutex_lock(&LOCK_hostname)); + pthread_mutex_lock(&LOCK_hostname); if (!(hp= gethostbyaddr((char*) &taddr, sizeof(taddr), AF_INET))) { - VOID(pthread_mutex_unlock(&LOCK_hostname)); + pthread_mutex_unlock(&LOCK_hostname); *null_value= 1; return 0; } - VOID(pthread_mutex_unlock(&LOCK_hostname)); + pthread_mutex_unlock(&LOCK_hostname); #endif *res_length=(ulong) (strmov(result,hp->h_name) - result); return result; -- cgit v1.2.1 From 93fb8bb23544a4b5b2a4a6e43e1c25d74ca9a6f0 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Fri, 2 Jul 2010 15:30:47 -0300 Subject: Bug#53445: Build with -Wall and fix warnings that it generates Apart strict-aliasing warnings, fix the remaining warnings generated by GCC 4.4.4 -Wall and -Wextra flags. One major source of warnings was the in-house function my_bcmp which (unconventionally) took pointers to unsigned characters as the byte sequences to be compared. Since my_bcmp and bcmp are deprecated functions whose only difference with memcmp is the return value, every use of the function is replaced with memcmp as the special return value wasn't actually being used by any caller. There were also various other warnings, mostly due to type mismatches, missing return values, missing prototypes, dead code (unreachable) and ignored return values. --- sql/udf_example.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index 82af58ec502..637293209e0 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -141,7 +141,9 @@ typedef long long longlong; #ifdef HAVE_DLOPEN +#if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_SOLARIS_STYLE_GETHOST) static pthread_mutex_t LOCK_hostname; +#endif /* These must be right or mysqld will not find the symbol! */ -- cgit v1.2.1 From c96b249fc3912f7a86f885cc62da1a3eeed537c6 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Tue, 20 Jul 2010 15:07:36 -0300 Subject: Bug#45288: pb2 returns a lot of compilation warnings on linux Fix warnings flagged by the new warning option -Wunused-but-set-variable that was added to GCC 4.6 and that is enabled by -Wunused and -Wall. The option causes a warning whenever a local variable is assigned to but is later unused. It also warns about meaningless pointer dereferences. --- sql/udf_example.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index 637293209e0..468118b44ef 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -1067,7 +1067,7 @@ char *myfunc_argument_name(UDF_INIT *initid __attribute__((unused)), { if (!args->attributes[0]) { - null_value= 0; + *null_value= 1; return 0; } (*length)--; /* space for ending \0 (for debugging purposes) */ -- cgit v1.2.1 From e81506971f2c465f583e3f6f23857f50a88c48de Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Fri, 23 Jul 2010 17:17:55 -0300 Subject: WL#5498: Remove dead and unused source code Remove workarounds for ancient systems. --- sql/udf_example.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index 284689d329f..5f8e71d25fa 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -133,7 +133,6 @@ typedef long long longlong; #include #define strmov(a,b) stpcpy(a,b) #define bzero(a,b) memset(a,0,b) -#define memcpy_fixed(a,b,c) memcpy(a,b,c) #endif #endif #include @@ -778,7 +777,7 @@ char *lookup(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, } pthread_mutex_unlock(&LOCK_hostname); #endif - memcpy_fixed((char*) &in,(char*) *hostent->h_addr_list, sizeof(in.s_addr)); + memcpy(&in, *hostent->h_addr_list, sizeof(in.s_addr)); *res_length= (ulong) (strmov(result, inet_ntoa(in)) - result); return result; } -- cgit v1.2.1 From e5ce023f5716212aa1d20c757ebc8c6cecdf055a Mon Sep 17 00:00:00 2001 From: Kent Boortz Date: Thu, 30 Jun 2011 17:31:31 +0200 Subject: Updated/added copyright headers --- sql/udf_example.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index 019d4d834dd..ef74e8f2b2f 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2002 MySQL AB +/* Copyright (c) 2000-2004, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc. + Use is subject to license terms. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -11,7 +12,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* ** example file of UDF (user definable functions) that are dynamicly loaded -- cgit v1.2.1 From cb9d0deb713f16956339f21af5e231dac63a9646 Mon Sep 17 00:00:00 2001 From: Vamsikrishna Bhagi Date: Wed, 3 Dec 2014 14:46:39 +0530 Subject: Bug #19688008 CREATE_ASYMMETRIC_PUB_KEY: CRASHES IN OPENSSL CODE Problem: UDF doesn't handle the arguments properly when they are of string type due to a misplaced break. The length of arguments is also not set properly when the argument is NULL. Solution: Fixed the code by putting the break at right place and setting the argument length to zero when the argument is NULL. --- sql/udf_example.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index bfd153b7d28..af625b7ebf0 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -295,9 +295,20 @@ char *metaphon(UDF_INIT *initid __attribute__((unused)), if (!word) /* Null argument */ { + /* The length is expected to be zero when the argument is NULL. */ + assert(args->lengths[0] == 0); *is_null=1; return 0; } + else + { + /* + A check to confirm that argument length has the value it is + expected to have. + */ + assert(strlen(word) == args->lengths[0]); + } + w_end=word+args->lengths[0]; org_result=result; -- cgit v1.2.1 From 12f17f08c7f8c34e1b9c596084539a6147564ec7 Mon Sep 17 00:00:00 2001 From: Vamsikrishna Bhagi Date: Tue, 9 Dec 2014 16:15:37 +0530 Subject: Bug #19688008 CREATE_ASYMMETRIC_PUB_KEY: CRASHES IN OPENSSL CODE Fixed a failure on pb2 caused by the patch previously pushed. --- sql/udf_example.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'sql/udf_example.c') diff --git a/sql/udf_example.c b/sql/udf_example.c index af625b7ebf0..ccb0cd827f2 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -300,14 +300,6 @@ char *metaphon(UDF_INIT *initid __attribute__((unused)), *is_null=1; return 0; } - else - { - /* - A check to confirm that argument length has the value it is - expected to have. - */ - assert(strlen(word) == args->lengths[0]); - } w_end=word+args->lengths[0]; org_result=result; -- cgit v1.2.1