📄 jvqdbutils.pas
字号:
begin
Fld := TField(Fields.First); {BG}
Result := CompareField(Fld, KeyValues) {BG}
end
else
begin
Result := True;
for I := 0 to FieldCount - 1 do
begin
Fld := TField(Fields[I]); {BG}
Result := Result and CompareField(Fld, KeyValues[I]); {BG}
end;
end;
end;
begin
Result := False;
with DataSet do
begin
CheckBrowseMode;
if IsEmpty then
Exit;
end;
Fields := TList.Create;
try
DataSet.GetFieldList(Fields, KeyFields);
FieldCount := Fields.Count;
Result := CompareRecord;
if Result then
Exit;
DataSet.DisableControls;
try
Bookmark := DataSet.Bookmark;
try
with DataSet do
begin
First;
while not Eof do
begin
Result := CompareRecord;
if Result then
Break;
Next;
end;
end;
finally
if not Result and DataSet.BookmarkValid(PChar(Bookmark)) then
DataSet.Bookmark := Bookmark;
end;
finally
DataSet.EnableControls;
end;
finally
Fields.Free;
end;
end;
{ DataSetSortedSearch. Navigate on sorted DataSet routine. }
function DataSetSortedSearch(DataSet: TDataSet; const Value,
FieldName: string; CaseInsensitive: Boolean): Boolean;
var
L, H, I: Longint;
CurrentPos: Longint;
CurrentValue: string;
BookMk: TBookmark;
Field: TField;
function UpStr(const Value: string): string;
begin
if CaseInsensitive then
Result := AnsiUpperCase(Value)
else
Result := Value;
end;
function GetCurrentStr: string;
begin
Result := Field.AsString;
if Length(Result) > Length(Value) then
SetLength(Result, Length(Value));
Result := UpStr(Result);
end;
begin
Result := False;
if DataSet = nil then
Exit;
Field := DataSet.FindField(FieldName);
if Field = nil then
Exit;
if Field.DataType = ftString then
begin
DataSet.DisableControls;
BookMk := DataSet.GetBookmark;
try
L := 0;
DataSet.First;
CurrentPos := 0;
H := DataSet.RecordCount - 1;
if Value <> '' then
begin
while L <= H do
begin
I := (L + H) shr 1;
if I <> CurrentPos then
DataSet.MoveBy(I - CurrentPos);
CurrentPos := I;
CurrentValue := GetCurrentStr;
if UpStr(Value) > CurrentValue then
L := I + 1
else
begin
H := I - 1;
if UpStr(Value) = CurrentValue then
Result := True;
end;
end;
if Result then
begin
if L <> CurrentPos then
DataSet.MoveBy(L - CurrentPos);
while (L < DataSet.RecordCount) and
(UpStr(Value) <> GetCurrentStr) do
begin
Inc(L);
DataSet.MoveBy(1);
end;
end;
end
else
Result := True;
if not Result then
SetToBookmark(DataSet, BookMk);
finally
DataSet.FreeBookmark(BookMk);
DataSet.EnableControls;
end;
end
else
DatabaseErrorFmt(SFieldTypeMismatch, [Field.DisplayName]);
end;
{ Save and restore DataSet Fields layout }
function DataSetSectionName(DataSet: TDataSet): string;
begin
with DataSet do
if (Owner <> nil) and (Owner is TCustomForm) then
Result := GetDefaultSection(Owner as TCustomForm)
else
Result := Name;
end;
function CheckSection(DataSet: TDataSet; const Section: string): string;
begin
Result := Section;
if Result = '' then
Result := DataSetSectionName(DataSet);
end;
procedure InternalSaveFields(DataSet: TDataSet; AppStorage: TJvCustomAppStorage; const Path: string);
var
I: Integer;
begin
with DataSet do
begin
for I := 0 to FieldCount - 1 do
begin
AppStorage.WriteString(AppStorage.ConcatPaths([CheckSection(DataSet, Path),
Name + Fields[I].FieldName]),
Format('%d,%d,%d', [Fields[I].Index, Fields[I].DisplayWidth,
Integer(Fields[I].Visible)]));
end;
end;
end;
procedure InternalRestoreFields(DataSet: TDataSet; AppStorage: TJvCustomAppStorage;
const Path: string; RestoreVisible: Boolean);
type
TFieldInfo = record
Field: TField;
EndIndex: Integer;
end;
PFieldArray = ^TFieldArray;
TFieldArray = array [0..(65528 div SizeOf(TFieldInfo)) - 1] of TFieldInfo;
const
Delims = [' ', ','];
var
I, J: Integer;
S: string;
FieldArray: PFieldArray;
begin
with DataSet do
begin
FieldArray := AllocMemo(FieldCount * SizeOf(TFieldInfo));
try
for I := 0 to FieldCount - 1 do
begin
S := AppStorage.ReadString(AppStorage.ConcatPaths([CheckSection(DataSet, Path),
Name + Fields[I].FieldName]), '');
FieldArray^[I].Field := Fields[I];
FieldArray^[I].EndIndex := Fields[I].Index;
if S <> '' then
begin
FieldArray^[I].EndIndex := StrToIntDef(ExtractWord(1, S, Delims),
FieldArray^[I].EndIndex);
Fields[I].DisplayWidth := StrToIntDef(ExtractWord(2, S, Delims),
Fields[I].DisplayWidth);
if RestoreVisible then
Fields[I].Visible := Boolean(StrToIntDef(ExtractWord(3, S, Delims),
Integer(Fields[I].Visible)));
end;
end;
for I := 0 to FieldCount - 1 do
begin
for J := 0 to FieldCount - 1 do
begin
if FieldArray^[J].EndIndex = I then
begin
FieldArray^[J].Field.Index := FieldArray^[J].EndIndex;
Break;
end;
end;
end;
finally
FreeMemo(Pointer(FieldArray));
end;
end;
end;
procedure SaveFields(DataSet: TDataSet; AppStorage: TJvCustomAppStorage; const Path: string);
begin
InternalSaveFields(DataSet, AppStorage, AppStorage.ConcatPaths([Path, DataSetSectionName(DataSet)]));
end;
procedure RestoreFields(DataSet: TDataSet; AppStorage: TJvCustomAppStorage; const Path: string;
RestoreVisible: Boolean);
begin
InternalRestoreFields(DataSet, AppStorage, AppStorage.ConcatPaths([DataSetSectionName(DataSet)]),
RestoreVisible);
end;
function IsDataSetEmpty(DataSet: TDataSet): Boolean;
begin
with DataSet do
Result := (not Active) or (Eof and Bof);
end;
{ SQL expressions }
function DateToSQL(Value: TDateTime): string;
begin
Result := IntToStr(Trunc(Value));
end;
function FormatSQLDateRange(Date1, Date2: TDateTime;
const FieldName: string): string;
begin
Result := TrueExpr;
if (Date1 = Date2) and (Date1 <> NullDate) then
begin
Result := Format('%s = %s', [FieldName, FormatDateTime(ServerDateFmt,
Date1)]);
end
else
if (Date1 <> NullDate) or (Date2 <> NullDate) then
begin
if Date1 = NullDate then
Result := Format('%s < %s', [FieldName,
FormatDateTime(ServerDateFmt, IncDay(Date2, 1))])
else
if Date2 = NullDate then
Result := Format('%s > %s', [FieldName,
FormatDateTime(ServerDateFmt, IncDay(Date1, -1))])
else
Result := Format('(%s < %s) AND (%s > %s)',
[FieldName, FormatDateTime(ServerDateFmt, IncDay(Date2, 1)),
FieldName, FormatDateTime(ServerDateFmt, IncDay(Date1, -1))]);
end;
end;
function FormatSQLDateRangeEx(Date1, Date2: TDateTime;
const FieldName: string): string;
begin
Result := TrueExpr;
if (Date1 <> NullDate) or (Date2 <> NullDate) then
begin
if Date1 = NullDate then
Result := Format('%s < %s', [FieldName,
FormatDateTime(ServerDateFmt, IncDay(Date2, 1))])
else
if Date2 = NullDate then
Result := Format('%s >= %s', [FieldName,
FormatDateTime(ServerDateFmt, Date1)])
else
Result := Format('(%s < %s) AND (%s >= %s)',
[FieldName, FormatDateTime(ServerDateFmt, IncDay(Date2, 1)),
FieldName, FormatDateTime(ServerDateFmt, Date1)]);
end;
end;
function FormatSQLNumericRange(const FieldName: string;
LowValue, HighValue, LowEmpty, HighEmpty: Double; Inclusive: Boolean): string;
const
Operators: array[Boolean, 1..2] of string[2] = (('>', '<'), ('>=', '<='));
begin
Result := TrueExpr;
if (LowValue = HighValue) and (LowValue <> LowEmpty) then
Result := Format('%s = %g', [FieldName, LowValue])
else
if (LowValue <> LowEmpty) or (HighValue <> HighEmpty) then
begin
if LowValue = LowEmpty then
Result := Format('%s %s %g', [FieldName, Operators[Inclusive, 2], HighValue])
else
if HighValue = HighEmpty then
Result := Format('%s %s %g', [FieldName, Operators[Inclusive, 1], LowValue])
else
Result := Format('(%s %s %g) AND (%s %s %g)',
[FieldName, Operators[Inclusive, 2], HighValue,
FieldName, Operators[Inclusive, 1], LowValue]);
end;
end;
function StrMaskSQL(const Value: string): string;
begin
if (Pos('*', Value) = 0) and (Pos('?', Value) = 0) and (Value <> '') then
Result := '*' + Value + '*'
else
Result := Value;
end;
function FormatSQLCondition(const FieldName, Operator, Value: string;
FieldType: TFieldType; Exact: Boolean): string;
var
EmptyValue: Boolean;
FieldValue: string;
DateValue: TDateTime;
LogicOperator: string;
begin
FieldValue := '';
DateValue := NullDate;
Exact := Exact or not (FieldType in
[ftString, ftDate, ftTime, ftDateTime]);
if FieldType in [ftDate, ftTime, ftDateTime] then
begin
DateValue := StrToDateDef(Value, NullDate);
EmptyValue := (DateValue = NullDate);
FieldValue := FormatDateTime(ServerDateFmt, DateValue);
end
else
begin
FieldValue := Value;
EmptyValue := FieldValue = '';
if not (Exact or EmptyValue) then
FieldValue := ReplaceStr(ReplaceStr(StrMaskSQL(FieldValue),
'*', '%'), '?', '_');
if FieldType = ftString then
FieldValue := '''' + FieldValue + '''';
end;
LogicOperator := Operator;
if LogicOperator = '' then
begin
if Exact then
LogicOperator := '='
else
begin
if FieldType = ftString then
LogicOperator := 'LIKE'
else
LogicOperator := '>=';
end;
end;
if EmptyValue then
Result := TrueExpr
else
if (FieldType = ftDateTime) and Exact then
begin
DateValue := IncDay(DateValue, 1);
Result := Format('(%s >= %s) and (%s < %s)', [FieldName, FieldValue,
FieldName, FormatDateTime(ServerDateFmt, DateValue)]);
end
else
Result := Format('%s %s %s', [FieldName, LogicOperator, FieldValue]);
end;
function FormatAnsiSQLCondition(const FieldName, Operator, Value: string;
FieldType: TFieldType; Exact: Boolean): string;
var
S, Esc: string;
begin
Esc := '';
if not Exact and (FieldType = ftString) then
begin
S := ReplaceStr(ReplaceStr(ReplaceStr(Value, '/', '//'),
'_', '/_'), '%', '/%');
if S <> Value then
Esc := ' ESCAPE''/''';
end
else
S := Value;
Result := FormatSQLCondition(FieldName, Operator, S, FieldType, Exact) + Esc;
end;
procedure CheckRequiredField(Field: TField);
begin
with Field do
if not ReadOnly and not Calculated and IsNull then
begin
FocusControl;
DatabaseErrorFmt(SFieldRequired, [DisplayName]);
end;
end;
procedure CheckRequiredFields(const Fields: array of TField);
var
I: Integer;
begin
for I := Low(Fields) to High(Fields) do
CheckRequiredField(Fields[I]);
end;
procedure AssignRecord(Source, Dest: TDataSet; ByName: Boolean);
var
I: Integer;
F, FSrc: TField;
begin
if not (Dest.State in dsEditModes) then
_DBError(SNotEditing);
if ByName then
begin
for I := 0 to Source.FieldCount - 1 do
begin
F := Dest.FindField(Source.Fields[I].FieldName);
if (F <> nil) and (F.DataType <> ftAutoInc) then
F.Value := Source.Fields[I].Value;
end;
end
else
begin
for I := 0 to Min(Source.FieldDefs.Count - 1, Dest.FieldDefs.Count - 1) do
begin
F := Dest.FindField(Dest.FieldDefs[I].Name);
FSrc := Source.FindField(Source.FieldDefs[I].Name);
if (F <> nil) and (FSrc <> nil) and (F.DataType <> ftAutoInc) then
F.Value := FSrc.Value;
end;
end;
end;
{$IFDEF UNITVERSIONING}
const
UnitVersioning: TUnitVersionInfo = (
RCSfile: '$RCSfile: JvQDBUtils.pas,v $';
Revision: '$Revision: 1.6 $';
Date: '$Date: 2004/12/21 09:45:16 $';
LogPath: 'JVCL\run'
);
initialization
RegisterUnitVersion(HInstance, UnitVersioning);
finalization
UnregisterUnitVersion(HInstance);
{$ENDIF UNITVERSIONING}
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -