Icon View Incident Report

Serious Serious
Reported By: Grzegorz Rewucki
Reported On: 7/2/2007
For: Version 1.04 Build 4
# 2400 Editing a Row Twice Can Cause #601 Corruption Error

EDB generates exception:

#601 The table TestTab is corrupt (Cannot find index page during retrieval from cache)

after second update the same record with null fields in table with defined before update trigger when trigger tries read this null fields.

How to reproduce problem:

1) Run project from attachment
2) Use Custom Edit button to change MyName value
3) Use Custom Edit button second time to change MyName field
in the same record as previously.

Maybe this is my bug but it is strange that exception doesn't occurs after insert and after first update.

procedure TForm1.Button1Click(Sender: TObject);
  var MyName: string;
begin
  if GridQuery.IsEmpty then
    Exit;
  MyName := GridQuery.FieldByName('MyName').AsString;
  if InputQuery('Custom Edit', 'My name', MyName) then
  begin
    GridQuery.Database.StartTransaction;
    try
      GridQuery.Edit;
      GridQuery.FieldByName('MyName').AsString := MyName;
      GridQuery.Post;
      GridQuery.Database.Commit;
    except
      GridQuery.Cancel;
      GridQuery.Database.Rollback;
    end;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
  var DBPath: string;
      i: Integer;
begin
  DBPath := ExtractFileDir(ParamStr(0));
  Engine.ConfigPath := DBPath;
  Engine.TempTablesPath := DBPath;
  Session.LoginUser := 'Administrator';
  Session.LoginPassword := 'EDBDefault';

  with MetaQuery do
  begin
    Close;
    DatabaseName := 'Configuration';
    SQL.Text := 'SELECT * FROM Databases WHERE Name = ''TestDB''';
    RequestSensitive := True;
    Open;

    if (RecordCount = 0) then
    begin
      Close;
      SQL.Text := 'CREATE DATABASE "TestDB" PATH ' + AnsiQuotedStr(DBPath, '''');
      ExecSQL;
    end;
    Close;

    EDB.Database := 'TestDB';
    EDB.DatabaseName := 'TestDB';
    EDB.Open;

    DatabaseName := 'TestDB';
    SQL.Text := 'SELECT * FROM Information.Tables WHERE Name = ''TestTab''';
    RequestSensitive:=True;
    Open;
    if (RecordCount = 0) then
    begin
      Close;
      SQL.Clear;
      SQL.Add('CREATE TABLE "TestTab"');
      SQL.Add('(');
      SQL.Add('"TextField" CLOB COLLATE "PLK_CI",');
      SQL.Add('"Id" GUID DEFAULT CURRENT_GUID,');
      SQL.Add('"MyName" VARCHAR(90),');
      SQL.Add('"MyInfo" VARCHAR(90),');
      SQL.Add('"MyDate" DATE DEFAULT CURRENT_DATE,');
      SQL.Add('CONSTRAINT "PK_TestTab" PRIMARY KEY ("Id")');
      SQL.Add(')');
      ExecSQL;
      Close;

      SQL.Clear;
      SQL.Add('CREATE TRIGGER "TESTTAB_BEFORE_INSERT" BEFORE INSERT ON "TestTab"');
      SQL.Add('BEGIN');
      SQL.Add('  SET NEWROW.TextField = ''''');
      SQL.Add('      +IFNULL(NEWROW.MyName,'''',CAST(NEWROW.MyName,VARCHAR(90))+#32+#13+#10)');
      SQL.Add('      +IFNULL(NEWROW.MyInfo,'''',CAST(NEWROW.MyInfo,VARCHAR(90))+#32+#13+#10)');
      SQL.Add('  ;');
      SQL.Add('END');
      ExecSQL;
      Close;

      SQL.Clear;
      SQL.Add('CREATE TRIGGER "TESTTAB_BEFORE_UPDATE" BEFORE UPDATE ON "TestTab"');
      SQL.Add('BEGIN');
      SQL.Add('  SET NEWROW.TextField = ''''');
      SQL.Add('      +IFNULL(NEWROW.MyName,'''',CAST(NEWROW.MyName,VARCHAR(90))+#32+#13+#10)');
      SQL.Add('      +IFNULL(NEWROW.MyInfo,'''',CAST(NEWROW.MyInfo,VARCHAR(90))+#32+#13+#10)');
      SQL.Add('  ;');
      SQL.Add('END');
      ExecSQL;
      Close;

      SQL.Text := 'CREATE INDEX "TestTab_MyDate_Idx" ON TestTab(MyDate)';
      ExecSQL;
      Close;

      SQL.Text := 'CREATE TEXT INDEX "TestTab_FTS_Idx" ON TestTab(TextField)';
      ExecSQL;
      Close;

    end;
    Close;
  end;

  with GridQuery do
  begin
    DatabaseName := 'TestDB';
    SQL.Text := 'SELECT * FROM TestTab ORDER BY MyDate';
    RequestSensitive:=True;
    Open;
    if IsEmpty then
    begin
      for I := 0 to 10 do
      begin
        GridQuery.Database.StartTransaction;
        try
          Insert;
          FieldByName('MyName').AsString := 'Name'+IntToStr(i);
          Post;
          GridQuery.Database.Commit;
        except
          GridQuery.Cancel;
          GridQuery.Database.Rollback;
        end;
      end;
    end;
  end;
end;



Comments Comments
The issue was caused by the transaction preventing a proper internal refresh of the row during the second Edit.


Resolution Resolution
Fixed Problem on 7/3/2007 in version 1.04 build 5


Products Affected Products Affected
ElevateDB Additional Software and Utilities
ElevateDB VCL Client-Server
ElevateDB VCL Client-Server with Source
ElevateDB VCL Standard
ElevateDB VCL Standard with Source
ElevateDB VCL Trial

Image