Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf3c6e8a

Browse files
committed
Add a utility function to extract variadic function arguments
This is epecially useful in the case or "VARIADIC ANY" functions. Thecaller can get the artguments and types regardless of whether or not andexplicit VARIADIC array argument has been used. The function alsoprovides an option to convert arguments on type "unknown" to to "text".Michael Paquier and me, reviewed by Tom Lane.Backpatch to 9.4 in order to support the following json bug fix.
1 parent896eb5e commitf3c6e8a

File tree

2 files changed

+137
-1
lines changed

2 files changed

+137
-1
lines changed

‎src/backend/utils/fmgr/funcapi.c

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
*
33
* funcapi.c
44
* Utility and convenience functions for fmgr functions that return
5-
* sets and/or composite types.
5+
* sets and/or composite types, or deal with VARIADIC inputs.
66
*
77
* Copyright (c) 2002-2017, PostgreSQL Global Development Group
88
*
@@ -1400,3 +1400,116 @@ TypeGetTupleDesc(Oid typeoid, List *colaliases)
14001400

14011401
returntupdesc;
14021402
}
1403+
1404+
/*
1405+
* extract_variadic_args
1406+
*
1407+
* Extract a set of argument values, types and NULL markers for a given
1408+
* input function which makes use of a VARIADIC input whose argument list
1409+
* depends on the caller context. When doing a VARIADIC call, the caller
1410+
* has provided one argument made of an array of values, so deconstruct the
1411+
* array data before using it for the next processing. If no VARIADIC call
1412+
* is used, just fill in the status data based on all the arguments given
1413+
* by the caller.
1414+
*
1415+
* This function returns the number of arguments generated, or -1 in the
1416+
* case of "VARIADIC NULL".
1417+
*/
1418+
int
1419+
extract_variadic_args(FunctionCallInfofcinfo,intvariadic_start,
1420+
boolconvert_unknown,Datum**args,Oid**types,
1421+
bool**nulls)
1422+
{
1423+
boolvariadic=get_fn_expr_variadic(fcinfo->flinfo);
1424+
Datum*args_res;
1425+
bool*nulls_res;
1426+
Oid*types_res;
1427+
intnargs,i;
1428+
1429+
*args=NULL;
1430+
*types=NULL;
1431+
*nulls=NULL;
1432+
1433+
if (variadic)
1434+
{
1435+
ArrayType*array_in;
1436+
Oidelement_type;
1437+
booltypbyval;
1438+
chartypalign;
1439+
int16typlen;
1440+
1441+
Assert(PG_NARGS()==variadic_start+1);
1442+
1443+
if (PG_ARGISNULL(variadic_start))
1444+
return-1;
1445+
1446+
array_in=PG_GETARG_ARRAYTYPE_P(variadic_start);
1447+
element_type=ARR_ELEMTYPE(array_in);
1448+
1449+
get_typlenbyvalalign(element_type,
1450+
&typlen,&typbyval,&typalign);
1451+
deconstruct_array(array_in,element_type,typlen,typbyval,
1452+
typalign,&args_res,&nulls_res,
1453+
&nargs);
1454+
1455+
/* All the elements of the array have the same type */
1456+
types_res= (Oid*)palloc0(nargs*sizeof(Oid));
1457+
for (i=0;i<nargs;i++)
1458+
types_res[i]=element_type;
1459+
}
1460+
else
1461+
{
1462+
nargs=PG_NARGS()-variadic_start;
1463+
Assert (nargs>0);
1464+
nulls_res= (bool*)palloc0(nargs*sizeof(bool));
1465+
args_res= (Datum*)palloc0(nargs*sizeof(Datum));
1466+
types_res= (Oid*)palloc0(nargs*sizeof(Oid));
1467+
1468+
for (i=0;i<nargs;i++)
1469+
{
1470+
nulls_res[i]=PG_ARGISNULL(i+variadic_start);
1471+
types_res[i]=get_fn_expr_argtype(fcinfo->flinfo,
1472+
i+variadic_start);
1473+
1474+
/*
1475+
* Turn a constant (more or less literal) value that's of unknown
1476+
* type into text if required . Unknowns come in as a cstring
1477+
* pointer.
1478+
* Note: for functions declared as taking type "any", the parser
1479+
* will not do any type conversion on unknown-type literals (that
1480+
* is, undecorated strings or NULLs).
1481+
*/
1482+
if (convert_unknown&&
1483+
types_res[i]==UNKNOWNOID&&
1484+
get_fn_expr_arg_stable(fcinfo->flinfo,i+variadic_start))
1485+
{
1486+
types_res[i]=TEXTOID;
1487+
1488+
if (PG_ARGISNULL(i+variadic_start))
1489+
args_res[i]= (Datum)0;
1490+
else
1491+
args_res[i]=
1492+
CStringGetTextDatum(PG_GETARG_POINTER(i+variadic_start));
1493+
}
1494+
else
1495+
{
1496+
/* no conversion needed, just take the datum as given */
1497+
args_res[i]=PG_GETARG_DATUM(i+variadic_start);
1498+
}
1499+
1500+
if (!OidIsValid(types_res[i])||
1501+
(convert_unknown&&types_res[i]==UNKNOWNOID))
1502+
ereport(ERROR,
1503+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1504+
errmsg("could not determine data type for argument %d",
1505+
i+1)));
1506+
}
1507+
}
1508+
1509+
/* Fill in results */
1510+
*args=args_res;
1511+
*nulls=nulls_res;
1512+
*types=types_res;
1513+
1514+
returnnargs;
1515+
}

‎src/include/funcapi.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
*
33
* funcapi.h
44
* Definitions for functions which return composite type and/or sets
5+
* or work on VARIADIC inputs.
56
*
67
* This file must be included by all Postgres modules that either define
78
* or call FUNCAPI-callable functions or macros.
@@ -315,4 +316,26 @@ extern void end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx);
315316
PG_RETURN_NULL(); \
316317
} while (0)
317318

319+
/*----------
320+
*Support to ease writing of functions dealing with VARIADIC inputs
321+
*----------
322+
*
323+
* This function extracts a set of argument values, types and NULL markers
324+
* for a given input function. This returns a set of data:
325+
* - **values includes the set of Datum values extracted.
326+
* - **types the data type OID for each element.
327+
* - **nulls tracks if an element is NULL.
328+
*
329+
* variadic_start indicates the argument number where the VARIADIC argument
330+
* starts.
331+
* convert_unknown set to true will enforce the conversion of arguments
332+
* with unknown data type to text.
333+
*
334+
* The return result is the number of elements stored, or -1 in the case of
335+
* "VARIADIC NULL".
336+
*/
337+
externintextract_variadic_args(FunctionCallInfofcinfo,intvariadic_start,
338+
boolconvert_unknown,Datum**values,
339+
Oid**types,bool**nulls);
340+
318341
#endif/* FUNCAPI_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp