Mercurial > hg > monetdb-java
comparison src/main/java/org/monetdb/jdbc/MonetDatabaseMetaData.java @ 427:e79bfbd0553e
Added support for escaped wildcards (\% en \_) in String arguments of
DatabaseMetaData methods which return a ResultSet, such as getTables(),
getColumns(), etc. When you do not want the characters % or _ to be
interpreted as wildcards but as normal characters you can prefix them
with a backslash (so \% and \_).
Note: be sure all wildcards characters in the String argument are escaped
else the search must still use a LIKE operator instead of an = comparison operator.
This fixes: https://github.com/MonetDB/monetdb-java/issues/3
author | Martin van Dinther <martin.van.dinther@monetdbsolutions.com> |
---|---|
date | Wed, 03 Feb 2021 19:41:44 +0100 (2021-02-03) |
parents | 95d15f1d750d |
children | 3924a8516d7b |
comparison
equal
deleted
inserted
replaced
426:3da79315783b | 427:e79bfbd0553e |
---|---|
4087 } | 4087 } |
4088 return rs; | 4088 return rs; |
4089 } | 4089 } |
4090 | 4090 |
4091 /** | 4091 /** |
4092 * Returns a SQL match part string where depending on the input value we | 4092 * Returns a SQL match part string where depending on the input value we compose |
4093 * compose an exact match (use =) or match with wildcards (use LIKE) or IS NULL | 4093 * - an exact string match (using = comparator) or |
4094 * - a match with wildcards (using LIKE comparator) or | |
4095 * - when input is missing (using IS NULL comparator) | |
4096 * | |
4097 * Note that wildcard characters can be escaped by prefix \ (a backslash) | |
4098 * When ALL wildcard characters are escaped then we remove the \'s and compose an = comparator string match. | |
4094 * | 4099 * |
4095 * @param in the string to match | 4100 * @param in the string to match |
4096 * @return the SQL match part string | 4101 * @return the SQL match part string |
4097 */ | 4102 */ |
4098 private final String composeMatchPart(final String in) { | 4103 private final String composeMatchPart(final String in) { |
4099 if (in == null) | 4104 if (in == null) |
4100 return "IS NULL"; | 4105 return "IS NULL"; |
4101 | 4106 |
4102 String cmp = "= "; | 4107 // Scan input string for SQL wildcard characters: % and _ |
4103 // check if SQL wildcards are used in the input, if so use LIKE | 4108 // When they are all prefixed by a backslash then the backslash is removed (to allow usage of = comparator) |
4104 if (in.contains("%") || in.contains("_")) | 4109 // else it needs to be interpreted as a wildcard and we need to use LIKE instead of = comparator. |
4105 cmp = "LIKE "; | 4110 // A backslash can be escaped by using two backslashes. |
4106 | 4111 final int len = in.length(); |
4107 return cmp + MonetWrapper.sq(in); | 4112 final StringBuilder sb = new StringBuilder(len); |
4113 boolean removed_bs = false; | |
4114 boolean use_like = false; | |
4115 boolean escaped = false; | |
4116 try { | |
4117 // parse all characters in input to find if the wildcards are escaped by a \. | |
4118 // note: the escape character \ can also be escaped, so \\. | |
4119 for (int i = 0; i < len; i++) { | |
4120 char c = in.charAt(i); | |
4121 switch(c) { | |
4122 case '\\': | |
4123 if (escaped) { | |
4124 // copy the 2 backslash characters as in the original string | |
4125 sb.append(c).append(c); | |
4126 escaped = false; | |
4127 } else { | |
4128 escaped = true; | |
4129 } | |
4130 break; | |
4131 case '%': | |
4132 case '_': | |
4133 if (escaped) { | |
4134 removed_bs = true; | |
4135 escaped = false; | |
4136 } else { | |
4137 use_like = true; | |
4138 i = len; /* no need to scan further */ | |
4139 } | |
4140 sb.append(c); | |
4141 break; | |
4142 default: | |
4143 if (escaped) { | |
4144 sb.append('\\'); // also copy the preceding escape found before this character | |
4145 escaped = false; | |
4146 } | |
4147 sb.append(c); | |
4148 break; | |
4149 } | |
4150 } | |
4151 } catch (IndexOutOfBoundsException iob) { | |
4152 /* ignore */ | |
4153 } | |
4154 | |
4155 if (use_like) { | |
4156 // for debug: System.out.println("input: " + in + " changed into: " + "LIKE " + MonetWrapper.sq(in)); | |
4157 // we found a non-escaped wildcard character, use like and the original input | |
4158 return "LIKE " + MonetWrapper.sq(in); | |
4159 } | |
4160 if (removed_bs) { | |
4161 // for debug: System.out.println("input: " + in + " changed into: " + "= " + MonetWrapper.sq(sb.toString())); | |
4162 // we found only escaped wildcard character(s), | |
4163 // use the edited string without the ecapes before the wildcard character(s) so an equals match can be done (its is faster than LIKE) | |
4164 return "= " + MonetWrapper.sq(sb.toString()); | |
4165 } | |
4166 // for debug: System.out.println("input: " + in + " changed into: " + "= " + MonetWrapper.sq(in)); | |
4167 return "= " + MonetWrapper.sq(in); | |
4108 } | 4168 } |
4109 | 4169 |
4110 //== end helper methods | 4170 //== end helper methods |
4111 } | 4171 } |