📄 jvqdbutils.pas
字号:
{******************************************************************************}
{* WARNING: JEDI VCL To CLX Converter generated unit. *}
{* Manual modifications will be lost on next release. *}
{******************************************************************************}
{-----------------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/MPL-1.1.html
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
the specific language governing rights and limitations under the License.
The Original Code is: JvDBUtils.PAS, released on 2002-07-04.
The Initial Developers of the Original Code are: Fedor Koshevnikov, Igor Pavluk and Serge Korolev
Copyright (c) 1997, 1998 Fedor Koshevnikov, Igor Pavluk and Serge Korolev
Copyright (c) 2001,2002 SGB Software
All Rights Reserved.
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
located at http://jvcl.sourceforge.net
Contributors:
tia
Known Issues:
-----------------------------------------------------------------------------}
// $Id: JvQDBUtils.pas,v 1.6 2004/12/21 09:45:16 asnepvangers Exp $
unit JvQDBUtils;
{$I jvcl.inc}
interface
uses
Classes, SysUtils, DB,
JvQAppStorage;
type
TCommit = (ctNone, ctStep, ctAll);
TJvDBProgressEvent = procedure(UserData: Integer; var Cancel: Boolean; Line: Integer) of object;
EJvScriptError = class(Exception)
private
FErrPos: Integer;
public
// The dummy parameter is only there for BCB compatibility so that
// when the hpp file gets generated, this constructor generates
// a C++ constructor that doesn't already exist
constructor Create(const AMessage: string; AErrPos: Integer; DummyForBCB: Integer = 0); overload;
property ErrPos: Integer read FErrPos;
end;
TJvLocateObject = class(TObject)
private
FDataSet: TDataSet;
FLookupField: TField;
FLookupValue: string;
FLookupExact: Boolean;
FCaseSensitive: Boolean;
FBookmark: TBookmark;
FIndexSwitch: Boolean;
procedure SetDataSet(Value: TDataSet);
protected
function MatchesLookup(Field: TField): Boolean;
procedure CheckFieldType(Field: TField); virtual;
procedure ActiveChanged; virtual;
function LocateFilter: Boolean; virtual;
function LocateKey: Boolean; virtual;
function LocateFull: Boolean; virtual;
function UseKey: Boolean; virtual;
function FilterApplicable: Boolean; virtual;
property LookupField: TField read FLookupField;
property LookupValue: string read FLookupValue;
property LookupExact: Boolean read FLookupExact;
property CaseSensitive: Boolean read FCaseSensitive;
property Bookmark: TBookmark read FBookmark write FBookmark;
public
function Locate(const KeyField, KeyValue: string; Exact,
CaseSensitive: Boolean): Boolean;
property DataSet: TDataSet read FDataSet write SetDataSet;
property IndexSwitch: Boolean read FIndexSwitch write FIndexSwitch;
end;
TCreateLocateObject = function: TJvLocateObject;
var
CreateLocateObject: TCreateLocateObject = nil;
function CreateLocate(DataSet: TDataSet): TJvLocateObject;
{ Utility routines }
function IsDataSetEmpty(DataSet: TDataSet): Boolean;
procedure RefreshQuery(Query: TDataSet);
function DataSetSortedSearch(DataSet: TDataSet;
const Value, FieldName: string; CaseInsensitive: Boolean): Boolean;
function DataSetSectionName(DataSet: TDataSet): string;
procedure InternalSaveFields(DataSet: TDataSet; AppStorage: TJvCustomAppStorage; const Path: string);
procedure InternalRestoreFields(DataSet: TDataSet; AppStorage: TJvCustomAppStorage;
const Path: string; RestoreVisible: Boolean);
function DataSetLocateThrough(DataSet: TDataSet; const KeyFields: string;
const KeyValues: Variant; Options: TLocateOptions): Boolean;
(*
procedure SaveFieldsReg(DataSet: TDataSet; IniFile: TRegIniFile);
procedure RestoreFieldsReg(DataSet: TDataSet; IniFile: TRegIniFile;
RestoreVisible: Boolean);
*)
procedure SaveFields(DataSet: TDataSet; AppStorage: TJvCustomAppStorage; const Path: string = '');
procedure RestoreFields(DataSet: TDataSet; AppStorage: TJvCustomAppStorage; const Path: string = '';
RestoreVisible: Boolean = True);
procedure AssignRecord(Source, Dest: TDataSet; ByName: Boolean);
function ConfirmDelete: Boolean;
procedure ConfirmDataSetCancel(DataSet: TDataSet);
procedure CheckRequiredField(Field: TField);
procedure CheckRequiredFields(const Fields: array of TField);
{ SQL expressions }
function DateToSQL(Value: TDateTime): string;
function FormatSQLDateRange(Date1, Date2: TDateTime;
const FieldName: string): string;
function FormatSQLDateRangeEx(Date1, Date2: TDateTime;
const FieldName: string): string;
function FormatSQLNumericRange(const FieldName: string;
LowValue, HighValue, LowEmpty, HighEmpty: Double; Inclusive: Boolean): string;
function StrMaskSQL(const Value: string): string;
function FormatSQLCondition(const FieldName, Operator, Value: string;
FieldType: TFieldType; Exact: Boolean): string;
function FormatAnsiSQLCondition(const FieldName, Operator, Value: string;
FieldType: TFieldType; Exact: Boolean): string;
const
TrueExpr = '0=0';
const
{ Server Date formats}
sdfStandard16 = '''"''mm''/''dd''/''yyyy''"'''; {"mm/dd/yyyy"}
sdfStandard32 = '''''''dd/mm/yyyy'''''''; {'dd/mm/yyyy'}
sdfOracle = '"TO_DATE(''"dd/mm/yyyy"'', ''DD/MM/YYYY'')"';
sdfInterbase = '"CAST(''"mm"/"dd"/"yyyy"'' AS DATE)"';
sdfMSSQL = '"CONVERT(datetime, ''"mm"/"dd"/"yyyy"'', 103)"';
const
ServerDateFmt: string[50] = sdfStandard16;
{.$NODEFINE ftNonTextTypes}
(*$HPPEMIT 'namespace JvDBUtils'*)
(*$HPPEMIT '{'*)
(*$HPPEMIT '#define ftNonTextTypes (System::Set<TFieldType, ftUnknown, ftCursor> () \'*)
(*$HPPEMIT ' << ftBytes << ftVarBytes << ftBlob << ftMemo << ftGraphic \'*)
(*$HPPEMIT ' << ftFmtMemo << ftParadoxOle << ftDBaseOle << ftTypedBinary << ftCursor )'*)
(*$HPPEMIT '}'*)
type
Largeint = Longint;
{$NODEFINE Largeint}
function NameDelimiter(C: Char): Boolean;
function IsLiteral(C: Char): Boolean;
procedure _DBError(const Msg: string);
implementation
uses
{$IFDEF UNITVERSIONING}
JclUnitVersioning,
{$ENDIF UNITVERSIONING}
{$IFDEF HAS_UNIT_VARIANTS}
Variants,
{$ENDIF HAS_UNIT_VARIANTS}
DBConsts, Math, QControls, QForms, QDialogs,
JvQJVCLUtils, JvQJCLUtils, JvQTypes, JvQConsts, JvQResources;
{ Utility routines }
function NameDelimiter(C: Char): Boolean;
begin
Result := C in [' ', ',', ';', ')', '.', Cr, Lf];
end;
function IsLiteral(C: Char): Boolean;
begin
Result := C in ['''', '"'];
end;
procedure _DBError(const Msg: string);
begin
DatabaseError(Msg);
end;
constructor EJvScriptError.Create(const AMessage: string; AErrPos: Integer; DummyForBCB: Integer);
begin
inherited Create(AMessage);
FErrPos := AErrPos;
end;
// (rom) better use Windows dialogs which are localized
function ConfirmDelete: Boolean;
begin
Screen.Cursor := crDefault;
Result := MessageDlg(SDeleteRecordQuestion, mtConfirmation,
[mbYes, mbNo], 0) = mrYes;
end;
procedure ConfirmDataSetCancel(DataSet: TDataSet);
begin
if DataSet.State in [dsEdit, dsInsert] then
begin
DataSet.UpdateRecord;
if DataSet.Modified then
begin
case MessageDlg(RsConfirmSave, mtConfirmation, mbYesNoCancel, 0) of
mrYes:
DataSet.Post;
mrNo:
DataSet.Cancel;
else
SysUtils.Abort;
end;
end
else
DataSet.Cancel;
end;
end;
function SetToBookmark(ADataSet: TDataSet; ABookmark: TBookmark): Boolean;
begin
Result := False;
with ADataSet do
if Active and (ABookmark <> nil) and not (Bof and Eof) and
BookmarkValid(ABookmark) then
try
ADataSet.GotoBookmark(ABookmark);
Result := True;
except
end;
end;
{ Refresh Query procedure }
procedure RefreshQuery(Query: TDataSet);
var
BookMk: TBookmark;
begin
with Query do
begin
DisableControls;
try
if Active then
BookMk := GetBookmark
else
BookMk := nil;
try
Close;
Open;
SetToBookmark(Query, BookMk);
finally
if BookMk <> nil then
FreeBookmark(BookMk);
end;
finally
EnableControls;
end;
end;
end;
procedure TJvLocateObject.SetDataSet(Value: TDataSet);
begin
ActiveChanged;
FDataSet := Value;
end;
function TJvLocateObject.LocateFull: Boolean;
begin
Result := False;
with DataSet do
begin
First;
while not Eof do
begin
if MatchesLookup(FLookupField) then
begin
Result := True;
Break;
end;
Next;
end;
end;
end;
function TJvLocateObject.LocateKey: Boolean;
begin
Result := False;
end;
function TJvLocateObject.FilterApplicable: Boolean;
begin
Result := FLookupField.FieldKind in [fkData, fkInternalCalc];
end;
function TJvLocateObject.LocateFilter: Boolean;
var
SaveCursor: TCursor;
Options: TLocateOptions;
Value: Variant;
begin
SaveCursor := Screen.Cursor;
Screen.Cursor := crHourGlass;
try
Options := [];
if not FCaseSensitive then
Include(Options, loCaseInsensitive);
if not FLookupExact then
Include(Options, loPartialKey);
if FLookupValue = '' then
VarClear(Value)
else
Value := FLookupValue;
Result := DataSet.Locate(FLookupField.FieldName, Value, Options);
finally
Screen.Cursor := SaveCursor;
end;
end;
procedure TJvLocateObject.CheckFieldType(Field: TField);
begin
end;
function TJvLocateObject.Locate(const KeyField, KeyValue: string;
Exact, CaseSensitive: Boolean): Boolean;
var
LookupKey: TField;
function IsStringType(FieldType: TFieldType): Boolean;
const
cStringTypes = [ftString, ftWideString];
begin
Result := FieldType in cStringTypes;
end;
begin
if DataSet = nil then
begin
Result := False;
Exit;
end;
DataSet.CheckBrowseMode;
LookupKey := DataSet.FieldByName(KeyField);
DataSet.CursorPosChanged;
FLookupField := LookupKey;
FLookupValue := KeyValue;
FLookupExact := Exact;
FCaseSensitive := CaseSensitive;
if not IsStringType(FLookupField.DataType) then
begin
FCaseSensitive := True;
try
CheckFieldType(FLookupField);
except
Result := False;
Exit;
end;
end
else
FCaseSensitive := CaseSensitive;
FBookmark := DataSet.GetBookmark;
try
DataSet.DisableControls;
try
Result := MatchesLookup(FLookupField);
if not Result then
begin
if UseKey then
Result := LocateKey
else
begin
if FilterApplicable then
Result := LocateFilter
else
Result := LocateFull;
end;
if not Result then
SetToBookmark(DataSet, FBookmark);
end;
finally
DataSet.EnableControls;
end;
finally
FLookupValue := '';
FLookupField := nil;
DataSet.FreeBookmark(FBookmark);
FBookmark := nil;
end;
end;
function TJvLocateObject.UseKey: Boolean;
begin
Result := False;
end;
procedure TJvLocateObject.ActiveChanged;
begin
end;
function TJvLocateObject.MatchesLookup(Field: TField): Boolean;
var
Temp: string;
begin
Temp := Field.AsString;
if not LookupExact then
SetLength(Temp, Min(Length(FLookupValue), Length(Temp)));
if CaseSensitive then
Result := AnsiSameStr(Temp, LookupValue)
else
Result := AnsiSameText(Temp, LookupValue);
end;
function CreateLocate(DataSet: TDataSet): TJvLocateObject;
begin
if Assigned(CreateLocateObject) then
Result := CreateLocateObject
else
Result := TJvLocateObject.Create;
if (Result <> nil) and (DataSet <> nil) then
Result.DataSet := DataSet;
end;
{ DataSet locate routines }
function DataSetLocateThrough(DataSet: TDataSet; const KeyFields: string;
const KeyValues: Variant; Options: TLocateOptions): Boolean;
var
FieldCount: Integer;
Fields: TList;
Fld: TField; {BG} //else BAD mem leak on 'Field.asString'
Bookmark: TBookmarkStr;
function CompareField(var Field: TField; Value: Variant): Boolean; {BG}
var
S: string;
begin
if Field.DataType = ftString then
begin
if Value = Null then
Result := Field.IsNull
else
begin
S := Field.AsString;
if loPartialKey in Options then
Delete(S, Length(Value) + 1, MaxInt);
if loCaseInsensitive in Options then
Result := AnsiSameText(S, Value)
else
Result := AnsiSameStr(S, Value);
end;
end
else
Result := (Field.Value = Value);
end;
function CompareRecord: Boolean;
var
I: Integer;
begin
if FieldCount = 1 then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -