|
8 | 8 | * |
9 | 9 | * |
10 | 10 | * IDENTIFICATION |
11 | | - * $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.119 2004/08/29 05:06:41 momjian Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.120 2004/10/07 18:38:48 tgl Exp $ |
12 | 12 | * |
13 | 13 | *------------------------------------------------------------------------- |
14 | 14 | */ |
|
18 | 18 | #include"catalog/catname.h" |
19 | 19 | #include"catalog/dependency.h" |
20 | 20 | #include"catalog/indexing.h" |
21 | | -#include"catalog/pg_language.h" |
22 | 21 | #include"catalog/pg_proc.h" |
23 | | -#include"executor/executor.h" |
24 | | -#include"fmgr.h" |
| 22 | +#include"catalog/pg_type.h" |
| 23 | +#include"executor/functions.h" |
25 | 24 | #include"miscadmin.h" |
26 | 25 | #include"mb/pg_wchar.h" |
27 | | -#include"parser/parse_coerce.h" |
28 | | -#include"parser/parse_expr.h" |
29 | 26 | #include"parser/parse_type.h" |
30 | 27 | #include"tcop/pquery.h" |
31 | 28 | #include"tcop/tcopprot.h" |
@@ -350,242 +347,6 @@ create_parameternames_array(int parameterCount, const char *parameterNames[]) |
350 | 347 | } |
351 | 348 |
|
352 | 349 |
|
353 | | -/* |
354 | | - * check_sql_fn_retval() -- check return value of a list of sql parse trees. |
355 | | - * |
356 | | - * The return value of a sql function is the value returned by |
357 | | - * the final query in the function. We do some ad-hoc type checking here |
358 | | - * to be sure that the user is returning the type he claims. |
359 | | - * |
360 | | - * This is normally applied during function definition, but in the case |
361 | | - * of a function with polymorphic arguments, we instead apply it during |
362 | | - * function execution startup.The rettype is then the actual resolved |
363 | | - * output type of the function, rather than the declared type.(Therefore, |
364 | | - * we should never see ANYARRAY or ANYELEMENT as rettype.) |
365 | | - * |
366 | | - * The return value is true if the function returns the entire tuple result |
367 | | - * of its final SELECT, and false otherwise. Note that because we allow |
368 | | - * "SELECT rowtype_expression", this may be false even when the declared |
369 | | - * function return type is a rowtype. |
370 | | - */ |
371 | | -bool |
372 | | -check_sql_fn_retval(Oidrettype,charfn_typtype,List*queryTreeList) |
373 | | -{ |
374 | | -Query*parse; |
375 | | -intcmd; |
376 | | -List*tlist; |
377 | | -ListCell*tlistitem; |
378 | | -inttlistlen; |
379 | | -Oidtyperelid; |
380 | | -Oidrestype; |
381 | | -Relationreln; |
382 | | -intrelnatts;/* physical number of columns in rel */ |
383 | | -intrellogcols;/* # of nondeleted columns in rel */ |
384 | | -intcolindex;/* physical column index */ |
385 | | - |
386 | | -/* guard against empty function body; OK only if void return type */ |
387 | | -if (queryTreeList==NIL) |
388 | | -{ |
389 | | -if (rettype!=VOIDOID) |
390 | | -ereport(ERROR, |
391 | | -(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), |
392 | | -errmsg("return type mismatch in function declared to return %s", |
393 | | -format_type_be(rettype)), |
394 | | -errdetail("Function's final statement must be a SELECT."))); |
395 | | -return false; |
396 | | -} |
397 | | - |
398 | | -/* find the final query */ |
399 | | -parse= (Query*)lfirst(list_tail(queryTreeList)); |
400 | | - |
401 | | -cmd=parse->commandType; |
402 | | -tlist=parse->targetList; |
403 | | - |
404 | | -/* |
405 | | - * The last query must be a SELECT if and only if return type isn't |
406 | | - * VOID. |
407 | | - */ |
408 | | -if (rettype==VOIDOID) |
409 | | -{ |
410 | | -if (cmd==CMD_SELECT) |
411 | | -ereport(ERROR, |
412 | | -(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), |
413 | | -errmsg("return type mismatch in function declared to return %s", |
414 | | -format_type_be(rettype)), |
415 | | -errdetail("Function's final statement must not be a SELECT."))); |
416 | | -return false; |
417 | | -} |
418 | | - |
419 | | -/* by here, the function is declared to return some type */ |
420 | | -if (cmd!=CMD_SELECT) |
421 | | -ereport(ERROR, |
422 | | -(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), |
423 | | -errmsg("return type mismatch in function declared to return %s", |
424 | | -format_type_be(rettype)), |
425 | | -errdetail("Function's final statement must be a SELECT."))); |
426 | | - |
427 | | -/* |
428 | | - * Count the non-junk entries in the result targetlist. |
429 | | - */ |
430 | | -tlistlen=ExecCleanTargetListLength(tlist); |
431 | | - |
432 | | -typerelid=typeidTypeRelid(rettype); |
433 | | - |
434 | | -if (fn_typtype=='b'||fn_typtype=='d') |
435 | | -{ |
436 | | -/* Shouldn't have a typerelid */ |
437 | | -Assert(typerelid==InvalidOid); |
438 | | - |
439 | | -/* |
440 | | - * For base-type returns, the target list should have exactly one |
441 | | - * entry, and its type should agree with what the user declared. |
442 | | - * (As of Postgres 7.2, we accept binary-compatible types too.) |
443 | | - */ |
444 | | -if (tlistlen!=1) |
445 | | -ereport(ERROR, |
446 | | -(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), |
447 | | -errmsg("return type mismatch in function declared to return %s", |
448 | | -format_type_be(rettype)), |
449 | | -errdetail("Final SELECT must return exactly one column."))); |
450 | | - |
451 | | -restype= ((TargetEntry*)linitial(tlist))->resdom->restype; |
452 | | -if (!IsBinaryCoercible(restype,rettype)) |
453 | | -ereport(ERROR, |
454 | | -(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), |
455 | | -errmsg("return type mismatch in function declared to return %s", |
456 | | -format_type_be(rettype)), |
457 | | -errdetail("Actual return type is %s.", |
458 | | -format_type_be(restype)))); |
459 | | -} |
460 | | -elseif (fn_typtype=='c') |
461 | | -{ |
462 | | -/* Must have a typerelid */ |
463 | | -Assert(typerelid!=InvalidOid); |
464 | | - |
465 | | -/* |
466 | | - * If the target list is of length 1, and the type of the varnode |
467 | | - * in the target list matches the declared return type, this is |
468 | | - * okay. This can happen, for example, where the body of the |
469 | | - * function is 'SELECT func2()', where func2 has the same return |
470 | | - * type as the function that's calling it. |
471 | | - */ |
472 | | -if (tlistlen==1) |
473 | | -{ |
474 | | -restype= ((TargetEntry*)linitial(tlist))->resdom->restype; |
475 | | -if (IsBinaryCoercible(restype,rettype)) |
476 | | -return false;/* NOT returning whole tuple */ |
477 | | -} |
478 | | - |
479 | | -/* |
480 | | - * Otherwise verify that the targetlist matches the return tuple |
481 | | - * type. This part of the typechecking is a hack. We look up the |
482 | | - * relation that is the declared return type, and scan the |
483 | | - * non-deleted attributes to ensure that they match the datatypes |
484 | | - * of the non-resjunk columns. |
485 | | - */ |
486 | | -reln=relation_open(typerelid,AccessShareLock); |
487 | | -relnatts=reln->rd_rel->relnatts; |
488 | | -rellogcols=0;/* we'll count nondeleted cols as we go */ |
489 | | -colindex=0; |
490 | | - |
491 | | -foreach(tlistitem,tlist) |
492 | | -{ |
493 | | -TargetEntry*tle= (TargetEntry*)lfirst(tlistitem); |
494 | | -Form_pg_attributeattr; |
495 | | -Oidtletype; |
496 | | -Oidatttype; |
497 | | - |
498 | | -if (tle->resdom->resjunk) |
499 | | -continue; |
500 | | - |
501 | | -do |
502 | | -{ |
503 | | -colindex++; |
504 | | -if (colindex>relnatts) |
505 | | -ereport(ERROR, |
506 | | -(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), |
507 | | -errmsg("return type mismatch in function declared to return %s", |
508 | | -format_type_be(rettype)), |
509 | | -errdetail("Final SELECT returns too many columns."))); |
510 | | -attr=reln->rd_att->attrs[colindex-1]; |
511 | | -}while (attr->attisdropped); |
512 | | -rellogcols++; |
513 | | - |
514 | | -tletype=exprType((Node*)tle->expr); |
515 | | -atttype=attr->atttypid; |
516 | | -if (!IsBinaryCoercible(tletype,atttype)) |
517 | | -ereport(ERROR, |
518 | | -(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), |
519 | | -errmsg("return type mismatch in function declared to return %s", |
520 | | -format_type_be(rettype)), |
521 | | -errdetail("Final SELECT returns %s instead of %s at column %d.", |
522 | | -format_type_be(tletype), |
523 | | -format_type_be(atttype), |
524 | | -rellogcols))); |
525 | | -} |
526 | | - |
527 | | -for (;;) |
528 | | -{ |
529 | | -colindex++; |
530 | | -if (colindex>relnatts) |
531 | | -break; |
532 | | -if (!reln->rd_att->attrs[colindex-1]->attisdropped) |
533 | | -rellogcols++; |
534 | | -} |
535 | | - |
536 | | -if (tlistlen!=rellogcols) |
537 | | -ereport(ERROR, |
538 | | -(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), |
539 | | -errmsg("return type mismatch in function declared to return %s", |
540 | | -format_type_be(rettype)), |
541 | | -errdetail("Final SELECT returns too few columns."))); |
542 | | - |
543 | | -relation_close(reln,AccessShareLock); |
544 | | - |
545 | | -/* Report that we are returning entire tuple result */ |
546 | | -return true; |
547 | | -} |
548 | | -elseif (rettype==RECORDOID) |
549 | | -{ |
550 | | -/* |
551 | | - * If the target list is of length 1, and the type of the varnode |
552 | | - * in the target list matches the declared return type, this is |
553 | | - * okay. This can happen, for example, where the body of the |
554 | | - * function is 'SELECT func2()', where func2 has the same return |
555 | | - * type as the function that's calling it. |
556 | | - */ |
557 | | -if (tlistlen==1) |
558 | | -{ |
559 | | -restype= ((TargetEntry*)linitial(tlist))->resdom->restype; |
560 | | -if (IsBinaryCoercible(restype,rettype)) |
561 | | -return false;/* NOT returning whole tuple */ |
562 | | -} |
563 | | - |
564 | | -/* |
565 | | - * Otherwise assume we are returning the whole tuple. |
566 | | - * Crosschecking against what the caller expects will happen at |
567 | | - * runtime. |
568 | | - */ |
569 | | -return true; |
570 | | -} |
571 | | -elseif (rettype==ANYARRAYOID||rettype==ANYELEMENTOID) |
572 | | -{ |
573 | | -/* This should already have been caught ... */ |
574 | | -ereport(ERROR, |
575 | | -(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), |
576 | | -errmsg("cannot determine result data type"), |
577 | | -errdetail("A function returning \"anyarray\" or \"anyelement\" must have at least one argument of either type."))); |
578 | | -} |
579 | | -else |
580 | | -ereport(ERROR, |
581 | | -(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), |
582 | | -errmsg("return type %s is not supported for SQL functions", |
583 | | -format_type_be(rettype)))); |
584 | | - |
585 | | -return false; |
586 | | -} |
587 | | - |
588 | | - |
589 | 350 |
|
590 | 351 | /* |
591 | 352 | * Validator for internal functions |
@@ -776,7 +537,7 @@ fmgr_sql_validator(PG_FUNCTION_ARGS) |
776 | 537 | proc->proargtypes, |
777 | 538 | proc->pronargs); |
778 | 539 | (void)check_sql_fn_retval(proc->prorettype,functyptype, |
779 | | -querytree_list); |
| 540 | +querytree_list,NULL); |
780 | 541 | } |
781 | 542 | else |
782 | 543 | querytree_list=pg_parse_query(prosrc); |
|