Библиотека для организации поисковой системы в произвольной БД с помощью динамических SQL запросов.
Описание:
Результатом работы функции:
Search_out(_путь : string): TConrolSearch;
является создание файла с формированным SQL запросом, который в последствии используется компонентов TQuery.
Функция возвращает значение - код ошибки при формировании запроса. Если 0, то запрос сформирован удачно, в противном случае формируется код ошибки (например 1, если послан нулевой запрос). Ошибки младших байтов от 0..4 не являются критическими в плане неправильного формирования запроса. Старшие байты от 5..8 вызывают критические ошибки (TSQL не может выполнить запрос).
Перед вызовом функции, необходимо задать параметры объекта для формирования файла sql запроса.
определяет использование '=' или '!=' с данным параметром (кроме типов 'C' и 'N')
.Equality[i] : EqType : boolean
определяет полное или частичное совпадение параметра поиска (только для типа 'S')
.param_value[i] : StrArr
определяет значения параметров
.param_name : string
текущее значение параметра
.NumEq : ETL (:EqTypeList)
определяет использование знака '=', '>', '<' вместе с типом 'N'
Процедура Clear_Search
очищает значения param_value в диапазоне от 1..50, рекомендуется использовать для очистки старых параметров поиска перед заданием новых параметров. По умолчанию процедура включена в основную функцию search_out.
Функция Param_Set
используется для установки параметров кретерия поиска.
c_d = 'C'
создать таблицу, 'D', удалить таблицу, 'N' - не создавать таблицу
unit Search_engine;
interfaceconst
err0 = 'Search_out';
eq = '=';
min = '<';
max = '>';
eq_min = '=<';
eq_max = '>=';
min_max = '!=';
SEL = 'SELECT';
FROM = 'FROM ';
U = '''';
C = ',';
C_ = '.';
P = ' :PARAM_';
L = ' LIKE ';
A = ' AND ';
PP = '+';
PR = '%';
BTW = ' BETWEEN ';
N = ' !';
UP = 'upper';
ORD_ = 'ORDER BY ';
type PTypeList = 'A'..'Z';
type TFieldList = array [1..50] ofstring;
type EqTypeList = string[2];
type TControlSearch = record
SetByte: byte;
GetByteString: array [0..7] ofstring;
end;
type StrArr = array [1..50] ofstring[30];
RefArr = array [1..50] of integer;
PType = array [1..50] of PTypeList; // 'S' - string, 'D' - dateTime, 'N' - numeric, 'C' - vocabulary
EqType = array [1..50] of boolean;
TOrder = array [1..50] of integer;
ETL = array [1..50] ofstring[2];
Param = object
param_value : StrArr;
Field_Name : StrArr;
Reference : RefArr;
Count : integer;
param_name : string;
param_type : PType;
Equality : EqType;
Inverse : EqType; //Working only if Equality[i] = true
NumEq : ETL;
Order : TOrder;
end;
type Param_Result_ = object
param_value : StrArr;
Field_Name : StrArr;
Reference : RefArr;
Count : integer;
param_name : string;
param_type : PType;
Equality : EqType;
Inverse : EqType;
NumEq : ETL;
Order : TOrder;
end;
var
search_param_count, tables_count: integer;
Sql_File : Text;
tables : StrArr;
Param_ : Param;
Param_Result : Param_Result_;
ListField : TFieldList;
ListFieldCount : integer;
path_ : string;
procedure Clear_Search;
procedure SetOrder(o : integer;str : string);
function Search_out(path : string) : TControlSearch;
function Param_Set(NumParam: integer; FieldName: string; Ref: integer;
Equal: boolean; P_Type: char; P_Value: variant): TControlSearch;
implementationuses
SysUtils;
procedure Clear_Search;
var
k: integer;
beginfor k := 1 to 50 do
Param_.param_value[k] := '';
end;
function Search_out(path: string): TControlSearch;
//Error Sectionconst
err1 = 'ZeroCtrlString';
var
first_str : string;
i : integer;
table_str : string;
Result_param : StrArr;
CtrlString : string;
SELECT,
TMP_SELECT : string;
FieldCount : integer;
f_type : string;
begin
i := 0;
Param_Result.Count := 0;
if ListFieldCount = 0 then
SELECT := 'SELECT* FROM '
elsebegin
SELECT := SEL;
TMP_SELECT := '';
for FieldCount := 1 to ListFieldCount dobeginif FieldCount = ListFieldCount thenbegin
TMP_SELECT := TMP_SELECT + ' ' + ListField[FieldCount];
break;
end;
TMP_SELECT := TMP_SELECT + ' ' + ListField[FieldCount] + C;
end;
SELECT := SELECT + ' ' + TMP_SELECT + ' ' + FROM;
end;
repeat
inc(i);
if Param_.param_value[i] <> '' thenbegin
inc(Param_Result.Count);
Param_Result.param_value[Param_Result.Count] := Param_.param_value[i];
CtrlString := CtrlString + Param_.param_value[i];
Param_Result.Field_Name[Param_Result.Count] := Param_.Field_Name[i];
Param_Result.Reference[Param_Result.Count] := Param_.Reference[i];
Param_Result.Param_type[Param_Result.Count] := Param_.Param_type[i];
Param_Result.Equality[Param_Result.Count] := Param_.Equality[i];
Param_Result.Inverse[Param_Result.Count] := Param_.Inverse[i];
Param_Result.NumEq[Param_Result.Count] := Param_.NumEq[i];
end;
until
i = Param_.Count;
// 1 BIT ERROR CHECKif CtrlString = '' thenbegin
Search_out.SetByte := 1;
Search_out.GetByteString[1] := Err0 + C_ + Err1;
AssignFile(Sql_File,path);
Rewrite(Sql_File);
writeln(Sql_File,SELECT+tables[1]);
CloseFile(Sql_file);
exit;
endelsebegin
Search_out.SetByte := 0;
Search_out.GetByteString[0] := '';
end;
i := 0;
AssignFile(Sql_File,path);
path_ := path;
Rewrite(Sql_File);
if tables_count > 1 thenbeginwhile i <> tables_count dobegin
inc(i);
if i = tables_count then
first_str := first_str + tables[i]
else
first_str := first_str + tables[i] + C;
end; //WHILEendelse
first_str := tables[1];
first_str := SELECT + first_str;
writeln(Sql_File,first_str);
writeln(Sql_File,'WHERE');
i := 0;
{!MAIN REPEAT!}repeat
inc(i);
table_str := tables[param_Result.Reference[i]];
Param_Result.param_name := Param_Result.param_value[i];
//СТРОКОВЫЙ ТИПif (Param_Result.param_type[i] = 'S') thenif i < Param_Result.Count thenbeginif Param_Result.Equality[i] = false then
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i] +
L + UP +'(' + U + Param_Result.param_name + PR + U +')' + A)
elseif Param_Result.Inverse[i] = false then
writeln(Sql_file,table_str + C_ + Param_Result.Field_Name[i] +
'='+U+ Param_Result.param_name+U+A)
else
writeln(Sql_file,table_str + C_ + Param_Result.Field_Name[i] +
N+'='+U+ Param_Result.param_name+U+A);
endelsebeginif Param_Result.Equality[i] = false then
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i] +
L + UP + '(' + U + Param_Result.param_name + PR + U + ')')
elseif Param_Result.Inverse[i] = false then
writeln(Sql_file,table_str + C_ + Param_Result.Field_Name[i] +
'='+U+ Param_Result.param_name+U)
else
writeln(Sql_file,table_str + C_ + Param_Result.Field_Name[i] +
N+'='+U+ Param_Result.param_name+U);
end;
// ТИП ДАТАif (Param_Result.param_type[i] = 'D') thenbeginif i + 1 < Param_Result.Count thenbeginif (Param_Result.param_type[i+1] = 'D') and
(Param_Result.Reference[i] = Param_Result.Reference[i + 1]) thenbegin
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i]
+ BTW + U+Param_Result.param_name +U+ ' ' + A +U +
Param_Result.param_value[i+1]+ U + ' '+ A);i := i + 1
endelse
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i]
+'='+U+Param_Result.param_name +U+A);
end;
if (i + 1 = Param_Result.Count) and (Param_Result.param_type[i+1] <> 'D') thenbeginif (Param_Result.param_type[i+1] = 'D')
and (Param_Result.Reference[i] = Param_Result.Reference[i + 1]) thenbegin
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i]
+ BTW + U+Param_Result.param_name +U+ ' ' + A +U +
Param_Result.param_value[i+1]+ U + ' '+ A);i := i + 1
endelse
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i]
+'='+U+Param_Result.param_name +U+A);
end;
if (i + 1 = Param_Result.Count) and (Param_Result.param_type[i+1] = 'D') thenbeginif (Param_Result.param_type[i+1] = 'D') and
(Param_Result.Reference[i] = Param_Result.Reference[i + 1]) thenbegin
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i]
+ BTW + U+Param_Result.param_name +U+ ' ' + A +U +
Param_Result.param_value[i+1]+ U + ' ');i := i + 1
endelse
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i]
+'='+U+Param_Result.param_name +U);
end;
end;
// ТИП СЛОВАРЬif (Param_Result.param_type[i] = 'C') thenif i < Param_Result.Count thenbeginif Param_Result.Equality[i] = false then
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i] +
L + Param_Result.param_name + PR + A)
elseif Param_Result.Inverse[i] = false then
writeln(Sql_file,table_str + C_ + Param_Result.Field_Name[i] +
'='+ Param_Result.param_name+A)
else
writeln(Sql_file,table_str + C_ + Param_Result.Field_Name[i] +
N+'='+ Param_Result.param_name+A);
endelsebeginif Param_Result.Equality[i] = false then
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i] +
L + Param_Result.param_name + PR )
elseif Param_Result.Inverse[i] = false then
writeln(Sql_file,table_str + C_ + Param_Result.Field_Name[i] +
'='+ Param_Result.param_name)
else
writeln(Sql_file,table_str + C_ + Param_Result.Field_Name[i] +
N+'='+ Param_Result.param_name);
end;
// ТИП ЧИСЛОВОЕ ЗНАЧЕНИЕif (Param_Result.param_type[i] = 'N') thenif i < Param_Result.Count thenbeginif Param_Result.NumEq[i] = eq then
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i] +
eq + Param_Result.param_name + A);
if Param_Result.NumEq[i] = min then
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i] +
min + Param_Result.param_name + A);
if Param_Result.NumEq[i] = max then
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i] +
max + Param_Result.param_name + A);
if Param_Result.NumEq[i] = eq_max then
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i] +
eq_max + Param_Result.param_name + A);
if Param_Result.NumEq[i] = eq_min then
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i] +
eq_min + Param_Result.param_name + A);
if Param_Result.NumEq[i] = min_max then
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i] +
min_max + Param_Result.param_name + A);
endelsebeginif Param_Result.NumEq[i] = eq then
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i] +
eq + Param_Result.param_name);
if Param_Result.NumEq[i] = min then
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i] +
min + Param_Result.param_name);
if Param_Result.NumEq[i] = max then
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i] +
max + Param_Result.param_name);
if Param_Result.NumEq[i] = eq_max then
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i] +
eq_max + Param_Result.param_name);
if Param_Result.NumEq[i] = eq_min then
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i] +
eq_min + Param_Result.param_name);
if Param_Result.NumEq[i] = min_max then
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i] +
min_max + Param_Result.param_name);
end;
{!MAIN REPEAT!}until
i = Param_Result.Count;
CloseFile(Sql_File);
Clear_Search;
end; // END FUNCTIONfunction Param_Set(NumParam: integer; FieldName: string; Ref: integer;
Equal: boolean; P_Type: char; P_Value: variant): TControlSearch;
begin
Param_.Field_Name[NumParam] := FieldName;
Param_.Reference[NumParam] := Ref;
Param_.Equality[NumParam] := Equal;
Param_.param_type[NumParam] := P_Type;
Param_.param_value[NumParam] := P_value;
end; //END FUNCTIONprocedure SetOrder(o: integer; str: string);
var
t_str: string;
begin
AssignFile(Sql_File,path_);
Append(Sql_File);
if str = 'N' thenbegin
t_str := tables[param_.Reference[o]];
writeln(Sql_file,ORD_+t_str+'.'+Param_.Field_Name[o]);
Close(Sql_File);
endelsebegin
writeln(Sql_file,ORD_+' '+str);
Close(Sql_File);
end;
end; // END PROCEDUREend.
Это библиотека Delphi для создания динамических скриптов SQL для организации поисковых систем в различных базах данных с помощью динамических запросов SQL.
Вот разбивка кода:
Структура библиотеки
Библиотека состоит из нескольких модулей, включая Search_engine, который содержит основные функции и процедуры. Другие модули используются для обработки конкретных задач или операций в библиотеке.
Основные функции и процедуры
1. Search_out: Функция генерирует файл SQL-скрипта на основе параметров, определенных пользователем, и критериев.
2. Param_Set: Процедура устанавливает параметры для поисковой системы, такие как имена полей, ссылки, условия равенства и типы параметров.
3. Clear_Search: Процедура очищает предыдущие результаты поиска и сбрасывает поисковую систему.
Логика поисковой системы
Функция Search_out перебирает список параметров (определенных в объекте Param_) для генерации запросов SQL для каждого параметра. Функция обрабатывает различные типы данных, такие как строки, даты, числовые значения и термины лексики, используя специфическую логику и синтаксис.
Например:
Для строковых параметров она использует оператор LIKE с wildcard ( % ) для поиска совпадающих значений.
Для параметров даты она использует оператор BETWEEN для указания диапазона дат.
Для числовых значений параметров она использует операторы сравнения (= , < , > и т.д.) для фильтрации результатов.
Обработка ошибок
Библиотека включает в себя основную обработку ошибок с помощью констант и сообщений об ошибках. Если происходит ошибка при поиске, функция возвращает конкретный код ошибки и сообщение.
Дополнительные процедуры
1. SetOrder: Процедура устанавливает порядок полей в выходном файле SQL-скрипта.
В целом, эта библиотека предоставляет мощную рамку для создания динамических скриптов SQL для поддержки поисковых операций в различных базах данных.
Библиотека для создания динамических SQL-скриптов, позволяющая формировать запросы к произвольной базе данных с помощью поисковой системы.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.