Icon View Incident Report

Serious Serious
Reported By: Danny Humphress
Reported On: 3/17/2004
For: Version 4.04 Build 1
# 1618 Executing Queries Inside of Custom Functions Can Result in Random AVs

I getting a mysterious access violation error that has the heading Debugger Fault Notification. If I trace through the code, everything works fine until it gets to the end of the DBISAMEngineCustomFunction handler.




function TForm1.StatusCount( ADatabasePath: string): integer;
var
  LocalSession: TDBISAMSession;
  LocalDatabase: TDBISAMDatabase;
  LocalQuery:   TDBISAMQuery;
begin
  LocalSession:=GetNewSession;
  try
    LocalDatabase:=TDBISAMDatabase.Create(nil);

    try
      with LocalDatabase do begin
        // Be sure to assign the same session name
        // as the TDBISAMSession component
        SessionName  := LocalSession.SessionName;
        DatabaseName := 'subquery';
        Directory    := ADatabasePath;
        Connected    := True;
      end;

      LocalQuery:=TDBISAMQuery.Create(nil);

      try

        with LocalQuery do begin
          // Be sure to assign the same session and
          // database name as the TDBISAMDatabase
          // component
          SessionName  := LocalSession.SessionName;
          DatabaseName := LocalDatabase.DatabaseName;
          SQL.Clear;
          SQL.Add('SELECT COUNT(*) AS TheCount FROM InvCtrl '+
                  'WHERE Number=110000');
          try
            Open;
            Result := FieldByName('TheCount').AsInteger;
          except
            Result := 0;
          end;
        end;

      finally
         LocalQuery.Free;
      end;

    finally
      LocalDatabase.Free;
    end;

  finally
    LocalSession.Free;
  end;

end;


procedure TForm1.DBISAMEngine2CustomFunction(Sender: TObject;
  const FunctionName: String; FunctionParams: TDBISAMParams;
  var Result: Variant);
begin
  if (AnsiCompareText(FunctionName,'StatusCount')=0) then begin
    try
      Result := StatusCount(FunctionParams[0].AsString);
    except on E:Exception do
      Result := null;
    end;
  end

end;

procedure TForm1.FormCreate(Sender: TObject);
begin


  with DBISAMEngine2.Functions.CreateFunction(ftInteger,
                          'StatusCount').Params do begin
    CreateFunctionParam(ftString);    // local database path
  end;

  LastSessionValue:=0;
  InitializeCriticalSection(SessionNameSection);

end;

function TForm1.GetNewSession: TDBISAMSession;
begin
  EnterCriticalSection(SessionNameSection);
  try
    Result:=TDBISAMSession.Create(nil);
    with Result do
      SessionName:='AccountSession1';
  finally
    LeaveCriticalSection(SessionNameSection);
  end;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
  DBISAMQuery1.SQL.Text := 
        'SELECT StatusCount(''c:\temp'',110000,''#CC'') FROM Test';
  DBISAMQuery1.Active:=True;
end;




Comments Comments
This problem has prompted us to change the behavior of adding custom functions. As of version 4.05 you will be required to add
all custom functions *prior* to activating the engine or else the engine will issue an exception. This bug was caused by the execution of the queries trying to reset the list of custom functions internally from those defined in the TDBISAMEngine component, and this is not feasible since it has to wipe out all previous records of the function.


Resolution Resolution
Fixed Problem on 3/18/2004 in version 4.05 build 1
Image