从外部UDF调用db2ReadLog

问题描述:

当试图通过调用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

同样的错误依然存在。 –

该文档声明“连接级别的API不能从外部函数或外部方法中调用”。而db2ReadLog API需要连接。文档链接是here

还有一个名为db2ReadLogNoconn的API,也许你应该尝试比较它的行为,虽然它可能会受到不同的限制。它被记录在here

否则,非外部UDF可以调用存储过程(受到一些限制),因此您可能可以包装存储过程,也许可以调查。

+0

通过尝试调用也需要数据库连接的sqlbmtsq来确认连接级别API限制的调用。 –

+0

从非外部UDF调用存储过程会导致原始错误。当尝试从外部UDF调用时也一样。 –