2010-07-17 8 views
5

Ich versuche, eine benutzerdefinierte Eigenschaftsfunktion für mysql zu schreiben, also nahm ich die str_ucwords Funktion von http://www.mysqludf.org/index.php als ein Beispiel, um mein eigenes zu erstellen.propercase mysql udf

my_bool str_ucwords_init(UDF_INIT *initid, UDF_ARGS *args, char *message) 
{ 
    /* make sure user has provided exactly one string argument */ 
    if (args->arg_count != 1 || args->arg_type[0] != STRING_RESULT || args->args[0] == NULL) 
    { 
     strcpy(message,"str_ucwords requires one string argument"); 
     return 1; 
    } 

    /* str_ucwords() will not be returning null */ 
    initid->maybe_null=0; 

    return 0; 
} 

char *str_ucwords(UDF_INIT *initid, UDF_ARGS *args, 
    char *result, unsigned long *res_length, 
    char *null_value, char *error) 
{ 
    int i; 
    int new_word = 0; 

    // copy the argument string into result 
    strncpy(result, args->args[0], args->lengths[0]); 

    *res_length = args->lengths[0]; 

    // capitalize the first character of each word in the string 
    for (i = 0; i < *res_length; i++) 
    { 
     if (my_isalpha(&my_charset_latin1, result[i])) 
     { 
      if (!new_word) 
      { 
       new_word = 1; 
       result[i] = my_toupper(&my_charset_latin1, result[i]); 
      } 
     } 
     else 
     { 
      new_word = 0; 
     } 
    } 

    return result; 
} 

Dies funktioniert gut, wenn ich select str_ucwords("test string"); versuchen, aber wenn ich versuche, ein Feld aus einer Datenbank wie select str_ucwords(name) from name; auszuwählen ich nichts zurückgegeben.

Wie kann ich diese Funktion ändern, damit ich Daten aus Feldern in der Datenbank abrufen kann?

Ich habe bereits versucht, args->arg_type[0] != STRING_RESULT von der Init-Funktion zu entfernen.

Antwort

2

Das Problem ist nicht der Typ des Arguments, es ist, dass es NULL ist, wenn str_ucwords_init aufgerufen wird (seit str_ucwords_init vor dem Abrufen von Zeilen aufgerufen wird). Um str_ucwords mit Feldern zu arbeiten, müssen Sie NULL-Werte unterstützen, indem sie initid->maybe_null-1 in der _init Funktion und das Setzen *null_value-1 (und result auf NULL, obwohl das nicht notwendig sein kann) in str_ucwords, wenn das tatsächliche Argument null ist .

my_bool str_ucwords_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { 
    unsigned long res_length; 

    /* make sure user has provided exactly one argument */ 
    if (args->arg_count != 1) { 
     snprintf(message, MYSQL_ERRMSG_SIZE, "wrong number of arguments: str_ucwords requires one string argument, got %d arguments", args->arg_count); 
     return 1; 
    } 
    /* make sure user has provided a string argument */ 
    if (args->arg_type[0] != STRING_RESULT) { 
     snprintf(message, MYSQL_ERRMSG_SIZE, "str_ucwords requires one string argument (expected type %d, got type %d)", STRING_RESULT, args->arg_type[0]); 
     return 1; 
    } 

    res_length = args->lengths[0]; 

    if (SIZE_MAX < res_length) { 
     snprintf(message, MYSQL_ERRMSG_SIZE, "res_length (%lu) cannot be greater than SIZE_MAX (%zu)", res_length, (size_t) (SIZE_MAX)); 
     return 1; 
    } 

    initid->ptr = NULL; 

    if (res_length > 255) { 
     char *tmp = (char *) malloc((size_t) res_length); /* This is a safe cast because res_length <= SIZE_MAX. */ 
     if (tmp == NULL) { 
      snprintf(message, MYSQL_ERRMSG_SIZE, "malloc() failed to allocate %zu bytes of memory", (size_t) res_length); 
      return 1; 
     } 
     initid->ptr = tmp; 
    } 

    initid->maybe_null = 1; 
    initid->max_length = res_length; 
    return 0; 
} 

char *str_ucwords(UDF_INIT *initid, UDF_ARGS *args, 
      char *result, unsigned long *res_length, 
      char *null_value, char *error) 
{ 
    int i; 
    int new_word = 1; 

    if (args->args[0] == NULL) { 
     result = NULL; 
     *res_length = 0; 
     *null_value = 1; 
    } else { 
     if (initid->ptr != NULL) { 
      result = initid->ptr; 
     } 

     // copy the argument string into result 
     memcpy(result, args->args[0], args->lengths[0]); 
     *res_length = args->lengths[0]; 

     // capitalize the first character of each word in the string 
     for (i = 0; i < *res_length; i++) { 
      if (my_isalpha(&my_charset_latin1, result[i])) { 
       if (new_word) { 
        new_word = 0; 
        result[i] = my_toupper(&my_charset_latin1, result[i]); 
       } else { 
        result[i] = my_tolower(&my_charset_latin1, result[i]); 
       } 
      } else { 
       new_word = 1; 
      } 
     } 
    } 
    return result; 
} 

Spätere Versionen von lib_mysqludf_str sollten NULL-Werte in den Funktionen ohne Veränderung unterstützen, das heißt, sie auch mit Tabellenspalten funktionieren soll.