C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
PostgreSQL, работа с типом BYTEA
Лена
Отправлено: 14.11.2006, 17:01


Мастер участка

Группа: Участник
Сообщений: 501



Подскажите как в базу данных PostgreSQL поместить фотографию?
Valdemar
Отправлено: 14.11.2006, 17:39


Мастер участка

Группа: Участник
Сообщений: 433



С PostgreSQL не работал, но думаю, что можно с помощью параметрического запроса. А значение параметра (фото) прочитать из файла или потока.
Лена
Отправлено: 14.11.2006, 18:05


Мастер участка

Группа: Участник
Сообщений: 501



QUOTE (Valdemar @ 14.11.2006, 17:39)
С PostgreSQL не работал, но думаю, что можно с помощью параметрического запроса. А значение параметра (фото) прочитать из файла или потока.

А примера нет, как это делается? У меня изображение в Image1.
Умные книжки посмотрела, нигде нет описания как послать картинку в базу. angry2.gif
Valdemar
Отправлено: 15.11.2006, 08:59


Мастер участка

Группа: Участник
Сообщений: 433



Что-то вроде этого:
CODE
   ADOQuery1->SQL->Text="INSERT INTO table (img) VALUES(:img)";
   TMemoryStream *MS = new(TMemoryStream);
   try
   {
       Image1->Picture->Graphic->SaveToStream(MS);
       MS->Seek(0, soFromBeginning);
       ADOQuery1->Parameters[0]->LoadFromStream(MS);
       ADOQuery1->ExecSQL();
   }
   __finally
   {
     delete MS;
   }
Лена
Отправлено: 15.11.2006, 11:52


Мастер участка

Группа: Участник
Сообщений: 501



Cкажите, почему не работает такой вариант:
Поместила на форму DBImage1 и привязала его к полю с фотографиями.
Пишу:
//PathPic путь к картинке
//DBImage1 привязан к полю photo из ClientDataSetVis
DataModule2->ClientDataSetVis->Edit();
DBImage1->Picture->LoadFromFile(PathPic);

После этого вижу картинку в DBImage1. Далее делаю:
DataModule2->ClientDataSetVis->Post();
И картинка из DBImage1 исчезает. sad.gif

В самом событии AfterPost есть код:
CODE

void __fastcall TDataModule2::ClientDataSetVisAfterPost(TDataSet *DataSet)
{
ClientDataSetVis->ApplyUpdates(-1);
ClientDataSetVis->Active = false;
ADOQueryVis->Active = false;
ADOQueryVis->Active = true;
ClientDataSetVis->Active = true;
ClientDataSetVis->First();

}


В ADOQueryVis текст select * from visitors order by lastname
Что может быть не правильно, почему картинка из DBImage1 не загоняется в базу?

Отредактировано Лена — 15.11.2006, 12:05
Лена
Отправлено: 15.11.2006, 14:51


Мастер участка

Группа: Участник
Сообщений: 501



Нашла в интернете код по пересылке картинки в базу данных PostgreSQL:
CODE

//Пишем в TADOQuery:

INSERT INTO my_table (my_blob) VALUES (:my_blob);

//Потом делаем:
my_ado.ParamByName('my_blob).Type:=ftBlob;
my_ado.ParamByName('my_blob).Value:=my_big_string_with_data;
my_ado.Exec;



Помогите переделать:
DataModule2->ADOQueryVis->SQL->Text="INSERT INTO visitors (photos) VALUES(:img)";
DataModule2->ADOQueryVis->Parameters->ParamByName("img")->нет типа в выпадающем списке???
DataModule2->ADOQueryVis->Parameters->ParamByName("img")->Value = здесь поставить поток с картинкой?
Valdemar
Отправлено: 15.11.2006, 15:40


Мастер участка

Группа: Участник
Сообщений: 433



Я же уже писал:
DataModule2->ADOQueryVis->Parameters->ParamByName("img")->DataType=ftBlob;
DataModule2->ADOQueryVis->Parameters->ParamByName("img")->LoadFromStream(MS);
или
DataModule2->ADOQueryVis->Parameters->ParamByName("img")->LoadFromFile(filename);

Отредактировано Valdemar — 15.11.2006, 15:42
Лена
Отправлено: 15.11.2006, 16:43


Мастер участка

Группа: Участник
Сообщений: 501



Написала так:
CODE

TMemoryStream *MS = new(TMemoryStream);

try
{
AdvPicture1->Picture->SaveToStream(MS);
MS->Seek(0, soFromBeginning);
int pos = DataModule2->ClientDataSetVis->RecNo;
DataModule2->ADOQueryVis->Parameters->ParamByName("img")->DataType = ftVarBytes; //такой тип колонки photo у ClientDataSetVis в инспекторе объектов
DataModule2->ADOQueryVis->Parameters->ParamByName("img")->LoadFromStream(MS, ftVarBytes);
DataModule2->ADOQueryVis->SQL->Text="UPDATE visitors SET photo=:img WHERE id =" + IntToStr(pos) +"";
DataModule2->ADOQueryVis->ExecSQL();
//DataModule2->ADOQueryVis->SQL->Text= "select * from visitors order by lastname";
}
__finally
{
delete MS;
}


Код выполнился один раз. Теперь при любом следующем страте приложения получаю исключение на рисунке.

P.S.
Проект запускается если в OnCreate главной формы закомментировать строки:
DataModule2->ClientDataSetVis->Open();
DataModule2->ClientDataSetVis->First();
Видимо что-то прозошло при попытке загнать фотографию в базу данных моим кодом выше.

Отредактировано Лена — 15.11.2006, 17:24

Присоединить изображение

Присоединить изображение

Лена
Отправлено: 15.11.2006, 17:56


Мастер участка

Группа: Участник
Сообщений: 501



После того как убрала поле photo из запроса:
select id, firstname, lastname, patronymic, post, number, org_id, group_id, remark, enabled from visitors
и после того как убрала поле photo из списка полей ADOQueryVis и ClientDataSetVis, проект стал работать. Что же делать с этим photo!?
Лена
Отправлено: 15.11.2006, 18:19


Мастер участка

Группа: Участник
Сообщений: 501



Просмотрела запрос на сервере в колонку photo мой предыдущий код занес какие-то данные (см.рис). Наверное провайдер не может их прочитать?



Присоединить изображение

Присоединить изображение

Лена
Отправлено: 17.11.2006, 11:58


Мастер участка

Группа: Участник
Сообщений: 501



Может кому пригодиться при работе с postgresql...
Код ниже заносит картинки bmp, jpg в базу.
CODE

#include <memory>
#include <Jpeg.hpp>
using namespace std;

//для jpg сложный путь

AnsiString  fileName = ThumbnailList1->Thumbnails->Items[ThumbnailList1->ItemIndex]->Filename;
 auto_ptr<TMemoryStream> stream(new TMemoryStream());
 auto_ptr<Graphics::TBitmap> bitmap(new Graphics::TBitmap());
  if( ExtractFileExt(fileName) ==".jpg")
    {
       auto_ptr<TJPEGImage> jpeg (new TJPEGImage());
       jpeg->LoadFromFile(fileName);
       bitmap->Assign(jpeg.get());
    }
      else
      {
          bitmap->LoadFromFile(fileName);
      }
 bitmap->SaveToStream(stream.get());
 stream->Position = 0;
 DataModule2->ADOQueryVis->SQL->Text="UPDATE visitors SET photo=:img WHERE id =" + DataModule2->ClientDataSetVisid->AsString;
 DataModule2->ADOQueryVis->Parameters->ParamByName("img")->DataType = ftBlob;
 DataModule2->ADOQueryVis->Parameters->ParamByName("img")->LoadFromStream(stream.get(), ftBlob);
 DataModule2->ADOQueryVis->ExecSQL();
 DataModule2->ADOQueryVis->SQL->Text= "select * from visitors order by lastname";


Также необходимо установить последний драйвер odbs для postgresql 8.02.02.00 и в настройках поставить галочку использовать тип bytea как LO.

Вернуться в Работа с базами данных в C++Builder