The args parameter points to a
          UDF_ARGS structure that has the members
          listed here:
        
              unsigned int arg_count
            
The number of arguments. Check this value in the initialization function if you require your function to be called with a particular number of arguments. For example:
if (args->arg_count != 2)
{
    strcpy(message,"XXX() requires two arguments");
    return 1;
}
              For other UDF_ARGS member values that
              are arrays, array references are zero-based. That is,
              refer to array members using index values from 0 to
              args->arg_count – 1.
            
              enum Item_result *arg_type
            
              A pointer to an array containing the types for each
              argument. The possible type values are
              STRING_RESULT,
              INT_RESULT, and
              REAL_RESULT.
            
              To make sure that arguments are of a given type and return
              an error if they are not, check the
              arg_type array in the initialization
              function. For example:
            
if (args->arg_type[0] != STRING_RESULT ||
    args->arg_type[1] != INT_RESULT)
{
    strcpy(message,"XXX() requires a string and an integer");
    return 1;
}
              As an alternative to requiring your function's arguments
              to be of particular types, you can use the initialization
              function to set the arg_type elements
              to the types you want. This causes MySQL to coerce
              arguments to those types for each call to
              xxx(). For example, to specify that the
              first two arguments should be coerced to string and
              integer, respectively, do this in
              xxx_init():
            
args->arg_type[0] = STRING_RESULT; args->arg_type[1] = INT_RESULT;
              char **args
            
              args->args communicates information
              to the initialization function about the general nature of
              the arguments passed to your function. For a constant
              argument i,
              args->args[i] points to the argument
              value. (See below for instructions on how to access the
              value properly.) For a nonconstant argument,
              args->args[i] is
              0. A constant argument is an expression
              that uses only constants, such as 3 or
              4*7-2 or
              SIN(3.14). A nonconstant
              argument is an expression that refers to values that may
              change from row to row, such as column names or functions
              that are called with nonconstant arguments.
            
              For each invocation of the main function,
              args->args contains the actual
              arguments that are passed for the row currently being
              processed.
            
              If argument i represents
              NULL,
              args->args[i] is a null pointer (0).
              If the argument is not NULL, functions
              can refer to it as follows:
            
                  An argument of type STRING_RESULT
                  is given as a string pointer plus a length, to allow
                  handling of binary data or data of arbitrary length.
                  The string contents are available as
                  args->args[i] and the string
                  length is args->lengths[i]. Do
                  not assume that the string is null-terminated.
                
                  For an argument of type INT_RESULT,
                  you must cast args->args[i] to a
                  long long value:
                
long long int_val; int_val = *((long long*) args->args[i]);
                  For an argument of type
                  REAL_RESULT, you must cast
                  args->args[i] to a
                  double value:
                
double real_val; real_val = *((double*) args->args[i]);
              unsigned long *lengths
            
              For the initialization function, the
              lengths array indicates the maximum
              string length for each argument. You should not change
              these. For each invocation of the main function,
              lengths contains the actual lengths of
              any string arguments that are passed for the row currently
              being processed. For arguments of types
              INT_RESULT or
              REAL_RESULT, lengths
              still contains the maximum length of the argument (as for
              the initialization function).
            
              char *maybe_null
            
              For the initialization function, the
              maybe_null array indicates for each
              argument whether the argument value might be null (0 if
              no, 1 if yes).
            


User Comments
Here is the code for the ***_add() function that works for me in an aggregate function to get the correct arguments (ints and strings) for each row.
The documentation above clearly explains how to get an int (long long), but I had to play around for a bit to get a string to be retrieved properly (since I'm not a C programmer and it wasn't obvious and most attempts ended up with corrupted data). Perhaps this code can help another programmer used to Java, C# etc trying to get started with a UDF in C.
The output from this via the fprintf commands will go into the MySQL error log.
NOTE: This code is not ready to go into prod ... it allocates memory (malloc) but does not clean it up.
void
show_row_arguments_add(UDF_INIT* initid, UDF_ARGS* args, char* is_null __attribute__((unused)), char* message __attribute__((unused))) {
fprintf(stderr, "------------------------------------------\n");
int numArgs = args->arg_count;
int i = 0;
while (i < numArgs) {
if (args->args[i]) {
if (args->arg_type[i] == 0) {
unsigned long argLength = args->lengths[i];
char *stringText = args->args[i];
char* myValue = NULL;
myValue = (char *)malloc(argLength);
strncpy(myValue, stringText,argLength);
fprintf(stderr, "args->args[%d] = %s - ", i, myValue);
fprintf(stderr, "STRING_RESULT \n");
}
else if (args->arg_type[i] == 1) {
fprintf(stderr, "args->args[%d] = %d - ", i, args->args[i]);
fprintf(stderr, "REAL_RESULT \n");
}
else if (args->arg_type[i] == 2) {
long long int_val;
int_val = *((long long*) args->args[i]);
fprintf(stderr, "args->args[%d] = %d - ", i, int_val);
fprintf(stderr, "INT_RESULT \n");
}
}
else {
fprintf(stderr, "args->args[%d] = null \n", i);
}
i++;
}
}
---------------------
A simple test with this could use the following table:
CREATE TABLE `test` (
`grp` int(11) DEFAULT NULL,
`a` varchar(50) DEFAULT NULL,
`b` varchar(50) DEFAULT NULL,
`c` int(11) DEFAULT NULL,
`d` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8
insert into test values (1, 'HP', null, 1, 1);
insert into test values (1, 'Laser', null, 1, 1);
insert into test values (1, 'Printer', null, 1, 1);
insert into test values (1, null, ' COLOR' , 1, 1);
select show_row_arguments(a, b, c, d) from test group by grp;
You would see the following in the logs:
------------------------------------------
args->args[0] = HP - STRING_RESULT
args->args[1] = null
args->args[2] = 1 - INT_RESULT
args->args[3] = 1 - INT_RESULT
------------------------------------------
args->args[0] = Laser - STRING_RESULT
args->args[1] = null
args->args[2] = 1 - INT_RESULT
args->args[3] = 1 - INT_RESULT
------------------------------------------
args->args[0] = Printer - STRING_RESULT
args->args[1] = null
args->args[2] = 1 - INT_RESULT
args->args[3] = 1 - INT_RESULT
------------------------------------------
args->args[0] = null
args->args[1] = COLOR - STRING_RESULT
args->args[2] = 1 - INT_RESULT
args->args[3] = 1 - INT_RESULT
Add your own comment.