diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2016-08-31 13:58:01 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2016-08-31 13:58:01 -0400 |
commit | 65a588b4c3b06aefe0b00d6222598d4cff3542c2 (patch) | |
tree | 08684c0af1d997a90d7e66eeb8f42022fc79d434 | |
parent | 679226337ac3f44e784de0a95a8599dfd86401e8 (diff) | |
download | postgresql-65a588b4c3b06aefe0b00d6222598d4cff3542c2.tar.gz postgresql-65a588b4c3b06aefe0b00d6222598d4cff3542c2.zip |
Try to fix portability issue in enum renumbering (again).
The hack embodied in commit 4ba61a487 no longer works after today's change
to allow DatumGetFloat4/Float4GetDatum to be inlined (commit 14cca1bf8).
Probably what's happening is that the faulty compilers are deciding that
the now-inlined assignment is a no-op and so they're not required to
round to float4 width.
We had a bunch of similar issues earlier this year in the degree-based
trig functions, and eventually settled on using volatile intermediate
variables as the least ugly method of forcing recalcitrant compilers
to do what the C standard says (cf commit 82311bcdd). Let's see if
that method works here.
Discussion: <4640.1472664476@sss.pgh.pa.us>
-rw-r--r-- | src/backend/catalog/pg_enum.c | 26 |
1 files changed, 14 insertions, 12 deletions
diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c index af89daa7128..c66f9632c29 100644 --- a/src/backend/catalog/pg_enum.c +++ b/src/backend/catalog/pg_enum.c @@ -315,21 +315,21 @@ restart: newelemorder = nbr_en->enumsortorder + 1; else { - other_nbr_en = (Form_pg_enum) GETSTRUCT(existing[other_nbr_index]); - newelemorder = (nbr_en->enumsortorder + - other_nbr_en->enumsortorder) / 2; - /* - * On some machines, newelemorder may be in a register that's - * wider than float4. We need to force it to be rounded to float4 - * precision before making the following comparisons, or we'll get - * wrong results. (Such behavior violates the C standard, but - * fixing the compilers is out of our reach.) + * The midpoint value computed here has to be rounded to float4 + * precision, else our equality comparisons against the adjacent + * values are meaningless. The most portable way of forcing that + * to happen with non-C-standard-compliant compilers is to store + * it into a volatile variable. */ - newelemorder = DatumGetFloat4(Float4GetDatum(newelemorder)); + volatile float4 midpoint; - if (newelemorder == nbr_en->enumsortorder || - newelemorder == other_nbr_en->enumsortorder) + other_nbr_en = (Form_pg_enum) GETSTRUCT(existing[other_nbr_index]); + midpoint = (nbr_en->enumsortorder + + other_nbr_en->enumsortorder) / 2; + + if (midpoint == nbr_en->enumsortorder || + midpoint == other_nbr_en->enumsortorder) { RenumberEnumType(pg_enum, existing, nelems); /* Clean up and start over */ @@ -337,6 +337,8 @@ restart: ReleaseCatCacheList(list); goto restart; } + + newelemorder = midpoint; } } |