{$IfDef FPC}{$CodePage cp1251}{$EndIf FPC}
unit m3AttrIndexSearcher;
// --------------------------------------------------------------------------
// Родители: "SearchByAttributes" <> MUID: (66C47D3E0363) :: "m3" <> MUID: (548712F60101) :: "Shared Delphi Low Level" <> MUID: (4ABCC25A0322)
// --------------------------------------------------------------------------
// Модуль: "w:\common\components\rtl\Garant\m3\m3AttrIndexSearcher.pas" GeneratorVersion: 1.0.0.883901
// Стереотип: "<>"
// Элемент модели: "Tm3AttrIndexSearcher" MUID: (66C47DB501FB)
// --------------------------------------------------------------------------
//#UC START# *66C47DB501FBbeforeDefines*
//#UC END# *66C47DB501FBbeforeDefines*
{$Include m3Define.inc}
interface
uses
l3IntfUses
, l3CProtoObject
, m3AttrIndexInterfaces
, m3SearcherInterfaces
, l3Variant
, m3DBInterfaces
, m3DocumentStorageCacher
, m3AttrIndexDumpersCache
, l3CoreInterfaces
, l3Interfaces
, m3StorageInterfaces
, l3Ranges
, l3MarshalledTypes
, l3StringsEnumerator
, l3Enumerators
, l3PrimString
, l3Date
//#UC START# *66C47DB501FBintf_uses*
, k2Tags
;
const
m3MandatoryAttributes = [
k2_tiExternalHandle,
k2_tiType,
k2_tiUserType,
k2_tiExternalVerLink,
k2_tiRelExternalHandle,
k2_tiRelInternalHandle,
k2_tiExternalNextVerLink
]
//#UC END# *66C47DB501FBintf_uses*
;
type
//#UC START# *66C47DB501FBci*
//#UC END# *66C47DB501FBci*
Tm3AttrIndexSearcher = class(Tl3CProtoObject, Im3AttrIndexSearcher)
private
f_BaseName: AnsiString;
f_PrevDumper: Im3AttrIndexDumper;
f_PrevAttr: Integer;
f_PrevDirect: Boolean;
f_DocumentHeaderData: Il3TagRef;
f_PrevDocID: Integer;
f_DB: Im3DB;
f_DumpersCache: Tm3AttrIndexDumpersCache;
{$If Defined(m3UseCacher)}
f_Cacher: Tm3DocumentStorageCacher;
{$IfEnd} // Defined(m3UseCacher)
private
function GetDocumentString(anAttrID: Integer;
aDocID: Tm3DocID): Il3CString;
procedure WriteDocumentString(anAttrID: Integer;
aDocID: Tm3DocID;
const aString: Il3CString);
function OpenDocStream(aDocID: Tm3DocID;
aMode: Tm3StoreAccess;
aDocPart: Tm3DocPartSelector;
aIndex: Integer): IStream;
protected
{$If Defined(m3UseCacher)}
function pm_GetCacher: Tm3DocumentStorageCacher;
{$IfEnd} // Defined(m3UseCacher)
function MakeDumper(anAttrID: Integer;
aDirect: Boolean): Im3AttrIndexDumper;
function SearchByKey(anAttrID: Integer;
aKey: Integer;
aDirect: Boolean): Il3RangeEnumerable; overload;
{* Ищет по ключу в индексе для атрнибута }
function ExternalHandleToInternalHandle(anID: Tm3DocID): Tm3DocID;
function InternalHandleToExternalHandle(anID: Tm3DocID): Tm3DocID;
function SearchFirstByKey(anAttrID: Integer;
aKey: Integer;
aDirect: Boolean): Integer;
function RelExternalHandleToInternalHandle(anID: Tm3DocID): Tm3DocID;
function InternalHandleToRelExternalHandle(anID: Tm3DocID): Tm3DocID;
function SearchByKeys(anAttrID: Integer;
const aKeys: Il3IntegerEnumerable): Il3RangeEnumerable; overload;
function NameByInternalHandle(anID: Tm3DocID): Il3CString;
function TypeByID(anID: Tm3DocID): TDocType;
function UserTypeByID(anID: Tm3DocID): TUserType;
function NameByID(anID: Tm3DocID): Il3CString;
function AllDocuments: Il3RangeEnumerable;
{* Все документы базы }
function IsRelated(anID: Tm3DocID): Boolean;
{* Определяет - является ли документ справкой. }
function ConstDocuments: Il3RangeEnumerable;
{* Документы из постояной части }
function ModifiedDocuments: Il3RangeEnumerable;
{* Документы из переменной части }
function IsSpravka(anID: Tm3DocID): Boolean;
function DeletedDocuments: Il3RangeEnumerable;
{* Удалённые документы }
function AllRelated: Il3RangeEnumerable;
{* Все справки }
function ConstRelated: Il3RangeEnumerable;
{* Справки в постоянной части }
function ModifiedRelated: Il3RangeEnumerable;
{* Справки в переменной части }
function IsAnnoOnly(anID: Tm3DocID): Boolean;
{* Документ содержит ТОЛЬКО аннотацию. Несколько "техническая" ручка. Обычно такой ситуации не должно быть. Но пусть будет }
function SearcheableAttributesNames: Il3StringsEnumerable;
{* Имена атрибутов для поиска }
function SearchByKeyEx(const anAttrID: array of Integer;
aKey: Integer;
aDirect: Boolean): Il3RangeEnumerable;
{* Ищет по ключу "иерархического" атрибута. Т.е. указывается "путь" в EVD. Сродни cAtomEx }
function ContextAttributesNames: Il3StringsEnumerable;
function SearchByKey(anAttrID: Integer;
aKey: Tl3PrimString): Il3RangeEnumerable; overload;
function SearchByKey(anAttrID: Integer;
const aKey: AnsiString): Il3RangeEnumerable; overload;
function SearchByKey(anAttrID: Integer;
const aKey: Tl3WString): Il3RangeEnumerable; overload;
function SearchByKeys(anAttrID: Integer;
const aKeys: Il3StringsEnumerable): Il3RangeEnumerable; overload;
function OutLinks(anID: Tm3DocID): Il3RangeEnumerable;
{* Исходящие ссылки. Респонденты. }
function InLinks(anID: Tm3DocID): Il3RangeEnumerable;
{* Входящие ссылки. Корреспонденты. }
function SearchByNumberType(aNumberType: TDNType): Il3RangeEnumerable;
function SearchByNumber(const aNumber: AnsiString): Il3RangeEnumerable;
function SearchBetweenKeys(const anAttrID: array of Integer;
aLowKey: Integer;
aHighKey: Integer;
aDirect: Boolean): Il3RangeEnumerable;
function SearchByDates(aFrom: TStDate;
aTo: TStDate): Il3RangeEnumerable;
function CommentByInternalHandle(anID: Tm3DocID): Il3CString;
function CommentByID(anID: Tm3DocID): Il3CString;
function Versions(anID: Tm3DocID): Il3IntegerEnumerable;
{* Версии документа. Включая сам документ }
function DocumentHeaderData(anID: Tm3DocID): Il3TagRef;
{* Данные заголовка документа. Например ActiveIntervals и NumAndDates }
function SearchByType(aDocType: TDocType): Il3RangeEnumerable;
function SearchByMaskInKey(anAttrID: Integer;
aMask: Integer): Il3RangeEnumerable;
{* https://mdp.garant.ru/pages/viewpage.action?pageId=877071294 }
function SearchByMaskInPriceLevel(aMask: Integer): Il3RangeEnumerable;
function IndexTimeStamp(anAttrID: Integer;
aDirect: Boolean): TDateTime;
procedure Cleanup; override;
{* Функция очистки полей объекта. }
procedure ClearFields; override;
public
constructor Create(const aBaseName: AnsiString); reintroduce; overload;
class function Make(const aBaseName: AnsiString): Im3AttrIndexSearcher; reintroduce; overload;
constructor Create(const aDB: Im3DB); reintroduce; overload;
class function Make(const aDB: Im3DB): Im3AttrIndexSearcher; reintroduce; overload;
{$If Defined(m3UseCacher)}
constructor Create(aCacher: Tm3DocumentStorageCacher); reintroduce; overload;
{$IfEnd} // Defined(m3UseCacher)
{$If Defined(m3UseCacher)}
class function Make(aCacher: Tm3DocumentStorageCacher): Im3AttrIndexSearcher; reintroduce; overload;
{$IfEnd} // Defined(m3UseCacher)
{$If NOT Defined(l3NoSRT)}
function SetRefTo(var thePlace: Tm3AttrIndexSearcher): Boolean; overload; {$If Defined(l3HasInl)}inline;{$IfEnd}
{$IfEnd} // NOT Defined(l3NoSRT)
private
{$If Defined(m3UseCacher)}
property Cacher: Tm3DocumentStorageCacher
read pm_GetCacher;
{$IfEnd} // Defined(m3UseCacher)
//#UC START# *66C47DB501FBpubl*
private
{$IfDef FPC}
class var f_SearcheableAttributesNames: Il3StringsEnumerable;
class var f_ContextAttributesNames: Il3StringsEnumerable;
{$EndIf FPC}
f_WasException : Boolean;
public
{$IfDef FPC}
class destructor done;
{$EndIf FPC}
constructor CreateFromDumper(const aDumper: Im3AttrIndexDumper;
anAttrID: Integer;
aDirect: Boolean);
class function MakeFromDumper(const aDumper: Im3AttrIndexDumper;
anAttrID: Integer;
aDirect: Boolean): Im3AttrIndexSearcher;
//#UC END# *66C47DB501FBpubl*
end;//Tm3AttrIndexSearcher
implementation
uses
l3ImplUses
, m3IndexDumper
, m3DBHelper
, m3DocumentInfoExtractor
, m3DocumentsMap
, m3DocumentsCache
, m3AttrIndexDumperJoin
, m3AttrIndexDumper
, l3SharedConstString
, k2DocumentHeaderBuffer
, m3ExternalIDtoInternalIDMap
//#UC START# *66C47DB501FBimpl_uses*
{$IfNDef FPC}
, Windows
{$EndIf FPC}
, SysUtils
, Classes
, Math
, DateUtils
, l3Core
, l3Types
, l3Chars
, l3CEmptyString
, l3String
, l3Bits
, l3Except
, l3StoreInterfaces
, l3_String
, l3StringList
, l3LongintList
, k2Attributes
, k2TagGen
, evdNativeReader
, m2COMLib
, m3Exceptions
, m3DB
, m3SplittedFileStream
, m3RangedDocumentsList
, m4SearchEx
, m4SimpleExpression
, m4Search
, m4SearchResult
, m3FirstTextExtractor
, m3DBTools
, m3CachersService
{$IfDef Archi}
{$IfDef AppClientSide}
, ddClientBaseEngine
{$EndIf AppClientSide}
{$EndIf Archi}
{$Define m3UseHeaderForName}
{$Define m3UseTypeForAllRelated}
{$Define m3UseTypeForAllDocuments}
//#UC END# *66C47DB501FBimpl_uses*
;
{$If Defined(m3UseCacher)}
function Tm3AttrIndexSearcher.pm_GetCacher: Tm3DocumentStorageCacher;
//#UC START# *68FF50220066_66C47DB501FBget_var*
//#UC END# *68FF50220066_66C47DB501FBget_var*
begin
//#UC START# *68FF50220066_66C47DB501FBget_impl*
if (f_Cacher = nil) then
begin
if (f_DB = nil) then
f_Cacher := Tm3DocumentStorageCacher.Create(Tm3DB.Make(f_BaseName), 0)
else
f_Cacher := Tm3DocumentStorageCacher.Create(f_DB, 0);
end;//f_Cacher = nil
Result := f_Cacher;
//#UC END# *68FF50220066_66C47DB501FBget_impl*
end;//Tm3AttrIndexSearcher.pm_GetCacher
{$IfEnd} // Defined(m3UseCacher)
constructor Tm3AttrIndexSearcher.Create(const aBaseName: AnsiString);
//#UC START# *66C47E91011E_66C47DB501FB_var*
//#UC END# *66C47E91011E_66C47DB501FB_var*
begin
//#UC START# *66C47E91011E_66C47DB501FB_impl*
f_WasException := false;
if (f_PrevDumper = nil) then
begin
f_PrevAttr := -1;
f_PrevDirect := false;
Assert(aBaseName <> '');
end;//f_PrevDumper = nil
f_PrevDocID := -1;
f_DocumentHeaderData := nil;
f_BaseName := aBaseName;
f_BaseName := Tm3SplittedFileStream.NormalizeFileName(f_BaseName);
f_BaseName := ChangeFileExt(f_BaseName, '');
inherited Create;
//#UC END# *66C47E91011E_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.Create
class function Tm3AttrIndexSearcher.Make(const aBaseName: AnsiString): Im3AttrIndexSearcher;
var
l_Inst : Tm3AttrIndexSearcher;
begin
l_Inst := Create(aBaseName);
try
Result := l_Inst;
finally
l_Inst.Free;
end;//try..finally
end;//Tm3AttrIndexSearcher.Make
constructor Tm3AttrIndexSearcher.Create(const aDB: Im3DB);
//#UC START# *67A3B7240286_66C47DB501FB_var*
//#UC END# *67A3B7240286_66C47DB501FB_var*
begin
//#UC START# *67A3B7240286_66C47DB501FB_impl*
Assert(aDB <> nil);
Create(aDB.xBaseName);
f_DB := aDB;
//#UC END# *67A3B7240286_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.Create
class function Tm3AttrIndexSearcher.Make(const aDB: Im3DB): Im3AttrIndexSearcher;
var
l_Inst : Tm3AttrIndexSearcher;
begin
l_Inst := Create(aDB);
try
Result := l_Inst;
finally
l_Inst.Free;
end;//try..finally
end;//Tm3AttrIndexSearcher.Make
function Tm3AttrIndexSearcher.MakeDumper(anAttrID: Integer;
aDirect: Boolean): Im3AttrIndexDumper;
//#UC START# *67AB413203A3_66C47DB501FB_var*
var
l_Dumper : Im3AttrIndexDumper;
l_Key : Tm3AttrIndexDumperKey;
l_Index : Integer;
//#UC END# *67AB413203A3_66C47DB501FB_var*
begin
//#UC START# *67AB413203A3_66C47DB501FB_impl*
l_Key := Tm3AttrIndexDumperKey_C(anAttrID, aDirect);
if (f_DumpersCache <> nil) then
if f_DumpersCache.Has(l_Key, l_Index) then
begin
Result := f_DumpersCache.ValueByIndex(l_Index);
Exit;
end;//f_DumpersCache.Has(l_Key, l_Index)
if (f_PrevDumper <> nil)
AND (f_PrevAttr = anAttrID)
AND (f_PrevDirect = aDirect)
then
l_Dumper := f_PrevDumper
else
l_Dumper := Tm3AttrIndexDumperJoin.MakeForAttribute(Self.f_BaseName, anAttrID, aDirect);
try
if (l_Dumper <> nil) then
begin
f_PrevAttr := anAttrID;
f_PrevDirect := aDirect;
f_PrevDumper := l_Dumper;
end;//l_Dumper <> nil
Result := l_Dumper;
finally
l_Dumper := nil;
end;//try..finally
if (f_DumpersCache = nil) then
f_DumpersCache := Tm3AttrIndexDumpersCache.Create;
f_DumpersCache.Add(l_Key, Result);
//#UC END# *67AB413203A3_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.MakeDumper
function Tm3AttrIndexSearcher.GetDocumentString(anAttrID: Integer;
aDocID: Tm3DocID): Il3CString;
//#UC START# *68EF6D26029F_66C47DB501FB_var*
var
(* l_DB : Im3DB;
l_Doc : Im3DBDocument;*)
l_DocStream : IStream;
l_Size : Int64;
l_Len : Int64;
l_S : Tl3_String;
//#UC END# *68EF6D26029F_66C47DB501FB_var*
begin
//#UC START# *68EF6D26029F_66C47DB501FB_impl*
Result := nil;
(* if (Self.f_DB <> nil) then
l_DB := Self.f_DB
else
l_DB := Tm3DB.Make(f_BaseName);
try
l_Doc := l_DB.GetDocument(aDocID);
if (l_Doc <> nil) then*)
begin
l_DocStream := Self.OpenDocStream(aDocID, m3_saRead, m3_dsNames, anAttrID);
//l_DocStream := l_Doc.Open(m3_saRead, m3_dsNames, anAttrID);
try
if (l_DocStream <> nil) then
begin
l_Size := m2COMGetSize(l_DocStream);
if (l_Size < 0) then
begin
Result := Tl3CEmptyString.Instance;
Exit;
end//l_Size < 0
else
if ((l_Size mod 2) <> 0) then
begin
Result := Tl3CEmptyString.Instance;
Exit;
end;//(l_Size mod 2) <> 0
Assert((l_Size mod 2) = 0);
if (l_Size = 0) then
Result := Tl3CEmptyString.Instance
else
if (l_Size > 0) then
begin
l_Len := l_Size div 2;
l_S := Tl3_String.Create;
try
l_S.CodePage := CP_Unicode;
l_S.Len := l_Len;
Assert(l_S.CodePage = CP_Unicode);
m2COMReadBuffer(l_DocStream, l_S.St^, l_Size);
l_S.CheckUnicode(true);
Result := l_S.AsCStr;
finally
FreeAndNil(l_S);
end;//try..finally
end;//l_Size > 0
end;//l_DocStream <> nil
finally
l_DocStream := nil;
end;//try..finally
end;//l_Doc <> nil
(* finally
l_DB := nil;
end;//try..finally*)
//#UC END# *68EF6D26029F_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.GetDocumentString
procedure Tm3AttrIndexSearcher.WriteDocumentString(anAttrID: Integer;
aDocID: Tm3DocID;
const aString: Il3CString);
//#UC START# *68F0B95202A8_66C47DB501FB_var*
var
l_DB : Im3DB;
l_S : Tl3WString;
//#UC END# *68F0B95202A8_66C47DB501FB_var*
begin
//#UC START# *68F0B95202A8_66C47DB501FB_impl*
if (aString = nil) then
Exit;
{$IfDef Archi}
{$IfDef AppClientSide}
//if false then
if (g_BaseEngine <> nil) then
if g_BaseEngine.WorkWithServer then
Exit;
{$EndIf AppClientSide}
{$EndIf Archi}
if (GetCurrentThreadID <> MainThreadID) then
Exit;
if f_WasException then
// - guiard of deadlocks
Exit;
if (Self.f_DB <> nil) then
l_DB := Self.f_DB
else
l_DB := Tm3DB.Make(f_BaseName);
try
l_S := aString.AsWStr;
//if l3IsNil(l_S) then
// Exit;
m3WriteStringToDocument(l_DB, aDocID, anAttrID, l_S);
finally
l_DB := nil;
end;//try..finally
//#UC END# *68F0B95202A8_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.WriteDocumentString
function Tm3AttrIndexSearcher.OpenDocStream(aDocID: Tm3DocID;
aMode: Tm3StoreAccess;
aDocPart: Tm3DocPartSelector;
aIndex: Integer): IStream;
//#UC START# *68FF51A101F5_66C47DB501FB_var*
var
{$IfDef m3UseCacher}
l_Cacher: Tm3DocumentStorageCacher;
{$EndIf m3UseCacher}
l_Doc : Im3DBDocument;
//#UC END# *68FF51A101F5_66C47DB501FB_var*
begin
//#UC START# *68FF51A101F5_66C47DB501FB_impl*
Result := nil;
if (f_DB <> nil) then
begin
if f_DB.IsExclusive then
begin
l_Doc := f_DB.GetDocument(aDocID);
if (l_Doc <> nil) then
Result := l_Doc.Open(aMode, aDocPart, aIndex);
Exit;
end;//f_DB.IsExclusive
end;//f_DB <> nil
{$IfDef m3UseCacher}
l_Cacher := Self.Cacher;
l_Cacher.DocID := aDocID;
try
Result := l_Cacher.OpenDocStream(aMode, aDocPart, aIndex);
except
on Em3RegionLocked do
begin
if Tm3CachersService.Exists then
Tm3CachersService.Instance.CloseCachers(aDocID);
try
Result := l_Cacher.OpenDocStream(aMode, aDocPart, aIndex);
except
on Em3RegionLocked do
begin
Result := nil;
end;//on Em3RegionLocked
end;//try..except
end;//on Em3RegionLocked
else
// - maybe wrong sav
Result := nil;
end;//try..except
{$Else m3UseCacher}
if (f_DB = nil) then
l_Doc := Tm3DB.Make(f_BaseName).GetDocument(aDocID)
else
l_Doc := f_DB.GetDocument(aDocID);
if (l_Doc <> nil) then
Result := l_Doc.Open(aMode, aDocPart, aIndex);
{$EndIf m3UseCacher}
//#UC END# *68FF51A101F5_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.OpenDocStream
{$If Defined(m3UseCacher)}
constructor Tm3AttrIndexSearcher.Create(aCacher: Tm3DocumentStorageCacher);
//#UC START# *69020AF40205_66C47DB501FB_var*
//#UC END# *69020AF40205_66C47DB501FB_var*
begin
//#UC START# *69020AF40205_66C47DB501FB_impl*
Assert(aCacher <> nil);
aCacher.SetRefTo(f_Cacher);
Create(aCacher.DB);
//#UC END# *69020AF40205_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.Create
{$IfEnd} // Defined(m3UseCacher)
{$If Defined(m3UseCacher)}
class function Tm3AttrIndexSearcher.Make(aCacher: Tm3DocumentStorageCacher): Im3AttrIndexSearcher;
var
l_Inst : Tm3AttrIndexSearcher;
begin
l_Inst := Create(aCacher);
try
Result := l_Inst;
finally
l_Inst.Free;
end;//try..finally
end;//Tm3AttrIndexSearcher.Make
{$IfEnd} // Defined(m3UseCacher)
{$If NOT Defined(l3NoSRT)}
function Tm3AttrIndexSearcher.SetRefTo(var thePlace: Tm3AttrIndexSearcher): Boolean;
begin
if (thePlace = Self) then
Result := false
else
begin
Result := true;
thePlace.Free;
thePlace := Self.Use;
end;//thePlace = Self
end;//Tm3AttrIndexSearcher.SetRefTo
{$IfEnd} // NOT Defined(l3NoSRT)
function Tm3AttrIndexSearcher.SearchByKey(anAttrID: Integer;
aKey: Integer;
aDirect: Boolean): Il3RangeEnumerable;
{* Ищет по ключу в индексе для атрнибута }
//#UC START# *66C47C8F006F_66C47DB501FB_var*
var
l_Dumper : Im3AttrIndexDumper;
function GetFromDoc: Boolean;
var
l_DocStream : IStream;
l_DT, l_IdT : TDateTime;
l_Size : Int64;
l_S : Il3Stream;
begin//GetFromDoc
Result := false;
if f_WasException then
// - чтобы не долбиться головой об стену
// https://mdp.garant.ru/pages/viewpage.action?pageId=902332536
Exit;
try
l_DocStream := Self.OpenDocStream(aKey, m3_saRead, m3_dsAttrs, anAttrID);
except
f_WasException := true;
Exit;
end;//try..except
try
if (l_DocStream <> nil) then
begin
if (anAttrID in m3MandatoryAttributes) then
begin
SearchByKey := Il3RangeEnumerable_CreateFromStream(l_DocStream);
Result := true;
Exit;
end//anAttrID in m3MandatoryAttributes
else
if (l_Dumper <> nil) then
begin
// - здесь будем timestamp проверять
l_IdT := BadDateTime;
l_DT := BadDateTime;
l_IdT := l_Dumper.TimeStamp;
l_Size := m2COMGetSize(l_DocStream);
if SameValue(l_IdT, BadDateTime) then
begin
SearchByKey := Il3RangeEnumerable_CreateFromStream(l_DocStream);
Result := true;
Exit;
end//SameValue(l_IdT, BadDateTime)
else
begin
l_DT := BadDateTime;
if Supports(l_DocStream, Il3Stream, l_S) then
try
l_DT := l_S.DateTime;
if (CompareDateTime(l_DT, l_IdT) >= 0) then
begin
SearchByKey := Il3RangeEnumerable_CreateFromStream(l_DocStream);
Result := true;
Exit;
end;//CompareDateTime(l_DT, l_IdT) >= 0
finally
l_S := nil;
end;//try..finally
end;//SameValue(l_IdT, BadDateTime)
end//l_Dumper <> nil
else
begin
SearchByKey := Il3RangeEnumerable_CreateFromStream(l_DocStream);
Result := true;
Exit;
end;//l_Dumper <> nil
end;//l_DocStream <> nil
finally
l_DocStream := nil;
end;//try..finally
end;//GetFromDoc
procedure WriteToDoc;
var
l_DocStream : IStream;
begin//WriteToDoc
if not aDirect then
Exit;
if (aKey <= 0) then
Exit;
//if not (anAttrID in m3MandatoryAttributes) then
begin
if (GetCurrentThreadID <> MainThreadID) then
Exit;
end;//not (anAttrID in m3MandatoryAttributes)
if not (anAttrID in m3MandatoryAttributes) then
begin
// if anAttrID IS NOT Mandatory then
// we NEED to check previous version
// and rewrite it or change its timestamp
// but now we do not have needed functionaslity
// so we simple exit at this point
Exit;
end;//not (anAttrID in m3MandatoryAttributes)
if f_WasException then
// - guiard of deadlocks
Exit;
{$IfDef Archi}
{$IfDef AppClientSide}
//if false then
if (g_BaseEngine <> nil) then
if g_BaseEngine.WorkWithServer then
Exit;
{$EndIf AppClientSide}
{$EndIf Archi}
l_DocStream := Self.OpenDocStream(aKey, m3_saReadWrite, m3_dsAttrs, anAttrID);
try
if (l_DocStream <> nil) then
Il3RangeEnumerable_WriteTo(Result, l_DocStream);
finally
l_DocStream := nil;
end;//try..finally
end;//WriteToDoc
//#UC END# *66C47C8F006F_66C47DB501FB_var*
begin
//#UC START# *66C47C8F006F_66C47DB501FB_impl*
Result := nil;
if aDirect then
begin
if (aKey <= 0) then
begin
// -- заточка
aKey := 0;
Exit;
end;//aKey <= 0
end;//aDirect
if aDirect then
begin
if (anAttrID > 0) AND (anAttrID < k2_tiLast) then
begin
if (anAttrID in m3MandatoryAttributes) then
if GetFromDoc then
Exit;
end;//(anAttrID > 0) AND (anAttrID < k2_tiLast)
end;//aDirect
l_Dumper := Self.MakeDumper(anAttrID, aDirect);
try
if aDirect then
begin
if (anAttrID > 0) AND (anAttrID < k2_tiLast) then
begin
if not (anAttrID in m3MandatoryAttributes) then
if GetFromDoc then
Exit;
end;//(anAttrID > 0) AND (anAttrID < k2_tiLast)
end;//aDirect
if (l_Dumper <> nil) then
begin
Result := l_Dumper.ValuesByKey(aKey);
if aDirect then
if (anAttrID > 0) AND (anAttrID < k2_tiLast) then
// - здесь будем писать в документ
begin
WriteToDoc;
end;//(anAttrID > 0) AND (anAttrID < k2_tiLast)
end;//l_Dumper <> nil
finally
l_Dumper := nil;
end;//try..finally
//#UC END# *66C47C8F006F_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByKey
function Tm3AttrIndexSearcher.ExternalHandleToInternalHandle(anID: Tm3DocID): Tm3DocID;
//#UC START# *66C47CD2030A_66C47DB501FB_var*
//#UC END# *66C47CD2030A_66C47DB501FB_var*
begin
//#UC START# *66C47CD2030A_66C47DB501FB_impl*
Result := Self.SearchFirstByKey(k2_tiExternalHandle, anID, false);
if (Result <= 0) then
begin
if Tm3ExternalIDtoInternalIDMap.Exists then
with Tm3ExternalIDtoInternalIDMap.Instance do
begin
Lock;
try
if Has(anID) then
begin
Result := ValueByKey(anID);
if (Result = 0) then
Result := -1;
end;//Has(anID)
finally
Unlock;
end;//try..finally
end;//with Tm3ExternalIDtoInternalIDMap.Instance
end;//Result <= 0
//#UC END# *66C47CD2030A_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.ExternalHandleToInternalHandle
function Tm3AttrIndexSearcher.InternalHandleToExternalHandle(anID: Tm3DocID): Tm3DocID;
//#UC START# *66C4D5330179_66C47DB501FB_var*
var
l_Header : Il3TagRef;
//#UC END# *66C4D5330179_66C47DB501FB_var*
begin
//#UC START# *66C4D5330179_66C47DB501FB_impl*
if (anID < 0) then
begin
Result := -1;
Exit;
end;//anID < 0
if (anID = 0) then
begin
Result := -1;
Exit;
end;//anID = 0
Result := Self.SearchFirstByKey(k2_tiExternalHandle, anID, true);
if (Result <= 0) then
begin
l_Header := Self.DocumentHeaderData(anID);
if (l_Header <> nil) then
if (l_Header.AsObject <> nil) then
if l_Header.AsObject.IsValid then
begin
Result := l_Header.AsObject.IntA[k2_tiExternalHandle];
if (Result = 0) then
Result := -1;
end;//l_Header.AsObject.IsValid
end;//Result <= 0
//Result := Self.SearchFirstByKey(k2_tiInternalHandle, anID, false);
//#UC END# *66C4D5330179_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.InternalHandleToExternalHandle
function Tm3AttrIndexSearcher.SearchFirstByKey(anAttrID: Integer;
aKey: Integer;
aDirect: Boolean): Integer;
//#UC START# *66D9AB76035A_66C47DB501FB_var*
var
l_E : Il3RangeEnumerable;
l_It : Il3RangeEnumerator;
//l_It : Il3IntegerEnumerator;
//#UC END# *66D9AB76035A_66C47DB501FB_var*
begin
//#UC START# *66D9AB76035A_66C47DB501FB_impl*
Result := -1;
l_E := Self.SearchByKey(anAttrID, aKey, aDirect);
if (l_E <> nil) then
begin
l_It := l_E.GetEnumerator;
if (l_It <> nil) then
if l_It.MoveNext then
Result := l_It.pCurrent^.rLow;
(* l_It := Il3RangeEnumerable_GetIntegerEnumerator(l_E);
if (l_It <> nil) then
if l_It.MoveNext then
Result := l_It.Current;*)
end;//l_E <> nil
//#UC END# *66D9AB76035A_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchFirstByKey
function Tm3AttrIndexSearcher.RelExternalHandleToInternalHandle(anID: Tm3DocID): Tm3DocID;
//#UC START# *66F675CD0025_66C47DB501FB_var*
//#UC END# *66F675CD0025_66C47DB501FB_var*
begin
//#UC START# *66F675CD0025_66C47DB501FB_impl*
Result := Self.SearchFirstByKey(k2_tiRelExternalHandle, anID, false);
//#UC END# *66F675CD0025_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.RelExternalHandleToInternalHandle
function Tm3AttrIndexSearcher.InternalHandleToRelExternalHandle(anID: Tm3DocID): Tm3DocID;
//#UC START# *66F675E602D6_66C47DB501FB_var*
var
l_Header : Il3TagRef;
//#UC END# *66F675E602D6_66C47DB501FB_var*
begin
//#UC START# *66F675E602D6_66C47DB501FB_impl*
Result := Self.SearchFirstByKey(k2_tiRelExternalHandle, anID, true);
if (Result <= 0) then
begin
l_Header := Self.DocumentHeaderData(anID);
if (l_Header <> nil) then
if (l_Header.AsObject <> nil) then
if l_Header.AsObject.IsValid then
begin
Result := l_Header.AsObject.IntA[k2_tiRelExternalHandle];
if (Result = 0) then
Result := -1;
end;//l_Header.AsObject.IsValid
end;//Result <= 0
//#UC END# *66F675E602D6_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.InternalHandleToRelExternalHandle
function Tm3AttrIndexSearcher.SearchByKeys(anAttrID: Integer;
const aKeys: Il3IntegerEnumerable): Il3RangeEnumerable;
//#UC START# *66F6B0710210_66C47DB501FB_var*
var
l_It : Il3IntegerEnumerator;
l_Found : Il3RangeEnumerable;
//#UC END# *66F6B0710210_66C47DB501FB_var*
begin
//#UC START# *66F6B0710210_66C47DB501FB_impl*
Result := nil;
if (aKeys <> nil) then
begin
l_It := aKeys.GetEnumerator;
if (l_It <> nil) then
begin
while l_It.MoveNext do
begin
l_Found := Self.SearchByKey(anAttrID, l_It.Current, false);
if (l_Found <> nil) then
begin
Result := Il3RangeEnumerable_JoinWithOther(Result, l_Found);
end;//l_Found <> nil
end;//while l_It.MoveNext
end;//l_It <> nil
end;//aKeys <> nil
//#UC END# *66F6B0710210_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByKeys
function Tm3AttrIndexSearcher.NameByInternalHandle(anID: Tm3DocID): Il3CString;
//#UC START# *66FFE0ED02C3_66C47DB501FB_var*
var
l_ID : Integer;
{$IfDef m3UseHeaderForName}
l_Header : Il3TagRef;
(* l_DB : Im3DB;
l_Doc : Im3DBDocument;*)
l_S : IStream;
l_TextExtractor : Tm3FirstTextExtractor;
l_Reader : TevdNativeReader;
l_WasAbortLoad : Boolean;
l_IsAnno : Boolean;
{$Else m3UseHeaderForName}
l_DB : Im3DB;
l_Doc : Im3DBDocument;
l_S : IStream;
l_Extractor : Tm3DocumentInfoExtractor;
l_Reader : TevdNativeReader;
l_WasAbortLoad : Boolean;
l_IsAnno : Boolean;
{$EndIf m3UseHeaderForName}
//#UC END# *66FFE0ED02C3_66C47DB501FB_var*
begin
//#UC START# *66FFE0ED02C3_66C47DB501FB_impl*
Result := nil;
Result := GetDocumentString(k2_tiName, anID);
if not l3IsNil(Result) then
//if (Result <> nil) then
Exit;
Result := GetDocumentString(k2_tiShortName, anID);
if not l3IsNil(Result) then
//if (Result <> nil) then
Exit;
Result := GetDocumentString(k2_tiText, anID);
if not l3IsNil(Result) then
//if (Result <> nil) then
Exit;
{$IfDef m3UseHeaderForName}
l_Header := Self.DocumentHeaderData(anID);
if (l_Header <> nil) then
if (l_Header.AsObject <> nil) then
if l_Header.AsObject.IsValid then
begin
Result := Il3CString_C(l_Header.AsObject.PCharLenA[k2_tiName]);
WriteDocumentString(k2_tiName, anID, Result);
if not l3IsNil(Result) then
Exit;
Result := Il3CString_C(l_Header.AsObject.PCharLenA[k2_tiShortName]);
WriteDocumentString(k2_tiShortName, anID, Result);
if not l3IsNil(Result) then
Exit;
end;//l_Header.AsObject.IsValid
{$Else m3UseHeaderForName}
l_WasAbortLoad := false;
if (Self.f_DB <> nil) then
l_DB := Self.f_DB
else
l_DB := Tm3DB.Make(f_BaseName);
try
l_Doc := l_DB.GetDocument(anID);
if (l_Doc <> nil) then
begin
l_IsAnno := false;
l_S := l_Doc.Open;
try
if (l_S <> nil) then
begin
if (m2COMGetSize(l_S) <= 0) then
begin
Result := l3Cat(Il3CString_C('Удалён: №'), IntToStr(anID));
Exit;
end;//m2COMGetSize(l_S) <= 0
end;//l_S <> nil
if (l_S = nil) then
begin
l_S := l_Doc.Open(m3_saRead, m3_dsAnno);
// - костылик для аннотаций
if (l_S <> nil) then
l_IsAnno := true;
end;//l_S = nil
if (l_S <> nil) then
begin
l_Extractor := Tm3DocumentInfoExtractor.Create;
try
l_Reader := TevdNativeReader.Create;
try
l_Reader.Generator := l_Extractor;
l_Reader.Filer.Mode := l3_fmRead;
l_Reader.Filer.COMStream := l_S;
try
l_Reader.Start;
try
try
l_Reader.Execute;
except
on El3AbortLoad do
begin
l_WasAbortLoad := true;
end;//on El3AbortLoad
end;//try..except
finally
try
if not l_WasAbortLoad then
l_Reader.Finish;
except
on Ek2TagGeneratorBadFinishCall do
begin
if not l_WasAbortLoad then
raise;
end;//on Ek2TagGeneratorBadFinishCall
end;//try..except
end;//try..finally
finally
l_Reader.Filer.COMStream := nil;
end;//try..finally
finally
FreeAndNil(l_Reader);
end;//try..finally
if not l3IsNil(l_Extractor.DocName) then
begin
if l_IsAnno then
Result := l3Cat('Аннотация: ', l_Extractor.DocName)
else
Result := l_Extractor.DocName;
Exit;
end;//not l3IsNil(l_Extractor.DocName)
if not l3IsNil(l_Extractor.DocShortName) then
begin
if l_IsAnno then
Result := l3Cat('Аннотация: ', l_Extractor.DocShortName)
else
Result := l_Extractor.DocShortName;
Exit;
end;//not l3IsNil(l_Extractor.DocShortName)
finally
FreeAndNil(l_Extractor);
end;//try..finally
end;//l_S <> nil
finally
l_S := nil;
end;//try..finally
end;//l_Doc <> nil
finally
l_DB := nil;
end;//try..finally
{$EndIf m3UseHeaderForName}
l_WasAbortLoad := false;
(* if (Self.f_DB <> nil) then
l_DB := Self.f_DB
else
l_DB := Tm3DB.Make(f_BaseName);
try
l_Doc := l_DB.GetDocument(anID);
if (l_Doc <> nil) then*)
begin
l_IsAnno := false;
l_S := Self.OpenDocStream(anID, m3_saRead, m3_dsMain, 0);
//l_S := l_Doc.Open;
try
if (l_S <> nil) then
begin
if (m2COMGetSize(l_S) <= 0) then
begin
Result := l3Cat(Il3CString_C('Удалён: №'), IntToStr(anID));
WriteDocumentString(k2_tiText, anID, Result);
Exit;
end;//m2COMGetSize(l_S) <= 0
end;//l_S <> nil
if (l_S = nil) then
begin
l_S := Self.OpenDocStream(anID, m3_saRead, m3_dsAnno, 0);
//l_S := l_Doc.Open(m3_saRead, m3_dsAnno);
// - костылик для аннотаций
if (l_S <> nil) then
l_IsAnno := true;
end;//l_S = nil
if (l_S <> nil) then
begin
l_TextExtractor := Tm3FirstTextExtractor.Create;
try
l_Reader := TevdNativeReader.Create;
try
l_Reader.Generator := l_TextExtractor;
l_Reader.Filer.Mode := l3_fmRead;
l_Reader.Filer.COMStream := l_S;
try
l_Reader.Start;
try
try
l_Reader.Execute;
except
on El3AbortLoad do
begin
l_WasAbortLoad := true;
end;//on El3AbortLoad
end;//try..except
finally
try
if not l_WasAbortLoad then
l_Reader.Finish;
except
on Ek2TagGeneratorBadFinishCall do
begin
if not l_WasAbortLoad then
raise;
end;//on Ek2TagGeneratorBadFinishCall
end;//try..except
end;//try..finally
finally
l_Reader.Filer.COMStream := nil;
end;//try..finally
finally
FreeAndNil(l_Reader);
end;//try..finally
if not l3IsNil(l_TextExtractor.Text) then
begin
if l_IsAnno then
Result := l3Cat('Аннотация: ', l_TextExtractor.Text)
else
Result := l_TextExtractor.Text;
WriteDocumentString(k2_tiText, anID, Result);
Exit;
end;//not l3IsNil(l_TextExtractor.Text)
finally
FreeAndNil(l_TextExtractor);
end;//try..finally
end;//l_S <> nil
finally
l_S := nil;
end;//try..finally
end;//l_Doc <> nil
(* finally
l_DB := nil;
end;//try..finally*)
l_ID := Self.InternalHandleToExternalHandle(anID);
if (l_ID < 0) then
l_ID := anID;
Result := l3Fmt('Документ №%d', [l_ID]);
WriteDocumentString(k2_tiText, anID, Result);
//#UC END# *66FFE0ED02C3_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.NameByInternalHandle
function Tm3AttrIndexSearcher.TypeByID(anID: Tm3DocID): TDocType;
//#UC START# *6700586B00FE_66C47DB501FB_var*
var
l_Header : Il3TagRef;
l_Result : Integer;
//#UC END# *6700586B00FE_66C47DB501FB_var*
begin
//#UC START# *6700586B00FE_66C47DB501FB_impl*
if (anID < 0) then
begin
Result := dtNone;
Exit;
end;//anID < 0
if (anID = 0) then
begin
Result := dtNone;
Exit;
end;//anID = 0
l_Result := Self.SearchFirstByKey(k2_tiType, anID, true);
if (l_Result < 0) then
begin
l_Header := Self.DocumentHeaderData(anID);
if (l_Header <> nil) then
if (l_Header.AsObject <> nil) then
if l_Header.AsObject.IsValid then
begin
l_Result := l_Header.AsObject.IntA[k2_tiType];
end;//l_Header.AsObject.IsValid
end;//l_Result < 0
if (l_Result < Ord(Low(Result))) OR (l_Result > Ord(High(Result))) then
Result := dtNone
else
Result := TDocType(l_Result);
//#UC END# *6700586B00FE_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.TypeByID
function Tm3AttrIndexSearcher.UserTypeByID(anID: Tm3DocID): TUserType;
//#UC START# *6700588601FB_66C47DB501FB_var*
var
l_Header : Il3TagRef;
l_Result : Integer;
//#UC END# *6700588601FB_66C47DB501FB_var*
begin
//#UC START# *6700588601FB_66C47DB501FB_impl*
if (anID < 0) then
begin
Result := utNone;
Exit;
end;//anID < 0
if (anID = 0) then
begin
Result := utNone;
Exit;
end;//anID = 0
l_Result := Self.SearchFirstByKey(k2_tiUserType, anID, true);
if (l_Result >= Ord(Low(Result))) AND (l_Result <= Ord(High(Result))) then
begin
Result := TUserType(l_Result);
Exit;
end;//l_Result >= Ord(Low(Result))
{$IfNDef Linux}
if (l_Result < 0) then
begin
l_Header := Self.DocumentHeaderData(anID);
if (l_Header <> nil) then
if (l_Header.AsObject <> nil) then
if l_Header.AsObject.IsValid then
begin
l_Result := l_Header.AsObject.IntA[k2_tiUserType];
end;//l_Header.AsObject.IsValid
end;//Result < 0
{$EndIf Linux}
if (l_Result < Ord(Low(Result))) OR (l_Result > Ord(High(Result))) then
Result := utNone
else
Result := TUserType(l_Result);
// - here we need to save Result to DocStream
//#UC END# *6700588601FB_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.UserTypeByID
function Tm3AttrIndexSearcher.NameByID(anID: Tm3DocID): Il3CString;
//#UC START# *67005EDA000A_66C47DB501FB_var*
//#UC END# *67005EDA000A_66C47DB501FB_var*
begin
//#UC START# *67005EDA000A_66C47DB501FB_impl*
Result := Self.NameByInternalHandle(anID);
//#UC END# *67005EDA000A_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.NameByID
function Tm3AttrIndexSearcher.AllDocuments: Il3RangeEnumerable;
{* Все документы базы }
//#UC START# *670679BD01C7_66C47DB501FB_var*
{$IfDef m3UseTypeForAllDocuments}
var
l_T : TDocType;
l_Found : Il3RangeEnumerable;
l_Dumper : Im3AttrIndexDumper;
l_TimeStamp : TDateTime;
l_Key : Tm3DocumentMapKey;
l_C : Tm3DocumentsCache;
{$EndIf m3UseTypeForAllDocuments}
//#UC END# *670679BD01C7_66C47DB501FB_var*
begin
//#UC START# *670679BD01C7_66C47DB501FB_impl*
{$IfDef m3UseTypeForAllDocuments}
Result := nil;
l_Key := Tm3DocumentMapKey_C(f_BaseName, 'AllDocuments');
l_C := Tm3DocumentsCache.Instance;
l_TimeStamp := l3MinDateTime;
l_Dumper := Self.MakeDumper(k2_tiType, false);
if (l_Dumper <> nil) then
begin
l_TimeStamp := l_Dumper.TimeStamp;
end;//l_Dumper <> nil
if l_C.Get(l_Key, l_TimeStamp, Result) then
Exit;
for l_T := Low(TDocType) to High(TDocType) do
begin
if (l_T <> dtRelText) then
begin
l_Found := Self.SearchByType(l_T);
Result := Il3RangeEnumerable_JoinWithOther(Result, l_Found);
end;//l_T <> dtRelText
end;//for l_T
l_C.Put(l_Key, l_TimeStamp, Result);
{$Else m3UseTypeForAllDocuments}
Result := Self.ConstDocuments;
Result := Il3RangeEnumerable_JoinWithOther(Result, Self.ModifiedDocuments);
{$EndIf m3UseTypeForAllDocuments}
//#UC END# *670679BD01C7_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.AllDocuments
function Tm3AttrIndexSearcher.IsRelated(anID: Tm3DocID): Boolean;
{* Определяет - является ли документ справкой. }
//#UC START# *670CEB0301D0_66C47DB501FB_var*
//#UC END# *670CEB0301D0_66C47DB501FB_var*
begin
//#UC START# *670CEB0301D0_66C47DB501FB_impl*
Result := TypeByID(anID) = dtRelText;
//#UC END# *670CEB0301D0_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.IsRelated
function Tm3AttrIndexSearcher.ConstDocuments: Il3RangeEnumerable;
{* Документы из постояной части }
//#UC START# *670CED2A00D5_66C47DB501FB_var*
var
l_L : Tm3RangedDocumentsList;
function DoElement(const aStoreInfo: Tm3StoreInfo; anIndex: Integer): Boolean;
begin//DoElement
Result := true;
if not IsSpravka(anIndex) then
l_L.Add(anIndex);
end;//DoElement
var
l_DB : Im3DB;
l_Main : Im3IndexedStorage;
l_Key : Tm3DocumentMapKey;
l_C : Tm3DocumentsCache;
//#UC END# *670CED2A00D5_66C47DB501FB_var*
begin
//#UC START# *670CED2A00D5_66C47DB501FB_impl*
l_Key := Tm3DocumentMapKey_C(f_BaseName, 'ConstDocuments');
l_C := Tm3DocumentsCache.Instance;
if l_C.Get(l_Key, Result) then
Exit;
l_L := Tm3RangedDocumentsList.Create;
try
if (Self.f_DB <> nil) then
l_DB := Self.f_DB
else
l_DB := Tm3DB.Make(f_BaseName);
try
if (l_DB <> nil) then
begin
l_Main := l_DB.MainStorage(m3_saRead);
if (l_Main <> nil) then
begin
l_Main.IterateIndexedF(L2Mm3StorageIteratorsIterateIndexedFAction(@DoElement), 0);
end;//l_Main <> nil
end;//l_DB <> nil
finally
l_DB := nil;
end;//try..finally
Result := l_L.AsEnumerable;
l_C.Put(l_Key, Result);
finally
FreeAndNil(l_L);
end;//try..finally
//#UC END# *670CED2A00D5_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.ConstDocuments
function Tm3AttrIndexSearcher.ModifiedDocuments: Il3RangeEnumerable;
{* Документы из переменной части }
//#UC START# *670CF2F2034E_66C47DB501FB_var*
var
l_L : Tm3RangedDocumentsList;
function DoElement(const aStoreInfo: Tm3StoreInfo; anIndex: Integer): Boolean;
begin//DoElement
Result := true;
if not IsSpravka(anIndex) then
l_L.Add(anIndex);
end;//DoElement
var
l_DB : Im3DB;
l_Versions : Im3IndexedStorage;
//#UC END# *670CF2F2034E_66C47DB501FB_var*
begin
//#UC START# *670CF2F2034E_66C47DB501FB_impl*
l_L := Tm3RangedDocumentsList.Create;
try
if (Self.f_DB <> nil) then
l_DB := Self.f_DB
else
l_DB := Tm3DB.Make(f_BaseName);
try
if (l_DB <> nil) then
begin
l_Versions := l_DB.GetVersionsStorage(m3_saRead);
if (l_Versions <> nil) then
begin
l_Versions.IterateIndexedF(L2Mm3StorageIteratorsIterateIndexedFAction(@DoElement), 0);
end;//l_Versions <> nil
end;//l_DB <> nil
finally
l_DB := nil;
end;//try..finally
Result := l_L.AsEnumerable;
finally
FreeAndNil(l_L);
end;//try..finally
//#UC END# *670CF2F2034E_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.ModifiedDocuments
function Tm3AttrIndexSearcher.IsSpravka(anID: Tm3DocID): Boolean;
//#UC START# *670CF548034A_66C47DB501FB_var*
//#UC END# *670CF548034A_66C47DB501FB_var*
begin
//#UC START# *670CF548034A_66C47DB501FB_impl*
Result := Self.IsRelated(anID);
//#UC END# *670CF548034A_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.IsSpravka
function Tm3AttrIndexSearcher.DeletedDocuments: Il3RangeEnumerable;
{* Удалённые документы }
//#UC START# *670CF7F601C4_66C47DB501FB_var*
//#UC END# *670CF7F601C4_66C47DB501FB_var*
begin
//#UC START# *670CF7F601C4_66C47DB501FB_impl*
Result := Self.SearchByKey(k2_tiDeleted, 1{true}, false);
//#UC END# *670CF7F601C4_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.DeletedDocuments
function Tm3AttrIndexSearcher.AllRelated: Il3RangeEnumerable;
{* Все справки }
//#UC START# *671022280052_66C47DB501FB_var*
{$IfDef m3UseTypeForAllRelated}
var
l_Dumper : Im3AttrIndexDumper;
l_TimeStamp : TDateTime;
l_Key : Tm3DocumentMapKey;
l_C : Tm3DocumentsCache;
{$EndIf m3UseTypeForAllRelated}
//#UC END# *671022280052_66C47DB501FB_var*
begin
//#UC START# *671022280052_66C47DB501FB_impl*
{$IfDef m3UseTypeForAllRelated}
l_Key := Tm3DocumentMapKey_C(f_BaseName, 'AllRelated');
l_C := Tm3DocumentsCache.Instance;
l_TimeStamp := l3MinDateTime;
l_Dumper := Self.MakeDumper(k2_tiType, false);
if (l_Dumper <> nil) then
begin
l_TimeStamp := l_Dumper.TimeStamp;
end;//l_Dumper <> nil
if l_C.Get(l_Key, l_TimeStamp, Result) then
Exit;
Result := Self.SearchByType(dtRelText);
l_C.Put(l_Key, l_TimeStamp, Result);
{$Else m3UseTypeForAllRelated}
Result := Self.ConstRelated;
Result := Il3RangeEnumerable_JoinWithOther(Result, Self.ModifiedRelated);
{$EndIf m3UseTypeForAllRelated}
//#UC END# *671022280052_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.AllRelated
function Tm3AttrIndexSearcher.ConstRelated: Il3RangeEnumerable;
{* Справки в постоянной части }
//#UC START# *6710223B00EB_66C47DB501FB_var*
var
l_L : Tm3RangedDocumentsList;
function DoElement(const aStoreInfo: Tm3StoreInfo; anIndex: Integer): Boolean;
begin//DoElement
Result := true;
if IsSpravka(anIndex) then
l_L.Add(anIndex);
end;//DoElement
var
l_DB : Im3DB;
l_Main : Im3IndexedStorage;
l_Key : Tm3DocumentMapKey;
l_C : Tm3DocumentsCache;
//#UC END# *6710223B00EB_66C47DB501FB_var*
begin
//#UC START# *6710223B00EB_66C47DB501FB_impl*
l_Key := Tm3DocumentMapKey_C(f_BaseName, 'ConstRelated');
l_C := Tm3DocumentsCache.Instance;
if l_C.Get(l_Key, Result) then
Exit;
l_L := Tm3RangedDocumentsList.Create;
try
if (Self.f_DB <> nil) then
l_DB := Self.f_DB
else
l_DB := Tm3DB.Make(f_BaseName);
try
if (l_DB <> nil) then
begin
l_Main := l_DB.MainStorage(m3_saRead);
if (l_Main <> nil) then
begin
l_Main.IterateIndexedF(L2Mm3StorageIteratorsIterateIndexedFAction(@DoElement), 0);
end;//l_Main <> nil
end;//l_DB <> nil
finally
l_DB := nil;
end;//try..finally
Result := l_L.AsEnumerable;
l_C.Put(l_Key, Result);
finally
FreeAndNil(l_L);
end;//try..finally
//#UC END# *6710223B00EB_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.ConstRelated
function Tm3AttrIndexSearcher.ModifiedRelated: Il3RangeEnumerable;
{* Справки в переменной части }
//#UC START# *6710224F0192_66C47DB501FB_var*
var
l_L : Tm3RangedDocumentsList;
function DoElement(const aStoreInfo: Tm3StoreInfo; anIndex: Integer): Boolean;
begin//DoElement
Result := true;
if IsSpravka(anIndex) then
l_L.Add(anIndex);
end;//DoElement
var
l_DB : Im3DB;
l_Versions : Im3IndexedStorage;
//#UC END# *6710224F0192_66C47DB501FB_var*
begin
//#UC START# *6710224F0192_66C47DB501FB_impl*
l_L := Tm3RangedDocumentsList.Create;
try
if (Self.f_DB <> nil) then
l_DB := Self.f_DB
else
l_DB := Tm3DB.Make(f_BaseName);
try
if (l_DB <> nil) then
begin
l_Versions := l_DB.GetVersionsStorage(m3_saRead);
if (l_Versions <> nil) then
begin
l_Versions.IterateIndexedF(L2Mm3StorageIteratorsIterateIndexedFAction(@DoElement), 0);
end;//l_Versions <> nil
end;//l_DB <> nil
finally
l_DB := nil;
end;//try..finally
Result := l_L.AsEnumerable;
finally
FreeAndNil(l_L);
end;//try..finally
//#UC END# *6710224F0192_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.ModifiedRelated
function Tm3AttrIndexSearcher.IsAnnoOnly(anID: Tm3DocID): Boolean;
{* Документ содержит ТОЛЬКО аннотацию. Несколько "техническая" ручка. Обычно такой ситуации не должно быть. Но пусть будет }
//#UC START# *671A1D4B0365_66C47DB501FB_var*
var
(* l_DB : Im3DB;
l_Doc : Im3DBDocument;*)
l_S : IStream;
//#UC END# *671A1D4B0365_66C47DB501FB_var*
begin
//#UC START# *671A1D4B0365_66C47DB501FB_impl*
Result := false;
(* if (Self.f_DB <> nil) then
l_DB := Self.f_DB
else
l_DB := Tm3DB.Make(f_BaseName);
try
l_Doc := l_DB.GetDocument(anID);
if (l_Doc <> nil) then*)
begin
l_S := Self.OpenDocStream(anID, m3_saRead, m3_dsMain, 0);
//l_S := l_Doc.Open;
try
if (l_S = nil) then
// - нет текста
begin
l_S := Self.OpenDocStream(anID, m3_saRead, m3_dsAnno, 0);
//l_S := l_Doc.Open(m3_saRead, m3_dsAnno);
// - костылик для аннотаций
if (l_S <> nil) then
Result := true;
end;//l_S = nil
finally
l_S := nil;
end;//try..finally
end;//l_Doc <> nil
(* finally
l_DB := nil;
end;//try..finally*)
//#UC END# *671A1D4B0365_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.IsAnnoOnly
function Tm3AttrIndexSearcher.SearcheableAttributesNames: Il3StringsEnumerable;
{* Имена атрибутов для поиска }
//#UC START# *671A2BE300C2_66C47DB501FB_var*
var
l_L : Tl3StringList;
//#UC END# *671A2BE300C2_66C47DB501FB_var*
begin
//#UC START# *671A2BE300C2_66C47DB501FB_impl*
{$IfDef FPC}
if (Self.f_SearcheableAttributesNames <> nil) then
begin
Result := Self.f_SearcheableAttributesNames;
Exit;
end;//Self.f_SearcheableAttributesNames <> nil
{$EndIf FPC}
l_L := Tl3StringList.CreateSorted;
try
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiType));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiUserType));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiRelExternalHandle));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiRelInternalHandle));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiExternalHandle));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiMaxHyperlinkHandle));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiGroups));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiAccGroups));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiSources));
l_L.Add(Tk2Attributes.Instance.NameByID(k2Tags.k2_tiTypes));
l_L.Add(Tk2Attributes.Instance.NameByID(k2Tags.k2_tiClasses));
l_L.Add(Tk2Attributes.Instance.NameByID(k2Tags.k2_tiKeyWords));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiAnnoClasses));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiNumANDDates));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiStages));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiLogRecords));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiActiveIntervals));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiSysLogRecords));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiNorm));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiWarnings));
l_L.Add(Tk2Attributes.Instance.NameByID(k2Tags.k2_tiPrefix));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiPublishedIn));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiPublishedIn) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSource));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiTerritory));
l_L.Add(Tk2Attributes.Instance.NameByID(k2Tags.k2_tiServiceInfo));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiNumANDDates) + '_' + Tk2Attributes.Instance.NameByID(k2_tiStart));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiNumANDDates) + '_' + Tk2Attributes.Instance.NameByID(k2_tiType));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiActiveIntervals) + '_' + Tk2Attributes.Instance.NameByID(k2_tiStart));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiActiveIntervals) + '_' + Tk2Attributes.Instance.NameByID(k2_tiFinish));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiActiveIntervals) + '_' + Tk2Attributes.Instance.NameByID(k2_tiType));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiLogRecords) + '_' + Tk2Attributes.Instance.NameByID(k2_tiStart));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiLogRecords) + '_' + Tk2Attributes.Instance.NameByID(k2_tiType));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiLogRecords) + '_' + Tk2Attributes.Instance.NameByID(k2_tiUser));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiSysLogRecords) + '_' + Tk2Attributes.Instance.NameByID(k2_tiStart));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiSysLogRecords) + '_' + Tk2Attributes.Instance.NameByID(k2_tiType));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiSysLogRecords) + '_' + Tk2Attributes.Instance.NameByID(k2_tiUser));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiStages) + '_' + Tk2Attributes.Instance.NameByID(k2_tiStart));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiStages) + '_' + Tk2Attributes.Instance.NameByID(k2_tiType));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiStages) + '_' + Tk2Attributes.Instance.NameByID(k2_tiUser));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiDocID));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiDeleted));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiExternalVerLink));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiExternalNextVerLink));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiInternalVerLink));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiInternalNextVerLink));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiSortDate));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiPriority));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiUrgency));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiPriceLevel));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiOldNSRC));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiGroups) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiAccGroups) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiSources) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
l_L.Add(Tk2Attributes.Instance.NameByID(k2Tags.k2_tiTypes) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
l_L.Add(Tk2Attributes.Instance.NameByID(k2Tags.k2_tiClasses) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
l_L.Add(Tk2Attributes.Instance.NameByID(k2Tags.k2_tiKeyWords) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiAnnoClasses) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiNumANDDates) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiNorm) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiWarnings) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
l_L.Add(Tk2Attributes.Instance.NameByID(k2Tags.k2_tiPrefix) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiPublishedIn) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiTerritory) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
l_L.Add(Tk2Attributes.Instance.NameByID(k2Tags.k2_tiServiceInfo) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiLogRecords) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiSysLogRecords) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiStages) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiActiveIntervals) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
Result := l_L.AsEnumerable;
{$IfDef FPC}
Self.f_SearcheableAttributesNames := Result;
{$EndIf FPC}
finally
FreeAndNil(l_L);
end;//try..finally
//#UC END# *671A2BE300C2_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearcheableAttributesNames
function Tm3AttrIndexSearcher.SearchByKeyEx(const anAttrID: array of Integer;
aKey: Integer;
aDirect: Boolean): Il3RangeEnumerable;
{* Ищет по ключу "иерархического" атрибута. Т.е. указывается "путь" в EVD. Сродни cAtomEx }
//#UC START# *671A571F021D_66C47DB501FB_var*
var
l_Dumper : Im3AttrIndexDumper;
//#UC END# *671A571F021D_66C47DB501FB_var*
begin
//#UC START# *671A571F021D_66C47DB501FB_impl*
Result := nil;
if (Low(anAttrID) = High(anAttrID)) then
Result := Self.SearchByKey(anAttrID[Low(anAttrID)], aKey, aDirect)
else
begin
l_Dumper := Tm3AttrIndexDumperJoin.MakeForAttribute(Self.f_BaseName, anAttrID, aDirect);
try
if (l_Dumper <> nil) then
Result := l_Dumper.ValuesByKey(aKey);
finally
l_Dumper := nil;
end;//try..finally
end;//Low(anAttrID) = High(anAttrID)
//#UC END# *671A571F021D_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByKeyEx
function Tm3AttrIndexSearcher.ContextAttributesNames: Il3StringsEnumerable;
//#UC START# *671CD7E302F5_66C47DB501FB_var*
var
l_L : Tl3StringList;
//#UC END# *671CD7E302F5_66C47DB501FB_var*
begin
//#UC START# *671CD7E302F5_66C47DB501FB_impl*
{$IfDef FPC}
if (Self.f_ContextAttributesNames <> nil) then
begin
Result := Self.f_ContextAttributesNames;
Exit;
end;//Self.f_ContextAttributesNames <> nil
{$EndIf FPC}
l_L := Tl3StringList.CreateSorted;
try
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiNumber));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiNumber) + '_' + Tk2Attributes.Instance.NameByID(k2_tiPublishedIn));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiName));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiShortName));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiComment));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiNameComment));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiName) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
l_L.Add(Tk2Attributes.Instance.NameByID(k2_tiShortName) + '_' + Tk2Attributes.Instance.NameByID(k2_tiSubs));
Result := l_L.AsEnumerable;
{$IfDef FPC}
Self.f_ContextAttributesNames := Result;
{$EndIf FPC}
finally
FreeAndNil(l_L);
end;//try..finally
//#UC END# *671CD7E302F5_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.ContextAttributesNames
function Tm3AttrIndexSearcher.SearchByKey(anAttrID: Integer;
aKey: Tl3PrimString): Il3RangeEnumerable;
//#UC START# *672B855300BE_66C47DB501FB_var*
var
l_Name : TFileName;
l_Searcher : Tm4SearchEngine;
l_Expr : Tm4WordExpression;
l_List : Tl3LongintList;
//l_Res : Tm4SearchResult;
//#UC END# *672B855300BE_66C47DB501FB_var*
begin
//#UC START# *672B855300BE_66C47DB501FB_impl*
Result := nil;
l_Name := f_BaseName;
l_Name := l_Name + '#';
l_Name := l_Name + Tk2Attributes.Instance.NameByID(anAttrID);
l_Name := l_Name + '_' + '(s)';
l_Name := l_Name + '#';
l_Searcher := Tm4SearchEngine.Create(l_Name, true);
try
l_Expr := Tm4WordExpression.Create(aKey.AsWStr, false);
try
l_List := l_Searcher.Search(l_Expr, nil);
//l_List := l_Searcher.Search(l_Expr, @l_Res);
try
if (l_List <> nil) then
begin
Result := Il3RangeEnumerable_FromIntegerEnumerable(l_List.AsEnumerable);
end;//l_List <> nil
finally
//FreeAndNil(l_Res);
FreeAndNil(l_List);
end;//try..finally
finally
FreeAndNil(l_Expr);
end;//try..finally
finally
FreeAndNil(l_Searcher);
end;//try..finally
//#UC END# *672B855300BE_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByKey
function Tm3AttrIndexSearcher.SearchByKey(anAttrID: Integer;
const aKey: AnsiString): Il3RangeEnumerable;
//#UC START# *672B85E20020_66C47DB501FB_var*
var
l_S : Tl3PrimString;
//#UC END# *672B85E20020_66C47DB501FB_var*
begin
//#UC START# *672B85E20020_66C47DB501FB_impl*
l_S := Tl3SharedConstString.CreateShared(aKey);
try
Result := SearchByKey(anAttrID, l_S);
finally
FreeAndNil(l_S);
end;//try..finally
//#UC END# *672B85E20020_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByKey
function Tm3AttrIndexSearcher.SearchByKey(anAttrID: Integer;
const aKey: Tl3WString): Il3RangeEnumerable;
//#UC START# *672B8A5E00CE_66C47DB501FB_var*
var
l_S : Tl3PrimString;
//#UC END# *672B8A5E00CE_66C47DB501FB_var*
begin
//#UC START# *672B8A5E00CE_66C47DB501FB_impl*
l_S := Tl3SharedConstString.CreateShared(aKey);
try
Result := SearchByKey(anAttrID, l_S);
finally
FreeAndNil(l_S);
end;//try..finally
//#UC END# *672B8A5E00CE_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByKey
function Tm3AttrIndexSearcher.SearchByKeys(anAttrID: Integer;
const aKeys: Il3StringsEnumerable): Il3RangeEnumerable;
//#UC START# *672B98710207_66C47DB501FB_var*
var
l_It : Il3StringsEnumerator;
l_Found : Il3RangeEnumerable;
//#UC END# *672B98710207_66C47DB501FB_var*
begin
//#UC START# *672B98710207_66C47DB501FB_impl*
Result := nil;
if (aKeys <> nil) then
begin
l_It := aKeys.GetEnumerator;
if (l_It <> nil) then
begin
while l_It.MoveNext do
begin
l_Found := Self.SearchByKey(anAttrID, l_It.Current);
if (l_Found <> nil) then
begin
Result := Il3RangeEnumerable_JoinWithOther(Result, l_Found);
end;//l_Found <> nil
end;//while l_It.MoveNext
end;//l_It <> nil
end;//aKeys <> nil
//#UC END# *672B98710207_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByKeys
function Tm3AttrIndexSearcher.OutLinks(anID: Tm3DocID): Il3RangeEnumerable;
{* Исходящие ссылки. Респонденты. }
//#UC START# *6733323601CE_66C47DB501FB_var*
//#UC END# *6733323601CE_66C47DB501FB_var*
begin
//#UC START# *6733323601CE_66C47DB501FB_impl*
Result := Self.SearchByKey(k2_tiDocID, anID, true);
//#UC END# *6733323601CE_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.OutLinks
function Tm3AttrIndexSearcher.InLinks(anID: Tm3DocID): Il3RangeEnumerable;
{* Входящие ссылки. Корреспонденты. }
//#UC START# *6733327900E9_66C47DB501FB_var*
//#UC END# *6733327900E9_66C47DB501FB_var*
begin
//#UC START# *6733327900E9_66C47DB501FB_impl*
Result := Self.SearchByKey(k2_tiDocID, anID, false);
//#UC END# *6733327900E9_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.InLinks
function Tm3AttrIndexSearcher.SearchByNumberType(aNumberType: TDNType): Il3RangeEnumerable;
//#UC START# *6734A06300CD_66C47DB501FB_var*
//#UC END# *6734A06300CD_66C47DB501FB_var*
begin
//#UC START# *6734A06300CD_66C47DB501FB_impl*
Result := Self.SearchByKeyEx([k2_tiNumANDDates, k2_tiType], Ord(aNumberType), false);
//#UC END# *6734A06300CD_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByNumberType
function Tm3AttrIndexSearcher.SearchByNumber(const aNumber: AnsiString): Il3RangeEnumerable;
//#UC START# *6735BE110028_66C47DB501FB_var*
//#UC END# *6735BE110028_66C47DB501FB_var*
begin
//#UC START# *6735BE110028_66C47DB501FB_impl*
Result := Self.SearchByKey(k2_tiNumber, aNumber);
//#UC END# *6735BE110028_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByNumber
function Tm3AttrIndexSearcher.SearchBetweenKeys(const anAttrID: array of Integer;
aLowKey: Integer;
aHighKey: Integer;
aDirect: Boolean): Il3RangeEnumerable;
//#UC START# *673F42AE005C_66C47DB501FB_var*
var
l_Dumper : Im3AttrIndexDumper;
l_It : Im3AttrIndexElementEnumerator;
l_Key : Integer;
l_Values : Il3RangeEnumerable;
//#UC END# *673F42AE005C_66C47DB501FB_var*
begin
//#UC START# *673F42AE005C_66C47DB501FB_impl*
Result := nil;
Assert(aLowKey <= aHighKey);
if (aLowKey = aHighKey) then
Result := Self.SearchByKeyEx(anAttrID, aLowKey, aDirect)
else
if (aHighKey - aLowKey <= 200) then
begin
l_Dumper := Tm3AttrIndexDumperJoin.MakeForAttribute(Self.f_BaseName, anAttrID, aDirect);
try
if (l_Dumper <> nil) then
begin
for l_Key := aLowKey to aHighKey do
begin
l_Values := l_Dumper.ValuesByKey(l_Key);
Result := Il3RangeEnumerable_JoinWithOther(Result, l_Values);
end;//for l_Key
end;//l_Dumper <> nil
finally
l_Dumper := nil;
end;//try..finally
end//aHighKey - aLowKey <= 200
else
begin
Assert(aLowKey < aHighKey);
l_Dumper := Tm3AttrIndexDumperJoin.MakeForAttribute(Self.f_BaseName, anAttrID, aDirect);
try
if (l_Dumper <> nil) then
begin
l_It := l_Dumper.GetEnumerator;
if (l_It <> nil) then
begin
while l_It.MoveNext do
begin
l_Key := l_It.Current.ID;
if (l_Key < aLowKey) then
continue
else
if (l_Key > aHighKey) then
break
else
begin
l_Values := l_It.Current.Values;
Result := Il3RangeEnumerable_JoinWithOther(Result, l_Values);
end;//else
end;//while l_It.MoveNext
end;//l_It <> nil
end;//l_Dumper <> nil
finally
l_Dumper := nil;
end;//try..finally
end;//aLowKey = aHighKey
//#UC END# *673F42AE005C_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchBetweenKeys
function Tm3AttrIndexSearcher.SearchByDates(aFrom: TStDate;
aTo: TStDate): Il3RangeEnumerable;
//#UC START# *674046B103B1_66C47DB501FB_var*
//#UC END# *674046B103B1_66C47DB501FB_var*
begin
//#UC START# *674046B103B1_66C47DB501FB_impl*
Result := Self.SearchBetweenKeys([k2_tiNumAndDates, k2_tiStart], aFrom, aTo, false);
//#UC END# *674046B103B1_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByDates
function Tm3AttrIndexSearcher.CommentByInternalHandle(anID: Tm3DocID): Il3CString;
//#UC START# *67484AAC0039_66C47DB501FB_var*
var
{$IfDef m3UseHeaderForName}
l_Header : Il3TagRef;
{$Else m3UseHeaderForName}
//l_ID : Integer;
l_DB : Im3DB;
l_Doc : Im3DBDocument;
l_S : IStream;
l_Extractor : Tm3DocumentInfoExtractor;
l_Reader : TevdNativeReader;
l_WasAbortLoad : Boolean;
l_IsAnno : Boolean;
{$EndIf m3UseHeaderForName}
//#UC END# *67484AAC0039_66C47DB501FB_var*
begin
//#UC START# *67484AAC0039_66C47DB501FB_impl*
Result := nil;
Result := GetDocumentString(k2_tiNameComment, anID);
if (Result <> nil) then
Exit;
Result := GetDocumentString(k2_tiComment, anID);
if (Result <> nil) then
Exit;
{$IfDef m3UseHeaderForName}
l_Header := Self.DocumentHeaderData(anID);
if (l_Header <> nil) then
if (l_Header.AsObject <> nil) then
if l_Header.AsObject.IsValid then
begin
Result := Il3CString_C(l_Header.AsObject.PCharLenA[k2_tiNameComment]);
WriteDocumentString(k2_tiNameComment, anID, Result);
if not l3IsNil(Result) then
Exit;
Result := Il3CString_C(l_Header.AsObject.PCharLenA[k2_tiComment]);
WriteDocumentString(k2_tiComment, anID, Result);
if not l3IsNil(Result) then
Exit;
end;//l_Header.AsObject.IsValid
{$Else m3UseHeaderForName}
l_WasAbortLoad := false;
if (Self.f_DB <> nil) then
l_DB := Self.f_DB
else
l_DB := Tm3DB.Make(f_BaseName);
try
l_Doc := l_DB.GetDocument(anID);
if (l_Doc <> nil) then
begin
l_IsAnno := false;
l_S := l_Doc.Open;
try
if (l_S <> nil) then
begin
if (m2COMGetSize(l_S) <= 0) then
begin
Result := l3Cat(Il3CString_C('Удалён: №'), IntToStr(anID));
Exit;
end;//m2COMGetSize(l_S) <= 0
end;//l_S <> nil
if (l_S = nil) then
begin
l_S := l_Doc.Open(m3_saRead, m3_dsAnno);
// - костылик для аннотаций
if (l_S <> nil) then
l_IsAnno := true;
end;//l_S = nil
if (l_S <> nil) then
begin
l_Extractor := Tm3DocumentInfoExtractor.Create;
try
l_Reader := TevdNativeReader.Create;
try
l_Reader.Generator := l_Extractor;
l_Reader.Filer.Mode := l3_fmRead;
l_Reader.Filer.COMStream := l_S;
try
l_Reader.Start;
try
try
l_Reader.Execute;
except
on El3AbortLoad do
begin
l_WasAbortLoad := true;
end;//on El3AbortLoad
end;//try..except
finally
try
if not l_WasAbortLoad then
l_Reader.Finish;
except
on Ek2TagGeneratorBadFinishCall do
begin
if not l_WasAbortLoad then
raise;
end;//on Ek2TagGeneratorBadFinishCall
end;//try..except
end;//try..finally
finally
l_Reader.Filer.COMStream := nil;
end;//try..finally
finally
FreeAndNil(l_Reader);
end;//try..finally
if not l3IsNil(l_Extractor.DocNameComment) then
begin
if l_IsAnno then
Result := l3Cat('Аннотация: ', l_Extractor.DocNameComment)
else
Result := l_Extractor.DocNameComment;
Exit;
end;//not l3IsNil(l_Extractor.DocNameComment)
if not l3IsNil(l_Extractor.DocComment) then
begin
if l_IsAnno then
Result := l3Cat('Аннотация: ', l_Extractor.DocComment)
else
Result := l_Extractor.DocComment;
Exit;
end;//not l3IsNil(l_Extractor.DocComment)
finally
FreeAndNil(l_Extractor);
end;//try..finally
end;//l_S <> nil
finally
l_S := nil;
end;//try..finally
end;//l_Doc <> nil
finally
l_DB := nil;
end;//try..finally
{$EndIf m3UseHeaderForName}
//l_ID := Self.InternalHandleToExternalHandle(anID);
//Result := nil;
//#UC END# *67484AAC0039_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.CommentByInternalHandle
function Tm3AttrIndexSearcher.CommentByID(anID: Tm3DocID): Il3CString;
//#UC START# *67484AC70170_66C47DB501FB_var*
//#UC END# *67484AC70170_66C47DB501FB_var*
begin
//#UC START# *67484AC70170_66C47DB501FB_impl*
Result := Self.CommentByInternalHandle(anID);
//#UC END# *67484AC70170_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.CommentByID
function Tm3AttrIndexSearcher.Versions(anID: Tm3DocID): Il3IntegerEnumerable;
{* Версии документа. Включая сам документ }
//#UC START# *67A089700158_66C47DB501FB_var*
var
l_L : Tl3LongintList;
l_Internal : Integer;
l_External : Integer;
//#UC END# *67A089700158_66C47DB501FB_var*
begin
//#UC START# *67A089700158_66C47DB501FB_impl*
l_L := Tl3LongintList.Create;
try
if (anID > 0) then
begin
l_L.Add(anID);
// - добавляем себя
l_Internal := anID;
while true do
// - тут ищем по прямому индексу
begin
l_External := Self.SearchFirstByKey(k2_tiExternalVerLink, l_Internal, true);
if (l_External <= 0) then
break;
l_Internal := Self.ExternalHandleToInternalHandle(l_External);
if (l_Internal <= 0) then
break;
if l_L.Has(l_Internal) then
// - чтобы не зацикливаться
break;
l_L.Add(l_Internal);
end;//while true
l_Internal := anID;
l_External := Self.InternalHandleToExternalHandle(l_Internal);
while true do
// - тут ищем по обратному индексу
begin
l_Internal := Self.SearchFirstByKey(k2_tiExternalVerLink, l_External, false);
if (l_Internal <= 0) then
break;
if l_L.Has(l_Internal) then
// - чтобы не зацикливаться
break;
l_L.Insert(0, l_Internal);
l_External := Self.InternalHandleToExternalHandle(l_Internal);
end;//while true
end;//anID > 0
Result := l_L.AsEnumerable;
finally
FreeAndNil(l_L);
end;//try..finally
//#UC END# *67A089700158_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.Versions
function Tm3AttrIndexSearcher.DocumentHeaderData(anID: Tm3DocID): Il3TagRef;
{* Данные заголовка документа. Например ActiveIntervals и NumAndDates }
//#UC START# *67A3604E0118_66C47DB501FB_var*
var
//l_ID : Integer;
(* l_DB : Im3DB;
l_Doc : Im3DBDocument;*)
l_S : IStream;
l_Extractor : Tk2DocumentHeaderBuffer;
l_Reader : TevdNativeReader;
l_WasAbortLoad : Boolean;
//l_IsAnno : Boolean;
//#UC END# *67A3604E0118_66C47DB501FB_var*
begin
//#UC START# *67A3604E0118_66C47DB501FB_impl*
Result := nil;
if (anID < 0) then
Exit;
if (anID = 0) then
Exit;
if (f_DocumentHeaderData <> nil) then
begin
if (f_DocumentHeaderData.AsObject <> nil) then
if f_DocumentHeaderData.AsObject.IsValid then
begin
if (anID = f_PrevDocID) then
begin
Result := f_DocumentHeaderData;
Exit;
end;//anID = f_PrevDocID
end;//f_DocumentHeaderData.AsObject.IsValid
end;//f_DocumentHeaderData <> nil
l_WasAbortLoad := false;
(* if (Self.f_DB <> nil) then
l_DB := Self.f_DB
else
l_DB := Tm3DB.Make(f_BaseName);
try
l_Doc := l_DB.GetDocument(anID);
if (l_Doc <> nil) then*)
begin
//l_IsAnno := false;
l_S := Self.OpenDocStream(anID, m3_saRead, m3_dsMain, 0);
//l_S := l_Doc.Open;
try
if (l_S <> nil) then
begin
if (m2COMGetSize(l_S) <= 0) then
begin
Result := nil;
Exit;
end;//m2COMGetSize(l_S) <= 0
end;//l_S <> nil
(* if (l_S = nil) then
begin
l_S := l_Doc.Open(m3_saRead, m3_dsAnno);
// - костылик для аннотаций
if (l_S <> nil) then
l_IsAnno := true;
end;//l_S = nil*)
if (l_S <> nil) then
begin
l_Extractor := Tk2DocumentHeaderBuffer.Create;
try
l_Reader := TevdNativeReader.Create;
try
l_Reader.Generator := l_Extractor;
l_Reader.Filer.Mode := l3_fmRead;
l_Reader.Filer.COMStream := l_S;
try
l_Reader.Start;
try
try
l_Reader.Execute;
except
on El3AbortLoad do
begin
l_WasAbortLoad := true;
end;//on El3AbortLoad
end;//try..except
finally
try
if not l_WasAbortLoad then
begin
if (l_Extractor.Root = nil) then
l_Reader.Finish
else
begin
Result := l_Extractor.Root.AsRef;
try
l_Reader.Generator := nil;
l_Reader.Finish;
except
on Ek2TagGeneratorBadFinishCall do
begin
end;//on Ek2TagGeneratorBadFinishCall
end;//try..finally
end;//l_Extractor.Root = nil
end;//not l_WasAbortLoad
except
on Ek2TagGeneratorBadFinishCall do
begin
if not l_WasAbortLoad then
raise;
end;//on Ek2TagGeneratorBadFinishCall
end;//try..except
end;//try..finally
finally
l_Reader.Filer.COMStream := nil;
end;//try..finally
finally
FreeAndNil(l_Reader);
end;//try..finally
Assert(l_Extractor.Root <> nil);
Result := l_Extractor.Root.AsRef;
f_DocumentHeaderData := Result;
f_PrevDocID := anID;
finally
FreeAndNil(l_Extractor);
end;//try..finally
end;//l_S <> nil
finally
l_S := nil;
end;//try..finally
end;//l_Doc <> nil
(* finally
l_DB := nil;
end;//try..finally*)
//#UC END# *67A3604E0118_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.DocumentHeaderData
function Tm3AttrIndexSearcher.SearchByType(aDocType: TDocType): Il3RangeEnumerable;
//#UC START# *67A48AB703AC_66C47DB501FB_var*
//#UC END# *67A48AB703AC_66C47DB501FB_var*
begin
//#UC START# *67A48AB703AC_66C47DB501FB_impl*
Result := Self.SearchByKey(k2_tiType, Ord(aDocType), false);
//#UC END# *67A48AB703AC_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByType
function Tm3AttrIndexSearcher.SearchByMaskInKey(anAttrID: Integer;
aMask: Integer): Il3RangeEnumerable;
{* https://mdp.garant.ru/pages/viewpage.action?pageId=877071294 }
//#UC START# *67AB40480209_66C47DB501FB_var*
var
l_Dumper : Im3AttrIndexDumper;
l_It : Im3AttrIndexElementEnumerator;
l_Key : Integer;
l_Values : Il3RangeEnumerable;
//#UC END# *67AB40480209_66C47DB501FB_var*
begin
//#UC START# *67AB40480209_66C47DB501FB_impl*
Result := nil;
l_Dumper := Self.MakeDumper(anAttrID, false);
try
if (l_Dumper <> nil) then
begin
l_It := l_Dumper.GetEnumerator;
if (l_It <> nil) then
begin
while l_It.MoveNext do
begin
l_Key := l_It.Current.ID;
if l3TestMask(l_Key, aMask) then
begin
l_Values := l_It.Current.Values;
Result := Il3RangeEnumerable_JoinWithOther(Result, l_Values);
end;//l3TestMask(l_Key, aMask)
end;//while l_It.MoveNext
end;//l_It <> nil
end;//l_Dumper <> nil
finally
l_Dumper := nil;
end;//try..finally
//#UC END# *67AB40480209_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByMaskInKey
function Tm3AttrIndexSearcher.SearchByMaskInPriceLevel(aMask: Integer): Il3RangeEnumerable;
//#UC START# *67AB45FF015E_66C47DB501FB_var*
//#UC END# *67AB45FF015E_66C47DB501FB_var*
begin
//#UC START# *67AB45FF015E_66C47DB501FB_impl*
Result := Self.SearchByMaskInKey(k2_tiPriceLevel, aMask);
//#UC END# *67AB45FF015E_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.SearchByMaskInPriceLevel
function Tm3AttrIndexSearcher.IndexTimeStamp(anAttrID: Integer;
aDirect: Boolean): TDateTime;
//#UC START# *68EA9627030F_66C47DB501FB_var*
var
l_Dumper : Im3AttrIndexDumper;
//#UC END# *68EA9627030F_66C47DB501FB_var*
begin
//#UC START# *68EA9627030F_66C47DB501FB_impl*
l_Dumper := Self.MakeDumper(anAttrID, aDirect);
if (l_Dumper = nil) then
Result := BadDateTime
else
Result := l_Dumper.TimeStamp;
//#UC END# *68EA9627030F_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.IndexTimeStamp
procedure Tm3AttrIndexSearcher.Cleanup;
{* Функция очистки полей объекта. }
//#UC START# *479731C50290_66C47DB501FB_var*
//#UC END# *479731C50290_66C47DB501FB_var*
begin
//#UC START# *479731C50290_66C47DB501FB_impl*
inherited;
f_PrevDumper := nil;
f_PrevAttr := -1;
f_PrevDocID := -1;
f_DocumentHeaderData := nil;
f_PrevDirect := false;
f_DB := nil;
{$IfDef m3UseCacher}
FreeAndNil(f_Cacher);
{$EndIf m3UseCacher}
FreeAndNil(f_DumpersCache);
f_WasException := false;
//#UC END# *479731C50290_66C47DB501FB_impl*
end;//Tm3AttrIndexSearcher.Cleanup
procedure Tm3AttrIndexSearcher.ClearFields;
begin
f_PrevDumper := nil;
f_DocumentHeaderData := nil;
f_DB := nil;
inherited;
end;//Tm3AttrIndexSearcher.ClearFields
//#UC START# *66C47DB501FBimpl*
{$IfDef FPC}
class destructor Tm3AttrIndexSearcher.done;
begin
f_SearcheableAttributesNames := nil;
f_ContextAttributesNames := nil;
end;
{$EndIf FPC}
constructor Tm3AttrIndexSearcher.CreateFromDumper(const aDumper: Im3AttrIndexDumper;
anAttrID: Integer;
aDirect: Boolean);
begin
f_PrevDumper := aDumper;
f_PrevAttr := anAttrID;
f_PrevDirect := aDirect;
Create('');
end;
class function Tm3AttrIndexSearcher.MakeFromDumper(const aDumper: Im3AttrIndexDumper;
anAttrID: Integer;
aDirect: Boolean): Im3AttrIndexSearcher;
var
l_Inst : Tm3AttrIndexSearcher;
begin
l_Inst := Tm3AttrIndexSearcher.CreateFromDumper(aDumper, anAttrID, aDirect);
try
Result := l_Inst;
finally
FreeAndNil(l_Inst);
end;//try..finally
end;
//#UC END# *66C47DB501FBimpl*
//#UC START# *66C47DB501FBforDiagramm*
(*
*)
//#UC END# *66C47DB501FBforDiagramm*
end.
Заметки о тестировании, программировании и прочий "поток сознания", который жалко писать "в стол"
воскресенье, 12 апреля 2026 г.
m3AttrIndexSearcher
Подписаться на:
Комментарии к сообщению (Atom)
Комментариев нет:
Отправить комментарий