9393#include "utils/float.h"
9494#include "utils/formatting.h"
9595#include "utils/int8.h"
96+ #include "utils/memutils.h"
9697#include "utils/numeric.h"
9798#include "utils/pg_locale.h"
9899
124125 */
125126typedef struct
126127{
127- char * name ;/* suffix string*/
128+ const char * name ;/* suffix string*/
128129int len ,/* suffix length*/
129130id ,/* used in node->suffix */
130- type ;/* prefix / postfix */
131+ type ;/* prefix / postfix*/
131132}KeySuffix ;
132133
133134/* ----------
@@ -155,10 +156,10 @@ typedef struct
155156
156157typedef struct
157158{
158- int type ;/* NODE_TYPE_XXX, see below */
159- const KeyWord * key ;/* if type is ACTION */
159+ uint8 type ;/* NODE_TYPE_XXX, see below */
160160char character [MAX_MULTIBYTE_CHAR_LEN + 1 ];/* if type is CHAR */
161- int suffix ;/* keyword prefix/suffix code, if any */
161+ uint8 suffix ;/* keyword prefix/suffix code, if any */
162+ const KeyWord * key ;/* if type is ACTION */
162163}FormatNode ;
163164
164165#define NODE_TYPE_END 1
@@ -358,14 +359,27 @@ typedef struct
358359 * For simplicity, the cache entries are fixed-size, so they allow for the
359360 * worst case of a FormatNode for each byte in the picture string.
360361 *
361- * The max number of entries in the caches is DCH_CACHE_ENTRIES
362+ * The CACHE_SIZE constants are computed to make sizeof(DCHCacheEntry) and
363+ * sizeof(NUMCacheEntry) be powers of 2, or just less than that, so that
364+ * we don't waste too much space by palloc'ing them individually. Be sure
365+ * to adjust those macros if you add fields to those structs.
366+ *
367+ * The max number of entries in each cache is DCH_CACHE_ENTRIES
362368 * resp. NUM_CACHE_ENTRIES.
363369 * ----------
364370 */
365- #define NUM_CACHE_SIZE 64
366- #define NUM_CACHE_ENTRIES 20
367- #define DCH_CACHE_SIZE 128
371+ #define DCH_CACHE_OVERHEAD \
372+ MAXALIGN(sizeof(bool) + sizeof(int))
373+ #define NUM_CACHE_OVERHEAD \
374+ MAXALIGN(sizeof(bool) + sizeof(int) + sizeof(NUMDesc))
375+
376+ #define DCH_CACHE_SIZE \
377+ ((2048 - DCH_CACHE_OVERHEAD) / (sizeof(FormatNode) + sizeof(char)) - 1)
378+ #define NUM_CACHE_SIZE \
379+ ((1024 - NUM_CACHE_OVERHEAD) / (sizeof(FormatNode) + sizeof(char)) - 1)
380+
368381#define DCH_CACHE_ENTRIES 20
382+ #define NUM_CACHE_ENTRIES 20
369383
370384typedef struct
371385{
@@ -385,12 +399,12 @@ typedef struct
385399}NUMCacheEntry ;
386400
387401/* global cache for date/time format pictures */
388- static DCHCacheEntry DCHCache [DCH_CACHE_ENTRIES ];
402+ static DCHCacheEntry * DCHCache [DCH_CACHE_ENTRIES ];
389403static int n_DCHCache = 0 ;/* current number of entries */
390404static int DCHCounter = 0 ;/* aging-event counter */
391405
392406/* global cache for number format pictures */
393- static NUMCacheEntry NUMCache [NUM_CACHE_ENTRIES ];
407+ static NUMCacheEntry * NUMCache [NUM_CACHE_ENTRIES ];
394408static int n_NUMCache = 0 ;/* current number of entries */
395409static int NUMCounter = 0 ;/* aging-event counter */
396410
@@ -496,7 +510,7 @@ do { \
496510 *****************************************************************************/
497511
498512/* ----------
499- * Suffixes:
513+ * Suffixes (FormatNode.suffix is an OR of these codes)
500514 * ----------
501515 */
502516#define DCH_S_FM 0x01
@@ -3368,29 +3382,30 @@ DCH_cache_getnew(const char *str)
33683382{
33693383DCHCacheEntry * ent ;
33703384
3371- /* counter overflowcheck - paranoia? */
3385+ /*handle counter overflowby resetting all ages */
33723386if (DCHCounter >= (INT_MAX - DCH_CACHE_ENTRIES ))
33733387{
33743388DCHCounter = 0 ;
33753389
3376- for (ent = DCHCache ; ent < ( DCHCache + DCH_CACHE_ENTRIES ); ent ++ )
3377- ent -> age = (++ DCHCounter );
3390+ for (int i = 0 ; i < n_DCHCache ; i ++ )
3391+ DCHCache [ i ] -> age = (++ DCHCounter );
33783392}
33793393
33803394/*
33813395 * If cache is full, remove oldest entry (or recycle first not-valid one)
33823396 */
33833397if (n_DCHCache >=DCH_CACHE_ENTRIES )
33843398{
3385- DCHCacheEntry * old = DCHCache + 0 ;
3399+ DCHCacheEntry * old = DCHCache [ 0 ] ;
33863400
33873401#ifdef DEBUG_TO_FROM_CHAR
33883402elog (DEBUG_elog_output ,"cache is full (%d)" ,n_DCHCache );
33893403#endif
33903404if (old -> valid )
33913405{
3392- for (ent = DCHCache + 1 ;ent < ( DCHCache + DCH_CACHE_ENTRIES ); ent ++ )
3406+ for (int i = 1 ;i < DCH_CACHE_ENTRIES ; i ++ )
33933407{
3408+ ent = DCHCache [i ];
33943409if (!ent -> valid )
33953410{
33963411old = ent ;
@@ -3414,7 +3429,9 @@ DCH_cache_getnew(const char *str)
34143429#ifdef DEBUG_TO_FROM_CHAR
34153430elog (DEBUG_elog_output ,"NEW (%d)" ,n_DCHCache );
34163431#endif
3417- ent = DCHCache + n_DCHCache ;
3432+ Assert (DCHCache [n_DCHCache ]== NULL );
3433+ DCHCache [n_DCHCache ]= ent = (DCHCacheEntry * )
3434+ MemoryContextAllocZero (TopMemoryContext ,sizeof (DCHCacheEntry ));
34183435ent -> valid = false;
34193436StrNCpy (ent -> str ,str ,DCH_CACHE_SIZE + 1 );
34203437ent -> age = (++ DCHCounter );
@@ -3428,20 +3445,19 @@ DCH_cache_getnew(const char *str)
34283445static DCHCacheEntry *
34293446DCH_cache_search (const char * str )
34303447{
3431- int i ;
3432- DCHCacheEntry * ent ;
3433-
3434- /* counter overflow check - paranoia? */
3448+ /* handle counter overflow by resetting all ages */
34353449if (DCHCounter >= (INT_MAX - DCH_CACHE_ENTRIES ))
34363450{
34373451DCHCounter = 0 ;
34383452
3439- for (ent = DCHCache ; ent < ( DCHCache + DCH_CACHE_ENTRIES ); ent ++ )
3440- ent -> age = (++ DCHCounter );
3453+ for (int i = 0 ; i < n_DCHCache ; i ++ )
3454+ DCHCache [ i ] -> age = (++ DCHCounter );
34413455}
34423456
3443- for (i = 0 , ent = DCHCache ;i < n_DCHCache ;i ++ , ent ++ )
3457+ for (int i = 0 ;i < n_DCHCache ;i ++ )
34443458{
3459+ DCHCacheEntry * ent = DCHCache [i ];
3460+
34453461if (ent -> valid && strcmp (ent -> str ,str )== 0 )
34463462{
34473463ent -> age = (++ DCHCounter );
@@ -4047,29 +4063,30 @@ NUM_cache_getnew(const char *str)
40474063{
40484064NUMCacheEntry * ent ;
40494065
4050- /* counter overflowcheck - paranoia? */
4066+ /*handle counter overflowby resetting all ages */
40514067if (NUMCounter >= (INT_MAX - NUM_CACHE_ENTRIES ))
40524068{
40534069NUMCounter = 0 ;
40544070
4055- for (ent = NUMCache ; ent < ( NUMCache + NUM_CACHE_ENTRIES ); ent ++ )
4056- ent -> age = (++ NUMCounter );
4071+ for (int i = 0 ; i < n_NUMCache ; i ++ )
4072+ NUMCache [ i ] -> age = (++ NUMCounter );
40574073}
40584074
40594075/*
40604076 * If cache is full, remove oldest entry (or recycle first not-valid one)
40614077 */
40624078if (n_NUMCache >=NUM_CACHE_ENTRIES )
40634079{
4064- NUMCacheEntry * old = NUMCache + 0 ;
4080+ NUMCacheEntry * old = NUMCache [ 0 ] ;
40654081
40664082#ifdef DEBUG_TO_FROM_CHAR
40674083elog (DEBUG_elog_output ,"Cache is full (%d)" ,n_NUMCache );
40684084#endif
40694085if (old -> valid )
40704086{
4071- for (ent = NUMCache + 1 ;ent < ( NUMCache + NUM_CACHE_ENTRIES ); ent ++ )
4087+ for (int i = 1 ;i < NUM_CACHE_ENTRIES ; i ++ )
40724088{
4089+ ent = NUMCache [i ];
40734090if (!ent -> valid )
40744091{
40754092old = ent ;
@@ -4093,7 +4110,9 @@ NUM_cache_getnew(const char *str)
40934110#ifdef DEBUG_TO_FROM_CHAR
40944111elog (DEBUG_elog_output ,"NEW (%d)" ,n_NUMCache );
40954112#endif
4096- ent = NUMCache + n_NUMCache ;
4113+ Assert (NUMCache [n_NUMCache ]== NULL );
4114+ NUMCache [n_NUMCache ]= ent = (NUMCacheEntry * )
4115+ MemoryContextAllocZero (TopMemoryContext ,sizeof (NUMCacheEntry ));
40974116ent -> valid = false;
40984117StrNCpy (ent -> str ,str ,NUM_CACHE_SIZE + 1 );
40994118ent -> age = (++ NUMCounter );
@@ -4107,20 +4126,19 @@ NUM_cache_getnew(const char *str)
41074126static NUMCacheEntry *
41084127NUM_cache_search (const char * str )
41094128{
4110- int i ;
4111- NUMCacheEntry * ent ;
4112-
4113- /* counter overflow check - paranoia? */
4129+ /* handle counter overflow by resetting all ages */
41144130if (NUMCounter >= (INT_MAX - NUM_CACHE_ENTRIES ))
41154131{
41164132NUMCounter = 0 ;
41174133
4118- for (ent = NUMCache ; ent < ( NUMCache + NUM_CACHE_ENTRIES ); ent ++ )
4119- ent -> age = (++ NUMCounter );
4134+ for (int i = 0 ; i < n_NUMCache ; i ++ )
4135+ NUMCache [ i ] -> age = (++ NUMCounter );
41204136}
41214137
4122- for (i = 0 , ent = NUMCache ;i < n_NUMCache ;i ++ , ent ++ )
4138+ for (int i = 0 ;i < n_NUMCache ;i ++ )
41234139{
4140+ NUMCacheEntry * ent = NUMCache [i ];
4141+
41244142if (ent -> valid && strcmp (ent -> str ,str )== 0 )
41254143{
41264144ent -> age = (++ NUMCounter );