date.c

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

C
2,565
字号
Datumtimetz_eq(PG_FUNCTION_ARGS){	TimeTzADT  *time1 = PG_GETARG_TIMETZADT_P(0);	TimeTzADT  *time2 = PG_GETARG_TIMETZADT_P(1);	PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) == 0);}Datumtimetz_ne(PG_FUNCTION_ARGS){	TimeTzADT  *time1 = PG_GETARG_TIMETZADT_P(0);	TimeTzADT  *time2 = PG_GETARG_TIMETZADT_P(1);	PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) != 0);}Datumtimetz_lt(PG_FUNCTION_ARGS){	TimeTzADT  *time1 = PG_GETARG_TIMETZADT_P(0);	TimeTzADT  *time2 = PG_GETARG_TIMETZADT_P(1);	PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) < 0);}Datumtimetz_le(PG_FUNCTION_ARGS){	TimeTzADT  *time1 = PG_GETARG_TIMETZADT_P(0);	TimeTzADT  *time2 = PG_GETARG_TIMETZADT_P(1);	PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) <= 0);}Datumtimetz_gt(PG_FUNCTION_ARGS){	TimeTzADT  *time1 = PG_GETARG_TIMETZADT_P(0);	TimeTzADT  *time2 = PG_GETARG_TIMETZADT_P(1);	PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) > 0);}Datumtimetz_ge(PG_FUNCTION_ARGS){	TimeTzADT  *time1 = PG_GETARG_TIMETZADT_P(0);	TimeTzADT  *time2 = PG_GETARG_TIMETZADT_P(1);	PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) >= 0);}Datumtimetz_cmp(PG_FUNCTION_ARGS){	TimeTzADT  *time1 = PG_GETARG_TIMETZADT_P(0);	TimeTzADT  *time2 = PG_GETARG_TIMETZADT_P(1);	PG_RETURN_INT32(timetz_cmp_internal(time1, time2));}Datumtimetz_hash(PG_FUNCTION_ARGS){	TimeTzADT  *key = PG_GETARG_TIMETZADT_P(0);	uint32		thash;	/*	 * To avoid any problems with padding bytes in the struct, we figure the	 * field hashes separately and XOR them.  This also provides a convenient	 * framework for dealing with the fact that the time field might be either	 * double or int64.	 */#ifdef HAVE_INT64_TIMESTAMP	thash = DatumGetUInt32(DirectFunctionCall1(hashint8,											   Int64GetDatumFast(key->time)));#else	thash = DatumGetUInt32(DirectFunctionCall1(hashfloat8,											 Float8GetDatumFast(key->time)));#endif	thash ^= DatumGetUInt32(hash_uint32(key->zone));	PG_RETURN_UINT32(thash);}Datumtimetz_larger(PG_FUNCTION_ARGS){	TimeTzADT  *time1 = PG_GETARG_TIMETZADT_P(0);	TimeTzADT  *time2 = PG_GETARG_TIMETZADT_P(1);	TimeTzADT  *result;	if (timetz_cmp_internal(time1, time2) > 0)		result = time1;	else		result = time2;	PG_RETURN_TIMETZADT_P(result);}Datumtimetz_smaller(PG_FUNCTION_ARGS){	TimeTzADT  *time1 = PG_GETARG_TIMETZADT_P(0);	TimeTzADT  *time2 = PG_GETARG_TIMETZADT_P(1);	TimeTzADT  *result;	if (timetz_cmp_internal(time1, time2) < 0)		result = time1;	else		result = time2;	PG_RETURN_TIMETZADT_P(result);}/* timetz_pl_interval() * Add interval to timetz. */Datumtimetz_pl_interval(PG_FUNCTION_ARGS){	TimeTzADT  *time = PG_GETARG_TIMETZADT_P(0);	Interval   *span = PG_GETARG_INTERVAL_P(1);	TimeTzADT  *result;#ifndef HAVE_INT64_TIMESTAMP	TimeTzADT	time1;#endif	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));#ifdef HAVE_INT64_TIMESTAMP	result->time = time->time + span->time;	result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY;	if (result->time < INT64CONST(0))		result->time += USECS_PER_DAY;#else	result->time = time->time + span->time;	TMODULO(result->time, time1.time, (double) SECS_PER_DAY);	if (result->time < 0)		result->time += SECS_PER_DAY;#endif	result->zone = time->zone;	PG_RETURN_TIMETZADT_P(result);}/* timetz_mi_interval() * Subtract interval from timetz. */Datumtimetz_mi_interval(PG_FUNCTION_ARGS){	TimeTzADT  *time = PG_GETARG_TIMETZADT_P(0);	Interval   *span = PG_GETARG_INTERVAL_P(1);	TimeTzADT  *result;#ifndef HAVE_INT64_TIMESTAMP	TimeTzADT	time1;#endif	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));#ifdef HAVE_INT64_TIMESTAMP	result->time = time->time - span->time;	result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY;	if (result->time < INT64CONST(0))		result->time += USECS_PER_DAY;#else	result->time = time->time - span->time;	TMODULO(result->time, time1.time, (double) SECS_PER_DAY);	if (result->time < 0)		result->time += SECS_PER_DAY;#endif	result->zone = time->zone;	PG_RETURN_TIMETZADT_P(result);}/* overlaps_timetz() --- 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_timetz(PG_FUNCTION_ARGS){	/*	 * The arguments are TimeTzADT *, but we leave them as generic Datums for	 * convenience of notation --- and to avoid dereferencing nulls.	 */	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 TIMETZ_GT(t1,t2) \	DatumGetBool(DirectFunctionCall2(timetz_gt,t1,t2))#define TIMETZ_LT(t1,t2) \	DatumGetBool(DirectFunctionCall2(timetz_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 (TIMETZ_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 (TIMETZ_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 (TIMETZ_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 (TIMETZ_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 (TIMETZ_LT(ts1, ts2))	{		/* This case is ts2 < te1 OR te2 < te1 */		if (te1IsNull)			PG_RETURN_NULL();		if (TIMETZ_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 TIMETZ_GT#undef TIMETZ_LT}Datumtimetz_time(PG_FUNCTION_ARGS){	TimeTzADT  *timetz = PG_GETARG_TIMETZADT_P(0);	TimeADT		result;	/* swallow the time zone and just return the time */	result = timetz->time;	PG_RETURN_TIMEADT(result);}Datumtime_timetz(PG_FUNCTION_ARGS){	TimeADT		time = PG_GETARG_TIMEADT(0);	TimeTzADT  *result;	struct pg_tm tt,			   *tm = &tt;	fsec_t		fsec;	int			tz;	GetCurrentDateTime(tm);	time2tm(time, tm, &fsec);	tz = DetermineTimeZoneOffset(tm, session_timezone);	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));	result->time = time;	result->zone = tz;	PG_RETURN_TIMETZADT_P(result);}/* timestamptz_timetz() * Convert timestamp to timetz data type. */Datumtimestamptz_timetz(PG_FUNCTION_ARGS){	TimestampTz timestamp = PG_GETARG_TIMESTAMP(0);	TimeTzADT  *result;	struct pg_tm tt,			   *tm = &tt;	int			tz;	fsec_t		fsec;	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 = (TimeTzADT *) palloc(sizeof(TimeTzADT));	tm2timetz(tm, fsec, tz, result);	PG_RETURN_TIMETZADT_P(result);}/* datetimetz_timestamptz() * Convert date and timetz to timestamp with time zone data type. * Timestamp is stored in GMT, so add the time zone * stored with the timetz to the result. * - thomas 2000-03-10 */Datumdatetimetz_timestamptz(PG_FUNCTION_ARGS){	DateADT		date = PG_GETARG_DATEADT(0);	TimeTzADT  *time = PG_GETARG_TIMETZADT_P(1);	TimestampTz result;#ifdef HAVE_INT64_TIMESTAMP	result = date * USECS_PER_DAY + time->time + time->zone * USECS_PER_SEC;#else	result = date * (double) SECS_PER_DAY + time->time + time->zone;#endif	PG_RETURN_TIMESTAMP(result);}/* timetz_part() * Extract specified field from time type. */Datumtimetz_part(PG_FUNCTION_ARGS){	text	   *units = PG_GETARG_TEXT_P(0);	TimeTzADT  *time = PG_GETARG_TIMETZADT_P(1);	float8		result;	int			type,				val;	char	   *lowunits;	lowunits = downcase_truncate_identifier(VARDATA(units),											VARSIZE(units) - VARHDRSZ,											false);	type = DecodeUnits(0, lowunits, &val);	if (type == UNKNOWN_FIELD)		type = DecodeSpecial(0, lowunits, &val);	if (type == UNITS)	{		double		dummy;		int			tz;		fsec_t		fsec;		struct pg_tm tt,				   *tm = &tt;		timetz2tm(time, tm, &fsec, &tz);		switch (val)		{			case DTK_TZ:				result = -tz;				break;			case DTK_TZ_MINUTE:				result = -tz;				result /= SECS_PER_MINUTE;				FMODULO(result, dummy, (double) SECS_PER_MINUTE);				break;			case DTK_TZ_HOUR:				dummy = -tz;				FMODULO(dummy, result, (double) SECS_PER_HOUR);				break;			case DTK_MICROSEC:#ifdef HAVE_INT64_TIMESTAMP				result = tm->tm_sec * USECS_PER_SEC + fsec;#else				result = (tm->tm_sec + fsec) * 1000000;#endif				break;			case DTK_MILLISEC:#ifdef HAVE_INT64_TIMESTAMP				result = tm->tm_sec * INT64CONST(1000) + fsec / INT64CONST(1000);#else				result = (tm->tm_sec + fsec) * 1000;#endif				break;			case DTK_SECOND:#ifdef HAVE_INT64_TIMESTAMP				result = tm->tm_sec + fsec / USECS_PER_SEC;#else				result = tm->tm_sec + fsec;#endif				break;			case DTK_MINUTE:				result = tm->tm_min;				break;			case DTK_HOUR:				result = tm->tm_hour;				break;			case DTK_DAY:			case DTK_MONTH:			case DTK_QUARTER:			case DTK_YEAR:			case DTK_DECADE:			case DTK_CENTURY:			case DTK_MILLENNIUM:			default:				ereport(ERROR,						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				errmsg("\"time with time zone\" units \"%s\" not recognized",					   DatumGetCString(DirectFunctionCall1(textout,												 PointerGetDatum(units))))));				result = 0;		}	}	else if (type == RESERV && val == DTK_EPOCH)	{#ifdef HAVE_INT64_TIMESTAMP		result = time->time / 1000000.0 + time->zone;#else		result = time->time + time->zone;#endif	}	else	{		ereport(ERROR,				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				 errmsg("\"time with time zone\" units \"%s\" not recognized",						DatumGetCString(DirectFunctionCall1(textout,												 PointerGetDatum(units))))));		result = 0;	}	PG_RETURN_FLOAT8(result);}/* timetz_zone() * Encode time with time zone type with specified time zone. * Applies DST rules as of the current date. */Datumtimetz_zone(PG_FUNCTION_ARGS){	text	   *zone = PG_GETARG_TEXT_P(0);	TimeTzADT  *t = PG_GETARG_TIMETZADT_P(1);	TimeTzADT  *result;	int			tz;	char		tzname[TZ_STRLEN_MAX + 1];	int			len;	char	   *lowzone;	int			type,				val;	pg_tz	   *tzp;	/*	 * Look up the requested timezone.  First we look in the date token table	 * (to handle cases like "EST"), and if that fails, we look in the	 * timezone database (to handle cases like "America/New_York").  (This	 * matches the order in which timestamp input checks the cases; it's	 * important because the timezone database unwisely uses a few zone names	 * that are identical to offset abbreviations.)	 */	lowzone = downcase_truncate_identifier(VARDATA(zone),										   VARSIZE(zone) - VARHDRSZ,										   false);	type = DecodeSpecial(0, lowzone, &val);	if (type == TZ || type == DTZ)		tz = val * 60;	else	{		len = Min(VARSIZE(zone) - VARHDRSZ, TZ_STRLEN_MAX);		memcpy(tzname, VARDATA(zone), len);		tzname[len] = '\0';		tzp = pg_tzset(tzname);		if (tzp)		{			/* Get the offset-from-GMT that is valid today for the zone */			pg_time_t	now;			struct pg_tm *tm;			now = time(NULL);			tm = pg_localtime(&now, tzp);			tz = -tm->tm_gmtoff;		}		else		{			ereport(ERROR,					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),					 errmsg("time zone \"%s\" not recognized", tzname)));			tz = 0;				/* keep compiler quiet */		}	}	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));#ifdef HAVE_INT64_TIMESTAMP	result->time = t->time + (t->zone - tz) * USECS_PER_SEC;	while (result->time < INT64CONST(0))		result->time += USECS_PER_DAY;	while (result->time >= USECS_PER_DAY)		result->time -= USECS_PER_DAY;#else	result->time = t->time + (t->zone - tz);	while (result->time < 0)		result->time += SECS_PER_DAY;	while (result->time >= SECS_PER_DAY)		result->time -= SECS_PER_DAY;#endif	result->zone = tz;	PG_RETURN_TIMETZADT_P(result);}/* timetz_izone() * Encode time with time zone type with specified time interval as time zone. */Datumtimetz_izone(PG_FUNCTION_ARGS){	Interval   *zone = PG_GETARG_INTERVAL_P(0);	TimeTzADT  *time = PG_GETARG_TIMETZADT_P(1);	TimeTzADT  *result;	int			tz;	if (zone->month != 0)		ereport(ERROR,				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				 errmsg("\"interval\" time zone \"%s\" not valid",						DatumGetCString(DirectFunctionCall1(interval_out,												  PointerGetDatum(zone))))));#ifdef HAVE_INT64_TIMESTAMP	tz = -(zone->time / USECS_PER_SEC);#else	tz = -(zone->time);#endif	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));#ifdef HAVE_INT64_TIMESTAMP	result->time = time->time + (time->zone - tz) * USECS_PER_SEC;	while (result->time < INT64CONST(0))		result->time += USECS_PER_DAY;	while (result->time >= USECS_PER_DAY)		result->time -= USECS_PER_DAY;#else	result->time = time->time + (time->zone - tz);	while (result->time < 0)		result->time += SECS_PER_DAY;	while (result->time >= SECS_PER_DAY)		result->time -= SECS_PER_DAY;#endif	result->zone = tz;	PG_RETURN_TIMETZADT_P(result);}

⌨️ 快捷键说明

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