aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2016-08-31 13:58:01 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2016-08-31 13:58:01 -0400
commit65a588b4c3b06aefe0b00d6222598d4cff3542c2 (patch)
tree08684c0af1d997a90d7e66eeb8f42022fc79d434
parent679226337ac3f44e784de0a95a8599dfd86401e8 (diff)
downloadpostgresql-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.c26
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;
}
}