【问题标题】:String manipulation by C language function of PostgreSQLPostgreSQL 的 C 语言函数的字符串操作
【发布时间】:2017-10-27 04:10:09
【问题描述】:

我想创建一个 postgresql c-Language 函数,它的参数和返回值都是 varchar,并且在处理过程中使用 Char []。

但是,它并没有按预期工作。

我做了一个这样的c程序。

#include <postgres.h>
#include <port.h>
#include <fmgr.h>
#include <stdlib.h>

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

// Required for windows.
extern PGDLLEXPORT Datum VARCHAR_CHAR_ARRAY_VARCHAR(PG_FUNCTION_ARGS);

PG_FUNCTION_INFO_V1(VARCHAR_CHAR_ARRAY_VARCHAR);

Datum VARCHAR_CHAR_ARRAY_VARCHAR(PG_FUNCTION_ARGS) {
    // Get arg.
    VarChar  *arg1 = (VarChar *)PG_GETARG_VARCHAR_P(0);

    // VarChar to Char[].
    char *c = (char *)VARDATA(arg1);

    elog(NOTICE, "VarChar to Char[]."); 
    elog(NOTICE, c);//Log1

    // Do something.(e.g. replace)
    // Since it uses another system, it must be Char [].

    //Char[] to VarChar.
    VarChar *rtn = (VarChar *)VARDATA(c);
    elog(NOTICE, "Char[] to VarChar.");
    elog(NOTICE, rtn);//Log2

    // Return VarChar.
    PG_RETURN_VARCHAR_P(rtn);
}

并且,创建了这样一个脚本。

CREATE OR REPLACE FUNCTION public.VARCHAR_CHAR_ARRAY_VARCHAR(character varying)
  RETURNS character varying AS
'$libdir/test/VARCHAR_CHAR_ARRAY_VARCHAR.dll', 'VARCHAR_CHAR_ARRAY_VARCHAR'
  LANGUAGE c VOLATILE STRICT;

执行结果是这样的。

SELECT VARCHAR_CHAR_ARRAY_VARCHAR('a');
-- Expected value: 'a'
-- Postgresql terminated abnormally... :(

SELECT VARCHAR_CHAR_ARRAY_VARCHAR('Action');
-- Expected return value: 'Action'
-- Actual return value  :'n'
-- Log1  :'NOTICE:  n'
-- Log2  :''

SELECT VARCHAR_CHAR_ARRAY_VARCHAR('ActionAction');
-- Expected return value: 'ActionAction'
-- Actual return value  : ''  <-Why?
-- Log1  :''
-- Log2  :''

SELECT VARCHAR_CHAR_ARRAY_VARCHAR('Action Action');
-- Expected return value: 'Action Action'
-- Actual return value  : 'n Action'
-- Log1  :'NOTICE:  Action Action'
-- Log2  :'NOTICE:  ction'

SELECT VARCHAR_CHAR_ARRAY_VARCHAR('1234567890');
-- Expected return value: '1234567890'
-- Actual return value  : '6789'
-- Log1  :'NOTICE:  1234567890'
-- Log2  :'NOTICE:  90'

执行环境:

  • Windows Server 2012 R2 x64
  • PostgreSQL 9.5.9,由 Visual C++ build 1800 编译,64 位

我是第一次使用 C 语言,所以很高兴提供示例代码。

对不起,我的英语不好。

【问题讨论】:

  • 如何它“没有按预期工作”?您向我们展示了实际结果,但预期结果是什么?请(re-)read about how to ask good questions.
  • 抱歉,我添加了一个期望值。无论如何,如果输入值按原样返回就可以了。 (必须在内部转换为 char []。)

标签: c postgresql postgresql-extensions


【解决方案1】:

像这样手动构造 textVarChar 是行不通的。你不能只是

VarChar *rtn = (VarChar *)VARDATA(c);

因为您正在尝试将char*c 解释为VarChar*,将前几个字节读取为VARLENA 标头,然后在其中获取一些子字符串作为价值。不会工作。

使用cstring_to_texttext_to_cstring 进行转换要容易得多text*VarChar* 完全兼容。 (他们在utils/builtins.h)。

例如

 PG_RETURN_VARCHAR_P(cstring_to_text(c));

要手动执行此操作,必须将 palloc 字符串与 strlen 字节 + VARHDRSIZESET_VARSIZE,然后将 strcpy 数据转移到 VARDATA 偏移量。请参阅src/include/utils/varlena.hsrc/backend/utils/adt/varlena.c。当 PostgreSQL 具有用于此目的的辅助函数时,这是繁琐且不必要的。

我个人建议完全忽略 varchar 进行 C 级编程。将您的函数定义为接受和返回text

【讨论】:

  • 感谢您的回答。但是,我找不到 cstring_from_text。也许,是 text_to_cstring?
猜你喜欢
  • 1970-01-01
  • 2020-07-25
  • 1970-01-01
  • 2021-03-29
  • 1970-01-01
  • 2014-09-30
  • 2021-09-06
  • 1970-01-01
  • 2020-09-20
相关资源
最近更新 更多