date.c
来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 2,565 行 · 第 1/4 页
C
2,565 行
Datumtimetz_eq(PG_FUNCTION_ARGS){ TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0); TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1); PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) == 0);}Datumtimetz_ne(PG_FUNCTION_ARGS){ TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0); TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1); PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) != 0);}Datumtimetz_lt(PG_FUNCTION_ARGS){ TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0); TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1); PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) < 0);}Datumtimetz_le(PG_FUNCTION_ARGS){ TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0); TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1); PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) <= 0);}Datumtimetz_gt(PG_FUNCTION_ARGS){ TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0); TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1); PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) > 0);}Datumtimetz_ge(PG_FUNCTION_ARGS){ TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0); TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1); PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) >= 0);}Datumtimetz_cmp(PG_FUNCTION_ARGS){ TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0); TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1); PG_RETURN_INT32(timetz_cmp_internal(time1, time2));}Datumtimetz_hash(PG_FUNCTION_ARGS){ TimeTzADT *key = PG_GETARG_TIMETZADT_P(0); uint32 thash; /* * To avoid any problems with padding bytes in the struct, we figure the * field hashes separately and XOR them. This also provides a convenient * framework for dealing with the fact that the time field might be either * double or int64. */#ifdef HAVE_INT64_TIMESTAMP thash = DatumGetUInt32(DirectFunctionCall1(hashint8, Int64GetDatumFast(key->time)));#else thash = DatumGetUInt32(DirectFunctionCall1(hashfloat8, Float8GetDatumFast(key->time)));#endif thash ^= DatumGetUInt32(hash_uint32(key->zone)); PG_RETURN_UINT32(thash);}Datumtimetz_larger(PG_FUNCTION_ARGS){ TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0); TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1); TimeTzADT *result; if (timetz_cmp_internal(time1, time2) > 0) result = time1; else result = time2; PG_RETURN_TIMETZADT_P(result);}Datumtimetz_smaller(PG_FUNCTION_ARGS){ TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0); TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1); TimeTzADT *result; if (timetz_cmp_internal(time1, time2) < 0) result = time1; else result = time2; PG_RETURN_TIMETZADT_P(result);}/* timetz_pl_interval() * Add interval to timetz. */Datumtimetz_pl_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 / USECS_PER_DAY * USECS_PER_DAY; if (result->time < INT64CONST(0)) result->time += USECS_PER_DAY;#else result->time = time->time + span->time; TMODULO(result->time, time1.time, (double) SECS_PER_DAY); if (result->time < 0) result->time += SECS_PER_DAY;#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 / USECS_PER_DAY * USECS_PER_DAY; if (result->time < INT64CONST(0)) result->time += USECS_PER_DAY;#else result->time = time->time - span->time; TMODULO(result->time, time1.time, (double) SECS_PER_DAY); if (result->time < 0) result->time += SECS_PER_DAY;#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 pg_tm tt, *tm = &tt; fsec_t fsec; int tz; GetCurrentDateTime(tm); time2tm(time, tm, &fsec); tz = DetermineTimeZoneOffset(tm, session_timezone); 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 pg_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, NULL) != 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 * USECS_PER_DAY + time->time + time->zone * USECS_PER_SEC;#else result = date * (double) SECS_PER_DAY + time->time + time->zone;#endif PG_RETURN_TIMESTAMP(result);}/* 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; char *lowunits; lowunits = downcase_truncate_identifier(VARDATA(units), VARSIZE(units) - VARHDRSZ, false); 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 pg_tm tt, *tm = &tt; timetz2tm(time, tm, &fsec, &tz); switch (val) { case DTK_TZ: result = -tz; break; case DTK_TZ_MINUTE: result = -tz; result /= SECS_PER_MINUTE; FMODULO(result, dummy, (double) SECS_PER_MINUTE); break; case DTK_TZ_HOUR: dummy = -tz; FMODULO(dummy, result, (double) SECS_PER_HOUR); break; case DTK_MICROSEC:#ifdef HAVE_INT64_TIMESTAMP result = tm->tm_sec * USECS_PER_SEC + 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 / USECS_PER_SEC;#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 / 1000000.0 + 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. * Applies DST rules as of the current date. */Datumtimetz_zone(PG_FUNCTION_ARGS){ text *zone = PG_GETARG_TEXT_P(0); TimeTzADT *t = PG_GETARG_TIMETZADT_P(1); TimeTzADT *result; int tz; char tzname[TZ_STRLEN_MAX + 1]; int len; char *lowzone; int type, val; pg_tz *tzp; /* * Look up the requested timezone. First we look in the date token table * (to handle cases like "EST"), and if that fails, we look in the * timezone database (to handle cases like "America/New_York"). (This * matches the order in which timestamp input checks the cases; it's * important because the timezone database unwisely uses a few zone names * that are identical to offset abbreviations.) */ lowzone = downcase_truncate_identifier(VARDATA(zone), VARSIZE(zone) - VARHDRSZ, false); type = DecodeSpecial(0, lowzone, &val); if (type == TZ || type == DTZ) tz = val * 60; else { len = Min(VARSIZE(zone) - VARHDRSZ, TZ_STRLEN_MAX); memcpy(tzname, VARDATA(zone), len); tzname[len] = '\0'; tzp = pg_tzset(tzname); if (tzp) { /* Get the offset-from-GMT that is valid today for the zone */ pg_time_t now; struct pg_tm *tm; now = time(NULL); tm = pg_localtime(&now, tzp); tz = -tm->tm_gmtoff; } else { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("time zone \"%s\" not recognized", tzname))); tz = 0; /* keep compiler quiet */ } } result = (TimeTzADT *) palloc(sizeof(TimeTzADT));#ifdef HAVE_INT64_TIMESTAMP result->time = t->time + (t->zone - tz) * USECS_PER_SEC; while (result->time < INT64CONST(0)) result->time += USECS_PER_DAY; while (result->time >= USECS_PER_DAY) result->time -= USECS_PER_DAY;#else result->time = t->time + (t->zone - tz); while (result->time < 0) result->time += SECS_PER_DAY; while (result->time >= SECS_PER_DAY) result->time -= SECS_PER_DAY;#endif result->zone = tz; PG_RETURN_TIMETZADT_P(result);}/* 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 / USECS_PER_SEC);#else tz = -(zone->time);#endif result = (TimeTzADT *) palloc(sizeof(TimeTzADT));#ifdef HAVE_INT64_TIMESTAMP result->time = time->time + (time->zone - tz) * USECS_PER_SEC; while (result->time < INT64CONST(0)) result->time += USECS_PER_DAY; while (result->time >= USECS_PER_DAY) result->time -= USECS_PER_DAY;#else result->time = time->time + (time->zone - tz); while (result->time < 0) result->time += SECS_PER_DAY; while (result->time >= SECS_PER_DAY) result->time -= SECS_PER_DAY;#endif result->zone = tz; PG_RETURN_TIMETZADT_P(result);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?