Сортировщик TRxDBGrid для TSQLQuery
 Добавлено: 23.07.2011 22:39:23
Добавлено: 23.07.2011 22:39:23Не нашел сортировщика для стандартного TSQLQuery, и решил написать свой.
Заработало, но появилась проблема, при отключении dataset для обновления запроса, rxgrid забывает, что у него идет сортировка по возрастанию, и сбрасывает свое состояние, считая, что он не сортирован вовсе. Таким образом, обратной сортировки так вот просто добиться не удалось.
Немного модифицировал RXDBGRID.PAS
Добавил переменную fSortingNow, которая запрещает сброс параметров сортировки в LinkActive RXDBGrid'а, если он срабатывает в момент сортировки.
Сортировка на стороне сервера, наконец, стала возможной . Приветстуются поправки и комментарии.
. Приветстуются поправки и комментарии.
			- Код: Выделить всё
- 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);
Сортировка на стороне сервера, наконец, стала возможной
 . Приветстуются поправки и комментарии.
. Приветстуются поправки и комментарии. . Ей подавай что-то вроде ORDER BY  tbl2.id, avg(tbl1.(value)). Наверное можно написать какой-нибудь парсер запроса, чтобы он по псевдониму находил ссылку на само поле, и подставлял его в операцию ORDER BY. В общем, простор для творчества тут еще имеется
. Ей подавай что-то вроде ORDER BY  tbl2.id, avg(tbl1.(value)). Наверное можно написать какой-нибудь парсер запроса, чтобы он по псевдониму находил ссылку на само поле, и подставлял его в операцию ORDER BY. В общем, простор для творчества тут еще имеется 