public static HintValueContext extractHint(final String sql) {
        if (!containsSQLHint(sql)) {
            return new HintValueContext();
        }
        HintValueContext result = new HintValueContext();
        int hintKeyValueBeginIndex = getHintKeyValueBeginIndex(sql);
        String hintKeyValueText = sql.substring(hintKeyValueBeginIndex, sql.indexOf(SQL_COMMENT_SUFFIX, hintKeyValueBeginIndex));
        Map<String, String> hintKeyValues = getSQLHintKeyValues(hintKeyValueText);
        if (containsHintKey(hintKeyValues, SQLHintPropertiesKey.DATASOURCE_NAME_KEY)) {
            result.setDataSourceName(getHintValue(hintKeyValues, SQLHintPropertiesKey.DATASOURCE_NAME_KEY));
        }
        if (containsHintKey(hintKeyValues, SQLHintPropertiesKey.WRITE_ROUTE_ONLY_KEY)) {
            result.setWriteRouteOnly(Boolean.parseBoolean(getHintValue(hintKeyValues, SQLHintPropertiesKey.WRITE_ROUTE_ONLY_KEY)));
        }
        if (containsHintKey(hintKeyValues, SQLHintPropertiesKey.SKIP_SQL_REWRITE_KEY)) {
            result.setSkipSQLRewrite(Boolean.parseBoolean(getHintValue(hintKeyValues, SQLHintPropertiesKey.SKIP_SQL_REWRITE_KEY)));
        }
        if (containsHintKey(hintKeyValues, SQLHintPropertiesKey.DISABLE_AUDIT_NAMES_KEY)) {
            String property = getHintValue(hintKeyValues, SQLHintPropertiesKey.DISABLE_AUDIT_NAMES_KEY);
            result.getDisableAuditNames().addAll(getSplitterSQLHintValue(property));
        }
        if (containsHintKey(hintKeyValues, SQLHintPropertiesKey.SHADOW_KEY)) {
            result.setShadow(Boolean.parseBoolean(getHintValue(hintKeyValues, SQLHintPropertiesKey.SHADOW_KEY)));
        }
        for (Entry<String, String> entry : hintKeyValues.entrySet()) {
            Object value = convert(entry.getValue());
            Comparable<?> comparable = value instanceof Comparable ? (Comparable<?>) value : Objects.toString(value);
            if (containsHintKey(Objects.toString(entry.getKey()), SQLHintPropertiesKey.SHARDING_DATABASE_VALUE_KEY)) {
                result.getShardingDatabaseValues().put(Objects.toString(entry.getKey()).toUpperCase(), comparable);
            }
            if (containsHintKey(Objects.toString(entry.getKey()), SQLHintPropertiesKey.SHARDING_TABLE_VALUE_KEY)) {
                result.getShardingTableValues().put(Objects.toString(entry.getKey()).toUpperCase(), comparable);
            }
        }
        return result;
    }
@Test
    void assertSQLHintWriteRouteOnlyWithCommentString() {
        HintValueContext actual = SQLHintUtils.extractHint("/* SHARDINGSPHERE_HINT: WRITE_ROUTE_ONLY=true */");
        assertTrue(actual.isWriteRouteOnly());
    }