HiveBrain v1.2.0
Get Started
← Back to all entries
snippetsqlMinor

PostgreSQL How do I convert struct text to plain *char in C functions?

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
postgresqlstructconvertchartexthowfunctionsplain

Problem

I'm using my internal C function which doesn't know about postgresql's text struct, how do I pass text argument when char * expected?

#include
#include
#include "postgres.h"
#include "fmgr.h"

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

PG_FUNCTION_INFO_V1(fun);

Datum fun(PG_FUNCTION_ARGS)
{
text str1, str2;

str1 = PG_GETARG_TEXT_P(0);
str2 = PG_GETARG_TEXT_P(1);

FILE *fp = fopen("/tmp/fun.log", "w");
fprintf(fp, "%s\n", VARDATA_ANY(str1));
fprintf(fp, "%s\n", VARDATA_ANY(str2));
fclose(fp);

PG_RETURN_INT32(0);
}


Here's what xxd sees in log file:

0000000: 666f 6f74 6261 6c6c c88d 7409 70d3 6b09 football..t.p.k.
0000010: 080a 7a6f 6f6d 0a ..zoom.


After executing:

SELECT * FROM fun('football','zoom');


Why junk after football?

Solution

The data pointed to by the text structure isn't null-terminated, so you can't use it with C "string" functions directly.

To determine the length of the text, you can use VARSIZE(your_text)-VARHDRSZ.

In your example, you could use fwrite instead of printf to output the string (passing in the length), or copy the text to a char* and terminate it manually if you intend to use C string functions.

Here's a sample of how either could be done:

#include
#include
#include "postgres.h"
#include "fmgr.h"

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

PG_FUNCTION_INFO_V1(fun);

size_t log_pgtext(FILE to, text what)
{
return fwrite(VARDATA(what), 1, VARSIZE(what)-VARHDRSZ, to);
}

char dup_pgtext(text what)
{
size_t len = VARSIZE(what)-VARHDRSZ;
char *dup = palloc(len+1);
memcpy(dup, VARDATA(what), len);
dup[len] = 0;
return dup;
}

Datum fun(PG_FUNCTION_ARGS)
{
text str1, str2;

str1 = PG_GETARG_TEXT_P(0);
str2 = PG_GETARG_TEXT_P(1);

FILE *fp = fopen("/tmp/fun.log", "w");

log_pgtext(fp, str1);
fprintf(fp, "\n");

char *str = dup_pgtext(str2);
fprintf(fp, "%s\n", str);
pfree(str);

fclose(fp);

PG_RETURN_INT32(0);
}


Reference documentation for PostgreSQL 9.2.

Context

StackExchange Database Administrators Q#33151, answer score: 3

Revisions (0)

No revisions yet.