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

📄 timestamp.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 5 页
字号:
	PG_RETURN_INTERVAL_P(result);}/* timestamp_pl_span() * Add a interval to a timestamp 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". */Datumtimestamp_pl_span(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 tm	tt,					   *tm = &tt;			fsec_t		fsec;			if (timestamp2tm(timestamp, NULL, tm, &fsec, 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 > 12)			{				tm->tm_year += ((tm->tm_mon - 1) / 12);				tm->tm_mon = (((tm->tm_mon - 1) % 12) + 1);			}			else if (tm->tm_mon < 1)			{				tm->tm_year += ((tm->tm_mon / 12) - 1);				tm->tm_mon = ((tm->tm_mon % 12) + 12);			}			/* 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")));		}		timestamp += span->time;		result = timestamp;	}	PG_RETURN_TIMESTAMP(result);}Datumtimestamp_mi_span(PG_FUNCTION_ARGS){	Timestamp	timestamp = PG_GETARG_TIMESTAMP(0);	Interval   *span = PG_GETARG_INTERVAL_P(1);	Interval	tspan;	tspan.month = -span->month;	tspan.time = -span->time;	return DirectFunctionCall2(timestamp_pl_span,							   TimestampGetDatum(timestamp),							   PointerGetDatum(&tspan));}/* timestamptz_pl_span() * 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_span(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 tm	tt,					   *tm = &tt;			fsec_t		fsec;			if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0)				ereport(ERROR,						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),						 errmsg("timestamp out of range")));			tm->tm_mon += span->month;			if (tm->tm_mon > 12)			{				tm->tm_year += ((tm->tm_mon - 1) / 12);				tm->tm_mon = (((tm->tm_mon - 1) % 12) + 1);			}			else if (tm->tm_mon < 1)			{				tm->tm_year += ((tm->tm_mon / 12) - 1);				tm->tm_mon = ((tm->tm_mon % 12) + 12);			}			/* 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 = DetermineLocalTimeZone(tm);			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_span(PG_FUNCTION_ARGS){	TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(0);	Interval   *span = PG_GETARG_INTERVAL_P(1);	Interval	tspan;	tspan.month = -span->month;	tspan.time = -span->time;	return DirectFunctionCall2(timestamptz_pl_span,							   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->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);#ifdef HAVE_INT64_TIMESTAMP	result->time = (span1->time + span2->time);#else	result->time = JROUND(span1->time + span2->time);#endif	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);#ifdef HAVE_INT64_TIMESTAMP	result->time = (span1->time - span2->time);#else	result->time = JROUND(span1->time - span2->time);#endif	PG_RETURN_INTERVAL_P(result);}Datuminterval_mul(PG_FUNCTION_ARGS){	Interval   *span1 = PG_GETARG_INTERVAL_P(0);	float8		factor = PG_GETARG_FLOAT8(1);	Interval   *result;#ifdef HAVE_INT64_TIMESTAMP	int64		months;#else	double		months;#endif	result = (Interval *) palloc(sizeof(Interval));	months = (span1->month * factor);#ifdef HAVE_INT64_TIMESTAMP	result->month = months;	result->time = (span1->time * factor);	result->time += ((months - result->month) * INT64CONST(30)					 * INT64CONST(86400000000));#else	result->month = rint(months);	result->time = JROUND(span1->time * factor);	/* evaluate fractional months as 30 days */	result->time += JROUND((months - result->month) * 30 * 86400);#endif	PG_RETURN_INTERVAL_P(result);}Datummul_d_interval(PG_FUNCTION_ARGS){	/* Args are float8 and Interval *, but leave them as generic Datum */	Datum		factor = PG_GETARG_DATUM(0);	Datum		span1 = PG_GETARG_DATUM(1);	return DirectFunctionCall2(interval_mul, span1, factor);}Datuminterval_div(PG_FUNCTION_ARGS){	Interval   *span = PG_GETARG_INTERVAL_P(0);	float8		factor = PG_GETARG_FLOAT8(1);	Interval   *result;#ifndef HAVE_INT64_TIMESTAMP	double		months;#endif	result = (Interval *) palloc(sizeof(Interval));	if (factor == 0.0)		ereport(ERROR,				(errcode(ERRCODE_DIVISION_BY_ZERO),				 errmsg("division by zero")));#ifdef HAVE_INT64_TIMESTAMP	result->month = (span->month / factor);	result->time = (span->time / factor);	/* evaluate fractional months as 30 days */	result->time += (((span->month - (result->month * factor))				   * INT64CONST(30) * INT64CONST(86400000000)) / factor);#else	months = (span->month / factor);	result->month = rint(months);	result->time = JROUND(span->time / factor);	/* evaluate fractional months as 30 days */	result->time += JROUND((months - result->month) * 30 * 86400);#endif	PG_RETURN_INTERVAL_P(result);}/* * interval_accum and interval_avg implement the AVG(interval) aggregate. * * The transition datatype for this aggregate is a 2-element array of * intervals, where the first is the running sum and the second contains * the number of values so far in its 'time' field.  This is a bit ugly * but it beats inventing a specialized datatype for the purpose. */Datuminterval_accum(PG_FUNCTION_ARGS){	ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);	Interval   *newval = PG_GETARG_INTERVAL_P(1);	Datum	   *transdatums;	int			ndatums;	Interval	sumX,				N;	Interval   *newsum;	ArrayType  *result;	/* We assume the input is array of interval */	deconstruct_array(transarray,					  INTERVALOID, 12, false, 'd',					  &transdatums, &ndatums);	if (ndatums != 2)		elog(ERROR, "expected 2-element interval array");	/*	 * XXX memcpy, instead of just extracting a pointer, to work around	 * buggy array code: it won't ensure proper alignment of Interval	 * objects on machines where double requires 8-byte alignment. That	 * should be fixed, but in the meantime...	 *	 * Note: must use DatumGetPointer here, not DatumGetIntervalP, else some	 * compilers optimize into double-aligned load/store anyway.	 */	memcpy((void *) &sumX, DatumGetPointer(transdatums[0]), sizeof(Interval));	memcpy((void *) &N, DatumGetPointer(transdatums[1]), sizeof(Interval));	newsum = DatumGetIntervalP(DirectFunctionCall2(interval_pl,												IntervalPGetDatum(&sumX),											 IntervalPGetDatum(newval)));	N.time += 1;	transdatums[0] = IntervalPGetDatum(newsum);	transdatums[1] = IntervalPGetDatum(&N);	result = construct_array(transdatums, 2,							 INTERVALOID, 12, false, 'd');	PG_RETURN_ARRAYTYPE_P(result);}Datuminterval_avg(PG_FUNCTION_ARGS){	ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);	Datum	   *transdatums;	int			ndatums;	Interval	sumX,				N;	/* We assume the input is array of interval */	deconstruct_array(transarray,					  INTERVALOID, 12, false, 'd',					  &transdatums, &ndatums);	if (ndatums != 2)		elog(ERROR, "expected 2-element interval array");	/*	 * XXX memcpy, instead of just extracting a pointer, to work around	 * buggy array code: it won't ensure proper alignment of Interval	 * objects on machines where double requires 8-byte alignment. That	 * should be fixed, but in the meantime...	 *	 * Note: must use DatumGetPointer here, not DatumGetIntervalP, else some	 * compilers optimize into double-aligned load/store anyway.	 */	memcpy((void *) &sumX, DatumGetPointer(transdatums[0]), sizeof(Interval));	memcpy((void *) &N, DatumGetPointer(transdatums[1]), sizeof(Interval));	/* SQL92 defines AVG of no values to be NULL */	if (N.time == 0)		PG_RETURN_NULL();	return DirectFunctionCall2(interval_div,							   IntervalPGetDatum(&sumX),							   Float8GetDatum(N.time));}/* timestamp_age() * Calculate time difference while retaining year/month fields. * Note that this does not result in an accurate absolute time span *	since year and month are out of context once the arithmetic *	is done. */Datumtimestamp_age(PG_FUNCTION_ARGS){	Timestamp	dt1 = PG_GETARG_TIMESTAMP(0);	Timestamp	dt2 = PG_GETARG_TIMESTAMP(1);	Interval   *result;	fsec_t		fsec,				fsec1,				fsec2;	struct tm	tt,			   *tm = &tt;	struct tm	tt1,			   *tm1 = &tt1;	struct tm	tt2,			   *tm2 = &tt2;	result = (Interval *) palloc(sizeof(Interval));	if ((timestamp2tm(dt1, NULL, tm1, &fsec1, NULL) == 0)		&& (timestamp2tm(dt2, NULL, tm2, &fsec2, NULL) == 0))	{		fsec = (fsec1 - fsec2);		tm->tm_sec = (tm1->tm_sec - tm2->tm_sec);		tm->tm_min = (tm1->tm_min - tm2->tm_min);		tm->tm_hour = (tm1->tm_hour - tm2->tm_hour);		tm->tm_mday = (tm1->tm_mday - tm2->tm_mday);		tm->tm_mon = (tm1->tm_mon - tm2->tm_mon);		tm->tm_year = (tm1->tm_year - tm2->tm_year);		/* flip sign if necessary... */		if (dt1 < dt2)		{			fsec = -fsec;			tm->tm_sec = -tm->tm_sec;			tm->tm_min = -tm->tm_min;			tm->tm_hour = -tm->tm_hour;			tm->tm_mday = -tm->tm_mday;			tm->tm_mon = -tm->tm_mon;			tm->tm_year = -tm->tm_year;		}		if (tm->tm_sec < 0)		{			tm->tm_sec += 60;			tm->tm_min--;		}		if (tm->tm_min < 0)		{			tm->tm_min += 60;			tm->tm_hour--;		}		if (tm->tm_hour < 0)		{			tm->tm_hour += 24;			tm->tm_mday--;		}		if (tm->tm_mday < 0)		{			if (dt1 < dt2)			{				tm->tm_mday += day_tab[isleap(tm1->tm_year)][tm1->tm_mon - 1];				tm->tm_mon--;			}			else			{				tm->tm_mday += day_tab[isleap(tm2->tm_year)][tm2->tm_mon - 1];				tm->tm_mon--;			}		}		if (tm->tm_mon < 0)		{			tm->tm_mon += 12;			tm->tm_year--;		}		/* recover sign if necessary... */		if (dt1 < dt2)		{			fsec = -fsec;			tm->tm_sec = -tm->tm_sec;			tm->tm_min = -tm->tm_min;			tm->tm_hour = -tm->tm_hour;			tm->tm_mday = -tm->tm_mday;			tm->tm_mon = -tm->tm_mon;			tm->tm_year = -tm->tm_year;		}		if (tm2interval(tm, fsec, result) != 0)			ereport(ERROR,					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),					 errmsg("interval out of range")));	}	else		ereport(ERROR,				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),				 errmsg("timestamp out of range")));	PG_RETURN_INTERVAL_P(result);}/* timestamptz_age() * Calculate time difference while retaining year/month fields. * Note that this does not result in an accurate absolute time span *	since year and month are out of context once the arithmetic *	is done. */Datumtimestamptz_age(PG_FUNCTION_ARGS){	TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);	TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1);	Interval   *result;	fsec_t		fsec,				fsec1,				fsec2;	struct tm	tt,			   *tm = &tt;	struct tm	tt1,			   *tm1 = &tt1;	struct tm	tt2,			   *tm2 = &tt2;	result = (Interval *) palloc(sizeof(Interval));	if ((timestamp2tm(dt1, NULL, tm1, &fsec1, NULL) == 0)		&& (timestamp2tm(dt2, NULL, tm2, &fsec2, NULL) == 0))	{		fsec = (fsec1 - fsec2);		tm->tm_sec = (tm1->tm_sec - tm2->tm_sec);		tm->tm_min = (tm1->tm_min - tm2->tm_min);		tm->tm_hour = (tm1->tm_hour - tm2->tm_hour);		tm->tm_mday = (tm1->tm_mday - tm2->tm_mday);		tm->tm_mon = (tm1->tm_mon - tm2->tm_mon);		tm->tm_year = (tm1->tm_year - tm2->tm_year);		/* flip sign if necessary... */		if (dt1 < dt2)		{			fsec = -fsec;			tm->tm_sec = -tm->tm_sec;			tm->tm_min = -tm->tm_min;			tm->tm_hour = -tm->tm_hour;			tm->tm_mday = -tm->tm_mday;			tm->tm_mon = -tm->tm_mon;			tm->tm_year = -tm->tm_year;

⌨️ 快捷键说明

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