Modified:
trunk/connector-j/CHANGES
trunk/connector-j/src/com/mysql/jdbc/CallableStatement.java
trunk/connector-j/src/com/mysql/jdbc/CharsetMapping.java
trunk/connector-j/src/com/mysql/jdbc/Connection.java
trunk/connector-j/src/com/mysql/jdbc/MysqlIO.java
trunk/connector-j/src/com/mysql/jdbc/PreparedStatement.java
trunk/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java
trunk/connector-j/src/com/mysql/jdbc/Statement.java
trunk/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java
trunk/connector-j/src/testsuite/regression/StringRegressionTest.java
Log:
Merges from 5.0.
Modified: trunk/connector-j/CHANGES
===================================================================
--- trunk/connector-j/CHANGES 2006-10-27 21:13:18 UTC (rev 5949)
+++ trunk/connector-j/CHANGES 2006-10-27 21:17:07 UTC (rev 5950)
@@ -1,6 +1,17 @@
# Changelog
# $Id$
+nn-nn-06 - Version 5.0.5
+
+ - Fixed BUG#23645 - Some collations/character sets reported as "unknown"
+ (specifically cias variants of existing character sets), and inability to override
+ the detected server character set.
+
+ - Performance enhancement of initial character set configuration, driver
+ will only send commands required to configure connection character set
+ session variables if the current values on the server do not match
+ what is required.
+
10-20-06 - Version 5.0.4
- Fixed BUG#21379 - column names don't match metadata in cases
Modified: trunk/connector-j/src/com/mysql/jdbc/CallableStatement.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/CallableStatement.java 2006-10-27 21:13:18 UTC
(rev 5949)
+++ trunk/connector-j/src/com/mysql/jdbc/CallableStatement.java 2006-10-27 21:17:07 UTC
(rev 5950)
@@ -124,6 +124,42 @@
Map parameterMap;
+ /**
+ * Constructor that converts a full list of parameter metadata into one
+ * that only represents the placeholders present in the {CALL ()}.
+ *
+ * @param fullParamInfo the metadata for all parameters for this stored
+ * procedure or function.
+ */
+ CallableStatementParamInfo(CallableStatementParamInfo fullParamInfo) {
+ this.nativeSql = originalSql;
+ this.catalogInUse = currentCatalog;
+ isFunctionCall = fullParamInfo.isFunctionCall;
+ int[] localParameterMap = placeholderToParameterIndexMap;
+ int parameterMapLength = localParameterMap.length;
+
+ parameterList = new ArrayList(fullParamInfo.numParameters);
+ parameterMap = new HashMap(fullParamInfo.numParameters);
+
+ if (isFunctionCall) {
+ // Take the return value
+ parameterList.add(fullParamInfo.parameterList.get(0));
+ }
+
+ int offset = isFunctionCall ? 1 : 0;
+
+ for (int i = 0; i < parameterMapLength; i++) {
+ if (localParameterMap[i] != 0) {
+ CallableStatementParam param =
(CallableStatementParam)fullParamInfo.parameterList.get(localParameterMap[i] + offset);
+
+ parameterList.add(param);
+ parameterMap.put(param.paramName, param);
+ }
+ }
+
+ this.numParameters = parameterList.size();
+ }
+
CallableStatementParamInfo(java.sql.ResultSet paramTypesRs)
throws SQLException {
boolean hadRows = paramTypesRs.last();
@@ -144,17 +180,16 @@
} else {
this.numParameters = 0;
}
+
+ if (isFunctionCall) {
+ this.numParameters += 1;
}
+ }
private void addParametersFromDBMD(java.sql.ResultSet paramTypesRs)
throws SQLException {
int i = 0;
- if (isFunctionCall) {
- // first row will be return value parameter
- paramTypesRs.next();
- }
-
while (paramTypesRs.next()) {
String paramName = paramTypesRs.getString(4);
int inOutModifier = paramTypesRs.getInt(5);
@@ -162,8 +197,11 @@
boolean isOutParameter = false;
boolean isInParameter = false;
- if (inOutModifier == DatabaseMetaData.procedureColumnInOut) {
+ if (i == 0 && isFunctionCall) {
isOutParameter = true;
+ isInParameter = false;
+ } else if (inOutModifier == DatabaseMetaData.procedureColumnInOut) {
+ isOutParameter = true;
isInParameter = true;
} else if (inOutModifier == DatabaseMetaData.procedureColumnIn) {
isOutParameter = false;
@@ -309,6 +347,10 @@
super(paramTypesRs);
}
+ public CallableStatementParamInfoJDBC3(CallableStatementParamInfo paramInfo) {
+ super(paramInfo);
+ }
+
public boolean isWrapperFor(Class arg0) throws SQLException {
throw new JDBC40NotYetImplementedException();
}
@@ -378,7 +420,11 @@
this.paramInfo = paramInfo;
this.callingStoredFunction = this.paramInfo.isFunctionCall;
+
+ if (this.callingStoredFunction) {
+ this.parameterCount += 1;
}
+ }
/**
* Creates a new CallableStatement
@@ -397,7 +443,11 @@
determineParameterTypes();
generateParameterMap();
+
+ if (this.callingStoredFunction) {
+ this.parameterCount += 1;
}
+ }
private int[] placeholderToParameterIndexMap;
@@ -406,12 +456,21 @@
// provide a map from the specified placeholders to the actual
// parameter numbers
+ int parameterCountFromMetaData = this.paramInfo.getParameterCount();
+
+ // Ignore the first ? if this is a stored function, it doesn't count
+
+ if (this.callingStoredFunction) {
+ parameterCountFromMetaData--;
+ }
+
if (this.paramInfo != null &&
- this.parameterCount != this.paramInfo.getParameterCount()) {
+ this.parameterCount != parameterCountFromMetaData) {
this.placeholderToParameterIndexMap = new int[this.parameterCount];
- int startPos = StringUtils.indexOfIgnoreCase(this.originalSql,
- "CALL");
+ int startPos = this.callingStoredFunction ?
StringUtils.indexOfIgnoreCase(this.originalSql,
+ "SELECT") : StringUtils.indexOfIgnoreCase(this.originalSql, "CALL");
+
if (startPos != -1) {
int parenOpenPos = this.originalSql.indexOf('(', startPos + 4);
@@ -464,7 +523,11 @@
determineParameterTypes();
generateParameterMap();
+
+ if (this.callingStoredFunction) {
+ this.parameterCount += 1;
}
+ }
/*
* (non-Javadoc)
@@ -1385,8 +1448,12 @@
public synchronized ParameterMetaData getParameterMetaData()
throws SQLException {
+ if (this.placeholderToParameterIndexMap == null) {
return (CallableStatementParamInfoJDBC3) this.paramInfo;
+ } else {
+ return new CallableStatementParamInfoJDBC3(this.paramInfo);
}
+ }
/**
* @see java.sql.CallableStatement#getRef(int)
@@ -1996,7 +2063,7 @@
CallableStatementParam outParamInfo = (CallableStatementParam) paramIter
.next();
- if (outParamInfo.isOut) {
+ if (!this.callingStoredFunction && outParamInfo.isOut) {
String outParameterName = mangleParameterName(outParamInfo.paramName);
int outParamIndex;
@@ -2090,16 +2157,12 @@
return super.executeBatch();
}
- public RowId getRowId(String parameterName) throws SQLException {
- ResultSet rs = getOutputParameters(0); // definitely not going to be
- // from ?=
-
- RowId retValue = rs.getRowId(fixParameterName(parameterName));
-
- this.outputParamWasNull = rs.wasNull();
-
- return retValue;
+ protected int getParameterIndexOffset() {
+ if (this.callingStoredFunction) {
+ return -1;
+ }
+ return super.getParameterIndexOffset();
}
public SQLXML getSQLXML(int parameterIndex) throws SQLException {
@@ -2357,4 +2420,15 @@
return retValue;
}
+
+ public RowId getRowId(String parameterName) throws SQLException {
+ ResultSet rs = getOutputParameters(0); // definitely not going to be
+ // from ?=
+
+ RowId retValue = rs.getRowId(fixParameterName(parameterName));
+
+ this.outputParamWasNull = rs.wasNull();
+
+ return retValue;
+ }
}
Modified: trunk/connector-j/src/com/mysql/jdbc/CharsetMapping.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/CharsetMapping.java 2006-10-27 21:13:18 UTC (rev
5949)
+++ trunk/connector-j/src/com/mysql/jdbc/CharsetMapping.java 2006-10-27 21:17:07 UTC (rev
5950)
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2002-2004 MySQL AB
+ Copyright (C) 2002-2006 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
@@ -62,6 +62,8 @@
private static final Map MULTIBYTE_CHARSETS;
private static final Map MYSQL_TO_JAVA_CHARSET_MAP;
+
+ private static final String NOT_USED = "ISO8859_1"; // punting for not-used character
sets
static {
@@ -102,8 +104,8 @@
+ "ISO8859_13 = estonia,"
+ "Cp437 = *>4.1.0 cp850,"
+ "Cp437 = dos,"
- + "Cp850 = Cp850,"
- + "Cp852 = Cp852,"
+ + "Cp850 = cp850,"
+ + "Cp852 = cp852,"
+ "Cp866 = cp866,"
+ "KOI8_R = koi8_ru,"
+ "KOI8_R = >4.1.0 koi8r,"
@@ -116,7 +118,7 @@
+ "Cp1251 = cp1251csas,"
+ "Cp1256 = cp1256,"
+ "Cp1251 = win1251ukr,"
- + "Cp1252 = latin1,"
+ + "Cp1252 = latin1,"
+ "Cp1257 = cp1257,"
+ "MacRoman = macroman,"
+ "MacCentralEurope = macce,"
@@ -239,18 +241,18 @@
try {
INDEX_TO_CHARSET[1] = getJavaEncodingForMysqlEncoding("big5", null);
INDEX_TO_CHARSET[2] = getJavaEncodingForMysqlEncoding("czech", null);
- INDEX_TO_CHARSET[3] = getJavaEncodingForMysqlEncoding("dec8", null);
- INDEX_TO_CHARSET[4] = getJavaEncodingForMysqlEncoding("dos", null);
+ INDEX_TO_CHARSET[3] = "ISO8859_1"; // punting for "dec8"
+ INDEX_TO_CHARSET[4] = "ISO8859_1"; // punting for "dos"
INDEX_TO_CHARSET[5] = getJavaEncodingForMysqlEncoding("german1",
null);
- INDEX_TO_CHARSET[6] = getJavaEncodingForMysqlEncoding("hp8", null);
+ INDEX_TO_CHARSET[6] = "ISO8859_1"; // punting for "hp8"
INDEX_TO_CHARSET[7] = getJavaEncodingForMysqlEncoding("koi8_ru",
null);
INDEX_TO_CHARSET[8] = getJavaEncodingForMysqlEncoding("latin1",
null);
INDEX_TO_CHARSET[9] = getJavaEncodingForMysqlEncoding("latin2",
null);
- INDEX_TO_CHARSET[10] = getJavaEncodingForMysqlEncoding("swe7", null);
+ INDEX_TO_CHARSET[10] = "ISO8859_1"; // punting for "swe7"
INDEX_TO_CHARSET[11] = getJavaEncodingForMysqlEncoding("usa7", null);
INDEX_TO_CHARSET[12] = getJavaEncodingForMysqlEncoding("ujis", null);
INDEX_TO_CHARSET[13] = getJavaEncodingForMysqlEncoding("sjis", null);
@@ -260,6 +262,9 @@
null);
INDEX_TO_CHARSET[16] = getJavaEncodingForMysqlEncoding("hebrew",
null);
+
+ INDEX_TO_CHARSET[17] = NOT_USED; // not used in the server
+
INDEX_TO_CHARSET[18] = getJavaEncodingForMysqlEncoding("tis620",
null);
INDEX_TO_CHARSET[19] = getJavaEncodingForMysqlEncoding("euc_kr",
@@ -268,8 +273,7 @@
null);
INDEX_TO_CHARSET[21] = getJavaEncodingForMysqlEncoding("hungarian",
null);
- INDEX_TO_CHARSET[22] = getJavaEncodingForMysqlEncoding("koi8_ukr",
- null);
+ INDEX_TO_CHARSET[22] = "KOI8_R"; //punting for "koi8_ukr"
INDEX_TO_CHARSET[23] = getJavaEncodingForMysqlEncoding(
"win1251ukr", null);
INDEX_TO_CHARSET[24] = getJavaEncodingForMysqlEncoding("gb2312",
@@ -287,60 +291,62 @@
null);
INDEX_TO_CHARSET[31] = getJavaEncodingForMysqlEncoding("latin1_de",
null);
- INDEX_TO_CHARSET[32] = getJavaEncodingForMysqlEncoding("armscii8",
- null);
+ INDEX_TO_CHARSET[32] = "ISO8859_1"; // punting "armscii8"
INDEX_TO_CHARSET[33] = getJavaEncodingForMysqlEncoding("utf8", null);
- INDEX_TO_CHARSET[34] = getJavaEncodingForMysqlEncoding("win1250ch",
- null);
+ INDEX_TO_CHARSET[34] = "Cp1250"; // punting "win1250ch"
INDEX_TO_CHARSET[35] = getJavaEncodingForMysqlEncoding("ucs2", null);
INDEX_TO_CHARSET[36] = getJavaEncodingForMysqlEncoding("cp866",
null);
- INDEX_TO_CHARSET[37] = getJavaEncodingForMysqlEncoding("keybcs2",
- null);
+ INDEX_TO_CHARSET[37] = "Cp895"; // punting "keybcs2"
INDEX_TO_CHARSET[38] = getJavaEncodingForMysqlEncoding("macce",
null);
INDEX_TO_CHARSET[39] = getJavaEncodingForMysqlEncoding("macroman",
null);
- INDEX_TO_CHARSET[40] = getJavaEncodingForMysqlEncoding("pclatin2",
- null);
+ INDEX_TO_CHARSET[40] = "latin2"; // punting "pclatin2"
INDEX_TO_CHARSET[41] = getJavaEncodingForMysqlEncoding("latvian",
null);
INDEX_TO_CHARSET[42] = getJavaEncodingForMysqlEncoding("latvian1",
null);
- INDEX_TO_CHARSET[43] = getJavaEncodingForMysqlEncoding("maccebin",
+ INDEX_TO_CHARSET[43] = getJavaEncodingForMysqlEncoding("macce",
null);
- INDEX_TO_CHARSET[44] = getJavaEncodingForMysqlEncoding("macceciai",
+ INDEX_TO_CHARSET[44] = getJavaEncodingForMysqlEncoding("macce",
null);
- INDEX_TO_CHARSET[45] = getJavaEncodingForMysqlEncoding("maccecias",
+ INDEX_TO_CHARSET[45] = getJavaEncodingForMysqlEncoding("macce",
null);
- INDEX_TO_CHARSET[46] = getJavaEncodingForMysqlEncoding("maccecsas",
+ INDEX_TO_CHARSET[46] = getJavaEncodingForMysqlEncoding("macce",
null);
- INDEX_TO_CHARSET[47] = getJavaEncodingForMysqlEncoding("latin1bin",
+ INDEX_TO_CHARSET[47] = getJavaEncodingForMysqlEncoding("latin1",
null);
INDEX_TO_CHARSET[48] = getJavaEncodingForMysqlEncoding(
- "latin1cias", null);
+ "latin1", null);
INDEX_TO_CHARSET[49] = getJavaEncodingForMysqlEncoding(
- "latin1csas", null);
- INDEX_TO_CHARSET[50] = getJavaEncodingForMysqlEncoding("cp1251bin",
+ "latin1", null);
+ INDEX_TO_CHARSET[50] = getJavaEncodingForMysqlEncoding("cp1251",
null);
INDEX_TO_CHARSET[51] = getJavaEncodingForMysqlEncoding(
- "cp1251cias", null);
+ "cp1251", null);
INDEX_TO_CHARSET[52] = getJavaEncodingForMysqlEncoding(
- "cp1251csas", null);
+ "cp1251", null);
INDEX_TO_CHARSET[53] = getJavaEncodingForMysqlEncoding(
- "macromanbin", null);
+ "macroman", null);
INDEX_TO_CHARSET[54] = getJavaEncodingForMysqlEncoding(
- "macromancias", null);
+ "macroman", null);
INDEX_TO_CHARSET[55] = getJavaEncodingForMysqlEncoding(
- "macromanciai", null);
+ "macroman", null);
INDEX_TO_CHARSET[56] = getJavaEncodingForMysqlEncoding(
- "macromancsas", null);
+ "macroman", null);
INDEX_TO_CHARSET[57] = getJavaEncodingForMysqlEncoding("cp1256",
null);
+
+ INDEX_TO_CHARSET[58] = NOT_USED; // not used
+ INDEX_TO_CHARSET[59] = NOT_USED; // not used
+ INDEX_TO_CHARSET[60] = NOT_USED; // not used
+ INDEX_TO_CHARSET[61] = NOT_USED; // not used
+ INDEX_TO_CHARSET[62] = NOT_USED; // not used
+
INDEX_TO_CHARSET[63] = getJavaEncodingForMysqlEncoding("binary",
null);
- INDEX_TO_CHARSET[64] = getJavaEncodingForMysqlEncoding("armscii",
- null);
+ INDEX_TO_CHARSET[64] = "ISO8859_2"; // punting "armscii"
INDEX_TO_CHARSET[65] = getJavaEncodingForMysqlEncoding("ascii",
null);
INDEX_TO_CHARSET[66] = getJavaEncodingForMysqlEncoding("cp1250",
@@ -349,18 +355,19 @@
null);
INDEX_TO_CHARSET[68] = getJavaEncodingForMysqlEncoding("cp866",
null);
- INDEX_TO_CHARSET[69] = getJavaEncodingForMysqlEncoding("dec8", null);
+ INDEX_TO_CHARSET[69] = "US-ASCII"; // punting for "dec8"
INDEX_TO_CHARSET[70] = getJavaEncodingForMysqlEncoding("greek",
null);
INDEX_TO_CHARSET[71] = getJavaEncodingForMysqlEncoding("hebrew",
null);
- INDEX_TO_CHARSET[72] = getJavaEncodingForMysqlEncoding("hp8", null);
- INDEX_TO_CHARSET[73] = getJavaEncodingForMysqlEncoding("keybcs2",
- null);
+ INDEX_TO_CHARSET[72] = "US-ASCII"; // punting for "hp8"
+ INDEX_TO_CHARSET[73] = "Cp895"; // punting for "keybcs2"
INDEX_TO_CHARSET[74] = getJavaEncodingForMysqlEncoding("koi8r",
null);
- INDEX_TO_CHARSET[75] = getJavaEncodingForMysqlEncoding("koi8ukr",
- null);
+ INDEX_TO_CHARSET[75] = "KOI8_r"; // punting for koi8ukr"
+
+ INDEX_TO_CHARSET[76] = NOT_USED; // not used
+
INDEX_TO_CHARSET[77] = getJavaEncodingForMysqlEncoding("latin2",
null);
INDEX_TO_CHARSET[78] = getJavaEncodingForMysqlEncoding("latin5",
@@ -371,7 +378,7 @@
null);
INDEX_TO_CHARSET[81] = getJavaEncodingForMysqlEncoding("cp852",
null);
- INDEX_TO_CHARSET[82] = getJavaEncodingForMysqlEncoding("swe7", null);
+ INDEX_TO_CHARSET[82] = "ISO8859_1"; // punting for "swe7"
INDEX_TO_CHARSET[83] = getJavaEncodingForMysqlEncoding("utf8", null);
INDEX_TO_CHARSET[84] = getJavaEncodingForMysqlEncoding("big5", null);
INDEX_TO_CHARSET[85] = getJavaEncodingForMysqlEncoding("euckr",
@@ -384,10 +391,8 @@
null);
INDEX_TO_CHARSET[90] = getJavaEncodingForMysqlEncoding("ucs2", null);
INDEX_TO_CHARSET[91] = getJavaEncodingForMysqlEncoding("ujis", null);
- INDEX_TO_CHARSET[92] = getJavaEncodingForMysqlEncoding("geostd8",
- null);
- INDEX_TO_CHARSET[93] = getJavaEncodingForMysqlEncoding("geostd8",
- null);
+ INDEX_TO_CHARSET[92] = "US-ASCII"; //punting for "geostd8"
+ INDEX_TO_CHARSET[93] = "US-ASCII"; // punting for "geostd8"
INDEX_TO_CHARSET[94] = getJavaEncodingForMysqlEncoding("latin1",
null);
INDEX_TO_CHARSET[95] = getJavaEncodingForMysqlEncoding("cp932",
@@ -399,6 +404,10 @@
INDEX_TO_CHARSET[98] = getJavaEncodingForMysqlEncoding("eucjpms",
null);
+ for (int i = 99; i < 128; i++) {
+ INDEX_TO_CHARSET[i] = NOT_USED; // not used
+ }
+
INDEX_TO_CHARSET[128] = getJavaEncodingForMysqlEncoding("ucs2",
null);
INDEX_TO_CHARSET[129] = getJavaEncodingForMysqlEncoding("ucs2",
@@ -438,6 +447,10 @@
INDEX_TO_CHARSET[146] = getJavaEncodingForMysqlEncoding("ucs2",
null);
+ for (int i = 147; i < 192; i++) {
+ INDEX_TO_CHARSET[i] = NOT_USED; // not used
+ }
+
INDEX_TO_CHARSET[192] = getJavaEncodingForMysqlEncoding("utf8",
null);
INDEX_TO_CHARSET[193] = getJavaEncodingForMysqlEncoding("utf8",
@@ -476,6 +489,14 @@
null);
INDEX_TO_CHARSET[210] = getJavaEncodingForMysqlEncoding("utf8",
null);
+
+ // Sanity check
+
+ for (int i = 1; i < INDEX_TO_CHARSET.length; i++) {
+ if (INDEX_TO_CHARSET[i] == null) {
+ throw new RuntimeException("Assertion failure: No mapping from charset index " + i +
" to a Java character set");
+ }
+ }
} catch (SQLException sqlEx) {
// ignore, it won't happen in this case
}
@@ -511,18 +532,18 @@
Collections.unmodifiableMap(tempMap);
}
- final static String getJavaEncodingForMysqlEncoding(String mysqlEncoding,
+ public final static String getJavaEncodingForMysqlEncoding(String mysqlEncoding,
Connection conn) throws SQLException {
-
- if (conn != null && conn.versionMeetsMinimum(4, 1, 0) &&
- "latin1".equalsIgnoreCase(mysqlEncoding)) {
- return "Cp1252";
- }
-
+
+ if (conn != null && conn.versionMeetsMinimum(4, 1, 0) &&
+ "latin1".equalsIgnoreCase(mysqlEncoding)) {
+ return "Cp1252";
+ }
+
return (String) MYSQL_TO_JAVA_CHARSET_MAP.get(mysqlEncoding);
}
- final static String getMysqlEncodingForJavaEncoding(String javaEncodingUC,
+ public final static String getMysqlEncodingForJavaEncoding(String javaEncodingUC,
Connection conn) throws SQLException {
List mysqlEncodings = (List) CharsetMapping.JAVA_UC_TO_MYSQL_CHARSET_MAP
.get(javaEncodingUC);
Modified: trunk/connector-j/src/com/mysql/jdbc/Connection.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/Connection.java 2006-10-27 21:13:18 UTC (rev
5949)
+++ trunk/connector-j/src/com/mysql/jdbc/Connection.java 2006-10-27 21:17:07 UTC (rev
5950)
@@ -1466,24 +1466,39 @@
// versions > 4.1.0
try {
+
+ // Fault injection for testing server character set indices
+
+ if (props != null &&
props.getProperty("com.mysql.jdbc.faultInjection.serverCharsetIndex") != null) {
+ this.io.serverCharsetIndex = Integer.parseInt(
+ props.getProperty(
+ "com.mysql.jdbc.faultInjection.serverCharsetIndex"));
+ }
+
String serverEncodingToSet =
CharsetMapping.INDEX_TO_CHARSET[this.io.serverCharsetIndex];
-
if (serverEncodingToSet == null || serverEncodingToSet.length() == 0) {
- throw SQLError.createSQLException(
- "Unknown initial character set index '"
- + this.io.serverCharsetIndex
- + "' received from server. Initial client character set can be forced via the
'characterEncoding' property.",
- SQLError.SQL_STATE_GENERAL_ERROR);
+ if (realJavaEncoding != null) {
+ // user knows best, try it
+ setEncoding(realJavaEncoding);
+ } else {
+ throw SQLError.createSQLException(
+ "Unknown initial character set index '"
+ + this.io.serverCharsetIndex
+ + "' received from server. Initial client character set can be forced via the
'characterEncoding' property.",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
}
+ // "latin1" on MySQL-4.1.0+ is actually CP1252, not ISO8859_1
if (versionMeetsMinimum(4, 1, 0) &&
"ISO8859_1".equalsIgnoreCase(serverEncodingToSet)) {
serverEncodingToSet = "Cp1252";
}
setEncoding(serverEncodingToSet);
+
} catch (ArrayIndexOutOfBoundsException outOfBoundsEx) {
if (realJavaEncoding != null) {
// user knows best, try it
@@ -1518,10 +1533,12 @@
// charset names are case-sensitive
if (!getUseOldUTF8Behavior()) {
- execSQL(null, "SET NAMES utf8", -1, null,
- java.sql.ResultSet.TYPE_FORWARD_ONLY,
- java.sql.ResultSet.CONCUR_READ_ONLY,
- false, this.database, true, false);
+ if (!characterSetNamesMatches("utf8")) {
+ execSQL(null, "SET NAMES utf8", -1, null,
+ java.sql.ResultSet.TYPE_FORWARD_ONLY,
+ java.sql.ResultSet.CONCUR_READ_ONLY,
+ false, this.database, true, false);
+ }
}
setEncoding(realJavaEncoding);
@@ -1542,11 +1559,14 @@
*/
if (mysqlEncodingName != null) {
- execSQL(null, "SET NAMES " + mysqlEncodingName,
+
+ if (!characterSetNamesMatches(mysqlEncodingName)) {
+ execSQL(null, "SET NAMES " + mysqlEncodingName,
-1, null,
java.sql.ResultSet.TYPE_FORWARD_ONLY,
java.sql.ResultSet.CONCUR_READ_ONLY,
false, this.database, true, false);
+ }
}
// Switch driver's encoding now, since the server
@@ -1562,10 +1582,12 @@
.getMysqlEncodingForJavaEncoding(getEncoding()
.toUpperCase(Locale.ENGLISH), this);
- execSQL(null, "SET NAMES " + mysqlEncodingName, -1,
+ if (!characterSetNamesMatches(mysqlEncodingName)) {
+ execSQL(null, "SET NAMES " + mysqlEncodingName, -1,
null, java.sql.ResultSet.TYPE_FORWARD_ONLY,
java.sql.ResultSet.CONCUR_READ_ONLY, false,
this.database, true, false);
+ }
realJavaEncoding = getEncoding();
}
@@ -1579,11 +1601,19 @@
//
if (getCharacterSetResults() == null) {
- execSQL(null, "SET character_set_results = NULL", -1, null,
- java.sql.ResultSet.TYPE_FORWARD_ONLY,
- java.sql.ResultSet.CONCUR_READ_ONLY, false,
- this.database, true,
- false);
+
+ //
+ // Only send if needed
+ //
+
+ if (this.serverVariables.get("character_set_results") != null) {
+
+ execSQL(null, "SET character_set_results = NULL", -1, null,
+ java.sql.ResultSet.TYPE_FORWARD_ONLY,
+ java.sql.ResultSet.CONCUR_READ_ONLY, false,
+ this.database, true,
+ false);
+ }
} else {
String charsetResults = getCharacterSetResults();
String mysqlEncodingName = null;
@@ -1597,16 +1627,23 @@
.toUpperCase(Locale.ENGLISH), this);
}
- StringBuffer setBuf = new StringBuffer(
- "SET character_set_results = ".length()
- + mysqlEncodingName.length());
- setBuf.append("SET character_set_results = ").append(
- mysqlEncodingName);
-
- execSQL(null, setBuf.toString(), -1, null,
- java.sql.ResultSet.TYPE_FORWARD_ONLY,
- java.sql.ResultSet.CONCUR_READ_ONLY, false,
- this.database, true, false);
+ //
+ // Only change the value if needed
+ //
+
+ if (!mysqlEncodingName.equalsIgnoreCase(
+ (String)this.serverVariables.get("character_set_results"))) {
+ StringBuffer setBuf = new StringBuffer(
+ "SET character_set_results = ".length()
+ + mysqlEncodingName.length());
+ setBuf.append("SET character_set_results = ").append(
+ mysqlEncodingName);
+
+ execSQL(null, setBuf.toString(), -1, null,
+ java.sql.ResultSet.TYPE_FORWARD_ONLY,
+ java.sql.ResultSet.CONCUR_READ_ONLY, false,
+ this.database, true, false);
+ }
}
if (getConnectionCollation() != null) {
@@ -1637,6 +1674,15 @@
return characterSetAlreadyConfigured;
}
+ private boolean characterSetNamesMatches(String mysqlEncodingName) {
+ // set names is equivalent to character_set_client ..._results and ..._connection,
+ // but we set _results later, so don't check it here.
+
+ return (mysqlEncodingName != null &&
+ mysqlEncodingName.equalsIgnoreCase((String)this.serverVariables.get("character_set_client"))
&&
+ mysqlEncodingName.equalsIgnoreCase((String)this.serverVariables.get("character_set_connection")));
+ }
+
/**
* Configures the client's timezone if required.
*
@@ -3037,10 +3083,6 @@
setTransformedBitIsBoolean(false);
}
- // We need to do this before any further data gets
- // sent to the server....
- boolean clientCharsetIsConfigured = configureClientCharacterSet();
-
this.parserKnowsUnicode = versionMeetsMinimum(4, 1, 0);
//
@@ -3099,14 +3141,8 @@
}
checkTransactionIsolationLevel();
-
- //
- // We only do this for servers older than 4.1.0, because
- // 4.1.0 and newer actually send the server charset
- // during the handshake, and that's handled at the
- // top of this method...
- //
- if (!clientCharsetIsConfigured) {
+
+ if (!versionMeetsMinimum(4, 1, 0)) {
checkServerEncoding();
}
@@ -3146,48 +3182,11 @@
this.errorMessageEncoding =
CharsetMapping.getCharacterEncodingForErrorMessages(this);
- boolean overrideDefaultAutocommit = false;
- String initConnectValue = (String) this.serverVariables
- .get("init_connect");
+ boolean overrideDefaultAutocommit = isAutoCommitNonDefaultOnServer();
+
+ configureClientCharacterSet();
- if (versionMeetsMinimum(4, 1, 2) && initConnectValue != null
- && initConnectValue.length() > 0) {
- // auto-commit might have changed
- java.sql.ResultSet rs = null;
- java.sql.Statement stmt = null;
-
- try {
- stmt = getMetadataSafeStatement();
-
- rs = stmt.executeQuery("SELECT @@session.autocommit");
-
- if (rs.next()) {
- this.autoCommit = rs.getBoolean(1);
- if (this.autoCommit != true) {
- overrideDefaultAutocommit = true;
- }
- }
-
- } finally {
- if (rs != null) {
- try {
- rs.close();
- } catch (SQLException sqlEx) {
- // do nothing
- }
- }
-
- if (stmt != null) {
- try {
- stmt.close();
- } catch (SQLException sqlEx) {
- // do nothing
- }
- }
- }
- }
-
if (versionMeetsMinimum(3, 23, 15)) {
this.transactionsSupported = true;
@@ -3266,6 +3265,68 @@
setupServerForTruncationChecks();
}
+ /**
+ * Has the default autocommit value of 0 been changed on the server
+ * via init_connect?
+ *
+ * @return true if autocommit is not the default of '0' on the server.
+ *
+ * @throws SQLException
+ */
+ private boolean isAutoCommitNonDefaultOnServer() throws SQLException {
+ boolean overrideDefaultAutocommit = false;
+
+ String initConnectValue = (String) this.serverVariables
+ .get("init_connect");
+
+ if (versionMeetsMinimum(4, 1, 2) && initConnectValue != null
+ && initConnectValue.length() > 0) {
+ if (!getElideSetAutoCommits()) {
+ // auto-commit might have changed
+ java.sql.ResultSet rs = null;
+ java.sql.Statement stmt = null;
+
+ try {
+ stmt = getMetadataSafeStatement();
+
+ rs = stmt.executeQuery("SELECT @@session.autocommit");
+
+ if (rs.next()) {
+ this.autoCommit = rs.getBoolean(1);
+ if (this.autoCommit != true) {
+ overrideDefaultAutocommit = true;
+ }
+ }
+
+ } finally {
+ if (rs != null) {
+ try {
+ rs.close();
+ } catch (SQLException sqlEx) {
+ // do nothing
+ }
+ }
+
+ if (stmt != null) {
+ try {
+ stmt.close();
+ } catch (SQLException sqlEx) {
+ // do nothing
+ }
+ }
+ }
+ } else {
+ if (this.getIO().isSetNeededForAutoCommitMode(true)) {
+ // we're not in standard autocommit=true mode
+ this.autoCommit = false;
+ overrideDefaultAutocommit = true;
+ }
+ }
+ }
+
+ return overrideDefaultAutocommit;
+ }
+
private void setupServerForTruncationChecks() throws SQLException {
if (getJdbcCompliantTruncation()) {
if (versionMeetsMinimum(5, 0, 2)) {
Modified: trunk/connector-j/src/com/mysql/jdbc/MysqlIO.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/MysqlIO.java 2006-10-27 21:13:18 UTC (rev 5949)
+++ trunk/connector-j/src/com/mysql/jdbc/MysqlIO.java 2006-10-27 21:17:07 UTC (rev 5950)
@@ -729,7 +729,7 @@
return !inTransactionOnServer;
}
- return !autoCommitModeOnServer;
+ return autoCommitModeOnServer != autoCommitFlag;
}
return true;
Modified: trunk/connector-j/src/com/mysql/jdbc/PreparedStatement.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/PreparedStatement.java 2006-10-27 21:13:18 UTC
(rev 5949)
+++ trunk/connector-j/src/com/mysql/jdbc/PreparedStatement.java 2006-10-27 21:17:07 UTC
(rev 5950)
@@ -1087,7 +1087,7 @@
} catch (SQLException ex) {
updateCounts[commandIndex] = EXECUTE_FAILED;
- if (locallyScopedConn.getContinueBatchOnError()) {
+ if (this.continueBatchOnError) {
sqlEx = ex;
} else {
int[] newUpdateCounts = new int[commandIndex];
@@ -2089,6 +2089,8 @@
if (x == null) {
setNull(parameterIndex, java.sql.Types.BINARY);
} else {
+ int parameterIndexOffset = getParameterIndexOffset();
+
if ((parameterIndex < 1)
|| (parameterIndex > this.staticSqlStrings.length)) {
throw SQLError.createSQLException(
@@ -2096,12 +2098,16 @@
+ parameterIndex
+ Messages.getString("PreparedStatement.3") + this.staticSqlStrings.length +
Messages.getString("PreparedStatement.4"), //$NON-NLS-1$ //$NON-NLS-2$
SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+ } else if (parameterIndexOffset == -1 && parameterIndex == 1) {
+ throw SQLError.createSQLException("Can't set IN parameter for return value of stored
function call.",
+ SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
- this.parameterStreams[parameterIndex - 1] = x;
- this.isStream[parameterIndex - 1] = true;
- this.streamLengths[parameterIndex - 1] = length;
- this.isNull[parameterIndex - 1] = false;
+
+ this.parameterStreams[parameterIndex - 1 + parameterIndexOffset] = x;
+ this.isStream[parameterIndex - 1 + parameterIndexOffset] = true;
+ this.streamLengths[parameterIndex - 1 + parameterIndexOffset] = length;
+ this.isNull[parameterIndex - 1 + parameterIndexOffset] = false;
}
}
@@ -2569,6 +2575,8 @@
SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
+ int parameterIndexOffset = getParameterIndexOffset();
+
if ((paramIndex < 1)) {
throw SQLError.createSQLException(
Messages.getString("PreparedStatement.49") //$NON-NLS-1$
@@ -2580,12 +2588,15 @@
+ paramIndex
+ Messages.getString("PreparedStatement.52") + (this.parameterValues.length) +
Messages.getString("PreparedStatement.53"), //$NON-NLS-1$ //$NON-NLS-2$
SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+ } else if (parameterIndexOffset == -1 && paramIndex == 1) {
+ throw SQLError.createSQLException("Can't set IN parameter for return value of stored
function call.",
+ SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
- this.isStream[paramIndex - 1] = false;
- this.isNull[paramIndex - 1] = false;
- this.parameterStreams[paramIndex - 1] = null;
- this.parameterValues[paramIndex - 1] = val;
+ this.isStream[paramIndex - 1 + parameterIndexOffset] = false;
+ this.isNull[paramIndex - 1 + parameterIndexOffset] = false;
+ this.parameterStreams[paramIndex - 1 + parameterIndexOffset] = null;
+ this.parameterValues[paramIndex - 1 + parameterIndexOffset] = val;
}
private final void setInternal(int paramIndex, String val)
@@ -4044,7 +4055,18 @@
public synchronized boolean isClosed() throws SQLException {
return this.isClosed;
}
-
+
+ /**
+ * For calling stored functions, this will be -1 as we don't really count
+ * the first '?' parameter marker, it's only syntax, but JDBC counts it
+ * as #1, otherwise it will return 0
+ *
+ */
+
+ protected int getParameterIndexOffset() {
+ return 0;
+ }
+
/**
* JDBC 4.0 Set a NCLOB parameter.
*
Modified: trunk/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java 2006-10-27 21:13:18
UTC (rev 5949)
+++ trunk/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java 2006-10-27 21:17:07
UTC (rev 5950)
@@ -643,7 +643,7 @@
} catch (SQLException ex) {
updateCounts[commandIndex] = EXECUTE_FAILED;
- if (this.connection.getContinueBatchOnError()) {
+ if (this.continueBatchOnError) {
sqlEx = ex;
} else {
int[] newUpdateCounts = new int[commandIndex];
Modified: trunk/connector-j/src/com/mysql/jdbc/Statement.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/Statement.java 2006-10-27 21:13:18 UTC (rev 5949)
+++ trunk/connector-j/src/com/mysql/jdbc/Statement.java 2006-10-27 21:17:07 UTC (rev 5950)
@@ -231,10 +231,12 @@
*/
protected boolean holdResultsOpenOverClose = false;
-protected ArrayList batchedGeneratedKeys = null;
+ protected ArrayList batchedGeneratedKeys = null;
protected boolean retrieveGeneratedKeys = false;
+ protected boolean continueBatchOnError = false;
+
/**
* Constructor for a Statement.
*
@@ -258,7 +260,8 @@
this.currentCatalog = catalog;
this.pedantic = this.connection.getPedantic();
-
+ this.continueBatchOnError = this.connection.getContinueBatchOnError();
+
if (!this.connection.getDontTrackOpenResources()) {
this.connection.registerStatement(this);
}
@@ -897,7 +900,7 @@
} catch (SQLException ex) {
updateCounts[commandIndex] = EXECUTE_FAILED;
- if (locallyScopedConn.getContinueBatchOnError()) {
+ if (this.continueBatchOnError) {
sqlEx = ex;
} else {
int[] newUpdateCounts = new int[commandIndex];
Modified: trunk/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java
===================================================================
---
trunk/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java 2006-10-27
21:13:18 UTC (rev 5949)
+++
trunk/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java 2006-10-27
21:17:07 UTC (rev 5950)
@@ -467,11 +467,17 @@
try {
this.stmt.executeUpdate("DROP FUNCTION IF EXISTS testBug10310");
this.stmt
- .executeUpdate("CREATE FUNCTION testBug10310(a float) RETURNS INT"
+ .executeUpdate("CREATE FUNCTION testBug10310(a float, b bigint, c int) RETURNS INT"
+ "\nBEGIN" + "\nRETURN a;" + "\nEND");
- cStmt = this.conn.prepareCall("{? = CALL testBug10310(?)}");
+ cStmt = this.conn.prepareCall("{? = CALL testBug10310(?,?,?)}");
cStmt.registerOutParameter(1, Types.INTEGER);
- cStmt.setFloat(1, 2);
+ cStmt.setFloat(2, 2);
+ cStmt.setInt(3, 1);
+ cStmt.setInt(4, 1);
+
+ assertEquals(4, cStmt.getParameterMetaData().getParameterCount());
+ assertEquals(Types.OTHER, cStmt.getParameterMetaData().getParameterType(1));
+
assertFalse(cStmt.execute());
assertEquals(2f, cStmt.getInt(1), .001);
assertEquals("java.lang.Integer", cStmt.getObject(1).getClass()
@@ -482,6 +488,20 @@
assertEquals("java.lang.Integer", cStmt.getObject(1).getClass()
.getName());
+ cStmt.setFloat("a", 4);
+ cStmt.setInt("b", 1);
+ cStmt.setInt("c", 1);
+
+ assertFalse(cStmt.execute());
+ assertEquals(4f, cStmt.getInt(1), .001);
+ assertEquals("java.lang.Integer", cStmt.getObject(1).getClass()
+ .getName());
+
+ assertEquals(-1, cStmt.executeUpdate());
+ assertEquals(4f, cStmt.getInt(1), .001);
+ assertEquals("java.lang.Integer", cStmt.getObject(1).getClass()
+ .getName());
+
// Check metadata while we're at it
java.sql.DatabaseMetaData dbmd = this.conn.getMetaData();
@@ -493,8 +513,10 @@
.getString("PROCEDURE_NAME"));
assertEquals(DatabaseMetaData.procedureReturnsResult, this.rs
.getShort("PROCEDURE_TYPE"));
- cStmt.setNull(1, Types.FLOAT);
-
+ cStmt.setNull(2, Types.FLOAT);
+ cStmt.setInt(3, 1);
+ cStmt.setInt(4, 1);
+
assertFalse(cStmt.execute());
assertEquals(0f, cStmt.getInt(1), .001);
assertEquals(true, cStmt.wasNull());
@@ -507,6 +529,25 @@
assertEquals(null, cStmt.getObject(1));
assertEquals(true, cStmt.wasNull());
+
+ // Check with literals, not all parameters filled!
+ cStmt = this.conn.prepareCall("{? = CALL testBug10310(4,5,?)}");
+ cStmt.registerOutParameter(1, Types.INTEGER);
+ cStmt.setInt(2, 1);
+
+ assertFalse(cStmt.execute());
+ assertEquals(4f, cStmt.getInt(1), .001);
+ assertEquals("java.lang.Integer", cStmt.getObject(1).getClass()
+ .getName());
+
+ assertEquals(-1, cStmt.executeUpdate());
+ assertEquals(4f, cStmt.getInt(1), .001);
+ assertEquals("java.lang.Integer", cStmt.getObject(1).getClass()
+ .getName());
+
+ assertEquals(2, cStmt.getParameterMetaData().getParameterCount());
+ assertEquals(Types.OTHER, cStmt.getParameterMetaData().getParameterType(1));
+ assertEquals(Types.INTEGER, cStmt.getParameterMetaData().getParameterType(2));
} finally {
if (this.rs != null) {
this.rs.close();
Modified: trunk/connector-j/src/testsuite/regression/StringRegressionTest.java
===================================================================
--- trunk/connector-j/src/testsuite/regression/StringRegressionTest.java 2006-10-27
21:13:18 UTC (rev 5949)
+++ trunk/connector-j/src/testsuite/regression/StringRegressionTest.java 2006-10-27
21:17:07 UTC (rev 5950)
@@ -36,6 +36,7 @@
import testsuite.BaseTestCase;
+import com.mysql.jdbc.CharsetMapping;
import com.mysql.jdbc.StringUtils;
/**
@@ -835,4 +836,50 @@
assertEquals(this.rs.getString(1), codePage1252);
}
}
+
+ /**
+ * Tests fix for BUG#23645 - Some collations/character sets reported as "unknown"
+ * (specifically cias variants of existing character sets), and inability to override
+ * the detected server character set.
+ *
+ * @throws Exception if the test fails.
+ */
+ public void testBug23645() throws Exception {
+ if (versionMeetsMinimum(4, 1)) {
+ // Part of this isn't easily testable, hence the assertion in CharsetMapping
+ // that checks for mappings existing in both directions...
+
+ // What we test here is the ability to override the character mapping
+ // when the server returns an "unknown" character encoding.
+
+ String currentlyConfiguredCharacterSet = getSingleIndexedValueWithQuery(2, "SHOW
VARIABLES LIKE 'character_set_connection'").toString();
+ System.out.println(currentlyConfiguredCharacterSet);
+
+ String javaNameForMysqlName =
CharsetMapping.getJavaEncodingForMysqlEncoding(currentlyConfiguredCharacterSet, null);
+ System.out.println(javaNameForMysqlName);
+
+ for (int i = 1; i < CharsetMapping.INDEX_TO_CHARSET.length; i++) {
+ String possibleCharset = CharsetMapping.INDEX_TO_CHARSET[i];
+
+ if (!javaNameForMysqlName.equals(possibleCharset)) {
+ System.out.println(possibleCharset);
+
+ Properties props = new Properties();
+ props.setProperty("characterEncoding", possibleCharset);
+ props.setProperty("com.mysql.jdbc.faultInjection.serverCharsetIndex", "65535");
+
+ Connection forcedCharConn = null;
+
+ forcedCharConn = getConnectionWithProps(props);
+
+ String forcedCharset = getSingleIndexedValueWithQuery(forcedCharConn, 2, "SHOW
VARIABLES LIKE 'character_set_connection'").toString();
+
+ System.out.println(forcedCharset);
+
+ break;
+ }
+ }
+
+ }
+ }
}
| Thread |
|---|
| • Connector/J commit: r5950 - in trunk/connector-j: . src/com/mysql/jdbc src/testsuite/regression | mmatthews | 27 Oct |