Browse Source

* Better transaction handling, improved ranking mechanism speed

Michaël Van Canneyt 2 years ago
parent
commit
e4ad313f8b
2 changed files with 111 additions and 19 deletions
  1. 77 12
      packages/fpindexer/src/fpindexer.pp
  2. 34 7
      packages/fpindexer/src/sqldbindexdb.pp

+ 77 - 12
packages/fpindexer/src/fpindexer.pp

@@ -67,13 +67,23 @@ type
     SearchWord: UTF8String;
     SearchWord: UTF8String;
     URL: UTF8String;
     URL: UTF8String;
   end;
   end;
+  PTSearchWordData = ^TSearchWordData;
 
 
   TFPSearch = class;
   TFPSearch = class;
 
 
   { TCustomIndexDB }
   { TCustomIndexDB }
 
 
+  TIndexLogType = (iltError, iltInfo, iltSQL);
+  TIndexLogTypes = Set of TIndexLogType;
+  TIndexLogEvent = procedure(Sender : TObject; aType: TIndexLogType; Const aMessage : string) of object;
+
   TAvailableMatch = (amAll,amExact,amContains,amStartsWith);
   TAvailableMatch = (amAll,amExact,amContains,amStartsWith);
   TCustomIndexDB = class(TComponent)
   TCustomIndexDB = class(TComponent)
+  private
+    FOnLog: TIndexLogEvent;
+  Protected
+    Procedure DoLog(aType : TIndexLogType; aMessage : String); overload;
+    Procedure DoLog(aType : TIndexLogType; const aFmt : String; args : Array of const); overload;
   public
   public
     procedure CreateDB; virtual; abstract;
     procedure CreateDB; virtual; abstract;
     procedure Connect; virtual; abstract;
     procedure Connect; virtual; abstract;
@@ -81,11 +91,14 @@ type
     procedure CompactDB; virtual; abstract;
     procedure CompactDB; virtual; abstract;
     procedure BeginTrans; virtual; abstract;
     procedure BeginTrans; virtual; abstract;
     procedure CommitTrans; virtual; abstract;
     procedure CommitTrans; virtual; abstract;
+    procedure RollbackTrans; virtual; abstract;
     procedure DeleteWordsFromFile(URL: UTF8String); virtual; abstract;
     procedure DeleteWordsFromFile(URL: UTF8String); virtual; abstract;
     procedure AddSearchData(ASearchData: TSearchWordData); virtual; abstract;
     procedure AddSearchData(ASearchData: TSearchWordData); virtual; abstract;
     procedure FindSearchData(SearchWord: TWordParser; FPSearch: TFPSearch; SearchOptions: TSearchOptions); virtual; abstract;
     procedure FindSearchData(SearchWord: TWordParser; FPSearch: TFPSearch; SearchOptions: TSearchOptions); virtual; abstract;
     Function GetAvailableWords(out aList : TUTF8StringArray; aContaining : UTF8String; Partial : TAvailableMatch) : integer;virtual; abstract;
     Function GetAvailableWords(out aList : TUTF8StringArray; aContaining : UTF8String; Partial : TAvailableMatch) : integer;virtual; abstract;
     procedure CreateIndexerTables; virtual; abstract;
     procedure CreateIndexerTables; virtual; abstract;
+    procedure ClearIndexerTables; virtual; abstract;
+    Property OnLog : TIndexLogEvent Read FOnLog Write FOnLog;
   end;
   end;
 
 
   TDatabaseID = record
   TDatabaseID = record
@@ -166,6 +179,7 @@ type
     function GetUrlSQL(UseParams: boolean = True): UTF8String; virtual;
     function GetUrlSQL(UseParams: boolean = True): UTF8String; virtual;
     function GetWordSQL(UseParams: boolean = True): UTF8String; virtual;
     function GetWordSQL(UseParams: boolean = True): UTF8String; virtual;
     function InsertSQL(const TableType: TIndexTable; UseParams: boolean = True): UTF8String; virtual;
     function InsertSQL(const TableType: TIndexTable; UseParams: boolean = True): UTF8String; virtual;
+    function ClearTableSQl(const TableType: TIndexTable) : UTF8String; virtual;
     Function AvailableWordsSQL(aContaining : UTF8String; Partial : TAvailableMatch) : UTF8String; virtual;
     Function AvailableWordsSQL(aContaining : UTF8String; Partial : TAvailableMatch) : UTF8String; virtual;
     procedure FinishCreateTable(const TableType: TIndexTable); virtual;
     procedure FinishCreateTable(const TableType: TIndexTable); virtual;
     procedure FinishDropTable(const TableType: TIndexTable); virtual;
     procedure FinishDropTable(const TableType: TIndexTable); virtual;
@@ -176,6 +190,7 @@ type
   public
   public
     procedure CreateIndexerTables; override;
     procedure CreateIndexerTables; override;
     procedure DeleteWordsFromFile(URL: UTF8String); override;
     procedure DeleteWordsFromFile(URL: UTF8String); override;
+    procedure ClearIndexerTables; override;
   end;
   end;
 
 
   TCustomFileReader = class;
   TCustomFileReader = class;
@@ -363,10 +378,12 @@ type
     FOptions: TSearchOptions;
     FOptions: TSearchOptions;
     FRankedCount: integer;
     FRankedCount: integer;
     FSearchWord: TWordParser;
     FSearchWord: TWordParser;
+    FUsePositionInRank: Boolean;
     ResultList: array of TSearchWordData;
     ResultList: array of TSearchWordData;
     RankedList: array of TSearchWordData;
     RankedList: array of TSearchWordData;
     function GetRankedResults(index: integer): TSearchWordData;
     function GetRankedResults(index: integer): TSearchWordData;
     function GetResults(index: integer): TSearchWordData;
     function GetResults(index: integer): TSearchWordData;
+    function SameRank(aIdx1, aIdx2: Integer): Boolean;
     procedure SetDatabase(AValue: TCustomIndexDB);
     procedure SetDatabase(AValue: TCustomIndexDB);
     procedure RankResults;
     procedure RankResults;
     procedure SetRankedCount(AValue: integer);
     procedure SetRankedCount(AValue: integer);
@@ -386,6 +403,7 @@ type
     property Database: TCustomIndexDB read FDatabase write SetDatabase;
     property Database: TCustomIndexDB read FDatabase write SetDatabase;
     property Options: TSearchOptions read FOptions write FOptions;
     property Options: TSearchOptions read FOptions write FOptions;
     property SearchWord: TWordParser read FSearchWord;
     property SearchWord: TWordParser read FSearchWord;
+    Property UsePositionInRank : Boolean Read FUsePositionInRank Write FUsePositionInRank;
   end;
   end;
 
 
   { TIgnoreListDef }
   { TIgnoreListDef }
@@ -618,6 +636,18 @@ end;
 
 
 { TCustomIndexDB }
 { TCustomIndexDB }
 
 
+procedure TCustomIndexDB.DoLog(aType: TIndexLogType; aMessage: String);
+begin
+  if Assigned(FOnLog) then
+    FonLog(Self,aType,aMessage);
+end;
+
+procedure TCustomIndexDB.DoLog(aType: TIndexLogType; const aFmt: String;
+  args: array of const);
+begin
+  DoLog(aType,Format(aFmt,args));
+end;
+
 procedure TCustomIndexDB.Disconnect;
 procedure TCustomIndexDB.Disconnect;
 begin
 begin
   // Do nothing
   // Do nothing
@@ -755,6 +785,15 @@ begin
   FDatabase := AValue;
   FDatabase := AValue;
 end;
 end;
 
 
+function TFPSearch.SameRank(aIdx1, aIdx2: Integer): Boolean;
+
+begin
+  Result:=True;
+  if UsePositionInRank then
+    Result:=RankedList[aIdx1].Position <> ResultList[aIdx2].Position;
+  Result:=Result and  (RankedList[aIdx1].URL <> ResultList[aIdx2].URL)
+end;
+
 procedure TFPSearch.RankResults;
 procedure TFPSearch.RankResults;
 var
 var
   i: integer;
   i: integer;
@@ -771,17 +810,16 @@ var
   end;
   end;
 
 
 begin
 begin
-  for i := 0 to FCount - 1 do
+
+  if FCount=0 then
+    exit;
+  AddNewRankedItem(ResultList[i]);
+  for i := 1 to FCount - 1 do
   begin
   begin
-    if FRankedCount > 0 then
-    begin
-      if RankedList[FRankedCount - 1].URL <> ResultList[i].URL then
-        AddNewRankedItem(ResultList[i])
-      else
-        RankedList[FRankedCount - 1].Rank := RankedList[FRankedCount - 1].Rank+ 1;
-    end
+    if SameRank(I,FRankedCount-1)  then
+      Inc(RankedList[FRankedCount-1].Rank)
     else
     else
-      AddNewRankedItem(ResultList[i]);
+      AddNewRankedItem(ResultList[i])
   end;
   end;
 
 
   //sort ranked list
   //sort ranked list
@@ -808,7 +846,8 @@ begin
   if FRankedCount = AValue then
   if FRankedCount = AValue then
     Exit;
     Exit;
   FRankedCount := AValue;
   FRankedCount := AValue;
-  SetLength(RankedList, AValue);
+  If FRankedCount>Length(RankedList) then
+    SetLength(RankedList, AValue);
 end;
 end;
 
 
 procedure TFPSearch.AddResult(index: integer; AValue: TSearchWordData);
 procedure TFPSearch.AddResult(index: integer; AValue: TSearchWordData);
@@ -830,7 +869,8 @@ begin
   FSearchWord.WildCardChar := '%';   //should come from DataBase
   FSearchWord.WildCardChar := '%';   //should come from DataBase
 end;
 end;
 
 
-Function TFPSearch.GetAvailableWords(out aList : TUTF8StringArray; aContaining: UTF8String; Partial: TAvailableMatch) : Integer;
+function TFPSearch.GetAvailableWords(out aList: TUTF8StringArray;
+  aContaining: UTF8String; Partial: TAvailableMatch): Integer;
 begin
 begin
   Database.Connect;
   Database.Connect;
   Result:=Database.GetAvailableWords(aList, aContaining, Partial);
   Result:=Database.GetAvailableWords(aList, aContaining, Partial);
@@ -843,7 +883,10 @@ end;
 
 
 function TFPSearch.GetRankedResults(index: integer): TSearchWordData;
 function TFPSearch.GetRankedResults(index: integer): TSearchWordData;
 begin
 begin
-  Result := RankedList[index];
+  if Index<FRankedCount then
+    Result := RankedList[index]
+  else
+    Result:=Default(TSearchWordData);
 end;
 end;
 
 
 constructor TFPSearch.Create(AOwner: TComponent);
 constructor TFPSearch.Create(AOwner: TComponent);
@@ -864,6 +907,7 @@ begin
   //reset previous searches
   //reset previous searches
   FCount := 0;
   FCount := 0;
   SetLength(ResultList, FCount);
   SetLength(ResultList, FCount);
+  RankedCount:=0;
   Database.Connect;
   Database.Connect;
   Database.FindSearchData(SearchWord, Self, Options);
   Database.FindSearchData(SearchWord, Self, Options);
   Result := Count;
   Result := Count;
@@ -1644,6 +1688,11 @@ begin
   Result := Format('INSERT INTO %s (%s) VALUES (%s)', [GetTableName(TableType), FL, VL]);
   Result := Format('INSERT INTO %s (%s) VALUES (%s)', [GetTableName(TableType), FL, VL]);
 end;
 end;
 
 
+function TSQLIndexDB.ClearTableSQl(const TableType: TIndexTable): UTF8String;
+begin
+  Result:='delete from '+GetTablename(TableType);
+end;
+
 function TSQLIndexDB.AvailableWordsSQL(aContaining: UTF8String; Partial: TAvailableMatch): UTF8String;
 function TSQLIndexDB.AvailableWordsSQL(aContaining: UTF8String; Partial: TAvailableMatch): UTF8String;
 
 
 begin
 begin
@@ -1780,6 +1829,22 @@ begin
     Execute(Format(DeleteWordsSQL(False), [FID]), False);
     Execute(Format(DeleteWordsSQL(False), [FID]), False);
 end;
 end;
 
 
+procedure TSQLIndexDB.ClearIndexerTables;
+begin
+  BeginTrans;
+  Execute(ClearTableSQl(itMatches),True);
+  CommitTrans;
+  BeginTrans;
+  Execute(ClearTableSQl(itWords),True);
+  CommitTrans;
+  BeginTrans;
+  Execute(ClearTableSQl(itFiles),True);
+  CommitTrans;
+  BeginTrans;
+  Execute(ClearTableSQl(itLanguages),True);
+  CommitTrans;
+end;
+
 initialization
 initialization
   FileHandlers := TFileHandlersManager.Create;
   FileHandlers := TFileHandlersManager.Create;
   IgnoreListManager := TIgnoreListManager.Create(nil);
   IgnoreListManager := TIgnoreListManager.Create(nil);

+ 34 - 7
packages/fpindexer/src/sqldbindexdb.pp

@@ -70,6 +70,8 @@ type
     procedure BeginTrans; override;
     procedure BeginTrans; override;
     procedure CommitTrans; override;
     procedure CommitTrans; override;
     procedure CompactDB; override;
     procedure CompactDB; override;
+    procedure RollbackTrans; override;
+    Procedure ClearTables;
     procedure AddSearchData(ASearchData: TSearchWordData); override;
     procedure AddSearchData(ASearchData: TSearchWordData); override;
     procedure FindSearchData(SearchWord: TWordParser; FPSearch: TFPSearch; SearchOptions: TSearchOptions); override;
     procedure FindSearchData(SearchWord: TWordParser; FPSearch: TFPSearch; SearchOptions: TSearchOptions); override;
     function GetAvailableWords(out aList : TUTF8StringArray; aContaining : UTF8String; Partial : TAvailableMatch) : integer;override;
     function GetAvailableWords(out aList : TUTF8StringArray; aContaining : UTF8String; Partial : TAvailableMatch) : integer;override;
@@ -119,7 +121,7 @@ begin
 end;
 end;
 
 
 
 
-function TSQLDBIndexDB.GetLanguageID(const ALanguage: UTF8String): int64;
+function TSQLDBIndexDB.GetLanguageID(const ALanguage: UTF8string): int64;
 var
 var
   Q: TSQLQuery;
   Q: TSQLQuery;
 begin
 begin
@@ -277,7 +279,8 @@ begin
   end;
   end;
 end;
 end;
 
 
-Function TSQLDBIndexDB.GetAvailableWords(out aList : TUTF8StringArray; aContaining: UTF8String; Partial: TAvailableMatch) : Integer;
+function TSQLDBIndexDB.GetAvailableWords(out aList: TUTF8StringArray;
+  aContaining: UTF8String; Partial: TAvailableMatch): integer;
 
 
 Var
 Var
   Q : TSQLQuery;
   Q : TSQLQuery;
@@ -317,18 +320,19 @@ begin
   FLastURL := '';
   FLastURL := '';
 end;
 end;
 
 
-procedure TSQLDBIndexDB.Execute(const sql: UTF8String; ignoreErrors: boolean = True);
+procedure TSQLDBIndexDB.Execute(const sql: UTF8string; ignoreErrors: boolean);
 begin
 begin
   if SQL = '' then
   if SQL = '' then
     exit;
     exit;
   try
   try
     FDB.ExecuteDirect(sql);
     FDB.ExecuteDirect(sql);
+    FDB.Transaction.Commit;
   except
   except
     on E : exception do
     on E : exception do
-      if not IgnoreErrors then
-        raise
+      if IgnoreErrors then
+        DoLog(iltError,'Exception %s while executing query "%s" : %s',[E.ClassName,Sql,E.Message]);
       else
       else
-        // Writeln(E.ClassName,' : ',E.Message);
+        raise
   end;
   end;
 end;
 end;
 
 
@@ -364,7 +368,8 @@ end;
 
 
 procedure TSQLDBIndexDB.BeginTrans;
 procedure TSQLDBIndexDB.BeginTrans;
 begin
 begin
-  FDB.Transaction.StartTransaction;
+  if not FDB.Transaction.Active then
+    FDB.Transaction.StartTransaction;
 end;
 end;
 
 
 procedure TSQLDBIndexDB.CommitTrans;
 procedure TSQLDBIndexDB.CommitTrans;
@@ -381,5 +386,27 @@ begin
   //not yet implemented
   //not yet implemented
 end;
 end;
 
 
+procedure TSQLDBIndexDB.RollbackTrans;
+
+Var
+  T : TCachedQueryType;
+begin
+  For T:=Low(TCachedQueryType) to High(TCachedQueryType) do
+    FreeAndNil(FQueries[T]);
+  FDB.Transaction.RollBack;
+end;
+
+procedure TSQLDBIndexDB.ClearTables;
+begin
+  BeginTrans;
+  try
+    ClearIndexerTables;
+    CommitTrans;
+  except
+    RollBackTrans;
+    Raise;
+  end;
+end;
+
 end.
 end.