diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index fa409d72b7b..6ab2c6435f8 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1933,6 +1933,7 @@ qtext_load_file(Size *buffer_size) char *buf; int fd; struct stat stat; + Size nread; fd = OpenTransientFile(PGSS_TEXT_FILE, O_RDONLY | PG_BINARY, 0); if (fd < 0) @@ -1973,28 +1974,40 @@ qtext_load_file(Size *buffer_size) } /* - * OK, slurp in the file. If we get a short read and errno doesn't get - * set, the reason is probably that garbage collection truncated the file - * since we did the fstat(), so we don't log a complaint --- but we don't - * return the data, either, since it's most likely corrupt due to - * concurrent writes from garbage collection. + * OK, slurp in the file. Windows fails if we try to read more than + * INT_MAX bytes at once, and other platforms might not like that either, + * so read a very large file in 1GB segments. */ - errno = 0; - if (read(fd, buf, stat.st_size) != stat.st_size) + nread = 0; + while (nread < stat.st_size) { - if (errno) - ereport(LOG, - (errcode_for_file_access(), - errmsg("could not read pg_stat_statement file \"%s\": %m", - PGSS_TEXT_FILE))); - free(buf); - CloseTransientFile(fd); - return NULL; + int toread = Min(1024 * 1024 * 1024, stat.st_size - nread); + + /* + * If we get a short read and errno doesn't get set, the reason is + * probably that garbage collection truncated the file since we did + * the fstat(), so we don't log a complaint --- but we don't return + * the data, either, since it's most likely corrupt due to concurrent + * writes from garbage collection. + */ + errno = 0; + if (read(fd, buf + nread, toread) != toread) + { + if (errno) + ereport(LOG, + (errcode_for_file_access(), + errmsg("could not read pg_stat_statement file \"%s\": %m", + PGSS_TEXT_FILE))); + free(buf); + CloseTransientFile(fd); + return NULL; + } + nread += toread; } CloseTransientFile(fd); - *buffer_size = stat.st_size; + *buffer_size = nread; return buf; }