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,
              REAL_RESULT, and
              DECIMAL_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;
}
              Arguments of type DECIMAL_RESULT are
              passed as strings, so you should handle them the same way
              as STRING_RESULT values.
            
              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;
              Exact-value decimal arguments such as
              1.3 or
              DECIMAL column values are
              passed with a type of DECIMAL_RESULT.
              However, the values are passed as strings. If you want to
              receive a number, use the initialization function to
              specify that the argument should be coerced to a
              REAL_RESULT value:
            
args->arg_type[2] = REAL_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 later 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]);
                  For an argument of type
                  DECIMAL_RESULT, the value is passed
                  as a string and should be handled like a
                  STRING_RESULT value.
                
                  ROW_RESULT arguments are not
                  implemented.
                
              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).
            
              char **attributes
            
              args->attributes communicates
              information about the names of the UDF arguments. For
              argument i, the attribute name is
              available as a string in
              args->attributes[i] and the
              attribute length is
              args->attribute_lengths[i]. Do not
              assume that the string is null-terminated.
            
              By default, the name of a UDF argument is the text of the
              expression used to specify the argument. For UDFs, an
              argument may also have an optional [AS]
               clause, in
              which case the argument name is
              alias_namealias_name. The
              attributes value for each argument thus
              depends on whether an alias was given.
            
              Suppose that a UDF my_udf() is invoked
              as follows:
            
SELECT my_udf(expr1, expr2 AS alias1, expr3 alias2);
              In this case, the attributes and
              attribute_lengths arrays will have
              these values:
            
args->attributes[0] = "expr1" args->attribute_lengths[0] = 5 args->attributes[1] = "alias1" args->attribute_lengths[1] = 6 args->attributes[2] = "alias2" args->attribute_lengths[2] = 6
              unsigned long *attribute_lengths
            
              The attribute_lengths array indicates
              the length of each argument name.
            


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.