date.c
来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 2,565 行 · 第 1/4 页
C
2,565 行
dt2 = date2timestamp(dateVal); PG_RETURN_INT32(timestamp_cmp_internal(dt1, dt2));}Datumtimestamptz_eq_date(PG_FUNCTION_ARGS){ TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0); DateADT dateVal = PG_GETARG_DATEADT(1); TimestampTz dt2; dt2 = date2timestamptz(dateVal); PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) == 0);}Datumtimestamptz_ne_date(PG_FUNCTION_ARGS){ TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0); DateADT dateVal = PG_GETARG_DATEADT(1); TimestampTz dt2; dt2 = date2timestamptz(dateVal); PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) != 0);}Datumtimestamptz_lt_date(PG_FUNCTION_ARGS){ TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0); DateADT dateVal = PG_GETARG_DATEADT(1); TimestampTz dt2; dt2 = date2timestamptz(dateVal); PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) < 0);}Datumtimestamptz_gt_date(PG_FUNCTION_ARGS){ TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0); DateADT dateVal = PG_GETARG_DATEADT(1); TimestampTz dt2; dt2 = date2timestamptz(dateVal); PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) > 0);}Datumtimestamptz_le_date(PG_FUNCTION_ARGS){ TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0); DateADT dateVal = PG_GETARG_DATEADT(1); TimestampTz dt2; dt2 = date2timestamptz(dateVal); PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) <= 0);}Datumtimestamptz_ge_date(PG_FUNCTION_ARGS){ TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0); DateADT dateVal = PG_GETARG_DATEADT(1); TimestampTz dt2; dt2 = date2timestamptz(dateVal); PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) >= 0);}Datumtimestamptz_cmp_date(PG_FUNCTION_ARGS){ TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0); DateADT dateVal = PG_GETARG_DATEADT(1); TimestampTz dt2; dt2 = date2timestamptz(dateVal); PG_RETURN_INT32(timestamptz_cmp_internal(dt1, dt2));}/* Add an interval to a date, giving a new date. * Must handle both positive and negative intervals. * * We implement this by promoting the date to timestamp (without time zone) * and then using the timestamp plus interval function. */Datumdate_pl_interval(PG_FUNCTION_ARGS){ DateADT dateVal = PG_GETARG_DATEADT(0); Interval *span = PG_GETARG_INTERVAL_P(1); Timestamp dateStamp; dateStamp = date2timestamp(dateVal); return DirectFunctionCall2(timestamp_pl_interval, TimestampGetDatum(dateStamp), PointerGetDatum(span));}/* Subtract an interval from a date, giving a new date. * Must handle both positive and negative intervals. * * We implement this by promoting the date to timestamp (without time zone) * and then using the timestamp minus interval function. */Datumdate_mi_interval(PG_FUNCTION_ARGS){ DateADT dateVal = PG_GETARG_DATEADT(0); Interval *span = PG_GETARG_INTERVAL_P(1); Timestamp dateStamp; dateStamp = date2timestamp(dateVal); return DirectFunctionCall2(timestamp_mi_interval, TimestampGetDatum(dateStamp), PointerGetDatum(span));}/* date_timestamp() * Convert date to timestamp data type. */Datumdate_timestamp(PG_FUNCTION_ARGS){ DateADT dateVal = PG_GETARG_DATEADT(0); Timestamp result; result = date2timestamp(dateVal); PG_RETURN_TIMESTAMP(result);}/* timestamp_date() * Convert timestamp to date data type. */Datumtimestamp_date(PG_FUNCTION_ARGS){ Timestamp timestamp = PG_GETARG_TIMESTAMP(0); DateADT result; struct pg_tm tt, *tm = &tt; fsec_t fsec; if (TIMESTAMP_NOT_FINITE(timestamp)) PG_RETURN_NULL(); if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE; PG_RETURN_DATEADT(result);}/* date_timestamptz() * Convert date to timestamp with time zone data type. */Datumdate_timestamptz(PG_FUNCTION_ARGS){ DateADT dateVal = PG_GETARG_DATEADT(0); TimestampTz result; result = date2timestamptz(dateVal); PG_RETURN_TIMESTAMP(result);}/* timestamptz_date() * Convert timestamp with time zone to date data type. */Datumtimestamptz_date(PG_FUNCTION_ARGS){ TimestampTz timestamp = PG_GETARG_TIMESTAMP(0); DateADT result; struct pg_tm tt, *tm = &tt; fsec_t fsec; int tz; 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 = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE; PG_RETURN_DATEADT(result);}/* abstime_date() * Convert abstime to date data type. */Datumabstime_date(PG_FUNCTION_ARGS){ AbsoluteTime abstime = PG_GETARG_ABSOLUTETIME(0); DateADT result; struct pg_tm tt, *tm = &tt; int tz; switch (abstime) { case INVALID_ABSTIME: case NOSTART_ABSTIME: case NOEND_ABSTIME: ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot convert reserved abstime value to date"))); /* * pretend to drop through to make compiler think that result will * be set */ default: abstime2tm(abstime, &tz, tm, NULL); result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE; break; } PG_RETURN_DATEADT(result);}/***************************************************************************** * Time ADT *****************************************************************************/Datumtime_in(PG_FUNCTION_ARGS){ char *str = PG_GETARG_CSTRING(0);#ifdef NOT_USED Oid typelem = PG_GETARG_OID(1);#endif int32 typmod = PG_GETARG_INT32(2); TimeADT result; fsec_t fsec; struct pg_tm tt, *tm = &tt; int tz; int nf; int dterr; char workbuf[MAXDATELEN + 1]; char *field[MAXDATEFIELDS]; int dtype; int ftype[MAXDATEFIELDS]; dterr = ParseDateTime(str, workbuf, sizeof(workbuf), field, ftype, MAXDATEFIELDS, &nf); if (dterr == 0) dterr = DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, &tz); if (dterr != 0) DateTimeParseError(dterr, str, "time"); tm2time(tm, fsec, &result); AdjustTimeForTypmod(&result, typmod); PG_RETURN_TIMEADT(result);}/* tm2time() * Convert a tm structure to a time data type. */static inttm2time(struct pg_tm * tm, fsec_t fsec, TimeADT *result){#ifdef HAVE_INT64_TIMESTAMP *result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) * USECS_PER_SEC) + fsec;#else *result = ((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec + fsec;#endif return 0;}/* time2tm() * Convert time data type to POSIX time structure. * For dates within the system-supported time_t range, convert to the * local time zone. If out of this range, leave as GMT. - tgl 97/05/27 */static inttime2tm(TimeADT time, struct pg_tm * tm, fsec_t *fsec){#ifdef HAVE_INT64_TIMESTAMP tm->tm_hour = time / USECS_PER_HOUR; time -= tm->tm_hour * USECS_PER_HOUR; tm->tm_min = time / USECS_PER_MINUTE; time -= tm->tm_min * USECS_PER_MINUTE; tm->tm_sec = time / USECS_PER_SEC; time -= tm->tm_sec * USECS_PER_SEC; *fsec = time;#else double trem;recalc: trem = time; TMODULO(trem, tm->tm_hour, (double) SECS_PER_HOUR); TMODULO(trem, tm->tm_min, (double) SECS_PER_MINUTE); TMODULO(trem, tm->tm_sec, 1.0); trem = TIMEROUND(trem); /* roundoff may need to propagate to higher-order fields */ if (trem >= 1.0) { time = ceil(time); goto recalc; } *fsec = trem;#endif return 0;}Datumtime_out(PG_FUNCTION_ARGS){ TimeADT time = PG_GETARG_TIMEADT(0); char *result; struct pg_tm tt, *tm = &tt; fsec_t fsec; char buf[MAXDATELEN + 1]; time2tm(time, tm, &fsec); EncodeTimeOnly(tm, fsec, NULL, DateStyle, buf); result = pstrdup(buf); PG_RETURN_CSTRING(result);}/* * time_recv - converts external binary format to time * * We make no attempt to provide compatibility between int and float * time representations ... */Datumtime_recv(PG_FUNCTION_ARGS){ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);#ifdef NOT_USED Oid typelem = PG_GETARG_OID(1);#endif int32 typmod = PG_GETARG_INT32(2); TimeADT result;#ifdef HAVE_INT64_TIMESTAMP result = pq_getmsgint64(buf);#else result = pq_getmsgfloat8(buf);#endif AdjustTimeForTypmod(&result, typmod); PG_RETURN_TIMEADT(result);}/* * time_send - converts time to binary format */Datumtime_send(PG_FUNCTION_ARGS){ TimeADT time = PG_GETARG_TIMEADT(0); StringInfoData buf; pq_begintypsend(&buf);#ifdef HAVE_INT64_TIMESTAMP pq_sendint64(&buf, time);#else pq_sendfloat8(&buf, time);#endif PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}Datumtimetypmodin(PG_FUNCTION_ARGS){ ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0); PG_RETURN_INT32(anytime_typmodin(false, ta));}Datumtimetypmodout(PG_FUNCTION_ARGS){ int32 typmod = PG_GETARG_INT32(0); PG_RETURN_CSTRING(anytime_typmodout(false, typmod));}/* time_scale() * Adjust time type for specified scale factor. * Used by PostgreSQL type system to stuff columns. */Datumtime_scale(PG_FUNCTION_ARGS){ TimeADT time = PG_GETARG_TIMEADT(0); int32 typmod = PG_GETARG_INT32(1); TimeADT result; result = time; AdjustTimeForTypmod(&result, typmod); 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 voidAdjustTimeForTypmod(TimeADT *time, int32 typmod){#ifdef HAVE_INT64_TIMESTAMP static const int64 TimeScales[MAX_TIME_PRECISION + 1] = { INT64CONST(1000000), INT64CONST(100000), INT64CONST(10000), INT64CONST(1000), INT64CONST(100), INT64CONST(10), INT64CONST(1) }; static const int64 TimeOffsets[MAX_TIME_PRECISION + 1] = { INT64CONST(500000), INT64CONST(50000), INT64CONST(5000), INT64CONST(500), INT64CONST(50), INT64CONST(5), INT64CONST(0) };#else /* note MAX_TIME_PRECISION differs in this case */ static const double TimeScales[MAX_TIME_PRECISION + 1] = { 1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 10000000.0, 100000000.0, 1000000000.0, 10000000000.0 };#endif if (typmod >= 0 && typmod <= MAX_TIME_PRECISION) { /* * Note: this round-to-nearest code is not completely consistent about * rounding values that are exactly halfway between integral values. * On most platforms, rint() will implement round-to-nearest-even, but * the integer code always rounds up (away from zero). Is it worth * trying to be consistent? */#ifdef HAVE_INT64_TIMESTAMP if (*time >= INT64CONST(0)) *time = ((*time + TimeOffsets[typmod]) / TimeScales[typmod]) * TimeScales[typmod]; else *time = -((((-*time) + TimeOffsets[typmod]) / TimeScales[typmod]) * TimeScales[typmod]);#else *time = rint((double) *time * TimeScales[typmod]) / TimeScales[typmod];#endif }}Datumtime_eq(PG_FUNCTION_ARGS){ TimeADT time1 = PG_GETARG_TIMEADT(0); TimeADT time2 = PG_GETARG_TIMEADT(1); PG_RETURN_BOOL(time1 == time2);}Datumtime_ne(PG_FUNCTION_ARGS){ TimeADT time1 = PG_GETARG_TIMEADT(0); TimeADT time2 = PG_GETARG_TIMEADT(1); PG_RETURN_BOOL(time1 != time2);}Datumtime_lt(PG_FUNCTION_ARGS){ TimeADT time1 = PG_GETARG_TIMEADT(0); TimeADT time2 = PG_GETARG_TIMEADT(1); PG_RETURN_BOOL(time1 < time2);}Datumtime_le(PG_FUNCTION_ARGS){ TimeADT time1 = PG_GETARG_TIMEADT(0); TimeADT time2 = PG_GETARG_TIMEADT(1); PG_RETURN_BOOL(time1 <= time2);}Datumtime_gt(PG_FUNCTION_ARGS){ TimeADT time1 = PG_GETARG_TIMEADT(0); TimeADT time2 = PG_GETARG_TIMEADT(1); PG_RETURN_BOOL(time1 > time2);}Datumtime_ge(PG_FUNCTION_ARGS){ TimeADT time1 = PG_GETARG_TIMEADT(0); TimeADT time2 = PG_GETARG_TIMEADT(1); PG_RETURN_BOOL(time1 >= time2);}Datumtime_cmp(PG_FUNCTION_ARGS){ TimeADT time1 = PG_GETARG_TIMEADT(0); TimeADT time2 = PG_GETARG_TIMEADT(1); if (time1 < time2) PG_RETURN_INT32(-1); if (time1 > time2) PG_RETURN_INT32(1); PG_RETURN_INT32(0);}Datumtime_hash(PG_FUNCTION_ARGS){ /* We can use either hashint8 or hashfloat8 directly */#ifdef HAVE_INT64_TIMESTAMP return hashint8(fcinfo);#else return hashfloat8(fcinfo);#endif}Datumtime_larger(PG_FUNCTION_ARGS){ TimeADT time1 = PG_GETARG_TIMEADT(0); TimeADT time2 = PG_GETARG_TIMEADT(1); PG_RETURN_TIMEADT((time1 > time2) ? time1 : time2);}Datumtime_smaller(PG_FUNCTION_ARGS){ TimeADT time1 = PG_GETARG_TIMEADT(0); TimeADT time2 = PG_GETARG_TIMEADT(1); PG_RETURN_TIMEADT((time1 < time2) ? time1 : time2);}/* overlaps_time() --- 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_time(PG_FUNCTION_ARGS){ /* * The arguments are TimeADT, but we leave them as generic Datums to avoid * dereferencing nulls (TimeADT is pass-by-reference!) */ 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 TIMEADT_GT(t1,t2) \ (DatumGetTimeADT(t1) > DatumGetTimeADT(t2))#define TIMEADT_LT(t1,t2) \ (DatumGetTimeADT(t1) < DatumGetTimeADT(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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?