/* * equivalent_locale() * * Best effort locale-name comparison. Return false if we are not 100% sure * the locales are equivalent. * * Note: The encoding parts of the names are ignored. This function is * currently used to compare locale names stored in pg_database, and * pg_database contains a separate encoding field. That's compared directly * in check_locale_and_encoding(). */ static bool equivalent_locale(int category, const char *loca, const char *locb) { const char *chara; const char *charb; char *canona; char *canonb; int lena; int lenb; /* * If the names are equal, the locales are equivalent. Checking this * first avoids calling setlocale() in the common case that the names * are equal. That's a good thing, if setlocale() is buggy, for example. */ if (pg_strcasecmp(loca, locb) == 0) return true; /* * Not identical. Canonicalize both names, remove the encoding parts, * and try again. */ canona = get_canonical_locale_name(category, loca); chara = strrchr(canona, '.'); lena = chara ? (chara - canona) : strlen(canona); canonb = get_canonical_locale_name(category, locb); charb = strrchr(canonb, '.'); lenb = charb ? (charb - canonb) : strlen(canonb); if (lena == lenb && pg_strncasecmp(canona, canonb, lena) == 0) return true; return false; }
/* * set_locale_and_encoding() * * query the database to get the template0 locale */ static void set_locale_and_encoding(ClusterInfo *cluster) { ControlData *ctrl = &cluster->controldata; PGconn *conn; PGresult *res; int i_encoding; int cluster_version = cluster->major_version; conn = connectToServer(cluster, "template1"); /* for pg < 80400, we got the values from pg_controldata */ if (cluster_version >= 80400) { int i_datcollate; int i_datctype; res = executeQueryOrDie(conn, "SELECT datcollate, datctype " "FROM pg_catalog.pg_database " "WHERE datname = 'template0' "); assert(PQntuples(res) == 1); i_datcollate = PQfnumber(res, "datcollate"); i_datctype = PQfnumber(res, "datctype"); if (GET_MAJOR_VERSION(cluster->major_version) < 902) { /* * Pre-9.2 did not canonicalize the supplied locale names to match * what the system returns, while 9.2+ does, so convert pre-9.2 to * match. */ ctrl->lc_collate = get_canonical_locale_name(LC_COLLATE, pg_strdup(PQgetvalue(res, 0, i_datcollate))); ctrl->lc_ctype = get_canonical_locale_name(LC_CTYPE, pg_strdup(PQgetvalue(res, 0, i_datctype))); } else { ctrl->lc_collate = pg_strdup(PQgetvalue(res, 0, i_datcollate)); ctrl->lc_ctype = pg_strdup(PQgetvalue(res, 0, i_datctype)); } PQclear(res); } res = executeQueryOrDie(conn, "SELECT pg_catalog.pg_encoding_to_char(encoding) " "FROM pg_catalog.pg_database " "WHERE datname = 'template0' "); assert(PQntuples(res) == 1); i_encoding = PQfnumber(res, "pg_encoding_to_char"); ctrl->encoding = pg_strdup(PQgetvalue(res, 0, i_encoding)); PQclear(res); PQfinish(conn); }