Skip to content
Permalink
Browse files

[CONJ-717] correction to support scalar for MySQL

  • Loading branch information...
rusher committed Aug 2, 2019
1 parent 5cdf785 commit fe789ffdad694d55605a363f9003b5e65763ff67
@@ -522,7 +522,7 @@ private PreparedStatement internalPrepareStatement(final String sql,

if (sql != null) {

String sqlQuery = Utils.nativeSql(sql, protocol.noBackslashEscapes());
String sqlQuery = Utils.nativeSql(sql, protocol);

if (options.useServerPrepStmts && PREPARABLE_STATEMENT_PATTERN.matcher(sqlQuery).find()) {
//prepare isn't delayed -> if prepare fail, fallback to client preparedStatement?
@@ -608,7 +608,7 @@ public CallableStatement prepareCall(final String sql, final int resultSetType,
+ sql);
}

String query = Utils.nativeSql(matcher.group(2), protocol.noBackslashEscapes());
String query = Utils.nativeSql(matcher.group(2), protocol);

boolean isFunction = (matcher.group(3) != null);
String databaseAndProcedure = matcher.group(8);
@@ -712,7 +712,7 @@ private CallableStatement createNewCallableStatement(String query, String proced

@Override
public String nativeSQL(final String sql) throws SQLException {
return Utils.nativeSql(sql, protocol.noBackslashEscapes());
return Utils.nativeSql(sql, protocol);
}

/**
@@ -330,7 +330,7 @@ private boolean executeInternal(String sql, int fetchSize, int autoGeneratedKeys
sql, null);

protocol.executeQuery(protocol.isMasterConnection(), results,
getTimeoutSql(Utils.nativeSql(sql, protocol.noBackslashEscapes())));
getTimeoutSql(Utils.nativeSql(sql, protocol)));
results.commandEnd();
return results.getResultSet() != null;

@@ -366,7 +366,7 @@ public boolean testExecute(String sql, Charset charset) throws SQLException {
results = new Results(this, fetchSize, false, 1, false, resultSetScrollType,
resultSetConcurrency, Statement.NO_GENERATED_KEYS, protocol.getAutoIncrementIncrement(), sql, null);
protocol.executeQuery(protocol.isMasterConnection(), results,
getTimeoutSql(Utils.nativeSql(sql, protocol.noBackslashEscapes())), charset);
getTimeoutSql(Utils.nativeSql(sql, protocol)), charset);
results.commandEnd();
return results.getResultSet() != null;

@@ -95,7 +95,7 @@ public short getErrorNumber() {
}

public String getSqlState() {
return new String(sqlState);
return sqlState;
}

public byte getSqlStateMarker() {
@@ -432,6 +432,10 @@ public boolean versionGreaterOrEqual(int major, int minor, int patch) {
return currentProtocol.versionGreaterOrEqual(major, minor, patch);
}

public boolean isServerMariaDb() {
return currentProtocol.isServerMariaDb();
}

public boolean sessionStateAware() {
return currentProtocol.sessionStateAware();
}
@@ -95,6 +95,7 @@
private static final String METHOD_GET_TIMEOUT = "getTimeout";
private static final String METHOD_GET_MAJOR_VERSION = "getMajorServerVersion";
private static final String METHOD_IN_TRANSACTION = "inTransaction";
private static final String METHOD_IS_MARIADB = "isServerMariaDb";


private static final Logger logger = LoggerFactory.getLogger(FailoverProxy.class);
@@ -157,6 +158,8 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl
return this.lock;
case METHOD_GET_NO_BACKSLASH:
return listener.noBackslashEscapes();
case METHOD_IS_MARIADB:
return listener.isServerMariaDb();
case METHOD_GET_CATALOG:
return listener.getCatalog();
case METHOD_GET_TIMEOUT:
@@ -129,6 +129,8 @@ void throwFailoverMessage(HostAddress failHostAddress, boolean wasMaster,

boolean versionGreaterOrEqual(int major, int minor, int patch);

boolean isServerMariaDb();

boolean sessionStateAware();

boolean noBackslashEscapes();
@@ -235,6 +235,12 @@ public boolean versionGreaterOrEqual(int major, int minor, int patch) {
return protocol.versionGreaterOrEqual(major, minor, patch);
}

@Override
public boolean isServerMariaDb() {
Protocol protocol = (currentProtocol != null) ? currentProtocol : secondaryProtocol;
return (protocol == null) ? false : protocol.isServerMariaDb();
}

@Override
public boolean sessionStateAware() {
Protocol protocol = (currentProtocol != null) ? currentProtocol : secondaryProtocol;
@@ -268,7 +268,7 @@ void resetStateAfterFailover(long maxRows, int transactionIsolationLevel, String

void setActiveFutureTask(FutureTask activeFutureTask);

boolean isServerMariaDb() throws SQLException;
boolean isServerMariaDb();

SQLException handleIoException(Exception initialException);

@@ -267,10 +267,11 @@ public static String escapeString(String value, boolean noBackslashEscapes) {
* <p>caution: this use MariaDB server conversion: 'SELECT CONVERT('2147483648', INTEGER)' will
* return a BIGINT. MySQL will throw a syntax error.</p>
*
* @param functionString - input string
* @param functionString input string
* @param protocol protocol
* @return unescaped string
*/
private static String replaceFunctionParameter(String functionString) {
private static String replaceFunctionParameter(String functionString, Protocol protocol) {

char[] input = functionString.toCharArray();
StringBuilder sb = new StringBuilder();
@@ -293,7 +294,8 @@ private static String replaceFunctionParameter(String functionString) {
// Handle "convert(value, type)" case
// extract last parameter, after the last ','
int lastCommaIndex = functionString.lastIndexOf(',');

int firstParentheses = functionString.indexOf('(');
String value = functionString.substring(firstParentheses + 1, lastCommaIndex);
for (index = lastCommaIndex + 1; index < input.length; index++) {
if (!Character.isWhitespace(input[index])) {
break;
@@ -314,12 +316,17 @@ private static String replaceFunctionParameter(String functionString) {
}

switch (typeParam) {
case "BIGINT":
case "BOOLEAN":
return "1=" + value;

case "BIGINT":
case "SMALLINT":
case "TINYINT":
typeParam = "SIGNED INTEGER";
break;

case "BIT":
typeParam = "INTEGER";
typeParam = "UNSIGNED INTEGER";
break;

case "BLOB":
@@ -342,9 +349,13 @@ private static String replaceFunctionParameter(String functionString) {
typeParam = "CHAR";
break;

case "DOUBLE":
case "FLOAT":
typeParam = "DOUBLE";
break;
if (protocol.isServerMariaDb() || protocol.versionGreaterOrEqual(8,0,17)) {
typeParam = "DOUBLE";
break;
}
return "0.0+" + value;

case "REAL":
case "NUMERIC":
@@ -384,20 +395,20 @@ private static String replaceFunctionParameter(String functionString) {
}
}

private static String resolveEscapes(String escaped, boolean noBackslashEscapes)
private static String resolveEscapes(String escaped, Protocol protocol)
throws SQLException {
if (escaped.charAt(0) != '{' || escaped.charAt(escaped.length() - 1) != '}') {
throw new SQLException("unexpected escaped string");
}
int endIndex = escaped.length() - 1;
String escapedLower = escaped.toLowerCase(Locale.ROOT);
if (escaped.startsWith("{fn ")) {
String resolvedParams = replaceFunctionParameter(escaped.substring(4, endIndex));
return nativeSql(resolvedParams, noBackslashEscapes);
String resolvedParams = replaceFunctionParameter(escaped.substring(4, endIndex), protocol);
return nativeSql(resolvedParams, protocol);
} else if (escapedLower.startsWith("{oj ")) {
// Outer join
// the server supports "oj" in any case, even "oJ"
return nativeSql(escaped.substring(4, endIndex), noBackslashEscapes);
return nativeSql(escaped.substring(4, endIndex), protocol);
} else if (escaped.startsWith("{d ")) {
// date literal
return escaped.substring(3, endIndex);
@@ -420,19 +431,19 @@ private static String resolveEscapes(String escaped, boolean noBackslashEscapes)
// We support uppercase "{CALL" only because Connector/J supports it. It is not in the JDBC
// spec.

return nativeSql(escaped.substring(1, endIndex), noBackslashEscapes);
return nativeSql(escaped.substring(1, endIndex), protocol);
} else if (escaped.startsWith("{escape ")) {
return escaped.substring(1, endIndex);
} else if (escaped.startsWith("{?")) {
// likely ?=call(...)
return nativeSql(escaped.substring(1, endIndex), noBackslashEscapes);
return nativeSql(escaped.substring(1, endIndex), protocol);
} else if (escaped.startsWith("{ ") || escaped.startsWith("{\n")) {
// Spaces and newlines before keyword, this is not JDBC compliant, however some it works in
// some drivers,
// so we support it, too
for (int i = 2; i < escaped.length(); i++) {
if (!Character.isWhitespace(escaped.charAt(i))) {
return resolveEscapes("{" + escaped.substring(i), noBackslashEscapes);
return resolveEscapes("{" + escaped.substring(i), protocol);
}
}
} else if (escaped.startsWith("{\r\n")) {
@@ -441,7 +452,7 @@ private static String resolveEscapes(String escaped, boolean noBackslashEscapes)
// so we support it, too
for (int i = 3; i < escaped.length(); i++) {
if (!Character.isWhitespace(escaped.charAt(i))) {
return resolveEscapes("{" + escaped.substring(i), noBackslashEscapes);
return resolveEscapes("{" + escaped.substring(i), protocol);
}
}
}
@@ -452,12 +463,12 @@ private static String resolveEscapes(String escaped, boolean noBackslashEscapes)
* Escape sql String.
*
* @param sql initial sql
* @param noBackslashEscapes must backslash be escape
* @param protocol protocol
* @return escaped sql string
* @throws SQLException if escape sequence is incorrect.
*/
@SuppressWarnings("ConstantConditions")
public static String nativeSql(String sql, boolean noBackslashEscapes) throws SQLException {
public static String nativeSql(String sql, Protocol protocol) throws SQLException {
if (!sql.contains("{")) {
return sql;
}
@@ -475,7 +486,7 @@ public static String nativeSql(String sql, boolean noBackslashEscapes) throws SQ

for (int i = 0; i < charArray.length; i++) {
char car = charArray[i];
if (lastChar == '\\' && !noBackslashEscapes) {
if (lastChar == '\\' && !protocol.noBackslashEscapes()) {
sqlBuffer.append(car);
continue;
}
@@ -539,7 +550,7 @@ public static String nativeSql(String sql, boolean noBackslashEscapes) throws SQ
inEscapeSeq--;
if (inEscapeSeq == 0) {
escapeSequenceBuf.append(car);
sqlBuffer.append(resolveEscapes(escapeSequenceBuf.toString(), noBackslashEscapes));
sqlBuffer.append(resolveEscapes(escapeSequenceBuf.toString(), protocol));
escapeSequenceBuf.setLength(0);
continue;
}

0 comments on commit fe789ff

Please sign in to comment.
You can’t perform that action at this time.