📄 ibstoredproc.pas
字号:
{************************************************************************}
{ }
{ Borland Delphi Visual Component Library }
{ InterBase Express core components }
{ }
{ Copyright (c) 1998-2001 Borland Software Corporation }
{ }
{ InterBase Express is based in part on the product }
{ Free IB Components, written by Gregory H. Deatz for }
{ Hoagland, Longo, Moran, Dunst & Doukas Company. }
{ Free IB Components is used under license. }
{ }
{ The contents of this file are subject to the InterBase }
{ Public License Version 1.0 (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.borland.com/interbase/IPL.html }
{ Software distributed under the License is distributed on }
{ an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either }
{ express or implied. See the License for the specific language }
{ governing rights and limitations under the License. }
{ The Original Code was created by InterBase Software Corporation }
{ and its successors. }
{ Portions created by Borland Software Corporation are Copyright }
{ (C) Borland Software Corporation. All Rights Reserved. }
{ Contributor(s): Jeff Overcash }
{ }
{************************************************************************}
unit IBStoredProc;
interface
uses SysUtils, Classes, DB, IB, IBDatabase, IBCustomDataSet,
IBHeader, IBSQL, IBUtils;
{ TIBStoredProc }
type
TIBStoredProc = class(TIBCustomDataSet)
private
FIBLoaded: Boolean;
FStmtHandle: TISC_STMT_HANDLE;
FProcName: string;
FParams: TParams;
FPrepared: Boolean;
FNameList: TStrings;
procedure SetParamsList(Value: TParams);
procedure FreeStatement;
function GetStoredProcedureNames: TStrings;
procedure GetStoredProcedureNamesFromServer;
procedure CreateParamDesc;
procedure SetParams;
procedure SetParamsFromCursor;
procedure GenerateSQL;
procedure FetchDataIntoOutputParams;
procedure ReadParamData(Reader: TReader);
procedure WriteParamData(Writer: TWriter);
protected
{ IProviderSupport }
procedure PSExecute; override;
function PSGetTableName: string; override;
function PSGetParams: TParams; override;
procedure PSSetCommandText(const CommandText: string); override;
procedure PSSetParams(AParams: TParams); override;
procedure DefineProperties(Filer: TFiler); override;
procedure SetFiltered(Value: Boolean); override;
function GetParamsCount: Word;
procedure SetPrepared(Value: Boolean);
procedure SetPrepare(Value: Boolean);
procedure SetProcName(Value: string);
procedure Disconnect; override;
procedure InternalOpen; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure CopyParams(Value: TParams);
procedure ExecProc;
function ParamByName(const Value: string): TParam;
procedure Prepare;
procedure UnPrepare;
property ParamCount: Word read GetParamsCount;
property StmtHandle: TISC_STMT_HANDLE read FStmtHandle;
property Prepared: Boolean read FPrepared write SetPrepare;
property StoredProcedureNames: TStrings read GetStoredProcedureNames;
published
property StoredProcName: string read FProcName write SetProcName;
property Params: TParams read FParams write SetParamsList stored false;
property Filtered;
property BeforeDatabaseDisconnect;
property AfterDatabaseDisconnect;
property DatabaseFree;
property BeforeTransactionEnd;
property AfterTransactionEnd;
property TransactionFree;
property OnFilterRecord;
end;
implementation
uses
IBIntf;
{ TIBStoredProc }
constructor TIBStoredProc.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FIBLoaded := False;
CheckIBLoaded;
FIBLoaded := True;
FParams := TParams.Create (self);
FNameList := TStringList.Create;
end;
destructor TIBStoredProc.Destroy;
begin
if FIBLoaded then
begin
Destroying;
Disconnect;
FParams.Free;
FNameList.Destroy;
end;
inherited Destroy;
end;
procedure TIBStoredProc.Disconnect;
begin
Close;
UnPrepare;
end;
procedure TIBStoredProc.ExecProc;
var
DidActivate: Boolean;
begin
CheckInActive;
if StoredProcName = '' then
IBError(ibxeNoStoredProcName, [nil]);
ActivateConnection;
DidActivate := ActivateTransaction;
try
SetPrepared(True);
if DataSource <> nil then
SetParamsFromCursor;
if FParams.Count > 0 then
SetParams;
InternalExecQuery;
FetchDataIntoOutputParams;
SetPrepared(false); // Unprepare the statement due to a bug in GDS32
finally
if DidActivate then
DeactivateTransaction;
end;
end;
procedure TIBStoredProc.SetProcName(Value: string);
begin
if not (csReading in ComponentState) then
begin
CheckInactive;
if Value <> FProcName then
begin
FProcName := Value;
FreeStatement;
FParams.Clear;
if (Value <> '') and
(Database <> nil) then
GenerateSQL;
end;
end
else
begin
FProcName := Value;
if (Value <> '') and (Database <> nil) then
GenerateSQL;
end;
end;
function TIBStoredProc.GetParamsCount: Word;
begin
Result := FParams.Count;
end;
procedure TIBStoredProc.SetFiltered(Value: Boolean);
begin
if(Filtered <> Value) then
begin
inherited SetFiltered(value);
if Active then
begin
Close;
Open;
end;
end
else
inherited SetFiltered(value);
end;
procedure TIBStoredProc.GenerateSQL;
var
Query : TIBSQL;
input : string;
begin
ActivateConnection;
Database.InternalTransaction.StartTransaction;
Query := TIBSQL.Create(self);
try
Query.Database := DataBase;
Query.Transaction := Database.InternalTransaction;
Query.SQL.Text := 'SELECT RDB$PARAMETER_NAME, RDB$PARAMETER_TYPE ' + {do not localize}
'FROM RDB$PROCEDURE_PARAMETERS ' + {do not localize}
'WHERE RDB$PROCEDURE_NAME = ' + {do not localize}
'''' + FormatIdentifierValue(Database.SQLDialect,
QuoteIdentifier(Database.SQLDialect, FProcName)) + '''' +
' ORDER BY RDB$PARAMETER_NUMBER'; {do not localize}
Query.Prepare;
Query.GoToFirstRecordOnExecute := False;
Query.ExecQuery;
while (not Query.EOF) and (Query.Next <> nil) do
begin
if (Query.Current.ByName('RDB$PARAMETER_TYPE').AsInteger = 0) then {do not localize}
begin
if (input <> '') then
input := input + ', :' +
QuoteIdentifier(Database.SQLDialect, Query.Current.ByName('RDB$PARAMETER_NAME').AsString) {do not localize}
else
input := ':' +
QuoteIdentifier(Database.SQLDialect, Query.Current.ByName('RDB$PARAMETER_NAME').AsString); {do not localize}
end
end;
if Input <> '' then
SelectSQL.Text := 'Execute Procedure ' + {do not localize}
QuoteIdentifier(Database.SQLDialect, FProcName) + '(' + input + ')'
else
SelectSQL.Text := 'Execute Procedure ' + {do not localize}
QuoteIdentifier(Database.SQLDialect, FProcName);
finally
Query.Free;
Database.InternalTransaction.Commit;
end;
end;
procedure TIBStoredProc.CreateParamDesc;
var
i : integer;
DataType : TFieldType;
begin
DataType := ftUnknown;
for i := 0 to QSelect.Current.Count - 1 do begin
case QSelect.Fields[i].SQLtype of
SQL_TYPE_DATE: DataType := ftDate;
SQL_TYPE_TIME: DataType := ftTime;
SQL_TIMESTAMP: DataType := ftDateTime;
SQL_SHORT:
if ((QSelect.Fields[i].AsXSQLVar)^.sqlscale = 0) then
DataType := ftSmallInt
else
DataType := ftBCD;
SQL_LONG:
if ((QSelect.Fields[i].AsXSQLVar)^.sqlscale = 0) then
DataType := ftInteger
else if ((QSelect.Fields[i].AsXSQLVar)^.sqlscale >= (-4)) then
DataType := ftBCD
else
DataType := ftFloat;
SQL_INT64:
if ((QSelect.Fields[i].AsXSQLVar)^.sqlscale = 0) then
DataType := ftLargeInt
else if ((QSelect.Fields[i].AsXSQLVar)^.sqlscale >= (-4)) then
DataType := ftBCD
else
DataType := ftFloat;
SQL_DOUBLE, SQL_FLOAT, SQL_D_FLOAT: DataType := ftFloat;
SQL_TEXT: DataType := ftString;
SQL_VARYING:
if ((QSelect.Fields[i].AsXSQLVar)^.sqllen < 1024) then
DataType := ftString
else DataType := ftBlob;
SQL_BLOB, SQL_ARRAY, SQL_QUAD: DataType := ftBlob;
end;
FParams.CreateParam(DataType, Trim(QSelect.Fields[i].Name), ptOutput);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -