Node.js中使用SERIAL的外键冲突

时间:2017-06-22 07:25:14

标签: node.js sequelize.js cockroachdb

在关注cockroachdb example使用sequelize orm for node.js构建应用程序的同时,我对其进行了扩展,以添加模型之间的关联。主键是INT,通过unique_rowid()自动递增。根据您的文档,这是您SERIAL的实现。

在同步我的模型后,我尝试使用以下代码创建记录:

models.sequelize.sync({ force: true })
  .then(function () {
    return models.Customer.create({
      name: "Sample Customer"
    })
  })
  .then(function (result) {
    const id = parseInt(result.dataValues.id, 10)
    return models.Order.bulkCreate([
      { subtotal: 100.00, customer_id: id },
      { subtotal: 200.00, customer_id: id }
    ])
  })

运行此功能后,我会得到" error: foreign key violation: value [255737842446434300] not found in customers@primary [id]"

我意识到我的parseInt似乎没有必要的精确度来获取客户创建时返回的字符串ID,但我不知道如何实现这一点。

1 个答案:

答案 0 :(得分:2)

2017年7月6日更新。

最新版本的sequelize-cockroachdb,v1.0.2,教会Sequelize将数字上下文中使用的字符串强制转换为CockroachDB整数。只是不要在parseInt上致电result.dataValues.id,它应该按预期工作!

models.sequelize.sync({ force: true })
  .then(function () {
    return models.Customer.create({
      name: "Sample Customer"
    })
  })
  .then(function (result) {
    return models.Order.bulkCreate([
      { subtotal: 100.00, customer_id: result.dataValues.id },
      { subtotal: 200.00, customer_id: result.dataValues.id }
    ])
  })

正如您所发现的那样,问题是由unique_rowid()生成的ID(如255737842446434300)太大而无法放入JavaScript Number,而CockroachDB side只能精确表示最多2个 53 - 1.这个问题的通常解决办法是 改为使用字符串。也就是说,您可以简单地忽略对parseInt的调用并将{ ..., customer_id: "255737842446434300"}直接传递给Order.bulkCreate

不幸的是,Sequelize会生成一个如下所示的SQL语句:

INSERT INTO orders (customer_id) VALUES ('255737842446434300');

PostgreSQL会很乐意将该字符串文字转换为int8,但CockroachDB会抱怨使用字符串文字,其中需要int8。我已打开PR以在Sequelize adapter sideenter image description here上修复此问题,但尚未登陆。我们几乎肯定会有v1.1的解决方案,但是!

与此同时 - 特别是如果您想要一个与CockroachDB v1.0兼容的解决方案 - 您可以通过使用Sequelize.BLOB类型的UUID主键来解决此问题。