2010-07-17 37 views
5

Tôi đang cố gắng viết một hàm tùy chỉnh người dùng được xác định thích hợp cho mysql vì vậy tôi đã lấy hàm str_ucwords từ http://www.mysqludf.org/index.php làm ví dụ để xây dựng của riêng tôi.mysql 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; 
} 

này hoạt động tốt nếu tôi cố gắng select str_ucwords("test string"); nhưng nếu tôi cố gắng chọn một lĩnh vực từ cơ sở dữ liệu như select str_ucwords(name) from name; tôi nhận được không có gì trả lại.

Làm cách nào để thay đổi chức năng này để cho phép tôi lấy dữ liệu từ các trường trên cơ sở dữ liệu?

Tôi đã thử xóa args->arg_type[0] != STRING_RESULT khỏi chức năng init.

Trả lời

2

Vấn đề không phải là loại đối số, đó là số NULL khi gọi str_ucwords_init (vì str_ucwords_init được gọi trước khi truy xuất bất kỳ hàng nào). Để có được str_ucwords để làm việc với các trường, bạn phải hỗ trợ giá trị NULL bằng cách đặt initid->maybe_null thành 1 trong hàm _init và đặt *null_value thành 1 (và result thành NULL, mặc dù điều đó có thể không cần thiết) trong str_ucwords khi đối số thực tế là 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; 
} 

Các phiên bản sau của lib_mysqludf_str phải hỗ trợ giá trị NULL trong các hàm không thay đổi, có nghĩa là chúng cũng nên hoạt động với các cột trong bảng.