date.c

来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 2,565 行 · 第 1/4 页

C
2,565
字号
	dt2 = date2timestamp(dateVal);	PG_RETURN_INT32(timestamp_cmp_internal(dt1, dt2));}Datumtimestamptz_eq_date(PG_FUNCTION_ARGS){	TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);	DateADT		dateVal = PG_GETARG_DATEADT(1);	TimestampTz dt2;	dt2 = date2timestamptz(dateVal);	PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) == 0);}Datumtimestamptz_ne_date(PG_FUNCTION_ARGS){	TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);	DateADT		dateVal = PG_GETARG_DATEADT(1);	TimestampTz dt2;	dt2 = date2timestamptz(dateVal);	PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) != 0);}Datumtimestamptz_lt_date(PG_FUNCTION_ARGS){	TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);	DateADT		dateVal = PG_GETARG_DATEADT(1);	TimestampTz dt2;	dt2 = date2timestamptz(dateVal);	PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) < 0);}Datumtimestamptz_gt_date(PG_FUNCTION_ARGS){	TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);	DateADT		dateVal = PG_GETARG_DATEADT(1);	TimestampTz dt2;	dt2 = date2timestamptz(dateVal);	PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) > 0);}Datumtimestamptz_le_date(PG_FUNCTION_ARGS){	TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);	DateADT		dateVal = PG_GETARG_DATEADT(1);	TimestampTz dt2;	dt2 = date2timestamptz(dateVal);	PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) <= 0);}Datumtimestamptz_ge_date(PG_FUNCTION_ARGS){	TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);	DateADT		dateVal = PG_GETARG_DATEADT(1);	TimestampTz dt2;	dt2 = date2timestamptz(dateVal);	PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) >= 0);}Datumtimestamptz_cmp_date(PG_FUNCTION_ARGS){	TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);	DateADT		dateVal = PG_GETARG_DATEADT(1);	TimestampTz dt2;	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);}/***************************************************************************** *	 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));}Datumtimetypmodin(PG_FUNCTION_ARGS){	ArrayType  *ta = PG_GETARG_ARRAYTYPE_P(0);	PG_RETURN_INT32(anytime_typmodin(false, ta));}Datumtimetypmodout(PG_FUNCTION_ARGS){	int32		typmod = PG_GETARG_INT32(0);	PG_RETURN_CSTRING(anytime_typmodout(false, typmod));}/* 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_hash(PG_FUNCTION_ARGS){	/* We can use either hashint8 or hashfloat8 directly */#ifdef HAVE_INT64_TIMESTAMP	return hashint8(fcinfo);#else	return hashfloat8(fcinfo);#endif}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;

⌨️ 快捷键说明

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