pgDac есть вопросы

Обсуждение возникших проблем, предложений и ошибок PgDAC компонентов
Закрыто
visualtech
Сообщения: 2
Зарегистрирован: Вт 16 янв 2018 06:20

pgDac есть вопросы

Сообщение visualtech » Вт 16 янв 2018 06:44

Здравствуйте.
Я выбираю компоненты для Postgres+Lazarus, заказчики хотят переехать с FireBird на Postgres, на данный момент для работы с FireBird использую собственный форк IBX, переделанный по типу FIBPlus. Ищу компоненты с подобным функционалом для Postgres чтобы на клиенте было минимум изменений. Есть вопросы по pgDac.
У меня сейчас механизм на FireBird работает следующим образом:
1. Генерацию первичных ключей я задаю на стороне сервера. В Insert запросах использую выражение Returning для возврата первичного ключа, таким образом ключ генерится на сервере и автоматически подставляется в набор данных в момент выполнения метода Post, никаких генераторов на клиенте указывать не нужно. Получив первичный ключ автоматически срабатывает refresh текущей записи по первичному ключу.
Можно ли с pgDac работать так-же, используя генерацию первичного ключа на стороне сервера и через выражение returning в insert запросе подставлять его в набор данных?

2 Все то-же самое, но в Insert запросе используется хранимая процедура, которая после вставки возвращает первичный ключ и он подставляется в набор данных.

3. Я пробовал использовать SQLdb из состава лазарус, но подтверждение транзакции после вставки, редактирования, удаления данных закрывает все наборы данных, SELECT по новой открывать надо.
Как с этим обстоят дела в pgDac?

AndreyZ
Devart Team
Сообщения: 328
Зарегистрирован: Чт 08 сен 2011 13:18

Re: pgDac есть вопросы

Сообщение AndreyZ » Чт 18 янв 2018 14:32

1. Об использовании в PgDAC ключевого слова RETURNING для получения значения со стороны PostgreSQL вы можете найти в нашей онлайн-документации: http://www.devart.com/pgdac/docs/index. ... ration.htm

Также PgDAC умеет автоматически получать значение ключевого поля, которое генерируется на сервере. Например:

Код: Выделить всё

  PgQuery1.SQL.Text := 'select * from emp;';
  PgQuery1.DMLRefresh := True;
  PgQuery1.Active := True;
  PgQuery1.Insert;
  PgQuery1.FieldByName('ename').AsString := 'Testing.';
  PgQuery1.Post;
  ShowMessage('New empno = ' + PgQuery1.FieldByName('empno').AsString);
2. Пожалуйста, покажите нам INSERT SQL запрос, в котором вы используете хранимую процедуру, а также скприпт для создания этой хранимой процедуры.

3. PgDAC при вызове метода TPgConnection.Commit не закрывает датасеты, которые используют этот экземпляр соединения.

visualtech
Сообщения: 2
Зарегистрирован: Вт 16 янв 2018 06:20

Re: pgDac есть вопросы

Сообщение visualtech » Пт 19 янв 2018 07:08

Пример функции, делает вставку в таблицу baseuser, возвращает первичный ключ baseuser_id через выходной параметр out_baseuser_id. Я бы хотел вызов такой функции вставить в InsertSQL набора данных. Как-то можно приспособить, чтобы выходной параметр out_baseuser_id сам подставлялся в набор данных после выполнения вставки записи?

Код: Выделить всё

CREATE OR REPLACE FUNCTION public.f_baseuser_ins (
  iarh boolean,
  iregdata date,
  isfam varchar,
  isimja varchar,
  isotch varchar,
  ibrig integer,
  out out_baseuser_id bigint
)
RETURNS bigint AS
$body$
DECLARE
    iuserfio VARCHAR(100);
BEGIN
  IF iarh IS NULL THEN 
    iarh := FALSE;
  END IF;
  
  iuserfio := isfam || ' ' || isimja;
  
  IF isotch <> '' THEN 
    iuserfio := iuserfio || ' ' || isotch; 
  END IF;
  
  
  INSERT INTO baseuser 
  (
    userfio,
    arh,
    regdata,
    sfam,
    simja,
    sotch,
    brig
  )
    VALUES
    (iuserfio,
     iarh,
     iregdata,
     isfam,
     isimja,
     isotch,
     ibrig
  )RETURNING baseuser_id INTO out_baseuser_id;
  
  RETURN;
END;

AndreyZ
Devart Team
Сообщения: 328
Зарегистрирован: Чт 08 сен 2011 13:18

Re: pgDac есть вопросы

Сообщение AndreyZ » Пн 22 янв 2018 14:51

Чтобы получить значение OUT параметра после вызова хранимой процедуры, используйте компонент TPgStoredProc. Например:

Код: Выделить всё

  PgStoredProc1.StoredProcName := 'f_baseuser_ins';
  ...
  PgStoredProc1.ExecProc;
  baseuser_id := PgStoredProc1.ParamByName('out_baseuser_id').AsLargeInt;
А присваивать полученное значение в поле набора данных вы можете в обработчике события AfterUpdateExecute:

Код: Выделить всё

procedure TForm1.PgQuery1AfterUpdateExecute(Sender: TDataSet;
  StatementTypes: TStatementTypes; Params: TDAParams);
begin
  if stInsert in StatementTypes then
  begin
    Sender.FieldByName('baseuser_id').ReadOnly := False;
    try
      Sender.FieldByName('baseuser_id').NewValue := baseuser_id;
    finally
      Sender.FieldByName('baseuser_id').ReadOnly := True;
    end;
  end;
end;

Закрыто