Commit b71310d8 authored by Thomas G. Lockhart's avatar Thomas G. Lockhart

Add guard code to protect from buffer overruns on long date/time input

 strings. Should go back in and look at doing this a bit more elegantly
 and (hopefully) cheaper. Probably not too bad anyway, but it seems a
 shame to scan the strings twice: once for length for this buffer overrun
 protection, and once to parse the line.
Remove use of pow() in date/time handling; was already gone from everything
 *but* the time data types.
Define macros for handling typmod manipulation for date/time types.
 Should be more robust than all of that brute-force inline code.
Rename macros for masking and typmod manipulation to put TIMESTAMP_
 or INTERVAL_ in front of the macro name, to reduce the possibility
 of name space collisions.
parent e025bb7a
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.69 2002/06/20 20:29:36 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.70 2002/08/04 06:44:47 thomas Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -57,6 +57,9 @@ date_in(PG_FUNCTION_ARGS) ...@@ -57,6 +57,9 @@ date_in(PG_FUNCTION_ARGS)
int ftype[MAXDATEFIELDS]; int ftype[MAXDATEFIELDS];
char lowstr[MAXDATELEN + 1]; char lowstr[MAXDATELEN + 1];
if (strlen(str) >= sizeof(lowstr))
elog(ERROR, "Bad date external representation (too long) '%s'", str);
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|| (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tzp) != 0)) || (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tzp) != 0))
elog(ERROR, "Bad date external representation '%s'", str); elog(ERROR, "Bad date external representation '%s'", str);
...@@ -518,6 +521,9 @@ time_in(PG_FUNCTION_ARGS) ...@@ -518,6 +521,9 @@ time_in(PG_FUNCTION_ARGS)
int dtype; int dtype;
int ftype[MAXDATEFIELDS]; int ftype[MAXDATEFIELDS];
if (strlen(str) >= sizeof(lowstr))
elog(ERROR, "Bad time external representation (too long) '%s'", str);
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|| (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, NULL) != 0)) || (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, NULL) != 0))
elog(ERROR, "Bad time external representation '%s'", str); elog(ERROR, "Bad time external representation '%s'", str);
...@@ -606,37 +612,85 @@ time_scale(PG_FUNCTION_ARGS) ...@@ -606,37 +612,85 @@ time_scale(PG_FUNCTION_ARGS)
PG_RETURN_TIMEADT(result); PG_RETURN_TIMEADT(result);
} }
/* AdjustTimeForTypmod()
* Force the precision of the time value to a specified value.
* Uses *exactly* the same code as in AdjustTimestampForTypemod()
* but we make a separate copy because those types do not
* have a fundamental tie together but rather a coincidence of
* implementation. - thomas
*/
static void static void
AdjustTimeForTypmod(TimeADT *time, int32 typmod) AdjustTimeForTypmod(TimeADT *time, int32 typmod)
{ {
if ((typmod >= 0) && (typmod <= MAX_TIME_PRECISION))
{
#ifdef HAVE_INT64_TIMESTAMP #ifdef HAVE_INT64_TIMESTAMP
static int64 TimeScale = INT64CONST(1000000); static const int64 TimeScales[MAX_TIMESTAMP_PRECISION+1] = {
INT64CONST(1000000),
INT64CONST(100000),
INT64CONST(10000),
INT64CONST(1000),
INT64CONST(100),
INT64CONST(10),
INT64CONST(1)
};
static const int64 TimeOffsets[MAX_TIMESTAMP_PRECISION+1] = {
INT64CONST(-500000),
INT64CONST(-50000),
INT64CONST(-5000),
INT64CONST(-500),
INT64CONST(-50),
INT64CONST(-5),
INT64CONST(0)
};
#else #else
static double TimeScale = 1; static const double TimeScales[MAX_TIMESTAMP_PRECISION+1] = {
1,
10,
100,
1000,
10000,
100000,
1000000
};
static const double TimeOffsets[MAX_TIMESTAMP_PRECISION+1] = {
0.5,
0.05,
0.005,
0.0005,
0.00005,
0.000005,
0.0000005
};
#endif #endif
static int32 TimeTypmod = 0;
if (typmod != TimeTypmod) if ((typmod >= 0) && (typmod <= MAX_TIME_PRECISION))
{ {
#ifdef HAVE_INT64_TIMESTAMP #ifdef HAVE_INT64_TIMESTAMP
TimeScale = pow(10.0, (MAX_TIME_PRECISION-typmod)); /* we have different truncation behavior depending on sign */
#else if (*time >= INT64CONST(0))
TimeScale = pow(10.0, typmod); {
#endif *time = ((*time / TimeScales[typmod])
TimeTypmod = typmod; * TimeScales[typmod]);
}
else
{
*time = (((*time + TimeOffsets[typmod]) / TimeScales[typmod])
* TimeScales[typmod]);
} }
#ifdef HAVE_INT64_TIMESTAMP
*time = ((*time / TimeScale) * TimeScale);
if (*time >= INT64CONST(86400000000))
*time -= INT64CONST(86400000000);
#else #else
*time = (rint(((double) *time) * TimeScale) / TimeScale); /* we have different truncation behavior depending on sign */
if (*time >= 0)
if (*time >= 86400) {
*time -= 86400; *time = (rint(((double) *time) * TimeScales[typmod])
/ TimeScales[typmod]);
}
else
{
/* Scale and truncate first, then add to help the rounding behavior */
*time = (rint((((double) *time) * TimeScales[typmod]) + TimeOffsets[typmod])
/ TimeScales[typmod]);
}
#endif #endif
} }
...@@ -1269,6 +1323,10 @@ timetz_in(PG_FUNCTION_ARGS) ...@@ -1269,6 +1323,10 @@ timetz_in(PG_FUNCTION_ARGS)
int dtype; int dtype;
int ftype[MAXDATEFIELDS]; int ftype[MAXDATEFIELDS];
if (strlen(str) >= sizeof(lowstr))
elog(ERROR, "Bad time with time zone"
" external representation (too long) '%s'", str);
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|| (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0)) || (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0))
elog(ERROR, "Bad time external representation '%s'", str); elog(ERROR, "Bad time external representation '%s'", str);
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.30 2002/06/20 20:29:37 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.31 2002/08/04 06:44:47 thomas Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -29,9 +29,6 @@ ...@@ -29,9 +29,6 @@
#include "mb/pg_wchar.h" #include "mb/pg_wchar.h"
#endif #endif
#define MASK(b) (1 << (b))
#define MAX_INT32_LEN 11 #define MAX_INT32_LEN 11
#define _textin(str) DirectFunctionCall1(textin, CStringGetDatum(str)) #define _textin(str) DirectFunctionCall1(textin, CStringGetDatum(str))
...@@ -258,52 +255,63 @@ format_type_internal(Oid type_oid, int32 typemod, ...@@ -258,52 +255,63 @@ format_type_internal(Oid type_oid, int32 typemod,
case INTERVALOID: case INTERVALOID:
if (with_typemod) if (with_typemod)
{ {
int fields = typemod >> 16; int fields = INTERVAL_RANGE(typemod);
int precision = typemod & 0xFFFF; int precision = INTERVAL_PRECISION(typemod);
const char *fieldstr; const char *fieldstr;
switch (fields) switch (fields)
{ {
case MASK(YEAR): case INTERVAL_MASK(YEAR):
fieldstr = " year"; fieldstr = " year";
break; break;
case MASK(MONTH): case INTERVAL_MASK(MONTH):
fieldstr = " month"; fieldstr = " month";
break; break;
case MASK(DAY): case INTERVAL_MASK(DAY):
fieldstr = " day"; fieldstr = " day";
break; break;
case MASK(HOUR): case INTERVAL_MASK(HOUR):
fieldstr = " hour"; fieldstr = " hour";
break; break;
case MASK(MINUTE): case INTERVAL_MASK(MINUTE):
fieldstr = " minute"; fieldstr = " minute";
break; break;
case MASK(SECOND): case INTERVAL_MASK(SECOND):
fieldstr = " second"; fieldstr = " second";
break; break;
case MASK(YEAR) | MASK(MONTH): case INTERVAL_MASK(YEAR)
| INTERVAL_MASK(MONTH):
fieldstr = " year to month"; fieldstr = " year to month";
break; break;
case MASK(DAY) | MASK(HOUR): case INTERVAL_MASK(DAY)
| INTERVAL_MASK(HOUR):
fieldstr = " day to hour"; fieldstr = " day to hour";
break; break;
case MASK(DAY) | MASK(HOUR) | MASK(MINUTE): case INTERVAL_MASK(DAY)
| INTERVAL_MASK(HOUR)
| INTERVAL_MASK(MINUTE):
fieldstr = " day to minute"; fieldstr = " day to minute";
break; break;
case MASK(DAY) | MASK(HOUR) | MASK(MINUTE) | MASK(SECOND): case INTERVAL_MASK(DAY)
| INTERVAL_MASK(HOUR)
| INTERVAL_MASK(MINUTE)
| INTERVAL_MASK(SECOND):
fieldstr = " day to second"; fieldstr = " day to second";
break; break;
case MASK(HOUR) | MASK(MINUTE): case INTERVAL_MASK(HOUR)
| INTERVAL_MASK(MINUTE):
fieldstr = " hour to minute"; fieldstr = " hour to minute";
break; break;
case MASK(HOUR) | MASK(MINUTE) | MASK(SECOND): case INTERVAL_MASK(HOUR)
| INTERVAL_MASK(MINUTE)
| INTERVAL_MASK(SECOND):
fieldstr = " hour to second"; fieldstr = " hour to second";
break; break;
case MASK(MINUTE) | MASK(SECOND): case INTERVAL_MASK(MINUTE)
| INTERVAL_MASK(SECOND):
fieldstr = " minute to second"; fieldstr = " minute to second";
break; break;
case 0x7FFF: case INTERVAL_FULL_RANGE:
fieldstr = ""; fieldstr = "";
break; break;
default: default:
...@@ -311,7 +319,7 @@ format_type_internal(Oid type_oid, int32 typemod, ...@@ -311,7 +319,7 @@ format_type_internal(Oid type_oid, int32 typemod,
fieldstr = ""; fieldstr = "";
break; break;
} }
if (precision != 0xFFFF) if (precision != INTERVAL_FULL_PRECISION)
buf = psnprintf(100, "interval(%d)%s", buf = psnprintf(100, "interval(%d)%s",
precision, fieldstr); precision, fieldstr);
else else
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.95 2002/06/20 20:29:37 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.96 2002/08/04 06:44:47 thomas Exp $
* *
* NOTES * NOTES
* *
...@@ -486,8 +486,8 @@ nabstimein(PG_FUNCTION_ARGS) ...@@ -486,8 +486,8 @@ nabstimein(PG_FUNCTION_ARGS)
int nf, int nf,
ftype[MAXDATEFIELDS]; ftype[MAXDATEFIELDS];
if (strlen(str) > MAXDATELEN) if (strlen(str) >= sizeof(lowstr))
elog(ERROR, "Bad (length) abstime external representation '%s'", str); elog(ERROR, "Bad abstime external representation (too long) '%s'", str);
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|| (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0)) || (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0))
...@@ -849,8 +849,8 @@ reltimein(PG_FUNCTION_ARGS) ...@@ -849,8 +849,8 @@ reltimein(PG_FUNCTION_ARGS)
ftype[MAXDATEFIELDS]; ftype[MAXDATEFIELDS];
char lowstr[MAXDATELEN + 1]; char lowstr[MAXDATELEN + 1];
if (strlen(str) > MAXDATELEN) if (strlen(str) >= sizeof(lowstr))
elog(ERROR, "Bad (length) reltime external representation '%s'", str); elog(ERROR, "Bad reltime external representation (too long) '%s'", str);
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|| (DecodeInterval(field, ftype, nf, &dtype, tm, &fsec) != 0)) || (DecodeInterval(field, ftype, nf, &dtype, tm, &fsec) != 0))
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.68 2002/06/20 20:29:38 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.69 2002/08/04 06:44:47 thomas Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -65,7 +65,10 @@ timestamp_in(PG_FUNCTION_ARGS) ...@@ -65,7 +65,10 @@ timestamp_in(PG_FUNCTION_ARGS)
int nf; int nf;
char *field[MAXDATEFIELDS]; char *field[MAXDATEFIELDS];
int ftype[MAXDATEFIELDS]; int ftype[MAXDATEFIELDS];
char lowstr[MAXDATELEN + 1]; char lowstr[MAXDATELEN + MAXDATEFIELDS];
if (strlen(str) >= sizeof(lowstr))
elog(ERROR, "Bad timestamp external representation (too long) '%s'", str);
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|| (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0)) || (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0))
...@@ -251,7 +254,11 @@ timestamptz_in(PG_FUNCTION_ARGS) ...@@ -251,7 +254,11 @@ timestamptz_in(PG_FUNCTION_ARGS)
int nf; int nf;
char *field[MAXDATEFIELDS]; char *field[MAXDATEFIELDS];
int ftype[MAXDATEFIELDS]; int ftype[MAXDATEFIELDS];
char lowstr[MAXDATELEN + 1]; char lowstr[MAXDATELEN + MAXDATEFIELDS];
if (strlen(str) >= sizeof(lowstr))
elog(ERROR, "Bad timestamp with time zone"
" external representation (too long) '%s'", str);
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|| (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0)) || (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0))
...@@ -359,7 +366,7 @@ interval_in(PG_FUNCTION_ARGS) ...@@ -359,7 +366,7 @@ interval_in(PG_FUNCTION_ARGS)
int nf; int nf;
char *field[MAXDATEFIELDS]; char *field[MAXDATEFIELDS];
int ftype[MAXDATEFIELDS]; int ftype[MAXDATEFIELDS];
char lowstr[MAXDATELEN + 1]; char lowstr[MAXDATELEN + MAXDATEFIELDS];
tm->tm_year = 0; tm->tm_year = 0;
tm->tm_mon = 0; tm->tm_mon = 0;
...@@ -369,6 +376,9 @@ interval_in(PG_FUNCTION_ARGS) ...@@ -369,6 +376,9 @@ interval_in(PG_FUNCTION_ARGS)
tm->tm_sec = 0; tm->tm_sec = 0;
fsec = 0; fsec = 0;
if (strlen(str) >= sizeof(lowstr))
elog(ERROR, "Bad interval external representation (too long) '%s'", str);
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|| (DecodeInterval(field, ftype, nf, &dtype, tm, &fsec) != 0)) || (DecodeInterval(field, ftype, nf, &dtype, tm, &fsec) != 0))
elog(ERROR, "Bad interval external representation '%s'", str); elog(ERROR, "Bad interval external representation '%s'", str);
...@@ -436,8 +446,6 @@ interval_scale(PG_FUNCTION_ARGS) ...@@ -436,8 +446,6 @@ interval_scale(PG_FUNCTION_ARGS)
PG_RETURN_INTERVAL_P(result); PG_RETURN_INTERVAL_P(result);
} }
#define MASK(b) (1 << (b))
static void static void
AdjustIntervalForTypmod(Interval *interval, int32 typmod) AdjustIntervalForTypmod(Interval *interval, int32 typmod)
{ {
...@@ -483,31 +491,34 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod) ...@@ -483,31 +491,34 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod)
}; };
#endif #endif
/* Unspecified range and precision? Then not necessary to adjust.
* Setting typmod to -1 is the convention for all types.
*/
if (typmod != -1) if (typmod != -1)
{ {
int range = ((typmod >> 16) & 0x7FFF); int range = INTERVAL_RANGE(typmod);
int precision = (typmod & 0xFFFF); int precision = INTERVAL_PRECISION(typmod);
if (range == 0x7FFF) if (range == INTERVAL_FULL_RANGE)
{ {
/* Do nothing... */ /* Do nothing... */
} }
else if (range == MASK(YEAR)) else if (range == INTERVAL_MASK(YEAR))
{ {
interval->month = ((interval->month / 12) * 12); interval->month = ((interval->month / 12) * 12);
interval->time = 0; interval->time = 0;
} }
else if (range == MASK(MONTH)) else if (range == INTERVAL_MASK(MONTH))
{ {
interval->month %= 12; interval->month %= 12;
interval->time = 0; interval->time = 0;
} }
/* YEAR TO MONTH */ /* YEAR TO MONTH */
else if (range == (MASK(YEAR) | MASK(MONTH))) else if (range == (INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH)))
{ {
interval->time = 0; interval->time = 0;
} }
else if (range == MASK(DAY)) else if (range == INTERVAL_MASK(DAY))
{ {
interval->month = 0; interval->month = 0;
#ifdef HAVE_INT64_TIMESTAMP #ifdef HAVE_INT64_TIMESTAMP
...@@ -517,7 +528,7 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod) ...@@ -517,7 +528,7 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod)
interval->time = (((int) (interval->time / 86400)) * 86400); interval->time = (((int) (interval->time / 86400)) * 86400);
#endif #endif
} }
else if (range == MASK(HOUR)) else if (range == INTERVAL_MASK(HOUR))
{ {
#ifdef HAVE_INT64_TIMESTAMP #ifdef HAVE_INT64_TIMESTAMP
int64 day; int64 day;
...@@ -536,7 +547,7 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod) ...@@ -536,7 +547,7 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod)
interval->time = (((int) (interval->time / 3600)) * 3600.0); interval->time = (((int) (interval->time / 3600)) * 3600.0);
#endif #endif
} }
else if (range == MASK(MINUTE)) else if (range == INTERVAL_MASK(MINUTE))
{ {
#ifdef HAVE_INT64_TIMESTAMP #ifdef HAVE_INT64_TIMESTAMP
int64 hour; int64 hour;
...@@ -555,7 +566,7 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod) ...@@ -555,7 +566,7 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod)
interval->time = (((int) (interval->time / 60)) * 60); interval->time = (((int) (interval->time / 60)) * 60);
#endif #endif
} }
else if (range == MASK(SECOND)) else if (range == INTERVAL_MASK(SECOND))
{ {
#ifdef HAVE_INT64_TIMESTAMP #ifdef HAVE_INT64_TIMESTAMP
int64 minute; int64 minute;
...@@ -573,7 +584,8 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod) ...@@ -573,7 +584,8 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod)
#endif #endif
} }
/* DAY TO HOUR */ /* DAY TO HOUR */
else if (range == (MASK(DAY) | MASK(HOUR))) else if (range == (INTERVAL_MASK(DAY) |
INTERVAL_MASK(HOUR)))
{ {
interval->month = 0; interval->month = 0;
#ifdef HAVE_INT64_TIMESTAMP #ifdef HAVE_INT64_TIMESTAMP
...@@ -584,7 +596,9 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod) ...@@ -584,7 +596,9 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod)
#endif #endif
} }
/* DAY TO MINUTE */ /* DAY TO MINUTE */
else if (range == (MASK(DAY) | MASK(HOUR) | MASK(MINUTE))) else if (range == (INTERVAL_MASK(DAY) |
INTERVAL_MASK(HOUR) |
INTERVAL_MASK(MINUTE)))
{ {
interval->month = 0; interval->month = 0;
#ifdef HAVE_INT64_TIMESTAMP #ifdef HAVE_INT64_TIMESTAMP
...@@ -595,12 +609,16 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod) ...@@ -595,12 +609,16 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod)
#endif #endif
} }
/* DAY TO SECOND */ /* DAY TO SECOND */
else if (range == (MASK(DAY) | MASK(HOUR) | MASK(MINUTE) | MASK(SECOND))) else if (range == (INTERVAL_MASK(DAY) |
INTERVAL_MASK(HOUR) |
INTERVAL_MASK(MINUTE) |
INTERVAL_MASK(SECOND)))
{ {
interval->month = 0; interval->month = 0;
} }
/* HOUR TO MINUTE */ /* HOUR TO MINUTE */
else if (range == (MASK(HOUR) | MASK(MINUTE))) else if (range == (INTERVAL_MASK(HOUR) |
INTERVAL_MASK(MINUTE)))
{ {
#ifdef HAVE_INT64_TIMESTAMP #ifdef HAVE_INT64_TIMESTAMP
int64 day; int64 day;
...@@ -620,7 +638,9 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod) ...@@ -620,7 +638,9 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod)
#endif #endif
} }
/* HOUR TO SECOND */ /* HOUR TO SECOND */
else if (range == (MASK(HOUR) | MASK(MINUTE) | MASK(SECOND))) else if (range == (INTERVAL_MASK(HOUR) |
INTERVAL_MASK(MINUTE) |
INTERVAL_MASK(SECOND)))
{ {
#ifdef HAVE_INT64_TIMESTAMP #ifdef HAVE_INT64_TIMESTAMP
int64 day; int64 day;
...@@ -637,7 +657,8 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod) ...@@ -637,7 +657,8 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod)
#endif #endif
} }
/* MINUTE TO SECOND */ /* MINUTE TO SECOND */
else if (range == (MASK(MINUTE) | MASK(SECOND))) else if (range == (INTERVAL_MASK(MINUTE) |
INTERVAL_MASK(SECOND)))
{ {
#ifdef HAVE_INT64_TIMESTAMP #ifdef HAVE_INT64_TIMESTAMP
int64 hour; int64 hour;
...@@ -657,7 +678,7 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod) ...@@ -657,7 +678,7 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod)
elog(ERROR, "AdjustIntervalForTypmod(): internal coding error"); elog(ERROR, "AdjustIntervalForTypmod(): internal coding error");
/* Need to adjust precision? If not, don't even try! */ /* Need to adjust precision? If not, don't even try! */
if (precision != 0xFFFF) if (precision != INTERVAL_FULL_PRECISION)
{ {
if ((precision < 0) || (precision > MAX_INTERVAL_PRECISION)) if ((precision < 0) || (precision > MAX_INTERVAL_PRECISION))
elog(ERROR, "INTERVAL(%d) precision must be between %d and %d", elog(ERROR, "INTERVAL(%d) precision must be between %d and %d",
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.86 2002/06/20 20:29:38 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.87 2002/08/04 06:44:47 thomas Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -550,7 +550,7 @@ varstr_cmp(char *arg1, int len1, char *arg2, int len2) ...@@ -550,7 +550,7 @@ varstr_cmp(char *arg1, int len1, char *arg2, int len2)
/* /*
* Unfortunately, there is no strncoll(), so in the non-C locale * Unfortunately, there is no strncoll(), so in the non-C locale
* case we have to do some memory copying. This turns out to be * case we have to do some memory copying. This turns out to be
* significantly slower, so we optimize the case were LC_COLLATE * significantly slower, so we optimize the case where LC_COLLATE
* is C. * is C.
*/ */
if (!lc_collate_is_c()) if (!lc_collate_is_c())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment