Перейти к содержанию
Fire Monkey от А до Я
  • 0

FireDAC, PostgreSQL процедуры и Blob параметры


Navadvipa Chandra das

Вопрос

Здравствуйте все!
Потихоньку начал переводит свою библиотеку, написанную для C++Builder 6 на новые рельсы C++Builder 10.3.3.
Компонент сохранения настроек TNNConfig работает с бинарным форматом и уже отлажен для сохранения и чтения настроек в файл:
TNNConfig->StoreKind = skFile; А вот если свойство StoreKind установить в значение skDB, то не получается сохранение в базе данных. База данных  PostgreSQL  13. Таблица сохранения настроек выглядит так:
-- Table: public.UserReg

-- DROP TABLE public."UserReg";

CREATE TABLE public."UserReg"
(
    "UserRegKey" character varying(720) COLLATE pg_catalog."default" NOT NULL,
    "UserData" bytea
)

TABLESPACE pg_default;

ALTER TABLE public."UserReg"
    OWNER to "Navadvipa_Chandra_das";

COMMENT ON TABLE public."UserReg"
    IS 'Таблица, содержащая настройки пользователей в бинарном виде!';

COMMENT ON COLUMN public."UserReg"."UserRegKey"
    IS 'Поле - первичный ключ для настройки!';

COMMENT ON COLUMN public."UserReg"."UserData"
    IS 'Поле - настройки пользователей в бинарном виде!';

-- PROCEDURE: public.SelectUserReg(character varying, bytea)

-- DROP PROCEDURE public."SelectUserReg"(character varying, bytea);

CREATE OR REPLACE PROCEDURE public."SelectUserReg"(
    "UserRegKey_" character varying,
    INOUT "UserData_" bytea)
LANGUAGE 'plpgsql'
AS $BODY$
begin
  select a."UserData" into "UserData_" from "UserReg" a
  where a."UserRegKey" = "UserRegKey_";
  --if not found then
  --  "UserData_" := Null;
  --end if;
end;
$BODY$;

-- PROCEDURE: public.UpdateUserReg(character varying, bytea)

-- DROP PROCEDURE public."UpdateUserReg"(character varying, bytea);

CREATE OR REPLACE PROCEDURE public."UpdateUserReg"(
    "UserRegKey_" character varying,
    INOUT "UserData_" bytea)
LANGUAGE 'plpgsql'
AS $BODY$
begin
  update "UserReg" a set a."UserData" = "UserData_"
  where a."UserRegKey" = "UserRegKey_";
  if not found then
    insert into "UserReg" ( "UserRegKey", "UserData" ) values ( "UserRegKey_", "UserData_" );
  end if;
end;
$BODY$;

COMMENT ON PROCEDURE public."UpdateUserReg"(character varying, bytea)
    IS 'Запись настроек пользователя';
 


Клиент PosgreSQL - 32 бит ODBC. 64 бит FireDAC недоступен для Community Edition.

Методы LoadFromDB и SaveToDB я приведу ниже, но они нерабочие и не понятно где копать, так как документация по этому вопросу крайне скудна.

bool __fastcall TNNConfig::LoadFromDB()
{
  if ( Connection && !Connection->Connected )
    return false;

  bool B = false;

  std::unique_ptr< TFDQuery > quReg( new TFDQuery( this ) );
  std::unique_ptr< TFDTransaction > trReg( new TFDTransaction( this ) );

  quReg->Connection  = Connection;
  trReg->Connection  = Connection;
  quReg->Transaction = trReg.get();

  Connection->StartTransaction();
  try {
    quReg->SQL->Text =
      "begin\n"
      "  \"SelectUserReg\"( :key_, :lob_ );\n"
      "end;";
    quReg->Params->Items[ 0 ]->DataType = ftString;
    quReg->Params->Items[ 0 ]->AsString = RegistryKey();
    quReg->Params->Items[ 1 ]->DataType = ftStream;
    quReg->Params->Items[ 1 ]->AsStream = Filer;

    //quReg->Params->Items[ 0 ]->DataType   = ftStream;
    //quReg->Params->Items[ 0 ]->FDDataType = dtBlob;
    quReg->Params->Items[ 1 ]->ParamType  = ptOutput;
    quReg->Params->Items[ 1 ]->StreamMode = smOpenRead;

    quReg->ExecSQL();

    TStream *LOB = quReg->Params->Items[ 0 ]->AsStream;

    if ( LOB && LOB->Size > 0 ) {
      ((TMemoryStream*)Filer->Stream)->Size = LOB->Size;
      LOB->Read( ((TMemoryStream*)(Filer->Stream))->Memory, Filer->Stream->Size );
    }

    Connection->Commit();
    B = true;
  } catch ( ... ) {
    Connection->Rollback();
  }
  return B;
}

Вот тестовое приложение - https://github.com/Navadvipa-Chandra-das/TestFMX
Вот библиотека Нижняя Навадвипа - https://github.com/Navadvipa-Chandra-das/NizhnyayaNavadvipa

Кто может, помогите!
Спасибо!

С уважением, Навадвипа Чандра дас.

Изменено пользователем Navadvipa Chandra das
ошибки и забыл процедуры написать
Ссылка на комментарий

Рекомендуемые сообщения

  • 0

Судя по всему, вы используете версию Community Edition, в которой функциональность FireDAC урезана.

Об этом нам и говорит сообщение "Клиент PosgreSQL - 32 бит ODBC. 64 бит FireDAC недоступен для Community Edition."

Для взаимодействия с сервером вам нужна полная версия Rad Studio.

 

Ссылка на комментарий
  • 0

Здравствуйте!
Нет, это не сообщение от С++Builder, но ответ от службы техподдержки Embarcadero, что FireDAC не поддерживается в Коммунити Едишн для разных платформ. Вот прислали ссылку возможностей разных версий - https://www.embarcadero.com/docs/rad-studio-feature-matrix.pdf
Но соединение с базой устанавливается, у компонента TFDConnection свойство OidAbLOB == Yes, UnknownFormat == BYTEA, если последнее свойство установить Error, то просто ошибка Invalid pointer operation. А я даже не могу понять где ошибка, может в SQL запросе, может в настройках параметров запроса или еще где.
С уважением, Навадвипа Чандра дас.

Ссылка на комментарий
  • 0

Здравствуйте!
Блоб параметры в процедурах PostgreSQL победить не удалось, а вот та же функциональность через Блоб-поля TFDQuery была достигнута. В целом такой вариант более универсален.

void __fastcall TNNConfig::SaveToDB()
{
  if ( Connection && !Connection->Connected )
    return;

  TMemoryStream* ms = new TMemoryStream();
  fFiler = new TNNTextStream( ms );

  try {
    SaveFilerFromUserEvent();

    std::unique_ptr< TFDQuery > quReg( new TFDQuery( this ) );
    std::unique_ptr< TFDTransaction > trReg( new TFDTransaction( this ) );

    quReg->Connection  = Connection;
    trReg->Connection  = Connection;
    quReg->Transaction = trReg.get();

    String RK = RegistryKey();
    Connection->StartTransaction();
    try {
      quReg->SQL->Text = "SELECT \"UserRegKey\", \"UserData\" FROM \"UserReg\" where \"UserRegKey\" = :UserRegKey_";
      quReg->Params->Items[ 0 ]->DataType   = ftString;
      quReg->Params->Items[ 0 ]->AsString   = RK;
      quReg->Open();

      if ( quReg->RecordCount == 0 ) {
        quReg->Insert();
        quReg->Fields->Fields[ 0 ]->AsString = RK;
      } else
        quReg->Edit();

      TBlobField *bf = ((TBlobField *)(quReg->Fields->Fields[ 1 ]));
      bf->LoadFromStream( Filer );

      quReg->Post();
      Connection->Commit();
    } catch ( ... ) {
      Connection->Rollback();
    }
  } __finally {
    delete fFiler;
    fFiler = nullptr;
  }
}

bool __fastcall TNNConfig::LoadFromDB()
{
  if ( Connection && !Connection->Connected )
    return false;

  bool B = false;

  std::unique_ptr< TFDQuery > quReg( new TFDQuery( this ) );
  std::unique_ptr< TFDTransaction > trReg( new TFDTransaction( this ) );

  quReg->Connection  = Connection;
  trReg->Connection  = Connection;
  quReg->Transaction = trReg.get();

  quReg->SQL->Text = "SELECT \"UserRegKey\", \"UserData\" FROM \"UserReg\" where \"UserRegKey\" = :UserRegKey_";
  quReg->Params->Items[ 0 ]->DataType   = ftString;
  quReg->Params->Items[ 0 ]->AsString   = RegistryKey();
  quReg->Open();

  if ( quReg->RecordCount == 1 ) {
    TBlobField *bf = ((TBlobField *)(quReg->Fields->Fields[ 1 ]));
    bf->SaveToStream( Filer );
    B = true;
  }

  return B;
}
 

Вопрос закрыт!
Спасибо!
С уважением, Навадвипа Чандра дас.

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...