@@ -48,55 +48,87 @@ unit_get_definitions(void)
4848 int i ;
4949 unit_names_t * unit_name ;
5050 unit_dimensions_t * unit_dim ;
51+ static HTAB * tmp_unit_names ;
52+ static HTAB * tmp_unit_dimensions ;
5153
52- /* unit_names : char *name -> Unit unit
54+ /* tmp_unit_names : char *name -> Unit unit
5355 * Lookup table that initially contains the base units and will cache all
5456 * units resolved at run time
5557 */
5658 hinfo .keysize = UNIT_NAME_LENGTH ;
5759 hinfo .entrysize = sizeof (unit_names_t );
5860 Assert (UNIT_NAME_LENGTH + sizeof (UnitShift ) == sizeof (unit_names_t ));
59- unit_names = hash_create ("unit_names" ,
61+ tmp_unit_names = hash_create ("unit_names" ,
6062 20 ,
6163 & hinfo ,
6264 HASH_ELEM ); /* Set keysize and entrysize */
6365
64- for ( i = 0 ; derived_units [ i ]. name ; i ++ )
66+ PG_TRY ();
6567 {
66- if (derived_units [i ].flags & U_DERIVED )
67- break ; // FIXME: split tables
68- unit_name = hash_search (unit_names ,
69- derived_units [i ].name ,
70- HASH_ENTER ,
71- NULL );
72- strlcpy (unit_name -> name , derived_units [i ].name , UNIT_NAME_LENGTH );
73- unit_name -> unit_shift .unit .value = derived_units [i ].factor ;
74- memcpy (unit_name -> unit_shift .unit .units , derived_units [i ].units , N_UNITS );
75- unit_name -> unit_shift .shift = 0.0 ;
68+ for (i = 0 ; derived_units [i ].name ; i ++ )
69+ {
70+ if (derived_units [i ].flags & U_DERIVED )
71+ break ; // FIXME: split tables
72+ unit_name = hash_search (tmp_unit_names ,
73+ derived_units [i ].name ,
74+ HASH_ENTER ,
75+ NULL );
76+ strlcpy (unit_name -> name , derived_units [i ].name , UNIT_NAME_LENGTH );
77+ unit_name -> unit_shift .unit .value = derived_units [i ].factor ;
78+ memcpy (unit_name -> unit_shift .unit .units , derived_units [i ].units , N_UNITS );
79+ unit_name -> unit_shift .shift = 0.0 ;
80+ }
81+ }
82+ PG_CATCH ();
83+ {
84+ /* free partially initialized table */
85+ hash_destroy (tmp_unit_names );
86+ PG_RE_THROW ();
7687 }
88+ PG_END_TRY ();
89+
90+ /* No OOM errors were thrown, use the new table */
91+ if (unit_names )
92+ hash_destroy (unit_names );
93+ unit_names = tmp_unit_names ;
7794
78- /* unit_dimensions : char dimension[N_UNITS] -> char *name
95+ /* tmp_unit_dimensions : char dimension[N_UNITS] -> char *name
7996 * Lookup table for formatting the well-known derived units on output
8097 */
8198 hinfo .keysize = N_UNITS ;
8299 hinfo .entrysize = sizeof (unit_dimensions_t );
83100 Assert (N_UNITS + UNIT_NAME_LENGTH == sizeof (unit_dimensions_t ));
84- unit_dimensions = hash_create ("unit_dimensions" ,
101+ tmp_unit_dimensions = hash_create ("unit_dimensions" ,
85102 20 ,
86103 & hinfo ,
87104 HASH_ELEM | HASH_BLOBS );
88105
89- for ( i = 0 ; derived_units [ i ]. name ; i ++ )
106+ PG_TRY ();
90107 {
91- if (! derived_units [i ].flags & U_DERIVED )
92- continue ;
93- unit_dim = hash_search (unit_dimensions ,
94- derived_units [i ].units ,
95- HASH_ENTER ,
96- NULL );
97- memcpy (unit_dim -> units , derived_units [i ].units , N_UNITS );
98- strlcpy (unit_dim -> name , derived_units [i ].name , UNIT_NAME_LENGTH );
108+ for (i = 0 ; derived_units [i ].name ; i ++ )
109+ {
110+ if (! derived_units [i ].flags & U_DERIVED )
111+ continue ;
112+ unit_dim = hash_search (tmp_unit_dimensions ,
113+ derived_units [i ].units ,
114+ HASH_ENTER ,
115+ NULL );
116+ memcpy (unit_dim -> units , derived_units [i ].units , N_UNITS );
117+ strlcpy (unit_dim -> name , derived_units [i ].name , UNIT_NAME_LENGTH );
118+ }
119+ }
120+ PG_CATCH ();
121+ {
122+ /* free partially initialized table */
123+ hash_destroy (tmp_unit_dimensions );
124+ PG_RE_THROW ();
99125 }
126+ PG_END_TRY ();
127+
128+ /* No OOM errors were thrown, use the new table */
129+ if (unit_dimensions )
130+ hash_destroy (unit_dimensions );
131+ unit_dimensions = tmp_unit_dimensions ;
100132}
101133
102134/* module initialization */
@@ -946,8 +978,6 @@ Datum
946978unit_reset (PG_FUNCTION_ARGS )
947979{
948980 /* reinitialize hash tables */
949- hash_destroy (unit_names );
950- hash_destroy (unit_dimensions );
951981 unit_get_definitions ();
952982
953983 PG_RETURN_VOID ();
0 commit comments