Сортировщик TRxDBGrid для TSQLQuery

Модераторы: alexs, Модераторы

Сортировщик TRxDBGrid для TSQLQuery

Сообщение BugMaker » 23.07.2011 22:39:23

Не нашел сортировщика для стандартного TSQLQuery, и решил написать свой.
Код: Выделить всё
unit exsortsql;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, DB,
  {$IFDEF FPC}
  RxDBGrid
  {$ELSE}
  exDBGrid
  {$ENDIF}
  ;

type

  { TSQLQuerySortEngine }

  TSQLQuerySortEngine = class(TRxDBGridSortEngine)
  public
    procedure Sort(Field:TField; ADataSet:TDataSet; Asc:boolean; SortOptions:TRxSortEngineOptions);override;
  end;

implementation
uses SQLDB, synRegExpr, strUtils;


procedure TSQLQuerySortEngine.Sort(Field: TField; ADataSet: TDataSet;
  Asc: boolean; SortOptions: TRxSortEngineOptions);
var cmd:string;
  strLen:Integer;
  RegExpr: TRegExpr;
  Mask:String;
  s:String;
begin
  if Assigned(ADataSet) and ADataset.Active then begin
    cmd:=(ADataSet as TSQLQuery).SQL.Text;
    strlen:=length(cmd);
    //Регулярное выражение позволяет найти уже имеющуюся конструкцию ORDER BY,
    //если она написана одной строкой, и между словами не понапихали комментариев :)
    //Работоспособные примеры:
    //ORDER BY FIELD1, FIELD2 DESC, FIELD100500
    //oRdeR bY    fielD1   ,   FiElD2,FieLD100500 DESC
    //Неработоспособный:
    //ORDER BY FIELD1,
    //FIELD2,
    //FIELD100500
    mask:='(?i)(^|\s)\s*order\s+by\s+\S+\.?\S*(\s+desc)?\s*(,\s*\S+\.?\S*(\s+desc)?(^|s*))*';
    with TRegExpr.Create do begin

      Expression := mask;
      if Exec(cmd) then begin
        s:=LeftStr(cmd,MatchPos[0]-1)
        +slinebreak+'order by '
        +Field.FieldName
        +' ';
        if not asc then s:=s+'DESC';
        s:=s+slineBreak
        +RightStr(cmd, strlen-MatchPos[0]-MatchLen[0]+1);
      end
      else
      begin
        s:=cmd+slinebreak+'order by '
        +Field.FieldName
        +' ';
        if not asc then s:=s+'DESC';
        s:=s+slineBreak
      end;
      ADataSet.Active:=False;
      (ADataSet as TSQLQuery).SQL.Text:=s;
      ADataSet.Active:=True;

      Free;
    end;
  end;
end;

initialization
  RegisterRxDBGridSortEngine(TSQLQuerySortEngine, TSQLQuery);
end.

Заработало, но появилась проблема, при отключении dataset для обновления запроса, rxgrid забывает, что у него идет сортировка по возрастанию, и сбрасывает свое состояние, считая, что он не сортирован вовсе. Таким образом, обратной сортировки так вот просто добиться не удалось.

Немного модифицировал RXDBGRID.PAS
Добавил переменную fSortingNow, которая запрещает сброс параметров сортировки в LinkActive RXDBGrid'а, если он срабатывает в момент сортировки.
Код: Выделить всё
--- C:/Users/BlackBug/Desktop/rxdbgrid.pas   Сб июл 23 17:14:44 2011
+++ C:/lazarus/components/rxfpc/rxdbgrid.pas   Вс июл 24 02:55:33 2011
@@ -325,6 +325,7 @@
   { TRxDBGrid }
   TRxDBGrid = class(TCustomDBGrid)
   private
+    FSortingNow:Boolean;
     FInProcessCalc: integer;
     FAllowedOperations: TRxDBGridAllowedOperations;
     FFooterColor: TColor;
@@ -1932,8 +1933,10 @@
     if SelectedRows.Count > 0 then
       SelectedRows.Clear;
   end;
-  FSortField := nil;
-  FSortOrder := smNone;
+  if not FSortingNow then begin
+    FSortField := nil;
+    FSortOrder := smNone;
+  end;

   F_SortListField.Clear;
   if not (csDestroying in ComponentState) and not (csDesigning in ComponentState) then
@@ -2080,8 +2083,10 @@
       FSortField := AField;
       FSortOrder := smUp;
     end;
+    FSortingNow:=true;
     FSortEngine.Sort(FSortField, DataSource.DataSet, FSortOrder =
       smUp, SortEngineOptions);
+    FSortingNow:=false;
   end
   else
     HeaderClick(True, ACol);

Сортировка на стороне сервера, наконец, стала возможной :). Приветстуются поправки и комментарии.
BugMaker
новенький
 
Сообщения: 10
Зарегистрирован: 23.07.2011 22:26:56

Re: Сортировщик TRxDBGrid для TSQLQuery

Сообщение BugMaker » 25.07.2011 02:41:27

Ребят, я сейчас делаю свой первый относительно крупный проект на лазаре. Перед этим был убежденным дельфистом. Попробовал написать консольное приложение, и забыл про Лазарь на несколько месяцев. Теперь понадобилось написать приложение, которое будет лицензионно чистым, и я вновь вернулся к лазарю. Хотелось бы получить ощущение, что я впервые сделал что-то полезное для Open Source сообщества, либо получить наставления для чайника, коим я по большому счету, и являюсь. Я сам привык ковыряться только в своем коде, и не лазить в чужом, считая его по умолчанию идеальным. Вроде как Delphi коммерческий проект, и в Borland (ныне CodeGear) работают спецы, коим я в подметки не гожусь. Я не разработал ни одного компонента ни в Delphi, ни в Лазаре. Потому что пока не вникал, как это делать. Надеюсь, вскоре разберусь. Регулярные выражения тоже были изучены мною лишь пару дней назад по википедии. До этого умудрялся обходиться без них. И что, ни у кого нет комментариев по поводу моего, вроде бы, не самого идеального кода?! Тем более, в RXLib я стал вникать лишь по поводу грида, имеющего сортировку (которую, по факту, после нескольких часов разборок причины отсутствия оной пришлось допиливать самому). До этого использовал в тяжелых случаях EhLib, либо обходился штатным DBGrid. Критикуйте, молчание намного суровее звучит, к тому же не вносит ни толики самообразования :)
BugMaker
новенький
 
Сообщения: 10
Зарегистрирован: 23.07.2011 22:26:56

Re: Сортировщик TRxDBGrid для TSQLQuery

Сообщение alexs » 27.07.2011 20:39:16

Спасибо
Включу код в транк.

PS
BugMaker писал(а): Критикуйте, молчание намного суровее звучит, к тому же не вносит ни толики самообразования :)

Всё нормально, не комплексуй...
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Сортировщик TRxDBGrid для TSQLQuery

Сообщение alexs » 28.08.2011 00:03:00

Приношу извинения за задержку с комитом.
Сегодня, входе плановых багофиксов над библиотекой, включил твой код в транк.
Если будут замечания по поводу заголовка файла - сообщай. Я указал для него лицензию, такую же, как и для всей библиотеки. Также указал в качестве автора твой ник с форума.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Сортировщик TRxDBGrid для TSQLQuery

Сообщение BugMaker » 04.09.2011 18:05:45

Вот он, момент славы :). На самом деле, код не идеальный. Мной не учтено, что может использоваться инструкция LIMIT в SQL запросе, поэтому если изначально в запросе не было инструкции ORDER BY, то он попытается вставить его в конце запроса - после LIMITа. Это приведет к ошибке. Поэтому в сложных запросах лучше вставить ORDER BY ROWID, если сортировка не нужна, или с любым другим полем, если нужна. Так же может быть проблема с JOINом нескольких таблиц, имеющих поля с одинаковым названием. В SQLITE это можно решить например, так: select tbl1.id as tbl1_id, select tbl2.id as tbl2_id, avg(tbl1.(value)) as avg_value. При этом сортировка отработает отлично по любому из этих полей, используя псевдоним (tbl1_id, tbl2_id, avg_value). А вот MS SQL, насколько я понимаю, такие финты ушами не одобряет :(. Ей подавай что-то вроде ORDER BY tbl2.id, avg(tbl1.(value)). Наверное можно написать какой-нибудь парсер запроса, чтобы он по псевдониму находил ссылку на само поле, и подставлял его в операцию ORDER BY. В общем, простор для творчества тут еще имеется :). Но я вряд ли займусь этим.
BugMaker
новенький
 
Сообщения: 10
Зарегистрирован: 23.07.2011 22:26:56

Re: Сортировщик TRxDBGrid для TSQLQuery

Сообщение alexs » 04.09.2011 20:36:44

По хорошему, необходимо разобраться с представлением данных в буфере TSQLQuery - и реализовать локальную сортировку, без переоткрытия запроса. Так будет лучше. Но это если у тебя будет желание и возможность.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Сортировщик TRxDBGrid для TSQLQuery

Сообщение Xenar » 23.02.2013 11:25:53

А есть ли рабочий пример работы сортировки в RxDBGrid для SQLQuery с учетом этого патча? Я так понял что в стандартном варианте сортировка работает только от RXMemoryData
Аватара пользователя
Xenar
постоялец
 
Сообщения: 158
Зарегистрирован: 08.06.2011 12:54:07

Re: Сортировщик TRxDBGrid для TSQLQuery

Сообщение alexs » 23.02.2013 17:24:26

Вот. Есть повод для статьи. Постараюсь в ближайщее время выложить описание.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Сортировщик TRxDBGrid для TSQLQuery

Сообщение Xenar » 23.02.2013 18:36:09

Очень жду.
Аватара пользователя
Xenar
постоялец
 
Сообщения: 158
Зарегистрирован: 08.06.2011 12:54:07

Re: Сортировщик TRxDBGrid для TSQLQuery

Сообщение alexs » 24.02.2013 00:48:31

Получилось немного сумбурно - http://w7site.ru/wp/?p=61
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Сортировщик TRxDBGrid для TSQLQuery

Сообщение Xenar » 24.02.2013 08:09:00

Спс за описание. Но идут следующие проблемы.
1) При подключении модуля exsortsql в uses получаю сообщение что не может найти этот модуль хотя по ссылке на него переходит. Ладно скинул этот файлик в проект. Прокатило.
2) При запуске проекта получаю сразу же ошибку
Код: Выделить всё
exsortsql.pas(104,60) Error: Incompatible type for arg no. 2: Got "Class Of TSQLQuery", expected "AnsiString"

на участок
Код: Выделить всё
RegisterRxDBGridSortEngine(TSQLQuerySortEngine, TSQLQuery);

Кроме как подключения этот модуля ничего более не делалось
Аватара пользователя
Xenar
постоялец
 
Сообщения: 158
Зарегистрирован: 08.06.2011 12:54:07

Re: Сортировщик TRxDBGrid для TSQLQuery

Сообщение alexs » 24.02.2013 13:15:53

Проверю. Именно эта сортировка не очень. Там при сортировке происходит переоткрытие запроса. Если есть возможность - лучше использовать для доступа к данным библиотеку Zeos. SqlDB штатный коряво написан. Я в свое время от него отказался - не смог победить все глюки.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Сортировщик TRxDBGrid для TSQLQuery

Сообщение alexs » 25.02.2013 21:24:46

Доработки сортировщиков. Сделал визуальный компонент для сортировщика SqlDB. Соответсвенно появился новый пакет - его надо установить предварительно.
Попутно исправил ошибки компиляции.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Сортировщик TRxDBGrid для TSQLQuery

Сообщение Xenar » 26.02.2013 11:05:16

Все отлично, заработало. Огромное спасибо. :!:
Аватара пользователя
Xenar
постоялец
 
Сообщения: 158
Зарегистрирован: 08.06.2011 12:54:07

Re: Сортировщик TRxDBGrid для TSQLQuery

Сообщение alexs » 03.04.2013 19:33:22

Если желание - покопай код.
Я этот движок не использую. Корявый он.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

След.

Вернуться в RxLib

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5

Рейтинг@Mail.ru