Как сделать: последовательный пакет db.batch с pg-обещанием

Я не могу понять, как выполнить пакетный вызов сгенерированных запросов последовательно.

Я пытаюсь обрезать каждую таблицу в БД. Мой код:

db.any(`
  SELECT table_name
  FROM information_schema.tables
  WHERE table_schema='public'
  AND table_type='BASE TABLE';
`)
.then(res => res.map(item => item.table_name)) // To get only an array with the names
.then(tables => tables.map(tableName => db.none(`TRUNCATE TABLE ${tableName} CASCADE`))) // ES6 template strings, because the table name must be bare here (no quotes)
.then(queries => db.tx(t => t.batch(queries)))

Я получаю тупик обнаруженных ошибок. Понятно, почему я получаю взаимоблокировки: запросы каскадируются и пытаются обрезать ту же таблицу, что и другой запрос. Вот почему мне нужно вызывать запросы синхронно. Я не могу понять, как это сделать. Я пытался с помощью db.sequence(), но я получаю те же ошибки. Каков правильный способ последовательного выполнения сгенерированных запросов с pg-promise? Большое спасибо.

1 ответ

Решение

Синтаксис поддерживается pg-promise очень гибкий. Ниже приведен только один такой синтаксис, который проще всего использовать в вашем случае и самый современный:

db.tx(async t => {
    const tables = await t.map(`
        SELECT table_name
        FROM information_schema.tables
        WHERE table_schema = $1
        AND table_type = $2
    `, ['public', 'BASE TABLE'], a => a.table_name);

    for (let i = 0; i < tables.length; i++) {
        await t.none('TRUNCATE TABLE $1:name CASCADE', tables[i]);
    }
});

// Шаблонные строки ES6, потому что здесь имя таблицы должно быть пустым (без кавычек)

это неправильно, имена должны быть в двойных кавычках, которые мы предоставляем с фильтром имен SQL.

Также смотрите отсюда:

Никогда не используйте зарезервированный синтаксис $ {} внутри строк шаблона ES6, так как они не знают, как форматировать значения для PostgreSQL.

Другие вопросы по тегам