Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

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

Delphi , Базы данных , SQL

Библиотека для создания динамических 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.

Это библиотека 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




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: SQL ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-19 13:29:56
2024-11-21 13:26:55/0.0069670677185059/1