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 */
128129 int len , /* suffix length */
129130 id , /* 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 */
160160 char 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{
33693383 DCHCacheEntry * ent ;
33703384
3371- /* counter overflow check - paranoia? */
3385+ /* handle counter overflow by resetting all ages */
33723386 if (DCHCounter >= (INT_MAX - DCH_CACHE_ENTRIES ))
33733387 {
33743388 DCHCounter = 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 */
33833397 if (n_DCHCache >= DCH_CACHE_ENTRIES )
33843398 {
3385- DCHCacheEntry * old = DCHCache + 0 ;
3399+ DCHCacheEntry * old = DCHCache [ 0 ] ;
33863400
33873401#ifdef DEBUG_TO_FROM_CHAR
33883402 elog (DEBUG_elog_output , "cache is full (%d)" , n_DCHCache );
33893403#endif
33903404 if (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 ];
33943409 if (!ent -> valid )
33953410 {
33963411 old = ent ;
@@ -3414,7 +3429,9 @@ DCH_cache_getnew(const char *str)
34143429#ifdef DEBUG_TO_FROM_CHAR
34153430 elog (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 ));
34183435 ent -> valid = false;
34193436 StrNCpy (ent -> str , str , DCH_CACHE_SIZE + 1 );
34203437 ent -> 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 */
34353449 if (DCHCounter >= (INT_MAX - DCH_CACHE_ENTRIES ))
34363450 {
34373451 DCHCounter = 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+
34453461 if (ent -> valid && strcmp (ent -> str , str ) == 0 )
34463462 {
34473463 ent -> age = (++ DCHCounter );
@@ -4047,29 +4063,30 @@ NUM_cache_getnew(const char *str)
40474063{
40484064 NUMCacheEntry * ent ;
40494065
4050- /* counter overflow check - paranoia? */
4066+ /* handle counter overflow by resetting all ages */
40514067 if (NUMCounter >= (INT_MAX - NUM_CACHE_ENTRIES ))
40524068 {
40534069 NUMCounter = 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 */
40624078 if (n_NUMCache >= NUM_CACHE_ENTRIES )
40634079 {
4064- NUMCacheEntry * old = NUMCache + 0 ;
4080+ NUMCacheEntry * old = NUMCache [ 0 ] ;
40654081
40664082#ifdef DEBUG_TO_FROM_CHAR
40674083 elog (DEBUG_elog_output , "Cache is full (%d)" , n_NUMCache );
40684084#endif
40694085 if (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 ];
40734090 if (!ent -> valid )
40744091 {
40754092 old = ent ;
@@ -4093,7 +4110,9 @@ NUM_cache_getnew(const char *str)
40934110#ifdef DEBUG_TO_FROM_CHAR
40944111 elog (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 ));
40974116 ent -> valid = false;
40984117 StrNCpy (ent -> str , str , NUM_CACHE_SIZE + 1 );
40994118 ent -> 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 */
41144130 if (NUMCounter >= (INT_MAX - NUM_CACHE_ENTRIES ))
41154131 {
41164132 NUMCounter = 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+
41244142 if (ent -> valid && strcmp (ent -> str , str ) == 0 )
41254143 {
41264144 ent -> age = (++ NUMCounter );
0 commit comments