2

I'm modifying the function Datum create_vlabel(PG_FUNCTION_ARGS), within Apache AGE.

But sometimes it's needed that one of the arguments to this function be NULL, and there's a check to that, like this:

if (!PG_ARGISNULL(2)) { ... }

The thing is, other functions need to call create_vlabel with the DirectFunctionCall command, but I can't figure out how to pass a NULL value through this command.

Everything I tried either broke the system or was not recognized as a proper NULL by the if clause mentioned above.

Here's everything I tried that did not work:

DirectFunctionCall1(create_vlabel, NULL) 
DirectFunctionCall1(create_vlabel, CStringGetDatum("NULL"))
DirectFunctionCall1(create_vlabel, CStringGetDatum(""))
DirectFunctionCall1(create_vlabel, CStringGetDatum(NULL))
DirectFunctionCall1(create_vlabel, PointerGetDatum(NULL))

So is there a proper way of sending a NULL argument through a DirectFunctionCall?

Marco Souza
  • 296
  • 7

1 Answers1

2

The comments in src/include/fmgr.h are quite clear on this topic:

/* These are for invocation of a specifically named function with a
 * directly-computed parameter list.  Note that neither arguments nor result
 * are allowed to be NULL.  Also, the function cannot be one that needs to
 * look at FmgrInfo, since there won't be any.
 */
extern Datum DirectFunctionCall1Coll(PGFunction func, Oid collation,
                                     Datum arg1);

[...]

#define DirectFunctionCall1(func, arg1) \
    DirectFunctionCall1Coll(func, InvalidOid, arg1)

If you need to call an SQL function will NULL values, you have to use FunctionCallInvoke(). Look at src/backend/tcop/fastpath.c for inspiration:

  • define fcinfo with

    LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
    
  • initialize it with InitFunctionCallInfoData()

  • set fcinfo->nargs and fcinfo->args[i]->isnull and fcinfo->args[i]->value for each argument

  • call FunctionCallInvoke(fcinfo)

Laurenz Albe
  • 209,280
  • 17
  • 206
  • 263