node-postgres: параметризованный запрос на вставку кэшируется, сбой при втором запуске

Я пытаюсь запустить два параметризованных запроса на вставку, используя node-postgres: первый указывает основной ключевой столбец, второй - нет.

Второй запрос, даже если не указывает столбец первичного ключа, не может сказать, что существует дублированный первичный ключ.

Моя таблица pg:

CREATE TABLE teams (
  id serial PRIMARY KEY,
  created_by int REFERENCES users,
  name text,
  logo text
);

Код, воспроизводящий эту проблему:

var pg = require('pg');

var insertWithId = 'INSERT INTO teams(id, name, created_by) VALUES($1, $2, $3) RETURNING id';
var insertWithoutId = 'INSERT INTO teams(name, created_by) VALUES($1, $2) RETURNING id';

pg.connect(process.env.POSTGRES_URI, function (err, client, releaseClient) {
  client.query(insertWithId, [1, 'First Team', 1], function (err, result) {
    releaseClient();

    if (err) {
      throw err;
    }

    console.log('first team created');
  });
});

pg.connect(process.env.POSTGRES_URI, function (err, client, releaseClient) {
  client.query(insertWithoutId, ['Second Team', 1], function (err, result) {
    releaseClient();

    if (err) {
      console.log(err);
    }
  });
});

И вывод запуска этого:

first team created

{ [error: duplicate key value violates unique constraint "teams_pkey"]
  name: 'error',
  length: 173,
  severity: 'ERROR',
  code: '23505',
  detail: 'Key (id)=(1) already exists.',
  hint: undefined,
  position: undefined,
  internalPosition: undefined,
  internalQuery: undefined,
  where: undefined,
  schema: 'public',
  table: 'teams',
  column: undefined,
  dataType: undefined,
  constraint: 'teams_pkey',
  file: 'nbtinsert.c',
  line: '406',
  routine: '_bt_check_unique' }

Как я понял из node-postgres источника, параметризованные запросы обрабатываются как подготовленные запросы, которые кэшируются, если они повторно используют параметр name; хотя, покопавшись в источнике, мне кажется, мне не кажется, что у моих запросов есть свойство name.

Есть ли у кого-нибудь идеи, как этого можно избежать?


person Andrei Serdeliuc ॐ    schedule 18.07.2015    source источник
comment
Первая вставка предоставляет значение для id, поэтому серийный номер не увеличивается. Серийный номер по-прежнему 1. Вторая вставка не предоставляет значение для id, поэтому используется серийный номер (= 1). Это дубликат. Лучшее решение - использовать только второй оператор и позволить приложению использовать возвращенный id, если необходимо.   -  person wildplasser    schedule 18.07.2015
comment
ну, я не думал об этом, после небольшого поиска в Google, похоже, что это действительно проблема ... Превратите свой комментарий в ответ, и я приму это :)   -  person Andrei Serdeliuc ॐ    schedule 18.07.2015


Ответы (1)


Первая вставка предоставляет значение для id, поэтому серийный номер не увеличивается. Серийный номер по-прежнему равен 1 после первой вставки. Вторая вставка не предоставляет значение для id, поэтому используется серийный номер (= 1). Это дубликат. Лучшее решение - только использовать второй оператор и позволить приложению использовать возвращенный идентификатор, если это необходимо.

Короче: не мешайте сериалам.


Если вам нужно исправить следующее значение последовательности, вы можете использовать что-то вроде инструкции ниже.

SELECT setval('teams_id_seq', (SELECT MAX(id) FROM teams) )
        ;
person wildplasser    schedule 18.07.2015