Вызов функции PL/PGSQL с параметрами, допускающими значение NULL

ПРОБЛЕМА:

У меня проблемы с функцией, которую я создал в Postgres (9.1) с языком plpgsql. Я пришел из мира SQL Server, поэтому здесь есть небольшой языковой пробел.

Моя проблема в том, что postgres, похоже, неправильно назначает параметры, которые я передаю.

Вот мое определение функции:

CREATE OR REPLACE FUNCTION func1 (
    IN param1 character varying,
    IN param2 character varying DEFAULT NULL::character varying,
    IN param3 int DEFAULT NULL::int)
RETURNS void
AS $$
BEGIN
    INSERT INTO table1
    (
        col1
        , col2
        , col3
    )
    VALUES
    (
        $1
        , $2
        , $3
    )
END;
$$ LANGUAGE plpgsql;

Сама функция отлично работает при тестировании в среде базы данных, но сейчас я пытаюсь вызвать ее из C++ через соединение ODBC.

Здесь я задаю параметры:

pCmd->paramIn( "param1", (char *)name.getString().c_str() );
pCmd->paramIn( "param3", 100 );

В этом случае я не присвоил param2 никакого значения. Это обнуляется - не должно быть проблемой.

Ошибка, которую я получаю:

ОШИБКА: функция func1(unknown, integer) не существует;

Из того, что я вижу, вызов пытается назначить параметры по порядку, игнорируя имена параметров.

ВОПРОС:

1 - Как я могу вызвать эту функцию, чтобы она работала? Должен ли я передать «NULL» в качестве отсутствующих параметров и убедиться, что они все в порядке?

2 - Если я использую соединение ODBC, что я, безусловно, использую, должен ли я вызывать функцию языка SQL, которая, в свою очередь, вызывает функцию PLPGSQL? Это немного запутанно, но я был бы готов попробовать.

3 - (не вопрос) Пожалуйста, не предлагайте "Не использовать ODBC". Кроме того, пожалуйста, не пытайтесь изменить внутренности функции, если в этом нет необходимости. Моей основной задачей сейчас является изучение того, как сделать вызов функции в postgres через ODBC.

Заранее всем спасибо за то, что нашли время, чтобы прочитать это, и большое спасибо всем, кто ответит.

ОБНОВЛЕНИЕ:

Вот DboCommand:

DboCommand *cmd;
cmd = new DboCommand(dbConnection, "{call func1 (?) (?)}");

Что раньше было этим

cmd = new DboCommand(dbConnection, "func1");

Теперь ошибка:

количество связанных параметров ‹ количество маркеров параметра


person Nick Vaccaro    schedule 27.03.2012    source источник


Ответы (2)


Вопрос № 1: да, вы должны передать NULL и заботиться о порядке (и типах).

Теоретически функции PostgreSQL можно вызывать с параметрами в именованной или позиционной записи. Это объясняется здесь: http://www.postgresql.org/docs/9.1/static/sql-syntax-calling-funcs.html

При использовании только позиционной записи можно опустить N-й параметр только в том случае, если любой следующий параметр также опущен. Поскольку ваш драйвер ODBC явно использует эту запись, вы должны указать второй параметр, если хотите указать третий. Предположительно, имена, которые вы выбираете в своем клиентском коде для параметров, совершенно не связаны с именами объявления функции plpgsql, это позиции и типы аргументов, которые имеют значение для сопоставления вызова с существующей функцией.

Вопрос №2: введение функции-заглушки SQL здесь не поможет.

Вопрос № 3: Возможность именования параметров с точки зрения вызывающей стороны появилась недавно (по-моему, появилась в PG 9.0), поэтому, возможно, драйвер ODBC не поддерживает ее.

person Daniel Vérité    schedule 27.03.2012

ERROR: function func1(unknown, integer) does not exist;

Это сообщение указывает на проблему: Postgres не может понять, какую функцию вызывать, потому что она имеет неполную сигнатуру функции, нет функции с именем func1, которая принимает неизвестный тип в качестве первого аргумента и целое число в качестве второго. Попробуйте привести заполнители к ожидаемому типу при вызове функции, чтобы postgres мог разрешить подпись, например что-то вроде: func1(:param1::character varying, :param2::character varying, :param3::integer) или func1( CAST(:param1 as character varying), CAST(:param2 as character varying), CAST(:param3 as integer) ). Вы не опубликовали вызов функции или оператор sql, поэтому я, исходя из стиля ваших вызовов привязки, предполагаю, что именованные заполнители формы: имя, используйте любую правильную форму для вашей клиентской библиотеки odbc. Мне было бы полезно узнать, какую клиентскую библиотеку C++ вы используете.

person dbenhur    schedule 27.03.2012
comment
Спасибо за совет. Я забыл добавить фактический объект DboCommand, в котором неправильно указан вызов функции. Я обновил свой код и вопрос и опубликовал новую ошибку, которую получаю. - person Nick Vaccaro; 27.03.2012