2017-10-16 116 views
0

當試圖通過調用db2ReadLog的外部UDF獲取DB2 LUW數據庫上的事務日誌信息時,返回SQL0487N(試圖在SQL語句上執行)。使用與存儲過程相同的共享庫可以正常工作。從外部UDF調用db2ReadLog

它需要成爲一個UDF的原因是最終能夠創建一個表值UDF,它將返回事務日誌中的實際條目。

這裏是C源爲UDF確定初始LRI:

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

以下SQL用於註冊C函數作爲外部UDF:

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 

和用於登記相同的代碼作爲存儲過程的SQL是:

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外部動作」。 – mustaccio

+0

同樣的錯誤依然存在。 –

回答

0

該文檔聲明「連接級別的API不能從外部函數或外部方法中調用」。而db2ReadLog API需要連接。文檔鏈接是here

還有一個名爲db2ReadLogNoconn的API,也許你應該嘗試比較它的行爲,雖然它可能會受到不同的限制。它被記錄在here

否則,非外部UDF可以調用存儲過程(受到一些限制),因此您可能可以包裝存儲過程,也許可以調查。

+0

通過嘗試調用也需要數據庫連接的sqlbmtsq來確認連接級別API限制的調用。 –

+0

從非外部UDF調用存儲過程會導致原始錯誤。當嘗試從外部UDF調用時也一樣。 –