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{
38473847 FuncCallContext * funcctx ;
38483848 int * pindex ;
38493849 Datum result ;
3850- Interval * resInterval ;
38513850 HeapTuple tuple ;
38523851 Datum values [3 ];
38533852 bool nulls [3 ];
38543853 char buffer [TOKMAXLEN + 1 ];
38553854 unsigned char * p ;
38563855 struct pg_tm tm ;
3856+ Interval * resInterval ;
38573857
38583858 /* stuff done only on the first call of the function */
38593859 if (SRF_IS_FIRSTCALL ())
@@ -3876,11 +3876,11 @@ pg_timezonenames(PG_FUNCTION_ARGS)
38763876 funcctx -> user_fctx = (void * ) pindex ;
38773877
38783878 /*
3879- * build tupdesc for result tuples. This must match the
3880- * definition of the pg_timezonenames view in system_views.sql
3879+ * build tupdesc for result tuples. This must match this function's
3880+ * pg_proc entry!
38813881 */
38823882 tupdesc = CreateTemplateTupleDesc (3 , false);
3883- TupleDescInitEntry (tupdesc , (AttrNumber ) 1 , "name " ,
3883+ TupleDescInitEntry (tupdesc , (AttrNumber ) 1 , "abbrev " ,
38843884 TEXTOID , -1 , 0 );
38853885 TupleDescInitEntry (tupdesc , (AttrNumber ) 2 , "utc_offset" ,
38863886 INTERVALOID , -1 , 0 );
@@ -3928,3 +3928,114 @@ pg_timezonenames(PG_FUNCTION_ARGS)
39283928
39293929 SRF_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+ }
0 commit comments