2010-07-17 53 views
5

我正在嘗試爲mysql編寫一個自定義的propercase用戶定義函數,所以我以http://www.mysqludf.org/index.php的str_ucwords函數爲例構建了自己的函數。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; 
} 

,如果我嘗試select str_ucwords("test string");但如果我嘗試從數據庫中像select str_ucwords(name) from name;選擇一個領域我什麼也沒有返回這工作得很好。

我該如何改變這個函數,使它能夠從數據庫的字段中提取數據?

我已經嘗試從init函數中刪除args->arg_type[0] != STRING_RESULT

回答

2

問題不在於參數的類型,而在於str_ucwords_init被調用時(因爲在檢索任何行之前調用str_ucwords_init)它是NULL。要使str_ucwords與字段一起使用,必須通過在_init函數中將initid->maybe_null設置爲1,並且在str_ucwords中將實際參數爲空時將*null_value設置爲1(並且result爲NULL,儘管可能不需要)來支持NULL值。

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; 
} 

lib_mysqludf_str的以後的版本應該支持該功能的NULL值沒有變化,這意味着它們也應符合表的列上工作。