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

📄 timestamp.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 5 页
字号:
/*------------------------------------------------------------------------- * * timestamp.c *	  Functions for the built-in SQL92 types "timestamp" and "interval". * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.96.2.1 2004/05/31 18:32:23 tgl Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include <ctype.h>#include <math.h>#include <errno.h>#include <float.h>#include <limits.h>/* for finite() on Solaris */#ifdef HAVE_IEEEFP_H#include <ieeefp.h>#endif#include "access/hash.h"#include "access/xact.h"#include "catalog/pg_type.h"#include "libpq/pqformat.h"#include "miscadmin.h"#include "utils/array.h"#include "utils/builtins.h"/* * gcc's -ffast-math switch breaks routines that expect exact results from * expressions like timeval / 3600, where timeval is double. */#ifdef __FAST_MATH__#error -ffast-math is known to break this code#endif#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);/***************************************************************************** *	 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 tm	tt,			   *tm = &tt;	int			tz;	int			dtype;	int			nf;	int			dterr;	char	   *field[MAXDATEFIELDS];	int			ftype[MAXDATEFIELDS];	char		lowstr[MAXDATELEN + MAXDATEFIELDS];	if (strlen(str) >= sizeof(lowstr))		dterr = DTERR_BAD_FORMAT;	else		dterr = ParseDateTime(str, lowstr, 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 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) == 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 HAVE_INT64_TIMESTAMP	PG_RETURN_TIMESTAMP((Timestamp) pq_getmsgint64(buf));#else	PG_RETURN_TIMESTAMP((Timestamp) pq_getmsgfloat8(buf));#endif}/* *		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 tm	tt,			   *tm = &tt;	int			tz;	int			dtype;	int			nf;	int			dterr;	char	   *field[MAXDATEFIELDS];	int			ftype[MAXDATEFIELDS];	char		lowstr[MAXDATELEN + MAXDATEFIELDS];	if (strlen(str) >= sizeof(lowstr))		dterr = DTERR_BAD_FORMAT;	else		dterr = ParseDateTime(str, lowstr, 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 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) == 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 HAVE_INT64_TIMESTAMP	PG_RETURN_TIMESTAMPTZ((TimestampTz) pq_getmsgint64(buf));#else	PG_RETURN_TIMESTAMPTZ((TimestampTz) pq_getmsgfloat8(buf));#endif}/* *		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 tm	tt,			   *tm = &tt;	int			dtype;	int			nf;	int			dterr;	char	   *field[MAXDATEFIELDS];	int			ftype[MAXDATEFIELDS];	char		lowstr[MAXDATELEN + MAXDATEFIELDS];	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;	if (strlen(str) >= sizeof(lowstr))		dterr = DTERR_BAD_FORMAT;	else		dterr = ParseDateTime(str, lowstr, 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")));			AdjustIntervalForTypmod(result, typmod);			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);	}	PG_RETURN_INTERVAL_P(result);}/* interval_out() * Convert a time span to external form. */Datuminterval_out(PG_FUNCTION_ARGS){	Interval   *span = PG_GETARG_INTERVAL_P(0);	char	   *result;	struct tm	tt,			   *tm = &tt;	fsec_t		fsec;	char		buf[MAXDATELEN + 1];	if (interval2tm(*span, tm, &fsec) != 0)		elog(ERROR, "could not convert interval to tm");	if (EncodeInterval(tm, fsec, DateStyle, buf) != 0)		elog(ERROR, "could not format interval");	result = pstrdup(buf);	PG_RETURN_CSTRING(result);}/* *		interval_recv			- converts external binary format to interval */Datuminterval_recv(PG_FUNCTION_ARGS){	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);	Interval   *interval;	interval = (Interval *) palloc(sizeof(Interval));#ifdef HAVE_INT64_TIMESTAMP	interval->time = pq_getmsgint64(buf);#else	interval->time = pq_getmsgfloat8(buf);#endif	interval->month = pq_getmsgint(buf, sizeof(interval->month));	PG_RETURN_INTERVAL_P(interval);}/* *		interval_send			- converts interval to binary format */Datuminterval_send(PG_FUNCTION_ARGS){	Interval   *interval = PG_GETARG_INTERVAL_P(0);	StringInfoData buf;

⌨️ 快捷键说明

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