1 package org.hibernate.sql; 3 4 import java.util.HashSet ; 5 import java.util.StringTokenizer ; 6 7 import org.hibernate.dialect.Dialect; 8 import org.hibernate.util.StringHelper; 9 10 15 public final class Template { 16 17 private static final java.util.Set KEYWORDS = new HashSet (); 18 private static final java.util.Set BEFORE_TABLE_KEYWORDS = new HashSet (); 19 private static final java.util.Set FUNCTION_KEYWORDS = new HashSet (); 20 static { 21 KEYWORDS.add("and"); 22 KEYWORDS.add("or"); 23 KEYWORDS.add("not"); 24 KEYWORDS.add("like"); 25 KEYWORDS.add("is"); 26 KEYWORDS.add("in"); 27 KEYWORDS.add("between"); 28 KEYWORDS.add("null"); 29 KEYWORDS.add("select"); 30 KEYWORDS.add("distinct"); 31 KEYWORDS.add("from"); 32 KEYWORDS.add("join"); 33 KEYWORDS.add("inner"); 34 KEYWORDS.add("outer"); 35 KEYWORDS.add("left"); 36 KEYWORDS.add("right"); 37 KEYWORDS.add("on"); 38 KEYWORDS.add("where"); 39 KEYWORDS.add("having"); 40 KEYWORDS.add("group"); 41 KEYWORDS.add("order"); 42 KEYWORDS.add("by"); 43 KEYWORDS.add("desc"); 44 KEYWORDS.add("asc"); 45 KEYWORDS.add("limit"); 46 KEYWORDS.add("any"); 47 KEYWORDS.add("some"); 48 KEYWORDS.add("exists"); 49 KEYWORDS.add("all"); 50 51 BEFORE_TABLE_KEYWORDS.add("from"); 52 BEFORE_TABLE_KEYWORDS.add("join"); 53 54 FUNCTION_KEYWORDS.add("as"); 55 FUNCTION_KEYWORDS.add("leading"); 56 FUNCTION_KEYWORDS.add("trailing"); 57 FUNCTION_KEYWORDS.add("from"); 58 FUNCTION_KEYWORDS.add("case"); 59 FUNCTION_KEYWORDS.add("when"); 60 FUNCTION_KEYWORDS.add("then"); 61 FUNCTION_KEYWORDS.add("else"); 62 FUNCTION_KEYWORDS.add("end"); 63 FUNCTION_KEYWORDS.add("current"); 65 FUNCTION_KEYWORDS.add("date"); 66 FUNCTION_KEYWORDS.add("time"); 67 FUNCTION_KEYWORDS.add("timestamp"); 68 } 69 70 public static final String TEMPLATE = "$PlaceHolder$"; 71 72 private Template() {} 73 74 public static String renderWhereStringTemplate(String sqlWhereString, Dialect dialect) { 75 return renderWhereStringTemplate(sqlWhereString, TEMPLATE, dialect); 76 } 77 78 83 public static String renderWhereStringTemplate(String sqlWhereString, String placeholder, Dialect dialect) { 84 String symbols = new StringBuffer () 86 .append("=><!+-*/()',|&`") 87 .append(StringHelper.WHITESPACE) 88 .append( dialect.openQuote() ) 89 .append( dialect.closeQuote() ) 90 .toString(); 91 StringTokenizer tokens = new StringTokenizer (sqlWhereString, symbols, true); 92 93 StringBuffer result = new StringBuffer (); 94 boolean quoted = false; 95 boolean quotedIdentifier = false; 96 boolean beforeTable = false; 97 boolean inFromClause = false; 98 boolean afterFromTable = false; 99 100 boolean hasMore = tokens.hasMoreTokens(); 101 String nextToken = hasMore ? tokens.nextToken() : null; 102 while (hasMore) { 103 String token = nextToken; 104 String lcToken = token.toLowerCase(); 105 hasMore = tokens.hasMoreTokens(); 106 nextToken = hasMore ? tokens.nextToken() : null; 107 108 boolean isQuoteCharacter = false; 109 110 if ( !quotedIdentifier && "'".equals(token) ) { 111 quoted = !quoted; 112 isQuoteCharacter = true; 113 } 114 115 if ( !quoted ) { 116 117 boolean isOpenQuote; 118 if ( "`".equals(token) ) { 119 isOpenQuote = !quotedIdentifier; 120 token = lcToken = isOpenQuote ? 121 new Character ( dialect.openQuote() ).toString() : 122 new Character ( dialect.closeQuote() ).toString(); 123 quotedIdentifier = isOpenQuote; 124 isQuoteCharacter = true; 125 } 126 else if ( !quotedIdentifier && ( dialect.openQuote()==token.charAt(0) ) ) { 127 isOpenQuote = true; 128 quotedIdentifier = true; 129 isQuoteCharacter = true; 130 } 131 else if ( quotedIdentifier && ( dialect.closeQuote()==token.charAt(0) ) ) { 132 quotedIdentifier = false; 133 isQuoteCharacter = true; 134 isOpenQuote = false; 135 } 136 else { 137 isOpenQuote = false; 138 } 139 140 if (isOpenQuote) { 141 result.append(TEMPLATE).append('.'); 142 } 143 144 } 145 146 boolean quotedOrWhitespace = quoted || 147 quotedIdentifier || 148 isQuoteCharacter || 149 Character.isWhitespace( token.charAt(0) ); 150 151 if (quotedOrWhitespace) { 152 result.append(token); 153 } 154 else if (beforeTable) { 155 result.append(token); 156 beforeTable = false; 157 afterFromTable = true; 158 } 159 else if (afterFromTable) { 160 if ( !"as".equals(lcToken) ) afterFromTable = false; 161 result.append(token); 162 } 163 else if ( isNamedParameter(token) ) { 164 result.append(token); 165 } 166 else if ( 167 isIdentifier(token, dialect) && 168 !isFunctionOrKeyword(lcToken, nextToken, dialect) 169 ) { 170 result.append(placeholder) 171 .append('.') 172 .append( dialect.quote(token) ); 173 } 174 else { 175 if ( BEFORE_TABLE_KEYWORDS.contains(lcToken) ) { 176 beforeTable = true; 177 inFromClause = true; 178 } 179 else if ( inFromClause && ",".equals(lcToken) ) { 180 beforeTable = true; 181 } 182 result.append(token); 183 } 184 185 if ( inFromClause && 187 KEYWORDS.contains(lcToken) && !BEFORE_TABLE_KEYWORDS.contains(lcToken) 189 ) { 190 inFromClause = false; 191 } 192 193 } 194 return result.toString(); 195 } 196 197 201 public static String renderOrderByStringTemplate(String sqlOrderByString, Dialect dialect) { 202 String symbols = new StringBuffer () 204 .append("=><!+-*/()',|&`") 205 .append(StringHelper.WHITESPACE) 206 .append( dialect.openQuote() ) 207 .append( dialect.closeQuote() ) 208 .toString(); 209 StringTokenizer tokens = new StringTokenizer (sqlOrderByString, symbols, true); 210 211 StringBuffer result = new StringBuffer (); 212 boolean quoted = false; 213 boolean quotedIdentifier = false; 214 215 boolean hasMore = tokens.hasMoreTokens(); 216 String nextToken = hasMore ? tokens.nextToken() : null; 217 while (hasMore) { 218 String token = nextToken; 219 String lcToken = token.toLowerCase(); 220 hasMore = tokens.hasMoreTokens(); 221 nextToken = hasMore ? tokens.nextToken() : null; 222 223 boolean isQuoteCharacter = false; 224 225 if ( !quotedIdentifier && "'".equals(token) ) { 226 quoted = !quoted; 227 isQuoteCharacter = true; 228 } 229 230 if ( !quoted ) { 231 232 boolean isOpenQuote; 233 if ( "`".equals(token) ) { 234 isOpenQuote = !quotedIdentifier; 235 token = lcToken = isOpenQuote ? 236 new Character ( dialect.openQuote() ).toString() : 237 new Character ( dialect.closeQuote() ).toString(); 238 quotedIdentifier = isOpenQuote; 239 isQuoteCharacter = true; 240 } 241 else if ( !quotedIdentifier && ( dialect.openQuote()==token.charAt(0) ) ) { 242 isOpenQuote = true; 243 quotedIdentifier = true; 244 isQuoteCharacter = true; 245 } 246 else if ( quotedIdentifier && ( dialect.closeQuote()==token.charAt(0) ) ) { 247 quotedIdentifier = false; 248 isQuoteCharacter = true; 249 isOpenQuote = false; 250 } 251 else { 252 isOpenQuote = false; 253 } 254 255 if (isOpenQuote) { 256 result.append(TEMPLATE).append('.'); 257 } 258 259 } 260 261 boolean quotedOrWhitespace = quoted || 262 quotedIdentifier || 263 isQuoteCharacter || 264 Character.isWhitespace( token.charAt(0) ); 265 266 if (quotedOrWhitespace) { 267 result.append(token); 268 } 269 else if ( 270 isIdentifier(token, dialect) && 271 !isFunctionOrKeyword(lcToken, nextToken, dialect) 272 ) { 273 result.append(TEMPLATE) 274 .append('.') 275 .append( dialect.quote(token) ); 276 } 277 else { 278 result.append(token); 279 } 280 } 281 return result.toString(); 282 } 283 284 private static boolean isNamedParameter(String token) { 285 return token.startsWith(":"); 286 } 287 288 private static boolean isFunctionOrKeyword(String lcToken, String nextToken, Dialect dialect) { 289 return "(".equals(nextToken) || 290 KEYWORDS.contains(lcToken) || 291 dialect.getFunctions().containsKey(lcToken) || 292 FUNCTION_KEYWORDS.contains(lcToken); 293 } 294 295 private static boolean isIdentifier(String token, Dialect dialect) { 296 return token.charAt(0)=='`' || ( Character.isLetter( token.charAt(0) ) && token.indexOf('.') < 0 299 ); 300 } 301 302 303 } 304 | Popular Tags |