简体   繁体   中英

Foreign key violations with SERIAL in Node.js

While following the cockroachdb example for building an app using the sequelize orm for node.js, I expanded upon it to add associations between my models. Primary keys are INT with auto-increment via unique_rowid(). Based on your documentation, this is your implementation of SERIAL .

After synching my models, I attempt to create records using the following code:

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 }
    ])
  })

When this is run, I get " error: foreign key violation: value [255737842446434300] not found in customers@primary [id] "

I realize my parseInt doesn't appear to have the precision required in order to take the string id returned from the customer creation, but I don't know how to accomplish this.

Update, 6 July 2017.

The latest version of sequelize-cockroachdb , v1.0.2, teaches Sequelize to coerce strings used in numeric contexts into CockroachDB integers. Simply don't call parseInt on result.dataValues.id and it should work as you expect!

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 }
    ])
  })

The problem, as you've discovered, is that IDs generated by unique_rowid() , like 255737842446434300, are too large to fit in a JavaScript Number , which can only exactly represent integers up to 2 53 - 1. The usual solution to this problem is to use strings instead. That is, you could simply elide the call to parseInt and pass { ..., customer_id: "255737842446434300"} directly to Order.bulkCreate .

Unfortunately, Sequelize will then generate a SQL statement that looks like this:

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

PostgreSQL will happily convert that string literal into an int8 , but CockroachDB will complain about using a string literal where an int8 is expected. I have open PRs to fix this on either the CockroachDB side or the Sequelize adapter side , but neither has landed yet. We'll almost certainly have a solution for v1.1, however!


In the meantime—particularly if you want a solution compatible with CockroachDB v1.0—you can work around the issue by using UUID primary keys with the Sequelize.BLOB type.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM