JSONObject parse(@NotNull final RequestMethod m
if (v instanceof String) {
int ind = k.indexOf(":");
String lang = ind < 0 ? null : k.substring(0, ind);
- ScriptEngine engine = getScriptEngine(lang);
+ ScriptEngine engine = getScriptEngine(StringUtil.isName(lang) ? lang : null);
k = ind < 0 ? k : k.substring(ind + 1);
boolean isElse = StringUtil.isEmpty(k, false); // 其它直接报错,不允许传 StringUtil.isEmpty(k, true) || "ELSE".equals(k);
From 1dcc19ebbda7c037d1f8632cbcc192b97ece54a7 Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Sun, 11 Jun 2023 17:00:42 +0800
Subject: [PATCH 016/253] Update README-English.md, fix typo
---
README-English.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README-English.md b/README-English.md
index ede0a5c92..c099c1353 100644
--- a/README-English.md
+++ b/README-English.md
@@ -194,7 +194,7 @@ See the latest release [here](https://github.com/Tencent/APIJSON/releases/tag/5.
-## 6. Auhtor
+## 6. Author
Check out the author's [github account](https://github.com/TommyLemon) to see more related projects.
From 6a66d7c954203a4373bbe9325496dd0e413a561c Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Sun, 11 Jun 2023 17:06:44 +0800
Subject: [PATCH 017/253] Update README-English.md, update company logos
https://github.com/Tencent/APIJSON/blob/master/README-English.md#users-of-apijson
---
README-English.md | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/README-English.md b/README-English.md
index c099c1353..86647974e 100644
--- a/README-English.md
+++ b/README-English.md
@@ -7,7 +7,7 @@ This source code is licensed under the Apache License Version 2.0
-
🏆 Tencent Top 9 Open Source Project, Achieved 5 Awards Inside & Outside Tencent 🚀
A JSON Transmission Protocol and an ORM Library for providing APIs and Documents without writing any code.
+🏆 Tencent Top 8 Open Source Project, Achieved 5 Awards Inside & Outside Tencent 🚀
A JSON Transmission Protocol and an ORM Library for providing APIs and Documents without writing any code.
中文版
@@ -244,6 +244,7 @@ https://github.com/Tencent/APIJSON/issues/187
+
@@ -252,8 +253,19 @@ https://github.com/Tencent/APIJSON/issues/187
-
+
+
+
+
+
+
+
+
+
+
+
+
[More APIJSON Users](https://github.com/Tencent/APIJSON/issues/73)
### Contributers of APIJSON:
From 9c090df05f8efb4de7d471476ba47e66670d9a10 Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Sun, 11 Jun 2023 17:57:54 +0800
Subject: [PATCH 018/253] Update README-English.md
---
README-English.md | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/README-English.md b/README-English.md
index 86647974e..3cd37214e 100644
--- a/README-English.md
+++ b/README-English.md
@@ -20,21 +20,33 @@ This source code is licensed under the Apache License Version 2.0
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -45,6 +57,7 @@ This source code is licensed under the Apache License Version 2.0
+
@@ -368,12 +381,12 @@ Thanks to all contributers of APIJSON!
### Statistics
-Hundreds of employees from big famous companies(Tencent, Google, Microsoft, Amazon, Huawei, Alibaba, Paypal, Meituan, Bytedance, IBM, Baidu, JD, NetEase, Kuaishou, Shopee, etc.) starred,
+Hundreds of employees from big famous companies(Tencent, Google, Apple, Microsoft, Amazon, Huawei, Alibaba, Paypal, Meituan, Bytedance(TikTok), IBM, Baidu, JD, NetEase, Kuaishou, Shopee, etc.) starred,
a lot of employees from big famous companies(Tencent, Huawei, Microsoft, Zoom, etc.) created PR/Issue, thank you all~
[](https://starchart.cc/Tencent/APIJSON)
-
-
-
+
+
+
From 530cc14869f33847c8f2e393220e860d6318bbfa Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Sun, 11 Jun 2023 17:57:58 +0800
Subject: [PATCH 019/253] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AF=B9=E8=85=BE?=
=?UTF-8?q?=E8=AE=AF=E5=88=86=E5=B8=83=E5=BC=8F=E6=95=B0=E6=8D=AE=E5=BA=93?=
=?UTF-8?q?=20TDSQL=20=E7=9A=84=E6=94=AF=E6=8C=81=E8=AF=B4=E6=98=8E?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
https://cloud.tencent.com/product/tddbms
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index 2c0e92f17..da45f3bd7 100644
--- a/README.md
+++ b/README.md
@@ -27,6 +27,7 @@ This source code is licensed under the Apache License Version 2.0
+
From 47cce42cce5eb7e4234c8107faa35af61c18636b Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Sun, 11 Jun 2023 18:00:28 +0800
Subject: [PATCH 020/253] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AF=B9=E8=85=BE?=
=?UTF-8?q?=E8=AE=AF=E4=BA=91=E6=95=B0=E6=8D=AE=E5=BA=93=20TencentDB=20?=
=?UTF-8?q?=E7=9A=84=E6=94=AF=E6=8C=81=E8=AF=B4=E6=98=8E?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
https://cloud.tencent.com/product/cdb
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index da45f3bd7..49a9c87d9 100644
--- a/README.md
+++ b/README.md
@@ -28,6 +28,7 @@ This source code is licensed under the Apache License Version 2.0
+
From fa190ef7bb98419f63f807c5aec7914f39d74bf8 Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Sat, 24 Jun 2023 23:48:51 +0800
Subject: [PATCH 021/253] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=B8=8A=E5=B8=82?=
=?UTF-8?q?=E5=85=AC=E5=8F=B8=E9=A3=9E=E4=BC=81=E4=BA=92=E8=81=94=E7=9A=84?=
=?UTF-8?q?=E5=87=8C=E4=BA=91=E4=B8=AD=E5=8F=B0=E5=AE=98=E7=BD=91=20"APIJS?=
=?UTF-8?q?ON=20=E4=BD=BF=E7=94=A8=E4=BB=8B=E7=BB=8D"=20=E7=9A=84=E9=93=BE?=
=?UTF-8?q?=E6=8E=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
http://api.flyrise.cn:9099/docs/open-docs//1459
---
README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/README.md b/README.md
index 49a9c87d9..ef5c4b5a7 100644
--- a/README.md
+++ b/README.md
@@ -574,6 +574,8 @@ Issue/问卷 一般解答顺序:贡献者 > 帮助他人的用户 > 提供任
[APIJSON使用](https://juejin.cn/post/7148253873478565902)
[apijson 初探](https://www.cnblogs.com/x3d/p/apijson-lowcode.html)
+
+[APIJSON使用介绍](http://api.flyrise.cn:9099/docs/open-docs//1459)
### 生态项目
[APIJSON-Demo](https://github.com/APIJSON/APIJSON-Demo) APIJSON 各种语言、各种框架 的 使用示例项目、上手文档、测试数据 SQL 文件 等
From 3b4ebf5470a88f119477c70c3dbcb4b6a24c681a Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Sun, 2 Jul 2023 13:42:06 +0800
Subject: [PATCH 022/253] =?UTF-8?q?APIJSONBoot=20=E7=BA=A6=E4=B8=80?=
=?UTF-8?q?=E4=B8=8B=E5=8D=88=20=E7=9B=B8=E5=BD=93=E4=BA=8E=20SSMH=20?=
=?UTF-8?q?=E5=A4=A7=E5=B0=8F=E5=91=A8=E8=B6=85=E8=BF=87=E5=8D=8A=E4=B8=AA?=
=?UTF-8?q?=E6=9C=88?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
https://github.com/Tencent/APIJSON#%E4%B8%BA%E4%BB%80%E4%B9%88%E9%80%89%E6%8B%A9-apijson
---
README.md | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index ef5c4b5a7..3c9cb3b73 100644
--- a/README.md
+++ b/README.md
@@ -191,8 +191,16 @@ https://github.com/Tencent/APIJSON/wiki
* **工程轻量小巧** (仅依赖 fastjson,Jar 仅 280KB,Java 文件仅 59 个共 13719 行代码,例如 APIJSONORM 4.3.1)
* **多年持续迭代** (自 2016 年起已连续维护 6 年,50+ 个贡献者、90+ 次发版、3000+ 次提交,不断更新迭代中...)
-
-
+**按照一般互联网中小型项目情况可得出以下对比表格:**
+
+表数量 T | 平均每表字段数 C | APIJSONBoot 按慢估计 | SSMH 按快估计 | APIJSONBoot 提速倍数
+-------- | --------- | ------------- | -------------- | -----------
+1 | 3 | 11 min(约十分钟) | 179 min(约一上午) | 15.27
+5 | 4 | 70 min(约一小时) | 1935 min(约朝九晚六一周) | 26.64
+10 | 10 | 320 min(约一下午) | 8550 min(大小周超过半个月) | 25.72
+20 | 15 | 940 min(约上班两天) | 31900 min(约 996 两个月) | 32.94
+50 | 20 | 3100 min(约上班一周) | 176750 min(11117 超过半年) | 56.02
+
### 用户反馈
**腾讯 IEG 数据产品开发组负责人 xinlin:**
“腾讯的 APIJSON 开源方案,它可以做到零代码生成接口和文档,并且整个生成过程是自动化。当企业有元数据的时候,马上就可以获得接口”
From b5b421a30b681b97cac5147f46207df7b1a55a69 Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Sun, 2 Jul 2023 13:44:00 +0800
Subject: [PATCH 023/253] =?UTF-8?q?APIJSONBoot=20=E7=BA=A6=E4=B8=80?=
=?UTF-8?q?=E4=B8=8B=E5=8D=88=20=E7=9B=B8=E5=BD=93=E4=BA=8E=20SSMH=20?=
=?UTF-8?q?=E5=A4=A7=E5=B0=8F=E5=91=A8=E8=BF=87=E5=8D=8A=E4=B8=AA=E6=9C=88?=
=?UTF-8?q?=EF=BC=8C=E5=BC=80=E5=8F=91=E6=95=88=E7=8E=87=E6=8F=90=E5=8D=87?=
=?UTF-8?q?=2026=20=E5=80=8D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
https://github.com/Tencent/APIJSON#%E4%B8%BA%E4%BB%80%E4%B9%88%E9%80%89%E6%8B%A9-apijson
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 3c9cb3b73..6dbd79243 100644
--- a/README.md
+++ b/README.md
@@ -197,9 +197,9 @@ https://github.com/Tencent/APIJSON/wiki
-------- | --------- | ------------- | -------------- | -----------
1 | 3 | 11 min(约十分钟) | 179 min(约一上午) | 15.27
5 | 4 | 70 min(约一小时) | 1935 min(约朝九晚六一周) | 26.64
-10 | 10 | 320 min(约一下午) | 8550 min(大小周超过半个月) | 25.72
+10 | 10 | 320 min(约一下午) | 8550 min(大小周超半个月) | 25.72
20 | 15 | 940 min(约上班两天) | 31900 min(约 996 两个月) | 32.94
-50 | 20 | 3100 min(约上班一周) | 176750 min(11117 超过半年) | 56.02
+50 | 20 | 3100 min(约上班一周) | 176750 min(11117 超半年) | 56.02
### 用户反馈
**腾讯 IEG 数据产品开发组负责人 xinlin:**
From b601195eeceef08df88fed4c5f6239319199b2f3 Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Sun, 2 Jul 2023 13:49:06 +0800
Subject: [PATCH 024/253] =?UTF-8?q?APIJSONBoot=20=E7=BA=A6=E4=B8=80?=
=?UTF-8?q?=E4=B8=8B=E5=8D=88=20=E7=9B=B8=E5=BD=93=E4=BA=8E=20SSMH=20?=
=?UTF-8?q?=E5=A4=A7=E5=B0=8F=E5=91=A8=E8=B6=85=E8=BF=87=E5=8D=8A=E4=B8=AA?=
=?UTF-8?q?=E6=9C=88=EF=BC=8C=E5=BC=80=E5=8F=91=E6=8F=90=E6=95=88=2026=20?=
=?UTF-8?q?=E5=80=8D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
https://github.com/Tencent/APIJSON#%E4%B8%BA%E4%BB%80%E4%B9%88%E9%80%89%E6%8B%A9-apijson
---
README.md | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
index 6dbd79243..3011c65ed 100644
--- a/README.md
+++ b/README.md
@@ -193,13 +193,13 @@ https://github.com/Tencent/APIJSON/wiki
**按照一般互联网中小型项目情况可得出以下对比表格:**
-表数量 T | 平均每表字段数 C | APIJSONBoot 按慢估计 | SSMH 按快估计 | APIJSONBoot 提速倍数
--------- | --------- | ------------- | -------------- | -----------
-1 | 3 | 11 min(约十分钟) | 179 min(约一上午) | 15.27
-5 | 4 | 70 min(约一小时) | 1935 min(约朝九晚六一周) | 26.64
-10 | 10 | 320 min(约一下午) | 8550 min(大小周超半个月) | 25.72
-20 | 15 | 940 min(约上班两天) | 31900 min(约 996 两个月) | 32.94
-50 | 20 | 3100 min(约上班一周) | 176750 min(11117 超半年) | 56.02
+表数量 T | 平均每表字段数 C | SSMH 按快估计 | APIJSONBoot 按慢估计 | APIJSONBoot 提速倍数
+-------- | --------- | --------------------- | ------------------ | -----------
+1 | 3 | 179 min(约一上午) | 11 min(约十分钟) | 15.27
+5 | 4 | 1935 min(约朝九晚六一周) | 70 min(约一小时) | 26.64
+10 | 10 | 8550 min(大小周超半个月) | 320 min(约一下午) | 25.72
+20 | 15 | 31900 min(约 996 两个月) | 940 min(约上班两天) | 32.94
+50 | 20 | 176750 min(11117 超半年) | 3100 min(约上班一周) | 56.02
### 用户反馈
**腾讯 IEG 数据产品开发组负责人 xinlin:**
From a37353d9108e51ef4b84bc121d78894a614c4fe6 Mon Sep 17 00:00:00 2001
From: "@BiuBiuDooo0" <68573559+YqxLzx@users.noreply.github.com>
Date: Wed, 5 Jul 2023 17:46:25 +0800
Subject: [PATCH 025/253] Update Document-English.md
Complete Doc-English , The English document compared with the Chinese document lacks the global keyword description
---
Document-English.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/Document-English.md b/Document-English.md
index c9d1a0a21..8d1fab8a4 100644
--- a/Document-English.md
+++ b/Document-English.md
@@ -330,6 +330,7 @@ Response:
Operations | &, \|, !
They're used in logic operations. It’s the same as AND, OR, NOT in SQL respectively.
By default, for the same key, it’s ‘\|’ (OR)operation among conditions; for different keys, the default operation among conditions is ‘&’(AND).
| ① ["id&{}":">80000,<=90000"](http://apijson.cn:8080/head/{"User":{"id&{}":">80000,<=90000"}})
In SQL, it's
`id>80000 AND id<=90000`,
meaning *id* needs to be id>80000 & id<=90000
② ["id\|{}":">90000,<=80000"](http://apijson.cn:8080/head/{"User":{"id\|{}":">90000,<=80000"}})
It's the same as "id{}":">90000,<=80000".
In SQL, it's
`id>80000 OR id<=90000`,
meaning that *id* needs to be id>90000 \| id<=80000
③ ["id!{}":[82001,38710]](http://apijson.cn:8080/head/{"User":{"id!{}":[82001,38710]}})
In SQL, it's
`id NOT IN(82001,38710)`,
meaning id needs to be ! (id=82001 \| id=38710).
Keywords in an Array: It can be self-defined. | As for `"key":Object`, *key* is the keyword of *{}* in *"[]":{}*. The type of *Object* is up to *key*.
① `"count":Integer` It's used to count the number. The default largest number is 100.
② `"page":Integer` It’s used for getting data from which page, starting from 0. The default largest number is 100. It’s usually used with COUNT.
③ `"query":Integer` Get the number of items that match conditions
When to get the object, the integer should be 0; when to get the total number, it’s 1; when both above, it’s 2.
You can get the total number with keyword total. It can be referred to other values.
Eg.
`"total@":"/[]/total"`
Put it as the same level of query.
*Query* and *total* are used in GET requests just for convenience. Generally, HEAD request is for getting numbers like the total number.
④ `"join":"&/Table0,Join tables:
"\<" - LEFT JOIN
">" - RIGHT JOIN
"&" - INNER JOIN
"\|" - FULL JOIN
"!" - OUTER JOIN
"@" - APP JOIN
Where @ APP JOIN is in application layer.It’ll get all the keys in tables that refKeys in result tables are referred to, like refKeys:[value0, value1….]. Then, as the results get data according to `key=$refKey` a number of times (COUNT), it uses key `IN($refKeys)` to put these counts together in just one SQL query, in order to improve the performance.
Other JOIN functions are the same as those in SQL.
`"join":"`"MainTable":{},`
`"ViceTable":{"key@":"/MainTable/refKey"}`
will return
`MainTable LEFT JOIN ViceTable`
`ON ViceTable.key=MainTable.refKey`
⑤ `"otherKey":Object` Self-defined keyword other than those that already in the system. It also returns with self-defined keywords.| ① Get User arrays with maximum of 5:
["count":5](http://apijson.cn:8080/get/{"[]":{"count":5,"User":{}}})
② Look into User arrays on page 3. Show 5 of them each page.
["count":5,
"page":3](http://apijson.cn:8080/get/{"[]":{"count":5,"page":3,"User":{}}})
③ Get User Arrays and count the total number of Users:
["[]":{
"query":2,
"User":{}
},
"total@":"/[]/total"](http://apijson.cn:8080/get/{"[]":{"query":2,"count":5,"User":{}},"total@":"%252F[]%252Ftotal"})
Questions like total page numbers or if there's next page can be solved by total,count,page functions,
Total page number:
`int totalPage = Math.ceil(total / count)`
If this is the last page:
`boolean hasNextPage = total > count*page`
If this is the first page:
`boolean isFirstPage = page <= 0`
If it's the last page:
`boolean isLastPage = total <= count*page`
...
④ Moment INNER JOIN User LEFT JOIN Comment:
["[]":{
"join": "&/User,\ "Moment":{},
"User":{
"name~":"t",
"id@": "/Moment/userId"
},
"Comment":{
"momentId@": "/Moment/id"
}
}](http://apijson.cn:8080/get/{"[]":{"count":5,"join":"&%252FUser,\<%252FComment","Moment":{"@column":"id,userId,content"},"User":{"name~":"t","id@":"%252FMoment%252FuserId","@column":"id,name,head"},"Comment":{"momentId@":"%252FMoment%252Fid","@column":"id,momentId,content"}}})
⑤ Add the current user to every level:
["User":{},
"[]":{
"name@":"User/name", //self-defined keyword
"Moment":{}
}](http://apijson.cn:8080/get/{"User":{},"[]":{"name@":"User%252Fname","Moment":{}}})
Keywords in Objects: It can be self-defined. | `"@key":Object` @key is the keyword of {} in Table:{}. The type of Object is decided by @key
① `"@combine":"&key0,&key1,\|key2,key3,`
`!key4,!key5,&key6,key7..."`
First, it’ll group data with same operators. Within one group, it operates from left to right. Then it’ll follow the order of & \| ! to do the operation. Different groups are connected with &. So the expression above will be :
(key0 & key1 & key6 & other key) & (key2 \| key3 \| key7) & !(key4 \| key5)
\| is optional.
② `"@column":"column;function(arg)..."` Return with specific columns.
③ `"@order":"column0+,column1-..."` Decide the order of returning results:
④ `"@group":"column0,column1..."` How to group data. If @column has declared Table id, this id need to be included in @group. In other situations, at least one of the following needs to be done:
1.Group id is declared in @column
2.Primary Key of the table is declared in @group.
⑤ `@having":"function0(...)?value0;function1(...)?value1;function2(...)?value2..."` Add conditions on return results with @having. Usually working with@group, it’s declared in @column.
⑥ `"@schema":"sys"` Can be set as default setting.
⑦ `"@database":"POSTGRESQL"` Get data from a different database.Can be set as default setting.
⑧ `"@role":"OWNER"` Get information of the user, including
UNKNOWN,LOGIN,CONTACT,CIRCLE,OWNER,ADMIN,
Can be set as default setting.
You can self-define a new role or rewrite a role. Use`Verifier.verify` etc. to self-define validation methods.
⑨ `"@explain":true` Profiling. Can be set as default setting.
⑩ `"@otherKey":Object` Self-define keyword | ① Search *Users* that *name* or *tag* contains the letter "a":
["name~":"a",
"tag~":"a",
"@combine":"name~,tag~"](http://apijson.cn:8080/get/{"User[]":{"count":10,"User":{"@column":"id,name,tag","name~":"a","tag~":"a","@combine":"name~,tag~"}}})
② Only search column id,sex,name and return with the same order:
["@column":"id,sex,name"](http://apijson.cn:8080/get/{"User":{"@column":"id,sex,name","id":38710}})
③ Search Users that have descending order of name and default order of id:
["@order":"name-,id"](http://apijson.cn:8080/get/{"[]":{"count":10,"User":{"@column":"name,id","@order":"name-,id"}}})
④ Search Moment grouped with userId:
["@group":"userId,id"](http://apijson.cn:8080/get/{"[]":{"count":10,"Moment":%7B"@column":"userId,id","@group":"userId,id"}}})
⑤ Search Moments that id equals or less than 100 and group with userId:
["@column":"userId;max(id)",
"@group":"userId",
"@having":"max(id)>=100"](http://apijson.cn:8080/get/{"[]":{"count":10,"Moment":{"@column":"userId%253Bmax(id)","@group":"userId","@having":"max(id)>=100"}}})
You can also define the name of the returned function:
["@column":"userId;max(id):maxId",
"@group":"userId",
"@having":"(maxId)>=100"](http://apijson.cn:8080/get/{"[]":{"count":10,"Moment":{"@column":"userId%253Bmax(id):maxId","@group":"userId","@having":"(maxId)>=100"}}})
⑥ Check Users table in sys:
["@schema":"sys"](http://apijson.cn:8080/get/{"User":{"@schema":"sys"}})
⑦ Check Users table in PostgreSQL:
["@database":"POSTGRESQL"](http://apijson.cn:8080/get/{"User":{"@database":"POSTGRESQL"}})
⑧ Check the current user's activity:
["@role":"OWNER"](http://apijson.cn:8080/get/{"[]":{"Moment":{"@role":"OWNER"}}})
⑨ Turn on profiling:
["@explain":true](http://apijson.cn:8080/get/{"[]":{"Moment":{"@explain":true}}})
⑩ Get the No.0 picture from pictureList:
["@position":0, //self-defined keyword
"firstPicture()":"getFromArray(pictureList,@position)"](http://apijson.cn:8080/get/{"User":{"id":38710,"@position":0,"firstPicture()":"getFromArray(pictureList,@position)"}})
+ global keyword. | It is a keyword inside the outermost object {}. Among them, @database, @schema, @datasource, @role, and @explain are basically the same as object keywords, see the above description, the difference is that the global keywords will be automatically inserted in each table object as the default value.
① "tag": String, the following tag is the identifier of the JSON structure matching the request in non-GET or HEAD requests, generally it is the name of the Table to be queried or the array Table[] or Table:[] corresponding to the name, determined by the backend specified in the Request table.
② "version": Integer, the interface version. If the version is not passed, null or <=0, the highest version will be used. If other valid values are passed, the lowest version closest to it will be used, which is specified in the backend Request table.
③ "format": Boolean, formatted to return the key of the Response JSON, generally converting TableName to tableName, TableName[] to tableNameList, Table:alias to alias, TableName-key[] to tableNameKeyList and other camelcase formats. | ① Check private information::
[{"tag":"Privacy","Privacy":{"id":82001}}](http://apijson.cn/api?url=http%3A%2F%2Fapijson.cn%3A8080%2Fgets&type=JSON&json={%22tag%22:%22Privacy%22,%22Privacy%22:{%22id%22:82001}})
② Use the version 1 interface to check private information::
[{"version":1,"tag":"Privacy","Privacy":{"id":82001}}](http://apijson.cn/api?url=http%3A%2F%2Fapijson.cn%3A8080%2Fgets&type=JSON&json={%22version%22:1,%22tag%22:%22Privacy%22,%22Privacy%22:{%22id%22:82001}})
③ Format Moments interface to return in JSON key:
[{
"format":true,
"[]":{
"page":0,
"count":3,
"Moment":{},
"User":{
"id@":"/Moment/userId"
},
"Comment[]":{
"count":3,
"Comment":{
"momentId@":"[]/Moment/id"
}
}
}
}](http://apijson.cn:8080/get/{"format":true,"[]":{"page":0,"count":3,"Moment":{},"User":{"id@":"%252FMoment%252FuserId"},"Comment[]":{"count":3,"Comment":{"momentId@":"[]%252FMoment%252Fid"}}}})
From f400f0917e7a3f603ee4e394e1b66e86f1c3c0db Mon Sep 17 00:00:00 2001
From: TommyLemon
Date: Sat, 8 Jul 2023 17:58:13 +0800
Subject: [PATCH 026/253] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=80=9A=E8=BF=87?=
=?UTF-8?q?=E8=84=9A=E6=9C=AC=E8=AF=AD=E8=A8=80=E6=A0=A1=E9=AA=8C=E5=8F=82?=
=?UTF-8?q?=E6=95=B0=E7=9A=84=E4=BB=A3=E7=A0=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/apijson/orm/AbstractVerifier.java | 53 ++++++++-----------
1 file changed, 22 insertions(+), 31 deletions(-)
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java b/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java
index bf6e50469..3429640fa 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java
@@ -1236,39 +1236,41 @@ public static JSONObject parse(@NotNull final RequestMethod m
if (ifIsStr) {
String ifStr = (String) _if;
int ind = ifStr.indexOf(":");
- String lang = ind < 0 ? null : ifStr.substring(0, ind);
- ScriptEngine engine = getScriptEngine(StringUtil.isName(lang) ? lang : null);
- engine.eval(preCode + "\n" + _if);
+ String lang = ind < 0 || ind > 20 ? null : ifStr.substring(0, ind);
+ boolean isName = StringUtil.isName(lang);
+ ScriptEngine engine = getScriptEngine(isName ? lang : null);
+ engine.eval(preCode + "\n" + (isName ? ifStr.substring(ind + 1) : ifStr));
}
else {
for (Map.Entry entry : ifSet) {
String k = entry == null ? null : entry.getKey();
-// if (condKeys.contains(k)) {
-// throw new IllegalArgumentException("Request 表 structure 配置的 " + ON.name()
-// + ":{ " + k + ":value } 中 key 不合法,不允许传 [" + StringUtil.join(condKeys.toArray(new String[]{})) + "] 中的任何一个 !");
-// }
+// if (condKeys.contains(k)) {
+// throw new IllegalArgumentException("Request 表 structure 配置的 " + ON.name()
+// + ":{ " + k + ":value } 中 key 不合法,不允许传 [" + StringUtil.join(condKeys.toArray(new String[]{})) + "] 中的任何一个 !");
+// }
Object v = k == null ? null : entry.getValue();
if (v instanceof String) {
int ind = k.indexOf(":");
- String lang = ind < 0 ? null : k.substring(0, ind);
- ScriptEngine engine = getScriptEngine(StringUtil.isName(lang) ? lang : null);
- k = ind < 0 ? k : k.substring(ind + 1);
+ String lang = ind < 0 || ind > 20 ? null : k.substring(0, ind);
+ boolean isName = StringUtil.isName(lang);
+ ScriptEngine engine = getScriptEngine(isName ? lang : null);
+ k = isName ? k.substring(ind + 1) : k;
boolean isElse = StringUtil.isEmpty(k, false); // 其它直接报错,不允许传 StringUtil.isEmpty(k, true) || "ELSE".equals(k);
// String code = preCode + "\n\n" + (StringUtil.isEmpty(v, false) ? k : (isElse ? v : "if (" + k + ") {\n " + v + "\n}"));
String code = preCode + "\n\n" + (isElse ? v : "if (" + k + ") {\n " + v + "\n}");
-// ScriptExecutor executor = new JavaScriptExecutor();
-// executor.execute(null, real, )
+// ScriptExecutor executor = new JavaScriptExecutor();
+// executor.execute(null, real, )
engine.eval(code);
-// PARSER_CREATOR.createFunctionParser()
-// .setCurrentObject(real)
-// .setKey(k)
-// .setMethod(method)
-// .invoke()
+// PARSER_CREATOR.createFunctionParser()
+// .setCurrentObject(real)
+// .setKey(k)
+// .setMethod(method)
+// .invoke()
continue;
}
@@ -1288,22 +1290,11 @@ public static JSONObject parse(@NotNull final RequestMethod m
}
public static ScriptEngine getScriptEngine(String lang) {
- List list = StringUtil.isEmpty(lang, true) ? null : SCRIPT_ENGINE_MANAGER.getEngineFactories();
-
- ScriptEngine engine = null;
- if (list == null || list.isEmpty()) {
- engine = SCRIPT_ENGINE; // StringUtil.isEmpty(lang) ? SCRIPT_ENGINE : null;
- }
- else {
- for (ScriptEngineFactory sef : list) {
- if (sef != null && lang.equals(sef.getEngineName())) {
- engine = sef.getScriptEngine();
- }
- }
- }
+ boolean isEmpty = StringUtil.isEmpty(lang, true);
+ ScriptEngine engine = isEmpty ? SCRIPT_ENGINE : SCRIPT_ENGINE_MANAGER.getEngineByName(lang);
if (engine == null) {
- throw new NullPointerException("找不到可执行 " + (StringUtil.isEmpty(lang, true) ? "js" : lang) + " 脚本的引擎!engine == null!");
+ throw new NullPointerException("找不到可执行 " + (isEmpty ? "js" : lang) + " 脚本的引擎!engine == null!");
}
return engine;
From 247f149c406c10c89840fbcfd0e2855d44e719b5 Mon Sep 17 00:00:00 2001
From: TommyLemon
Date: Sat, 8 Jul 2023 19:08:31 +0800
Subject: [PATCH 027/253] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=94=AF=E6=8C=81?=
=?UTF-8?q?=E5=9C=A8=20@column:=20value=20=E4=B8=AD=E4=BC=A0=E8=87=AA?=
=?UTF-8?q?=E5=AE=9A=E4=B9=89=E8=A1=A8=E5=90=8D=EF=BC=8C=E4=BE=8B=E5=A6=82?=
=?UTF-8?q?=20Comment.toId,=20Moment.userId=20=E7=AD=89?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/apijson/orm/AbstractSQLConfig.java | 85 +++++++++++++------
1 file changed, 57 insertions(+), 28 deletions(-)
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
index 2a4823449..a37ba132b 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
@@ -2120,6 +2120,7 @@ else if (SQL_FUNCTION_MAP.containsKey(fun) == false) {
private String[] parseArgsSplitWithComma(String param, boolean isColumn, boolean containRaw, boolean allowAlias) {
// 以"," 分割参数
String quote = getQuote();
+ boolean isKeyPrefix = isKeyPrefix();
String tableAlias = getAliasWithQuote();
String ckeys[] = StringUtil.split(param); // 以","分割参数
if (ckeys != null && ckeys.length > 0) {
@@ -2190,12 +2191,10 @@ else if ("!=null".equals(ck)) {
// 以空格分割参数
String[] mkes = containRaw ? StringUtil.split(ck, " ", true) : new String[]{ ck };
- //如果参数中含有空格(少数情况) 比如 fun(arg1 arg2 arg3 ,arg4) 中的 arg1 arg2 arg3,比如 DISTINCT id
+ //如果参数中含有空格(少数情况) 比如 fun(arg1, arg2,arg3,arg4) 中的 arg1 arg2 arg3,比如 DISTINCT id
if (mkes != null && mkes.length >= 2) {
- origin = praseArgsSplitWithSpace(mkes);
+ origin = parseArgsSplitWithSpace(mkes);
} else {
- boolean isName = false;
-
String mk = RAW_MAP.get(origin);
if (mk != null) { // newSQLConfig 提前处理好的
if (mk.length() > 0) {
@@ -2203,15 +2202,30 @@ else if ("!=null".equals(ck)) {
}
} else if (StringUtil.isNumer(origin)) {
//do nothing
- } else if (StringUtil.isName(origin)) {
- origin = quote + origin + quote;
- isName = true;
} else {
- origin = getValue(origin).toString();
- }
+ String[] keys = origin.split("[.]");
+ StringBuilder sb = new StringBuilder();
+
+ int len = keys == null ? 0 : keys.length;
+ if (len > 0) {
+ boolean first = true;
+ for (String k : keys) {
+ if (StringUtil.isName(k) == false) {
+ sb = null;
+ break;
+ }
+
+ sb.append(first ? "" : ".").append(quote).append(k).append(quote);
+ first = false;
+ }
+ }
- if (isName && isKeyPrefix()) {
- origin = tableAlias + "." + origin;
+ String s = sb == null ? null : sb.toString();
+ if (StringUtil.isNotEmpty(s, true)) {
+ origin = (len == 1 && isKeyPrefix ? tableAlias + "." : "") + s;
+ } else {
+ origin = getValue(origin).toString();
+ }
}
if (isColumn && StringUtil.isEmpty(alias, true) == false) {
@@ -2235,8 +2249,9 @@ else if ("!=null".equals(ck)) {
* @param mkes
* @return
*/
- private String praseArgsSplitWithSpace(String mkes[]) {
+ private String parseArgsSplitWithSpace(String mkes[]) {
String quote = getQuote();
+ boolean isKeyPrefix = isKeyPrefix();
String tableAlias = getAliasWithQuote();
// 包含空格的参数 肯定不包含别名 不用处理别名
@@ -2264,7 +2279,7 @@ private String praseArgsSplitWithSpace(String mkes[]) {
+ " 中所有字符串 column 都必须必须为1个单词 !");
}
- mkes[j] = getKey(origin).toString();
+ mkes[j] = getKey(origin);
continue;
}
else if (ck.startsWith("'") && ck.endsWith("'")) {
@@ -2285,18 +2300,32 @@ else if (ck.contains("`") || ck.contains("'") || origin.startsWith("_") || origi
+ " 中所有 arg 都必须是1个不以 _ 开头的单词 或者符合正则表达式 " + PATTERN_FUNCTION + " 且不包含连续减号 -- !DISTINCT 必须全大写,且后面必须有且只有 1 个空格!其它情况不允许空格!");
}
- boolean isName = false;
if (StringUtil.isNumer(origin)) {
//do nothing
- } else if (StringUtil.isName(origin)) {
- origin = quote + origin + quote;
- isName = true;
} else {
- origin = getValue(origin).toString();
- }
+ String[] keys = origin.split("[.]");
+ StringBuilder sb = new StringBuilder();
+
+ int len = keys == null ? 0 : keys.length;
+ if (len > 0) {
+ boolean first = true;
+ for (String k : keys) {
+ if (StringUtil.isName(k) == false) {
+ sb = null;
+ break;
+ }
- if (isName && isKeyPrefix()) {
- origin = tableAlias + "." + origin;
+ sb.append(first ? "" : ".").append(quote).append(k).append(quote);
+ first = false;
+ }
+ }
+
+ String s = sb == null ? null : sb.toString();
+ if (StringUtil.isNotEmpty(s, true)) {
+ origin = (len == 1 && isKeyPrefix ? tableAlias + "." : "") + s;
+ } else {
+ origin = getValue(origin).toString();
+ }
}
mkes[j] = origin;
@@ -2894,13 +2923,13 @@ protected String parseCombineExpression(RequestMethod method, String quote, Stri
} else {
wi = isHaving ? getHavingItem(quote, table, alias, column, (String) value, containRaw) : getWhereItem(column, value, method, verifyName);
}
-
+
if (1.0f*allCount/size > maxCombineRatio && maxCombineRatio > 0) {
throw new IllegalArgumentException(errPrefix + " 中字符 '" + s + "' 不合法!"
+ "其中 key 数量 " + allCount + " / 条件键值对数量 " + size + " = " + (1.0f*allCount/size)
+ " 已超过 最大倍数,必须在条件键值对数量 0-" + maxCombineRatio + " 倍内!");
}
-
+
if (StringUtil.isEmpty(wi, true)) { // 转成 1=1 ?
throw new IllegalArgumentException(errPrefix + " 中字符 '" + key
+ "' 对应的 " + column + ":value 不是有效条件键值对!");
@@ -5127,7 +5156,7 @@ else if (userId instanceof Subquery) {}
if(StringUtil.equals(table, from.getConfig().getTable())) {
isFakeDelete = false;
}
-
+
if(from.getConfig().getJoinList() != null) {
for(Join join : from.getConfig().getJoinList()) {
if(StringUtil.equals(table, join.getTable())) {
@@ -5144,9 +5173,9 @@ else if (userId instanceof Subquery) {}
whereList.addAll(fakeDeleteMap.keySet());
}
}
- }
+ }
}
-
+
if (StringUtil.isNotEmpty(combineExpr, true)) {
List banKeyList = Arrays.asList(idKey, idInKey, userIdKey, userIdInKey);
for (String key : banKeyList) {
@@ -5206,7 +5235,7 @@ else if (w.startsWith("!")) {
}
//条件>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
-
+
Map tableContent = new LinkedHashMap();
Object value;
for (String key : set) {
@@ -5252,7 +5281,7 @@ else if (w.startsWith("!")) {
fakeDeleteMap.put(accessFakeDeleteMap.get("deletedKey").toString(), accessFakeDeleteMap.get("deletedValue"));
config.setMethod(PUT);
config.setContent(fakeDeleteMap);
- }
+ }
}
}
From 0f1b105c7c8ff6f1c04e90c7614c190dd4d5b708 Mon Sep 17 00:00:00 2001
From: TommyLemon
Date: Sat, 8 Jul 2023 19:39:01 +0800
Subject: [PATCH 028/253] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=94=AF=E6=8C=81?=
=?UTF-8?q?=E5=AD=90=E6=9F=A5=E8=AF=A2=E5=AF=B9=E8=B1=A1=E5=86=85=E7=9C=81?=
=?UTF-8?q?=E7=95=A5=E5=85=B3=E9=94=AE=E8=AF=8D=20from=EF=BC=8C=E8=87=AA?=
=?UTF-8?q?=E5=8A=A8=E5=8F=96=E6=9C=80=E4=B8=8A=E6=96=B9=E7=9A=84=E8=A1=A8?=
=?UTF-8?q?=E5=AF=B9=E8=B1=A1=20key=20=E4=BD=9C=E4=B8=BA=20from?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/apijson/orm/AbstractObjectParser.java | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java
index b39b7c267..f81cc0eb9 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java
@@ -258,7 +258,7 @@ public AbstractObjectParser parse(String name, boolean isReuse) throws Exception
if (obj instanceof JSONObject) {
((JSONObject) obj).put(apijson.JSONObject.KEY_METHOD, GET);
}
-
+
try {
boolean startsWithAt = key.startsWith("@");
//if (startsWithAt || (key.endsWith("()") == false)) {
@@ -372,7 +372,21 @@ public boolean onParse(@NotNull String key, @NotNull Object value) throws Except
}
String from = subquery.getString(JSONRequest.KEY_SUBQUERY_FROM);
- JSONObject arrObj = from == null ? null : obj.getJSONObject(from);
+ boolean isEmpty = StringUtil.isEmpty(from);
+ JSONObject arrObj = isEmpty ? null : obj.getJSONObject(from);
+ if (isEmpty) {
+ Set> set = obj.entrySet();
+ for (Entry e : set) {
+ String k = e == null ? null : e.getKey();
+ Object v = k == null ? null : e.getValue();
+ if (v instanceof JSONObject && JSONRequest.isTableKey(k)) {
+ from = k;
+ arrObj = (JSONObject) v;
+ break;
+ }
+ }
+ }
+
if (arrObj == null) {
throw new IllegalArgumentException("子查询 " + path + "/"
+ key + ":{ from:value } 中 value 对应的主表对象 " + from + ":{} 不存在!");
From 718a5bbc4665d643cd5bfb6a752b32f7f450a25d Mon Sep 17 00:00:00 2001
From: TommyLemon
Date: Mon, 10 Jul 2023 00:35:54 +0800
Subject: [PATCH 029/253] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=94=AF=E6=8C=81?=
=?UTF-8?q?=E5=AF=B9=E6=8C=87=E5=AE=9A=E7=9A=84=E6=96=B9=E6=B3=95=E5=BF=BD?=
=?UTF-8?q?=E7=95=A5=E7=A9=BA=E5=AD=97=E7=AC=A6=E4=B8=B2=E4=BD=9C=E4=B8=BA?=
=?UTF-8?q?=E6=9D=A1=E4=BB=B6=E5=80=BC=E6=88=96=E5=86=99=E5=85=A5=E5=80=BC?=
=?UTF-8?q?=E7=AD=89?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/apijson/orm/AbstractSQLConfig.java | 56 +++++++++++++------
1 file changed, 39 insertions(+), 17 deletions(-)
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
index a37ba132b..26b5e29df 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
@@ -98,6 +98,15 @@ public abstract class AbstractSQLConfig implements SQLConfig {
*/
public static boolean ENABLE_WITH_AS = false;
+ /**
+ * 对指定的方法,忽略空字符串,不作为 GET 条件,PUT 值等。可取值 new RequestMethod[]{ RequestMethod.GET, RequestMethod.POST ... }
+ */
+ public static List IGNORE_EMPTY_STRING_METHOD_LIST = null;
+ /**
+ * 对指定的方法,忽略空白字符串。即首尾 trim 去掉所有不可见字符后,仍然为空的,就忽略,不作为 GET 条件,PUT 值等。
+ * 可取值 new RequestMethod[]{ RequestMethod.GET, RequestMethod.POST ... }
+ */
+ public static List IGNORE_BLANK_STRING_METHOD_LIST = null;
public static int MAX_HAVING_COUNT = 5;
public static int MAX_WHERE_COUNT = 10;
public static int MAX_COMBINE_DEPTH = 2;
@@ -5056,11 +5065,17 @@ else if (userId instanceof Subquery) {}
String[] rawArr = StringUtil.split(raw);
config.setRaw(rawArr == null || rawArr.length <= 0 ? null : new ArrayList<>(Arrays.asList(rawArr)));
- Map tableWhere = new LinkedHashMap();//保证顺序好优化 WHERE id > 1 AND name LIKE...
+ Map tableWhere = new LinkedHashMap(); // 保证顺序好优化 WHERE id > 1 AND name LIKE...
+
+ boolean ignoreBlankStr = IGNORE_BLANK_STRING_METHOD_LIST != null && IGNORE_BLANK_STRING_METHOD_LIST.contains(method);
+ boolean ignoreEmptyStr = ignoreBlankStr || (IGNORE_EMPTY_STRING_METHOD_LIST != null && IGNORE_EMPTY_STRING_METHOD_LIST.contains(method));
+ boolean ignoreEmptyOrBlankStr = ignoreEmptyStr || ignoreBlankStr;
- //已经remove了id和id{},以及@key
- Set set = request.keySet(); //前面已经判断request是否为空
- if (method == POST) { //POST操作
+ boolean enableFakeDelete = config.isFakeDelete();
+
+ // 已经 remove了 id 和 id{},以及 @key
+ Set set = request.keySet(); // 前面已经判断 request 是否为空
+ if (method == POST) { // POST操作
if (idIn != null) {
throw new IllegalArgumentException(table + ":{" + idInKey + ": value} 里的 key 不合法!POST 请求中不允许传 " + idInKey
+ " 这种非字段命名 key !必须为 英文字母 开头且只包含 英文字母、数字、下划线的 字段命名!"); }
@@ -5237,17 +5252,21 @@ else if (w.startsWith("!")) {
//条件>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Map tableContent = new LinkedHashMap();
- Object value;
for (String key : set) {
- value = request.get(key);
+ Object value = request.get(key);
+ if (ignoreEmptyOrBlankStr && value instanceof String && StringUtil.isEmpty(value, ignoreBlankStr)) {
+ continue;
+ }
- if (key.endsWith("<>") == false && value instanceof Map) {//只允许常规Object
- throw new IllegalArgumentException(table + ":{ " + key + ":value } 中 value 类型错误!除了 key<>:{} 外,不允许 " + key + " 等其它任何 key 对应 value 的类型为 JSONObject {} !");
+ if (key.endsWith("<>") == false && value instanceof Map) { // 只允许常规 Object
+ throw new IllegalArgumentException(table + ":{ " + key + ":value } 中 value 类型错误!除了 key<>:{} 外,不允许 "
+ + key + " 等其它任何 key 对应 value 的类型为 JSONObject {} !");
}
- //兼容 PUT @combine
- //解决AccessVerifier新增userId没有作为条件,而是作为内容,导致PUT,DELETE出错
- if ((isWhere || (StringUtil.isName(key.replaceFirst("[+-]$", "")) == false)) || (isWhere == false && StringUtil.isNotEmpty(combineExpr, true) && keyInCombineExpr(combineExpr, key))) {
+ // 兼容 PUT @combine
+ // 解决AccessVerifier新增userId没有作为条件,而是作为内容,导致PUT,DELETE出错
+ if ((isWhere || (StringUtil.isName(key.replaceFirst("[+-]$", "")) == false))
+ || (isWhere == false && StringUtil.isNotEmpty(combineExpr, true) && keyInCombineExpr(combineExpr, key))) {
tableWhere.put(key, value);
if (whereList.contains(key) == false) {
andList.add(key);
@@ -5255,7 +5274,7 @@ else if (w.startsWith("!")) {
} else if (whereList.contains(key)) {
tableWhere.put(key, value);
} else {
- tableContent.put(key, value); //一样 instanceof JSONArray ? JSON.toJSONString(value) : value);
+ tableContent.put(key, value); // 一样 instanceof JSONArray ? JSON.toJSONString(value) : value);
}
}
@@ -5305,11 +5324,11 @@ else if (w.startsWith("!")) {
}
}
- boolean distinct = column == null || rawColumnSQL != null ? false : column.startsWith(PREFIX_DISTINCT);
+ boolean distinct = rawColumnSQL == null && column != null && column.startsWith(PREFIX_DISTINCT);
if (rawColumnSQL == null) {
- String[] fks = StringUtil.split(distinct ? column.substring(PREFIX_DISTINCT.length()) : column, ";"); // key0,key1;fun0(key0,...);fun1(key0,...);key3;fun2(key0,...)
+ // key0,key1;fun0(key0,...);fun1(key0,...);key3;fun2(key0,...)
+ String[] fks = StringUtil.split(distinct ? column.substring(PREFIX_DISTINCT.length()) : column, ";");
if (fks != null) {
- String[] ks;
for (String fk : fks) {
if (containColumnRaw) {
String rawSQL = config.getRawSQL(KEY_COLUMN, fk);
@@ -5322,8 +5341,8 @@ else if (w.startsWith("!")) {
if (fk.contains("(")) { // fun0(key0,...)
cs.add(fk);
}
- else { //key0,key1...
- ks = StringUtil.split(fk);
+ else { // key0,key1...
+ String[] ks = StringUtil.split(fk);
if (ks != null && ks.length > 0) {
cs.addAll(Arrays.asList(ks));
}
@@ -5403,6 +5422,9 @@ else if (newHaving instanceof JSONObject) {
throw new IllegalArgumentException(table + ":{ " + havingKey + ":{ " + k + ":value } } 里的"
+ " value 不合法!类型只能是 String,且不允许为空!");
}
+ if (ignoreEmptyOrBlankStr && StringUtil.isEmpty(v, ignoreBlankStr)) {
+ continue;
+ }
if (KEY_COMBINE.equals(k)) {
havingCombine = (String) v;
From 7a24178c7d624563fe55fab523b72eb138fa739f Mon Sep 17 00:00:00 2001
From: TommyLemon
Date: Mon, 10 Jul 2023 00:38:10 +0800
Subject: [PATCH 030/253] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=81=87=E5=88=A0?=
=?UTF-8?q?=E9=99=A4=EF=BC=8C=E6=94=AF=E6=8C=81=20notDeletedValue=EF=BC=8C?=
=?UTF-8?q?=E9=80=82=E9=85=8D=20deletedTime=20=3D=20NULL=20=E8=A1=A8?=
=?UTF-8?q?=E7=A4=BA=E6=9C=AA=E5=88=A0=E9=99=A4=E7=AD=89=E9=9C=80=E6=B1=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/apijson/orm/AbstractSQLConfig.java | 104 ++++++++++++------
1 file changed, 71 insertions(+), 33 deletions(-)
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
index 26b5e29df..6eacf22a4 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
@@ -107,6 +107,11 @@ public abstract class AbstractSQLConfig implements SQLConfig {
* 可取值 new RequestMethod[]{ RequestMethod.GET, RequestMethod.POST ... }
*/
public static List IGNORE_BLANK_STRING_METHOD_LIST = null;
+
+ public static String KEY_DELETED_KEY = "deletedKey";
+ public static String KEY_DELETED_VALUE = "deletedValue";
+ public static String KEY_NOT_DELETED_VALUE = "notDeletedValue";
+
public static int MAX_HAVING_COUNT = 5;
public static int MAX_WHERE_COUNT = 10;
public static int MAX_COMBINE_DEPTH = 2;
@@ -4295,6 +4300,15 @@ public String getRemoveString(String key, String column, Object value) throws Il
}
//SET >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+ @Override
+ public boolean isFakeDelete() {
+ return false;
+ }
+
+ @Override
+ public Map onFakeDelete(Map map) {
+ return map;
+ }
/**
* @return
@@ -5159,33 +5173,49 @@ else if (userId instanceof Subquery) {}
whereList.add(userIdInKey);
}
- if(config.isFakeDelete()) {
- // 查询Access假删除
- Map accessFakeDeleteMap = AbstractVerifier.ACCESS_FAKE_DELETE_MAP.get(config.getTable());
- if (accessFakeDeleteMap != null && StringUtil.isNotEmpty(accessFakeDeleteMap.get("deletedKey"), true)) {
- Map fakeDeleteMap = new HashMap<>();
+ if (enableFakeDelete) {
+ // 查询 Access 假删除
+ Map accessFakeDeleteMap = method == DELETE
+ ? null : AbstractVerifier.ACCESS_FAKE_DELETE_MAP.get(config.getTable());
+ Object deletedKey = accessFakeDeleteMap == null ? null : accessFakeDeleteMap.get(KEY_DELETED_KEY);
+ boolean hasKey = deletedKey instanceof String && StringUtil.isNotEmpty(deletedKey, true);
+ Object deletedValue = hasKey ? accessFakeDeleteMap.get(KEY_DELETED_VALUE) : null;
+ boolean containNotDeletedValue = hasKey ? accessFakeDeleteMap.containsKey(KEY_NOT_DELETED_VALUE) : null;
+ Object notDeletedValue = containNotDeletedValue ? accessFakeDeleteMap.get(KEY_NOT_DELETED_VALUE) : null;
+
+ if (deletedValue != null || containNotDeletedValue) {
boolean isFakeDelete = true;
- if(method != DELETE) {
- if(from != null) {
- // 兼容 join 外层select 重复生成deletedKey
- if(StringUtil.equals(table, from.getConfig().getTable())) {
- isFakeDelete = false;
- }
+ if (from != null) {
+ // 兼容 JOIN 外层 SELECT 重复生成 deletedKey
+ SQLConfig> cfg = from.getConfig();
+ if (cfg != null && StringUtil.equals(table, cfg.getTable())) {
+ isFakeDelete = false;
+ }
- if(from.getConfig().getJoinList() != null) {
- for(Join join : from.getConfig().getJoinList()) {
- if(StringUtil.equals(table, join.getTable())) {
- isFakeDelete = false;
- break;
- }
+ List jl = isFakeDelete && cfg != null ? cfg.getJoinList() : null;
+ if (jl != null) {
+ for (Join join : jl) {
+ if (join != null && StringUtil.equals(table, join.getTable())) {
+ isFakeDelete = false;
+ break;
}
}
}
- if(isFakeDelete) {
- fakeDeleteMap.put(accessFakeDeleteMap.get("deletedKey").toString()+"!", accessFakeDeleteMap.get("deletedValue"));
- tableWhere.putAll(fakeDeleteMap);
- andList.addAll(fakeDeleteMap.keySet());
- whereList.addAll(fakeDeleteMap.keySet());
+ }
+
+ if (isFakeDelete) { // 支持 deleted != 1 / deleted is null 等表达式
+ if (deletedValue != null) { // deletedKey != deletedValue
+ String key = deletedKey + "!";
+ tableWhere.put(key, deletedValue);
+ andList.add(key);
+ whereList.add(key);
+ }
+
+ if (containNotDeletedValue) { // deletedKey = notDeletedValue
+ String key = deletedKey.toString();
+ tableWhere.put(key, notDeletedValue);
+ andList.add(key);
+ whereList.add(key);
}
}
}
@@ -5289,18 +5319,26 @@ else if (w.startsWith("!")) {
config.setContent(tableContent);
}
- if(method == DELETE) {
- if(config.isFakeDelete()) {
- //查询Access假删除
- Map accessFakeDeleteMap = AbstractVerifier.ACCESS_FAKE_DELETE_MAP.get(config.getTable());
- if (StringUtil.isNotEmpty(accessFakeDeleteMap.get("deletedKey"), true)) {
- //假删除需要更新的其他字段,比如:删除时间 deletedTime 之类的
- Map fakeDeleteMap = new HashMap<>();
- config.onFakeDelete(fakeDeleteMap);
- fakeDeleteMap.put(accessFakeDeleteMap.get("deletedKey").toString(), accessFakeDeleteMap.get("deletedValue"));
- config.setMethod(PUT);
- config.setContent(fakeDeleteMap);
+ if (enableFakeDelete && method == DELETE) {
+ // 查询 Access 假删除
+ Map accessFakeDeleteMap = AbstractVerifier.ACCESS_FAKE_DELETE_MAP.get(config.getTable());
+
+ Object deletedKey = accessFakeDeleteMap.get(KEY_DELETED_KEY);
+ if (StringUtil.isNotEmpty(deletedKey, true)) {
+ // 假删除需要更新的其他字段,比如:删除时间 deletedTime 之类的
+ Map fakeDeleteMap = new HashMap<>();
+ fakeDeleteMap.put(deletedKey.toString(), accessFakeDeleteMap.get(KEY_DELETED_VALUE));
+ fakeDeleteMap = config.onFakeDelete(fakeDeleteMap);
+
+ Map content = config.getContent();
+ if (content == null || content.isEmpty()) {
+ content = fakeDeleteMap;
+ } else {
+ content.putAll(fakeDeleteMap);
}
+
+ config.setMethod(PUT);
+ config.setContent(content);
}
}
From e0d9a7c6e34cc4d0215b270679e819e51eafba29 Mon Sep 17 00:00:00 2001
From: TommyLemon
Date: Mon, 10 Jul 2023 00:40:08 +0800
Subject: [PATCH 031/253] =?UTF-8?q?SQLConfig=20=E5=92=8C=20SQLExecutor=20?=
=?UTF-8?q?=E4=B9=9F=E6=8C=87=E5=AE=9A=E4=B8=BB=E9=94=AE=E6=B3=9B=E5=9E=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/apijson/orm/AbstractFunctionParser.java | 11 +++++++++++
.../src/main/java/apijson/orm/AbstractParser.java | 1 +
.../main/java/apijson/orm/AbstractSQLConfig.java | 2 +-
.../java/apijson/orm/AbstractSQLExecutor.java | 15 +++++++++++++--
.../src/main/java/apijson/orm/FunctionParser.java | 4 ++++
.../src/main/java/apijson/orm/SQLConfig.java | 12 ++++++------
.../src/main/java/apijson/orm/SQLExecutor.java | 4 +++-
7 files changed, 39 insertions(+), 10 deletions(-)
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
index 35848af06..0498e5cb6 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
@@ -62,6 +62,17 @@ public AbstractFunctionParser(RequestMethod method, String tag, int version, @No
setRequest(request);
}
+ private Parser> parser;
+ @Override
+ public Parser> getParser() {
+ return parser;
+ }
+ @Override
+ public AbstractFunctionParser setParser(Parser> parser) {
+ this.parser = parser;
+ return this;
+ }
+
@Override
public RequestMethod getMethod() {
return method;
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
index 06f96a164..2aab3cd88 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
@@ -344,6 +344,7 @@ public AbstractParser setNeedVerifyContent(boolean needVerifyContent) {
public SQLExecutor getSQLExecutor() {
if (sqlExecutor == null) {
sqlExecutor = createSQLExecutor();
+ sqlExecutor.setParser(this);
}
return sqlExecutor;
}
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
index 6eacf22a4..6111f66d5 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
@@ -79,7 +79,7 @@
/**config sql for JSON Request
* @author Lemon
*/
-public abstract class AbstractSQLConfig implements SQLConfig {
+public abstract class AbstractSQLConfig implements SQLConfig {
private static final String TAG = "AbstractSQLConfig";
/**
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java
index b2d4544ab..7b10b3193 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java
@@ -46,11 +46,22 @@
/**executor for query(read) or update(write) MySQL database
* @author Lemon
*/
-public abstract class AbstractSQLExecutor implements SQLExecutor {
+public abstract class AbstractSQLExecutor implements SQLExecutor {
private static final String TAG = "AbstractSQLExecutor";
public static String KEY_RAW_LIST = "@RAW@LIST"; // 避免和字段命名冲突,不用 $RAW@LIST$ 是因为 $ 会在 fastjson 内部转义,浪费性能
+ private Parser parser;
+ @Override
+ public Parser getParser() {
+ return parser;
+ }
+ @Override
+ public AbstractSQLExecutor setParser(Parser parser) {
+ this.parser = parser;
+ return this;
+ }
+
private int generatedSQLCount = 0;
private int cachedSQLCount = 0;
private int executedSQLCount = 0;
@@ -1195,7 +1206,7 @@ public void setTransactionIsolation(int transactionIsolation) {
@Override
public void begin(int transactionIsolation) throws SQLException {
Log.d("\n\n" + TAG, "<<<<<<<<<<<<<< TRANSACTION begin transactionIsolation = " + transactionIsolation + " >>>>>>>>>>>>>>>>>>>>>>> \n\n");
- //不做判断,如果掩盖了问题,调用层都不知道为啥事务没有提交成功
+ // 不做判断,如果掩盖了问题,调用层都不知道为啥事务没有提交成功
// if (connection == null || connection.isClosed()) {
// return;
// }
diff --git a/APIJSONORM/src/main/java/apijson/orm/FunctionParser.java b/APIJSONORM/src/main/java/apijson/orm/FunctionParser.java
index b7dab569d..189d9d447 100644
--- a/APIJSONORM/src/main/java/apijson/orm/FunctionParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/FunctionParser.java
@@ -19,6 +19,10 @@ public interface FunctionParser {
Object invoke(@NotNull String function, @NotNull JSONObject currentObject) throws Exception;
Object invoke(@NotNull String function, @NotNull JSONObject currentObject, boolean containRaw) throws Exception;
+ Parser> getParser();
+
+ AbstractFunctionParser setParser(Parser> parser);
+
RequestMethod getMethod();
FunctionParser setMethod(RequestMethod method);
diff --git a/APIJSONORM/src/main/java/apijson/orm/SQLConfig.java b/APIJSONORM/src/main/java/apijson/orm/SQLConfig.java
index 838d4d57d..4e47c9d15 100755
--- a/APIJSONORM/src/main/java/apijson/orm/SQLConfig.java
+++ b/APIJSONORM/src/main/java/apijson/orm/SQLConfig.java
@@ -15,7 +15,7 @@
/**SQL配置
* @author Lemon
*/
-public interface SQLConfig {
+public interface SQLConfig {
String DATABASE_MYSQL = "MYSQL"; // https://www.mysql.com
String DATABASE_POSTGRESQL = "POSTGRESQL"; // https://www.postgresql.org
@@ -48,9 +48,9 @@ public interface SQLConfig {
int TYPE_ITEM = 1;
int TYPE_ITEM_CHILD_0 = 2;
- Parser> getParser();
+ Parser getParser();
- AbstractSQLConfig setParser(Parser> parser);
+ AbstractSQLConfig setParser(Parser parser);
ObjectParser getObjectParser();
@@ -345,9 +345,9 @@ default int[] getDBVersionNums() {
List
From c944c9f7ab90cab455e1a380f21455c6c98af9d5 Mon Sep 17 00:00:00 2001
From: TommyLemon
Date: Sun, 30 Jul 2023 23:43:47 +0800
Subject: [PATCH 036/253] =?UTF-8?q?=E8=BF=9C=E7=A8=8B=E5=87=BD=E6=95=B0?=
=?UTF-8?q?=EF=BC=9A=E6=96=B0=E5=A2=9E=E6=A0=B9=E6=8D=AE=E8=B7=AF=E5=BE=84?=
=?UTF-8?q?=E4=BB=8E=E5=BD=93=E5=89=8D=E5=AF=B9=E8=B1=A1=E5=8F=96=E5=80=BC?=
=?UTF-8?q?=E7=9A=84=E6=96=B9=E6=B3=95=20getArgVal(String)=EF=BC=8C?=
=?UTF-8?q?=E6=96=B9=E4=BE=BF=20Long=20uid=20=3D=20getArgVal("User/id")=20?=
=?UTF-8?q?=E8=BF=99=E6=A0=B7=E5=8F=96=E5=80=BC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../apijson/orm/AbstractFunctionParser.java | 18 ++++++++++++++++++
.../main/java/apijson/orm/AbstractParser.java | 6 +++---
2 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
index 0498e5cb6..eb4a0119c 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
@@ -156,6 +156,24 @@ public AbstractFunctionParser setCurrentObject(@NotNull JSONObject currentObject
return this;
}
+ /**根据路径从当前对象取值
+ * @param path
+ * @return
+ * @param
+ */
+ public T getArgVal(String path) {
+ return getArgVal(getCurrentObject(), path);
+ }
+ /**根据路径从对象 obj 中取值
+ * @param obj
+ * @param path
+ * @return
+ * @param
+ */
+ public static T getArgVal(JSONObject obj, String path) {
+ return AbstractParser.getValue(obj, StringUtil.splitPath(path));
+ }
+
/**反射调用
* @param function 例如get(object,key),参数只允许引用,不能直接传值
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
index 2060fe769..92bdfabaa 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
@@ -1683,10 +1683,10 @@ else if (join != null){
* @param pathKeys
* @return
*/
- protected static Object getValue(JSONObject parent, String[] pathKeys) {
+ public static V getValue(JSONObject parent, String[] pathKeys) {
if (parent == null || pathKeys == null || pathKeys.length <= 0) {
Log.w(TAG, "getChild parent == null || pathKeys == null || pathKeys.length <= 0 >> return parent;");
- return parent;
+ return (V) parent;
}
//逐层到达child的直接容器JSONObject parent
@@ -1698,7 +1698,7 @@ protected static Object getValue(JSONObject parent, String[] pathKeys) {
parent = getJSONObject(parent, pathKeys[i]);
}
- return parent == null ? null : parent.get(pathKeys[last]);
+ return parent == null ? null : (V) parent.get(pathKeys[last]);
}
From 3f458611cfbddb26166efa1b70cf784fea0a767c Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Wed, 9 Aug 2023 11:29:11 +0800
Subject: [PATCH 037/253] =?UTF-8?q?=E8=87=AA=202016=20=E5=B9=B4=E8=B5=B7?=
=?UTF-8?q?=E5=B7=B2=E8=BF=9E=E7=BB=AD=E7=BB=B4=E6=8A=A4=E8=BF=91=207=20?=
=?UTF-8?q?=E5=B9=B4=EF=BC=8C50+=20=E4=B8=AA=E8=B4=A1=E7=8C=AE=E8=80=85?=
=?UTF-8?q?=E3=80=8190+=20=E6=AC=A1=E5=8F=91=E7=89=88=E3=80=813000+=20?=
=?UTF-8?q?=E6=AC=A1=E6=8F=90=E4=BA=A4=EF=BC=8C=E4=B8=8D=E6=96=AD=E6=9B=B4?=
=?UTF-8?q?=E6=96=B0=E8=BF=AD=E4=BB=A3=E4=B8=AD...?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
https://github.com/Tencent/APIJSON#%E4%B8%BA%E4%BB%80%E4%B9%88%E9%80%89%E6%8B%A9-apijson
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 11a3da68b..51181e00d 100644
--- a/README.md
+++ b/README.md
@@ -189,7 +189,7 @@ https://github.com/Tencent/APIJSON/wiki
* **高质可靠代码** (代码严谨规范,商业分析软件源伞 Pinpoint 代码扫描报告平均每行代码 Bug 率低至 0.15%)
* **兼容各种项目** (协议不限 HTTP,与其它库无冲突,对各类 Web 框架集成友好且提供 SpringBoot, JFinal 的示例)
* **工程轻量小巧** (仅依赖 fastjson,Jar 仅 280KB,Java 文件仅 59 个共 13719 行代码,例如 APIJSONORM 4.3.1)
-* **多年持续迭代** (自 2016 年起已连续维护 6 年,50+ 个贡献者、90+ 次发版、3000+ 次提交,不断更新迭代中...)
+* **多年持续迭代** (自 2016 年起已连续维护近 7 年,50+ 个贡献者、90+ 次发版、3000+ 次提交,不断更新迭代中...)
**按照一般互联网中小型项目情况可得出以下对比表格:**
From d92ab71807979c2a9e2860d348355528db2b9d8f Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Wed, 9 Aug 2023 11:30:31 +0800
Subject: [PATCH 038/253] =?UTF-8?q?15.6K=20Star=20=E5=9C=A8=20400W=C2=A0Ja?=
=?UTF-8?q?va=20=E9=A1=B9=E7=9B=AE=E6=8E=92=E5=90=8D=E5=89=8D=20100?=
=?UTF-8?q?=EF=BC=8C=E8=BF=9C=E8=B6=85=20FLAG,=20BAT=20=E7=AD=89=E5=9B=BD?=
=?UTF-8?q?=E5=86=85=E5=A4=96=E7=BB=9D=E5=A4=A7=E9=83=A8=E5=88=86=E5=BC=80?=
=?UTF-8?q?=E6=BA=90=E9=A1=B9=E7=9B=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
https://github.com/Tencent/APIJSON#%E4%B8%BA%E4%BB%80%E4%B9%88%E9%80%89%E6%8B%A9-apijson
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 51181e00d..0dd54b28f 100644
--- a/README.md
+++ b/README.md
@@ -177,7 +177,7 @@ https://github.com/Tencent/APIJSON/wiki
* **解决十大痛点** (可帮前后端开发大幅提振开发效率、强力杜绝联调扯皮、巧妙规避文档缺陷、非常节省流量带宽)
* **开发提速很大** (CRUD 零代码热更新全自动,APIJSONBoot 对比 SSM、SSH 等保守估计可提速 20 倍以上)
* **腾讯官方开源** (使用 GitHub、Gitee、工蜂 等平台的官方账号开源,微信公众号、腾讯云+社区 等官方公告)
-* **社区影响力大** (GitHub 15.5K Star 在 400W Java 项目排名前 100,远超 FLAG, BAT 等国内外绝大部分开源项目)
+* **社区影响力大** (GitHub 15.6K Star 在 400W Java 项目排名前 100,远超 FLAG, BAT 等国内外绝大部分开源项目)
* **各项荣誉成就** (腾讯内外 5 个奖项、腾讯开源前八、腾讯后端 Star 第一、GitHub Java 日周月榜大满贯 等)
* **多样用户案例** (腾讯内有互娱、音乐、微信、云与智慧,外部有华为、华能、百度、快手、中兴、圆通、传音等)
* **适用场景广泛** (社交聊天、阅读资讯、影音娱乐、办公学习 等各种 App、网站、小程序、公众号 等非金融类项目)
From 47439d1add677e861e5718daeda306a123f6888c Mon Sep 17 00:00:00 2001
From: TommyLemon
Date: Sun, 20 Aug 2023 22:45:15 +0800
Subject: [PATCH 039/253] =?UTF-8?q?=E8=BF=9C=E7=A8=8B=E5=87=BD=E6=95=B0?=
=?UTF-8?q?=EF=BC=9A=E6=96=B0=E5=A2=9E=E6=94=AF=E6=8C=81=E4=BB=8E=E5=BD=93?=
=?UTF-8?q?=E5=89=8D=E8=AF=B7=E6=B1=82=E7=9A=84=E5=85=A8=E5=B1=80=E5=AF=B9?=
=?UTF-8?q?=E8=B1=A1=E5=8F=8A=20Parser=20=E5=85=A8=E5=B1=80=E7=BC=93?=
=?UTF-8?q?=E5=AD=98=E5=8F=96=E5=8F=82=E6=95=B0=E5=80=BC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
APIJSONORM/src/main/java/apijson/Log.java | 2 +-
.../apijson/orm/AbstractFunctionParser.java | 17 ++++++++++++++++-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/APIJSONORM/src/main/java/apijson/Log.java b/APIJSONORM/src/main/java/apijson/Log.java
index 0f3ce3cb4..a1fe34257 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 = "6.1.0";
+ public static final String VERSION = "6.2.1";
public static final String KEY_SYSTEM_INFO_DIVIDER = "\n---|-----APIJSON SYSTEM INFO-----|---\n";
public static final String OS_NAME;
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
index eb4a0119c..eaea97843 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
@@ -162,7 +162,22 @@ public AbstractFunctionParser setCurrentObject(@NotNull JSONObject currentObject
* @param
*/
public T getArgVal(String path) {
- return getArgVal(getCurrentObject(), path);
+ return getArgVal(path, false);
+ }
+ /**根据路径取值
+ * @param path
+ * @param tryAll false-仅当前对象,true-本次请求的全局对象以及 Parser 缓存值
+ * @return
+ * @param
+ */
+ public T getArgVal(String path, boolean tryAll) {
+ T val = getArgVal(getCurrentObject(), path);
+ if (tryAll == false || val != null) {
+ return val;
+ }
+
+ Parser> p = getParser();
+ return p == null ? null : (T) p.getValueByPath(path);
}
/**根据路径从对象 obj 中取值
* @param obj
From 36d4972233ca8a7db584e37333a95bb3b23d2f4d Mon Sep 17 00:00:00 2001
From: TommyLemon
Date: Sun, 20 Aug 2023 22:47:28 +0800
Subject: [PATCH 040/253] =?UTF-8?q?=E8=BF=9C=E7=A8=8B=E5=87=BD=E6=95=B0?=
=?UTF-8?q?=EF=BC=9A=E9=BB=98=E8=AE=A4=E6=94=AF=E6=8C=81=E4=BB=8E=E5=BD=93?=
=?UTF-8?q?=E5=89=8D=E8=AF=B7=E6=B1=82=E7=9A=84=E5=85=A8=E5=B1=80=E5=AF=B9?=
=?UTF-8?q?=E8=B1=A1=E5=8F=8A=20Parser=20=E5=85=A8=E5=B1=80=E7=BC=93?=
=?UTF-8?q?=E5=AD=98=E5=8F=96=E5=8F=82=E6=95=B0=E5=80=BC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/main/java/apijson/orm/AbstractFunctionParser.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
index eaea97843..c030de16a 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
@@ -162,7 +162,7 @@ public AbstractFunctionParser setCurrentObject(@NotNull JSONObject currentObject
* @param
*/
public T getArgVal(String path) {
- return getArgVal(path, false);
+ return getArgVal(path, true); // 误判概率很小 false);
}
/**根据路径取值
* @param path
From c8c3b92ce3bfec5922eab2919588039ddbc99709 Mon Sep 17 00:00:00 2001
From: TommyLemon
Date: Sun, 20 Aug 2023 23:32:28 +0800
Subject: [PATCH 041/253] =?UTF-8?q?=E8=BF=9C=E7=A8=8B=E5=87=BD=E6=95=B0?=
=?UTF-8?q?=EF=BC=9AgetArgVal=20=E6=96=B0=E5=A2=9E=E6=94=AF=E6=8C=81?=
=?UTF-8?q?=E4=BC=A0=20Class=20=20=E8=BF=94=E5=9B=9E=E6=8C=87=E5=AE=9A?=
=?UTF-8?q?=E7=B1=BB=E5=9E=8B=EF=BC=8C=E8=A7=A3=E5=86=B3=E7=94=A8=E7=BC=BA?=
=?UTF-8?q?=E7=9C=81=E7=9B=B8=E5=AF=B9=E8=B7=AF=E5=BE=84=E4=BB=8E=E5=BD=93?=
=?UTF-8?q?=E5=89=8D=E8=AF=B7=E6=B1=82=E7=9A=84=E5=85=A8=E5=B1=80=E5=AF=B9?=
=?UTF-8?q?=E8=B1=A1=E5=8F=8A=20Parser=20=E5=85=A8=E5=B1=80=E7=BC=93?=
=?UTF-8?q?=E5=AD=98=E5=8F=96=E4=B8=8D=E5=88=B0=E5=8F=82=E6=95=B0=E5=80=BC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../apijson/orm/AbstractFunctionParser.java | 28 +++++++++++++++----
.../apijson/orm/AbstractObjectParser.java | 4 +--
2 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
index c030de16a..afb1fb6b0 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
@@ -21,6 +21,7 @@
import java.util.*;
import static apijson.orm.AbstractSQLConfig.PATTERN_SCHEMA;
+import static apijson.orm.SQLConfig.TYPE_ITEM;
/**可远程调用的函数类
* @author Lemon
@@ -156,28 +157,39 @@ public AbstractFunctionParser setCurrentObject(@NotNull JSONObject currentObject
return this;
}
- /**根据路径从当前对象取值
+ /**根据路径取值
* @param path
* @return
* @param
*/
public T getArgVal(String path) {
- return getArgVal(path, true); // 误判概率很小 false);
+ return getArgVal(path, null); // 误判概率很小 false);
+ }
+ /**根据路径取值
+ * @param path
+ * @param clazz
+ * @return
+ * @param
+ */
+ public T getArgVal(String path, Class clazz) {
+ return getArgVal(path, clazz, true);
}
/**根据路径取值
* @param path
+ * @param clazz
* @param tryAll false-仅当前对象,true-本次请求的全局对象以及 Parser 缓存值
* @return
* @param
*/
- public T getArgVal(String path, boolean tryAll) {
- T val = getArgVal(getCurrentObject(), path);
+ public T getArgVal(String path, Class clazz, boolean tryAll) {
+ T val = getArgVal(getCurrentObject(), path, clazz);
if (tryAll == false || val != null) {
return val;
}
Parser> p = getParser();
- return p == null ? null : (T) p.getValueByPath(path);
+ String targetPath = AbstractParser.getValuePath(getParentPath(), path);
+ return p == null ? null : (T) p.getValueByPath(targetPath);
}
/**根据路径从对象 obj 中取值
* @param obj
@@ -186,7 +198,11 @@ public T getArgVal(String path, boolean tryAll) {
* @param
*/
public static T getArgVal(JSONObject obj, String path) {
- return AbstractParser.getValue(obj, StringUtil.splitPath(path));
+ return getArgVal(obj, path, null);
+ }
+ public static T getArgVal(JSONObject obj, String path, Class clazz) {
+ Object v = AbstractParser.getValue(obj, StringUtil.splitPath(path));
+ return clazz == null ? (T) v : TypeUtils.cast(v, clazz, ParserConfig.getGlobalInstance());
}
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java
index 61e17475e..301914dc9 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java
@@ -482,7 +482,7 @@ else if (isPlus) {
}
if (isPlus == false && isTable == false) {
- parseFunction(key, k, (String) value, parentPath, name, request, isMinus);
+ parseFunction(key, k, (String) value, this.type == TYPE_ITEM ? path : parentPath, name, request, isMinus);
}
else {
//远程函数比较少用,一般一个Table:{}内用到也就一两个,所以这里循环里new出来对性能影响不大。
@@ -958,7 +958,7 @@ public void onFunctionResponse(String type) throws Exception {
JSONObject json = isMinus ? sqlRequest : response; // key-():function 是实时执行,而不是在这里批量执行
for (Entry entry : functionSet) {
- parseFunction(entry.getKey(), entry.getKey(), entry.getValue(), parentPath, name, json, isMinus);
+ parseFunction(entry.getKey(), entry.getKey(), entry.getValue(), this.type == TYPE_ITEM ? path : parentPath, name, json, isMinus);
}
}
}
From 668ca2ab40b49260cbc12d08ea033200146c7383 Mon Sep 17 00:00:00 2001
From: cloudAndMonkey
Date: Fri, 25 Aug 2023 17:57:42 +0800
Subject: [PATCH 042/253] Update AbstractSQLConfig.java
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
https://github.com/Tencent/APIJSON/issues/602
假删除bug
---
APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
index 9d6018378..a471cd98f 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
@@ -5242,8 +5242,8 @@ else if (userId instanceof Subquery) {}
Object deletedKey = accessFakeDeleteMap == null ? null : accessFakeDeleteMap.get(KEY_DELETED_KEY);
boolean hasKey = deletedKey instanceof String && StringUtil.isNotEmpty(deletedKey, true);
Object deletedValue = hasKey ? accessFakeDeleteMap.get(KEY_DELETED_VALUE) : null;
- boolean containNotDeletedValue = hasKey ? accessFakeDeleteMap.containsKey(KEY_NOT_DELETED_VALUE) : null;
- Object notDeletedValue = containNotDeletedValue ? accessFakeDeleteMap.get(KEY_NOT_DELETED_VALUE) : null;
+ boolean containNotDeletedValue = hasKey ? accessFakeDeleteMap.containsKey(KEY_NOT_DELETED_VALUE) : false;
+ Object notDeletedValue = containNotDeletedValue ? accessFakeDeleteMap.get(KEY_NOT_DELETED_VALUE) : false;
if (deletedValue != null || containNotDeletedValue) {
boolean isFakeDelete = true;
@@ -5962,4 +5962,4 @@ public AbstractSQLConfig setWithAsExprPreparedValueList(List list) {
this.withAsExprPreparedValueList = list;
return this;
}
-}
\ No newline at end of file
+}
From 22a9406af592f171dc4a630d572fa3fd8d79b508 Mon Sep 17 00:00:00 2001
From: TommyLemon <1184482681@qq.com>
Date: Mon, 28 Aug 2023 22:02:42 +0800
Subject: [PATCH 043/253] =?UTF-8?q?=E7=94=9F=E6=80=81=EF=BC=9AAPIJSON=20?=
=?UTF-8?q?=E5=92=8C=20RuoYi=20=E6=A1=86=E6=9E=B6=E6=95=B4=E5=90=88?=
=?UTF-8?q?=EF=BC=8C=E5=AE=9E=E7=8E=B0=E9=9B=B6=E4=BB=A3=E7=A0=81=E7=94=9F?=
=?UTF-8?q?=E6=88=90=E9=A1=B5=E9=9D=A2=E6=A8=A1=E6=9D=BF=E6=8E=A5=E5=8F=A3?=
=?UTF-8?q?=EF=BC=8C=E5=9C=A8=E7=BA=BF=E7=BB=B4=E6=8A=A4=20APIJSON=20?=
=?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E9=85=8D=E7=BD=AE=E7=AD=89?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
创作不易,为热心的作者打开链接点亮 ⭐️ Star 支持/收藏 下吧~
https://gitee.com/TommyLemon/apijson-ruoyi
---
README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/README.md b/README.md
index 0dd54b28f..9a53bc6f3 100644
--- a/README.md
+++ b/README.md
@@ -646,6 +646,8 @@ Issue/问卷 一般解答顺序:贡献者 > 帮助他人的用户 > 提供任
[apijson-examples](https://gitee.com/drone/apijson-examples) APIJSON 的前端、业务后端、管理后端 Demo
+[apijson-ruoyi](https://gitee.com/yxiedd/apijson-ruoyi) APIJSON 和 RuoYi 框架整合,实现零代码生成页面模板接口,在线维护 APIJSON 数据库配置等
+
[light4j](https://github.com/xlongwei/light4j) 整合 APIJSON 和微服务框架 light-4j 的 Demo,同时接入了 Redis
[SpringServer1.2-APIJSON](https://github.com/Airforce-1/SpringServer1.2-APIJSON) 智慧党建服务器端,提供 上传 和 下载 文件的接口
From da15edb94b4faa7b614bac7012833a94570a5659 Mon Sep 17 00:00:00 2001
From: Jarrod Quan
Date: Fri, 1 Sep 2023 22:19:20 +0800
Subject: [PATCH 044/253] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=89=88=E6=9C=AC?=
=?UTF-8?q?=E5=8F=B7?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
APIJSONORM/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/APIJSONORM/pom.xml b/APIJSONORM/pom.xml
index e72689312..60378cbd9 100644
--- a/APIJSONORM/pom.xml
+++ b/APIJSONORM/pom.xml
@@ -5,7 +5,7 @@
com.github.Tencent
APIJSON
- 6.1.0
+ 6.2.0
jar
APIJSONORM
From 2a6b81816ad43725d7236a5aadec7b746123eb02 Mon Sep 17 00:00:00 2001
From: Jarrod Quan
Date: Fri, 1 Sep 2023 22:19:59 +0800
Subject: [PATCH 045/253] =?UTF-8?q?=E6=B7=BB=E5=8A=A0source=E6=8F=92?=
=?UTF-8?q?=E4=BB=B6=EF=BC=8C=E6=96=B9=E4=BE=BF=E4=BD=BF=E7=94=A8=E8=80=85?=
=?UTF-8?q?=E6=8B=89=E5=8F=96=E6=BA=90=E7=A0=81=E6=9F=A5=E9=98=85?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
APIJSONORM/pom.xml | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/APIJSONORM/pom.xml b/APIJSONORM/pom.xml
index 60378cbd9..b29887e04 100644
--- a/APIJSONORM/pom.xml
+++ b/APIJSONORM/pom.xml
@@ -36,6 +36,20 @@
1.8
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.2.1
+
+
+ package
+
+ jar-no-fork
+
+
+
+
From d4675cd1c56b5de37d93193ea283582c3330ddf7 Mon Sep 17 00:00:00 2001
From: TommyLemon
Date: Sat, 2 Sep 2023 21:42:51 +0800
Subject: [PATCH 046/253] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E4=B8=80=E4=B8=AA?=
=?UTF-8?q?=E4=BA=8B=E5=8A=A1=E5=86=85=E6=9C=89=E5=A4=9A=E7=B1=BB=E5=9E=8B?=
=?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93/=E5=A4=9A=E4=B8=AA=E4=B8=8D?=
=?UTF-8?q?=E5=90=8C=E6=95=B0=E6=8D=AE=E5=BA=93=E8=BF=9E=E6=8E=A5=E6=9C=89?=
=?UTF-8?q?=E6=97=B6=E4=B8=8D=E8=83=BD=E5=90=8C=E6=AD=A5=E6=8F=90=E4=BA=A4?=
=?UTF-8?q?/=E5=9B=9E=E6=BB=9A=EF=BC=9B=E8=A7=A3=E5=86=B3=E7=89=B9?=
=?UTF-8?q?=E5=AE=9A=E7=89=88=E6=9C=AC=E7=9A=84=20MySQL=20=E7=AD=89?=
=?UTF-8?q?=E9=83=A8=E5=88=86=E6=95=B0=E6=8D=AE=E5=BA=93=E9=87=8D=E5=A4=8D?=
=?UTF-8?q?=20setAutoCommit/setTransactionIsolation=20=E6=8A=A5=E9=94=99?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../apijson/orm/AbstractFunctionParser.java | 4 +
.../java/apijson/orm/AbstractSQLExecutor.java | 100 +++++++++++-------
2 files changed, 63 insertions(+), 41 deletions(-)
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
index afb1fb6b0..dc40ac41e 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
@@ -511,6 +511,10 @@ public static void verifySchema(String sch, String table) {
}
public static String extractSchema(String sch, String table) {
+ if (StringUtil.isEmpty(sch)) {
+ return sch;
+ }
+
if (table == null) {
table = "Table";
}
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java
index 7b10b3193..d11638bd1 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java
@@ -9,7 +9,7 @@
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
-import java.util.Date;
+import java.util.*;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -22,14 +22,7 @@
import java.time.LocalDateTime;
import java.time.Month;
import java.time.Year;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
import java.util.Map.Entry;
-import java.util.Set;
import java.util.regex.Pattern;
import com.alibaba.fastjson.JSON;
@@ -1202,7 +1195,7 @@ public void setTransactionIsolation(int transactionIsolation) {
this.transactionIsolation = transactionIsolation;
}
- private boolean isIsolationStatusSet = false; //已设置事务等级
+ protected Map isolationMap = new LinkedHashMap<>();
@Override
public void begin(int transactionIsolation) throws SQLException {
Log.d("\n\n" + TAG, "<<<<<<<<<<<<<< TRANSACTION begin transactionIsolation = " + transactionIsolation + " >>>>>>>>>>>>>>>>>>>>>>> \n\n");
@@ -1210,27 +1203,47 @@ public void begin(int transactionIsolation) throws SQLException {
// if (connection == null || connection.isClosed()) {
// return;
// }
- if (! isIsolationStatusSet) { //只设置一次Isolation等级 PG重复设置事务等级会报错
- isIsolationStatusSet = true;
- connection.setTransactionIsolation(transactionIsolation); // 这句导致 TDengine 驱动报错
+
+ // 将所有连接设置隔离级别,且禁止自动提交,需要以下代码来 commit/rollback
+ Collection connections = connectionMap.values();
+ if (connections != null) {
+ for (Connection connection : connections) {
+ try {
+ Integer isolation = isolationMap.get(connection);
+ if (isolation == null || isolation != transactionIsolation) { // 只设置一次 Isolation 等级 PG 及 MySQL 某些版本重复设置事务等级会报错
+ isolationMap.put(connection, transactionIsolation);
+
+ connection.setTransactionIsolation(transactionIsolation); // 这句导致 TDengine 驱动报错
+ if (isolation == null) {
+ connection.setAutoCommit(false); // java.sql.SQLException: Can''t call commit when autocommit=true
+ }
+ }
+ }
+ catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
}
- connection.setAutoCommit(false); //java.sql.SQLException: Can''t call commit when autocommit=true
}
+
@Override
public void rollback() throws SQLException {
Log.d("\n\n" + TAG, "<<<<<<<<<<<<<< TRANSACTION rollback >>>>>>>>>>>>>>>>>>>>>>> \n\n");
//权限校验不通过,connection 也不会生成,还是得判断 //不做判断,如果掩盖了问题,调用层都不知道为啥事务没有提交成功
- if (connection == null) { // || connection.isClosed()) {
- return;
- }
+// if (connection == null) { // || connection.isClosed()) {
+// return;
+// }
+
// 将所有连接进行回滚
Collection connections = connectionMap.values();
-
if (connections != null) {
for (Connection connection : connections) {
try {
if (connection != null && connection.isClosed() == false) {
connection.rollback();
+ connection.setAutoCommit(true);
+
+ isolationMap.remove(connection);
}
}
catch (SQLException e) {
@@ -1239,50 +1252,56 @@ public void rollback() throws SQLException {
}
}
}
+
@Override
public void rollback(Savepoint savepoint) throws SQLException {
Log.d("\n\n" + TAG, "<<<<<<<<<<<<<< TRANSACTION rollback savepoint " + (savepoint == null ? "" : "!") + "= null >>>>>>>>>>>>>>>>>>>>>>> \n\n");
- //权限校验不通过,connection 也不会生成,还是得判断 //不做判断,如果掩盖了问题,调用层都不知道为啥事务没有提交成功
- if (connection == null) { // || connection.isClosed()) {
+ if (savepoint == null) {
+ rollback();
return;
}
-
- if(StringUtil.isEmpty(savepoint)) {
- // 将所有连接进行回滚
- Collection connections = connectionMap.values();
-
- if (connections != null) {
- for (Connection connection : connections) {
- try {
- if (connection != null && connection.isClosed() == false) {
- connection.rollback();
- }
- }
- catch (SQLException e) {
- e.printStackTrace();
+
+ //权限校验不通过,connection 也不会生成,还是得判断 //不做判断,如果掩盖了问题,调用层都不知道为啥事务没有提交成功
+// if (connection == null) { // || connection.isClosed()) {
+// return;
+// }
+
+ // 将所有连接进行回滚
+ Collection connections = connectionMap.values();
+ if (connections != null) {
+ for (Connection connection : connections) {
+ try {
+ if (connection != null && connection.isClosed() == false) {
+ connection.rollback(savepoint);
+ connection.setAutoCommit(true);
+
+ isolationMap.remove(connection);
}
}
+ catch (SQLException e) {
+ e.printStackTrace();
+ }
}
- } else {
- connection.rollback(savepoint);
}
}
+
@Override
public void commit() throws SQLException {
Log.d("\n\n" + TAG, "<<<<<<<<<<<<<< TRANSACTION commit >>>>>>>>>>>>>>>>>>>>>>> \n\n");
//权限校验不通过,connection 也不会生成,还是得判断 //不做判断,如果掩盖了问题,调用层都不知道为啥事务没有提交成功
- if (connection == null) { // || connection.isClosed()) {
- return;
- }
+// if (connection == null) { // || connection.isClosed()) {
+// return;
+// }
// 将所有连接进行提交
Collection connections = connectionMap.values();
-
if (connections != null) {
for (Connection connection : connections) {
try {
if (connection != null && connection.isClosed() == false) {
connection.commit();
+
+ isolationMap.remove(connection);
}
}
catch (SQLException e) {
@@ -1309,7 +1328,6 @@ public void close() {
}
Collection connections = connectionMap.values();
-
if (connections != null) {
for (Connection connection : connections) {
try {
@@ -1334,7 +1352,7 @@ public ResultSet executeQuery(@NotNull SQLConfig config, String sql) throws Exce
Connection conn = getConnection(config);
Statement stt = conn.createStatement();
- //Statement stt = config.isTDengine()
+ // Statement stt = config.isTDengine()
// ? conn.createStatement() // fix Presto: ResultSet: Exception: set type is TYPE_FORWARD_ONLY, Result set concurrency must be CONCUR_READ_ONLY
// : conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
From 1d6307887b98aa3a9bd0a634bace3b8d70cdf261 Mon Sep 17 00:00:00 2001
From: TommyLemon
Date: Sat, 2 Sep 2023 21:55:46 +0800
Subject: [PATCH 047/253] =?UTF-8?q?=E6=9D=83=E9=99=90=EF=BC=9A=E8=A7=A3?=
=?UTF-8?q?=E5=86=B3=E5=88=A0=E6=94=B9=E4=B8=8D=E6=94=AF=E6=8C=81=20String?=
=?UTF-8?q?=20=E7=B1=BB=E5=9E=8B=E4=B8=BB=E9=94=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/apijson/orm/AbstractVerifier.java | 35 ++++++++++++-------
1 file changed, 22 insertions(+), 13 deletions(-)
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java b/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java
index 3429640fa..79c1d1191 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java
@@ -376,18 +376,18 @@ public void verifyUseRole(SQLConfig config, String table, RequestMethod method,
break;
case CONTACT:
case CIRCLE:
- //TODO 做一个缓存contactMap,提高[]:{}查询性能, removeAccessInfo时map.remove(visitorId)
- //不能在Visitor内null -> [] ! 否则会导致某些查询加上不需要的条件!
+ // TODO 做一个缓存contactMap,提高[]:{}查询性能, removeAccessInfo时map.remove(visitorId)
+ // 不能在 Visitor内null -> [] ! 否则会导致某些查询加上不需要的条件!
List list = visitor.getContactIdList() == null
? new ArrayList() : new ArrayList(visitor.getContactIdList());
if (CIRCLE.equals(role)) {
list.add(visitorId);
}
- //key!{}:[] 或 其它没有明确id的条件 等 可以和key{}:list组合。类型错误就报错
- requestId = config.getWhere(visitorIdKey, true);//JSON里数值不能保证是Long,可能是Integer
+ // key!{}:[] 或 其它没有明确id的条件 等 可以和 key{}:[] 组合。类型错误就报错
+ requestId = config.getWhere(visitorIdKey, true); // JSON 里数值不能保证是 Long,可能是 Integer
@SuppressWarnings("unchecked")
- Collection requestIdArray = (Collection) config.getWhere(visitorIdKey + "{}", true);//不能是 &{}, |{} 不要传,直接{}
+ Collection requestIdArray = (Collection) config.getWhere(visitorIdKey + "{}", true); // 不能是 &{}, |{} 不要传,直接 {}
if (requestId != null) {
if (requestIdArray == null) {
requestIdArray = new JSONArray();
@@ -395,20 +395,29 @@ public void verifyUseRole(SQLConfig config, String table, RequestMethod method,
requestIdArray.add(requestId);
}
- if (requestIdArray == null) {//可能是@得到 || requestIdArray.isEmpty()) {//请求未声明key:id或key{}:[...]条件,自动补全
- config.putWhere(visitorIdKey+"{}", JSON.parseArray(list), true); //key{}:[]有效,SQLConfig里throw NotExistException
+ if (requestIdArray == null) { // 可能是 @ 得到 || requestIdArray.isEmpty()) { // 请求未声明 key:id 或 key{}:[...] 条件,自动补全
+ config.putWhere(visitorIdKey+"{}", JSON.parseArray(list), true); // key{}:[] 有效,SQLConfig 里 throw NotExistException
}
- else {//请求已声明key:id或key{}:[]条件,直接验证
+ else { // 请求已声明 key:id 或 key{}:[] 条件,直接验证
for (Object id : requestIdArray) {
if (id == null) {
continue;
}
- if (id instanceof Number == false) {//不能准确地判断Long,可能是Integer
- throw new UnsupportedDataTypeException(table + ".id类型错误,id类型必须是Long!");
+
+ if (id instanceof Number) { // 不能准确地判断 Long,可能是 Integer
+ if (((Number) id).longValue() <= 0 || list.contains(Long.valueOf("" + id)) == false) { // Integer等转为 Long 才能正确判断,强转崩溃
+ throw new IllegalAccessException(visitorIdKey + " = " + id + " 的 " + table
+ + " 不允许 " + role + " 用户的 " + method.name() + " 请求!");
+ }
+ }
+ else if (id instanceof String) {
+ if (StringUtil.isEmpty(id) || list.contains(id) == false) {
+ throw new IllegalAccessException(visitorIdKey + " = " + id + " 的 " + table
+ + " 不允许 " + role + " 用户的 " + method.name() + " 请求!");
+ }
}
- if (list.contains(Long.valueOf("" + id)) == false) {//Integer等转为Long才能正确判断。强转崩溃
- throw new IllegalAccessException(visitorIdKey + " = " + id + " 的 " + table
- + " 不允许 " + role + " 用户的 " + method.name() + " 请求!");
+ else {
+ throw new UnsupportedDataTypeException(table + ".id 类型错误,类型必须是 Long/String!");
}
}
}
From d748641814ccfe340597239f81927aba2bfc35d4 Mon Sep 17 00:00:00 2001
From: TommyLemon
Date: Sat, 2 Sep 2023 22:00:36 +0800
Subject: [PATCH 048/253] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E5=BC=95=E7=94=A8?=
=?UTF-8?q?=E8=B5=8B=E5=80=BC=E6=9F=A5=E4=B8=8D=E5=88=B0=E5=80=BC=E6=97=B6?=
=?UTF-8?q?=E8=BF=94=E5=9B=9E=E4=BC=A0=E5=85=A5=E8=B7=AF=E5=BE=84=E5=AF=BC?=
=?UTF-8?q?=E8=87=B4=E6=9F=A5=E8=AF=A2=E3=80=81=E6=9D=83=E9=99=90=E7=AD=89?=
=?UTF-8?q?=E5=90=84=E7=A7=8D=E5=BC=82=E5=B8=B8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
APIJSONORM/src/main/java/apijson/orm/AbstractParser.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
index 92bdfabaa..685f1c8ac 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
@@ -1850,8 +1850,8 @@ public Object getValueByPath(String valuePath) {
return target;
}
- Log.i(TAG, "getValueByPath return valuePath;");
- return valuePath;
+ Log.i(TAG, "getValueByPath return null;");
+ return null;
}
//依赖引用关系 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
From d4be7ce52ae94768fce21909d31a124416eb72f7 Mon Sep 17 00:00:00 2001
From: TommyLemon
Date: Sun, 3 Sep 2023 02:56:48 +0800
Subject: [PATCH 049/253] =?UTF-8?q?=E8=BF=9C=E7=A8=8B=E5=87=BD=E6=95=B0?=
=?UTF-8?q?=EF=BC=9A=E4=B8=B0=E5=AF=8C=E5=8F=96=E5=B8=B8=E7=94=A8=E7=B1=BB?=
=?UTF-8?q?=E5=9E=8B=E5=8F=82=E6=95=B0=E5=80=BC=E7=9A=84=E5=87=BD=E6=95=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../apijson/orm/AbstractFunctionParser.java | 135 ++++++++++++++++--
1 file changed, 126 insertions(+), 9 deletions(-)
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
index dc40ac41e..75f0d261d 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
@@ -5,12 +5,10 @@
package apijson.orm;
-import apijson.Log;
-import apijson.NotNull;
-import apijson.RequestMethod;
-import apijson.StringUtil;
+import apijson.*;
import apijson.orm.exception.UnsupportedDataTypeException;
import apijson.orm.script.ScriptExecutor;
+import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.util.TypeUtils;
@@ -18,6 +16,7 @@
import java.lang.invoke.WrongMethodTypeException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.math.BigDecimal;
import java.util.*;
import static apijson.orm.AbstractSQLConfig.PATTERN_SCHEMA;
@@ -44,6 +43,7 @@ public class AbstractFunctionParser implements FunctionParser {
// >
public static Map SCRIPT_EXECUTOR_MAP;
public static Map FUNCTION_MAP;
+
static {
FUNCTION_MAP = new HashMap<>();
SCRIPT_EXECUTOR_MAP = new HashMap<>();
@@ -53,9 +53,11 @@ public class AbstractFunctionParser implements FunctionParser {
private String tag;
private int version;
private JSONObject request;
+
public AbstractFunctionParser() {
this(null, null, 0, null);
}
+
public AbstractFunctionParser(RequestMethod method, String tag, int version, @NotNull JSONObject request) {
setMethod(method == null ? RequestMethod.GET : method);
setTag(tag);
@@ -64,10 +66,12 @@ public AbstractFunctionParser(RequestMethod method, String tag, int version, @No
}
private Parser> parser;
+
@Override
public Parser> getParser() {
return parser;
}
+
@Override
public AbstractFunctionParser setParser(Parser> parser) {
this.parser = parser;
@@ -78,85 +82,198 @@ public AbstractFunctionParser setParser(Parser> parser) {
public RequestMethod getMethod() {
return method;
}
+
@Override
public AbstractFunctionParser setMethod(RequestMethod method) {
this.method = method;
return this;
}
+
@Override
public String getTag() {
return tag;
}
+
@Override
public AbstractFunctionParser setTag(String tag) {
this.tag = tag;
return this;
}
+
@Override
public int getVersion() {
return version;
}
+
@Override
public AbstractFunctionParser setVersion(int version) {
this.version = version;
return this;
}
-
+
private String key;
+
@Override
public String getKey() {
return key;
}
+
@Override
public AbstractFunctionParser setKey(String key) {
this.key = key;
return this;
}
-
+
private String parentPath;
+
@Override
public String getParentPath() {
return parentPath;
}
+
@Override
public AbstractFunctionParser setParentPath(String parentPath) {
this.parentPath = parentPath;
return this;
}
+
private String currentName;
+
@Override
public String getCurrentName() {
return currentName;
}
+
@Override
public AbstractFunctionParser setCurrentName(String currentName) {
this.currentName = currentName;
return this;
}
-
+
@NotNull
@Override
public JSONObject getRequest() {
return request;
}
+
@Override
public AbstractFunctionParser setRequest(@NotNull JSONObject request) {
this.request = request;
return this;
}
-
+
private JSONObject currentObject;
- @NotNull
+
+ @NotNull
@Override
public JSONObject getCurrentObject() {
return currentObject;
}
+
@Override
public AbstractFunctionParser setCurrentObject(@NotNull JSONObject currentObject) {
this.currentObject = currentObject;
return this;
}
+ /**根据路径取 Boolean 值
+ * @param path
+ * @return
+ */
+ public Boolean getArgBool(String path) {
+ return getArgVal(path, Boolean.class);
+ }
+
+ /**根据路径取 Integer 值
+ * @param path
+ * @return
+ */
+ public Integer getArgInt(String path) {
+ return getArgVal(path, Integer.class);
+ }
+
+ /**根据路径取 Long 值
+ * @param path
+ * @return
+ */
+ public Long getArgLong(String path) {
+ return getArgVal(path, Long.class);
+ }
+
+ /**根据路径取 Float 值
+ * @param path
+ * @return
+ */
+ public Float getArgFloat(String path) {
+ return getArgVal(path, Float.class);
+ }
+
+ /**根据路径取 Double 值
+ * @param path
+ * @return
+ */
+ public Double getArgDouble(String path) {
+ return getArgVal(path, Double.class);
+ }
+
+ /**根据路径取 Number 值
+ * @param path
+ * @return
+ */
+ public Number getArgNum(String path) {
+ return getArgVal(path, Number.class);
+ }
+
+ /**根据路径取 BigDecimal 值
+ * @param path
+ * @return
+ */
+ public BigDecimal getArgDecimal(String path) {
+ return getArgVal(path, BigDecimal.class);
+ }
+
+ /**根据路径取 String 值
+ * @param path
+ * @return
+ */
+ public String getArgStr(String path) {
+ Object obj = getArgVal(path);
+ return JSON.toJSONString(obj);
+ }
+
+ /**根据路径取 JSONObject 值
+ * @param path
+ * @return
+ */
+ public JSONObject getArgObj(String path) {
+ return getArgVal(path, JSONObject.class);
+ }
+
+ /**根据路径取 JSONArray 值
+ * @param path
+ * @return
+ */
+ public JSONArray getArgArr(String path) {
+ return getArgVal(path, JSONArray.class);
+ }
+
+ /**根据路径取 List 值
+ * @param path
+ * @return
+ */
+ public List getArgList(String path) {
+ return getArgList(path, null);
+ }
+
+ /**根据路径取 List 值
+ * @param path
+ * @return
+ */
+ public List getArgList(String path, Class clazz) {
+ String s = getArgStr(path);
+ return JSON.parseArray(s, clazz);
+ }
+
/**根据路径取值
* @param path
* @return
From eccf2524669d390dcadd9ab1caaa07fab19330bb Mon Sep 17 00:00:00 2001
From: TommyLemon
Date: Sun, 3 Sep 2023 03:52:49 +0800
Subject: [PATCH 050/253] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=90=8C=E4=B8=80?=
=?UTF-8?q?=E4=B8=AA=E8=AF=B7=E6=B1=82=E5=86=85=E5=A4=9A=E7=A7=8D=E4=B8=8D?=
=?UTF-8?q?=E5=90=8C=E6=93=8D=E4=BD=9C=E7=9A=84=E5=85=B3=E9=94=AE=E8=AF=8D?=
=?UTF-8?q?=EF=BC=8C=E6=96=B0=E5=A2=9E=E6=94=AF=E6=8C=81=20@post:=20"User"?=
=?UTF-8?q?,=20@gets:=20{=20"Privacy":=20"Privacy-phone"=20}=20=E7=AD=89?=
=?UTF-8?q?=E7=AE=80=E5=8C=96=E5=86=99=E6=B3=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/main/java/apijson/JSONObject.java | 28 +++-
.../src/main/java/apijson/RequestMethod.java | 20 ++-
.../main/java/apijson/orm/AbstractParser.java | 144 +++++++++++-------
.../java/apijson/orm/AbstractSQLConfig.java | 78 +++++++---
4 files changed, 184 insertions(+), 86 deletions(-)
diff --git a/APIJSONORM/src/main/java/apijson/JSONObject.java b/APIJSONORM/src/main/java/apijson/JSONObject.java
index a73203596..571c0aedf 100755
--- a/APIJSONORM/src/main/java/apijson/JSONObject.java
+++ b/APIJSONORM/src/main/java/apijson/JSONObject.java
@@ -6,6 +6,7 @@
package apijson;
import java.util.ArrayList;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -151,7 +152,16 @@ public JSONObject setUserIdIn(List list) {
public static final String KEY_ORDER = "@order"; //排序方式
public static final String KEY_RAW = "@raw"; // 自定义原始 SQL 片段
public static final String KEY_JSON = "@json"; //SQL Server 把字段转为 JSON 输出
- public static final String KEY_METHOD = "@method"; //json对象配置操作方法
+ public static final String KEY_METHOD = "@method"; // json 对象配置操作方法
+ public static final String KEY_GET = "@get"; // json 对象配置操作方法
+ public static final String KEY_GETS = "@gets"; // json 对象配置操作方法
+ public static final String KEY_HEAD = "@head"; // json 对象配置操作方法
+ public static final String KEY_HEADS = "@heads"; // json 对象配置操作方法
+ public static final String KEY_POST = "@post"; // json 对象配置操作方法
+ public static final String KEY_PUT = "@put"; // json 对象配置操作方法
+ public static final String KEY_DELETE = "@delete"; // json 对象配置操作方法
+
+ public static final Map KEY_METHOD_ENUM_MAP;
public static final List TABLE_KEY_LIST;
static {
@@ -174,6 +184,22 @@ public JSONObject setUserIdIn(List list) {
TABLE_KEY_LIST.add(KEY_RAW);
TABLE_KEY_LIST.add(KEY_JSON);
TABLE_KEY_LIST.add(KEY_METHOD);
+ TABLE_KEY_LIST.add(KEY_GET);
+ TABLE_KEY_LIST.add(KEY_GETS);
+ TABLE_KEY_LIST.add(KEY_HEAD);
+ TABLE_KEY_LIST.add(KEY_HEADS);
+ TABLE_KEY_LIST.add(KEY_POST);
+ TABLE_KEY_LIST.add(KEY_PUT);
+ TABLE_KEY_LIST.add(KEY_DELETE);
+
+ KEY_METHOD_ENUM_MAP = new LinkedHashMap<>();
+ KEY_METHOD_ENUM_MAP.put(KEY_GET, RequestMethod.GET);
+ KEY_METHOD_ENUM_MAP.put(KEY_GETS, RequestMethod.GETS);
+ KEY_METHOD_ENUM_MAP.put(KEY_HEAD, RequestMethod.HEAD);
+ KEY_METHOD_ENUM_MAP.put(KEY_HEADS, RequestMethod.HEADS);
+ KEY_METHOD_ENUM_MAP.put(KEY_POST, RequestMethod.POST);
+ KEY_METHOD_ENUM_MAP.put(KEY_PUT, RequestMethod.PUT);
+ KEY_METHOD_ENUM_MAP.put(KEY_DELETE, RequestMethod.DELETE);
}
//@key关键字都放这个类 >>>>>>>>>>>>>>>>>>>>>>
diff --git a/APIJSONORM/src/main/java/apijson/RequestMethod.java b/APIJSONORM/src/main/java/apijson/RequestMethod.java
index 9e2f09bef..410775c1a 100755
--- a/APIJSONORM/src/main/java/apijson/RequestMethod.java
+++ b/APIJSONORM/src/main/java/apijson/RequestMethod.java
@@ -5,6 +5,9 @@
package apijson;
+import java.util.Arrays;
+import java.util.List;
+
/**请求方法,对应org.springframework.web.bind.annotation.RequestMethod,多出GETS,HEADS方法
* @author Lemon
*/
@@ -41,17 +44,20 @@ public enum RequestMethod {
PUT,
/**
- * json包含多条语句,支持增删改查,函数调用
+ * 删除数据
*/
- CRUD,
-
+ DELETE,
+
/**
- * 删除数据
+ * json 包含多条语句,支持增删改查、函数调用
*/
- DELETE;
-
- public static final RequestMethod[] ALL = new RequestMethod[]{ GET, HEAD, GETS, HEADS, POST, PUT, CRUD, DELETE};
+ CRUD;
+ public static final RequestMethod[] ALL = new RequestMethod[]{ GET, HEAD, GETS, HEADS, POST, PUT, DELETE, CRUD };
+ public static final List ALL_NAME_LIST = Arrays.asList(
+ GET.name(), HEAD.name(), GETS.name(), HEADS.name(), POST.name(), PUT.name(), DELETE.name(), CRUD.name()
+ );
+
/**是否为GET请求方法
* @param method
* @param containPrivate 包含私密(非明文)获取方法GETS
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
index 685f1c8ac..c731b02c3 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
@@ -410,11 +410,12 @@ public JSONObject parseResponse(JSONObject request) {
requestObject = request;
try {
setVersion(requestObject.getIntValue(JSONRequest.KEY_VERSION));
+ requestObject.remove(JSONRequest.KEY_VERSION);
+
if (getMethod() != RequestMethod.CRUD) {
setTag(requestObject.getString(JSONRequest.KEY_TAG));
requestObject.remove(JSONRequest.KEY_TAG);
}
- requestObject.remove(JSONRequest.KEY_VERSION);
} catch (Exception e) {
return extendErrorResult(requestObject, e, requestMethod, getRequestURL(), isRoot);
}
@@ -2089,7 +2090,7 @@ protected JSONObject getRequestStructure(RequestMethod method, String tag, int v
}
protected JSONObject batchVerify(RequestMethod method, String tag, int version, String name, @NotNull JSONObject request, int maxUpdateCount, SQLCreator creator) throws Exception {
- JSONObject jsonObject = new JSONObject(true);
+ JSONObject correctRequest = new JSONObject(true);
List removeTmpKeys = new ArrayList<>(); // 请求json里面的临时变量,不需要带入后面的业务中,比如 @post、@get等
Set reqSet = request == null ? null : request.keySet();
@@ -2098,49 +2099,82 @@ protected JSONObject batchVerify(RequestMethod method, String tag, int version,
}
for (String key : reqSet) {
- // key重复直接抛错(xxx:alias, xxx:alias[])
- if (jsonObject.containsKey(key) || jsonObject.containsKey(key + apijson.JSONObject.KEY_ARRAY)) {
- throw new IllegalArgumentException("对象名重复,请添加别名区分 ! ,重复对象名为: " + key);
+ // key 重复直接抛错(xxx:alias, xxx:alias[])
+ if (correctRequest.containsKey(key) || correctRequest.containsKey(key + apijson.JSONObject.KEY_ARRAY)) {
+ throw new IllegalArgumentException("对象名重复,请添加别名区分 ! 重复对象名为: " + key);
}
- // @post、@get等RequestMethod
+ // @post、@get 等 RequestMethod
try {
- if (key.startsWith("@") && getEnum(RequestMethod.class, key.substring(1).toUpperCase(), null) != null) {
+ RequestMethod keyMethod = apijson.orm.JSONRequest.KEY_METHOD_ENUM_MAP.get(key);
+ if (keyMethod != null) {
// 如果不匹配,异常不处理即可
- RequestMethod _method = RequestMethod.valueOf(key.substring(1).toUpperCase());
removeTmpKeys.add(key);
- JSONObject obj = request.getJSONObject(key);
- Set set = obj == null ? new HashSet<>() : obj.keySet();
+ Object val = request.get(key);
+ JSONObject obj = val instanceof JSONObject ? request.getJSONObject(key) : null;
+ if (obj == null) {
+ if (val instanceof String) {
+ String[] tbls = StringUtil.split((String) val);
+ if (tbls != null && tbls.length > 0) {
+ obj = new JSONObject(true);
+ for (int i = 0; i < tbls.length; i++) {
+ String tbl = tbls[i];
+ if (obj.containsKey(tbl)) {
+ throw new ConflictException(key + ": value 中 " + tbl + " 已经存在,不能重复!");
+ }
+ obj.put(tbl, new JSONObject(true));
+ }
+ }
+ }
+ else {
+ throw new IllegalArgumentException(key + ": value 中 value 类型错误,只能是 String 或 JSONObject {} !");
+ }
+ }
+
+ Set> set = obj == null ? new HashSet<>() : obj.entrySet();
- for (String objKey : set) {
+ for (Entry objEntry : set) {
+ String objKey = objEntry == null ? null : objEntry.getKey();
if (objKey == null) {
continue;
}
Map objAttrMap = new HashMap<>();
- objAttrMap.put(apijson.JSONObject.KEY_METHOD, _method);
+ objAttrMap.put(apijson.JSONObject.KEY_METHOD, keyMethod);
keyObjectAttributesMap.put(objKey, objAttrMap);
- JSONObject objAttrJson = obj.getJSONObject(objKey);
- Set> objSet = objAttrJson == null ? new HashSet<>() : objAttrJson.entrySet();
- for (Entry entry : objSet) {
- String objAttrKey = entry == null ? null : entry.getKey();
- if (objAttrKey == null) {
- continue;
+ Object objVal = objEntry.getValue();
+ JSONObject objAttrJson = objVal instanceof JSONObject ? obj.getJSONObject(objKey) : null;
+ if (objAttrJson == null) {
+ if (objVal instanceof String) {
+ objAttrMap.put(JSONRequest.KEY_TAG, objVal);
}
+ else {
+ throw new IllegalArgumentException(key + ": { " + objKey + ": value 中 value 类型错误,只能是 String 或 JSONObject {} !");
+ }
+ }
+ else {
+ Set> objSet = objAttrJson == null ? new HashSet<>() : objAttrJson.entrySet();
- switch (objAttrKey) {
- case apijson.JSONObject.KEY_DATASOURCE:
- case apijson.JSONObject.KEY_SCHEMA:
- case apijson.JSONObject.KEY_DATABASE:
- case JSONRequest.KEY_VERSION:
- case apijson.JSONObject.KEY_ROLE:
- case JSONRequest.KEY_TAG:
- objAttrMap.put(objAttrKey, entry.getValue());
- break;
- default:
- break;
+ for (Entry entry : objSet) {
+ String objAttrKey = entry == null ? null : entry.getKey();
+ if (objAttrKey == null) {
+ continue;
+ }
+
+ switch (objAttrKey) {
+ case apijson.JSONObject.KEY_DATASOURCE:
+ case apijson.JSONObject.KEY_SCHEMA:
+ case apijson.JSONObject.KEY_DATABASE:
+ case JSONRequest.KEY_VERSION:
+ case apijson.JSONObject.KEY_ROLE:
+ case JSONRequest.KEY_TAG:
+ objAttrMap.put(objAttrKey, entry.getValue());
+ break;
+ default:
+ break;
+ }
}
}
}
@@ -2189,15 +2223,17 @@ protected JSONObject batchVerify(RequestMethod method, String tag, int version,
}
if (key.startsWith("@") || key.endsWith("@")) {
- jsonObject.put(key, obj);
+ correctRequest.put(key, obj);
continue;
}
if (obj instanceof JSONObject || obj instanceof JSONArray) {
- RequestMethod _method = null;
+ RequestMethod _method;
if (obj instanceof JSONObject) {
- _method = RequestMethod.valueOf(request.getJSONObject(key).getString(apijson.JSONObject.KEY_METHOD).toUpperCase());
- String combine = request.getJSONObject(key).getString(KEY_COMBINE);
+ JSONObject tblObj = request.getJSONObject(key);
+ String mn = tblObj == null ? null : tblObj.getString(apijson.JSONObject.KEY_METHOD);
+ _method = mn == null ? null : RequestMethod.valueOf(mn);
+ String combine = _method == null ? null : tblObj.getString(KEY_COMBINE);
if (combine != null && RequestMethod.isPublicMethod(_method) == false) {
throw new IllegalArgumentException(key + ":{} 里的 @combine:value 不合法!开放请求 GET、HEAD 才允许传 @combine:value !");
}
@@ -2207,22 +2243,14 @@ protected JSONObject batchVerify(RequestMethod method, String tag, int version,
if (attrMap == null) {
if (method == RequestMethod.CRUD) {
_method = GET;
- if (attrMap == null) {
- Map objAttrMap = new HashMap<>();
- objAttrMap.put(apijson.JSONObject.KEY_METHOD, GET);
- keyObjectAttributesMap.put(key, objAttrMap);
- } else {
- attrMap.put(apijson.JSONObject.KEY_METHOD, GET);
- }
+ Map objAttrMap = new HashMap<>();
+ objAttrMap.put(apijson.JSONObject.KEY_METHOD, GET);
+ keyObjectAttributesMap.put(key, objAttrMap);
} else {
_method = method;
- if (attrMap == null) {
- Map objAttrMap = new HashMap<>();
- objAttrMap.put(apijson.JSONObject.KEY_METHOD, method);
- keyObjectAttributesMap.put(key, objAttrMap);
- } else {
- attrMap.put(apijson.JSONObject.KEY_METHOD, method);
- }
+ Map objAttrMap = new HashMap<>();
+ objAttrMap.put(apijson.JSONObject.KEY_METHOD, method);
+ keyObjectAttributesMap.put(key, objAttrMap);
}
} else {
_method = (RequestMethod) attrMap.get(apijson.JSONObject.KEY_METHOD);
@@ -2236,29 +2264,29 @@ protected JSONObject batchVerify(RequestMethod method, String tag, int version,
// get请求不校验
if (RequestMethod.isPublicMethod(_method)) {
- jsonObject.put(key, obj);
+ correctRequest.put(key, obj);
continue;
}
- if(tag != null && !tag.contains(":")) {
+ if (tag != null && ! tag.contains(":")) {
JSONObject object = getRequestStructure(_method, tag, version);
JSONObject ret = objectVerify(_method, tag, version, name, request, maxUpdateCount, creator, object);
- jsonObject.putAll(ret);
+ correctRequest.putAll(ret);
break;
}
String _tag = buildTag(request, key, method, tag);
JSONObject object = getRequestStructure(_method, _tag, version);
- if(method == RequestMethod.CRUD && StringUtil.isEmpty(tag, true)) {
+ if (method == RequestMethod.CRUD && StringUtil.isEmpty(tag, true)) {
JSONObject requestItem = new JSONObject();
requestItem.put(key, obj);
JSONObject ret = objectVerify(_method, _tag, version, name, requestItem, maxUpdateCount, creator, object);
- jsonObject.put(key, ret.get(key));
+ correctRequest.put(key, ret.get(key));
} else {
return objectVerify(_method, _tag, version, name, request, maxUpdateCount, creator, object);
}
} else {
- jsonObject.put(key, obj);
+ correctRequest.put(key, obj);
}
} catch (Exception e) {
e.printStackTrace();
@@ -2266,12 +2294,12 @@ protected JSONObject batchVerify(RequestMethod method, String tag, int version,
}
}
- // 这里是requestObject ref request 的引用, 删除不需要的临时变量
+ // 这里是 requestObject ref request 的引用, 删除不需要的临时变量
for (String removeKey : removeTmpKeys) {
request.remove(removeKey);
}
- return jsonObject;
+ return correctRequest;
}
public static > E getEnum(final Class enumClass, final String enumName, final E defaultEnum) {
@@ -2284,7 +2312,7 @@ public static > E getEnum(final Class enumClass, final Stri
return defaultEnum;
}
}
-
+
protected void setRequestAttribute(String key, boolean isArray, String attrKey, @NotNull JSONObject request) {
Map attrMap = keyObjectAttributesMap.get(isArray ? key + apijson.JSONObject.KEY_ARRAY : key);
Object attrVal = attrMap == null ? null : attrMap.get(attrKey);
@@ -2308,7 +2336,7 @@ protected String buildTag(JSONObject request, String key, RequestMethod method,
}
return tag;
}
-
+
protected JSONObject objectVerify(RequestMethod method, String tag, int version, String name, @NotNull JSONObject request
, int maxUpdateCount, SQLCreator creator, JSONObject object) throws Exception {
@@ -2317,7 +2345,7 @@ protected JSONObject objectVerify(RequestMethod method, String tag, int version,
// JSONObject clone 浅拷贝没用,Structure.parse 会导致 structure 里面被清空,第二次从缓存里取到的就是 {}
return getVerifier().verifyRequest(method, name, target, request, maxUpdateCount, getGlobalDatabase(), getGlobalSchema(), creator);
}
-
+
/***
* 兼容url crud, 获取真实method
* @param method = crud
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
index 9d6018378..eaf3bbf86 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
@@ -4901,8 +4901,8 @@ public static SQLConfig newSQLConfig(RequestMethod method, St
throw new NullPointerException(TAG + ": newSQLConfig request == null!");
}
- boolean explain = request.getBooleanValue(KEY_EXPLAIN);
- if (explain && Log.DEBUG == false) { // 不在 config.setExplain 抛异常,一方面处理更早性能更好,另一方面为了内部调用可以绕过这个限制
+ Boolean explain = request.getBoolean(KEY_EXPLAIN);
+ if (explain != null && explain && Log.DEBUG == false) { // 不在 config.setExplain 抛异常,一方面处理更早性能更好,另一方面为了内部调用可以绕过这个限制
throw new UnsupportedOperationException("非DEBUG模式, 不允许传 " + KEY_EXPLAIN + " !");
}
@@ -5065,6 +5065,7 @@ else if (userId instanceof Subquery) {}
String order = request.getString(KEY_ORDER);
String raw = request.getString(KEY_RAW);
String json = request.getString(KEY_JSON);
+ String mthd = request.getString(KEY_METHOD);
try {
// 强制作为条件且放在最前面优化性能
@@ -5547,7 +5548,7 @@ else if (newHaving != null) {
// @having, @haivng& >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- config.setExplain(explain);
+ config.setExplain(explain != null && explain);
config.setCache(getCache(cache));
config.setDistinct(distinct);
config.setColumn(column == null ? null : cs); //解决总是 config.column != null,总是不能得到 *
@@ -5587,23 +5588,60 @@ else if (newHaving != null) {
}
// 关键词
- request.put(KEY_DATABASE, database);
- request.put(KEY_ROLE, role);
- request.put(KEY_EXPLAIN, explain);
- request.put(KEY_CACHE, cache);
- request.put(KEY_DATASOURCE, datasource);
- request.put(KEY_SCHEMA, schema);
- request.put(KEY_FROM, from);
- request.put(KEY_COLUMN, column);
- request.put(KEY_NULL, nulls);
- request.put(KEY_CAST, cast);
- request.put(KEY_COMBINE, combine);
- request.put(KEY_GROUP, group);
- request.put(KEY_HAVING, having);
- request.put(KEY_HAVING_AND, havingAnd);
- request.put(KEY_ORDER, order);
- request.put(KEY_RAW, raw);
- request.put(KEY_JSON, json);
+ if (role != null) {
+ request.put(KEY_ROLE, role);
+ }
+ if (explain != null) {
+ request.put(KEY_EXPLAIN, explain);
+ }
+ if (cache != null) {
+ request.put(KEY_CACHE, cache);
+ }
+ if (database != null) {
+ request.put(KEY_DATABASE, database);
+ }
+ if (datasource != null) {
+ request.put(KEY_DATASOURCE, datasource);
+ }
+ if (schema != null) {
+ request.put(KEY_SCHEMA, schema);
+ }
+ if (from != null) {
+ request.put(KEY_FROM, from);
+ }
+ if (column != null) {
+ request.put(KEY_COLUMN, column);
+ }
+ if (nulls != null) {
+ request.put(KEY_NULL, nulls);
+ }
+ if (cast != null) {
+ request.put(KEY_CAST, cast);
+ }
+ if (combine != null) {
+ request.put(KEY_COMBINE, combine);
+ }
+ if (group != null) {
+ request.put(KEY_GROUP, group);
+ }
+ if (having != null) {
+ request.put(KEY_HAVING, having);
+ }
+ if (havingAnd != null) {
+ request.put(KEY_HAVING_AND, havingAnd);
+ }
+ if (order != null) {
+ request.put(KEY_ORDER, order);
+ }
+ if (raw != null) {
+ request.put(KEY_RAW, raw);
+ }
+ if (json != null) {
+ request.put(KEY_JSON, json);
+ }
+ if (mthd != null) {
+ request.put(KEY_METHOD, mthd);
+ }
}
return config;
From 0852e889b3b4a2af9445426d97b4b03f118cd2d6 Mon Sep 17 00:00:00 2001
From: TommyLemon
Date: Sun, 3 Sep 2023 03:53:56 +0800
Subject: [PATCH 051/253] =?UTF-8?q?=E8=A1=A5=E5=85=85=E4=B8=8A=E6=AC=A1?=
=?UTF-8?q?=E5=B0=91=E6=8F=90=E4=BA=A4=E7=9A=84=20import=20=E4=BB=A3?=
=?UTF-8?q?=E7=A0=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
APIJSONORM/src/main/java/apijson/orm/AbstractParser.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
index c731b02c3..5cbfe7c68 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
@@ -5,6 +5,7 @@
package apijson.orm;
+import apijson.orm.exception.ConflictException;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
From 83e878033544a6bb3d3729584de8ee35833607fa Mon Sep 17 00:00:00 2001
From: TommyLemon
Date: Sun, 3 Sep 2023 17:25:21 +0800
Subject: [PATCH 052/253] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E5=BC=95=E7=94=A8?=
=?UTF-8?q?=E8=B5=8B=E5=80=BC=E5=8F=96=E4=B8=8D=E5=88=B0=E6=9C=89=E6=95=88?=
=?UTF-8?q?=E5=80=BC=EF=BC=8C=E7=9B=B4=E6=8E=A5=E5=BF=BD=E7=95=A5=E6=9D=A1?=
=?UTF-8?q?=E4=BB=B6=E4=BB=8D=E7=84=B6=E6=89=A7=E8=A1=8C=E6=9F=A5=E8=AF=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../main/java/apijson/orm/AbstractObjectParser.java | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java
index 301914dc9..6c010cde9 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java
@@ -423,7 +423,15 @@ else if (value instanceof String) { // //key{}@ getRealKey, 引用赋值路径
if (target == null) { // String#equals(null)会出错
Log.d(TAG, "onParse target == null >> return true;");
- return true;
+ // 非查询关键词 @key 不影响查询,直接跳过
+ if (isTable && (key.startsWith("@") == false || JSONRequest.TABLE_KEY_LIST.contains(key))) {
+ Log.e(TAG, "onParse isTable && (key.startsWith(@) == false"
+ + " || JSONRequest.TABLE_KEY_LIST.contains(key)) >> return null;");
+ return false; // 获取不到就不用再做无效的 query 了。不考虑 Table:{Table:{}} 嵌套
+ }
+
+ Log.d(TAG, "onParse isTable(table) == false >> return true;");
+ return true; // 舍去,对Table无影响
}
// if (target instanceof Map) { // target 可能是从 requestObject 里取出的 {}
From 83eeaa28a5ec019fafc9d68d059b424acb2dc761 Mon Sep 17 00:00:00 2001
From: TommyLemon
Date: Sun, 10 Sep 2023 02:30:03 +0800
Subject: [PATCH 053/253] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AF=B9=E5=85=81?=
=?UTF-8?q?=E8=AE=B8=E4=BD=86=E5=AE=B9=E6=98=93=E5=AF=BC=E8=87=B4=E6=BD=9C?=
=?UTF-8?q?=E5=9C=A8=E9=97=AE=E9=A2=98=E7=9A=84=E6=83=85=E5=86=B5=E5=9C=A8?=
=?UTF-8?q?=20DEBUG=20=E4=B8=8B=E8=BF=94=E5=9B=9E=E8=AD=A6=E5=91=8A?=
=?UTF-8?q?=E4=BF=A1=E6=81=AF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../apijson/orm/AbstractObjectParser.java | 27 +++
.../main/java/apijson/orm/AbstractParser.java | 209 ++++++++++++------
.../java/apijson/orm/AbstractSQLConfig.java | 45 +++-
3 files changed, 210 insertions(+), 71 deletions(-)
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java
index 6c010cde9..7bfc9ff6b 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java
@@ -833,12 +833,39 @@ public JSONObject parseResponse(SQLConfig config, boolean isProcedure) throws Ex
if (parser.getSQLExecutor() == null) {
parser.createSQLExecutor();
}
+ if (parser != null && config.getParser() == null) {
+ config.setParser(parser);
+ }
return parser.getSQLExecutor().execute(config, isProcedure);
}
@Override
public SQLConfig newSQLConfig(boolean isProcedure) throws Exception {
+ String raw = Log.DEBUG == false || sqlRequest == null ? null : sqlRequest.getString(apijson.JSONRequest.KEY_RAW);
+ String[] keys = raw == null ? null : StringUtil.split(raw);
+ if (keys != null && keys.length > 0) {
+ boolean allow = AbstractSQLConfig.ALLOW_MISSING_KEY_4_COMBINE;
+
+ for (String key : keys) {
+ if (sqlRequest.get(key) != null) {
+ continue;
+ }
+
+ String msg = "@raw:value 的 value 中 " + key + " 不合法!对应的 "
+ + key + ": value 在当前对象 " + name + " 不存在或 value = null,无法有效转为原始 SQL 片段!";
+
+ if (allow == false) {
+ throw new UnsupportedOperationException(msg);
+ }
+
+ if (parser instanceof AbstractParser) {
+ ((AbstractParser) parser).putWarnIfNeed(JSONRequest.KEY_RAW, msg);
+ }
+ break;
+ }
+ }
+
return newSQLConfig(method, table, alias, sqlRequest, joinList, isProcedure)
.setParser(parser)
.setObjectParser(this);
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
index 5cbfe7c68..4a5ed4bce 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
@@ -121,10 +121,10 @@ public AbstractParser() {
* @param method null ? requestMethod = GET
*/
public AbstractParser(RequestMethod method) {
- super();
- setMethod(method);
- setNeedVerifyRole(AbstractVerifier.ENABLE_VERIFY_ROLE);
- setNeedVerifyContent(AbstractVerifier.ENABLE_VERIFY_CONTENT);
+ super();
+ setMethod(method);
+ setNeedVerifyRole(AbstractVerifier.ENABLE_VERIFY_ROLE);
+ setNeedVerifyContent(AbstractVerifier.ENABLE_VERIFY_CONTENT);
}
/**
* @param method null ? requestMethod = GET
@@ -145,6 +145,57 @@ public AbstractParser setRoot(boolean isRoot) {
return this;
}
+ public static final String KEY_REF = "Reference";
+
+ /**警告信息
+ * Map<"Reference", "引用赋值获取路径 /Comment/userId 对应的值为 null!">
+ */
+ protected Map warnMap = new LinkedHashMap<>();
+ public String getWarn(String type) {
+ return warnMap == null ? null : warnMap.get(type);
+ }
+ public AbstractParser putWarnIfNeed(String type, String warn) {
+ if (Log.DEBUG) {
+ String w = getWarn(type);
+ if (StringUtil.isEmpty(w, true)) {
+ putWarn(type, warn);
+ }
+ }
+ return this;
+ }
+ public AbstractParser putWarn(String type, String warn) {
+ if (warnMap == null) {
+ warnMap = new LinkedHashMap<>();
+ }
+ warnMap.put(type, warn);
+ return this;
+ }
+ /**获取警告信息
+ * @return
+ */
+ public String getWarnString() {
+ Set> set = warnMap == null ? null : warnMap.entrySet();
+ if (set == null || set.isEmpty()) {
+ return null;
+ }
+
+ StringBuilder sb = new StringBuilder();
+ for (Entry e : set) {
+ String k = e == null ? null : e.getKey();
+ String v = k == null ? null : e.getValue();
+ if (StringUtil.isEmpty(v, true)) {
+ continue;
+ }
+
+ if (StringUtil.isNotEmpty(k, true)) {
+ sb.append("[" + k + "]: ");
+ }
+ sb.append(v + "; ");
+ }
+
+ return sb.toString();
+ }
+
@NotNull
protected Visitor visitor;
@@ -334,9 +385,6 @@ public AbstractParser setNeedVerifyContent(boolean needVerifyContent) {
}
-
-
-
protected SQLExecutor sqlExecutor;
protected Verifier verifier;
protected Map queryResultMap;//path-result
@@ -487,7 +535,9 @@ public JSONObject parseResponse(JSONObject request) {
onRollback();
}
- requestObject = error == null ? extendSuccessResult(requestObject, isRoot) : extendErrorResult(requestObject, error, requestMethod, getRequestURL(), isRoot);
+ String warn = Log.DEBUG == false || error != null ? null : getWarnString();
+
+ requestObject = error == null ? extendSuccessResult(requestObject, warn, isRoot) : extendErrorResult(requestObject, error, requestMethod, getRequestURL(), isRoot);
JSONObject res = (globalFormat != null && globalFormat) && JSONResponse.isSuccess(requestObject) ? new JSONResponse(requestObject) : requestObject;
@@ -663,31 +713,49 @@ else if (target.containsKey(key) == false) {
* @return
*/
public static JSONObject newResult(int code, String msg) {
- return newResult(code, msg, false);
+ return newResult(code, msg, null);
}
- /**新建带状态内容的JSONObject
+
+ /**
+ * 添加JSONObject的状态内容,一般用于错误提示结果
+ *
* @param code
* @param msg
+ * @param warn
+ * @return
+ */
+ public static JSONObject newResult(int code, String msg, String warn) {
+ return newResult(code, msg, warn, false);
+ }
+
+ /**
+ * 新建带状态内容的JSONObject
+ *
+ * @param code
+ * @param msg
+ * @param warn
* @param isRoot
* @return
*/
- public static JSONObject newResult(int code, String msg, boolean isRoot) {
- return extendResult(null, code, msg, isRoot);
+ public static JSONObject newResult(int code, String msg, String warn, boolean isRoot) {
+ return extendResult(null, code, msg, warn, isRoot);
}
- /**添加JSONObject的状态内容,一般用于错误提示结果
+ /**
+ * 添加JSONObject的状态内容,一般用于错误提示结果
+ *
* @param object
* @param code
* @param msg
* @return
*/
- public static JSONObject extendResult(JSONObject object, int code, String msg, boolean isRoot) {
+ public static JSONObject extendResult(JSONObject object, int code, String msg, String warn, boolean isRoot) {
int index = Log.DEBUG == false || isRoot == false || msg == null ? -1 : msg.lastIndexOf(Log.KEY_SYSTEM_INFO_DIVIDER);
String debug = Log.DEBUG == false || isRoot == false ? null : (index >= 0 ? msg.substring(index + Log.KEY_SYSTEM_INFO_DIVIDER.length()).trim()
: " \n提 bug 请发请求和响应的【完整截屏】,没图的自行解决!"
- + " \n开发者有限的时间和精力主要放在【维护项目源码和文档】上!"
- + " \n【描述不详细】 或 【文档/常见问题 已有答案】 的问题可能会被忽略!!"
- + " \n【态度 不文明/不友善】的可能会被踢出群,问题也可能不予解答!!!"
+ + " \n开发者有限的时间和精力主要放在【维护项目源码和文档】上!"
+ + " \n【描述不详细】 或 【文档/常见问题 已有答案】 的问题可能会被忽略!!"
+ + " \n【态度 不文明/不友善】的可能会被踢出群,问题也可能不予解答!!!"
+ " \n\n **环境信息** "
+ " \n系统: " + Log.OS_NAME + " " + Log.OS_VERSION
+ " \n数据库: DEFAULT_DATABASE = " + AbstractSQLConfig.DEFAULT_DATABASE
@@ -717,6 +785,9 @@ public static JSONObject extendResult(JSONObject object, int code, String msg, b
object.put(JSONResponse.KEY_MSG, msg);
if (debug != null) {
+ if (StringUtil.isNotEmpty(warn, true)) {
+ debug += "\n 【警告】:" + warn;
+ }
object.put("debug:info|help", debug);
}
@@ -724,33 +795,51 @@ public static JSONObject extendResult(JSONObject object, int code, String msg, b
}
- /**添加请求成功的状态内容
+ /**
+ * 添加请求成功的状态内容
+ *
* @param object
* @return
*/
public static JSONObject extendSuccessResult(JSONObject object) {
return extendSuccessResult(object, false);
}
+
+ public static JSONObject extendSuccessResult(JSONObject object, boolean isRoot) {
+ return extendSuccessResult(object, null, isRoot);
+ }
+
/**添加请求成功的状态内容
* @param object
* @param isRoot
* @return
*/
- public static JSONObject extendSuccessResult(JSONObject object, boolean isRoot) {
- return extendResult(object, JSONResponse.CODE_SUCCESS, JSONResponse.MSG_SUCCEED, isRoot);
+ public static JSONObject extendSuccessResult(JSONObject object, String warn, boolean isRoot) {
+ return extendResult(object, JSONResponse.CODE_SUCCESS, JSONResponse.MSG_SUCCEED, warn, isRoot);
}
+
/**获取请求成功的状态内容
* @return
*/
public static JSONObject newSuccessResult() {
- return newSuccessResult(false);
+ return newSuccessResult(null);
}
+
/**获取请求成功的状态内容
+ * @param warn
+ * @return
+ */
+ public static JSONObject newSuccessResult(String warn) {
+ return newSuccessResult(warn, false);
+ }
+
+ /**获取请求成功的状态内容
+ * @param warn
* @param isRoot
* @return
*/
- public static JSONObject newSuccessResult(boolean isRoot) {
- return newResult(JSONResponse.CODE_SUCCESS, JSONResponse.MSG_SUCCEED, isRoot);
+ public static JSONObject newSuccessResult(String warn, boolean isRoot) {
+ return newResult(JSONResponse.CODE_SUCCESS, JSONResponse.MSG_SUCCEED, warn, isRoot);
}
/**添加请求成功的状态内容
@@ -848,7 +937,7 @@ public static JSONObject extendErrorResult(JSONObject object, Throwable e, Reque
}
int code = CommonException.getCode(e);
- return extendResult(object, code, msg, isRoot);
+ return extendResult(object, code, msg, null, isRoot);
}
/**新建错误状态内容
@@ -872,16 +961,13 @@ public static JSONObject newErrorResult(Exception e, boolean isRoot) {
String msg = CommonException.getMsg(e);
Integer code = CommonException.getCode(e);
- return newResult(code, msg, isRoot);
+ return newResult(code, msg, null, isRoot);
}
- return newResult(JSONResponse.CODE_SERVER_ERROR, JSONResponse.MSG_SERVER_ERROR, isRoot);
+ return newResult(JSONResponse.CODE_SERVER_ERROR, JSONResponse.MSG_SERVER_ERROR, null, isRoot);
}
-
-
- //TODO 启动时一次性加载Request所有内容,作为初始化。
/**获取正确的请求,非GET请求必须是服务器指定的
* @return
* @throws Exception
@@ -902,7 +988,6 @@ public JSONObject parseCorrectRequest() throws Exception {
*/
@Override
public JSONObject getStructure(@NotNull String table, String method, String tag, int version) throws Exception {
- // TODO 目前只使用 Request 而不使用 Response,所以这里写死用 REQUEST_MAP,以后可能 Response 表也会与 Request 表合并,用字段来区分
String cacheKey = AbstractVerifier.getCacheKeyForRequest(method, tag);
SortedMap versionedMap = AbstractVerifier.REQUEST_MAP.get(cacheKey);
@@ -1419,17 +1504,17 @@ else if (join != null){
index = path.lastIndexOf("/");
String tableKey = index < 0 ? path : path.substring(0, index); // User:owner
- int index2 = tableKey.lastIndexOf("/");
- String arrKey = index2 < 0 ? null : tableKey.substring(0, index2);
- if (arrKey != null && JSONRequest.isArrayKey(arrKey) == false) {
+ int index2 = tableKey.lastIndexOf("/");
+ String arrKey = index2 < 0 ? null : tableKey.substring(0, index2);
+ if (arrKey != null && JSONRequest.isArrayKey(arrKey) == false) {
throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":'" + e.getKey() + "' 对应的 " + arrKey + " 不是合法的数组 key[] !" +
- "@ APP JOIN 最多允许跨 1 层,只能是子数组,且数组对象中不能有 join: value 键值对!");
- }
+ "@ APP JOIN 最多允许跨 1 层,只能是子数组,且数组对象中不能有 join: value 键值对!");
+ }
- tableKey = index2 < 0 ? tableKey : tableKey.substring(index2+1);
+ tableKey = index2 < 0 ? tableKey : tableKey.substring(index2+1);
- apijson.orm.Entry entry = Pair.parseEntry(tableKey, true);
- String table = entry.getKey(); // User
+ apijson.orm.Entry entry = Pair.parseEntry(tableKey, true);
+ String table = entry.getKey(); // User
if (StringUtil.isName(table) == false) {
throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":value 中 value 的 Table 值 " + table + " 不合法!"
+ "必须为 &/Table0, te = tk == null || p.substring(ind2 + 1).indexOf("/") >= 0 ? null : Pair.parseEntry(tk, true);
if (te != null && JSONRequest.isTableKey(te.getKey()) && request.get(tk) instanceof JSONObject) {
- if (isAppJoin) {
- if (refObj.size() >= 1) {
- throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":" + e.getKey() + " 中 " + k + " 不合法!"
- + "@ APP JOIN 必须有且只有一个引用赋值键值对!");
- }
+ if (isAppJoin) {
+ if (refObj.size() >= 1) {
+ throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":" + e.getKey() + " 中 " + k + " 不合法!"
+ + "@ APP JOIN 必须有且只有一个引用赋值键值对!");
+ }
- if (StringUtil.isName(k.substring(0, k.length() - 1)) == false) {
- throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":'" + e.getKey() + "' 中 " + k + " 不合法 !" +
- "@ APP JOIN 只允许 key@:/Table/refKey 这种 = 等价连接!");
+ if (StringUtil.isName(k.substring(0, k.length() - 1)) == false) {
+ throw new IllegalArgumentException(JSONRequest.KEY_JOIN + ":'" + e.getKey() + "' 中 " + k + " 不合法 !" +
+ "@ APP JOIN 只允许 key@:/Table/refKey 这种 = 等价连接!");
+ }
}
- }
- refObj.put(k, v);
- continue;
+ refObj.put(k, v);
+ continue;
}
}
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
index eaf3bbf86..d162f6a79 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java
@@ -118,6 +118,7 @@ public abstract class AbstractSQLConfig implements SQLConfig implements SQLConfig parser;
@Override
public Parser getParser() {
+ if (parser == null && objectParser != null) {
+ parser = objectParser.getParser();
+ }
return parser;
}
@Override
- public AbstractSQLConfig setParser(Parser parser) {
+ public AbstractSQLConfig setParser(Parser parser) {
this.parser = parser;
return this;
}
+ public AbstractSQLConfig putWarnIfNeed(String type, String warn) {
+ if (Log.DEBUG && parser instanceof AbstractParser) {
+ ((AbstractParser) parser).putWarnIfNeed(type, warn);
+ }
+ return this;
+ }
+ public AbstractSQLConfig putWarn(String type, String warn) {
+ if (Log.DEBUG && parser instanceof AbstractParser) {
+ ((AbstractParser) parser).putWarn(type, warn);
+ }
+ return this;
+ }
private ObjectParser objectParser;
@Override
@@ -799,7 +815,7 @@ public ObjectParser getObjectParser() {
return objectParser;
}
@Override
- public AbstractSQLConfig setObjectParser(ObjectParser objectParser) {
+ public AbstractSQLConfig setObjectParser(ObjectParser objectParser) {
this.objectParser = objectParser;
return this;
}
@@ -1665,7 +1681,7 @@ public SQLConfig setRaw(List raw) {
*/
@Override
public String getRawSQL(String key, Object value) throws Exception {
- return getRawSQL(key, value, false);
+ return getRawSQL(key, value, ! ALLOW_MISSING_KEY_4_COMBINE);
}
/**获取原始 SQL 片段
* @param key
@@ -1694,6 +1710,9 @@ public String getRawSQL(String key, Object value, boolean throwWhenMissing) thro
throw new UnsupportedOperationException("@raw:value 的 value 中 " + key + " 不合法!"
+ "对应的 " + key + ":value 中 value 值 " + value + " 未在后端 RAW_MAP 中配置 !");
}
+
+ putWarnIfNeed(JSONRequest.KEY_RAW, "@raw:value 的 value 中 "
+ + key + " 不合法!对应的 " + key + ":value 中 value 值 " + value + " 未在后端 RAW_MAP 中配置 !");
}
else if (rawSQL.isEmpty()) {
return (String) value;
@@ -3397,7 +3416,7 @@ else if (key.endsWith("<")) {
String column = getRealKey(method, key, false, true, verifyName);
// 原始 SQL 片段
- String rawSQL = getRawSQL(key, value, keyType != 4 || value instanceof String == false);
+ String rawSQL = getRawSQL(key, value);
switch (keyType) {
case 1:
@@ -5287,7 +5306,7 @@ else if (userId instanceof Subquery) {}
if (StringUtil.isNotEmpty(combineExpr, true)) {
List banKeyList = Arrays.asList(idKey, idInKey, userIdKey, userIdInKey);
for (String key : banKeyList) {
- if(keyInCombineExpr(combineExpr, key)) {
+ if (isKeyInCombineExpr(combineExpr, key)) {
throw new UnsupportedOperationException(table + ":{} 里的 @combine:value 中的 value 里 " + key + " 不合法!"
+ "不允许传 [" + idKey + ", " + idInKey + ", " + userIdKey + ", " + userIdInKey + "] 其中任何一个!");
}
@@ -5339,6 +5358,10 @@ else if (w.startsWith("!")) {
if (request.containsKey(w) == false) { // 和 request.get(w) == null 没区别,前面 Parser 已经过滤了 null
// throw new IllegalArgumentException(table + ":{} 里的 @combine:value 中的value里 " + ws[i] + " 对应的 " + w + " 不在它里面!");
callback.onMissingKey4Combine(table, request, combine, ws[i], w);
+ if (config instanceof AbstractSQLConfig) {
+ ((AbstractSQLConfig) config).putWarnIfNeed(KEY_COMBINE, table + ":{} 里的 @combine:value 中的 value 里 "
+ + ws[i] + " 对应的条件 " + w + ":value 中 value 必须存在且不能为 null!");
+ }
}
}
}
@@ -5361,7 +5384,7 @@ else if (w.startsWith("!")) {
// 兼容 PUT @combine
// 解决AccessVerifier新增userId没有作为条件,而是作为内容,导致PUT,DELETE出错
if ((isWhere || (StringUtil.isName(key.replaceFirst("[+-]$", "")) == false))
- || (isWhere == false && StringUtil.isNotEmpty(combineExpr, true) && keyInCombineExpr(combineExpr, key))) {
+ || (isWhere == false && StringUtil.isNotEmpty(combineExpr, true) && isKeyInCombineExpr(combineExpr, key))) {
tableWhere.put(key, value);
if (whereList.contains(key) == false) {
andList.add(key);
@@ -5918,7 +5941,7 @@ public static interface Callback extends IdCallback {
* @param key
* @param request
*/
- public void onMissingKey4Combine(String name, JSONObject request, String combine, String item, String key) throws Exception;
+ void onMissingKey4Combine(String name, JSONObject request, String combine, String item, String key) throws Exception;
}
public static Long LAST_ID;
@@ -5952,13 +5975,16 @@ public String getUserIdKey(String database, String schema, String datasource, St
@Override
public void onMissingKey4Combine(String name, JSONObject request, String combine, String item, String key) throws Exception {
+ if (ALLOW_MISSING_KEY_4_COMBINE) {
+ return;
+ }
throw new IllegalArgumentException(name + ":{} 里的 @combine:value 中的value里 "
- + item + " 对应的条件 " + key + ":value 中 value 不能为 null!");
+ + item + " 对应的条件 " + key + ":value 中 value 必须存在且不能为 null!");
}
}
- private static boolean keyInCombineExpr(String combineExpr, String key) {
+ private static boolean isKeyInCombineExpr(String combineExpr, String key) {
while (combineExpr.isEmpty() == false) {
int index = combineExpr.indexOf(key);
if (index < 0) {
@@ -5976,6 +6002,7 @@ private static boolean keyInCombineExpr(String combineExpr, String key) {
}
combineExpr = combineExpr.substring(newIndex);
}
+
return false;
}
From 74f4e73e92cf58064c882fd4505b13f74d5e974a Mon Sep 17 00:00:00 2001
From: TommyLemon
Date: Sun, 10 Sep 2023 02:31:29 +0800
Subject: [PATCH 054/253] =?UTF-8?q?=E5=BD=93=E6=89=BE=E4=B8=8D=E5=88=B0?=
=?UTF-8?q?=E5=BC=95=E7=94=A8=E8=B5=8B=E5=80=BC=E8=B7=AF=E5=BE=84=E5=AF=B9?=
=?UTF-8?q?=E5=BA=94=E7=9A=84=E9=9D=9E=20null=20=E5=80=BC=E6=97=B6?=
=?UTF-8?q?=E5=9C=A8=20DEBUG=20=E4=B8=8B=E8=BF=94=E5=9B=9E=E8=AD=A6?=
=?UTF-8?q?=E5=91=8A=E4=BF=A1=E6=81=AF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/main/java/apijson/orm/AbstractObjectParser.java | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java
index 7bfc9ff6b..bd4a68467 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java
@@ -423,6 +423,11 @@ else if (value instanceof String) { // //key{}@ getRealKey, 引用赋值路径
if (target == null) { // String#equals(null)会出错
Log.d(TAG, "onParse target == null >> return true;");
+
+ if (Log.DEBUG) {
+ parser.putWarnIfNeed(AbstractParser.KEY_REF, path + "/" + key + ": " + targetPath + " 引用赋值获取路径对应的值为 null!请检查路径是否错误!");
+ }
+
// 非查询关键词 @key 不影响查询,直接跳过
if (isTable && (key.startsWith("@") == false || JSONRequest.TABLE_KEY_LIST.contains(key))) {
Log.e(TAG, "onParse isTable && (key.startsWith(@) == false"
From 72524b29569b162a9d3fe9ba9e9b02abaf073254 Mon Sep 17 00:00:00 2001
From: TommyLemon
Date: Sun, 10 Sep 2023 03:13:03 +0800
Subject: [PATCH 055/253] =?UTF-8?q?=E4=B8=BB=E9=94=AE=E7=B1=BB=E5=9E=8B?=
=?UTF-8?q?=E7=9B=B8=E5=85=B3=E4=BB=A3=E7=A0=81=E5=85=A8=E9=9D=A2=E4=BD=BF?=
=?UTF-8?q?=E7=94=A8=E6=B3=9B=E5=9E=8B=EF=BC=9B=E5=88=A0=E9=99=A4=20@Depre?=
=?UTF-8?q?cated=20=E4=BB=A3=E7=A0=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/main/java/apijson/JSONObject.java | 12 ----
.../apijson/orm/AbstractFunctionParser.java | 42 ++++++-------
.../apijson/orm/AbstractObjectParser.java | 25 +++++---
.../main/java/apijson/orm/AbstractParser.java | 30 ++++-----
.../java/apijson/orm/AbstractSQLConfig.java | 23 +++----
.../java/apijson/orm/AbstractSQLExecutor.java | 61 +++++++++----------
.../main/java/apijson/orm/FunctionParser.java | 22 +++----
.../main/java/apijson/orm/ObjectParser.java | 32 +++++-----
.../src/main/java/apijson/orm/Parser.java | 10 +--
.../main/java/apijson/orm/SQLExecutor.java | 28 ++++-----
10 files changed, 136 insertions(+), 149 deletions(-)
diff --git a/APIJSONORM/src/main/java/apijson/JSONObject.java b/APIJSONORM/src/main/java/apijson/JSONObject.java
index 571c0aedf..5d5077405 100755
--- a/APIJSONORM/src/main/java/apijson/JSONObject.java
+++ b/APIJSONORM/src/main/java/apijson/JSONObject.java
@@ -421,18 +421,6 @@ public JSONObject setJson(String keys) {
return puts(KEY_JSON, keys);
}
- /**用 setJson 替代。
- * set keys to cast to json
- * @param keys "key0,key1,key2..."
- * @return
- * @see #{@link #setJson(String)}
- */
- @Deprecated
- public JSONObject setJSON(String keys) {
- return puts(KEY_JSON, keys);
- }
-
-
//JSONObject内关键词 key >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
index 75f0d261d..25739bf17 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractFunctionParser.java
@@ -25,7 +25,7 @@
/**可远程调用的函数类
* @author Lemon
*/
-public class AbstractFunctionParser implements FunctionParser {
+public class AbstractFunctionParser implements FunctionParser {
private static final String TAG = "AbstractFunctionParser";
/**是否解析参数 key 的对应的值,不用手动编码 curObj.getString(key)
@@ -65,15 +65,15 @@ public AbstractFunctionParser(RequestMethod method, String tag, int version, @No
setRequest(request);
}
- private Parser> parser;
+ private Parser parser;
@Override
- public Parser> getParser() {
+ public Parser getParser() {
return parser;
}
@Override
- public AbstractFunctionParser setParser(Parser> parser) {
+ public AbstractFunctionParser setParser(Parser parser) {
this.parser = parser;
return this;
}
@@ -84,7 +84,7 @@ public RequestMethod getMethod() {
}
@Override
- public AbstractFunctionParser setMethod(RequestMethod method) {
+ public AbstractFunctionParser setMethod(RequestMethod method) {
this.method = method;
return this;
}
@@ -95,7 +95,7 @@ public String getTag() {
}
@Override
- public AbstractFunctionParser setTag(String tag) {
+ public AbstractFunctionParser setTag(String tag) {
this.tag = tag;
return this;
}
@@ -106,7 +106,7 @@ public int getVersion() {
}
@Override
- public AbstractFunctionParser setVersion(int version) {
+ public AbstractFunctionParser setVersion(int version) {
this.version = version;
return this;
}
@@ -119,7 +119,7 @@ public String getKey() {
}
@Override
- public AbstractFunctionParser setKey(String key) {
+ public AbstractFunctionParser setKey(String key) {
this.key = key;
return this;
}
@@ -132,7 +132,7 @@ public String getParentPath() {
}
@Override
- public AbstractFunctionParser setParentPath(String parentPath) {
+ public AbstractFunctionParser setParentPath(String parentPath) {
this.parentPath = parentPath;
return this;
}
@@ -145,7 +145,7 @@ public String getCurrentName() {
}
@Override
- public AbstractFunctionParser setCurrentName(String currentName) {
+ public AbstractFunctionParser setCurrentName(String currentName) {
this.currentName = currentName;
return this;
}
@@ -157,7 +157,7 @@ public JSONObject getRequest() {
}
@Override
- public AbstractFunctionParser setRequest(@NotNull JSONObject request) {
+ public AbstractFunctionParser setRequest(@NotNull JSONObject request) {
this.request = request;
return this;
}
@@ -171,7 +171,7 @@ public JSONObject getCurrentObject() {
}
@Override
- public AbstractFunctionParser setCurrentObject(@NotNull JSONObject currentObject) {
+ public AbstractFunctionParser setCurrentObject(@NotNull JSONObject currentObject) {
this.currentObject = currentObject;
return this;
}
@@ -294,7 +294,7 @@ public T getArgVal(String path, Class clazz) {
/**根据路径取值
* @param path
* @param clazz
- * @param tryAll false-仅当前对象,true-本次请求的全局对象以及 Parser 缓存值
+ * @param tryAll false-仅当前对象,true-本次请求的全局对象以及 Parser 缓存值
* @return
* @param
*/
@@ -342,14 +342,14 @@ public Object invoke(@NotNull String function, @NotNull JSONObject currentObject
public Object invoke(@NotNull String function, @NotNull JSONObject currentObject, boolean containRaw) throws Exception {
return invoke(this, function, currentObject, containRaw);
}
-
+
/**反射调用
* @param parser
* @param function 例如get(Map:map,key),参数只允许引用,不能直接传值
* @param currentObject
* @return {@link #invoke(AbstractFunctionParser, String, Class[], Object[])}
*/
- public static Object invoke(@NotNull AbstractFunctionParser parser, @NotNull String function, @NotNull JSONObject currentObject, boolean containRaw) throws Exception {
+ public static Object invoke(@NotNull AbstractFunctionParser parser, @NotNull String function, @NotNull JSONObject currentObject, boolean containRaw) throws Exception {
if (ENABLE_REMOTE_FUNCTION == false) {
throw new UnsupportedOperationException("AbstractFunctionParser.ENABLE_REMOTE_FUNCTION" +
" == false 时不支持远程函数!如需支持则设置 AbstractFunctionParser.ENABLE_REMOTE_FUNCTION = true !");
@@ -369,9 +369,9 @@ public static Object invoke(@NotNull AbstractFunctionParser parser, @NotNull Str
throw new UnsupportedOperationException("language = " + language + " 不合法!AbstractFunctionParser.ENABLE_SCRIPT_FUNCTION" +
" == false 时不支持远程函数中的脚本形式!如需支持则设置 AbstractFunctionParser.ENABLE_SCRIPT_FUNCTION = true !");
}
-
+
if (lang != null && SCRIPT_EXECUTOR_MAP.get(lang) == null) {
- throw new ClassNotFoundException("找不到脚本语言 " + lang + " 对应的执行引擎!请先依赖相关库并在后端 APIJSONFunctionParser 中注册!");
+ throw new ClassNotFoundException("找不到脚本语言 " + lang + " 对应的执行引擎!请先依赖相关库并在后端 APIJSONFunctionParser 中注册!");
}
int version = row.getIntValue("version");
@@ -413,7 +413,7 @@ public static Object invoke(@NotNull AbstractFunctionParser parser, @NotNull Str
}
}
-
+
/**反射调用
* @param parser
* @param methodName
@@ -422,7 +422,7 @@ public static Object invoke(@NotNull AbstractFunctionParser parser, @NotNull Str
* @return {@link #invoke(AbstractFunctionParser, String, Class[], Object[], String, JSONObject, ScriptExecutor)}
* @throws Exception
*/
- public static Object invoke(@NotNull AbstractFunctionParser parser, @NotNull String methodName
+ public static Object invoke(@NotNull AbstractFunctionParser parser, @NotNull String methodName
, @NotNull Class>[] parameterTypes, @NotNull Object[] args) throws Exception {
return invoke(parser, methodName, parameterTypes, args, null, null, null);
}
@@ -437,7 +437,7 @@ public static Object invoke(@NotNull AbstractFunctionParser parser, @NotNull Str
* @return
* @throws Exception
*/
- public static Object invoke(@NotNull AbstractFunctionParser parser, @NotNull String methodName
+ public static Object invoke(@NotNull AbstractFunctionParser parser, @NotNull String methodName
, @NotNull Class>[] parameterTypes, @NotNull Object[] args, String returnType
, JSONObject currentObject, ScriptExecutor scriptExecutor) throws Exception {
if (scriptExecutor != null) {
@@ -474,7 +474,7 @@ public static Object invoke(@NotNull AbstractFunctionParser parser, @NotNull Str
* @return
* @throws Exception
*/
- public static Object invokeScript(@NotNull AbstractFunctionParser parser, @NotNull String methodName
+ public static Object invokeScript(@NotNull AbstractFunctionParser parser, @NotNull String methodName
, @NotNull Class>[] parameterTypes, @NotNull Object[] args, String returnType, JSONObject currentObject, ScriptExecutor scriptExecutor) throws Exception {
Object result = scriptExecutor.execute(parser, currentObject, methodName, args);
if (Log.DEBUG && result != null) {
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java
index bd4a68467..e64420138 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java
@@ -35,20 +35,24 @@
/**简化Parser,getObject和getArray(getArrayConfig)都能用
* @author Lemon
*/
-public abstract class AbstractObjectParser implements ObjectParser {
+public abstract class AbstractObjectParser implements ObjectParser {
private static final String TAG = "AbstractObjectParser";
@NotNull
- protected AbstractParser> parser;
- public AbstractObjectParser setParser(AbstractParser> parser) {
- this.parser = parser;
+ protected AbstractParser parser;
+ @Override
+ public AbstractParser getParser() {
+ return parser;
+ }
+ @Override
+ public AbstractObjectParser setParser(Parser parser) {
+ this.parser = (AbstractParser) parser;
return this;
}
-
protected JSONObject request;//不用final是为了recycle
protected String parentPath;//不用final是为了recycle
- protected SQLConfig arrayConfig;//不用final是为了recycle
+ protected SQLConfig arrayConfig;//不用final是为了recycle
protected boolean isSubquery;
protected final int type;
@@ -435,6 +439,7 @@ else if (value instanceof String) { // //key{}@ getRealKey, 引用赋值路径
return false; // 获取不到就不用再做无效的 query 了。不考虑 Table:{Table:{}} 嵌套
}
+
Log.d(TAG, "onParse isTable(table) == false >> return true;");
return true; // 舍去,对Table无影响
}
@@ -828,13 +833,13 @@ public void onTableArrayParse(String key, JSONArray valueArray) throws Exception
@Override
public JSONObject parseResponse(RequestMethod method, String table, String alias
, JSONObject request, List joinList, boolean isProcedure) throws Exception {
- SQLConfig config = newSQLConfig(method, table, alias, request, joinList, isProcedure)
+ SQLConfig config = newSQLConfig(method, table, alias, request, joinList, isProcedure)
.setParser(parser)
.setObjectParser(this);
return parseResponse(config, isProcedure);
}
@Override
- public JSONObject parseResponse(SQLConfig config, boolean isProcedure) throws Exception {
+ public JSONObject parseResponse(SQLConfig config, boolean isProcedure) throws Exception {
if (parser.getSQLExecutor() == null) {
parser.createSQLExecutor();
}
@@ -1217,13 +1222,13 @@ public String getAlias() {
return alias;
}
@Override
- public SQLConfig getArrayConfig() {
+ public SQLConfig getArrayConfig() {
return arrayConfig;
}
@Override
- public SQLConfig getSQLConfig() {
+ public SQLConfig getSQLConfig() {
return sqlConfig;
}
diff --git a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
index 4a5ed4bce..c552888b2 100755
--- a/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
+++ b/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java
@@ -39,7 +39,7 @@
import static apijson.RequestMethod.CRUD;
import static apijson.RequestMethod.GET;
-/**parser for parsing request to JSONObject
+/**Parser for parsing request to JSONObject
* @author Lemon
*/
public abstract class AbstractParser implements Parser, ParserCreator, VerifierCreator, SQLCreator {
@@ -595,7 +595,7 @@ public void onVerifyContent() throws Exception {
* @throws Exception
*/
@Override
- public void onVerifyRole(@NotNull SQLConfig config) throws Exception {
+ public void onVerifyRole(@NotNull SQLConfig config) throws Exception {
if (Log.DEBUG) {
Log.i(TAG, "onVerifyRole config = " + JSON.toJSONString(config));
}
@@ -1036,7 +1036,7 @@ public JSONObject getStructure(@NotNull String table, String method, String tag,
}
// 获取指定的JSON结构 <<<<<<<<<<<<<<
- SQLConfig config = createSQLConfig().setMethod(GET).setTable(table);
+ SQLConfig config = createSQLConfig().setMethod(GET).setTable(table);
config.setPrepared(false);
config.setColumn(Arrays.asList("structure"));
@@ -1066,7 +1066,7 @@ public JSONObject getStructure(@NotNull String table, String method, String tag,
protected Map arrayObjectParserCacheMap = new HashMap<>();
- // protected SQLConfig itemConfig;
+ // protected SQLConfig itemConfig;
/**获取单个对象,该对象处于parentObject内
* @param request parentObject 的 value
* @param parentPath parentObject 的路径
@@ -1078,7 +1078,7 @@ public JSONObject getStructure(@NotNull String table, String method, String tag,
*/
@Override
public JSONObject onObjectParse(final JSONObject request
- , String parentPath, String name, final SQLConfig arrayConfig, boolean isSubquery) throws Exception {
+ , String parentPath, String name, final SQLConfig