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 + -
显示快捷键?