Răsfoiți Sursa

数据中心查询优化3

o2sword 5 ani în urmă
părinte
comite
3f3d4effa7

+ 121 - 14
o2server/x_query_assemble_surface/src/main/java/com/x/query/assemble/surface/jaxrs/statement/ActionExecuteV2.java

@@ -6,8 +6,11 @@ import com.x.base.core.container.factory.EntityManagerContainerFactory;
 import com.x.base.core.entity.JpaObject;
 import com.x.base.core.entity.dynamic.DynamicBaseEntity;
 import com.x.base.core.entity.dynamic.DynamicEntity;
+import com.x.base.core.project.annotation.FieldDescribe;
+import com.x.base.core.project.annotation.FieldTypeDescribe;
 import com.x.base.core.project.exception.ExceptionAccessDenied;
 import com.x.base.core.project.exception.ExceptionEntityNotExist;
+import com.x.base.core.project.gson.GsonPropertyObject;
 import com.x.base.core.project.http.ActionResult;
 import com.x.base.core.project.http.EffectivePerson;
 import com.x.base.core.project.logger.Logger;
@@ -20,7 +23,10 @@ import com.x.query.assemble.surface.Business;
 import com.x.query.assemble.surface.ThisApplication;
 import com.x.query.core.entity.schema.Statement;
 import com.x.query.core.entity.schema.Table;
+import com.x.query.core.express.plan.Comparison;
+import com.x.query.core.express.plan.FilterEntry;
 import com.x.query.core.express.statement.Runtime;
+import org.apache.commons.collections4.list.TreeList;
 import org.apache.commons.lang3.StringUtils;
 
 import javax.persistence.EntityManager;
@@ -29,11 +35,14 @@ import javax.persistence.Query;
 import javax.script.Bindings;
 import javax.script.ScriptContext;
 import javax.script.SimpleScriptContext;
-import java.util.Objects;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 class ActionExecuteV2 extends BaseAction {
 
 	private static Logger logger = LoggerFactory.getLogger(ActionExecuteV2.class);
+	private final static String[] keys = {"group by","GROUP BY","order by","ORDER BY","limit","LIMIT"};
 
 	ActionResult<Object> execute(EffectivePerson effectivePerson, String flag, String mode, Integer page, Integer size,
 			JsonElement jsonElement) throws Exception {
@@ -48,8 +57,8 @@ class ActionExecuteV2 extends BaseAction {
 			if (!business.executable(effectivePerson, statement)) {
 				throw new ExceptionAccessDenied(effectivePerson, statement);
 			}
-
-			Runtime runtime = this.runtime(effectivePerson, jsonElement, business, page, size);
+			Wi wi = this.convertToWrapIn(jsonElement, Wi.class);
+			Runtime runtime = this.runtime(effectivePerson, wi.getParameter(), business, page, size);
 
 			Object data = null;
 			Object count = null;
@@ -57,10 +66,10 @@ class ActionExecuteV2 extends BaseAction {
 				case Statement.MODE_DATA:
 					switch (Objects.toString(statement.getFormat(), "")) {
 						case Statement.FORMAT_SCRIPT:
-							data = this.script(effectivePerson, business, statement, runtime, mode);
+							data = this.script(effectivePerson, business, statement, runtime, mode, wi);
 							break;
 						default:
-							data = this.jpql(effectivePerson, business, statement, runtime, mode);
+							data = this.jpql(effectivePerson, business, statement, runtime, mode, wi);
 							break;
 					}
 					result.setData(data);
@@ -68,10 +77,10 @@ class ActionExecuteV2 extends BaseAction {
 				case Statement.MODE_COUNT:
 					switch (Objects.toString(statement.getFormat(), "")) {
 						case Statement.FORMAT_SCRIPT:
-							count = this.script(effectivePerson, business, statement, runtime, mode);
+							count = this.script(effectivePerson, business, statement, runtime, mode, wi);
 							break;
 						default:
-							count = this.jpql(effectivePerson, business, statement, runtime, mode);
+							count = this.jpql(effectivePerson, business, statement, runtime, mode, wi);
 							break;
 					}
 					result.setData(count);
@@ -80,12 +89,12 @@ class ActionExecuteV2 extends BaseAction {
 				default:
 					switch (Objects.toString(statement.getFormat(), "")) {
 						case Statement.FORMAT_SCRIPT:
-							data = this.script(effectivePerson, business, statement, runtime, Statement.MODE_DATA);
-							count = this.script(effectivePerson, business, statement, runtime, Statement.MODE_COUNT);
+							data = this.script(effectivePerson, business, statement, runtime, Statement.MODE_DATA, wi);
+							count = this.script(effectivePerson, business, statement, runtime, Statement.MODE_COUNT, wi);
 							break;
 						default:
-							data = this.jpql(effectivePerson, business, statement, runtime, Statement.MODE_DATA);
-							count = this.jpql(effectivePerson, business, statement, runtime, Statement.MODE_COUNT);
+							data = this.jpql(effectivePerson, business, statement, runtime, Statement.MODE_DATA, wi);
+							count = this.jpql(effectivePerson, business, statement, runtime, Statement.MODE_COUNT, wi);
 							break;
 					}
 					result.setData(data);
@@ -95,7 +104,7 @@ class ActionExecuteV2 extends BaseAction {
 		}
 	}
 
-	private Object script(EffectivePerson effectivePerson, Business business, Statement statement, Runtime runtime, String mode)
+	private Object script(EffectivePerson effectivePerson, Business business, Statement statement, Runtime runtime, String mode, Wi wi)
 			throws Exception {
 		Object data = null;
 		ScriptContext scriptContext = this.scriptContext(effectivePerson, business, runtime);
@@ -115,6 +124,8 @@ class ActionExecuteV2 extends BaseAction {
 		}else{
 			em = business.entityManagerContainer().get(cls);
 		}
+		text = joinSql(text, wi);
+		logger.print("执行的sql:{}",text);
 		Query query = em.createQuery(text);
 		for (Parameter<?> p : query.getParameters()) {
 			if (runtime.hasParameter(p.getName())) {
@@ -137,7 +148,7 @@ class ActionExecuteV2 extends BaseAction {
 		return data;
 	}
 
-	private Object jpql(EffectivePerson effectivePerson, Business business, Statement statement, Runtime runtime, String mode)
+	private Object jpql(EffectivePerson effectivePerson, Business business, Statement statement, Runtime runtime, String mode, Wi wi)
 			throws Exception {
 		Object data = null;
 		Class<? extends JpaObject> cls = this.clazz(business, statement);
@@ -152,6 +163,8 @@ class ActionExecuteV2 extends BaseAction {
 		if(Statement.MODE_COUNT.equals(mode)) {
 			jpqlData = statement.getCountData();
 		}
+		jpqlData = joinSql(jpqlData, wi);
+		logger.print("执行的sql:{}",jpqlData);
 		Query query = em.createQuery(jpqlData);
 		for (Parameter<?> p : query.getParameters()) {
 			if (runtime.hasParameter(p.getName())) {
@@ -193,7 +206,7 @@ class ActionExecuteV2 extends BaseAction {
 	private ScriptContext scriptContext(EffectivePerson effectivePerson, Business business, Runtime runtime)
 			throws Exception {
 		ScriptContext scriptContext = new SimpleScriptContext();
-		ActionExecute.Resources resources = new ActionExecute.Resources();
+		Resources resources = new Resources();
 		resources.setEntityManagerContainer(business.entityManagerContainer());
 		resources.setContext(ThisApplication.context());
 		resources.setApplications(ThisApplication.context().applications());
@@ -206,6 +219,72 @@ class ActionExecuteV2 extends BaseAction {
 		return scriptContext;
 	}
 
+	private String joinSql(String sql, Wi wi) throws Exception{
+		if(wi.getFilterList()!=null && !wi.getFilterList().isEmpty()) {
+			List<String> list = new ArrayList<>();
+			String whereSql = sql.replaceAll("\\s{1,}", " ");
+			String rightSql = "";
+			String leftSql = "";
+			boolean hasWhere = false;
+			if (sql.indexOf("where") > -1) {
+				whereSql = StringUtils.substringAfter(sql, "where");
+				leftSql = StringUtils.substringBefore(sql, "where");
+				hasWhere = true;
+			} else if (sql.indexOf("WHERE") > -1) {
+				whereSql = StringUtils.substringAfter(sql, "WHERE");
+				leftSql = StringUtils.substringBefore(sql, "WHERE");
+				hasWhere = true;
+			}
+			String matchKey = "";
+			for(String key : keys){
+				if (whereSql.indexOf(key) > -1) {
+					matchKey = key;
+					rightSql = StringUtils.substringAfter(whereSql, key);
+					whereSql = StringUtils.substringBefore(whereSql, key);
+					break;
+				}
+			}
+			List<String> filterList = new ArrayList<>();
+			for (FilterEntry filterEntry : wi.getFilterList()){
+				if(StringUtils.isNotBlank(filterEntry.path) && StringUtils.isNotBlank(filterEntry.value)){
+					StringBuilder sb = new StringBuilder();
+					sb.append(filterEntry.path);
+					sb.append(" ");
+					sb.append(Comparison.getMatchCom(filterEntry.comparison));
+					sb.append(" ");
+					sb.append(":"+filterEntry.value);
+					filterList.add(sb.toString());
+				}
+			}
+			if(hasWhere){
+				list.add(leftSql);
+				list.add("WHERE");
+			}else{
+				list.add(whereSql);
+				if(!filterList.isEmpty()){
+					list.add("WHERE");
+				}
+			}
+			if(!filterList.isEmpty()){
+				list.add("(");
+				list.add(StringUtils.join(filterList, " AND "));
+				list.add(")");
+			}
+			if(hasWhere){
+				list.add("AND");
+				list.add("(");
+				list.add(whereSql);
+				list.add(")");
+			}
+			if(StringUtils.isNotBlank(matchKey)){
+				list.add(matchKey);
+				list.add(rightSql);
+			}
+			sql = StringUtils.join(list, " ");
+		}
+		return sql;
+	}
+
 	public static class Resources extends AbstractResources {
 
 		private Organization organization;
@@ -220,4 +299,32 @@ class ActionExecuteV2 extends BaseAction {
 
 	}
 
+	public static class Wi extends GsonPropertyObject {
+		@FieldDescribe("过滤")
+		@FieldTypeDescribe(fieldType="class",fieldTypeName = "com.x.query.core.express.plan.FilterEntry",
+				fieldValue="{\"logic\": \"and\", \"path\": \"o.name\", \"comparison\": \"equals\", \"value\": \"name\", \"formatType\": \"textValue\"}",
+				fieldSample="{\"logic\":\"逻辑运算:and\",\"path\":\"data数据的路径:o.title\",\"comparison\":\"比较运算符:equals|notEquals|like|notLike|greaterThan|greaterThanOrEqualTo|lessThan|lessThanOrEqualTo\"," +
+						"\"value\":\"7月\",\"formatType\":\"textValue|numberValue|dateTimeValue|booleanValue\"}")
+		private List<FilterEntry> filterList = new TreeList<>();
+
+		@FieldDescribe("参数")
+		private JsonElement parameter;
+
+		public List<FilterEntry> getFilterList() {
+			return filterList;
+		}
+
+		public void setFilterList(List<FilterEntry> filterList) {
+			this.filterList = filterList;
+		}
+
+		public JsonElement getParameter() {
+			return parameter;
+		}
+
+		public void setParameter(JsonElement parameter) {
+			this.parameter = parameter;
+		}
+	}
+
 }

+ 2 - 2
o2server/x_query_assemble_surface/src/main/java/com/x/query/assemble/surface/jaxrs/statement/BaseAction.java

@@ -29,7 +29,7 @@ abstract class BaseAction extends StandardJaxrsAction {
 		}
 		runtime.page = this.adjustPage(page);
 		runtime.size = this.adjustSize(size);
-		Set<String> keys = runtime.parameters.keySet();
+		/*Set<String> keys = runtime.parameters.keySet();
 		if (keys.contains(Runtime.PARAMETER_PERSON)) {
 			runtime.parameters.put(Runtime.PARAMETER_PERSON, effectivePerson.getDistinguishedName());
 		}
@@ -52,7 +52,7 @@ abstract class BaseAction extends StandardJaxrsAction {
 		if (keys.contains(Runtime.PARAMETER_ROLELIST)) {
 			runtime.parameters.put(Runtime.PARAMETER_ROLELIST,
 					business.organization().role().listWithPerson(effectivePerson));
-		}
+		}*/
 
 		return runtime;
 	}

+ 29 - 2
o2server/x_query_core_express/src/main/java/com/x/query/core/express/plan/Comparison.java

@@ -10,8 +10,8 @@ public abstract class Comparison {
 	private static String[] lessThan = new String[] { "lessThan", "<" };
 	private static String[] lessThanOrEqualTo = new String[] { "lessThanOrEqualTo", "<=" };
 	private static String[] like = new String[] { "like" };
-	private static String[] notLike = new String[] { "notLike" };
-	private static String[] between = new String[] { "between", "range" };
+	private static String[] notLike = new String[] { "notLike", "not like" };
+	private static String[] between = new String[] { "range", "between" };
 
 	public static boolean isEquals(String comparison) throws Exception {
 		for (String str : equals) {
@@ -93,4 +93,31 @@ public abstract class Comparison {
 		}
 		return false;
 	}
+
+	public static String getMatchCom(String comparison) throws Exception {
+		if(isNotEquals(comparison)){
+			return notEquals[notEquals.length-1];
+
+		}else if(isGreaterThan(comparison)){
+			return greaterThan[greaterThan.length-1];
+
+		}else if(isGreaterThanOrEqualTo(comparison)){
+			return greaterThanOrEqualTo[greaterThanOrEqualTo.length-1];
+
+		}else if(isLessThan(comparison)){
+			return lessThan[lessThan.length-1];
+
+		}else if(isLessThanOrEqualTo(comparison)){
+			return lessThanOrEqualTo[lessThanOrEqualTo.length-1];
+
+		}else if(isLike(comparison)){
+			return like[like.length-1];
+
+		}else if(isNotLike(comparison)){
+			return notLike[notLike.length-1];
+
+		}else{
+			return equals[equals.length-1];
+		}
+	}
 }