From d8bab57fa12e6f20f161efd8b76318125ba52b2e Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Fri, 13 Nov 2026 10:58:53 +0100 Subject: [PATCH 3/5] Fix -Wformat-nonliteral warnings When the format string for printf-style (and strftime-style) functions is not a literal, the compiler cannot check that the arguments are correct. Accidental mistakes in that area can cause robustness and security problems. PostgreSQL code in a number of places ran afoul of this. Error messages were looked up in an array or list indexed by, say, object type, often with a code comment explaining which placeholders should be included. But this relied on vigilance, not on compiler checks. (Also note that in many cases there is a translation layer on top of this, which would be equally unchecked.) Note that these issues were not flagged by -Wformat-security. This patch fixes almost all of these issues. In most cases, the code is rearranged to a switch statement indexed by object type that then calls errmsg (or errdetail etc.) directly, which preserves the association between function call and message that the compiler needs. In some cases, that switch statement is refactored into a separate helper function, similar to pre-existing errdetail_relkind_not_supported() or errdetail_busy_db(). In some places, we just have to duplicate the code a bit, but this is usually just for a small number of branches, so it seems manageable. Overall, this does not increase code size of complexity much, and arguably it makes the code easier to follow in some places. A few warnings are left in place by this patch, either because the refactoring would be too complicated or because we really do want a variable format string. These will be dealt with separately. Some light logical changes introduced by this patch: - In xlog.c, issue_xlog_fsync() translated the message twice. This is now fixed. - In oauth-curl.c, report_type_mismatch(), the unreachable default message was changed to internal. - In tablecmds.c, DropErrorMsgWrongType() would previously call errmsg(NULL) for an unknown "rightkind", which could crash. Now it doesn't call errmsg() at all, which is handled more safely. These are "shouldn't happen" conditions in any case. - In bufmgr.c, buffer_readv_report(), some light pluralization improvements were applied in passing. --- src/backend/access/heap/vacuumlazy.c | 60 ++- src/backend/access/transam/xlog.c | 43 +- src/backend/catalog/aclchk.c | 559 +++++++++++------------- src/backend/catalog/pg_publication.c | 40 +- src/backend/commands/alter.c | 62 ++- src/backend/commands/analyze.c | 16 +- src/backend/commands/dropcmds.c | 311 ++++++------- src/backend/commands/tablecmds.c | 226 +++++----- src/backend/libpq/auth.c | 80 ++-- src/backend/parser/parse_agg.c | 18 +- src/backend/parser/parse_cte.c | 40 +- src/backend/storage/buffer/bufmgr.c | 63 ++- src/backend/storage/lmgr/lmgr.c | 47 +- src/backend/utils/adt/jsonb.c | 58 +-- src/backend/utils/adt/xml.c | 25 +- src/backend/utils/misc/guc_funcs.c | 51 +-- src/bin/pgbench/pgbench.c | 18 +- src/interfaces/ecpg/ecpglib/misc.c | 36 +- src/interfaces/libpq-oauth/oauth-curl.c | 12 +- src/interfaces/libpq/fe-print.c | 30 +- src/test/regress/pg_regress.c | 12 +- 21 files changed, 911 insertions(+), 896 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 30a3e1b7063..026fc8fc73b 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -994,7 +994,6 @@ heap_vacuum_rel(Relation rel, const VacuumParams *params, WalUsage walusage; BufferUsage bufferusage; StringInfoData buf; - char *msgfmt; int32 diff; double read_rate = 0, write_rate = 0; @@ -1023,7 +1022,12 @@ heap_vacuum_rel(Relation rel, const VacuumParams *params, * VACUUM VERBOSE ereport */ Assert(!params->is_wraparound); - msgfmt = _("finished vacuuming \"%s.%s.%s\": index scans: %d\n"); + appendStringInfo(&buf, + _("finished vacuuming \"%s.%s.%s\": index scans: %d\n"), + vacrel->dbname, + vacrel->relnamespace, + vacrel->relname, + vacrel->num_index_scans); } else if (params->is_wraparound) { @@ -1034,22 +1038,37 @@ heap_vacuum_rel(Relation rel, const VacuumParams *params, * case all the same, just in case. */ if (vacrel->aggressive) - msgfmt = _("automatic aggressive vacuum to prevent wraparound of table \"%s.%s.%s\": index scans: %d\n"); + appendStringInfo(&buf, + _("automatic aggressive vacuum to prevent wraparound of table \"%s.%s.%s\": index scans: %d\n"), + vacrel->dbname, + vacrel->relnamespace, + vacrel->relname, + vacrel->num_index_scans); else - msgfmt = _("automatic vacuum to prevent wraparound of table \"%s.%s.%s\": index scans: %d\n"); + appendStringInfo(&buf, + _("automatic vacuum to prevent wraparound of table \"%s.%s.%s\": index scans: %d\n"), + vacrel->dbname, + vacrel->relnamespace, + vacrel->relname, + vacrel->num_index_scans); } else { if (vacrel->aggressive) - msgfmt = _("automatic aggressive vacuum of table \"%s.%s.%s\": index scans: %d\n"); + appendStringInfo(&buf, + _("automatic aggressive vacuum of table \"%s.%s.%s\": index scans: %d\n"), + vacrel->dbname, + vacrel->relnamespace, + vacrel->relname, + vacrel->num_index_scans); else - msgfmt = _("automatic vacuum of table \"%s.%s.%s\": index scans: %d\n"); + appendStringInfo(&buf, + _("automatic vacuum of table \"%s.%s.%s\": index scans: %d\n"), + vacrel->dbname, + vacrel->relnamespace, + vacrel->relname, + vacrel->num_index_scans); } - appendStringInfo(&buf, msgfmt, - vacrel->dbname, - vacrel->relnamespace, - vacrel->relname, - vacrel->num_index_scans); appendStringInfo(&buf, _("pages: %u removed, %u remain, %u scanned (%.2f%% of total), %u eagerly scanned\n"), vacrel->removed_pages, new_rel_pages, @@ -1109,7 +1128,12 @@ heap_vacuum_rel(Relation rel, const VacuumParams *params, else appendStringInfoString(&buf, _("index scan needed: ")); - msgfmt = _("%u pages from table (%.2f%% of total) had %" PRId64 " dead item identifiers removed\n"); + appendStringInfo(&buf, + _("%u pages from table (%.2f%% of total) had %" PRId64 " dead item identifiers removed\n"), + vacrel->lpdead_item_pages, + orig_rel_pages == 0 ? 100.0 : + 100.0 * vacrel->lpdead_item_pages / orig_rel_pages, + vacrel->lpdead_items); } else { @@ -1118,13 +1142,13 @@ heap_vacuum_rel(Relation rel, const VacuumParams *params, else appendStringInfoString(&buf, _("index scan bypassed by failsafe: ")); - msgfmt = _("%u pages from table (%.2f%% of total) have %" PRId64 " dead item identifiers\n"); + appendStringInfo(&buf, + _("%u pages from table (%.2f%% of total) have %" PRId64 " dead item identifiers\n"), + vacrel->lpdead_item_pages, + orig_rel_pages == 0 ? 100.0 : + 100.0 * vacrel->lpdead_item_pages / orig_rel_pages, + vacrel->lpdead_items); } - appendStringInfo(&buf, msgfmt, - vacrel->lpdead_item_pages, - orig_rel_pages == 0 ? 100.0 : - 100.0 * vacrel->lpdead_item_pages / orig_rel_pages, - vacrel->lpdead_items); if (vacrel->worker_usage.vacuum.nplanned > 0) appendStringInfo(&buf, diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index fd37ea4f607..27ef4c02bea 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -9890,8 +9890,9 @@ assign_wal_sync_method(int new_wal_sync_method, void *extra) void issue_xlog_fsync(int fd, XLogSegNo segno, TimeLineID tli) { - char *msg = NULL; instr_time start; + char xlogfname[MAXFNAMELEN]; + int save_errno; Assert(tli != 0); @@ -9914,17 +9915,38 @@ issue_xlog_fsync(int fd, XLogSegNo segno, TimeLineID tli) { case WAL_SYNC_METHOD_FSYNC: if (pg_fsync_no_writethrough(fd) != 0) - msg = _("could not fsync file \"%s\": %m"); + { + save_errno = errno; + XLogFileName(xlogfname, tli, segno, wal_segment_size); + errno = save_errno; + ereport(PANIC, + (errcode_for_file_access(), + errmsg("could not fsync file \"%s\": %m", xlogfname))); + } break; #ifdef HAVE_FSYNC_WRITETHROUGH case WAL_SYNC_METHOD_FSYNC_WRITETHROUGH: if (pg_fsync_writethrough(fd) != 0) - msg = _("could not fsync write-through file \"%s\": %m"); + { + save_errno = errno; + XLogFileName(xlogfname, tli, segno, wal_segment_size); + errno = save_errno; + ereport(PANIC, + (errcode_for_file_access(), + errmsg("could not fsync write-through file \"%s\": %m", xlogfname))); + } break; #endif case WAL_SYNC_METHOD_FDATASYNC: if (pg_fdatasync(fd) != 0) - msg = _("could not fdatasync file \"%s\": %m"); + { + save_errno = errno; + XLogFileName(xlogfname, tli, segno, wal_segment_size); + errno = save_errno; + ereport(PANIC, + (errcode_for_file_access(), + errmsg("could not fdatasync file \"%s\": %m", xlogfname))); + } break; case WAL_SYNC_METHOD_OPEN: case WAL_SYNC_METHOD_OPEN_DSYNC: @@ -9938,19 +9960,6 @@ issue_xlog_fsync(int fd, XLogSegNo segno, TimeLineID tli) break; } - /* PANIC if failed to fsync */ - if (msg) - { - char xlogfname[MAXFNAMELEN]; - int save_errno = errno; - - XLogFileName(xlogfname, tli, segno, wal_segment_size); - errno = save_errno; - ereport(PANIC, - (errcode_for_file_access(), - errmsg(msg, xlogfname))); - } - pgstat_report_wait_end(); pgstat_count_io_op_time(IOOBJECT_WAL, IOCONTEXT_NORMAL, IOOP_FSYNC, diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index 2bbcc3e824b..7b82255dbe6 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -385,6 +385,50 @@ restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs, return this_privileges; } +static int +errmsg_invalid_privilege_type(ObjectType objtype, AclMode priv) +{ + const char *ps = privilege_to_string(priv); + + switch (objtype) + { + case OBJECT_TABLE: + return errmsg("invalid privilege type %s for relation", ps); + case OBJECT_SEQUENCE: + return errmsg("invalid privilege type %s for sequence", ps); + case OBJECT_DATABASE: + return errmsg("invalid privilege type %s for database", ps); + case OBJECT_DOMAIN: + return errmsg("invalid privilege type %s for domain", ps); + case OBJECT_FUNCTION: + return errmsg("invalid privilege type %s for function", ps); + case OBJECT_LANGUAGE: + return errmsg("invalid privilege type %s for language", ps); + case OBJECT_LARGEOBJECT: + return errmsg("invalid privilege type %s for large object", ps); + case OBJECT_SCHEMA: + return errmsg("invalid privilege type %s for schema", ps); + case OBJECT_PROCEDURE: + return errmsg("invalid privilege type %s for procedure", ps); + case OBJECT_ROUTINE: + return errmsg("invalid privilege type %s for routine", ps); + case OBJECT_TABLESPACE: + return errmsg("invalid privilege type %s for tablespace", ps); + case OBJECT_TYPE: + return errmsg("invalid privilege type %s for type", ps); + case OBJECT_FDW: + return errmsg("invalid privilege type %s for foreign-data wrapper", ps); + case OBJECT_FOREIGN_SERVER: + return errmsg("invalid privilege type %s for foreign server", ps); + case OBJECT_PARAMETER_ACL: + return errmsg("invalid privilege type %s for parameter", ps); + default: + elog(ERROR, "unrecognized GrantStmt.objtype: %d", (int) objtype); + } + + return 0; +} + /* * Called to execute the utility commands GRANT and REVOKE */ @@ -393,7 +437,6 @@ ExecuteGrantStmt(GrantStmt *stmt) { InternalGrant istmt; ListCell *cell; - const char *errormsg; AclMode all_privileges; /* @@ -462,70 +505,54 @@ ExecuteGrantStmt(GrantStmt *stmt) * the object type. */ all_privileges = ACL_ALL_RIGHTS_RELATION | ACL_ALL_RIGHTS_SEQUENCE; - errormsg = gettext_noop("invalid privilege type %s for relation"); break; case OBJECT_SEQUENCE: all_privileges = ACL_ALL_RIGHTS_SEQUENCE; - errormsg = gettext_noop("invalid privilege type %s for sequence"); break; case OBJECT_DATABASE: all_privileges = ACL_ALL_RIGHTS_DATABASE; - errormsg = gettext_noop("invalid privilege type %s for database"); break; case OBJECT_DOMAIN: all_privileges = ACL_ALL_RIGHTS_TYPE; - errormsg = gettext_noop("invalid privilege type %s for domain"); break; case OBJECT_FUNCTION: all_privileges = ACL_ALL_RIGHTS_FUNCTION; - errormsg = gettext_noop("invalid privilege type %s for function"); break; case OBJECT_LANGUAGE: all_privileges = ACL_ALL_RIGHTS_LANGUAGE; - errormsg = gettext_noop("invalid privilege type %s for language"); break; case OBJECT_LARGEOBJECT: all_privileges = ACL_ALL_RIGHTS_LARGEOBJECT; - errormsg = gettext_noop("invalid privilege type %s for large object"); break; case OBJECT_SCHEMA: all_privileges = ACL_ALL_RIGHTS_SCHEMA; - errormsg = gettext_noop("invalid privilege type %s for schema"); break; case OBJECT_PROCEDURE: all_privileges = ACL_ALL_RIGHTS_FUNCTION; - errormsg = gettext_noop("invalid privilege type %s for procedure"); break; case OBJECT_ROUTINE: all_privileges = ACL_ALL_RIGHTS_FUNCTION; - errormsg = gettext_noop("invalid privilege type %s for routine"); break; case OBJECT_TABLESPACE: all_privileges = ACL_ALL_RIGHTS_TABLESPACE; - errormsg = gettext_noop("invalid privilege type %s for tablespace"); break; case OBJECT_TYPE: all_privileges = ACL_ALL_RIGHTS_TYPE; - errormsg = gettext_noop("invalid privilege type %s for type"); break; case OBJECT_FDW: all_privileges = ACL_ALL_RIGHTS_FDW; - errormsg = gettext_noop("invalid privilege type %s for foreign-data wrapper"); break; case OBJECT_FOREIGN_SERVER: all_privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER; - errormsg = gettext_noop("invalid privilege type %s for foreign server"); break; case OBJECT_PARAMETER_ACL: all_privileges = ACL_ALL_RIGHTS_PARAMETER_ACL; - errormsg = gettext_noop("invalid privilege type %s for parameter"); break; default: elog(ERROR, "unrecognized GrantStmt.objtype: %d", (int) stmt->objtype); /* keep compiler quiet */ all_privileges = ACL_NO_RIGHTS; - errormsg = NULL; } if (stmt->privileges == NIL) @@ -569,7 +596,7 @@ ExecuteGrantStmt(GrantStmt *stmt) if (priv & ~all_privileges) ereport(ERROR, (errcode(ERRCODE_INVALID_GRANT_OPERATION), - errmsg(errormsg, privilege_to_string(priv)))); + errmsg_invalid_privilege_type(stmt->objtype, priv))); istmt.privileges |= priv; } @@ -909,7 +936,6 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s DefElem *drolespecs = NULL; DefElem *dnspnames = NULL; AclMode all_privileges; - const char *errormsg; /* Deconstruct the "options" part of the statement */ foreach(cell, stmt->options) @@ -979,42 +1005,33 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s { case OBJECT_TABLE: all_privileges = ACL_ALL_RIGHTS_RELATION; - errormsg = gettext_noop("invalid privilege type %s for relation"); break; case OBJECT_SEQUENCE: all_privileges = ACL_ALL_RIGHTS_SEQUENCE; - errormsg = gettext_noop("invalid privilege type %s for sequence"); break; case OBJECT_FUNCTION: all_privileges = ACL_ALL_RIGHTS_FUNCTION; - errormsg = gettext_noop("invalid privilege type %s for function"); break; case OBJECT_PROCEDURE: all_privileges = ACL_ALL_RIGHTS_FUNCTION; - errormsg = gettext_noop("invalid privilege type %s for procedure"); break; case OBJECT_ROUTINE: all_privileges = ACL_ALL_RIGHTS_FUNCTION; - errormsg = gettext_noop("invalid privilege type %s for routine"); break; case OBJECT_TYPE: all_privileges = ACL_ALL_RIGHTS_TYPE; - errormsg = gettext_noop("invalid privilege type %s for type"); break; case OBJECT_SCHEMA: all_privileges = ACL_ALL_RIGHTS_SCHEMA; - errormsg = gettext_noop("invalid privilege type %s for schema"); break; case OBJECT_LARGEOBJECT: all_privileges = ACL_ALL_RIGHTS_LARGEOBJECT; - errormsg = gettext_noop("invalid privilege type %s for large object"); break; default: elog(ERROR, "unrecognized GrantStmt.objtype: %d", (int) action->objtype); /* keep compiler quiet */ all_privileges = ACL_NO_RIGHTS; - errormsg = NULL; } if (action->privileges == NIL) @@ -1049,7 +1066,7 @@ ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s if (priv & ~all_privileges) ereport(ERROR, (errcode(ERRCODE_INVALID_GRANT_OPERATION), - errmsg(errormsg, privilege_to_string(priv)))); + errmsg_invalid_privilege_type(action->objtype, priv))); iacls.privileges |= priv; } @@ -2639,6 +2656,209 @@ privilege_to_string(AclMode privilege) * Note: we do not double-quote the %s's below, because many callers * supply strings that might be already quoted. */ + +static int +errmsg_permission_denied(ObjectType objtype, const char *objectname) +{ + switch (objtype) + { + case OBJECT_AGGREGATE: + return errmsg("permission denied for aggregate %s", objectname); + case OBJECT_COLLATION: + return errmsg("permission denied for collation %s", objectname); + case OBJECT_COLUMN: + return errmsg("permission denied for column %s", objectname); + case OBJECT_CONVERSION: + return errmsg("permission denied for conversion %s", objectname); + case OBJECT_DATABASE: + return errmsg("permission denied for database %s", objectname); + case OBJECT_DOMAIN: + return errmsg("permission denied for domain %s", objectname); + case OBJECT_EVENT_TRIGGER: + return errmsg("permission denied for event trigger %s", objectname); + case OBJECT_EXTENSION: + return errmsg("permission denied for extension %s", objectname); + case OBJECT_FDW: + return errmsg("permission denied for foreign-data wrapper %s", objectname); + case OBJECT_FOREIGN_SERVER: + return errmsg("permission denied for foreign server %s", objectname); + case OBJECT_FOREIGN_TABLE: + return errmsg("permission denied for foreign table %s", objectname); + case OBJECT_FUNCTION: + return errmsg("permission denied for function %s", objectname); + case OBJECT_INDEX: + return errmsg("permission denied for index %s", objectname); + case OBJECT_LANGUAGE: + return errmsg("permission denied for language %s", objectname); + case OBJECT_LARGEOBJECT: + return errmsg("permission denied for large object %s", objectname); + case OBJECT_MATVIEW: + return errmsg("permission denied for materialized view %s", objectname); + case OBJECT_OPCLASS: + return errmsg("permission denied for operator class %s", objectname); + case OBJECT_OPERATOR: + return errmsg("permission denied for operator %s", objectname); + case OBJECT_OPFAMILY: + return errmsg("permission denied for operator family %s", objectname); + case OBJECT_PARAMETER_ACL: + return errmsg("permission denied for parameter %s", objectname); + case OBJECT_POLICY: + return errmsg("permission denied for policy %s", objectname); + case OBJECT_PROCEDURE: + return errmsg("permission denied for procedure %s", objectname); + case OBJECT_PUBLICATION: + return errmsg("permission denied for publication %s", objectname); + case OBJECT_ROUTINE: + return errmsg("permission denied for routine %s", objectname); + case OBJECT_SCHEMA: + return errmsg("permission denied for schema %s", objectname); + case OBJECT_SEQUENCE: + return errmsg("permission denied for sequence %s", objectname); + case OBJECT_STATISTIC_EXT: + return errmsg("permission denied for statistics object %s", objectname); + case OBJECT_SUBSCRIPTION: + return errmsg("permission denied for subscription %s", objectname); + case OBJECT_TABLE: + return errmsg("permission denied for table %s", objectname); + case OBJECT_TABLESPACE: + return errmsg("permission denied for tablespace %s", objectname); + case OBJECT_TSCONFIGURATION: + return errmsg("permission denied for text search configuration %s", objectname); + case OBJECT_TSDICTIONARY: + return errmsg("permission denied for text search dictionary %s", objectname); + case OBJECT_TYPE: + return errmsg("permission denied for type %s", objectname); + case OBJECT_VIEW: + return errmsg("permission denied for view %s", objectname); + /* these currently aren't used */ + case OBJECT_ACCESS_METHOD: + case OBJECT_AMOP: + case OBJECT_AMPROC: + case OBJECT_ATTRIBUTE: + case OBJECT_CAST: + case OBJECT_DEFAULT: + case OBJECT_DEFACL: + case OBJECT_DOMCONSTRAINT: + case OBJECT_PUBLICATION_EXCLUDED_REL: + case OBJECT_PUBLICATION_NAMESPACE: + case OBJECT_PUBLICATION_REL: + case OBJECT_ROLE: + case OBJECT_RULE: + case OBJECT_TABCONSTRAINT: + case OBJECT_TRANSFORM: + case OBJECT_TRIGGER: + case OBJECT_TSPARSER: + case OBJECT_TSTEMPLATE: + case OBJECT_USER_MAPPING: + elog(ERROR, "unsupported object type: %d", objtype); + } + + return 0; +} + +static int +errmsg_not_owner(ObjectType objtype, const char *objectname) +{ + switch (objtype) + { + case OBJECT_AGGREGATE: + return errmsg("must be owner of aggregate %s", objectname); + case OBJECT_COLLATION: + return errmsg("must be owner of collation %s", objectname); + case OBJECT_CONVERSION: + return errmsg("must be owner of conversion %s", objectname); + case OBJECT_DATABASE: + return errmsg("must be owner of database %s", objectname); + case OBJECT_DOMAIN: + return errmsg("must be owner of domain %s", objectname); + case OBJECT_EVENT_TRIGGER: + return errmsg("must be owner of event trigger %s", objectname); + case OBJECT_EXTENSION: + return errmsg("must be owner of extension %s", objectname); + case OBJECT_FDW: + return errmsg("must be owner of foreign-data wrapper %s", objectname); + case OBJECT_FOREIGN_SERVER: + return errmsg("must be owner of foreign server %s", objectname); + case OBJECT_FOREIGN_TABLE: + return errmsg("must be owner of foreign table %s", objectname); + case OBJECT_FUNCTION: + return errmsg("must be owner of function %s", objectname); + case OBJECT_INDEX: + return errmsg("must be owner of index %s", objectname); + case OBJECT_LANGUAGE: + return errmsg("must be owner of language %s", objectname); + case OBJECT_LARGEOBJECT: + return errmsg("must be owner of large object %s", objectname); + case OBJECT_MATVIEW: + return errmsg("must be owner of materialized view %s", objectname); + case OBJECT_OPCLASS: + return errmsg("must be owner of operator class %s", objectname); + case OBJECT_OPERATOR: + return errmsg("must be owner of operator %s", objectname); + case OBJECT_OPFAMILY: + return errmsg("must be owner of operator family %s", objectname); + case OBJECT_PROCEDURE: + return errmsg("must be owner of procedure %s", objectname); + case OBJECT_PUBLICATION: + return errmsg("must be owner of publication %s", objectname); + case OBJECT_ROUTINE: + return errmsg("must be owner of routine %s", objectname); + case OBJECT_SEQUENCE: + return errmsg("must be owner of sequence %s", objectname); + case OBJECT_SUBSCRIPTION: + return errmsg("must be owner of subscription %s", objectname); + case OBJECT_TABLE: + return errmsg("must be owner of table %s", objectname); + case OBJECT_TYPE: + return errmsg("must be owner of type %s", objectname); + case OBJECT_VIEW: + return errmsg("must be owner of view %s", objectname); + case OBJECT_SCHEMA: + return errmsg("must be owner of schema %s", objectname); + case OBJECT_STATISTIC_EXT: + return errmsg("must be owner of statistics object %s", objectname); + case OBJECT_TABLESPACE: + return errmsg("must be owner of tablespace %s", objectname); + case OBJECT_TSCONFIGURATION: + return errmsg("must be owner of text search configuration %s", objectname); + case OBJECT_TSDICTIONARY: + return errmsg("must be owner of text search dictionary %s", objectname); + + /* + * Special cases: For these, the error message talks about + * "relation", because that's where the ownership is attached. See + * also check_object_ownership(). + */ + case OBJECT_COLUMN: + case OBJECT_POLICY: + case OBJECT_RULE: + case OBJECT_TABCONSTRAINT: + case OBJECT_TRIGGER: + return errmsg("must be owner of relation %s", objectname); + /* these currently aren't used */ + case OBJECT_ACCESS_METHOD: + case OBJECT_AMOP: + case OBJECT_AMPROC: + case OBJECT_ATTRIBUTE: + case OBJECT_CAST: + case OBJECT_DEFAULT: + case OBJECT_DEFACL: + case OBJECT_DOMCONSTRAINT: + case OBJECT_PARAMETER_ACL: + case OBJECT_PUBLICATION_EXCLUDED_REL: + case OBJECT_PUBLICATION_NAMESPACE: + case OBJECT_PUBLICATION_REL: + case OBJECT_ROLE: + case OBJECT_TRANSFORM: + case OBJECT_TSPARSER: + case OBJECT_TSTEMPLATE: + case OBJECT_USER_MAPPING: + elog(ERROR, "unsupported object type: %d", objtype); + } + + return 0; +} + void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname) @@ -2649,280 +2869,15 @@ aclcheck_error(AclResult aclerr, ObjectType objtype, /* no error, so return to caller */ break; case ACLCHECK_NO_PRIV: - { - const char *msg = "???"; - - switch (objtype) - { - case OBJECT_AGGREGATE: - msg = gettext_noop("permission denied for aggregate %s"); - break; - case OBJECT_COLLATION: - msg = gettext_noop("permission denied for collation %s"); - break; - case OBJECT_COLUMN: - msg = gettext_noop("permission denied for column %s"); - break; - case OBJECT_CONVERSION: - msg = gettext_noop("permission denied for conversion %s"); - break; - case OBJECT_DATABASE: - msg = gettext_noop("permission denied for database %s"); - break; - case OBJECT_DOMAIN: - msg = gettext_noop("permission denied for domain %s"); - break; - case OBJECT_EVENT_TRIGGER: - msg = gettext_noop("permission denied for event trigger %s"); - break; - case OBJECT_EXTENSION: - msg = gettext_noop("permission denied for extension %s"); - break; - case OBJECT_FDW: - msg = gettext_noop("permission denied for foreign-data wrapper %s"); - break; - case OBJECT_FOREIGN_SERVER: - msg = gettext_noop("permission denied for foreign server %s"); - break; - case OBJECT_FOREIGN_TABLE: - msg = gettext_noop("permission denied for foreign table %s"); - break; - case OBJECT_FUNCTION: - msg = gettext_noop("permission denied for function %s"); - break; - case OBJECT_INDEX: - msg = gettext_noop("permission denied for index %s"); - break; - case OBJECT_LANGUAGE: - msg = gettext_noop("permission denied for language %s"); - break; - case OBJECT_LARGEOBJECT: - msg = gettext_noop("permission denied for large object %s"); - break; - case OBJECT_MATVIEW: - msg = gettext_noop("permission denied for materialized view %s"); - break; - case OBJECT_OPCLASS: - msg = gettext_noop("permission denied for operator class %s"); - break; - case OBJECT_OPERATOR: - msg = gettext_noop("permission denied for operator %s"); - break; - case OBJECT_OPFAMILY: - msg = gettext_noop("permission denied for operator family %s"); - break; - case OBJECT_PARAMETER_ACL: - msg = gettext_noop("permission denied for parameter %s"); - break; - case OBJECT_POLICY: - msg = gettext_noop("permission denied for policy %s"); - break; - case OBJECT_PROCEDURE: - msg = gettext_noop("permission denied for procedure %s"); - break; - case OBJECT_PUBLICATION: - msg = gettext_noop("permission denied for publication %s"); - break; - case OBJECT_ROUTINE: - msg = gettext_noop("permission denied for routine %s"); - break; - case OBJECT_SCHEMA: - msg = gettext_noop("permission denied for schema %s"); - break; - case OBJECT_SEQUENCE: - msg = gettext_noop("permission denied for sequence %s"); - break; - case OBJECT_STATISTIC_EXT: - msg = gettext_noop("permission denied for statistics object %s"); - break; - case OBJECT_SUBSCRIPTION: - msg = gettext_noop("permission denied for subscription %s"); - break; - case OBJECT_TABLE: - msg = gettext_noop("permission denied for table %s"); - break; - case OBJECT_TABLESPACE: - msg = gettext_noop("permission denied for tablespace %s"); - break; - case OBJECT_TSCONFIGURATION: - msg = gettext_noop("permission denied for text search configuration %s"); - break; - case OBJECT_TSDICTIONARY: - msg = gettext_noop("permission denied for text search dictionary %s"); - break; - case OBJECT_TYPE: - msg = gettext_noop("permission denied for type %s"); - break; - case OBJECT_VIEW: - msg = gettext_noop("permission denied for view %s"); - break; - /* these currently aren't used */ - case OBJECT_ACCESS_METHOD: - case OBJECT_AMOP: - case OBJECT_AMPROC: - case OBJECT_ATTRIBUTE: - case OBJECT_CAST: - case OBJECT_DEFAULT: - case OBJECT_DEFACL: - case OBJECT_DOMCONSTRAINT: - case OBJECT_PUBLICATION_EXCLUDED_REL: - case OBJECT_PUBLICATION_NAMESPACE: - case OBJECT_PUBLICATION_REL: - case OBJECT_ROLE: - case OBJECT_RULE: - case OBJECT_TABCONSTRAINT: - case OBJECT_TRANSFORM: - case OBJECT_TRIGGER: - case OBJECT_TSPARSER: - case OBJECT_TSTEMPLATE: - case OBJECT_USER_MAPPING: - elog(ERROR, "unsupported object type: %d", objtype); - } - - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg(msg, objectname))); - break; - } + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg_permission_denied(objtype, objectname))); + break; case ACLCHECK_NOT_OWNER: - { - const char *msg = "???"; - - switch (objtype) - { - case OBJECT_AGGREGATE: - msg = gettext_noop("must be owner of aggregate %s"); - break; - case OBJECT_COLLATION: - msg = gettext_noop("must be owner of collation %s"); - break; - case OBJECT_CONVERSION: - msg = gettext_noop("must be owner of conversion %s"); - break; - case OBJECT_DATABASE: - msg = gettext_noop("must be owner of database %s"); - break; - case OBJECT_DOMAIN: - msg = gettext_noop("must be owner of domain %s"); - break; - case OBJECT_EVENT_TRIGGER: - msg = gettext_noop("must be owner of event trigger %s"); - break; - case OBJECT_EXTENSION: - msg = gettext_noop("must be owner of extension %s"); - break; - case OBJECT_FDW: - msg = gettext_noop("must be owner of foreign-data wrapper %s"); - break; - case OBJECT_FOREIGN_SERVER: - msg = gettext_noop("must be owner of foreign server %s"); - break; - case OBJECT_FOREIGN_TABLE: - msg = gettext_noop("must be owner of foreign table %s"); - break; - case OBJECT_FUNCTION: - msg = gettext_noop("must be owner of function %s"); - break; - case OBJECT_INDEX: - msg = gettext_noop("must be owner of index %s"); - break; - case OBJECT_LANGUAGE: - msg = gettext_noop("must be owner of language %s"); - break; - case OBJECT_LARGEOBJECT: - msg = gettext_noop("must be owner of large object %s"); - break; - case OBJECT_MATVIEW: - msg = gettext_noop("must be owner of materialized view %s"); - break; - case OBJECT_OPCLASS: - msg = gettext_noop("must be owner of operator class %s"); - break; - case OBJECT_OPERATOR: - msg = gettext_noop("must be owner of operator %s"); - break; - case OBJECT_OPFAMILY: - msg = gettext_noop("must be owner of operator family %s"); - break; - case OBJECT_PROCEDURE: - msg = gettext_noop("must be owner of procedure %s"); - break; - case OBJECT_PUBLICATION: - msg = gettext_noop("must be owner of publication %s"); - break; - case OBJECT_ROUTINE: - msg = gettext_noop("must be owner of routine %s"); - break; - case OBJECT_SEQUENCE: - msg = gettext_noop("must be owner of sequence %s"); - break; - case OBJECT_SUBSCRIPTION: - msg = gettext_noop("must be owner of subscription %s"); - break; - case OBJECT_TABLE: - msg = gettext_noop("must be owner of table %s"); - break; - case OBJECT_TYPE: - msg = gettext_noop("must be owner of type %s"); - break; - case OBJECT_VIEW: - msg = gettext_noop("must be owner of view %s"); - break; - case OBJECT_SCHEMA: - msg = gettext_noop("must be owner of schema %s"); - break; - case OBJECT_STATISTIC_EXT: - msg = gettext_noop("must be owner of statistics object %s"); - break; - case OBJECT_TABLESPACE: - msg = gettext_noop("must be owner of tablespace %s"); - break; - case OBJECT_TSCONFIGURATION: - msg = gettext_noop("must be owner of text search configuration %s"); - break; - case OBJECT_TSDICTIONARY: - msg = gettext_noop("must be owner of text search dictionary %s"); - break; - - /* - * Special cases: For these, the error message talks - * about "relation", because that's where the - * ownership is attached. See also - * check_object_ownership(). - */ - case OBJECT_COLUMN: - case OBJECT_POLICY: - case OBJECT_RULE: - case OBJECT_TABCONSTRAINT: - case OBJECT_TRIGGER: - msg = gettext_noop("must be owner of relation %s"); - break; - /* these currently aren't used */ - case OBJECT_ACCESS_METHOD: - case OBJECT_AMOP: - case OBJECT_AMPROC: - case OBJECT_ATTRIBUTE: - case OBJECT_CAST: - case OBJECT_DEFAULT: - case OBJECT_DEFACL: - case OBJECT_DOMCONSTRAINT: - case OBJECT_PARAMETER_ACL: - case OBJECT_PUBLICATION_EXCLUDED_REL: - case OBJECT_PUBLICATION_NAMESPACE: - case OBJECT_PUBLICATION_REL: - case OBJECT_ROLE: - case OBJECT_TRANSFORM: - case OBJECT_TSPARSER: - case OBJECT_TSTEMPLATE: - case OBJECT_USER_MAPPING: - elog(ERROR, "unsupported object type: %d", objtype); - } - - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg(msg, objectname))); - break; - } + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg_not_owner(objtype, objectname))); + break; default: elog(ERROR, "unrecognized AclResult: %d", (int) aclerr); break; diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c index f11ea8839ca..e413280fcc0 100644 --- a/src/backend/catalog/pg_publication.c +++ b/src/backend/catalog/pg_publication.c @@ -49,18 +49,12 @@ typedef struct * table. */ } published_rel; -/* - * Check if relation can be in given publication and throws appropriate - * error if not. - */ -static void -check_publication_add_relation(PublicationRelInfo *pri) +static int +errmsg_publication_relation(bool except, Relation targetrel) { - Relation targetrel = pri->relation; const char *relname; - const char *errormsg; - if (pri->except) + if (except) { /* * The name parts must not be quoted here, because the message already @@ -69,13 +63,23 @@ check_publication_add_relation(PublicationRelInfo *pri) relname = psprintf("%s.%s", get_namespace_name(RelationGetNamespace(targetrel)), RelationGetRelationName(targetrel)); - errormsg = gettext_noop("cannot specify relation \"%s\" in the publication EXCEPT clause"); + return errmsg("cannot specify relation \"%s\" in the publication EXCEPT clause", relname); } else { relname = RelationGetRelationName(targetrel); - errormsg = gettext_noop("cannot add relation \"%s\" to publication"); + return errmsg("cannot add relation \"%s\" to publication", relname); } +} + +/* + * Check if relation can be in given publication and throws appropriate + * error if not. + */ +static void +check_publication_add_relation(PublicationRelInfo *pri) +{ + Relation targetrel = pri->relation; /* If in EXCEPT clause, must be root partitioned table */ if (pri->except && targetrel->rd_rel->relispartition) @@ -83,13 +87,13 @@ check_publication_add_relation(PublicationRelInfo *pri) if (PartitionHasPendingDetach(RelationGetRelid(targetrel))) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg(errormsg, relname), + errmsg_publication_relation(pri->except, targetrel), errdetail("This operation is not supported for partitions with an incomplete detach."), errhint("Use ALTER TABLE ... DETACH PARTITION ... FINALIZE to complete the pending detach operation."))); ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg(errormsg, relname), + errmsg_publication_relation(pri->except, targetrel), errdetail("This operation is not supported for individual partitions."))); } @@ -98,33 +102,33 @@ check_publication_add_relation(PublicationRelInfo *pri) RelationGetForm(targetrel)->relkind != RELKIND_PARTITIONED_TABLE) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg(errormsg, relname), + errmsg_publication_relation(pri->except, targetrel), errdetail_relkind_not_supported(RelationGetForm(targetrel)->relkind))); /* Can't be system table */ if (IsCatalogRelation(targetrel)) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg(errormsg, relname), + errmsg_publication_relation(pri->except, targetrel), errdetail("This operation is not supported for system tables."))); /* Can't be conflict log table */ if (IsConflictLogTableNamespace(RelationGetNamespace(targetrel))) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg(errormsg, relname), + errmsg_publication_relation(pri->except, targetrel), errdetail("This operation is not supported for conflict log tables."))); /* UNLOGGED and TEMP relations cannot be part of publication. */ if (targetrel->rd_rel->relpersistence == RELPERSISTENCE_TEMP) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg(errormsg, relname), + errmsg_publication_relation(pri->except, targetrel), errdetail("This operation is not supported for temporary tables."))); else if (targetrel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg(errormsg, relname), + errmsg_publication_relation(pri->except, targetrel), errdetail("This operation is not supported for unlogged tables."))); } diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c index 3f2af57167c..ca83a83a8b3 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -75,73 +75,89 @@ static Oid AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid); static void report_name_conflict(Oid classId, const char *name) { - char *msgfmt; - switch (classId) { case EventTriggerRelationId: - msgfmt = gettext_noop("event trigger \"%s\" already exists"); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("event trigger \"%s\" already exists", name))); break; case ForeignDataWrapperRelationId: - msgfmt = gettext_noop("foreign-data wrapper \"%s\" already exists"); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("foreign-data wrapper \"%s\" already exists", name))); break; case ForeignServerRelationId: - msgfmt = gettext_noop("server \"%s\" already exists"); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("server \"%s\" already exists", name))); break; case LanguageRelationId: - msgfmt = gettext_noop("language \"%s\" already exists"); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("language \"%s\" already exists", name))); break; case PublicationRelationId: - msgfmt = gettext_noop("publication \"%s\" already exists"); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("publication \"%s\" already exists", name))); break; case SubscriptionRelationId: - msgfmt = gettext_noop("subscription \"%s\" already exists"); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("subscription \"%s\" already exists", name))); break; default: elog(ERROR, "unsupported object class: %u", classId); break; } - - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg(msgfmt, name))); } static void report_namespace_conflict(Oid classId, const char *name, Oid nspOid) { - char *msgfmt; + char *nspname; Assert(OidIsValid(nspOid)); + nspname = get_namespace_name(nspOid); + switch (classId) { case ConversionRelationId: - msgfmt = gettext_noop("conversion \"%s\" already exists in schema \"%s\""); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("conversion \"%s\" already exists in schema \"%s\"", name, nspname))); break; case StatisticExtRelationId: - msgfmt = gettext_noop("statistics object \"%s\" already exists in schema \"%s\""); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("statistics object \"%s\" already exists in schema \"%s\"", name, nspname))); break; case TSParserRelationId: - msgfmt = gettext_noop("text search parser \"%s\" already exists in schema \"%s\""); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("text search parser \"%s\" already exists in schema \"%s\"", name, nspname))); break; case TSDictionaryRelationId: - msgfmt = gettext_noop("text search dictionary \"%s\" already exists in schema \"%s\""); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("text search dictionary \"%s\" already exists in schema \"%s\"", name, nspname))); break; case TSTemplateRelationId: - msgfmt = gettext_noop("text search template \"%s\" already exists in schema \"%s\""); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("text search template \"%s\" already exists in schema \"%s\"", name, nspname))); break; case TSConfigRelationId: - msgfmt = gettext_noop("text search configuration \"%s\" already exists in schema \"%s\""); + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("text search configuration \"%s\" already exists in schema \"%s\"", name, nspname))); break; default: elog(ERROR, "unsupported object class: %u", classId); break; } - - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg(msgfmt, name, get_namespace_name(nspOid)))); } /* diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index 1857f8a484d..8a34f43bb2e 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -777,7 +777,6 @@ do_analyze_rel(Relation onerel, const VacuumParams *params, WalUsage walusage; double read_rate = 0; double write_rate = 0; - char *msgfmt; StringInfoData buf; int64 total_blks_hit; int64 total_blks_read; @@ -833,14 +832,15 @@ do_analyze_rel(Relation onerel, const VacuumParams *params, initStringInfo(&buf); if (AmAutoVacuumWorkerProcess()) - msgfmt = _("automatic analyze of table \"%s.%s.%s\"\n"); + appendStringInfo(&buf, _("automatic analyze of table \"%s.%s.%s\"\n"), + get_database_name(MyDatabaseId), + get_namespace_name(RelationGetNamespace(onerel)), + RelationGetRelationName(onerel)); else - msgfmt = _("finished analyzing table \"%s.%s.%s\"\n"); - - appendStringInfo(&buf, msgfmt, - get_database_name(MyDatabaseId), - get_namespace_name(RelationGetNamespace(onerel)), - RelationGetRelationName(onerel)); + appendStringInfo(&buf, _("finished analyzing table \"%s.%s.%s\"\n"), + get_database_name(MyDatabaseId), + get_namespace_name(RelationGetNamespace(onerel)), + RelationGetRelationName(onerel)); if (track_cost_delay_timing) { /* diff --git a/src/backend/commands/dropcmds.c b/src/backend/commands/dropcmds.c index 228959e1050..72d252f27b4 100644 --- a/src/backend/commands/dropcmds.c +++ b/src/backend/commands/dropcmds.c @@ -30,12 +30,9 @@ static void does_not_exist_skipping(ObjectType objtype, Node *object); -static bool owningrel_does_not_exist_skipping(List *object, - const char **msg, char **name); -static bool schema_does_not_exist_skipping(List *object, - const char **msg, char **name); -static bool type_in_list_does_not_exist_skipping(List *typenames, - const char **msg, char **name); +static bool owningrel_does_not_exist_skipping(List *object); +static bool schema_does_not_exist_skipping(List *object); +static bool type_in_list_does_not_exist_skipping(List *typenames); /* @@ -133,25 +130,25 @@ RemoveObjects(DropStmt *stmt) * the specified object does not exist, test whether its owning relation, and * its schema, exist or not; if they do, return false --- the trigger or rule * itself is missing instead. If the owning relation or its schema do not - * exist, fill the error message format string and name, and return true. + * exist, issue a notice message and return true. */ static bool -owningrel_does_not_exist_skipping(List *object, const char **msg, char **name) +owningrel_does_not_exist_skipping(List *object) { List *parent_object; RangeVar *parent_rel; parent_object = list_copy_head(object, list_length(object) - 1); - if (schema_does_not_exist_skipping(parent_object, msg, name)) + if (schema_does_not_exist_skipping(parent_object)) return true; parent_rel = makeRangeVarFromNameList(parent_object); if (!OidIsValid(RangeVarGetRelid(parent_rel, NoLock, true))) { - *msg = gettext_noop("relation \"%s\" does not exist, skipping"); - *name = NameListToString(parent_object); + ereport(NOTICE, + errmsg("relation \"%s\" does not exist, skipping", NameListToString(parent_object))); return true; } @@ -167,11 +164,10 @@ owningrel_does_not_exist_skipping(List *object, const char **msg, char **name) * refers to an object that does not exist, test whether the specified schema * exists or not. If no schema was specified, or if the schema does exist, * return false -- the object itself is missing instead. If the specified - * schema does not exist, fill the error message format string and the - * specified schema name, and return true. + * schema does not exist, issue a notice message and return true. */ static bool -schema_does_not_exist_skipping(List *object, const char **msg, char **name) +schema_does_not_exist_skipping(List *object) { RangeVar *rel; @@ -180,8 +176,8 @@ schema_does_not_exist_skipping(List *object, const char **msg, char **name) if (rel->schemaname != NULL && !OidIsValid(LookupNamespaceNoError(rel->schemaname))) { - *msg = gettext_noop("schema \"%s\" does not exist, skipping"); - *name = rel->schemaname; + ereport(NOTICE, + errmsg("schema \"%s\" does not exist, skipping", rel->schemaname)); return true; } @@ -197,14 +193,12 @@ schema_does_not_exist_skipping(List *object, const char **msg, char **name) * operator returns that the specified object does not exist, test whether the * involved datatypes, and their schemas, exist or not; if they do, return * false --- the original object itself is missing instead. If the datatypes - * or schemas do not exist, fill the error message format string and the - * missing name, and return true. + * or schemas do not exist, issue a notice message and return true. * * First parameter is a list of TypeNames. */ static bool -type_in_list_does_not_exist_skipping(List *typenames, const char **msg, - char **name) +type_in_list_does_not_exist_skipping(List *typenames) { ListCell *l; @@ -217,11 +211,11 @@ type_in_list_does_not_exist_skipping(List *typenames, const char **msg, if (!OidIsValid(LookupTypeNameOid(NULL, typeName, true))) { /* type doesn't exist, try to find why */ - if (schema_does_not_exist_skipping(typeName->names, msg, name)) + if (schema_does_not_exist_skipping(typeName->names)) return true; - *msg = gettext_noop("type \"%s\" does not exist, skipping"); - *name = TypeNameToString(typeName); + ereport(NOTICE, + errmsg("type \"%s\" does not exist, skipping", TypeNameToString(typeName))); return true; } @@ -242,239 +236,217 @@ type_in_list_does_not_exist_skipping(List *typenames, const char **msg, static void does_not_exist_skipping(ObjectType objtype, Node *object) { - const char *msg = NULL; - char *name = NULL; - char *args = NULL; - switch (objtype) { case OBJECT_ACCESS_METHOD: - msg = gettext_noop("access method \"%s\" does not exist, skipping"); - name = strVal(object); + ereport(NOTICE, + errmsg("access method \"%s\" does not exist, skipping", + strVal(object))); break; case OBJECT_TYPE: case OBJECT_DOMAIN: { TypeName *typ = castNode(TypeName, object); - if (!schema_does_not_exist_skipping(typ->names, &msg, &name)) - { - msg = gettext_noop("type \"%s\" does not exist, skipping"); - name = TypeNameToString(typ); - } + if (!schema_does_not_exist_skipping(typ->names)) + ereport(NOTICE, + errmsg("type \"%s\" does not exist, skipping", + TypeNameToString(typ))); } break; case OBJECT_COLLATION: - if (!schema_does_not_exist_skipping(castNode(List, object), &msg, &name)) - { - msg = gettext_noop("collation \"%s\" does not exist, skipping"); - name = NameListToString(castNode(List, object)); - } + if (!schema_does_not_exist_skipping(castNode(List, object))) + ereport(NOTICE, + errmsg("collation \"%s\" does not exist, skipping", + NameListToString(castNode(List, object)))); break; case OBJECT_CONVERSION: - if (!schema_does_not_exist_skipping(castNode(List, object), &msg, &name)) - { - msg = gettext_noop("conversion \"%s\" does not exist, skipping"); - name = NameListToString(castNode(List, object)); - } + if (!schema_does_not_exist_skipping(castNode(List, object))) + ereport(NOTICE, + errmsg("conversion \"%s\" does not exist, skipping", + NameListToString(castNode(List, object)))); break; case OBJECT_SCHEMA: - msg = gettext_noop("schema \"%s\" does not exist, skipping"); - name = strVal(object); + ereport(NOTICE, + errmsg("schema \"%s\" does not exist, skipping", + strVal(object))); break; case OBJECT_STATISTIC_EXT: - if (!schema_does_not_exist_skipping(castNode(List, object), &msg, &name)) - { - msg = gettext_noop("statistics object \"%s\" does not exist, skipping"); - name = NameListToString(castNode(List, object)); - } + if (!schema_does_not_exist_skipping(castNode(List, object))) + ereport(NOTICE, + errmsg("statistics object \"%s\" does not exist, skipping", + NameListToString(castNode(List, object)))); break; case OBJECT_TSPARSER: - if (!schema_does_not_exist_skipping(castNode(List, object), &msg, &name)) - { - msg = gettext_noop("text search parser \"%s\" does not exist, skipping"); - name = NameListToString(castNode(List, object)); - } + if (!schema_does_not_exist_skipping(castNode(List, object))) + ereport(NOTICE, + errmsg("text search parser \"%s\" does not exist, skipping", + NameListToString(castNode(List, object)))); break; case OBJECT_TSDICTIONARY: - if (!schema_does_not_exist_skipping(castNode(List, object), &msg, &name)) - { - msg = gettext_noop("text search dictionary \"%s\" does not exist, skipping"); - name = NameListToString(castNode(List, object)); - } + if (!schema_does_not_exist_skipping(castNode(List, object))) + ereport(NOTICE, + errmsg("text search dictionary \"%s\" does not exist, skipping", + NameListToString(castNode(List, object)))); break; case OBJECT_TSTEMPLATE: - if (!schema_does_not_exist_skipping(castNode(List, object), &msg, &name)) - { - msg = gettext_noop("text search template \"%s\" does not exist, skipping"); - name = NameListToString(castNode(List, object)); - } + if (!schema_does_not_exist_skipping(castNode(List, object))) + ereport(NOTICE, + errmsg("text search template \"%s\" does not exist, skipping", + NameListToString(castNode(List, object)))); break; case OBJECT_TSCONFIGURATION: - if (!schema_does_not_exist_skipping(castNode(List, object), &msg, &name)) - { - msg = gettext_noop("text search configuration \"%s\" does not exist, skipping"); - name = NameListToString(castNode(List, object)); - } + if (!schema_does_not_exist_skipping(castNode(List, object))) + ereport(NOTICE, + errmsg("text search configuration \"%s\" does not exist, skipping", + NameListToString(castNode(List, object)))); break; case OBJECT_EXTENSION: - msg = gettext_noop("extension \"%s\" does not exist, skipping"); - name = strVal(object); + ereport(NOTICE, + errmsg("extension \"%s\" does not exist, skipping", + strVal(object))); break; case OBJECT_FUNCTION: { ObjectWithArgs *owa = castNode(ObjectWithArgs, object); - if (!schema_does_not_exist_skipping(owa->objname, &msg, &name) && - !type_in_list_does_not_exist_skipping(owa->objargs, &msg, &name)) - { - msg = gettext_noop("function %s(%s) does not exist, skipping"); - name = NameListToString(owa->objname); - args = TypeNameListToString(owa->objargs); - } + if (!schema_does_not_exist_skipping(owa->objname) && + !type_in_list_does_not_exist_skipping(owa->objargs)) + ereport(NOTICE, + errmsg("function %s(%s) does not exist, skipping", + NameListToString(owa->objname), TypeNameListToString(owa->objargs))); break; } case OBJECT_PROCEDURE: { ObjectWithArgs *owa = castNode(ObjectWithArgs, object); - if (!schema_does_not_exist_skipping(owa->objname, &msg, &name) && - !type_in_list_does_not_exist_skipping(owa->objargs, &msg, &name)) - { - msg = gettext_noop("procedure %s(%s) does not exist, skipping"); - name = NameListToString(owa->objname); - args = TypeNameListToString(owa->objargs); - } + if (!schema_does_not_exist_skipping(owa->objname) && + !type_in_list_does_not_exist_skipping(owa->objargs)) + ereport(NOTICE, + errmsg("procedure %s(%s) does not exist, skipping", + NameListToString(owa->objname), TypeNameListToString(owa->objargs))); break; } case OBJECT_ROUTINE: { ObjectWithArgs *owa = castNode(ObjectWithArgs, object); - if (!schema_does_not_exist_skipping(owa->objname, &msg, &name) && - !type_in_list_does_not_exist_skipping(owa->objargs, &msg, &name)) - { - msg = gettext_noop("routine %s(%s) does not exist, skipping"); - name = NameListToString(owa->objname); - args = TypeNameListToString(owa->objargs); - } + if (!schema_does_not_exist_skipping(owa->objname) && + !type_in_list_does_not_exist_skipping(owa->objargs)) + ereport(NOTICE, + errmsg("routine %s(%s) does not exist, skipping", + NameListToString(owa->objname), TypeNameListToString(owa->objargs))); break; } case OBJECT_AGGREGATE: { ObjectWithArgs *owa = castNode(ObjectWithArgs, object); - if (!schema_does_not_exist_skipping(owa->objname, &msg, &name) && - !type_in_list_does_not_exist_skipping(owa->objargs, &msg, &name)) - { - msg = gettext_noop("aggregate %s(%s) does not exist, skipping"); - name = NameListToString(owa->objname); - args = TypeNameListToString(owa->objargs); - } + if (!schema_does_not_exist_skipping(owa->objname) && + !type_in_list_does_not_exist_skipping(owa->objargs)) + ereport(NOTICE, + errmsg("aggregate %s(%s) does not exist, skipping", + NameListToString(owa->objname), TypeNameListToString(owa->objargs))); break; } case OBJECT_OPERATOR: { ObjectWithArgs *owa = castNode(ObjectWithArgs, object); - if (!schema_does_not_exist_skipping(owa->objname, &msg, &name) && - !type_in_list_does_not_exist_skipping(owa->objargs, &msg, &name)) - { - msg = gettext_noop("operator %s does not exist, skipping"); - name = NameListToString(owa->objname); - } + if (!schema_does_not_exist_skipping(owa->objname) && + !type_in_list_does_not_exist_skipping(owa->objargs)) + ereport(NOTICE, + errmsg("operator %s does not exist, skipping", + NameListToString(owa->objname))); break; } case OBJECT_LANGUAGE: - msg = gettext_noop("language \"%s\" does not exist, skipping"); - name = strVal(object); + ereport(NOTICE, + errmsg("language \"%s\" does not exist, skipping", + strVal(object))); break; case OBJECT_CAST: - { - if (!type_in_list_does_not_exist_skipping(list_make1(linitial(castNode(List, object))), &msg, &name) && - !type_in_list_does_not_exist_skipping(list_make1(lsecond(castNode(List, object))), &msg, &name)) - { - /* XXX quote or no quote? */ - msg = gettext_noop("cast from type %s to type %s does not exist, skipping"); - name = TypeNameToString(linitial_node(TypeName, castNode(List, object))); - args = TypeNameToString(lsecond_node(TypeName, castNode(List, object))); - } - } + if (!type_in_list_does_not_exist_skipping(list_make1(linitial(castNode(List, object)))) && + !type_in_list_does_not_exist_skipping(list_make1(lsecond(castNode(List, object))))) + ereport(NOTICE, + /* XXX quote or no quote? */ + errmsg("cast from type %s to type %s does not exist, skipping", + TypeNameToString(linitial_node(TypeName, castNode(List, object))), + TypeNameToString(lsecond_node(TypeName, castNode(List, object))))); break; case OBJECT_TRANSFORM: - if (!type_in_list_does_not_exist_skipping(list_make1(linitial(castNode(List, object))), &msg, &name)) - { - msg = gettext_noop("transform for type %s language \"%s\" does not exist, skipping"); - name = TypeNameToString(linitial_node(TypeName, castNode(List, object))); - args = strVal(lsecond(castNode(List, object))); - } + if (!type_in_list_does_not_exist_skipping(list_make1(linitial(castNode(List, object))))) + ereport(NOTICE, + errmsg("transform for type %s language \"%s\" does not exist, skipping", + TypeNameToString(linitial_node(TypeName, castNode(List, object))), + strVal(lsecond(castNode(List, object))))); break; case OBJECT_TRIGGER: - if (!owningrel_does_not_exist_skipping(castNode(List, object), &msg, &name)) - { - msg = gettext_noop("trigger \"%s\" for relation \"%s\" does not exist, skipping"); - name = strVal(llast(castNode(List, object))); - args = NameListToString(list_copy_head(castNode(List, object), - list_length(castNode(List, object)) - 1)); - } + if (!owningrel_does_not_exist_skipping(castNode(List, object))) + ereport(NOTICE, + errmsg("trigger \"%s\" for relation \"%s\" does not exist, skipping", + strVal(llast(castNode(List, object))), + NameListToString(list_copy_head(castNode(List, object), + list_length(castNode(List, object)) - 1)))); break; case OBJECT_POLICY: - if (!owningrel_does_not_exist_skipping(castNode(List, object), &msg, &name)) - { - msg = gettext_noop("policy \"%s\" for relation \"%s\" does not exist, skipping"); - name = strVal(llast(castNode(List, object))); - args = NameListToString(list_copy_head(castNode(List, object), - list_length(castNode(List, object)) - 1)); - } + if (!owningrel_does_not_exist_skipping(castNode(List, object))) + ereport(NOTICE, + errmsg("policy \"%s\" for relation \"%s\" does not exist, skipping", + strVal(llast(castNode(List, object))), + NameListToString(list_copy_head(castNode(List, object), + list_length(castNode(List, object)) - 1)))); break; case OBJECT_EVENT_TRIGGER: - msg = gettext_noop("event trigger \"%s\" does not exist, skipping"); - name = strVal(object); + ereport(NOTICE, + errmsg("event trigger \"%s\" does not exist, skipping", + strVal(object))); break; case OBJECT_RULE: - if (!owningrel_does_not_exist_skipping(castNode(List, object), &msg, &name)) - { - msg = gettext_noop("rule \"%s\" for relation \"%s\" does not exist, skipping"); - name = strVal(llast(castNode(List, object))); - args = NameListToString(list_copy_head(castNode(List, object), - list_length(castNode(List, object)) - 1)); - } + if (!owningrel_does_not_exist_skipping(castNode(List, object))) + ereport(NOTICE, + errmsg("rule \"%s\" for relation \"%s\" does not exist, skipping", + strVal(llast(castNode(List, object))), + NameListToString(list_copy_head(castNode(List, object), + list_length(castNode(List, object)) - 1)))); break; case OBJECT_FDW: - msg = gettext_noop("foreign-data wrapper \"%s\" does not exist, skipping"); - name = strVal(object); + ereport(NOTICE, + errmsg("foreign-data wrapper \"%s\" does not exist, skipping", + strVal(object))); break; case OBJECT_FOREIGN_SERVER: - msg = gettext_noop("server \"%s\" does not exist, skipping"); - name = strVal(object); + ereport(NOTICE, + errmsg("server \"%s\" does not exist, skipping", + strVal(object))); break; case OBJECT_OPCLASS: { List *opcname = list_copy_tail(castNode(List, object), 1); - if (!schema_does_not_exist_skipping(opcname, &msg, &name)) - { - msg = gettext_noop("operator class \"%s\" does not exist for access method \"%s\", skipping"); - name = NameListToString(opcname); - args = strVal(linitial(castNode(List, object))); - } + if (!schema_does_not_exist_skipping(opcname)) + ereport(NOTICE, + errmsg("operator class \"%s\" does not exist for access method \"%s\", skipping", + NameListToString(opcname), + strVal(linitial(castNode(List, object))))); } break; case OBJECT_OPFAMILY: { List *opfname = list_copy_tail(castNode(List, object), 1); - if (!schema_does_not_exist_skipping(opfname, &msg, &name)) - { - msg = gettext_noop("operator family \"%s\" does not exist for access method \"%s\", skipping"); - name = NameListToString(opfname); - args = strVal(linitial(castNode(List, object))); - } + if (!schema_does_not_exist_skipping(opfname)) + ereport(NOTICE, + errmsg("operator family \"%s\" does not exist for access method \"%s\", skipping", + NameListToString(opfname), + strVal(linitial(castNode(List, object))))); } break; case OBJECT_PUBLICATION: - msg = gettext_noop("publication \"%s\" does not exist, skipping"); - name = strVal(object); + ereport(NOTICE, + errmsg("publication \"%s\" does not exist, skipping", + strVal(object))); break; case OBJECT_COLUMN: @@ -515,11 +487,4 @@ does_not_exist_skipping(ObjectType objtype, Node *object) /* no default, to let compiler warn about missing case */ } - if (!msg) - elog(ERROR, "unrecognized object type: %d", (int) objtype); - - if (!args) - ereport(NOTICE, (errmsg(msg, name))); - else - ereport(NOTICE, (errmsg(msg, name, args))); } diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index b6700929459..50a0eecec56 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -245,77 +245,6 @@ typedef struct NewColumnValue bool is_generated; /* is it a GENERATED expression? */ } NewColumnValue; -/* - * Error-reporting support for RemoveRelations - */ -struct dropmsgstrings -{ - char kind; - int nonexistent_code; - const char *nonexistent_msg; - const char *skipping_msg; - const char *nota_msg; - const char *drophint_msg; -}; - -static const struct dropmsgstrings dropmsgstringarray[] = { - {RELKIND_RELATION, - ERRCODE_UNDEFINED_TABLE, - gettext_noop("table \"%s\" does not exist"), - gettext_noop("table \"%s\" does not exist, skipping"), - gettext_noop("\"%s\" is not a table"), - gettext_noop("Use DROP TABLE to remove a table.")}, - {RELKIND_SEQUENCE, - ERRCODE_UNDEFINED_TABLE, - gettext_noop("sequence \"%s\" does not exist"), - gettext_noop("sequence \"%s\" does not exist, skipping"), - gettext_noop("\"%s\" is not a sequence"), - gettext_noop("Use DROP SEQUENCE to remove a sequence.")}, - {RELKIND_VIEW, - ERRCODE_UNDEFINED_TABLE, - gettext_noop("view \"%s\" does not exist"), - gettext_noop("view \"%s\" does not exist, skipping"), - gettext_noop("\"%s\" is not a view"), - gettext_noop("Use DROP VIEW to remove a view.")}, - {RELKIND_MATVIEW, - ERRCODE_UNDEFINED_TABLE, - gettext_noop("materialized view \"%s\" does not exist"), - gettext_noop("materialized view \"%s\" does not exist, skipping"), - gettext_noop("\"%s\" is not a materialized view"), - gettext_noop("Use DROP MATERIALIZED VIEW to remove a materialized view.")}, - {RELKIND_INDEX, - ERRCODE_UNDEFINED_OBJECT, - gettext_noop("index \"%s\" does not exist"), - gettext_noop("index \"%s\" does not exist, skipping"), - gettext_noop("\"%s\" is not an index"), - gettext_noop("Use DROP INDEX to remove an index.")}, - {RELKIND_COMPOSITE_TYPE, - ERRCODE_UNDEFINED_OBJECT, - gettext_noop("type \"%s\" does not exist"), - gettext_noop("type \"%s\" does not exist, skipping"), - gettext_noop("\"%s\" is not a type"), - gettext_noop("Use DROP TYPE to remove a type.")}, - {RELKIND_FOREIGN_TABLE, - ERRCODE_UNDEFINED_OBJECT, - gettext_noop("foreign table \"%s\" does not exist"), - gettext_noop("foreign table \"%s\" does not exist, skipping"), - gettext_noop("\"%s\" is not a foreign table"), - gettext_noop("Use DROP FOREIGN TABLE to remove a foreign table.")}, - {RELKIND_PARTITIONED_TABLE, - ERRCODE_UNDEFINED_TABLE, - gettext_noop("table \"%s\" does not exist"), - gettext_noop("table \"%s\" does not exist, skipping"), - gettext_noop("\"%s\" is not a table"), - gettext_noop("Use DROP TABLE to remove a table.")}, - {RELKIND_PARTITIONED_INDEX, - ERRCODE_UNDEFINED_OBJECT, - gettext_noop("index \"%s\" does not exist"), - gettext_noop("index \"%s\" does not exist, skipping"), - gettext_noop("\"%s\" is not an index"), - gettext_noop("Use DROP INDEX to remove an index.")}, - {'\0', 0, NULL, NULL, NULL, NULL} -}; - /* communication between RemoveRelations and RangeVarCallbackForDropRelation */ struct DropRelationCallbackState { @@ -1506,8 +1435,6 @@ BuildDescForRelation(const List *columns) static void DropErrorMsgNonExistent(RangeVar *rel, char rightkind, bool missing_ok) { - const struct dropmsgstrings *rentry; - if (rel->schemaname != NULL && !OidIsValid(LookupNamespaceNoError(rel->schemaname))) { @@ -1526,25 +1453,137 @@ DropErrorMsgNonExistent(RangeVar *rel, char rightkind, bool missing_ok) return; } - for (rentry = dropmsgstringarray; rentry->kind != '\0'; rentry++) + if (!missing_ok) { - if (rentry->kind == rightkind) + switch (rightkind) { - if (!missing_ok) - { + case RELKIND_RELATION: + case RELKIND_PARTITIONED_TABLE: ereport(ERROR, - (errcode(rentry->nonexistent_code), - errmsg(rentry->nonexistent_msg, rel->relname))); - } - else - { - ereport(NOTICE, (errmsg(rentry->skipping_msg, rel->relname))); + errcode(ERRCODE_UNDEFINED_TABLE), + errmsg("table \"%s\" does not exist", rel->relname)); + break; + case RELKIND_SEQUENCE: + ereport(ERROR, + errcode(ERRCODE_UNDEFINED_TABLE), + errmsg("sequence \"%s\" does not exist", rel->relname)); + break; + case RELKIND_VIEW: + ereport(ERROR, + errcode(ERRCODE_UNDEFINED_TABLE), + errmsg("view \"%s\" does not exist", rel->relname)); + break; + case RELKIND_MATVIEW: + ereport(ERROR, + errcode(ERRCODE_UNDEFINED_TABLE), + errmsg("materialized view \"%s\" does not exist", rel->relname)); + break; + case RELKIND_INDEX: + case RELKIND_PARTITIONED_INDEX: + ereport(ERROR, + errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("index \"%s\" does not exist", rel->relname)); + break; + case RELKIND_COMPOSITE_TYPE: + ereport(ERROR, + errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("type \"%s\" does not exist", rel->relname)); + break; + case RELKIND_FOREIGN_TABLE: + ereport(ERROR, + errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("foreign table \"%s\" does not exist", rel->relname)); + break; + } + } + else + { + switch (rightkind) + { + case RELKIND_RELATION: + case RELKIND_PARTITIONED_TABLE: + ereport(NOTICE, + errmsg("table \"%s\" does not exist, skipping", rel->relname)); + break; + case RELKIND_SEQUENCE: + ereport(NOTICE, + errmsg("sequence \"%s\" does not exist, skipping", rel->relname)); + break; + case RELKIND_VIEW: + ereport(NOTICE, + errmsg("view \"%s\" does not exist, skipping", rel->relname)); + break; + case RELKIND_MATVIEW: + ereport(NOTICE, + errmsg("materialized view \"%s\" does not exist, skipping", rel->relname)); + break; + case RELKIND_INDEX: + case RELKIND_PARTITIONED_INDEX: + ereport(NOTICE, + errmsg("index \"%s\" does not exist, skipping", rel->relname)); + break; + case RELKIND_COMPOSITE_TYPE: + ereport(NOTICE, + errmsg("type \"%s\" does not exist, skipping", rel->relname)); + break; + case RELKIND_FOREIGN_TABLE: + ereport(NOTICE, + errmsg("foreign table \"%s\" does not exist, skipping", rel->relname)); break; - } } } +} - Assert(rentry->kind != '\0'); /* Should be impossible */ +static int +errmsg_nota(char relkind, const char *relname) +{ + switch (relkind) + { + case RELKIND_RELATION: + case RELKIND_PARTITIONED_TABLE: + return errmsg("\"%s\" is not a table", relname); + case RELKIND_SEQUENCE: + return errmsg("\"%s\" is not a sequence", relname); + case RELKIND_VIEW: + return errmsg("\"%s\" is not a view", relname); + case RELKIND_MATVIEW: + return errmsg("\"%s\" is not a materialized view", relname); + case RELKIND_INDEX: + case RELKIND_PARTITIONED_INDEX: + return errmsg("\"%s\" is not an index", relname); + case RELKIND_COMPOSITE_TYPE: + return errmsg("\"%s\" is not a type", relname); + case RELKIND_FOREIGN_TABLE: + return errmsg("\"%s\" is not a foreign table", relname); + } + Assert(false); + return 0; +} + +static int +errhint_dropcmd(char relkind) +{ + switch (relkind) + { + case RELKIND_RELATION: + case RELKIND_PARTITIONED_TABLE: + return errhint("Use DROP TABLE to remove a table."); + case RELKIND_SEQUENCE: + return errhint("Use DROP SEQUENCE to remove a sequence."); + case RELKIND_VIEW: + return errhint("Use DROP VIEW to remove a view."); + case RELKIND_MATVIEW: + return errhint("Use DROP MATERIALIZED VIEW to remove a materialized view."); + case RELKIND_INDEX: + case RELKIND_PARTITIONED_INDEX: + return errhint("Use DROP INDEX to remove an index."); + case RELKIND_COMPOSITE_TYPE: + return errhint("Use DROP TYPE to remove a type."); + case RELKIND_FOREIGN_TABLE: + return errhint("Use DROP FOREIGN TABLE to remove a foreign table."); + } + /* relkind could be something we don't handle here ... */ + return 0; } /* @@ -1554,23 +1593,10 @@ DropErrorMsgNonExistent(RangeVar *rel, char rightkind, bool missing_ok) static void DropErrorMsgWrongType(const char *relname, char wrongkind, char rightkind) { - const struct dropmsgstrings *rentry; - const struct dropmsgstrings *wentry; - - for (rentry = dropmsgstringarray; rentry->kind != '\0'; rentry++) - if (rentry->kind == rightkind) - break; - Assert(rentry->kind != '\0'); - - for (wentry = dropmsgstringarray; wentry->kind != '\0'; wentry++) - if (wentry->kind == wrongkind) - break; - /* wrongkind could be something we don't have in our table... */ - ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg(rentry->nota_msg, relname), - (wentry->kind != '\0') ? errhint("%s", _(wentry->drophint_msg)) : 0)); + errmsg_nota(rightkind, relname), + errhint_dropcmd(wrongkind))); } /* diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index 12bf153d66f..351910320a8 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -218,6 +218,43 @@ static int pg_SSPI_make_upn(char *accountname, */ ClientAuthentication_hook_type ClientAuthentication_hook = NULL; +static int +errmsg_auth_failed(UserAuth auth_method, const char *user_name) +{ + switch (auth_method) + { + case uaReject: + case uaImplicitReject: + return errmsg("authentication failed for user \"%s\": host rejected", user_name); + case uaTrust: + return errmsg("\"trust\" authentication failed for user \"%s\"", user_name); + case uaIdent: + return errmsg("Ident authentication failed for user \"%s\"", user_name); + case uaPeer: + return errmsg("Peer authentication failed for user \"%s\"", user_name); + case uaPassword: + case uaMD5: + case uaSCRAM: + return errmsg("password authentication failed for user \"%s\"", user_name); + case uaGSS: + return errmsg("GSSAPI authentication failed for user \"%s\"", user_name); + case uaSSPI: + return errmsg("SSPI authentication failed for user \"%s\"", user_name); + case uaPAM: + return errmsg("PAM authentication failed for user \"%s\"", user_name); + case uaBSD: + return errmsg("BSD authentication failed for user \"%s\"", user_name); + case uaLDAP: + return errmsg("LDAP authentication failed for user \"%s\"", user_name); + case uaCert: + return errmsg("certificate authentication failed for user \"%s\"", user_name); + case uaOAuth: + return errmsg("OAuth bearer authentication failed for user \"%s\"", user_name); + default: + return errmsg("authentication failed for user \"%s\": invalid authentication method", user_name); + } +} + /* * Tell the user the authentication failed, but not (much about) why. * @@ -235,9 +272,8 @@ ClientAuthentication_hook_type ClientAuthentication_hook = NULL; static void auth_failed(Port *port, int elevel, int status, const char *logdetail) { - const char *errstr; char *cdetail; - int errcode_return = ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION; + int errcode_return; Assert(elevel >= FATAL); /* we must exit here */ @@ -256,50 +292,14 @@ auth_failed(Port *port, int elevel, int status, const char *logdetail) switch (port->hba->auth_method) { - case uaReject: - case uaImplicitReject: - errstr = gettext_noop("authentication failed for user \"%s\": host rejected"); - break; - case uaTrust: - errstr = gettext_noop("\"trust\" authentication failed for user \"%s\""); - break; - case uaIdent: - errstr = gettext_noop("Ident authentication failed for user \"%s\""); - break; - case uaPeer: - errstr = gettext_noop("Peer authentication failed for user \"%s\""); - break; case uaPassword: case uaMD5: case uaSCRAM: - errstr = gettext_noop("password authentication failed for user \"%s\""); /* We use it to indicate if a .pgpass password failed. */ errcode_return = ERRCODE_INVALID_PASSWORD; break; - case uaGSS: - errstr = gettext_noop("GSSAPI authentication failed for user \"%s\""); - break; - case uaSSPI: - errstr = gettext_noop("SSPI authentication failed for user \"%s\""); - break; - case uaPAM: - errstr = gettext_noop("PAM authentication failed for user \"%s\""); - break; - case uaBSD: - errstr = gettext_noop("BSD authentication failed for user \"%s\""); - break; - case uaLDAP: - errstr = gettext_noop("LDAP authentication failed for user \"%s\""); - break; - case uaCert: - errstr = gettext_noop("certificate authentication failed for user \"%s\""); - break; - case uaOAuth: - errstr = gettext_noop("OAuth bearer authentication failed for user \"%s\""); - break; default: - errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method"); - break; + errcode_return = ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION; } cdetail = psprintf(_("Connection matched file \"%s\" line %d: \"%s\""), @@ -312,7 +312,7 @@ auth_failed(Port *port, int elevel, int status, const char *logdetail) ereport(elevel, (errcode(errcode_return), - errmsg(errstr, port->user_name), + errmsg_auth_failed(port->hba->auth_method, port->user_name), logdetail ? errdetail_log("%s", logdetail) : 0)); /* doesn't return */ diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index a5424c9d24c..475a9d8cee6 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -603,17 +603,19 @@ check_agglevels_and_constraints(ParseState *pstate, Node *expr) if (errkind) { if (isAgg) + ereport(ERROR, + (errcode(ERRCODE_GROUPING_ERROR), /* translator: %s is name of a SQL construct, eg GROUP BY */ - err = _("aggregate functions are not allowed in %s"); + errmsg("aggregate functions are not allowed in %s", + ParseExprKindName(pstate->p_expr_kind)), + parser_errposition(pstate, location))); else + ereport(ERROR, + (errcode(ERRCODE_GROUPING_ERROR), /* translator: %s is name of a SQL construct, eg GROUP BY */ - err = _("grouping operations are not allowed in %s"); - - ereport(ERROR, - (errcode(ERRCODE_GROUPING_ERROR), - errmsg_internal(err, - ParseExprKindName(pstate->p_expr_kind)), - parser_errposition(pstate, location))); + errmsg("grouping operations are not allowed in %s", + ParseExprKindName(pstate->p_expr_kind)), + parser_errposition(pstate, location))); } } diff --git a/src/backend/parser/parse_cte.c b/src/backend/parser/parse_cte.c index 73e86b7422f..0c97c2cdfb8 100644 --- a/src/backend/parser/parse_cte.c +++ b/src/backend/parser/parse_cte.c @@ -38,21 +38,27 @@ typedef enum RECURSION_EXCEPT, /* underneath EXCEPT (ALL) */ } RecursionContext; -/* Associated error messages --- each must have one %s for CTE name */ -static const char *const recursion_errormsgs[] = { - /* RECURSION_OK */ - NULL, - /* RECURSION_NONRECURSIVETERM */ - gettext_noop("recursive reference to query \"%s\" must not appear within its non-recursive term"), - /* RECURSION_SUBLINK */ - gettext_noop("recursive reference to query \"%s\" must not appear within a subquery"), - /* RECURSION_OUTERJOIN */ - gettext_noop("recursive reference to query \"%s\" must not appear within an outer join"), - /* RECURSION_INTERSECT */ - gettext_noop("recursive reference to query \"%s\" must not appear within INTERSECT"), - /* RECURSION_EXCEPT */ - gettext_noop("recursive reference to query \"%s\" must not appear within EXCEPT") -}; +static int +errmsg_recursion(RecursionContext context, const char *ctename) +{ + switch (context) + { + case RECURSION_OK: + return 0; + case RECURSION_NONRECURSIVETERM: + return errmsg("recursive reference to query \"%s\" must not appear within its non-recursive term", ctename); + case RECURSION_SUBLINK: + return errmsg("recursive reference to query \"%s\" must not appear within a subquery", ctename); + case RECURSION_OUTERJOIN: + return errmsg("recursive reference to query \"%s\" must not appear within an outer join", ctename); + case RECURSION_INTERSECT: + return errmsg("recursive reference to query \"%s\" must not appear within INTERSECT", ctename); + case RECURSION_EXCEPT: + return errmsg("recursive reference to query \"%s\" must not appear within EXCEPT", ctename); + } + + return 0; +} /* * For WITH RECURSIVE, we have to find an ordering of the clause members @@ -1063,8 +1069,8 @@ checkWellFormedRecursionWalker(Node *node, CteState *cstate) if (cstate->context != RECURSION_OK) ereport(ERROR, (errcode(ERRCODE_INVALID_RECURSION), - errmsg(recursion_errormsgs[cstate->context], - mycte->ctename), + errmsg_recursion(cstate->context, + mycte->ctename), parser_errposition(cstate->pstate, rv->location))); /* Count references */ diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index c17fc3590f0..121e2834fe9 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -8847,10 +8847,6 @@ buffer_readv_report(PgAioResult result, const PgAioTargetData *td, checkfail_count, first_off; uint8 affected_count; - const char *msg_one, - *msg_mult, - *det_mult, - *hint_mult; buffer_readv_decode_error(result, &zeroed_any, &ignored_any, &zeroed_or_error_count, @@ -8892,37 +8888,56 @@ buffer_readv_report(PgAioResult result, const PgAioTargetData *td, { Assert(!zeroed_any); /* can't have invalid pages when zeroing them */ affected_count = zeroed_or_error_count; - msg_one = _("invalid page in block %u of relation \"%s\""); - msg_mult = _("%u invalid pages among blocks %u..%u of relation \"%s\""); - det_mult = _("Block %u held the first invalid page."); - hint_mult = _("See server log for the other %u invalid block(s)."); + ereport(elevel, + errcode(ERRCODE_DATA_CORRUPTED), + affected_count == 1 ? + errmsg("invalid page in block %u of relation \"%s\"", first + first_off, rpath.str) : + errmsg_plural("%u invalid page among blocks %u..%u of relation \"%s\"", + "%u invalid pages among blocks %u..%u of relation \"%s\"", + affected_count, + affected_count, first, last, rpath.str), + affected_count > 1 ? errdetail("Block %u held the first invalid page.", first + first_off) : 0, + affected_count > 1 ? errhint_plural("See server log for the other %u invalid block.", + "See server log for the other %u invalid blocks.", + affected_count - 1, + affected_count - 1) : 0); } else if (zeroed_any && !ignored_any) { affected_count = zeroed_or_error_count; - msg_one = _("invalid page in block %u of relation \"%s\"; zeroing out page"); - msg_mult = _("zeroing out %u invalid pages among blocks %u..%u of relation \"%s\""); - det_mult = _("Block %u held the first zeroed page."); - hint_mult = _("See server log for the other %u zeroed block(s)."); + ereport(elevel, + errcode(ERRCODE_DATA_CORRUPTED), + affected_count == 1 ? + errmsg("invalid page in block %u of relation \"%s\"; zeroing out page", first + first_off, rpath.str) : + errmsg_plural("zeroing out %u invalid page among blocks %u..%u of relation \"%s\"", + "zeroing out %u invalid pages among blocks %u..%u of relation \"%s\"", + affected_count, + affected_count, first, last, rpath.str), + affected_count > 1 ? errdetail("Block %u held the first zeroed page.", first + first_off) : 0, + affected_count > 1 ? errhint_plural("See server log for the other %u zeroed block.", + "See server log for the other %u zeroed blocks.", + affected_count - 1, + affected_count - 1) : 0); } else if (!zeroed_any && ignored_any) { affected_count = checkfail_count; - msg_one = _("ignoring checksum failure in block %u of relation \"%s\""); - msg_mult = _("ignoring %u checksum failures among blocks %u..%u of relation \"%s\""); - det_mult = _("Block %u held the first ignored page."); - hint_mult = _("See server log for the other %u ignored block(s)."); + ereport(elevel, + errcode(ERRCODE_DATA_CORRUPTED), + affected_count == 1 ? + errmsg("ignoring checksum failure in block %u of relation \"%s\"", first + first_off, rpath.str) : + errmsg_plural("ignoring %u checksum failure among blocks %u..%u of relation \"%s\"", + "ignoring %u checksum failures among blocks %u..%u of relation \"%s\"", + affected_count, + affected_count, first, last, rpath.str), + affected_count > 1 ? errdetail("Block %u held the first ignored page.", first + first_off) : 0, + affected_count > 1 ? errhint_plural("See server log for the other %u ignored block.", + "See server log for the other %u ignored blocks.", + affected_count - 1, + affected_count - 1) : 0); } else pg_unreachable(); - - ereport(elevel, - errcode(ERRCODE_DATA_CORRUPTED), - affected_count == 1 ? - errmsg_internal(msg_one, first + first_off, rpath.str) : - errmsg_internal(msg_mult, affected_count, first, last, rpath.str), - affected_count > 1 ? errdetail_internal(det_mult, first + first_off) : 0, - affected_count > 1 ? errhint_internal(hint_mult, affected_count - 1) : 0); } static void diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c index 2ccf7237fee..9297c7d2dbf 100644 --- a/src/backend/storage/lmgr/lmgr.c +++ b/src/backend/storage/lmgr/lmgr.c @@ -854,43 +854,60 @@ XactLockTableWaitErrorCb(void *arg) if (info->oper != XLTW_None && ItemPointerIsValid(info->ctid) && RelationIsValid(info->rel)) { - const char *cxt; - switch (info->oper) { case XLTW_Update: - cxt = gettext_noop("while updating tuple (%u,%u) in relation \"%s\""); + errcontext("while updating tuple (%u,%u) in relation \"%s\"", + ItemPointerGetBlockNumber(info->ctid), + ItemPointerGetOffsetNumber(info->ctid), + RelationGetRelationName(info->rel)); break; case XLTW_Delete: - cxt = gettext_noop("while deleting tuple (%u,%u) in relation \"%s\""); + errcontext("while deleting tuple (%u,%u) in relation \"%s\"", + ItemPointerGetBlockNumber(info->ctid), + ItemPointerGetOffsetNumber(info->ctid), + RelationGetRelationName(info->rel)); break; case XLTW_Lock: - cxt = gettext_noop("while locking tuple (%u,%u) in relation \"%s\""); + errcontext("while locking tuple (%u,%u) in relation \"%s\"", + ItemPointerGetBlockNumber(info->ctid), + ItemPointerGetOffsetNumber(info->ctid), + RelationGetRelationName(info->rel)); break; case XLTW_LockUpdated: - cxt = gettext_noop("while locking updated version (%u,%u) of tuple in relation \"%s\""); + errcontext("while locking updated version (%u,%u) of tuple in relation \"%s\"", + ItemPointerGetBlockNumber(info->ctid), + ItemPointerGetOffsetNumber(info->ctid), + RelationGetRelationName(info->rel)); break; case XLTW_InsertIndex: - cxt = gettext_noop("while inserting index tuple (%u,%u) in relation \"%s\""); + errcontext("while inserting index tuple (%u,%u) in relation \"%s\"", + ItemPointerGetBlockNumber(info->ctid), + ItemPointerGetOffsetNumber(info->ctid), + RelationGetRelationName(info->rel)); break; case XLTW_InsertIndexUnique: - cxt = gettext_noop("while checking uniqueness of tuple (%u,%u) in relation \"%s\""); + errcontext("while checking uniqueness of tuple (%u,%u) in relation \"%s\"", + ItemPointerGetBlockNumber(info->ctid), + ItemPointerGetOffsetNumber(info->ctid), + RelationGetRelationName(info->rel)); break; case XLTW_FetchUpdated: - cxt = gettext_noop("while rechecking updated tuple (%u,%u) in relation \"%s\""); + errcontext("while rechecking updated tuple (%u,%u) in relation \"%s\"", + ItemPointerGetBlockNumber(info->ctid), + ItemPointerGetOffsetNumber(info->ctid), + RelationGetRelationName(info->rel)); break; case XLTW_RecheckExclusionConstr: - cxt = gettext_noop("while checking exclusion constraint on tuple (%u,%u) in relation \"%s\""); + errcontext("while checking exclusion constraint on tuple (%u,%u) in relation \"%s\"", + ItemPointerGetBlockNumber(info->ctid), + ItemPointerGetOffsetNumber(info->ctid), + RelationGetRelationName(info->rel)); break; default: return; } - - errcontext(cxt, - ItemPointerGetBlockNumber(info->ctid), - ItemPointerGetOffsetNumber(info->ctid), - RelationGetRelationName(info->rel)); } } diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c index 8a22d177414..193781c36ee 100644 --- a/src/backend/utils/adt/jsonb.c +++ b/src/backend/utils/adt/jsonb.c @@ -1841,37 +1841,43 @@ JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res) return true; } -/* - * Emit correct, translatable cast error message - */ -static Datum -cannotCastJsonbValue(enum jbvType type, const char *sqltype, Node *escontext) +static int +errmsg_cannot_cast_jsonb(enum jbvType type, const char *sqltype) { - static const struct + switch (type) { - enum jbvType type; - const char *msg; + case jbvNull: + return errmsg("cannot cast jsonb null to type %s", sqltype); + case jbvString: + return errmsg("cannot cast jsonb string to type %s", sqltype); + case jbvNumeric: + return errmsg("cannot cast jsonb numeric to type %s", sqltype); + case jbvBool: + return errmsg("cannot cast jsonb boolean to type %s", sqltype); + case jbvArray: + return errmsg("cannot cast jsonb array to type %s", sqltype); + case jbvObject: + return errmsg("cannot cast jsonb object to type %s", sqltype); + case jbvBinary: + return errmsg("cannot cast jsonb array or object to type %s", sqltype); + case jbvDatetime: + /* rejected by caller */ + break; } - messages[] = - { - {jbvNull, gettext_noop("cannot cast jsonb null to type %s")}, - {jbvString, gettext_noop("cannot cast jsonb string to type %s")}, - {jbvNumeric, gettext_noop("cannot cast jsonb numeric to type %s")}, - {jbvBool, gettext_noop("cannot cast jsonb boolean to type %s")}, - {jbvArray, gettext_noop("cannot cast jsonb array to type %s")}, - {jbvObject, gettext_noop("cannot cast jsonb object to type %s")}, - {jbvBinary, gettext_noop("cannot cast jsonb array or object to type %s")} - }; - - for (size_t i = 0; i < lengthof(messages); i++) - if (messages[i].type == type) - ereturn(escontext, (Datum) 0, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg(messages[i].msg, sqltype))); + elog(ERROR, "unknown jsonb type: %d", (int) type); + return 0; +} +static Datum +cannotCastJsonbValue(enum jbvType type, const char *sqltype, Node *escontext) +{ /* should be unreachable */ - elog(ERROR, "unknown jsonb type: %d", (int) type); - return (Datum) 0; + if (type == jbvDatetime) + elog(ERROR, "unexpected jsonb type: %d", (int) type); + + ereturn(escontext, (Datum) 0, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg_cannot_cast_jsonb(type, sqltype))); } Datum diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index 44a3a21d135..142876d00f9 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -2331,34 +2331,23 @@ xml_errorHandler(void *data, PgXmlErrorPtr error) static int errdetail_for_xml_code(int code) { - const char *det; - switch (code) { case XML_ERR_INVALID_CHAR: - det = gettext_noop("Invalid character value."); - break; + return errdetail("Invalid character value."); case XML_ERR_SPACE_REQUIRED: - det = gettext_noop("Space required."); - break; + return errdetail("Space required."); case XML_ERR_STANDALONE_VALUE: - det = gettext_noop("standalone accepts only 'yes' or 'no'."); - break; + return errdetail("standalone accepts only 'yes' or 'no'."); case XML_ERR_VERSION_MISSING: - det = gettext_noop("Malformed declaration: missing version."); - break; + return errdetail("Malformed declaration: missing version."); case XML_ERR_MISSING_ENCODING: - det = gettext_noop("Missing encoding in text declaration."); - break; + return errdetail("Missing encoding in text declaration."); case XML_ERR_XMLDECL_NOT_FINISHED: - det = gettext_noop("Parsing XML declaration: '?>' expected."); - break; + return errdetail("Parsing XML declaration: '?>' expected."); default: - det = gettext_noop("Unrecognized libxml error code: %d."); - break; + return errdetail("Unrecognized libxml error code: %d.", code); } - - return errdetail(det, code); } diff --git a/src/backend/utils/misc/guc_funcs.c b/src/backend/utils/misc/guc_funcs.c index b137bf08e56..75c2d5c73f8 100644 --- a/src/backend/utils/misc/guc_funcs.c +++ b/src/backend/utils/misc/guc_funcs.c @@ -618,14 +618,27 @@ ConfigOptionIsVisible(const struct config_generic *conf) return true; } +static char * +guc_print_int(int val, int flags) +{ + if (flags & GUC_SHOW_IN_OCTAL) + return psprintf("0%03o", val); + else + return psprintf("%d", val); +} + +static char * +guc_print_real(double val) +{ + return psprintf("%g", val); +} + /* * Extract fields to show in pg_settings for given variable. */ static void GetConfigOptionValues(const struct config_generic *conf, const char **values) { - char buffer[256]; - /* first get the generic attributes */ /* name */ @@ -682,32 +695,21 @@ GetConfigOptionValues(const struct config_generic *conf, const char **values) case PGC_INT: { const struct config_int *lconf = &conf->_int; - const char *fmt; - - /* choose display format */ - if (conf->flags & GUC_SHOW_IN_OCTAL) - fmt = "0%03o"; - else - fmt = "%d"; /* min_val */ - snprintf(buffer, sizeof(buffer), fmt, lconf->min); - values[9] = pstrdup(buffer); + values[9] = guc_print_int(lconf->min, conf->flags); /* max_val */ - snprintf(buffer, sizeof(buffer), fmt, lconf->max); - values[10] = pstrdup(buffer); + values[10] = guc_print_int(lconf->max, conf->flags); /* enumvals */ values[11] = NULL; /* boot_val */ - snprintf(buffer, sizeof(buffer), fmt, lconf->boot_val); - values[12] = pstrdup(buffer); + values[12] = guc_print_int(lconf->boot_val, conf->flags); /* reset_val */ - snprintf(buffer, sizeof(buffer), fmt, lconf->reset_val); - values[13] = pstrdup(buffer); + values[13] = guc_print_int(lconf->reset_val, conf->flags); } break; @@ -716,23 +718,19 @@ GetConfigOptionValues(const struct config_generic *conf, const char **values) const struct config_real *lconf = &conf->_real; /* min_val */ - snprintf(buffer, sizeof(buffer), "%g", lconf->min); - values[9] = pstrdup(buffer); + values[9] = guc_print_real(lconf->min); /* max_val */ - snprintf(buffer, sizeof(buffer), "%g", lconf->max); - values[10] = pstrdup(buffer); + values[10] = guc_print_real(lconf->max); /* enumvals */ values[11] = NULL; /* boot_val */ - snprintf(buffer, sizeof(buffer), "%g", lconf->boot_val); - values[12] = pstrdup(buffer); + values[12] = guc_print_real(lconf->boot_val); /* reset_val */ - snprintf(buffer, sizeof(buffer), "%g", lconf->reset_val); - values[13] = pstrdup(buffer); + values[13] = guc_print_real(lconf->reset_val); } break; @@ -825,8 +823,7 @@ GetConfigOptionValues(const struct config_generic *conf, const char **values) has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS)) { values[14] = conf->sourcefile; - snprintf(buffer, sizeof(buffer), "%d", conf->sourceline); - values[15] = pstrdup(buffer); + values[15] = psprintf("%d", conf->sourceline); } else { diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c index 06c43fd6942..18b58b0250f 100644 --- a/src/bin/pgbench/pgbench.c +++ b/src/bin/pgbench/pgbench.c @@ -5039,14 +5039,11 @@ static void initPopulateTable(PGconn *con, const char *table, int64 base, initRowMethod init_row) { - int n; int64 k; int chars = 0; int prev_chars = 0; PGresult *res; PQExpBufferData sql; - char copy_statement[256]; - const char *copy_statement_fmt = "copy %s from stdin"; int64 total = base * scale; /* used to track elapsed time and estimate of the remaining time */ @@ -5061,21 +5058,18 @@ initPopulateTable(PGconn *con, const char *table, int64 base, /* Use COPY with FREEZE on v14 and later for all ordinary tables */ if ((PQserverVersion(con) >= 140000) && get_table_relkind(con, table) == RELKIND_RELATION) - copy_statement_fmt = "copy %s from stdin with (freeze on)"; - - - n = pg_snprintf(copy_statement, sizeof(copy_statement), copy_statement_fmt, table); - if (n >= sizeof(copy_statement)) - pg_fatal("invalid buffer size: must be at least %d characters long", n); - else if (n == -1) - pg_fatal("invalid format string"); + printfPQExpBuffer(&sql, "copy %s from stdin with (freeze on)", table); + else + printfPQExpBuffer(&sql, "copy %s from stdin", table); - res = PQexec(con, copy_statement); + res = PQexec(con, sql.data); if (PQresultStatus(res) != PGRES_COPY_IN) pg_fatal("unexpected copy in result: %s", PQerrorMessage(con)); PQclear(res); + resetPQExpBuffer(&sql); + start = pg_time_now(); for (k = 0; k < total; k++) diff --git a/src/interfaces/ecpg/ecpglib/misc.c b/src/interfaces/ecpg/ecpglib/misc.c index 354a2e731fc..44a670452a6 100644 --- a/src/interfaces/ecpg/ecpglib/misc.c +++ b/src/interfaces/ecpg/ecpglib/misc.c @@ -231,10 +231,6 @@ ECPGdebug(int n, FILE *dbgs) void ecpg_log(const char *format, ...) { - va_list ap; - const char *intl_format; - int bufsize; - char *fmt; struct sqlca_t *sqlca; /* @@ -245,23 +241,6 @@ ecpg_log(const char *format, ...) if (!simple_debug) return; - /* localize the error message string */ - intl_format = ecpg_gettext(format); - - /* - * Insert PID into the format, unless ecpg_internal_regression_mode is set - * (regression tests want unchanging output). - */ - bufsize = strlen(intl_format) + 100; - fmt = (char *) malloc(bufsize); - if (fmt == NULL) - return; - - if (ecpg_internal_regression_mode) - snprintf(fmt, bufsize, "[NO_PID]: %s", intl_format); - else - snprintf(fmt, bufsize, "[%d]: %s", (int) getpid(), intl_format); - sqlca = ECPGget_sqlca(); pthread_mutex_lock(&debug_mutex); @@ -269,8 +248,19 @@ ecpg_log(const char *format, ...) /* Now that we hold the mutex, recheck simple_debug */ if (simple_debug) { + va_list ap; + + /* + * Print PID, unless ecpg_internal_regression_mode is set (regression + * tests want unchanging output). + */ + if (ecpg_internal_regression_mode) + fprintf(debugstream, "[NO_PID]: "); + else + fprintf(debugstream, "[%d]: ", (int) getpid()); + va_start(ap, format); - vfprintf(debugstream, fmt, ap); + vfprintf(debugstream, ecpg_gettext(format), ap); va_end(ap); /* dump out internal sqlca variables */ @@ -284,8 +274,6 @@ ecpg_log(const char *format, ...) } pthread_mutex_unlock(&debug_mutex); - - free(fmt); } void diff --git a/src/interfaces/libpq-oauth/oauth-curl.c b/src/interfaces/libpq-oauth/oauth-curl.c index 9e0d39773e5..cf88dc2f990 100644 --- a/src/interfaces/libpq-oauth/oauth-curl.c +++ b/src/interfaces/libpq-oauth/oauth-curl.c @@ -516,8 +516,6 @@ struct oauth_parse static void report_type_mismatch(struct oauth_parse *ctx) { - char *msgfmt; - Assert(ctx->active); /* @@ -527,23 +525,21 @@ report_type_mismatch(struct oauth_parse *ctx) switch (ctx->active->type) { case JSON_TOKEN_STRING: - msgfmt = gettext_noop("field \"%s\" must be a string"); + oauth_parse_set_error(ctx, "field \"%s\" must be a string", ctx->active->name); break; case JSON_TOKEN_NUMBER: - msgfmt = gettext_noop("field \"%s\" must be a number"); + oauth_parse_set_error(ctx, "field \"%s\" must be a number", ctx->active->name); break; case JSON_TOKEN_ARRAY_START: - msgfmt = gettext_noop("field \"%s\" must be an array of strings"); + oauth_parse_set_error(ctx, "field \"%s\" must be an array of strings", ctx->active->name); break; default: Assert(false); - msgfmt = gettext_noop("field \"%s\" has unexpected type"); + oauth_parse_set_error_internal(ctx, "field \"%s\" has unexpected type", ctx->active->name); } - - oauth_parse_set_error(ctx, msgfmt, ctx->active->name); } static JsonParseErrorType diff --git a/src/interfaces/libpq/fe-print.c b/src/interfaces/libpq/fe-print.c index c4c709bc3e4..84170a5dddb 100644 --- a/src/interfaces/libpq/fe-print.c +++ b/src/interfaces/libpq/fe-print.c @@ -710,17 +710,11 @@ PQprintTuples(const PGresult *res, int nTups; int i, j; - char formatString[80]; char *tborder = NULL; nFields = PQnfields(res); nTups = PQntuples(res); - if (colWidth > 0) - sprintf(formatString, "%%s %%-%ds", colWidth); - else - sprintf(formatString, "%%s %%s"); - if (nFields > 0) { /* only print rows with at least 1 field. */ @@ -745,9 +739,15 @@ PQprintTuples(const PGresult *res, { if (PrintAttNames) { - fprintf(fout, formatString, - TerseOutput ? "" : "|", - PQfname(res, i)); + if (colWidth > 0) + fprintf(fout, "%s %-*s", + TerseOutput ? "" : "|", + colWidth, + PQfname(res, i)); + else + fprintf(fout, "%s %s", + TerseOutput ? "" : "|", + PQfname(res, i)); } } @@ -765,9 +765,15 @@ PQprintTuples(const PGresult *res, { const char *pval = PQgetvalue(res, i, j); - fprintf(fout, formatString, - TerseOutput ? "" : "|", - pval ? pval : ""); + if (colWidth > 0) + fprintf(fout, "%s %-*s", + TerseOutput ? "" : "|", + colWidth, + pval ? pval : ""); + else + fprintf(fout, "%s %s", + TerseOutput ? "" : "|", + pval ? pval : ""); } if (TerseOutput) fprintf(fout, "\n"); diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c index 13944701bc7..e4f2ccb79f5 100644 --- a/src/test/regress/pg_regress.c +++ b/src/test/regress/pg_regress.c @@ -2435,22 +2435,22 @@ regression_main(int argc, char *argv[], else { #ifndef WIN32 - const char *copycmd = "cp -RPp \"%s\" \"%s/data\""; - int expected_exitcode = 0; +#define COPYCMD "cp -RPp \"%s\" \"%s/data\"" +#define COPYCMD_EXPECTED_EXITCODE 0 #else - const char *copycmd = "robocopy /E /NJS /NJH /NFL /NDL /NP \"%s\" \"%s/data\""; - int expected_exitcode = 1; /* 1 denotes files were copied */ +#define COPYCMD "robocopy /E /NJS /NJH /NFL /NDL /NP \"%s\" \"%s/data\"" +#define COPYCMD_EXPECTED_EXITCODE 1 /* 1 denotes files were copied */ #endif note("initializing database system by copying initdb template"); appendStringInfo(&cmd, - copycmd, + COPYCMD, initdb_template_dir, temp_instance); appendStringInfo(&cmd, " > \"%s/log/initdb.log\" 2>&1", outputdir); fflush(NULL); - if (system(cmd.data) != expected_exitcode) + if (system(cmd.data) != COPYCMD_EXPECTED_EXITCODE) { bail("copying of initdb template failed\n" "# Examine \"%s/log/initdb.log\" for the reason.\n" -- 2.56.0