org.onetwo.common.db.sql.SimpleSqlCauseParser Maven / Gradle / Ivy
package org.onetwo.common.db.sql;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.onetwo.common.exception.BaseException;
import org.onetwo.common.profiling.TimeProfileStack;
import org.onetwo.common.utils.Assert;
import org.onetwo.common.utils.LangUtils;
import org.onetwo.common.utils.SToken;
import org.onetwo.common.utils.StringUtils;
import org.onetwo.common.utils.StringSpliter;
import com.google.common.collect.ImmutableList;
@SuppressWarnings("unchecked")
public class SimpleSqlCauseParser implements SqlCauseParser {
private static final String JDBC_PARAM_PLACEHODER = ConditionToken.JDBC_PARAM_PLACEHODER;
public static final String PARENTHESIS_LEFT = "(";
public static final String PARENTHESIS_RIGHT = ")";
public static final List KEYWORDS = ImmutableList.of("and", "or", "where");
public static final List OPERATORS = ImmutableList.of("=", "<", ">", ">=", "<=", "!=", "<>", "in", "like");
public static final List RETAIN_SEPS = ImmutableList.of(" ", ",", "(", ")", "=", "<", ">", ">=", "<=", "!=", "<>", " in", " like ");//seperator
// public static final int DEFAULT_CACHE_LIMIT = 256;
protected List operators = OPERATORS;
protected List retainSeperators = RETAIN_SEPS;
protected Map> caches;
protected int cacheLimit = -1;//-1 is no limited
public SimpleSqlCauseParser() {
this(-1);
}
@SuppressWarnings("serial")
public SimpleSqlCauseParser(int cacheLimit) {
this.cacheLimit = cacheLimit;
if(isCacheEnable()){
caches = new LinkedHashMap>(cacheLimit, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry> eldest) {
return size() > getCacheLimit();
}
};
// caches = new ConcurrentHashMap>();
}
}
public int getCacheLimit() {
return cacheLimit;
}
protected boolean isCacheEnable(){
return cacheLimit>0;
}
/*@Override
public List parseSql(String originalSql) {
int key = originalSql.hashCode();
List tokens = null;
if(isCacheEnable()){
if(caches.containsKey(key))
return caches.get(key);
}
tokens = _parseSql(originalSql);
if(isCacheEnable()){
caches.put(key, tokens);
}
return tokens;
}*/
@Override
public List parseSql(String originalSql) {
if(!isCacheEnable())
return _parseSql(originalSql);
int key = originalSql.hashCode();
List tokens = null;
synchronized (this.caches) {
tokens = this.caches.get(key);
if(tokens==null){
tokens = _parseSql(originalSql);
this.caches.put(key, tokens);
}
}
return tokens;
}
public List _parseSql(String originalSql) {
Assert.hasText(originalSql);
if(TimeProfileStack.isActive()){
TimeProfileStack.push("parseSql");
}
StringSpliter sg = StringSpliter.wrap(originalSql, null, getRetainSeperators());
String[] strs = sg.getArrays();
// LangUtils.println("tokens: ", strs);
List tokens = new ArrayList();
SToken token = null;
ConditionToken cond = null;
int conditionCount = 0;
tokens = new ArrayList();
for (int i = 0; i < strs.length;) {
token = new SToken(strs[i], i);
// System.out.println("--:" + token);
try {
cond = createCondition(tokens, token, strs, conditionCount);
} catch (Exception e) {
throw new BaseException("parse condition error : " + LangUtils.toString(tokens), e);
}
if(cond!=null){
cond.setIndex(conditionCount);
tokens.add(cond);
i = cond.getEndStrIndex()+1;
conditionCount++;
/*System.out.println("add condition["+conditionCount+"] : " + cond);
System.out.println("tokens ["+tokens.size()+"]: " + tokens);
System.out.println("\n\n");*/
}else{
tokens.add(token);
i++;
}
}
if(TimeProfileStack.isActive()){
TimeProfileStack.pop("parseSql");
}
// LangUtils.println("conditions size:"+conditions.size());
return tokens;
}
protected List getKeyWords(){
return KEYWORDS;
}
protected QueryToken findOp(List tokens, int currentIndex){
if(currentIndex>tokens.size()-1)
currentIndex = tokens.size()-1;
String op = "";
// int matchFlag = -1;// 0:match, 1:end match
int startIndex = -1;
int endIndex = -1;
for(int i=currentIndex; i>0; i--){
SToken token = tokens.get(i);
// if(token.isEmptyStr())
if(token.isBlankStr())
continue;
if(Condition.class.isInstance(token))
break;
String str = token.getName();
if(getKeyWords().contains(str.toLowerCase())){
return null;
}
if(!getOperators().contains(str.toLowerCase())){
if(startIndex!=-1)
endIndex = i+1;
else
continue;
}
if(startIndex==-1){
startIndex = i;
}else if(endIndex!=-1){
QueryToken qt = new QueryToken(op, tokens.get(startIndex).getStrIndex());
qt.setTokenIndex(endIndex);
qt.setEndStrIndex(tokens.get(endIndex).getStrIndex());
return qt;
}
op = str + op;
}
return null;
}
/*********
* if use function on the field name, condtion name will be included the function name
* @param tokens
* @param currentIndex
* @return
*/
protected QueryToken findName(List tokens, int currentIndex){
if(currentIndex>tokens.size()-1)
currentIndex = tokens.size()-1;
QueryToken nameToken = null;
String name = "";
int functionFlag = -1;//falg => -1:not function, 0:), 1:(, 2:functionName
for(int i=currentIndex-1; i>0; i--){
SToken token = tokens.get(i);
if(Condition.class.isInstance(token))
break;
String str = token.getName();
if(StringUtils.isBlank(str))
continue;
if(str.trim().equals(PARENTHESIS_RIGHT)){
functionFlag = 0;
}else if(str.trim().equals(PARENTHESIS_LEFT)){
functionFlag = 1;
}else if(functionFlag==1){
functionFlag = 2;
}
name = str + name;
if(functionFlag==-1 || functionFlag==2){
nameToken = new QueryToken(name, token.getStrIndex());
nameToken.setTokenIndex(i);
break;
}
}
return nameToken;
}
protected SToken findFullVarname(SToken varnameToken, QueryToken opToken, String[] tokenStrs){
SToken nameToken = null;
String name = "";
String token = null;
int functionFlag = -1;//falg => -1:not function, 0:(, 1:), 2:functionName
for(int i=opToken.getEndStrIndex()+1; i strs, int currentIndex, int offsize){
int count = 0;
if(currentIndex>strs.size()-1)
currentIndex = strs.size()-1;
for(int i=currentIndex; i>0; i--){
if(StringUtils.isBlank(strs.get(i)))
continue;
if(count==offsize){
SToken t = new SToken(strs.get(i), i);
return t;
}
count++;
}
return null;
}
protected List getSeperators(){
return null;
}
protected List getRetainSeperators(){
return retainSeperators;
}
protected List getOperators(){
return OPERATORS;
}
protected String getNamedParameterPrefix(){
return ":";
}
protected ConditionToken newCondition(SToken token, QueryToken opToken){
return new ConditionToken();
}
protected ConditionToken createCondition(List tokens, SToken stoken, String[] strs, int conditionCount){
String token = stoken.getName();
ConditionToken cond = null;
String varPrefix = getNamedParameterPrefix();
int index = conditionCount;
boolean named = token.startsWith(varPrefix);
boolean paramToken = token.equals(JDBC_PARAM_PLACEHODER) || named;
if(paramToken){
QueryToken opToken = findOp(tokens, tokens.size());
cond = newCondition(stoken, opToken);
/*if(token.startsWith(":maxtime")){
System.out.println("");
}*/
if (opToken!=null) {
QueryToken nameToken = findName(tokens, opToken.getTokenIndex());
cond.setName(nameToken.getName());
cond.setOp(opToken.getName());
if(named){
cond.setVarname(token.substring(varPrefix.length()));
}else{
cond.setVarname(token+index);
}
SToken fullVar = findFullVarname(stoken, opToken, strs);
cond.setStrIndex(nameToken.getStrIndex());
if(fullVar!=null){
cond.setEndStrIndex(fullVar.getStrIndex());
cond.setActualPlaceHolder(fullVar.getName());
}else{
cond.setEndStrIndex(stoken.getStrIndex());
cond.setActualPlaceHolder(JDBC_PARAM_PLACEHODER);
}
LangUtils.remove(tokens, nameToken.getTokenIndex(), tokens.size());
}else{
if(named){
cond.setName(token.substring(varPrefix.length()));
}else{
cond.setName(token+index);// ?0, ?1
}
cond.setOp(null);
cond.setInfixOperator(false);
cond.setVarname(cond.getName());
cond.setStrIndex(stoken.getStrIndex());
cond.setEndStrIndex(stoken.getStrIndex());
cond.setActualPlaceHolder(JDBC_PARAM_PLACEHODER);
}
}
return cond;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy