Вызов функции PL / PGSQL с обнуляемыми параметрами - PullRequest
1 голос
/ 27 марта 2012

ПРОБЛЕМА:

У меня проблемы с функцией, которую я создал в 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 (неизвестно, целое число) не существует;

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

ВОПРОС:

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

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

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

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

UPDATE:

Вот DboCommand:

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

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

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

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

количество связанных параметров <количество маркеров параметров </p>

Ответы [ 2 ]

2 голосов
/ 27 марта 2012

Вопрос № 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 не поддерживает его.

1 голос
/ 27 марта 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, поэтому я, исходя из стиля ваших вызовов bind, я предполагаю именованные заполнители формы: name, используйте любую правильную форму для вашей клиентской библиотеки odbc. Было бы полезно узнать, какую клиентскую библиотеку C ++ вы используете.

...