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

Commit216311d

Browse files
committed
First bits of work on error message editing.
1 parent44f665b commit216311d

File tree

21 files changed

+1083
-534
lines changed

21 files changed

+1083
-534
lines changed

‎doc/src/sgml/sources.sgml

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/sources.sgml,v 2.8 2003/06/22 16:17:01 tgl Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/sources.sgml,v 2.9 2003/07/18 23:20:32 tgl Exp $
33
-->
44

55
<chapter id="source">
@@ -125,11 +125,12 @@ less -x4
125125
Here is a more complex example:
126126
<programlisting>
127127
ereport(ERROR,
128-
(errmsg("Unable to identify an operator %s %s %s",
129-
format_type_be(arg1),
130-
NameListToString(op),
131-
format_type_be(arg2)),
132-
errhint("Try explicitly casting the arguments to appropriate types")));
128+
(errcode(ERRCODE_AMBIGUOUS_FUNCTION),
129+
errmsg("function %s is not unique",
130+
func_signature_string(funcname, nargs,
131+
actual_arg_types)),
132+
errhint("Unable to choose a best candidate function. "
133+
"You may need to add explicit typecasts.")));
133134
</programlisting>
134135
This illustrates the use of format codes to embed run-time values into
135136
a message text. Also, an optional <quote>hint</> message is provided.
@@ -141,11 +142,14 @@ less -x4
141142
<listitem>
142143
<para>
143144
<function>errcode</>(sqlerrcode) specifies the SQLSTATE error identifier
144-
code for the condition. If this is not specified, it defaults to
145-
<literal>ERRCODE_INTERNAL_ERROR</>, which is a convenient default since
146-
a large number of <function>ereport</> calls are in fact for internal
147-
<quote>can't happen</> conditions. But never use this default when
148-
reporting user mistakes.
145+
code for the condition. If this routine is not called, the error
146+
identifier defaults to
147+
<literal>ERRCODE_INTERNAL_ERROR</> when the error level is
148+
<literal>ERROR</> or higher, <literal>ERRCODE_WARNING</> when the
149+
error level is <literal>WARNING</>, otherwise (for <literal>NOTICE</>
150+
and below) <literal>ERRCODE_SUCCESSFUL_COMPLETION</>.
151+
While these defaults are often convenient, always think whether they
152+
are appropriate before omitting the <function>errcode</>() call.
149153
</para>
150154
</listitem>
151155
<listitem>
@@ -220,15 +224,25 @@ less -x4
220224
query processing.
221225
</para>
222226
</listitem>
227+
<listitem>
228+
<para>
229+
<function>errcode_for_file_access</>() is a convenience function that
230+
selects an appropriate SQLSTATE error identifier for a failure in a
231+
file-access-related system call. It uses the saved
232+
<literal>errno</> to determine which error code to generate.
233+
Usually this should be used in combination with <literal>%m</> in the
234+
primary error message text.
235+
</para>
236+
</listitem>
223237
</itemizedlist>
224238
</para>
225239

226240
<para>
227241
You may also see uses of the older function <function>elog</>. This
228242
is equivalent to an <function>ereport</> call specifying only severity
229-
level and primary message.Because the error code always defaults to
230-
<literal>ERRCODE_INTERNAL_ERROR</>, <function>elog</> should only be
231-
used forinternal errors.
243+
level and primary message.<function>elog</> should only be used if
244+
the default errcode assignment is appropriate; this generally restricts
245+
its use tointernal errors and debug logging output.
232246
</para>
233247

234248
<para>
@@ -270,7 +284,7 @@ less -x4
270284
write
271285
<programlisting>
272286
Primary: could not create shared memory segment: %m
273-
Detail: Failed syscall was shmget(key=%d, size=%u, 0%o)
287+
Detail: Failed syscall was shmget(key=%d, size=%u, 0%o).
274288
Hint: the addendum
275289
</programlisting>
276290
</para>

‎src/backend/catalog/pg_proc.c

Lines changed: 100 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.99 2003/07/01 01:28:32 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.100 2003/07/18 23:20:32 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -82,8 +82,10 @@ ProcedureCreate(const char *procedureName,
8282
Assert(PointerIsValid(probin));
8383

8484
if (parameterCount<0||parameterCount>FUNC_MAX_ARGS)
85-
elog(ERROR,"functions cannot have more than %d arguments",
86-
FUNC_MAX_ARGS);
85+
ereport(ERROR,
86+
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
87+
errmsg("functions cannot have more than %d arguments",
88+
FUNC_MAX_ARGS)));
8789

8890
/*
8991
* Do not allow return type ANYARRAY or ANYELEMENT unless at least one
@@ -104,8 +106,9 @@ ProcedureCreate(const char *procedureName,
104106
}
105107

106108
if (!genericParam)
107-
elog(ERROR,"functions returning ANYARRAY or ANYELEMENT must " \
108-
"have at least one argument of either type");
109+
ereport(ERROR,
110+
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
111+
errmsg("functions returning ANYARRAY or ANYELEMENT must have at least one argument of either type")));
109112
}
110113

111114
/* Make sure we have a zero-padded param type array */
@@ -156,10 +159,12 @@ ProcedureCreate(const char *procedureName,
156159
* existing attributes of the type
157160
*/
158161
if (parameterCount==1&&OidIsValid(typev[0])&&
159-
(relid=typeidTypeRelid(typev[0]))!=0&&
162+
(relid=typeidTypeRelid(typev[0]))!=InvalidOid&&
160163
get_attnum(relid, (char*)procedureName)!=InvalidAttrNumber)
161-
elog(ERROR,"method %s already an attribute of type %s",
162-
procedureName,format_type_be(typev[0]));
164+
ereport(ERROR,
165+
(errcode(ERRCODE_DUPLICATE_COLUMN),
166+
errmsg("\"%s\" is already an attribute of type %s",
167+
procedureName,format_type_be(typev[0]))));
163168

164169
/*
165170
* All seems OK; prepare the data to be inserted into pg_proc.
@@ -208,30 +213,40 @@ ProcedureCreate(const char *procedureName,
208213
Form_pg_procoldproc= (Form_pg_proc)GETSTRUCT(oldtup);
209214

210215
if (!replace)
211-
elog(ERROR,"function %s already exists with same argument types",
212-
procedureName);
216+
ereport(ERROR,
217+
(errcode(ERRCODE_DUPLICATE_FUNCTION),
218+
errmsg("function \"%s\" already exists with same argument types",
219+
procedureName)));
213220
if (GetUserId()!=oldproc->proowner&& !superuser())
214-
elog(ERROR,"ProcedureCreate: you do not have permission to replace function %s",
215-
procedureName);
221+
ereport(ERROR,
222+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
223+
errmsg("you do not have permission to replace function \"%s\"",
224+
procedureName)));
216225

217226
/*
218227
* Not okay to change the return type of the existing proc, since
219228
* existing rules, views, etc may depend on the return type.
220229
*/
221230
if (returnType!=oldproc->prorettype||
222231
returnsSet!=oldproc->proretset)
223-
elog(ERROR,"ProcedureCreate: cannot change return type of existing function."
224-
"\n\tUse DROP FUNCTION first.");
232+
ereport(ERROR,
233+
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
234+
errmsg("cannot change return type of existing function"),
235+
errhint("Use DROP FUNCTION first.")));
225236

226237
/* Can't change aggregate status, either */
227238
if (oldproc->proisagg!=isAgg)
228239
{
229240
if (oldproc->proisagg)
230-
elog(ERROR,"function %s is an aggregate",
231-
procedureName);
241+
ereport(ERROR,
242+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
243+
errmsg("function \"%s\" is an aggregate",
244+
procedureName)));
232245
else
233-
elog(ERROR,"function %s is not an aggregate",
234-
procedureName);
246+
ereport(ERROR,
247+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
248+
errmsg("function \"%s\" is not an aggregate",
249+
procedureName)));
235250
}
236251

237252
/* do not change existing ownership or permissions, either */
@@ -347,8 +362,11 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList)
347362
if (queryTreeList==NIL)
348363
{
349364
if (rettype!=VOIDOID)
350-
elog(ERROR,"function declared to return %s, but no SELECT provided",
351-
format_type_be(rettype));
365+
ereport(ERROR,
366+
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
367+
errmsg("return type mismatch in function declared to return %s",
368+
format_type_be(rettype)),
369+
errdetail("Function's final statement must be a SELECT.")));
352370
return;
353371
}
354372

@@ -365,14 +383,21 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList)
365383
if (rettype==VOIDOID)
366384
{
367385
if (cmd==CMD_SELECT)
368-
elog(ERROR,"function declared to return void, but final statement is a SELECT");
386+
ereport(ERROR,
387+
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
388+
errmsg("return type mismatch in function declared to return %s",
389+
format_type_be(rettype)),
390+
errdetail("Function's final statement must not be a SELECT.")));
369391
return;
370392
}
371393

372394
/* by here, the function is declared to return some type */
373395
if (cmd!=CMD_SELECT)
374-
elog(ERROR,"function declared to return %s, but final statement is not a SELECT",
375-
format_type_be(rettype));
396+
ereport(ERROR,
397+
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
398+
errmsg("return type mismatch in function declared to return %s",
399+
format_type_be(rettype)),
400+
errdetail("Function's final statement must be a SELECT.")));
376401

377402
/*
378403
* Count the non-junk entries in the result targetlist.
@@ -392,13 +417,20 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList)
392417
* (As of Postgres 7.2, we accept binary-compatible types too.)
393418
*/
394419
if (tlistlen!=1)
395-
elog(ERROR,"function declared to return %s returns multiple columns in final SELECT",
396-
format_type_be(rettype));
420+
ereport(ERROR,
421+
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
422+
errmsg("return type mismatch in function declared to return %s",
423+
format_type_be(rettype)),
424+
errdetail("Final SELECT must return exactly one column.")));
397425

398426
restype= ((TargetEntry*)lfirst(tlist))->resdom->restype;
399427
if (!IsBinaryCoercible(restype,rettype))
400-
elog(ERROR,"return type mismatch in function: declared to return %s, returns %s",
401-
format_type_be(rettype),format_type_be(restype));
428+
ereport(ERROR,
429+
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
430+
errmsg("return type mismatch in function declared to return %s",
431+
format_type_be(rettype)),
432+
errdetail("Actual return type is %s.",
433+
format_type_be(restype))));
402434
}
403435
elseif (fn_typtype=='c')
404436
{
@@ -445,20 +477,26 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList)
445477
{
446478
colindex++;
447479
if (colindex>relnatts)
448-
elog(ERROR,"function declared to return %s does not SELECT the right number of columns (%d)",
449-
format_type_be(rettype),rellogcols);
480+
ereport(ERROR,
481+
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
482+
errmsg("return type mismatch in function declared to return %s",
483+
format_type_be(rettype)),
484+
errdetail("Final SELECT returns too many columns.")));
450485
attr=reln->rd_att->attrs[colindex-1];
451486
}while (attr->attisdropped);
452487
rellogcols++;
453488

454489
tletype=exprType((Node*)tle->expr);
455490
atttype=attr->atttypid;
456491
if (!IsBinaryCoercible(tletype,atttype))
457-
elog(ERROR,"function declared to return %s returns %s instead of %s at column %d",
458-
format_type_be(rettype),
459-
format_type_be(tletype),
460-
format_type_be(atttype),
461-
rellogcols);
492+
ereport(ERROR,
493+
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
494+
errmsg("return type mismatch in function declared to return %s",
495+
format_type_be(rettype)),
496+
errdetail("Final SELECT returns %s instead of %s at column %d.",
497+
format_type_be(tletype),
498+
format_type_be(atttype),
499+
rellogcols)));
462500
}
463501

464502
for (;;)
@@ -471,8 +509,11 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList)
471509
}
472510

473511
if (tlistlen!=rellogcols)
474-
elog(ERROR,"function declared to return %s does not SELECT the right number of columns (%d)",
475-
format_type_be(rettype),rellogcols);
512+
ereport(ERROR,
513+
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
514+
errmsg("return type mismatch in function declared to return %s",
515+
format_type_be(rettype)),
516+
errdetail("Final SELECT returns too few columns.")));
476517

477518
relation_close(reln,AccessShareLock);
478519
}
@@ -488,15 +529,16 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList)
488529
}
489530
elseif (rettype==ANYARRAYOID||rettype==ANYELEMENTOID)
490531
{
491-
/*
492-
* This should already have been caught ...
493-
*/
494-
elog(ERROR,"functions returning ANYARRAY or ANYELEMENT must " \
495-
"have at least one argument of either type");
532+
/* This should already have been caught ... */
533+
ereport(ERROR,
534+
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
535+
errmsg("functions returning ANYARRAY or ANYELEMENT must have at least one argument of either type")));
496536
}
497537
else
498-
elog(ERROR,"return type %s is not supported for SQL functions",
499-
format_type_be(rettype));
538+
ereport(ERROR,
539+
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
540+
errmsg("return type %s is not supported for SQL functions",
541+
format_type_be(rettype))));
500542
}
501543

502544

@@ -521,7 +563,7 @@ fmgr_internal_validator(PG_FUNCTION_ARGS)
521563
ObjectIdGetDatum(funcoid),
522564
0,0,0);
523565
if (!HeapTupleIsValid(tuple))
524-
elog(ERROR,"cache lookupoffunction %u failed",funcoid);
566+
elog(ERROR,"cache lookupfailed forfunction %u",funcoid);
525567
proc= (Form_pg_proc)GETSTRUCT(tuple);
526568

527569
tmp=SysCacheGetAttr(PROCOID,tuple,Anum_pg_proc_prosrc,&isnull);
@@ -530,7 +572,10 @@ fmgr_internal_validator(PG_FUNCTION_ARGS)
530572
prosrc=DatumGetCString(DirectFunctionCall1(textout,tmp));
531573

532574
if (fmgr_internal_function(prosrc)==InvalidOid)
533-
elog(ERROR,"there is no built-in function named \"%s\"",prosrc);
575+
ereport(ERROR,
576+
(errcode(ERRCODE_UNDEFINED_FUNCTION),
577+
errmsg("there is no built-in function named \"%s\"",
578+
prosrc)));
534579

535580
ReleaseSysCache(tuple);
536581

@@ -562,7 +607,7 @@ fmgr_c_validator(PG_FUNCTION_ARGS)
562607
ObjectIdGetDatum(funcoid),
563608
0,0,0);
564609
if (!HeapTupleIsValid(tuple))
565-
elog(ERROR,"cache lookupoffunction %u failed",funcoid);
610+
elog(ERROR,"cache lookupfailed forfunction %u",funcoid);
566611
proc= (Form_pg_proc)GETSTRUCT(tuple);
567612

568613
tmp=SysCacheGetAttr(PROCOID,tuple,Anum_pg_proc_prosrc,&isnull);
@@ -608,7 +653,7 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
608653
ObjectIdGetDatum(funcoid),
609654
0,0,0);
610655
if (!HeapTupleIsValid(tuple))
611-
elog(ERROR,"cache lookupoffunction %u failed",funcoid);
656+
elog(ERROR,"cache lookupfailed forfunction %u",funcoid);
612657
proc= (Form_pg_proc)GETSTRUCT(tuple);
613658

614659
functyptype=get_typtype(proc->prorettype);
@@ -620,8 +665,10 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
620665
proc->prorettype!=VOIDOID&&
621666
proc->prorettype!=ANYARRAYOID&&
622667
proc->prorettype!=ANYELEMENTOID)
623-
elog(ERROR,"SQL functions cannot return type %s",
624-
format_type_be(proc->prorettype));
668+
ereport(ERROR,
669+
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
670+
errmsg("SQL functions cannot return type %s",
671+
format_type_be(proc->prorettype))));
625672

626673
/* Disallow pseudotypes in arguments */
627674
/* except for ANYARRAY or ANYELEMENT */
@@ -634,8 +681,10 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
634681
proc->proargtypes[i]==ANYELEMENTOID)
635682
haspolyarg= true;
636683
else
637-
elog(ERROR,"SQL functions cannot have arguments of type %s",
638-
format_type_be(proc->proargtypes[i]));
684+
ereport(ERROR,
685+
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
686+
errmsg("SQL functions cannot have arguments of type %s",
687+
format_type_be(proc->proargtypes[i]))));
639688
}
640689
}
641690

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp