public void configurePostHandshake()

in src/main/core-impl/java/com/mysql/cj/NativeCharsetSettings.java [255:429]


    public void configurePostHandshake(boolean dontCheckServerMatch) {
        buildCollationMapping();

        /*
         * Configuring characterEncoding.
         */

        String requiredCollation = this.connectionCollation.getStringValue();
        String requiredEncoding = this.characterEncoding.getValue();
        String passwordEncoding = this.passwordCharacterEncoding.getValue();
        Integer requiredCollationIndex;
        String sessionCharsetName = getServerDefaultCharset();
        String sessionCollationClause = "";

        try {
            // connectionCollation overrides the characterEncoding value
            if (requiredCollation != null && (requiredCollationIndex = getCollationIndexForCollationName(requiredCollation)) != null) {
                if (isImpermissibleCollation(requiredCollationIndex)) {
                    if (this.serverSession.getCapabilities().getServerVersion().meetsMinimum(new ServerVersion(8, 0, 1))) {
                        requiredCollationIndex = MYSQL_COLLATION_INDEX_utf8mb4_0900_ai_ci;
                        requiredCollation = "utf8mb4_0900_ai_ci";
                    } else {
                        requiredCollationIndex = MYSQL_COLLATION_INDEX_utf8mb4_general_ci;
                        requiredCollation = "utf8mb4_general_ci";
                    }
                }
                sessionCollationClause = " COLLATE " + requiredCollation;
                sessionCharsetName = getMysqlCharsetNameForCollationIndex(requiredCollationIndex);
                requiredEncoding = getJavaEncodingForCollationIndex(requiredCollationIndex, requiredEncoding);
                this.sessionCollationIndex = requiredCollationIndex;
            }

            if (requiredEncoding != null) { // If either connectionCollation or characterEncoding is defined.
                if (sessionCollationClause.length() == 0) {  // If no connectionCollation is defined.
                    sessionCharsetName = getMysqlCharsetForJavaEncoding(requiredEncoding.toUpperCase(Locale.ENGLISH), this.serverSession.getServerVersion());
                }

            } else { // Neither connectionCollation nor characterEncoding are defined.
                // Collations with index > 255 don't fit into server greeting packet.
                // Now we can set sessionCollationIndex according to "collation_server" value.
                if (!StringUtils.isNullOrEmpty(passwordEncoding)) {
                    if (this.serverSession.getCapabilities().getServerVersion().meetsMinimum(new ServerVersion(8, 0, 1))) {
                        this.sessionCollationIndex = MYSQL_COLLATION_INDEX_utf8mb4_0900_ai_ci; // We can't do more, just trying to use utf8mb4_0900_ai_ci because the most of collations in that range are utf8mb4.
                        requiredCollation = "utf8mb4_0900_ai_ci";
                    } else {
                        this.sessionCollationIndex = MYSQL_COLLATION_INDEX_utf8mb4_general_ci;
                        requiredCollation = "utf8mb4_general_ci";
                    }
                    sessionCollationClause = " COLLATE " + getCollationNameForCollationIndex(this.sessionCollationIndex);
                }

                if ((requiredEncoding = getJavaEncodingForCollationIndex(this.sessionCollationIndex, requiredEncoding)) == null) {
                    // if there is no mapping for default collation index leave characterEncoding as specified by user
                    throw ExceptionFactory.createException(Messages.getString("Connection.5", new Object[] { this.sessionCollationIndex.toString() }),
                            this.session.getExceptionInterceptor());
                }

                sessionCharsetName = getMysqlCharsetNameForCollationIndex(this.sessionCollationIndex);
            }

        } catch (ArrayIndexOutOfBoundsException outOfBoundsEx) {
            throw ExceptionFactory.createException(Messages.getString("Connection.6", new Object[] { this.sessionCollationIndex }),
                    this.session.getExceptionInterceptor());
        }

        this.characterEncoding.setValue(requiredEncoding);

        if (sessionCharsetName != null) {
            boolean isCharsetDifferent = !characterSetNamesMatches(sessionCharsetName);
            boolean isCollationDifferent = sessionCollationClause.length() > 0
                    && !requiredCollation.equalsIgnoreCase(this.serverSession.getServerVariable(COLLATION_CONNECTION));
            if (dontCheckServerMatch || isCharsetDifferent || isCollationDifferent) {
                String sql = "SET NAMES " + sessionCharsetName + sessionCollationClause;
                telemetryWrapSendCommand(() -> this.session.getProtocol().sendCommand(getCommandBuilder().buildComQuery(null, this.session, sql), false, 0),
                        TelemetrySpanName.SET_CHARSET);
                this.serverSession.getServerVariables().put(CHARACTER_SET_CLIENT, sessionCharsetName);
                this.serverSession.getServerVariables().put(CHARACTER_SET_CONNECTION, sessionCharsetName);

                if (sessionCollationClause.length() > 0) {
                    this.serverSession.getServerVariables().put(COLLATION_CONNECTION, requiredCollation);
                } else {
                    int idx = getCollationIndexForMysqlCharsetName(sessionCharsetName);
                    if (idx == MYSQL_COLLATION_INDEX_utf8mb4_0900_ai_ci
                            && !this.serverSession.getCapabilities().getServerVersion().meetsMinimum(new ServerVersion(8, 0, 1))) {
                        idx = MYSQL_COLLATION_INDEX_utf8mb4_general_ci;
                    }
                    this.serverSession.getServerVariables().put(COLLATION_CONNECTION, getCollationNameForCollationIndex(idx));
                }
            }
        }

        /*
         * Configuring characterSetResults.
         *
         * We know how to deal with any charset coming back from the database, so tell the server not to do conversion
         * if the user hasn't 'forced' a result-set character set.
         */

        String sessionResultsCharset = this.serverSession.getServerVariable(CHARACTER_SET_RESULTS);
        String characterSetResultsValue = this.characterSetResults.getValue();
        if (StringUtils.isNullOrEmpty(characterSetResultsValue) || "null".equalsIgnoreCase(characterSetResultsValue)) {
            if (!StringUtils.isNullOrEmpty(sessionResultsCharset) && !"NULL".equalsIgnoreCase(sessionResultsCharset)) {
                telemetryWrapSendCommand(() -> this.session.getProtocol()
                        .sendCommand(getCommandBuilder().buildComQuery(null, this.session, "SET character_set_results = NULL"), false, 0),
                        TelemetrySpanName.SET_VARIABLE, "character_set_results");
                this.serverSession.getServerVariables().put(CHARACTER_SET_RESULTS, null);
            }

            String defaultMetadataCharsetMysql = this.serverSession.getServerVariable("character_set_system");
            this.metadataEncoding = defaultMetadataCharsetMysql != null ? getJavaEncodingForMysqlCharset(defaultMetadataCharsetMysql) : "UTF-8";
            this.errorMessageEncoding = "UTF-8";

        } else {
            String resultsCharsetName = getMysqlCharsetForJavaEncoding(characterSetResultsValue.toUpperCase(Locale.ENGLISH),
                    this.serverSession.getServerVersion());

            if (resultsCharsetName == null) {
                throw ExceptionFactory.createException(WrongArgumentException.class,
                        Messages.getString("Connection.7", new Object[] { characterSetResultsValue }), this.session.getExceptionInterceptor());
            }

            if (!resultsCharsetName.equalsIgnoreCase(sessionResultsCharset)) {
                telemetryWrapSendCommand(
                        () -> this.session.getProtocol().sendCommand(
                                getCommandBuilder().buildComQuery(null, this.session, "SET character_set_results = " + resultsCharsetName), false, 0),
                        TelemetrySpanName.SET_VARIABLE, "character_set_results");
                this.serverSession.getServerVariables().put(CHARACTER_SET_RESULTS, resultsCharsetName);
            }

            this.metadataEncoding = characterSetResultsValue;
            this.errorMessageEncoding = characterSetResultsValue;
        }

        this.metadataCollationIndex = getCollationIndexForJavaEncoding(this.metadataEncoding, this.serverSession.getServerVersion());

        checkForCharsetMismatch();

        /**
         * Check if we need a CharsetEncoder for escaping codepoints that are
         * transformed to backslash (0x5c) in the connection encoding.
         */
        try {
            CharsetEncoder enc = Charset.forName(this.characterEncoding.getValue()).newEncoder();
            CharBuffer cbuf = CharBuffer.allocate(1);
            ByteBuffer bbuf = ByteBuffer.allocate(1);

            cbuf.put("\u00a5");
            cbuf.position(0);
            enc.encode(cbuf, bbuf, true);
            if (bbuf.get(0) == '\\') {
                this.requiresEscapingEncoder = true;
            } else {
                cbuf.clear();
                bbuf.clear();

                cbuf.put("\u20a9");
                cbuf.position(0);
                enc.encode(cbuf, bbuf, true);
                if (bbuf.get(0) == '\\') {
                    this.requiresEscapingEncoder = true;
                }
            }
        } catch (java.nio.charset.UnsupportedCharsetException ucex) {
            // fallback to String API
            byte bbuf[] = StringUtils.getBytes("\u00a5", this.characterEncoding.getValue());
            if (bbuf[0] == '\\') {
                this.requiresEscapingEncoder = true;
            } else {
                bbuf = StringUtils.getBytes("\u20a9", this.characterEncoding.getValue());
                if (bbuf[0] == '\\') {
                    this.requiresEscapingEncoder = true;
                }
            }
        }
    }