WEBから入力された検索ワードをDB検索に使う場合、
SQLインジェクション対策のため通常PreparedStatementを使用しますが、
MySQLでProcedureなどを使ったときに、ダブルクオーテーションを使用しないといけないことがあります。
こんなん
CALL somethingFunc("table={WORD}")
通常以下のようにしたいところですが、
CALL somethingFunc("table=?")
JDBCの実装で
com.mysql.jdbc.PreparedStatement if ((c == '?') && !inQuotes && !inQuotedId) { endpointList.add(new int[] { lastParmEnd, i }); lastParmEnd = i + 1; if (isOnDuplicateKeyUpdate && i > locationOfOnDuplicateKeyUpdate) { parametersInDuplicateKeyClause = true; } }
というのがあり、クオートの中の?は除外するようになっています。
そのため自前でエスケープをするする必要があります。
幸いJDBCのソースにそうゆうのがあるのでそのまま使ってしまいます。
public static String getEscapedStringForMysql(String text) { if (StringUtils.isEmpty(text)) { return text; } StringBuffer buf = new StringBuffer(); for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); switch (c) { case 0: /* Must be escaped for 'mysql' */ buf.append('\\'); buf.append('0'); break; case '\n': /* Must be escaped for logs */ buf.append('\\'); buf.append('n'); break; case '\r': buf.append('\\'); buf.append('r'); break; case '\\': buf.append('\\'); buf.append('\\'); break; case '\'': buf.append('\\'); buf.append('\''); break; case '"': /* Better safe than sorry */ buf.append('\\'); buf.append('"'); break; case '32': /* This gives problems on Win32 */ buf.append('\\'); buf.append('Z'); break; default: buf.append(c); } } return buf.toString(); }