对同一段orm数据库代码,发布市场,ubuntu安装后执行出问题(bug?求助?)

在同样的yarn 环境下
ubuntu用全新的yarn create koishi实例会复现这个问题(多数据表),而在我的win服务器却是正常运行(一个数据表)

ubuntu在运行的时候,每次运行cck都会显示[首次游玩],并产生后续错误。

(因为本应该覆盖数据行,结果加了新的数据行,程序检测到原本(第一行)的[首次游玩],并导致后续错误)


多次执行会创建很多重复的数据行,从图中可以看到,platform和guildId都是一样的,理论上应该不会出现这种情况。

代码大概是这样


const rows = [{
        platform: platform,
        guildId: guildId,
        ...
      }];

await ctx.database.upsert('cck_set', rows, ['platform', 'guildId']);

当然我也不确定是不是单纯是这段代码的问题,全部代码:
改成tsx)上面的代码位于515行

求助一下,想问是我编写问题还是数据库bug

1 个赞

很巧,我在之前开发自己的第一个插件—— verify 插件的时候,也遇到了 upsert 反而添加了新行的问题,在咨询过关门歇业以后,在 autoInc: true 后添加了 unique 这个属性,从而解决了问题。

对应应该在 L107。

所以修改成这样大概就可以解决问题了吧:

   }, {
     // 使用自增的主键值
     autoInc: true,
+    unique: [['platform', 'guildId']],
   })

我到现在也仍然觉得很奇怪,upsert() 方法的文档里明明说的是「使用 upsert 修改数据」,为什么最后却添加了新行呢?我认为实现和文档至少有一方是有问题的,@关门歇业 请一定要看一下!

1 个赞

这是符合预期的

首先,你遇到问题的本质,是由于你数据中 guildId为空
我不清楚是否对每个driver都有相同的行为,但在我所知的范围内,你get出的数据库内的guildId会是null
而此时你的session.guildId是undefined
二者不相等,所以upsert创建了一条新数据

解决方案的话,可以就像楼上所说的,当然我会习惯更强的把他们作成composite primary key

另外upsert一般用于修改对于常规的数据库是没有问题的,不过由于koishi并没有其他的batch operation,所以也必须依赖upsert来做batchInsert,行为上应该没有问题,文档可能可以再明确一些?

1 个赞

感谢解答

1 个赞

谢谢,我才发现
修改了unique: [[‘qq’, ‘group’]],会变成 #
而开发环境原来是什么样子我也不清楚了
还是感谢解答

1 个赞