88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.170 2006/09/04 01:26:27 tgl Exp $
11+ * $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.171 2006/09/16 20:14:33 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -3839,21 +3839,21 @@ InstallTimeZoneAbbrevs(tzEntry *abbrevs, int n)
38393839
38403840/*
38413841 * This set-returning function reads all the available time zone abbreviations
3842- * and returns a set of (name , utc_offset, is_dst).
3842+ * and returns a set of (abbrev , utc_offset, is_dst).
38433843 */
38443844Datum
3845- pg_timezonenames (PG_FUNCTION_ARGS )
3845+ pg_timezone_abbrevs (PG_FUNCTION_ARGS )
38463846{
38473847FuncCallContext * funcctx ;
38483848int * pindex ;
38493849Datum result ;
3850- Interval * resInterval ;
38513850HeapTuple tuple ;
38523851Datum values [3 ];
38533852bool nulls [3 ];
38543853char buffer [TOKMAXLEN + 1 ];
38553854unsignedchar * p ;
38563855struct pg_tm tm ;
3856+ Interval * resInterval ;
38573857
38583858/* stuff done only on the first call of the function */
38593859if (SRF_IS_FIRSTCALL ())
@@ -3876,11 +3876,11 @@ pg_timezonenames(PG_FUNCTION_ARGS)
38763876funcctx -> user_fctx = (void * )pindex ;
38773877
38783878/*
3879- * build tupdesc for result tuples. This must matchthe
3880- *definition of the pg_timezonenames view in system_views.sql
3879+ * build tupdesc for result tuples. This must matchthis function's
3880+ *pg_proc entry!
38813881 */
38823882tupdesc = CreateTemplateTupleDesc (3 , false);
3883- TupleDescInitEntry (tupdesc , (AttrNumber )1 ,"name " ,
3883+ TupleDescInitEntry (tupdesc , (AttrNumber )1 ,"abbrev " ,
38843884TEXTOID ,-1 ,0 );
38853885TupleDescInitEntry (tupdesc , (AttrNumber )2 ,"utc_offset" ,
38863886INTERVALOID ,-1 ,0 );
@@ -3928,3 +3928,114 @@ pg_timezonenames(PG_FUNCTION_ARGS)
39283928
39293929SRF_RETURN_NEXT (funcctx ,result );
39303930}
3931+
3932+ /*
3933+ * This set-returning function reads all the available full time zones
3934+ * and returns a set of (name, abbrev, utc_offset, is_dst).
3935+ */
3936+ Datum
3937+ pg_timezone_names (PG_FUNCTION_ARGS )
3938+ {
3939+ MemoryContext oldcontext ;
3940+ FuncCallContext * funcctx ;
3941+ pg_tzenum * tzenum ;
3942+ pg_tz * tz ;
3943+ Datum result ;
3944+ HeapTuple tuple ;
3945+ Datum values [4 ];
3946+ bool nulls [4 ];
3947+ int tzoff ;
3948+ struct pg_tm tm ;
3949+ fsec_t fsec ;
3950+ char * tzn ;
3951+ Interval * resInterval ;
3952+ struct pg_tm itm ;
3953+
3954+ /* stuff done only on the first call of the function */
3955+ if (SRF_IS_FIRSTCALL ())
3956+ {
3957+ TupleDesc tupdesc ;
3958+
3959+ /* create a function context for cross-call persistence */
3960+ funcctx = SRF_FIRSTCALL_INIT ();
3961+
3962+ /*
3963+ * switch to memory context appropriate for multiple function
3964+ * calls
3965+ */
3966+ oldcontext = MemoryContextSwitchTo (funcctx -> multi_call_memory_ctx );
3967+
3968+ /* initialize timezone scanning code */
3969+ tzenum = pg_tzenumerate_start ();
3970+ funcctx -> user_fctx = (void * )tzenum ;
3971+
3972+ /*
3973+ * build tupdesc for result tuples. This must match this function's
3974+ * pg_proc entry!
3975+ */
3976+ tupdesc = CreateTemplateTupleDesc (4 , false);
3977+ TupleDescInitEntry (tupdesc , (AttrNumber )1 ,"name" ,
3978+ TEXTOID ,-1 ,0 );
3979+ TupleDescInitEntry (tupdesc , (AttrNumber )2 ,"abbrev" ,
3980+ TEXTOID ,-1 ,0 );
3981+ TupleDescInitEntry (tupdesc , (AttrNumber )3 ,"utc_offset" ,
3982+ INTERVALOID ,-1 ,0 );
3983+ TupleDescInitEntry (tupdesc , (AttrNumber )4 ,"is_dst" ,
3984+ BOOLOID ,-1 ,0 );
3985+
3986+ funcctx -> tuple_desc = BlessTupleDesc (tupdesc );
3987+ MemoryContextSwitchTo (oldcontext );
3988+ }
3989+
3990+ /* stuff done on every call of the function */
3991+ funcctx = SRF_PERCALL_SETUP ();
3992+ tzenum = (pg_tzenum * )funcctx -> user_fctx ;
3993+
3994+ /* search for another zone to display */
3995+ for (;;)
3996+ {
3997+ oldcontext = MemoryContextSwitchTo (funcctx -> multi_call_memory_ctx );
3998+ tz = pg_tzenumerate_next (tzenum );
3999+ MemoryContextSwitchTo (oldcontext );
4000+
4001+ if (!tz )
4002+ {
4003+ pg_tzenumerate_end (tzenum );
4004+ funcctx -> user_fctx = NULL ;
4005+ SRF_RETURN_DONE (funcctx );
4006+ }
4007+
4008+ /* Convert now() to local time in this zone */
4009+ if (timestamp2tm (GetCurrentTransactionStartTimestamp (),
4010+ & tzoff ,& tm ,& fsec ,& tzn ,tz )!= 0 )
4011+ continue ;/* ignore if conversion fails */
4012+
4013+ /* Ignore zic's rather silly "Factory" time zone */
4014+ if (tzn && strcmp (tzn ,"Local time zone must be set--see zic manual page" )== 0 )
4015+ continue ;
4016+
4017+ /* Found a displayable zone */
4018+ break ;
4019+ }
4020+
4021+ MemSet (nulls ,0 ,sizeof (nulls ));
4022+
4023+ values [0 ]= DirectFunctionCall1 (textin ,
4024+ CStringGetDatum (pg_get_timezone_name (tz )));
4025+
4026+ values [1 ]= DirectFunctionCall1 (textin ,
4027+ CStringGetDatum (tzn ?tzn :"" ));
4028+
4029+ MemSet (& itm ,0 ,sizeof (struct pg_tm ));
4030+ itm .tm_sec = - tzoff ;
4031+ resInterval = (Interval * )palloc (sizeof (Interval ));
4032+ tm2interval (& itm ,0 ,resInterval );
4033+ values [2 ]= IntervalPGetDatum (resInterval );
4034+
4035+ values [3 ]= BoolGetDatum (tm .tm_isdst > 0 );
4036+
4037+ tuple = heap_form_tuple (funcctx -> tuple_desc ,values ,nulls );
4038+ result = HeapTupleGetDatum (tuple );
4039+
4040+ SRF_RETURN_NEXT (funcctx ,result );
4041+ }