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

📄 timestamp.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
#else	double		span1,				span2;#endif	span1 = interval1->time;	span2 = interval2->time;#ifdef HAVE_INT64_TIMESTAMP	span1 += interval1->month * INT64CONST(30) * USECS_PER_DAY;	span1 += interval1->day * INT64CONST(24) * USECS_PER_HOUR;	span2 += interval2->month * INT64CONST(30) * USECS_PER_DAY;	span2 += interval2->day * INT64CONST(24) * USECS_PER_HOUR;#else	span1 += interval1->month * ((double) DAYS_PER_MONTH * SECS_PER_DAY);	span1 += interval1->day * ((double) HOURS_PER_DAY * SECS_PER_HOUR);	span2 += interval2->month * ((double) DAYS_PER_MONTH * SECS_PER_DAY);	span2 += interval2->day * ((double) HOURS_PER_DAY * SECS_PER_HOUR);#endif	return ((span1 < span2) ? -1 : (span1 > span2) ? 1 : 0);}Datuminterval_eq(PG_FUNCTION_ARGS){	Interval   *interval1 = PG_GETARG_INTERVAL_P(0);	Interval   *interval2 = PG_GETARG_INTERVAL_P(1);	PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) == 0);}Datuminterval_ne(PG_FUNCTION_ARGS){	Interval   *interval1 = PG_GETARG_INTERVAL_P(0);	Interval   *interval2 = PG_GETARG_INTERVAL_P(1);	PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) != 0);}Datuminterval_lt(PG_FUNCTION_ARGS){	Interval   *interval1 = PG_GETARG_INTERVAL_P(0);	Interval   *interval2 = PG_GETARG_INTERVAL_P(1);	PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) < 0);}Datuminterval_gt(PG_FUNCTION_ARGS){	Interval   *interval1 = PG_GETARG_INTERVAL_P(0);	Interval   *interval2 = PG_GETARG_INTERVAL_P(1);	PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) > 0);}Datuminterval_le(PG_FUNCTION_ARGS){	Interval   *interval1 = PG_GETARG_INTERVAL_P(0);	Interval   *interval2 = PG_GETARG_INTERVAL_P(1);	PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) <= 0);}Datuminterval_ge(PG_FUNCTION_ARGS){	Interval   *interval1 = PG_GETARG_INTERVAL_P(0);	Interval   *interval2 = PG_GETARG_INTERVAL_P(1);	PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) >= 0);}Datuminterval_cmp(PG_FUNCTION_ARGS){	Interval   *interval1 = PG_GETARG_INTERVAL_P(0);	Interval   *interval2 = PG_GETARG_INTERVAL_P(1);	PG_RETURN_INT32(interval_cmp_internal(interval1, interval2));}/* * interval, being an unusual size, needs a specialized hash function. */Datuminterval_hash(PG_FUNCTION_ARGS){	Interval   *key = PG_GETARG_INTERVAL_P(0);	/*	 * Specify hash length as sizeof(double) + sizeof(int4), not as	 * sizeof(Interval), so that any garbage pad bytes in the structure won't	 * be included in the hash!	 */	return hash_any((unsigned char *) key,				  sizeof(key->time) + sizeof(key->day) + sizeof(key->month));}/* overlaps_timestamp() --- implements the SQL92 OVERLAPS operator. * * Algorithm is per SQL92 spec.  This is much harder than you'd think * because the spec requires us to deliver a non-null answer in some cases * where some of the inputs are null. */Datumoverlaps_timestamp(PG_FUNCTION_ARGS){	/*	 * The arguments are Timestamps, but we leave them as generic Datums to	 * avoid unnecessary conversions between value and reference forms --- not	 * to mention possible dereferences of null pointers.	 */	Datum		ts1 = PG_GETARG_DATUM(0);	Datum		te1 = PG_GETARG_DATUM(1);	Datum		ts2 = PG_GETARG_DATUM(2);	Datum		te2 = PG_GETARG_DATUM(3);	bool		ts1IsNull = PG_ARGISNULL(0);	bool		te1IsNull = PG_ARGISNULL(1);	bool		ts2IsNull = PG_ARGISNULL(2);	bool		te2IsNull = PG_ARGISNULL(3);#define TIMESTAMP_GT(t1,t2) \	DatumGetBool(DirectFunctionCall2(timestamp_gt,t1,t2))#define TIMESTAMP_LT(t1,t2) \	DatumGetBool(DirectFunctionCall2(timestamp_lt,t1,t2))	/*	 * If both endpoints of interval 1 are null, the result is null (unknown).	 * If just one endpoint is null, take ts1 as the non-null one. Otherwise,	 * take ts1 as the lesser endpoint.	 */	if (ts1IsNull)	{		if (te1IsNull)			PG_RETURN_NULL();		/* swap null for non-null */		ts1 = te1;		te1IsNull = true;	}	else if (!te1IsNull)	{		if (TIMESTAMP_GT(ts1, te1))		{			Datum		tt = ts1;			ts1 = te1;			te1 = tt;		}	}	/* Likewise for interval 2. */	if (ts2IsNull)	{		if (te2IsNull)			PG_RETURN_NULL();		/* swap null for non-null */		ts2 = te2;		te2IsNull = true;	}	else if (!te2IsNull)	{		if (TIMESTAMP_GT(ts2, te2))		{			Datum		tt = ts2;			ts2 = te2;			te2 = tt;		}	}	/*	 * At this point neither ts1 nor ts2 is null, so we can consider three	 * cases: ts1 > ts2, ts1 < ts2, ts1 = ts2	 */	if (TIMESTAMP_GT(ts1, ts2))	{		/*		 * This case is ts1 < te2 OR te1 < te2, which may look redundant but		 * in the presence of nulls it's not quite completely so.		 */		if (te2IsNull)			PG_RETURN_NULL();		if (TIMESTAMP_LT(ts1, te2))			PG_RETURN_BOOL(true);		if (te1IsNull)			PG_RETURN_NULL();		/*		 * If te1 is not null then we had ts1 <= te1 above, and we just found		 * ts1 >= te2, hence te1 >= te2.		 */		PG_RETURN_BOOL(false);	}	else if (TIMESTAMP_LT(ts1, ts2))	{		/* 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_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... */	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;	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, global_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, global_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);}Datum

⌨️ 快捷键说明

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