From b05d3ae1edf557e174f80624219854767963dc66 Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Tue, 22 Jul 2003 19:00:12 +0000 Subject: [PATCH] Error message editing in backend/libpq, backend/postmaster, backend/tcop. Along the way, fix some logic problems in pgstat_initstats, notably the bogus assumption that malloc returns zeroed memory. --- doc/src/sgml/sources.sgml | 9 +- src/backend/commands/alter.c | 35 +-- src/backend/commands/copy.c | 4 +- src/backend/libpq/auth.c | 156 ++++++---- src/backend/libpq/be-fsstubs.c | 75 +++-- src/backend/libpq/be-secure.c | 59 +++- src/backend/libpq/crypt.c | 6 +- src/backend/libpq/hba.c | 319 +++++++++++--------- src/backend/libpq/pqcomm.c | 120 +++++--- src/backend/libpq/pqformat.c | 30 +- src/backend/postmaster/pgstat.c | 418 ++++++++++++++------------ src/backend/postmaster/postmaster.c | 250 +++++++++------ src/backend/tcop/dest.c | 8 +- src/backend/tcop/fastpath.c | 83 +++-- src/backend/tcop/postgres.c | 233 +++++++++----- src/backend/tcop/pquery.c | 37 ++- src/backend/tcop/utility.c | 158 ++++++---- src/backend/utils/error/elog.c | 38 ++- src/include/tcop/utility.h | 4 +- src/include/utils/elog.h | 13 +- src/test/regress/expected/portals.out | 4 +- 21 files changed, 1249 insertions(+), 810 deletions(-) diff --git a/doc/src/sgml/sources.sgml b/doc/src/sgml/sources.sgml index 18fd7597de0..57a587e24fd 100644 --- a/doc/src/sgml/sources.sgml +++ b/doc/src/sgml/sources.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/sources.sgml,v 2.9 2003/07/18 23:20:32 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/sources.sgml,v 2.10 2003/07/22 19:00:07 tgl Exp $ --> <chapter id="source"> @@ -234,6 +234,13 @@ less -x4 primary error message text. </para> </listitem> + <listitem> + <para> + <function>errcode_for_socket_access</>() is a convenience function that + selects an appropriate SQLSTATE error identifier for a failure in a + socket-related system call. + </para> + </listitem> </itemizedlist> </para> diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c index c90a84b68f6..7c49e40d5cb 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/alter.c,v 1.2 2003/07/20 21:56:32 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/alter.c,v 1.3 2003/07/22 19:00:07 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -29,41 +29,12 @@ #include "commands/user.h" #include "miscadmin.h" #include "parser/parse_clause.h" +#include "tcop/utility.h" #include "utils/acl.h" #include "utils/lsyscache.h" #include "utils/syscache.h" -static void -CheckOwnership(RangeVar *rel, bool noCatalogs) -{ - Oid relOid; - HeapTuple tuple; - - relOid = RangeVarGetRelid(rel, false); - tuple = SearchSysCache(RELOID, - ObjectIdGetDatum(relOid), - 0, 0, 0); - if (!HeapTupleIsValid(tuple)) /* should not happen */ - elog(ERROR, "cache lookup failed for relation %u", relOid); - - if (!pg_class_ownercheck(relOid, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, rel->relname); - - if (noCatalogs) - { - if (!allowSystemTableMods && - IsSystemClass((Form_pg_class) GETSTRUCT(tuple))) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("relation \"%s\" is a system catalog", - rel->relname))); - } - - ReleaseSysCache(tuple); -} - - void ExecRenameStmt(RenameStmt *stmt) { @@ -111,7 +82,7 @@ ExecRenameStmt(RenameStmt *stmt) { Oid relid; - CheckOwnership(stmt->relation, true); + CheckRelationOwnership(stmt->relation, true); relid = RangeVarGetRelid(stmt->relation, false); diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 07b52d9201f..976fdaa8616 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.203 2003/07/21 17:04:58 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.204 2003/07/22 19:00:07 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1923,7 +1923,7 @@ CopyReadBinaryAttribute(int column_no, FmgrInfo *flinfo, Oid typelem, /* Trouble if it didn't eat the whole buffer */ if (attribute_buf.cursor != attribute_buf.len) ereport(ERROR, - (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), + (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("incorrect binary data format in field %d", column_no))); diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index 080b025ce2f..ca6bfcf4d7e 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.103 2003/06/25 01:19:47 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.104 2003/07/22 19:00:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -109,20 +109,22 @@ pg_krb4_recvauth(Port *port) version); if (status != KSUCCESS) { - elog(LOG, "pg_krb4_recvauth: kerberos error: %s", - krb_err_txt[status]); + ereport(LOG, + (errmsg("kerberos error: %s", krb_err_txt[status]))); return STATUS_ERROR; } if (strncmp(version, PG_KRB4_VERSION, KRB_SENDAUTH_VLEN) != 0) { - elog(LOG, "pg_krb4_recvauth: protocol version \"%s\" != \"%s\"", - version, PG_KRB4_VERSION); + ereport(LOG, + (errmsg("kerberos protocol version \"%s\" != \"%s\"", + version, PG_KRB4_VERSION))); return STATUS_ERROR; } if (strncmp(port->user_name, auth_data.pname, SM_DATABASE_USER) != 0) { - elog(LOG, "pg_krb4_recvauth: name \"%s\" != \"%s\"", - port->user_name, auth_data.pname); + ereport(LOG, + (errmsg("kerberos user name \"%s\" != \"%s\"", + port->user_name, auth_data.pname))); return STATUS_ERROR; } return STATUS_OK; @@ -133,7 +135,9 @@ pg_krb4_recvauth(Port *port) static int pg_krb4_recvauth(Port *port) { - elog(LOG, "pg_krb4_recvauth: Kerberos not implemented on this server"); + ereport(LOG, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("kerberos v4 not implemented on this server"))); return STATUS_ERROR; } #endif /* KRB4 */ @@ -193,8 +197,9 @@ pg_krb5_init(void) retval = krb5_init_context(&pg_krb5_context); if (retval) { - elog(LOG, "pg_krb5_init: krb5_init_context returned Kerberos error %d", - retval); + ereport(LOG, + (errmsg("kerberos init returned error %d", + retval))); com_err("postgres", retval, "while initializing krb5"); return STATUS_ERROR; } @@ -202,9 +207,10 @@ pg_krb5_init(void) retval = krb5_kt_resolve(pg_krb5_context, pg_krb_server_keyfile, &pg_krb5_keytab); if (retval) { - elog(LOG, "pg_krb5_init: krb5_kt_resolve returned Kerberos error %d", - retval); - com_err("postgres", retval, "while resolving keytab file %s", + ereport(LOG, + (errmsg("kerberos keytab resolve returned error %d", + retval))); + com_err("postgres", retval, "while resolving keytab file \"%s\"", pg_krb_server_keyfile); krb5_free_context(pg_krb5_context); return STATUS_ERROR; @@ -214,10 +220,11 @@ pg_krb5_init(void) KRB5_NT_SRV_HST, &pg_krb5_server); if (retval) { - elog(LOG, "pg_krb5_init: krb5_sname_to_principal returned Kerberos error %d", - retval); + ereport(LOG, + (errmsg("kerberos sname_to_principal(\"%s\") returned error %d", + PG_KRB_SRVNAM, retval))); com_err("postgres", retval, - "while getting server principal for service %s", + "while getting server principal for service \"%s\"", PG_KRB_SRVNAM); krb5_kt_close(pg_krb5_context, pg_krb5_keytab); krb5_free_context(pg_krb5_context); @@ -258,8 +265,9 @@ pg_krb5_recvauth(Port *port) pg_krb5_server, 0, pg_krb5_keytab, &ticket); if (retval) { - elog(LOG, "pg_krb5_recvauth: krb5_recvauth returned Kerberos error %d", - retval); + ereport(LOG, + (errmsg("kerberos recvauth returned error %d", + retval))); com_err("postgres", retval, "from krb5_recvauth"); return STATUS_ERROR; } @@ -282,8 +290,9 @@ pg_krb5_recvauth(Port *port) #endif if (retval) { - elog(LOG, "pg_krb5_recvauth: krb5_unparse_name returned Kerberos error %d", - retval); + ereport(LOG, + (errmsg("kerberos unparse_name returned error %d", + retval))); com_err("postgres", retval, "while unparsing client name"); krb5_free_ticket(pg_krb5_context, ticket); krb5_auth_con_free(pg_krb5_context, auth_context); @@ -293,8 +302,9 @@ pg_krb5_recvauth(Port *port) kusername = pg_an_to_ln(kusername); if (strncmp(port->user_name, kusername, SM_DATABASE_USER)) { - elog(LOG, "pg_krb5_recvauth: user name \"%s\" != krb5 name \"%s\"", - port->user_name, kusername); + ereport(LOG, + (errmsg("kerberos user name \"%s\" != \"%s\"", + port->user_name, kusername))); ret = STATUS_ERROR; } else @@ -312,7 +322,9 @@ pg_krb5_recvauth(Port *port) static int pg_krb5_recvauth(Port *port) { - elog(LOG, "pg_krb5_recvauth: Kerberos not implemented on this server"); + ereport(LOG, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("kerberos v5 not implemented on this server"))); return STATUS_ERROR; } #endif /* KRB5 */ @@ -377,8 +389,10 @@ auth_failed(Port *port, int status) #endif /* USE_PAM */ } - elog(FATAL, "%s authentication failed for user \"%s\"", - authmethod, port->user_name); + ereport(FATAL, + (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), + errmsg("%s authentication failed for user \"%s\"", + authmethod, port->user_name))); /* doesn't return */ } @@ -399,7 +413,10 @@ ClientAuthentication(Port *port) * an error message into the postmaster logfile if it failed. */ if (hba_getauthmethod(port) != STATUS_OK) - elog(FATAL, "Missing or erroneous pg_hba.conf file, see postmaster log for details"); + ereport(FATAL, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("missing or erroneous pg_hba.conf file"), + errhint("See postmaster log for details."))); switch (port->auth_method) { @@ -417,15 +434,16 @@ ClientAuthentication(Port *port) { char hostinfo[NI_MAXHOST]; - getnameinfo( - (struct sockaddr *)&port->raddr.addr, - port->raddr.salen, - hostinfo, sizeof(hostinfo), - NULL, 0, NI_NUMERICHOST); + getnameinfo((struct sockaddr *) &port->raddr.addr, + port->raddr.salen, + hostinfo, sizeof(hostinfo), + NULL, 0, + NI_NUMERICHOST); - elog(FATAL, - "No pg_hba.conf entry for host %s, user %s, database %s", - hostinfo, port->user_name, port->database_name); + ereport(FATAL, + (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), + errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\"", + hostinfo, port->user_name, port->database_name))); break; } @@ -433,10 +451,9 @@ ClientAuthentication(Port *port) /* Kerberos 4 only seems to work with AF_INET. */ if (port->raddr.addr.ss_family != AF_INET || port->laddr.addr.ss_family != AF_INET) - { - elog(FATAL, - "Unsupported protocol for Kerberos 4"); - } + ereport(FATAL, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("kerberos 4 only supports IPv4 connections"))); sendAuthRequest(port, AUTH_REQ_KRB4); status = pg_krb4_recvauth(port); break; @@ -466,7 +483,9 @@ ClientAuthentication(Port *port) int on = 1; if (setsockopt(port->sock, 0, LOCAL_CREDS, &on, sizeof(on)) < 0) - elog(FATAL, "pg_local_sendauth: can't do setsockopt: %m"); + ereport(FATAL, + (errcode_for_socket_access(), + errmsg("failed to enable credential receipt: %m"))); } #endif if (port->raddr.addr.ss_family == AF_UNIX) @@ -552,12 +571,14 @@ pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg, switch (msg[0]->msg_style) { case PAM_ERROR_MSG: - elog(LOG, "pam_passwd_conv_proc: Error from underlying PAM layer: '%s'", - msg[0]->msg); + ereport(LOG, + (errmsg("error from underlying PAM layer: %s", + msg[0]->msg))); return PAM_CONV_ERR; default: - elog(LOG, "pam_passwd_conv_proc: Unexpected PAM conversation %d/'%s'", - msg[0]->msg_style, msg[0]->msg); + ereport(LOG, + (errmsg("unsupported PAM conversation %d/%s", + msg[0]->msg_style, msg[0]->msg))); return PAM_CONV_ERR; } } @@ -587,7 +608,8 @@ pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg, if (strlen(passwd) == 0) { - elog(LOG, "pam_passwd_conv_proc: no password"); + ereport(LOG, + (errmsg("empty password returned by client"))); return PAM_CONV_ERR; } appdata_ptr = passwd; @@ -600,7 +622,9 @@ pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg, *resp = calloc(num_msg, sizeof(struct pam_response)); if (!*resp) { - elog(LOG, "pam_passwd_conv_proc: Out of memory!"); + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); return PAM_CONV_ERR; } @@ -644,8 +668,9 @@ CheckPAMAuth(Port *port, char *user, char *password) if (retval != PAM_SUCCESS) { - elog(LOG, "CheckPAMAuth: Failed to create PAM authenticator: '%s'", - pam_strerror(pamh, retval)); + ereport(LOG, + (errmsg("Failed to create PAM authenticator: %s", + pam_strerror(pamh, retval)))); pam_passwd = NULL; /* Unset pam_passwd */ return STATUS_ERROR; } @@ -654,8 +679,9 @@ CheckPAMAuth(Port *port, char *user, char *password) if (retval != PAM_SUCCESS) { - elog(LOG, "CheckPAMAuth: pam_set_item(PAM_USER) failed: '%s'", - pam_strerror(pamh, retval)); + ereport(LOG, + (errmsg("pam_set_item(PAM_USER) failed: %s", + pam_strerror(pamh, retval)))); pam_passwd = NULL; /* Unset pam_passwd */ return STATUS_ERROR; } @@ -664,8 +690,9 @@ CheckPAMAuth(Port *port, char *user, char *password) if (retval != PAM_SUCCESS) { - elog(LOG, "CheckPAMAuth: pam_set_item(PAM_CONV) failed: '%s'", - pam_strerror(pamh, retval)); + ereport(LOG, + (errmsg("pam_set_item(PAM_CONV) failed: %s", + pam_strerror(pamh, retval)))); pam_passwd = NULL; /* Unset pam_passwd */ return STATUS_ERROR; } @@ -674,8 +701,9 @@ CheckPAMAuth(Port *port, char *user, char *password) if (retval != PAM_SUCCESS) { - elog(LOG, "CheckPAMAuth: pam_authenticate failed: '%s'", - pam_strerror(pamh, retval)); + ereport(LOG, + (errmsg("pam_authenticate failed: %s", + pam_strerror(pamh, retval)))); pam_passwd = NULL; /* Unset pam_passwd */ return STATUS_ERROR; } @@ -684,8 +712,9 @@ CheckPAMAuth(Port *port, char *user, char *password) if (retval != PAM_SUCCESS) { - elog(LOG, "CheckPAMAuth: pam_acct_mgmt failed: '%s'", - pam_strerror(pamh, retval)); + ereport(LOG, + (errmsg("pam_acct_mgmt failed: %s", + pam_strerror(pamh, retval)))); pam_passwd = NULL; /* Unset pam_passwd */ return STATUS_ERROR; } @@ -694,8 +723,9 @@ CheckPAMAuth(Port *port, char *user, char *password) if (retval != PAM_SUCCESS) { - elog(LOG, "CheckPAMAuth: Failed to release PAM authenticator: '%s'", - pam_strerror(pamh, retval)); + ereport(LOG, + (errmsg("failed to release PAM authenticator: %s", + pam_strerror(pamh, retval)))); } pam_passwd = NULL; /* Unset pam_passwd */ @@ -730,7 +760,10 @@ recv_password_packet(Port *port) * the log. */ if (mtype != EOF) - elog(COMMERROR, "Expected password response, got %c", mtype); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("expected password response, got msg type %d", + mtype))); return NULL; /* EOF or bad message type */ } } @@ -755,10 +788,13 @@ recv_password_packet(Port *port) * StringInfo is guaranteed to have an appended '\0'. */ if (strlen(buf.data) + 1 != buf.len) - elog(COMMERROR, "bogus password packet size"); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("invalid password packet size"))); /* Do not echo password to logs, for security. */ - elog(DEBUG5, "received password packet"); + ereport(DEBUG5, + (errmsg("received password packet"))); /* * Return the received string. Note we do not attempt to do any diff --git a/src/backend/libpq/be-fsstubs.c b/src/backend/libpq/be-fsstubs.c index a560812a6e0..bdfac16f7c1 100644 --- a/src/backend/libpq/be-fsstubs.c +++ b/src/backend/libpq/be-fsstubs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/be-fsstubs.c,v 1.64 2003/05/27 17:49:46 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/be-fsstubs.c,v 1.65 2003/07/22 19:00:10 tgl Exp $ * * NOTES * This should be moved to a more appropriate place. It is here @@ -119,7 +119,9 @@ lo_close(PG_FUNCTION_ARGS) if (fd < 0 || fd >= cookies_size || cookies[fd] == NULL) { - elog(ERROR, "lo_close: invalid large obj descriptor (%d)", fd); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("invalid large-object descriptor: %d", fd))); PG_RETURN_INT32(-1); } #if FSDB @@ -155,7 +157,9 @@ lo_read(int fd, char *buf, int len) if (fd < 0 || fd >= cookies_size || cookies[fd] == NULL) { - elog(ERROR, "lo_read: invalid large obj descriptor (%d)", fd); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("invalid large-object descriptor: %d", fd))); return -1; } @@ -177,7 +181,9 @@ lo_write(int fd, char *buf, int len) if (fd < 0 || fd >= cookies_size || cookies[fd] == NULL) { - elog(ERROR, "lo_write: invalid large obj descriptor (%d)", fd); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("invalid large-object descriptor: %d", fd))); return -1; } @@ -203,7 +209,9 @@ lo_lseek(PG_FUNCTION_ARGS) if (fd < 0 || fd >= cookies_size || cookies[fd] == NULL) { - elog(ERROR, "lo_lseek: invalid large obj descriptor (%d)", fd); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("invalid large-object descriptor: %d", fd))); PG_RETURN_INT32(-1); } @@ -258,7 +266,9 @@ lo_tell(PG_FUNCTION_ARGS) if (fd < 0 || fd >= cookies_size || cookies[fd] == NULL) { - elog(ERROR, "lo_tell: invalid large object descriptor (%d)", fd); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("invalid large-object descriptor: %d", fd))); PG_RETURN_INT32(-1); } @@ -360,9 +370,10 @@ lo_import(PG_FUNCTION_ARGS) #ifndef ALLOW_DANGEROUS_LO_FUNCTIONS if (!superuser()) - elog(ERROR, "You must have Postgres superuser privilege to use " - "server-side lo_import().\n\tAnyone can use the " - "client-side lo_import() provided by libpq."); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be superuser to use server-side lo_import()"), + errhint("Anyone can use the client-side lo_import() provided by libpq."))); #endif /* @@ -375,16 +386,15 @@ lo_import(PG_FUNCTION_ARGS) fnamebuf[nbytes] = '\0'; fd = PathNameOpenFile(fnamebuf, O_RDONLY | PG_BINARY, 0666); if (fd < 0) - elog(ERROR, "lo_import: can't open unix file \"%s\": %m", - fnamebuf); + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not open server file \"%s\": %m", + fnamebuf))); /* - * create an inversion "object" + * create an inversion object */ lobj = inv_create(INV_READ | INV_WRITE); - if (lobj == NULL) - elog(ERROR, "lo_import: can't create inv object for \"%s\"", - fnamebuf); lobjOid = lobj->id; /* @@ -393,11 +403,15 @@ lo_import(PG_FUNCTION_ARGS) while ((nbytes = FileRead(fd, buf, BUFSIZE)) > 0) { tmp = inv_write(lobj, buf, nbytes); - if (tmp != nbytes) - elog(ERROR, "lo_import: error while reading \"%s\"", - fnamebuf); + Assert(tmp == nbytes); } + if (nbytes < 0) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not read server file \"%s\": %m", + fnamebuf))); + FileClose(fd); inv_close(lobj); @@ -423,17 +437,16 @@ lo_export(PG_FUNCTION_ARGS) #ifndef ALLOW_DANGEROUS_LO_FUNCTIONS if (!superuser()) - elog(ERROR, "You must have Postgres superuser privilege to use " - "server-side lo_export().\n\tAnyone can use the " - "client-side lo_export() provided by libpq."); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be superuser to use server-side lo_export()"), + errhint("Anyone can use the client-side lo_export() provided by libpq."))); #endif /* - * open the inversion "object" + * open the inversion object (no need to test for failure) */ lobj = inv_open(lobjId, INV_READ); - if (lobj == NULL) - elog(ERROR, "lo_export: can't open inv object %u", lobjId); /* * open the file to be written to @@ -451,8 +464,10 @@ lo_export(PG_FUNCTION_ARGS) fd = PathNameOpenFile(fnamebuf, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, 0666); umask(oumask); if (fd < 0) - elog(ERROR, "lo_export: can't open unix file \"%s\": %m", - fnamebuf); + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not create server file \"%s\": %m", + fnamebuf))); /* * read in from the inversion file and write to the Unix file @@ -461,12 +476,14 @@ lo_export(PG_FUNCTION_ARGS) { tmp = FileWrite(fd, buf, nbytes); if (tmp != nbytes) - elog(ERROR, "lo_export: error while writing \"%s\"", - fnamebuf); + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not write server file \"%s\": %m", + fnamebuf))); } - inv_close(lobj); FileClose(fd); + inv_close(lobj); PG_RETURN_INT32(1); } diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c index e4c8b060547..4d482ce73e0 100644 --- a/src/backend/libpq/be-secure.c +++ b/src/backend/libpq/be-secure.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/be-secure.c,v 1.35 2003/07/01 13:49:47 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/be-secure.c,v 1.36 2003/07/22 19:00:10 tgl Exp $ * * Since the server static private key ($DataDir/server.key) * will normally be stored unencrypted so that the database @@ -277,12 +277,18 @@ secure_read(Port *port, void *ptr, size_t len) goto rloop; case SSL_ERROR_SYSCALL: if (n == -1) - elog(COMMERROR, "SSL SYSCALL error: %m"); + ereport(COMMERROR, + (errcode_for_socket_access(), + errmsg("SSL SYSCALL error: %m"))); else - elog(COMMERROR, "SSL SYSCALL error: EOF detected"); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("SSL SYSCALL error: EOF detected"))); break; case SSL_ERROR_SSL: - elog(COMMERROR, "SSL error: %s", SSLerrmessage()); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("SSL error: %s", SSLerrmessage()))); /* fall through */ case SSL_ERROR_ZERO_RETURN: secure_close(port); @@ -290,7 +296,9 @@ secure_read(Port *port, void *ptr, size_t len) n = -1; break; default: - elog(COMMERROR, "Unknown SSL error code"); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("unrecognized SSL error code"))); break; } } @@ -317,15 +325,23 @@ secure_write(Port *port, void *ptr, size_t len) SSL_set_session_id_context(port->ssl, (void *) &SSL_context, sizeof(SSL_context)); if (SSL_renegotiate(port->ssl) <= 0) - elog(COMMERROR, "SSL renegotiation failure"); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("SSL renegotiation failure"))); if (SSL_do_handshake(port->ssl) <= 0) - elog(COMMERROR, "SSL renegotiation failure"); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("SSL renegotiation failure"))); if (port->ssl->state != SSL_ST_OK) - elog(COMMERROR, "SSL failed to send renegotiation request"); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("SSL failed to send renegotiation request"))); port->ssl->state |= SSL_ST_ACCEPT; SSL_do_handshake(port->ssl); if (port->ssl->state != SSL_ST_OK) - elog(COMMERROR, "SSL renegotiation failure"); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("SSL renegotiation failure"))); port->count = 0; } @@ -341,12 +357,18 @@ secure_write(Port *port, void *ptr, size_t len) goto wloop; case SSL_ERROR_SYSCALL: if (n == -1) - elog(COMMERROR, "SSL SYSCALL error: %m"); + ereport(COMMERROR, + (errcode_for_socket_access(), + errmsg("SSL SYSCALL error: %m"))); else - elog(COMMERROR, "SSL SYSCALL error: EOF detected"); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("SSL SYSCALL error: EOF detected"))); break; case SSL_ERROR_SSL: - elog(COMMERROR, "SSL error: %s", SSLerrmessage()); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("SSL error: %s", SSLerrmessage()))); /* fall through */ case SSL_ERROR_ZERO_RETURN: secure_close(port); @@ -354,7 +376,9 @@ secure_write(Port *port, void *ptr, size_t len) n = -1; break; default: - elog(COMMERROR, "Unknown SSL error code"); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("unrecognized SSL error code"))); break; } } @@ -419,7 +443,7 @@ load_dh_file(int keylength) (codes & DH_CHECK_P_NOT_SAFE_PRIME)) { elog(LOG, - "DH error (%s): neither suitable generator or safe prime", + "DH error (%s): neither suitable generator or safe prime", fnbuf); return NULL; } @@ -690,7 +714,10 @@ open_server_SSL(Port *port) !SSL_set_fd(port->ssl, port->sock) || SSL_accept(port->ssl) <= 0) { - elog(COMMERROR, "failed to initialize SSL connection: %s", SSLerrmessage()); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("failed to initialize SSL connection: %s", + SSLerrmessage()))); close_SSL(port); return -1; } @@ -712,7 +739,7 @@ open_server_SSL(Port *port) NID_commonName, port->peer_cn, sizeof(port->peer_cn)); port->peer_cn[sizeof(port->peer_cn) - 1] = '\0'; } - elog(DEBUG2, "secure connection from '%s'", port->peer_cn); + elog(DEBUG2, "secure connection from \"%s\"", port->peer_cn); /* set up debugging/info callback */ SSL_CTX_set_info_callback(SSL_context, info_cb); diff --git a/src/backend/libpq/crypt.c b/src/backend/libpq/crypt.c index 20eb510a767..c1443e56744 100644 --- a/src/backend/libpq/crypt.c +++ b/src/backend/libpq/crypt.c @@ -9,7 +9,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/libpq/crypt.c,v 1.53 2003/05/12 23:08:50 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/crypt.c,v 1.54 2003/07/22 19:00:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -58,8 +58,8 @@ md5_crypt_verify(const Port *port, const char *user, char *client_pass) /* We can't do crypt with pg_shadow MD5 passwords */ if (isMD5(shadow_pass) && port->auth_method == uaCrypt) { - elog(LOG, "Password is stored MD5 encrypted. " - "'crypt' auth method cannot be used."); + ereport(LOG, + (errmsg("cannot use CRYPT auth method because password is MD5-encrypted"))); return STATUS_ERROR; } diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index 3b623066241..955a1115909 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.104 2003/06/15 16:21:39 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.105 2003/07/22 19:00:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -124,7 +124,10 @@ next_token(FILE *fp, char *buf, const int bufsz) if (buf >= end_buf) { - elog(LOG, "Token too long in authentication file, skipping, %s", buf); + ereport(LOG, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("authentication file token too long, skipping: \"%s\"", + buf))); /* Discard remainder of line */ while ((c = getc(fp)) != EOF && c != '\n') ; @@ -257,8 +260,10 @@ tokenize_inc_file(const char *inc_filename) inc_file = AllocateFile(inc_fullname, "r"); if (!inc_file) { - elog(LOG, "tokenize_inc_file: Unable to open secondary authentication file \"@%s\" as \"%s\": %m", - inc_filename, inc_fullname); + ereport(LOG, + (errcode_for_file_access(), + errmsg("could not open secondary authentication file \"@%s\" as \"%s\": %m", + inc_filename, inc_fullname))); pfree(inc_fullname); /* return empty string, it matches nothing */ @@ -631,9 +636,7 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) /* Check if it has a CIDR suffix and if so isolate it */ cidr_slash = strchr(token,'/'); if (cidr_slash) - { *cidr_slash = '\0'; - } hints.ai_flags = AI_NUMERICHOST; hints.ai_family = PF_UNSPEC; @@ -646,13 +649,14 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) /* Get the IP address either way */ ret = getaddrinfo2(token, NULL, &hints, &file_ip_addr); - if (ret) + if (ret || !file_ip_addr) { - elog(LOG, "getaddrinfo2() returned %d", ret); + ereport(LOG, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("failed to interpret IP address \"%s\" in config file: %s", + token, gai_strerror(ret)))); if (cidr_slash) - { *cidr_slash = '/'; - } goto hba_syntax; } @@ -669,9 +673,7 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) *cidr_slash = '/'; if (SockAddr_cidr_mask(&mask, cidr_slash + 1, file_ip_addr->ai_family) < 0) - { - goto hba_syntax; - } + goto hba_syntax; } else { @@ -682,16 +684,13 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) token = lfirst(line); ret = getaddrinfo2(token, NULL, &hints, &file_ip_mask); - if (ret) - { + if (ret || !file_ip_mask) goto hba_syntax; - } + mask = (struct sockaddr_storage *)file_ip_mask->ai_addr; if(file_ip_addr->ai_family != mask->ss_family) - { goto hba_syntax; - } } /* Read the rest of the line. */ @@ -705,14 +704,11 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) /* Must meet network restrictions */ if (!rangeSockAddr(&port->raddr.addr, (struct sockaddr_storage *)file_ip_addr->ai_addr, mask)) - { goto hba_freeaddr; - } + freeaddrinfo2(hints.ai_family, file_ip_addr); if (file_ip_mask) - { freeaddrinfo2(hints.ai_family, file_ip_mask); - } } else goto hba_syntax; @@ -727,22 +723,24 @@ parse_hba(List *line, hbaPort *port, bool *found_p, bool *error_p) return; hba_syntax: - elog(LOG, "parse_hba: invalid syntax in pg_hba.conf file at line %d, token \"%s\"", - line_number, - line ? (const char *) lfirst(line) : "(end of line)"); + if (line) + ereport(LOG, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("invalid entry in pg_hba.conf file at line %d, token \"%s\"", + line_number, (const char *) lfirst(line)))); + else + ereport(LOG, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("missing entry in pg_hba.conf file at end of line %d", + line_number))); *error_p = true; hba_freeaddr: if (file_ip_addr) - { freeaddrinfo2(hints.ai_family, file_ip_addr); - } if (file_ip_mask) - { freeaddrinfo2(hints.ai_family, file_ip_mask); - } - return; } @@ -790,7 +788,9 @@ group_openfile(void) groupfile = AllocateFile(filename, "r"); if (groupfile == NULL && errno != ENOENT) - elog(LOG, "could not open %s: %m", filename); + ereport(LOG, + (errcode_for_file_access(), + errmsg("could not open \"%s\": %m", filename))); pfree(filename); @@ -812,7 +812,9 @@ user_openfile(void) pwdfile = AllocateFile(filename, "r"); if (pwdfile == NULL && errno != ENOENT) - elog(LOG, "could not open %s: %m", filename); + ereport(LOG, + (errcode_for_file_access(), + errmsg("could not open \"%s\": %m", filename))); pfree(filename); @@ -929,9 +931,10 @@ load_hba(void) file = AllocateFile(conf_file, "r"); if (file == NULL) - elog(FATAL, - "load_hba: Unable to open authentication config file \"%s\": %m", - conf_file); + ereport(FATAL, + (errcode_for_file_access(), + errmsg("could not open config file \"%s\": %m", + conf_file))); hba_lines = tokenize_file(file); FreeFile(file); @@ -989,12 +992,18 @@ parse_ident_usermap(List *line, const char *usermap_name, const char *pg_user, return; ident_syntax: - elog(LOG, "parse_ident_usermap: invalid syntax in pg_ident.conf file at line %d, token \"%s\"", - line_number, - line ? (const char *) lfirst(line) : "(end of line)"); + if (line) + ereport(LOG, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("invalid entry in pg_ident.conf file at line %d, token \"%s\"", + line_number, (const char *) lfirst(line)))); + else + ereport(LOG, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("missing entry in pg_ident.conf file at end of line %d", + line_number))); *error_p = true; - return; } @@ -1021,10 +1030,9 @@ check_ident_usermap(const char *usermap_name, if (usermap_name == NULL || usermap_name[0] == '\0') { - elog(LOG, "check_ident_usermap: hba configuration file does not " - "have the usermap field filled in in the entry that pertains " - "to this connection. That field is essential for Ident-based " - "authentication."); + ereport(LOG, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("cannot use IDENT authentication without usermap field"))); found_entry = false; } else if (strcmp(usermap_name, "sameuser") == 0) @@ -1070,9 +1078,10 @@ load_ident(void) file = AllocateFile(map_file, "r"); if (file == NULL) { - /* The open of the map file failed. */ - elog(LOG, "load_ident: Unable to open usermap file \"%s\": %m", - map_file); + ereport(LOG, + (errcode_for_file_access(), + errmsg("could not open usermap file \"%s\": %m", + map_file))); } else { @@ -1192,18 +1201,22 @@ ident_inet(const SockAddr remote_addr, char local_addr_s[NI_MAXHOST]; char local_port[NI_MAXSERV]; char ident_port[NI_MAXSERV]; + char ident_query[80]; + char ident_response[80 + IDENT_USERNAME_MAX]; struct addrinfo *ident_serv = NULL, *la = NULL, hints; - /* Might look a little weird to first convert it to text and - * then back to sockaddr, but it's protocol indepedant. */ - getnameinfo((struct sockaddr *)&remote_addr.addr, - remote_addr.salen, remote_addr_s, sizeof(remote_addr_s), - remote_port, sizeof(remote_port), - NI_NUMERICHOST|NI_NUMERICSERV); - getnameinfo((struct sockaddr *)&local_addr.addr, - local_addr.salen, local_addr_s, sizeof(local_addr_s), - local_port, sizeof(local_port), - NI_NUMERICHOST|NI_NUMERICSERV); + /* + * Might look a little weird to first convert it to text and + * then back to sockaddr, but it's protocol independent. + */ + getnameinfo((struct sockaddr *)&remote_addr.addr, remote_addr.salen, + remote_addr_s, sizeof(remote_addr_s), + remote_port, sizeof(remote_port), + NI_NUMERICHOST | NI_NUMERICSERV); + getnameinfo((struct sockaddr *)&local_addr.addr, local_addr.salen, + local_addr_s, sizeof(local_addr_s), + local_port, sizeof(local_port), + NI_NUMERICHOST | NI_NUMERICSERV); snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT); hints.ai_flags = AI_NUMERICHOST; @@ -1214,94 +1227,104 @@ ident_inet(const SockAddr remote_addr, hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; - getaddrinfo2(remote_addr_s, ident_port, &hints, &ident_serv); - getaddrinfo2(local_addr_s, NULL, &hints, &la); + rc = getaddrinfo2(remote_addr_s, ident_port, &hints, &ident_serv); + if (rc || !ident_serv) + return false; /* we don't expect this to happen */ + + hints.ai_flags = AI_NUMERICHOST; + hints.ai_family = local_addr.addr.ss_family; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + hints.ai_addrlen = 0; + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + rc = getaddrinfo2(local_addr_s, NULL, &hints, &la); + if (rc || !la) + return false; /* we don't expect this to happen */ sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype, - ident_serv->ai_protocol); - - if (sock_fd == -1) + ident_serv->ai_protocol); + if (sock_fd < 0) { - elog(LOG, "Failed to create socket on which to talk to Ident server: %m"); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("could not create socket for IDENT connection: %m"))); ident_return = false; + goto ident_inet_done; } - else + /* + * Bind to the address which the client originally contacted, + * otherwise the ident server won't be able to match up the right + * connection. This is necessary if the PostgreSQL server is + * running on an IP alias. + */ + rc = bind(sock_fd, la->ai_addr, la->ai_addrlen); + if (rc != 0) { - /* - * Bind to the address which the client originally contacted, - * otherwise the ident server won't be able to match up the right - * connection. This is necessary if the PostgreSQL server is - * running on an IP alias. - */ + ereport(LOG, + (errcode_for_socket_access(), + errmsg("could not bind to local address \"%s\": %m", + local_addr_s))); + ident_return = false; + goto ident_inet_done; + } - rc = bind(sock_fd, la->ai_addr, la->ai_addrlen); - if (rc == 0) - { - rc = connect(sock_fd, ident_serv->ai_addr, - ident_serv->ai_addrlen); - } - if (rc != 0) - { - int save_errno = errno; + rc = connect(sock_fd, ident_serv->ai_addr, + ident_serv->ai_addrlen); + if (rc != 0) + { + ereport(LOG, + (errcode_for_socket_access(), + errmsg("could not connect to IDENT server at address \"%s\", port %s): %m", + remote_addr_s, ident_port))); + ident_return = false; + goto ident_inet_done; + } - elog(LOG, "Unable to connect to Ident server on the host which is " - "trying to connect to Postgres " - "(Address %s, Port %s): %s", remote_addr_s, - ident_port, strerror(save_errno)); - ident_return = false; - } - else - { - char ident_query[80]; + /* The query we send to the Ident server */ + snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n", + remote_port, local_port); - /* The query we send to the Ident server */ - snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n", - remote_port, local_port); - /* loop in case send is interrupted */ - do - { - rc = send(sock_fd, ident_query, strlen(ident_query), 0); - } while (rc < 0 && errno == EINTR); - if (rc < 0) - { - int save_errno = errno; + /* loop in case send is interrupted */ + do + { + rc = send(sock_fd, ident_query, strlen(ident_query), 0); + } while (rc < 0 && errno == EINTR); - elog(LOG, "Unable to send query to Ident server on the host which is " - "trying to connect to Postgres (Host %s, Port %s), " - "even though we successfully connected to it: %s", - remote_addr_s, ident_port, strerror(save_errno)); - ident_return = false; - } - else - { - char ident_response[80 + IDENT_USERNAME_MAX]; + if (rc < 0) + { + ereport(LOG, + (errcode_for_socket_access(), + errmsg("could not send query to IDENT server at address \"%s\", port %s): %m", + remote_addr_s, ident_port))); + ident_return = false; + goto ident_inet_done; + } - rc = recv(sock_fd, ident_response, - sizeof(ident_response) - 1, 0); - if (rc < 0) - { - int save_errno = errno; - - elog(LOG, "Unable to receive response from Ident server " - "on the host which is " - "trying to connect to Postgres (Host %s, Port %s), " - "even though we successfully sent our query to it: %s", - remote_addr_s, ident_port, - strerror(save_errno)); - ident_return = false; - } - else - { - ident_response[rc] = '\0'; - ident_return = interpret_ident_response(ident_response, - ident_user); - } - } - closesocket(sock_fd); - } + do + { + rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0); + } while (rc < 0 && errno == EINTR); + + if (rc < 0) + { + ereport(LOG, + (errcode_for_socket_access(), + errmsg("could not receive response from IDENT server at address \"%s\", port %s): %m", + remote_addr_s, ident_port))); + ident_return = false; + goto ident_inet_done; } - freeaddrinfo2(hints.ai_family, la); - freeaddrinfo2(hints.ai_family, ident_serv); + + ident_response[rc] = '\0'; + ident_return = interpret_ident_response(ident_response, ident_user); + +ident_inet_done: + if (sock_fd >= 0) + closesocket(sock_fd); + freeaddrinfo2(remote_addr.addr.ss_family, ident_serv); + freeaddrinfo2(local_addr.addr.ss_family, la); return ident_return; } @@ -1325,7 +1348,9 @@ ident_unix(int sock, char *ident_user) if (getpeereid(sock,&uid,&gid) != 0) { /* We didn't get a valid credentials struct. */ - elog(LOG, "ident_unix: error receiving credentials: %m"); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("could not receive credentials: %m"))); return false; } @@ -1333,8 +1358,9 @@ ident_unix(int sock, char *ident_user) if (pass == NULL) { - elog(LOG, "ident_unix: unknown local user with uid %d", - (int) uid); + ereport(LOG, + (errmsg("local user with uid %d is not known to getpwuid", + (int) uid))); return false; } @@ -1353,7 +1379,9 @@ ident_unix(int sock, char *ident_user) so_len != sizeof(peercred)) { /* We didn't get a valid credentials struct. */ - elog(LOG, "ident_unix: error receiving credentials: %m"); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("could not receive credentials: %m"))); return false; } @@ -1361,8 +1389,9 @@ ident_unix(int sock, char *ident_user) if (pass == NULL) { - elog(LOG, "ident_unix: unknown local user with uid %d", - (int) peercred.uid); + ereport(LOG, + (errmsg("local user with uid %d is not known to getpwuid", + (int) peercred.uid); return false; } @@ -1418,17 +1447,21 @@ ident_unix(int sock, char *ident_user) cmsg->cmsg_len < sizeof(cmsgmem) || cmsg->cmsg_type != SCM_CREDS) { - elog(LOG, "ident_unix: error receiving credentials: %m"); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("could not receive credentials: %m"))); return false; } cred = (Cred *) CMSG_DATA(cmsg); pw = getpwuid(cred->cruid); + if (pw == NULL) { - elog(LOG, "ident_unix: unknown local user with uid %d", - (int) cred->cruid); + ereport(LOG, + (errmsg("local user with uid %d is not known to getpwuid", + (int) cred->cruid); return false; } @@ -1437,7 +1470,9 @@ ident_unix(int sock, char *ident_user) return true; #else - elog(LOG, "'ident' auth is not supported on local connections on this platform"); + ereport(LOG, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("IDENT auth is not supported on local connections on this platform"))); return false; #endif diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index 2cd2c9223f7..7f3013925ae 100644 --- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -10,7 +10,7 @@ * Unfortunately, COPY OUT was designed to commandeer the communication * channel (it just transfers data without wrapping it into messages). * No other messages can be sent while COPY OUT is in progress; and if the - * copy is aborted by an elog(ERROR), we need to close out the copy so that + * copy is aborted by an ereport(ERROR), we need to close out the copy so that * the frontend gets back into sync. Therefore, these routines have to be * aware of COPY OUT state. (New COPY-OUT is message-based and does *not* * set the DoingCopyOut flag.) @@ -20,8 +20,8 @@ * to send. Instead, use the routines in pqformat.c to construct the message * in a buffer and then emit it in one call to pq_putmessage. This ensures * that the channel will not be clogged by an incomplete message if execution - * is aborted by elog(ERROR) partway through the message. The only non-libpq - * code that should call pq_putbytes directly is old-style COPY OUT. + * is aborted by ereport(ERROR) partway through the message. The only + * non-libpq code that should call pq_putbytes directly is old-style COPY OUT. * * At one time, libpq was shared between frontend and backend, but now * the backend's "backend/libpq" is quite separate from "interfaces/libpq". @@ -30,7 +30,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.157 2003/06/12 07:36:51 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.158 2003/07/22 19:00:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -237,8 +237,9 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, ret = getaddrinfo2(hostName, service, &hint, &addrs); if (ret || addrs == NULL) { - elog(LOG, "server socket failure: getaddrinfo2(): %s", - gai_strerror(ret)); + ereport(LOG, + (errmsg("failed to translate hostname to address: %s", + gai_strerror(ret)))); freeaddrinfo2(hint.ai_family, addrs); return STATUS_ERROR; } @@ -269,8 +270,9 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, if ((fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol)) < 0) { - elog(LOG, "server socket failure: socket(): %s", - strerror(errno)); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("failed to create socket: %m"))); continue; } @@ -281,9 +283,9 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one))) == -1) { - elog(LOG, "server socket failure: " - "setsockopt(SO_REUSEADDR): %s", - strerror(errno)); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("setsockopt(SO_REUSEADDR) failed: %m"))); closesocket(fd); continue; } @@ -295,9 +297,9 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) == -1) { - elog(LOG, "server socket failure: " - "setsockopt(IPV6_V6ONLY): %s", - strerror(errno)); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("setsockopt(IPV6_V6ONLY) failed: %m"))); closesocket(fd); continue; } @@ -313,19 +315,16 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, err = bind(fd, addr->ai_addr, addr->ai_addrlen); if (err < 0) { - elog(LOG, "server socket failure: bind(): %s\n" - "\tIs another postmaster already running on " - "port %d?", strerror(errno), (int) portNumber); - if (addr->ai_family == AF_UNIX) - { - elog(LOG, "\tIf not, remove socket node (%s) " - "and retry.", sock_path); - } - else - { - elog(LOG, "\tIf not, wait a few seconds and " - "retry."); - } + ereport(LOG, + (errcode_for_socket_access(), + errmsg("failed to bind server socket: %m"), + (addr->ai_family == AF_UNIX) ? + errhint("Is another postmaster already running on port %d?" + " If not, remove socket node \"%s\" and retry.", + (int) portNumber, sock_path) : + errhint("Is another postmaster already running on port %d?" + " If not, wait a few seconds and retry.", + (int) portNumber))); closesocket(fd); continue; } @@ -354,8 +353,9 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, err = listen(fd, maxconn); if (err < 0) { - elog(LOG, "server socket failure: listen(): %s", - strerror(errno)); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("failed to listen on server socket: %m"))); closesocket(fd); continue; } @@ -417,7 +417,7 @@ Setup_AF_UNIX(void) if (Unix_socket_group[0] != '\0') { #ifdef WIN32 - elog(FATAL, "Config value 'unix_socket_group' not supported on this platform"); + elog(WARNING, "configuration item unix_socket_group is not supported on this platform"); #else char *endptr; unsigned long int val; @@ -435,16 +435,19 @@ Setup_AF_UNIX(void) gr = getgrnam(Unix_socket_group); if (!gr) { - elog(LOG, "server socket failure: no such group '%s'", - Unix_socket_group); + ereport(LOG, + (errmsg("group \"%s\" does not exist", + Unix_socket_group))); return STATUS_ERROR; } gid = gr->gr_gid; } if (chown(sock_path, -1, gid) == -1) { - elog(LOG, "server socket failure: could not set group of %s: %s", - sock_path, strerror(errno)); + ereport(LOG, + (errcode_for_file_access(), + errmsg("could not set group of \"%s\": %m", + sock_path))); return STATUS_ERROR; } #endif @@ -452,8 +455,10 @@ Setup_AF_UNIX(void) if (chmod(sock_path, Unix_socket_permissions) == -1) { - elog(LOG, "server socket failure: could not set permissions on %s: %s", - sock_path, strerror(errno)); + ereport(LOG, + (errcode_for_file_access(), + errmsg("could not set permissions of \"%s\": %m", + sock_path))); return STATUS_ERROR; } return STATUS_OK; @@ -475,13 +480,15 @@ Setup_AF_UNIX(void) int StreamConnection(int server_fd, Port *port) { - /* accept connection (and fill in the client (remote) address) */ + /* accept connection and fill in the client (remote) address */ port->raddr.salen = sizeof(port->raddr.addr); if ((port->sock = accept(server_fd, (struct sockaddr *) &port->raddr.addr, &port->raddr.salen)) < 0) { - elog(LOG, "StreamConnection: accept() failed: %m"); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("could not accept new connection: %m"))); return STATUS_ERROR; } @@ -496,30 +503,33 @@ StreamConnection(int server_fd, Port *port) /* fill in the server (local) address */ port->laddr.salen = sizeof(port->laddr.addr); - if (getsockname(port->sock, (struct sockaddr *) & port->laddr.addr, + if (getsockname(port->sock, + (struct sockaddr *) & port->laddr.addr, &port->laddr.salen) < 0) { - elog(LOG, "StreamConnection: getsockname() failed: %m"); + elog(LOG, "getsockname() failed: %m"); return STATUS_ERROR; } /* select NODELAY and KEEPALIVE options if it's a TCP connection */ if (!IS_AF_UNIX(port->laddr.addr.ss_family)) { - int on = 1; + int on; #ifdef TCP_NODELAY + on = 1; if (setsockopt(port->sock, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(on)) < 0) { - elog(LOG, "StreamConnection: setsockopt(TCP_NODELAY) failed: %m"); + elog(LOG, "setsockopt(TCP_NODELAY) failed: %m"); return STATUS_ERROR; } #endif + on = 1; if (setsockopt(port->sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on)) < 0) { - elog(LOG, "StreamConnection: setsockopt(SO_KEEPALIVE) failed: %m"); + elog(LOG, "setsockopt(SO_KEEPALIVE) failed: %m"); return STATUS_ERROR; } } @@ -622,11 +632,13 @@ pq_recvbuf(void) continue; /* Ok if interrupted */ /* - * Careful: an elog() that tries to write to the client would + * Careful: an ereport() that tries to write to the client would * cause recursion to here, leading to stack overflow and core * dump! This message must go *only* to the postmaster log. */ - elog(COMMERROR, "pq_recvbuf: recv() failed: %m"); + ereport(COMMERROR, + (errcode_for_socket_access(), + errmsg("could not receive data from client: %m"))); return EOF; } if (r == 0) @@ -787,7 +799,9 @@ pq_getmessage(StringInfo s, int maxlen) /* Read message length word */ if (pq_getbytes((char *) &len, 4) == EOF) { - elog(COMMERROR, "unexpected EOF within message length word"); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("unexpected EOF within message length word"))); return EOF; } @@ -797,7 +811,9 @@ pq_getmessage(StringInfo s, int maxlen) if (len < 0 || (maxlen > 0 && len > maxlen)) { - elog(COMMERROR, "invalid message length"); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("invalid message length"))); return EOF; } @@ -809,7 +825,9 @@ pq_getmessage(StringInfo s, int maxlen) /* And grab the message */ if (pq_getbytes(s->data, len) == EOF) { - elog(COMMERROR, "incomplete client message"); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("incomplete message from client"))); return EOF; } s->len = len; @@ -874,7 +892,7 @@ pq_flush(void) continue; /* Ok if we were interrupted */ /* - * Careful: an elog() that tries to write to the client would + * Careful: an ereport() that tries to write to the client would * cause recursion to here, leading to stack overflow and core * dump! This message must go *only* to the postmaster log. * @@ -885,7 +903,9 @@ pq_flush(void) if (errno != last_reported_send_errno) { last_reported_send_errno = errno; - elog(COMMERROR, "pq_flush: send() failed: %m"); + ereport(COMMERROR, + (errcode_for_socket_access(), + errmsg("could not send data to client: %m"))); } /* diff --git a/src/backend/libpq/pqformat.c b/src/backend/libpq/pqformat.c index 0ea055b5222..8b04dbe7055 100644 --- a/src/backend/libpq/pqformat.c +++ b/src/backend/libpq/pqformat.c @@ -24,7 +24,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/libpq/pqformat.c,v 1.31 2003/05/09 21:19:49 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/pqformat.c,v 1.32 2003/07/22 19:00:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -231,7 +231,7 @@ pq_sendint(StringInfo buf, int i, int b) appendBinaryStringInfo(buf, (char *) &n32, 4); break; default: - elog(ERROR, "pq_sendint: unsupported size %d", b); + elog(ERROR, "unsupported integer size %d", b); break; } } @@ -440,7 +440,9 @@ int pq_getmsgbyte(StringInfo msg) { if (msg->cursor >= msg->len) - elog(ERROR, "pq_getmsgbyte: no data left in message"); + ereport(ERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("no data left in message"))); return (unsigned char) msg->data[msg->cursor++]; } @@ -473,7 +475,7 @@ pq_getmsgint(StringInfo msg, int b) result = ntohl(n32); break; default: - elog(ERROR, "pq_getmsgint: unsupported size %d", b); + elog(ERROR, "unsupported integer size %d", b); result = 0; /* keep compiler quiet */ break; } @@ -586,7 +588,9 @@ pq_getmsgbytes(StringInfo msg, int datalen) const char *result; if (datalen < 0 || datalen > (msg->len - msg->cursor)) - elog(ERROR, "pq_getmsgbytes: insufficient data left in message"); + ereport(ERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("insufficient data left in message"))); result = &msg->data[msg->cursor]; msg->cursor += datalen; return result; @@ -602,7 +606,9 @@ void pq_copymsgbytes(StringInfo msg, char *buf, int datalen) { if (datalen < 0 || datalen > (msg->len - msg->cursor)) - elog(ERROR, "pq_copymsgbytes: insufficient data left in message"); + ereport(ERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("insufficient data left in message"))); memcpy(buf, &msg->data[msg->cursor], datalen); msg->cursor += datalen; } @@ -621,7 +627,9 @@ pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes) char *p; if (rawbytes < 0 || rawbytes > (msg->len - msg->cursor)) - elog(ERROR, "pq_getmsgtext: insufficient data left in message"); + ereport(ERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("insufficient data left in message"))); str = &msg->data[msg->cursor]; msg->cursor += rawbytes; @@ -661,7 +669,9 @@ pq_getmsgstring(StringInfo msg) */ slen = strlen(str); if (msg->cursor + slen >= msg->len) - elog(ERROR, "pq_getmsgstring: invalid string in message"); + ereport(ERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("invalid string in message"))); msg->cursor += slen + 1; return (const char *) pg_client_to_server((unsigned char *) str, slen); @@ -675,5 +685,7 @@ void pq_getmsgend(StringInfo msg) { if (msg->cursor != msg->len) - elog(ERROR, "pq_getmsgend: invalid message format"); + ereport(ERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("invalid message format"))); } diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index a0495fff855..c2bb6274345 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -13,7 +13,7 @@ * * Copyright (c) 2001-2003, PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.37 2003/06/12 07:36:51 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.38 2003/07/22 19:00:10 tgl Exp $ * ---------- */ #include "postgres.h" @@ -81,13 +81,15 @@ static time_t last_pgstat_start_time; static long pgStatNumMessages = 0; static bool pgStatRunningInCollector = FALSE; + static int pgStatTabstatAlloc = 0; static int pgStatTabstatUsed = 0; static PgStat_MsgTabstat **pgStatTabstatMessages = NULL; +#define TABSTAT_QUANTUM 4 /* we alloc this many at a time */ + static int pgStatXactCommit = 0; static int pgStatXactRollback = 0; - static TransactionId pgStatDBHashXact = InvalidTransactionId; static HTAB *pgStatDBHash = NULL; static HTAB *pgStatBeDead = NULL; @@ -145,7 +147,7 @@ void pgstat_init(void) { ACCEPT_TYPE_ARG3 alen; - struct addrinfo *addr, hints; + struct addrinfo *addr = NULL, hints; int ret; /* @@ -190,15 +192,18 @@ pgstat_init(void) ret = getaddrinfo2("localhost", NULL, &hints, &addr); if (ret || !addr) { - elog(LOG, "PGSTAT: getaddrinfo2() failed: %s", - gai_strerror(ret)); + ereport(LOG, + (errmsg("getaddrinfo2(\"localhost\") failed: %s", + gai_strerror(ret)))); goto startup_failed; } if ((pgStatSock = socket(addr->ai_family, - addr->ai_socktype, addr->ai_protocol)) < 0) + addr->ai_socktype, addr->ai_protocol)) < 0) { - elog(LOG, "PGSTAT: socket() failed: %m"); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("could not create socket for statistics: %m"))); goto startup_failed; } @@ -208,7 +213,9 @@ pgstat_init(void) */ if (bind(pgStatSock, addr->ai_addr, addr->ai_addrlen) < 0) { - elog(LOG, "PGSTAT: bind() failed: %m"); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("could not bind socket for statistics: %m"))); goto startup_failed; } freeaddrinfo2(hints.ai_family, addr); @@ -217,7 +224,9 @@ pgstat_init(void) alen = sizeof(pgStatAddr); if (getsockname(pgStatSock, (struct sockaddr *)&pgStatAddr, &alen) < 0) { - elog(LOG, "PGSTAT: getsockname() failed: %m"); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("could not get address of socket for statistics: %m"))); goto startup_failed; } @@ -229,7 +238,9 @@ pgstat_init(void) */ if (connect(pgStatSock, (struct sockaddr *) & pgStatAddr, alen) < 0) { - elog(LOG, "PGSTAT: connect() failed: %m"); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("could not connect socket for statistics: %m"))); goto startup_failed; } @@ -241,7 +252,9 @@ pgstat_init(void) */ if (FCNTL_NONBLOCK(pgStatSock) < 0) { - elog(LOG, "PGSTAT: fcntl() failed: %m"); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("could not set statistics socket to nonblock mode: %m"))); goto startup_failed; } @@ -250,7 +263,9 @@ pgstat_init(void) */ if (pipe(pgStatPmPipe) < 0) { - elog(LOG, "PGSTAT: pipe() failed: %m"); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("could not create pipe for statistics collector: %m"))); goto startup_failed; } @@ -258,9 +273,7 @@ pgstat_init(void) startup_failed: if (addr) - { freeaddrinfo2(hints.ai_family, addr); - } if (pgStatSock >= 0) closesocket(pgStatSock); @@ -312,7 +325,8 @@ pgstat_start(void) */ if (pgStatSock < 0) { - elog(LOG, "PGSTAT: statistics collector startup skipped"); + ereport(LOG, + (errmsg("statistics collector startup skipped"))); /* * We can only get here if someone tries to manually turn * pgstat_collect_startcollector on after it had been off. @@ -340,7 +354,8 @@ pgstat_start(void) /* Specific beos actions */ beos_backend_startup_failed(); #endif - elog(LOG, "PGSTAT: fork() failed: %m"); + ereport(LOG, + (errmsg("could not fork statistics buffer: %m"))); return; case 0: @@ -744,7 +759,9 @@ pgstat_reset_counters(void) return; if (!superuser()) - elog(ERROR, "Only database superusers can reset statistic counters"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be superuser to reset statistics counters"))); pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_RESETCOUNTER); pgstat_send(&msg, sizeof(msg)); @@ -802,32 +819,41 @@ pgstat_initstats(PgStat_Info *stats, Relation rel) } /* - * On the first of all calls initialize the message buffers. + * On the first of all calls create some message buffers. */ - if (pgStatTabstatAlloc == 0) + if (pgStatTabstatMessages == NULL) { - pgStatTabstatAlloc = 4; - pgStatTabstatMessages = (PgStat_MsgTabstat **) - malloc(sizeof(PgStat_MsgTabstat *) * pgStatTabstatAlloc); - if (pgStatTabstatMessages == NULL) + PgStat_MsgTabstat *newMessages; + PgStat_MsgTabstat **msgArray; + + newMessages = (PgStat_MsgTabstat *) + malloc(sizeof(PgStat_MsgTabstat) * TABSTAT_QUANTUM); + if (newMessages == NULL) { - elog(LOG, "PGSTATBE: malloc() failed"); + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); return; } - for (i = 0; i < pgStatTabstatAlloc; i++) + msgArray = (PgStat_MsgTabstat **) + malloc(sizeof(PgStat_MsgTabstat *) * TABSTAT_QUANTUM); + if (msgArray == NULL) { - pgStatTabstatMessages[i] = (PgStat_MsgTabstat *) - malloc(sizeof(PgStat_MsgTabstat)); - if (pgStatTabstatMessages[i] == NULL) - { - elog(LOG, "PGSTATBE: malloc() failed"); - return; - } + free(newMessages); + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + return; } + MemSet(newMessages, 0, sizeof(PgStat_MsgTabstat) * TABSTAT_QUANTUM); + for (i = 0; i < TABSTAT_QUANTUM; i++) + msgArray[i] = newMessages++; + pgStatTabstatMessages = msgArray; + pgStatTabstatAlloc = TABSTAT_QUANTUM; } /* - * Lookup the so far used table slots for this relation. + * Search the already-used message slots for this relation. */ for (mb = 0; mb < pgStatTabstatUsed; mb++) { @@ -849,7 +875,6 @@ pgstat_initstats(PgStat_Info *stats, Relation rel) */ i = pgStatTabstatMessages[mb]->m_nentries++; useent = &pgStatTabstatMessages[mb]->m_entry[i]; - memset(useent, 0, sizeof(PgStat_TableEntry)); useent->t_id = rel_id; stats->tabentry = (void *) useent; return; @@ -860,27 +885,35 @@ pgstat_initstats(PgStat_Info *stats, Relation rel) */ if (pgStatTabstatUsed >= pgStatTabstatAlloc) { - pgStatTabstatAlloc += 4; - pgStatTabstatMessages = (PgStat_MsgTabstat **) - realloc(pgStatTabstatMessages, - sizeof(PgStat_MsgTabstat *) * pgStatTabstatAlloc); - if (pgStatTabstatMessages == NULL) + int newAlloc = pgStatTabstatAlloc + TABSTAT_QUANTUM; + PgStat_MsgTabstat *newMessages; + PgStat_MsgTabstat **msgArray; + + newMessages = (PgStat_MsgTabstat *) + malloc(sizeof(PgStat_MsgTabstat) * TABSTAT_QUANTUM); + if (newMessages == NULL) { - pgStatTabstatAlloc -= 4; - elog(LOG, "PGSTATBE: malloc() failed"); + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); return; } - for (i = pgStatTabstatUsed; i < pgStatTabstatAlloc; i++) + msgArray = (PgStat_MsgTabstat **) + realloc(pgStatTabstatMessages, + sizeof(PgStat_MsgTabstat *) * newAlloc); + if (msgArray == NULL) { - pgStatTabstatMessages[i] = (PgStat_MsgTabstat *) - malloc(sizeof(PgStat_MsgTabstat)); - if (pgStatTabstatMessages[i] == NULL) - { - pgStatTabstatAlloc -= 4; - elog(LOG, "PGSTATBE: malloc() failed"); - return; - } + free(newMessages); + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + return; } + MemSet(newMessages, 0, sizeof(PgStat_MsgTabstat) * TABSTAT_QUANTUM); + for (i = 0; i < TABSTAT_QUANTUM; i++) + msgArray[pgStatTabstatAlloc + i] = newMessages++; + pgStatTabstatMessages = msgArray; + pgStatTabstatAlloc = newAlloc; } /* @@ -889,10 +922,8 @@ pgstat_initstats(PgStat_Info *stats, Relation rel) mb = pgStatTabstatUsed++; pgStatTabstatMessages[mb]->m_nentries = 1; useent = &pgStatTabstatMessages[mb]->m_entry[0]; - memset(useent, 0, sizeof(PgStat_TableEntry)); useent->t_id = rel_id; stats->tabentry = (void *) useent; - return; } @@ -1205,14 +1236,17 @@ pgstat_main(void) */ if (pipe(pgStatPipe) < 0) { - elog(LOG, "PGSTAT: pipe() failed: %m"); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("could not create pipe for statistics buffer: %m"))); exit(1); } switch (fork()) { case -1: - elog(LOG, "PGSTAT: fork() failed: %m"); + ereport(LOG, + (errmsg("could not fork statistics collector: %m"))); exit(1); case 0: @@ -1266,7 +1300,10 @@ pgstat_main(void) &hash_ctl, HASH_ELEM | HASH_FUNCTION); if (pgStatBeDead == NULL) { - elog(LOG, "PGSTAT: Creation of dead backend hash table failed"); + /* assume the problem is out-of-memory */ + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory in statistics collector --- abort"))); exit(1); } @@ -1277,7 +1314,8 @@ pgstat_main(void) sizeof(PgStat_StatBeEntry) * MaxBackends); if (pgStatBeTable == NULL) { - elog(LOG, "PGSTAT: Allocation of backend table failed"); + ereport(LOG, + (errmsg("allocation of backend table failed"))); exit(1); } memset(pgStatBeTable, 0, sizeof(PgStat_StatBeEntry) * MaxBackends); @@ -1341,7 +1379,9 @@ pgstat_main(void) { if (errno == EINTR) continue; - elog(LOG, "PGSTAT: select() failed: %m"); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("select failed in statistics collector: %m"))); exit(1); } @@ -1381,7 +1421,9 @@ pgstat_main(void) { if (errno == EINTR) continue; - elog(LOG, "PGSTAT: read() failed: %m"); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("could not read from statistics pipe: %m"))); exit(1); } if (len == 0) /* EOF on the pipe! */ @@ -1399,7 +1441,8 @@ pgstat_main(void) * sync with the buffer process somehow. Abort so * that we can restart both processes. */ - elog(LOG, "PGSTAT: bogus message length"); + ereport(LOG, + (errmsg("invalid statistics message length"))); exit(1); } } @@ -1549,7 +1592,9 @@ pgstat_recvbuffer(void) */ if (FCNTL_NONBLOCK(writePipe) < 0) { - elog(LOG, "PGSTATBUFF: fcntl() failed: %m"); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("could not set statistics pipe to nonblock mode: %m"))); exit(1); } @@ -1559,7 +1604,9 @@ pgstat_recvbuffer(void) msgbuffer = (char *) malloc(PGSTAT_RECVBUFFERSZ); if (msgbuffer == NULL) { - elog(LOG, "PGSTATBUFF: malloc() failed"); + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory in statistics collector --- abort"))); exit(1); } @@ -1586,7 +1633,8 @@ pgstat_recvbuffer(void) { if (!overflow) { - elog(LOG, "PGSTATBUFF: Warning - receive buffer full"); + ereport(LOG, + (errmsg("statistics buffer is full"))); overflow = true; } } @@ -1617,7 +1665,9 @@ pgstat_recvbuffer(void) { if (errno == EINTR) continue; - elog(LOG, "PGSTATBUFF: select() failed: %m"); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("select failed in statistics buffer: %m"))); exit(1); } @@ -1633,7 +1683,9 @@ pgstat_recvbuffer(void) (struct sockaddr *) &fromaddr, &fromlen); if (len < 0) { - elog(LOG, "PGSTATBUFF: recvfrom() failed: %m"); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("failed to read statistics message: %m"))); exit(1); } @@ -1706,7 +1758,9 @@ pgstat_recvbuffer(void) { if (errno == EINTR || errno == EAGAIN) continue; /* not enough space in pipe */ - elog(LOG, "PGSTATBUFF: write() failed: %m"); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("failed to write statistics pipe: %m"))); exit(1); } /* NB: len < xfr is okay */ @@ -1759,7 +1813,8 @@ pgstat_add_backend(PgStat_MsgHdr *msg) */ if (msg->m_backendid < 1 || msg->m_backendid > MaxBackends) { - elog(LOG, "PGSTAT: Invalid backend ID %d", msg->m_backendid); + ereport(LOG, + (errmsg("invalid backend ID %d", msg->m_backendid))); return -1; } @@ -1817,7 +1872,9 @@ pgstat_add_backend(PgStat_MsgHdr *msg) HASH_ENTER, &found); if (dbentry == NULL) { - elog(LOG, "PGSTAT: DB hash table out of memory - abort"); + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory in statistics collector --- abort"))); exit(1); } @@ -1846,8 +1903,10 @@ pgstat_add_backend(PgStat_MsgHdr *msg) HASH_ELEM | HASH_FUNCTION); if (dbentry->tables == NULL) { - elog(LOG, "PGSTAT: failed to initialize hash table for " - "new database entry"); + /* assume the problem is out-of-memory */ + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory in statistics collector --- abort"))); exit(1); } } @@ -1895,10 +1954,13 @@ pgstat_sub_backend(int procpid) */ deadbe = (PgStat_StatBeDead *) hash_search(pgStatBeDead, (void *) &procpid, - HASH_ENTER, &found); + HASH_ENTER, + &found); if (deadbe == NULL) { - elog(LOG, "PGSTAT: dead backend hash table out of memory"); + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory in statistics collector --- abort"))); exit(1); } if (!found) @@ -1945,8 +2007,10 @@ pgstat_write_statsfile(void) fpout = fopen(pgStat_tmpfname, PG_BINARY_W); if (fpout == NULL) { - elog(LOG, "PGSTAT: cannot open temp stats file %s: %m", - pgStat_tmpfname); + ereport(LOG, + (errcode_for_file_access(), + errmsg("cannot write temp statistics file \"%s\": %m", + pgStat_tmpfname))); return; } @@ -1971,8 +2035,9 @@ pgstat_write_statsfile(void) (void *) &(dbentry->databaseid), HASH_REMOVE, NULL) == NULL) { - elog(LOG, "PGSTAT: database hash table corrupted " - "during cleanup - abort"); + ereport(LOG, + (errmsg("database hash table corrupted " + "during cleanup --- abort"))); exit(1); } } @@ -2007,10 +2072,11 @@ pgstat_write_statsfile(void) (void *) &(tabentry->tableid), HASH_REMOVE, NULL) == NULL) { - elog(LOG, "PGSTAT: tables hash table for " - "database %d corrupted during " - "cleanup - abort", - dbentry->databaseid); + ereport(LOG, + (errmsg("tables hash table for " + "database %u corrupted during " + "cleanup --- abort", + dbentry->databaseid))); exit(1); } } @@ -2049,20 +2115,24 @@ pgstat_write_statsfile(void) /* * No more output to be done. Close the temp file and replace the old - * pgstat.stat with it's content. + * pgstat.stat with it. */ fputc('E', fpout); if (fclose(fpout) < 0) { - elog(LOG, "PGSTAT: Error closing temp stats file %s: %m", - pgStat_tmpfname); + ereport(LOG, + (errcode_for_file_access(), + errmsg("could not write temp statistics file \"%s\": %m", + pgStat_tmpfname))); } else { if (rename(pgStat_tmpfname, pgStat_fname) < 0) { - elog(LOG, "PGSTAT: Cannot rename temp stats file %s: %m", - pgStat_fname); + ereport(LOG, + (errcode_for_file_access(), + errmsg("could not rename temp statistics file \"%s\" to \"%s\": %m", + pgStat_tmpfname, pgStat_fname))); } } @@ -2082,8 +2152,9 @@ pgstat_write_statsfile(void) (void *) &(deadbe->procpid), HASH_REMOVE, NULL) == NULL) { - elog(LOG, "PGSTAT: dead backend hash table corrupted " - "during cleanup - abort"); + ereport(LOG, + (errmsg("dead-backend hash table corrupted " + "during cleanup --- abort"))); exit(1); } } @@ -2145,13 +2216,18 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb, HASH_ELEM | HASH_FUNCTION | mcxt_flags); if (*dbhash == NULL) { + /* assume the problem is out-of-memory */ if (pgStatRunningInCollector) { - elog(LOG, "PGSTAT: Creation of DB hash table failed"); + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory in statistics collector --- abort"))); exit(1); } /* in backend, can do normal error */ - elog(ERROR, "PGSTAT: Creation of DB hash table failed"); + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); } /* @@ -2187,18 +2263,10 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb, case 'D': if (fread(&dbbuf, 1, sizeof(dbbuf), fpin) != sizeof(dbbuf)) { - if (pgStatRunningInCollector) - { - elog(LOG, "PGSTAT: corrupted pgstat.stat file"); - fclose(fpin); - return; - } - else - { - elog(WARNING, "PGSTAT: corrupted pgstat.stat file"); - fclose(fpin); - return; - } + ereport(pgStatRunningInCollector ? LOG : WARNING, + (errmsg("corrupted pgstat.stat file"))); + fclose(fpin); + return; } /* @@ -2206,34 +2274,31 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb, */ dbentry = (PgStat_StatDBEntry *) hash_search(*dbhash, (void *) &dbbuf.databaseid, - HASH_ENTER, &found); + HASH_ENTER, + &found); if (dbentry == NULL) { if (pgStatRunningInCollector) { - elog(LOG, "PGSTAT: DB hash table out of memory"); + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory in statistics collector --- abort"))); exit(1); } else { fclose(fpin); - elog(ERROR, "PGSTAT: DB hash table out of memory"); + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); } } if (found) { - if (pgStatRunningInCollector) - { - elog(LOG, "PGSTAT: corrupted pgstat.stat file"); - fclose(fpin); - return; - } - else - { - elog(WARNING, "PGSTAT: corrupted pgstat.stat file"); - fclose(fpin); - return; - } + ereport(pgStatRunningInCollector ? LOG : WARNING, + (errmsg("corrupted pgstat.stat file"))); + fclose(fpin); + return; } memcpy(dbentry, &dbbuf, sizeof(PgStat_StatDBEntry)); @@ -2247,7 +2312,6 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb, if (onlydb != InvalidOid && onlydb != dbbuf.databaseid) break; - memset(&hash_ctl, 0, sizeof(hash_ctl)); hash_ctl.keysize = sizeof(Oid); hash_ctl.entrysize = sizeof(PgStat_StatTabEntry); @@ -2259,18 +2323,19 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb, HASH_ELEM | HASH_FUNCTION | mcxt_flags); if (dbentry->tables == NULL) { + /* assume the problem is out-of-memory */ if (pgStatRunningInCollector) { - elog(LOG, "PGSTAT: failed to initialize " - "hash table for new database entry"); + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory in statistics collector --- abort"))); exit(1); } - else - { - fclose(fpin); - elog(ERROR, "PGSTAT: failed to initialize " - "hash table for new database entry"); - } + /* in backend, can do normal error */ + fclose(fpin); + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); } /* @@ -2293,18 +2358,10 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb, case 'T': if (fread(&tabbuf, 1, sizeof(tabbuf), fpin) != sizeof(tabbuf)) { - if (pgStatRunningInCollector) - { - elog(LOG, "PGSTAT: corrupted pgstat.stat file"); - fclose(fpin); - return; - } - else - { - elog(WARNING, "PGSTAT: corrupted pgstat.stat file"); - fclose(fpin); - return; - } + ereport(pgStatRunningInCollector ? LOG : WARNING, + (errmsg("corrupted pgstat.stat file"))); + fclose(fpin); + return; } /* @@ -2320,30 +2377,24 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb, { if (pgStatRunningInCollector) { - elog(LOG, "PGSTAT: Tab hash table out of memory"); + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory in statistics collector --- abort"))); exit(1); } - else - { - fclose(fpin); - elog(ERROR, "PGSTAT: Tab hash table out of memory"); - } + /* in backend, can do normal error */ + fclose(fpin); + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); } if (found) { - if (pgStatRunningInCollector) - { - elog(LOG, "PGSTAT: corrupted pgstat.stat file"); - fclose(fpin); - return; - } - else - { - elog(WARNING, "PGSTAT: corrupted pgstat.stat file"); - fclose(fpin); - return; - } + ereport(pgStatRunningInCollector ? LOG : WARNING, + (errmsg("corrupted pgstat.stat file"))); + fclose(fpin); + return; } memcpy(tabentry, &tabbuf, sizeof(tabbuf)); @@ -2361,18 +2412,10 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb, if (fread(&maxbackends, 1, sizeof(maxbackends), fpin) != sizeof(maxbackends)) { - if (pgStatRunningInCollector) - { - elog(LOG, "PGSTAT: corrupted pgstat.stat file"); - fclose(fpin); - return; - } - else - { - elog(WARNING, "PGSTAT: corrupted pgstat.stat file"); - fclose(fpin); - return; - } + ereport(pgStatRunningInCollector ? LOG : WARNING, + (errmsg("corrupted pgstat.stat file"))); + fclose(fpin); + return; } if (maxbackends == 0) { @@ -2415,18 +2458,10 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb, sizeof(PgStat_StatBeEntry), fpin) != sizeof(PgStat_StatBeEntry)) { - if (pgStatRunningInCollector) - { - elog(LOG, "PGSTAT: corrupted pgstat.stat file"); - fclose(fpin); - return; - } - else - { - elog(WARNING, "PGSTAT: corrupted pgstat.stat file"); - fclose(fpin); - return; - } + ereport(pgStatRunningInCollector ? LOG : WARNING, + (errmsg("corrupted pgstat.stat file"))); + fclose(fpin); + return; } /* @@ -2456,18 +2491,10 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb, return; default: - if (pgStatRunningInCollector) - { - elog(LOG, "PGSTAT: corrupted pgstat.stat file"); - fclose(fpin); - return; - } - else - { - elog(WARNING, "PGSTAT: corrupted pgstat.stat file"); - fclose(fpin); - return; - } + ereport(pgStatRunningInCollector ? LOG : WARNING, + (errmsg("corrupted pgstat.stat file"))); + fclose(fpin); + return; } } @@ -2579,8 +2606,9 @@ pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len) HASH_ENTER, &found); if (tabentry == NULL) { - elog(LOG, "PGSTAT: tables hash table out of memory for " - "database %d - abort", dbentry->databaseid); + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory in statistics collector --- abort"))); exit(1); } @@ -2759,8 +2787,10 @@ pgstat_recv_resetcounter(PgStat_MsgResetcounter *msg, int len) HASH_ELEM | HASH_FUNCTION); if (dbentry->tables == NULL) { - elog(LOG, "PGSTAT: failed to reinitialize hash table for " - "database entry"); + /* assume the problem is out-of-memory */ + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory in statistics collector --- abort"))); exit(1); } } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index e32a668bc71..ec98fc6f538 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -37,7 +37,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.333 2003/06/12 07:36:51 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.334 2003/07/22 19:00:10 tgl Exp $ * * NOTES * @@ -327,10 +327,15 @@ checkDataDir(const char *checkdir) if (stat(checkdir, &stat_buf) == -1) { if (errno == ENOENT) - elog(FATAL, "data directory %s was not found", checkdir); + ereport(FATAL, + (errcode_for_file_access(), + errmsg("data directory \"%s\" does not exist", + checkdir))); else - elog(FATAL, "could not read permissions of directory %s: %m", - checkdir); + ereport(FATAL, + (errcode_for_file_access(), + errmsg("could not read permissions of directory \"%s\": %m", + checkdir))); } /* @@ -342,8 +347,11 @@ checkDataDir(const char *checkdir) */ #if !defined(__CYGWIN__) && !defined(WIN32) if (stat_buf.st_mode & (S_IRWXG | S_IRWXO)) - elog(FATAL, "data directory %s has group or world access; permissions should be u=rwx (0700)", - checkdir); + ereport(FATAL, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("data directory \"%s\" has group or world access", + checkdir), + errdetail("permissions should be u=rwx (0700)"))); #endif /* Look for PG_VERSION before looking for pg_control */ @@ -560,9 +568,15 @@ PostmasterMain(int argc, char *argv[]) if (!value) { if (opt == '-') - elog(ERROR, "--%s requires argument", optarg); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("--%s requires a value", + optarg))); else - elog(ERROR, "-c %s requires argument", optarg); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("-c %s requires a value", + optarg))); } SetConfigOption(name, value, PGC_POSTMASTER, PGC_S_ARGV); @@ -654,8 +668,9 @@ PostmasterMain(int argc, char *argv[]) * On some systems our dynloader code needs the executable's pathname. */ if (FindExec(pg_pathname, progname, "postgres") < 0) - elog(FATAL, "%s: could not locate executable, bailing out...", - progname); + ereport(FATAL, + (errmsg("%s: could not locate postgres executable", + progname))); /* * Initialize SSL library, if specified. @@ -830,7 +845,7 @@ PostmasterMain(int argc, char *argv[]) /* * Reset whereToSendOutput from Debug (its starting state) to None. - * This prevents elog from sending log messages to stderr unless the + * This prevents ereport from sending log messages to stderr unless the * syslog/stderr switch permits. We don't do this until the * postmaster is fully launched, since startup failures may as well be * reported to stderr. @@ -1049,7 +1064,9 @@ ServerLoop(void) PG_SETMASK(&BlockSig); if (errno == EINTR || errno == EWOULDBLOCK) continue; - elog(LOG, "ServerLoop: select failed: %m"); + ereport(LOG, + (errcode_for_socket_access(), + errmsg("select failed in postmaster: %m"))); return STATUS_ERROR; } @@ -1138,10 +1155,10 @@ initMasks(fd_set *rmask, fd_set *wmask) /* * Read the startup packet and do something according to it. * - * Returns STATUS_OK or STATUS_ERROR, or might call elog(FATAL) and + * Returns STATUS_OK or STATUS_ERROR, or might call ereport(FATAL) and * not return at all. * - * (Note that elog(FATAL) stuff is sent to the client, so only use it + * (Note that ereport(FATAL) stuff is sent to the client, so only use it * if that's what you want. Return STATUS_ERROR if you don't want to * send anything to the client, which would typically be appropriate * if we detect a communications failure.) @@ -1163,7 +1180,9 @@ ProcessStartupPacket(Port *port, bool SSLdone) * so don't clutter the log with a complaint. */ if (!SSLdone) - elog(COMMERROR, "incomplete startup packet"); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("incomplete startup packet"))); return STATUS_ERROR; } @@ -1173,7 +1192,9 @@ ProcessStartupPacket(Port *port, bool SSLdone) if (len < (int32) sizeof(ProtocolVersion) || len > MAX_STARTUP_PACKET_LENGTH) { - elog(COMMERROR, "invalid length of startup packet"); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("invalid length of startup packet"))); return STATUS_ERROR; } @@ -1190,7 +1211,9 @@ ProcessStartupPacket(Port *port, bool SSLdone) if (pq_getbytes(buf, len) == EOF) { - elog(COMMERROR, "incomplete startup packet"); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("incomplete startup packet"))); return STATUS_ERROR; } @@ -1221,7 +1244,9 @@ ProcessStartupPacket(Port *port, bool SSLdone) #endif if (send(port->sock, &SSLok, 1, 0) != 1) { - elog(COMMERROR, "failed to send SSL negotiation response: %m"); + ereport(COMMERROR, + (errcode_for_socket_access(), + errmsg("failed to send SSL negotiation response: %m"))); return STATUS_ERROR; /* close the connection */ } @@ -1237,7 +1262,7 @@ ProcessStartupPacket(Port *port, bool SSLdone) /* Could add additional special packet types here */ /* - * Set FrontendProtocol now so that elog() knows what format to send + * Set FrontendProtocol now so that ereport() knows what format to send * if we fail during startup. */ FrontendProtocol = proto; @@ -1248,11 +1273,13 @@ ProcessStartupPacket(Port *port, bool SSLdone) PG_PROTOCOL_MAJOR(proto) > PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST) || (PG_PROTOCOL_MAJOR(proto) == PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST) && PG_PROTOCOL_MINOR(proto) > PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST))) - elog(FATAL, "unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u", - PG_PROTOCOL_MAJOR(proto), PG_PROTOCOL_MINOR(proto), - PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST), - PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST), - PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST)); + ereport(FATAL, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u", + PG_PROTOCOL_MAJOR(proto), PG_PROTOCOL_MINOR(proto), + PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST), + PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST), + PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST)))); /* * Now fetch parameters out of startup packet and save them into the @@ -1309,7 +1336,9 @@ ProcessStartupPacket(Port *port, bool SSLdone) * given packet length, complain. */ if (offset != len-1) - elog(FATAL, "invalid startup packet layout: expected terminator as last byte"); + ereport(FATAL, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("invalid startup packet layout: expected terminator as last byte"))); } else { @@ -1335,7 +1364,9 @@ ProcessStartupPacket(Port *port, bool SSLdone) /* Check a user name was given. */ if (port->user_name == NULL || port->user_name[0] == '\0') - elog(FATAL, "no PostgreSQL user name specified in startup packet"); + ereport(FATAL, + (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), + errmsg("no PostgreSQL user name specified in startup packet"))); /* The database defaults to the user name. */ if (port->database_name == NULL || port->database_name[0] == '\0') @@ -1388,16 +1419,24 @@ ProcessStartupPacket(Port *port, bool SSLdone) switch (cac) { case CAC_STARTUP: - elog(FATAL, "The database system is starting up"); + ereport(FATAL, + (errcode(ERRCODE_CANNOT_CONNECT_NOW), + errmsg("the database system is starting up"))); break; case CAC_SHUTDOWN: - elog(FATAL, "The database system is shutting down"); + ereport(FATAL, + (errcode(ERRCODE_CANNOT_CONNECT_NOW), + errmsg("the database system is shutting down"))); break; case CAC_RECOVERY: - elog(FATAL, "The database system is in recovery mode"); + ereport(FATAL, + (errcode(ERRCODE_CANNOT_CONNECT_NOW), + errmsg("the database system is in recovery mode"))); break; case CAC_TOOMANY: - elog(FATAL, "Sorry, too many clients already"); + ereport(FATAL, + (errcode(ERRCODE_TOO_MANY_CONNECTIONS), + errmsg("sorry, too many clients already"))); break; case CAC_OK: default: @@ -1427,7 +1466,8 @@ processCancelRequest(Port *port, void *pkt) if (backendPID == CheckPointPID) { - elog(DEBUG2, "processCancelRequest: CheckPointPID in cancel request for process %d", backendPID); + elog(DEBUG2, "ignoring cancel request for checkpoint process %d", + backendPID); return; } else if (ExecBackend) @@ -1501,7 +1541,9 @@ ConnCreate(int serverFd) if (!(port = (Port *) calloc(1, sizeof(Port)))) { - elog(LOG, "ConnCreate: malloc failed"); + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); SignalChildren(SIGQUIT); ExitPostmaster(1); } @@ -1600,7 +1642,8 @@ SIGHUP_handler(SIGNAL_ARGS) if (Shutdown <= SmartShutdown) { - elog(LOG, "Received SIGHUP, reloading configuration files"); + ereport(LOG, + (errmsg("received SIGHUP, reloading configuration files"))); ProcessConfigFile(PGC_SIGHUP); #ifdef EXEC_BACKEND write_nondefault_variables(PGC_SIGHUP); @@ -1627,7 +1670,7 @@ pmdie(SIGNAL_ARGS) PG_SETMASK(&BlockSig); - elog(DEBUG2, "pmdie %d", postgres_signal_arg); + elog(DEBUG2, "postmaster received signal %d", postgres_signal_arg); switch (postgres_signal_arg) { @@ -1641,7 +1684,8 @@ pmdie(SIGNAL_ARGS) if (Shutdown >= SmartShutdown) break; Shutdown = SmartShutdown; - elog(LOG, "smart shutdown request"); + ereport(LOG, + (errmsg("received smart shutdown request"))); if (DLGetHead(BackendList)) /* let reaper() handle this */ break; @@ -1671,13 +1715,15 @@ pmdie(SIGNAL_ARGS) */ if (Shutdown >= FastShutdown) break; - elog(LOG, "fast shutdown request"); + ereport(LOG, + (errmsg("received fast shutdown request"))); if (DLGetHead(BackendList)) /* let reaper() handle this */ { Shutdown = FastShutdown; if (!FatalError) { - elog(LOG, "aborting any active transactions"); + ereport(LOG, + (errmsg("aborting any active transactions"))); SignalChildren(SIGTERM); } break; @@ -1713,7 +1759,8 @@ pmdie(SIGNAL_ARGS) * abort all children with SIGQUIT and exit without attempt to * properly shutdown data base system. */ - elog(LOG, "immediate shutdown request"); + ereport(LOG, + (errmsg("received immediate shutdown request"))); if (ShutdownPID > 0) kill(ShutdownPID, SIGQUIT); if (StartupPID > 0) @@ -1795,7 +1842,8 @@ reaper(SIGNAL_ARGS) { LogChildExit(LOG, gettext("startup process"), pid, exitstatus); - elog(LOG, "aborting startup due to startup process failure"); + ereport(LOG, + (errmsg("aborting startup due to startup process failure"))); ExitPostmaster(1); } StartupPID = 0; @@ -1849,7 +1897,8 @@ reaper(SIGNAL_ARGS) */ if (DLGetHead(BackendList) || StartupPID > 0 || ShutdownPID > 0) goto reaper_done; - elog(LOG, "all server processes terminated; reinitializing shared memory and semaphores"); + ereport(LOG, + (errmsg("all server processes terminated; reinitializing"))); shmem_exit(0); reset_shared(PostPortNumber); @@ -1936,7 +1985,8 @@ CleanupProc(int pid, (pid == CheckPointPID) ? gettext("checkpoint process") : gettext("server process"), pid, exitstatus); - elog(LOG, "terminating any other active server processes"); + ereport(LOG, + (errmsg("terminating any other active server processes"))); } curr = DLGetHead(BackendList); @@ -1957,7 +2007,7 @@ CleanupProc(int pid, */ if (!FatalError) { - elog(DEBUG2, "CleanupProc: sending %s to process %d", + elog(DEBUG2, "sending %s to process %d", (SendStop ? "SIGSTOP" : "SIGQUIT"), (int) bp->pid); kill(bp->pid, (SendStop ? SIGSTOP : SIGQUIT)); } @@ -1996,19 +2046,30 @@ CleanupProc(int pid, static void LogChildExit(int lev, const char *procname, int pid, int exitstatus) { - /* - * translator: the first %s in these messages is a noun phrase - * describing a child process, such as "server process" - */ if (WIFEXITED(exitstatus)) - elog(lev, "%s (pid %d) exited with exit code %d", - procname, pid, WEXITSTATUS(exitstatus)); + ereport(lev, + /* + * translator: %s is a noun phrase describing a child process, + * such as "server process" + */ + (errmsg("%s (pid %d) exited with exit code %d", + procname, pid, WEXITSTATUS(exitstatus)))); else if (WIFSIGNALED(exitstatus)) - elog(lev, "%s (pid %d) was terminated by signal %d", - procname, pid, WTERMSIG(exitstatus)); + ereport(lev, + /* + * translator: %s is a noun phrase describing a child process, + * such as "server process" + */ + (errmsg("%s (pid %d) was terminated by signal %d", + procname, pid, WTERMSIG(exitstatus)))); else - elog(lev, "%s (pid %d) exited with unexpected status %d", - procname, pid, exitstatus); + ereport(lev, + /* + * translator: %s is a noun phrase describing a child process, + * such as "server process" + */ + (errmsg("%s (pid %d) exited with unexpected status %d", + procname, pid, exitstatus))); } /* @@ -2029,7 +2090,7 @@ SignalChildren(int signal) if (bp->pid != MyProcPid) { - elog(DEBUG2, "SignalChildren: sending signal %d to process %d", + elog(DEBUG2, "sending signal %d to process %d", signal, (int) bp->pid); kill(bp->pid, signal); } @@ -2067,7 +2128,9 @@ BackendStartup(Port *port) bn = (Backend *) malloc(sizeof(Backend)); if (!bn) { - elog(LOG, "out of memory; connection startup aborted"); + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); return STATUS_ERROR; } @@ -2118,7 +2181,8 @@ BackendStartup(Port *port) status = BackendFork(port); if (status != 0) - elog(LOG, "connection startup failed"); + ereport(LOG, + (errmsg("connection startup failed"))); proc_exit(status); } @@ -2132,15 +2196,16 @@ BackendStartup(Port *port) beos_backend_startup_failed(); #endif free(bn); - elog(LOG, "connection startup failed (fork failure): %s", - strerror(save_errno)); + errno = save_errno; + ereport(LOG, + (errmsg("could not fork new process for connection: %m"))); report_fork_failure_to_client(port, save_errno); return STATUS_ERROR; } /* in parent, normal */ - elog(DEBUG2, "BackendStartup: forked pid=%d socket=%d", (int) pid, - port->sock); + elog(DEBUG2, "forked new backend, pid=%d socket=%d", + (int) pid, port->sock); /* * Everything's been successful, it's safe to add this backend to our @@ -2166,9 +2231,9 @@ report_fork_failure_to_client(Port *port, int errnum) { char buffer[1000]; - /* Format the error message packet */ + /* Format the error message packet (always V2 protocol) */ snprintf(buffer, sizeof(buffer), "E%s%s\n", - gettext("Server process fork() failed: "), + gettext("could not fork new process for connection: "), strerror(errnum)); /* Set port to non-blocking. Don't do send() if this fails */ @@ -2262,12 +2327,12 @@ BackendFork(Port *port) MyProcPid = getpid(); /* - * Initialize libpq and enable reporting of elog errors to the client. + * Initialize libpq and enable reporting of ereport errors to the client. * Must do this now because authentication uses libpq to send * messages. */ pq_init(); /* initialize libpq to talk to client */ - whereToSendOutput = Remote; /* now safe to elog to client */ + whereToSendOutput = Remote; /* now safe to ereport to client */ /* * We arrange for a simple exit(0) if we receive SIGTERM or SIGQUIT @@ -2286,10 +2351,10 @@ BackendFork(Port *port) remote_host[0] = '\0'; remote_port[0] = '\0'; if (!getnameinfo((struct sockaddr *)&port->raddr.addr, - port->raddr.salen, - remote_host, sizeof(remote_host), - remote_port, sizeof(remote_host), - (log_hostname ? 0 : NI_NUMERICHOST) | NI_NUMERICSERV)) + port->raddr.salen, + remote_host, sizeof(remote_host), + remote_port, sizeof(remote_host), + (log_hostname ? 0 : NI_NUMERICHOST) | NI_NUMERICSERV)) { getnameinfo((struct sockaddr *)&port->raddr.addr, port->raddr.salen, @@ -2299,21 +2364,17 @@ BackendFork(Port *port) } if (Log_connections) - { - elog(LOG, "connection received: host=%s port=%s", - remote_host, remote_port); - } + ereport(LOG, + (errmsg("connection received: host=%s port=%s", + remote_host, remote_port))); if (LogSourcePort) { /* modify remote_host for use in ps status */ - int slen = strlen(remote_host) + 10; - char *str = palloc(slen); + char tmphost[sizeof(remote_host) + 10]; - snprintf(str, slen, "%s:%s", remote_host, remote_port); - strncpy(remote_host, str, sizeof(remote_host)); - remote_host[sizeof(remote_host) - 1] = '\0'; - pfree(str); + snprintf(tmphost, sizeof(tmphost), "%s:%s", remote_host, remote_port); + StrNCpy(remote_host, tmphost, sizeof(remote_host)); } /* @@ -2332,7 +2393,7 @@ BackendFork(Port *port) * indefinitely. PreAuthDelay doesn't count against the time limit. */ if (!enable_sig_alarm(AuthenticationTimeout * 1000, false)) - elog(FATAL, "BackendFork: Unable to set timer for auth timeout"); + elog(FATAL, "could not set timer for authorization timeout"); /* * Receive the startup packet (which might turn out to be a cancel @@ -2361,12 +2422,13 @@ BackendFork(Port *port) * SIGTERM/SIGQUIT again until backend startup is complete. */ if (!disable_sig_alarm(false)) - elog(FATAL, "BackendFork: Unable to disable timer for auth timeout"); + elog(FATAL, "could not disable timer for authorization timeout"); PG_SETMASK(&BlockSig); if (Log_connections) - elog(LOG, "connection authorized: user=%s database=%s", - port->user_name, port->database_name); + ereport(LOG, + (errmsg("connection authorized: user=%s database=%s", + port->user_name, port->database_name))); /* * Don't want backend to be able to see the postmaster random number @@ -2519,9 +2581,10 @@ sigusr1_handler(SIGNAL_ARGS) int elapsed_secs = now - LastSignalledCheckpoint; if (elapsed_secs < CheckPointWarning) - elog(LOG, "Checkpoint segments are being created too frequently (%d secs)" - "\n\tConsider increasing CHECKPOINT_SEGMENTS", - elapsed_secs); + ereport(LOG, + (errmsg("checkpoints are occurring too frequently (%d seconds apart)", + elapsed_secs), + errhint("Consider increasing CHECKPOINT_SEGMENTS."))); } LastSignalledCheckpoint = now; } @@ -2787,15 +2850,20 @@ SSDataBase(int xlop) switch (xlop) { case BS_XLOG_STARTUP: - elog(LOG, "could not launch startup process (fork failure): %m"); + ereport(LOG, + (errmsg("could not fork startup process: %m"))); break; case BS_XLOG_CHECKPOINT: - elog(LOG, "could not launch checkpoint process (fork failure): %m"); + ereport(LOG, + (errmsg("could not fork checkpoint process: %m"))); break; case BS_XLOG_SHUTDOWN: - elog(LOG, "could not launch shutdown process (fork failure): %m"); + ereport(LOG, + (errmsg("could not fork shutdown process: %m"))); break; default: + ereport(LOG, + (errmsg("could not fork process: %m"))); break; } @@ -2817,7 +2885,9 @@ SSDataBase(int xlop) { if (!(bn = (Backend *) malloc(sizeof(Backend)))) { - elog(LOG, "CheckPointDataBase: malloc failed"); + ereport(LOG, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); ExitPostmaster(1); } @@ -2857,7 +2927,7 @@ CreateOptsFile(int argc, char *argv[]) if ((fp = fopen(filename, "w")) == NULL) { - postmaster_error("cannot create file %s: %s", + postmaster_error("cannot create file \"%s\": %s", filename, strerror(errno)); return false; } @@ -2880,7 +2950,7 @@ CreateOptsFile(int argc, char *argv[]) /* * This should be used only for reporting "interactive" errors (ie, errors - * during startup. Once the postmaster is launched, use elog. + * during startup). Once the postmaster is launched, use ereport. */ void postmaster_error(const char *fmt,...) diff --git a/src/backend/tcop/dest.c b/src/backend/tcop/dest.c index a590cffd35a..76990d34f7c 100644 --- a/src/backend/tcop/dest.c +++ b/src/backend/tcop/dest.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/dest.c,v 1.58 2003/05/08 18:16:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/dest.c,v 1.59 2003/07/22 19:00:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -104,7 +104,7 @@ CreateDestReceiver(CommandDest dest, Portal portal) case Remote: case RemoteExecute: if (portal == NULL) - elog(ERROR, "CreateDestReceiver: no portal specified"); + elog(ERROR, "no portal specified for Remote receiver"); return printtup_create_DR(dest, portal); case None: @@ -118,10 +118,10 @@ CreateDestReceiver(CommandDest dest, Portal portal) case Tuplestore: if (portal == NULL) - elog(ERROR, "CreateDestReceiver: no portal specified"); + elog(ERROR, "no portal specified for Tuplestore receiver"); if (portal->holdStore == NULL || portal->holdContext == NULL) - elog(ERROR, "CreateDestReceiver: portal has no holdStore"); + elog(ERROR, "portal has no holdStore"); return CreateTuplestoreDestReceiver(portal->holdStore, portal->holdContext); } diff --git a/src/backend/tcop/fastpath.c b/src/backend/tcop/fastpath.c index 37b7c3d8d9d..7ab856d6131 100644 --- a/src/backend/tcop/fastpath.c +++ b/src/backend/tcop/fastpath.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.64 2003/05/09 18:18:54 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.65 2003/07/22 19:00:11 tgl Exp $ * * NOTES * This cruft is the server side of PQfn. @@ -101,8 +101,10 @@ GetOldFunctionMessage(StringInfo buf) if (argsize < -1) { /* FATAL here since no hope of regaining message sync */ - elog(FATAL, "HandleFunctionRequest: bogus argsize %d", - argsize); + ereport(FATAL, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("invalid argument size %d in function call message", + argsize))); } /* and arg contents */ if (argsize > 0) @@ -180,7 +182,9 @@ SendFunctionResult(Datum retval, bool isnull, Oid rettype, int16 format) pfree(outputbytes); } else - elog(ERROR, "Invalid format code %d", format); + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("unsupported format code: %d", format))); } if (!newstyle) @@ -208,7 +212,7 @@ fetch_fp_info(Oid func_id, struct fp_info * fip) * Since the validity of this structure is determined by whether the * funcid is OK, we clear the funcid here. It must not be set to the * correct value until we are about to return with a good struct - * fp_info, since we can be interrupted (i.e., with an elog(ERROR, + * fp_info, since we can be interrupted (i.e., with an ereport(ERROR, * ...)) at any time. [No longer really an issue since we don't save * the struct fp_info across transactions anymore, but keep it * anyway.] @@ -222,8 +226,9 @@ fetch_fp_info(Oid func_id, struct fp_info * fip) ObjectIdGetDatum(func_id), 0, 0, 0); if (!HeapTupleIsValid(func_htp)) - elog(ERROR, "fetch_fp_info: cache lookup for function %u failed", - func_id); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("function with OID %u does not exist", func_id))); pp = (Form_pg_proc) GETSTRUCT(func_htp); fip->namespace = pp->pronamespace; @@ -254,8 +259,8 @@ fetch_fp_info(Oid func_id, struct fp_info * fip) * RETURNS: * 0 if successful completion, EOF if frontend connection lost. * - * Note: All ordinary errors result in elog(ERROR,...). However, - * if we lose the frontend connection there is no one to elog to, + * Note: All ordinary errors result in ereport(ERROR,...). However, + * if we lose the frontend connection there is no one to ereport to, * and no use in proceeding... * * Note: palloc()s done here and in the called function do not need to be @@ -282,19 +287,23 @@ HandleFunctionRequest(StringInfo msgBuf) { if (GetOldFunctionMessage(msgBuf)) { - elog(COMMERROR, "unexpected EOF on client connection"); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("unexpected EOF on client connection"))); return EOF; } } /* * Now that we've eaten the input message, check to see if we actually - * want to do the function call or not. It's now safe to elog(); we won't - * lose sync with the frontend. + * want to do the function call or not. It's now safe to ereport(); + * we won't lose sync with the frontend. */ if (IsAbortedTransactionBlockState()) - elog(ERROR, "current transaction is aborted, " - "queries ignored until end of transaction block"); + ereport(ERROR, + (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION), + errmsg("current transaction is aborted, " + "queries ignored until end of transaction block"))); /* * Begin parsing the buffer contents. @@ -404,14 +413,18 @@ parse_fcall_arguments(StringInfo msgBuf, struct fp_info *fip, nargs = pq_getmsgint(msgBuf, 2); /* # of arguments */ if (fip->flinfo.fn_nargs != nargs || nargs > FUNC_MAX_ARGS) - elog(ERROR, "HandleFunctionRequest: actual arguments (%d) != registered arguments (%d)", - nargs, fip->flinfo.fn_nargs); + ereport(ERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("function call message contains %d arguments but function requires %d", + nargs, fip->flinfo.fn_nargs))); fcinfo->nargs = nargs; if (numAFormats > 1 && numAFormats != nargs) - elog(ERROR, "Function Call message has %d argument formats but %d arguments", - numAFormats, nargs); + ereport(ERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("function call message contains %d argument formats but %d arguments", + numAFormats, nargs))); initStringInfo(&abuf); @@ -430,8 +443,10 @@ parse_fcall_arguments(StringInfo msgBuf, struct fp_info *fip, continue; } if (argsize < 0) - elog(ERROR, "HandleFunctionRequest: bogus argsize %d", - argsize); + ereport(ERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("invalid argument size %d in function call message", + argsize))); /* Reset abuf to empty, and insert raw data into it */ abuf.len = 0; @@ -489,11 +504,15 @@ parse_fcall_arguments(StringInfo msgBuf, struct fp_info *fip, /* Trouble if it didn't eat the whole buffer */ if (abuf.cursor != abuf.len) - elog(ERROR, "Improper binary format in function argument %d", - i + 1); + ereport(ERROR, + (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), + errmsg("incorrect binary data format in function argument %d", + i + 1))); } else - elog(ERROR, "Invalid format code %d", aformat); + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("unsupported format code: %d", aformat))); } /* Return result format code */ @@ -517,8 +536,10 @@ parse_fcall_arguments_20(StringInfo msgBuf, struct fp_info *fip, nargs = pq_getmsgint(msgBuf, 4); /* # of arguments */ if (fip->flinfo.fn_nargs != nargs || nargs > FUNC_MAX_ARGS) - elog(ERROR, "HandleFunctionRequest: actual arguments (%d) != registered arguments (%d)", - nargs, fip->flinfo.fn_nargs); + ereport(ERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("function call message contains %d arguments but function requires %d", + nargs, fip->flinfo.fn_nargs))); fcinfo->nargs = nargs; @@ -545,8 +566,10 @@ parse_fcall_arguments_20(StringInfo msgBuf, struct fp_info *fip, continue; } if (argsize < 0) - elog(ERROR, "HandleFunctionRequest: bogus argsize %d", - argsize); + ereport(ERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("invalid argument size %d in function call message", + argsize))); /* Reset abuf to empty, and insert raw data into it */ abuf.len = 0; @@ -566,8 +589,10 @@ parse_fcall_arguments_20(StringInfo msgBuf, struct fp_info *fip, /* Trouble if it didn't eat the whole buffer */ if (abuf.cursor != abuf.len) - elog(ERROR, "Improper binary format in function argument %d", - i + 1); + ereport(ERROR, + (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), + errmsg("incorrect binary data format in function argument %d", + i + 1))); } /* Desired result format is always binary in protocol 2.0 */ diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index f0c2254edd8..ae4a50629f3 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.350 2003/07/09 06:47:34 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.351 2003/07/22 19:00:11 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -275,7 +275,9 @@ SocketBackend(StringInfo inBuf) if (qtype == EOF) /* frontend disconnected */ { - elog(COMMERROR, "unexpected EOF on client connection"); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("unexpected EOF on client connection"))); return qtype; } @@ -296,7 +298,9 @@ SocketBackend(StringInfo inBuf) /* old style without length word; convert */ if (pq_getstring(inBuf)) { - elog(COMMERROR, "unexpected EOF on client connection"); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("unexpected EOF on client connection"))); return EOF; } } @@ -321,7 +325,9 @@ SocketBackend(StringInfo inBuf) doing_extended_query_message = true; /* these are only legal in protocol 3 */ if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3) - elog(FATAL, "Socket command type %c unknown", qtype); + ereport(FATAL, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("invalid frontend message type %d", qtype))); break; case 'S': /* sync */ @@ -331,7 +337,9 @@ SocketBackend(StringInfo inBuf) doing_extended_query_message = false; /* only legal in protocol 3 */ if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3) - elog(FATAL, "Socket command type %c unknown", qtype); + ereport(FATAL, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("invalid frontend message type %d", qtype))); break; case 'd': /* copy data */ @@ -340,7 +348,9 @@ SocketBackend(StringInfo inBuf) doing_extended_query_message = false; /* these are only legal in protocol 3 */ if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3) - elog(FATAL, "Socket command type %c unknown", qtype); + ereport(FATAL, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("invalid frontend message type %d", qtype))); break; default: @@ -349,7 +359,9 @@ SocketBackend(StringInfo inBuf) * as fatal because we have probably lost message boundary sync, * and there's no good way to recover. */ - elog(FATAL, "Socket command type %c unknown", qtype); + ereport(FATAL, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("invalid frontend message type %d", qtype))); break; } @@ -446,7 +458,8 @@ pg_parse_query(const char *query_string) List *raw_parsetree_list; if (log_statement) - elog(LOG, "query: %s", query_string); + ereport(LOG, + (errmsg("query: %s", query_string))); if (log_parser_stats) ResetUsage(); @@ -544,7 +557,8 @@ pg_rewrite_queries(List *querytree_list) new_list = (List *) copyObject(querytree_list); /* This checks both copyObject() and the equal() routines... */ if (!equal(new_list, querytree_list)) - elog(WARNING, "pg_rewrite_queries: copyObject failed on parse tree"); + ereport(WARNING, + (errmsg("copyObject failed to produce an equal parse tree"))); else querytree_list = new_list; #endif @@ -588,7 +602,8 @@ pg_plan_query(Query *querytree) #ifdef NOT_USED /* This checks both copyObject() and the equal() routines... */ if (!equal(new_plan, plan)) - elog(WARNING, "pg_plan_query: copyObject failed on plan tree"); + ereport(WARNING, + (errmsg("copyObject failed to produce an equal plan tree"))); else #endif plan = new_plan; @@ -774,8 +789,10 @@ exec_simple_query(const char *query_string) } if (!allowit) - elog(ERROR, "current transaction is aborted, " - "queries ignored until end of transaction block"); + ereport(ERROR, + (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION), + errmsg("current transaction is aborted, " + "queries ignored until end of transaction block"))); } /* Make sure we are in a transaction command */ @@ -936,19 +953,21 @@ exec_simple_query(const char *query_string) * min duration. */ if (usecs >= save_log_min_duration_statement * 1000) - elog(LOG, "duration_statement: %ld.%06ld %s", - (long) (stop_t.tv_sec - start_t.tv_sec), - (long) (stop_t.tv_usec - start_t.tv_usec), - query_string); + ereport(LOG, + (errmsg("duration_statement: %ld.%06ld %s", + (long) (stop_t.tv_sec - start_t.tv_sec), + (long) (stop_t.tv_usec - start_t.tv_usec), + query_string))); /* * If the user is requesting logging of all durations, then log * that as well. */ if (save_log_duration) - elog(LOG, "duration: %ld.%06ld sec", - (long) (stop_t.tv_sec - start_t.tv_sec), - (long) (stop_t.tv_usec - start_t.tv_usec)); + ereport(LOG, + (errmsg("duration: %ld.%06ld sec", + (long) (stop_t.tv_sec - start_t.tv_sec), + (long) (stop_t.tv_usec - start_t.tv_usec)))); } if (save_log_statement_stats) @@ -1050,7 +1069,9 @@ exec_parse_message(const char *query_string, /* string to execute */ * to worry about multiple result tupdescs and things like that. */ if (length(parsetree_list) > 1) - elog(ERROR, "Cannot insert multiple commands into a prepared statement"); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("cannot insert multiple commands into a prepared statement"))); if (parsetree_list != NIL) { @@ -1084,8 +1105,10 @@ exec_parse_message(const char *query_string, /* string to execute */ } if (!allowit) - elog(ERROR, "current transaction is aborted, " - "queries ignored until end of transaction block"); + ereport(ERROR, + (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION), + errmsg("current transaction is aborted, " + "queries ignored until end of transaction block"))); } /* @@ -1110,8 +1133,10 @@ exec_parse_message(const char *query_string, /* string to execute */ Oid ptype = paramTypes[i]; if (ptype == InvalidOid || ptype == UNKNOWNOID) - elog(ERROR, "Could not determine datatype of parameter $%d", - i + 1); + ereport(ERROR, + (errcode(ERRCODE_INDETERMINATE_DATATYPE), + errmsg("could not determine datatype of parameter $%d", + i + 1))); param_list = lappendo(param_list, ptype); } @@ -1237,8 +1262,10 @@ exec_bind_message(StringInfo input_message) numParams = pq_getmsgint(input_message, 2); if (numPFormats > 1 && numPFormats != numParams) - elog(ERROR, "BIND message has %d parameter formats but %d parameters", - numPFormats, numParams); + ereport(ERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("bind message has %d parameter formats but %d parameters", + numPFormats, numParams))); /* Find prepared statement */ if (stmt_name[0] != '\0') @@ -1248,12 +1275,16 @@ exec_bind_message(StringInfo input_message) /* special-case the unnamed statement */ pstmt = unnamed_stmt_pstmt; if (!pstmt) - elog(ERROR, "Unnamed prepared statement does not exist"); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_PSTATEMENT), + errmsg("unnamed prepared statement does not exist"))); } if (numParams != length(pstmt->argtype_list)) - elog(ERROR, "Bind message supplies %d parameters, but prepared statement \"%s\" requires %d", - numParams, stmt_name, length(pstmt->argtype_list)); + ereport(ERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("bind message supplies %d parameters, but prepared statement \"%s\" requires %d", + numParams, stmt_name, length(pstmt->argtype_list)))); /* * Create the portal. Allow silent replacement of an existing portal @@ -1375,12 +1406,17 @@ exec_bind_message(StringInfo input_message) /* Trouble if it didn't eat the whole buffer */ if (pbuf.cursor != pbuf.len) - elog(ERROR, "Improper binary format in BIND parameter %d", - i + 1); + ereport(ERROR, + (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), + errmsg("incorrect binary data format in bind parameter %d", + i + 1))); } else { - elog(ERROR, "Invalid format code %d", pformat); + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("unsupported format code: %d", + pformat))); } /* Restore message buffer contents */ @@ -1453,7 +1489,9 @@ exec_execute_message(const char *portal_name, long max_rows) portal = GetPortalByName(portal_name); if (!PortalIsValid(portal)) - elog(ERROR, "Portal \"%s\" not found", portal_name); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_CURSOR), + errmsg("portal \"%s\" does not exist", portal_name))); /* * If the original query was a null string, just return EmptyQueryResponse. @@ -1517,8 +1555,10 @@ exec_execute_message(const char *portal_name, long max_rows) if (IsAbortedTransactionBlockState()) { if (!is_trans_exit) - elog(ERROR, "current transaction is aborted, " - "queries ignored until end of transaction block"); + ereport(ERROR, + (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION), + errmsg("current transaction is aborted, " + "queries ignored until end of transaction block"))); } /* Check for cancel signal before we start execution */ @@ -1591,7 +1631,9 @@ exec_describe_statement_message(const char *stmt_name) /* special-case the unnamed statement */ pstmt = unnamed_stmt_pstmt; if (!pstmt) - elog(ERROR, "Unnamed prepared statement does not exist"); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_PSTATEMENT), + errmsg("unnamed prepared statement does not exist"))); } if (whereToSendOutput != Remote) @@ -1642,7 +1684,9 @@ exec_describe_portal_message(const char *portal_name) portal = GetPortalByName(portal_name); if (!PortalIsValid(portal)) - elog(ERROR, "Portal \"%s\" not found", portal_name); + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_CURSOR), + errmsg("portal \"%s\" does not exist", portal_name))); if (whereToSendOutput != Remote) return; /* can't actually do anything... */ @@ -1724,13 +1768,19 @@ void quickdie(SIGNAL_ARGS) { PG_SETMASK(&BlockSig); - elog(WARNING, "Message from PostgreSQL backend:" - "\n\tThe Postmaster has informed me that some other backend" - "\n\tdied abnormally and possibly corrupted shared memory." - "\n\tI have rolled back the current transaction and am" - "\n\tgoing to terminate your database system connection and exit." - "\n\tPlease reconnect to the database system and repeat your query."); - + /* + * Ideally this should be ereport(FATAL), but then we'd not get control + * back (perhaps could fix by doing local sigsetjmp?) + */ + ereport(WARNING, + (errcode(ERRCODE_CRASH_SHUTDOWN), + errmsg("terminating connection due to crash of another backend"), + errdetail("The postmaster has commanded this backend to roll back" + " the current transaction and exit, because another" + " backend exited abnormally and possibly corrupted" + " shared memory."), + errhint("In a moment you should be able to reconnect to the" + " database and repeat your query."))); /* * DO NOT proc_exit() -- we're here because shared memory may be * corrupted, so we don't want to try to clean up our transaction. @@ -1741,7 +1791,6 @@ quickdie(SIGNAL_ARGS) * random backend. This is necessary precisely because we don't clean * up our shared memory state. */ - exit(1); } @@ -1842,9 +1891,12 @@ StatementCancelHandler(SIGNAL_ARGS) static void FloatExceptionHandler(SIGNAL_ARGS) { - elog(ERROR, "floating point exception!" - " The last floating point operation either exceeded legal ranges" - " or was a divide by zero"); + ereport(ERROR, + (errcode(ERRCODE_FLOATING_POINT_EXCEPTION), + errmsg("floating-point exception"), + errdetail("An invalid floating-point operation was signaled. " + "This probably means an out-of-range result or an " + "invalid operation, such as division by zero."))); } /* SIGHUP: set flag to re-read config file at next convenient time */ @@ -1875,14 +1927,18 @@ ProcessInterrupts(void) QueryCancelPending = false; /* ProcDie trumps QueryCancel */ ImmediateInterruptOK = false; /* not idle anymore */ DisableNotifyInterrupt(); - elog(FATAL, "This connection has been terminated by the administrator."); + ereport(FATAL, + (errcode(ERRCODE_ADMIN_SHUTDOWN), + errmsg("terminating connection due to administrator command"))); } if (QueryCancelPending) { QueryCancelPending = false; ImmediateInterruptOK = false; /* not idle anymore */ DisableNotifyInterrupt(); - elog(ERROR, "Query was canceled."); + ereport(ERROR, + (errcode(ERRCODE_QUERY_CANCELED), + errmsg("canceling query due to user request"))); } /* If we get here, do nothing (probably, QueryCancelPending was reset) */ } @@ -2028,7 +2084,9 @@ PostgresMain(int argc, char *argv[], const char *username) #ifdef USE_ASSERT_CHECKING SetConfigOption("debug_assertions", optarg, ctx, gucsource); #else - elog(WARNING, "Assert checking is not compiled in"); + ereport(WARNING, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("assert checking is not compiled in"))); #endif break; @@ -2313,9 +2371,15 @@ PostgresMain(int argc, char *argv[], const char *username) if (!value) { if (flag == '-') - elog(ERROR, "--%s requires argument", optarg); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("--%s requires a value", + optarg))); else - elog(ERROR, "-c %s requires argument", optarg); + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("-c %s requires a value", + optarg))); } SetConfigOption(name, value, ctx, gucsource); @@ -2372,7 +2436,9 @@ PostgresMain(int argc, char *argv[], const char *username) if (log_statement_stats && (log_parser_stats || log_planner_stats || log_executor_stats)) { - elog(WARNING, "Query statistics are disabled because parser, planner, or executor statistics are on."); + ereport(WARNING, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("query-level statistics are disabled because parser, planner, or executor statistics are on"))); SetConfigOption("show_statement_stats", "false", ctx, gucsource); } @@ -2452,10 +2518,10 @@ PostgresMain(int argc, char *argv[], const char *username) /* noninteractive case: nothing should be left after switches */ if (errs || argc != optind || dbname == NULL) { - elog(WARNING, "%s: invalid command line arguments\nTry -? for help.", - argv[0]); - proc_exit(0); /* not 1, that causes system-wide - * restart... */ + ereport(FATAL, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("invalid backend command-line arguments"), + errhint("Try -? for help."))); } BaseInit(); #ifdef EXECBACKEND @@ -2467,17 +2533,20 @@ PostgresMain(int argc, char *argv[], const char *username) /* interactive case: database name can be last arg on command line */ if (errs || argc - optind > 1) { - elog(WARNING, "%s: invalid command line arguments\nTry -? for help.", - argv[0]); - proc_exit(1); + ereport(FATAL, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("%s: invalid command-line arguments", + argv[0]), + errhint("Try -? for help."))); } else if (argc - optind == 1) dbname = argv[optind]; else if ((dbname = username) == NULL) { - elog(WARNING, "%s: user name undefined and no database specified", - argv[0]); - proc_exit(1); + ereport(FATAL, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("%s: no database nor user name specified", + argv[0]))); } /* @@ -2485,8 +2554,9 @@ PostgresMain(int argc, char *argv[], const char *username) * pathname. (If under postmaster, this was done already.) */ if (FindExec(pg_pathname, argv[0], "postgres") < 0) - elog(FATAL, "%s: could not locate executable, bailing out...", - argv[0]); + ereport(FATAL, + (errmsg("%s: could not locate postgres executable", + argv[0]))); /* * Validate we have been given a reasonable-looking DataDir (if @@ -2556,7 +2626,7 @@ PostgresMain(int argc, char *argv[], const char *username) if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.350 $ $Date: 2003/07/09 06:47:34 $\n"); + puts("$Revision: 1.351 $ $Date: 2003/07/22 19:00:11 $\n"); } /* @@ -2594,7 +2664,7 @@ PostgresMain(int argc, char *argv[], const char *username) * * Make sure we're not interrupted while cleaning up. Also forget * any pending QueryCancel request, since we're aborting anyway. - * Force InterruptHoldoffCount to a known state in case we elog'd + * Force InterruptHoldoffCount to a known state in case we ereport'd * from inside a holdoff section. */ ImmediateInterruptOK = false; @@ -2648,7 +2718,7 @@ PostgresMain(int argc, char *argv[], const char *username) RESUME_INTERRUPTS(); } - Warn_restart_ready = true; /* we can now handle elog(ERROR) */ + Warn_restart_ready = true; /* we can now handle ereport(ERROR) */ PG_SETMASK(&UnBlockSig); @@ -2826,7 +2896,7 @@ PostgresMain(int argc, char *argv[], const char *username) /* lost frontend connection during F message input */ /* - * Reset whereToSendOutput to prevent elog from + * Reset whereToSendOutput to prevent ereport from * attempting to send any more messages to client. */ if (whereToSendOutput == Remote) @@ -2877,8 +2947,10 @@ PostgresMain(int argc, char *argv[], const char *username) } break; default: - elog(ERROR, "Invalid Close message subtype %d", - close_type); + ereport(ERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("invalid CLOSE message subtype %d", + close_type))); break; } @@ -2905,8 +2977,10 @@ PostgresMain(int argc, char *argv[], const char *username) exec_describe_portal_message(describe_target); break; default: - elog(ERROR, "Invalid Describe message subtype %d", - describe_type); + ereport(ERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("invalid DESCRIBE message subtype %d", + describe_type))); break; } } @@ -2933,7 +3007,7 @@ PostgresMain(int argc, char *argv[], const char *username) case EOF: /* - * Reset whereToSendOutput to prevent elog from attempting + * Reset whereToSendOutput to prevent ereport from attempting * to send any more messages to client. */ if (whereToSendOutput == Remote) @@ -2959,7 +3033,10 @@ PostgresMain(int argc, char *argv[], const char *username) break; default: - elog(FATAL, "Socket command type %c unknown", firstchar); + ereport(FATAL, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("invalid frontend message type %d", + firstchar))); } #ifdef MEMORY_CONTEXT_CHECKING @@ -3088,7 +3165,9 @@ ShowUsage(const char *title) if (str.data[str.len - 1] == '\n') str.data[--str.len] = '\0'; - elog(LOG, "%s\n%s", title, str.data); + ereport(LOG, + (errmsg_internal("%s", title), + errdetail("%s", str.data))); pfree(str.data); } diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c index 1cad3ec31a3..cd9f49f4612 100644 --- a/src/backend/tcop/pquery.c +++ b/src/backend/tcop/pquery.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.66 2003/05/28 16:03:58 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.67 2003/07/22 19:00:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -341,8 +341,10 @@ PortalSetResultFormat(Portal portal, int nFormats, int16 *formats) { /* format specified for each column */ if (nFormats != natts) - elog(ERROR, "BIND message has %d result formats but query has %d columns", - nFormats, natts); + ereport(ERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("bind message has %d result formats but query has %d columns", + nFormats, natts))); memcpy(portal->formats, formats, natts * sizeof(int16)); } else if (nFormats > 0) { @@ -401,9 +403,13 @@ PortalRun(Portal portal, long count, * Check for improper portal use, and mark portal active. */ if (portal->portalDone) - elog(ERROR, "Portal \"%s\" cannot be run anymore", portal->name); + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("portal \"%s\" cannot be run anymore", portal->name))); if (portal->portalActive) - elog(ERROR, "Portal \"%s\" already active", portal->name); + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("portal \"%s\" already active", portal->name))); portal->portalActive = true; /* @@ -468,7 +474,8 @@ PortalRun(Portal portal, long count, break; default: - elog(ERROR, "PortalRun: bogus portal strategy"); + elog(ERROR, "unrecognized portal strategy: %d", + (int) portal->strategy); result = false; /* keep compiler quiet */ break; } @@ -577,8 +584,10 @@ PortalRunSelect(Portal portal, else { if (portal->cursorOptions & CURSOR_OPT_NO_SCROLL) - elog(ERROR, "Cursor can only scan forward" - "\n\tDeclare it with SCROLL option to enable backward scan"); + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("cursor can only scan forward"), + errhint("Declare it with SCROLL option to enable backward scan."))); if (portal->atStart || count <= 0) direction = NoMovementScanDirection; @@ -900,9 +909,13 @@ PortalRunFetch(Portal portal, * Check for improper portal use, and mark portal active. */ if (portal->portalDone) - elog(ERROR, "Portal \"%s\" cannot be run anymore", portal->name); + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("portal \"%s\" cannot be run anymore", portal->name))); if (portal->portalActive) - elog(ERROR, "Portal \"%s\" already active", portal->name); + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("portal \"%s\" already active", portal->name))); portal->portalActive = true; /* @@ -922,7 +935,7 @@ PortalRunFetch(Portal portal, break; default: - elog(ERROR, "PortalRunFetch: unsupported portal strategy"); + elog(ERROR, "unsupported portal strategy"); result = 0; /* keep compiler quiet */ break; } @@ -1053,7 +1066,7 @@ DoPortalRunFetch(Portal portal, } break; default: - elog(ERROR, "PortalRunFetch: bogus direction"); + elog(ERROR, "bogus direction"); break; } diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index be47708d4b1..068ae2a724f 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.201 2003/06/27 14:45:30 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.202 2003/07/22 19:00:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -60,69 +60,90 @@ * Error-checking support for DROP commands */ -struct kindstrings +struct msgstrings { char kind; - char *indef_article; - char *name; - char *command; + int nonexistent_code; + const char *nonexistent_msg; + const char *nota_msg; + const char *drophint_msg; }; -static struct kindstrings kindstringarray[] = { - {RELKIND_RELATION, "a", "table", "TABLE"}, - {RELKIND_SEQUENCE, "a", "sequence", "SEQUENCE"}, - {RELKIND_VIEW, "a", "view", "VIEW"}, - {RELKIND_INDEX, "an", "index", "INDEX"}, - {RELKIND_COMPOSITE_TYPE, "a", "type", "TYPE"}, - {'\0', "a", "???", "???"} +static const struct msgstrings msgstringarray[] = { + { RELKIND_RELATION, + ERRCODE_UNDEFINED_TABLE, + gettext_noop("table \"%s\" does not exist"), + 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("\"%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("\"%s\" is not a view"), + gettext_noop("Use DROP VIEW to remove a view.") }, + { RELKIND_INDEX, + ERRCODE_UNDEFINED_OBJECT, + gettext_noop("index \"%s\" does not exist"), + 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("\"%s\" is not a type"), + gettext_noop("Use DROP TYPE to remove a type.") }, + { '\0', 0, NULL, NULL, NULL } }; static void DropErrorMsg(char *relname, char wrongkind, char rightkind) { - struct kindstrings *rentry; - struct kindstrings *wentry; + const struct msgstrings *rentry; + const struct msgstrings *wentry; - for (rentry = kindstringarray; rentry->kind != '\0'; rentry++) + for (rentry = msgstringarray; rentry->kind != '\0'; rentry++) if (rentry->kind == rightkind) break; Assert(rentry->kind != '\0'); - for (wentry = kindstringarray; wentry->kind != '\0'; wentry++) + for (wentry = msgstringarray; wentry->kind != '\0'; wentry++) if (wentry->kind == wrongkind) break; /* wrongkind could be something we don't have in our table... */ - if (wentry->kind != '\0') - elog(ERROR, "\"%s\" is not %s %s. Use DROP %s to remove %s %s", - relname, rentry->indef_article, rentry->name, - wentry->command, wentry->indef_article, wentry->name); - else - elog(ERROR, "\"%s\" is not %s %s", - relname, rentry->indef_article, rentry->name); + + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg(rentry->nota_msg, relname), + (wentry->kind != '\0') ? errhint(wentry->drophint_msg) : 0)); } static void CheckDropPermissions(RangeVar *rel, char rightkind) { - struct kindstrings *rentry; + const struct msgstrings *rentry; Oid relOid; HeapTuple tuple; Form_pg_class classform; - for (rentry = kindstringarray; rentry->kind != '\0'; rentry++) + for (rentry = msgstringarray; rentry->kind != '\0'; rentry++) if (rentry->kind == rightkind) break; Assert(rentry->kind != '\0'); relOid = RangeVarGetRelid(rel, true); if (!OidIsValid(relOid)) - elog(ERROR, "%s \"%s\" does not exist", rentry->name, rel->relname); + ereport(ERROR, + (errcode(rentry->nonexistent_code), + errmsg(rentry->nonexistent_msg, rel->relname))); tuple = SearchSysCache(RELOID, ObjectIdGetDatum(relOid), 0, 0, 0); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "%s \"%s\" does not exist", rentry->name, rel->relname); + elog(ERROR, "cache lookup failed for relation %u", relOid); classform = (Form_pg_class) GETSTRUCT(tuple); @@ -135,14 +156,22 @@ CheckDropPermissions(RangeVar *rel, char rightkind) aclcheck_error(ACLCHECK_NOT_OWNER, rel->relname); if (!allowSystemTableMods && IsSystemClass(classform)) - elog(ERROR, "%s \"%s\" is a system %s", - rentry->name, rel->relname, rentry->name); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("\"%s\" is a system catalog", + rel->relname))); ReleaseSysCache(tuple); } -static void -CheckOwnership(RangeVar *rel, bool noCatalogs) +/* + * Verify user has ownership of specified relation, else ereport. + * + * If noCatalogs is true then we also deny access to system catalogs, + * except when allowSystemTableMods is true. + */ +void +CheckRelationOwnership(RangeVar *rel, bool noCatalogs) { Oid relOid; HeapTuple tuple; @@ -151,8 +180,8 @@ CheckOwnership(RangeVar *rel, bool noCatalogs) tuple = SearchSysCache(RELOID, ObjectIdGetDatum(relOid), 0, 0, 0); - if (!HeapTupleIsValid(tuple)) - elog(ERROR, "Relation \"%s\" does not exist", rel->relname); + if (!HeapTupleIsValid(tuple)) /* should not happen */ + elog(ERROR, "cache lookup failed for relation %u", relOid); if (!pg_class_ownercheck(relOid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, rel->relname); @@ -161,8 +190,10 @@ CheckOwnership(RangeVar *rel, bool noCatalogs) { if (!allowSystemTableMods && IsSystemClass((Form_pg_class) GETSTRUCT(tuple))) - elog(ERROR, "relation \"%s\" is a system catalog", - rel->relname); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("\"%s\" is a system catalog", + rel->relname))); } ReleaseSysCache(tuple); @@ -222,10 +253,13 @@ check_xact_readonly(Node *parsetree) case T_DropUserStmt: case T_GrantStmt: case T_TruncateStmt: - elog(ERROR, "transaction is read-only"); + ereport(ERROR, + (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION), + errmsg("transaction is read-only"))); break; default: - /*nothing*/; + /* do nothing */ + break; } } @@ -407,7 +441,9 @@ ProcessUtility(Node *parsetree, break; default: - elog(ERROR, "invalid object type for DropStmt: %d", stmt->removeType); + elog(ERROR, "unrecognized drop object type: %d", + (int) stmt->removeType); + break; } /* @@ -551,7 +587,9 @@ ProcessUtility(Node *parsetree, case 'U': /* ALTER OWNER */ /* check that we are the superuser */ if (!superuser()) - elog(ERROR, "ALTER TABLE: permission denied"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied"))); /* get_usesysid raises an error if no such user */ AlterTableOwner(relid, get_usesysid(stmt->name)); @@ -565,8 +603,8 @@ ProcessUtility(Node *parsetree, false); break; default: /* oops */ - elog(ERROR, "ProcessUtility: Invalid type for AlterTableStmt: %d", - stmt->subtype); + elog(ERROR, "unrecognized alter table type: %d", + (int) stmt->subtype); break; } } @@ -611,14 +649,16 @@ ProcessUtility(Node *parsetree, case 'U': /* OWNER TO */ /* check that we are the superuser */ if (!superuser()) - elog(ERROR, "ALTER DOMAIN: permission denied"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied"))); /* get_usesysid raises an error if no such user */ AlterTypeOwner(stmt->typename, get_usesysid(stmt->name)); break; default: /* oops */ - elog(ERROR, "ProcessUtility: Invalid type for AlterDomainStmt: %d", - stmt->subtype); + elog(ERROR, "unrecognized alter domain type: %d", + (int) stmt->subtype); break; } } @@ -650,7 +690,9 @@ ProcessUtility(Node *parsetree, DefineType(stmt->defnames, stmt->definition); break; default: - elog(ERROR, "invalid object type for DefineStmt: %d", stmt->kind); + elog(ERROR, "unrecognized define stmt type: %d", + (int) stmt->kind); + break; } } break; @@ -679,7 +721,7 @@ ProcessUtility(Node *parsetree, { IndexStmt *stmt = (IndexStmt *) parsetree; - CheckOwnership(stmt->relation, true); + CheckRelationOwnership(stmt->relation, true); DefineIndex(stmt->relation, /* relation */ stmt->idxname, /* index name */ @@ -865,7 +907,9 @@ ProcessUtility(Node *parsetree, stmt->behavior); break; default: - elog(ERROR, "invalid object type for DropPropertyStmt: %d", stmt->removeType); + elog(ERROR, "unrecognized object type: %d", + (int) stmt->removeType); + break; } } break; @@ -926,7 +970,9 @@ ProcessUtility(Node *parsetree, case T_CheckPointStmt: if (!superuser()) - elog(ERROR, "CHECKPOINT: permission denied"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied"))); CreateCheckPoint(false, false); break; @@ -937,18 +983,20 @@ ProcessUtility(Node *parsetree, switch (stmt->kind) { case OBJECT_INDEX: - CheckOwnership(stmt->relation, false); + CheckRelationOwnership(stmt->relation, false); ReindexIndex(stmt->relation, stmt->force); break; case OBJECT_TABLE: - CheckOwnership(stmt->relation, false); + CheckRelationOwnership(stmt->relation, false); ReindexTable(stmt->relation, stmt->force); break; case OBJECT_DATABASE: ReindexDatabase(stmt->name, stmt->force, false); break; default: - elog(ERROR, "invalid object type for ReindexStmt: %d", stmt->kind); + elog(ERROR, "unrecognized object type: %d", + (int) stmt->kind); + break; } break; } @@ -975,8 +1023,8 @@ ProcessUtility(Node *parsetree, break; default: - elog(ERROR, "ProcessUtility: command #%d unsupported", - nodeTag(parsetree)); + elog(ERROR, "unrecognized node type: %d", + (int) nodeTag(parsetree)); break; } } @@ -1500,8 +1548,8 @@ CreateCommandTag(Node *parsetree) break; default: - elog(LOG, "CreateCommandTag: unknown parse node type %d", - nodeTag(parsetree)); + elog(NOTICE, "unrecognized node type: %d", + (int) nodeTag(parsetree)); tag = "???"; break; } diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index 4d646b9b926..4564a9f9f21 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -37,7 +37,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.113 2003/07/18 23:20:32 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.114 2003/07/22 19:00:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -572,6 +572,42 @@ errcode_for_file_access(void) return 0; /* return value does not matter */ } +/* + * errcode_for_socket_access --- add SQLSTATE error code to the current error + * + * The SQLSTATE code is chosen based on the saved errno value. We assume + * that the failing operation was some type of socket access. + * + * NOTE: the primary error message string should generally include %m + * when this is used. + */ +int +errcode_for_socket_access(void) +{ + ErrorData *edata = &errordata[errordata_stack_depth]; + + /* we don't bother incrementing recursion_depth */ + CHECK_STACK_DEPTH(); + + switch (edata->saved_errno) + { + /* Loss of connection */ + case EPIPE: +#ifdef ECONNRESET + case ECONNRESET: +#endif + edata->sqlerrcode = ERRCODE_CONNECTION_FAILURE; + break; + + /* All else is classified as internal errors */ + default: + edata->sqlerrcode = ERRCODE_INTERNAL_ERROR; + break; + } + + return 0; /* return value does not matter */ +} + /* * This macro handles expansion of a format string and associated parameters; diff --git a/src/include/tcop/utility.h b/src/include/tcop/utility.h index 38edd4346a8..54098395e3d 100644 --- a/src/include/tcop/utility.h +++ b/src/include/tcop/utility.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: utility.h,v 1.18 2003/05/06 20:26:28 tgl Exp $ + * $Id: utility.h,v 1.19 2003/07/22 19:00:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -25,4 +25,6 @@ extern TupleDesc UtilityTupleDescriptor(Node *parsetree); extern const char *CreateCommandTag(Node *parsetree); +extern void CheckRelationOwnership(RangeVar *rel, bool noCatalogs); + #endif /* UTILITY_H */ diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index 7b08854ebba..732b0e7cfbd 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: elog.h,v 1.53 2003/07/21 20:29:39 tgl Exp $ + * $Id: elog.h,v 1.54 2003/07/22 19:00:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -155,6 +155,8 @@ #define ERRCODE_UNTERMINATED_C_STRING MAKE_SQLSTATE('2','2', '0','2','4') #define ERRCODE_ZERO_LENGTH_CHARACTER_STRING MAKE_SQLSTATE('2','2', '0','0','F') #define ERRCODE_BAD_COPY_FILE_FORMAT MAKE_SQLSTATE('2','2', 'P','0','1') +#define ERRCODE_INVALID_BINARY_REPRESENTATION MAKE_SQLSTATE('2','2', 'P','0','2') +#define ERRCODE_FLOATING_POINT_EXCEPTION MAKE_SQLSTATE('2','2', 'P','0','3') /* Class 23 - Integrity Constraint Violation */ #define ERRCODE_INTEGRITY_CONSTRAINT_VIOLATION MAKE_SQLSTATE('2','3', '0','0','0') @@ -178,6 +180,7 @@ #define ERRCODE_READ_ONLY_SQL_TRANSACTION MAKE_SQLSTATE('2','5', '0','0','6') #define ERRCODE_SCHEMA_AND_DATA_STATEMENT_MIXING_NOT_SUPPORTED MAKE_SQLSTATE('2','5', '0','0','7') #define ERRCODE_NO_ACTIVE_SQL_TRANSACTION MAKE_SQLSTATE('2','5', 'P','0','1') +#define ERRCODE_IN_FAILED_SQL_TRANSACTION MAKE_SQLSTATE('2','5', 'P','0','2') /* Class 26 - Invalid SQL Statement Name */ /* (we take this to mean prepared statements) */ @@ -244,6 +247,7 @@ #define ERRCODE_NAME_TOO_LONG MAKE_SQLSTATE('4','2', '6','2','2') #define ERRCODE_RESERVED_NAME MAKE_SQLSTATE('4','2', '9','3','9') #define ERRCODE_DATATYPE_MISMATCH MAKE_SQLSTATE('4','2', '8','0','4') +#define ERRCODE_INDETERMINATE_DATATYPE MAKE_SQLSTATE('4','2', 'P','1','8') #define ERRCODE_WRONG_OBJECT_TYPE MAKE_SQLSTATE('4','2', '8','0','9') /* * Note: for ERRCODE purposes, we divide namable objects into these categories: @@ -314,11 +318,17 @@ /* Class 57 - Operator Intervention (class borrowed from DB2) */ #define ERRCODE_OPERATOR_INTERVENTION MAKE_SQLSTATE('5','7', '0','0','0') #define ERRCODE_QUERY_CANCELED MAKE_SQLSTATE('5','7', '0','1','4') +#define ERRCODE_ADMIN_SHUTDOWN MAKE_SQLSTATE('5','7', 'P','0','1') +#define ERRCODE_CRASH_SHUTDOWN MAKE_SQLSTATE('5','7', 'P','0','2') +#define ERRCODE_CANNOT_CONNECT_NOW MAKE_SQLSTATE('5','7', 'P','0','3') /* Class 58 - System Error (class borrowed from DB2) */ /* (we define this as errors external to PostgreSQL itself) */ #define ERRCODE_IO_ERROR MAKE_SQLSTATE('5','8', '0','3','0') +/* Class F0 - Configuration File Error (PostgreSQL-specific error class) */ +#define ERRCODE_CONFIG_FILE_ERROR MAKE_SQLSTATE('F','0', '0','0','0') + /* Class XX - Internal Error (PostgreSQL-specific error class) */ /* (this is for "can't-happen" conditions and software bugs) */ #define ERRCODE_INTERNAL_ERROR MAKE_SQLSTATE('X','X', '0','0','0') @@ -361,6 +371,7 @@ extern void errfinish(int dummy, ...); extern int errcode(int sqlerrcode); extern int errcode_for_file_access(void); +extern int errcode_for_socket_access(void); extern int errmsg(const char *fmt, ...) /* This extension allows gcc to check the format string for consistency with diff --git a/src/test/regress/expected/portals.out b/src/test/regress/expected/portals.out index 5122f098431..245edffe543 100644 --- a/src/test/regress/expected/portals.out +++ b/src/test/regress/expected/portals.out @@ -689,8 +689,8 @@ FETCH 1 FROM foo24; (1 row) FETCH BACKWARD 1 FROM foo24; -- should fail -ERROR: Cursor can only scan forward - Declare it with SCROLL option to enable backward scan +ERROR: cursor can only scan forward +HINT: Declare it with SCROLL option to enable backward scan. END; -- -- Cursors outside transaction blocks -- GitLab