changeset 370:2ab474af487c

Add utility method to replace calls to x.replaceAll().replaceAll() in several places.
author Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
date Thu, 17 Sep 2020 17:33:49 +0200 (2020-09-17)
parents aa2e5d8c5047
children 67fa5c6147d7
files src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java
diffstat 3 files changed, 30 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java
@@ -1640,6 +1640,8 @@ public class MonetConnection
 	//== end methods of interface java.sql.Connection
 
 
+	//== internal helper methods which do not belong to the JDBC interface
+
 	/**
 	 * @return whether the JDBC BLOB type should be mapped to VARBINARY type.
 	 * This allows generic JDBC programs to fetch Blob data via getBytes()
@@ -1683,6 +1685,23 @@ public class MonetConnection
 		return sb.toString();
 	}
 
+	/**
+	 * Utility method to escape all ocurrences of special characters
+	 * (double slashes and single quotes) in a string literal
+	 * It is called from: MonetDatabaseMetaData and MonetPreparedStatement
+	 */
+	final String escapeSpecialChars(final String in) {
+		String ret = in;
+		if (ret.contains("\\\\"))
+			// all double slashes in input need to be escaped.
+			ret = ret.replaceAll("\\\\", "\\\\\\\\");
+		if (ret.contains("'"))
+			// all single quotes in input need to be escaped.
+			ret = ret.replaceAll("'", "\\\\'");
+		return ret;
+	}
+
+
 	// Internal cache for 3 static mserver environment values, so they aren't queried from mserver again and again
 	private String env_current_user = null;
 	private String env_monet_version = null;
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java
@@ -4035,7 +4035,7 @@ public class MonetDatabaseMetaData
 	 * As the Statement object is created internally (the caller does not see it and thus can not close it),
 	 * we set it to close (and free server resources) when the ResultSet object is closed by the caller.
 	 */
-	private ResultSet executeMetaDataQuery(final String query) throws SQLException {
+	private final ResultSet executeMetaDataQuery(final String query) throws SQLException {
 		final Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
 		ResultSet rs = null;
 		if (stmt != null) {
@@ -4059,7 +4059,7 @@ public class MonetDatabaseMetaData
 	 * @param in the string to match
 	 * @return the SQL match part string
 	 */
-	private static final String composeMatchPart(final String in) {
+	private final String composeMatchPart(final String in) {
 		if (in == null)
 			return "IS NULL";
 
@@ -4068,12 +4068,7 @@ public class MonetDatabaseMetaData
 		if (in.contains("%") || in.contains("_"))
 			cmp = "LIKE '";
 
-		String val = in;
-		if (in.contains("\\") || in.contains("'"))
-			// all slashes and single quotes in input are escaped with a slash.
-			val = in.replaceAll("\\\\", "\\\\\\\\").replaceAll("'", "\\\\'");
-
-		return cmp + val + "'";
+		return cmp + con.escapeSpecialChars(in) + "'";
 	}
 
 	/**
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java
@@ -2014,9 +2014,7 @@ public class MonetPreparedStatement
 					// representation is given, but we need to prefix it
 					// with the actual sqltype the server expects, or we
 					// will get an error back
-					setValue(paramnr,
-						sqltype + " '" + x.replaceAll("\\\\", "\\\\\\\\").replaceAll("'", "\\\\'") + "'"
-					);
+					setValue(paramnr, sqltype + " '" + connection.escapeSpecialChars(x) + "'");
 				}
 
 				@Override
@@ -2245,7 +2243,7 @@ public class MonetPreparedStatement
 						} catch (SQLException se) {
 							throw new SQLDataException("Conversion of string: " + x + " to parameter data type " + paramMonetdbType + " failed. " + se.getMessage(), "22M29");
 						}
-						castprefix = "inet ";
+						castprefix = "inet";
 						break;
 					case "json":
 						// There is no support for JSON in standard java class libraries.
@@ -2266,7 +2264,7 @@ public class MonetPreparedStatement
 
 						// TODO check completely if x represents a valid json string
 
-						castprefix = "json ";
+						castprefix = "json";
 						break;
 					case "url":
 						try {
@@ -2276,7 +2274,7 @@ public class MonetPreparedStatement
 						} catch (java.net.MalformedURLException mue) {
 							throw new SQLDataException("Conversion of string: " + x + " to parameter data type " + paramMonetdbType + " failed. " + mue.getMessage(), "22M30");
 						}
-						castprefix = "url ";
+						castprefix = "url";
 						break;
 					case "uuid":
 						try {
@@ -2286,11 +2284,12 @@ public class MonetPreparedStatement
 						} catch (IllegalArgumentException iae) {
 							throw new SQLDataException("Conversion of string: " + x + " to parameter data type " + paramMonetdbType + " failed. " + iae.getMessage(), "22M31");
 						}
-						castprefix = "uuid ";
+						castprefix = "uuid";
 						break;
 				}
 				/* in specific cases prefix the string with: inet or json or url or uuid */
-				setValue(parameterIndex, castprefix + "'" + x.replaceAll("\\\\", "\\\\\\\\").replaceAll("'", "\\\\'") + "'");
+				setValue(parameterIndex, castprefix + " '" + connection.escapeSpecialChars(x) + "'");
+
 				break;
 			}
 			case Types.TINYINT:
@@ -2574,7 +2573,7 @@ public class MonetPreparedStatement
 			return;
 		}
 
-		setValue(parameterIndex, "url '" + x.toString().replaceAll("\\\\", "\\\\\\\\").replaceAll("'", "\\\\'") + "'");
+		setValue(parameterIndex, "url '" + connection.escapeSpecialChars(x.toString()) + "'");
 	}
 
 	/**