Thread: more custom C function fun
I have a custom C function that takes two text*s and returns a text*. My problem is with this code: PG_FUNCTION_INFO_V1(get_agent); PGMODULEEXPORT Datum get_agent(PG_FUNCTION_ARGS) { if(!PG_ARGISNULL(0)) { text* calling_party = PG_GETARG_TEXT_P(0); char* thestr = VARDATA(calling_party); if(thestr[20] == ')') { PG_RETURN_TEXT_P(calling_party); } } /* the other argument is ignored for now */ PG_RETURN_NULL(); } The problem is, the comparison in the inner if statement is always true. If I change to compare, say, thestr[0] == 'N', then it works as expected (returning only those text*s whose first letter is N, returning null for the rest). However if I try to compare any character inside the text* with a parenthesis (both '(' and ')'), then the equality is apparently always true (the function never returns null, always returning calling_party), whether or not there is any data in that column that contains a parenthesis in that column. Does anyone know of any oddities or whatnot I should be accounting for when reading character data out of a text*? - Dan
Harvey, Allan AC wrote: > Try if(thestr[20] == 0x29) > might reveal something in the parsing if it works. No effect. - Dan
On Mon, May 05, 2008 at 11:43:40PM -0600, Dan Heron Myers wrote: > I have a custom C function that takes two text*s and returns a text*. > > text* calling_party = PG_GETARG_TEXT_P(0); > > char* thestr = VARDATA(calling_party); > if(thestr[20] == ')') > { > PG_RETURN_TEXT_P(calling_party); > } You do realise that VARDATA does not return a null terminated string? Try using something like text_to_cstring or using elog(NOTICE) to display what's actually being compared. Have a nice day, -- Martijn van Oosterhout <kleptog@svana.org> http://svana.org/kleptog/ > Please line up in a tree and maintain the heap invariant while > boarding. Thank you for flying nlogn airlines.
Attachment
Martijn van Oosterhout wrote: > You do realise that VARDATA does not return a null terminated string? I did not realize that... but it led me in the right direction. > Try using something like text_to_cstring or using elog(NOTICE) to > display what's actually being compared. I've outputted some things with elog (which is the other thing I needed to figure this out). Using DatumToCString(mytextvariable), I get single-character-length strings that do not match the data actually in the fields. Using VARDATA(mytextvariable) as the char*, I get things like this (name obscured) (using strlen to get the string's length): string: "Hillary Clinton(6611)", length 21 string: "95555551234nton(6611)", length 21 Of course, then I realized that strlen isn't the right tool for the job; I need: int len = VARSIZE(mytextvariable) - VARHDRSZ; Using that with the VARDATA as my char*, I get this: string: "Hillary Clinton(6611)" - length: 21 string: "95555551234" - length: 11 Which is what I need. Perhaps we could get some documentation about how to use this stuff? I was unable to find any on the Postgres site, if there is any. Thanks for your help guys :) - Dan
On Tue, May 06, 2008 at 09:39:50AM -0600, Dan Heron Myers wrote: > Using DatumToCString(mytextvariable), I get single-character-length > strings that do not match the data actually in the fields. Correct, because it's not a cstring. Pretending it is one gives you garbage. > Using VARDATA(mytextvariable) as the char*, I get things like this (name > obscured) (using strlen to get the string's length): Not null terminated. > Which is what I need. Perhaps we could get some documentation about how > to use this stuff? I was unable to find any on the Postgres site, if > there is any. Well, here's an example of how you should do it: http://www.postgresql.org/docs/8.2/interactive/spi-examples.html Not the most obvious place. The best place is the source, utils/adt/text contains lots of functions on text variables, so you can see how they work. Have a nice day, -- Martijn van Oosterhout <kleptog@svana.org> http://svana.org/kleptog/ > Please line up in a tree and maintain the heap invariant while > boarding. Thank you for flying nlogn airlines.