mirror of
https://gitlab.com/freepascal.org/fpc/pas2js.git
synced 2025-04-17 16:39:22 +02:00
* Added filtering
This commit is contained in:
parent
50d5a647bd
commit
5d7b0b4891
@ -5,7 +5,7 @@ unit JSONDataset;
|
||||
interface
|
||||
|
||||
uses
|
||||
Types, JS, DB, Classes, SysUtils, typinfo;
|
||||
Types, JS, DB, Classes, SysUtils, typinfo, fpexprpars;
|
||||
|
||||
type
|
||||
TBaseJSONDataset = Class;
|
||||
@ -255,14 +255,28 @@ type
|
||||
// When editing, this object is edited.
|
||||
FEditIdx : Integer;
|
||||
FEditRow : JSValue;
|
||||
// When filtering, this is the current row;
|
||||
FFilterRow : JSValue;
|
||||
FUseDateTimeFormatFields: Boolean;
|
||||
FRowType: TJSONRowType;
|
||||
FFilterExpression : TFPExpressionParser;
|
||||
function GetFilterField(const AName: String): TFPExpressionResult;
|
||||
procedure SetActiveIndex(AValue: String);
|
||||
procedure SetIndexes(AValue: TJSONIndexDefs);
|
||||
procedure SetMetaData(AValue: TJSObject);
|
||||
procedure SetRows(AValue: TJSArray);
|
||||
procedure SetRowType(AValue: TJSONRowType);
|
||||
protected
|
||||
// Determine filter value type based on field type
|
||||
function FieldTypeToExpressionType(aDataType: TFieldType): TResultType; virtual;
|
||||
// Callback for IsNull filter function.
|
||||
function GetFilterIsNull(const Args: TExprParameterArray): TFPExpressionResult; virtual;
|
||||
// Expression parser class. Override this to create a customized version.
|
||||
function FilterExpressionClass: TFPExpressionParserClass; virtual;
|
||||
// Create filter expression.
|
||||
function CreateFilterExpression: TFPExpressionParser; virtual;
|
||||
// Function called to check if current buffer should be accepted.
|
||||
function DoFilterRecord: Boolean; virtual;
|
||||
// Override this to return customized version.
|
||||
function CreateIndexDefs: TJSONIndexDefs; virtual;
|
||||
// override this to return a customized version if you are so inclined
|
||||
@ -287,6 +301,8 @@ type
|
||||
procedure InternalCancel; override;
|
||||
procedure InternalInitFieldDefs; override;
|
||||
procedure InternalSetToRecord(Buffer: TDataRecord); override;
|
||||
procedure SetFilterText(const Value: string); override;
|
||||
procedure SetFiltered(Value: Boolean); override;
|
||||
function GetFieldClass(FieldType: TFieldType): TFieldClass; override;
|
||||
function IsCursorOpen: Boolean; override;
|
||||
// Bookmark operations
|
||||
@ -1142,36 +1158,141 @@ begin
|
||||
FCurrentIndex:=FDefaultIndex;
|
||||
end;
|
||||
|
||||
function TBaseJSONDataSet.FilterExpressionClass : TFPExpressionParserClass;
|
||||
|
||||
begin
|
||||
Result:=TFPExpressionParser;
|
||||
end;
|
||||
|
||||
function TBaseJSONDataSet.GetFilterIsNull(Const Args : TExprParameterArray) : TFPExpressionResult;
|
||||
|
||||
begin
|
||||
Result.ResultType:=rtBoolean;
|
||||
Result.ResValue:=FieldByName(String(Args[0].resValue)).IsNull;
|
||||
end;
|
||||
|
||||
function TBaseJSONDataSet.FieldTypeToExpressionType(aDataType : TFieldType) : TResultType;
|
||||
|
||||
begin
|
||||
Case aDataType of
|
||||
ftMemo,
|
||||
ftFixedChar,
|
||||
ftString : Result:=rtString;
|
||||
ftInteger,
|
||||
ftAutoInc,
|
||||
ftLargeInt : Result:=rtInteger;
|
||||
ftBoolean : Result:=rtBoolean;
|
||||
ftFloat : Result:=rtFloat;
|
||||
ftDate,
|
||||
ftTime,
|
||||
ftDateTime : Result:=rtDateTime;
|
||||
else
|
||||
DatabaseErrorFmt('Fields of type %s are not supported in filter expressions.',[Fieldtypenames[aDataType]],Self);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBaseJSONDataSet.GetFilterField(Const AName : String) : TFPExpressionResult;
|
||||
|
||||
Var
|
||||
F : TField;
|
||||
C : Currency;
|
||||
|
||||
begin
|
||||
F:=FieldByName(aName);
|
||||
Result.resultType:=FieldTypeToExpressionType(F.DataType);
|
||||
case Result.resultType of
|
||||
rtBoolean : Result.resValue:=F.AsBoolean;
|
||||
rtInteger : Result.resValue:=F.AsLargeInt;
|
||||
rtFloat : Result.resValue:=F.AsFloat;
|
||||
rtDateTime : Result.resValue:=F.AsDateTime;
|
||||
rtString : Result.resValue:=F.AsString;
|
||||
rtCurrency :
|
||||
begin
|
||||
C:=Currency(F.AsFloat);
|
||||
Result.resValue:=C;
|
||||
end;
|
||||
end;
|
||||
// Writeln('Filtering field ',aName,'value: ',result.resValue);
|
||||
end;
|
||||
|
||||
|
||||
function TBaseJSONDataSet.CreateFilterExpression : TFPExpressionParser;
|
||||
|
||||
Var
|
||||
I : Integer;
|
||||
|
||||
begin
|
||||
Result:=FilterExpressionClass.Create(Self);
|
||||
for I:=0 to Fields.Count-1 do
|
||||
Result.Identifiers.AddVariable(Fields[i].FieldName,FieldTypeToExpressionType(Fields[i].DataType),@GetFilterField);
|
||||
Result.Identifiers.AddFunction('IsNull','B','S',@GetFilterIsNull);
|
||||
Result.Expression:=Filter;
|
||||
end;
|
||||
|
||||
function TBaseJSONDataSet.DoFilterRecord : Boolean;
|
||||
|
||||
Var
|
||||
DS : TDatasetState;
|
||||
|
||||
begin
|
||||
// Writeln('Filtering');
|
||||
Result:=True;
|
||||
DS:=SetTempState(dsFilter);
|
||||
try
|
||||
if Assigned(OnFilterRecord) then
|
||||
begin
|
||||
OnFilterRecord(Self,Result);
|
||||
if Not Result then
|
||||
Exit;
|
||||
end;
|
||||
if not Filtered or (Filter='') then
|
||||
Exit;
|
||||
if (FFilterExpression=Nil) then
|
||||
FFilterExpression:=CreateFilterExpression;
|
||||
Result:=FFilterExpression.AsBoolean;
|
||||
finally
|
||||
RestoreState(DS);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBaseJSONDataSet.GetRecord(Var Buffer: TDataRecord; GetMode: TGetMode; DoCheck: Boolean): TGetResult;
|
||||
|
||||
Var
|
||||
BkmIdx : Integer;
|
||||
|
||||
recordAccepted : Boolean;
|
||||
begin
|
||||
Result := grOK; // default
|
||||
case GetMode of
|
||||
gmNext: // move on
|
||||
if fCurrent < fCurrentIndex.Count - 1 then
|
||||
Inc (fCurrent)
|
||||
else
|
||||
Result := grEOF; // end of file
|
||||
gmPrior: // move back
|
||||
if fCurrent > 0 then
|
||||
Dec (fCurrent)
|
||||
else
|
||||
Result := grBOF; // begin of file
|
||||
gmCurrent: // check if empty
|
||||
if fCurrent >= fCurrentIndex.Count then
|
||||
Result := grEOF;
|
||||
end;
|
||||
if Result = grOK then // read the data
|
||||
begin
|
||||
BkmIdx:=FCurrentIndex.RecordIndex[FCurrent];
|
||||
Buffer.Data:=FRows[bkmIdx];
|
||||
Buffer.BookmarkFlag := bfCurrent;
|
||||
Buffer.Bookmark:=BkmIdx;
|
||||
CalculateFields(Buffer);
|
||||
Repeat
|
||||
recordAccepted:=True;
|
||||
case GetMode of
|
||||
gmNext: // move on
|
||||
if fCurrent < fCurrentIndex.Count - 1 then
|
||||
Inc (fCurrent)
|
||||
else
|
||||
Result := grEOF; // end of file
|
||||
gmPrior: // move back
|
||||
if fCurrent > 0 then
|
||||
Dec (fCurrent)
|
||||
else
|
||||
Result := grBOF; // begin of file
|
||||
gmCurrent: // check if empty
|
||||
if fCurrent >= fCurrentIndex.Count then
|
||||
Result := grEOF;
|
||||
end;
|
||||
if Result = grOK then // read the data
|
||||
begin
|
||||
BkmIdx:=FCurrentIndex.RecordIndex[FCurrent];
|
||||
Buffer.Data:=FRows[bkmIdx];
|
||||
Buffer.BookmarkFlag := bfCurrent;
|
||||
Buffer.Bookmark:=BkmIdx;
|
||||
CalculateFields(Buffer);
|
||||
if Filtered then
|
||||
begin
|
||||
FFilterRow:=Buffer.Data;
|
||||
recordAccepted:=DoFilterRecord;
|
||||
end;
|
||||
end;
|
||||
until recordAccepted;
|
||||
end;
|
||||
|
||||
function TBaseJSONDataSet.GetRecordCount: Integer;
|
||||
@ -1355,6 +1476,22 @@ begin
|
||||
FCurrent:=FCurrentIndex.FindRecord(Integer(Buffer.Bookmark));
|
||||
end;
|
||||
|
||||
procedure TBaseJSONDataSet.SetFilterText(const Value: string);
|
||||
begin
|
||||
inherited SetFilterText(Value);
|
||||
FreeAndNil(FFilterExpression);
|
||||
if Active then
|
||||
Resync([rmCenter]);
|
||||
end;
|
||||
|
||||
procedure TBaseJSONDataSet.SetFiltered(Value: Boolean);
|
||||
begin
|
||||
inherited SetFiltered(Value);
|
||||
FreeAndNil(FFilterExpression);
|
||||
if Active then
|
||||
Resync([rmCenter]);
|
||||
end;
|
||||
|
||||
function TBaseJSONDataSet.GetFieldClass(FieldType: TFieldType): TFieldClass;
|
||||
begin
|
||||
If UseDateTimeFormatFields and (FieldType in [ftDate,ftDateTime,ftTime]) then
|
||||
@ -1445,6 +1582,8 @@ var
|
||||
begin
|
||||
if State in [dsCalcFields,dsInternalCalc] then
|
||||
R:=CalcBuffer.data
|
||||
else if (State=dsFilter) then
|
||||
R:=FFilterRow
|
||||
else if (FEditIdx=Buffer.Bookmark) then
|
||||
begin
|
||||
if State=dsOldValue then
|
||||
@ -1525,6 +1664,7 @@ end;
|
||||
|
||||
destructor TBaseJSONDataSet.Destroy;
|
||||
begin
|
||||
FreeAndNil(FFilterExpression);
|
||||
FreeAndNil(FIndexes);
|
||||
FEditIdx:=-1;
|
||||
FreeData;
|
||||
|
Loading…
Reference in New Issue
Block a user