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

📄 timestamp.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
}/* interval_out() * Convert a time span to external form. */Datuminterval_out(PG_FUNCTION_ARGS){	Interval   *span = PG_GETARG_INTERVAL_P(0);	char	   *result;	struct pg_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);#ifdef NOT_USED	Oid			typelem = PG_GETARG_OID(1);#endif	int32		typmod = PG_GETARG_INT32(2);	Interval   *interval;	interval = (Interval *) palloc(sizeof(Interval));#ifdef HAVE_INT64_TIMESTAMP	interval->time = pq_getmsgint64(buf);#else	interval->time = pq_getmsgfloat8(buf);#endif	interval->day = pq_getmsgint(buf, sizeof(interval->day));	interval->month = pq_getmsgint(buf, sizeof(interval->month));	AdjustIntervalForTypmod(interval, typmod);	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;	pq_begintypsend(&buf);#ifdef HAVE_INT64_TIMESTAMP	pq_sendint64(&buf, interval->time);#else	pq_sendfloat8(&buf, interval->time);#endif	pq_sendint(&buf, interval->day, sizeof(interval->day));	pq_sendint(&buf, interval->month, sizeof(interval->month));	PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}/* interval_scale() * Adjust interval type for specified fields. * Used by PostgreSQL type system to stuff columns. */Datuminterval_scale(PG_FUNCTION_ARGS){	Interval   *interval = PG_GETARG_INTERVAL_P(0);	int32		typmod = PG_GETARG_INT32(1);	Interval   *result;	result = palloc(sizeof(Interval));	*result = *interval;	AdjustIntervalForTypmod(result, typmod);	PG_RETURN_INTERVAL_P(result);}/* *	Adjust interval for specified precision, in both YEAR to SECOND *	range and sub-second precision. */static voidAdjustIntervalForTypmod(Interval *interval, int32 typmod){#ifdef HAVE_INT64_TIMESTAMP	static const int64 IntervalScales[MAX_INTERVAL_PRECISION + 1] = {		INT64CONST(1000000),		INT64CONST(100000),		INT64CONST(10000),		INT64CONST(1000),		INT64CONST(100),		INT64CONST(10),		INT64CONST(1)	};	static const int64 IntervalOffsets[MAX_INTERVAL_PRECISION + 1] = {		INT64CONST(500000),		INT64CONST(50000),		INT64CONST(5000),		INT64CONST(500),		INT64CONST(50),		INT64CONST(5),		INT64CONST(0)	};#else	static const double IntervalScales[MAX_INTERVAL_PRECISION + 1] = {		1,		10,		100,		1000,		10000,		100000,		1000000	};#endif	/*	 * Unspecified range and precision? Then not necessary to adjust. Setting	 * typmod to -1 is the convention for all types.	 */	if (typmod != -1)	{		int			range = INTERVAL_RANGE(typmod);		int			precision = INTERVAL_PRECISION(typmod);		if (range == INTERVAL_FULL_RANGE)		{			/* Do nothing... */		}		else if (range == INTERVAL_MASK(YEAR))		{			interval->month = (interval->month / MONTHS_PER_YEAR) * MONTHS_PER_YEAR;			interval->day = 0;			interval->time = 0;		}		else if (range == INTERVAL_MASK(MONTH))		{			interval->month %= MONTHS_PER_YEAR;			interval->day = 0;			interval->time = 0;		}		/* YEAR TO MONTH */		else if (range == (INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH)))		{			/* month is already year to month */			interval->day = 0;			interval->time = 0;		}		else if (range == INTERVAL_MASK(DAY))		{			interval->month = 0;			interval->time = 0;		}		else if (range == INTERVAL_MASK(HOUR))		{			interval->month = 0;			interval->day = 0;#ifdef HAVE_INT64_TIMESTAMP			interval->time = (interval->time / USECS_PER_HOUR) *				USECS_PER_HOUR;#else			interval->time = ((int) (interval->time / SECS_PER_HOUR)) * (double) SECS_PER_HOUR;#endif		}		else if (range == INTERVAL_MASK(MINUTE))		{#ifdef HAVE_INT64_TIMESTAMP			int64		hour;#else			double		hour;#endif			interval->month = 0;			interval->day = 0;#ifdef HAVE_INT64_TIMESTAMP			hour = interval->time / USECS_PER_HOUR;			interval->time -= hour * USECS_PER_HOUR;			interval->time = (interval->time / USECS_PER_MINUTE) *				USECS_PER_MINUTE;#else			TMODULO(interval->time, hour, (double) SECS_PER_HOUR);			interval->time = ((int) (interval->time / SECS_PER_MINUTE)) * (double) SECS_PER_MINUTE;#endif		}		else if (range == INTERVAL_MASK(SECOND))		{#ifdef HAVE_INT64_TIMESTAMP			int64		minute;#else			double		minute;#endif			interval->month = 0;			interval->day = 0;#ifdef HAVE_INT64_TIMESTAMP			minute = interval->time / USECS_PER_MINUTE;			interval->time -= minute * USECS_PER_MINUTE;#else			TMODULO(interval->time, minute, (double) SECS_PER_MINUTE);			/* return subseconds too */#endif		}		/* DAY TO HOUR */		else if (range == (INTERVAL_MASK(DAY) |						   INTERVAL_MASK(HOUR)))		{			interval->month = 0;#ifdef HAVE_INT64_TIMESTAMP			interval->time = (interval->time / USECS_PER_HOUR) *				USECS_PER_HOUR;#else			interval->time = ((int) (interval->time / SECS_PER_HOUR)) * (double) SECS_PER_HOUR;#endif		}		/* DAY TO MINUTE */		else if (range == (INTERVAL_MASK(DAY) |						   INTERVAL_MASK(HOUR) |						   INTERVAL_MASK(MINUTE)))		{			interval->month = 0;#ifdef HAVE_INT64_TIMESTAMP			interval->time = (interval->time / USECS_PER_MINUTE) *				USECS_PER_MINUTE;#else			interval->time = ((int) (interval->time / SECS_PER_MINUTE)) * (double) SECS_PER_MINUTE;#endif		}		/* DAY TO SECOND */		else if (range == (INTERVAL_MASK(DAY) |						   INTERVAL_MASK(HOUR) |						   INTERVAL_MASK(MINUTE) |						   INTERVAL_MASK(SECOND)))			interval->month = 0;		/* HOUR TO MINUTE */		else if (range == (INTERVAL_MASK(HOUR) |						   INTERVAL_MASK(MINUTE)))		{			interval->month = 0;			interval->day = 0;#ifdef HAVE_INT64_TIMESTAMP			interval->time = (interval->time / USECS_PER_MINUTE) *				USECS_PER_MINUTE;#else			interval->time = ((int) (interval->time / SECS_PER_MINUTE)) * (double) SECS_PER_MINUTE;#endif		}		/* HOUR TO SECOND */		else if (range == (INTERVAL_MASK(HOUR) |						   INTERVAL_MASK(MINUTE) |						   INTERVAL_MASK(SECOND)))		{			interval->month = 0;			interval->day = 0;			/* return subseconds too */		}		/* MINUTE TO SECOND */		else if (range == (INTERVAL_MASK(MINUTE) |						   INTERVAL_MASK(SECOND)))		{#ifdef HAVE_INT64_TIMESTAMP			int64		hour;#else			double		hour;#endif			interval->month = 0;			interval->day = 0;#ifdef HAVE_INT64_TIMESTAMP			hour = interval->time / USECS_PER_HOUR;			interval->time -= hour * USECS_PER_HOUR;#else			TMODULO(interval->time, hour, (double) SECS_PER_HOUR);#endif		}		else			elog(ERROR, "unrecognized interval typmod: %d", typmod);		/* Need to adjust subsecond precision? */		if (precision != INTERVAL_FULL_PRECISION)		{			if (precision < 0 || precision > MAX_INTERVAL_PRECISION)				ereport(ERROR,						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				   errmsg("interval(%d) precision must be between %d and %d",						  precision, 0, MAX_INTERVAL_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 (interval->time >= INT64CONST(0))			{				interval->time = ((interval->time +								   IntervalOffsets[precision]) /								  IntervalScales[precision]) *					IntervalScales[precision];			}			else			{				interval->time = -(((-interval->time +									 IntervalOffsets[precision]) /									IntervalScales[precision]) *								   IntervalScales[precision]);			}#else			interval->time = rint(((double) interval->time) *								  IntervalScales[precision]) /				IntervalScales[precision];#endif		}	}	return;}/* EncodeSpecialTimestamp() * Convert reserved timestamp data type to string. */static intEncodeSpecialTimestamp(Timestamp dt, char *str){	if (TIMESTAMP_IS_NOBEGIN(dt))		strcpy(str, EARLY);	else if (TIMESTAMP_IS_NOEND(dt))		strcpy(str, LATE);	else		return FALSE;	return TRUE;}	/* EncodeSpecialTimestamp() */Datumnow(PG_FUNCTION_ARGS){	PG_RETURN_TIMESTAMPTZ(GetCurrentTransactionStartTimestamp());}Datumpgsql_postmaster_start_time(PG_FUNCTION_ARGS){	PG_RETURN_TIMESTAMPTZ(PgStartTime);}/* * GetCurrentTimestamp -- get the current operating system time * * Result is in the form of a TimestampTz value, and is expressed to the * full precision of the gettimeofday() syscall */TimestampTzGetCurrentTimestamp(void){	TimestampTz result;	struct timeval tp;	gettimeofday(&tp, NULL);	result = (TimestampTz) tp.tv_sec -		((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);#ifdef HAVE_INT64_TIMESTAMP	result = (result * USECS_PER_SEC) + tp.tv_usec;#else	result = result + (tp.tv_usec / 1000000.0);#endif	return result;}/* * Convert a time_t to TimestampTz. * * We do not use time_t internally in Postgres, but this is provided for use * by functions that need to interpret, say, a stat(2) result. */TimestampTztime_t_to_timestamptz(time_t tm){	TimestampTz result;	result = (TimestampTz) tm -		((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);#ifdef HAVE_INT64_TIMESTAMP	result *= USECS_PER_SEC;#endif	return result;}voiddt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec){#ifdef HAVE_INT64_TIMESTAMP	int64		time;#else	double		time;#endif	time = jd;#ifdef HAVE_INT64_TIMESTAMP	*hour = time / USECS_PER_HOUR;	time -= (*hour) * USECS_PER_HOUR;	*min = time / USECS_PER_MINUTE;	time -= (*min) * USECS_PER_MINUTE;	*sec = time / USECS_PER_SEC;	*fsec = time - (*sec * USECS_PER_SEC);#else	*hour = time / SECS_PER_HOUR;	time -= (*hour) * SECS_PER_HOUR;	*min = time / SECS_PER_MINUTE;	time -= (*min) * SECS_PER_MINUTE;	*sec = time;	*fsec = time - *sec;#endif}	/* dt2time() *//* * timestamp2tm() - Convert timestamp data type to POSIX time structure. * * Note that year is _not_ 1900-based, but is an explicit full value. * Also, month is one-based, _not_ zero-based. * Returns: *	 0 on success *	-1 on out of range * * If attimezone is NULL, the global timezone (including possibly brute forced * timezone) will be used. */inttimestamp2tm(Timestamp dt, int *tzp, struct pg_tm * tm, fsec_t *fsec, char **tzn, pg_tz *attimezone){	Timestamp	date;	Timestamp	time;	pg_time_t	utime;	/*	 * 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 (attimezone == NULL && HasCTZSet && tzp != NULL)	{#ifdef HAVE_INT64_TIMESTAMP		dt -= CTimeZone * USECS_PER_SEC;#else		dt -= CTimeZone;#endif	}#ifdef HAVE_INT64_TIMESTAMP	time = dt;	TMODULO(time, date, USECS_PER_DAY);	if (time < INT64CONST(0))	{		time += USECS_PER_DAY;		date -= 1;	}	/* add offset to go from J2000 back to standard Julian date */	date += POSTGRES_EPOCH_JDATE;	/* Julian day routine does not work for negative Julian days */	if (date < 0 || date > (Timestamp) INT_MAX)		return -1;	j2date((int) date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);	dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);#else	time = dt;	TMODULO(time, date, (double) SECS_PER_DAY);	if (time < 0)	{		time += SECS_PER_DAY;		date -= 1;	}	/* add offset to go from J2000 back to standard Julian date */	date += POSTGRES_EPOCH_JDATE;recalc_d:	/* Julian day routine does not work for negative Julian days */	if (date < 0 || date > (Timestamp) INT_MAX)		return -1;	j2date((int) date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);recalc_t:	dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);	*fsec = TSROUND(*fsec);	/* roundoff may need to propagate to higher-order fields */	if (*fsec >= 1.0)	{		time = ceil(time);		if (time >= (double) SECS_PER_DAY)		{			time = 0;			date += 1;			goto recalc_d;		}		goto recalc_t;	}#endif	/* Done if no TZ conversion wanted */	if (tzp == NULL)	{		tm->tm_isdst = -1;		tm->tm_gmtoff = 0;		tm->tm_zone = NULL;		if (tzn != NULL)			*tzn = NULL;		return 0;	}	/*	 * We have a brute force time zone per SQL99? Then use it without change	 * since we have already rotated to the time zone.

⌨️ 快捷键说明

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