【发布时间】:2016-05-26 15:45:05
【问题描述】:
我有一个实现 Netezza 用户定义函数的 cpp 类(文档here)。它接受一个参数,该参数将是某种日期格式的字符串,并将其转换为 YYYYMMDD 格式。如果它不是一个有效的日期,它将返回“99991231”。每当我在某些表上运行代码时,每次相同的输入都会得到不同的输出。我认为有一些我没有看到的内存问题。
从逻辑上讲,我们将 char 数组 retval 设置为等于 date 命令的输出。如果它给出一个空输出,我们设置为“99991231”。然后我们将一个临时字符数组设置为 retval 的前 9 个字节(最后一个是空终止符)。然后我们 memcpy 进入 ret->data (我们必须返回的结构的一个字符指针)。
#include <stdarg.h>
#include <string.h>
#include "udxinc.h"
#include "udxhelpers.h"
using namespace nz::udx_ver2;
class Dateconvert: public Udf
{
public:
Dateconvert(UdxInit *pInit) : Udf(pInit){}
~Dateconvert(){}
static Udf* instantiate(UdxInit *pInit);
virtual ReturnValue evaluate()
{
StringReturn* ret = stringReturnInfo();
StringArg *str;
str = stringArg(0);
int lengths = str->length;
char *datas = str->data;
string tempData = datas;
string shell_arg = tempData;
shell_arg = "'" + shell_arg + "'";
string cmd="date -d " + shell_arg + " +%Y%m%d 2>/dev/null";
FILE *ls = popen(cmd.c_str(), "r");
char retval[100];
retval[0]='n';
fgets(retval, sizeof(retval), ls);
if(!isdigit(retval[0]))
{
strcpy(retval,"99991231");
}
pclose(ls);
char temp1[9];
memcpy(temp1, retval, 8);
temp1[8]='\0';
ret->size = 9;
memcpy(ret->data, temp1, 9);
NZ_UDX_RETURN_STRING(ret);
}
};
Udf* Dateconvert::instantiate(UdxInit *pInit)
{
return new Dateconvert(pInit);
}
当我在 Netezza 中对一个不同的值运行 UDF 时,它给了我预期的输出。但是,当我在多列上运行它时,输出有时是正确的,有时是错误的,似乎是随机的。我认为这必须是内部内存问题。例子:
input output
1) 8/11/2014 20140811
2) 8/11/2014 20140811
Fri 10/17/14 20141017
3) 8/11/2014 99991231
Fri 10/17/14 20141017
4) 8/11/2014 20140811
Fri 10/17/14 20141017
5) 8/11/2014 20140811
Fri 10/17/14 20141017
9-Nov-12 20121109
6) 8/11/2014 20140811
Fri 10/17/14 20141017
9-Nov-12 01241109 (what?)
7) 8/11/2014 99991231
Fri 10/17/14 20141017
9-Nov-12 20121109
只要函数只有一次调用,它就会返回正确的答案。多次调用时会出现问题,我不明白。为什么会有东西被带走?在评估函数结束时将返回值大小从 9 更改为 8 并不能解决问题。
这是调用函数的格式:
select a.val1, DATECONVERT(a.val1)
from
(
select '8/11/2014' as val1 from calendar
union
select 'Fri 10/17/14' as val1 from calendar
union
select '9-Nov-12' as val1 from calendar
) a
并为 UDF 编译命令:
nzudxcompile /export/home/nz/dateconvert.cpp -o dateconvert.o --sig "Dateconvert(VARCHAR(200))" --version 2 --return "VARCHAR(200)" --class Dateconvert --user user1 --pw mypw --db mydb
【问题讨论】:
-
我已经添加了查询示例和编译命令。 @巴里
-
应该没什么区别,但是你可以用
strcpy()而不是memcpy(),那么它会自动放空终止符。 -
为什么要先复制到
temp1再复制到ret->data? -
我还没有浏览UDF文档,你需要做一些事情来为
ret->data分配空间吗?
标签: c++ arrays memory user-defined-functions netezza