скрыть

скрыть

  Форум  

Delphi FAQ - Часто задаваемые вопросы

| Базы данных | Графика и Игры | Интернет и Сети | Компоненты и Классы | Мультимедиа |
| ОС и Железо | Программа и Интерфейс | Рабочий стол | Синтаксис | Технологии | Файловая система |



Google  
 

Библиотека для создания динамических SQL скриптов



Автор: Подкопаев Владимир

Библиотека для организации поисковой системы в произвольной БД с помощью динамических 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.






Copyright © 2004-2016 "Delphi Sources". Delphi World FAQ




Группа ВКонтакте   Ссылка на Twitter   Группа на Facebook