Skip to content

Commit cfbb978

Browse files
committed
Server:新增JOIN,初步完成LEFT JOIN
1 parent 0abe229 commit cfbb978

File tree

9 files changed

+435
-47
lines changed

9 files changed

+435
-47
lines changed

APIJSON-Java-Server/APIJSONDemo/src/main/java/apijson/demo/server/DemoObjectParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public DemoObjectParser setParser(Parser parser) {
6464

6565
@Override
6666
public SQLConfig newSQLConfig() throws Exception {
67-
return DemoSQLConfig.newSQLConfig(method, table, sqlRequest);
67+
return DemoSQLConfig.newSQLConfig(method, table, sqlRequest, join);
6868
}
6969

7070

APIJSON-Java-Server/APIJSONDemo/src/main/java/apijson/demo/server/DemoSQLConfig.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414

1515
package apijson.demo.server;
1616

17+
import java.util.List;
18+
import java.util.Map;
19+
1720
import com.alibaba.fastjson.JSONObject;
1821

1922
import apijson.demo.server.model.Privacy;
@@ -74,8 +77,8 @@ public DemoSQLConfig(RequestMethod method, int count, int page) {
7477
* @return
7578
* @throws Exception
7679
*/
77-
public static SQLConfig newSQLConfig(RequestMethod method, String table, JSONObject request) throws Exception {
78-
return newSQLConfig(method, table, request, new Callback() {
80+
public static SQLConfig newSQLConfig(RequestMethod method, String table, JSONObject request, List<Map<String, Object>> join) throws Exception {
81+
return newSQLConfig(method, table, request, join, new Callback() {
7982

8083
@Override
8184
public DemoSQLConfig getSQLConfig(RequestMethod method, String table) {

APIJSON-Java-Server/APIJSONLibrary/src/main/java/zuo/biao/apijson/JSONRequest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ public JSONRequest setVersion(String version) {
8282
public static final String KEY_QUERY = "query";
8383
public static final String KEY_COUNT = "count";
8484
public static final String KEY_PAGE = "page";
85+
public static final String KEY_JOIN = "join";
8586

8687
public static final List<String> ARRAY_KEY_LIST;
8788
static {

APIJSON-Java-Server/APIJSONLibrary/src/main/java/zuo/biao/apijson/RequestMethod.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,5 +90,9 @@ public static boolean isQueryMethod(RequestMethod method) {
9090
public static boolean isPublicMethod(RequestMethod method) {
9191
return method == null || method == GET || method == HEAD;
9292
}
93+
94+
public static String getName(RequestMethod method) {
95+
return method == null ? GET.name() : method.name();
96+
}
9397

9498
}

APIJSON-Java-Server/APIJSONLibrary/src/main/java/zuo/biao/apijson/server/AbstractObjectParser.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public AbstractObjectParser setParser(Parser parser) {
6363
protected SQLConfig arrayConfig;//不用final是为了recycle
6464

6565
protected final int type;
66+
protected final List<Map<String, Object>> join;
6667
protected final boolean isTable;
6768
protected final String path;
6869
protected final String table;
@@ -90,6 +91,7 @@ public AbstractObjectParser(@NotNull JSONObject request, String parentPath, Stri
9091
this.arrayConfig = arrayConfig;
9192

9293
this.type = arrayConfig == null ? 0 : arrayConfig.getType();
94+
this.join = arrayConfig == null ? null : arrayConfig.getJoin();
9395
this.path = AbstractParser.getAbsPath(parentPath, name);
9496
this.table = Pair.parseEntry(name, true).getKey();
9597
this.isTable = zuo.biao.apijson.JSONObject.isTableKey(table);

APIJSON-Java-Server/APIJSONLibrary/src/main/java/zuo/biao/apijson/server/AbstractParser.java

Lines changed: 182 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@
1717
import static zuo.biao.apijson.RequestMethod.GET;
1818

1919
import java.io.UnsupportedEncodingException;
20+
import java.util.ArrayList;
2021
import java.util.HashMap;
22+
import java.util.HashSet;
23+
import java.util.LinkedHashMap;
2124
import java.util.List;
2225
import java.util.Map;
2326
import java.util.Set;
@@ -78,12 +81,12 @@ public AbstractParser(RequestMethod method, boolean noVerify) {
7881
public Visitor getVisitor() {
7982
if (visitor == null) {
8083
visitor = new Visitor() {
81-
84+
8285
@Override
8386
public Long getId() {
8487
return 0L;
8588
}
86-
89+
8790
@Override
8891
public List<Long> getContactIdList() {
8992
return null;
@@ -302,8 +305,8 @@ protected void onVerifyLogin() throws Exception {
302305
protected void onVerifyContent() throws Exception {
303306
requestObject = parseCorrectRequest();
304307
}
305-
306-
308+
309+
307310
/**解析请求JSONObject
308311
* @param request => URLDecoder.decode(request, UTF_8);
309312
* @return
@@ -560,7 +563,7 @@ public JSONObject onObjectParse(final JSONObject request
560563
if (request == null) {// Moment:{} || request.isEmpty()) {//key-value条件
561564
return null;
562565
}
563-
566+
564567
int type = arrayConfig == null ? 0 : arrayConfig.getType();
565568

566569
ObjectParser op = createObjectParser(request, parentPath, name, arrayConfig).parse();
@@ -618,7 +621,7 @@ public JSONObject onObjectParse(final JSONObject request
618621
* @throws Exception
619622
*/
620623
@Override
621-
public JSONArray onArrayParse(final JSONObject request, String parentPath, String name) throws Exception {
624+
public JSONArray onArrayParse(JSONObject request, String parentPath, String name) throws Exception {
622625
Log.i(TAG, "\n\n\n getArray parentPath = " + parentPath
623626
+ "; name = " + name + "; request = " + JSON.toJSONString(request));
624627
//不能允许GETS,否则会被通过"[]":{"@role":"ADMIN"},"Table":{},"tag":"Table"绕过权限并能批量查询
@@ -634,10 +637,12 @@ public JSONArray onArrayParse(final JSONObject request, String parentPath, Strin
634637
final int query = request.getIntValue(JSONRequest.KEY_QUERY);
635638
final int count = request.getIntValue(JSONRequest.KEY_COUNT);
636639
final int page = request.getIntValue(JSONRequest.KEY_PAGE);
640+
final String join = request.getString(JSONRequest.KEY_JOIN);
637641
request.remove(JSONRequest.KEY_QUERY);
638642
request.remove(JSONRequest.KEY_COUNT);
639643
request.remove(JSONRequest.KEY_PAGE);
640-
Log.d(TAG, "getArray query = " + query + "; count = " + count + "; page = " + page);
644+
request.remove(JSONRequest.KEY_JOIN);
645+
Log.d(TAG, "getArray query = " + query + "; count = " + count + "; page = " + page + "; join = " + join);
641646

642647
if (request.isEmpty()) {//如果条件成立,说明所有的 parentPath/name:request 中request都无效!!!
643648
Log.e(TAG, "getArray request.isEmpty() >> return null;");
@@ -667,7 +672,8 @@ public JSONArray onArrayParse(final JSONObject request, String parentPath, Strin
667672
.setMethod(requestMethod)
668673
.setCount(size)
669674
.setPage(page)
670-
.setQuery(query);
675+
.setQuery(query)
676+
.setJoin(onJoinParse(join, request));
671677

672678
JSONObject parent;
673679
//生成size个
@@ -681,7 +687,7 @@ public JSONArray onArrayParse(final JSONObject request, String parentPath, Strin
681687
}
682688
//Table>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
683689

684-
690+
685691
/*
686692
* 支持引用取值后的数组
687693
{
@@ -701,17 +707,182 @@ public JSONArray onArrayParse(final JSONObject request, String parentPath, Strin
701707
if (fo instanceof Boolean || fo instanceof Number || fo instanceof String) { //[{}] 和 [[]] 都没意义
702708
putQueryResult(path, response);
703709
}
704-
705-
710+
711+
706712
//后面还可能用到,要还原
707713
request.put(JSONRequest.KEY_QUERY, query);
708714
request.put(JSONRequest.KEY_COUNT, count);
709715
request.put(JSONRequest.KEY_PAGE, page);
716+
request.put(JSONRequest.KEY_JOIN, join);
710717

711718
Log.i(TAG, "getArray return response = \n" + JSON.toJSONString(response) + "\n>>>>>>>>>>>>>>>\n\n\n");
712719
return response;
713720
}
714721

722+
/**多表同时筛选
723+
* @param join "&/User/id@,</User[]/User/id{}@,</[]/Comment/momentId@"
724+
* @param request
725+
* @return
726+
* @throws Exception
727+
*/
728+
private List<Map<String, Object>> onJoinParse(String join, JSONObject request) throws Exception {
729+
String[] sArr = request == null || request.isEmpty() ? null : StringUtil.split(join);
730+
if (sArr == null || sArr.length <= 0) {
731+
Log.e(TAG, "doJoin sArr == null || sArr.length <= 0 >> return request;");
732+
return null;
733+
}
734+
735+
List<Map<String, Object>> joinList = new ArrayList<>();
736+
737+
738+
JSONObject tableObj;
739+
String targetPath;
740+
741+
JSONObject targetObj;
742+
String targetTable;
743+
String targetKey;
744+
745+
String path;
746+
747+
// List<String> onList = new ArrayList<>();
748+
for (int i = 0; i < sArr.length; i++) {//User/id@
749+
//分割 /Table/key
750+
path = "" + sArr[i];
751+
752+
int index = path.indexOf("/");
753+
if (index < 0) {
754+
throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":value 中value不合法!"
755+
+ "必须为 &/Table0/key0,</Table1/key1,... 这种形式!");
756+
}
757+
String type = path.substring(0, index); //& | ! < > ( ) <> () *
758+
if (StringUtil.isEmpty(type, true)) {
759+
type = "|"; // FULL JOIN / UNIOIN
760+
}
761+
path = path.substring(index + 1);
762+
763+
index = path.indexOf("/");
764+
String table = index < 0 ? null : path.substring(0, index);//User
765+
String key = StringUtil.isEmpty(table, true) ? null : path.substring(index + 1);//id@
766+
if (StringUtil.isEmpty(key, true)) {
767+
throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":value 中value不合法!"
768+
+ "必须为 &/Table0/key0,</Table1/key1,... 这种形式!");
769+
}
770+
771+
//取出Table对应的JSONObject,及内部引用赋值 key:value
772+
tableObj = request.getJSONObject(table);
773+
targetPath = tableObj == null ? null : tableObj.getString(key+"@");
774+
if (StringUtil.isEmpty(targetPath, true)) {
775+
throw new IllegalArgumentException(table + "." + key + "@:value 中value必须为引用赋值的路径 '/targetTable/targetKey' !");
776+
}
777+
778+
//取出引用赋值路径targetPath对应的Table和key
779+
index = targetPath.lastIndexOf("/");
780+
targetKey = index < 0 ? null : targetPath.substring(index + 1);
781+
if (StringUtil.isEmpty(targetKey, true)) {
782+
throw new IllegalArgumentException(table + "." + key + "@:'/targetTable/targetKey' 中targetKey不能为空!");
783+
}
784+
785+
targetPath = targetPath.substring(0, index);
786+
index = targetPath.lastIndexOf("/");
787+
targetTable = index < 0 ? targetPath : targetPath.substring(index + 1);
788+
789+
790+
//对引用的JSONObject添加条件
791+
targetObj = request.getJSONObject(targetTable);
792+
if (targetObj == null) {
793+
throw new IllegalArgumentException(targetTable + "." + targetKey
794+
+ "@:'/targetTable/targetKey' 中路径对应的对象不存在!");
795+
}
796+
targetObj.put(key+"@", targetObj.remove(key+"@")); //保证和SQLExcecutor缓存的Config里where顺序一致,生成的SQL也就一致
797+
798+
Map<String, Object> joinMap = new LinkedHashMap<>();
799+
joinMap.put("type", type); //TODO 要么减少数量,要么封装为一个对象
800+
joinMap.put("key", key);
801+
joinMap.put("targetKey", targetKey);
802+
joinMap.put("targetTable", targetTable);
803+
joinMap.put("name", table);
804+
joinMap.put("table", getJoinObject(table, tableObj, key));
805+
806+
joinList.add(joinMap);
807+
808+
// onList.add(table + "." + key + " = " + targetTable + "." + targetKey); // ON User.id = Moment.userId
809+
810+
}
811+
812+
813+
//拼接多个 SQLConfig 的SQL语句,然后执行,再把结果分别缓存(Moment, User等)到 SQLExecutor 的 cacheMap
814+
// AbstractSQLConfig config0 = null;
815+
// String sql = "SELECT " + config0.getColumnString() + " FROM " + config0.getTable() + " INNER JOIN " + targetTable + " ON "
816+
// + onList.get(0) + config0.getGroupString() + config0.getHavingString() + config0.getOrderString();
817+
818+
819+
return joinList;
820+
}
821+
822+
823+
824+
private static final List<String> JOIN_COPY_KEY_LIST;
825+
static {//TODO 不全
826+
JOIN_COPY_KEY_LIST = new ArrayList<String>();
827+
JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_SCHEMA);
828+
JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_COLUMN);
829+
JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_ORDER);
830+
JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_COMBINE);
831+
JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_HAVING);
832+
JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_GROUP);
833+
}
834+
835+
/**
836+
* 取指定json对象的id集合
837+
* @param table
838+
* @param key
839+
* @param obj
840+
* @param targetKey
841+
* @return null ? 全部 : 有限的数组
842+
*/
843+
private JSONObject getJoinObject(String table, JSONObject obj, String key) {
844+
if (obj == null || obj.isEmpty()) {
845+
Log.e(TAG, "getIdList obj == null || obj.isEmpty() >> return null;");
846+
return null;
847+
}
848+
if (StringUtil.isEmpty(key, true)) {
849+
Log.e(TAG, "getIdList StringUtil.isEmpty(key, true) >> return null;");
850+
return null;
851+
}
852+
853+
//取出所有join条件
854+
JSONObject requestObj = new JSONObject(true);//(JSONObject) obj.clone();//
855+
HashSet<String> set = new HashSet<>(obj.keySet());
856+
for (String k : set) {
857+
if (StringUtil.isEmpty(k, true)) {
858+
continue;
859+
}
860+
861+
if (k.startsWith("@")) {
862+
if (JOIN_COPY_KEY_LIST.contains(k)) {
863+
requestObj.put(k, obj.get(k)); //保留
864+
}
865+
}
866+
else {
867+
if (k.endsWith("@")) {
868+
if (k.equals(key+"@")) {
869+
continue;
870+
}
871+
throw new UnsupportedOperationException(table + "." + k + " 不合法!" + JSONRequest.KEY_JOIN
872+
+ " 关联的Table中只能有1个 key@:value !");
873+
}
874+
875+
if (k.contains("()") == false) { //不需要远程函数
876+
// requestObj.put(k, obj.remove(k)); //remove是为了避免重复查询副表
877+
requestObj.put(k, obj.get(k)); //remove是为了避免重复查询副表
878+
}
879+
}
880+
}
881+
882+
883+
return requestObj;
884+
}
885+
715886

716887
/**根据路径取值
717888
* @param parent

0 commit comments

Comments
 (0)