Выполнить функцию Postgresql, которая принимает массив параметров, используя pg-обещание - PullRequest
2 голосов
/ 17 марта 2020

У нас есть postgresql тип:

create type order_input as (
    item text,
    quantity integer);

И эта postgresql функция:

create or replace function insert_into_orders(order_input[])
returns void language plpgsql as $$
declare 
    inserted_id integer;
begin
    insert into public.orders(orderdate) 
    values (now()) 
    returning orderid into inserted_id;

    insert into public.orderdetails(orderid, item, quantity)
    select inserted_id, item, quantity
    from unnest($1);
end $$;

Для выполнения в pgadmin-4 мы запускаем:

select insert_into_orders(
    array[
        ('Red Widget', 10), 
        ('Blue Widget', 5)
    ]::order_input[]
);

Я пытаюсь выяснить, как выполнить функцию insert_into_orders с использованием библиотеки pg-prom javascript. Я попытался сделать следующее:

const pgp = require("pg-promise")();
const db = pgp(connectionObj);

await db.func("insert_into_orders", [{item:"Red Widget", quantity:10}, {item:"Blue Widget", quantity:5}]

, но получил следующее сообщение:

{
  "error": {
    "message": "malformed array literal: \"{\"item\":\"Red Widget\", \"quantity\":10}\""
  }
}

Был бы очень признателен, если бы кто-нибудь знал, как я должен был структурировать свой ввод для pg-обещания, Исходное сообщение отсюда: Postgres Функция для вставки нескольких записей в две таблицы

1 Ответ

1 голос
/ 17 марта 2020

Метод fun c ожидает массив значений в качестве второго параметра. В вашем случае это должен быть один параметр - массив объектов. Но вместо этого вы даете ему 2 параметра, каждый объект - отсюда и ошибка.

Правильный путь:

const orderInput = [{item:"Red Widget", quantity:10}, {item:"Blue Widget", quantity:5}];

await db.func('insert_into_orders', [orderInput]);

В любом случае, вы должны использовать событие query или pg-monitor , чтобы увидеть, что было сгенерировано SQL.

Кроме того, ваша insert_into_orders должна быть хранимой процедурой , а затем выполняться через pro c, по крайней мере. Однако его реализация выглядит так, как будто это должна быть просто транзакция в вашем коде.

После этого ошибка вернулась как "error": {"message": "function insert_into_orders(text[]) does not exist"}

Это из-за типа несоответствие, которое требует приведения типа ...

Вы можете либо вызвать функцию с помощью обычного метода запроса, либо использовать Пользовательское форматирование типа для изменения формата данных:

const data = {
    toPostgres: () => `${pgp.as.array(orderInput)}::json[]::order_input[]`,
    rawType: true
};

Затем передайте это вместо:

await db.func('insert_into_orders', [data]);
...