📄 template.java
字号:
//$Id: Template.java 8056 2005-08-31 22:22:10Z oneovthafew $
package org.hibernate.sql;
import java.util.HashSet;
import java.util.StringTokenizer;
import org.hibernate.dialect.Dialect;
import org.hibernate.util.StringHelper;
/**
* Parses SQL fragments specified in mapping documents
*
* @author Gavin King
*/
public final class Template {
private static final java.util.Set KEYWORDS = new HashSet();
private static final java.util.Set BEFORE_TABLE_KEYWORDS = new HashSet();
private static final java.util.Set FUNCTION_KEYWORDS = new HashSet();
static {
KEYWORDS.add("and");
KEYWORDS.add("or");
KEYWORDS.add("not");
KEYWORDS.add("like");
KEYWORDS.add("is");
KEYWORDS.add("in");
KEYWORDS.add("between");
KEYWORDS.add("null");
KEYWORDS.add("select");
KEYWORDS.add("distinct");
KEYWORDS.add("from");
KEYWORDS.add("join");
KEYWORDS.add("inner");
KEYWORDS.add("outer");
KEYWORDS.add("left");
KEYWORDS.add("right");
KEYWORDS.add("on");
KEYWORDS.add("where");
KEYWORDS.add("having");
KEYWORDS.add("group");
KEYWORDS.add("order");
KEYWORDS.add("by");
KEYWORDS.add("desc");
KEYWORDS.add("asc");
KEYWORDS.add("limit");
KEYWORDS.add("any");
KEYWORDS.add("some");
KEYWORDS.add("exists");
KEYWORDS.add("all");
BEFORE_TABLE_KEYWORDS.add("from");
BEFORE_TABLE_KEYWORDS.add("join");
FUNCTION_KEYWORDS.add("as");
FUNCTION_KEYWORDS.add("leading");
FUNCTION_KEYWORDS.add("trailing");
FUNCTION_KEYWORDS.add("from");
FUNCTION_KEYWORDS.add("case");
FUNCTION_KEYWORDS.add("when");
FUNCTION_KEYWORDS.add("then");
FUNCTION_KEYWORDS.add("else");
FUNCTION_KEYWORDS.add("end");
}
public static final String TEMPLATE = "$PlaceHolder$";
private Template() {}
public static String renderWhereStringTemplate(String sqlWhereString, Dialect dialect) {
return renderWhereStringTemplate(sqlWhereString, TEMPLATE, dialect);
}
/**
* Takes the where condition provided in the mapping attribute and interpolates the alias.
* Handles subselects, quoted identifiers, quoted strings, expressions, SQL functions,
* named parameters.
*/
public static String renderWhereStringTemplate(String sqlWhereString, String placeholder, Dialect dialect) {
//TODO: make this a bit nicer
String symbols = new StringBuffer()
.append("=><!+-*/()',|&`")
.append(StringHelper.WHITESPACE)
.append( dialect.openQuote() )
.append( dialect.closeQuote() )
.toString();
StringTokenizer tokens = new StringTokenizer(sqlWhereString, symbols, true);
StringBuffer result = new StringBuffer();
boolean quoted = false;
boolean quotedIdentifier = false;
boolean beforeTable = false;
boolean inFromClause = false;
boolean afterFromTable = false;
boolean hasMore = tokens.hasMoreTokens();
String nextToken = hasMore ? tokens.nextToken() : null;
while (hasMore) {
String token = nextToken;
String lcToken = token.toLowerCase();
hasMore = tokens.hasMoreTokens();
nextToken = hasMore ? tokens.nextToken() : null;
boolean isQuoteCharacter = false;
if ( !quotedIdentifier && "'".equals(token) ) {
quoted = !quoted;
isQuoteCharacter = true;
}
if ( !quoted ) {
boolean isOpenQuote;
if ( "`".equals(token) ) {
isOpenQuote = !quotedIdentifier;
token = lcToken = isOpenQuote ?
new Character( dialect.openQuote() ).toString() :
new Character( dialect.closeQuote() ).toString();
quotedIdentifier = isOpenQuote;
isQuoteCharacter = true;
}
else if ( !quotedIdentifier && ( dialect.openQuote()==token.charAt(0) ) ) {
isOpenQuote = true;
quotedIdentifier = true;
isQuoteCharacter = true;
}
else if ( quotedIdentifier && ( dialect.closeQuote()==token.charAt(0) ) ) {
quotedIdentifier = false;
isQuoteCharacter = true;
isOpenQuote = false;
}
else {
isOpenQuote = false;
}
if (isOpenQuote) {
result.append(placeholder).append('.');
}
}
boolean quotedOrWhitespace = quoted ||
quotedIdentifier ||
isQuoteCharacter ||
Character.isWhitespace( token.charAt(0) );
if (quotedOrWhitespace) {
result.append(token);
}
else if (beforeTable) {
result.append(token);
beforeTable = false;
afterFromTable = true;
}
else if (afterFromTable) {
if ( !"as".equals(lcToken) ) afterFromTable = false;
result.append(token);
}
else if ( isNamedParameter(token) ) {
result.append(token);
}
else if (
isIdentifier(token, dialect) &&
!isFunctionOrKeyword(lcToken, nextToken, dialect)
) {
result.append(placeholder)
.append('.')
.append( dialect.quote(token) );
}
else {
if ( BEFORE_TABLE_KEYWORDS.contains(lcToken) ) {
beforeTable = true;
inFromClause = true;
}
else if ( inFromClause && ",".equals(lcToken) ) {
beforeTable = true;
}
result.append(token);
}
if ( //Yuck:
inFromClause &&
KEYWORDS.contains(lcToken) && //"as" is not in KEYWORDS
!BEFORE_TABLE_KEYWORDS.contains(lcToken)
) {
inFromClause = false;
}
}
return result.toString();
}
/**
* Takes order by clause provided in the mapping attribute and interpolates the alias.
* Handles asc, desc, SQL functions, quoted identifiers.
*/
public static String renderOrderByStringTemplate(String sqlOrderByString, Dialect dialect) {
//TODO: make this a bit nicer
String symbols = new StringBuffer()
.append("=><!+-*/()',|&`")
.append(StringHelper.WHITESPACE)
.append( dialect.openQuote() )
.append( dialect.closeQuote() )
.toString();
StringTokenizer tokens = new StringTokenizer(sqlOrderByString, symbols, true);
StringBuffer result = new StringBuffer();
boolean quoted = false;
boolean quotedIdentifier = false;
boolean hasMore = tokens.hasMoreTokens();
String nextToken = hasMore ? tokens.nextToken() : null;
while (hasMore) {
String token = nextToken;
String lcToken = token.toLowerCase();
hasMore = tokens.hasMoreTokens();
nextToken = hasMore ? tokens.nextToken() : null;
boolean isQuoteCharacter = false;
if ( !quotedIdentifier && "'".equals(token) ) {
quoted = !quoted;
isQuoteCharacter = true;
}
if ( !quoted ) {
boolean isOpenQuote;
if ( "`".equals(token) ) {
isOpenQuote = !quotedIdentifier;
token = lcToken = isOpenQuote ?
new Character( dialect.openQuote() ).toString() :
new Character( dialect.closeQuote() ).toString();
quotedIdentifier = isOpenQuote;
isQuoteCharacter = true;
}
else if ( !quotedIdentifier && ( dialect.openQuote()==token.charAt(0) ) ) {
isOpenQuote = true;
quotedIdentifier = true;
isQuoteCharacter = true;
}
else if ( quotedIdentifier && ( dialect.closeQuote()==token.charAt(0) ) ) {
quotedIdentifier = false;
isQuoteCharacter = true;
isOpenQuote = false;
}
else {
isOpenQuote = false;
}
if (isOpenQuote) {
result.append(TEMPLATE).append('.');
}
}
boolean quotedOrWhitespace = quoted ||
quotedIdentifier ||
isQuoteCharacter ||
Character.isWhitespace( token.charAt(0) );
if (quotedOrWhitespace) {
result.append(token);
}
else if (
isIdentifier(token, dialect) &&
!isFunctionOrKeyword(lcToken, nextToken, dialect)
) {
result.append(TEMPLATE)
.append('.')
.append( dialect.quote(token) );
}
else {
result.append(token);
}
}
return result.toString();
}
private static boolean isNamedParameter(String token) {
return token.startsWith(":");
}
private static boolean isFunctionOrKeyword(String lcToken, String nextToken, Dialect dialect) {
return "(".equals(nextToken) ||
KEYWORDS.contains(lcToken) ||
dialect.getFunctions().containsKey(lcToken) ||
dialect.getKeywords().contains(lcToken) ||
FUNCTION_KEYWORDS.contains(lcToken);
}
private static boolean isIdentifier(String token, Dialect dialect) {
return token.charAt(0)=='`' || ( //allow any identifier quoted with backtick
Character.isLetter( token.charAt(0) ) && //only recognizes identifiers beginning with a letter
token.indexOf('.') < 0
);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -