These changes should generally improve correctness/maintainability.
A nice side benefit is that several kilobytes move from initialized
data to text segment, allowing them to be shared across processes and
probably reducing copy-on-write overhead while forking a new backend.
Unfortunately this doesn't seem to help libpq in the same way (at least
not when it's compiled with -fpic on x86_64), but we can hope the linker
at least collects all nominally-const data together even if it's not
actually part of the text segment.
Also, make pg_encname_tbl[] static in encnames.c, since there seems
no very good reason for any other code to use it; per a suggestion
from Wim Lewis, who independently submitted a patch that was mostly
a subset of this one.
Oskari Saarenmaa, with some editorialization by me
* class? */
} ObjectPropertyType;
-static ObjectPropertyType ObjectProperty[] =
+static const ObjectPropertyType ObjectProperty[] =
{
{
CastRelationId,
List *objname, bool missing_ok);
static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname,
List *objargs, bool missing_ok);
-static ObjectPropertyType *get_object_property_data(Oid class_id);
+static const ObjectPropertyType *get_object_property_data(Oid class_id);
static void getRelationDescription(StringInfo buffer, Oid relid);
static void getOpFamilyDescription(StringInfo buffer, Oid opfid);
HeapTuple tuple;
bool isnull;
Oid oid;
- ObjectPropertyType *property;
+ const ObjectPropertyType *property;
/* If not owned by a namespace, just return InvalidOid. */
property = get_object_property_data(address->classId);
Oid
get_object_oid_index(Oid class_id)
{
- ObjectPropertyType *prop = get_object_property_data(class_id);
+ const ObjectPropertyType *prop = get_object_property_data(class_id);
return prop->oid_index_oid;
}
int
get_object_catcache_oid(Oid class_id)
{
- ObjectPropertyType *prop = get_object_property_data(class_id);
+ const ObjectPropertyType *prop = get_object_property_data(class_id);
return prop->oid_catcache_id;
}
int
get_object_catcache_name(Oid class_id)
{
- ObjectPropertyType *prop = get_object_property_data(class_id);
+ const ObjectPropertyType *prop = get_object_property_data(class_id);
return prop->name_catcache_id;
}
AttrNumber
get_object_attnum_name(Oid class_id)
{
- ObjectPropertyType *prop = get_object_property_data(class_id);
+ const ObjectPropertyType *prop = get_object_property_data(class_id);
return prop->attnum_name;
}
AttrNumber
get_object_attnum_namespace(Oid class_id)
{
- ObjectPropertyType *prop = get_object_property_data(class_id);
+ const ObjectPropertyType *prop = get_object_property_data(class_id);
return prop->attnum_namespace;
}
AttrNumber
get_object_attnum_owner(Oid class_id)
{
- ObjectPropertyType *prop = get_object_property_data(class_id);
+ const ObjectPropertyType *prop = get_object_property_data(class_id);
return prop->attnum_owner;
}
AttrNumber
get_object_attnum_acl(Oid class_id)
{
- ObjectPropertyType *prop = get_object_property_data(class_id);
+ const ObjectPropertyType *prop = get_object_property_data(class_id);
return prop->attnum_acl;
}
AclObjectKind
get_object_aclkind(Oid class_id)
{
- ObjectPropertyType *prop = get_object_property_data(class_id);
+ const ObjectPropertyType *prop = get_object_property_data(class_id);
return prop->acl_kind;
}
bool
get_object_namensp_unique(Oid class_id)
{
- ObjectPropertyType *prop = get_object_property_data(class_id);
+ const ObjectPropertyType *prop = get_object_property_data(class_id);
return prop->is_nsp_name_unique;
}
/*
* Find ObjectProperty structure by class_id.
*/
-static ObjectPropertyType *
+static const ObjectPropertyType *
get_object_property_data(Oid class_id)
{
- static ObjectPropertyType *prop_last = NULL;
+ static const ObjectPropertyType *prop_last = NULL;
int index;
/*
const char *from_encoding_name = stmt->for_encoding_name;
const char *to_encoding_name = stmt->to_encoding_name;
List *func_name = stmt->func_name;
- static Oid funcargs[] = {INT4OID, INT4OID, CSTRINGOID, INTERNALOID, INT4OID};
+ static const Oid funcargs[] = {INT4OID, INT4OID, CSTRINGOID, INTERNALOID, INT4OID};
char result[1];
/* Convert list of names to a name and namespace */
lexescape(struct vars * v)
{
chr c;
- static chr alert[] = {
+ static const chr alert[] = {
CHR('a'), CHR('l'), CHR('e'), CHR('r'), CHR('t')
};
- static chr esc[] = {
+ static const chr esc[] = {
CHR('E'), CHR('S'), CHR('C')
};
const chr *save;
/* static function list */
-static struct fns functions = {
+static const struct fns functions = {
rfree, /* regfree insides */
};
#include "regex/regguts.h"
/* unknown-error explanation */
-static char unk[] = "*** unknown regex error code 0x%x ***";
+static const char unk[] = "*** unknown regex error code 0x%x ***";
/* struct to map among codes, code names, and explanations */
-static struct rerr
+static const struct rerr
{
int code;
const char *name;
char *errbuf, /* result buffer (unless errbuf_size==0) */
size_t errbuf_size) /* available space in errbuf, can be 0 */
{
- struct rerr *r;
+ const struct rerr *r;
const char *msg;
char convbuf[sizeof(unk) + 50]; /* 50 = plenty for int */
size_t len;
*/
if (GetDatabaseEncoding() == PG_UTF8 && prs->usewide)
{
- static pg_wchar strange_letter[] = {
+ static const pg_wchar strange_letter[] = {
/*
* use binary search, so elements should be ordered
*/
0xAA34, /* CHAM CONSONANT SIGN RA */
0xAA4D /* CHAM CONSONANT SIGN FINAL H */
};
- pg_wchar *StopLow = strange_letter,
+ const pg_wchar *StopLow = strange_letter,
*StopHigh = strange_letter + lengthof(strange_letter),
*StopMiddle;
pg_wchar c;
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}
};
-char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+const char *const months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL};
-char *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
+const char *const days[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday", NULL};
static int szdatetktbl = sizeof datetktbl / sizeof datetktbl[0];
-static datetkn deltatktbl[] = {
+static const datetkn deltatktbl[] = {
/* text, token, lexval */
{"@", IGNORE_DTF, 0}, /* postgres relative prefix */
{DAGO, AGO, 0}, /* "ago" indicates negative time offset */
#define MAXDOUBLEWIDTH 500
-/* ----------
- * External (defined in PgSQL datetime.c (timestamp utils))
- * ----------
- */
-extern char *months[], /* month abbreviation */
- *days[]; /* full days */
-
/* ----------
* Format parser structs
* ----------
* Full months
* ----------
*/
-static char *months_full[] = {
+static const char *const months_full[] = {
"January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December", NULL
};
-static char *days_short[] = {
+static const char *const days_short[] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL
};
* matches for BC have an odd index. So the boolean value for BC is given by
* taking the array index of the match, modulo 2.
*/
-static char *adbc_strings[] = {ad_STR, bc_STR, AD_STR, BC_STR, NULL};
-static char *adbc_strings_long[] = {a_d_STR, b_c_STR, A_D_STR, B_C_STR, NULL};
+static const char *const adbc_strings[] = {ad_STR, bc_STR, AD_STR, BC_STR, NULL};
+static const char *const adbc_strings_long[] = {a_d_STR, b_c_STR, A_D_STR, B_C_STR, NULL};
/* ----------
* AM / PM
* matches for PM have an odd index. So the boolean value for PM is given by
* taking the array index of the match, modulo 2.
*/
-static char *ampm_strings[] = {am_STR, pm_STR, AM_STR, PM_STR, NULL};
-static char *ampm_strings_long[] = {a_m_STR, p_m_STR, A_M_STR, P_M_STR, NULL};
+static const char *const ampm_strings[] = {am_STR, pm_STR, AM_STR, PM_STR, NULL};
+static const char *const ampm_strings_long[] = {a_m_STR, p_m_STR, A_M_STR, P_M_STR, NULL};
/* ----------
* Months in roman-numeral
* 'VIII' must have higher precedence than 'V')
* ----------
*/
-static char *rm_months_upper[] =
+static const char *const rm_months_upper[] =
{"XII", "XI", "X", "IX", "VIII", "VII", "VI", "V", "IV", "III", "II", "I", NULL};
-static char *rm_months_lower[] =
+static const char *const rm_months_lower[] =
{"xii", "xi", "x", "ix", "viii", "vii", "vi", "v", "iv", "iii", "ii", "i", NULL};
/* ----------
* Roman numbers
* ----------
*/
-static char *rm1[] = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", NULL};
-static char *rm10[] = {"X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC", NULL};
-static char *rm100[] = {"C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", NULL};
+static const char *const rm1[] = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", NULL};
+static const char *const rm10[] = {"X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC", NULL};
+static const char *const rm100[] = {"C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", NULL};
/* ----------
* Ordinal postfixes
* ----------
*/
-static char *numTH[] = {"ST", "ND", "RD", "TH", NULL};
-static char *numth[] = {"st", "nd", "rd", "th", NULL};
+static const char *const numTH[] = {"ST", "ND", "RD", "TH", NULL};
+static const char *const numth[] = {"st", "nd", "rd", "th", NULL};
/* ----------
* Flags & Options:
* Suffixes definition for DATE-TIME TO/FROM CHAR
* ----------
*/
-static KeySuffix DCH_suff[] = {
+static const KeySuffix DCH_suff[] = {
{"FM", 2, DCH_S_FM, SUFFTYPE_PREFIX},
{"fm", 2, DCH_S_FM, SUFFTYPE_PREFIX},
{"TM", 2, DCH_S_TM, SUFFTYPE_PREFIX},
*/
static const KeyWord *index_seq_search(char *str, const KeyWord *kw,
const int *index);
-static KeySuffix *suff_search(char *str, KeySuffix *suf, int type);
+static const KeySuffix *suff_search(char *str, const KeySuffix *suf, int type);
static void NUMDesc_prepare(NUMDesc *num, FormatNode *n);
static void parse_format(FormatNode *node, char *str, const KeyWord *kw,
- KeySuffix *suf, const int *index, int ver, NUMDesc *Num);
+ const KeySuffix *suf, const int *index, int ver, NUMDesc *Num);
static void DCH_to_char(FormatNode *node, bool is_interval,
TmToChar *in, char *out, Oid collid);
static void dump_node(FormatNode *node, int max);
#endif
-static char *get_th(char *num, int type);
+static const char *get_th(char *num, int type);
static char *str_numth(char *dest, char *num, int type);
static int adjust_partial_year_to_2020(int year);
static int strspace_len(char *str);
static void from_char_set_int(int *dest, const int value, const FormatNode *node);
static int from_char_parse_int_len(int *dest, char **src, const int len, FormatNode *node);
static int from_char_parse_int(int *dest, char **src, FormatNode *node);
-static int seq_search(char *name, char **array, int type, int max, int *len);
-static int from_char_seq_search(int *dest, char **src, char **array, int type, int max, FormatNode *node);
+static int seq_search(char *name, const char *const * array, int type, int max, int *len);
+static int from_char_seq_search(int *dest, char **src, const char *const * array, int type, int max, FormatNode *node);
static void do_to_timestamp(text *date_txt, text *fmt,
struct pg_tm * tm, fsec_t *fsec);
static char *fill_str(char *str, int c, int max);
return NULL;
}
-static KeySuffix *
-suff_search(char *str, KeySuffix *suf, int type)
+static const KeySuffix *
+suff_search(char *str, const KeySuffix *suf, int type)
{
- KeySuffix *s;
+ const KeySuffix *s;
for (s = suf; s->name != NULL; s++)
{
*/
static void
parse_format(FormatNode *node, char *str, const KeyWord *kw,
- KeySuffix *suf, const int *index, int ver, NUMDesc *Num)
+ const KeySuffix *suf, const int *index, int ver, NUMDesc *Num)
{
- KeySuffix *s;
+ const KeySuffix *s;
FormatNode *n;
int node_set = 0,
suffix,
* type --> 0 upper, 1 lower
* ----------
*/
-static char *
+static const char *
get_th(char *num, int type)
{
int len = strlen(num),
* ----------
*/
static int
-seq_search(char *name, char **array, int type, int max, int *len)
+seq_search(char *name, const char *const * array, int type, int max, int *len)
{
- char *p,
- *n,
- **a;
+ const char *p;
+ const char *const * a;
+ char *n;
int last,
i;
* If the string doesn't match, throw an error.
*/
static int
-from_char_seq_search(int *dest, char **src, char **array, int type, int max,
+from_char_seq_search(int *dest, char **src, const char *const * array, int type, int max,
FormatNode *node)
{
int len;
#include "miscadmin.h"
-static float weights[] = {0.1f, 0.2f, 0.4f, 1.0f};
+static const float weights[] = {0.1f, 0.2f, 0.4f, 1.0f};
#define wpos(wep) ( w[ WEP_GETWEIGHT(wep) ] )
#define RANK_NORM_RDIVRPLUS1 0x20
#define DEF_NORM_METHOD RANK_NO_NORM
-static float calc_rank_or(float *w, TSVector t, TSQuery q);
-static float calc_rank_and(float *w, TSVector t, TSQuery q);
+static float calc_rank_or(const float *w, TSVector t, TSQuery q);
+static float calc_rank_and(const float *w, TSVector t, TSQuery q);
/*
* Returns a weight of a word collocation
};
static float
-calc_rank_and(float *w, TSVector t, TSQuery q)
+calc_rank_and(const float *w, TSVector t, TSQuery q)
{
WordEntryPosVector **pos;
int i,
}
static float
-calc_rank_or(float *w, TSVector t, TSQuery q)
+calc_rank_or(const float *w, TSVector t, TSQuery q)
{
WordEntry *entry,
*firstentry;
}
static float
-calc_rank(float *w, TSVector t, TSQuery q, int32 method)
+calc_rank(const float *w, TSVector t, TSQuery q, int32 method)
{
QueryItem *item = GETQUERY(q);
float res = 0.0;
return res;
}
-static float *
+static const float *
getWeights(ArrayType *win)
{
static float ws[lengthof(weights)];
}
static float4
-calc_rank_cd(float4 *arrdata, TSVector txt, TSQuery query, int method)
+calc_rank_cd(const float4 *arrdata, TSVector txt, TSQuery query, int method)
{
DocRepresentation *doc;
int len,
* Karel Zak, Aug 2001
* ----------
*/
-pg_encname pg_encname_tbl[] =
+typedef struct pg_encname
+{
+ const char *name;
+ pg_enc encoding;
+} pg_encname;
+
+static const pg_encname pg_encname_tbl[] =
{
{
"abc", PG_WIN1258
}, /* alias for UHC */
{
"windows950", PG_BIG5
- }, /* alias for BIG5 */
- {
- NULL, 0
- } /* last */
+ } /* alias for BIG5 */
};
-unsigned int pg_encname_tbl_sz = \
-sizeof(pg_encname_tbl) / sizeof(pg_encname_tbl[0]) - 1;
-
/* ----------
* These are "official" encoding names.
* XXX must be sorted by the same order as enum pg_enc (in mb/pg_wchar.h)
#else
#define DEF_ENC2NAME(name, codepage) { #name, PG_##name, codepage }
#endif
-pg_enc2name pg_enc2name_tbl[] =
+const pg_enc2name pg_enc2name_tbl[] =
{
DEF_ENC2NAME(SQL_ASCII, 0),
DEF_ENC2NAME(EUC_JP, 20932),
* This covers all encodings except MULE_INTERNAL, which is alien to gettext.
* ----------
*/
-pg_enc2gettext pg_enc2gettext_tbl[] =
+const pg_enc2gettext pg_enc2gettext_tbl[] =
{
{PG_SQL_ASCII, "US-ASCII"},
{PG_UTF8, "UTF-8"},
/* ----------
* Search encoding by encoding name
+ *
+ * Returns encoding ID, or -1 for error
* ----------
*/
-pg_encname *
-pg_char_to_encname_struct(const char *name)
+int
+pg_char_to_encoding(const char *name)
{
- unsigned int nel = pg_encname_tbl_sz;
- pg_encname *base = pg_encname_tbl,
+ unsigned int nel = lengthof(pg_encname_tbl);
+ const pg_encname *base = pg_encname_tbl,
*last = base + nel - 1,
*position;
int result;
*key;
if (name == NULL || *name == '\0')
- return NULL;
+ return -1;
if (strlen(name) >= NAMEDATALEN)
{
#ifdef FRONTEND
fprintf(stderr, "encoding name too long\n");
- return NULL;
+ return -1;
#else
ereport(ERROR,
(errcode(ERRCODE_NAME_TOO_LONG),
{
result = strcmp(key, position->name);
if (result == 0)
- return position;
+ return position->encoding;
}
if (result < 0)
last = position - 1;
else
base = position + 1;
}
- return NULL;
-}
-
-/*
- * Returns encoding or -1 for error
- */
-int
-pg_char_to_encoding(const char *name)
-{
- pg_encname *p;
-
- if (!name)
- return -1;
-
- p = pg_char_to_encname_struct(name);
- return p ? p->encoding : -1;
+ return -1;
}
#ifndef FRONTEND
{
if (PG_VALID_ENCODING(encoding))
{
- pg_enc2name *p = &pg_enc2name_tbl[encoding];
+ const pg_enc2name *p = &pg_enc2name_tbl[encoding];
Assert(encoding == p->encoding);
return p->name;
/*
* These variables track the currently-selected encodings.
*/
-static pg_enc2name *ClientEncoding = &pg_enc2name_tbl[PG_SQL_ASCII];
-static pg_enc2name *DatabaseEncoding = &pg_enc2name_tbl[PG_SQL_ASCII];
-static pg_enc2name *MessageEncoding = &pg_enc2name_tbl[PG_SQL_ASCII];
+static const pg_enc2name *ClientEncoding = &pg_enc2name_tbl[PG_SQL_ASCII];
+static const pg_enc2name *DatabaseEncoding = &pg_enc2name_tbl[PG_SQL_ASCII];
+static const pg_enc2name *MessageEncoding = &pg_enc2name_tbl[PG_SQL_ASCII];
/*
* During backend startup we can't set client encoding because we (a)
* XXX must be sorted by the same order as enum pg_enc (in mb/pg_wchar.h)
*-------------------------------------------------------------------
*/
-pg_wchar_tbl pg_wchar_table[] = {
+const pg_wchar_tbl pg_wchar_table[] = {
{pg_ascii2wchar_with_len, pg_wchar2single_with_len, pg_ascii_mblen, pg_ascii_dsplen, pg_ascii_verifier, 1}, /* PG_SQL_ASCII */
{pg_eucjp2wchar_with_len, pg_wchar2euc_with_len, pg_eucjp_mblen, pg_eucjp_dsplen, pg_eucjp_verifier, 3}, /* PG_EUC_JP */
{pg_euccn2wchar_with_len, pg_wchar2euc_with_len, pg_euccn_mblen, pg_euccn_dsplen, pg_euccn_verifier, 2}, /* PG_EUC_CN */
* documentation for pg_relation_size(). Also keep FORKNAMECHARS above
* up-to-date.
*/
-const char *forkNames[] = {
+const char *const forkNames[] = {
"main", /* MAIN_FORKNUM */
"fsm", /* FSM_FORKNUM */
"vm", /* VISIBILITYMAP_FORKNUM */
#define TABLESPACE_VERSION_DIRECTORY "PG_" PG_MAJORVERSION "_" \
CppAsString2(CATALOG_VERSION_NO)
-extern const char *forkNames[];
+extern const char *const forkNames[];
+
extern int forkname_chars(const char *str, ForkNumber *fork);
extern char *relpathbackend(RelFileNode rnode, BackendId backend,
ForkNumber forknum);
#define PG_VALID_FE_ENCODING(_enc) PG_VALID_ENCODING(_enc)
/*
- * Encoding names with all aliases
- */
-typedef struct pg_encname
-{
- char *name;
- pg_enc encoding;
-} pg_encname;
-
-extern pg_encname pg_encname_tbl[];
-extern unsigned int pg_encname_tbl_sz;
-
-/*
- * Careful:
+ * Table for mapping an encoding number to official encoding name and
+ * possibly other subsidiary data. Be careful to check encoding number
+ * before accessing a table entry!
*
* if (PG_VALID_ENCODING(encoding))
* pg_enc2name_tbl[ encoding ];
*/
typedef struct pg_enc2name
{
- char *name;
+ const char *name;
pg_enc encoding;
#ifdef WIN32
unsigned codepage; /* codepage for WIN32 */
#endif
} pg_enc2name;
-extern pg_enc2name pg_enc2name_tbl[];
+extern const pg_enc2name pg_enc2name_tbl[];
/*
* Encoding names for gettext
const char *name;
} pg_enc2gettext;
-extern pg_enc2gettext pg_enc2gettext_tbl[];
+extern const pg_enc2gettext pg_enc2gettext_tbl[];
/*
* pg_wchar stuff
int maxmblen; /* max bytes for a char in this encoding */
} pg_wchar_tbl;
-extern pg_wchar_tbl pg_wchar_table[];
+extern const pg_wchar_tbl pg_wchar_table[];
/*
* UTF-8 to local code conversion map
* Remaining functions are not considered part of libpq's API, though many
* of them do exist inside libpq.
*/
-extern pg_encname *pg_char_to_encname_struct(const char *name);
-
extern int pg_mb2wchar(const char *from, pg_wchar *to);
extern int pg_mb2wchar_with_len(const char *from, pg_wchar *to, int len);
extern int pg_encoding_mb2wchar_with_len(int encoding,
* Include check for leap year.
*/
+extern const char *const months[]; /* months (3-char abbreviations) */
+extern const char *const days[]; /* days (full names) */
extern const int day_tab[2][13];
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))