pg-promise: передать функцию в качестве параметра функции func()

Я использую pg-promise для доступа к нашей базе данных postgres. Я хочу вызвать хранимую процедуру foo(geom), которая принимает тип данных геометрии (PostGIS). У меня есть только латы/длины для начала, поэтому я хочу преобразовать их с помощью postGIS.

Это выглядит так:

db.func('foo', 'ST_MakePoint(' + location.lat + ', ' + location.lng + ')')
  .then((result) => {
    console.log(bar);
  });

Я сейчас получаю ошибку, жалуясь, что у меня неверная геометрия (преобразование не происходит). Я уверен, что ST_MakePoint работает для значений, которые у меня есть. Я предполагаю, что он интерпретирует его как строку, а не как вызов функции при выполнении в БД.

Как мне передать этот параметр, чтобы он работал?


person Kevin    schedule 25.01.2017    source источник


Ответы (1)


Я автор pg-promise;)

В отличие от обычного форматирования запроса с помощью pg-promise, где вы указываете свой шаблон форматирования через форматирование переменные, вы пропускаете это при использовании методов func и proc, поэтому они подразумеваются из типа значений.

Самое элегантное решение — использовать поддерживаемое форматирование пользовательского типа. библиотекой, которая позволяет вам переопределять любой тип данных и обеспечивать собственное форматирование.

Вы можете ввести свой собственный класс Point следующим образом:

function Point(lat, lng) {
    this.lat = +lat;
    this.lng = +lng;
    this.rawType = true; /* use as raw/unescaped value */
    this.toPostgres = p => {
        return 'ST_MakePoint(' + p.lat + ',' + p.lng + ')';
    };
}

Затем вы можете передать его как обычное значение:

const p = new Point(1, 2);

db.func('foo', [p]).then(...)

Кроме того, вы можете выполнить свой запрос напрямую. Не переоценивать метод func, который просто выполняет SELECT * FROM foo, поэтому ты можешь сделать:

const p = 'ST_MakePoint(' + lat + ',' + lng + ')';

db.any('SELECT * FROM foo($1:raw)', p).then(...)

:raw - вводит необработанное/неэкранированное значение.

P.S. В будущем вместо того, чтобы гадать, что выполняет pg-promise, попробуйте pg-monitor вместо этого или хотя бы обрабатывать событие query.

ОБНОВЛЕНИЕ: 29 апреля 2018 г.

Обновлен синтаксис для Форматирование пользовательского типа, чтобы соответствовать последним поддерживается pg-promise.

И самый короткий синтаксис для завершения точки:

const point = (lat, lng) => ({
    toPostgres: ()=> pgp.as.format('ST_MakePoint($1, $2)', [lat, lng]),
    rawType: true
});

Таким образом, вы можете передать его просто как:

db.func('foo', point(1, 2))
person vitaly-t    schedule 25.01.2017