⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nabstime.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/*------------------------------------------------------------------------- * * nabstime.c *	  Utilities for the built-in type "AbsoluteTime". *	  Functions for the built-in type "RelativeTime". *	  Functions for the built-in type "TimeInterval". * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/utils/adt/nabstime.c,v 1.146 2005/10/22 14:27:29 adunstan Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include <ctype.h>#include <float.h>#include <limits.h>#include <time.h>#include <sys/time.h>#include "access/xact.h"#include "libpq/pqformat.h"#include "miscadmin.h"#include "pgtime.h"#include "utils/builtins.h"#include "utils/nabstime.h"#define MIN_DAYNUM (-24856)		/* December 13, 1901 */#define MAX_DAYNUM 24854		/* January 18, 2038 */#define INVALID_RELTIME_STR		"Undefined RelTime"#define INVALID_RELTIME_STR_LEN (sizeof(INVALID_RELTIME_STR)-1)#define RELTIME_LABEL			'@'#define RELTIME_PAST			"ago"#define DIRMAXLEN				(sizeof(RELTIME_PAST)-1)/* * Unix epoch is Jan  1 00:00:00 1970. * Postgres knows about times sixty-eight years on either side of that * for these 4-byte types. * * "tinterval" is two 4-byte fields. * Definitions for parsing tinterval. */#define IsSpace(C)				((C) == ' ')#define T_INTERVAL_INVAL   0	/* data represents no valid tinterval */#define T_INTERVAL_VALID   1	/* data represents a valid tinterval *//* * ['Mon May 10 23:59:12 1943 PST' 'Sun Jan 14 03:14:21 1973 PST'] * 0		1		  2			3		  4			5		  6 * 1234567890123456789012345678901234567890123456789012345678901234 * * we allocate some extra -- timezones are usually 3 characters but * this is not in the POSIX standard... */#define T_INTERVAL_LEN					80#define INVALID_INTERVAL_STR			"Undefined Range"#define INVALID_INTERVAL_STR_LEN		(sizeof(INVALID_INTERVAL_STR)-1)#define ABSTIMEMIN(t1, t2) \	(DatumGetBool(DirectFunctionCall2(abstimele, \				  AbsoluteTimeGetDatum(t1), \				  AbsoluteTimeGetDatum(t2))) ? (t1) : (t2))#define ABSTIMEMAX(t1, t2) \	(DatumGetBool(DirectFunctionCall2(abstimelt, \				  AbsoluteTimeGetDatum(t1), \				  AbsoluteTimeGetDatum(t2))) ? (t2) : (t1))/* * Function prototypes -- internal to this file only */static AbsoluteTime tm2abstime(struct pg_tm * tm, int tz);static void reltime2tm(RelativeTime time, struct pg_tm * tm);static void parsetinterval(char *i_string,			   AbsoluteTime *i_start,			   AbsoluteTime *i_end);/* * GetCurrentAbsoluteTime() * * Get the current system time (relative to Unix epoch). */AbsoluteTimeGetCurrentAbsoluteTime(void){	time_t		now;	now = time(NULL);	return (AbsoluteTime) now;}voidabstime2tm(AbsoluteTime _time, int *tzp, struct pg_tm * tm, char **tzn){	pg_time_t	time = (pg_time_t) _time;	struct pg_tm *tx;	/*	 * If HasCTZSet is true then we have a brute force time zone specified. Go	 * ahead and rotate to the local time zone since we will later bypass any	 * calls which adjust the tm fields.	 */	if (HasCTZSet && (tzp != NULL))		time -= CTimeZone;	if (!HasCTZSet && tzp != NULL)		tx = pg_localtime(&time, global_timezone);	else		tx = pg_gmtime(&time);	tm->tm_year = tx->tm_year + 1900;	tm->tm_mon = tx->tm_mon + 1;	tm->tm_mday = tx->tm_mday;	tm->tm_hour = tx->tm_hour;	tm->tm_min = tx->tm_min;	tm->tm_sec = tx->tm_sec;	tm->tm_isdst = tx->tm_isdst;	tm->tm_gmtoff = tx->tm_gmtoff;	tm->tm_zone = tx->tm_zone;	if (tzp != NULL)	{		/*		 * We have a brute force time zone per SQL99? Then use it without		 * change since we have already rotated to the time zone.		 */		if (HasCTZSet)		{			*tzp = CTimeZone;			tm->tm_gmtoff = CTimeZone;			tm->tm_isdst = 0;			tm->tm_zone = NULL;			if (tzn != NULL)				*tzn = NULL;		}		else		{			*tzp = -tm->tm_gmtoff;		/* tm_gmtoff is Sun/DEC-ism */			/*			 * XXX FreeBSD man pages indicate that this should work - tgl			 * 97/04/23			 */			if (tzn != NULL)			{				/*				 * Copy no more than MAXTZLEN bytes of timezone to tzn, in				 * case it contains an error message, which doesn't fit in the				 * buffer				 */				StrNCpy(*tzn, tm->tm_zone, MAXTZLEN + 1);				if (strlen(tm->tm_zone) > MAXTZLEN)					ereport(WARNING,							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),							 errmsg("invalid time zone name: \"%s\"",									tm->tm_zone)));			}		}	}	else		tm->tm_isdst = -1;}/* tm2abstime() * Convert a tm structure to abstime. * Note that tm has full year (not 1900-based) and 1-based month. */static AbsoluteTimetm2abstime(struct pg_tm * tm, int tz){	int			day;	AbsoluteTime sec;	/* validate, before going out of range on some members */	if (tm->tm_year < 1901 || tm->tm_year > 2038 ||		tm->tm_mon < 1 || tm->tm_mon > 12 ||		tm->tm_mday < 1 || tm->tm_mday > 31 ||		tm->tm_hour < 0 ||		tm->tm_hour > 24 ||		/* test for > 24:00:00 */		(tm->tm_hour == 24 && (tm->tm_min > 0 || tm->tm_sec > 0)) ||		tm->tm_min < 0 || tm->tm_min > 59 ||		tm->tm_sec < 0 || tm->tm_sec > 60)		return INVALID_ABSTIME;	day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - UNIX_EPOCH_JDATE;	/* check for time out of range */	if (day < MIN_DAYNUM || day > MAX_DAYNUM)		return INVALID_ABSTIME;	/* convert to seconds */	sec = tm->tm_sec + tz + (tm->tm_min + (day * HOURS_PER_DAY + tm->tm_hour) * MINS_PER_HOUR) * SECS_PER_MINUTE;	/*	 * check for overflow.	We need a little slop here because the H/M/S plus	 * TZ offset could add up to more than 1 day.	 */	if ((day >= MAX_DAYNUM - 10 && sec < 0) ||		(day <= MIN_DAYNUM + 10 && sec > 0))		return INVALID_ABSTIME;	/* check for reserved values (e.g. "current" on edge of usual range */	if (!AbsoluteTimeIsReal(sec))		return INVALID_ABSTIME;	return sec;}/* abstimein() * Decode date/time string and return abstime. */Datumabstimein(PG_FUNCTION_ARGS){	char	   *str = PG_GETARG_CSTRING(0);	AbsoluteTime result;	fsec_t		fsec;	int			tz = 0;	struct pg_tm date,			   *tm = &date;	int			dterr;	char	   *field[MAXDATEFIELDS];	char		workbuf[MAXDATELEN + 1];	int			dtype;	int			nf,				ftype[MAXDATEFIELDS];	dterr = ParseDateTime(str, workbuf, sizeof(workbuf),						  field, ftype, MAXDATEFIELDS, &nf);	if (dterr == 0)		dterr = DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz);	if (dterr != 0)		DateTimeParseError(dterr, str, "abstime");	switch (dtype)	{		case DTK_DATE:			result = tm2abstime(tm, tz);			break;		case DTK_EPOCH:			/*			 * Don't bother retaining this as a reserved value, but instead			 * just set to the actual epoch time (1970-01-01)			 */			result = 0;			break;		case DTK_LATE:			result = NOEND_ABSTIME;			break;		case DTK_EARLY:			result = NOSTART_ABSTIME;			break;		case DTK_INVALID:			result = INVALID_ABSTIME;			break;		default:			elog(ERROR, "unexpected dtype %d while parsing abstime \"%s\"",				 dtype, str);			result = INVALID_ABSTIME;			break;	};	PG_RETURN_ABSOLUTETIME(result);}/* abstimeout() * Given an AbsoluteTime return the English text version of the date */Datumabstimeout(PG_FUNCTION_ARGS){	AbsoluteTime time = PG_GETARG_ABSOLUTETIME(0);	char	   *result;	int			tz;	double		fsec = 0;	struct pg_tm tt,			   *tm = &tt;	char		buf[MAXDATELEN + 1];	char		zone[MAXDATELEN + 1],			   *tzn = zone;	switch (time)	{			/*			 * Note that timestamp no longer supports 'invalid'. Retain			 * 'invalid' for abstime for now, but dump it someday.			 */		case INVALID_ABSTIME:			strcpy(buf, INVALID);			break;		case NOEND_ABSTIME:			strcpy(buf, LATE);			break;		case NOSTART_ABSTIME:			strcpy(buf, EARLY);			break;		default:			abstime2tm(time, &tz, tm, &tzn);			EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);			break;	}	result = pstrdup(buf);	PG_RETURN_CSTRING(result);}/* *		abstimerecv			- converts external binary format to abstime */Datumabstimerecv(PG_FUNCTION_ARGS){	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);	PG_RETURN_ABSOLUTETIME((AbsoluteTime) pq_getmsgint(buf, sizeof(AbsoluteTime)));}/* *		abstimesend			- converts abstime to binary format */Datumabstimesend(PG_FUNCTION_ARGS){	AbsoluteTime time = PG_GETARG_ABSOLUTETIME(0);	StringInfoData buf;	pq_begintypsend(&buf);	pq_sendint(&buf, time, sizeof(time));	PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}/* abstime_finite() */Datumabstime_finite(PG_FUNCTION_ARGS){	AbsoluteTime abstime = PG_GETARG_ABSOLUTETIME(0);	PG_RETURN_BOOL(abstime != INVALID_ABSTIME &&				   abstime != NOSTART_ABSTIME &&				   abstime != NOEND_ABSTIME);}/* * abstime comparison routines */static intabstime_cmp_internal(AbsoluteTime a, AbsoluteTime b){	/*	 * We consider all INVALIDs to be equal and larger than any non-INVALID.	 * This is somewhat arbitrary; the important thing is to have a consistent	 * sort order.	 */	if (a == INVALID_ABSTIME)	{		if (b == INVALID_ABSTIME)			return 0;			/* INVALID = INVALID */		else			return 1;			/* INVALID > non-INVALID */	}	if (b == INVALID_ABSTIME)		return -1;				/* non-INVALID < INVALID */	if (a > b)		return 1;	else if (a == b)		return 0;	else		return -1;}Datumabstimeeq(PG_FUNCTION_ARGS){	AbsoluteTime t1 = PG_GETARG_ABSOLUTETIME(0);	AbsoluteTime t2 = PG_GETARG_ABSOLUTETIME(1);	PG_RETURN_BOOL(abstime_cmp_internal(t1, t2) == 0);}Datumabstimene(PG_FUNCTION_ARGS){	AbsoluteTime t1 = PG_GETARG_ABSOLUTETIME(0);	AbsoluteTime t2 = PG_GETARG_ABSOLUTETIME(1);	PG_RETURN_BOOL(abstime_cmp_internal(t1, t2) != 0);}Datumabstimelt(PG_FUNCTION_ARGS){	AbsoluteTime t1 = PG_GETARG_ABSOLUTETIME(0);	AbsoluteTime t2 = PG_GETARG_ABSOLUTETIME(1);	PG_RETURN_BOOL(abstime_cmp_internal(t1, t2) < 0);}Datumabstimegt(PG_FUNCTION_ARGS){	AbsoluteTime t1 = PG_GETARG_ABSOLUTETIME(0);	AbsoluteTime t2 = PG_GETARG_ABSOLUTETIME(1);	PG_RETURN_BOOL(abstime_cmp_internal(t1, t2) > 0);}Datumabstimele(PG_FUNCTION_ARGS){	AbsoluteTime t1 = PG_GETARG_ABSOLUTETIME(0);	AbsoluteTime t2 = PG_GETARG_ABSOLUTETIME(1);	PG_RETURN_BOOL(abstime_cmp_internal(t1, t2) <= 0);}Datumabstimege(PG_FUNCTION_ARGS){	AbsoluteTime t1 = PG_GETARG_ABSOLUTETIME(0);	AbsoluteTime t2 = PG_GETARG_ABSOLUTETIME(1);	PG_RETURN_BOOL(abstime_cmp_internal(t1, t2) >= 0);}Datumbtabstimecmp(PG_FUNCTION_ARGS){	AbsoluteTime t1 = PG_GETARG_ABSOLUTETIME(0);	AbsoluteTime t2 = PG_GETARG_ABSOLUTETIME(1);	PG_RETURN_INT32(abstime_cmp_internal(t1, t2));}/* timestamp_abstime() * Convert timestamp to abstime. */Datumtimestamp_abstime(PG_FUNCTION_ARGS){	Timestamp	timestamp = PG_GETARG_TIMESTAMP(0);	AbsoluteTime result;	fsec_t		fsec;	int			tz;	struct pg_tm tt,			   *tm = &tt;	if (TIMESTAMP_IS_NOBEGIN(timestamp))		result = NOSTART_ABSTIME;	else if (TIMESTAMP_IS_NOEND(timestamp))		result = NOEND_ABSTIME;	else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) == 0)	{		tz = DetermineTimeZoneOffset(tm, global_timezone);		result = tm2abstime(tm, tz);	}	else	{		ereport(ERROR,				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),				 errmsg("timestamp out of range")));		result = INVALID_ABSTIME;	}	PG_RETURN_ABSOLUTETIME(result);}/* abstime_timestamp() * Convert abstime to timestamp. */Datumabstime_timestamp(PG_FUNCTION_ARGS){	AbsoluteTime abstime = PG_GETARG_ABSOLUTETIME(0);	Timestamp	result;	struct pg_tm tt,			   *tm = &tt;	int			tz;	char		zone[MAXDATELEN + 1],			   *tzn = zone;	switch (abstime)	{		case INVALID_ABSTIME:			ereport(ERROR,					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),				 errmsg("cannot convert abstime \"invalid\" to timestamp")));			TIMESTAMP_NOBEGIN(result);			break;		case NOSTART_ABSTIME:			TIMESTAMP_NOBEGIN(result);			break;		case NOEND_ABSTIME:			TIMESTAMP_NOEND(result);			break;		default:			abstime2tm(abstime, &tz, tm, &tzn);			if (tm2timestamp(tm, 0, NULL, &result) != 0)				ereport(ERROR,						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),						 errmsg("timestamp out of range")));			break;	};	PG_RETURN_TIMESTAMP(result);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -