Ошибка записи в Postgres

Такая ситуация. После создания таблиц в БД, сидами добавляю нового пользователя (в конфигурации id = 1). Все норм отрабатывает, пользователь записан в БД. Но если я добавляю нового пользователя через приложение, вылетает ошибка "Validation error". Если пытаюсь еще раз - та же ошибка. При третьей попытке аккаунт создается, но уже с id = 3.

Поле id инкрементное. В дебаге "спотыкается" о метод create (sequelize).

Что это может быть, куда смотреть?

DDL ::

CREATE TABLE IF NOT EXISTS public.users
(
    id integer NOT NULL DEFAULT nextval('users_id_seq'::regclass),
    login character varying(255) COLLATE pg_catalog."default" NOT NULL,
    email character varying(255) COLLATE pg_catalog."default" NOT NULL,
    password character varying(255) COLLATE pg_catalog."default" NOT NULL,
    "roleId" integer,
    banned boolean DEFAULT false,
    CONSTRAINT users_pkey PRIMARY KEY (id),
    CONSTRAINT users_email_key UNIQUE (email),
    CONSTRAINT users_login_key UNIQUE (login),
    CONSTRAINT "users_roleId_fkey" FOREIGN KEY ("roleId")
        REFERENCES public.roles (id) MATCH SIMPLE
        ON UPDATE CASCADE
        ON DELETE NO ACTION
)

Ответы (2 шт):

Автор решения: philip_philipch

Основная проблема заключается в "рассинхронизации первичных ключей в Postgres":
"Postgres обрабатывает автоматическое увеличение немного иначе, чем MySQL. В Postgres при создании serial поля вы также создаете поле последовательности, которое отслеживает используемый идентификатор. Это поле последовательности будет начинаться со значения 1.

Если вы вставляете в таблицу новую запись и не указываете поле id, она будет использовать значение последовательности, а затем увеличивать последовательность.

Однако если вы укажете id поле, последовательность не будет использоваться и не будет обновляться".
(взято отсюда: https://stackoverflow.com/questions/37970743/postgresql-unique-violation-7-error-duplicate-key-value-violates-unique-const)

Используя следующий скрипт можно пофиксить данную проблему:

SELECT setval(pg_get_serial_sequence('users', 'id'), max(id)) FROM users;

После этого, последовательность используется в обычном порядке, т.е. инкремент работает как обычно.
(https://stackoverflow.com/questions/244243/how-to-reset-postgres-primary-key-sequence-when-it-falls-out-of-sync)

Вот как реализовал в seed:

async up (queryInterface) {
    await queryInterface.bulkInsert('users', [userdata])

    await queryInterface.sequelize.query(
        `SELECT setval(pg_get_serial_sequence('users', 'id'), max(id)) FROM users;`,
        {type: queryInterface.sequelize.QueryTypes.SELECT}
    );
}

Будет интересно почитать комментарии более лучшего решения

→ Ссылка
Автор решения: philip_philipch

Переделал так:

// utils.js
const updateSequence = async (table, column, { queryInterface, transaction }) => {
    const [[{ max }]] = await queryInterface.sequelize.query(`SELECT MAX(${column}) FROM ${table}`, {
        transaction,
    });

    if (!max) return;

    await queryInterface.sequelize.query(
        `SELECT setval(pg_get_serial_sequence('${table}', '${column}'), max(${column})) FROM ${table};`,
        { transaction }
    );
};

module.exports = { updateSequence };

Seed:

const { updateSequence } = require("../utils");

//...

async up (queryInterface) {
    await queryInterface.bulkInsert('users', [userdata])

    await updateSequence('users', 'id', { queryInterface });
},

updateSequence, в принципе, можно использозвать в миграции, после описания таблицы:

await queryInterface.createTable('users', {
  ...
});

await updateSequence('users', 'id', { queryInterface });
→ Ссылка