Как сделать: последовательный пакет 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.