Быстрый поиск в базах данных

{codecitation class=»brush: pascal; gutter: false;» width=»600px»}

Кинул как-то уркаган маляву по Яндексу…

Я представляю на Ваш суд утилиту быстрого поиска по базе данных. Данная технология производит поиск по полям, преобразуя их значения в строки (все значения преобразуются в верхний регистр, включая действительные числа). Данное решение может быть не самым быстрым, однако на поверку оно оказывается быстрее остальных, обнаруженных мною в Интернете (может вам повезет больше). Более того, представьте, что действительное значение какого-либо поля равно 4.509375354, а значение поиска равно 7, в этом случае утилита засчитает «попадание». Утилита удобна также тем, что она за один проход производит поиск более, чем в одном поле. Это удобно, если у Вас имеются, к примеру, два поля с адресами. Это моя первая «серьезная» разработка, так как первое, с чем я столкнулся, изучая Delphi, стала необходимость включения процедуры поиска в любое приложение, работающее с базой данных. А так как поиск — вещь тоже сугубо специфическая, как и любое приложение, то мне пришлось побороть свой страх перед «крутым программированием» и попр

обовать написать свой поисковый механизм, удовлетворивший меня (и, надеюсь, других) своей скоростью и возможностью «мульти»-поиска по нескольким полям. Я надеюсь, что он поможет тем программистам, кто часто сталкивается с подобными задачами. Технология довольно легка для понимания, но если у Вас возникли какие-либо вопросы, пошлите мне письмо электронной почтой, я буду рад Вам помочь. Посмотрев код, можно легко узнать поддерживаемые типы полей (добавить новые не составит проблем). Если кто-либо обнаружит ошибочный код или расширит функциональность утилиты, пожалуйста, пошлите это мне, я буду весьма благодарен. Спасибо.

unit Finder;

interface

uses DB, DBTables, SysUtils;

function GrabMemoFieldAsPChar(TheField: TMemoField): PChar;

function DoFindIn(TheField: TField; SFor: string): Boolean;

function FindIt(TheTable: TDataSet; TheFields: array of integer;

SearchBackward: Boolean; FromBeginning: Boolean; SFor: string): Boolean;

{применение функции FindIt —

if FindIt(NotesSearchT,

[NotesSearchT.FieldByName(‘Leadman’).Index],

False, True, SearchText.Text) then DoSomething; }

implementation

function GrabMemoFieldAsPChar(TheField: TMemoField): PChar;

begin

with TBlobStream.Create(TheField, bmRead) do

begin

GetMem(Result, Size 1);

FillChar(Result^, Size 1, #0);

Read(Result^, Size);

Free;

end;

end;

function DoFindIn(TheField: TField; SFor: string): Boolean;

var

PChForMemo: PChar;

begin

Result := False;

case TheField.DataType of

ftString:

begin

if (Pos(SFor, UpperCase(TheField.AsString)) > 0) then

Result := True;

end;

ftInteger:

begin

if (Pos(SFor, TheField.AsString) > 0) then

Result := True;

end;

ftBoolean:

begin

if SFor = UpperCase(TheField.AsString) then

Result := True;

end;

ftFloat:

begin

if (Pos(SFor, TheField.AsString) > 0) then

Result := True;

end;

ftCurrency:

begin

if (Pos(SFor, TheField.AsString) > 0) then

Result := True;

end;

ftDate..ftDateTime:

begin

if (Pos(SFor, TheField.AsString) > 0) then

Result := True;

end;

ftMemo:

begin

SFor[Ord(SFor[0]) 1] := #0;

PChForMemo := GrabMemoFieldAsPChar(TMemoField(TheField));

StrUpper(PChForMemo);

if not (StrPos(PChForMemo, @SFor[1]) = nil) then

Result :=

True;

FreeMem(PChForMemo, StrLen(PChForMemo 1));

end;

end;

end;

function FindIt(TheTable: TDataSet; TheFields: array of integer;

SearchBackward: Boolean; FromBeginning: Boolean; SFor: string): Boolean;

var

i, HighTheFields, LowTheFields: integer;

BM: TBookmark;

begin

TheTable.DisableControls;

BM := TheTable.GetBookmark;

try

LowTheFields := Low(TheFields);

HighTheFields := High(TheFields);

SFor := UpperCase(SFor);

Result := False;

if FromBeginning then

TheTable.First;

if SearchBackward then

begin

TheTable.Prior;

while not TheTable.BOF do

begin

for i := LowTheFields to HighTheFields do

begin

if DoFindIn(TheTable.Fields[TheFields[i]], SFor) then

begin

Result := True;

Break;

end;

end;

if Result then

Break

else

TheTable.Prior;

end;

end

else

begin

TheTable.Next;

while not TheTable.EOF do

begin

for i := LowTheFields to HighTheFields do

begin

if DoFindIn(TheTable.Fields[TheFields[i]], SFor) then

begin

Result := True;

Break;

end;

end;

if Result then

Break

else

TheTable.Next;

end;

end;

finally

TheTable.EnableControls;

if not Result then

TheTable.GotoBookmark(BM);

TheTable.FreeBookmark(BM);

end;

end;

end.

{/codecitation}

Добавить комментарий