新增支持假删除

1、新增支持假删除
2、修改bug
{
    "User_address": {
        "user_id!": "3123f016-a4cc-455c-aac5-264c1230dcb",
        "count": 11,
        "count+": 1,
        "@combine": "user_id! | count"
    },
    "tag": "User_address",
    "@explain": true
}
条件 修改、删除,@combine 强制指定 "count": "" 为条件
This commit is contained in:
cloudAndMonkey 2023-01-06 11:28:33 +08:00 committed by GitHub
parent 256dd81803
commit 5f5300e63e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 108 additions and 42 deletions

View File

@ -68,8 +68,6 @@ import static apijson.JSONObject.KEY_SCHEMA;
import static apijson.JSONObject.KEY_USER_ID;
import static apijson.RequestMethod.DELETE;
import static apijson.RequestMethod.GET;
import static apijson.RequestMethod.GETS;
import static apijson.RequestMethod.HEADS;
import static apijson.RequestMethod.POST;
import static apijson.RequestMethod.PUT;
import static apijson.JSONObject.KEY_METHOD;
@ -171,7 +169,8 @@ public abstract class AbstractSQLConfig implements SQLConfig {
DATABASE_LIST.add(DATABASE_TRINO);
DATABASE_LIST.add(DATABASE_INFLUXDB);
DATABASE_LIST.add(DATABASE_TDENGINE);
DATABASE_LIST.add(DATABASE_REDIS);
DATABASE_LIST.add(DATABASE_MQ);
RAW_MAP = new LinkedHashMap<>(); // 保证顺序避免配置冲突等意外情况
@ -1116,6 +1115,21 @@ public abstract class AbstractSQLConfig implements SQLConfig {
return DATABASE_TDENGINE.equals(db);
}
@Override
public boolean isRedis() {
return isRedis(getSQLDatabase());
}
public static boolean isRedis(String db) {
return DATABASE_REDIS.equals(db);
}
@Override
public boolean isMQ() {
return isMQ(getSQLDatabase());
}
public static boolean isMQ(String db) {
return DATABASE_MQ.equals(db);
}
@Override
public String getQuote() {
@ -4956,10 +4970,6 @@ public abstract class AbstractSQLConfig implements SQLConfig {
//条件<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
String[] ws = StringUtil.split(combine);
if (ws != null && (method == DELETE || method == GETS || method == HEADS)) {
throw new IllegalArgumentException(table + ":{} 里的 @combine:value 不合法DELETE,GETS,HEADS 请求不允许传 @combine:value !");
}
String combineExpr = ws == null || ws.length != 1 ? null : ws[0];
Map<String, List<String>> combineMap = new LinkedHashMap<>();
@ -4991,28 +5001,44 @@ public abstract class AbstractSQLConfig implements SQLConfig {
whereList.add(userIdInKey);
}
if(config.isFakeDelete()) {
// 查询Access假删除
Map<String, Object> accessFakeDeleteMap = AbstractVerifier.ACCESS_FAKE_DELETE_MAP.get(config.getTable());
if (StringUtil.isNotEmpty(accessFakeDeleteMap.get("deletedKey"), true)) {
Map<String, Object> fakeDeleteMap = new HashMap<>();
boolean isFakeDelete = true;
if(method != DELETE) {
if(from != null) {
// 兼容 join 外层select 重复生成deletedKey
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())) {
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 (StringUtil.isNotEmpty(combineExpr, true)) {
List<String> banKeyList = Arrays.asList(idKey, idInKey, userIdKey, userIdInKey);
for (String key : banKeyList) {
String str = combineExpr;
while (str.isEmpty() == false) {
int index = str.indexOf(key);
if (index < 0) {
break;
}
char left = index <= 0 ? ' ' : str.charAt(index - 1);
char right = index >= str.length() - key.length() ? ' ' : str.charAt(index + key.length());
if ((left == ' ' || left == '(' || left == '&' || left == '|' || left == '!') && (right == ' ' || right == ')')) {
throw new UnsupportedOperationException(table + ":{} 里的 @combine:value 中的 value 里 " + key + " 不合法!"
+ "不允许传 [" + idKey + ", " + idInKey + ", " + userIdKey + ", " + userIdInKey + "] 其中任何一个!");
}
int newIndex = index + key.length() + 1;
if (str.length() <= newIndex) {
break;
}
str = str.substring(newIndex);
if(keyInCombineExpr(combineExpr, key)) {
throw new UnsupportedOperationException(table + ":{} 里的 @combine:value 中的 value 里 " + key + " 不合法!"
+ "不允许传 [" + idKey + ", " + idInKey + ", " + userIdKey + ", " + userIdInKey + "] 其中任何一个!");
}
}
}
@ -5066,7 +5092,7 @@ public abstract class AbstractSQLConfig implements SQLConfig {
}
//条件>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Map<String, Object> tableContent = new LinkedHashMap<String, Object>();
Object value;
for (String key : set) {
@ -5076,18 +5102,17 @@ public abstract class AbstractSQLConfig implements SQLConfig {
throw new IllegalArgumentException(table + ":{ " + key + ":value } 中 value 类型错误!除了 key<>:{} 外,不允许 " + key + " 等其它任何 key 对应 value 的类型为 JSONObject {} !");
}
//兼容 PUT @combine
//解决AccessVerifier新增userId没有作为条件而是作为内容导致PUTDELETE出错
if (isWhere || (StringUtil.isName(key.replaceFirst("[+-]$", "")) == false)) {
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);
}
}
else if (whereList.contains(key)) {
} else if (whereList.contains(key)) {
tableWhere.put(key, value);
}
else {
tableContent.put(key, value); //一样 instanceof JSONArray ? JSON.toJSONString(value) : value);
} else {
tableContent.put(key, value); //一样 instanceof JSONArray ? JSON.toJSONString(value) : value);
}
}
@ -5102,6 +5127,20 @@ public abstract class AbstractSQLConfig implements SQLConfig {
config.setContent(tableContent);
}
if(method == DELETE) {
if(config.isFakeDelete()) {
//查询Access假删除
Map<String, Object> accessFakeDeleteMap = AbstractVerifier.ACCESS_FAKE_DELETE_MAP.get(config.getTable());
if (StringUtil.isNotEmpty(accessFakeDeleteMap.get("deletedKey"), true)) {
//假删除需要更新的其他字段比如删除时间 deletedTime 之类的
Map<String, Object> fakeDeleteMap = new HashMap<>();
config.onFakeDelete(fakeDeleteMap);
fakeDeleteMap.put(accessFakeDeleteMap.get("deletedKey").toString(), accessFakeDeleteMap.get("deletedValue"));
config.setMethod(PUT);
config.setContent(fakeDeleteMap);
}
}
}
List<String> cs = new ArrayList<>();
@ -5494,14 +5533,12 @@ public abstract class AbstractSQLConfig implements SQLConfig {
//TODO if (key.endsWith("-")) { // 表示 key value 顺序反过来: value LIKE key
String last = null;//不用Logic优化代码否则 key 可能变为 key| 导致 key=value 变成 key|=value 而出错
if (RequestMethod.isQueryMethod(method)) {//逻辑运算符仅供GET,HEAD方法使用
last = key.isEmpty() ? "" : key.substring(key.length() - 1);
if ("&".equals(last) || "|".equals(last) || "!".equals(last)) {
key = key.substring(0, key.length() - 1);
} else {
last = null;//避免key + StringUtil.getString(last)错误延长
}
//不用Logic优化代码否则 key 可能变为 key| 导致 key=value 变成 key|=value 而出错
String last = key.isEmpty() ? "" : key.substring(key.length() - 1);
if ("&".equals(last) || "|".equals(last) || "!".equals(last)) {
key = key.substring(0, key.length() - 1);
} else {
last = null;//避免key + StringUtil.getString(last)错误延长
}
//"User:toUser":User转换"toUser":User, User为查询同名Table得到的JSONObject交给客户端处理更好
@ -5606,6 +5643,27 @@ public abstract class AbstractSQLConfig implements SQLConfig {
}
private static boolean keyInCombineExpr(String combineExpr, String key) {
while (combineExpr.isEmpty() == false) {
int index = combineExpr.indexOf(key);
if (index < 0) {
return false;
}
char left = index <= 0 ? ' ' : combineExpr.charAt(index - 1);
char right = index >= combineExpr.length() - key.length() ? ' ' : combineExpr.charAt(index + key.length());
if ((left == ' ' || left == '(' || left == '&' || left == '|' || left == '!') && (right == ' ' || right == ')')) {
return true;
}
int newIndex = index + key.length() + 1;
if (combineExpr.length() <= newIndex) {
break;
}
combineExpr = combineExpr.substring(newIndex);
}
return false;
}
private void setWithAsExpreList() {
// mysql8版本以上,子查询支持with as表达式
if(this.isMySQL() && this.getDBVersionNums()[0] >= 8) {

View File

@ -127,6 +127,8 @@ public abstract class AbstractVerifier<T extends Object> implements Verifier<T>,
public static Map<String, Map<RequestMethod, String[]>> SYSTEM_ACCESS_MAP;
@NotNull
public static Map<String, Map<RequestMethod, String[]>> ACCESS_MAP;
@NotNull
public static Map<String, Map<String, Object>> ACCESS_FAKE_DELETE_MAP;
// <method tag, <version, Request>>
// <PUT Comment, <1, { "method":"PUT", "tag":"Comment", "structure":{ "MUST":"id"... }... }>>

View File

@ -33,7 +33,8 @@ public interface SQLConfig {
String DATABASE_TRINO = "TRINO"; // PrestoSQL https://trino.io
String DATABASE_INFLUXDB = "INFLUXDB"; // https://www.influxdata.com/products/influxdb-overview
String DATABASE_TDENGINE = "TDENGINE"; // https://tdengine.com
String DATABASE_REDIS = "REDIS";
String DATABASE_MQ = "MQ";
String SCHEMA_INFORMATION = "information_schema"; //MySQL, PostgreSQL, SQL Server 都有的系统模式
String SCHEMA_SYS = "sys"; //SQL Server 系统模式
@ -60,6 +61,8 @@ public interface SQLConfig {
boolean isTrino();
boolean isInfluxDB();
boolean isTDengine();
boolean isRedis();
boolean isMQ();
//暂时只兼容以上几种
@ -317,4 +320,7 @@ public interface SQLConfig {
List<Object> getWithAsExprePreparedValueList();
void setWithAsExprePreparedValueList(List<Object> withAsExprePreparedValueList);
boolean isFakeDelete();
void onFakeDelete(Map<String, Object> map);
}