从外部 UDF 调用 db2ReadLog

Posted

技术标签:

【中文标题】从外部 UDF 调用 db2ReadLog【英文标题】:Calling db2ReadLog from external UDF 【发布时间】:2017-10-16 20:37:37 【问题描述】:

当尝试通过调用 db2ReadLog 的外部 UDF 获取 DB2 LUW 数据库的事务日志信息时,返回 SQL0487N(尝试在 SQL 语句上执行)。使用与存储过程相同的共享库可以正常工作。

它需要成为 UDF 的原因是能够最终创建一个表值 UDF,该 UDF 将从事务日志中返回实际条目。

这里是 UDF 确定初始 LRI 的 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;

以下 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?

【问题讨论】:

尝试将其声明为contains sql external action 同样的错误仍然存​​在。 【参考方案1】:

文档指出“不能从外部函数或外部方法中调用连接级 API”。 db2ReadLog API 需要连接。文档链接是here。

还有另一个名为 db2ReadLogNoconn 的 API,也许您应该尝试比较它的行为,尽管它可能受到不同的限制。它记录在here。

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

【讨论】:

刚刚通过尝试调用同样需要数据库连接的sqlbmtsq确认了连接级别API的调用限制。 从非外部 UDF 调用存储过程会导致原始错误。尝试从外部 UDF 调用时也是如此。

以上是关于从外部 UDF 调用 db2ReadLog的主要内容,如果未能解决你的问题,请参考以下文章

如何将复杂的外部变量(例如映射值)从 Spark 与 Java 中的驱动程序传递给 UDF?

使用外部 Java 库的猪 UDF

使用外部 UDF 库运行 BigQuery Standard SQL

Hive实战UDF 外部依赖文件找不到的问题#yyds干货盘点#

在pyspark的pandas_udf中使用外部库

当 UDF 使用一些外部资源文件但在本机运行时,为啥 Hive 错误 FileNotFoundException?