⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pfibdataset.pas

📁 FIBPlus is a component suite intended for work with InterBase. It is direct, fast and flexible Inter
💻 PAS
📖 第 1 页 / 共 5 页
字号:
{***************************************************************}
{ FIBPlus - component library for direct access to Firebird and }
{ InterBase databases                                           }
{                                                               }
{    FIBPlus is based in part on the product                    }
{    Free IB Components, written by Gregory H. Deatz for        }
{    Hoagland, Longo, Moran, Dunst & Doukas Company.            }
{    mailto:gdeatz@hlmdd.com                                    }
{                                                               }
{    Copyright (c) 1998-2007 Devrace Ltd.                       }
{    Written by Serge Buzadzhy (buzz@devrace.com)               }
{                                                               }
{ ------------------------------------------------------------- }
{    FIBPlus home page: http://www.fibplus.com/                 }
{    FIBPlus support  : http://www.devrace.com/support/         }
{ ------------------------------------------------------------- }
{                                                               }
{  Please see the file License.txt for full license information }
{***************************************************************}

unit pFIBDataSet;

interface
{$I FIBPlus.inc}

uses
  SysUtils, Classes,StdFuncs, DB, ibase, IB_Intf, IB_Externals,
  fib, FIBMiscellaneous, pFIBDatabase,  FIBDataBase, FIBDataSet, FIBQuery,
  pFIBLists,  pFIBQuery, DSContainer, pFIBProps,  IB_ErrorCodes,pFIBInterfaces,
  pFIBDataInfo,
  {$IFDEF WINDOWS}
    {$IFDEF D6+}FMTBcd, Variants, {$ENDIF}
    Windows,   Messages;
  {$ENDIF}
  {$IFDEF LINUX}
    Types,FMTBcd, Variants;
  {$ENDIF}




type

  TLockStatus = (lsSuccess, lsDeadLock, lsNotExist, lsMultiply, lsUnknownError);
  TLockErrorEvent =
    procedure(DataSet: TDataSet; LockError: TLockStatus;
    var ErrorMessage: string; var Action: TDataAction) of object;

  TCachRefreshKind = (frkEdit, frkInsert);
  TOnGetSQLTextProc = procedure(DataSet: TFIBDataSet; var SQLText: string) of object;


  TIncludeFieldsToSQL=(ifsAllFields,ifsNoBlob,ifsOnlyBlob);

  TpFIBDataSet = class(TFIBDataSet)
  private
    vQryRecordCount: TFIBQuery;
    vLockQry: TFIBQuery;
    FDataSet_ID: integer;
    FLoadedDataSet_ID: integer;
    FDefaultFormats: TFormatFields;
    FOnLockError: TLockErrorEvent;
    vUserOnPostError: TDataSetErrorEvent;
    vUserOnDeleteError: TDataSetErrorEvent;
    // lists of UpdateObjects
    vUpdates: TList;
    vDeletes: TList;
    vInserts: TList;


    FReceiveEvents: TStrings;
{$IFDEF USE_DEPRECATE_METHODS2}
    FOnUserEvent: TUserEvent;
{$ENDIF }

    FHaveUncommitedChanges: boolean;
    FHaveRollbackedChanges: boolean;

    FDescription: string;
    FOnAskRecordCount: TOnGetSQLTextProc;
    FOnApplyDefaultValue:TOnApplyDefaultValue;
    FSQLTextChanges: integer;
    FBlobsUpdate: TpFIBUpdateObject;
    FOnApplyFieldRepository:TOnApplyFieldRepository;
    FContainer: TDataSetsContainer;
    FDefaultsInited:boolean;
    FParamsForFields: array of TFIBXSQLVAR;
    FGeneratorBeUsed:boolean;
    procedure SetContainer(Value: TDataSetsContainer);
{$IFDEF USE_DEPRECATE_METHODS2}
    procedure SetReceiveEvents(Value: TStrings);
{$ENDIF}
    //Property access procedures
    function  GetSelectSQL: TStrings;
    procedure SetSelectSQL(Value: TStrings);

    // UpdateObjects support
    function ListForUO(KindUpdate: TUpdateKind): TList;
    procedure SynchroOrdersUO(List: TList);

    //

    procedure SetDataSet_ID(Value: Integer);
    function GetFieldForTable(const Relation: string): TField;
    function WillGenerateSQLs: boolean;
    function  GetFIBVersion: string;
    procedure SetFIBVersion(const vs: string);

  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation);  override;
    function  GetVisibleRecno: Integer;
    procedure SetVisibleRecno(Value: Integer);
    function  GetRecNo: Integer; override;
    procedure SetRecNo(Value: Integer); override;
    procedure InternalPost; override;
    procedure InternalOpen ;override;
    procedure SetPrepareOptions(Value: TpPrepareOptions); override;
    procedure DoOnPostError(DataSet: TDataSet; E: DB.EDatabaseError; var Action:
      TDataAction); override;
    procedure DoOnDeleteError(DataSet: TDataSet; E: DB.EDatabaseError; var
      Action: TDataAction);

    function  CompareFieldValues(Field:TField;const S1,S2:variant):integer; override;
    //     IProviderSupport
  protected
//    FParams: TParams;



{$IFNDEF D10+}
    function PSGetTableName: string; override;
    function PSGetKeyFields: string; override;
    function PSGetQuoteChar: string; override;
    procedure PSSetCommandText(const CommandText: string); override;
{$ELSE}
    procedure PSSetCommandText(const CommandText: Widestring); override;
    function PSGetTableNameW: WideString; override;
    function PSGetKeyFieldsW: WideString; override;
    function PSGetQuoteCharW: Widestring; override;
    function PSGetCommandTextW: WideString;override;
{$ENDIF}
    function PSGetUpdateException(E: Exception; Prev: EUpdateError):
      EUpdateError; override;
    function PSInTransaction: Boolean; override;
    function PSIsSQLBased: Boolean; override;
    function PSIsSQLSupported: Boolean; override;
    procedure PSStartTransaction; override;
    procedure PSEndTransaction(Commit: Boolean); override;

    procedure PSReset; override;
    function PSUpdateRecord(UpdateKind: TUpdateKind; Delta: TDataSet): Boolean;
      override;
    function PSExecuteStatement(const ASQL: {$IFNDEF D10+} string{$ELSE} Widestring{$ENDIF}; AParams: TParams;
      ResultSet: Pointer = nil): Integer; override;
    procedure PSExecute; override;
    function PSGetParams: TParams; override;
    procedure PSSetParams(AParams: TParams); override;




    function IsVisible(Buffer: PChar): Boolean; override;

    procedure InternalPostRecord(Qry: TFIBQuery; Buff: Pointer); override;
    procedure InternalDeleteRecord(Qry: TFIBQuery; Buff: Pointer); override;
    procedure AddedFilterRecord(DataSet: TDataSet; var Accept: Boolean);
      virtual;

    procedure InternalDoBeforeOpen; override;
    procedure DoBeforeOpen; override;
    procedure DoAfterOpen; override;
    procedure DoAfterClose; override;
    procedure DoBeforeInsert; override;
    procedure DoAfterInsert; override;
    procedure DoBeforeEdit; override;
    procedure DoBeforePost; override;
    procedure DoAfterPost; override;
    procedure DoBeforeCancel; override;
    procedure DoAfterCancel; override;
    procedure DoBeforeDelete; override;
    procedure DoOnNewRecord; override;
    procedure DoAfterDelete; override;
    procedure DoAfterEdit; override;
    procedure DoAfterScroll; override;
    procedure DoBeforeClose; override;
    procedure DoBeforeScroll; override;
    procedure DoOnCalcFields; override;

    procedure DoBeforeRefresh; override;
    procedure DoAfterRefresh; override;

    procedure DoOnApplyDefaultValue(Field:TField; var Applied:boolean); dynamic;

    function  GetRecordCount: Integer; override;
    procedure UpdateFieldsProps; virtual;

    procedure DoAfterEndUpdateTransaction(EndingTR:TFIBTransaction;Action: TTransactionAction;
      Force: Boolean); override;

    procedure ClearModifFlags(Kind: byte; NeedRefreshFields:boolean=True);
    procedure CloseProtect;
    function RaiseLockError(LockError: TLockStatus; ExceptMessage: string):
      TDataAction;
  private
//
    FBlockContextCount:integer;
    FBlockSize:Integer;
    FExecBlockStatement:TStrings;
    function  AddStatementToExecuteBlock(SK:TpSQLKind):boolean;
    //=Succes add to execblock
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

    function RecordCountFromSrv: integer; dynamic;
    function VisibleRecordCount: Integer;
    function VisibleRecnoToRecno(VisRN: integer): Integer;

    procedure ParseParamToFieldsLinks(Dest: TStrings);
    procedure Prepare; override;
    function CanEdit: Boolean; override;
    function CanInsert: Boolean; override;
    function CanDelete: Boolean; override;
    function IsSequenced: Boolean; override; // Scroll bar

    function ExistActiveUO(KindUpdate: TUpdateKind): boolean;
    // Exist active Update objects

    function AddUpdateObject(Value: TpFIBUpdateObject): integer;
    procedure RemoveUpdateObject(Value: TpFIBUpdateObject);

    function ParamByName(const ParamName: string): TFIBXSQLVAR;
    function FindParam(const ParamName: string): TFIBXSQLVAR;

    function RecordStatus(RecNumber: integer): TUpdateStatus;
    procedure CloneRecord(SrcRecord: integer; IgnoreFields: array of const);
    procedure CloneCurRecord(IgnoreFields: array of const);
    // Cached Routine
    procedure CommitUpdToCach; // Clear CU buffers
    procedure ApplyUpdToBase(DontChangeCacheFlags:boolean=True); // Send Updates to Base
    procedure ApplyUpdates;

    // SaveLoad Buffer functions

    procedure SaveToStream(Stream: TStream; SeekBegin: boolean);
    procedure LoadFromStream(Stream: TStream; SeekBegin: boolean);

    procedure SaveToFile(const FileName: string);
    procedure LoadFromFile(const FileName: string);

    // End SaveLoad

    function LockRecord(RaiseErr: boolean= True): TLockStatus;
    function FieldByFieldNo(FieldNo: Integer): TField;
    function ParamNameCount(const aParamName: string): integer;
    function ParamCount: integer;
    procedure ExecUpdateObjects(KindUpdate: TUpdateKind; Buff: Pointer;
      aExecuteOrder: TFIBOrderExecUO);
{$IFDEF USE_DEPRECATE_METHODS2}
    procedure DoUserEvent(Sender: TObject; const UDE: string; var Info: string);
      dynamic; deprecated;
{$ENDIF}
    procedure OpenWP(const ParamValues: array of Variant); overload;
    procedure OpenWP(const ParamNames : string;const ParamValues: array of Variant); overload;
    procedure OpenWPS(const ParamSources: array of ISQLObject);

    procedure ReOpenWP(const ParamValues: array of Variant); overload;
    procedure ReOpenWP(const ParamNames : string;const ParamValues: array of Variant); overload;
    procedure ReOpenWPS(const ParamSources: array of ISQLObject);


    procedure BatchRecordToQuery(ToQuery:TFIBQuery);
    procedure BatchAllRecordsToQuery(ToQuery:TFIBQuery);
    procedure AutoGenerateSQLText(ForState: TDataSetState);


    function GenerateSQLText
      (const TableName, KeyFieldNames: string; SK: TpSQLKind; IncludeFields:TIncludeFieldsToSQL=ifsAllFields): string;

    function GenerateSQLTextNoParams
      (const TableName, KeyFieldNames: string; SK: TpSQLKind): string;

    function GenerateSQLTextWA
      (const TableName: string; SK: TpSQLKind; IncludeFields:TIncludeFieldsToSQL=ifsAllFields): string;
      // Where All
    procedure GenerateUpdateBlobsSQL;
    procedure GenerateSQLs;
    function CanGenerateSQLs: boolean;

    //AutoUpdate operations
    function KeyField: TField;
    function SqlTextGenID: string;
    procedure IncGenerator; virtual;


    function AllKeyFields(const TableName: string): string;

    procedure CacheModify(
      aFields: array of integer; Values: array of Variant;  KindModify: byte
    );

    procedure CacheEdit(aFields: array of integer; Values: array of Variant);
    procedure CacheAppend(aFields: array of integer; Values: array of Variant);
      overload;
    procedure CacheAppend(Value: Variant; DoRefresh: boolean = False); overload;

    procedure CacheInsert(aFields: array of integer; Values: array of Variant);
      overload;
    procedure CacheInsert(Value: Variant; DoRefresh: boolean = False); overload;

    procedure CacheRefresh(FromDataSet: TDataSet; Kind: TCachRefreshKind
      ; FieldMap: Tstrings
      );
    procedure CacheRefreshByArrMap(
      FromDataSet: TDataSet; Kind: TCachRefreshKind;
      const SourceFields, DestFields: array of string
      );
    function RecordFieldAsFloat(Field: TField; RecNumber: integer;
      IsVisibleRecordNum: boolean = True): Double;

  public
    property HasUncommitedChanges: boolean read FHaveUncommitedChanges;
    property HaveRollbackedChanges: boolean read FHaveRollbackedChanges;
    property AllRecordCount: integer read FAllRecordCount;
    property VisibleRecno: integer read GetVisibleRecno write SetVisibleRecno;
  published

    //Added properties
    property Filtered;
    property OnFilterRecord;

    property DeleteSQL: TStrings read GetDeleteSQL write SetDeleteSQL;
    property UpdateSQL: TStrings read GetUpdateSQL write SetUpdateSQL;
    property InsertSQL: TStrings read GetInsertSQL write SetInsertSQL;
    property RefreshSQL: TStrings read GetRefreshSQL write SetRefreshSQL;
    property SelectSQL: TStrings read GetSelectSQL write SetSelectSQL;

    property DefaultFormats: TFormatFields read FDefaultFormats write
      FDefaultFormats;
    property OnPostError: TDataSetErrorEvent read vUserOnPostError write
      vUserOnPostError;
    property OnDeleteError: TDataSetErrorEvent read vUserOnDeleteError write
      vUserOnDeleteError;
    property OnLockError: TLockErrorEvent read FOnLockError write FOnLockError;
{$IFDEF USE_DEPRECATE_METHODS2}

    property OnUserEvent: TUserEvent read FOnUserEvent write FOnUserEvent;

    property ReceiveEvents: TStrings read FReceiveEvents write SetReceiveEvents;
{$ENDIF}    
    property DataSet_ID: integer read FDataSet_ID write SetDataSet_ID default 0;
    property Description: string read FDescription write FDescription;
    property Container:TDataSetsContainer read FContainer write SetContainer;
    property OnAskRecordCount: TOnGetSQLTextProc read FOnAskRecordCount write
      FOnAskRecordCount;
    property About: string read GetFIBVersion write SetFIBVersion stored False;
    property OnApplyDefaultValue:TOnApplyDefaultValue read FOnApplyDefaultValue write FOnApplyDefaultValue;
    property OnApplyFieldRepository:TOnApplyFieldRepository read FOnApplyFieldRepository write FOnApplyFieldRepository;
  end;

function FieldInArray(Field: TField; Arr: array of const): boolean;


implementation

uses
{$IFNDEF NO_MONITOR}
  FIBSQLMonitor,
{$ENDIF}

  StrUtil, DBConsts, SqlTxtRtns, FIBConsts, //Commonib,
  pFIBFieldsDescr, pFIBCacheQueries,VariantRtn;

const
  SQLKindNames: array[TpSQLKind] of string = (
    'UpdateSQL',
    'InsertSQL',
    'DeleteSQL',
    'RefreshSQL'
    );

  StreamSignature = 'FIB$DATASET';

function UseFormat(const sFormat: string; Scale: integer): string;
var
  L, pD: integer;
begin
  L := Length(sFormat);
  if (L = 0) then
    Result := sFormat
  else
  if (sFormat[L] = '.') then
    Result := sFormat + MakeStr('0', Scale)
  else
  begin
    pD := PosCh('.', sFormat);
    if pD = 0 then
      Result := sFormat
    else
    if (pD = L - 1) then
      Result := FastCopy(sFormat, 1, Pred(pd)) + '.' + MakeStr(sFormat[L], Scale)
    else
      Result := sFormat
  end;
end;

//

constructor TpFIBDataSet.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FDefaultFormats := TFormatFields.Create(Self);
  inherited OnPostError := DoOnPostError;
  inherited OnDeleteError := DoOnDeleteError;

  vUpdates := TList.Create;
  vDeletes := TList.Create;
  vInserts := TList.Create;

  FReceiveEvents := TStringList.Create;

  vQryRecordCount := TFIBQuery.Create(Self);
  vQryRecordCount.ParamCheck := True;
  vLockQry := TFIBQuery.Create(Self);
  vLockQry.ParamCheck := True;

end;

destructor TpFIBDataSet.Destroy;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -