aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/dbcommands.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/dbcommands.c')
-rw-r--r--src/backend/commands/dbcommands.c116
1 files changed, 60 insertions, 56 deletions
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index c7e0c6a8778..87d9e545b4f 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -129,8 +129,6 @@ createdb(const CreatedbStmt *stmt)
char *dbctype = NULL;
int encoding = -1;
int dbconnlimit = -1;
- int ctype_encoding;
- int collate_encoding;
int notherbackends;
int npreparedxacts;
createdb_failure_params fparms;
@@ -334,60 +332,7 @@ createdb(const CreatedbStmt *stmt)
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("invalid locale name %s", dbctype)));
- /*
- * Check whether chosen encoding matches chosen locale settings. This
- * restriction is necessary because libc's locale-specific code usually
- * fails when presented with data in an encoding it's not expecting. We
- * allow mismatch in four cases:
- *
- * 1. locale encoding = SQL_ASCII, which means that the locale is C/POSIX
- * which works with any encoding.
- *
- * 2. locale encoding = -1, which means that we couldn't determine the
- * locale's encoding and have to trust the user to get it right.
- *
- * 3. selected encoding is UTF8 and platform is win32. This is because
- * UTF8 is a pseudo codepage that is supported in all locales since it's
- * converted to UTF16 before being used.
- *
- * 4. selected encoding is SQL_ASCII, but only if you're a superuser. This
- * is risky but we have historically allowed it --- notably, the
- * regression tests require it.
- *
- * Note: if you change this policy, fix initdb to match.
- */
- ctype_encoding = pg_get_encoding_from_locale(dbctype, true);
- collate_encoding = pg_get_encoding_from_locale(dbcollate, true);
-
- if (!(ctype_encoding == encoding ||
- ctype_encoding == PG_SQL_ASCII ||
- ctype_encoding == -1 ||
-#ifdef WIN32
- encoding == PG_UTF8 ||
-#endif
- (encoding == PG_SQL_ASCII && superuser())))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("encoding %s does not match locale %s",
- pg_encoding_to_char(encoding),
- dbctype),
- errdetail("The chosen LC_CTYPE setting requires encoding %s.",
- pg_encoding_to_char(ctype_encoding))));
-
- if (!(collate_encoding == encoding ||
- collate_encoding == PG_SQL_ASCII ||
- collate_encoding == -1 ||
-#ifdef WIN32
- encoding == PG_UTF8 ||
-#endif
- (encoding == PG_SQL_ASCII && superuser())))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("encoding %s does not match locale %s",
- pg_encoding_to_char(encoding),
- dbcollate),
- errdetail("The chosen LC_COLLATE setting requires encoding %s.",
- pg_encoding_to_char(collate_encoding))));
+ check_encoding_locale_matches(encoding, dbcollate, dbctype);
/*
* Check that the new encoding and locale settings match the source
@@ -710,6 +655,65 @@ createdb(const CreatedbStmt *stmt)
PointerGetDatum(&fparms));
}
+/*
+ * Check whether chosen encoding matches chosen locale settings. This
+ * restriction is necessary because libc's locale-specific code usually
+ * fails when presented with data in an encoding it's not expecting. We
+ * allow mismatch in four cases:
+ *
+ * 1. locale encoding = SQL_ASCII, which means that the locale is C/POSIX
+ * which works with any encoding.
+ *
+ * 2. locale encoding = -1, which means that we couldn't determine the
+ * locale's encoding and have to trust the user to get it right.
+ *
+ * 3. selected encoding is UTF8 and platform is win32. This is because
+ * UTF8 is a pseudo codepage that is supported in all locales since it's
+ * converted to UTF16 before being used.
+ *
+ * 4. selected encoding is SQL_ASCII, but only if you're a superuser. This
+ * is risky but we have historically allowed it --- notably, the
+ * regression tests require it.
+ *
+ * Note: if you change this policy, fix initdb to match.
+ */
+void
+check_encoding_locale_matches(int encoding, const char *collate, const char *ctype)
+{
+ int ctype_encoding = pg_get_encoding_from_locale(ctype, true);
+ int collate_encoding = pg_get_encoding_from_locale(collate, true);
+
+ if (!(ctype_encoding == encoding ||
+ ctype_encoding == PG_SQL_ASCII ||
+ ctype_encoding == -1 ||
+#ifdef WIN32
+ encoding == PG_UTF8 ||
+#endif
+ (encoding == PG_SQL_ASCII && superuser())))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("encoding %s does not match locale %s",
+ pg_encoding_to_char(encoding),
+ ctype),
+ errdetail("The chosen LC_CTYPE setting requires encoding %s.",
+ pg_encoding_to_char(ctype_encoding))));
+
+ if (!(collate_encoding == encoding ||
+ collate_encoding == PG_SQL_ASCII ||
+ collate_encoding == -1 ||
+#ifdef WIN32
+ encoding == PG_UTF8 ||
+#endif
+ (encoding == PG_SQL_ASCII && superuser())))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("encoding %s does not match locale %s",
+ pg_encoding_to_char(encoding),
+ collate),
+ errdetail("The chosen LC_COLLATE setting requires encoding %s.",
+ pg_encoding_to_char(collate_encoding))));
+}
+
/* Error cleanup callback for createdb */
static void
createdb_failure_callback(int code, Datum arg)