| Line | Hits | Source | Commit |
| 95 |
- |
ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, |
- |
| 96 |
- |
Node *last_srf, FuncCall *fn, bool proc_call, int location) |
- |
| 97 |
- |
{ |
- |
| 98 |
- |
bool is_column = (fn == NULL); |
- |
| 99 |
- |
List *agg_order = (fn ? fn->agg_order : NIL); |
- |
| 100 |
- |
Expr *agg_filter = NULL; |
- |
| 101 |
- |
WindowDef *over = (fn ? fn->over : NULL); |
- |
| 102 |
- |
bool agg_within_group = (fn ? fn->agg_within_group : false); |
- |
| 103 |
- |
bool agg_star = (fn ? fn->agg_star : false); |
- |
| 104 |
- |
bool agg_distinct = (fn ? fn->agg_distinct : false); |
- |
| 105 |
- |
bool func_variadic = (fn ? fn->func_variadic : false); |
- |
| 106 |
- |
int ignore_nulls = (fn ? fn->ignore_nulls : NO_NULLTREATMENT); |
- |
| 107 |
- |
CoercionForm funcformat = (fn ? fn->funcformat : COERCE_EXPLICIT_CALL); |
- |
| 108 |
- |
bool could_be_projection; |
- |
| 109 |
- |
Oid rettype; |
- |
| 110 |
- |
Oid funcid; |
- |
| 111 |
- |
ListCell *l; |
- |
| 112 |
- |
Node *first_arg = NULL; |
- |
| 113 |
- |
int nargs; |
- |
| 114 |
- |
int nargsplusdefs; |
- |
| 115 |
- |
Oid actual_arg_types[FUNC_MAX_ARGS]; |
- |
| 116 |
- |
Oid *declared_arg_types; |
- |
| 117 |
- |
List *argnames; |
- |
| 118 |
- |
List *argdefaults; |
- |
| 119 |
- |
Node *retval; |
- |
| 120 |
- |
bool retset; |
- |
| 121 |
- |
int nvargs; |
- |
| 122 |
- |
Oid vatype; |
- |
| 123 |
- |
FuncDetailCode fdresult; |
- |
| 124 |
- |
int fgc_flags; |
- |
| 125 |
- |
char aggkind = 0; |
- |
| 126 |
- |
ParseCallbackState pcbstate; |
- |
| 127 |
514476 |
bool could_be_rpr_nav = false; |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 128 |
- |
|
- |
| 129 |
- |
/* |
- |
| 130 |
- |
* If there's an aggregate filter, transform it using transformWhereClause |
- |
| 131 |
- |
*/ |
- |
| 132 |
- |
if (fn && fn->agg_filter != NULL) |
- |
| 133 |
- |
agg_filter = (Expr *) transformWhereClause(pstate, fn->agg_filter, |
- |
| 134 |
- |
EXPR_KIND_FILTER, |
- |
| 135 |
- |
"FILTER"); |
- |
| 136 |
- |
|
- |
| 137 |
- |
/* |
- |
| 138 |
- |
* Most of the rest of the parser just assumes that functions do not have |
- |
| 139 |
- |
* more than FUNC_MAX_ARGS parameters. We have to test here to protect |
- |
| 140 |
- |
* against array overruns, etc. Of course, this may not be a function, |
- |
| 141 |
- |
* but the test doesn't hurt. |
- |
| 142 |
- |
*/ |
- |
| 143 |
- |
if (list_length(fargs) > FUNC_MAX_ARGS) |
- |
| 144 |
- |
ereport(ERROR, |
- |
| 145 |
- |
(errcode(ERRCODE_TOO_MANY_ARGUMENTS), |
- |
| 146 |
- |
errmsg_plural("cannot pass more than %d argument to a function", |
- |
| 147 |
- |
"cannot pass more than %d arguments to a function", |
- |
| 148 |
- |
FUNC_MAX_ARGS, |
- |
| 149 |
- |
FUNC_MAX_ARGS), |
- |
| 150 |
- |
parser_errposition(pstate, location))); |
- |
| 151 |
- |
|
- |
| 152 |
- |
/* |
- |
| 153 |
- |
* Extract arg type info in preparation for function lookup. |
- |
| 154 |
- |
* |
- |
| 155 |
- |
* If any arguments are Param markers of type VOID, we discard them from |
- |
| 156 |
- |
* the parameter list. This is a hack to allow the JDBC driver to not have |
- |
| 157 |
- |
* to distinguish "input" and "output" parameter symbols while parsing |
- |
| 158 |
- |
* function-call constructs. Don't do this if dealing with column syntax, |
- |
| 159 |
- |
* nor if we had WITHIN GROUP (because in that case it's critical to keep |
- |
| 160 |
- |
* the argument count unchanged). |
- |
| 161 |
- |
*/ |
- |
| 162 |
- |
nargs = 0; |
- |
| 163 |
- |
foreach(l, fargs) |
- |
| 164 |
- |
{ |
- |
| 165 |
- |
Node *arg = lfirst(l); |
- |
| 166 |
- |
Oid argtype = exprType(arg); |
- |
| 167 |
- |
|
- |
| 168 |
- |
if (argtype == VOIDOID && IsA(arg, Param) && |
- |
| 169 |
- |
!is_column && !agg_within_group) |
- |
| 170 |
- |
{ |
- |
| 171 |
- |
fargs = foreach_delete_current(fargs, l); |
- |
| 172 |
- |
continue; |
- |
| 173 |
- |
} |
- |
| 174 |
- |
|
- |
| 175 |
- |
actual_arg_types[nargs++] = argtype; |
- |
| 176 |
- |
} |
- |
| 177 |
- |
|
- |
| 178 |
- |
/* |
- |
| 179 |
- |
* Check for named arguments; if there are any, build a list of names. |
- |
| 180 |
- |
* |
- |
| 181 |
- |
* We allow mixed notation (some named and some not), but only with all |
- |
| 182 |
- |
* the named parameters after all the unnamed ones. So the name list |
- |
| 183 |
- |
* corresponds to the last N actual parameters and we don't need any extra |
- |
| 184 |
- |
* bookkeeping to match things up. |
- |
| 185 |
- |
*/ |
- |
| 186 |
- |
argnames = NIL; |
- |
| 187 |
- |
foreach(l, fargs) |
- |
| 188 |
- |
{ |
- |
| 189 |
- |
Node *arg = lfirst(l); |
- |
| 190 |
- |
|
- |
| 191 |
- |
if (IsA(arg, NamedArgExpr)) |
- |
| 192 |
- |
{ |
- |
| 193 |
- |
NamedArgExpr *na = (NamedArgExpr *) arg; |
- |
| 194 |
- |
ListCell *lc; |
- |
| 195 |
- |
|
- |
| 196 |
- |
/* Reject duplicate arg names */ |
- |
| 197 |
- |
foreach(lc, argnames) |
- |
| 198 |
- |
{ |
- |
| 199 |
- |
if (strcmp(na->name, (char *) lfirst(lc)) == 0) |
- |
| 200 |
- |
ereport(ERROR, |
- |
| 201 |
- |
(errcode(ERRCODE_SYNTAX_ERROR), |
- |
| 202 |
- |
errmsg("argument name \"%s\" used more than once", |
- |
| 203 |
- |
na->name), |
- |
| 204 |
- |
parser_errposition(pstate, na->location))); |
- |
| 205 |
- |
} |
- |
| 206 |
- |
argnames = lappend(argnames, na->name); |
- |
| 207 |
- |
} |
- |
| 208 |
- |
else |
- |
| 209 |
- |
{ |
- |
| 210 |
- |
if (argnames != NIL) |
- |
| 211 |
- |
ereport(ERROR, |
- |
| 212 |
- |
(errcode(ERRCODE_SYNTAX_ERROR), |
- |
| 213 |
- |
errmsg("positional argument cannot follow named argument"), |
- |
| 214 |
- |
parser_errposition(pstate, exprLocation(arg)))); |
- |
| 215 |
- |
} |
- |
| 216 |
- |
} |
- |
| 217 |
- |
|
- |
| 218 |
- |
if (fargs) |
- |
| 219 |
- |
{ |
- |
| 220 |
- |
first_arg = linitial(fargs); |
- |
| 221 |
- |
Assert(first_arg != NULL); |
- |
| 222 |
- |
} |
- |
| 223 |
- |
|
- |
| 224 |
- |
/* |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 225 |
- |
* Inside an RPR DEFINE clause, an unqualified call to one of the row |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 226 |
- |
* pattern navigation names PREV/NEXT/FIRST/LAST denotes the navigation |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 227 |
- |
* operation, not an ordinary function. Just note that here; the catalog |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 228 |
- |
* lookup is skipped and the RPRNavExpr is built at the end, after the |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 229 |
- |
* common decoration checks have run (see the could_be_rpr_nav handling |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 230 |
- |
* below). A schema-qualified call is the explicit way to reach an |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 231 |
- |
* ordinary function of one of these names. |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 232 |
- |
*/ |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 233 |
261484 |
if (!is_column && !proc_call && |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 234 |
252657 |
pstate->p_expr_kind == EXPR_KIND_RPR_DEFINE && |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 235 |
1660 |
list_length(funcname) == 1) |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 236 |
- |
{ |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 237 |
1648 |
const char *name = strVal(linitial(funcname)); |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 238 |
- |
|
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 239 |
1648 |
if (strcmp(name, "prev") == 0 || |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 240 |
588 |
strcmp(name, "next") == 0 || |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 241 |
423 |
strcmp(name, "first") == 0 || |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 242 |
192 |
strcmp(name, "last") == 0) |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 243 |
1596 |
could_be_rpr_nav = true; |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 244 |
- |
} |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 245 |
- |
|
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 246 |
- |
/* |
- |
| 247 |
- |
* Decide whether it's legitimate to consider the construct to be a column |
- |
| 248 |
- |
* projection. For that, there has to be a single argument of complex |
- |
| 249 |
- |
* type, the function name must not be qualified, and there cannot be any |
- |
| 250 |
- |
* syntactic decoration that'd require it to be a function (such as |
- |
| 251 |
- |
* aggregate or variadic decoration, or named arguments). |
- |
| 252 |
- |
*/ |
- |
| 253 |
- |
could_be_projection = (nargs == 1 && !proc_call && |
- |
| 254 |
- |
agg_order == NIL && agg_filter == NULL && |
- |
| 255 |
- |
!agg_star && !agg_distinct && over == NULL && |
- |
| 256 |
- |
!func_variadic && argnames == NIL && |
- |
| 257 |
- |
list_length(funcname) == 1 && |
- |
| 258 |
- |
(actual_arg_types[0] == RECORDOID || |
- |
| 259 |
- |
ISCOMPLEX(actual_arg_types[0]))); |
- |
| 260 |
- |
|
- |
| 261 |
- |
/* |
- |
| 262 |
- |
* If it's column syntax, check for column projection case first. |
- |
| 263 |
- |
*/ |
- |
| 264 |
- |
if (could_be_projection && is_column) |
- |
| 265 |
- |
{ |
- |
| 266 |
- |
retval = ParseComplexProjection(pstate, |
- |
| 267 |
- |
strVal(linitial(funcname)), |
- |
| 268 |
- |
first_arg, |
- |
| 269 |
- |
location); |
- |
| 270 |
- |
if (retval) |
- |
| 271 |
- |
return retval; |
- |
| 272 |
- |
|
- |
| 273 |
- |
/* |
- |
| 274 |
- |
* If ParseComplexProjection doesn't recognize it as a projection, |
- |
| 275 |
- |
* just press on. |
- |
| 276 |
- |
*/ |
- |
| 277 |
- |
} |
- |
| 278 |
- |
|
- |
| 279 |
- |
/* |
- |
| 280 |
- |
* func_get_detail looks up the function in the catalogs, does |
- |
| 281 |
- |
* disambiguation for polymorphic functions, handles inheritance, and |
- |
| 282 |
- |
* returns the funcid and type and set or singleton status of the |
- |
| 283 |
- |
* function's return value. It also returns the true argument types to |
- |
| 284 |
- |
* the function. |
- |
| 285 |
- |
* |
- |
| 286 |
- |
* Note: for a named-notation or variadic function call, the reported |
- |
| 287 |
- |
* "true" types aren't really what is in pg_proc: the types are reordered |
- |
| 288 |
- |
* to match the given argument order of named arguments, and a variadic |
- |
| 289 |
- |
* argument is replaced by a suitable number of copies of its element |
- |
| 290 |
- |
* type. We'll fix up the variadic case below. We may also have to deal |
- |
| 291 |
- |
* with default arguments. |
- |
| 292 |
- |
*/ |
- |
| 293 |
- |
|
- |
| 294 |
253145 |
if (!could_be_rpr_nav) |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 295 |
- |
{ |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 296 |
251549 |
setup_parser_errposition_callback(&pcbstate, pstate, location); |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 297 |
- |
|
- |
| 298 |
503098 |
fdresult = func_get_detail(funcname, fargs, argnames, nargs, |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 299 |
- |
actual_arg_types, |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 300 |
- |
!func_variadic, true, proc_call, |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 301 |
- |
&fgc_flags, |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 302 |
- |
&funcid, &rettype, &retset, |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 303 |
- |
&nvargs, &vatype, |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 304 |
251549 |
&declared_arg_types, &argdefaults); |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 305 |
- |
|
- |
| 306 |
251549 |
cancel_parser_errposition_callback(&pcbstate); |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 307 |
- |
} |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 308 |
- |
else |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 309 |
- |
{ |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 310 |
- |
/* |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 311 |
- |
* A recognized navigation name skips catalog lookup entirely. Treat |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 312 |
- |
* it as an ordinary function so the common wrong-kind-of-routine and |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 313 |
- |
* decoration checks below run with the existing messages, then route |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 314 |
- |
* to ParseRPRNavCall to build the RPRNavExpr. |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 315 |
- |
*/ |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 316 |
1596 |
Assert(!proc_call); |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 317 |
- |
|
b8d226bSetup cursor position for schema-qualified elements |
| 318 |
- |
fdresult = FUNCDETAIL_NORMAL; |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 319 |
- |
} |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 320 |
- |
|
- |
| 321 |
- |
/* |
- |
| 322 |
- |
* Check for various wrong-kind-of-routine cases. |
- |
| 323 |
- |
*/ |
- |
| 324 |
- |
|
- |
| 325 |
- |
/* If this is a CALL, reject things that aren't procedures */ |
- |
| 326 |
- |
if (proc_call && |
- |
| 327 |
- |
(fdresult == FUNCDETAIL_NORMAL || |
- |
| 328 |
- |
fdresult == FUNCDETAIL_AGGREGATE || |
- |
| 329 |
- |
fdresult == FUNCDETAIL_WINDOWFUNC || |
- |
| 330 |
- |
fdresult == FUNCDETAIL_COERCION)) |
- |
| 331 |
- |
ereport(ERROR, |
- |
| 332 |
- |
(errcode(ERRCODE_WRONG_OBJECT_TYPE), |
- |
| 333 |
- |
errmsg("%s is not a procedure", |
- |
| 334 |
- |
func_signature_string(funcname, nargs, |
- |
| 335 |
- |
argnames, |
- |
| 336 |
- |
actual_arg_types)), |
- |
| 337 |
- |
errhint("To call a function, use SELECT."), |
- |
| 338 |
- |
parser_errposition(pstate, location))); |
- |
| 339 |
- |
/* Conversely, if not a CALL, reject procedures */ |
- |
| 340 |
- |
if (fdresult == FUNCDETAIL_PROCEDURE && !proc_call) |
- |
| 341 |
- |
ereport(ERROR, |
- |
| 342 |
- |
(errcode(ERRCODE_WRONG_OBJECT_TYPE), |
- |
| 343 |
- |
errmsg("%s is a procedure", |
- |
| 344 |
- |
func_signature_string(funcname, nargs, |
- |
| 345 |
- |
argnames, |
- |
| 346 |
- |
actual_arg_types)), |
- |
| 347 |
- |
errhint("To call a procedure, use CALL."), |
- |
| 348 |
- |
parser_errposition(pstate, location))); |
- |
| 349 |
- |
|
- |
| 350 |
- |
if (fdresult == FUNCDETAIL_NORMAL || |
- |
| 351 |
- |
fdresult == FUNCDETAIL_PROCEDURE || |
- |
| 352 |
- |
fdresult == FUNCDETAIL_COERCION) |
- |
| 353 |
- |
{ |
- |
| 354 |
- |
/* |
- |
| 355 |
- |
* In these cases, complain if there was anything indicating it must |
- |
| 356 |
- |
* be an aggregate or window function. |
- |
| 357 |
- |
*/ |
- |
| 358 |
- |
if (agg_star) |
- |
| 359 |
- |
ereport(ERROR, |
- |
| 360 |
- |
(errcode(ERRCODE_WRONG_OBJECT_TYPE), |
- |
| 361 |
- |
errmsg("%s(*) specified, but %s is not an aggregate function", |
- |
| 362 |
- |
NameListToString(funcname), |
- |
| 363 |
- |
NameListToString(funcname)), |
- |
| 364 |
- |
parser_errposition(pstate, location))); |
- |
| 365 |
- |
if (agg_distinct) |
- |
| 366 |
- |
ereport(ERROR, |
- |
| 367 |
- |
(errcode(ERRCODE_WRONG_OBJECT_TYPE), |
- |
| 368 |
- |
errmsg("DISTINCT specified, but %s is not an aggregate function", |
- |
| 369 |
- |
NameListToString(funcname)), |
- |
| 370 |
- |
parser_errposition(pstate, location))); |
- |
| 371 |
- |
if (agg_within_group) |
- |
| 372 |
- |
ereport(ERROR, |
- |
| 373 |
- |
(errcode(ERRCODE_WRONG_OBJECT_TYPE), |
- |
| 374 |
- |
errmsg("WITHIN GROUP specified, but %s is not an aggregate function", |
- |
| 375 |
- |
NameListToString(funcname)), |
- |
| 376 |
- |
parser_errposition(pstate, location))); |
- |
| 377 |
- |
if (agg_order != NIL) |
- |
| 378 |
- |
ereport(ERROR, |
- |
| 379 |
- |
(errcode(ERRCODE_WRONG_OBJECT_TYPE), |
- |
| 380 |
- |
errmsg("ORDER BY specified, but %s is not an aggregate function", |
- |
| 381 |
- |
NameListToString(funcname)), |
- |
| 382 |
- |
parser_errposition(pstate, location))); |
- |
| 383 |
- |
if (agg_filter) |
- |
| 384 |
- |
ereport(ERROR, |
- |
| 385 |
- |
(errcode(ERRCODE_WRONG_OBJECT_TYPE), |
- |
| 386 |
- |
errmsg("FILTER specified, but %s is not an aggregate function", |
- |
| 387 |
- |
NameListToString(funcname)), |
- |
| 388 |
- |
parser_errposition(pstate, location))); |
- |
| 389 |
- |
if (over) |
- |
| 390 |
- |
ereport(ERROR, |
- |
| 391 |
- |
(errcode(ERRCODE_WRONG_OBJECT_TYPE), |
- |
| 392 |
- |
errmsg("OVER specified, but %s is not a window function nor an aggregate function", |
- |
| 393 |
- |
NameListToString(funcname)), |
- |
| 394 |
- |
parser_errposition(pstate, location))); |
- |
| 395 |
- |
} |
- |
| 396 |
- |
|
- |
| 397 |
- |
/* |
- |
| 398 |
- |
* NULL TREATEMENT is only allowed for window functions per spec. |
- |
| 399 |
- |
*/ |
- |
| 400 |
- |
if (fdresult != FUNCDETAIL_WINDOWFUNC && ignore_nulls != NO_NULLTREATMENT) |
- |
| 401 |
- |
ereport(ERROR, |
- |
| 402 |
- |
errcode(ERRCODE_WRONG_OBJECT_TYPE), |
- |
| 403 |
- |
errmsg("only window functions accept RESPECT/IGNORE NULLS"), |
- |
| 404 |
- |
parser_errposition(pstate, location)); |
- |
| 405 |
- |
|
- |
| 406 |
- |
/* |
- |
| 407 |
- |
* So far so good, so do some fdresult-type-specific processing. |
- |
| 408 |
- |
*/ |
- |
| 409 |
- |
if (fdresult == FUNCDETAIL_NORMAL || fdresult == FUNCDETAIL_PROCEDURE) |
- |
| 410 |
- |
{ |
- |
| 411 |
- |
/* Nothing special to do for these cases. */ |
- |
| 412 |
- |
} |
- |
| 413 |
- |
else if (fdresult == FUNCDETAIL_AGGREGATE) |
- |
| 414 |
- |
{ |
- |
| 415 |
- |
/* |
- |
| 416 |
- |
* It's an aggregate; fetch needed info from the pg_aggregate entry. |
- |
| 417 |
- |
*/ |
- |
| 418 |
- |
HeapTuple tup; |
- |
| 419 |
- |
Form_pg_aggregate classForm; |
- |
| 420 |
- |
int catDirectArgs; |
- |
| 421 |
- |
|
- |
| 422 |
- |
tup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(funcid)); |
- |
| 423 |
- |
if (!HeapTupleIsValid(tup)) /* should not happen */ |
- |
| 424 |
- |
elog(ERROR, "cache lookup failed for aggregate %u", funcid); |
- |
| 425 |
- |
classForm = (Form_pg_aggregate) GETSTRUCT(tup); |
- |
| 426 |
- |
aggkind = classForm->aggkind; |
- |
| 427 |
- |
catDirectArgs = classForm->aggnumdirectargs; |
- |
| 428 |
- |
ReleaseSysCache(tup); |
- |
| 429 |
- |
|
- |
| 430 |
- |
/* Now check various disallowed cases. */ |
- |
| 431 |
- |
if (AGGKIND_IS_ORDERED_SET(aggkind)) |
- |
| 432 |
- |
{ |
- |
| 433 |
- |
int numAggregatedArgs; |
- |
| 434 |
- |
int numDirectArgs; |
- |
| 435 |
- |
|
- |
| 436 |
- |
if (!agg_within_group) |
- |
| 437 |
- |
ereport(ERROR, |
- |
| 438 |
- |
(errcode(ERRCODE_WRONG_OBJECT_TYPE), |
- |
| 439 |
- |
errmsg("WITHIN GROUP is required for ordered-set aggregate %s", |
- |
| 440 |
- |
NameListToString(funcname)), |
- |
| 441 |
- |
parser_errposition(pstate, location))); |
- |
| 442 |
- |
if (over) |
- |
| 443 |
- |
ereport(ERROR, |
- |
| 444 |
- |
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
- |
| 445 |
- |
errmsg("OVER is not supported for ordered-set aggregate %s", |
- |
| 446 |
- |
NameListToString(funcname)), |
- |
| 447 |
- |
parser_errposition(pstate, location))); |
- |
| 448 |
- |
/* gram.y rejects DISTINCT + WITHIN GROUP */ |
- |
| 449 |
- |
Assert(!agg_distinct); |
- |
| 450 |
- |
/* gram.y rejects VARIADIC + WITHIN GROUP */ |
- |
| 451 |
- |
Assert(!func_variadic); |
- |
| 452 |
- |
|
- |
| 453 |
- |
/* |
- |
| 454 |
- |
* Since func_get_detail was working with an undifferentiated list |
- |
| 455 |
- |
* of arguments, it might have selected an aggregate that doesn't |
- |
| 456 |
- |
* really match because it requires a different division of direct |
- |
| 457 |
- |
* and aggregated arguments. Check that the number of direct |
- |
| 458 |
- |
* arguments is actually OK; if not, throw an "undefined function" |
- |
| 459 |
- |
* error, similarly to the case where a misplaced ORDER BY is used |
- |
| 460 |
- |
* in a regular aggregate call. |
- |
| 461 |
- |
*/ |
- |
| 462 |
- |
numAggregatedArgs = list_length(agg_order); |
- |
| 463 |
- |
numDirectArgs = nargs - numAggregatedArgs; |
- |
| 464 |
- |
Assert(numDirectArgs >= 0); |
- |
| 465 |
- |
|
- |
| 466 |
- |
if (!OidIsValid(vatype)) |
- |
| 467 |
- |
{ |
- |
| 468 |
- |
/* Test is simple if aggregate isn't variadic */ |
- |
| 469 |
- |
if (numDirectArgs != catDirectArgs) |
- |
| 470 |
- |
ereport(ERROR, |
- |
| 471 |
- |
(errcode(ERRCODE_UNDEFINED_FUNCTION), |
- |
| 472 |
- |
errmsg("function %s does not exist", |
- |
| 473 |
- |
func_signature_string(funcname, nargs, |
- |
| 474 |
- |
argnames, |
- |
| 475 |
- |
actual_arg_types)), |
- |
| 476 |
- |
errhint_plural("There is an ordered-set aggregate %s, but it requires %d direct argument, not %d.", |
- |
| 477 |
- |
"There is an ordered-set aggregate %s, but it requires %d direct arguments, not %d.", |
- |
| 478 |
- |
catDirectArgs, |
- |
| 479 |
- |
NameListToString(funcname), |
- |
| 480 |
- |
catDirectArgs, numDirectArgs), |
- |
| 481 |
- |
parser_errposition(pstate, location))); |
- |
| 482 |
- |
} |
- |
| 483 |
- |
else |
- |
| 484 |
- |
{ |
- |
| 485 |
- |
/* |
- |
| 486 |
- |
* If it's variadic, we have two cases depending on whether |
- |
| 487 |
- |
* the agg was "... ORDER BY VARIADIC" or "..., VARIADIC ORDER |
- |
| 488 |
- |
* BY VARIADIC". It's the latter if catDirectArgs equals |
- |
| 489 |
- |
* pronargs; to save a catalog lookup, we reverse-engineer |
- |
| 490 |
- |
* pronargs from the info we got from func_get_detail. |
- |
| 491 |
- |
*/ |
- |
| 492 |
- |
int pronargs; |
- |
| 493 |
- |
|
- |
| 494 |
- |
pronargs = nargs; |
- |
| 495 |
- |
if (nvargs > 1) |
- |
| 496 |
- |
pronargs -= nvargs - 1; |
- |
| 497 |
- |
if (catDirectArgs < pronargs) |
- |
| 498 |
- |
{ |
- |
| 499 |
- |
/* VARIADIC isn't part of direct args, so still easy */ |
- |
| 500 |
- |
if (numDirectArgs != catDirectArgs) |
- |
| 501 |
- |
ereport(ERROR, |
- |
| 502 |
- |
(errcode(ERRCODE_UNDEFINED_FUNCTION), |
- |
| 503 |
- |
errmsg("function %s does not exist", |
- |
| 504 |
- |
func_signature_string(funcname, nargs, |
- |
| 505 |
- |
argnames, |
- |
| 506 |
- |
actual_arg_types)), |
- |
| 507 |
- |
errhint_plural("There is an ordered-set aggregate %s, but it requires %d direct argument, not %d.", |
- |
| 508 |
- |
"There is an ordered-set aggregate %s, but it requires %d direct arguments, not %d.", |
- |
| 509 |
- |
catDirectArgs, |
- |
| 510 |
- |
NameListToString(funcname), |
- |
| 511 |
- |
catDirectArgs, numDirectArgs), |
- |
| 512 |
- |
parser_errposition(pstate, location))); |
- |
| 513 |
- |
} |
- |
| 514 |
- |
else |
- |
| 515 |
- |
{ |
- |
| 516 |
- |
/* |
- |
| 517 |
- |
* Both direct and aggregated args were declared variadic. |
- |
| 518 |
- |
* For a standard ordered-set aggregate, it's okay as long |
- |
| 519 |
- |
* as there aren't too few direct args. For a |
- |
| 520 |
- |
* hypothetical-set aggregate, we assume that the |
- |
| 521 |
- |
* hypothetical arguments are those that matched the |
- |
| 522 |
- |
* variadic parameter; there must be just as many of them |
- |
| 523 |
- |
* as there are aggregated arguments. |
- |
| 524 |
- |
*/ |
- |
| 525 |
- |
if (aggkind == AGGKIND_HYPOTHETICAL) |
- |
| 526 |
- |
{ |
- |
| 527 |
- |
if (nvargs != 2 * numAggregatedArgs) |
- |
| 528 |
- |
ereport(ERROR, |
- |
| 529 |
- |
(errcode(ERRCODE_UNDEFINED_FUNCTION), |
- |
| 530 |
- |
errmsg("function %s does not exist", |
- |
| 531 |
- |
func_signature_string(funcname, nargs, |
- |
| 532 |
- |
argnames, |
- |
| 533 |
- |
actual_arg_types)), |
- |
| 534 |
- |
errhint("To use the hypothetical-set aggregate %s, the number of hypothetical direct arguments (here %d) must match the number of ordering columns (here %d).", |
- |
| 535 |
- |
NameListToString(funcname), |
- |
| 536 |
- |
nvargs - numAggregatedArgs, numAggregatedArgs), |
- |
| 537 |
- |
parser_errposition(pstate, location))); |
- |
| 538 |
- |
} |
- |
| 539 |
- |
else |
- |
| 540 |
- |
{ |
- |
| 541 |
- |
if (nvargs <= numAggregatedArgs) |
- |
| 542 |
- |
ereport(ERROR, |
- |
| 543 |
- |
(errcode(ERRCODE_UNDEFINED_FUNCTION), |
- |
| 544 |
- |
errmsg("function %s does not exist", |
- |
| 545 |
- |
func_signature_string(funcname, nargs, |
- |
| 546 |
- |
argnames, |
- |
| 547 |
- |
actual_arg_types)), |
- |
| 548 |
- |
errhint_plural("There is an ordered-set aggregate %s, but it requires at least %d direct argument.", |
- |
| 549 |
- |
"There is an ordered-set aggregate %s, but it requires at least %d direct arguments.", |
- |
| 550 |
- |
catDirectArgs, |
- |
| 551 |
- |
NameListToString(funcname), |
- |
| 552 |
- |
catDirectArgs), |
- |
| 553 |
- |
parser_errposition(pstate, location))); |
- |
| 554 |
- |
} |
- |
| 555 |
- |
} |
- |
| 556 |
- |
} |
- |
| 557 |
- |
|
- |
| 558 |
- |
/* Check type matching of hypothetical arguments */ |
- |
| 559 |
- |
if (aggkind == AGGKIND_HYPOTHETICAL) |
- |
| 560 |
- |
unify_hypothetical_args(pstate, fargs, numAggregatedArgs, |
- |
| 561 |
- |
actual_arg_types, declared_arg_types); |
- |
| 562 |
- |
} |
- |
| 563 |
- |
else |
- |
| 564 |
- |
{ |
- |
| 565 |
- |
/* Normal aggregate, so it can't have WITHIN GROUP */ |
- |
| 566 |
- |
if (agg_within_group) |
- |
| 567 |
- |
ereport(ERROR, |
- |
| 568 |
- |
(errcode(ERRCODE_WRONG_OBJECT_TYPE), |
- |
| 569 |
- |
errmsg("%s is not an ordered-set aggregate, so it cannot have WITHIN GROUP", |
- |
| 570 |
- |
NameListToString(funcname)), |
- |
| 571 |
- |
parser_errposition(pstate, location))); |
- |
| 572 |
- |
} |
- |
| 573 |
- |
} |
- |
| 574 |
- |
else if (fdresult == FUNCDETAIL_WINDOWFUNC) |
- |
| 575 |
- |
{ |
- |
| 576 |
- |
/* |
- |
| 577 |
- |
* True window functions must be called with a window definition. |
- |
| 578 |
- |
*/ |
- |
| 579 |
- |
if (!over) |
- |
| 580 |
- |
ereport(ERROR, |
- |
| 581 |
- |
(errcode(ERRCODE_WRONG_OBJECT_TYPE), |
- |
| 582 |
- |
errmsg("window function %s requires an OVER clause", |
- |
| 583 |
- |
NameListToString(funcname)), |
- |
| 584 |
- |
parser_errposition(pstate, location))); |
- |
| 585 |
- |
/* And, per spec, WITHIN GROUP isn't allowed */ |
- |
| 586 |
- |
if (agg_within_group) |
- |
| 587 |
- |
ereport(ERROR, |
- |
| 588 |
- |
(errcode(ERRCODE_WRONG_OBJECT_TYPE), |
- |
| 589 |
- |
errmsg("window function %s cannot have WITHIN GROUP", |
- |
| 590 |
- |
NameListToString(funcname)), |
- |
| 591 |
- |
parser_errposition(pstate, location))); |
- |
| 592 |
- |
} |
- |
| 593 |
- |
else if (fdresult == FUNCDETAIL_COERCION) |
- |
| 594 |
- |
{ |
- |
| 595 |
- |
/* |
- |
| 596 |
- |
* We interpreted it as a type coercion. coerce_type can handle these |
- |
| 597 |
- |
* cases, so why duplicate code... |
- |
| 598 |
- |
*/ |
- |
| 599 |
- |
return coerce_type(pstate, linitial(fargs), |
- |
| 600 |
- |
actual_arg_types[0], rettype, -1, |
- |
| 601 |
- |
COERCION_EXPLICIT, COERCE_EXPLICIT_CALL, location); |
- |
| 602 |
- |
} |
- |
| 603 |
- |
else if (fdresult == FUNCDETAIL_MULTIPLE) |
- |
| 604 |
- |
{ |
- |
| 605 |
- |
/* |
- |
| 606 |
- |
* We found multiple possible functional matches. If we are dealing |
- |
| 607 |
- |
* with attribute notation, return failure, letting the caller report |
- |
| 608 |
- |
* "no such column" (we already determined there wasn't one). If |
- |
| 609 |
- |
* dealing with function notation, report "ambiguous function", |
- |
| 610 |
- |
* regardless of whether there's also a column by this name. |
- |
| 611 |
- |
*/ |
- |
| 612 |
- |
if (is_column) |
- |
| 613 |
- |
return NULL; |
- |
| 614 |
- |
|
- |
| 615 |
- |
if (proc_call) |
- |
| 616 |
- |
ereport(ERROR, |
- |
| 617 |
- |
(errcode(ERRCODE_AMBIGUOUS_FUNCTION), |
- |
| 618 |
- |
errmsg("procedure %s is not unique", |
- |
| 619 |
- |
func_signature_string(funcname, nargs, argnames, |
- |
| 620 |
- |
actual_arg_types)), |
- |
| 621 |
- |
errdetail("Could not choose a best candidate procedure."), |
- |
| 622 |
- |
errhint("You might need to add explicit type casts."), |
- |
| 623 |
- |
parser_errposition(pstate, location))); |
- |
| 624 |
- |
else |
- |
| 625 |
- |
ereport(ERROR, |
- |
| 626 |
- |
(errcode(ERRCODE_AMBIGUOUS_FUNCTION), |
- |
| 627 |
- |
errmsg("function %s is not unique", |
- |
| 628 |
- |
func_signature_string(funcname, nargs, argnames, |
- |
| 629 |
- |
actual_arg_types)), |
- |
| 630 |
- |
errdetail("Could not choose a best candidate function."), |
- |
| 631 |
- |
errhint("You might need to add explicit type casts."), |
- |
| 632 |
- |
parser_errposition(pstate, location))); |
- |
| 633 |
- |
} |
- |
| 634 |
- |
else |
- |
| 635 |
- |
{ |
- |
| 636 |
- |
/* |
- |
| 637 |
- |
* Not found as a function. If we are dealing with attribute |
- |
| 638 |
- |
* notation, return failure, letting the caller report "no such |
- |
| 639 |
- |
* column" (we already determined there wasn't one). |
- |
| 640 |
- |
*/ |
- |
| 641 |
- |
if (is_column) |
- |
| 642 |
- |
return NULL; |
- |
| 643 |
- |
|
- |
| 644 |
- |
/* |
- |
| 645 |
- |
* Check for column projection interpretation, since we didn't before. |
- |
| 646 |
- |
*/ |
- |
| 647 |
- |
if (could_be_projection) |
- |
| 648 |
- |
{ |
- |
| 649 |
- |
retval = ParseComplexProjection(pstate, |
- |
| 650 |
- |
strVal(linitial(funcname)), |
- |
| 651 |
- |
first_arg, |
- |
| 652 |
- |
location); |
- |
| 653 |
- |
if (retval) |
- |
| 654 |
- |
return retval; |
- |
| 655 |
- |
} |
- |
| 656 |
- |
|
- |
| 657 |
- |
/* |
- |
| 658 |
- |
* No function, and no column either. Since we're dealing with |
- |
| 659 |
- |
* function notation, report "function/procedure does not exist". |
- |
| 660 |
- |
* Depending on what was returned in fgc_flags, we can add some color |
- |
| 661 |
- |
* to that with detail or hint messages. |
- |
| 662 |
- |
*/ |
- |
| 663 |
- |
if (list_length(agg_order) > 1 && !agg_within_group) |
- |
| 664 |
- |
{ |
- |
| 665 |
- |
/* It's agg(x, ORDER BY y,z) ... perhaps misplaced ORDER BY */ |
- |
| 666 |
- |
ereport(ERROR, |
- |
| 667 |
- |
(errcode(ERRCODE_UNDEFINED_FUNCTION), |
- |
| 668 |
- |
errmsg("function %s does not exist", |
- |
| 669 |
- |
func_signature_string(funcname, nargs, argnames, |
- |
| 670 |
- |
actual_arg_types)), |
- |
| 671 |
- |
errdetail("No aggregate function matches the given name and argument types."), |
- |
| 672 |
- |
errhint("Perhaps you misplaced ORDER BY; ORDER BY must appear " |
- |
| 673 |
- |
"after all regular arguments of the aggregate."), |
- |
| 674 |
- |
parser_errposition(pstate, location))); |
- |
| 675 |
- |
} |
- |
| 676 |
- |
else if (proc_call) |
- |
| 677 |
- |
ereport(ERROR, |
- |
| 678 |
- |
(errcode(ERRCODE_UNDEFINED_FUNCTION), |
- |
| 679 |
- |
errmsg("procedure %s does not exist", |
- |
| 680 |
- |
func_signature_string(funcname, nargs, argnames, |
- |
| 681 |
- |
actual_arg_types)), |
- |
| 682 |
- |
func_lookup_failure_details(fgc_flags, argnames, |
- |
| 683 |
- |
proc_call), |
- |
| 684 |
- |
parser_errposition(pstate, location))); |
- |
| 685 |
- |
else |
- |
| 686 |
- |
ereport(ERROR, |
- |
| 687 |
- |
(errcode(ERRCODE_UNDEFINED_FUNCTION), |
- |
| 688 |
- |
errmsg("function %s does not exist", |
- |
| 689 |
- |
func_signature_string(funcname, nargs, argnames, |
- |
| 690 |
- |
actual_arg_types)), |
- |
| 691 |
- |
func_lookup_failure_details(fgc_flags, argnames, |
- |
| 692 |
- |
proc_call), |
- |
| 693 |
- |
parser_errposition(pstate, location))); |
- |
| 694 |
- |
} |
- |
| 695 |
- |
|
- |
| 696 |
- |
/* |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 697 |
- |
* A recognized navigation name has now passed the common decoration and |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 698 |
- |
* wrong-kind checks above; build the RPRNavExpr. No fallback to function |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 699 |
- |
* resolution ever happens here. |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 700 |
- |
*/ |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 701 |
252179 |
if (could_be_rpr_nav) |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 702 |
1568 |
return ParseRPRNavCall(pstate, funcname, fargs, argnames, fn, |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 703 |
- |
location); |
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 704 |
- |
|
7f135d9Recognize row pattern navigation operations by name in DEFINE |
| 705 |
- |
/* |
- |
| 706 |
- |
* If there are default arguments, we have to include their types in |
- |
| 707 |
- |
* actual_arg_types for the purpose of checking generic type consistency. |
- |
| 708 |
- |
* However, we do NOT put them into the generated parse node, because |
- |
| 709 |
- |
* their actual values might change before the query gets run. The |
- |
| 710 |
- |
* planner has to insert the up-to-date values at plan time. |
- |
| 711 |
- |
*/ |
- |
| 712 |
- |
nargsplusdefs = nargs; |
- |
| 713 |
- |
foreach(l, argdefaults) |
- |
| 714 |
- |
{ |
- |
| 715 |
- |
Node *expr = (Node *) lfirst(l); |
- |
| 716 |
- |
|
- |
| 717 |
- |
/* probably shouldn't happen ... */ |
- |
| 718 |
- |
if (nargsplusdefs >= FUNC_MAX_ARGS) |
- |
| 719 |
- |
ereport(ERROR, |
- |
| 720 |
- |
(errcode(ERRCODE_TOO_MANY_ARGUMENTS), |
- |
| 721 |
- |
errmsg_plural("cannot pass more than %d argument to a function", |
- |
| 722 |
- |
"cannot pass more than %d arguments to a function", |
- |
| 723 |
- |
FUNC_MAX_ARGS, |
- |
| 724 |
- |
FUNC_MAX_ARGS), |
- |
| 725 |
- |
parser_errposition(pstate, location))); |
- |
| 726 |
- |
|
- |
| 727 |
- |
actual_arg_types[nargsplusdefs++] = exprType(expr); |
- |
| 728 |
- |
} |
- |
| 729 |
- |
|
- |
| 730 |
- |
/* |
- |
| 731 |
- |
* enforce consistency with polymorphic argument and return types, |
- |
| 732 |
- |
* possibly adjusting return type or declared_arg_types (which will be |
- |
| 733 |
- |
* used as the cast destination by make_fn_arguments) |
- |
| 734 |
- |
*/ |
- |
| 735 |
- |
rettype = enforce_generic_type_consistency(actual_arg_types, |
- |
| 736 |
- |
declared_arg_types, |
- |
| 737 |
- |
nargsplusdefs, |
- |
| 738 |
- |
rettype, |
- |
| 739 |
- |
false); |
- |
| 740 |
- |
|
- |
| 741 |
- |
/* perform the necessary typecasting of arguments */ |
- |
| 742 |
- |
make_fn_arguments(pstate, fargs, actual_arg_types, declared_arg_types); |
- |
| 743 |
- |
|
- |
| 744 |
- |
/* |
- |
| 745 |
- |
* If the function isn't actually variadic, forget any VARIADIC decoration |
- |
| 746 |
- |
* on the call. (Perhaps we should throw an error instead, but |
- |
| 747 |
- |
* historically we've allowed people to write that.) |
- |
| 748 |
- |
*/ |
- |
| 749 |
- |
if (!OidIsValid(vatype)) |
- |
| 750 |
- |
{ |
- |
| 751 |
- |
Assert(nvargs == 0); |
- |
| 752 |
- |
func_variadic = false; |
- |
| 753 |
- |
} |
- |
| 754 |
- |
|
- |
| 755 |
- |
/* |
- |
| 756 |
- |
* If it's a variadic function call, transform the last nvargs arguments |
- |
| 757 |
- |
* into an array --- unless it's an "any" variadic. |
- |
| 758 |
- |
*/ |
- |
| 759 |
- |
if (nvargs > 0 && vatype != ANYOID) |
- |
| 760 |
- |
{ |
- |
| 761 |
- |
ArrayExpr *newa = makeNode(ArrayExpr); |
- |
| 762 |
- |
int non_var_args = nargs - nvargs; |
- |
| 763 |
- |
List *vargs; |
- |
| 764 |
- |
|
- |
| 765 |
- |
Assert(non_var_args >= 0); |
- |
| 766 |
- |
vargs = list_copy_tail(fargs, non_var_args); |
- |
| 767 |
- |
fargs = list_truncate(fargs, non_var_args); |
- |
| 768 |
- |
|
- |
| 769 |
- |
newa->elements = vargs; |
- |
| 770 |
- |
/* assume all the variadic arguments were coerced to the same type */ |
- |
| 771 |
- |
newa->element_typeid = exprType((Node *) linitial(vargs)); |
- |
| 772 |
- |
newa->array_typeid = get_array_type(newa->element_typeid); |
- |
| 773 |
- |
if (!OidIsValid(newa->array_typeid)) |
- |
| 774 |
- |
ereport(ERROR, |
- |
| 775 |
- |
(errcode(ERRCODE_UNDEFINED_OBJECT), |
- |
| 776 |
- |
errmsg("could not find array type for data type %s", |
- |
| 777 |
- |
format_type_be(newa->element_typeid)), |
- |
| 778 |
- |
parser_errposition(pstate, exprLocation((Node *) vargs)))); |
- |
| 779 |
- |
/* array_collid will be set by parse_collate.c */ |
- |
| 780 |
- |
newa->multidims = false; |
- |
| 781 |
- |
newa->location = exprLocation((Node *) vargs); |
- |
| 782 |
- |
|
- |
| 783 |
- |
fargs = lappend(fargs, newa); |
- |
| 784 |
- |
|
- |
| 785 |
- |
/* We could not have had VARIADIC marking before ... */ |
- |
| 786 |
- |
Assert(!func_variadic); |
- |
| 787 |
- |
/* ... but now, it's a VARIADIC call */ |
- |
| 788 |
- |
func_variadic = true; |
- |
| 789 |
- |
} |
- |
| 790 |
- |
|
- |
| 791 |
- |
/* |
- |
| 792 |
- |
* If an "any" variadic is called with explicit VARIADIC marking, insist |
- |
| 793 |
- |
* that the variadic parameter be of some array type. |
- |
| 794 |
- |
*/ |
- |
| 795 |
- |
if (nargs > 0 && vatype == ANYOID && func_variadic) |
- |
| 796 |
- |
{ |
- |
| 797 |
- |
Oid va_arr_typid = actual_arg_types[nargs - 1]; |
- |
| 798 |
- |
|
- |
| 799 |
- |
if (!OidIsValid(get_base_element_type(va_arr_typid))) |
- |
| 800 |
- |
ereport(ERROR, |
- |
| 801 |
- |
(errcode(ERRCODE_DATATYPE_MISMATCH), |
- |
| 802 |
- |
errmsg("VARIADIC argument must be an array"), |
- |
| 803 |
- |
parser_errposition(pstate, |
- |
| 804 |
- |
exprLocation((Node *) llast(fargs))))); |
- |
| 805 |
- |
} |
- |
| 806 |
- |
|
- |
| 807 |
- |
/* if it returns a set, check that's OK */ |
- |
| 808 |
- |
if (retset) |
- |
| 809 |
- |
check_srf_call_placement(pstate, last_srf, location); |
- |
| 810 |
- |
|
- |
| 811 |
- |
/* build the appropriate output structure */ |
- |
| 812 |
- |
if (fdresult == FUNCDETAIL_NORMAL || fdresult == FUNCDETAIL_PROCEDURE) |
- |
| 813 |
- |
{ |
- |
| 814 |
- |
FuncExpr *funcexpr = makeNode(FuncExpr); |
- |
| 815 |
- |
|
- |
| 816 |
- |
funcexpr->funcid = funcid; |
- |
| 817 |
- |
funcexpr->funcresulttype = rettype; |
- |
| 818 |
- |
funcexpr->funcretset = retset; |
- |
| 819 |
- |
funcexpr->funcvariadic = func_variadic; |
- |
| 820 |
- |
funcexpr->funcformat = funcformat; |
- |
| 821 |
- |
/* funccollid and inputcollid will be set by parse_collate.c */ |
- |
| 822 |
- |
funcexpr->args = fargs; |
- |
| 823 |
- |
funcexpr->location = location; |
- |
| 824 |
- |
|
- |
| 825 |
- |
retval = (Node *) funcexpr; |
- |
| 826 |
- |
} |
- |
| 827 |
- |
else if (fdresult == FUNCDETAIL_AGGREGATE && !over) |
- |
| 828 |
- |
{ |
- |
| 829 |
- |
/* aggregate function */ |
- |
| 830 |
- |
Aggref *aggref = makeNode(Aggref); |
- |
| 831 |
- |
|
- |
| 832 |
- |
aggref->aggfnoid = funcid; |
- |
| 833 |
- |
aggref->aggtype = rettype; |
- |
| 834 |
- |
/* aggcollid and inputcollid will be set by parse_collate.c */ |
- |
| 835 |
- |
aggref->aggtranstype = InvalidOid; /* will be set by planner */ |
- |
| 836 |
- |
/* aggargtypes will be set by transformAggregateCall */ |
- |
| 837 |
- |
/* aggdirectargs and args will be set by transformAggregateCall */ |
- |
| 838 |
- |
/* aggorder and aggdistinct will be set by transformAggregateCall */ |
- |
| 839 |
- |
aggref->aggfilter = agg_filter; |
- |
| 840 |
- |
aggref->aggstar = agg_star; |
- |
| 841 |
- |
aggref->aggvariadic = func_variadic; |
- |
| 842 |
- |
aggref->aggkind = aggkind; |
- |
| 843 |
- |
aggref->aggpresorted = false; |
- |
| 844 |
- |
/* agglevelsup will be set by transformAggregateCall */ |
- |
| 845 |
- |
aggref->aggsplit = AGGSPLIT_SIMPLE; /* planner might change this */ |
- |
| 846 |
- |
aggref->aggno = -1; /* planner will set aggno and aggtransno */ |
- |
| 847 |
- |
aggref->aggtransno = -1; |
- |
| 848 |
- |
aggref->location = location; |
- |
| 849 |
- |
|
- |
| 850 |
- |
/* |
- |
| 851 |
- |
* Reject attempt to call a parameterless aggregate without (*) |
- |
| 852 |
- |
* syntax. This is mere pedantry but some folks insisted ... |
- |
| 853 |
- |
*/ |
- |
| 854 |
- |
if (fargs == NIL && !agg_star && !agg_within_group) |
- |
| 855 |
- |
ereport(ERROR, |
- |
| 856 |
- |
(errcode(ERRCODE_WRONG_OBJECT_TYPE), |
- |
| 857 |
- |
errmsg("%s(*) must be used to call a parameterless aggregate function", |
- |
| 858 |
- |
NameListToString(funcname)), |
- |
| 859 |
- |
parser_errposition(pstate, location))); |
- |
| 860 |
- |
|
- |
| 861 |
- |
if (retset) |
- |
| 862 |
- |
ereport(ERROR, |
- |
| 863 |
- |
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), |
- |
| 864 |
- |
errmsg("aggregates cannot return sets"), |
- |
| 865 |
- |
parser_errposition(pstate, location))); |
- |
| 866 |
- |
|
- |
| 867 |
- |
/* |
- |
| 868 |
- |
* We might want to support named arguments later, but disallow it for |
- |
| 869 |
- |
* now. We'd need to figure out the parsed representation (should the |
- |
| 870 |
- |
* NamedArgExprs go above or below the TargetEntry nodes?) and then |
- |
| 871 |
- |
* teach the planner to reorder the list properly. Or maybe we could |
- |
| 872 |
- |
* make transformAggregateCall do that? However, if you'd also like |
- |
| 873 |
- |
* to allow default arguments for aggregates, we'd need to do it in |
- |
| 874 |
- |
* planning to avoid semantic problems. |
- |
| 875 |
- |
*/ |
- |
| 876 |
- |
if (argnames != NIL) |
- |
| 877 |
- |
ereport(ERROR, |
- |
| 878 |
- |
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
- |
| 879 |
- |
errmsg("aggregates cannot use named arguments"), |
- |
| 880 |
- |
parser_errposition(pstate, location))); |
- |
| 881 |
- |
|
- |
| 882 |
- |
/* parse_agg.c does additional aggregate-specific processing */ |
- |
| 883 |
- |
transformAggregateCall(pstate, aggref, fargs, agg_order, agg_distinct); |
- |
| 884 |
- |
|
- |
| 885 |
- |
retval = (Node *) aggref; |
- |
| 886 |
- |
} |
- |
| 887 |
- |
else |
- |
| 888 |
- |
{ |
- |
| 889 |
- |
/* window function */ |
- |
| 890 |
- |
WindowFunc *wfunc = makeNode(WindowFunc); |
- |
| 891 |
- |
|
- |
| 892 |
- |
Assert(over); /* lack of this was checked above */ |
- |
| 893 |
- |
Assert(!agg_within_group); /* also checked above */ |
- |
| 894 |
- |
|
- |
| 895 |
- |
wfunc->winfnoid = funcid; |
- |
| 896 |
- |
wfunc->wintype = rettype; |
- |
| 897 |
- |
/* wincollid and inputcollid will be set by parse_collate.c */ |
- |
| 898 |
- |
wfunc->args = fargs; |
- |
| 899 |
- |
/* winref will be set by transformWindowFuncCall */ |
- |
| 900 |
- |
wfunc->winstar = agg_star; |
- |
| 901 |
- |
wfunc->winagg = (fdresult == FUNCDETAIL_AGGREGATE); |
- |
| 902 |
- |
wfunc->aggfilter = agg_filter; |
- |
| 903 |
- |
wfunc->ignore_nulls = ignore_nulls; |
- |
| 904 |
- |
wfunc->runCondition = NIL; |
- |
| 905 |
- |
wfunc->location = location; |
- |
| 906 |
- |
|
- |
| 907 |
- |
/* |
- |
| 908 |
- |
* agg_star is allowed for aggregate functions but distinct isn't |
- |
| 909 |
- |
*/ |
- |
| 910 |
- |
if (agg_distinct) |
- |
| 911 |
- |
ereport(ERROR, |
- |
| 912 |
- |
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
- |
| 913 |
- |
errmsg("DISTINCT is not implemented for window functions"), |
- |
| 914 |
- |
parser_errposition(pstate, location))); |
- |
| 915 |
- |
|
- |
| 916 |
- |
/* |
- |
| 917 |
- |
* Reject attempt to call a parameterless aggregate without (*) |
- |
| 918 |
- |
* syntax. This is mere pedantry but some folks insisted ... |
- |
| 919 |
- |
*/ |
- |
| 920 |
- |
if (wfunc->winagg && fargs == NIL && !agg_star) |
- |
| 921 |
- |
ereport(ERROR, |
- |
| 922 |
- |
(errcode(ERRCODE_WRONG_OBJECT_TYPE), |
- |
| 923 |
- |
errmsg("%s(*) must be used to call a parameterless aggregate function", |
- |
| 924 |
- |
NameListToString(funcname)), |
- |
| 925 |
- |
parser_errposition(pstate, location))); |
- |
| 926 |
- |
|
- |
| 927 |
- |
/* |
- |
| 928 |
- |
* ordered aggs not allowed in windows yet |
- |
| 929 |
- |
*/ |
- |
| 930 |
- |
if (agg_order != NIL) |
- |
| 931 |
- |
ereport(ERROR, |
- |
| 932 |
- |
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
- |
| 933 |
- |
errmsg("aggregate ORDER BY is not implemented for window functions"), |
- |
| 934 |
- |
parser_errposition(pstate, location))); |
- |
| 935 |
- |
|
- |
| 936 |
- |
/* |
- |
| 937 |
- |
* FILTER is not yet supported with true window functions |
- |
| 938 |
- |
*/ |
- |
| 939 |
- |
if (!wfunc->winagg && agg_filter) |
- |
| 940 |
- |
ereport(ERROR, |
- |
| 941 |
- |
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
- |
| 942 |
- |
errmsg("FILTER is not implemented for non-aggregate window functions"), |
- |
| 943 |
- |
parser_errposition(pstate, location))); |
- |
| 944 |
- |
|
- |
| 945 |
- |
/* |
- |
| 946 |
- |
* Window functions can't either take or return sets |
- |
| 947 |
- |
*/ |
- |
| 948 |
- |
if (pstate->p_last_srf != last_srf) |
- |
| 949 |
- |
ereport(ERROR, |
- |
| 950 |
- |
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
- |
| 951 |
- |
errmsg("window function calls cannot contain set-returning function calls"), |
- |
| 952 |
- |
errhint("You might be able to move the set-returning function into a LATERAL FROM item."), |
- |
| 953 |
- |
parser_errposition(pstate, |
- |
| 954 |
- |
exprLocation(pstate->p_last_srf)))); |
- |
| 955 |
- |
|
- |
| 956 |
- |
if (retset) |
- |
| 957 |
- |
ereport(ERROR, |
- |
| 958 |
- |
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), |
- |
| 959 |
- |
errmsg("window functions cannot return sets"), |
- |
| 960 |
- |
parser_errposition(pstate, location))); |
- |
| 961 |
- |
|
- |
| 962 |
- |
/* parse_agg.c does additional window-func-specific processing */ |
- |
| 963 |
- |
transformWindowFuncCall(pstate, wfunc, over); |
- |
| 964 |
- |
|
- |
| 965 |
- |
retval = (Node *) wfunc; |
- |
| 966 |
- |
} |
- |
| 967 |
- |
|
- |
| 968 |
- |
/* if it returns a set, remember it for error checks at higher levels */ |
- |
| 969 |
- |
if (retset) |
- |
| 970 |
- |
pstate->p_last_srf = retval; |
- |
| 971 |
- |
|
- |
| 972 |
- |
return retval; |
- |
| 973 |
- |
} |
- |