Sample Header Ad - 728x90

How to write a heterogeneous variadic function

1 vote
0 answers
119 views
I am trying to write a postgres stored procedure that can take a variable number of arguments of potentially different types (i.e. a heterogeneous list of arguments). As I learned from here , the heterogeneous variadic argument list is only possible in C. To learn how to write such a C function, I worked on a simple example that takes the heterogeneous list , converts each argument to a json string, and then returns the concatenated string. My code for this minimal example is listed below. I think I got the shape of this function right my mimicking how jsonb_build_object() works. But I can't figure out how to convert each argument value to json be and then turn it into a c-string. I tried to adapt the code of the to_json function (as indicated by //problem_lines marker below). But couldn't get the code to even compile. I am not very familiar with the internals of server side C programming with PostgreSQL (as of 16). *Could anyone with the expertise help explain how to make the conversion to json string work?* -- My code so far -- #include "postgres.h" #include "catalog/pg_type.h" #include "fmgr.h" #include "funcapi.h" //#include "utils/array.h" // for var_concat //#include "common/jsonapi.h" #include "utils/json.h" #include "utils/jsonb.h" #include "utils/jsonfuncs.h" PG_MODULE_MAGIC; // take a heterogeneous variadic list of values; convert them into json string, and then return the concatenated string Datum var_concat_worker(int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null, bool unique_keys) { int i; Jsonb *jb; char *strVal; char *result; int bufLen = 16; result = (char*)malloc(bufLen*sizeof(char)); Datum val; if (nargs flinfo, 0); JsonTypeCategory tcategory; Oid outfuncoid; if (val_type == InvalidOid) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("could not determine input data type"))); json_categorize_type(val_type, true, &tcategory, &outfuncoid); // jb = datum_to_jsonb(val, tcategory, outfuncoid); strVal = JsonbToCString(NULL, &jb->root, VARSIZE(jb)); if (strlen(strVal) + strlen(result) >= bufLen) { bufLen = bufLen * 2; result = realloc(result, bufLen); } strcat(result, strVal); } PG_RETURN_CSTRING(result); } /* SQL function var_concat(variadic "any") */ Datum var_concat(PG_FUNCTION_ARGS) { Datum *args; bool *nulls; Oid *types; /* build argument values to build the object */ int nargs = extract_variadic_args(fcinfo, 0, true, &args, &types, &nulls); if (nargs < 0) PG_RETURN_NULL(); PG_RETURN_DATUM(var_concat_worker(nargs, args, nulls, types, false, false)); } Related: https://dba.stackexchange.com/questions/264327
Asked by tinlyx (3820 rep)
Oct 31, 2023, 02:02 AM