Em sex., 2 de jul. de 2021 às 13:29, Alvaro Herrera <alvhe...@alvh.no-ip.org> escreveu:
> On 2021-Jul-02, Justin Pryzby wrote: > > > On Fri, Jul 02, 2021 at 12:09:23PM +0200, Peter Eisentraut wrote: > > > > The use of InvalidBlockNumber with vac_update_relstats() looks a bit > fishy > > > to me. We are using in the same call 0 as the default for > > > num_all_visible_pages, and we generally elsewhere also use 0 as the > starting > > > value for relpages, so it's not clear to me why it should be -1 or > > > InvalidBlockNumber here. I'd rather leave it "slightly wrong" for now > so it > > > can be checked again. > > > |commit 0e69f705cc1a3df273b38c9883fb5765991e04fe > > |Author: Alvaro Herrera <alvhe...@alvh.no-ip.org> > > |Date: Fri Apr 9 11:29:08 2021 -0400 > > | > > | Set pg_class.reltuples for partitioned tables > > > > 3d35 also affects partitioned tables, and 0e69 appears to do the right > thing by > > preserving relpages=-1 during auto-analyze. > > I suppose the question is what is the value used for. BlockNumber is > typedef'd uint32, an unsigned variable, so using -1 for it is quite > fishy. The weird thing is that in vac_update_relstats we cast it to > (int32) when storing it in the pg_class tuple, so that's quite fishy > too. > > What we really want is for table_block_relation_estimate_size to work > properly. What that does is get the signed-int32 value from pg_class > and cast it back to BlockNumber. If that assignment gets -1 again, then > it's all fine. I didn't test it. > It seems to me that it is happening, but it is risky to make comparisons between different types. 1) #define InvalidBlockNumber 0xFFFFFFFF int main() { unsigned int num_pages; int rel_pages; num_pages = -1; rel_pages = (int) num_pages; printf("num_pages = %u\n", num_pages); printf("rel_pages = %d\n", rel_pages); printf("(num_pages == InvalidBlockNumber) => %u\n", (num_pages == InvalidBlockNumber)); printf("(rel_pages == InvalidBlockNumber) => %u\n", (rel_pages == InvalidBlockNumber)); } num_pages = 4294967295 rel_pages = -1 (num_pages == InvalidBlockNumber) => 1 (rel_pages == InvalidBlockNumber) => 1 /* 17:68: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] */ If num_pages is promoted to uint64 and rel_pages to int64: 2) #define InvalidBlockNumber 0xFFFFFFFF int main() { unsigned long int num_pages; long int rel_pages; num_pages = -1; rel_pages = (int) num_pages; printf("num_pages = %lu\n", num_pages); printf("rel_pages = %ld\n", rel_pages); printf("(num_pages == InvalidBlockNumber) => %u\n", (num_pages == InvalidBlockNumber)); printf("(rel_pages == InvalidBlockNumber) => %u\n", (rel_pages == InvalidBlockNumber)); } num_pages = 18446744073709551615 rel_pages = -1 (num_pages == InvalidBlockNumber) => 0 (rel_pages == InvalidBlockNumber) => 0 /* 17:68: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] */ As Kyotaro said: "they might be different if we forget to widen the constant when widening the types" regards, Ranier Vilela