From: | Amaury Bouchard <amaury(dot)bouchard(at)anasen(dot)com> |
---|---|
To: | pgsql-general(at)lists(dot)postgresql(dot)org |
Subject: | Weird behaviour of C extension function |
Date: | 2020-04-24 12:53:38 |
Message-ID: | CAFZmo02foTnbWfffNG6sOsP4Xsm0HBWu2zbWFONEioODuteHcg@mail.gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-general |
Hello everybody,
I have a really strange behaviour with a C function, wich gets a text as
parameter.
Everything works fine when I call the function directly, giving a text
string as parameter. But a problem occurs when I try to read data from a
table.
To illustrate the problem, I stripped the function down to the minimum. The
source code is below, but first, here is the behaviour :
Direct call
-----------
> select passthru('hello world!'), passthru('utf8 çhàràtérs'), passthru('
h3110 123 456 ');
INFO: INPUT STRING: 'hello world!' (12)
INFO: INPUT STRING: 'utf8 çhàràtérs' (18)
INFO: INPUT STRING: ' h3110 123 456 ' (15)
(as you can see, the log messages show the correct input, with the number
of bytes between parentheses)
Reading a table data
--------------------
> create table mytable ( str text);
> insert into mytable (str) values ('hello world!'), ('utf8 çhàràtérs'), ('
h3110 123 456 ');
> select passthru(str) from mytable;
INFO: INPUT STRING: 'lo world!' (12)
INFO: INPUT STRING: '8 çhàràtérs' (18)
INFO: INPUT STRING: '110 123 456 �
' (15)
INFO: INPUT STRING: '��' (5)
INFO: INPUT STRING: '' (3)
There, you can see that the pointer seems to be shifted 3 bytes farther.
Do you have any clue for this strange behaviour?
The source code
---------------
#include "postgres.h"
#include "fmgr.h"
#include "funcapi.h"
// PG module init
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
void _PG_init(void);
Datum passthru(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(passthru);
void _PG_init() {
}
Datum passthru(PG_FUNCTION_ARGS) {
// get the input string
text *input = PG_GETARG_TEXT_PP(0);
char *input_pt = (char*)VARDATA(input);
int32 input_len = VARSIZE_ANY_EXHDR(input);
// create a null terminated copy of the input string
char *str_copy = calloc(1, input_len + 1);
memcpy(str_copy, input_pt, input_len);
// log message
elog(INFO, "INPUT STRING: '%s' (%d)", str_copy, input_len);
free(str_copy);
PG_RETURN_NULL();
}
Thank you.
Best regards,
Amaury Bouchard
From | Date | Subject | |
---|---|---|---|
Next Message | Laurenz Albe | 2020-04-24 13:27:12 | Re: Weird behaviour of C extension function |
Previous Message | Michael Paquier | 2020-04-24 07:12:50 | Re: Can I tell libpq to connect to the primary? |