2017-10-16 5 views
0

db2ReadLog를 호출하는 외부 UDF를 통해 DB2 LUW 데이터베이스에서 트랜잭션 로그 정보를 얻으 려 할 때 SQL0487N (SQL 문에서 실행을 시도 함)이 리턴됩니다. 동일한 공유 라이브러리를 저장 프로 시저로 사용하면 오류없이 작동합니다.외부 UDF에서 db2ReadLog 호출

UDF가 필요한 이유는 트랜잭션 로그에서 실제 항목을 리턴하는 테이블 값 UDF를 결국 작성할 수 있기 때문입니다. 여기

초기 LRI UDF를 결정하기위한 C 소스이다

다음 SQL 외부 UDF로 C 함수를 등록에 사용되는
#include <sqlca.h> 
#include <db2ApiDf.h> 
#include <sqludf.h> 
#include <string.h> 
#include <stdio.h> 
#include <inttypes.h> 

#ifdef __plusplus 
extern "C" 
#endif 
SQL_API_RC SQL_API_FN get_initial_lri(SQLUDF_CHAR *lri, SQLUDF_NULLIND 
    *lri_null_ind, SQLUDF_TRAIL_ARGS) 
{ 
    struct sqlca sqlca; 
    db2ReadLogStruct read_log_params; 
    db2ReadLogInfoStruct info; 
    SQL_API_RC rc; 
    char state_msg[1024], error_msg[1024]; 

    memset(&sqlca, 0, sizeof sqlca); 
    memset(&read_log_params, 0, sizeof read_log_params); 
    memset(&info, 0, sizeof info); 

    read_log_params.iCallerAction = DB2READLOG_QUERY; 
    read_log_params.iFilterOption = DB2READLOG_FILTER_OFF; 
    read_log_params.poReadLogInfo = &info; 

    rc = db2ReadLog(db2Version1058, &read_log_params, &sqlca); 
    if (rc < 0) { 
      memcpy(SQLUDF_STATE, "38TA0", SQLUDF_SQLSTATE_LEN); 
      strncpy(SQLUDF_MSGTX, "Could not query log for initial LRI", SQLUDF_MSGTEXT_LEN); 

      goto error; 
    } else if (sqlca.sqlcode < 0) { 
      strncpy(SQLUDF_STATE, sqlca.sqlstate, SQLUDF_SQLSTATE_LEN); 
      SQLUDF_MSGTX[0] = '\0'; 
      rc = sqlaintp(error_msg, sizeof error_msg, 80, &sqlca); 
      if (rc > 0) { 
        strncpy(SQLUDF_MSGTX, error_msg, SQLUDF_MSGTEXT_LEN); 
      } 
      strncat(SQLUDF_MSGTX, "|", SQLUDF_MSGTEXT_LEN); 
      rc = sqlogstt(state_msg, sizeof state_msg, 80, sqlca.sqlstate); 
      if (rc > 0) { 
        strncat(SQLUDF_MSGTX, state_msg, SQLUDF_MSGTEXT_LEN); 
      } 

      goto error; 
    } else { 
      snprintf(lri, 101, "%" PRIx64 ":%" PRIx64 ":%" PRIx64, info.nextStartLRI.lriType, info.nextStartLRI.part1, info.nextStartLRI.part2); 
    } 

    return 0; 

error: 
    return SQLZ_DISCONNECT_PROC; 
} 

:

create or replace function get_initial_lri() 
    returns varchar(100) 
    language c 
    external name 'get_initial_lri_0!get_initial_lri' 
    parameter style sql 
    fenced not threadsafe 
    reads sql data 
    no external action 
    no scratchpad 
    no final call 
    disallow parallel 
    no dbinfo 

가입에 대해 저장 프로 시저와 동일한 코드는 다음과 같습니다.

create or replace procedure get_initial_lri_sp(out lri varchar(100)) 
    language c 
    dynamic result sets 0 
    reads sql data 
    not deterministic 
    external name 'get_initial_lri_0!get_initial_lri' 
    fenced not threadsafe 
    no external action 
    program type sub 
    no dbinfo 
    parameter style sql 

C 소스 코드

gcc -o get_initial_lri_0 get_initial_lri.c -L ~/sqllib/lib64 -ldb2 -shared -fpic -D_REENTRANT -I ~/sqllib/include 

DB2 버전은 v10.5.0.8입니다.

사용자 정의 함수에서 db2ReadLog API를 호출 할 수 있습니까?

+0

대신'sql external action'을 선언하십시오. – mustaccio

+0

같은 오류가 지속됩니다. –

답변

0

"외부 함수 또는 외부 메서드 내에서 연결 수준 API를 호출 할 수 없습니다."라는 내용의 문서가 나와 있습니다. 그리고 db2ReadLog API에는 연결이 필요합니다. 문서 링크는 here입니다.

db2ReadLogNoconn이라는 또 다른 API가 있는데, 다른 제한 사항이있을 수 있지만 그 동작을 비교해보십시오. 문서 번호 here.

그렇지 않은 경우, 비 외부 UDF는 스토어드 프로 시저 (일부 제한이 있음)를 호출하여 스토어드 프로 시저를 랩 할 수 있으므로 조사 할 수 있습니다.

+0

데이터베이스 연결이 필요한 sqlbmtsq를 호출하여 연결 수준 API의 제한 사항 호출을 확인했습니다. –

+0

비 외부 UDF에서 스토어드 프로 시저를 호출하면 원래 오류가 발생합니다. 외부 UDF에서 호출하려고 할 때도 동일합니다. –