Refrain from canonicalizing a client_encoding setting of "UNICODE".
authorTom Lane
Tue, 19 Apr 2011 16:17:13 +0000 (12:17 -0400)
committerTom Lane
Tue, 19 Apr 2011 16:25:13 +0000 (12:25 -0400)
While "UTF8" is the correct name for this encoding, existing JDBC drivers
expect that if they send "UNICODE" it will read back the same way; they
fail with an opaque "Protocol error" complaint if not.  This will be fixed
in the 9.1 drivers, but until older drivers are no longer in use in the
wild, we'd better leave "UNICODE" alone.  Continue to canonicalize all
other inputs.  Per report from Steve Singer and subsequent discussion.

src/backend/commands/variable.c

index 5d0fbdfb40fa79a01304ef72a632c2c47f0bab7d..9efd20f2bcfd29e3006df8582d0a214087dec601 100644 (file)
@@ -759,12 +759,16 @@ bool
 check_client_encoding(char **newval, void **extra, GucSource source)
 {
    int         encoding;
+   const char *canonical_name;
 
    /* Look up the encoding by name */
    encoding = pg_valid_client_encoding(*newval);
    if (encoding < 0)
        return false;
 
+   /* Get the canonical name (no aliases, uniform case) */
+   canonical_name = pg_encoding_to_char(encoding);
+
    /*
     * If we are not within a transaction then PrepareClientEncoding will not
     * be able to look up the necessary conversion procs.  If we are still
@@ -786,7 +790,7 @@ check_client_encoding(char **newval, void **extra, GucSource source)
            /* Must be a genuine no-such-conversion problem */
            GUC_check_errcode(ERRCODE_FEATURE_NOT_SUPPORTED);
            GUC_check_errdetail("Conversion between %s and %s is not supported.",
-                               pg_encoding_to_char(encoding),
+                               canonical_name,
                                GetDatabaseEncodingName());
        }
        else
@@ -798,13 +802,27 @@ check_client_encoding(char **newval, void **extra, GucSource source)
    }
 
    /*
-    * Return the encoding's canonical name, and save its ID in *extra.
+    * Replace the user-supplied string with the encoding's canonical name.
+    * This gets rid of aliases and case-folding variations.
+    *
+    * XXX Although canonicalizing seems like a good idea in the abstract, it
+    * breaks pre-9.1 JDBC drivers, which expect that if they send "UNICODE"
+    * as the client_encoding setting then it will read back the same way.
+    * As a workaround, don't replace the string if it's "UNICODE".  Remove
+    * that hack when pre-9.1 JDBC drivers are no longer in use.
     */
-   free(*newval);
-   *newval = strdup(pg_encoding_to_char(encoding));
-   if (!*newval)
-       return false;
+   if (strcmp(*newval, canonical_name) != 0 &&
+       strcmp(*newval, "UNICODE") != 0)
+   {
+       free(*newval);
+       *newval = strdup(canonical_name);
+       if (!*newval)
+           return false;
+   }
 
+   /*
+    * Save the encoding's ID in *extra, for use by assign_client_encoding.
+    */
    *extra = malloc(sizeof(int));
    if (!*extra)
        return false;