From a6ac4b726a649f277384f525e0d9f339b7f59862 Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Sun, 30 Jan 2022 18:44:50 +0800
Subject: [PATCH 001/695] Update README.md
---
README.md | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 33e7ec713..3a6f0cf6a 100644
--- a/README.md
+++ b/README.md
@@ -244,7 +244,11 @@ https://github.com/Tencent/APIJSON/issues/187
* [腾讯科技有限公司](https://www.tencent.com)
-
+ * [腾讯音乐娱乐集团](https://www.tencentmusic.com)
+ * [华能贵成信托有限公司](https://www.hngtrust.com)
+ * [投投科技](https://www.toutou.com.cn)
+ * [圆通科技](https://www.tencentmusic.com)
+ * [乐拼科技](https://www.lepinyongche.com)
### 贡献者们
主项目 APIJSON 的贡献者们(6 个腾讯工程师、1 个知乎基础研发架构师、1 个圆通工程师 等):
From ff8efebd33eb89eeb997bc8555d527ad4ee449f0 Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Sun, 30 Jan 2022 18:46:49 +0800
Subject: [PATCH 002/695] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 3a6f0cf6a..eaf7445e4 100644
--- a/README.md
+++ b/README.md
@@ -245,7 +245,7 @@ https://github.com/Tencent/APIJSON/issues/187
* [腾讯科技有限公司](https://www.tencent.com)
* [腾讯音乐娱乐集团](https://www.tencentmusic.com)
- * [华能贵成信托有限公司](https://www.hngtrust.com)
+ * [华能贵诚信托有限公司](https://www.hngtrust.com)
* [投投科技](https://www.toutou.com.cn)
* [圆通科技](https://www.tencentmusic.com)
* [乐拼科技](https://www.lepinyongche.com)
From bfe4c9d8a1c0b4c1cef510e9ddb3e273ef473378 Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Sun, 30 Jan 2022 18:50:12 +0800
Subject: [PATCH 003/695] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index eaf7445e4..f63435b13 100644
--- a/README.md
+++ b/README.md
@@ -247,7 +247,7 @@ https://github.com/Tencent/APIJSON/issues/187
* [腾讯音乐娱乐集团](https://www.tencentmusic.com)
* [华能贵诚信托有限公司](https://www.hngtrust.com)
* [投投科技](https://www.toutou.com.cn)
- * [圆通科技](https://www.tencentmusic.com)
+ * [圆通科技](https://www.yto.net.cn)
* [乐拼科技](https://www.lepinyongche.com)
### 贡献者们
From 6ef55cb4ca8f01a15f690fa31295fb87e1fd2c33 Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Sun, 30 Jan 2022 18:52:21 +0800
Subject: [PATCH 004/695] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index f63435b13..d367d6109 100644
--- a/README.md
+++ b/README.md
@@ -247,7 +247,7 @@ https://github.com/Tencent/APIJSON/issues/187
* [腾讯音乐娱乐集团](https://www.tencentmusic.com)
* [华能贵诚信托有限公司](https://www.hngtrust.com)
* [投投科技](https://www.toutou.com.cn)
- * [圆通科技](https://www.yto.net.cn)
+ * [圆通速递](https://www.yto.net.cn)
* [乐拼科技](https://www.lepinyongche.com)
### 贡献者们
From 2da22e618585f4009145c69965092ab3987004b3 Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Sun, 6 Feb 2022 21:08:59 +0800
Subject: [PATCH 005/695] =?UTF-8?q?=E6=8F=90=E5=8D=87=E7=89=88=E6=9C=AC?=
=?UTF-8?q?=E5=8F=B7=E4=B8=BA=204.9.0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
APIJSONORM/pom.xml | 2 +-
APIJSONORM/src/main/java/apijson/Log.java | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/APIJSONORM/pom.xml b/APIJSONORM/pom.xml
index f1fdcd63a..377ecc644 100755
--- a/APIJSONORM/pom.xml
+++ b/APIJSONORM/pom.xml
@@ -5,7 +5,7 @@
apijson.orm
apijson-orm
- 4.8.0
+ 4.9.0
jar
APIJSONORM
diff --git a/APIJSONORM/src/main/java/apijson/Log.java b/APIJSONORM/src/main/java/apijson/Log.java
index 6dfc96caf..f97fae342 100755
--- a/APIJSONORM/src/main/java/apijson/Log.java
+++ b/APIJSONORM/src/main/java/apijson/Log.java
@@ -14,7 +14,7 @@ public class Log {
public static boolean DEBUG = true;
- public static final String VERSION = "4.8.5";
+ public static final String VERSION = "4.9.0";
public static final String KEY_SYSTEM_INFO_DIVIDER = "---|-----APIJSON SYSTEM INFO-----|---";
//默认的时间格式
From d6bd9dd4e4725c35acdcddfca5feb7347dd7ef12 Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Sun, 6 Feb 2022 21:15:24 +0800
Subject: [PATCH 006/695] Update README.md
---
README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/README.md b/README.md
index d367d6109..c5f4f9069 100644
--- a/README.md
+++ b/README.md
@@ -245,6 +245,8 @@ https://github.com/Tencent/APIJSON/issues/187
* [腾讯科技有限公司](https://www.tencent.com)
* [腾讯音乐娱乐集团](https://www.tencentmusic.com)
+ * [深圳市传音通讯有限公司](http://www.transsion.com)
+ * [社宝信息科技(上海)有限公司](http://shebaochina.com)
* [华能贵诚信托有限公司](https://www.hngtrust.com)
* [投投科技](https://www.toutou.com.cn)
* [圆通速递](https://www.yto.net.cn)
From 7531e2e6602a52c51472d0c6722ca7a3bf04c99f Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Sun, 6 Feb 2022 21:18:14 +0800
Subject: [PATCH 007/695] Update README.md
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index c5f4f9069..7fea8ebd9 100644
--- a/README.md
+++ b/README.md
@@ -245,8 +245,8 @@ https://github.com/Tencent/APIJSON/issues/187
* [腾讯科技有限公司](https://www.tencent.com)
* [腾讯音乐娱乐集团](https://www.tencentmusic.com)
- * [深圳市传音通讯有限公司](http://www.transsion.com)
- * [社宝信息科技(上海)有限公司](http://shebaochina.com)
+ * [深圳市传音通讯有限公司](https://www.transsion.com)
+ * [社宝信息科技(上海)有限公司](https://shebaochina.com)
* [华能贵诚信托有限公司](https://www.hngtrust.com)
* [投投科技](https://www.toutou.com.cn)
* [圆通速递](https://www.yto.net.cn)
From 5b29c96691df01b5a06da51fe58c8d490c9ce439 Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Sun, 20 Feb 2022 20:45:08 +0800
Subject: [PATCH 008/695] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=8A=9F=E8=83=BD?=
=?UTF-8?q?=E6=BC=94=E7=A4=BA=E8=AF=B4=E6=98=8E=20GIF=20=E5=9B=BE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 3 +++
1 file changed, 3 insertions(+)
diff --git a/README.md b/README.md
index 7fea8ebd9..2a1d989a5 100644
--- a/README.md
+++ b/README.md
@@ -91,6 +91,7 @@ APIJSON 是一种专为 API 而生的 JSON 网络传输协议 以及 基于这

+
@@ -119,6 +120,8 @@ APIJSON 是一种专为 API 而生的 JSON 网络传输协议 以及 基于这

+
+
From 60f6bbe73f183f08b9b6f02ebd7ea2626f750c61 Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Sun, 20 Feb 2022 21:01:28 +0800
Subject: [PATCH 009/695] =?UTF-8?q?=E6=96=87=E6=A1=A3=EF=BC=9A=E6=96=B0?=
=?UTF-8?q?=E5=A2=9E=E5=8A=9F=E8=83=BD=E6=BC=94=E7=A4=BA=E5=8F=8A=E8=AF=B4?=
=?UTF-8?q?=E6=98=8E=E7=9A=84=20GIF=20=E5=9B=BE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Document.md | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/Document.md b/Document.md
index 73f262b15..fdcc24238 100644
--- a/Document.md
+++ b/Document.md
@@ -52,6 +52,8 @@ https://github.com/Tencent/APIJSON
}
+
+
#### 获取用户列表
@@ -95,6 +97,8 @@ https://github.com/Tencent/APIJSON
}
+
+
#### 获取动态及发布者用户
@@ -134,6 +138,8 @@ https://github.com/Tencent/APIJSON
"msg":"success"
}
+
+
@@ -254,6 +260,29 @@ https://github.com/Tencent/APIJSON
}
+
+
+
+ APIJSON 各种 JOIN:< LEFT, > RIGHT, & INNER 等
+
+
+
+
+
+
+
+ APIJSON 各种子查询:@from@ 数据源, key@ =, key{}@ IN, key<>@ CONTAINS, key}{@ EXISTS 等
+
+
+
+
+
+
+
+ APIJSON 部分功能演示集合,由浅入深、由简单到复杂
+
+
+
From 7214c8d66ce48bfd3d48f4dc4dbf2c30213183f8 Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Sun, 20 Feb 2022 21:54:31 +0800
Subject: [PATCH 010/695] =?UTF-8?q?=E9=80=9A=E7=94=A8=E6=96=87=E6=A1=A3?=
=?UTF-8?q?=EF=BC=9A=E5=AE=8C=E5=96=84=E5=8A=9F=E8=83=BD=E6=BC=94=E7=A4=BA?=
=?UTF-8?q?=E5=8F=8A=E8=AF=B4=E6=98=8E=E7=9A=84=20GIF=20=E5=9B=BE=E6=A0=87?=
=?UTF-8?q?=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Document.md | 26 +++++++++++++++++++-------
1 file changed, 19 insertions(+), 7 deletions(-)
diff --git a/Document.md b/Document.md
index fdcc24238..9187c4a43 100644
--- a/Document.md
+++ b/Document.md
@@ -52,6 +52,10 @@ https://github.com/Tencent/APIJSON
}
+
+ APIJSON 各种单表对象查询:简单查询、统计、分组、排序、聚合、比较、筛选字段、字段别名 等
+
+

@@ -97,6 +101,10 @@ https://github.com/Tencent/APIJSON
}
+
+ APIJSON 各种单表数组查询:简单查询、统计、分组、排序、聚合、分页、比较、搜索、正则、条件组合 等
+
+

@@ -139,8 +147,6 @@ https://github.com/Tencent/APIJSON
}
-
-
#### 获取类似微信朋友圈的动态列表
@@ -260,20 +266,26 @@ https://github.com/Tencent/APIJSON
}
+
+ APIJSON 各种多表关联查询:一对一、一对多、多对一、各种条件 等
+
+
+
+
- APIJSON 各种 JOIN:< LEFT, > RIGHT, & INNER 等
+ APIJSON 各种 JOIN:< LEFT JOIN, & INNER JOIN 等
-
+

- APIJSON 各种子查询:@from@ 数据源, key@ =, key{}@ IN, key<>@ CONTAINS, key}{@ EXISTS 等
+ APIJSON 各种子查询:@from@ FROM, key@ =, key>@ >, key{}@ IN, key}{@ EXISTS 等
-
+

@@ -281,7 +293,7 @@ https://github.com/Tencent/APIJSON
APIJSON 部分功能演示集合,由浅入深、由简单到复杂
-
+

From cc34a54e27f467af5b82651d16f15fea6c24ec19 Mon Sep 17 00:00:00 2001
From: fanpocha <289484900@qq.com>
Date: Tue, 22 Feb 2022 10:34:27 +0800
Subject: [PATCH 011/695] Update README.md
add caizu
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index 2a1d989a5..61a28a7cf 100644
--- a/README.md
+++ b/README.md
@@ -244,6 +244,7 @@ https://github.com/Tencent/APIJSON/issues/187
+ 珠海采筑电子商务有限公司
* [腾讯科技有限公司](https://www.tencent.com)
From 24e5c0b264fbd858bb4af9ab7ece71e548d225cf Mon Sep 17 00:00:00 2001
From: fanpocha <289484900@qq.com>
Date: Tue, 22 Feb 2022 10:37:11 +0800
Subject: [PATCH 012/695] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 61a28a7cf..a7057b70a 100644
--- a/README.md
+++ b/README.md
@@ -244,7 +244,7 @@ https://github.com/Tencent/APIJSON/issues/187
- 珠海采筑电子商务有限公司
+
* [腾讯科技有限公司](https://www.tencent.com)
From b2059445ab16e94d5a39227c29444fba67a76c06 Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Tue, 22 Feb 2022 23:43:51 +0800
Subject: [PATCH 013/695] =?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=99=BB=E8=AE=B0?=
=?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E7=8F=A0=E6=B5=B7=E9=87=87=E7=AD=91?=
=?UTF-8?q?=E7=94=B5=E5=AD=90=E5=95=86=E5=8A=A1=E6=9C=89=E9=99=90=E5=85=AC?=
=?UTF-8?q?=E5=8F=B8=EF=BC=8C=E6=96=B0=E5=A2=9E=20=E4=B9=90=E6=8B=BC?=
=?UTF-8?q?=E7=94=A8=E8=BD=A6=20=E7=9A=84=20Logo?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
https://github.com/Tencent/APIJSON#%E4%BD%BF%E7%94%A8%E7%99%BB%E8%AE%B0
---
README.md | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index a7057b70a..22390da85 100644
--- a/README.md
+++ b/README.md
@@ -226,7 +226,7 @@ https://github.com/Tencent/APIJSON/issues/36
如果您在使用 APIJSON,请让我们知道,您的使用对我们非常重要(按登记顺序排列):
https://github.com/Tencent/APIJSON/issues/187
-

+
@@ -244,6 +244,7 @@ https://github.com/Tencent/APIJSON/issues/187

+
@@ -255,6 +256,7 @@ https://github.com/Tencent/APIJSON/issues/187
* [投投科技](https://www.toutou.com.cn)
* [圆通速递](https://www.yto.net.cn)
* [乐拼科技](https://www.lepinyongche.com)
+ * [珠海采筑电子商务有限公司](https://www.aupup.com)
### 贡献者们
主项目 APIJSON 的贡献者们(6 个腾讯工程师、1 个知乎基础研发架构师、1 个圆通工程师 等):
From dda1120c5d0e16344d4ac905ed79ea7abf947537 Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Sun, 27 Feb 2022 02:31:16 +0800
Subject: [PATCH 014/695] =?UTF-8?q?JOIN=20=E6=94=AF=E6=8C=81=E5=A4=9A?=
=?UTF-8?q?=E4=B8=AA=E5=AD=97=E6=AE=B5=E5=85=B3=E8=81=94=E5=8F=8A=E5=BC=95?=
=?UTF-8?q?=E7=94=A8=E8=B5=8B=E5=80=BC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../main/java/apijson/orm/AbstractParser.java | 350 ++++++++++--------
.../java/apijson/orm/AbstractSQLConfig.java | 62 ++--
.../java/apijson/orm/AbstractSQLExecutor.java | 48 ++-
.../src/main/java/apijson/orm/Entry.java | 7 +-
.../src/main/java/apijson/orm/Join.java | 204 +++++-----
5 files changed, 384 insertions(+), 287 deletions(-)
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
index 529f4025f..3e3703468 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
@@ -18,6 +18,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -1307,8 +1308,25 @@ else if (childKeys.length == 1 && JSONRequest.isTableKey(childKeys[0])) { //
return response;
}
- /**多表同时筛选
- * @param join "&/User/id@, JOIN_COPY_KEY_LIST;
+ static { // TODO 不全
+ JOIN_COPY_KEY_LIST = new ArrayList
();
+ JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_ROLE);
+ JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_DATABASE);
+ JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_SCHEMA);
+ JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_DATASOURCE);
+ JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_COLUMN);
+ JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_COMBINE);
+ JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_GROUP);
+ JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_HAVING);
+ JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_ORDER);
+ JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_RAW);
+ }
+
+ /**JOIN 多表同时筛选
+ * @param join "&/User, joinList = new ArrayList<>();
-
- JSONObject tableObj;
- String targetPath;
-
- JSONObject targetObj;
- String targetTable;
- String targetKey;
-
- String path;
-
- // List onList = new ArrayList<>();
- for (Entry e : set) {//User/id@
- if (e.getValue() instanceof JSONObject == false) {
+ for (Entry e : set) { // { &/User:{}, ( ) <> () *
// if (StringUtil.isEmpty(joinType, true)) {
@@ -1373,192 +1380,223 @@ else if (join != null){
path = path.substring(index + 1);
index = path.indexOf("/");
- String tableKey = index < 0 ? null : path.substring(0, index); //User:owner
+ String tableKey = index < 0 ? path : path.substring(0, index); // User:owner
apijson.orm.Entry entry = Pair.parseEntry(tableKey, true);
- String table = entry.getKey(); //User
+ String table = entry.getKey(); // User
if (StringUtil.isName(table) == false) {
throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":value 中 value 的 Table 值 " + table + " 不合法!"
- + "必须为 &/Table0/key0,> tableSet = tableObj.entrySet();
+ // 取出所有 join 条件
+ JSONObject requestObj = new JSONObject(true); // (JSONObject) obj.clone();
+
+ boolean matchSingle = false;
+ for (Entry tableEntry : tableSet) {
+ String k = tableEntry.getKey();
+ Object v = k == null ? null : tableEntry.getValue();
+ if (v == null) {
+ continue;
+ }
- // 主表不允许别名
- // apijson.orm.Entry targetEntry = Pair.parseEntry(targetTableKey, true);
- // targetTable = targetEntry.getKey(); //User
- // if (StringUtil.isName(targetTable) == false) {
- // throw new IllegalArgumentException("/" + path + ":'/targetTable/targetKey' 中 targetTable 值 " + targetTable + " 不合法!必须满足大写字母开头的表对象英文单词 key 格式!");
- // }
- //
- // String targetAlias = targetEntry.getValue(); //owner
- // if (StringUtil.isNotEmpty(targetAlias, true) && StringUtil.isName(targetAlias) == false) {
- // throw new IllegalArgumentException("/" + path + ":'/targetTable:targetAlias/targetKey' 中 targetAlias 值 " + targetAlias + " 不合法!必须满足英文单词变量名格式!");
- // }
+ matchSingle = matchSingle == false && k.equals(key);
+ if (matchSingle) {
+ continue;
+ }
- targetTable = targetTableKey; // 主表不允许别名
- if (StringUtil.isName(targetTable) == false) {
- throw new IllegalArgumentException("/" + path + ":'/targetTable/targetKey' 中 targetTable 值 " + targetTable + " 不合法!必须满足大写字母开头的表对象英文单词 key 格式!");
- }
+ if (k.length() > 1 && k.indexOf("@") == k.length() - 1 && v instanceof String) {
+ String sv = (String) v;
+ int ind = sv.endsWith("@") ? -1 : sv.indexOf("/");
+ if (ind == 0 && key == null) { // 指定了某个就只允许一个 ON 条件
+ String p = sv.substring(1);
+ int ind2 = p.indexOf("/");
+ String tk = ind2 < 0 ? null : p.substring(0, ind2);
- //对引用的JSONObject添加条件
- try {
- targetObj = request.getJSONObject(targetTableKey);
- }
- catch (Exception e2) {
- throw new IllegalArgumentException("/" + path + ":'/targetTable/targetKey' 中路径对应的 '" + targetTableKey + "':value 中 value 类型不合法!必须是 {} 这种 JSONObject 格式!" + e2.getMessage());
- }
+ apijson.orm.Entry te = tk == null || p.substring(ind2 + 1).indexOf("/") >= 0 ? null : Pair.parseEntry(tk, true);
- if (targetObj == null) {
- throw new IllegalArgumentException("/" + path + ":'/targetTable/targetKey' 中路径对应的对象 '" + targetTableKey + "':{} 不存在或值为 null !必须是 {} 这种 JSONObject 格式!");
- }
+ if (te != null && JSONRequest.isTableKey(te.getKey()) && request.get(tk) instanceof JSONObject) {
+ refObj.put(k, v);
+ continue;
+ }
+ }
- // 保证和 SQLExcecutor 缓存的 Config 里 where 顺序一致,生成的 SQL 也就一致 <<<<<<<<<
- // AbstractSQLConfig.newSQLConfig 中强制把 id, id{}, userId, userId{} 放到了最前面 tableObj.put(key, tableObj.remove(key));
+ Object rv = getValueByPath(sv);
+ if (rv != null && rv.equals(sv) == false) {
+ requestObj.put(k.substring(0, k.length() - 1), rv);
+ continue;
+ }
- if (tableObj.size() > 1) { // 把 key 强制放最前,AbstractSQLExcecutor 中 config.putWhere 也是放尽可能最前
- JSONObject newTableObj = new JSONObject(tableObj.size(), true);
- newTableObj.put(key, tableObj.remove(key));
- newTableObj.putAll(tableObj);
+ throw new UnsupportedOperationException(table + "/" + k + " 不合法!" + JSONRequest.KEY_JOIN + " 关联的 Table 中,"
+ + "join: ?/Table/key 时只能有 1 个 key@:value;join: ?/Table 时所有 key@:value 要么是符合 join 格式,要么能直接解析成具体值!"); // TODO 支持 join on
+ }
- tableObj = newTableObj;
- request.put(tableKey, tableObj);
+ if (k.startsWith("@")) {
+ if (JOIN_COPY_KEY_LIST.contains(k)) {
+ requestObj.put(k, v); // 保留
+ }
+ }
+ else {
+ if (k.endsWith("@")) {
+ throw new UnsupportedOperationException(table + "/" + k + " 不合法!" + JSONRequest.KEY_JOIN + " 关联的 Table 中,"
+ + "join: ?/Table/key 时只能有 1 个 key@:value;join: ?/Table 时所有 key@:value 要么是符合 join 格式,要么能直接解析成具体值!"); // TODO 支持 join on
+ }
-// tableObj.clear();
-// tableObj.putAll(newTableObj);
+ if (k.contains("()") == false) { // 不需要远程函数
+ requestObj.put(k, v); // 保留
+ }
+ }
+ }
+
+ Set> refSet = refObj.entrySet();
+ if (refSet.isEmpty()) {
+ throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":value 中 value 的 alias 值 " + alias + " 不合法!"
+ + "必须为 &/Table0,>>>>>>>>
Join j = new Join();
- j.setPath(path);
- j.setOriginKey(key);
- j.setOriginValue(targetPath);
+ j.setPath(e.getKey());
j.setJoinType(joinType);
j.setTable(table);
j.setAlias(alias);
- j.setTargetTable(targetTable);
- // j.setTargetAlias(targetAlias);
- j.setTargetKey(targetKey);
- j.setKeyAndType(key);
- j.setRequest(getJoinObject(table, tableObj, key));
- j.setOuter((JSONObject) e.getValue());
-
- if (StringUtil.isName(j.getKey()) == false) {
- throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":value 中 value 的 key@ 中 key 值 " + j.getKey() + " 不合法!必须满足英文单词变量名格式!");
- }
+ j.setOuter((JSONObject) outer);
+ j.setRequest(requestObj);
- joinList.add(j);
-
- // onList.add(table + "." + key + " = " + targetTable + "." + targetKey); // ON User.id = Moment.userId
+ List onList = new ArrayList<>();
+ for (Entry refEntry : refSet) {
+ String originKey = refEntry.getKey();
- }
-
-
- //拼接多个 SQLConfig 的SQL语句,然后执行,再把结果分别缓存(Moment, User等)到 SQLExecutor 的 cacheMap
- // AbstractSQLConfig config0 = null;
- // String sql = "SELECT " + config0.getColumnString() + " FROM " + config0.getTable() + " INNER JOIN " + targetTable + " ON "
- // + onList.get(0) + config0.getGroupString() + config0.getHavingString() + config0.getOrderString();
-
-
- return joinList;
- }
+ String targetPath = (String) refEntry.getValue();
+ if (StringUtil.isEmpty(targetPath, true)) {
+ throw new IllegalArgumentException(e.getKey() + ":value 中 value 值 " + targetPath + " 不合法!必须为引用赋值的路径 '/targetTable/targetKey' !");
+ }
+ // 取出引用赋值路径 targetPath 对应的 Table 和 key
+ index = targetPath.lastIndexOf("/");
+ String targetKey = index < 0 ? null : targetPath.substring(index + 1);
+ if (StringUtil.isName(targetKey) == false) {
+ throw new IllegalArgumentException(e.getKey() + ":'/targetTable/targetKey' 中 targetKey 值 " + targetKey + " 不合法!必须满足英文单词变量名格式!");
+ }
+ targetPath = targetPath.substring(0, index);
+ index = targetPath.lastIndexOf("/");
+ String targetTableKey = index < 0 ? targetPath : targetPath.substring(index + 1);
- private static final List JOIN_COPY_KEY_LIST;
- static { // TODO 不全
- JOIN_COPY_KEY_LIST = new ArrayList();
- JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_ROLE);
- JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_DATABASE);
- JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_SCHEMA);
- JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_DATASOURCE);
- JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_COLUMN);
- JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_COMBINE);
- JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_GROUP);
- JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_HAVING);
- JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_ORDER);
- JOIN_COPY_KEY_LIST.add(JSONRequest.KEY_RAW);
- }
+ // 主表允许别名
+ apijson.orm.Entry targetEntry = Pair.parseEntry(targetTableKey, true);
+ String targetTable = targetEntry.getKey(); //User
+ if (StringUtil.isName(targetTable) == false) {
+ throw new IllegalArgumentException(e.getKey() + ":'/targetTable/targetKey' 中 targetTable 值 " + targetTable + " 不合法!必须满足大写字母开头的表对象英文单词 key 格式!");
+ }
- /**取指定 JSON 对象的 id 集合
- * @param table
- * @param key
- * @param obj
- * @return null ? 全部 : 有限的数组
- */
- private JSONObject getJoinObject(String table, JSONObject obj, String key) {
- if (obj == null || obj.isEmpty()) {
- Log.e(TAG, "getIdList obj == null || obj.isEmpty() >> return null;");
- return null;
- }
- if (StringUtil.isEmpty(key, true)) {
- Log.e(TAG, "getIdList StringUtil.isEmpty(key, true) >> return null;");
- return null;
- }
+ String targetAlias = targetEntry.getValue(); //owner
+ if (StringUtil.isNotEmpty(targetAlias, true) && StringUtil.isName(targetAlias) == false) {
+ throw new IllegalArgumentException(e.getKey() + ":'/targetTable:targetAlias/targetKey' 中 targetAlias 值 " + targetAlias + " 不合法!必须满足英文单词变量名格式!");
+ }
- // 取出所有 join 条件
- JSONObject requestObj = new JSONObject(true); // (JSONObject) obj.clone();
- Set set = new LinkedHashSet<>(obj.keySet());
- for (String k : set) {
- if (StringUtil.isEmpty(k, true)) {
- continue;
- }
+ targetTable = targetTableKey; // 主表允许别名
+ if (StringUtil.isName(targetTable) == false) {
+ throw new IllegalArgumentException(e.getKey() + ":'/targetTable/targetKey' 中 targetTable 值 " + targetTable + " 不合法!必须满足大写字母开头的表对象英文单词 key 格式!");
+ }
- if (k.startsWith("@")) {
- if (JOIN_COPY_KEY_LIST.contains(k)) {
- requestObj.put(k, obj.get(k)); //保留
+ //对引用的JSONObject添加条件
+ JSONObject targetObj;
+ try {
+ targetObj = request.getJSONObject(targetTableKey);
}
- }
- else {
- if (k.endsWith("@")) {
- if (k.equals(key)) {
- continue;
- }
- throw new UnsupportedOperationException(table + "." + k + " 不合法!" + JSONRequest.KEY_JOIN
- + " 关联的Table中只能有1个 key@:value !"); // TODO 支持 join on
+ catch (Exception e2) {
+ throw new IllegalArgumentException(e.getKey() + ":'/targetTable/targetKey' 中路径对应的 '" + targetTableKey + "':value 中 value 类型不合法!必须是 {} 这种 JSONObject 格式!" + e2.getMessage());
}
- if (k.contains("()") == false) { //不需要远程函数
- // requestObj.put(k, obj.remove(k)); //remove是为了避免重复查询副表
- requestObj.put(k, obj.get(k)); //remove是为了避免重复查询副表
+ if (targetObj == null) {
+ throw new IllegalArgumentException(e.getKey() + ":'/targetTable/targetKey' 中路径对应的对象 '" + targetTableKey + "':{} 不存在或值为 null !必须是 {} 这种 JSONObject 格式!");
}
+
+ Join.On on = new Join.On();
+ on.setKeyAndType(j.getJoinType(), j.getTable(), originKey);
+ if (StringUtil.isName(on.getKey()) == false) {
+ throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":value 中 value 的 key@ 中 key 值 " + on.getKey() + " 不合法!必须满足英文单词变量名格式!");
+ }
+
+ on.setOriginKey(originKey);
+ on.setOriginValue((String) refEntry.getValue());
+ on.setTargetTable(targetTable);
+ on.setTargetAlias(targetAlias);
+ on.setTargetKey(targetKey);
+
+ onList.add(on);
}
+
+ j.setOnList(onList);
+
+ joinList.add(j);
+ // onList.add(table + "." + key + " = " + targetTable + "." + targetKey); // ON User.id = Moment.userId
+
+ // 保证和 SQLExcecutor 缓存的 Config 里 where 顺序一致,生成的 SQL 也就一致 <<<<<<<<<
+ // AbstractSQLConfig.newSQLConfig 中强制把 id, id{}, userId, userId{} 放到了最前面 tableObj.put(key, tableObj.remove(key));
+
+ if (refObj.size() != tableObj.size()) { // 把 key 强制放最前,AbstractSQLExcecutor 中 config.putWhere 也是放尽可能最前
+ refObj.putAll(tableObj);
+ request.put(tableKey, refObj);
+
+// tableObj.clear();
+// tableObj.putAll(refObj);
+ }
+ // 保证和 SQLExcecutor 缓存的 Config 里 where 顺序一致,生成的 SQL 也就一致 >>>>>>>>>
}
+ //拼接多个 SQLConfig 的SQL语句,然后执行,再把结果分别缓存(Moment, User等)到 SQLExecutor 的 cacheMap
+ // AbstractSQLConfig config0 = null;
+ // String sql = "SELECT " + config0.getColumnString() + " FROM " + config0.getTable() + " INNER JOIN " + targetTable + " ON "
+ // + onList.get(0) + config0.getGroupString() + config0.getHavingString() + config0.getOrderString();
- return requestObj;
+ return joinList;
}
+
+
+
@Override
public int getDefaultQueryCount() {
return DEFAULT_QUERY_COUNT;
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
index c28d07ad1..eb78e1613 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
@@ -56,6 +56,7 @@
import apijson.RequestMethod;
import apijson.SQL;
import apijson.StringUtil;
+import apijson.orm.Join.On;
import apijson.orm.exception.NotExistException;
import apijson.orm.model.Access;
import apijson.orm.model.Column;
@@ -83,7 +84,6 @@ public abstract class AbstractSQLConfig implements SQLConfig {
// * 和 / 不能同时出现,防止 /* */ 段注释! # 和 -- 不能出现,防止行注释! ; 不能出现,防止隔断SQL语句!空格不能出现,防止 CRUD,DROP,SHOW TABLES等语句!
private static final Pattern PATTERN_RANGE;
private static final Pattern PATTERN_FUNCTION;
- private static final Pattern PATTERN_STRING;
/**
* 表名映射,隐藏真实表名,对安全要求很高的表可以这么做
@@ -97,10 +97,9 @@ public abstract class AbstractSQLConfig implements SQLConfig {
// 允许调用的 SQL 函数:当 substring 为 null 时忽略;当 substring 为 "" 时整个 value 是 raw SQL;其它情况则只是 substring 这段为 raw SQL
public static final Map SQL_FUNCTION_MAP;
- static { // 凡是 SQL 边界符、分隔符、注释符 都不允许,例如 ' " ` ( ) ; # -- ,以免拼接 SQL 时被注入意外可执行指令
+ static { // 凡是 SQL 边界符、分隔符、注释符 都不允许,例如 ' " ` ( ) ; # -- /**/ ,以免拼接 SQL 时被注入意外可执行指令
PATTERN_RANGE = Pattern.compile("^[0-9%,!=\\<\\>/\\.\\+\\-\\*\\^]+$"); // ^[a-zA-Z0-9_*%!=<>(),"]+$ 导致 exists(select*from(Comment)) 通过!
PATTERN_FUNCTION = Pattern.compile("^[A-Za-z0-9%,:_@&~`!=\\<\\>\\|\\[\\]\\{\\} /\\.\\+\\-\\*\\^\\?\\(\\)\\$]+$"); //TODO 改成更好的正则,校验前面为单词,中间为操作符,后面为值
- PATTERN_STRING = Pattern.compile("^[,#;\"`]+$");
TABLE_KEY_MAP = new HashMap();
TABLE_KEY_MAP.put(Table.class.getSimpleName(), Table.TABLE_NAME);
@@ -3378,10 +3377,6 @@ public String getJoinString() throws Exception {
List