- Код: Выделить всё
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);
Сортировка на стороне сервера, наконец, стала возможной . Приветстуются поправки и комментарии.