tbytes is a dynamic array that means that the length and size of the array are managed internally with hidden fields it is impossible to cast one dynamic array to an other and have the rtl function properly, it might be easier to extend the database component to support a pbyte and a length parameter instead of a tbytes.
Yes, but for your purpose you should not use TBytes. See my example for sharing an integer and a byte array in the exact same memory.tbytes is a dynamic array that means that the length and size of the array are managed internally with hidden fields it is impossible to cast one dynamic array to an other and have the rtl function properly, it might be easier to extend the database component to support a pbyte and a length parameter instead of a tbytes.
I do not know how to implement, is there a sample code?
Yes, but for your purpose you should not use TBytes. See my example for sharing an integer and a byte array in the exact same memory.tbytes is a dynamic array that means that the length and size of the array are managed internally with hidden fields it is impossible to cast one dynamic array to an other and have the rtl function properly, it might be easier to extend the database component to support a pbyte and a length parameter instead of a tbytes.
I do not know how to implement, is there a sample code?
That can not be guaranteed with a dynamic array (they can be relocated...).
@Taazz plz read subject! A better way is maybe a variant record with an array of integer and an array of byte.... He needs the same memory, w/o copy.
I need to see the code that uses the TBytes in order to provide a sample.tbytes is a dynamic array that means that the length and size of the array are managed internally with hidden fields it is impossible to cast one dynamic array to an other and have the rtl function properly, it might be easier to extend the database component to support a pbyte and a length parameter instead of a tbytes.
I do not know how to implement, is there a sample code?
I need to see the code that uses the TBytes in order to provide a sample.tbytes is a dynamic array that means that the length and size of the array are managed internally with hidden fields it is impossible to cast one dynamic array to an other and have the rtl function properly, it might be easier to extend the database component to support a pbyte and a length parameter instead of a tbytes.
I do not know how to implement, is there a sample code?
The only thing you can do is to convert your data to TBytes or to a string and pass that to the parameter. I would recomend converting it to a string, for the correct procedure of doing so see the method TParam.GetAsString in the db unit, because this is done for your data internally when you execute it, this way you avoid a 3 way convertion.I need to see the code that uses the TBytes in order to provide a sample.tbytes is a dynamic array that means that the length and size of the array are managed internally with hidden fields it is impossible to cast one dynamic array to an other and have the rtl function properly, it might be easier to extend the database component to support a pbyte and a length parameter instead of a tbytes.
I do not know how to implement, is there a sample code?
this is my code (Simplified):
unit Unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, sqlite3conn, sqldb; type TTestDB = class(TObject) SQLConn: TSQLite3Connection; SQLQuery: TSQLQuery; SQLTran: TSQLTransaction; private procedure CreateTable; public constructor Create; destructor Destroy; override; function OpenDB(FileName: string): boolean; procedure CloseDB(Save: boolean = True); function GetData(ID: integer): TBytes; procedure SetData(ID: integer; Data: TBytes); function NewRecord(Data: TBytes): integer; end; { TForm1 } TForm1 = class(TForm) procedure FormCreate(Sender: TObject); end; var Form1: TForm1; implementation {$R *.lfm} procedure Test; var FileName: string; bytes: TBytes; TestDB: TTestDB; i: integer; begin FileName := ExtractFilePath(Application.ExeName); FileName := ConcatPaths([FileName, 'test.db']); DeleteFile(FileName); TestDB := TTestDB.Create; TestDB.OpenDB(FileName); SetLength(bytes, 5 * sizeof(integer)); for i := 0 to 4 do PInteger(@bytes[i * Sizeof(integer)])^ := i + 1; // Write TestDB.NewRecord(bytes); // Read bytes := TestDB.GetData(1); for i := 0 to 4 do begin ShowMessage(IntToStr(PInteger(@bytes[i * Sizeof(integer)])^)); end; end; procedure TForm1.FormCreate(Sender: TObject); begin Test; end; constructor TTestDB.Create; var LibFile: string; AppPath: string; begin inherited Create; SQLConn := TSQLite3Connection.Create(nil); SQLTran := TSQLTransaction.Create(nil); SQLQuery := TSQLQuery.Create(nil); SQLConn.Transaction := SQLTran; SQLTran.DataBase := SQLConn; SQLQuery.DataBase := SQLConn; AppPath := ExtractFilePath(Application.ExeName); {$ifdef MSWINDOWS} LibFile := ConcatPaths([AppPath, 'lib', 'sqlite3.dll']); {$else} LibFile := ConcatPaths([AppPath, 'lib', 'libsqlite3.so']); {$endif} if FileExists(LibFile) then SQLiteLibraryName := LibFile; end; destructor TTestDB.Destroy; begin FreeAndNil(SQLQuery); FreeAndNil(SQLTran); FreeAndNil(SQLConn); inherited Destroy; end; procedure TTestDB.CreateTable; begin SQLConn.ExecuteDirect('Create Table "main"("data" Blob);'); end; function TTestDB.OpenDB(FileName: string): boolean; begin SQLConn.DatabaseName := FileName; SQLConn.Open; SQLTran.Active := True; CreateTable; end; procedure TTestDB.CloseDB(Save: boolean = True); begin if SQLTran.Active then if Save then SQLTran.Commit else SQLTran.Rollback; SQLConn.Close(True); end; function TTestDB.NewRecord(Data: TBytes): integer; begin SQLQuery.SQL.Text := 'Insert Into main (data) Values (:data)'; SQLQuery.Params.ParamByName('data').AsBytes := Data; SQLQuery.ExecSQL; SQLQuery.SQL.Text := 'Select last_insert_rowid() From main'; SQLQuery.Open; Result := SQLQuery.Fields[0].AsInteger; SQLQuery.Close; end; function TTestDB.GetData(ID: integer): TBytes; begin SQLQuery.SQL.Text := 'Select data From main where rowid=:rowid'; SQLQuery.Params.ParamByName('rowid').AsInteger := ID; SQLQuery.Open; Result := SQLQuery.Fields[0].AsBytes; SQLQuery.Close; end; procedure TTestDB.SetData(ID: integer; Data: TBytes); begin SQLQuery.SQL.Text := 'Update main Set data=:data Where rowid=:rowid'; SQLQuery.Params.ParamByName('data').AsBytes := Data; SQLQuery.Params.ParamByName('rowid').AsInteger := ID; SQLQuery.ExecSQL; end; end.
I don't know if the second method is correct, but it can work properly.A little safer with the test:
A little safer with the test: