Автор: Подкопаев Владимир
Библиотека для организации поисковой системы в произвольной БД с
помощью динамических SQL запросов.
Описание:
Результатом работы функции:
Search_out(_путь : string): TConrolSearch;
|
является создание файла с формированным SQL запросом, который в
последствии используется компонентов TQuery.
Функция возвращает значение - код ошибки при формировании
запроса. Если 0, то запрос сформирован удачно, в противном случае
формируется код ошибки (например 1, если послан нулевой запрос).
Ошибки младших байтов от 0..4 не являются критическими в плане
неправильного формирования запроса. Старшие байты от 5..8 вызывают
критические ошибки (TSQL не может выполнить запрос).
Перед вызовом функции, необходимо задать параметры объекта для
формирования файла sql запроса.
Описание переменыых объекта Param_:
- table_count
- кол-во используемых таблиц
- tables[1]...tables[table_count]
- список используемых таблиц
Например:
tables_count := 2;
tables[1] := 'uchet';
tables[2] := 'ispol';
|
- Param_.Count
- количество параметров поиска
- .Refernce[i], где 0<i<=Param_.Count
- определяет к какой таблице ссылается параметр.
Например (2 таблицы, 9 параметров):
Param_.Count := 9;
if (UchetCheck.Checked = true) and (IspolCheck.Checked = true) then
begin
tables_count := 2;
tables[1] := 'uchet';
tables[2] := 'ispol';
Param_.Reference[1] := 1;
Param_.Reference[2] := 1;
Param_.Reference[3] := 1;
Param_.Reference[4] := 2;
Param_.Reference[5] := 1;
Param_.Reference[6] := 1;
Param_.Reference[8] := 2;
Param_.Reference[9] := 2;
end;
|
- .Field_Name[i] : String, 0<i<=Param_.Count
- список полей таблиц, связанных с параметрами поиска
- .param_type[i] : PType, 0<i<=Param_.Count
- тип параметра ('S' - строка, 'D' -дата, 'C' - словарь, 'N' -
числовой)
- .Inverse[i] : EqType : boolean
- определяет использование '=' или '!=' с данным параметром
(кроме типов '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;
interface
const
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] of string;
type EqTypeList = string[2];
type TControlSearch = record
SetByte: byte;
GetByteString: array [0..7] of string;
end;
type StrArr = array [1..50] of string[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] of string[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;
implementation
uses
SysUtils;
procedure Clear_Search;
var
k: integer;
begin
for k := 1 to 50 do
Param_.param_value[k] := '';
end;
function Search_out(path: string): TControlSearch;
//Error Section
const
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 '
else
begin
SELECT := SEL;
TMP_SELECT := '';
for FieldCount := 1 to ListFieldCount do
begin
if FieldCount = ListFieldCount then
begin
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] <> '' then
begin
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 CHECK
if CtrlString = '' then
begin
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;
end
else
begin
Search_out.SetByte := 0;
Search_out.GetByteString[0] := '';
end;
i := 0;
AssignFile(Sql_File,path);
path_ := path;
Rewrite(Sql_File);
if tables_count > 1 then
begin
while i <> tables_count do
begin
inc(i);
if i = tables_count then
first_str := first_str + tables[i]
else
first_str := first_str + tables[i] + C;
end; //WHILE
end
else
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') then
if i < Param_Result.Count then
begin
if 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)
else
if 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);
end
else
begin
if 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 + ')')
else
if 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') then
begin
if i + 1 < Param_Result.Count then
begin
if (Param_Result.param_type[i+1] = 'D') and
(Param_Result.Reference[i] = Param_Result.Reference[i + 1]) then
begin
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
end
else
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') then
begin
if (Param_Result.param_type[i+1] = 'D')
and (Param_Result.Reference[i] = Param_Result.Reference[i + 1]) then
begin
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
end
else
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') then
begin
if (Param_Result.param_type[i+1] = 'D') and
(Param_Result.Reference[i] = Param_Result.Reference[i + 1]) then
begin
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
end
else
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') then
if i < Param_Result.Count then
begin
if Param_Result.Equality[i] = false then
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i] +
L + Param_Result.param_name + PR + A)
else
if 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);
end
else
begin
if Param_Result.Equality[i] = false then
writeln(Sql_File,table_str + C_ + Param_Result.Field_Name[i] +
L + Param_Result.param_name + PR )
else
if 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') then
if i < Param_Result.Count then
begin
if 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);
end
else
begin
if 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 FUNCTION
function 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 FUNCTION
procedure SetOrder(o: integer; str: string);
var
t_str: string;
begin
AssignFile(Sql_File,path_);
Append(Sql_File);
if str = 'N' then
begin
t_str := tables[param_.Reference[o]];
writeln(Sql_file,ORD_+t_str+'.'+Param_.Field_Name[o]);
Close(Sql_File);
end
else
begin
writeln(Sql_file,ORD_+' '+str);
Close(Sql_File);
end;
end; // END PROCEDURE
end.
|
|