From 216311d590de4638997eb391722f915026a29e88 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 18 Jul 2003 23:20:33 +0000 Subject: [PATCH] First bits of work on error message editing. --- doc/src/sgml/sources.sgml | 44 ++- src/backend/catalog/pg_proc.c | 151 ++++++--- src/backend/commands/dbcommands.c | 192 +++++++---- src/backend/commands/functioncmds.c | 299 +++++++++++------- src/backend/commands/opclasscmds.c | 116 ++++--- src/backend/commands/proclang.c | 45 +-- src/backend/commands/schemacmds.c | 43 +-- src/backend/commands/user.c | 264 ++++++++++------ src/backend/parser/analyze.c | 12 +- src/backend/parser/parse_coerce.c | 18 +- src/backend/parser/parse_expr.c | 13 +- src/backend/parser/parse_func.c | 111 ++++--- src/backend/parser/parse_oper.c | 52 ++- src/backend/parser/scan.l | 24 +- src/backend/utils/error/elog.c | 89 +++++- src/backend/utils/fmgr/dfmgr.c | 45 ++- src/include/utils/elog.h | 57 +++- src/test/regress/expected/alter_table.out | 4 +- src/test/regress/expected/create_type.out | 10 +- src/test/regress/expected/privileges.out | 4 +- .../regress/output/create_function_1.source | 24 +- 21 files changed, 1083 insertions(+), 534 deletions(-) diff --git a/doc/src/sgml/sources.sgml b/doc/src/sgml/sources.sgml index 7ebcd24e77..18fd7597de 100644 --- a/doc/src/sgml/sources.sgml +++ b/doc/src/sgml/sources.sgml @@ -1,5 +1,5 @@ @@ -125,11 +125,12 @@ less -x4 Here is a more complex example: ereport(ERROR, - (errmsg("Unable to identify an operator %s %s %s", - format_type_be(arg1), - NameListToString(op), - format_type_be(arg2)), - errhint("Try explicitly casting the arguments to appropriate types"))); + (errcode(ERRCODE_AMBIGUOUS_FUNCTION), + errmsg("function %s is not unique", + func_signature_string(funcname, nargs, + actual_arg_types)), + errhint("Unable to choose a best candidate function. " + "You may need to add explicit typecasts."))); This illustrates the use of format codes to embed run-time values into a message text. Also, an optional hint message is provided. @@ -141,11 +142,14 @@ less -x4 errcode(sqlerrcode) specifies the SQLSTATE error identifier - code for the condition. If this is not specified, it defaults to - ERRCODE_INTERNAL_ERROR, which is a convenient default since - a large number of ereport calls are in fact for internal - can't happen conditions. But never use this default when - reporting user mistakes. + code for the condition. If this routine is not called, the error + identifier defaults to + ERRCODE_INTERNAL_ERROR when the error level is + ERROR or higher, ERRCODE_WARNING when the + error level is WARNING, otherwise (for NOTICE + and below) ERRCODE_SUCCESSFUL_COMPLETION. + While these defaults are often convenient, always think whether they + are appropriate before omitting the errcode() call. @@ -220,15 +224,25 @@ less -x4 query processing. + + + errcode_for_file_access() is a convenience function that + selects an appropriate SQLSTATE error identifier for a failure in a + file-access-related system call. It uses the saved + errno to determine which error code to generate. + Usually this should be used in combination with %m in the + primary error message text. + + You may also see uses of the older function elog. This is equivalent to an ereport call specifying only severity - level and primary message. Because the error code always defaults to - ERRCODE_INTERNAL_ERROR, elog should only be - used for internal errors. + level and primary message. elog should only be used if + the default errcode assignment is appropriate; this generally restricts + its use to internal errors and debug logging output. @@ -270,7 +284,7 @@ less -x4 write Primary: could not create shared memory segment: %m - Detail: Failed syscall was shmget(key=%d, size=%u, 0%o) + Detail: Failed syscall was shmget(key=%d, size=%u, 0%o). Hint: the addendum diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index 897ae682a3..c2d3eb7ca1 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.99 2003/07/01 01:28:32 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.100 2003/07/18 23:20:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -82,8 +82,10 @@ ProcedureCreate(const char *procedureName, Assert(PointerIsValid(probin)); if (parameterCount < 0 || parameterCount > FUNC_MAX_ARGS) - elog(ERROR, "functions cannot have more than %d arguments", - FUNC_MAX_ARGS); + ereport(ERROR, + (errcode(ERRCODE_TOO_MANY_ARGUMENTS), + errmsg("functions cannot have more than %d arguments", + FUNC_MAX_ARGS))); /* * Do not allow return type ANYARRAY or ANYELEMENT unless at least one @@ -104,8 +106,9 @@ ProcedureCreate(const char *procedureName, } if (!genericParam) - elog(ERROR, "functions returning ANYARRAY or ANYELEMENT must " \ - "have at least one argument of either type"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("functions returning ANYARRAY or ANYELEMENT must have at least one argument of either type"))); } /* Make sure we have a zero-padded param type array */ @@ -156,10 +159,12 @@ ProcedureCreate(const char *procedureName, * existing attributes of the type */ if (parameterCount == 1 && OidIsValid(typev[0]) && - (relid = typeidTypeRelid(typev[0])) != 0 && + (relid = typeidTypeRelid(typev[0])) != InvalidOid && get_attnum(relid, (char *) procedureName) != InvalidAttrNumber) - elog(ERROR, "method %s already an attribute of type %s", - procedureName, format_type_be(typev[0])); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_COLUMN), + errmsg("\"%s\" is already an attribute of type %s", + procedureName, format_type_be(typev[0])))); /* * All seems OK; prepare the data to be inserted into pg_proc. @@ -208,11 +213,15 @@ ProcedureCreate(const char *procedureName, Form_pg_proc oldproc = (Form_pg_proc) GETSTRUCT(oldtup); if (!replace) - elog(ERROR, "function %s already exists with same argument types", - procedureName); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_FUNCTION), + errmsg("function \"%s\" already exists with same argument types", + procedureName))); if (GetUserId() != oldproc->proowner && !superuser()) - elog(ERROR, "ProcedureCreate: you do not have permission to replace function %s", - procedureName); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("you do not have permission to replace function \"%s\"", + procedureName))); /* * Not okay to change the return type of the existing proc, since @@ -220,18 +229,24 @@ ProcedureCreate(const char *procedureName, */ if (returnType != oldproc->prorettype || returnsSet != oldproc->proretset) - elog(ERROR, "ProcedureCreate: cannot change return type of existing function." - "\n\tUse DROP FUNCTION first."); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("cannot change return type of existing function"), + errhint("Use DROP FUNCTION first."))); /* Can't change aggregate status, either */ if (oldproc->proisagg != isAgg) { if (oldproc->proisagg) - elog(ERROR, "function %s is an aggregate", - procedureName); + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("function \"%s\" is an aggregate", + procedureName))); else - elog(ERROR, "function %s is not an aggregate", - procedureName); + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("function \"%s\" is not an aggregate", + procedureName))); } /* do not change existing ownership or permissions, either */ @@ -347,8 +362,11 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList) if (queryTreeList == NIL) { if (rettype != VOIDOID) - elog(ERROR, "function declared to return %s, but no SELECT provided", - format_type_be(rettype)); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("return type mismatch in function declared to return %s", + format_type_be(rettype)), + errdetail("Function's final statement must be a SELECT."))); return; } @@ -365,14 +383,21 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList) if (rettype == VOIDOID) { if (cmd == CMD_SELECT) - elog(ERROR, "function declared to return void, but final statement is a SELECT"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("return type mismatch in function declared to return %s", + format_type_be(rettype)), + errdetail("Function's final statement must not be a SELECT."))); return; } /* by here, the function is declared to return some type */ if (cmd != CMD_SELECT) - elog(ERROR, "function declared to return %s, but final statement is not a SELECT", - format_type_be(rettype)); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("return type mismatch in function declared to return %s", + format_type_be(rettype)), + errdetail("Function's final statement must be a SELECT."))); /* * Count the non-junk entries in the result targetlist. @@ -392,13 +417,20 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList) * (As of Postgres 7.2, we accept binary-compatible types too.) */ if (tlistlen != 1) - elog(ERROR, "function declared to return %s returns multiple columns in final SELECT", - format_type_be(rettype)); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("return type mismatch in function declared to return %s", + format_type_be(rettype)), + errdetail("Final SELECT must return exactly one column."))); restype = ((TargetEntry *) lfirst(tlist))->resdom->restype; if (!IsBinaryCoercible(restype, rettype)) - elog(ERROR, "return type mismatch in function: declared to return %s, returns %s", - format_type_be(rettype), format_type_be(restype)); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("return type mismatch in function declared to return %s", + format_type_be(rettype)), + errdetail("Actual return type is %s.", + format_type_be(restype)))); } else if (fn_typtype == 'c') { @@ -445,8 +477,11 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList) { colindex++; if (colindex > relnatts) - elog(ERROR, "function declared to return %s does not SELECT the right number of columns (%d)", - format_type_be(rettype), rellogcols); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("return type mismatch in function declared to return %s", + format_type_be(rettype)), + errdetail("Final SELECT returns too many columns."))); attr = reln->rd_att->attrs[colindex - 1]; } while (attr->attisdropped); rellogcols++; @@ -454,11 +489,14 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList) tletype = exprType((Node *) tle->expr); atttype = attr->atttypid; if (!IsBinaryCoercible(tletype, atttype)) - elog(ERROR, "function declared to return %s returns %s instead of %s at column %d", - format_type_be(rettype), - format_type_be(tletype), - format_type_be(atttype), - rellogcols); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("return type mismatch in function declared to return %s", + format_type_be(rettype)), + errdetail("Final SELECT returns %s instead of %s at column %d.", + format_type_be(tletype), + format_type_be(atttype), + rellogcols))); } for (;;) @@ -471,8 +509,11 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList) } if (tlistlen != rellogcols) - elog(ERROR, "function declared to return %s does not SELECT the right number of columns (%d)", - format_type_be(rettype), rellogcols); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("return type mismatch in function declared to return %s", + format_type_be(rettype)), + errdetail("Final SELECT returns too few columns."))); relation_close(reln, AccessShareLock); } @@ -488,15 +529,16 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList) } else if (rettype == ANYARRAYOID || rettype == ANYELEMENTOID) { - /* - * This should already have been caught ... - */ - elog(ERROR, "functions returning ANYARRAY or ANYELEMENT must " \ - "have at least one argument of either type"); + /* This should already have been caught ... */ + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("functions returning ANYARRAY or ANYELEMENT must have at least one argument of either type"))); } else - elog(ERROR, "return type %s is not supported for SQL functions", - format_type_be(rettype)); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("return type %s is not supported for SQL functions", + format_type_be(rettype)))); } @@ -521,7 +563,7 @@ fmgr_internal_validator(PG_FUNCTION_ARGS) ObjectIdGetDatum(funcoid), 0, 0, 0); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "cache lookup of function %u failed", funcoid); + elog(ERROR, "cache lookup failed for function %u", funcoid); proc = (Form_pg_proc) GETSTRUCT(tuple); tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull); @@ -530,7 +572,10 @@ fmgr_internal_validator(PG_FUNCTION_ARGS) prosrc = DatumGetCString(DirectFunctionCall1(textout, tmp)); if (fmgr_internal_function(prosrc) == InvalidOid) - elog(ERROR, "there is no built-in function named \"%s\"", prosrc); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("there is no built-in function named \"%s\"", + prosrc))); ReleaseSysCache(tuple); @@ -562,7 +607,7 @@ fmgr_c_validator(PG_FUNCTION_ARGS) ObjectIdGetDatum(funcoid), 0, 0, 0); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "cache lookup of function %u failed", funcoid); + elog(ERROR, "cache lookup failed for function %u", funcoid); proc = (Form_pg_proc) GETSTRUCT(tuple); tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull); @@ -608,7 +653,7 @@ fmgr_sql_validator(PG_FUNCTION_ARGS) ObjectIdGetDatum(funcoid), 0, 0, 0); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "cache lookup of function %u failed", funcoid); + elog(ERROR, "cache lookup failed for function %u", funcoid); proc = (Form_pg_proc) GETSTRUCT(tuple); functyptype = get_typtype(proc->prorettype); @@ -620,8 +665,10 @@ fmgr_sql_validator(PG_FUNCTION_ARGS) proc->prorettype != VOIDOID && proc->prorettype != ANYARRAYOID && proc->prorettype != ANYELEMENTOID) - elog(ERROR, "SQL functions cannot return type %s", - format_type_be(proc->prorettype)); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("SQL functions cannot return type %s", + format_type_be(proc->prorettype)))); /* Disallow pseudotypes in arguments */ /* except for ANYARRAY or ANYELEMENT */ @@ -634,8 +681,10 @@ fmgr_sql_validator(PG_FUNCTION_ARGS) proc->proargtypes[i] == ANYELEMENTOID) haspolyarg = true; else - elog(ERROR, "SQL functions cannot have arguments of type %s", - format_type_be(proc->proargtypes[i])); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("SQL functions cannot have arguments of type %s", + format_type_be(proc->proargtypes[i])))); } } diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 55f44f9d8c..24ad0bf41a 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.116 2003/06/27 14:45:27 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.117 2003/07/18 23:20:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -98,29 +98,37 @@ createdb(const CreatedbStmt *stmt) if (strcmp(defel->defname, "owner") == 0) { if (downer) - elog(ERROR, "CREATE DATABASE: conflicting options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); downer = defel; } else if (strcmp(defel->defname, "location") == 0) { if (dpath) - elog(ERROR, "CREATE DATABASE: conflicting options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); dpath = defel; } else if (strcmp(defel->defname, "template") == 0) { if (dtemplate) - elog(ERROR, "CREATE DATABASE: conflicting options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); dtemplate = defel; } else if (strcmp(defel->defname, "encoding") == 0) { if (dencoding) - elog(ERROR, "CREATE DATABASE: conflicting options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); dencoding = defel; } else - elog(ERROR, "CREATE DATABASE: option \"%s\" not recognized", + elog(ERROR, "option \"%s\" not recognized", defel->defname); } @@ -140,22 +148,29 @@ createdb(const CreatedbStmt *stmt) encoding_name = pg_encoding_to_char(encoding); if (strcmp(encoding_name, "") == 0 || pg_valid_server_encoding(encoding_name) < 0) - elog(ERROR, "%d is not a valid encoding code", encoding); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("%d is not a valid encoding code", + encoding))); } else if (IsA(dencoding->arg, String)) { encoding_name = strVal(dencoding->arg); if (pg_valid_server_encoding(encoding_name) < 0) - elog(ERROR, "%s is not a valid encoding name", encoding_name); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("%s is not a valid encoding name", + encoding_name))); encoding = pg_char_to_encoding(encoding_name); } else - elog(ERROR, "CREATE DATABASE: bogus encoding parameter"); + elog(ERROR, "unrecognized node type: %d", + nodeTag(dencoding->arg)); } /* obtain sysid of proposed owner */ if (dbowner) - datdba = get_usesysid(dbowner); /* will elog if no such user */ + datdba = get_usesysid(dbowner); /* will ereport if no such user */ else datdba = GetUserId(); @@ -163,22 +178,29 @@ createdb(const CreatedbStmt *stmt) { /* creating database for self: can be superuser or createdb */ if (!superuser() && !have_createdb_privilege()) - elog(ERROR, "CREATE DATABASE: permission denied"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied"))); } else { /* creating database for someone else: must be superuser */ /* note that the someone else need not have any permissions */ if (!superuser()) - elog(ERROR, "CREATE DATABASE: permission denied"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied"))); } /* don't call this in a transaction block */ PreventTransactionChain((void *) stmt, "CREATE DATABASE"); + /* alternate location requires symlinks */ #ifndef HAVE_SYMLINK if (dbpath != NULL) - elog(ERROR, "CREATE DATABASE: may not use an alternate location on this platform"); + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot use an alternate location on this platform"))); #endif /* @@ -190,7 +212,9 @@ createdb(const CreatedbStmt *stmt) * after we grab the exclusive lock. */ if (get_db_info(dbname, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) - elog(ERROR, "CREATE DATABASE: database \"%s\" already exists", dbname); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_DATABASE), + errmsg("database \"%s\" already exists", dbname))); /* * Lookup database (template) to be cloned. @@ -202,8 +226,9 @@ createdb(const CreatedbStmt *stmt) &src_istemplate, &src_lastsysoid, &src_vacuumxid, &src_frozenxid, src_dbpath)) - elog(ERROR, "CREATE DATABASE: template \"%s\" does not exist", - dbtemplate); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_DATABASE), + errmsg("template \"%s\" does not exist", dbtemplate))); /* * Permission check: to copy a DB that's not marked datistemplate, you @@ -212,8 +237,10 @@ createdb(const CreatedbStmt *stmt) if (!src_istemplate) { if (!superuser() && GetUserId() != src_owner) - elog(ERROR, "CREATE DATABASE: permission to copy \"%s\" denied", - dbtemplate); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission to copy \"%s\" denied", + dbtemplate))); } /* @@ -231,7 +258,10 @@ createdb(const CreatedbStmt *stmt) * bulletproof, since someone might connect while we are copying... */ if (DatabaseHasActiveBackends(src_dboid, true)) - elog(ERROR, "CREATE DATABASE: source database \"%s\" is being accessed by other users", dbtemplate); + ereport(ERROR, + (errcode(ERRCODE_OBJECT_IN_USE), + errmsg("source database \"%s\" is being accessed by other users", + dbtemplate))); /* If encoding is defaulted, use source's encoding */ if (encoding < 0) @@ -239,7 +269,9 @@ createdb(const CreatedbStmt *stmt) /* Some encodings are client only */ if (!PG_VALID_BE_ENCODING(encoding)) - elog(ERROR, "CREATE DATABASE: invalid backend encoding"); + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("invalid backend encoding %d", encoding))); /* * Preassign OID for pg_database tuple, so that we can compute db @@ -267,11 +299,17 @@ createdb(const CreatedbStmt *stmt) } if (strchr(nominal_loc, '\'')) - elog(ERROR, "database path may not contain single quotes"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_NAME), + errmsg("database path may not contain single quotes"))); if (alt_loc && strchr(alt_loc, '\'')) - elog(ERROR, "database path may not contain single quotes"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_NAME), + errmsg("database path may not contain single quotes"))); if (strchr(src_loc, '\'')) - elog(ERROR, "database path may not contain single quotes"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_NAME), + errmsg("database path may not contain single quotes"))); /* ... otherwise we'd be open to shell exploits below */ /* @@ -294,11 +332,15 @@ createdb(const CreatedbStmt *stmt) target_dir = alt_loc ? alt_loc : nominal_loc; if (mkdir(target_dir, S_IRWXU) != 0) - elog(ERROR, "CREATE DATABASE: unable to create database directory '%s': %m", - target_dir); + ereport(ERROR, + (errcode_for_file_access(), + errmsg("unable to create database directory \"%s\": %m", + target_dir))); if (rmdir(target_dir) != 0) - elog(ERROR, "CREATE DATABASE: unable to remove temp directory '%s': %m", - target_dir); + ereport(ERROR, + (errcode_for_file_access(), + errmsg("unable to remove temp directory \"%s\": %m", + target_dir))); /* Make the symlink, if needed */ if (alt_loc) @@ -306,8 +348,10 @@ createdb(const CreatedbStmt *stmt) #ifdef HAVE_SYMLINK /* already throws error above */ if (symlink(alt_loc, nominal_loc) != 0) #endif - elog(ERROR, "CREATE DATABASE: could not link '%s' to '%s': %m", - nominal_loc, alt_loc); + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not link \"%s\" to \"%s\": %m", + nominal_loc, alt_loc))); } /* Copy the template database to the new location */ @@ -319,9 +363,9 @@ createdb(const CreatedbStmt *stmt) #endif { if (remove_dbdirs(nominal_loc, alt_loc)) - elog(ERROR, "CREATE DATABASE: could not initialize database directory"); + elog(ERROR, "could not initialize database directory"); else - elog(ERROR, "CREATE DATABASE: could not initialize database directory; delete failed as well"); + elog(ERROR, "could not initialize database directory; delete failed as well"); } /* @@ -335,7 +379,9 @@ createdb(const CreatedbStmt *stmt) /* Don't hold lock while doing recursive remove */ heap_close(pg_database_rel, AccessExclusiveLock); remove_dbdirs(nominal_loc, alt_loc); - elog(ERROR, "CREATE DATABASE: database \"%s\" already exists", dbname); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_DATABASE), + errmsg("database \"%s\" already exists", dbname))); } /* @@ -411,7 +457,9 @@ dropdb(const char *dbname) AssertArg(dbname); if (strcmp(dbname, get_database_name(MyDatabaseId)) == 0) - elog(ERROR, "DROP DATABASE: cannot be executed on the currently open database"); + ereport(ERROR, + (errcode(ERRCODE_OBJECT_IN_USE), + errmsg("cannot drop the currently open database"))); PreventTransactionChain((void *) dbname, "DROP DATABASE"); @@ -428,10 +476,14 @@ dropdb(const char *dbname) if (!get_db_info(dbname, &db_id, &db_owner, NULL, &db_istemplate, NULL, NULL, NULL, dbpath)) - elog(ERROR, "DROP DATABASE: database \"%s\" does not exist", dbname); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_DATABASE), + errmsg("database \"%s\" does not exist", dbname))); if (GetUserId() != db_owner && !superuser()) - elog(ERROR, "DROP DATABASE: permission denied"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied"))); /* * Disallow dropping a DB that is marked istemplate. This is just to @@ -439,7 +491,9 @@ dropdb(const char *dbname) * they can do so if they're really determined ... */ if (db_istemplate) - elog(ERROR, "DROP DATABASE: database is marked as a template"); + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot drop a template database"))); nominal_loc = GetDatabasePath(db_id); alt_loc = resolve_alt_dbpath(dbpath, db_id); @@ -448,7 +502,10 @@ dropdb(const char *dbname) * Check for active backends in the target database. */ if (DatabaseHasActiveBackends(db_id, false)) - elog(ERROR, "DROP DATABASE: database \"%s\" is being accessed by other users", dbname); + ereport(ERROR, + (errcode(ERRCODE_OBJECT_IN_USE), + errmsg("database \"%s\" is being accessed by other users", + dbname))); /* * Find the database's tuple by OID (should be unique). @@ -465,7 +522,7 @@ dropdb(const char *dbname) * This error should never come up since the existence of the * database is checked earlier */ - elog(ERROR, "DROP DATABASE: Database \"%s\" doesn't exist despite earlier reports to the contrary", + elog(ERROR, "database \"%s\" doesn't exist despite earlier reports to the contrary", dbname); } @@ -539,7 +596,7 @@ RenameDatabase(const char *oldname, const char *newname) tup = systable_getnext(scan); if (!HeapTupleIsValid(tup)) ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + (errcode(ERRCODE_UNDEFINED_DATABASE), errmsg("database \"%s\" does not exist", oldname))); /* @@ -550,7 +607,7 @@ RenameDatabase(const char *oldname, const char *newname) */ if (HeapTupleGetOid(tup) == MyDatabaseId) ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("current database may not be renamed"))); /* @@ -559,18 +616,19 @@ RenameDatabase(const char *oldname, const char *newname) * operations. */ if (DatabaseHasActiveBackends(HeapTupleGetOid(tup), false)) - elog(ERROR, "database \"%s\" is being accessed by other users", oldname); + ereport(ERROR, + (errcode(ERRCODE_OBJECT_IN_USE), + errmsg("database \"%s\" is being accessed by other users", + oldname))); /* make sure the new name doesn't exist */ ScanKeyEntryInitialize(&key2, 0, Anum_pg_database_datname, F_NAMEEQ, NameGetDatum(newname)); scan2 = systable_beginscan(rel, DatabaseNameIndex, true, SnapshotNow, 1, &key2); if (HeapTupleIsValid(systable_getnext(scan2))) - { ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + (errcode(ERRCODE_DUPLICATE_DATABASE), errmsg("database \"%s\" already exists", newname))); - } systable_endscan(scan2); /* must be owner */ @@ -579,11 +637,9 @@ RenameDatabase(const char *oldname, const char *newname) /* must have createdb */ if (!have_createdb_privilege()) - { ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied"))); - } /* rename */ newtup = heap_copytuple(tup); @@ -628,11 +684,15 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt) scan = systable_beginscan(rel, DatabaseNameIndex, true, SnapshotNow, 1, &scankey); tuple = systable_getnext(scan); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "database \"%s\" does not exist", stmt->dbname); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_DATABASE), + errmsg("database \"%s\" does not exist", stmt->dbname))); if (!(superuser() - || ((Form_pg_database) GETSTRUCT(tuple))->datdba == GetUserId())) - elog(ERROR, "ALTER DATABASE SET: permission denied"); + || ((Form_pg_database) GETSTRUCT(tuple))->datdba == GetUserId())) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied"))); MemSet(repl_repl, ' ', sizeof(repl_repl)); repl_repl[Anum_pg_database_datconfig - 1] = 'r'; @@ -797,9 +857,13 @@ resolve_alt_dbpath(const char *dbpath, Oid dboid) if (first_path_separator(dbpath)) { if (!is_absolute_path(dbpath)) - elog(ERROR, "Relative paths are not allowed as database locations"); + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("relative paths are not allowed as database locations"))); #ifndef ALLOW_ABSOLUTE_DBPATHS - elog(ERROR, "Absolute paths are not allowed as database locations"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("absolute paths are not allowed as database locations"))); #endif prefix = dbpath; } @@ -809,15 +873,23 @@ resolve_alt_dbpath(const char *dbpath, Oid dboid) char *var = getenv(dbpath); if (!var) - elog(ERROR, "Postmaster environment variable '%s' not set", dbpath); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("postmaster environment variable \"%s\" not found", + dbpath))); if (!is_absolute_path(var)) - elog(ERROR, "Postmaster environment variable '%s' must be absolute path", dbpath); + ereport(ERROR, + (errcode(ERRCODE_INVALID_NAME), + errmsg("postmaster environment variable \"%s\" must be absolute path", + dbpath))); prefix = var; } len = strlen(prefix) + 6 + sizeof(Oid) * 8 + 1; if (len >= MAXPGPATH - 100) - elog(ERROR, "Alternate path is too long"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_NAME), + errmsg("alternate path is too long"))); ret = palloc(len); snprintf(ret, len, "%s/base/%u", prefix, dboid); @@ -846,7 +918,9 @@ remove_dbdirs(const char *nominal_loc, const char *alt_loc) /* remove symlink */ if (unlink(nominal_loc) != 0) { - elog(WARNING, "could not remove '%s': %m", nominal_loc); + ereport(WARNING, + (errcode_for_file_access(), + errmsg("could not remove \"%s\": %m", nominal_loc))); success = false; } } @@ -859,8 +933,10 @@ remove_dbdirs(const char *nominal_loc, const char *alt_loc) if (system(buf) != 0) { - elog(WARNING, "database directory '%s' could not be removed", - target_dir); + ereport(WARNING, + (errcode_for_file_access(), + errmsg("could not remove database directory \"%s\": %m", + target_dir))); success = false; } diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index a7c7c47e19..e09f48edd3 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.27 2003/07/04 02:51:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.28 2003/07/18 23:20:32 tgl Exp $ * * DESCRIPTION * These routines take the parse tree and pick out the @@ -78,11 +78,15 @@ compute_return_type(TypeName *returnType, Oid languageOid, if (!get_typisdefined(rettype)) { if (languageOid == SQLlanguageId) - elog(ERROR, "SQL function cannot return shell type \"%s\"", - TypeNameToString(returnType)); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("SQL function cannot return shell type %s", + TypeNameToString(returnType)))); else - elog(NOTICE, "Return type \"%s\" is only a shell", - TypeNameToString(returnType)); + ereport(NOTICE, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("return type %s is only a shell", + TypeNameToString(returnType)))); } } else @@ -100,11 +104,15 @@ compute_return_type(TypeName *returnType, Oid languageOid, */ if (languageOid != INTERNALlanguageId && languageOid != ClanguageId) - elog(ERROR, "Type \"%s\" does not exist", typnam); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("type %s does not exist", typnam))); /* Otherwise, go ahead and make a shell type */ - elog(NOTICE, "ProcedureCreate: type %s is not yet defined", - typnam); + ereport(NOTICE, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("type %s is not yet defined", typnam), + errdetail("Creating a shell type definition."))); namespaceId = QualifiedNameGetCreationNamespace(returnType->names, &typname); aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), @@ -112,8 +120,7 @@ compute_return_type(TypeName *returnType, Oid languageOid, if (aclresult != ACLCHECK_OK) aclcheck_error(aclresult, get_namespace_name(namespaceId)); rettype = TypeShellMake(typname, namespaceId); - if (!OidIsValid(rettype)) - elog(ERROR, "could not create type %s", typnam); + Assert(OidIsValid(rettype)); } *prorettype_p = rettype; @@ -137,8 +144,10 @@ compute_parameter_types(List *argTypes, Oid languageOid, Oid toid; if (parameterCount >= FUNC_MAX_ARGS) - elog(ERROR, "functions cannot have more than %d arguments", - FUNC_MAX_ARGS); + ereport(ERROR, + (errcode(ERRCODE_TOO_MANY_ARGUMENTS), + errmsg("functions cannot have more than %d arguments", + FUNC_MAX_ARGS))); toid = LookupTypeName(t); if (OidIsValid(toid)) @@ -147,21 +156,29 @@ compute_parameter_types(List *argTypes, Oid languageOid, { /* As above, hard error if language is SQL */ if (languageOid == SQLlanguageId) - elog(ERROR, "SQL function cannot accept shell type \"%s\"", - TypeNameToString(t)); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("SQL function cannot accept shell type %s", + TypeNameToString(t)))); else - elog(NOTICE, "Argument type \"%s\" is only a shell", - TypeNameToString(t)); + ereport(NOTICE, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("argument type %s is only a shell", + TypeNameToString(t)))); } } else { - elog(ERROR, "Type \"%s\" does not exist", - TypeNameToString(t)); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("type %s does not exist", + TypeNameToString(t)))); } if (t->setof) - elog(ERROR, "Functions cannot accept set arguments"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("functions cannot accept set arguments"))); parameterTypes[parameterCount++] = toid; } @@ -197,46 +214,61 @@ compute_attributes_sql_style(const List *options, if (strcmp(defel->defname, "as") == 0) { if (as_item) - elog(ERROR, "conflicting or redundant options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); as_item = defel; } else if (strcmp(defel->defname, "language") == 0) { if (language_item) - elog(ERROR, "conflicting or redundant options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); language_item = defel; } else if (strcmp(defel->defname, "volatility") == 0) { if (volatility_item) - elog(ERROR, "conflicting or redundant options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); volatility_item = defel; } else if (strcmp(defel->defname, "strict") == 0) { if (strict_item) - elog(ERROR, "conflicting or redundant options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); strict_item = defel; } else if (strcmp(defel->defname, "security") == 0) { if (security_item) - elog(ERROR, "conflicting or redundant options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); security_item = defel; } else - elog(ERROR, "invalid CREATE FUNCTION option"); + elog(ERROR, "option \"%s\" not recognized", + defel->defname); } if (as_item) *as = (List *) as_item->arg; else - elog(ERROR, "no function body specified"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("no function body specified"))); if (language_item) *language = strVal(language_item->arg); else - elog(ERROR, "no language specified"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("no language specified"))); if (volatility_item) { @@ -247,7 +279,8 @@ compute_attributes_sql_style(const List *options, else if (strcmp(strVal(volatility_item->arg), "volatile") == 0) *volatility_p = PROVOLATILE_VOLATILE; else - elog(ERROR, "invalid volatility"); + elog(ERROR, "invalid volatility \"%s\"", + strVal(volatility_item->arg)); } if (strict_item) @@ -294,8 +327,10 @@ compute_attributes_with_style(List *parameters, bool *isStrict_p, char *volatili *volatility_p = PROVOLATILE_IMMUTABLE; } else - elog(WARNING, "Unrecognized function attribute '%s' ignored", - param->defname); + ereport(WARNING, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("unrecognized function attribute \"%s\" ignored", + param->defname))); } } @@ -336,8 +371,10 @@ interpret_AS_clause(Oid languageOid, const char *languageName, const List *as, *probin_str_p = "-"; if (lnext(as) != NIL) - elog(ERROR, "CREATE FUNCTION: only one AS item needed for %s language", - languageName); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("only one AS item needed for language \"%s\"", + languageName))); } } @@ -396,7 +433,9 @@ CreateFunction(CreateFunctionStmt *stmt) PointerGetDatum(languageName), 0, 0, 0); if (!HeapTupleIsValid(languageTuple)) - elog(ERROR, "language \"%s\" does not exist", languageName); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("language \"%s\" does not exist", languageName))); languageOid = HeapTupleGetOid(languageTuple); languageStruct = (Form_pg_language) GETSTRUCT(languageTuple); @@ -501,8 +540,7 @@ RemoveFunction(RemoveFuncStmt *stmt) ObjectIdGetDatum(funcOid), 0, 0, 0); if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "RemoveFunction: couldn't find tuple for function %s", - NameListToString(functionName)); + elog(ERROR, "cache lookup failed for function %u", funcOid); /* Permission check: must own func or its namespace */ if (!pg_proc_ownercheck(funcOid, GetUserId()) && @@ -511,15 +549,19 @@ RemoveFunction(RemoveFuncStmt *stmt) aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(functionName)); if (((Form_pg_proc) GETSTRUCT(tup))->proisagg) - elog(ERROR, "RemoveFunction: function '%s' is an aggregate" - "\n\tUse DROP AGGREGATE to remove it", - NameListToString(functionName)); + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is an aggregate function", + NameListToString(functionName)), + errhint("Use DROP AGGREGATE to drop aggregate functions."))); if (((Form_pg_proc) GETSTRUCT(tup))->prolang == INTERNALlanguageId) { /* "Helpful" NOTICE when removing a builtin function ... */ - elog(NOTICE, "Removing built-in function \"%s\"", - NameListToString(functionName)); + ereport(NOTICE, + (errcode(ERRCODE_WARNING), + errmsg("removing built-in function \"%s\"", + NameListToString(functionName)))); } ReleaseSysCache(tup); @@ -556,8 +598,7 @@ RemoveFunctionById(Oid funcOid) ObjectIdGetDatum(funcOid), 0, 0, 0); if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "RemoveFunctionById: couldn't find tuple for function %u", - funcOid); + elog(ERROR, "cache lookup failed for function %u", funcOid); isagg = ((Form_pg_proc) GETSTRUCT(tup))->proisagg; @@ -578,8 +619,7 @@ RemoveFunctionById(Oid funcOid) ObjectIdGetDatum(funcOid), 0, 0, 0); if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "RemoveFunctionById: couldn't find pg_aggregate tuple for %u", - funcOid); + elog(ERROR, "cache lookup failed for pg_aggregate tuple for function %u", funcOid); simple_heap_delete(relation, &tup->t_self); @@ -598,11 +638,10 @@ RenameFunction(List *name, List *argtypes, const char *newname) { Oid procOid; Oid namespaceOid; - Oid oid_array[FUNC_MAX_ARGS]; HeapTuple tup; + Form_pg_proc procForm; Relation rel; AclResult aclresult; - int16 nargs; rel = heap_openr(ProcedureRelationName, RowExclusiveLock); @@ -612,29 +651,31 @@ RenameFunction(List *name, List *argtypes, const char *newname) ObjectIdGetDatum(procOid), 0, 0, 0); if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "RenameFunction: couldn't find pg_proc tuple for %s", - NameListToString(name)); + elog(ERROR, "cache lookup failed for function %u", procOid); + procForm = (Form_pg_proc) GETSTRUCT(tup); - if (((Form_pg_proc) GETSTRUCT(tup))->proisagg) + if (procForm->proisagg) ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), - errmsg("%s is an aggregate function", NameListToString(name)), + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is an aggregate function", + NameListToString(name)), errhint("Use ALTER AGGREGATE to rename aggregate functions."))); - namespaceOid = ((Form_pg_proc) GETSTRUCT(tup))->pronamespace; + namespaceOid = procForm->pronamespace; /* make sure the new name doesn't exist */ - nargs = compute_parameter_types(argtypes, ((Form_pg_proc) GETSTRUCT(tup))->prolang, oid_array); if (SearchSysCacheExists(PROCNAMENSP, CStringGetDatum(newname), - Int16GetDatum(nargs), - PointerGetDatum(oid_array), + Int16GetDatum(procForm->pronargs), + PointerGetDatum(procForm->proargtypes), ObjectIdGetDatum(namespaceOid))) { ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), - errmsg("function %s with the same argument types already exists in schema %s", - newname, get_namespace_name(namespaceOid)))); + (errcode(ERRCODE_DUPLICATE_FUNCTION), + errmsg("function %s already exists", + func_signature_string(name, + procForm->pronargs, + procForm->proargtypes)))); } /* must be owner */ @@ -647,7 +688,7 @@ RenameFunction(List *name, List *argtypes, const char *newname) aclcheck_error(aclresult, get_namespace_name(namespaceOid)); /* rename */ - namestrcpy(&(((Form_pg_proc) GETSTRUCT(tup))->proname), newname); + namestrcpy(&(procForm->proname), newname); simple_heap_update(rel, &tup->t_self, tup); CatalogUpdateIndexes(rel, tup); @@ -676,13 +717,11 @@ SetFunctionReturnType(Oid funcOid, Oid newRetType) ObjectIdGetDatum(funcOid), 0, 0, 0); if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "SetFunctionReturnType: couldn't find tuple for function %u", - funcOid); + elog(ERROR, "cache lookup failed for function %u", funcOid); procForm = (Form_pg_proc) GETSTRUCT(tup); - if (procForm->prorettype != OPAQUEOID) - elog(ERROR, "SetFunctionReturnType: function %u doesn't return OPAQUE", - funcOid); + if (procForm->prorettype != OPAQUEOID) /* caller messed up */ + elog(ERROR, "function %u doesn't return OPAQUE", funcOid); /* okay to overwrite copied tuple */ procForm->prorettype = newRetType; @@ -714,14 +753,12 @@ SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType) ObjectIdGetDatum(funcOid), 0, 0, 0); if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "SetFunctionArgType: couldn't find tuple for function %u", - funcOid); + elog(ERROR, "cache lookup failed for function %u", funcOid); procForm = (Form_pg_proc) GETSTRUCT(tup); if (argIndex < 0 || argIndex >= procForm->pronargs || procForm->proargtypes[argIndex] != OPAQUEOID) - elog(ERROR, "SetFunctionArgType: function %u doesn't take OPAQUE", - funcOid); + elog(ERROR, "function %u doesn't take OPAQUE", funcOid); /* okay to overwrite copied tuple */ procForm->proargtypes[argIndex] = newArgType; @@ -755,39 +792,56 @@ CreateCast(CreateCastStmt *stmt) sourcetypeid = LookupTypeName(stmt->sourcetype); if (!OidIsValid(sourcetypeid)) - elog(ERROR, "source data type %s does not exist", - TypeNameToString(stmt->sourcetype)); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("source data type %s does not exist", + TypeNameToString(stmt->sourcetype)))); targettypeid = LookupTypeName(stmt->targettype); if (!OidIsValid(targettypeid)) - elog(ERROR, "target data type %s does not exist", - TypeNameToString(stmt->targettype)); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("target data type %s does not exist", + TypeNameToString(stmt->targettype)))); if (sourcetypeid == targettypeid) - elog(ERROR, "source data type and target data type are the same"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("source data type and target data type are the same"))); /* No shells, no pseudo-types allowed */ if (!get_typisdefined(sourcetypeid)) - elog(ERROR, "source data type %s is only a shell", - TypeNameToString(stmt->sourcetype)); + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("source data type %s is only a shell", + TypeNameToString(stmt->sourcetype)))); if (!get_typisdefined(targettypeid)) - elog(ERROR, "target data type %s is only a shell", - TypeNameToString(stmt->targettype)); + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("target data type %s is only a shell", + TypeNameToString(stmt->targettype)))); if (get_typtype(sourcetypeid) == 'p') - elog(ERROR, "source data type %s is a pseudo-type", - TypeNameToString(stmt->sourcetype)); + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("source data type %s is a pseudo-type", + TypeNameToString(stmt->sourcetype)))); if (get_typtype(targettypeid) == 'p') - elog(ERROR, "target data type %s is a pseudo-type", - TypeNameToString(stmt->targettype)); + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("target data type %s is a pseudo-type", + TypeNameToString(stmt->targettype)))); + /* Permission check */ if (!pg_type_ownercheck(sourcetypeid, GetUserId()) && !pg_type_ownercheck(targettypeid, GetUserId())) - elog(ERROR, "must be owner of type %s or type %s", - TypeNameToString(stmt->sourcetype), - TypeNameToString(stmt->targettype)); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be owner of type %s or type %s", + TypeNameToString(stmt->sourcetype), + TypeNameToString(stmt->targettype)))); if (stmt->func != NULL) { @@ -801,15 +855,21 @@ CreateCast(CreateCastStmt *stmt) ObjectIdGetDatum(funcid), 0, 0, 0); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "cache lookup of function %u failed", funcid); + elog(ERROR, "cache lookup failed for function %u", funcid); procstruct = (Form_pg_proc) GETSTRUCT(tuple); if (procstruct->pronargs != 1) - elog(ERROR, "cast function must take 1 argument"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("cast function must take 1 argument"))); if (procstruct->proargtypes[0] != sourcetypeid) - elog(ERROR, "argument of cast function must match source data type"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("argument of cast function must match source data type"))); if (procstruct->prorettype != targettypeid) - elog(ERROR, "return data type of cast function must match target data type"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("return data type of cast function must match target data type"))); /* * Restricting the volatility of a cast function may or may not be * a good idea in the abstract, but it definitely breaks many old @@ -817,12 +877,18 @@ CreateCast(CreateCastStmt *stmt) */ #ifdef NOT_USED if (procstruct->provolatile == PROVOLATILE_VOLATILE) - elog(ERROR, "cast function must not be volatile"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("cast function must not be volatile"))); #endif if (procstruct->proisagg) - elog(ERROR, "cast function must not be an aggregate function"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("cast function must not be an aggregate function"))); if (procstruct->proretset) - elog(ERROR, "cast function must not return a set"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("cast function must not return a set"))); ReleaseSysCache(tuple); } @@ -843,7 +909,9 @@ CreateCast(CreateCastStmt *stmt) * erroneous casts can easily crash the backend. */ if (!superuser()) - elog(ERROR, "Must be superuser to create a cast WITHOUT FUNCTION"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be superuser to create a cast WITHOUT FUNCTION"))); /* * Also, insist that the types match as to size, alignment, and @@ -856,7 +924,9 @@ CreateCast(CreateCastStmt *stmt) if (typ1len != typ2len || typ1byval != typ2byval || typ1align != typ2align) - elog(ERROR, "source and target datatypes are not physically compatible"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("source and target datatypes are not physically compatible"))); } /* convert CoercionContext enum to char value for castcontext */ @@ -872,7 +942,7 @@ CreateCast(CreateCastStmt *stmt) castcontext = COERCION_CODE_EXPLICIT; break; default: - elog(ERROR, "CreateCast: bogus CoercionContext %c", stmt->context); + elog(ERROR, "unrecognized CoercionContext: %d", stmt->context); castcontext = 0; /* keep compiler quiet */ break; } @@ -889,9 +959,11 @@ CreateCast(CreateCastStmt *stmt) ObjectIdGetDatum(targettypeid), 0, 0); if (HeapTupleIsValid(tuple)) - elog(ERROR, "cast from data type %s to data type %s already exists", - TypeNameToString(stmt->sourcetype), - TypeNameToString(stmt->targettype)); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("cast from data type %s to data type %s already exists", + TypeNameToString(stmt->sourcetype), + TypeNameToString(stmt->targettype)))); /* ready to go */ values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid); @@ -953,29 +1025,37 @@ DropCast(DropCastStmt *stmt) sourcetypeid = LookupTypeName(stmt->sourcetype); if (!OidIsValid(sourcetypeid)) - elog(ERROR, "source data type %s does not exist", - TypeNameToString(stmt->sourcetype)); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("source data type %s does not exist", + TypeNameToString(stmt->sourcetype)))); targettypeid = LookupTypeName(stmt->targettype); if (!OidIsValid(targettypeid)) - elog(ERROR, "target data type %s does not exist", - TypeNameToString(stmt->targettype)); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("target data type %s does not exist", + TypeNameToString(stmt->targettype)))); tuple = SearchSysCache(CASTSOURCETARGET, ObjectIdGetDatum(sourcetypeid), ObjectIdGetDatum(targettypeid), 0, 0); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "cast from type %s to type %s does not exist", - TypeNameToString(stmt->sourcetype), - TypeNameToString(stmt->targettype)); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("cast from type %s to type %s does not exist", + TypeNameToString(stmt->sourcetype), + TypeNameToString(stmt->targettype)))); /* Permission check */ if (!pg_type_ownercheck(sourcetypeid, GetUserId()) && !pg_type_ownercheck(targettypeid, GetUserId())) - elog(ERROR, "must be owner of type %s or type %s", - TypeNameToString(stmt->sourcetype), - TypeNameToString(stmt->targettype)); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be owner of type %s or type %s", + TypeNameToString(stmt->sourcetype), + TypeNameToString(stmt->targettype)))); /* * Do the deletion @@ -1006,10 +1086,9 @@ DropCastById(Oid castOid) 1, F_OIDEQ, ObjectIdGetDatum(castOid)); scan = index_beginscan(relation, index, SnapshotNow, 1, &scankey); tuple = index_getnext(scan, ForwardScanDirection); - if (HeapTupleIsValid(tuple)) - simple_heap_delete(relation, &tuple->t_self); - else + if (!HeapTupleIsValid(tuple)) elog(ERROR, "could not find tuple for cast %u", castOid); + simple_heap_delete(relation, &tuple->t_self); index_endscan(scan); index_close(index); diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index 84a01446d4..fde8f95d9c 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.11 2003/07/04 02:51:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.12 2003/07/18 23:20:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -85,8 +85,10 @@ DefineOpClass(CreateOpClassStmt *stmt) CStringGetDatum(stmt->amname), 0, 0, 0); if (!HeapTupleIsValid(tup)) - elog(ERROR, "DefineOpClass: access method \"%s\" not found", - stmt->amname); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("access method \"%s\" does not exist", + stmt->amname))); amoid = HeapTupleGetOid(tup); numOperators = ((Form_pg_am) GETSTRUCT(tup))->amstrategies; @@ -104,7 +106,9 @@ DefineOpClass(CreateOpClassStmt *stmt) * if it can be done without solving the halting problem :-( */ if (!superuser()) - elog(ERROR, "Must be superuser to create an operator class"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be superuser to create an operator class"))); /* Look up the datatype */ typeoid = typenameTypeId(stmt->datatype); @@ -143,12 +147,16 @@ DefineOpClass(CreateOpClassStmt *stmt) { case OPCLASS_ITEM_OPERATOR: if (item->number <= 0 || item->number > numOperators) - elog(ERROR, "DefineOpClass: invalid operator number %d," - " must be between 1 and %d", - item->number, numOperators); + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("invalid operator number %d," + " must be between 1 and %d", + item->number, numOperators))); if (operators[item->number - 1] != InvalidOid) - elog(ERROR, "DefineOpClass: operator number %d appears more than once", - item->number); + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("operator number %d appears more than once", + item->number))); if (item->args != NIL) { TypeName *typeName1 = (TypeName *) lfirst(item->args); @@ -176,12 +184,16 @@ DefineOpClass(CreateOpClassStmt *stmt) break; case OPCLASS_ITEM_FUNCTION: if (item->number <= 0 || item->number > numProcs) - elog(ERROR, "DefineOpClass: invalid procedure number %d," - " must be between 1 and %d", - item->number, numProcs); + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("invalid procedure number %d," + " must be between 1 and %d", + item->number, numProcs))); if (procedures[item->number - 1] != InvalidOid) - elog(ERROR, "DefineOpClass: procedure number %d appears more than once", - item->number); + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("DefineOpClass: procedure number %d appears more than once", + item->number))); funcOid = LookupFuncNameTypeNames(item->name, item->args, false); /* Caller must have execute permission on functions */ @@ -193,12 +205,13 @@ DefineOpClass(CreateOpClassStmt *stmt) break; case OPCLASS_ITEM_STORAGETYPE: if (OidIsValid(storageoid)) - elog(ERROR, "DefineOpClass: storage type specified more than once"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("storage type specified more than once"))); storageoid = typenameTypeId(item->storedtype); break; default: - elog(ERROR, "DefineOpClass: bogus item type %d", - item->itemtype); + elog(ERROR, "unrecognized item type: %d", item->itemtype); break; } } @@ -219,8 +232,10 @@ DefineOpClass(CreateOpClassStmt *stmt) * favor of adding another boolean column to pg_am ... */ if (amoid != GIST_AM_OID) - elog(ERROR, "Storage type may not be different from datatype for access method %s", - stmt->amname); + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("storage type may not be different from datatype for access method \"%s\"", + stmt->amname))); } } @@ -235,8 +250,10 @@ DefineOpClass(CreateOpClassStmt *stmt) CStringGetDatum(opcname), ObjectIdGetDatum(namespaceoid), 0)) - elog(ERROR, "Operator class \"%s\" already exists for access method \"%s\"", - opcname, stmt->amname); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("operator class \"%s\" already exists for access method \"%s\"", + opcname, stmt->amname))); /* * If we are creating a default opclass, check there isn't one @@ -259,11 +276,13 @@ DefineOpClass(CreateOpClassStmt *stmt) Form_pg_opclass opclass = (Form_pg_opclass) GETSTRUCT(tup); if (opclass->opcintype == typeoid && opclass->opcdefault) - elog(ERROR, "Can't add class \"%s\" as default for type %s" - "\n\tclass \"%s\" already is the default", - opcname, - TypeNameToString(stmt->datatype), - NameStr(opclass->opcname)); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("cannot make class \"%s\" be default for type %s", + opcname, + TypeNameToString(stmt->datatype)), + errdetail("class \"%s\" already is the default", + NameStr(opclass->opcname)))); } systable_endscan(scan); @@ -467,8 +486,10 @@ RemoveOpClass(RemoveOpClassStmt *stmt) CStringGetDatum(stmt->amname), 0, 0, 0); if (!OidIsValid(amID)) - elog(ERROR, "RemoveOpClass: access method \"%s\" not found", - stmt->amname); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("access method \"%s\" does not exist", + stmt->amname))); /* * Look up the opclass. @@ -494,16 +515,20 @@ RemoveOpClass(RemoveOpClassStmt *stmt) /* Unqualified opclass name, so search the search path */ opcID = OpclassnameGetOpcid(amID, opcname); if (!OidIsValid(opcID)) - elog(ERROR, "RemoveOpClass: operator class \"%s\" not supported by access method \"%s\"", - opcname, stmt->amname); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("operator class \"%s\" does not exist for access method \"%s\"", + opcname, stmt->amname))); tuple = SearchSysCache(CLAOID, ObjectIdGetDatum(opcID), 0, 0, 0); } if (!HeapTupleIsValid(tuple)) - elog(ERROR, "RemoveOpClass: operator class \"%s\" not supported by access method \"%s\"", - NameListToString(stmt->opclassname), stmt->amname); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("operator class \"%s\" does not exist for access method \"%s\"", + NameListToString(stmt->opclassname), stmt->amname))); opcID = HeapTupleGetOid(tuple); @@ -546,8 +571,7 @@ RemoveOpClassById(Oid opclassOid) ObjectIdGetDatum(opclassOid), 0, 0, 0); if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "RemoveOpClassById: couldn't find pg_opclass entry %u", - opclassOid); + elog(ERROR, "cache lookup failed for opclass %u", opclassOid); simple_heap_delete(rel, &tup->t_self); @@ -612,7 +636,10 @@ RenameOpClass(List *name, const char *access_method, const char *newname) CStringGetDatum(access_method), 0, 0, 0); if (!OidIsValid(amOid)) - elog(ERROR, "access method \"%s\" not found", access_method); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("access method \"%s\" does not exist", + access_method))); rel = heap_openr(OperatorClassRelationName, RowExclusiveLock); @@ -631,8 +658,10 @@ RenameOpClass(List *name, const char *access_method, const char *newname) ObjectIdGetDatum(namespaceOid), 0); if (!HeapTupleIsValid(tup)) - elog(ERROR, "operator class \"%s\" for access method \"%s\" does not exist", - opcname, access_method); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("operator class \"%s\" does not exist for access method \"%s\"", + opcname, access_method))); opcOid = HeapTupleGetOid(tup); } @@ -640,14 +669,16 @@ RenameOpClass(List *name, const char *access_method, const char *newname) { opcOid = OpclassnameGetOpcid(amOid, opcname); if (!OidIsValid(opcOid)) - elog(ERROR, "operator class \"%s\" for access method \"%s\" does not exist", - opcname, access_method); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("operator class \"%s\" does not exist for access method \"%s\"", + opcname, access_method))); tup = SearchSysCacheCopy(CLAOID, ObjectIdGetDatum(opcOid), 0, 0, 0); if (!HeapTupleIsValid(tup)) /* should not happen */ - elog(ERROR, "couldn't find pg_opclass tuple for %u", opcOid); + elog(ERROR, "cache lookup failed for opclass %u", opcOid); namespaceOid = ((Form_pg_opclass) GETSTRUCT(tup))->opcnamespace; } @@ -660,9 +691,10 @@ RenameOpClass(List *name, const char *access_method, const char *newname) 0)) { ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("operator class \"%s\" for access method \"%s\" already exists in schema \"%s\"", - newname, access_method, get_namespace_name(namespaceOid)))); + newname, access_method, + get_namespace_name(namespaceOid)))); } /* must be owner */ diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index 65c82fbab8..ea7c5c6570 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.45 2003/07/04 02:51:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.46 2003/07/18 23:20:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -58,8 +58,9 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) * Check permission */ if (!superuser()) - elog(ERROR, "Only users with superuser privilege are " - "permitted to create procedural languages"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be superuser to create procedural language"))); /* * Translate the language name and check that this language doesn't @@ -70,7 +71,9 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) if (SearchSysCacheExists(LANGNAME, PointerGetDatum(languageName), 0, 0, 0)) - elog(ERROR, "Language %s already exists", languageName); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("language \"%s\" already exists", languageName))); /* * Lookup the PL handler function and check that it is of the expected @@ -88,13 +91,17 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) */ if (funcrettype == OPAQUEOID) { - elog(NOTICE, "CreateProceduralLanguage: changing return type of function %s() from OPAQUE to LANGUAGE_HANDLER", - NameListToString(stmt->plhandler)); + ereport(NOTICE, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("changing return type of function %s() from OPAQUE to LANGUAGE_HANDLER", + NameListToString(stmt->plhandler)))); SetFunctionReturnType(procOid, LANGUAGE_HANDLEROID); } else - elog(ERROR, "CreateProceduralLanguage: function %s() must return LANGUAGE_HANDLER", - NameListToString(stmt->plhandler)); + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("function %s() must return LANGUAGE_HANDLER", + NameListToString(stmt->plhandler)))); } /* validate the validator function */ @@ -174,8 +181,9 @@ DropProceduralLanguage(DropPLangStmt *stmt) * Check permission */ if (!superuser()) - elog(ERROR, "Only users with superuser privilege are " - "permitted to drop procedural languages"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be superuser to drop procedural language"))); /* * Translate the language name, check that this language exist and is @@ -187,7 +195,9 @@ DropProceduralLanguage(DropPLangStmt *stmt) CStringGetDatum(languageName), 0, 0, 0); if (!HeapTupleIsValid(langTup)) - elog(ERROR, "Language %s doesn't exist", languageName); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("language \"%s\" does not exist", languageName))); object.classId = get_system_catalog_relid(LanguageRelationName); object.objectId = HeapTupleGetOid(langTup); @@ -215,9 +225,8 @@ DropProceduralLanguageById(Oid langOid) langTup = SearchSysCache(LANGOID, ObjectIdGetDatum(langOid), 0, 0, 0); - if (!HeapTupleIsValid(langTup)) - elog(ERROR, "DropProceduralLanguageById: language %u not found", - langOid); + if (!HeapTupleIsValid(langTup)) /* should not happen */ + elog(ERROR, "cache lookup failed for language %u", langOid); simple_heap_delete(rel, &langTup->t_self); @@ -242,23 +251,21 @@ RenameLanguage(const char *oldname, const char *newname) 0, 0, 0); if (!HeapTupleIsValid(tup)) ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("language \"%s\" does not exist", oldname))); /* make sure the new name doesn't exist */ if (SearchSysCacheExists(LANGNAME, CStringGetDatum(newname), 0, 0, 0)) - { ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("language \"%s\" already exists", newname))); - } /* must be superuser */ if (!superuser()) ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied"))); /* rename */ diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c index 1fbd987db4..8d50f0d69c 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.11 2003/06/27 17:05:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.12 2003/07/18 23:20:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -74,14 +74,16 @@ CreateSchemaCommand(CreateSchemaStmt *stmt) SetUserId(owner_userid); } else -/* not superuser */ { + /* not superuser */ owner_userid = saved_userid; owner_name = GetUserNameFromId(owner_userid); if (strcmp(authId, owner_name) != 0) - elog(ERROR, "CREATE SCHEMA: permission denied" - "\n\t\"%s\" is not a superuser, so cannot create a schema for \"%s\"", - owner_name, authId); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied"), + errdetail("\"%s\" is not a superuser, so cannot create a schema for \"%s\"", + owner_name, authId))); } /* @@ -92,8 +94,10 @@ CreateSchemaCommand(CreateSchemaStmt *stmt) aclcheck_error(aclresult, get_database_name(MyDatabaseId)); if (!allowSystemTableMods && IsReservedName(schemaName)) - elog(ERROR, "CREATE SCHEMA: Illegal schema name: \"%s\" -- pg_ is reserved for system schemas", - schemaName); + ereport(ERROR, + (errcode(ERRCODE_RESERVED_NAME), + errmsg("unacceptable schema name \"%s\"", schemaName), + errdetail("The prefix pg_ is reserved for system schemas."))); /* Create the schema's namespace */ namespaceId = NamespaceCreate(schemaName, owner_userid); @@ -162,14 +166,18 @@ RemoveSchema(List *names, DropBehavior behavior) ObjectAddress object; if (length(names) != 1) - elog(ERROR, "Schema name may not be qualified"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("schema name may not be qualified"))); namespaceName = strVal(lfirst(names)); namespaceId = GetSysCacheOid(NAMESPACENAME, CStringGetDatum(namespaceName), 0, 0, 0); if (!OidIsValid(namespaceId)) - elog(ERROR, "Schema \"%s\" does not exist", namespaceName); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_SCHEMA), + errmsg("schema \"%s\" does not exist", namespaceName))); /* Permission check */ if (!pg_namespace_ownercheck(namespaceId, GetUserId())) @@ -205,9 +213,8 @@ RemoveSchemaById(Oid schemaOid) tup = SearchSysCache(NAMESPACEOID, ObjectIdGetDatum(schemaOid), 0, 0, 0); - if (!HeapTupleIsValid(tup)) - elog(ERROR, "RemoveSchemaById: schema %u not found", - schemaOid); + if (!HeapTupleIsValid(tup)) /* should not happen */ + elog(ERROR, "cache lookup failed for schema %u", schemaOid); simple_heap_delete(relation, &tup->t_self); @@ -234,7 +241,7 @@ RenameSchema(const char *oldname, const char *newname) 0, 0, 0); if (!HeapTupleIsValid(tup)) ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + (errcode(ERRCODE_UNDEFINED_SCHEMA), errmsg("schema \"%s\" does not exist", oldname))); /* make sure the new name doesn't exist */ @@ -242,11 +249,9 @@ RenameSchema(const char *oldname, const char *newname) SearchSysCache(NAMESPACENAME, CStringGetDatum(newname), 0, 0, 0))) - { ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + (errcode(ERRCODE_DUPLICATE_SCHEMA), errmsg("schema \"%s\" already exists", newname))); - } /* must be owner */ if (!pg_namespace_ownercheck(HeapTupleGetOid(tup), GetUserId())) @@ -258,8 +263,10 @@ RenameSchema(const char *oldname, const char *newname) aclcheck_error(aclresult, get_database_name(MyDatabaseId)); if (!allowSystemTableMods && IsReservedName(newname)) - elog(ERROR, "illegal schema name: \"%s\" -- pg_ is reserved for system schemas", - newname); + ereport(ERROR, + (errcode(ERRCODE_RESERVED_NAME), + errmsg("unacceptable schema name \"%s\"", newname), + errdetail("The prefix pg_ is reserved for system schemas."))); /* rename */ namestrcpy(&(((Form_pg_namespace) GETSTRUCT(tup))->nspname), newname); diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index be588b0863..a54162e24c 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.118 2003/06/27 14:45:27 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.119 2003/07/18 23:20:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -144,7 +144,9 @@ write_group_file(Relation grel) fp = AllocateFile(tempname, "w"); umask(oumask); if (fp == NULL) - elog(ERROR, "write_group_file: unable to write %s: %m", tempname); + ereport(ERROR, + (errcode_for_file_access(), + errmsg("unable to write temp file \"%s\": %m", tempname))); /* * Read pg_group and write the file. Note we use SnapshotSelf to ensure @@ -178,7 +180,7 @@ write_group_file(Relation grel) i = strcspn(groname, "\n"); if (groname[i] != '\0') { - elog(LOG, "Invalid group name '%s'", groname); + elog(LOG, "invalid group name \"%s\"", groname); continue; } @@ -208,7 +210,7 @@ write_group_file(Relation grel) j = strcspn(usename, "\n"); if (usename[j] != '\0') { - elog(LOG, "Invalid user name '%s'", usename); + elog(LOG, "invalid user name \"%s\"", usename); continue; } @@ -239,7 +241,9 @@ write_group_file(Relation grel) fflush(fp); if (ferror(fp)) - elog(ERROR, "%s: %m", tempname); + ereport(ERROR, + (errcode_for_file_access(), + errmsg("unable to write temp file \"%s\": %m", tempname))); FreeFile(fp); /* @@ -247,7 +251,10 @@ write_group_file(Relation grel) * expect that rename(2) is an atomic action. */ if (rename(tempname, filename)) - elog(ERROR, "rename %s to %s: %m", tempname, filename); + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not rename \"%s\" to \"%s\": %m", + tempname, filename))); pfree((void *) tempname); pfree((void *) filename); @@ -283,7 +290,9 @@ write_user_file(Relation urel) fp = AllocateFile(tempname, "w"); umask(oumask); if (fp == NULL) - elog(ERROR, "write_user_file: unable to write %s: %m", tempname); + ereport(ERROR, + (errcode_for_file_access(), + errmsg("unable to write temp file \"%s\": %m", tempname))); /* * Read pg_shadow and write the file. Note we use SnapshotSelf to ensure @@ -332,13 +341,13 @@ write_user_file(Relation urel) i = strcspn(usename, "\n"); if (usename[i] != '\0') { - elog(LOG, "Invalid user name '%s'", usename); + elog(LOG, "invalid user name \"%s\"", usename); continue; } i = strcspn(passwd, "\n"); if (passwd[i] != '\0') { - elog(LOG, "Invalid user password '%s'", passwd); + elog(LOG, "invalid user password \"%s\"", passwd); continue; } @@ -361,7 +370,9 @@ write_user_file(Relation urel) fflush(fp); if (ferror(fp)) - elog(ERROR, "%s: %m", tempname); + ereport(ERROR, + (errcode_for_file_access(), + errmsg("unable to write temp file \"%s\": %m", tempname))); FreeFile(fp); /* @@ -369,7 +380,10 @@ write_user_file(Relation urel) * expect that rename(2) is an atomic action. */ if (rename(tempname, filename)) - elog(ERROR, "rename %s to %s: %m", tempname, filename); + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not rename \"%s\" to \"%s\": %m", + tempname, filename))); pfree((void *) tempname); pfree((void *) filename); @@ -502,7 +516,9 @@ CreateUser(CreateUserStmt *stmt) strcmp(defel->defname, "unencryptedPassword") == 0) { if (dpassword) - elog(ERROR, "CREATE USER: conflicting options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); dpassword = defel; if (strcmp(defel->defname, "encryptedPassword") == 0) encrypt_password = true; @@ -512,35 +528,45 @@ CreateUser(CreateUserStmt *stmt) else if (strcmp(defel->defname, "sysid") == 0) { if (dsysid) - elog(ERROR, "CREATE USER: conflicting options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); dsysid = defel; } else if (strcmp(defel->defname, "createdb") == 0) { if (dcreatedb) - elog(ERROR, "CREATE USER: conflicting options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); dcreatedb = defel; } else if (strcmp(defel->defname, "createuser") == 0) { if (dcreateuser) - elog(ERROR, "CREATE USER: conflicting options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); dcreateuser = defel; } else if (strcmp(defel->defname, "groupElts") == 0) { if (dgroupElts) - elog(ERROR, "CREATE USER: conflicting options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); dgroupElts = defel; } else if (strcmp(defel->defname, "validUntil") == 0) { if (dvalidUntil) - elog(ERROR, "CREATE USER: conflicting options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); dvalidUntil = defel; } else - elog(ERROR, "CREATE USER: option \"%s\" not recognized", + elog(ERROR, "option \"%s\" not recognized", defel->defname); } @@ -552,7 +578,9 @@ CreateUser(CreateUserStmt *stmt) { sysid = intVal(dsysid->arg); if (sysid <= 0) - elog(ERROR, "user id must be positive"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("user id must be positive"))); havesysid = true; } if (dvalidUntil) @@ -567,11 +595,15 @@ CreateUser(CreateUserStmt *stmt) CheckPgUserAclNotNull(); if (!superuser()) - elog(ERROR, "CREATE USER: permission denied"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied"))); if (strcmp(stmt->user, "public") == 0) - elog(ERROR, "CREATE USER: user name \"%s\" is reserved", - stmt->user); + ereport(ERROR, + (errcode(ERRCODE_RESERVED_NAME), + errmsg("user name \"%s\" is reserved", + stmt->user))); /* * Scan the pg_shadow relation to be certain the user or id doesn't @@ -605,10 +637,14 @@ CreateUser(CreateUserStmt *stmt) heap_endscan(scan); if (user_exists) - elog(ERROR, "CREATE USER: user name \"%s\" already exists", - stmt->user); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("user \"%s\" already exists", + stmt->user))); if (sysid_exists) - elog(ERROR, "CREATE USER: sysid %d is already assigned", sysid); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("sysid %d is already assigned", sysid))); /* If no sysid given, use max existing id + 1 */ if (!havesysid) @@ -639,7 +675,7 @@ CreateUser(CreateUserStmt *stmt) { if (!EncryptMD5(password, stmt->user, strlen(stmt->user), encrypted_password)) - elog(ERROR, "CREATE USER: password encryption failed"); + elog(ERROR, "password encryption failed"); new_record[Anum_pg_shadow_passwd - 1] = DirectFunctionCall1(textin, CStringGetDatum(encrypted_password)); } @@ -730,7 +766,9 @@ AlterUser(AlterUserStmt *stmt) strcmp(defel->defname, "unencryptedPassword") == 0) { if (dpassword) - elog(ERROR, "ALTER USER: conflicting options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); dpassword = defel; if (strcmp(defel->defname, "encryptedPassword") == 0) encrypt_password = true; @@ -740,23 +778,29 @@ AlterUser(AlterUserStmt *stmt) else if (strcmp(defel->defname, "createdb") == 0) { if (dcreatedb) - elog(ERROR, "ALTER USER: conflicting options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); dcreatedb = defel; } else if (strcmp(defel->defname, "createuser") == 0) { if (dcreateuser) - elog(ERROR, "ALTER USER: conflicting options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); dcreateuser = defel; } else if (strcmp(defel->defname, "validUntil") == 0) { if (dvalidUntil) - elog(ERROR, "ALTER USER: conflicting options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); dvalidUntil = defel; } else - elog(ERROR, "ALTER USER: option \"%s\" not recognized", + elog(ERROR, "option \"%s\" not recognized", defel->defname); } @@ -779,7 +823,9 @@ AlterUser(AlterUserStmt *stmt) !validUntil && password && strcmp(GetUserNameFromId(GetUserId()), stmt->user) == 0)) - elog(ERROR, "ALTER USER: permission denied"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied"))); /* * Scan the pg_shadow relation to be certain the user exists. Note we @@ -793,7 +839,9 @@ AlterUser(AlterUserStmt *stmt) PointerGetDatum(stmt->user), 0, 0, 0); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "ALTER USER: user \"%s\" does not exist", stmt->user); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("user \"%s\" does not exist", stmt->user))); /* * Build an updated tuple, perusing the information just obtained @@ -840,7 +888,7 @@ AlterUser(AlterUserStmt *stmt) { if (!EncryptMD5(password, stmt->user, strlen(stmt->user), encrypted_password)) - elog(ERROR, "CREATE USER: password encryption failed"); + elog(ERROR, "password encryption failed"); new_record[Anum_pg_shadow_passwd - 1] = DirectFunctionCall1(textin, CStringGetDatum(encrypted_password)); } @@ -904,11 +952,15 @@ AlterUserSet(AlterUserSetStmt *stmt) PointerGetDatum(stmt->user), 0, 0, 0); if (!HeapTupleIsValid(oldtuple)) - elog(ERROR, "user \"%s\" does not exist", stmt->user); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("user \"%s\" does not exist", stmt->user))); if (!(superuser() || ((Form_pg_shadow) GETSTRUCT(oldtuple))->usesysid == GetUserId())) - elog(ERROR, "ALTER USER SET: permission denied"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied"))); for (i = 0; i < Natts_pg_shadow; i++) repl_repl[i] = ' '; @@ -965,7 +1017,9 @@ DropUser(DropUserStmt *stmt) List *item; if (!superuser()) - elog(ERROR, "DROP USER: permission denied"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied"))); /* * Scan the pg_shadow relation to find the usesysid of the user to be @@ -990,19 +1044,20 @@ DropUser(DropUserStmt *stmt) PointerGetDatum(user), 0, 0, 0); if (!HeapTupleIsValid(tuple)) - { - if (length(stmt->users) > 1) - elog(ERROR, "DROP USER: user \"%s\" does not exist (no users removed)", user); - else - elog(ERROR, "DROP USER: user \"%s\" does not exist", user); - } + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("user \"%s\" does not exist", user))); usesysid = ((Form_pg_shadow) GETSTRUCT(tuple))->usesysid; if (usesysid == GetUserId()) - elog(ERROR, "current user cannot be dropped"); + ereport(ERROR, + (errcode(ERRCODE_OBJECT_IN_USE), + errmsg("current user cannot be dropped"))); if (usesysid == GetSessionUserId()) - elog(ERROR, "session user cannot be dropped"); + ereport(ERROR, + (errcode(ERRCODE_OBJECT_IN_USE), + errmsg("session user cannot be dropped"))); /* * Check if user still owns a database. If so, error out. @@ -1026,9 +1081,10 @@ DropUser(DropUserStmt *stmt) char *dbname; dbname = NameStr(((Form_pg_database) GETSTRUCT(tmp_tuple))->datname); - elog(ERROR, "DROP USER: user \"%s\" owns database \"%s\", cannot be removed%s", - user, dbname, - (length(stmt->users) > 1) ? " (no users removed)" : ""); + ereport(ERROR, + (errcode(ERRCODE_OBJECT_IN_USE), + errmsg("user \"%s\" cannot be dropped", user), + errdetail("The user owns database \"%s\".", dbname))); } heap_endscan(scan); @@ -1108,7 +1164,7 @@ RenameUser(const char *oldname, const char *newname) 0, 0, 0); if (!HeapTupleIsValid(tup)) ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("user \"%s\" does not exist", oldname))); /* @@ -1119,23 +1175,21 @@ RenameUser(const char *oldname, const char *newname) */ if (((Form_pg_shadow) GETSTRUCT(tup))->usesysid == GetSessionUserId()) ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("session user may not be renamed"))); /* make sure the new name doesn't exist */ if (SearchSysCacheExists(SHADOWNAME, CStringGetDatum(newname), 0, 0, 0)) - { ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("user \"%s\" already exists", newname))); - } /* must be superuser */ if (!superuser()) ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied"))); /* rename */ @@ -1163,16 +1217,17 @@ CheckPgUserAclNotNull(void) htup = SearchSysCache(RELOID, ObjectIdGetDatum(RelOid_pg_shadow), 0, 0, 0); - if (!HeapTupleIsValid(htup)) - elog(ERROR, "CheckPgUserAclNotNull: \"%s\" not found", - ShadowRelationName); + if (!HeapTupleIsValid(htup)) /* should not happen, we hope */ + elog(ERROR, "cache lookup failed for relation %u", RelOid_pg_shadow); if (heap_attisnull(htup, Anum_pg_class_relacl)) - elog(ERROR, - "To use passwords, you have to revoke permissions on %s " - "so normal users cannot read the passwords. " - "Try 'REVOKE ALL ON \"%s\" FROM PUBLIC'.", - ShadowRelationName, ShadowRelationName); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("before using passwords you must revoke permissions on %s", + ShadowRelationName), + errdetail("This restriction is to prevent unprivileged users from reading the passwords."), + errhint("Try 'REVOKE ALL ON \"%s\" FROM PUBLIC'.", + ShadowRelationName))); ReleaseSysCache(htup); } @@ -1211,17 +1266,21 @@ CreateGroup(CreateGroupStmt *stmt) if (strcmp(defel->defname, "sysid") == 0) { if (dsysid) - elog(ERROR, "CREATE GROUP: conflicting options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); dsysid = defel; } else if (strcmp(defel->defname, "userElts") == 0) { if (duserElts) - elog(ERROR, "CREATE GROUP: conflicting options"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); duserElts = defel; } else - elog(ERROR, "CREATE GROUP: option \"%s\" not recognized", + elog(ERROR, "option \"%s\" not recognized", defel->defname); } @@ -1229,7 +1288,9 @@ CreateGroup(CreateGroupStmt *stmt) { sysid = intVal(dsysid->arg); if (sysid <= 0) - elog(ERROR, "group id must be positive"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("group id must be positive"))); havesysid = true; } @@ -1240,11 +1301,15 @@ CreateGroup(CreateGroupStmt *stmt) * Make sure the user can do this. */ if (!superuser()) - elog(ERROR, "CREATE GROUP: permission denied"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied"))); if (strcmp(stmt->name, "public") == 0) - elog(ERROR, "CREATE GROUP: group name \"%s\" is reserved", - stmt->name); + ereport(ERROR, + (errcode(ERRCODE_RESERVED_NAME), + errmsg("group name \"%s\" is reserved", + stmt->name))); /* * Scan the pg_group relation to be certain the group or id doesn't @@ -1278,12 +1343,16 @@ CreateGroup(CreateGroupStmt *stmt) heap_endscan(scan); if (group_exists) - elog(ERROR, "CREATE GROUP: group name \"%s\" already exists", - stmt->name); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("group \"%s\" already exists", + stmt->name))); if (sysid_exists) - elog(ERROR, "CREATE GROUP: group sysid %d is already assigned", - sysid); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("sysid %d is already assigned", sysid))); + /* If no sysid given, use max existing id + 1 */ if (!havesysid) sysid = max_id + 1; @@ -1359,7 +1428,9 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag) * Make sure the user can do this. */ if (!superuser()) - elog(ERROR, "%s: permission denied", tag); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied"))); /* * Secure exclusive lock to protect our update of the flat group file. @@ -1374,7 +1445,9 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag) PointerGetDatum(stmt->name), 0, 0, 0); if (!HeapTupleIsValid(group_tuple)) - elog(ERROR, "%s: group \"%s\" does not exist", tag, stmt->name); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("group \"%s\" does not exist", stmt->name))); /* Fetch old group membership. */ datum = heap_getattr(group_tuple, Anum_pg_group_grolist, @@ -1415,20 +1488,17 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag) } else { - elog(ERROR, "AlterGroup: unknown tag %s", tag); + elog(ERROR, "unexpected tag: \"%s\"", tag); sysid = 0; /* keep compiler quiet */ } if (!intMember(sysid, newlist)) newlist = lappendi(newlist, sysid); else - - /* - * we silently assume here that this error will only come - * up in a ALTER GROUP statement - */ - elog(WARNING, "%s: user \"%s\" is already in group \"%s\"", - tag, strVal(lfirst(item)), stmt->name); + ereport(WARNING, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("user \"%s\" is already in group \"%s\"", + strVal(lfirst(item)), stmt->name))); } /* Do the update */ @@ -1442,7 +1512,10 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag) if (newlist == NIL) { if (!is_dropuser) - elog(WARNING, "ALTER GROUP: group \"%s\" does not have any members", stmt->name); + ereport(WARNING, + (errcode(ERRCODE_WARNING), + errmsg("group \"%s\" does not have any members", + stmt->name))); } else { @@ -1467,7 +1540,10 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag) if (intMember(sysid, newlist)) newlist = lremovei(sysid, newlist); else if (!is_dropuser) - elog(WARNING, "ALTER GROUP: user \"%s\" is not in group \"%s\"", strVal(lfirst(item)), stmt->name); + ereport(WARNING, + (errcode(ERRCODE_WARNING), + errmsg("user \"%s\" is not in group \"%s\"", + strVal(lfirst(item)), stmt->name))); } /* Do the update */ @@ -1596,7 +1672,9 @@ DropGroup(DropGroupStmt *stmt) * Make sure the user can do this. */ if (!superuser()) - elog(ERROR, "DROP GROUP: permission denied"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied"))); /* * Secure exclusive lock to protect our update of the flat group file. @@ -1609,7 +1687,9 @@ DropGroup(DropGroupStmt *stmt) PointerGetDatum(stmt->name), 0, 0, 0); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "DROP GROUP: group \"%s\" does not exist", stmt->name); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("group \"%s\" does not exist", stmt->name))); simple_heap_delete(pg_group_rel, &tuple->t_self); @@ -1643,23 +1723,21 @@ RenameGroup(const char *oldname, const char *newname) 0, 0, 0); if (!HeapTupleIsValid(tup)) ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("group \"%s\" does not exist", oldname))); /* make sure the new name doesn't exist */ if (SearchSysCacheExists(GRONAME, CStringGetDatum(newname), 0, 0, 0)) - { ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), - errmsg("a group \"%s\" already exists", newname))); - } + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("group \"%s\" already exists", newname))); /* must be superuser */ if (!superuser()) ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION), + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied"))); /* rename */ diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index ca7759cfc8..8298e3613b 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.279 2003/07/16 17:25:48 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.280 2003/07/18 23:20:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -3095,11 +3095,15 @@ check_parameter_resolution_walker(Node *node, if (paramno <= 0 || /* shouldn't happen, but... */ paramno > context->numParams) - elog(ERROR, "Parameter '$%d' is out of range", paramno); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_PARAMETER), + errmsg("there is no parameter $%d", paramno))); if (param->paramtype != context->paramTypes[paramno-1]) - elog(ERROR, "Could not determine datatype of parameter $%d", - paramno); + ereport(ERROR, + (errcode(ERRCODE_AMBIGUOUS_PARAMETER), + errmsg("could not determine datatype of parameter $%d", + paramno))); } return false; } diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index 1544f94cf2..1e2af3785f 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.103 2003/07/03 19:07:48 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.104 2003/07/18 23:20:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -228,7 +228,9 @@ coerce_type(ParseState *pstate, Node *node, if (paramno <= 0 || /* shouldn't happen, but... */ paramno > toppstate->p_numparams) - elog(ERROR, "Parameter '$%d' is out of range", paramno); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_PARAMETER), + errmsg("there is no parameter $%d", paramno))); if (toppstate->p_paramtypes[paramno-1] == UNKNOWNOID) { @@ -242,11 +244,13 @@ coerce_type(ParseState *pstate, Node *node, else { /* Ooops */ - elog(ERROR, "Inconsistent types deduced for parameter '$%d'" - "\n\tCould be either %s or %s", - paramno, - format_type_be(toppstate->p_paramtypes[paramno-1]), - format_type_be(targetTypeId)); + ereport(ERROR, + (errcode(ERRCODE_AMBIGUOUS_PARAMETER), + errmsg("inconsistent types deduced for parameter $%d", + paramno), + errdetail("Could be either %s or %s.", + format_type_be(toppstate->p_paramtypes[paramno-1]), + format_type_be(targetTypeId)))); } param->paramtype = targetTypeId; diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 4519c7ffb5..fbfa204694 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.155 2003/07/03 16:34:16 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.156 2003/07/18 23:20:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -128,13 +128,16 @@ transformExpr(ParseState *pstate, Node *expr) /* Check parameter number is in range */ if (paramno <= 0) /* probably can't happen? */ - elog(ERROR, "Parameter '$%d' is out of range", - paramno); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_PARAMETER), + errmsg("there is no parameter $%d", paramno))); if (paramno > toppstate->p_numparams) { if (!toppstate->p_variableparams) - elog(ERROR, "Parameter '$%d' is out of range", - paramno); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_PARAMETER), + errmsg("there is no parameter $%d", + paramno))); /* Okay to enlarge param array */ if (toppstate->p_paramtypes) toppstate->p_paramtypes = diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index cb2da292a0..48abb68235 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.153 2003/07/04 02:51:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.154 2003/07/18 23:20:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -84,15 +84,15 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, * function, but the test doesn't hurt. */ if (nargs > FUNC_MAX_ARGS) - elog(ERROR, "Cannot pass more than %d arguments to a function", - FUNC_MAX_ARGS); + ereport(ERROR, + (errcode(ERRCODE_TOO_MANY_ARGUMENTS), + errmsg("cannot pass more than %d arguments to a function", + FUNC_MAX_ARGS))); if (fargs) { first_arg = lfirst(fargs); - if (first_arg == NULL) /* should not happen */ - elog(ERROR, "Function '%s' does not allow NULL input", - NameListToString(funcname)); + Assert(first_arg != NULL); } /* @@ -179,7 +179,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, case RTE_RELATION: toid = get_rel_type_id(rte->relid); if (!OidIsValid(toid)) - elog(ERROR, "Cannot find type OID for relation %u", + elog(ERROR, "cannot find type OID for relation %u", rte->relid); /* replace RangeVar in the arg list */ lfirst(i) = makeVar(vnum, @@ -219,8 +219,10 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, unknown_attribute(schemaname, relname, strVal(lfirst(funcname))); else - elog(ERROR, "Cannot pass result of sub-select or join %s to a function", - relname); + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot pass result of sub-select or join %s to a function", + relname))); toid = InvalidOid; /* keep compiler quiet */ break; } @@ -258,11 +260,16 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, * an aggregate? */ if (agg_star) - elog(ERROR, "%s(*) specified, but %s is not an aggregate function", - NameListToString(funcname), NameListToString(funcname)); + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("%s(*) specified, but %s is not an aggregate function", + NameListToString(funcname), + NameListToString(funcname)))); if (agg_distinct) - elog(ERROR, "DISTINCT specified, but %s is not an aggregate function", - NameListToString(funcname)); + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("DISTINCT specified, but %s is not an aggregate function", + NameListToString(funcname)))); } else if (fdresult != FUNCDETAIL_AGGREGATE) { @@ -284,11 +291,15 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, colname); relTypeId = exprType(first_arg); if (!ISCOMPLEX(relTypeId)) - elog(ERROR, "Attribute notation .%s applied to type %s, which is not a complex type", - colname, format_type_be(relTypeId)); + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("attribute notation .%s applied to type %s, which is not a complex type", + colname, format_type_be(relTypeId)))); else - elog(ERROR, "Attribute \"%s\" not found in datatype %s", - colname, format_type_be(relTypeId)); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("attribute \"%s\" not found in datatype %s", + colname, format_type_be(relTypeId)))); } /* @@ -302,7 +313,6 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, actual_arg_types)), errhint("Unable to choose a best candidate function. " "You may need to add explicit typecasts."))); - else ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), @@ -356,7 +366,9 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, retval = (Node *) aggref; if (retset) - elog(ERROR, "Aggregates may not return sets"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), + errmsg("aggregates may not return sets"))); } return retval; @@ -921,7 +933,7 @@ func_get_detail(List *funcname, ObjectIdGetDatum(best_candidate->oid), 0, 0, 0); if (!HeapTupleIsValid(ftup)) /* should not happen */ - elog(ERROR, "cache lookup of function %u failed", + elog(ERROR, "cache lookup failed for function %u", best_candidate->oid); pform = (Form_pg_proc) GETSTRUCT(ftup); *rettype = pform->prorettype; @@ -1249,8 +1261,10 @@ setup_field_select(Node *input, char *attname, Oid relid) attno = get_attnum(relid, attname); if (attno == InvalidAttrNumber) - elog(ERROR, "Relation \"%s\" has no column \"%s\"", - get_rel_name(relid), attname); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("relation \"%s\" has no column \"%s\"", + get_rel_name(relid), attname))); fselect->arg = (Expr *) input; fselect->fieldnum = attno; @@ -1323,18 +1337,22 @@ ParseComplexProjection(char *funcname, Node *first_arg) } /* - * Simple helper routine for delivering "No such attribute" error message + * Simple helper routine for delivering "no such attribute" error message */ static void unknown_attribute(const char *schemaname, const char *relname, const char *attname) { if (schemaname) - elog(ERROR, "No such attribute %s.%s.%s", - schemaname, relname, attname); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("no such attribute %s.%s.%s", + schemaname, relname, attname))); else - elog(ERROR, "No such attribute %s.%s", - relname, attname); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("no such attribute %s.%s", + relname, attname))); } /* @@ -1389,11 +1407,16 @@ find_aggregate_func(List *aggname, Oid basetype, bool noError) if (noError) return InvalidOid; if (basetype == ANYOID) - elog(ERROR, "aggregate %s(*) does not exist", - NameListToString(aggname)); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("aggregate %s(*) does not exist", + NameListToString(aggname)))); else - elog(ERROR, "aggregate %s(%s) does not exist", - NameListToString(aggname), format_type_be(basetype)); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("aggregate %s(%s) does not exist", + NameListToString(aggname), + format_type_be(basetype)))); } /* Make sure it's an aggregate */ @@ -1401,7 +1424,7 @@ find_aggregate_func(List *aggname, Oid basetype, bool noError) ObjectIdGetDatum(oid), 0, 0, 0); if (!HeapTupleIsValid(ftup)) /* should not happen */ - elog(ERROR, "function %u not found", oid); + elog(ERROR, "cache lookup failed for function %u", oid); pform = (Form_pg_proc) GETSTRUCT(ftup); if (!pform->proisagg) @@ -1410,8 +1433,10 @@ find_aggregate_func(List *aggname, Oid basetype, bool noError) if (noError) return InvalidOid; /* we do not use the (*) notation for functions... */ - elog(ERROR, "function %s(%s) is not an aggregate", - NameListToString(aggname), format_type_be(basetype)); + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("function %s(%s) is not an aggregate", + NameListToString(aggname), format_type_be(basetype)))); } ReleaseSysCache(ftup); @@ -1445,8 +1470,10 @@ LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError) } if (!noError) - elog(ERROR, "function %s does not exist", - func_signature_string(funcname, nargs, argtypes)); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("function %s does not exist", + func_signature_string(funcname, nargs, argtypes)))); return InvalidOid; } @@ -1466,8 +1493,10 @@ LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError) MemSet(argoids, 0, FUNC_MAX_ARGS * sizeof(Oid)); argcount = length(argtypes); if (argcount > FUNC_MAX_ARGS) - elog(ERROR, "functions cannot have more than %d arguments", - FUNC_MAX_ARGS); + ereport(ERROR, + (errcode(ERRCODE_TOO_MANY_ARGUMENTS), + errmsg("functions cannot have more than %d arguments", + FUNC_MAX_ARGS))); for (i = 0; i < argcount; i++) { @@ -1476,8 +1505,10 @@ LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError) argoids[i] = LookupTypeName(t); if (!OidIsValid(argoids[i])) - elog(ERROR, "Type \"%s\" does not exist", - TypeNameToString(t)); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("type \"%s\" does not exist", + TypeNameToString(t)))); argtypes = lnext(argtypes); } diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c index 99b5a3078c..8ecc11a661 100644 --- a/src/backend/parser/parse_oper.c +++ b/src/backend/parser/parse_oper.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.69 2003/07/04 02:51:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.70 2003/07/18 23:20:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -107,8 +107,10 @@ LookupOperNameTypeNames(List *opername, TypeName *oprleft, { leftoid = LookupTypeName(oprleft); if (!OidIsValid(leftoid)) - elog(ERROR, "type %s does not exist", - TypeNameToString(oprleft)); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("type %s does not exist", + TypeNameToString(oprleft)))); } if (oprright == NULL) rightoid = InvalidOid; @@ -116,8 +118,10 @@ LookupOperNameTypeNames(List *opername, TypeName *oprleft, { rightoid = LookupTypeName(oprright); if (!OidIsValid(rightoid)) - elog(ERROR, "type %s does not exist", - TypeNameToString(oprright)); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("type %s does not exist", + TypeNameToString(oprright)))); } return LookupOperName(opername, leftoid, rightoid, noError); @@ -178,8 +182,10 @@ equality_oper(Oid argtype, bool noError) } } if (!noError) - elog(ERROR, "unable to identify an equality operator for type %s", - format_type_be(argtype)); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("unable to identify an equality operator for type %s", + format_type_be(argtype)))); return NULL; } @@ -239,9 +245,11 @@ ordering_oper(Oid argtype, bool noError) } } if (!noError) - elog(ERROR, "unable to identify an ordering operator for type %s" - "\n\tUse an explicit ordering operator or modify the query", - format_type_be(argtype)); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("unable to identify an ordering operator for type %s", + format_type_be(argtype)), + errhint("Use an explicit ordering operator or modify the query."))); return NULL; } @@ -483,8 +491,10 @@ compatible_oper(List *op, Oid arg1, Oid arg2, bool noError) ReleaseSysCache(optup); if (!noError) - elog(ERROR, "operator requires run-time type coercion: %s", - op_signature_string(op, 'b', arg1, arg2)); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("operator requires run-time type coercion: %s", + op_signature_string(op, 'b', arg1, arg2)))); return (Operator) NULL; } @@ -773,7 +783,9 @@ make_scalar_array_op(ParseState *pstate, List *opname, { rtypeId = get_element_type(atypeId); if (!OidIsValid(rtypeId)) - elog(ERROR, "op ANY/ALL (array) requires array on right side"); + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("op ANY/ALL (array) requires array on right side"))); } /* Now resolve the operator */ @@ -800,9 +812,13 @@ make_scalar_array_op(ParseState *pstate, List *opname, * Check that operator result is boolean */ if (rettype != BOOLOID) - elog(ERROR, "op ANY/ALL (array) requires operator to yield boolean"); + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("op ANY/ALL (array) requires operator to yield boolean"))); if (get_func_retset(opform->oprcode)) - elog(ERROR, "op ANY/ALL (array) requires operator not to return a set"); + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("op ANY/ALL (array) requires operator not to return a set"))); /* * Now switch back to the array type on the right, arranging for @@ -810,8 +826,10 @@ make_scalar_array_op(ParseState *pstate, List *opname, */ res_atypeId = get_array_type(declared_arg_types[1]); if (!OidIsValid(res_atypeId)) - elog(ERROR, "unable to find datatype for array of %s", - format_type_be(declared_arg_types[1])); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("unable to find datatype for array of %s", + format_type_be(declared_arg_types[1])))); actual_arg_types[1] = atypeId; declared_arg_types[1] = res_atypeId; diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l index 6aa2676e20..f940a0c267 100644 --- a/src/backend/parser/scan.l +++ b/src/backend/parser/scan.l @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/scan.l,v 1.108 2003/06/19 23:22:40 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/scan.l,v 1.109 2003/07/18 23:20:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -403,8 +403,10 @@ other . len = pg_mbcliplen(literalbuf, literallen, NAMEDATALEN-1); - elog(NOTICE, "identifier \"%s\" will be truncated to \"%.*s\"", - literalbuf, len, literalbuf); + ereport(NOTICE, + (errcode(ERRCODE_NAME_TOO_LONG), + errmsg("identifier \"%s\" will be truncated to \"%.*s\"", + literalbuf, len, literalbuf))); literalbuf[len] = '\0'; literallen = len; } @@ -559,8 +561,10 @@ other . int len; len = pg_mbcliplen(ident, i, NAMEDATALEN-1); - elog(NOTICE, "identifier \"%s\" will be truncated to \"%.*s\"", - ident, len, ident); + ereport(NOTICE, + (errcode(ERRCODE_NAME_TOO_LONG), + errmsg("identifier \"%s\" will be truncated to \"%.*s\"", + ident, len, ident))); ident[len] = '\0'; } yylval.str = ident; @@ -582,16 +586,18 @@ yyerror(const char *message) if (*loc == YY_END_OF_BUFFER_CHAR) { - /* translator: %s is typically "syntax error" */ ereport(ERROR, - (errmsg("%s at end of input", message), + (errcode(ERRCODE_SYNTAX_ERROR), + /* translator: %s is typically "syntax error" */ + errmsg("%s at end of input", message), errposition(cursorpos))); } else { - /* translator: first %s is typically "syntax error" */ ereport(ERROR, - (errmsg("%s at or near \"%s\"", message, loc), + (errcode(ERRCODE_SYNTAX_ERROR), + /* translator: first %s is typically "syntax error" */ + errmsg("%s at or near \"%s\"", message, loc), errposition(cursorpos))); } } diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index 0660aaab9a..4d646b9b92 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -37,7 +37,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.112 2003/06/30 16:47:01 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.113 2003/07/18 23:20:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -288,7 +288,13 @@ errstart(int elevel, const char *filename, int lineno, edata->filename = filename; edata->lineno = lineno; edata->funcname = funcname; - edata->sqlerrcode = ERRCODE_INTERNAL_ERROR; /* default errcode */ + /* Select default errcode based on elevel */ + if (elevel >= ERROR) + edata->sqlerrcode = ERRCODE_INTERNAL_ERROR; + else if (elevel == WARNING) + edata->sqlerrcode = ERRCODE_WARNING; + else + edata->sqlerrcode = ERRCODE_SUCCESSFUL_COMPLETION; /* errno is saved here so that error parameter eval can't change it */ edata->saved_errno = errno; @@ -497,6 +503,76 @@ errcode(int sqlerrcode) } +/* + * errcode_for_file_access --- add SQLSTATE error code to the current error + * + * The SQLSTATE code is chosen based on the saved errno value. We assume + * that the failing operation was some type of disk file access. + * + * NOTE: the primary error message string should generally include %m + * when this is used. + */ +int +errcode_for_file_access(void) +{ + ErrorData *edata = &errordata[errordata_stack_depth]; + + /* we don't bother incrementing recursion_depth */ + CHECK_STACK_DEPTH(); + + switch (edata->saved_errno) + { + /* Permission-denied failures */ + case EPERM: /* Not super-user */ + case EACCES: /* Permission denied */ +#ifdef EROFS + case EROFS: /* Read only file system */ +#endif + edata->sqlerrcode = ERRCODE_INSUFFICIENT_PRIVILEGE; + break; + + /* Object not found */ + case ENOENT: /* No such file or directory */ + edata->sqlerrcode = ERRCODE_UNDEFINED_OBJECT; + break; + + /* Duplicate object */ + case EEXIST: /* File exists */ + edata->sqlerrcode = ERRCODE_DUPLICATE_OBJECT; + break; + + /* Wrong object type or state */ + case ENOTDIR: /* Not a directory */ + case EISDIR: /* Is a directory */ + case ENOTEMPTY: /* Directory not empty */ + edata->sqlerrcode = ERRCODE_WRONG_OBJECT_TYPE; + break; + + /* Insufficient resources */ + case ENOSPC: /* No space left on device */ + edata->sqlerrcode = ERRCODE_DISK_FULL; + break; + + case ENFILE: /* File table overflow */ + case EMFILE: /* Too many open files */ + edata->sqlerrcode = ERRCODE_INSUFFICIENT_RESOURCES; + break; + + /* Hardware failure */ + case EIO: /* I/O error */ + edata->sqlerrcode = ERRCODE_IO_ERROR; + break; + + /* All else is classified as internal errors */ + default: + edata->sqlerrcode = ERRCODE_INTERNAL_ERROR; + break; + } + + return 0; /* return value does not matter */ +} + + /* * This macro handles expansion of a format string and associated parameters; * it's common code for errmsg(), errdetail(), etc. Must be called inside @@ -759,7 +835,8 @@ DebugFileOpen(void) if ((fd = open(OutputFileName, O_CREAT | O_APPEND | O_WRONLY, 0666)) < 0) ereport(FATAL, - (errmsg("failed to open %s: %m", OutputFileName))); + (errcode_for_file_access(), + errmsg("failed to open \"%s\": %m", OutputFileName))); istty = isatty(fd); close(fd); @@ -768,7 +845,8 @@ DebugFileOpen(void) */ if (!freopen(OutputFileName, "a", stderr)) ereport(FATAL, - (errmsg("failed to reopen %s as stderr: %m", + (errcode_for_file_access(), + errmsg("failed to reopen \"%s\" as stderr: %m", OutputFileName))); /* @@ -780,7 +858,8 @@ DebugFileOpen(void) if (istty && IsUnderPostmaster) if (!freopen(OutputFileName, "a", stdout)) ereport(FATAL, - (errmsg("failed to reopen %s as stdout: %m", + (errcode_for_file_access(), + errmsg("failed to reopen \"%s\" as stdout: %m", OutputFileName))); } } diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c index 671962d0f5..8803bcd0a6 100644 --- a/src/backend/utils/fmgr/dfmgr.c +++ b/src/backend/utils/fmgr/dfmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.60 2003/05/27 17:49:46 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.61 2003/07/18 23:20:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -58,7 +58,7 @@ static char *substitute_libpath_macro(const char *name); * * If the function is not found, we raise an error if signalNotFound is true, * else return (PGFunction) NULL. Note that errors in loading the library - * will provoke elog regardless of signalNotFound. + * will provoke ereport() regardless of signalNotFound. * * If filehandle is not NULL, then *filehandle will be set to a handle * identifying the library file. The filehandle can be used with @@ -94,7 +94,9 @@ load_external_function(char *filename, char *funcname, * Check for same files - different paths (ie, symlink or link) */ if (stat(fullname, &stat_buf) == -1) - elog(ERROR, "stat failed on file '%s': %m", fullname); + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not access file \"%s\": %m", fullname))); for (file_scanner = file_list; file_scanner != (DynamicFileList *) NULL && @@ -111,7 +113,9 @@ load_external_function(char *filename, char *funcname, file_scanner = (DynamicFileList *) malloc(sizeof(DynamicFileList) + strlen(fullname)); if (file_scanner == NULL) - elog(ERROR, "Out of memory in load_external_function"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_RESOURCES), + errmsg("out of memory"))); MemSet((char *) file_scanner, 0, sizeof(DynamicFileList)); strcpy(file_scanner->filename, fullname); @@ -124,7 +128,11 @@ load_external_function(char *filename, char *funcname, { load_error = (char *) pg_dlerror(); free((char *) file_scanner); - elog(ERROR, "Load of file %s failed: %s", fullname, load_error); + /* errcode_for_file_access might not be appropriate here? */ + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not load library \"%s\": %s", + fullname, load_error))); } /* OK to link it into list */ @@ -151,7 +159,10 @@ load_external_function(char *filename, char *funcname, retval = pg_dlsym(file_scanner->handle, funcname); if (retval == (PGFunction) NULL && signalNotFound) - elog(ERROR, "Can't find function %s in file %s", funcname, fullname); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("could not find function \"%s\" in file \"%s\"", + funcname, fullname))); pfree(fullname); return retval; @@ -181,7 +192,9 @@ load_file(char *filename) * good error message if bogus file name given. */ if (stat(fullname, &stat_buf) == -1) - elog(ERROR, "LOAD: could not open file '%s': %m", fullname); + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not access file \"%s\": %m", fullname))); if (file_list != (DynamicFileList *) NULL) { @@ -236,7 +249,9 @@ file_exists(const char *name) if (stat(name, &st) == 0) return S_ISDIR(st.st_mode) ? false : true; else if (!(errno == ENOENT || errno == ENOTDIR || errno == EACCES)) - elog(ERROR, "stat failed on %s: %s", name, strerror(errno)); + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not access file \"%s\": %m", name))); return false; } @@ -335,7 +350,9 @@ substitute_libpath_macro(const char *name) if (strncmp(name, "$libdir", macroname_len) == 0) replacement = PKGLIBDIR; else - elog(ERROR, "invalid macro name in dynamic library path"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_NAME), + errmsg("invalid macro name in dynamic library path"))); if (name[macroname_len] == '\0') return pstrdup(replacement); @@ -385,7 +402,9 @@ find_in_dynamic_libpath(const char *basename) len = strcspn(p, ":"); if (len == 0) - elog(ERROR, "zero length dynamic_library_path component"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_NAME), + errmsg("zero-length component in DYNAMIC_LIBRARY_PATH"))); piece = palloc(len + 1); strncpy(piece, p, len); @@ -396,13 +415,15 @@ find_in_dynamic_libpath(const char *basename) /* only absolute paths */ if (!is_absolute_path(mangled)) - elog(ERROR, "dynamic_library_path component is not absolute"); + ereport(ERROR, + (errcode(ERRCODE_INVALID_NAME), + errmsg("DYNAMIC_LIBRARY_PATH component is not absolute"))); full = palloc(strlen(mangled) + 1 + baselen + 1); sprintf(full, "%s/%s", mangled, basename); pfree(mangled); - elog(DEBUG3, "find_in_dynamic_libpath: trying %s", full); + elog(DEBUG3, "find_in_dynamic_libpath: trying \"%s\"", full); if (file_exists(full)) return full; diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index 7cd815f628..73b7e491cb 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: elog.h,v 1.47 2003/07/14 23:36:15 tgl Exp $ + * $Id: elog.h,v 1.48 2003/07/18 23:20:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -177,31 +177,62 @@ #define ERRCODE_INTERNAL_ERROR MAKE_SQLSTATE('X','X', '0','0','0') #define ERRCODE_INSUFFICIENT_PRIVILEGE MAKE_SQLSTATE('4','2', '5','0','1') #define ERRCODE_SYNTAX_ERROR MAKE_SQLSTATE('4','2', '6','0','1') +#define ERRCODE_INVALID_NAME MAKE_SQLSTATE('4','2', '6','0','2') +#define ERRCODE_NAME_TOO_LONG MAKE_SQLSTATE('4','2', '6','2','2') +#define ERRCODE_RESERVED_NAME MAKE_SQLSTATE('4','2', '9','3','9') #define ERRCODE_UNTERMINATED_LITERAL MAKE_SQLSTATE('4','2', '6','0','3') #define ERRCODE_INVALID_LITERAL MAKE_SQLSTATE('4','2', '6','0','6') +#define ERRCODE_STATEMENT_TOO_COMPLEX MAKE_SQLSTATE('5','4', '0','0','1') #define ERRCODE_TOO_MANY_ARGUMENTS MAKE_SQLSTATE('4','2', '6','0','5') -#define ERRCODE_UNDEFINED_COLUMN MAKE_SQLSTATE('4','2', '7','0','3') +#define ERRCODE_TOO_MANY_COLUMNS MAKE_SQLSTATE('5','4', '0','1','1') /* * Note: use the above SQL-standard error codes for undefined catalog, schema, - * prepared statement, or cursor names. Curiously, they don't define error - * codes for any other kinds of objects. We choose to define an errcode for - * undefined tables, as well as one for functions (also used for operators); - * all other names (rules, triggers, etc) are lumped as UNDEFINED_OBJECT. - * The same breakdown is used for "ambiguous" and "duplicate" complaints. + * prepared statement, and cursor names. Curiously, they don't define error + * codes for any other kinds of objects. We choose to define separate error + * codes for undefined table and column names, as well as one for functions + * (also used for operators). All other names (rules, triggers, etc) are + * lumped as UNDEFINED_OBJECT. + * The same breakdown is used for "ambiguous" and "duplicate" complaints, + * as well as complaints associated with incorrect declarations. */ -#define ERRCODE_UNDEFINED_TABLE MAKE_SQLSTATE('4','2', '7','0','4') +#define ERRCODE_UNDEFINED_COLUMN MAKE_SQLSTATE('4','2', '7','0','3') +#define ERRCODE_UNDEFINED_CURSOR ERRCODE_INVALID_CURSOR_NAME +#define ERRCODE_UNDEFINED_DATABASE ERRCODE_INVALID_CATALOG_NAME #define ERRCODE_UNDEFINED_FUNCTION MAKE_SQLSTATE('4','2', '8','8','3') +#define ERRCODE_UNDEFINED_PSTATEMENT ERRCODE_INVALID_SQL_STATEMENT_NAME +#define ERRCODE_UNDEFINED_SCHEMA ERRCODE_INVALID_SCHEMA_NAME +#define ERRCODE_UNDEFINED_TABLE MAKE_SQLSTATE('4','2', '7','0','4') #define ERRCODE_UNDEFINED_OBJECT MAKE_SQLSTATE('4','2', '7','0','5') +#define ERRCODE_UNDEFINED_PARAMETER MAKE_SQLSTATE('4','2', '7','1','5') #define ERRCODE_AMBIGUOUS_COLUMN MAKE_SQLSTATE('4','2', '7','0','2') #define ERRCODE_AMBIGUOUS_FUNCTION MAKE_SQLSTATE('4','2', '7','2','5') +#define ERRCODE_AMBIGUOUS_PARAMETER MAKE_SQLSTATE('4','2', '7','1','6') #define ERRCODE_DUPLICATE_COLUMN MAKE_SQLSTATE('4','2', '7','1','1') -#define ERRCODE_DUPLICATE_TABLE MAKE_SQLSTATE('4','2', '7','2','2') +#define ERRCODE_DUPLICATE_CURSOR ERRCODE_DUPLICATE_OBJECT +#define ERRCODE_DUPLICATE_DATABASE ERRCODE_DUPLICATE_OBJECT #define ERRCODE_DUPLICATE_FUNCTION MAKE_SQLSTATE('4','2', '7','2','3') +#define ERRCODE_DUPLICATE_PSTATEMENT ERRCODE_DUPLICATE_OBJECT +#define ERRCODE_DUPLICATE_SCHEMA ERRCODE_DUPLICATE_OBJECT +#define ERRCODE_DUPLICATE_TABLE MAKE_SQLSTATE('4','2', '7','2','2') #define ERRCODE_DUPLICATE_OBJECT MAKE_SQLSTATE('4','2', '7','1','0') +#define ERRCODE_INVALID_COLUMN_DEFINITION MAKE_SQLSTATE('4','2', 'A','0','1') +#define ERRCODE_INVALID_CURSOR_DEFINITION MAKE_SQLSTATE('4','2', 'A','0','2') +#define ERRCODE_INVALID_DATABASE_DEFINITION MAKE_SQLSTATE('4','2', 'A','0','3') +#define ERRCODE_INVALID_FUNCTION_DEFINITION MAKE_SQLSTATE('4','2', 'A','0','4') +#define ERRCODE_INVALID_PSTATEMENT_DEFINITION MAKE_SQLSTATE('4','2', 'A','0','5') +#define ERRCODE_INVALID_SCHEMA_DEFINITION MAKE_SQLSTATE('4','2', 'A','0','6') +#define ERRCODE_INVALID_TABLE_DEFINITION MAKE_SQLSTATE('4','2', 'A','0','7') +#define ERRCODE_INVALID_OBJECT_DEFINITION MAKE_SQLSTATE('4','2', 'A','0','8') +#define ERRCODE_WRONG_OBJECT_TYPE MAKE_SQLSTATE('4','2', '8','0','9') +#define ERRCODE_OBJECT_IN_USE MAKE_SQLSTATE('5','5', '0','0','6') #define ERRCODE_GROUPING_ERROR MAKE_SQLSTATE('4','2', '8','0','3') #define ERRCODE_TYPE_MISMATCH MAKE_SQLSTATE('4','2', '8','0','4') #define ERRCODE_CANNOT_COERCE MAKE_SQLSTATE('4','2', '8','4','6') #define ERRCODE_INVALID_FOREIGN_KEY MAKE_SQLSTATE('4','2', '8','3','0') +#define ERRCODE_TOO_MANY_CONNECTIONS MAKE_SQLSTATE('5','7', '0','3','2') +#define ERRCODE_DISK_FULL MAKE_SQLSTATE('5','4', '1','0','0') +#define ERRCODE_INSUFFICIENT_RESOURCES MAKE_SQLSTATE('5','4', '2','0','0') +#define ERRCODE_IO_ERROR MAKE_SQLSTATE('5','8', '0','3','0') /* Which __func__ symbol do we have, if any? */ @@ -219,13 +250,15 @@ /*---------- * New-style error reporting API: to be used in this way: * ereport(ERROR, - * (errcode(ERRCODE_INVALID_CURSOR_NAME), + * (errcode(ERRCODE_UNDEFINED_CURSOR), * errmsg("portal \"%s\" not found", stmt->portalname), * ... other errxxx() fields as needed ...)); * * The error level is required, and so is a primary error message (errmsg * or errmsg_internal). All else is optional. errcode() defaults to - * ERRCODE_INTERNAL_ERROR. + * ERRCODE_INTERNAL_ERROR if elevel is ERROR or more, ERRCODE_WARNING + * if elevel is WARNING, or ERRCODE_SUCCESSFUL_COMPLETION if elevel is + * NOTICE or below. *---------- */ #define ereport(elevel, rest) \ @@ -238,6 +271,8 @@ extern void errfinish(int dummy, ...); extern int errcode(int sqlerrcode); +extern int errcode_for_file_access(void); + extern int errmsg(const char *fmt, ...) /* This extension allows gcc to check the format string for consistency with the supplied arguments. */ diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out index cdd6c88831..655a417416 100644 --- a/src/test/regress/expected/alter_table.out +++ b/src/test/regress/expected/alter_table.out @@ -775,7 +775,7 @@ select atacc1.* from atacc1; select a from atacc1; ERROR: Attribute "a" not found select atacc1.a from atacc1; -ERROR: No such attribute atacc1.a +ERROR: no such attribute atacc1.a select b,c,d from atacc1; b | c | d ---+---+--- @@ -789,7 +789,7 @@ ERROR: Attribute "a" not found select "........pg.dropped.1........" from atacc1; ERROR: Attribute "........pg.dropped.1........" not found select atacc1."........pg.dropped.1........" from atacc1; -ERROR: No such attribute atacc1.........pg.dropped.1........ +ERROR: no such attribute atacc1.........pg.dropped.1........ select "........pg.dropped.1........",b,c,d from atacc1; ERROR: Attribute "........pg.dropped.1........" not found select * from atacc1 where "........pg.dropped.1........" = 1; diff --git a/src/test/regress/expected/create_type.out b/src/test/regress/expected/create_type.out index ea103d2ff4..b70289b9f1 100644 --- a/src/test/regress/expected/create_type.out +++ b/src/test/regress/expected/create_type.out @@ -19,22 +19,24 @@ CREATE FUNCTION int42_in(cstring) RETURNS int42 AS 'int4in' LANGUAGE 'internal' WITH (isStrict); -NOTICE: ProcedureCreate: type int42 is not yet defined +NOTICE: type int42 is not yet defined +DETAIL: Creating a shell type definition. CREATE FUNCTION int42_out(int42) RETURNS cstring AS 'int4out' LANGUAGE 'internal' WITH (isStrict); -NOTICE: Argument type "int42" is only a shell +NOTICE: argument type int42 is only a shell CREATE FUNCTION text_w_default_in(cstring) RETURNS text_w_default AS 'textin' LANGUAGE 'internal' WITH (isStrict); -NOTICE: ProcedureCreate: type text_w_default is not yet defined +NOTICE: type text_w_default is not yet defined +DETAIL: Creating a shell type definition. CREATE FUNCTION text_w_default_out(text_w_default) RETURNS cstring AS 'textout' LANGUAGE 'internal' WITH (isStrict); -NOTICE: Argument type "text_w_default" is only a shell +NOTICE: argument type text_w_default is only a shell CREATE TYPE int42 ( internallength = 4, input = int42_in, diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out index 1114f68865..99e3e995ae 100644 --- a/src/test/regress/expected/privileges.out +++ b/src/test/regress/expected/privileges.out @@ -6,12 +6,12 @@ CREATE USER regressuser2; CREATE USER regressuser3; CREATE USER regressuser4; CREATE USER regressuser4; -- duplicate -ERROR: CREATE USER: user name "regressuser4" already exists +ERROR: user "regressuser4" already exists CREATE GROUP regressgroup1; CREATE GROUP regressgroup2 WITH USER regressuser1, regressuser2; ALTER GROUP regressgroup1 ADD USER regressuser4; ALTER GROUP regressgroup2 ADD USER regressuser2; -- duplicate -WARNING: ALTER GROUP: user "regressuser2" is already in group "regressgroup2" +WARNING: user "regressuser2" is already in group "regressgroup2" ALTER GROUP regressgroup2 DROP USER regressuser2; ALTER GROUP regressgroup2 ADD USER regressuser4; -- test owner privileges diff --git a/src/test/regress/output/create_function_1.source b/src/test/regress/output/create_function_1.source index fcca5be63d..7779485305 100644 --- a/src/test/regress/output/create_function_1.source +++ b/src/test/regress/output/create_function_1.source @@ -5,22 +5,24 @@ CREATE FUNCTION widget_in(cstring) RETURNS widget AS '@abs_builddir@/regress@DLSUFFIX@' LANGUAGE 'c'; -NOTICE: ProcedureCreate: type widget is not yet defined +NOTICE: type widget is not yet defined +DETAIL: Creating a shell type definition. CREATE FUNCTION widget_out(widget) RETURNS cstring AS '@abs_builddir@/regress@DLSUFFIX@' LANGUAGE 'c'; -NOTICE: Argument type "widget" is only a shell +NOTICE: argument type widget is only a shell CREATE FUNCTION int44in(cstring) RETURNS city_budget AS '@abs_builddir@/regress@DLSUFFIX@' LANGUAGE 'c'; -NOTICE: ProcedureCreate: type city_budget is not yet defined +NOTICE: type city_budget is not yet defined +DETAIL: Creating a shell type definition. CREATE FUNCTION int44out(city_budget) RETURNS cstring AS '@abs_builddir@/regress@DLSUFFIX@' LANGUAGE 'c'; -NOTICE: Argument type "city_budget" is only a shell +NOTICE: argument type city_budget is only a shell CREATE FUNCTION check_primary_key () RETURNS trigger AS '@abs_builddir@/../../../contrib/spi/refint@DLSUFFIX@' @@ -48,25 +50,27 @@ CREATE FUNCTION set_ttdummy (int4) -- Things that shouldn't work: CREATE FUNCTION test1 (int) RETURNS int LANGUAGE sql AS 'SELECT ''not an integer'';'; -ERROR: return type mismatch in function: declared to return integer, returns "unknown" +ERROR: return type mismatch in function declared to return integer +DETAIL: Actual return type is "unknown". CREATE FUNCTION test1 (int) RETURNS int LANGUAGE sql AS 'not even SQL'; ERROR: syntax error at or near "not" at character 1 CREATE FUNCTION test1 (int) RETURNS int LANGUAGE sql AS 'SELECT 1, 2, 3;'; -ERROR: function declared to return integer returns multiple columns in final SELECT +ERROR: return type mismatch in function declared to return integer +DETAIL: Final SELECT must return exactly one column. CREATE FUNCTION test1 (int) RETURNS int LANGUAGE sql AS 'SELECT $2;'; -ERROR: Parameter '$2' is out of range +ERROR: there is no parameter $2 CREATE FUNCTION test1 (int) RETURNS int LANGUAGE sql AS 'a', 'b'; -ERROR: CREATE FUNCTION: only one AS item needed for sql language +ERROR: only one AS item needed for language "sql" CREATE FUNCTION test1 (int) RETURNS int LANGUAGE c AS 'nosuchfile'; -ERROR: stat failed on file 'nosuchfile': No such file or directory +ERROR: could not access file "nosuchfile": No such file or directory CREATE FUNCTION test1 (int) RETURNS int LANGUAGE c AS '@abs_builddir@/regress@DLSUFFIX@', 'nosuchsymbol'; -ERROR: Can't find function nosuchsymbol in file @abs_builddir@/regress@DLSUFFIX@ +ERROR: could not find function "nosuchsymbol" in file "@abs_builddir@/regress@DLSUFFIX@" CREATE FUNCTION test1 (int) RETURNS int LANGUAGE internal AS 'nosuch'; ERROR: there is no built-in function named "nosuch"