Skip to content

Commit 29d8d1e

Browse files
committed
JOIN ON 及普通条件新增支持在 key$:value 的 key 中定制占位符 %, _ 与 value 的拼接方式
1 parent 895917b commit 29d8d1e

File tree

2 files changed

+99
-8
lines changed

2 files changed

+99
-8
lines changed

APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3891,9 +3891,55 @@ protected String concatJoinOn(@NotNull String sql, @NotNull String quote, @NotNu
38913891
sql += (first ? ON : AND) + quote + jt + quote + "." + quote + on.getKey() + quote + " " + rt + " "
38923892
+ quote + on.getTargetTable() + quote + "." + quote + on.getTargetKey() + quote;
38933893
}
3894-
else if ("$".equals(rt)) {
3895-
sql += (first ? ON : AND) + quote + jt + quote + "." + quote + on.getKey() + quote + (isNot ? NOT : "")
3896-
+ " LIKE concat('%', " + quote + on.getTargetTable() + quote + "." + quote + on.getTargetKey() + quote + ", '%')";
3894+
else if (rt.endsWith("$")) {
3895+
String t = rt.substring(0, rt.length() - 1);
3896+
char r = t.isEmpty() ? 0 : t.charAt(t.length() - 1);
3897+
3898+
char l;
3899+
if (r == '%' || r == '_' || r == '?') {
3900+
t = t.substring(0, t.length() - 1);
3901+
3902+
if (t.isEmpty()) {
3903+
if (r == '?') {
3904+
throw new IllegalArgumentException(on.getOriginKey() + ":value 中字符 " + on.getOriginKey() + " 不合法!key$:value 中不允许只有单独的 '?',必须和 '%', '_' 之一配合使用 !");
3905+
}
3906+
3907+
l = r;
3908+
}
3909+
else {
3910+
l = t.charAt(t.length() - 1);
3911+
if (l == '%' || l == '_' || l == '?') {
3912+
if (l == r) {
3913+
throw new IllegalArgumentException(on.getOriginKey() + ":value 中字符 " + t + " 不合法!key$:value 中不允许 key 中有连续相同的占位符!");
3914+
}
3915+
3916+
t = t.substring(0, t.length() - 1);
3917+
}
3918+
else if (l > 0 && StringUtil.isName(String.valueOf(l))) {
3919+
l = r;
3920+
}
3921+
}
3922+
3923+
if (l == '?') {
3924+
l = 0;
3925+
}
3926+
if (r == '?') {
3927+
r = 0;
3928+
}
3929+
}
3930+
else {
3931+
l = r = 0;
3932+
}
3933+
3934+
if (l <= 0 && r <= 0) {
3935+
sql += (first ? ON : AND) + quote + jt + quote + "." + quote + on.getKey() + quote + (isNot ? NOT : "")
3936+
+ " LIKE " + quote + on.getTargetTable() + quote + "." + quote + on.getTargetKey() + quote;
3937+
}
3938+
else {
3939+
sql += (first ? ON : AND) + quote + jt + quote + "." + quote + on.getKey() + quote + (isNot ? NOT : "")
3940+
+ (l <= 0 ? " LIKE concat(" : " LIKE concat('" + l + "', ") + quote + on.getTargetTable() + quote
3941+
+ "." + quote + on.getTargetKey() + quote + (r <= 0 ? ")" : ", '" + r + "')");
3942+
}
38973943
}
38983944
else if (rt.endsWith("~")) {
38993945
boolean ignoreCase = "*~".equals(rt);
@@ -3992,10 +4038,10 @@ else if (isClickHouse()) {
39924038
}
39934039

39944040
protected void onJoinNotRelation(String sql, String quote, Join j, String jt, List<On> onList, On on) {
3995-
throw new UnsupportedOperationException("JOIN 已禁用 '!' 非逻辑连接符 !性能很差、需求极少,如要取消禁用可在后端重写相关方法!");
4041+
// throw new UnsupportedOperationException("JOIN 已禁用 '!' 非逻辑连接符 !性能很差、需求极少,如要取消禁用可在后端重写相关方法!");
39964042
}
39974043
protected void onJoinComplextRelation(String sql, String quote, Join j, String jt, List<On> onList, On on) {
3998-
throw new UnsupportedOperationException("JOIN 已禁用 $, ~, {}, <>, >, <, >=, <= 等复杂关联 !性能很差、需求极少,默认只允许等价关联,如要取消禁用可在后端重写相关方法!");
4044+
// throw new UnsupportedOperationException("JOIN 已禁用 $, ~, {}, <>, >, <, >=, <= 等复杂关联 !性能很差、需求极少,默认只允许等价关联,如要取消禁用可在后端重写相关方法!");
39994045
}
40004046
protected void onGetCrossJoinString(Join j) throws UnsupportedOperationException {
40014047
throw new UnsupportedOperationException("已禁用 * CROSS JOIN !性能很差、需求极少,如要取消禁用可在后端重写相关方法!");
@@ -4599,7 +4645,27 @@ public static String getRealKey(RequestMethod method, String originKey
45994645

46004646
String key = new String(originKey);
46014647
if (key.endsWith("$")) {//搜索 LIKE,查询时处理
4602-
key = key.substring(0, key.length() - 1);
4648+
String k = key.substring(0, key.length() - 1);
4649+
// key%$:"a" -> key LIKE '%a%'; key?%$:"a" -> key LIKE 'a%'; key_?$:"a" -> key LIKE '_a'; key_%$:"a" -> key LIKE '_a%'
4650+
char c = k.isEmpty() ? 0 : k.charAt(k.length() - 1);
4651+
4652+
if (c == '%' || c == '_' || c == '?') {
4653+
k = k.substring(0, k.length() - 1);
4654+
4655+
char c2 = k.isEmpty() ? 0 : k.charAt(k.length() - 1);
4656+
if (c2 == '%' || c2 == '_' || c2 == '?') {
4657+
if (c2 == c) {
4658+
throw new IllegalArgumentException(originKey + ":value 中字符 " + k + " 不合法!key$:value 中不允许 key 中有连续相同的占位符!");
4659+
}
4660+
4661+
k = k.substring(0, k.length() - 1);
4662+
}
4663+
else if (c == '?') {
4664+
throw new IllegalArgumentException(originKey + ":value 中字符 " + originKey + " 不合法!key$:value 中不允许只有单独的 '?',必须和 '%', '_' 之一配合使用 !");
4665+
}
4666+
}
4667+
4668+
key = k;
46034669
}
46044670
else if (key.endsWith("~")) {//匹配正则表达式 REGEXP,查询时处理
46054671
key = key.substring(0, key.length() - 1);
@@ -4648,6 +4714,8 @@ else if (key.endsWith("-")) {//缩减,PUT查询时处理
46484714
}
46494715
}
46504716

4717+
//TODO if (key.endsWith("-")) { // 表示 key 和 value 顺序反过来: value LIKE key
4718+
46514719
String last = null;//不用Logic优化代码,否则 key 可能变为 key| 导致 key=value 变成 key|=value 而出错
46524720
if (RequestMethod.isQueryMethod(method)) {//逻辑运算符仅供GET,HEAD方法使用
46534721
last = key.isEmpty() ? "" : key.substring(key.length() - 1);

APIJSONORM/src/main/java/apijson/orm/Join.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,9 +242,30 @@ else if (originKey.endsWith("<>")) {
242242
setRelateType("<>");
243243
k = originKey.substring(0, originKey.length() - 2);
244244
}
245-
else if (originKey.endsWith("$")) {
246-
setRelateType("$");
245+
else if (originKey.endsWith("$")) { // key%$:"a" -> key LIKE '%a%'; key?%$:"a" -> key LIKE 'a%'; key_?$:"a" -> key LIKE '_a'; key_%$:"a" -> key LIKE '_a%'
247246
k = originKey.substring(0, originKey.length() - 1);
247+
char c = k.isEmpty() ? 0 : k.charAt(k.length() - 1);
248+
249+
String t = "$";
250+
if (c == '%' || c == '_' || c == '?') {
251+
t = c + t;
252+
k = k.substring(0, k.length() - 1);
253+
254+
char c2 = k.isEmpty() ? 0 : k.charAt(k.length() - 1);
255+
if (c2 == '%' || c2 == '_' || c2 == '?') {
256+
if (c2 == c) {
257+
throw new IllegalArgumentException(originKey + ":value 中字符 " + k + " 不合法!key$:value 中不允许 key 中有连续相同的占位符!");
258+
}
259+
260+
t = c2 + t;
261+
k = k.substring(0, k.length() - 1);
262+
}
263+
else if (c == '?') {
264+
throw new IllegalArgumentException(originKey + ":value 中字符 " + originKey + " 不合法!key$:value 中不允许只有单独的 '?',必须和 '%', '_' 之一配合使用 !");
265+
}
266+
}
267+
268+
setRelateType(t);
248269
}
249270
else if (originKey.endsWith("~")) {
250271
boolean ignoreCase = originKey.endsWith("*~");
@@ -276,6 +297,8 @@ else if (originKey.endsWith("<")) {
276297
throw new UnsupportedOperationException(joinType + "/.../" + table + "/" + originKey + " 中字符 " + k + " 不合法!与或非逻辑符仅支持 '!' 非逻辑符 !");
277298
}
278299

300+
//TODO if (c3 == '-') { // 表示 key 和 value 顺序反过来: value LIKE key
301+
279302
Logic l = new Logic(k);
280303
setLogic(l);
281304

0 commit comments

Comments
 (0)