Open sangyuan6122 opened 11 months ago
@i will solve it@
多个PR中修复该问题, 但是我看了之后认为这是oracle插件的问题,需要在oracle插件中修复。
configHistoryInfo是数据库查出来的内容,tenant为null说明存储的namespace就是null, 如果是数据源插件的特殊处理, 应该在插件中修复。
PR我都先关闭, 现在issue中讨论清楚
多个PR中修复该问题, 但是我看了之后认为这是oracle插件的问题,需要在oracle插件中修复。
configHistoryInfo是数据库查出来的内容,tenant为null说明存储的namespace就是null, 如果是数据源插件的特殊处理, 应该在插件中修复。
现有的代码HistoryController中的getConfigHistoryInfo方法已经把输入为null的tenant修正为空字符串(个人理解),如下:
@GetMapping
@Secured(action = ActionTypes.READ, signType = SignType.CONFIG)
public ConfigHistoryInfo getConfigHistoryInfo(@RequestParam("dataId") String dataId,
@RequestParam("group") String group,
@RequestParam(value = "tenant", required = false, defaultValue = StringUtils.EMPTY) String tenant,
@RequestParam("nid") Long nid) throws AccessException {
return historyService.getConfigHistoryInfo(dataId, group, tenant, nid);
}
多数据源插件的功能只能提供对应数据库的sql语句,并不能去修改Sql查出来的结果,而通过Sql语句在Oracle中查出来的只能是null,没有空字符串的概念。例如:select '' "A",null "B" from dual 这里属性A、B查出来都是null,这样情况插件中无法修复吧,怎么解决当前问题呢?
api接口处的定义是nacos的openapi定义, null和''可以做等义。
但是configHistoryInfo是数据库查询的结果,既数据库的存储内容, 做了null=‘’的转译,会影响其他数据库的判断条件,因为其他数据库这两者不等价(只有Oracle等价),所以不能再PR那里中做处理, 需要让Oracle插件来做处理。
换句话说, 从nacos的视角里, 这个值传给数据库不可能为null, 数据库存储的值也必定不为null, 既然是Oracle自己做的特殊处理,不管出于什么原因, Oracle需要把数据按照原样返还给nacos层面,这样才能够接耦清楚。
所以这个数据必须要感知Oracle的情况,才能做null-》‘’的等价转换,对nacos的处理过程中来看, 这个值输入时是‘’, 查询出来也应该是''
换句话说, 从nacos的视角里, 这个值传给数据库不可能为null, 数据库存储的值也必定不为null, 既然是Oracle自己做的特殊处理,不管出于什么原因, Oracle需要把数据按照原样返还给nacos层面,这样才能够接耦清楚。
所以这个数据必须要感知Oracle的情况,才能做null-》‘’的等价转换,对nacos的处理过程中来看, 这个值输入时是‘’, 查询出来也应该是''
所以需要在Oracle插件层面做适配。
传给数据库的值不可能为null这点没问题,但是Oracle存长度为0的字符串确实是null,这也是事实。当前从插件层面去解决确实最优,实际情况插件层面我们只能去修改对应的sql语句,无法对语句的结果进行修正。 configHistoryInfo做null=''的转义,应该是目前代价最小的方式,nacos存的时候已经明确无论是null还是''存的都是'',这里已经做了转义。而如果数据库查出来是''自然没问题,说明数据库也支持'',否则可能对接的数据库不支持长度为0的字符串,仅支持null,这里去做个容错是否可以呢 讨论这些还是希望能找一个解决方案,如果是插件层面解决具体怎么做呢?我们这边的客户用的都是Oracle,所以希望能用多数据源去做适配,能否加钉钉:sangyuan6122 详细聊下呢,拜谢!
如果是做单独一个工程项目, 以代价最小的方式来实现没有问题, 但是这不是单个工程,而是针对所有数据库的场景, 单纯针对Oracle在通用核心处做特殊适配是不合理的, 主要是这个适配改变了数据库语义,这是不可行的。
既然是Oracle导致的问题,就应该去修复Oracle或者是Oracle的适配层,也即Oracle的插件层, 方法我并不清楚,因为Oracle的插件是由社区自行贡献的。
比如是否可以改下SQL,让Oracle返回的时候如果是null的话转换成''呢?
若假如我再多一种数据源呢,是不是又得回来改这个方法。应该是Oracle插件里找到对应的sql,做修改比较合适,在插件层面做适配。
如果能在多数据源插件层面做适配这个issue肯定就不提了,无论对sql语句进行怎样的处理,都不行,建议大佬们亲测下 例如:select nvl(tenant_id,'') 、select to_char(nvl(tenant_id,''))、select nvl(tenant_id,CHR(0))
这肯定是能做适配的,如果不能适配就讨论通用的方法, 比如插件是否再开放一个resultHandler之类的东西,让插件来做这种结果转化。
但是肯定不能在core里去做这种改变语义的内容。
插件中尝试了各种方法肯定是不能适配,或者给一个能适配的方法,主要是解决这个问题
我认为可以基于PaginationHelper ,根据数据源 扩展出一个Oracle的实现类,并重写sql。在对应业务代码里,使用该实现类。
BUG描述 使用多数据源插件扩展Oracle数据库支持后,public空间下的配置历史版本点击详情报错"Please check dataId, group or namespaceId.",其余命名空间下对应功能正常。 初步分析: 当使用默认命名空间public时,前端 tenant参数会给默认值空字符串,而对应的oracle库中tenant只能查出null,两者在代码中进行了相等判断,这里肯定不等,所以报错。 1)HistoryController类中getConfigHistoryInfo方法请求参数中tenant默认(public)为空字符串而则非null(很多处入参都如此操作); 2)Oralce数据库对空字符串和null没有区别查询出来的字段值都是null; 3)在HistoryService类中getConfigHistoryInfo调用了checkHistoryInfoPermission方法,此方法需入参tenant需等于数据库查出来的对应数据的tenant值,而Oracle库中查出来的是null和空字符串不相等,所以方法报错; 建议: 1)checkHistoryInfoPermission中对数据库中查询出tenant进行修正,如修改为:
Desktop (please complete the following information):