Hi Tom, thanks for looking. On 2020-May-25, Tom Lane wrote:
> I don't mind if you want to extend that paradigm to also use "wrote only > %d bytes" wording, but the important point is to get the SQLSTATE set on > the basis of ENOSPC rather than whatever random value errno will have > otherwise. Hmm, right -- I was extending the partial read case to apply to a partial write, and we deal with those very differently. I changed the write case to use our standard approach. -- Álvaro Herrera https://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c index d13efc4d98..3817c41225 100644 --- a/src/backend/executor/nodeHashjoin.c +++ b/src/backend/executor/nodeHashjoin.c @@ -882,16 +882,26 @@ ExecHashJoinSaveTuple(MinimalTuple tuple, uint32 hashvalue, } written = BufFileWrite(file, (void *) &hashvalue, sizeof(uint32)); - if (written != sizeof(uint32)) + if (written < 0) + { + /* if write didn't set errno, assume problem is no disk space */ + if (errno == 0) + errno = ENOSPC; ereport(ERROR, (errcode_for_file_access(), errmsg("could not write to hash-join temporary file: %m"))); + } written = BufFileWrite(file, (void *) tuple, tuple->t_len); - if (written != tuple->t_len) + if (written < 0) + { + /* if write didn't set errno, assume problem is no disk space */ + if (errno == 0) + errno = ENOSPC; ereport(ERROR, (errcode_for_file_access(), errmsg("could not write to hash-join temporary file: %m"))); + } } /* @@ -929,20 +939,30 @@ ExecHashJoinGetSavedTuple(HashJoinState *hjstate, ExecClearTuple(tupleSlot); return NULL; } - if (nread != sizeof(header)) + else if (nread < 0) ereport(ERROR, (errcode_for_file_access(), errmsg("could not read from hash-join temporary file: %m"))); + else if (nread != sizeof(header)) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not read from hash-join temporary file: read only %d of %d bytes", + (int) nread, (int) sizeof(header)))); *hashvalue = header[0]; tuple = (MinimalTuple) palloc(header[1]); tuple->t_len = header[1]; nread = BufFileRead(file, (void *) ((char *) tuple + sizeof(uint32)), header[1] - sizeof(uint32)); - if (nread != header[1] - sizeof(uint32)) + if (nread < 0) ereport(ERROR, (errcode_for_file_access(), errmsg("could not read from hash-join temporary file: %m"))); + else if (nread != header[1] - sizeof(uint32)) /* might read zero bytes */ + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not read from hash-join temporary file: read only %d of %d bytes", + (int) nread, (int) (header[1] - sizeof(uint32))))); return ExecStoreMinimalTuple(tuple, tupleSlot, true); }