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

📄 timestamp.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
timestamptz_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->time;	PG_RETURN_INTERVAL_P(result);}Datuminterval_mul(PG_FUNCTION_ARGS){	Interval   *span = PG_GETARG_INTERVAL_P(0);	float8		factor = PG_GETARG_FLOAT8(1);	double		month_remainder,				day_remainder,				month_remainder_days;	Interval   *result;	result = (Interval *) palloc(sizeof(Interval));	month_remainder = span->month * factor;	day_remainder = span->day * factor;	result->month = (int32) month_remainder;	result->day = (int32) day_remainder;	month_remainder -= result->month;	day_remainder -= result->day;	/*	 * The above correctly handles the whole-number part of the month and day	 * products, but we have to do something with any fractional part	 * resulting when the factor is nonintegral.  We cascade the fractions	 * down to lower units using the conversion factors DAYS_PER_MONTH and	 * SECS_PER_DAY.  Note we do NOT cascade up, since we are not forced to do	 * so by the representation.  The user can choose to cascade up later,	 * using justify_hours and/or justify_days.	 */	/* fractional months full days into days */	month_remainder_days = month_remainder * DAYS_PER_MONTH;	result->day += (int32) month_remainder_days;	/* fractional months partial days into time */	day_remainder += month_remainder_days - (int32) month_remainder_days;#ifdef HAVE_INT64_TIMESTAMP	result->time = rint(span->time * factor + day_remainder * USECS_PER_DAY);#else	result->time = span->time * factor + day_remainder * SECS_PER_DAY;#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		span = PG_GETARG_DATUM(1);	return DirectFunctionCall2(interval_mul, span, factor);}Datuminterval_div(PG_FUNCTION_ARGS){	Interval   *span = PG_GETARG_INTERVAL_P(0);	float8		factor = PG_GETARG_FLOAT8(1);	double		month_remainder,				day_remainder,				month_remainder_days;	Interval   *result;	result = (Interval *) palloc(sizeof(Interval));	if (factor == 0.0)		ereport(ERROR,				(errcode(ERRCODE_DIVISION_BY_ZERO),				 errmsg("division by zero")));	month_remainder = span->month / factor;	day_remainder = span->day / factor;	result->month = (int32) month_remainder;	result->day = (int32) day_remainder;	month_remainder -= result->month;	day_remainder -= result->day;	/*	 * Handle any fractional parts the same way as in interval_mul.	 */	/* fractional months full days into days */	month_remainder_days = month_remainder * DAYS_PER_MONTH;	result->day += (int32) month_remainder_days;	/* fractional months partial days into time */	day_remainder += month_remainder_days - (int32) month_remainder_days;#ifdef HAVE_INT64_TIMESTAMP	result->time = rint(span->time / factor + day_remainder * USECS_PER_DAY);#else	result->time = span->time / factor + day_remainder * SECS_PER_DAY;#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;	deconstruct_array(transarray,					  INTERVALOID, sizeof(Interval), 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, sizeof(Interval), 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;	deconstruct_array(transarray,					  INTERVALOID, sizeof(Interval), 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 pg_tm tt,			   *tm = &tt;	struct pg_tm tt1,			   *tm1 = &tt1;	struct pg_tm tt2,			   *tm2 = &tt2;	result = (Interval *) palloc(sizeof(Interval));	if (timestamp2tm(dt1, NULL, tm1, &fsec1, NULL, NULL) == 0 &&		timestamp2tm(dt2, NULL, tm2, &fsec2, NULL, 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;		}		while (tm->tm_sec < 0)		{			tm->tm_sec += SECS_PER_MINUTE;			tm->tm_min--;		}		while (tm->tm_min < 0)		{			tm->tm_min += MINS_PER_HOUR;			tm->tm_hour--;		}		while (tm->tm_hour < 0)		{			tm->tm_hour += HOURS_PER_DAY;			tm->tm_mday--;		}		while (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--;			}		}		while (tm->tm_mon < 0)		{			tm->tm_mon += MONTHS_PER_YEAR;			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 pg_tm tt,			   *tm = &tt;	struct pg_tm tt1,			   *tm1 = &tt1;	struct pg_tm tt2,			   *tm2 = &tt2;	int			tz1;	int			tz2;	char	   *tzn;	result = (Interval *) palloc(sizeof(Interval));	if (timestamp2tm(dt1, &tz1, tm1, &fsec1, &tzn, NULL) == 0 &&		timestamp2tm(dt2, &tz2, tm2, &fsec2, &tzn, 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;		}		while (tm->tm_sec < 0)		{			tm->tm_sec += SECS_PER_MINUTE;			tm->tm_min--;		}		while (tm->tm_min < 0)		{			tm->tm_min += MINS_PER_HOUR;			tm->tm_hour--;		}		while (tm->tm_hour < 0)		{			tm->tm_hour += HOURS_PER_DAY;			tm->tm_mday--;		}		while (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--;			}		}		while (tm->tm_mon < 0)		{			tm->tm_mon += MONTHS_PER_YEAR;			tm->tm_year--;		}		/*		 * Note: we deliberately ignore any difference between tz1 and tz2.		 */		/* 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);}/*---------------------------------------------------------- *	Conversion operators. *---------------------------------------------------------*//* timestamp_text() * Convert timestamp to text data type. */Datumtimestamp_text(PG_FUNCTION_ARGS){	/* Input is a Timestamp, but may as well leave it in Datum form */	Datum		timestamp = PG_GETARG_DATUM(0);	text	   *result;	char	   *str;	int			len;	str = DatumGetCString(DirectFunctionCall1(timestamp_out, timestamp));	len = (strlen(str) + VARHDRSZ);	result = palloc(len);	VARATT_SIZEP(result) = len;	memmove(VARDATA(result), str, len - VARHDRSZ);	pfree(str);	PG_RETURN_TEXT_P(result);}/* text_timestamp() * Convert text string to timestamp. * Text type is not null terminated, so use temporary string *	then call the standard input routine. */Datumtext_timestamp(PG_FUNCTION_ARGS){	text	   *str = PG_GETARG_TEXT_P(0);	int			i;	char	   *sp,			   *dp

⌨️ 快捷键说明

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