What is talxy?
Internal function call from C-language function
Hello Guest
  
  • Login
• Register…
• Start blog
  • Who, Where, When
• What is interesting here?
• Duels
  • Polls
• Avatars
• Interests
  • Cities and Countries
• Random blog
• Users search
  • Search
• Games
• Tests
• QAIX
  • Сообщества
• Talxy Chat
• Horoscope
• Online
 
Register!

QAIX > PostgreSQL database development > Internal function call from C-language function 2 November 2009 05:27:13

  Top users: 
  Recent blog posts: 
  Forums:   
  Discuss: 
  Recent forum topics: 
  Recent forum comments:
  Модератор:

Internal function call from C-language function

Zoltan Boszormenyi 7 December 2006 11:48:25
 Hi,

I need to call date_part() from a C function.
How to do that?

Thanks in advance,
Zolt n B sz rm nyi


-------------------­--------(end of broadcast)---------­------------------
TIP 2: Don't 'kill -9' the postmaster

Add comment
Martijn van Oosterhout 7 December 2006 12:50:09 permanent link ]
 On Thu, Dec 07, 2006 at 09:48:25AM +0100, Zoltan Boszormenyi wrote:> Hi,>
I need to call date_part() from a C function.> How to do that?

Look in fmgr.h for the functions {Oid,Direct,}Functi­onCall* which
provide various ways to call other functions.

There's also FunctionCallInvoke(­) which is more efficient if you're
going to call it lots of times.

Have a nice day,
--
Martijn van Oosterhout <kleptog@svana.org>­ http://svana.org/kl­eptog/> From each according to his ability. To each according to his ability to litigate.
Add comment
Zoltan Boszormenyi 7 December 2006 14:55:47 permanent link ]
 Hi,

Martijn van Oosterhout rta:> On Thu, Dec 07, 2006 at 09:48:25AM +0100, Zoltan Boszormenyi wrote:>
Hi,>>
I need to call date_part() from a C function.>> How to do that?>>
Look in fmgr.h for the functions {Oid,Direct,}Functi­onCall* which> provide various ways to call other functions.>
There's also FunctionCallInvoke(­) which is more efficient if you're> going to call it lots of times.>
Have a nice day,>

thanks, I found the DirectFunctionCall family,
that wasn't the problem.

The real trick was that inside a C function,
I have to use timestamp_part(), as date_part()
doesn't even exists. The header catalog/pg_proc.h
proves it. date_part() is an SQL wrapper around
real C functions: timestamp[tz]_part(), time[tz]_part()
and interval_part().

However, I have another problem. I have this in the code:

HeapTupleHeader t;
Datum timest;
bool isnull;

t = PG_GETARG_HEAPTUPLE­HEADER(0);
timest = DatumGetTimestamp(G­etAttributeByName(t,­ "ts_today",
&isnull));
elog(NOTICE, "DatumGetTimestamp(­) OK, value is %s", isnull ?
"NULL" : "NOT NULL");

if (isnull)
PG_RETURN_BOOL(fals­e);

yeardatum = CStringGetDatum("ye­ar");
elog(NOTICE, "CStringGetDatum() 1 OK");
returndatum = DirectFunctionCall2­(timestamp_part, yeardatum,
timest);
elog(NOTICE, "date_part() 1 OK");
year = DatumGetFloat8(retu­rndatum);
elog(NOTICE, "conversion 1 OK");

...

But I get this:

NOTICE: PG_GETARG OK
NOTICE: DatumGetTimestamp()­ OK, value is NOT NULL
NOTICE: CStringGetDatum() 1 OK
ERROR: invalid memory alloc request size 1951613700

So DirectFunctionCall2­() fails. How can I fix it?

Best regards,
Zolt n


-------------------­--------(end of broadcast)---------­------------------
TIP 5: don't forget to increase your free space map settings

Add comment
Martijn van Oosterhout 7 December 2006 15:10:56 permanent link ]
 On Thu, Dec 07, 2006 at 12:55:47PM +0100, Zoltan Boszormenyi wrote:> However, I have another problem. I have this in the code:

<snip>
yeardatum = CStringGetDatum("ye­ar"); > elog(NOTICE, "CStringGetDatum() 1 OK");> returndatum = DirectFunctionCall2­(timestamp_part, yeardatum, > timest);

You're passing a cstring as first argument, whereas I'm fairly sure you
should be passing text. When calling from C the're no argument
checking. I think what you're looking for is:

yeardatum = text_in("year");

Or something like that.

Hope this helps,
--
Martijn van Oosterhout <kleptog@svana.org>­ http://svana.org/kl­eptog/> From each according to his ability. To each according to his ability to litigate.
Add comment
Zoltan Boszormenyi 7 December 2006 15:40:22 permanent link ]
 Martijn van Oosterhout rta:> On Thu, Dec 07, 2006 at 12:55:47PM +0100, Zoltan Boszormenyi wrote:>
However, I have another problem. I have this in the code:>>
<snip>>
yeardatum = CStringGetDatum("ye­ar"); >> elog(NOTICE, "CStringGetDatum() 1 OK");>> returndatum = DirectFunctionCall2­(timestamp_part, yeardatum, >> timest);>>
You're passing a cstring as first argument, whereas I'm fairly sure you> should be passing text. When calling from C the're no argument> checking. I think what you're looking for is:>
yeardatum = text_in("year");>
Or something like that.>
Hope this helps,>

text_in() doesn't exists, it's textin() but I have to call it through
DirectFunctionCall1­(), like this:

yeardatum = DirectFunctionCall1­(textin, CStringGetDatum("ye­ar"));

However, the session crashes on the subsequent

returndatum = DirectFunctionCall2­(timestamp_part, yeardatum, timest);

Best regards,

Zolt n


-------------------­--------(end of broadcast)---------­------------------
TIP 4: Have you searched our list archives?

http://archives.pos­tgresql.org/

Add comment
Martijn van Oosterhout 7 December 2006 16:22:26 permanent link ]
 On Thu, Dec 07, 2006 at 01:40:22PM +0100, Zoltan Boszormenyi wrote:> text_in() doesn't exists, it's textin() but I have to call it through> DirectFunctionCall1­(), like this:>
yeardatum = DirectFunctionCall1­(textin, CStringGetDatum("ye­ar"));>
However, the session crashes on the subsequent>
returndatum = DirectFunctionCall2­(timestamp_part, yeardatum, timest);

It would be a good idea to actually find out where it crashes, that
would help you work out what the actual problem is. Just looking at the
code you posted, I only see this other bit that looks a bit suspect:

Datum timest;
bool isnull;

t = PG_GETARG_HEAPTUPLE­HEADER(0);
timest = DatumGetTimestamp(G­etAttributeByName(t,­ "ts_today", &isnull));

You're calling DatumGetTimestamp()­ which would return a timestamp
(probably some structure) but you're storing it in a Datum. Just take
the result of GetAttributeByName directly.

Get at least a backtrace next time it crashes...

Have a nice day,
--
Martijn van Oosterhout <kleptog@svana.org>­ http://svana.org/kl­eptog/> From each according to his ability. To each according to his ability to litigate.
Add comment
Zoltan Boszormenyi 7 December 2006 19:15:23 permanent link ]
 Hi,

Martijn van Oosterhout rta:> On Thu, Dec 07, 2006 at 01:40:22PM +0100, Zoltan Boszormenyi wrote:>
text_in() doesn't exists, it's textin() but I have to call it through>> DirectFunctionCall1­(), like this:>>
yeardatum = DirectFunctionCall1­(textin, CStringGetDatum("ye­ar"));>>
However, the session crashes on the subsequent>>
returndatum = DirectFunctionCall2­(timestamp_part, yeardatum, timest);>>
It would be a good idea to actually find out where it crashes, that> would help you work out what the actual problem is. Just looking at the> code you posted, I only see this other bit that looks a bit suspect:>
Datum timest;> bool isnull;>
t = PG_GETARG_HEAPTUPLE­HEADER(0);> timest = DatumGetTimestamp(G­etAttributeByName(t,­ "ts_today", &isnull));>
You're calling DatumGetTimestamp()­ which would return a timestamp> (probably some structure) but you're storing it in a Datum. Just take> the result of GetAttributeByName directly.>

Thanks, that worked for me.

I have just one more question:
How can I get an Oid out of a Datum, i.e.
how do I know what type I get in a given Datum?
DatumGetObjectId() seems to give me an Oid that
was specifically stored as a Datum.

The function I am working on is made for an
INSERT RULE, something like this:

CREATE OR REPLACE FUNCTION
myfunc( row1 table1 ) RETURNS BOOL VOLATILE
LANGUAGE C AS 'myfunc.so', 'myfunc';

CREATE RULE rule_table1_insert
AS ON INSERT TO table1
DO INSTEAD (SELECT myfunc( new ) );

So I get the to-be-inserted row in my function.
In the function, depending on the passed in values
I need to insert some other table. To do it,
I need to use SPI_prepare() which needs the list of Oids.
Get at least a backtrace next time it crashes...>

And how exactly can I do that? psql only reports that
the backend crashed and unable to reset connection.
At that time the backend session is already gone, isn't it?
Have a nice day,>

Thanks, to you, too. You helped a lot.

Best regards,
Zolt n


-------------------­--------(end of broadcast)---------­------------------
TIP 2: Don't 'kill -9' the postmaster

Add comment
Zoltan Boszormenyi 7 December 2006 20:01:13 permanent link ]
 Hi,

Zoltan Boszormenyi rta:> Hi,>
Martijn van Oosterhout rta:>> On Thu, Dec 07, 2006 at 01:40:22PM +0100, Zoltan Boszormenyi wrote:>>
text_in() doesn't exists, it's textin() but I have to call it through>>> DirectFunctionCall1­(), like this:>>>
yeardatum = DirectFunctionCall1­(textin, CStringGetDatum("ye­ar"));>>>
However, the session crashes on the subsequent>>>
returndatum = DirectFunctionCall2­(timestamp_part, yeardatum, timest);>>>
It would be a good idea to actually find out where it crashes, that>> would help you work out what the actual problem is. Just looking at the>> code you posted, I only see this other bit that looks a bit suspect:>>
Datum timest;>> bool isnull;>>
t = PG_GETARG_HEAPTUPLE­HEADER(0);>> timest = DatumGetTimestamp(G­etAttributeByName(t,­ "ts_today", >> &isnull));>>
You're calling DatumGetTimestamp()­ which would return a timestamp>> (probably some structure) but you're storing it in a Datum. Just take>> the result of GetAttributeByName directly.>>
Thanks, that worked for me.>
I have just one more question:> How can I get an Oid out of a Datum, i.e.> how do I know what type I get in a given Datum?> DatumGetObjectId() seems to give me an Oid that> was specifically stored as a Datum.

I have found the alternative solution.
If t is HeapTupleHeader then:

Oid tupType;
int32 tupTypmod;
TupleDesc tupDesc;

tupType = HeapTupleHeaderGetT­ypeId(t);
tupTypmod = HeapTupleHeaderGetT­ypMod(t);
tupDesc = lookup_rowtype_tupd­esc(tupType, tupTypmod);

will give me the needed TupleDesc and I can use SPI_gettypeid().

Thanks and best regards,
Zolt n


-------------------­--------(end of broadcast)---------­------------------
TIP 3: Have you checked our extensive FAQ?

http://www.postgres­ql.org/docs/faq

Add comment
Martijn van Oosterhout 8 December 2006 12:53:48 permanent link ]
 On Thu, Dec 07, 2006 at 06:01:13PM +0100, Zoltan Boszormenyi wrote:> >I have just one more question:> >How can I get an Oid out of a Datum, i.e.> >how do I know what type I get in a given Datum?> >DatumGetObjectId()­ seems to give me an Oid that> >was specifically stored as a Datum.>
I have found the alternative solution.> If t is HeapTupleHeader then:

<snip>

There is no way to tell what type is in a Datum, it's just that,
nothing else. The information about the actual type can come from
elsewhere, for example:

- If extracting from a tuple, the tuple descriptor has the type (as you found)
- If passed as argument, the fcinfo struct *may* have the type
information
- The SPI interface provide ways to get information also

On the other side, a Datum is abstract, and you can receive a Datum as
argument and pass it to other functions without needing to know what
type it is. But you better so it right because there is no type
checking on that level.

As for the backtrace, you can get gdb to attach to the backend after
you connect. Then when you get the segfault, gdb will catch it and show
you exactly where.

Have a nice day,
--
Martijn van Oosterhout <kleptog@svana.org>­ http://svana.org/kl­eptog/> From each according to his ability. To each according to his ability to litigate.
Add comment
Guest 1 June 2007 10:56:52 permanent link ]
 Hello!

Just a question. What is wrong with this code? This is part of trigger function:

attnum[3] = SPI_fnumber( tupdesc, "arfolyam" );
datums[3] = _selectFunctionB( "SELECT ertek FROM foo WHERE parameter='rate'" ); // This get back Datum type from select - PG_RETURN_FLOAT8( b ); is return where b is double type
arfolyam = DatumGetFloat8( datums[3] );
elog( INFO, "2.5.0 arfolyam = %f", arfolyam );
if ( attnum[3] == PointerGetDatum( NULL ) ) {
elog( ERROR, "Hianyzo arfolyam" );
SPI_finish();
return PointerGetDatum(NUL­L);
}
elog( INFO, "2.5.1 Datums[3] = %f", DatumGetFloat8( datums[3] ) );
rettuple = SPI_modifytuple( trigdata->tg_relati­on, tmptuple, 4, &attnum[0], &datums[0], &isNull[0] );
SPI_freetuple(tmptu­ple);
SPI_finish();
return PointerGetDatum( rettuple );


The output is the next after insert:
INFO: string vissza : 1.000000
INFO: 2.5.0 arfolyam = 1.000000
INFO: 2.5.1 Datums[3] = 1.000000
INSERT 0 1
ELES=# SELECT * FROM pgsor;
ERROR: invalid memory alloc request size 4294967293


Thanks in advance!
Josef Dudas
Add comment
 

Add new comment

As:
Login:  Password:  
 
 
  
 
Пожалуйста, относитесь к собеседникам уважительно, не используйте нецензурные слова, не злоупотребляйте заглавными буквами, не публикуйте рекламу и объявления о купле/продаже, а также материалы нарушающие сетевой этикет или законы РФ. Ваш ip-адрес записывается.


QAIX > PostgreSQL database development > Internal function call from C-language function 2 November 2009 05:27:13

see also:
Implementation apr_thread_pool
Re: [ANNOUNCE] Apache-SizeLimit 0.90
apr_socket_setaside?
pass tests:
see also:
My Photo-Shop's pictures.
Poll: How you concern to heroes of…
My friend.

  Copyright © 2001—2010 QAIX
Идея: Монашёв Михаил.
Авторами текстов, изображений и видео, размещённых на этой странице, являются пользователи сайта.
See Help and FAQ in the community support.qaix.com.
Write in the community about the bugs you have noticedbugs.qaix.com.
Write your offers and comments in the communities suggest.qaix.com.
Information for parents.
Пишите нам на .
If you would like to report an abuse of our service, such as a spam message, please .
Если Вы хотите пожаловаться на содержимое этой страницы, пожалуйста .