Работа со строками с помощью функции языка C PostgreSQL
Я хотел бы создать функцию c-Language postgresql, аргументы и возвращаемые значения которой 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-битный
Я впервые использую язык Си, поэтому я рад представить пример кода.
Извините, мой английский не очень хорош.
1 ответ
Построение вручную text
или же VarChar
как это не будет работать. Ты не можешь просто
VarChar *rtn = (VarChar *)VARDATA(c);
потому что то, что вы делаете там, пытается интерпретировать char*
значение c
как будто это было VarChar*
, читая первые несколько байтов как VARLENA
заголовок, а затем получить некоторую подстроку в нем в качестве значения. Не собираюсь на работу.
Это намного проще в использовании cstring_to_text
а также text_to_cstring
преобразовать. text*
точно совместим с VarChar*
, (Они в utils/builtins.h
).
например
PG_RETURN_VARCHAR_P(cstring_to_text(c));
Чтобы сделать это вручную, нужно palloc
строка с strlen
байт + VARHDRSIZE
, SET_VARSIZE
, затем strcpy
данные к VARDATA
смещение. Увидеть src/include/utils/varlena.h
а также src/backend/utils/adt/varlena.c
, Это неудобно и не нужно, когда PostgreSQL имеет вспомогательные функции для этой цели.
Лично я рекомендую игнорировать varchar
полностью для программирования на уровне C. Определите свои функции как принятие и возврат text
,