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

📄 date.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 4 页
字号:
	dt2 = date2timestamptz(dateVal);	PG_RETURN_INT32(timestamptz_cmp_internal(dt1, dt2));}/* Add an interval to a date, giving a new date. * Must handle both positive and negative intervals. * * We implement this by promoting the date to timestamp (without time zone) * and then using the timestamp plus interval function. */Datumdate_pl_interval(PG_FUNCTION_ARGS){	DateADT		dateVal = PG_GETARG_DATEADT(0);	Interval   *span = PG_GETARG_INTERVAL_P(1);	Timestamp	dateStamp;	dateStamp = date2timestamp(dateVal);	return DirectFunctionCall2(timestamp_pl_interval,							   TimestampGetDatum(dateStamp),							   PointerGetDatum(span));}/* Subtract an interval from a date, giving a new date. * Must handle both positive and negative intervals. * * We implement this by promoting the date to timestamp (without time zone) * and then using the timestamp minus interval function. */Datumdate_mi_interval(PG_FUNCTION_ARGS){	DateADT		dateVal = PG_GETARG_DATEADT(0);	Interval   *span = PG_GETARG_INTERVAL_P(1);	Timestamp	dateStamp;	dateStamp = date2timestamp(dateVal);	return DirectFunctionCall2(timestamp_mi_interval,							   TimestampGetDatum(dateStamp),							   PointerGetDatum(span));}/* date_timestamp() * Convert date to timestamp data type. */Datumdate_timestamp(PG_FUNCTION_ARGS){	DateADT		dateVal = PG_GETARG_DATEADT(0);	Timestamp	result;	result = date2timestamp(dateVal);	PG_RETURN_TIMESTAMP(result);}/* timestamp_date() * Convert timestamp to date data type. */Datumtimestamp_date(PG_FUNCTION_ARGS){	Timestamp	timestamp = PG_GETARG_TIMESTAMP(0);	DateADT		result;	struct pg_tm tt,			   *tm = &tt;	fsec_t		fsec;	if (TIMESTAMP_NOT_FINITE(timestamp))		PG_RETURN_NULL();	if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)		ereport(ERROR,				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),				 errmsg("timestamp out of range")));	result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;	PG_RETURN_DATEADT(result);}/* date_timestamptz() * Convert date to timestamp with time zone data type. */Datumdate_timestamptz(PG_FUNCTION_ARGS){	DateADT		dateVal = PG_GETARG_DATEADT(0);	TimestampTz result;	result = date2timestamptz(dateVal);	PG_RETURN_TIMESTAMP(result);}/* timestamptz_date() * Convert timestamp with time zone to date data type. */Datumtimestamptz_date(PG_FUNCTION_ARGS){	TimestampTz timestamp = PG_GETARG_TIMESTAMP(0);	DateADT		result;	struct pg_tm tt,			   *tm = &tt;	fsec_t		fsec;	int			tz;	char	   *tzn;	if (TIMESTAMP_NOT_FINITE(timestamp))		PG_RETURN_NULL();	if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) != 0)		ereport(ERROR,				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),				 errmsg("timestamp out of range")));	result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;	PG_RETURN_DATEADT(result);}/* abstime_date() * Convert abstime to date data type. */Datumabstime_date(PG_FUNCTION_ARGS){	AbsoluteTime abstime = PG_GETARG_ABSOLUTETIME(0);	DateADT		result;	struct pg_tm tt,			   *tm = &tt;	int			tz;	switch (abstime)	{		case INVALID_ABSTIME:		case NOSTART_ABSTIME:		case NOEND_ABSTIME:			ereport(ERROR,					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),				   errmsg("cannot convert reserved abstime value to date")));			/*			 * pretend to drop through to make compiler think that result will			 * be set			 */		default:			abstime2tm(abstime, &tz, tm, NULL);			result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;			break;	}	PG_RETURN_DATEADT(result);}/* date_text() * Convert date to text data type. */Datumdate_text(PG_FUNCTION_ARGS){	/* Input is a Date, but may as well leave it in Datum form */	Datum		date = PG_GETARG_DATUM(0);	text	   *result;	char	   *str;	int			len;	str = DatumGetCString(DirectFunctionCall1(date_out, date));	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_date() * Convert text string to date. * Text type is not null terminated, so use temporary string *	then call the standard input routine. */Datumtext_date(PG_FUNCTION_ARGS){	text	   *str = PG_GETARG_TEXT_P(0);	int			i;	char	   *sp,			   *dp,				dstr[MAXDATELEN + 1];	if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)		ereport(ERROR,				(errcode(ERRCODE_INVALID_DATETIME_FORMAT),				 errmsg("invalid input syntax for type date: \"%s\"",						VARDATA(str))));	sp = VARDATA(str);	dp = dstr;	for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)		*dp++ = *sp++;	*dp = '\0';	return DirectFunctionCall1(date_in,							   CStringGetDatum(dstr));}/***************************************************************************** *	 Time ADT *****************************************************************************/Datumtime_in(PG_FUNCTION_ARGS){	char	   *str = PG_GETARG_CSTRING(0);#ifdef NOT_USED	Oid			typelem = PG_GETARG_OID(1);#endif	int32		typmod = PG_GETARG_INT32(2);	TimeADT		result;	fsec_t		fsec;	struct pg_tm tt,			   *tm = &tt;	int			tz;	int			nf;	int			dterr;	char		workbuf[MAXDATELEN + 1];	char	   *field[MAXDATEFIELDS];	int			dtype;	int			ftype[MAXDATEFIELDS];	dterr = ParseDateTime(str, workbuf, sizeof(workbuf),						  field, ftype, MAXDATEFIELDS, &nf);	if (dterr == 0)		dterr = DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, &tz);	if (dterr != 0)		DateTimeParseError(dterr, str, "time");	tm2time(tm, fsec, &result);	AdjustTimeForTypmod(&result, typmod);	PG_RETURN_TIMEADT(result);}/* tm2time() * Convert a tm structure to a time data type. */static inttm2time(struct pg_tm * tm, fsec_t fsec, TimeADT *result){#ifdef HAVE_INT64_TIMESTAMP	*result = ((((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec)			   * USECS_PER_SEC) + fsec;#else	*result = ((tm->tm_hour * MINS_PER_HOUR + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec + fsec;#endif	return 0;}/* time2tm() * Convert time data type to POSIX time structure. * For dates within the system-supported time_t range, convert to the *	local time zone. If out of this range, leave as GMT. - tgl 97/05/27 */static inttime2tm(TimeADT time, struct pg_tm * tm, fsec_t *fsec){#ifdef HAVE_INT64_TIMESTAMP	tm->tm_hour = time / USECS_PER_HOUR;	time -= tm->tm_hour * USECS_PER_HOUR;	tm->tm_min = time / USECS_PER_MINUTE;	time -= tm->tm_min * USECS_PER_MINUTE;	tm->tm_sec = time / USECS_PER_SEC;	time -= tm->tm_sec * USECS_PER_SEC;	*fsec = time;#else	double		trem;recalc:	trem = time;	TMODULO(trem, tm->tm_hour, (double) SECS_PER_HOUR);	TMODULO(trem, tm->tm_min, (double) SECS_PER_MINUTE);	TMODULO(trem, tm->tm_sec, 1.0);	trem = TIMEROUND(trem);	/* roundoff may need to propagate to higher-order fields */	if (trem >= 1.0)	{		time = ceil(time);		goto recalc;	}	*fsec = trem;#endif	return 0;}Datumtime_out(PG_FUNCTION_ARGS){	TimeADT		time = PG_GETARG_TIMEADT(0);	char	   *result;	struct pg_tm tt,			   *tm = &tt;	fsec_t		fsec;	char		buf[MAXDATELEN + 1];	time2tm(time, tm, &fsec);	EncodeTimeOnly(tm, fsec, NULL, DateStyle, buf);	result = pstrdup(buf);	PG_RETURN_CSTRING(result);}/* *		time_recv			- converts external binary format to time * * We make no attempt to provide compatibility between int and float * time representations ... */Datumtime_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);	TimeADT		result;#ifdef HAVE_INT64_TIMESTAMP	result = pq_getmsgint64(buf);#else	result = pq_getmsgfloat8(buf);#endif	AdjustTimeForTypmod(&result, typmod);	PG_RETURN_TIMEADT(result);}/* *		time_send			- converts time to binary format */Datumtime_send(PG_FUNCTION_ARGS){	TimeADT		time = PG_GETARG_TIMEADT(0);	StringInfoData buf;	pq_begintypsend(&buf);#ifdef HAVE_INT64_TIMESTAMP	pq_sendint64(&buf, time);#else	pq_sendfloat8(&buf, time);#endif	PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}/* time_scale() * Adjust time type for specified scale factor. * Used by PostgreSQL type system to stuff columns. */Datumtime_scale(PG_FUNCTION_ARGS){	TimeADT		time = PG_GETARG_TIMEADT(0);	int32		typmod = PG_GETARG_INT32(1);	TimeADT		result;	result = time;	AdjustTimeForTypmod(&result, typmod);	PG_RETURN_TIMEADT(result);}/* AdjustTimeForTypmod() * Force the precision of the time value to a specified value. * Uses *exactly* the same code as in AdjustTimestampForTypemod() * but we make a separate copy because those types do not * have a fundamental tie together but rather a coincidence of * implementation. - thomas */static voidAdjustTimeForTypmod(TimeADT *time, int32 typmod){#ifdef HAVE_INT64_TIMESTAMP	static const int64 TimeScales[MAX_TIME_PRECISION + 1] = {		INT64CONST(1000000),		INT64CONST(100000),		INT64CONST(10000),		INT64CONST(1000),		INT64CONST(100),		INT64CONST(10),		INT64CONST(1)	};	static const int64 TimeOffsets[MAX_TIME_PRECISION + 1] = {		INT64CONST(500000),		INT64CONST(50000),		INT64CONST(5000),		INT64CONST(500),		INT64CONST(50),		INT64CONST(5),		INT64CONST(0)	};#else	/* note MAX_TIME_PRECISION differs in this case */	static const double TimeScales[MAX_TIME_PRECISION + 1] = {		1.0,		10.0,		100.0,		1000.0,		10000.0,		100000.0,		1000000.0,		10000000.0,		100000000.0,		1000000000.0,		10000000000.0	};#endif	if (typmod >= 0 && typmod <= MAX_TIME_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 (*time >= INT64CONST(0))			*time = ((*time + TimeOffsets[typmod]) / TimeScales[typmod]) *				TimeScales[typmod];		else			*time = -((((-*time) + TimeOffsets[typmod]) / TimeScales[typmod]) *					  TimeScales[typmod]);#else		*time = rint((double) *time * TimeScales[typmod]) / TimeScales[typmod];#endif	}}Datumtime_eq(PG_FUNCTION_ARGS){	TimeADT		time1 = PG_GETARG_TIMEADT(0);	TimeADT		time2 = PG_GETARG_TIMEADT(1);	PG_RETURN_BOOL(time1 == time2);}Datumtime_ne(PG_FUNCTION_ARGS){	TimeADT		time1 = PG_GETARG_TIMEADT(0);	TimeADT		time2 = PG_GETARG_TIMEADT(1);	PG_RETURN_BOOL(time1 != time2);}Datumtime_lt(PG_FUNCTION_ARGS){	TimeADT		time1 = PG_GETARG_TIMEADT(0);	TimeADT		time2 = PG_GETARG_TIMEADT(1);	PG_RETURN_BOOL(time1 < time2);}Datumtime_le(PG_FUNCTION_ARGS){	TimeADT		time1 = PG_GETARG_TIMEADT(0);	TimeADT		time2 = PG_GETARG_TIMEADT(1);	PG_RETURN_BOOL(time1 <= time2);}Datumtime_gt(PG_FUNCTION_ARGS){	TimeADT		time1 = PG_GETARG_TIMEADT(0);	TimeADT		time2 = PG_GETARG_TIMEADT(1);	PG_RETURN_BOOL(time1 > time2);}Datumtime_ge(PG_FUNCTION_ARGS){	TimeADT		time1 = PG_GETARG_TIMEADT(0);	TimeADT		time2 = PG_GETARG_TIMEADT(1);	PG_RETURN_BOOL(time1 >= time2);}Datumtime_cmp(PG_FUNCTION_ARGS){	TimeADT		time1 = PG_GETARG_TIMEADT(0);	TimeADT		time2 = PG_GETARG_TIMEADT(1);	if (time1 < time2)		PG_RETURN_INT32(-1);	if (time1 > time2)		PG_RETURN_INT32(1);	PG_RETURN_INT32(0);}Datumtime_larger(PG_FUNCTION_ARGS){	TimeADT		time1 = PG_GETARG_TIMEADT(0);	TimeADT		time2 = PG_GETARG_TIMEADT(1);	PG_RETURN_TIMEADT((time1 > time2) ? time1 : time2);}Datumtime_smaller(PG_FUNCTION_ARGS){	TimeADT		time1 = PG_GETARG_TIMEADT(0);	TimeADT		time2 = PG_GETARG_TIMEADT(1);	PG_RETURN_TIMEADT((time1 < time2) ? time1 : time2);}/* overlaps_time() --- 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_time(PG_FUNCTION_ARGS){	/*	 * The arguments are TimeADT, but we leave them as generic Datums to avoid	 * dereferencing nulls (TimeADT is pass-by-reference!)	 */	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 TIMEADT_GT(t1,t2) \	(DatumGetTimeADT(t1) > DatumGetTimeADT(t2))#define TIMEADT_LT(t1,t2) \	(DatumGetTimeADT(t1) < DatumGetTimeADT(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 (TIMEADT_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 (TIMEADT_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 (TIMEADT_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 (TIMEADT_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 (TIMEADT_LT(ts1, ts2))	{		/* This case is ts2 < te1 OR te2 < te1 */		if (te1IsNull)			PG_RETURN_NULL();		if (TIMEADT_LT(ts2, te1))			PG_RETURN_BOOL(true);		if (te2IsNull)			PG_RETURN_NULL();		/*

⌨️ 快捷键说明

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