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

📄 timestamp.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
/*------------------------------------------------------------------------- * * timestamp.c *	  Functions for the built-in SQL92 types "timestamp" and "interval". * * 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/timestamp.c,v 1.157.2.1 2005/11/22 18:23:22 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include <ctype.h>#include <math.h>#include <float.h>#include <limits.h>#include <sys/time.h>#include "access/hash.h"#include "access/xact.h"#include "catalog/pg_type.h"#include "libpq/pqformat.h"#include "miscadmin.h"#include "parser/scansup.h"#include "utils/array.h"#include "utils/builtins.h"#include "utils/datetime.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#endif/* Set at postmaster start */TimestampTz PgStartTime;#ifdef HAVE_INT64_TIMESTAMPstatic int64 time2t(const int hour, const int min, const int sec, const fsec_t fsec);#elsestatic double time2t(const int hour, const int min, const int sec, const fsec_t fsec);#endifstatic int	EncodeSpecialTimestamp(Timestamp dt, char *str);static Timestamp dt2local(Timestamp dt, int timezone);static void AdjustTimestampForTypmod(Timestamp *time, int32 typmod);static void AdjustIntervalForTypmod(Interval *interval, int32 typmod);static TimestampTz timestamp2timestamptz(Timestamp timestamp);/***************************************************************************** *	 USER I/O ROUTINES														 * *****************************************************************************//* timestamp_in() * Convert a string to internal form. */Datumtimestamp_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);	Timestamp	result;	fsec_t		fsec;	struct pg_tm tt,			   *tm = &tt;	int			tz;	int			dtype;	int			nf;	int			dterr;	char	   *field[MAXDATEFIELDS];	int			ftype[MAXDATEFIELDS];	char		workbuf[MAXDATELEN + 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, "timestamp");	switch (dtype)	{		case DTK_DATE:			if (tm2timestamp(tm, fsec, NULL, &result) != 0)				ereport(ERROR,						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),						 errmsg("timestamp out of range: \"%s\"", str)));			break;		case DTK_EPOCH:			result = SetEpochTimestamp();			break;		case DTK_LATE:			TIMESTAMP_NOEND(result);			break;		case DTK_EARLY:			TIMESTAMP_NOBEGIN(result);			break;		case DTK_INVALID:			ereport(ERROR,					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),			  errmsg("date/time value \"%s\" is no longer supported", str)));			TIMESTAMP_NOEND(result);			break;		default:			elog(ERROR, "unexpected dtype %d while parsing timestamp \"%s\"",				 dtype, str);			TIMESTAMP_NOEND(result);	}	AdjustTimestampForTypmod(&result, typmod);	PG_RETURN_TIMESTAMP(result);}/* timestamp_out() * Convert a timestamp to external form. */Datumtimestamp_out(PG_FUNCTION_ARGS){	Timestamp	timestamp = PG_GETARG_TIMESTAMP(0);	char	   *result;	struct pg_tm tt,			   *tm = &tt;	fsec_t		fsec;	char	   *tzn = NULL;	char		buf[MAXDATELEN + 1];	if (TIMESTAMP_NOT_FINITE(timestamp))		EncodeSpecialTimestamp(timestamp, buf);	else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) == 0)		EncodeDateTime(tm, fsec, NULL, &tzn, DateStyle, buf);	else		ereport(ERROR,				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),				 errmsg("timestamp out of range")));	result = pstrdup(buf);	PG_RETURN_CSTRING(result);}/* *		timestamp_recv			- converts external binary format to timestamp * * We make no attempt to provide compatibility between int and float * timestamp representations ... */Datumtimestamp_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);	Timestamp	timestamp;	struct pg_tm tt,			   *tm = &tt;	fsec_t		fsec;#ifdef HAVE_INT64_TIMESTAMP	timestamp = (Timestamp) pq_getmsgint64(buf);#else	timestamp = (Timestamp) pq_getmsgfloat8(buf);#endif	/* rangecheck: see if timestamp_out would like it */	if (TIMESTAMP_NOT_FINITE(timestamp))		 /* ok */ ;	else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)		ereport(ERROR,				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),				 errmsg("timestamp out of range")));	AdjustTimestampForTypmod(&timestamp, typmod);	PG_RETURN_TIMESTAMP(timestamp);}/* *		timestamp_send			- converts timestamp to binary format */Datumtimestamp_send(PG_FUNCTION_ARGS){	Timestamp	timestamp = PG_GETARG_TIMESTAMP(0);	StringInfoData buf;	pq_begintypsend(&buf);#ifdef HAVE_INT64_TIMESTAMP	pq_sendint64(&buf, timestamp);#else	pq_sendfloat8(&buf, timestamp);#endif	PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}/* timestamp_scale() * Adjust time type for specified scale factor. * Used by PostgreSQL type system to stuff columns. */Datumtimestamp_scale(PG_FUNCTION_ARGS){	Timestamp	timestamp = PG_GETARG_TIMESTAMP(0);	int32		typmod = PG_GETARG_INT32(1);	Timestamp	result;	result = timestamp;	AdjustTimestampForTypmod(&result, typmod);	PG_RETURN_TIMESTAMP(result);}static voidAdjustTimestampForTypmod(Timestamp *time, int32 typmod){#ifdef HAVE_INT64_TIMESTAMP	static const int64 TimestampScales[MAX_TIMESTAMP_PRECISION + 1] = {		INT64CONST(1000000),		INT64CONST(100000),		INT64CONST(10000),		INT64CONST(1000),		INT64CONST(100),		INT64CONST(10),		INT64CONST(1)	};	static const int64 TimestampOffsets[MAX_TIMESTAMP_PRECISION + 1] = {		INT64CONST(500000),		INT64CONST(50000),		INT64CONST(5000),		INT64CONST(500),		INT64CONST(50),		INT64CONST(5),		INT64CONST(0)	};#else	static const double TimestampScales[MAX_TIMESTAMP_PRECISION + 1] = {		1,		10,		100,		1000,		10000,		100000,		1000000	};#endif	if (!TIMESTAMP_NOT_FINITE(*time)		&& (typmod != -1) && (typmod != MAX_TIMESTAMP_PRECISION))	{		if (typmod < 0 || typmod > MAX_TIMESTAMP_PRECISION)			ereport(ERROR,					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				  errmsg("timestamp(%d) precision must be between %d and %d",						 typmod, 0, MAX_TIMESTAMP_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 + TimestampOffsets[typmod]) / TimestampScales[typmod]) *				TimestampScales[typmod];		}		else		{			*time = -((((-*time) + TimestampOffsets[typmod]) / TimestampScales[typmod])					  * TimestampScales[typmod]);		}#else		*time = rint((double) *time * TimestampScales[typmod]) / TimestampScales[typmod];#endif	}}/* timestamptz_in() * Convert a string to internal form. */Datumtimestamptz_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);	TimestampTz result;	fsec_t		fsec;	struct pg_tm tt,			   *tm = &tt;	int			tz;	int			dtype;	int			nf;	int			dterr;	char	   *field[MAXDATEFIELDS];	int			ftype[MAXDATEFIELDS];	char		workbuf[MAXDATELEN + 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, "timestamp with time zone");	switch (dtype)	{		case DTK_DATE:			if (tm2timestamp(tm, fsec, &tz, &result) != 0)				ereport(ERROR,						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),						 errmsg("timestamp out of range: \"%s\"", str)));			break;		case DTK_EPOCH:			result = SetEpochTimestamp();			break;		case DTK_LATE:			TIMESTAMP_NOEND(result);			break;		case DTK_EARLY:			TIMESTAMP_NOBEGIN(result);			break;		case DTK_INVALID:			ereport(ERROR,					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),			  errmsg("date/time value \"%s\" is no longer supported", str)));			TIMESTAMP_NOEND(result);			break;		default:			elog(ERROR, "unexpected dtype %d while parsing timestamptz \"%s\"",				 dtype, str);			TIMESTAMP_NOEND(result);	}	AdjustTimestampForTypmod(&result, typmod);	PG_RETURN_TIMESTAMPTZ(result);}/* timestamptz_out() * Convert a timestamp to external form. */Datumtimestamptz_out(PG_FUNCTION_ARGS){	TimestampTz dt = PG_GETARG_TIMESTAMPTZ(0);	char	   *result;	int			tz;	struct pg_tm tt,			   *tm = &tt;	fsec_t		fsec;	char	   *tzn;	char		buf[MAXDATELEN + 1];	if (TIMESTAMP_NOT_FINITE(dt))		EncodeSpecialTimestamp(dt, buf);	else if (timestamp2tm(dt, &tz, tm, &fsec, &tzn, NULL) == 0)		EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);	else		ereport(ERROR,				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),				 errmsg("timestamp out of range")));	result = pstrdup(buf);	PG_RETURN_CSTRING(result);}/* *		timestamptz_recv			- converts external binary format to timestamptz * * We make no attempt to provide compatibility between int and float * timestamp representations ... */Datumtimestamptz_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);	TimestampTz timestamp;	int			tz;	struct pg_tm tt,			   *tm = &tt;	fsec_t		fsec;	char	   *tzn;#ifdef HAVE_INT64_TIMESTAMP	timestamp = (TimestampTz) pq_getmsgint64(buf);#else	timestamp = (TimestampTz) pq_getmsgfloat8(buf);#endif	/* rangecheck: see if timestamptz_out would like it */	if (TIMESTAMP_NOT_FINITE(timestamp))		 /* ok */ ;	else if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) != 0)		ereport(ERROR,				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),				 errmsg("timestamp out of range")));	AdjustTimestampForTypmod(&timestamp, typmod);	PG_RETURN_TIMESTAMPTZ(timestamp);}/* *		timestamptz_send			- converts timestamptz to binary format */Datumtimestamptz_send(PG_FUNCTION_ARGS){	TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(0);	StringInfoData buf;	pq_begintypsend(&buf);#ifdef HAVE_INT64_TIMESTAMP	pq_sendint64(&buf, timestamp);#else	pq_sendfloat8(&buf, timestamp);#endif	PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}/* timestamptz_scale() * Adjust time type for specified scale factor. * Used by PostgreSQL type system to stuff columns. */Datumtimestamptz_scale(PG_FUNCTION_ARGS){	TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(0);	int32		typmod = PG_GETARG_INT32(1);	TimestampTz result;	result = timestamp;	AdjustTimestampForTypmod(&result, typmod);	PG_RETURN_TIMESTAMPTZ(result);}/* interval_in() * Convert a string to internal form. * * External format(s): *	Uses the generic date/time parsing and decoding routines. */Datuminterval_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);	Interval   *result;	fsec_t		fsec;	struct pg_tm tt,			   *tm = &tt;	int			dtype;	int			nf;	int			dterr;	char	   *field[MAXDATEFIELDS];	int			ftype[MAXDATEFIELDS];	char		workbuf[256];	tm->tm_year = 0;	tm->tm_mon = 0;	tm->tm_mday = 0;	tm->tm_hour = 0;	tm->tm_min = 0;	tm->tm_sec = 0;	fsec = 0;	dterr = ParseDateTime(str, workbuf, sizeof(workbuf), field,						  ftype, MAXDATEFIELDS, &nf);	if (dterr == 0)		dterr = DecodeInterval(field, ftype, nf, &dtype, tm, &fsec);	if (dterr != 0)	{		if (dterr == DTERR_FIELD_OVERFLOW)			dterr = DTERR_INTERVAL_OVERFLOW;		DateTimeParseError(dterr, str, "interval");	}	result = (Interval *) palloc(sizeof(Interval));	switch (dtype)	{		case DTK_DELTA:			if (tm2interval(tm, fsec, result) != 0)				ereport(ERROR,						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),						 errmsg("interval out of range")));			break;		case DTK_INVALID:			ereport(ERROR,					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),			  errmsg("date/time value \"%s\" is no longer supported", str)));			break;		default:			elog(ERROR, "unexpected dtype %d while parsing interval \"%s\"",				 dtype, str);	}	AdjustIntervalForTypmod(result, typmod);	PG_RETURN_INTERVAL_P(result);

⌨️ 快捷键说明

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