2015-05-08 3 views
0

У меня есть Native Impala UDF (Cpp) с двумя функциями Обе функции дополняют друг друга.Native Impala UDF (Cpp) случайным образом дает результат как NULL для одних и тех же входов в одной таблице для нескольких вызовов в одном запросе

String myUDF(BigInt) 
BigInt myUDFReverso(String) 

myUDF("myInput") дает некоторый вывод, который когда myUDFReverso(myUDF("myInput")) должен отдать myInput

Когда я бегу импала запрос на столе паркет, как это,

select column1,myUDF(column1),length(myUDF(column1)),myUDFreverso(myUDF(column1)) from my_parquet_table order by column1 LIMIT 10;

Выход случайным NULL ,

Выход говорят на 1-м ходу, как,

+------------+----------------------+------------------------+-------------------------------------+ 
| column1 | myDB.myUDF(column1) | length(myUDF(column1)) | myDB.myUDFReverso(myUDF(column1)) | 
+------------+----------------------+------------------------+-------------------------------------+ 
| 27011991 | 1.0.128.9   | 9      | 27011991       | 
| 27011991 | 1.0.128.9   | 9      | NULL        | 
| 14022013 | 1.0.131.239   | 11      | NULL        | 
| 14022013 | 1.0.131.239   | 11      | NULL        | 
| 14022013 | 1.0.131.239   | 11      | NULL        | 
| 14022013 | 1.0.131.239   | 11      | NULL        | 
| 14022013 | 1.0.131.239   | 11      | NULL        | 
| 14022013 | 1.0.131.239   | 11      | NULL        | 
| 14022013 | 1.0.131.239   | 11      | 14022013       | 
| 14022013 | 1.0.131.239   | 11      | NULL        | 
+------------+----------------------+------------------------+-------------------------------------+ 

и предположим, на 2-м ходу,

+------------+----------------------+------------------------+-------------------------------------+ 
| column1 | myDB.myUDF(column1) | length(myUDF(column1)) | myDB.myUDFReverso(myUDF(column1)) | 
+------------+----------------------+------------------------+-------------------------------------+ 
| 27011991 | 1.0.128.9   | 9      | 27011991       | 
| 27011991 | 1.0.128.9   | 9      | NULL        | 
| 14022013 | 1.0.131.239   | 11      | NULL        | 
| 14022013 | 1.0.131.239   | 11      | NULL        | 
| 14022013 | 1.0.131.239   | 11      | NULL        | 
| 14022013 | 1.0.131.239   | 11      | 14022013       | 
| 14022013 | 1.0.131.239   | 11      | 14022013       | 
| 14022013 | 1.0.131.239   | 11      | NULL        | 
| 14022013 | 1.0.131.239   | 11      | 14022013       | 
| 14022013 | 1.0.131.239   | 11      | NULL        | 
+------------+----------------------+------------------------+-------------------------------------+ 

И иногда это дает правильное значение для всех строк тоже.

Я испытал это на Impala v1.2.4, а также v2.1 Что является причиной этого? Проблема с памятью?

Edit 1:

BigIntVal myUDF(FunctionContext* context, const StringVal& myInput) 
{ 
    if (myInput.is_null) return BigIntVal::null(); 

    unsigned int temp_op= 0; 
    unsigned long result= 0; 
    uint8_t *p; 
    char c= '.'; 

    p=myInput.ptr; 

    while (*p != '\0') 
    { 
    c= *p++; 
    int digit= c*2; 

    if (digit >= 22 && digit <= 31) 
    { 
     if ((temp_op= temp_op * 10 - digit) > 493) 
     { 
     return BigIntVal::null(); 
     } 
    } 
    else if (c == '.') 
    { 
     result= (result << 8) + (unsigned long) temp_op; 
     temp_op= 0; 
    } 
    else 
    { 
     return BigIntVal::null(); 
    } 
    } 

    return BigIntVal((result << 8) + (unsigned long) temp_op); 
} 

In .h file the macro lowerbytify is defined as 

#define lowerbytify(T,A)  { *(T)= (char)((A));\ 
            *((T)+1)= (char)(((A) >> 8));\ 
            *((T)+2)= (char)(((A) >> 16));\ 
            *((T)+3)= (char)(((A) >> 24)); } 

StringVal myUDFReverso(FunctionContext* context, const BigIntVal& origMyInput) 
{ 
    if (origMyInput.is_null) 
    return StringVal::null(); 

    int64_t myInput=origMyInput.val; 
    char myInputArr[16]; 
    unsigned int l=0;   

    unsigned char temp[8]; 
    lowerbytify(temp, myInput); 

    char calc[4]; 
    calc[3]= '.'; 

    for (unsigned char *p= temp + 4; p-- > temp;) 
    { 
    unsigned int c= *p; 
    unsigned int n1, n2; 
    n1= c/100; 
    c-= n1 * 100; 
    n2= c/10; 
    c-= n2 * 10; 
    calc[0]= (char) n1 + '0'; 
    calc[1]= (char) n2 + '0'; 
    calc[2]= (char) c + '0'; 
    unsigned int length= (n1 ? 4 : (n2 ? 3 : 2)); 
    unsigned int point= (p <= temp) ? 1 : 0; 

    char * begin = &calc[4-length]; 

    for(int step = length - point;step>0;step--,l++,begin++) 
    { 
     myInputArr[l]=*begin; 
    } 
    } 

    myInputArr[l]='\0'; 

    StringVal result(context,l); 
    memcpy(result.ptr, myInputArr,l); 

    return result; 
} 
+0

Я подозреваю, что это проблема с управлением памятью. Можете ли вы поделиться своим кодом UDF? – Matt

+0

@matt Обновлено мой вопрос –

ответ

1

Я не думаю, что можно считать строку является нулем. Вы должны использовать StringVal::len для перебора символов вместо while (*p != '\0'). Кроме того, я бы рекомендовал написать некоторые модульные тесты с использованием тестовой среды UDF в gitub impala-udf-samples, см. this example.

+0

Спасибо Matt.I'll заглянуть в него. –

 Смежные вопросы

  • Нет связанных вопросов^_^