И так, получилось
Может кому-то пригодится.
Сначала о граблях.
1. Основные грабли - это нулевые символы в данных. При работе с PChar, AnsiString получаем кучу гемора.
2. Нужно быть очень аккуратными при работе с MemoryStreamN.Write
3. Нужно аккуратно использовать mysql_real_escape_string. Оно преобразовывает все, в том числе и те кавычки, которые не нужно було
Долго с этим возился
4. При анализе данных в watch-окне, в строках фигурируют вопросительные знаки. Это все UTF8. Нужно побайтно просматривать.
Что нужно (желательно) использовать.
1. В запросах делаем CAST("...'" as binary)
2. Служебные символы Мускуля обходим с помощью mysql_real_escape_string, но аккуратно.
3. Размер вывода получаем через mysql_fetch_lengths(PResult) (другие функции обрезают длину по нулевому символу.)
Примеры наведу позже, после глобальной чистки кода.
Добавлено спустя 6 часов 10 минут 48 секунд:Re: (Решено) Картинку в блоб-полеОбещаный код:
Подпрограмма записи в блоб-поле:
- Код: Выделить всё
Function QuerryP(Const MySock : PMYSQL; Const SelStr: PChar; Const len: longint; Out MySQLErrMsg : AnsiString): boolean;
Begin
Result := True;
if (mysql_real_query(MySock,SelStr, len) <> 0) then
begin
MySQLErrMsg := 'Query failed. '+ mysql_error(MySock);
Result := False;
exit;
end;
End;
Подпрограмма форимрования запроса для записи:
- Код: Выделить всё
procedure TFrmWebcam.Button2Click(Sender: TObject);
const S1='insert into foto set unsprava=1, foto=CAST("';
S2='" as binary)';
var
Stream: TMemoryStream;
w1, w2: Pchar;
begin
// Image1.Picture.Jpeg.SaveToFile('test.jpg');
Stream := TMemoryStream.Create;
// Image1.Picture.Jpeg.SetSize(10,10);
Image1.Picture.Jpeg.SaveToStream(Stream); // Сохраняем Jpeg-картинку в поток
Stream.Position:=0;
GetMem(w1, Stream.Size);
Stream.Read(w1[0], Stream.Size); // Читаем с потока в переменную w1
GetMem(w2, 2*Stream.Size);
mysql_real_escape_string(MySockW, w2, w1, Stream.Size); //Делаем читабельную для Мускуля строку
Stream.Free;
if not QuerryP(MySockW, Pchar(s1+w2+s2), Length(s1+w2+s2), ErrMsg) then ShowMessage(ErrMsg);
Freemem(w1);Freemem(w2);
end;
Подпрограмма чтения блоб-поля:
- Код: Выделить всё
Function SelectToMemoryStream(Const Mysock: PMYSQL; Const SelStr: AnsiString; Var MemoryStreamN: TMemoryStream; Out VMySQLErrMsg : AnsiString): boolean;
Var FieldCount: Integer;
PCurrentRow: {$IFDEF FPC}MySQL_Row{$ELSE}PMySQL_Row{$ENDIF};
PResult: Pointer;
RecordCount: Integer;
LenArray: PDWord;
Begin
Result := True;
if (mysql_query(MySock,PChar(SelStr)) > 0) then
begin
VMySQLErrMsg := 'Ошибка запроса. '+ mysql_error(MySock);
Result := False;
exit;
end;
PResult:= MySQL_Use_Result(MySock); {Can be called for select and none-select. Returns nil if storing failed or if query was none-select}
if PResult = nil then
begin
if MySQL_Field_Count(MySock) = 0 then {It was a none-select}
begin
VMySQLErrMsg := 'Запрос не возвратил поля. '+chr(10)+chr(13)+
'Обработано '+IntToStr(MySQL_Affected_Rows(MySock))+' записей.';
Result := False;
exit;
end
else {It was a select query, but an error has occured}
begin
VMySQLErrMsg := 'Ошибка запроса. '+ mysql_error(MySock);
Result := False;
exit;
end;
end;
// else Result is not null - receiving data
try
// Fields count receiving
FieldCount:= MySQL_Num_Fields(PResult);
if (FieldCount=0) or (FieldCount>1) then
begin
VMySQLErrMsg := 'Запрос не возвратил поля либо полей больше 1';
Result := False;
exit;
end;
// Record data receiving
RecordCount := 0;
PCurrentRow:= MySQL_Fetch_Row(PResult);
LenArray:=mysql_fetch_lengths(PResult);
while PCurrentRow <> nil do
begin
Inc(RecordCount);
MemoryStreamN.Position:=0;
MemoryStreamN.Write(PCurrentRow[0][0], LenArray[0]);
PCurrentRow:= MySQL_Fetch_Row(PResult);
end;
finally
MySQL_Free_Result(PResult);
PResult:=nil;
PCurrentRow:=nil;
end;
End;
Подпрограмма формирования запроса и вставки картинки:
- Код: Выделить всё
procedure TFrmWebcam.Button3Click(Sender: TObject);
Var Stream: TMemoryStream;
Begin
Stream := TMemoryStream.Create;
if not SelectToMemoryStream(MySockW,
'select CAST(foto as binary) from foto',
Stream, ErrMsg) then
ShowMessage(ErrMsg)
else
begin
Stream.Position:=0;
Image1.Picture.Jpeg.LoadFromStream(Stream);
end;
Stream.Free;
End;