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

📄 timestamp.c

📁 postgresql8.3.4源码,开源数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
		/* This case is ts2 < te1 OR te2 < te1 */		if (te1IsNull)			PG_RETURN_NULL();		if (TIMESTAMP_LT(ts2, te1))			PG_RETURN_BOOL(true);		if (te2IsNull)			PG_RETURN_NULL();		/*		 * If te2 is not null then we had ts2 <= te2 above, and we just found		 * ts2 >= te1, hence te2 >= te1.		 */		PG_RETURN_BOOL(false);	}	else	{		/*		 * For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a		 * rather silly way of saying "true if both are nonnull, else null".		 */		if (te1IsNull || te2IsNull)			PG_RETURN_NULL();		PG_RETURN_BOOL(true);	}#undef TIMESTAMP_GT#undef TIMESTAMP_LT}/*---------------------------------------------------------- *	"Arithmetic" operators on date/times. *---------------------------------------------------------*/Datumtimestamp_smaller(PG_FUNCTION_ARGS){	Timestamp	dt1 = PG_GETARG_TIMESTAMP(0);	Timestamp	dt2 = PG_GETARG_TIMESTAMP(1);	Timestamp	result;	/* use timestamp_cmp_internal to be sure this agrees with comparisons */	if (timestamp_cmp_internal(dt1, dt2) < 0)		result = dt1;	else		result = dt2;	PG_RETURN_TIMESTAMP(result);}Datumtimestamp_larger(PG_FUNCTION_ARGS){	Timestamp	dt1 = PG_GETARG_TIMESTAMP(0);	Timestamp	dt2 = PG_GETARG_TIMESTAMP(1);	Timestamp	result;	if (timestamp_cmp_internal(dt1, dt2) > 0)		result = dt1;	else		result = dt2;	PG_RETURN_TIMESTAMP(result);}Datumtimestamp_mi(PG_FUNCTION_ARGS){	Timestamp	dt1 = PG_GETARG_TIMESTAMP(0);	Timestamp	dt2 = PG_GETARG_TIMESTAMP(1);	Interval   *result;	result = (Interval *) palloc(sizeof(Interval));	if (TIMESTAMP_NOT_FINITE(dt1) || TIMESTAMP_NOT_FINITE(dt2))		ereport(ERROR,				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),				 errmsg("cannot subtract infinite timestamps")));	result->time = dt1 - dt2;	result->month = 0;	result->day = 0;	/*----------	 *	This is wrong, but removing it breaks a lot of regression tests.	 *	For example:	 *	 *	test=> SET timezone = 'EST5EDT';	 *	test=> SELECT	 *	test-> ('2005-10-30 13:22:00-05'::timestamptz -	 *	test(>	'2005-10-29 13:22:00-04'::timestamptz);	 *	?column?	 *	----------------	 *	 1 day 01:00:00	 *	 (1 row)	 *	 *	so adding that to the first timestamp gets:	 *	 *	 test=> SELECT	 *	 test-> ('2005-10-29 13:22:00-04'::timestamptz +	 *	 test(> ('2005-10-30 13:22:00-05'::timestamptz -	 *	 test(>  '2005-10-29 13:22:00-04'::timestamptz)) at time zone 'EST';	 *		timezone	 *	--------------------	 *	2005-10-30 14:22:00	 *	(1 row)	 *----------	 */	result = DatumGetIntervalP(DirectFunctionCall1(interval_justify_hours,												 IntervalPGetDatum(result)));	PG_RETURN_INTERVAL_P(result);}/* *	interval_justify_interval() * *	Adjust interval so 'month', 'day', and 'time' portions are within *	customary bounds.  Specifically: * *		0 <= abs(time) < 24 hours *		0 <= abs(day)  < 30 days * *	Also, the sign bit on all three fields is made equal, so either *	all three fields are negative or all are positive. */Datuminterval_justify_interval(PG_FUNCTION_ARGS){	Interval   *span = PG_GETARG_INTERVAL_P(0);	Interval   *result;#ifdef HAVE_INT64_TIMESTAMP	int64		wholeday;#else	double		wholeday;#endif	int32		wholemonth;	result = (Interval *) palloc(sizeof(Interval));	result->month = span->month;	result->day = span->day;	result->time = span->time;#ifdef HAVE_INT64_TIMESTAMP	TMODULO(result->time, wholeday, USECS_PER_DAY);#else	TMODULO(result->time, wholeday, (double) SECS_PER_DAY);#endif	result->day += wholeday;	/* could overflow... */	wholemonth = result->day / DAYS_PER_MONTH;	result->day -= wholemonth * DAYS_PER_MONTH;	result->month += wholemonth;	if (result->month > 0 &&		(result->day < 0 || (result->day == 0 && result->time < 0)))	{		result->day += DAYS_PER_MONTH;		result->month--;	}	else if (result->month < 0 &&			 (result->day > 0 || (result->day == 0 && result->time > 0)))	{		result->day -= DAYS_PER_MONTH;		result->month++;	}	if (result->day > 0 && result->time < 0)	{#ifdef HAVE_INT64_TIMESTAMP		result->time += USECS_PER_DAY;#else		result->time += (double) SECS_PER_DAY;#endif		result->day--;	}	else if (result->day < 0 && result->time > 0)	{#ifdef HAVE_INT64_TIMESTAMP		result->time -= USECS_PER_DAY;#else		result->time -= (double) SECS_PER_DAY;#endif		result->day++;	}	PG_RETURN_INTERVAL_P(result);}/* *	interval_justify_hours() * *	Adjust interval so 'time' contains less than a whole day, adding *	the excess to 'day'.  This is useful for *	situations (such as non-TZ) where '1 day' = '24 hours' is valid, *	e.g. interval subtraction and division. */Datuminterval_justify_hours(PG_FUNCTION_ARGS){	Interval   *span = PG_GETARG_INTERVAL_P(0);	Interval   *result;#ifdef HAVE_INT64_TIMESTAMP	int64		wholeday;#else	double		wholeday;#endif	result = (Interval *) palloc(sizeof(Interval));	result->month = span->month;	result->day = span->day;	result->time = span->time;#ifdef HAVE_INT64_TIMESTAMP	TMODULO(result->time, wholeday, USECS_PER_DAY);#else	TMODULO(result->time, wholeday, (double) SECS_PER_DAY);#endif	result->day += wholeday;	/* could overflow... */	if (result->day > 0 && result->time < 0)	{#ifdef HAVE_INT64_TIMESTAMP		result->time += USECS_PER_DAY;#else		result->time += (double) SECS_PER_DAY;#endif		result->day--;	}	else if (result->day < 0 && result->time > 0)	{#ifdef HAVE_INT64_TIMESTAMP		result->time -= USECS_PER_DAY;#else		result->time -= (double) SECS_PER_DAY;#endif		result->day++;	}	PG_RETURN_INTERVAL_P(result);}/* *	interval_justify_days() * *	Adjust interval so 'day' contains less than 30 days, adding *	the excess to 'month'. */Datuminterval_justify_days(PG_FUNCTION_ARGS){	Interval   *span = PG_GETARG_INTERVAL_P(0);	Interval   *result;	int32		wholemonth;	result = (Interval *) palloc(sizeof(Interval));	result->month = span->month;	result->day = span->day;	result->time = span->time;	wholemonth = result->day / DAYS_PER_MONTH;	result->day -= wholemonth * DAYS_PER_MONTH;	result->month += wholemonth;	if (result->month > 0 && result->day < 0)	{		result->day += DAYS_PER_MONTH;		result->month--;	}	else if (result->month < 0 && result->day > 0)	{		result->day -= DAYS_PER_MONTH;		result->month++;	}	PG_RETURN_INTERVAL_P(result);}/* timestamp_pl_interval() * Add a interval to a timestamp data type. * Note that interval has provisions for qualitative year/month and day *	units, so try to do the right thing with them. * To add a month, increment the month, and use the same day of month. * Then, if the next month has fewer days, set the day of month *	to the last day of month. * To add a day, increment the mday, and use the same time of day. * Lastly, add in the "quantitative time". */Datumtimestamp_pl_interval(PG_FUNCTION_ARGS){	Timestamp	timestamp = PG_GETARG_TIMESTAMP(0);	Interval   *span = PG_GETARG_INTERVAL_P(1);	Timestamp	result;	if (TIMESTAMP_NOT_FINITE(timestamp))		result = timestamp;	else	{		if (span->month != 0)		{			struct pg_tm tt,					   *tm = &tt;			fsec_t		fsec;			if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)				ereport(ERROR,						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),						 errmsg("timestamp out of range")));			tm->tm_mon += span->month;			if (tm->tm_mon > MONTHS_PER_YEAR)			{				tm->tm_year += (tm->tm_mon - 1) / MONTHS_PER_YEAR;				tm->tm_mon = ((tm->tm_mon - 1) % MONTHS_PER_YEAR) + 1;			}			else if (tm->tm_mon < 1)			{				tm->tm_year += tm->tm_mon / MONTHS_PER_YEAR - 1;				tm->tm_mon = tm->tm_mon % MONTHS_PER_YEAR + MONTHS_PER_YEAR;			}			/* adjust for end of month boundary problems... */			if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])				tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]);			if (tm2timestamp(tm, fsec, NULL, &timestamp) != 0)				ereport(ERROR,						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),						 errmsg("timestamp out of range")));		}		if (span->day != 0)		{			struct pg_tm tt,					   *tm = &tt;			fsec_t		fsec;			int			julian;			if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)				ereport(ERROR,						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),						 errmsg("timestamp out of range")));			/* Add days by converting to and from julian */			julian = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + span->day;			j2date(julian, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);			if (tm2timestamp(tm, fsec, NULL, &timestamp) != 0)				ereport(ERROR,						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),						 errmsg("timestamp out of range")));		}		timestamp += span->time;		result = timestamp;	}	PG_RETURN_TIMESTAMP(result);}Datumtimestamp_mi_interval(PG_FUNCTION_ARGS){	Timestamp	timestamp = PG_GETARG_TIMESTAMP(0);	Interval   *span = PG_GETARG_INTERVAL_P(1);	Interval	tspan;	tspan.month = -span->month;	tspan.day = -span->day;	tspan.time = -span->time;	return DirectFunctionCall2(timestamp_pl_interval,							   TimestampGetDatum(timestamp),							   PointerGetDatum(&tspan));}/* timestamptz_pl_interval() * Add a interval to a timestamp with time zone data type. * Note that interval has provisions for qualitative year/month *	units, so try to do the right thing with them. * To add a month, increment the month, and use the same day of month. * Then, if the next month has fewer days, set the day of month *	to the last day of month. * Lastly, add in the "quantitative time". */Datumtimestamptz_pl_interval(PG_FUNCTION_ARGS){	TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(0);	Interval   *span = PG_GETARG_INTERVAL_P(1);	TimestampTz result;	int			tz;	char	   *tzn;	if (TIMESTAMP_NOT_FINITE(timestamp))		result = timestamp;	else	{		if (span->month != 0)		{			struct pg_tm tt,					   *tm = &tt;			fsec_t		fsec;			if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) != 0)				ereport(ERROR,						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),						 errmsg("timestamp out of range")));			tm->tm_mon += span->month;			if (tm->tm_mon > MONTHS_PER_YEAR)			{				tm->tm_year += (tm->tm_mon - 1) / MONTHS_PER_YEAR;				tm->tm_mon = ((tm->tm_mon - 1) % MONTHS_PER_YEAR) + 1;			}			else if (tm->tm_mon < 1)			{				tm->tm_year += tm->tm_mon / MONTHS_PER_YEAR - 1;				tm->tm_mon = tm->tm_mon % MONTHS_PER_YEAR + MONTHS_PER_YEAR;			}			/* adjust for end of month boundary problems... */			if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])				tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]);			tz = DetermineTimeZoneOffset(tm, session_timezone);			if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)				ereport(ERROR,						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),						 errmsg("timestamp out of range")));		}		if (span->day != 0)		{			struct pg_tm tt,					   *tm = &tt;			fsec_t		fsec;			int			julian;			if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) != 0)				ereport(ERROR,						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),						 errmsg("timestamp out of range")));			/* Add days by converting to and from julian */			julian = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + span->day;			j2date(julian, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);			tz = DetermineTimeZoneOffset(tm, session_timezone);			if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)				ereport(ERROR,						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),						 errmsg("timestamp out of range")));		}		timestamp += span->time;		result = timestamp;	}	PG_RETURN_TIMESTAMP(result);}Datumtimestamptz_mi_interval(PG_FUNCTION_ARGS){	TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(0);	Interval   *span = PG_GETARG_INTERVAL_P(1);	Interval	tspan;	tspan.month = -span->month;	tspan.day = -span->day;	tspan.time = -span->time;	return DirectFunctionCall2(timestamptz_pl_interval,							   TimestampGetDatum(timestamp),							   PointerGetDatum(&tspan));}Datuminterval_um(PG_FUNCTION_ARGS){	Interval   *interval = PG_GETARG_INTERVAL_P(0);	Interval   *result;	result = (Interval *) palloc(sizeof(Interval));	result->time = -interval->time;	result->day = -interval->day;	result->month = -interval->month;	PG_RETURN_INTERVAL_P(result);}Datuminterval_smaller(PG_FUNCTION_ARGS){	Interval   *interval1 = PG_GETARG_INTERVAL_P(0);	Interval   *interval2 = PG_GETARG_INTERVAL_P(1);	Interval   *result;	/* use interval_cmp_internal to be sure this agrees with comparisons */	if (interval_cmp_internal(interval1, interval2) < 0)		result = interval1;	else		result = interval2;	PG_RETURN_INTERVAL_P(result);}Datuminterval_larger(PG_FUNCTION_ARGS){	Interval   *interval1 = PG_GETARG_INTERVAL_P(0);	Interval   *interval2 = PG_GETARG_INTERVAL_P(1);	Interval   *result;	if (interval_cmp_internal(interval1, interval2) > 0)		result = interval1;	else		result = interval2;	PG_RETURN_INTERVAL_P(result);}Datuminterval_pl(PG_FUNCTION_ARGS){	Interval   *span1 = PG_GETARG_INTERVAL_P(0);	Interval   *span2 = PG_GETARG_INTERVAL_P(1);	Interval   *result;	result = (Interval *) palloc(sizeof(Interval));	result->month = span1->month + span2->month;	result->day = span1->day + span2->day;	result->time = span1->time + span2->time;	PG_RETURN_INTERVAL_P(result);}Datuminterval_mi(PG_FUNCTION_ARGS){	Interval   *span1 = PG_GETARG_INTERVAL_P(0);	Interval   *span2 = PG_GETARG_INTERVAL_P(1);	Interval   *result;	result = (Interval *) palloc(sizeof(Interval));	result->month = span1->month - span2->month;	result->day = span1->day - span2->day;	result->time = span1->time - span2->ti

⌨️ 快捷键说明

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