Take the 2-minute tour ×
Database Administrators Stack Exchange is a question and answer site for database professionals who wish to improve their database skills and learn from others in the community. It's 100% free, no registration required.

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 <stdio.h>
#include <string.h>
#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?

share|improve this question
    
Hi, it's not very clear what you're doing exactly. What is your "internal C function"? Is it something that uses the libpq (or other) API from outside the DB? Is it an extension? What exactly do you mean by pg's "text struct"? (A little piece of code explaining what you're attempting to do might help clarify too.) –  Mat Jan 18 '13 at 14:34
    
Here's some examples goo.gl/6aDP5 –  Moe Jan 18 '13 at 15:01
1  
Could you please edit the relevant information into your question? (There's an edit link right under the tags.) Your questions here (and on other Stack Exchange sites) needs to be as clear and self-contained as possible so that others having the same question/problem as you can find it easily. –  Mat Jan 18 '13 at 15:06
    
Furthermore, please don't use short URLs since nobody knows in advance where it points. Please consult the help link just to the right of the comment box about how to place links in comments. Thanks! –  dezso Jan 18 '13 at 16:35

1 Answer 1

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 <stdio.h>
#include <string.h>
#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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.