If you have a variable number of arguments you need to either:
- Declare it
VARIADIC;
- Create n different signatures for the function with different numbers of arguments; or
- In
C create only the most general form, the 7-argument variety, and then create SQL function wrappers for the fewer-arguments cases that call the most general form.
If you really only need 3,4,5,6, and 7-argument versions I'd do something like:
CREATE FUNCTION embed0(text,text,text,text,text,text,text) RETURNS text
LANGUAGE 'C' AS 'embed0','embed0';
CREATE OR REPLACE FUNCTION embed0(text,text,text) RETURNS text AS $$
SELECT embed0($1,$2,$2,NULL,NULL,NULL,NULL);
$$ LANGUAGE 'SQL';
// ... etc
If 7 args was just an arbitrary upper bound and you can actually take any number of arguments you should instead just write:
CREATE FUNCTION embed0(text,text,text,VARIADIC text) RETURNS text
LANGUAGE 'C' AS 'embed0','embed0';
and handle the variable arguments in your C function. See the PostgreSQL source code for the concat function for how. Its implementation is text_concat in src/backend/utils/adt/varlena.c on line 3842 in current git head; your line number will differ. Most of the work is done in concat_internal.
Another example is the format function, with C implementation text_format (via lookup in pg_proc.h), located in varlena.c (according to git grep '^text_format'; Pg coding style rules specify that the function name must begin on the hard left of the line), line 3953 in current git. While a more complicated function it might be better as an example for you because it does all the work in one place rather than splitting out for a helper function call. It's declared in pg_proc.h but if it were declared in SQL it'd look something like:
CREATE FUNCTION format(text, VARIADIC text) RETURNS text AS 'internal','text_format';
There you'll see that VARIADIC arguments are accessed like any other from C, using the PG_GETARG_...(argno) macros. The PG_NARGS() macro reports the number of arguments passed. VARIADIC arguments may be null so you have to use PG_ARGISNULL(argno) and handle the case of a null argument.
So: I'd write it as a VARIADIC function using PG_NARGS, PG_GETARG_TEXT_P, PG_ARGISNULL. Because Pg's VARIADIC functions cannot be called implicitly with zero variadic arguments, I'd write a wrapper for the 3-argument case that does:
CREATE OR REPLACE FUNCTION embed_0(text,text,text) RETURNS text AS $$
SELECT embed_0($1,$2,$2, VARIADIC ARRAY[]::text[]);
$$ LANGUAGE 'SQL';
, passing an empty array as the variadic parameter. That way you can call it with 3 args too.
BTW, when coding be aware that the string in a Pg text is not null terminated, unlike those passed to main(). You must use the lengths PostgreSQL provides.. See src/include/fmgr.h, the tutorial, and the text handling in the functions in the source code. Don't use strlen, strcat, strcpy, etc because they expect null-terminated strings.