Sequelize upsert генерирует уникальное нарушение для схемы с обнуляемым уникальным столбцом - PullRequest
0 голосов
/ 11 января 2020

Я сталкиваюсь с уникальной проблемой нарушения ограничений при выполнении upsert, потому что запрос UPDATE, созданный sequelize, игнорирует ограничение частичного индекса, определенное моделью (если это не имеет значения). Я новичок в node + sequelize, поэтому я мог упустить что-то очевидное, но я обошел все возможные места для поиска подходящих ответов, включая код sequelize, но я не смог найти ответ, который ищу за. Очень ценю вашу помощь!
Мои текущие версии:

"pg": "7.9.0",
"sequelize": "5.21.3"

У меня есть модель, состоящая из первичного ключа: id и двух других уникальных индексов, один из которых является пустым полем.

module.exports.Entities = sequelize.define('entities', {
    id: {type: Sequelize.UUID, defaultValue: Sequelize.UUIDV4, allowNull: false, primaryKey: true},
    cId: {type: Sequelize.STRING, allowNull: false},
    pId: {type: Sequelize.UUID, allowNull: false},
    eKey: {type: Sequelize.INTEGER, allowNull: true}
}, {
    indexes: [
        {
            name: 'unique_c_id_p_id',
            fields: ['c_id', 'p_id'],
            unique: true
        },
        {
            name: 'unique_e_key',
            fields: ['e_key'],
            unique: true,
            where: {
                eKey: {
                    [Op.not]: null
                }
            }
        }
    ]
})

и сама таблица выглядит следующим образом:

CREATE TABLE public.entities (
  id UUID DEFAULT uuid_generate_v4 (),
  c_id UUID NOT NULL,
  p_id UUID NOT NULL,
  e_key INTEGER DEFAULT NULL,
  CONSTRAINT ENTITY_SERVICE_PKEY PRIMARY KEY (id),
  CONSTRAINT unique_c_id_p_id UNIQUE (c_id, p_id)
);

CREATE UNIQUE INDEX unique_e_key ON public.entities (e_key) WHERE e_key IS NOT NULL;

Вызов метода upsert выглядит следующим образом:
module.exports.upsert = async (Model, values) => Model.upsert(values, {returning: true})

Я пропускаю вышеуказанную Entities модель и приведенное ниже значение в качестве аргументов этой функции.

{ 
  "id"="3169d4e2-8e2d-451e-8be0-40c0b28e2aa9", 
  "c_id"="00000000-0000-0000-0000-000000000000", 
  "p_id"="78bce392-4a15-4a8a-986b-c9398787345f",
  "e_key"= null
}

Issue : SequelizeUniqueConstraintError
Sequelize пытается выполнить вставку с последующим запросом на обновление, когда мы пытаемся обновить существующий запись с использованием метода upsert. Запрос вставки показывает конфликт, так как запись уже существует, и продолжение вызова upsert продолжает вызывать запрос на обновление.

Однако запрос, который он строит в UPDATE, выглядит примерно так:

"SQL statement UPDATE entities SET id='3169d4e2-8e2d-451e-8be0-40c0b28e2aa9',c_id='00000000-0000-0000-0000-000000000000',p_id='78bce392-4a15-4a8a-986b-c9398787345f',e_key=NULL 
WHERE (id = '3169d4e2-8e2d-451e-8be0-40c0b28e2aa9' 
OR e_key IS NULL 
OR (c_id = '00000000-0000-0000-0000-000000000000' AND p_id = '78bce392-4a15-4a8a-986b-c9398787345f')) 
RETURNING id\nPL/pgSQL function pg_temp_5.sequelize_upsert() line 1 at SQL statement"

Теперь я понимаю причину, по которой он генерирует уникальное нарушение ограничения, так как в приведенном выше запросе WHERE предложение секвелирует вызовы OR e_key IS NULL, поскольку e_key = null, и это может потенциально вернуть более 1 записи, и SET пытается обновить одно и то же значение для всех тех записей, которые были возвращены, тем самым нарушая ограничения primaryKey, ограничения уникальности и т. д. c.

Я хотел бы понять, что:

  1. Почему sequelize не исключает уникальное ограничение e_key, основанное на определенном частичном индексе, учитывая, что оно выбирает атрибуты предложения WHERE на основе ограничений, определенных в модели и ее индексах?
  2. Могу ли я что-нибудь сделать, чтобы обойти эту проблему?
  3. Или я пропускаю что-то очевидное, что я могу исправить и попробовать?

Действительно ценю, что вы нашли время, чтобы прочитать и ответить. Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...