date.c
来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 2,274 行 · 第 1/4 页
C
2,274 行
result->time = (time->time + span->time); result->time -= (result->time / INT64CONST(86400000000) * INT64CONST(86400000000)); if (result->time < INT64CONST(0)) result->time += INT64CONST(86400000000);#else result->time = (time->time + span->time); TMODULO(result->time, time1.time, 86400e0); if (result->time < 0) result->time += 86400;#endif result->zone = time->zone; PG_RETURN_TIMETZADT_P(result);}/* timetz_mi_interval() * Subtract interval from timetz. */Datumtimetz_mi_interval(PG_FUNCTION_ARGS){ TimeTzADT *time = PG_GETARG_TIMETZADT_P(0); Interval *span = PG_GETARG_INTERVAL_P(1); TimeTzADT *result;#ifndef HAVE_INT64_TIMESTAMP TimeTzADT time1;#endif result = (TimeTzADT *) palloc(sizeof(TimeTzADT));#ifdef HAVE_INT64_TIMESTAMP result->time = (time->time - span->time); result->time -= (result->time / INT64CONST(86400000000) * INT64CONST(86400000000)); if (result->time < INT64CONST(0)) result->time += INT64CONST(86400000000);#else result->time = (time->time - span->time); TMODULO(result->time, time1.time, 86400e0); if (result->time < 0) result->time += 86400;#endif result->zone = time->zone; PG_RETURN_TIMETZADT_P(result);}/* overlaps_timetz() --- implements the SQL92 OVERLAPS operator. * * Algorithm is per SQL92 spec. This is much harder than you'd think * because the spec requires us to deliver a non-null answer in some cases * where some of the inputs are null. */Datumoverlaps_timetz(PG_FUNCTION_ARGS){ /* * The arguments are TimeTzADT *, but we leave them as generic Datums * for convenience of notation --- and to avoid dereferencing nulls. */ Datum ts1 = PG_GETARG_DATUM(0); Datum te1 = PG_GETARG_DATUM(1); Datum ts2 = PG_GETARG_DATUM(2); Datum te2 = PG_GETARG_DATUM(3); bool ts1IsNull = PG_ARGISNULL(0); bool te1IsNull = PG_ARGISNULL(1); bool ts2IsNull = PG_ARGISNULL(2); bool te2IsNull = PG_ARGISNULL(3);#define TIMETZ_GT(t1,t2) \ DatumGetBool(DirectFunctionCall2(timetz_gt,t1,t2))#define TIMETZ_LT(t1,t2) \ DatumGetBool(DirectFunctionCall2(timetz_lt,t1,t2)) /* * If both endpoints of interval 1 are null, the result is null * (unknown). If just one endpoint is null, take ts1 as the non-null * one. Otherwise, take ts1 as the lesser endpoint. */ if (ts1IsNull) { if (te1IsNull) PG_RETURN_NULL(); /* swap null for non-null */ ts1 = te1; te1IsNull = true; } else if (!te1IsNull) { if (TIMETZ_GT(ts1, te1)) { Datum tt = ts1; ts1 = te1; te1 = tt; } } /* Likewise for interval 2. */ if (ts2IsNull) { if (te2IsNull) PG_RETURN_NULL(); /* swap null for non-null */ ts2 = te2; te2IsNull = true; } else if (!te2IsNull) { if (TIMETZ_GT(ts2, te2)) { Datum tt = ts2; ts2 = te2; te2 = tt; } } /* * At this point neither ts1 nor ts2 is null, so we can consider three * cases: ts1 > ts2, ts1 < ts2, ts1 = ts2 */ if (TIMETZ_GT(ts1, ts2)) { /* * This case is ts1 < te2 OR te1 < te2, which may look redundant * but in the presence of nulls it's not quite completely so. */ if (te2IsNull) PG_RETURN_NULL(); if (TIMETZ_LT(ts1, te2)) PG_RETURN_BOOL(true); if (te1IsNull) PG_RETURN_NULL(); /* * If te1 is not null then we had ts1 <= te1 above, and we just * found ts1 >= te2, hence te1 >= te2. */ PG_RETURN_BOOL(false); } else if (TIMETZ_LT(ts1, ts2)) { /* This case is ts2 < te1 OR te2 < te1 */ if (te1IsNull) PG_RETURN_NULL(); if (TIMETZ_LT(ts2, te1)) PG_RETURN_BOOL(true); if (te2IsNull) PG_RETURN_NULL(); /* * If te2 is not null then we had ts2 <= te2 above, and we just * found ts2 >= te1, hence te2 >= te1. */ PG_RETURN_BOOL(false); } else { /* * For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a * rather silly way of saying "true if both are nonnull, else * null". */ if (te1IsNull || te2IsNull) PG_RETURN_NULL(); PG_RETURN_BOOL(true); }#undef TIMETZ_GT#undef TIMETZ_LT}Datumtimetz_time(PG_FUNCTION_ARGS){ TimeTzADT *timetz = PG_GETARG_TIMETZADT_P(0); TimeADT result; /* swallow the time zone and just return the time */ result = timetz->time; PG_RETURN_TIMEADT(result);}Datumtime_timetz(PG_FUNCTION_ARGS){ TimeADT time = PG_GETARG_TIMEADT(0); TimeTzADT *result; struct tm tt, *tm = &tt; fsec_t fsec; int tz; GetCurrentDateTime(tm); time2tm(time, tm, &fsec); tz = DetermineLocalTimeZone(tm); result = (TimeTzADT *) palloc(sizeof(TimeTzADT)); result->time = time; result->zone = tz; PG_RETURN_TIMETZADT_P(result);}/* timestamptz_timetz() * Convert timestamp to timetz data type. */Datumtimestamptz_timetz(PG_FUNCTION_ARGS){ TimestampTz timestamp = PG_GETARG_TIMESTAMP(0); TimeTzADT *result; struct tm tt, *tm = &tt; int tz; fsec_t fsec; char *tzn; if (TIMESTAMP_NOT_FINITE(timestamp)) PG_RETURN_NULL(); if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); result = (TimeTzADT *) palloc(sizeof(TimeTzADT)); tm2timetz(tm, fsec, tz, result); PG_RETURN_TIMETZADT_P(result);}/* datetimetz_timestamptz() * Convert date and timetz to timestamp with time zone data type. * Timestamp is stored in GMT, so add the time zone * stored with the timetz to the result. * - thomas 2000-03-10 */Datumdatetimetz_timestamptz(PG_FUNCTION_ARGS){ DateADT date = PG_GETARG_DATEADT(0); TimeTzADT *time = PG_GETARG_TIMETZADT_P(1); TimestampTz result;#ifdef HAVE_INT64_TIMESTAMP result = (((date * INT64CONST(86400000000)) + time->time) + (time->zone * INT64CONST(1000000)));#else result = (((date * 86400.0) + time->time) + time->zone);#endif PG_RETURN_TIMESTAMP(result);}/* timetz_text() * Convert timetz to text data type. */Datumtimetz_text(PG_FUNCTION_ARGS){ /* Input is a Timetz, but may as well leave it in Datum form */ Datum timetz = PG_GETARG_DATUM(0); text *result; char *str; int len; str = DatumGetCString(DirectFunctionCall1(timetz_out, timetz)); len = (strlen(str) + VARHDRSZ); result = palloc(len); VARATT_SIZEP(result) = len; memmove(VARDATA(result), str, (len - VARHDRSZ)); pfree(str); PG_RETURN_TEXT_P(result);}/* text_timetz() * Convert text string to timetz. * Text type is not null terminated, so use temporary string * then call the standard input routine. */Datumtext_timetz(PG_FUNCTION_ARGS){ text *str = PG_GETARG_TEXT_P(0); int i; char *sp, *dp, dstr[MAXDATELEN + 1]; if (VARSIZE(str) - VARHDRSZ > MAXDATELEN) ereport(ERROR, (errcode(ERRCODE_INVALID_DATETIME_FORMAT), errmsg("invalid input syntax for type time with time zone: \"%s\"", VARDATA(str)))); sp = VARDATA(str); dp = dstr; for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++) *dp++ = *sp++; *dp = '\0'; return DirectFunctionCall3(timetz_in, CStringGetDatum(dstr), ObjectIdGetDatum(InvalidOid), Int32GetDatum(-1));}/* timetz_part() * Extract specified field from time type. */Datumtimetz_part(PG_FUNCTION_ARGS){ text *units = PG_GETARG_TEXT_P(0); TimeTzADT *time = PG_GETARG_TIMETZADT_P(1); float8 result; int type, val; int i; char *up, *lp, lowunits[MAXDATELEN + 1]; if (VARSIZE(units) - VARHDRSZ > MAXDATELEN) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("\"time with time zone\" units \"%s\" not recognized", DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(units)))))); up = VARDATA(units); lp = lowunits; for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++) *lp++ = tolower((unsigned char) *up++); *lp = '\0'; type = DecodeUnits(0, lowunits, &val); if (type == UNKNOWN_FIELD) type = DecodeSpecial(0, lowunits, &val); if (type == UNITS) { double dummy; int tz; fsec_t fsec; struct tm tt, *tm = &tt; timetz2tm(time, tm, &fsec, &tz); switch (val) { case DTK_TZ: result = -tz; break; case DTK_TZ_MINUTE: result = -tz; result /= 60; FMODULO(result, dummy, 60e0); break; case DTK_TZ_HOUR: dummy = -tz; FMODULO(dummy, result, 3600e0); break; case DTK_MICROSEC:#ifdef HAVE_INT64_TIMESTAMP result = ((tm->tm_sec * INT64CONST(1000000)) + fsec);#else result = ((tm->tm_sec + fsec) * 1000000);#endif break; case DTK_MILLISEC:#ifdef HAVE_INT64_TIMESTAMP result = ((tm->tm_sec * INT64CONST(1000)) + (fsec / INT64CONST(1000)));#else result = ((tm->tm_sec + fsec) * 1000);#endif break; case DTK_SECOND:#ifdef HAVE_INT64_TIMESTAMP result = (tm->tm_sec + (fsec / INT64CONST(1000000)));#else result = (tm->tm_sec + fsec);#endif break; case DTK_MINUTE: result = tm->tm_min; break; case DTK_HOUR: result = tm->tm_hour; break; case DTK_DAY: case DTK_MONTH: case DTK_QUARTER: case DTK_YEAR: case DTK_DECADE: case DTK_CENTURY: case DTK_MILLENNIUM: default: ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("\"time with time zone\" units \"%s\" not recognized", DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(units)))))); result = 0; } } else if ((type == RESERV) && (val == DTK_EPOCH)) {#ifdef HAVE_INT64_TIMESTAMP result = ((time->time / 1000000e0) - time->zone);#else result = (time->time - time->zone);#endif } else { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("\"time with time zone\" units \"%s\" not recognized", DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(units)))))); result = 0; } PG_RETURN_FLOAT8(result);}/* timetz_zone() * Encode time with time zone type with specified time zone. */Datumtimetz_zone(PG_FUNCTION_ARGS){ text *zone = PG_GETARG_TEXT_P(0); TimeTzADT *time = PG_GETARG_TIMETZADT_P(1); TimeTzADT *result; int tz; int type, val; int i; char *up, *lp, lowzone[MAXDATELEN + 1]; if (VARSIZE(zone) - VARHDRSZ > MAXDATELEN) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("time zone \"%s\" not recognized", DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(zone)))))); up = VARDATA(zone); lp = lowzone; for (i = 0; i < (VARSIZE(zone) - VARHDRSZ); i++) *lp++ = tolower((unsigned char) *up++); *lp = '\0'; type = DecodeSpecial(0, lowzone, &val); result = (TimeTzADT *) palloc(sizeof(TimeTzADT)); if ((type == TZ) || (type == DTZ)) { tz = val * 60;#ifdef HAVE_INT64_TIMESTAMP result->time = time->time + ((time->zone - tz) * INT64CONST(1000000)); while (result->time < INT64CONST(0)) result->time += INT64CONST(86400000000); while (result->time >= INT64CONST(86400000000)) result->time -= INT64CONST(86400000000);#else result->time = time->time + (time->zone - tz); while (result->time < 0) result->time += 86400; while (result->time >= 86400) result->time -= 86400;#endif result->zone = tz; } else { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("time zone \"%s\" not recognized", lowzone))); PG_RETURN_NULL(); } PG_RETURN_TIMETZADT_P(result);} /* timetz_zone() *//* timetz_izone() * Encode time with time zone type with specified time interval as time zone. */Datumtimetz_izone(PG_FUNCTION_ARGS){ Interval *zone = PG_GETARG_INTERVAL_P(0); TimeTzADT *time = PG_GETARG_TIMETZADT_P(1); TimeTzADT *result; int tz; if (zone->month != 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("\"interval\" time zone \"%s\" not valid", DatumGetCString(DirectFunctionCall1(interval_out, PointerGetDatum(zone))))));#ifdef HAVE_INT64_TIMESTAMP tz = -(zone->time / INT64CONST(1000000));#else tz = -(zone->time);#endif result = (TimeTzADT *) palloc(sizeof(TimeTzADT));#ifdef HAVE_INT64_TIMESTAMP result->time = time->time + ((time->zone - tz) * INT64CONST(1000000)); while (result->time < INT64CONST(0)) result->time += INT64CONST(86400000000); while (result->time >= INT64CONST(86400000000)) result->time -= INT64CONST(86400000000);#else result->time = time->time + (time->zone - tz); while (result->time < 0) result->time += 86400; while (result->time >= 86400) result->time -= 86400;#endif result->zone = tz; PG_RETURN_TIMETZADT_P(result);} /* timetz_izone() */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?