date.c
来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 2,565 行 · 第 1/4 页
C
2,565 行
/*------------------------------------------------------------------------- * * date.c * implements DATE and TIME data types specified in SQL-92 standard * * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994-5, Regents of the University of California * * * IDENTIFICATION * $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.138.2.1 2008/07/07 18:09:53 tgl Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include <ctype.h>#include <limits.h>#include <float.h>#include <time.h>#include "access/hash.h"#include "libpq/pqformat.h"#include "miscadmin.h"#include "parser/scansup.h"#include "utils/array.h"#include "utils/builtins.h"#include "utils/date.h"#include "utils/nabstime.h"/* * gcc's -ffast-math switch breaks routines that expect exact results from * expressions like timeval / SECS_PER_HOUR, where timeval is double. */#ifdef __FAST_MATH__#error -ffast-math is known to break this code#endifstatic int time2tm(TimeADT time, struct pg_tm * tm, fsec_t *fsec);static int timetz2tm(TimeTzADT *time, struct pg_tm * tm, fsec_t *fsec, int *tzp);static int tm2time(struct pg_tm * tm, fsec_t fsec, TimeADT *result);static int tm2timetz(struct pg_tm * tm, fsec_t fsec, int tz, TimeTzADT *result);static void AdjustTimeForTypmod(TimeADT *time, int32 typmod);/* common code for timetypmodin and timetztypmodin */static int32anytime_typmodin(bool istz, ArrayType *ta){ int32 typmod; int32 *tl; int n; tl = ArrayGetIntegerTypmods(ta, &n); /* * we're not too tense about good error message here because grammar * shouldn't allow wrong number of modifiers for TIME */ if (n != 1) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid type modifier"))); if (*tl < 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("TIME(%d)%s precision must not be negative", *tl, (istz ? " WITH TIME ZONE" : "")))); if (*tl > MAX_TIME_PRECISION) { ereport(WARNING, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("TIME(%d)%s precision reduced to maximum allowed, %d", *tl, (istz ? " WITH TIME ZONE" : ""), MAX_TIME_PRECISION))); typmod = MAX_TIME_PRECISION; } else typmod = *tl; return typmod;}/* common code for timetypmodout and timetztypmodout */static char *anytime_typmodout(bool istz, int32 typmod){ char *res = (char *) palloc(64); const char *tz = istz ? " with time zone" : " without time zone"; if (typmod >= 0) snprintf(res, 64, "(%d)%s", (int) typmod, tz); else snprintf(res, 64, "%s", tz); return res;}/***************************************************************************** * Date ADT *****************************************************************************//* date_in() * Given date text string, convert to internal date format. */Datumdate_in(PG_FUNCTION_ARGS){ char *str = PG_GETARG_CSTRING(0); DateADT date; fsec_t fsec; struct pg_tm tt, *tm = &tt; int tzp; int dtype; int nf; int dterr; char *field[MAXDATEFIELDS]; int ftype[MAXDATEFIELDS]; char workbuf[MAXDATELEN + 1]; dterr = ParseDateTime(str, workbuf, sizeof(workbuf), field, ftype, MAXDATEFIELDS, &nf); if (dterr == 0) dterr = DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tzp); if (dterr != 0) DateTimeParseError(dterr, str, "date"); switch (dtype) { case DTK_DATE: break; case DTK_CURRENT: ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("date/time value \"current\" is no longer supported"))); GetCurrentDateTime(tm); break; case DTK_EPOCH: GetEpochTime(tm); break; default: DateTimeParseError(DTERR_BAD_FORMAT, str, "date"); break; } if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday)) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("date out of range: \"%s\"", str))); date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE; PG_RETURN_DATEADT(date);}/* date_out() * Given internal format date, convert to text string. */Datumdate_out(PG_FUNCTION_ARGS){ DateADT date = PG_GETARG_DATEADT(0); char *result; struct pg_tm tt, *tm = &tt; char buf[MAXDATELEN + 1]; j2date(date + POSTGRES_EPOCH_JDATE, &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); EncodeDateOnly(tm, DateStyle, buf); result = pstrdup(buf); PG_RETURN_CSTRING(result);}/* * date_recv - converts external binary format to date */Datumdate_recv(PG_FUNCTION_ARGS){ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); PG_RETURN_DATEADT((DateADT) pq_getmsgint(buf, sizeof(DateADT)));}/* * date_send - converts date to binary format */Datumdate_send(PG_FUNCTION_ARGS){ DateADT date = PG_GETARG_DATEADT(0); StringInfoData buf; pq_begintypsend(&buf); pq_sendint(&buf, date, sizeof(date)); PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}/* * Comparison functions for dates */Datumdate_eq(PG_FUNCTION_ARGS){ DateADT dateVal1 = PG_GETARG_DATEADT(0); DateADT dateVal2 = PG_GETARG_DATEADT(1); PG_RETURN_BOOL(dateVal1 == dateVal2);}Datumdate_ne(PG_FUNCTION_ARGS){ DateADT dateVal1 = PG_GETARG_DATEADT(0); DateADT dateVal2 = PG_GETARG_DATEADT(1); PG_RETURN_BOOL(dateVal1 != dateVal2);}Datumdate_lt(PG_FUNCTION_ARGS){ DateADT dateVal1 = PG_GETARG_DATEADT(0); DateADT dateVal2 = PG_GETARG_DATEADT(1); PG_RETURN_BOOL(dateVal1 < dateVal2);}Datumdate_le(PG_FUNCTION_ARGS){ DateADT dateVal1 = PG_GETARG_DATEADT(0); DateADT dateVal2 = PG_GETARG_DATEADT(1); PG_RETURN_BOOL(dateVal1 <= dateVal2);}Datumdate_gt(PG_FUNCTION_ARGS){ DateADT dateVal1 = PG_GETARG_DATEADT(0); DateADT dateVal2 = PG_GETARG_DATEADT(1); PG_RETURN_BOOL(dateVal1 > dateVal2);}Datumdate_ge(PG_FUNCTION_ARGS){ DateADT dateVal1 = PG_GETARG_DATEADT(0); DateADT dateVal2 = PG_GETARG_DATEADT(1); PG_RETURN_BOOL(dateVal1 >= dateVal2);}Datumdate_cmp(PG_FUNCTION_ARGS){ DateADT dateVal1 = PG_GETARG_DATEADT(0); DateADT dateVal2 = PG_GETARG_DATEADT(1); if (dateVal1 < dateVal2) PG_RETURN_INT32(-1); else if (dateVal1 > dateVal2) PG_RETURN_INT32(1); PG_RETURN_INT32(0);}Datumdate_larger(PG_FUNCTION_ARGS){ DateADT dateVal1 = PG_GETARG_DATEADT(0); DateADT dateVal2 = PG_GETARG_DATEADT(1); PG_RETURN_DATEADT((dateVal1 > dateVal2) ? dateVal1 : dateVal2);}Datumdate_smaller(PG_FUNCTION_ARGS){ DateADT dateVal1 = PG_GETARG_DATEADT(0); DateADT dateVal2 = PG_GETARG_DATEADT(1); PG_RETURN_DATEADT((dateVal1 < dateVal2) ? dateVal1 : dateVal2);}/* Compute difference between two dates in days. */Datumdate_mi(PG_FUNCTION_ARGS){ DateADT dateVal1 = PG_GETARG_DATEADT(0); DateADT dateVal2 = PG_GETARG_DATEADT(1); PG_RETURN_INT32((int32) (dateVal1 - dateVal2));}/* Add a number of days to a date, giving a new date. * Must handle both positive and negative numbers of days. */Datumdate_pli(PG_FUNCTION_ARGS){ DateADT dateVal = PG_GETARG_DATEADT(0); int32 days = PG_GETARG_INT32(1); PG_RETURN_DATEADT(dateVal + days);}/* Subtract a number of days from a date, giving a new date. */Datumdate_mii(PG_FUNCTION_ARGS){ DateADT dateVal = PG_GETARG_DATEADT(0); int32 days = PG_GETARG_INT32(1); PG_RETURN_DATEADT(dateVal - days);}/* * Internal routines for promoting date to timestamp and timestamp with * time zone */static Timestampdate2timestamp(DateADT dateVal){ Timestamp result;#ifdef HAVE_INT64_TIMESTAMP /* date is days since 2000, timestamp is microseconds since same... */ result = dateVal * USECS_PER_DAY; /* Date's range is wider than timestamp's, so must check for overflow */ if (result / USECS_PER_DAY != dateVal) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("date out of range for timestamp")));#else /* date is days since 2000, timestamp is seconds since same... */ result = dateVal * (double) SECS_PER_DAY;#endif return result;}static TimestampTzdate2timestamptz(DateADT dateVal){ TimestampTz result; struct pg_tm tt, *tm = &tt; int tz; j2date(dateVal + POSTGRES_EPOCH_JDATE, &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); tm->tm_hour = 0; tm->tm_min = 0; tm->tm_sec = 0; tz = DetermineTimeZoneOffset(tm, session_timezone);#ifdef HAVE_INT64_TIMESTAMP result = dateVal * USECS_PER_DAY + tz * USECS_PER_SEC; /* Date's range is wider than timestamp's, so must check for overflow */ if ((result - tz * USECS_PER_SEC) / USECS_PER_DAY != dateVal) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("date out of range for timestamp")));#else result = dateVal * (double) SECS_PER_DAY + tz;#endif return result;}/* * Crosstype comparison functions for dates */Datumdate_eq_timestamp(PG_FUNCTION_ARGS){ DateADT dateVal = PG_GETARG_DATEADT(0); Timestamp dt2 = PG_GETARG_TIMESTAMP(1); Timestamp dt1; dt1 = date2timestamp(dateVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) == 0);}Datumdate_ne_timestamp(PG_FUNCTION_ARGS){ DateADT dateVal = PG_GETARG_DATEADT(0); Timestamp dt2 = PG_GETARG_TIMESTAMP(1); Timestamp dt1; dt1 = date2timestamp(dateVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) != 0);}Datumdate_lt_timestamp(PG_FUNCTION_ARGS){ DateADT dateVal = PG_GETARG_DATEADT(0); Timestamp dt2 = PG_GETARG_TIMESTAMP(1); Timestamp dt1; dt1 = date2timestamp(dateVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) < 0);}Datumdate_gt_timestamp(PG_FUNCTION_ARGS){ DateADT dateVal = PG_GETARG_DATEADT(0); Timestamp dt2 = PG_GETARG_TIMESTAMP(1); Timestamp dt1; dt1 = date2timestamp(dateVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) > 0);}Datumdate_le_timestamp(PG_FUNCTION_ARGS){ DateADT dateVal = PG_GETARG_DATEADT(0); Timestamp dt2 = PG_GETARG_TIMESTAMP(1); Timestamp dt1; dt1 = date2timestamp(dateVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) <= 0);}Datumdate_ge_timestamp(PG_FUNCTION_ARGS){ DateADT dateVal = PG_GETARG_DATEADT(0); Timestamp dt2 = PG_GETARG_TIMESTAMP(1); Timestamp dt1; dt1 = date2timestamp(dateVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) >= 0);}Datumdate_cmp_timestamp(PG_FUNCTION_ARGS){ DateADT dateVal = PG_GETARG_DATEADT(0); Timestamp dt2 = PG_GETARG_TIMESTAMP(1); Timestamp dt1; dt1 = date2timestamp(dateVal); PG_RETURN_INT32(timestamp_cmp_internal(dt1, dt2));}Datumdate_eq_timestamptz(PG_FUNCTION_ARGS){ DateADT dateVal = PG_GETARG_DATEADT(0); TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1); TimestampTz dt1; dt1 = date2timestamptz(dateVal); PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) == 0);}Datumdate_ne_timestamptz(PG_FUNCTION_ARGS){ DateADT dateVal = PG_GETARG_DATEADT(0); TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1); TimestampTz dt1; dt1 = date2timestamptz(dateVal); PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) != 0);}Datumdate_lt_timestamptz(PG_FUNCTION_ARGS){ DateADT dateVal = PG_GETARG_DATEADT(0); TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1); TimestampTz dt1; dt1 = date2timestamptz(dateVal); PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) < 0);}Datumdate_gt_timestamptz(PG_FUNCTION_ARGS){ DateADT dateVal = PG_GETARG_DATEADT(0); TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1); TimestampTz dt1; dt1 = date2timestamptz(dateVal); PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) > 0);}Datumdate_le_timestamptz(PG_FUNCTION_ARGS){ DateADT dateVal = PG_GETARG_DATEADT(0); TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1); TimestampTz dt1; dt1 = date2timestamptz(dateVal); PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) <= 0);}Datumdate_ge_timestamptz(PG_FUNCTION_ARGS){ DateADT dateVal = PG_GETARG_DATEADT(0); TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1); TimestampTz dt1; dt1 = date2timestamptz(dateVal); PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) >= 0);}Datumdate_cmp_timestamptz(PG_FUNCTION_ARGS){ DateADT dateVal = PG_GETARG_DATEADT(0); TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1); TimestampTz dt1; dt1 = date2timestamptz(dateVal); PG_RETURN_INT32(timestamptz_cmp_internal(dt1, dt2));}Datumtimestamp_eq_date(PG_FUNCTION_ARGS){ Timestamp dt1 = PG_GETARG_TIMESTAMP(0); DateADT dateVal = PG_GETARG_DATEADT(1); Timestamp dt2; dt2 = date2timestamp(dateVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) == 0);}Datumtimestamp_ne_date(PG_FUNCTION_ARGS){ Timestamp dt1 = PG_GETARG_TIMESTAMP(0); DateADT dateVal = PG_GETARG_DATEADT(1); Timestamp dt2; dt2 = date2timestamp(dateVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) != 0);}Datumtimestamp_lt_date(PG_FUNCTION_ARGS){ Timestamp dt1 = PG_GETARG_TIMESTAMP(0); DateADT dateVal = PG_GETARG_DATEADT(1); Timestamp dt2; dt2 = date2timestamp(dateVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) < 0);}Datumtimestamp_gt_date(PG_FUNCTION_ARGS){ Timestamp dt1 = PG_GETARG_TIMESTAMP(0); DateADT dateVal = PG_GETARG_DATEADT(1); Timestamp dt2; dt2 = date2timestamp(dateVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) > 0);}Datumtimestamp_le_date(PG_FUNCTION_ARGS){ Timestamp dt1 = PG_GETARG_TIMESTAMP(0); DateADT dateVal = PG_GETARG_DATEADT(1); Timestamp dt2; dt2 = date2timestamp(dateVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) <= 0);}Datumtimestamp_ge_date(PG_FUNCTION_ARGS){ Timestamp dt1 = PG_GETARG_TIMESTAMP(0); DateADT dateVal = PG_GETARG_DATEADT(1); Timestamp dt2; dt2 = date2timestamp(dateVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) >= 0);}Datumtimestamp_cmp_date(PG_FUNCTION_ARGS){ Timestamp dt1 = PG_GETARG_TIMESTAMP(0); DateADT dateVal = PG_GETARG_DATEADT(1); Timestamp dt2;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?