Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

apijson json服务编排 #482

Open
cloudAndMonkey opened this issue Nov 26, 2022 · 243 comments
Open

apijson json服务编排 #482

cloudAndMonkey opened this issue Nov 26, 2022 · 243 comments
Labels
Ecosystem 周边生态 完善生态(Go语言版、更多Demo、周边工具等) Enhancement 增强 增强功能、提高性能等

Comments

@cloudAndMonkey
Copy link
Contributor

cloudAndMonkey commented Nov 26, 2022

Description

@TommyLemon
功能描述:
一个服务编排的伪码流程设计
将伪码转换为 apijson json、前置、后置函数、javascript、redis、elasticSearch等
并且能够mork每一步,执行中间流程,还能查询每个阶段执行的sql语句,及结果.

json格式:

{
    "@transaction": true, 
    "id@-()": "getCurrentUserId()", // 前置函数
    "@post": [
        "xxx"
    ], 
    "xxx": {
     "@method": "xxx",
      "@version": "", // 版本,控制校验
      "@datasource": "" // 数据源相关配置
     // 分表规则等,后面再说
   }
"@explain": true
}

1、独立定义一个url method, 通过解析不同method执行不同流程
和已有method区分开,避免歧义
2、最外层新增传参 "transaction": true 来指定开启事务
3、控制每条语句的数据源
4、完善 “@Explain"
如果没有执行计划,则返回sql语句. 能够在 reponse返回值中, 看到json中执行的每条sql,方便排错
5、@Version支持
定义不同场景的 新增、修改、删除等执行规则. 请通过version版本区分
6、前置函数

  1. 要能拿到其他数据源
  2. 能拿到json执行过程中的数据
  3. 拿到当前数据源(和外部json一个事物执行)
  4. 从数据库/或其他数据源 查询获取对照关系
    组装数据, 调用对应数据源的api方法执行即可
  5. 前置函数,能调用其他函数
    把一些计算, 执行,计算 等 放到一个函数进行整合
    还没细化
    7、支持mork
    通过伪码,分解为不同 阶段 的json语句执行

测试点:
1、测试 一个json多条语句,后置函数啥时候执行
2、操作其他数据源, 事物是json执行完才会提交, 需要保证一致性
3、redis、elasticSearch、javascript、lua等功能测试

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 26, 2022

@TommyLemon
1、独立定义一个url method, 通过解析不同method执行不同流程
和已有method区分开,避免歧义
对,这样更好,enum RequestMethod.java 新增 CRUD 这个枚举值,对应 URL 为 /crud,对于前端没传参 transaction: true 时自动放入 transaction: true。

场景:
method= crud
1、传递 "@transaction": true
2、不传
这里实现方案要考虑几个点:
1、在校验模块, 遍历json每个对象、数组的 method, 就知道是否需要开启事物
但是 为了后面 函数调用支持事物, 这个方式有局限性
2、对应 URL 为 /crud,对于前端没传参 transaction: true 时自动放入 transaction: true
3、将不同method功能区分开
现在json执行是通用解析,需不需要控制, 只能调用crud 方法,才能支持增删改查等操作. 其他method, 除了函数、子查询,就只能和 url method保持一致的操作

@TommyLemon
Copy link
Collaborator

TommyLemon commented Nov 26, 2022

1、在校验模块, 遍历json每个对象、数组的 method, 就知道是否需要开启事物

扫描所有字段来识别是否有 transaction 代价太大了。
没有 transaction: true,那就不做全局事务处理,局部有 增删改 就局部处理事务。
如果业务需求必须整体有事务,那就通过 Request 表配置规则来强制 PUT transaction: true。

非 CRUD 方法,都只能和 URL method 完全一致,避免意料之外的安全风险。
如果传了 method 相关键值对("@delete":"Comment" 等),直接抛异常 "不支持在 GET 中 DELETE !"

话说现有使用方式 "@delete":["Comment"] 麻烦了点,前端传参应该尽可能简化,除非有兼容等严重问题或实现代价太大,APIJSON 所有 key 不支持逗号 , 分号 ; 斜杠 / 反斜杠 \,所以 "@delete":"Comment[],Moment" 并不会有兼容问题。
可以用 StringUtil.split 分割逗号,内部处理了整体空值、局部空值等。

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 26, 2022

@TommyLemon
1、扫描所有字段来识别是否有 transaction 代价太大了。
要考虑数组的情况, 不可行. 我当时就是不想全部解析, 只通过key及@变量
2、事物这块
那就通过 Request 表配置规则来强制 PUT transaction: true。
不需要, 每条执行语句都知道它的method
我先测一下
3、 "@delete":["Comment"]
我来改一下, 当时采用数组, 是想到后台直接jsonArray转换方便
4、非 CRUD 方法,都只能和 URL method 完全一致,避免意料之外的安全风险。
如果传了 method 相关键值对("@delete":"Comment" 等),直接抛异常 "不支持在 GET 中 DELETE !"

@TommyLemon
Copy link
Collaborator

TommyLemon commented Nov 26, 2022

为了支持跨数据源的事务,需要在 AbstractParser 新增一个

// Map<数据源标识, SQLExecutor 实例>
Map<String, SQLExecutor> datasourceSQLExecutorMap

数据源标识同 AbstractSQLExecutor.connectionMap 的 key
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java#L1135-L1156
image

AbstractParser.getSQLExecutor 根据 数据源标识 get 到非 null 就返回,没有才 createSQLExecutor 然后 put 进 map 再返回;
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java#L344-L349
image

Parser.begin 时只对当前的 SQLExecutor 调用 begin。

Parser.rollback 时统一遍历 datasourceSQLExecutorMap 的所有 SQLExecutor 来 rollback;
Parser.commit 时统一遍历 datasourceSQLExecutorMap 的所有 SQLExecutor 来 commit;
Parser.close 时统一遍历 datasourceSQLExecutorMap 的所有 SQLExecutor 来 close;

https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java#L1971-L1994
image

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 27, 2022

1、在校验模块, 遍历json每个对象、数组的 method, 就知道是否需要开启事物

扫描所有字段来识别是否有 transaction 代价太大了。 没有 transaction: true,那就不做全局事务处理,局部有 增删改 就局部处理事务。 如果业务需求必须整体有事务,那就通过 Request 表配置规则来强制 PUT transaction: true。

非 CRUD 方法,都只能和 URL method 完全一致,避免意料之外的安全风险。 如果传了 method 相关键值对("@delete":"Comment" 等),直接抛异常 "不支持在 GET 中 DELETE !"

话说现有使用方式 "@delete":["Comment"] 麻烦了点,前端传参应该尽可能简化,除非有兼容等严重问题或实现代价太大,APIJSON 所有 key 不支持逗号 , 分号 ; 斜杠 / 反斜杠 \,所以 "@delete":"Comment[],Moment" 并不会有兼容问题。 可以用 StringUtil.split 分割逗号,内部处理了整体空值、局部空值等。

@TommyLemon
1、全局事物这块
没有 transaction: true,那就不做全局事务处理,局部有 增删改 就局部处理事务。
不好意思, 这里我没有理解你的意思.
说说我的理解哈
json配置 datasource, 是知道哪些操作共享一个 datasource.
同一个数据源, 多个 PUT、DELETE、POST 使用同一个Connection.
也就是说, 只要一个 connection, 存在 PUT、DELETE、POST,就开启全局事物?
不好意思, 还是你更优的解决方案,我没有get到?
image
image
commit 提交事物:
是在多个 操作( PUT、DELETE、POST ) 执行完, 才调用:
image

@TommyLemon
Copy link
Collaborator

如果不是全局事务,那就只有当执行 增/删/改 时开启,执行完马上 commit,碰到下一个 增/删/改 再开启和 commit。
如果是全局事务,则一开始就开启,执行完整个请求再 commit。

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 28, 2022

@TommyLemon
这几点我已经搞好了
1、url method crud支持

解析顺序

  1. 对象内 "@method"
  2. "@post","@put","@delete"
  3. 对于没有显式声明操作方法的,直接用 URL(/get, /post 等) 对应的默认操作方法
    第三点不适用了,url method =crud,必须显示定义操作方法
    throw new IllegalArgumentException("url crud方法,必须定义 " + key + " 对应的method, 例如: @post: "xxx,xxx[]" 或者 对象内 @method="POST" !");
    image

2、非 CRUD 方法,都只能和 URL method 完全一致,避免意料之外的安全风险。
如果传了 method 相关键值对("@delete":"Comment" 等),直接抛异常 "不支持在 GET 中 DELETE !"
http://xxx/put

{
	"@post": "User:aa",
    "User:aa":{
        "username":"test-3",
        "password": "233223",
		"state": 1
    },
    "tag": "User",
    "@explain": true
}

image
3、非crud
支持函数、sql@ 子查询调用.
4、修改 "@get": 数组 改为 字符串

{
   "@post": "User:aa,User_address[]",
   "User:aa":{
        "username":"test1",
        "password": "123456",
		"state": 1
    },
    "User_address[]": [
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd",
    	"count": 1
    	},
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd1",
    	"count": 2
    	}
    ],
    "@delete": "User:delUser,User_address:delUserAddress",
    "User:delUser":{
    	"id{}": ["b6d7c307-cb82-4780-8361-2509973d88de", "c63d7bd8-cbb8-41f8-9ee0-713f0d30474b","cadeca84-2901-4850-aa36-6672d9d34299"]
    },
    "User_address:delUserAddress": {
    	"id{}": ["887edfe9-0206-415d-96de-325d97e248cb", "24eb9e05-d3ef-4661-8d22-c063643f61cd"]
    },
    "@explain": true
}

image

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 28, 2022

@TommyLemon
还有一个功能需要支持, put, 能够按照 name="xxx" 来修改.例如 update xxx set xxx ="" wehre name = "xxx"
目前非id put修改,只能通过ref引用做为条件进行修改,例如:
// 非id修改

{
	"sql@": {
		"@method": "GET",
        "with": true,
        "from": "User",
        "User": {
          "@column": "username",
		  "username": "非id-update-test-0"
        }
    },
    "User": {
    	"@state": 1,
    	"password": "123456",
        "username{}@": "sql"
    },
    "explan": true
}
WITH  `sql` AS (SELECT `username` FROM `housekeeping`.`User` WHERE  (  (`username` = '非id-update-test-0')  ) ) 
UPDATE `housekeeping`.`User` SET `password` = '123456_1669605075502' WHERE  (  (`username` IN ( SELECT * FROM `sql`) )  ) 

你看这么改行不?
对象内的临时变量 @xxx 作为条件, 例如 :

"User": {
    	"@state": 1,
    	"password": "123456"
    }
update user set password = "123456" where state = 1;

@TommyLemon
Copy link
Collaborator

@TommyLemon 这几点我已经搞好了 1、url method crud支持

解析顺序

  1. 对象内 "@method"
  2. "@post","@put","@delete"
  3. 对于没有显式声明操作方法的,直接用 URL(/get, /post 等) 对应的默认操作方法
    第三点不适用了,url method =crud,必须显示定义操作方法
    throw new IllegalArgumentException("url crud方法,必须定义 " + key + " 对应的method, 例如: @post: "xxx,xxx[]" 或者 对象内 @method="POST" !");
    image

2、非 CRUD 方法,都只能和 URL method 完全一致,避免意料之外的安全风险。 如果传了 method 相关键值对("@delete":"Comment" 等),直接抛异常 "不支持在 GET 中 DELETE !" http://xxx/put { "@post": "User:aa", "User:aa":{ "username":"test-3", "password": "233223", "state": 1 }, "tag": "User", "@Explain": true } image 3、非crud 支持函数、sql@ 子查询调用. 4、修改 "@get": 数组 改为 字符串 { "@post": "User:aa,User_address[]", "User:aa":{ "username":"test1", "password": "123456", "state": 1 }, "User_address[]": [ { "user_id@": "User:aa/id", "addr": "ddd", "count": 1 }, { "user_id@": "User:aa/id", "addr": "ddd1", "count": 2 } ], "@delete": "User:delUser,User_address:delUserAddress", "User:delUser":{ "id{}": ["b6d7c307-cb82-4780-8361-2509973d88de", "c63d7bd8-cbb8-41f8-9ee0-713f0d30474b","cadeca84-2901-4850-aa36-6672d9d34299"] }, "User_address:delUserAddress": { "id{}": ["887edfe9-0206-415d-96de-325d97e248cb", "24eb9e05-d3ef-4661-8d22-c063643f61cd"] }, "@Explain": true } image

CRUD 方法,没有声明就用 GET。
@method 看起来已经没有必要了,可以考虑去掉。

@TommyLemon
Copy link
Collaborator

WITH  `sql` AS (SELECT `username` FROM `housekeeping`.`User` WHERE  (  (`username` = '非id-update-test-0')  ) ) 

@State 会被认为是自定义关键词,与现有语法冲突,不合适。
目前可以用
"@combine":"state" 指定 "state": 1 是条件。
https://github.com/Tencent/APIJSON/blob/master/Document.md#3.2
image

#277
#425

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 28, 2022

WITH  `sql` AS (SELECT `username` FROM `housekeeping`.`User` WHERE  (  (`username` = '非id-update-test-0')  ) ) 

@State 会被认为是自定义关键词,与现有语法冲突,不合适。 目前可以用 "@combine":"state" 指定 "state": 1 是条件。 https://github.com/Tencent/APIJSON/blob/master/Document.md#3.2 image

#277 #425

嗯嗯,不好意思, 应该先查文档
测了一下,没问题, 转换为了regexp_like 正则匹配

{
    "User": {
    	"state~": "1",
    	"password": "123456",
        "username~": "test4",
        "@combine": "state~ & username~"
    },
    "explan": true
}
UPDATE `housekeeping`.`User` SET `password` = '123456_1669608632896' WHERE ( regexp_like(`state`, '1', 'c') ) AND ( regexp_like(`username`, 'test4', 'c') )

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 28, 2022

CRUD 方法,没有声明就用 GET。 @method 看起来已经没有必要了,可以考虑去掉。

@TommyLemon
CRUD 方法,没有声明就用 GET。
会出现吞并 json执行语句, 返回200的情况. 不方便排错.
框架是"正确"执行, 但是 对于用户来说, 就是一种"错觉"
这也是我很想避免的情况
比如: http://xxx/crud

{
   "User:aa":{
        "username":"test1",
        "password": "123456",
		"state": 1
    },
    "User_address[]": [
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd",
    	"count": 1
    	},
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd1",
    	"count": 2
    	}
    ],
    "@put": "User_address:modifUA",
    "User_address:modifUA": 
	{
		"id": "5e2d528c-106a-4f14-90b2-f27b5943e3e1",
    	"user_id@": "User:aa/id",
    	"addr": "addr-01",
    	"count": 1
	},
	
    "@explain": true
}

image

@TommyLemon
Copy link
Collaborator

        "username~": "test4",

带有查询条件功能符的话,不用声明在 @combine 内,也会作为条件

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 28, 2022

json 不用传递 @method, 代码我已经调整
我也做了head 子查询sql@的兼容,避免子查询别转化为 count执行
错误语句:

WITH  `sql` AS (SELECT count(*) FROM `housekeeping`.`Sys_user_role` WHERE  (  (`user_id` = '4732209c-5785-4827-b532-5092f154fd94')  ) ) \nSELECT * FROM `housekeeping`.`Sys_role` WHERE  (  (`id` IN ( SELECT * FROM `sql`) )  )  LIMIT 1

正确语句:

WITH  `sql` AS (SELECT `role_id` FROM `housekeeping`.`Sys_user_role` WHERE  (  (`user_id` = '4732209c-5785-4827-b532-5092f154fd94')  ) ) \nSELECT * FROM `housekeeping`.`Sys_role` WHERE  (  (`id` IN ( SELECT * FROM `sql`) )  )  LIMIT 1

@TommyLemon
Copy link
Collaborator

TommyLemon commented Nov 28, 2022

CRUD 方法,没有声明就用 GET。 @method 看起来已经没有必要了,可以考虑去掉。

@TommyLemon CRUD 方法,没有声明就用 GET。 会出现吞并 json执行语句, 返回200的情况. 不方便排错. 框架是"正确"执行, 但是 对于用户来说, 就是一种"错觉" 这也是我很想避免的情况 比如: http://xxx/crud

{
   "User:aa":{
        "username":"test1",
        "password": "123456",
		"state": 1
    },
    "User_address[]": [
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd",
    	"count": 1
    	},
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd1",
    	"count": 2
    	}
    ],
    "@put": "User_address:modifUA",
    "User_address:modifUA": 
	{
		"id": "5e2d528c-106a-4f14-90b2-f27b5943e3e1",
    	"user_id@": "User:aa/id",
    	"addr": "addr-01",
    	"count": 1
	},
	
    "@explain": true
}

image

未显示声明 method,默认用 GET,至于参数被吞掉,没有实际执行,这是 bug,改掉就好了

@cloudAndMonkey
Copy link
Contributor Author

CRUD 方法,没有声明就用 GET。 @method 看起来已经没有必要了,可以考虑去掉。

@TommyLemon CRUD 方法,没有声明就用 GET。 会出现吞并 json执行语句, 返回200的情况. 不方便排错. 框架是"正确"执行, 但是 对于用户来说, 就是一种"错觉" 这也是我很想避免的情况 比如: http://xxx/crud

{
   "User:aa":{
        "username":"test1",
        "password": "123456",
		"state": 1
    },
    "User_address[]": [
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd",
    	"count": 1
    	},
    	{
    	"user_id@": "User:aa/id",
    	"addr": "ddd1",
    	"count": 2
    	}
    ],
    "@put": "User_address:modifUA",
    "User_address:modifUA": 
	{
		"id": "5e2d528c-106a-4f14-90b2-f27b5943e3e1",
    	"user_id@": "User:aa/id",
    	"addr": "addr-01",
    	"count": 1
	},
	
    "@explain": true
}

image

未显示声明 method,默认用 GET,至于参数被吞掉,没有实际执行,这是 bug,改掉就好了
哈哈,那我来改掉. 不然我受不了. 用apijson这段时间,我最讨厌的就是json吞并问题

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 28, 2022

@TommyLemon
我分析了一下代码, 主要有两个点:
1、无法匹配执行流程, 将json语句原样添加到 sqlRequest
image
2、子查询出错 "user_id@": "User:aa/id",
image
如果 ref 找不到,语句将不会执行, json就会被吞掉
当开启 AbstractVerifier.IS_UPDATE_MUST_HAVE_ID_CONDITION = false; ref就是查询关键词了.

你看这里是 不管IS_UPDATE_MUST_HAVE_ID_CONDITION 的值,无法找到引用对象,就抛异常嘛?
image
我想起来了, 我当时为啥要整理 #467
就是因为ref找不到, json被吞掉,不执行
image

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 28, 2022

累死我了, json支持事物、多条语句执行, http crud支持 很完善了
我去搞elasticSearch了
后面回过头再来搞 多数据源,以及控制每条语句connection

@TommyLemon
Copy link
Collaborator

TommyLemon commented Nov 28, 2022

@TommyLemon 我分析了一下代码, 主要有两个点: 1、无法匹配执行流程, 将json语句原样添加到 sqlRequest image 2、子查询出错 "user_id@": "User:aa/id", image 如果 ref 找不到,语句将不会执行, json就会被吞掉 当开启 AbstractVerifier.IS_UPDATE_MUST_HAVE_ID_CONDITION = false; ref就是查询关键词了.

你看这里是 不管IS_UPDATE_MUST_HAVE_ID_CONDITION 的值,无法找到引用对象,就抛异常嘛? image 我想起来了, 我当时为啥要整理 #467 就是因为ref找不到, json被吞掉,不执行 image

1.GET/GETS/HEAD/HEADS/DELETE 都不会处理 Table[]:[] ,这个没有对应的协议及功能,不用管,用户这么传,原样返回,这是他们用法问题。

2.引用赋值,如果关联的值查不到或者为 null,不能允许继续查询,因为这会导致范围扩大,不符合绝大部分需求,而且有严重的安全隐患,例如 GETS/HEADS/PUT/DELETE 的 id/userId 条件限制因为允许 null 而失效。这不是 bug,是功能特性,所以也不用管。

#467 应该是写法问题
#467 (comment)

@TommyLemon
Copy link
Collaborator

累死我了, json支持事物、多条语句执行, http crud支持 很完善了 我去搞elasticSearch了 后面回过头再来搞 多数据源,以及控制每条语句connection

可以的

@cloudAndMonkey
Copy link
Contributor Author

1.GET/GETS/HEAD/HEADS/DELETE 都不会处理 Table[]:[] ,这个没有对应的协议及功能,不用管,用户这么传,原样返回,这是他们用法问题。

2.引用赋值,如果关联的值查不到或者为 null,不能允许继续查询,因为这会导致范围扩大,不符合绝大部分需求,而且有严重的安全隐患,例如 GETS/HEADS/PUT/DELETE 的 id/userId 条件限制因为允许 null 而失效。这不是 bug,是功能特性,所以也不用管。
@TommyLemon
我知道这是用户使用的问题
吞掉执行语句, crud里面有/POST/PUT/DELETE语句 ,会提交成功的.
要考虑新手入门,练手阶段
吞掉执行语句, explain模式 返回结果要能让人家通过结果知道 为啥没有执行sql语句,是因为引用失败了

@cloudAndMonkey
Copy link
Contributor Author

我看了apijson elasticSearch demo. 引入 elasticsearch-sql. json里面配置多数据源,我测一下

@TommyLemon
Copy link
Collaborator

TommyLemon commented Nov 28, 2022

1.GET/GETS/HEAD/HEADS/DELETE 都不会处理 Table[]:[] ,这个没有对应的协议及功能,不用管,用户这么传,原样返回,这是他们用法问题。

2.引用赋值,如果关联的值查不到或者为 null,不能允许继续查询,因为这会导致范围扩大,不符合绝大部分需求,而且有严重的安全隐患,例如 GETS/HEADS/PUT/DELETE 的 id/userId 条件限制因为允许 null 而失效。这不是 bug,是功能特性,所以也不用管。 @TommyLemon 我知道这是用户使用的问题 吞掉执行语句, crud里面有/POST/PUT/DELETE语句 ,会提交成功的. 要考虑新手入门,练手阶段 吞掉执行语句, explain模式 返回结果要能让人家通过结果知道 为啥没有执行sql语句,是因为引用失败了

这个通过 APIAuto 来解决吧,新增一个提示。类似
"user": {}
这种小写字母开头的,不符合 APIJSON 表名规范,就会有提示。
image
https://apijson.cn/api/?send=false&type=JSON&url=http%3A%2F%2Fapijson.cn%3A8080%2Fget&json={%22user%22:{%22id%22:82001}}

@Explain: true 也不返回,这个是 bug,可以在 AbstractObjectParser 中处理下
sqlResponse = null;
加上判断 isExplain 时
sqlResponse = new JSONObject();
put 进 @Explain: {
"msg": "引用赋值未获取到有效的关联值,返回空"
}

https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java#L735-L747
image

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 29, 2022

@TommyLemon
我看了 官网X-Pack sql(收费)支持:
https://www.elastic.co/guide/en/elasticsearch/reference/7.17/sql-getting-started.html
开源: https://github.com/NLPchina/elasticsearch-sql
如果apijson要支持elasticsearch sql,有几个点,需要解决:
1、新增、修改
它们都不支持新增、修改, 如果要支持新增修改, 通过如下语句执行:
image
elasticsearch-sql 是通过: org.elasticsearch.client.transport.TransportClient 方式执行插入
image
image
删除:
image
apijson需要按照数据源类型, 生成不同格式的新增/修改 sql语句, 删除,查询 还没有细测
2、查询 估计还是会有一部分兼容问题
目前还没有细测,查询是按照jdbc 语句来执行
image

@TommyLemon
Copy link
Collaborator

TommyLemon commented Nov 29, 2022

@TommyLemon 我看了 官网X-Pack sql(收费)支持: https://www.elastic.co/guide/en/elasticsearch/reference/7.17/sql-getting-started.html 开源: https://github.com/NLPchina/elasticsearch-sql 如果apijson要支持elasticsearch sql,有几个点,需要解决: 1、新增、修改 它们都不支持新增、修改, 如果要支持新增修改, 通过如下语句执行: image elasticsearch-sql 是通过: org.elasticsearch.client.transport.TransportClient 方式执行插入 image image 删除: image apijson需要按照数据源类型, 生成不同格式的新增/修改 sql语句, 删除,查询 还没有细测 2、查询 估计还是会有一部分兼容问题 目前还没有细测,查询是按照jdbc 语句来执行 image

1、Elasticsearch-SQL 不支持增删改的话,APIJSON 也先不急着支持,用户可以用 RESTful API 的方式自己实现。后续如果这方面需求的用户比较多再考虑。

/refresh 这种接口也让用户自己调用。APIJSON 暂时先主要支持最核心也最常用的查询功能。

2、截屏的代码没有用 APIJSON,可以用 APIJSON 再试试。

@TommyLemon
Copy link
Collaborator

之前改 bug 等源码变更,可以先提交 PR 哦,有了 fork 项目,提 PR 只需要 Git 推送到 fork 项目,然后点 Contribute > Open Pull Request,例如

image

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 29, 2022

@TommyLemon
1、我这两天就提交,应该不用大改了,我明天再回归测试一下
2、用apijson使用elasticSearch
用户可以用 RESTful API 的方式自己实现.
需要我实现接口来新增、修改、删除?
目前apijson除了数据源支持elasticSearch, 执行方法方面如何集成?
比如: 多数据源, 其中一个数据源是 elasticSearch, 执行插入, apijson会生成sql语句,然后调用 执行方法?

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Nov 29, 2022

@TommyLemon
redis这块, 我今天看了一下. redis 也支持 sql语句方式来操作表,比如:
https://github.com/RedBeardLab/rediSQL(不更新了), 改为收费版: https://zeesql.com/#pricing
https://help.aliyun.com/document_detail/99960.html
我通过docker测试了一下:
支持redis表 新增、修改、删除、查询、分组、关联查询等
image
在某些维度统计,不需要走大数据分析的情况, 能解决elasticSearch无法关联查询的情况

@TommyLemon
Copy link
Collaborator

2、用户直接调用 Elasticsearch 的官方 API(目前是 RESTful API)实现增删改、初始化、权限管理等,也可以用配套的管理界面或 CLI 等。

执行方法是指 SQL 函数?远程函数?还是存储过程?如果是前 2 者应该都没问题,至于存储过程看 Elasticsearch 是否支持。

这个第三方库倒是支持 SQL 语法比较全,不过 新增和修改 看文档还不支持,可以对比下官方的,看情况决定用哪个。
https://github.com/NLPchina/elasticsearch-sql#sql-features
image

@TommyLemon
Copy link
Collaborator

TommyLemon commented Nov 29, 2022

@TommyLemon redis这块, 我今天看了一下. redis 也支持 sql语句方式来操作表,比如: https://github.com/RedBeardLab/rediSQL(不更新了), 改为收费版: https://zeesql.com/#pricing https://help.aliyun.com/document_detail/99960.html 我通过docker测试了一下: 支持redis表 新增、修改、删除、查询、分组、关联查询等 image 在某些维度统计,不需要走大数据分析的情况, 能解决elasticSearch无法关联查询的情况

赞,也可以通过 SQL 语法支持 APIJSON 对接 Redis 了。

@TommyLemon
Copy link
Collaborator

TommyLemon commented Jan 4, 2023

notDeletedValue 目前看起来没必要,
deletedKey != deletedValue 就包含了 deletedKey = notDeletedValue 的情况。
或者用
validKey = validValue 表示数据有效(未删除),validKey != validValue 表示无效(已删除),
因为 deletedTime 是不固定的,不能用一个值表示已删除,所以最好用一个值(NULL, 0, '' 等其中一个)表示未删除,其它表示已删除更好

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Jan 5, 2023

notDeletedValue 目前看起来没必要, deletedKey != deletedValue 就包含了 deletedKey = notDeletedValue 的情况。 或者用 validKey = validValue 表示数据有效(未删除),validKey != validValue 表示无效(已删除), 因为 deletedTime 是不固定的,不能用一个值表示已删除,所以最好用一个值(NULL, 0, '' 等其中一个)表示未删除,其它表示已删除更好

@TommyLemon
update、delete where 条件 不支持 不等于
{
"User_address": {
"user_id!~": "3123f016-a4cc-455c-aac5-264c1230dcb4",
"count+": 1
},
"tag": "User_address",
"@Explain": true
}
image

查询支持
{
"User_address:a": {
"user_id!~": "3123f016-a4cc-455c-aac5-264c1230dcb4"
},
"@Explain": true
}
image

源码 查询做了处理:
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L5490-L5510
image

@TommyLemon
Copy link
Collaborator

TommyLemon commented Jan 5, 2023

@cloudAndMonkey 现在可以取消 isQueryMethod 这个限制了。
另外
"key!": value
就是
key != value
如果是
"key!~": value
那就是正则
key NOT REGEXP value

378BF271-E8C9-4FBB-A06D-EA63DB3B33E7

https://github.com/Tencent/APIJSON/blob/master/Document.md#3.2

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Jan 5, 2023

@cloudAndMonkey 现在可以取消 isQueryMethod 这个限制了。 另外 "key!": value 就是 key != value 如果是 "key!~": value 那就是正则 key NOT REGEXP value

378BF271-E8C9-4FBB-A06D-EA63DB3B33E7

https://github.com/Tencent/APIJSON/blob/master/Document.md#3.2
@TommyLemon
取消 isQueryMethod 这个限制
PUT 条件修改, 非和正则 都能正常执行:
{
"User_address": {
"user_id!": "3123f016-a4cc-455c-aac5-264c1230dcb4",
"count+": 1
},
"tag": "User_address",
"@Explain": true
}
"sql": "UPDATE housekeeping.User_address SET count = count + 1, addr = 'null_1672896387696' WHERE ( (deleted = '0') AND (user_id != '3123f016-a4cc-455c-aac5-264c1230dcb') ) "

请问PUT 条件修改 json 如何实现 where a = "" 呢?
区分不了呀,哈哈😁
image
update 是把key作为 update set 字段执行

@TommyLemon
Copy link
Collaborator

TommyLemon commented Jan 5, 2023

@cloudAndMonkey "@combine": "a" 强制指定 "a": "" 为条件,
带功能符号的就直接作为条件,可以不用 @combine
#277

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Jan 5, 2023

@cloudAndMonkey "@combine": "a" 强制指定 "a": "" 为条件, 带功能符号的就直接作为条件,可以不用 @combine #277
@TommyLemon
嗯嗯, 你以前跟我说过 ,带功能符号的就直接作为条件,可以不用 @combine

{
"User_address": {
"user_id": "3123f016-a4cc-455c-aac5-264c1230dcb",
"count+": 1,
"@combine": "user_id"
},
"tag": "User_address",
"@Explain": true
}

"msg": "User_address:{ @combine:'user_id' } 中字符 'user_id' 对应的条件键值对 user_id:value 不存在!"

这个和apijson解析顺序有关, 如果要实现"h@combine": "a" 强制指定 "a": "" 为条件,需要调整解析顺序,还要考虑是否有其他影响?

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Jan 5, 2023

@MethodAccess
@TommyLemon
注解方式需要实现 假删除吗?
image
// 由 init 方法读取数据库 Access 表来替代手动输入配置
// // <TableName, <METHOD, allowRoles>>
// // <User, <GET, [OWNER, ADMIN]>>
// static { //注册权限
// ACCESS_MAP.put(User.class.getSimpleName(), getAccessMap(User.class.getAnnotation(MethodAccess.class)));
// ACCESS_MAP.put(Privacy.class.getSimpleName(), getAccessMap(Privacy.class.getAnnotation(MethodAccess.class)));
// ACCESS_MAP.put(Moment.class.getSimpleName(), getAccessMap(Moment.class.getAnnotation(MethodAccess.class)));
// ACCESS_MAP.put(Comment.class.getSimpleName(), getAccessMap(Comment.class.getAnnotation(MethodAccess.class)));
// ACCESS_MAP.put(Verify.class.getSimpleName(), getAccessMap(Verify.class.getAnnotation(MethodAccess.class)));
// ACCESS_MAP.put(Login.class.getSimpleName(), getAccessMap(Login.class.getAnnotation(MethodAccess.class)));
// }

@TommyLemon
Copy link
Collaborator

TommyLemon commented Jan 5, 2023

这个不方便用注解实现,直接用一个 Map 存假删除配置就行,虽然字段在一张表,但代码中配置可以分离

@cloudAndMonkey
Copy link
Contributor Author

这个不方便用注解实现,直接用一个 Map 存假删除配置就行,虽然字段在一张表,但代码中配置可以分离

哈哈,已经弄好了
image

@TommyLemon
Copy link
Collaborator

TommyLemon commented Jan 5, 2023

@cloudAndMonkey "@combine": "a" 强制指定 "a": "" 为条件, 带功能符号的就直接作为条件,可以不用 @combine #277
@TommyLemon
嗯嗯, 你以前跟我说过 ,带功能符号的就直接作为条件,可以不用 @combine

{ "User_address": { "user_id": "3123f016-a4cc-455c-aac5-264c1230dcb", "count+": 1, "@combine": "user_id" }, "tag": "User_address", "@Explain": true }

"msg": "User_address:{ @combine:'user_id' } 中字符 'user_id' 对应的条件键值对 user_id:value 不存在!"

这个和apijson解析顺序有关, 如果要实现"h@combine": "a" 强制指定 "a": "" 为条件,需要调整解析顺序,还要考虑是否有其他影响?

应该是解析到 @combine 时是从 Map<String, Object> where 中取值,但 PUT user_id 是放在 Map<String, Object> content 中,
应该要提前处理 @combine,或者 where 中取不到再从 content 中取。

有两个 getWhereString 方法都需要多传一个参数 content,然后有个再传给 parseCombineExpression
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2677-L2679
image

https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2688-L2714
image

https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2798
image

@cloudAndMonkey
Copy link
Contributor Author

@TommyLemon
是的,那我来调整一下

@cloudAndMonkey
Copy link
Contributor Author

@TommyLemon
假删除 功能已经开发完,我再测一下
delete 扩展 update set 字段,比如deletedTime
我已经搞好了, 业务侧按照 table 去控制即可
image
@OverRide
public void onFakeDelete(Map<String, Object> map) {
map.put("deletedTime", DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN));
}

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Jan 5, 2023

@cloudAndMonkey "@combine": "a" 强制指定 "a": "" 为条件, 带功能符号的就直接作为条件,可以不用 @combine #277
@TommyLemon
嗯嗯, 你以前跟我说过 ,带功能符号的就直接作为条件,可以不用 @combine

{ "User_address": { "user_id": "3123f016-a4cc-455c-aac5-264c1230dcb", "count+": 1, "@combine": "user_id" }, "tag": "User_address", "@Explain": true }
"msg": "User_address:{ @combine:'user_id' } 中字符 'user_id' 对应的条件键值对 user_id:value 不存在!"
这个和apijson解析顺序有关, 如果要实现"h@combine": "a" 强制指定 "a": "" 为条件,需要调整解析顺序,还要考虑是否有其他影响?

应该是解析到 @combine 时是从 Map<String, Object> where 中取值,但 PUT user_id 是放在 Map<String, Object> content 中, 应该要提前处理 @combine,或者 where 中取不到再从 content 中取。

需要多传一个参数 content https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2688-L2714 image
@TommyLemon
应该要提前处理 @combine,或者 where 中取不到再从 content 中取。
json数据只能放到 content、where其中之一
我先看看代码逻辑

@TommyLemon
Copy link
Collaborator

TommyLemon commented Jan 5, 2023

条件键值对都放在 wehre,PUT(UPDATE) 赋值键值对都放在 content,POST(INSERT) 赋值键值对都放在 values

@TommyLemon
Copy link
Collaborator

TommyLemon commented Jan 5, 2023

@cloudAndMonkey "@combine": "a" 强制指定 "a": "" 为条件, 带功能符号的就直接作为条件,可以不用 @combine #277
@TommyLemon
嗯嗯, 你以前跟我说过 ,带功能符号的就直接作为条件,可以不用 @combine

{ "User_address": { "user_id": "3123f016-a4cc-455c-aac5-264c1230dcb", "count+": 1, "@combine": "user_id" }, "tag": "User_address", "@Explain": true }
"msg": "User_address:{ @combine:'user_id' } 中字符 'user_id' 对应的条件键值对 user_id:value 不存在!"
这个和apijson解析顺序有关, 如果要实现"h@combine": "a" 强制指定 "a": "" 为条件,需要调整解析顺序,还要考虑是否有其他影响?

应该是解析到 @combine 时是从 Map<String, Object> where 中取值,但 PUT user_id 是放在 Map<String, Object> content 中, 应该要提前处理 @combine,或者 where 中取不到再从 content 中取。

有两个 getWhereString 方法都需要多传一个参数 content,然后有个再传给 parseCombineExpression https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2677-L2679 image

https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2688-L2714 image

https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2798 image

应该只有 "@combine":"a | (b & c)" 这种逻辑表达式才会出现以上 bug,只需要改 parseCombineExpression 相关的。

因为 "@combine":"a,b,&c,!d" 这种简单组合方式已经提前处理过了:

https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L4951-L4956
image

https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L5013-L5050
image

https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L5072-L5085
image

解析表达式比较复杂,所以这里就没有提前处理了,还是简单的加个 content 参数再加上
if (value == null) {
value = content.get(key)
}
来解决 bug 更简单方便

@TommyLemon
Copy link
Collaborator

加了个用户业务侧自己使用 Redis 缓存的 Demo
APIJSON/APIJSON-Demo@060a10e

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Jan 5, 2023

@TommyLemon
哈哈,很早以前我加过,差点蒙圈😁
redis好像还有一个问题
更新数据库Access、Request表字段,重启没法自动更新redis。需要调用增量初始化接口

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Jan 5, 2023

@cloudAndMonkey "@combine": "a" 强制指定 "a": "" 为条件, 带功能符号的就直接作为条件,可以不用 @combine #277
@TommyLemon
嗯嗯, 你以前跟我说过 ,带功能符号的就直接作为条件,可以不用 @combine

{ "User_address": { "user_id": "3123f016-a4cc-455c-aac5-264c1230dcb", "count+": 1, "@combine": "user_id" }, "tag": "User_address", "@Explain": true }
"msg": "User_address:{ @combine:'user_id' } 中字符 'user_id' 对应的条件键值对 user_id:value 不存在!"
这个和apijson解析顺序有关, 如果要实现"h@combine": "a" 强制指定 "a": "" 为条件,需要调整解析顺序,还要考虑是否有其他影响?

应该是解析到 @combine 时是从 Map<String, Object> where 中取值,但 PUT user_id 是放在 Map<String, Object> content 中, 应该要提前处理 @combine,或者 where 中取不到再从 content 中取。
有两个 getWhereString 方法都需要多传一个参数 content,然后有个再传给 parseCombineExpression https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2677-L2679 image
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2688-L2714 image
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2798 image

应该只有 "@combine":"a | (b & c)" 这种逻辑表达式才会出现以上 bug,只需要改 parseCombineExpression 相关的。

因为 "@combine":"a,b,&c,!d" 这种简单组合方式已经提前处理过了:

https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L4951-L4956 image

https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L5013-L5050 image

https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L5072-L5085 image

解析表达式比较复杂,所以这里就没有提前处理了,还是简单的加个 content 参数再加上 if (value == null) { value = content.get(key) } 来解决 bug 更简单方便

@TommyLemon
兼容 PUT @combine
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L5073
image

这里需要将key 和 combineExpr 表达式进行比较,或者 将combineExpr表达式进行解析获取字段名,然后进行比较?
{
"User_address": {
"user_id!": "3123f016-a4cc-455c-aac5-264c1230dcb",
"count": "10",
"count+": 1,
"@combine": "user_id! | count"
},
"tag": "User_address",
"@Explain": true
}
UPDATE housekeeping.User_address SET count = count + 1, addr = 'null_1672908535358' WHERE (deleted != '1') AND ( ( user_id != '3123f016-a4cc-455c-aac5-264c1230dcb' ) OR ( count = '10' ) )

@TommyLemon
Copy link
Collaborator

TommyLemon commented Jan 5, 2023

@TommyLemon 哈哈,很早以前我加过,差点蒙圈😁 redis好像还有一个问题 更新数据库Access、Request表字段,重启没法自动更新redis。需要调用增量初始化接口

可以在启动后、init 前 REDIS_TEMPLATE.discard(); 清空缓存,但更好的方式是不缓存 APIJSON 配置表,毕竟数据量非常有限,而且很少更新(尤其是相当于业务表,更新频率低很多)。
APIJSON/APIJSON-Demo@3c1a542

@TommyLemon
Copy link
Collaborator

TommyLemon commented Jan 5, 2023

@cloudAndMonkey "@combine": "a" 强制指定 "a": "" 为条件, 带功能符号的就直接作为条件,可以不用 @combine #277
@TommyLemon
嗯嗯, 你以前跟我说过 ,带功能符号的就直接作为条件,可以不用 @combine

{ "User_address": { "user_id": "3123f016-a4cc-455c-aac5-264c1230dcb", "count+": 1, "@combine": "user_id" }, "tag": "User_address", "@Explain": true }
"msg": "User_address:{ @combine:'user_id' } 中字符 'user_id' 对应的条件键值对 user_id:value 不存在!"
这个和apijson解析顺序有关, 如果要实现"h@combine": "a" 强制指定 "a": "" 为条件,需要调整解析顺序,还要考虑是否有其他影响?

应该是解析到 @combine 时是从 Map<String, Object> where 中取值,但 PUT user_id 是放在 Map<String, Object> content 中, 应该要提前处理 @combine,或者 where 中取不到再从 content 中取。
有两个 getWhereString 方法都需要多传一个参数 content,然后有个再传给 parseCombineExpression https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2677-L2679 image
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2688-L2714 image
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2798 image

应该只有 "@combine":"a | (b & c)" 这种逻辑表达式才会出现以上 bug,只需要改 parseCombineExpression 相关的。
因为 "@combine":"a,b,&c,!d" 这种简单组合方式已经提前处理过了:
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L4951-L4956 image
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L5013-L5050 image
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L5072-L5085 image
解析表达式比较复杂,所以这里就没有提前处理了,还是简单的加个 content 参数再加上 if (value == null) { value = content.get(key) } 来解决 bug 更简单方便

@TommyLemon 兼容 PUT @combine https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L5073 image

这里需要将key 和 combineExpr 表达式进行比较,或者 将combineExpr表达式进行解析获取字段名,然后进行比较? { "User_address": { "user_id!": "3123f016-a4cc-455c-aac5-264c1230dcb", "count": "10", "count+": 1, "@combine": "user_id! | count" }, "tag": "User_address", "@Explain": true } UPDATE housekeeping.User_address SET count = count + 1, addr = 'null_1672908535358' WHERE (deleted != '1') AND ( ( user_id != '3123f016-a4cc-455c-aac5-264c1230dcb' ) OR ( count = '10' ) )

直接 combineExpr.contains(key) 会有误判,例如 "admin_user_id | name".contains("user_id"),
image

可以按这个逻辑来判断,key 左侧、右侧可能的字符不能和它拼接成一个有效的键名
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L4992-L5002
image

@cloudAndMonkey
Copy link
Contributor Author

@cloudAndMonkey "@combine": "a" 强制指定 "a": "" 为条件, 带功能符号的就直接作为条件,可以不用 @combine #277
@TommyLemon
嗯嗯, 你以前跟我说过 ,带功能符号的就直接作为条件,可以不用 @combine

{ "User_address": { "user_id": "3123f016-a4cc-455c-aac5-264c1230dcb", "count+": 1, "@combine": "user_id" }, "tag": "User_address", "@Explain": true }
"msg": "User_address:{ @combine:'user_id' } 中字符 'user_id' 对应的条件键值对 user_id:value 不存在!"
这个和apijson解析顺序有关, 如果要实现"h@combine": "a" 强制指定 "a": "" 为条件,需要调整解析顺序,还要考虑是否有其他影响?

应该是解析到 @combine 时是从 Map<String, Object> where 中取值,但 PUT user_id 是放在 Map<String, Object> content 中, 应该要提前处理 @combine,或者 where 中取不到再从 content 中取。
有两个 getWhereString 方法都需要多传一个参数 content,然后有个再传给 parseCombineExpression https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2677-L2679 image
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2688-L2714 image
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2798 image

应该只有 "@combine":"a | (b & c)" 这种逻辑表达式才会出现以上 bug,只需要改 parseCombineExpression 相关的。
因为 "@combine":"a,b,&c,!d" 这种简单组合方式已经提前处理过了:
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L4951-L4956 image
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L5013-L5050 image
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L5072-L5085 image
解析表达式比较复杂,所以这里就没有提前处理了,还是简单的加个 content 参数再加上 if (value == null) { value = content.get(key) } 来解决 bug 更简单方便

@TommyLemon 兼容 PUT @combine https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L5073 image
这里需要将key 和 combineExpr 表达式进行比较,或者 将combineExpr表达式进行解析获取字段名,然后进行比较? { "User_address": { "user_id!": "3123f016-a4cc-455c-aac5-264c1230dcb", "count": "10", "count+": 1, "@combine": "user_id! | count" }, "tag": "User_address", "@Explain": true } UPDATE housekeeping.User_address SET count = count + 1, addr = 'null_1672908535358' WHERE (deleted != '1') AND ( ( user_id != '3123f016-a4cc-455c-aac5-264c1230dcb' ) OR ( count = '10' ) )

直接 combineExpr.contains(key) 会有误判,例如 "admin_user_id | name".contains("user_id"), image

可以按这个逻辑来判断,key 左侧、右侧可能的字符不能和它拼接成一个有效的键名 https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L4992-L5002 image

收到,我改一下

@cloudAndMonkey
Copy link
Contributor Author

@TommyLemon
private static boolean keyInCombineExpr(String combineExpr, String key) {
// while 解决 key = "count" ,combineExpr = "ab & (user_id! | count! | count )" 的场景
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;
}

我把这个地方改一下,调用一个方法哈
https://github.com/Tencent/APIJSON/blob/master/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L4992-L5002

@cloudAndMonkey
Copy link
Contributor Author

搞完了, 累死了
明天来提交代码
redis(api太多了)、redisql (调整了,还没复测),测完我提交

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Jan 6, 2023

赞,这样的话可以把 RequestMethod method, String tag, int version, @NotNull JSONObject request, HttpSession session 等参数作为全局参数传进去供脚本使用
@TommyLemon
脚本支持传递全局对象参数, 也可以自定义java类,供脚本调用, 这块你改一下哈

@TommyLemon
Copy link
Collaborator

可以的

@cloudAndMonkey
Copy link
Contributor Author

cloudAndMonkey commented Jan 6, 2023

可以的
@TommyLemon
纠结了一下,哈哈
等我忙完,我来加吧,最近整理了资料,我搞也要不了多久
把自定义类传参也加上去,抽象一个方法,业务侧通过脚本名去控制

@TommyLemon
Copy link
Collaborator

哈哈,感谢~

@TommyLemon TommyLemon added Enhancement 增强 增强功能、提高性能等 Ecosystem 周边生态 完善生态(Go语言版、更多Demo、周边工具等) labels Feb 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Ecosystem 周边生态 完善生态(Go语言版、更多Demo、周边工具等) Enhancement 增强 增强功能、提高性能等
Projects
None yet
Development

No branches or pull requests

2 participants