Передать массив из node-postgres в функцию plpgsql

Функция plpgsql:

CREATE OR REPLACE FUNCTION testarray (int[]) returns int as $$
  DECLARE
    len int;
  BEGIN
    len := array_upper($1);
  return len;
  END
$$ language plpgsql;

Запрос node-postgres + тестовый массив:

var ta = [1,2,3,4,5];
client.query('SELECT testarray($1)', [ta], function(err, result) {
  console.log('err: ' + err);
  console.log('result: ' + result);
});

Вывод с сервера узла:

err: error: значение массива должно начинаться с "{" или информация об измерении
результат: undefined

Я также попытался применить параметр в клиентском запросе, например testarray($1::int[]), который вернул ту же ошибку.

Я изменил аргумент функции на (anyarray int), и ошибка вывода изменилась:

err: error: недопустимый синтаксис ввода для целого числа: "1,2,3,4,5"
результат: undefined

А также пара других вариантов.

Я ищу вариант, который не вызывает ошибок и возвращает 5.

Я читал о проблеме синтаксического анализа Postgres и об этом вопросе о переполнении стека для параметризованных массивов в node-postgres:

Но ответа, похоже, не было.


person Community    schedule 11.11.2012    source источник


Ответы (3)


Параметр должен быть в одной из следующих форм:

'{1,2,3,4,5}'         -- array literal
'{1,2,3,4,5}'::int[]  -- array literal with explicit cast
ARRAY[1,2,3,4,5]      -- array constructor

Также вы можете упростить свою функцию:

CREATE OR REPLACE FUNCTION testarray (int[])
  RETURNS int AS
$func$
BEGIN
  RETURN array_length($1, 1);
END
$func$ LANGUAGE plpgsql IMMUTABLE;

Или простая функция SQL:

CREATE OR REPLACE FUNCTION testarray2 (int[])
  RETURNS int AS 'SELECT array_length($1, 1)' LANGUAGE sql IMMUTABLE;

Или просто используйте array_length($1, 1) напрямую.

  • array_upper() - это неправильная функция. Массивы могут иметь произвольные индексы. array_length() делает то, что вы ищете. Связанный вопрос:

  • И array_length(), и array_upper() требуют двух параметров. Второй - это размер массива - в вашем случае 1.

person Erwin Brandstetter    schedule 11.11.2012
comment
спасибо за краткое изложение массивов. Я ходил кругами по документам. Мне удалось заставить все эти варианты работать в node-postgres без параметров. спасибо за подробности о array_length. - person ; 11.11.2012

благодаря ответам PinnyM и Erwin. Я просмотрел варианты и перечитал связанные ответы.

Форматы массивов, описанные Эрвином, работают в node-postgres буквально следующим образом:

'select testarray(' + "'{1,2,3,4,5}'" + ')'
'select testarray(' + "'{1,2,3,4,5}'" + '::INT[])'
'select testarray(ARRAY[1,2,3,4,5])'

tl: dr цитирования javascript

чтобы параметризовать их в node-postgres: (на основе этого ответа)

var ta = [1,2,3,4,5];
var tas = '{' + ta.join() + '}';

...skipped over the pg connect code

client.query("select testarray($1)", [tas] ...
client.query("select testarray($1::int[])", [tas] ...
not sure about the ARRAY constructor.
person Community    schedule 11.11.2012

Основываясь на опубликованном вами ответе, это может сработать для вас:

var ta = [1,2,3,4,5];
var params = [];
for(var i = 1, i <= ta.length; i++) {
    params.push('$'+i);
}
var ta = [1,2,3,4,5];
client.query('SELECT testarray(\'{' + params.join(', ') + '}\')', ta, function(err, result) {
  console.log('err: ' + err);
  console.log('result: ' + result);
});
person PinnyM    schedule 11.11.2012
comment
Он выдает новую ошибку из postgresql: синтаксическая ошибка около или около { - person ; 11.11.2012
comment
Да, я забыл, что это нужно заключить в кавычки. Обновлено. - person PinnyM; 11.11.2012
comment
это тоже не сработало. что действительно работало: client.query (select testarray ($ 1 :: int []), [ta], ... и т. д. - person ; 11.11.2012
comment
Это представляет собой серьезную угрозу безопасности! - person Miles Rout; 06.05.2015
comment
@MilesRout можете уточнить? Объединенные параметры генерируются сервером - проблема в длине переданного массива параметров? - person PinnyM; 06.05.2015