#1 2015-07-07 08:52:03

nextglory
Member
Registered: 2015-07-07
Posts: 5

procedure TForm1.btnDeleteClick(Sender: TObject); var i:Integer; beg

When i delete TSynBigTableMetaData 's record in below way, it successfully deleted, when i open the file next time, it says error: TFileBufferReader:invalid content.
Any suggestions I'm missing or it's a bug?

procedure TForm1.btnDeleteClick(Sender: TObject);
var
  i:Integer;
begin
   i:= StrToIntDef(lstIDs.Items[lstIDs.ItemIndex],-1);

   if (i>0) and (TF.Delete(i)) then
   begin
      Caption:= Format('Deleted successful, record left is:%d',[TF.Count]);
      TF.Pack(True);
      refreshIDs;
   end
   else Caption:= 'NOT ABLE TO DELETE RECORD';
end;

Offline

#2 2015-07-07 10:02:31

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,165
Website

Re: procedure TForm1.btnDeleteClick(Sender: TObject); var i:Integer; beg

Try without the Pack()

I guess the issue is not with Delete(), but with Pack().

Offline

#3 2015-07-08 01:20:22

nextglory
Member
Registered: 2015-07-07
Posts: 5

Re: procedure TForm1.btnDeleteClick(Sender: TObject); var i:Integer; beg

Dear Administrator,

I tried removed Pack(), the problem still exists, it's strange than every time I delete the last record, it will be fine, but when i delete any of the records in between, it just failed.

here is the entire code, by the way, I'm using the version of SynBigtable v1.15  :

unit Demo_SynBigTableMetaData;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Buttons, SynBigTable, SynCommons,
  Vcl.StdCtrls, RzLabel, Vcl.Mask, RzEdit, Vcl.ExtCtrls,Jpeg,pngimage, RzLstBox,inifiles,
  System.Classes;

type
  TForm1 = class(TForm)
    OpenDialog1: TOpenDialog;
    btnOpen: TSpeedButton;
    rzlbl1: TRzLabel;
    imgPreview: TImage;
    lstIDs: TRzListBox;
    lblNotes: TRzLabel;
    btnDelete: TSpeedButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btnOpenClick(Sender: TObject);
    procedure lstIDsClick(Sender: TObject);
    procedure btnDeleteClick(Sender: TObject);
  private
    { Private declarations }
    App_Path,myFile:string;
    TF:TSynBigTableMetaData;
    App_Ini:Tinifile;
    procedure initDatabase;
    procedure refreshIDs;
    procedure readMetaTable(id:Int64);
  public
    { Public declarations }
  end;
  const
    // Sets UnixStartDate to TDateTime of 01/01/1970
    UnixStartDate: TDateTime = 25569.0;
var
  Form1: TForm1;

implementation
uses
  xMsg;
{$R *.dfm}


//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
function IsIntStr(const S: string): boolean;
begin
  Result:=StrToIntDef(S,0)=StrToIntDef(S,1);
end;

function DateTimeToUnix(ConvDate: TDateTime): Longint;
begin
  Result := Round((ConvDate - UnixStartDate) * 86400);
end;

function StrPad(inString :string; maxLength :integer; padChar :char; left :boolean) :string;
begin
  result := inString;
  while (Length(result) < maxLength) do
  if (left) then
    result := padChar + result
  else
    result := result + padChar;
end;

procedure TForm1.initDatabase;
var
  FieldChanged:Boolean;
begin
  {Initializing the database}
  TF := TSynBigTableMetaData.Create(myFile,'mdata', fmShareDenyNone);
  if TF.Table['mid'] = nil then begin
    TF.AddField('mid',tftInt64,[tfoIndex,tfoUnique]);
    FieldChanged := True;
  end;
  if TF.Table['size'] = nil then begin
    TF.AddField('size',tftInt64,[tfoIndex]);
    FieldChanged := True;
  end;
  if TF.Table['ext'] = nil then begin
    TF.AddField('ext',tftUTF8 );
    FieldChanged := True;
  end;
  if FieldChanged then TF.AddFieldUpdate;
end;

procedure TForm1.refreshIDs;
var
  i,m:Integer;
begin
  m:=0;
  lstIDs.Clear;
  lstIDs.Items.BeginUpdate;
  for i:= 0 to TF.Count-1 do begin
    m := TF.NumericalID[i];
    lstIDs.Items.Add(IntToStr(m));
  end;
  lstIDs.Items.EndUpdate;
end;

procedure TForm1.readMetaTable(id:Int64);
var
  rec: TSynTableData; {rec: variant;}
  size:integer; ext, fn:string;
  jpg:TJpegImage; png:TPngImage;
  MS:TMemoryStream;
begin
  try
    rec.Init(TF.Table );
    {fetch the record}
    TF.RecordGet(id, rec);
    ext := rec.Field['ext'];
    size:= rec.Field['size'];

    {Copy the binary to memorystream}
    MS := TMemoryStream.Create;
    MS.CopyFrom(TF.GetAsStream(id), TF.GetAsStream(id).Size);
    MS.Position:=0;

    if ext='.jpg' then
    begin
      jpg := TJpegImage.Create;
      jpg.LoadFromStream(MS);
      imgPreview.Picture.Assign(jpg);
    end else if ext='.png' then
    begin
      png := TPngImage.Create;
      png.LoadFromStream(MS);
      imgPreview.Picture.Assign(png);
    end else
    begin
      lblNotes.Caption := 'Sorry, the file cannot be displayed!!';
    end;
    lblNotes.Caption := Format('file size:%d, file type:%s', [size,ext]);
  finally
    MS.Destroy;
  end;
end;

//------------------------------------------------------------------------------
// Form Related
//------------------------------------------------------------------------------
procedure TForm1.FormCreate(Sender: TObject);
begin
  App_Path := ExtractFilePath(Application.ExeName);
  App_Ini:=Tinifile.Create(App_Path + 'config.ini');

  myFile := App_Path + 'synbigtable_metadata.test';
  Self.Left:= App_Ini.ReadInteger('main','left',0);
  Self.Top := App_Ini.ReadInteger('main','top',0);

  {Initialize database}
  initDatabase;
  {Load the ids}
  refreshIDs;
end;


procedure TForm1.FormDestroy(Sender: TObject);
begin
  App_Ini.WriteInteger('main','left',Self.Left);
  App_Ini.WriteInteger('main','top',Self.Top);
  TF.Pack(True);
  TF.Free;
end;

procedure TForm1.lstIDsClick(Sender: TObject);
var
  i:Int64;
  aData:RawByteString;
begin
  if lstIDs.ItemIndex<0 then Exit;

  i:= StrToIntDef(lstIDs.Items[lstIDs.ItemIndex],-1);
  if (i>=0) then begin
    lblNotes.Caption := Format('Selected id is:%d',[i]) ;
    readMetaTable(i);
  end
  else caption := '<INDEX ERROR>';
end;

//------------------------------------------------------------------------------
// Button actions
//------------------------------------------------------------------------------
procedure TForm1.btnOpenClick(Sender: TObject);
var
  rec: TSynTableData;
  tmp: RawByteString;
  MS: TMemoryStream;
  newId:Integer;
  fld1,fld2,fld3:TSynTableFieldProperties;
begin
  if OpenDialog1.Execute then
  begin
    try
      MS := TMemoryStream.Create;
      MS.LoadFromFile(OpenDialog1.FileName);

      SetString(tmp,PAnsiChar(MS.Memory),MS.Size);

      rec.Init(TF.Table);
      rec.Field['mid']  := DateTimeToUnix(Now);
      rec.Field['size'] := Length(tmp);
      rec.Field['ext']  := LowerCase(ExtractFileExt(OpenDialog1.FileName));

      newId := TF.RecordAdd(tmp,rec);
      if newId>0 then begin
        Caption := Format('Added file size:%d, record id is: %d',[Length(tmp), newId]) ;
      end
      else
       Caption := 'Sorry failed!';

      //TF.Pack(True);
      refreshIDs;
    finally
      MS.Free;
    end;
  end;
end;

procedure TForm1.btnDeleteClick(Sender: TObject);
var
  i:Integer;
begin
  if lstIDs.ItemIndex<0 then Exit;

  i:= StrToIntDef(lstIDs.Items[lstIDs.ItemIndex],-1);
  if (i>0) and (TF.Delete(i)) then
  begin
    imgPreview.Picture.Assign(nil);
    Caption:= Format('Deleted successful, record left is:%d, File size:%d',[TF.Count, 888]);

    //TF.Pack;
    refreshIDs;
  end
  else Caption:= Format('NOT ABLE TO DELETE RECORD: %d', [i]) ;
end;

end.

Offline

#4 2015-07-08 06:21:50

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,165
Website

Re: procedure TForm1.btnDeleteClick(Sender: TObject); var i:Integer; beg

You may try the version within the latest 1.18 nightly archive of the framework.

Offline

#5 2015-07-08 10:26:47

nextglory
Member
Registered: 2015-07-07
Posts: 5

Re: procedure TForm1.btnDeleteClick(Sender: TObject); var i:Integer; beg

hi, ad, I tried v1.18 nightly version, it not working either. I also diffed the source code, the delete() method not changed.

Here is the entire code I tested:

unit Demo_SynBigTableMetaData;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Buttons, SynBigTable, SynCommons,
  Vcl.StdCtrls, RzLabel, Vcl.Mask, RzEdit, Vcl.ExtCtrls,Jpeg,pngimage, RzLstBox,inifiles,
  System.Classes;

type
  TForm1 = class(TForm)
    OpenDialog1: TOpenDialog;
    btnOpen: TSpeedButton;
    rzlbl1: TRzLabel;
    imgPreview: TImage;
    lstIDs: TRzListBox;
    lblNotes: TRzLabel;
    btnDelete: TSpeedButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btnOpenClick(Sender: TObject);
    procedure lstIDsClick(Sender: TObject);
    procedure btnDeleteClick(Sender: TObject);
  private
    { Private declarations }
    App_Path,myFile:string;
    TF:TSynBigTableMetaData;
    App_Ini:Tinifile;
    procedure initDatabase;
    procedure refreshIDs;
    procedure readMetaTable(id:Int64);
  public
    { Public declarations }
  end;
  const
    // Sets UnixStartDate to TDateTime of 01/01/1970
    UnixStartDate: TDateTime = 25569.0;
var
  Form1: TForm1;

implementation
uses
  xMsg;
{$R *.dfm}


//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
function IsIntStr(const S: string): boolean;
begin
  Result:=StrToIntDef(S,0)=StrToIntDef(S,1);
end;

function DateTimeToUnix(ConvDate: TDateTime): Longint;
begin
  Result := Round((ConvDate - UnixStartDate) * 86400);
end;

procedure TForm1.initDatabase;
var
  FieldChanged:Boolean;
begin
  {Initializing the database}
[ins]
  TF := TSynBigTableMetaData.Create(myFile,'mdata', fmShareDenyNone);
[/ins]
  if TF.Table['mid'] = nil then begin
    TF.AddField('mid',tftInt64,[tfoIndex,tfoUnique]);
    FieldChanged := True;
  end;
  if TF.Table['size'] = nil then begin
    TF.AddField('size',tftInt64,[tfoIndex]);
    FieldChanged := True;
  end;
  if TF.Table['ext'] = nil then begin
    TF.AddField('ext',tftUTF8 );
    FieldChanged := True;
  end;
  if FieldChanged then TF.AddFieldUpdate;
end;

procedure TForm1.refreshIDs;
var
  i,m:Integer;
begin
  m:=0;
  lstIDs.Clear;
  lstIDs.Items.BeginUpdate;
[ins]
  for i:= 0 to TF.Count-1 do begin
    m := TF.NumericalID[i];
    lstIDs.Items.Add(IntToStr(m));
  end;
[/ins]
  lstIDs.Items.EndUpdate;
end;

procedure TForm1.readMetaTable(id:Int64);
var
  rec: TSynTableData; {rec: variant;}
  size:integer; ext, fn:string;
  jpg:TJpegImage; png:TPngImage;
  MS:TMemoryStream;
begin
  try
    rec.Init(TF.Table );
    {fetch the record}
    TF.RecordGet(id, rec);
    ext := rec.Field['ext'];
    size:= rec.Field['size'];

    {Copy the binary to memorystream}
    MS := TMemoryStream.Create;
    MS.CopyFrom(TF.GetAsStream(id), TF.GetAsStream(id).Size);
    MS.Position:=0;

    if ext='.jpg' then
    begin
      jpg := TJpegImage.Create;
      jpg.LoadFromStream(MS);
      imgPreview.Picture.Assign(jpg);
    end else if ext='.png' then
    begin
      png := TPngImage.Create;
      png.LoadFromStream(MS);
      imgPreview.Picture.Assign(png);
    end else
    begin
      lblNotes.Caption := 'Sorry, the file cannot be displayed!!';
    end;
    lblNotes.Caption := Format('file size:%d, file type:%s', [size,ext]);
  finally
    MS.Destroy;
  end;
end;

//------------------------------------------------------------------------------
// Form Related
//------------------------------------------------------------------------------
procedure TForm1.FormCreate(Sender: TObject);
begin
  App_Path := ExtractFilePath(Application.ExeName);
  App_Ini:=Tinifile.Create(App_Path + 'config.ini');
[ins]
  myFile := App_Path + 'synbigtable_metadata.test';
[/ins]
  Self.Left:= App_Ini.ReadInteger('main','left',0);
  Self.Top := App_Ini.ReadInteger('main','top',0);

  {Initialize database}
  initDatabase;
  {Load the ids}
  refreshIDs;
end;


procedure TForm1.FormDestroy(Sender: TObject);
begin
  App_Ini.WriteInteger('main','left',Self.Left);
  App_Ini.WriteInteger('main','top',Self.Top);
  TF.Pack(True);
  TF.Free;
end;

procedure TForm1.lstIDsClick(Sender: TObject);
var
  i:Int64;
  aData:RawByteString;
begin
  if lstIDs.ItemIndex<0 then Exit;
[ins]
  i:= StrToIntDef(lstIDs.Items[lstIDs.ItemIndex],-1);
  if (i>=0) then begin
    lblNotes.Caption := Format('Selected id is:%d',[i]) ;
    readMetaTable(i);
  end
  else caption := '<INDEX ERROR>';
[/ins]
end;

//------------------------------------------------------------------------------
// Button actions
//------------------------------------------------------------------------------
procedure TForm1.btnOpenClick(Sender: TObject);
var
  rec: TSynTableData;
  tmp: RawByteString;
  MS: TMemoryStream;
  newId:Integer;
  fld1,fld2,fld3:TSynTableFieldProperties;
begin
  if OpenDialog1.Execute then
  begin
    try
      MS := TMemoryStream.Create;
      MS.LoadFromFile(OpenDialog1.FileName);

      SetString(tmp,PAnsiChar(MS.Memory),MS.Size);
[ins]
      rec.Init(TF.Table);
      rec.Field['mid']  := DateTimeToUnix(Now);
      rec.Field['size'] := Length(tmp);
      rec.Field['ext']  := LowerCase(ExtractFileExt(OpenDialog1.FileName));
      newId := TF.RecordAdd(tmp,rec);
[/ins]

      if newId>0 then begin
        Caption := Format('Added file size:%d, record id is: %d',[Length(tmp), newId]) ;
      end
      else
       Caption := 'Sorry failed!';

      //TF.Pack(True);
      refreshIDs;
    finally
      MS.Free;
    end;
  end;
end;

procedure TForm1.btnDeleteClick(Sender: TObject);
var
  i:Integer;
begin
  if lstIDs.ItemIndex<0 then Exit;
[ins]
  i:= StrToIntDef(lstIDs.Items[lstIDs.ItemIndex],-1);
  if (i>0) and (TF.Delete(i)) then
  begin
    imgPreview.Picture.Assign(nil);
    Caption:= Format('Deleted successful, record left is:%d, File size:%d',[TF.Count, 888]);
[/ins]
    [del]//TF.Pack[/del];
    refreshIDs;
  end
  else Caption:= Format('NOT ABLE TO DELETE RECORD: %d', [i]) ;
end;

end.

Is it a real bug? any suggestions?

Andy

Offline

#6 2015-07-08 11:19:30

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,165
Website

Re: procedure TForm1.btnDeleteClick(Sender: TObject); var i:Integer; beg

This may be a bug.

We do not use SynBigTable in production here, any more.

Feedbacks and patches are welcome!

Offline

Board footer

Powered by FluxBB