aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/timestamp.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2017-01-18 15:21:52 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2017-01-18 15:22:07 -0500
commitc22ecc6562aac895f0f0529707d7bdb460fd2a49 (patch)
tree322a0c455f701565e5df7f4ed5b9d6601d9bc98b /src/backend/utils/adt/timestamp.c
parente509e7f9e3c565043e1186f5a83122d71653d111 (diff)
downloadpostgresql-c22ecc6562aac895f0f0529707d7bdb460fd2a49.tar.gz
postgresql-c22ecc6562aac895f0f0529707d7bdb460fd2a49.zip
Disable transforms that replaced AT TIME ZONE with RelabelType.
These resulted in wrong answers if the relabeled argument could be matched to an index column, as shown in bug #14504 from Evgeniy Kozlov. We might be able to resurrect these optimizations by adjusting the planner's treatment of RelabelType, or by adjusting btree's rules for selecting comparison functions, but either solution will take careful analysis and does not sound like a fit candidate for backpatching. I left the catalog infrastructure in place and just reduced the transform functions to always-return-NULL. This would be necessary anyway in the back branches, and it doesn't seem important to be more invasive in HEAD. Bug introduced by commit b8a18ad48. Back-patch to 9.5 where that came in. Report: https://postgr.es/m/20170118144828.1432.52823@wrigleys.postgresql.org Discussion: https://postgr.es/m/18771.1484759439@sss.pgh.pa.us
Diffstat (limited to 'src/backend/utils/adt/timestamp.c')
-rw-r--r--src/backend/utils/adt/timestamp.c123
1 files changed, 10 insertions, 113 deletions
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index a87f9828b00..f2784da3605 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -5202,84 +5202,15 @@ interval_part(PG_FUNCTION_ARGS)
/* timestamp_zone_transform()
- * If the zone argument of a timestamp_zone() or timestamptz_zone() call is a
- * plan-time constant denoting a zone equivalent to UTC, the call will always
- * return its second argument unchanged. Simplify the expression tree
- * accordingly. Civil time zones almost never qualify, because jurisdictions
- * that follow UTC today have not done so continuously.
+ * The original optimization here caused problems by relabeling Vars that
+ * could be matched to index entries. It might be possible to resurrect it
+ * at some point by teaching the planner to be less cavalier with RelabelType
+ * nodes, but that will take careful analysis.
*/
Datum
timestamp_zone_transform(PG_FUNCTION_ARGS)
{
- Node *func_node = (Node *) PG_GETARG_POINTER(0);
- FuncExpr *expr = (FuncExpr *) func_node;
- Node *ret = NULL;
- Node *zone_node;
-
- Assert(IsA(expr, FuncExpr));
- Assert(list_length(expr->args) == 2);
-
- zone_node = (Node *) linitial(expr->args);
-
- if (IsA(zone_node, Const) &&!((Const *) zone_node)->constisnull)
- {
- text *zone = DatumGetTextPP(((Const *) zone_node)->constvalue);
- char tzname[TZ_STRLEN_MAX + 1];
- char *lowzone;
- int type,
- abbrev_offset;
- pg_tz *tzp;
- bool noop = false;
-
- /*
- * If the timezone is forever UTC+0, the FuncExpr function call is a
- * no-op for all possible timestamps. This passage mirrors code in
- * timestamp_zone().
- */
- text_to_cstring_buffer(zone, tzname, sizeof(tzname));
- lowzone = downcase_truncate_identifier(tzname,
- strlen(tzname),
- false);
- type = DecodeTimezoneAbbrev(0, lowzone, &abbrev_offset, &tzp);
- if (type == TZ || type == DTZ)
- noop = (abbrev_offset == 0);
- else if (type == DYNTZ)
- {
- /*
- * An abbreviation of a single-offset timezone ought not to be
- * configured as a DYNTZ, so don't bother checking.
- */
- }
- else
- {
- long tzname_offset;
-
- tzp = pg_tzset(tzname);
- if (tzp && pg_get_timezone_offset(tzp, &tzname_offset))
- noop = (tzname_offset == 0);
- }
-
- if (noop)
- {
- Node *timestamp = (Node *) lsecond(expr->args);
-
- /* Strip any existing RelabelType node(s) */
- while (timestamp && IsA(timestamp, RelabelType))
- timestamp = (Node *) ((RelabelType *) timestamp)->arg;
-
- /*
- * Replace the FuncExpr with its timestamp argument, relabeled as
- * though the function call had computed it.
- */
- ret = (Node *) makeRelabelType((Expr *) timestamp,
- exprType(func_node),
- exprTypmod(func_node),
- exprCollation(func_node),
- COERCE_EXPLICIT_CAST);
- }
- }
-
- PG_RETURN_POINTER(ret);
+ PG_RETURN_POINTER(NULL);
}
/* timestamp_zone()
@@ -5376,49 +5307,15 @@ timestamp_zone(PG_FUNCTION_ARGS)
}
/* timestamp_izone_transform()
- * If we deduce at plan time that a particular timestamp_izone() or
- * timestamptz_izone() call can only compute tz=0, the call will always return
- * its second argument unchanged. Simplify the expression tree accordingly.
+ * The original optimization here caused problems by relabeling Vars that
+ * could be matched to index entries. It might be possible to resurrect it
+ * at some point by teaching the planner to be less cavalier with RelabelType
+ * nodes, but that will take careful analysis.
*/
Datum
timestamp_izone_transform(PG_FUNCTION_ARGS)
{
- Node *func_node = (Node *) PG_GETARG_POINTER(0);
- FuncExpr *expr = (FuncExpr *) func_node;
- Node *ret = NULL;
- Node *zone_node;
-
- Assert(IsA(expr, FuncExpr));
- Assert(list_length(expr->args) == 2);
-
- zone_node = (Node *) linitial(expr->args);
-
- if (IsA(zone_node, Const) &&!((Const *) zone_node)->constisnull)
- {
- Interval *zone;
-
- zone = DatumGetIntervalP(((Const *) zone_node)->constvalue);
- if (zone->month == 0 && zone->day == 0 && zone->time == 0)
- {
- Node *timestamp = (Node *) lsecond(expr->args);
-
- /* Strip any existing RelabelType node(s) */
- while (timestamp && IsA(timestamp, RelabelType))
- timestamp = (Node *) ((RelabelType *) timestamp)->arg;
-
- /*
- * Replace the FuncExpr with its timestamp argument, relabeled as
- * though the function call had computed it.
- */
- ret = (Node *) makeRelabelType((Expr *) timestamp,
- exprType(func_node),
- exprTypmod(func_node),
- exprCollation(func_node),
- COERCE_EXPLICIT_CAST);
- }
- }
-
- PG_RETURN_POINTER(ret);
+ PG_RETURN_POINTER(NULL);
}
/* timestamp_izone()