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

Sqlite: bulkCreate with updateOnDuplicate fails when the model contains a composite key. #11534

Closed
2 of 7 tasks
jpvanoosten opened this issue Oct 10, 2019 · 2 comments
Closed
2 of 7 tasks
Labels
dialect: sqlite For issues and PRs. Things that involve SQLite (and do not involve all dialects). status: understood For issues. Applied when the issue is understood / reproducible. type: bug

Comments

@jpvanoosten
Copy link

jpvanoosten commented Oct 10, 2019

Related issue: #11432

Issue Description

The bulkCreate fails if the model contains a composite key and doesn't explicitly define a primary key.

The upsertKeys array is emptied when the model contains a composite key since the length of the fields array of the compositeKey object will be of size > 1 (which causes this filter to skip it):

options.upsertKeys = _.chain(model.uniqueKeys).values().filter(c => c.fields.length === 1).map('column').value();

My model looks like this:

"use strict";
module.exports = (sequelize, DataTypes) => {
  const User = sequelize.define(
    "User",
    {
      username: { type: DataTypes.STRING, unique: "compositeKey" },
      discordId: { type: DataTypes.STRING, unique: "compositeKey" }
    },
    {}
  );
  User.associate = function(models) {
    // associations can be defined here
  };
  return User;
};

In this case, the model.uniqueKeys object only contains a single compositeKey object.
Shouldn't the model.uniqueKeys object also contain the automatically generated id primary key for this model?

Changing the model to this works:

"use strict";
module.exports = (sequelize, DataTypes) => {
  const User = sequelize.define(
    "User",
    {
      username: { type: DataTypes.STRING, unique: true },
      discordId: { type: DataTypes.STRING, unique: true }
    },
    {}
  );
  User.associate = function(models) {
    // associations can be defined here
  };
  return User;
};

What are you doing?

Upserting users for testing:

models.sequelize
  .sync()
  .then(async () => {
    if (process.env.UPSERT_TEST_USERS === "true") {
      const numTestUsers = parseInt(process.env.NUM_TEST_USERS || 50);
      const testUsers = new Array(numTestUsers).fill(null).map((user, i) => ({
        id: i,
        username: `Test${i}`,
        discordId: `discordId${i}`
      }));

      await models.User.bulkCreate(testUsers, {
        updateOnDuplicate: ["username", "discordId"]
      });
    }
  })
  .then(() => {
    debug("Database synchronization succeeded.");

    /**
     * Listen on provided port, on all network interfaces.
     */
    server.listen(port);
    server.on("error", onError);
    server.on("listening", onListening);
  })
  .catch(err => {
    debug(`Database synchronization failed: ${err}`);
  });

What do you expect to happen?

I expect the bulkCreate method to succeed and upsert the test users to the database.

What is actually happening?

Doing this with this model results in the following error:

SequelizeDatabaseError: SQLITE_ERROR: near ")": syntax error

The error is referring to the ON CONFLICT() since it is an error to have an empty ON CONFLICT clause. This should be:

ON CONFLICT('username', 'discordId')

Additional context

Add any other context or screenshots about the feature request here.

Environment

  • Sequelize version: 5.19.3
  • Node.js version: v10.16.3
  • Operating System: Windows 10
  • If TypeScript related: TypeScript version: N/A

Issue Template Checklist

How does this problem relate to dialects?

  • I think this problem happens regardless of the dialect.
  • I think this problem happens only for the following dialect(s): Postgres, Sqlite
  • I don't know, I was using PUT-YOUR-DIALECT-HERE, with connector library version XXX and database version XXX

Would you be willing to resolve this issue by submitting a Pull Request?

  • Yes, I have the time and I know how to start.
  • Yes, I have the time but I don't know how to start, I would need guidance.
  • No, I don't have the time, although I believe I could do it if I had the time...
  • No, I don't have the time and I wouldn't even know how to start.
@papb papb added dialect: sqlite For issues and PRs. Things that involve SQLite (and do not involve all dialects). status: understood For issues. Applied when the issue is understood / reproducible. type: bug labels Oct 23, 2019
@papb
Copy link
Member

papb commented Oct 23, 2019

Hello, thanks for the report!

Yes, I have the time but I don't know how to start, I would need guidance.

Great! What kind of guidance do you want?

fnimick added a commit to fnimick/sequelize that referenced this issue Oct 25, 2019
…eateOptions`

This allows the use of a unique index for a `bulkCreate` with
`updateOnDuplicate` set, in postgres. The unique index may be
a partial index.

Closes sequelize#11534, sequelize#11569
fnimick added a commit to fnimick/sequelize that referenced this issue Oct 25, 2019
…eateOptions`

This allows the use of a unique index for a `bulkCreate` with
`updateOnDuplicate` set, in postgres. The unique index may be
a partial index.

Closes sequelize#11534, sequelize#11569
fnimick added a commit to fnimick/sequelize that referenced this issue Jan 8, 2020
…eateOptions`

This allows the use of a unique index for a `bulkCreate` with
`updateOnDuplicate` set, in postgres. The unique index may be
a partial index.

Closes sequelize#11534, sequelize#11569
@sushantdhiman
Copy link
Contributor

Fixed with #11984

fnimick added a commit to fnimick/sequelize that referenced this issue Jun 9, 2020
Adds options `upsertKeys` and `upsertIndex`.

This allows the use of a unique index for a `bulkCreate` with
`updateOnDuplicate` set, in postgres. The unique index may be
a partial index.

Closes sequelize#11534, sequelize#11569
fnimick added a commit to fnimick/sequelize that referenced this issue Jun 9, 2020
Adds options `upsertKeys` and `upsertIndex`.

This allows the use of a unique index for a `bulkCreate` with
`updateOnDuplicate` set, in postgres. The unique index may be
a partial index.

Closes sequelize#11534, sequelize#11569
fnimick added a commit to fnimick/sequelize that referenced this issue Jun 9, 2020
Adds options `upsertKeys` and `upsertIndex`.

This allows the use of a unique index for a `bulkCreate` with
`updateOnDuplicate` set, in postgres. The unique index may be
a partial index.

Closes sequelize#11534, sequelize#11569
fnimick added a commit to fnimick/sequelize that referenced this issue Jun 9, 2020
Adds options `upsertKeys` and `upsertIndex`. These options work with
sqlite as well as postgres.

This allows the use of a unique index for a `bulkCreate` with
`updateOnDuplicate` set. The unique index may be
a partial index.

Closes sequelize#11534, sequelize#11569
PitchLabsAsh pushed a commit to PitchLabs/sequelize that referenced this issue Jul 8, 2020
Adds options `upsertKeys` and `upsertIndex`. These options work with
sqlite as well as postgres.

This allows the use of a unique index for a `bulkCreate` with
`updateOnDuplicate` set. The unique index may be
a partial index.

Closes sequelize#11534, sequelize#11569
PitchLabsAsh pushed a commit to PitchLabs/sequelize that referenced this issue Oct 10, 2020
Adds options `upsertKeys` and `upsertIndex`. These options work with
sqlite as well as postgres.

This allows the use of a unique index for a `bulkCreate` with
`updateOnDuplicate` set. The unique index may be
a partial index.

Closes sequelize#11534, sequelize#11569
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dialect: sqlite For issues and PRs. Things that involve SQLite (and do not involve all dialects). status: understood For issues. Applied when the issue is understood / reproducible. type: bug
Projects
None yet
3 participants