ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/runtime/IBStoredProc.pas
Revision: 1
Committed: Mon Jul 31 16:43:00 2000 UTC (23 years, 9 months ago) by tony
Content type: text/x-pascal
File size: 15694 byte(s)
Log Message:
Borland IBX Open Source Release

File Contents

# User Rev Content
1 tony 1 {************************************************************************}
2     { }
3     { Borland Delphi Visual Component Library }
4     { InterBase Express core components }
5     { }
6     { Copyright (c) 1998-2000 Inprise Corporation }
7     { }
8     { InterBase Express is based in part on the product }
9     { Free IB Components, written by Gregory H. Deatz for }
10     { Hoagland, Longo, Moran, Dunst & Doukas Company. }
11     { Free IB Components is used under license. }
12     { }
13     { The contents of this file are subject to the InterBase }
14     { Public License Version 1.0 (the "License"); you may not }
15     { use this file except in compliance with the License. You }
16     { may obtain a copy of the License at http://www.Inprise.com/IPL.html }
17     { Software distributed under the License is distributed on }
18     { an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either }
19     { express or implied. See the License for the specific language }
20     { governing rights and limitations under the License. }
21     { The Original Code was created by InterBase Software Corporation }
22     { and its successors. }
23     { Portions created by Inprise Corporation are Copyright (C) Inprise }
24     { Corporation. All Rights Reserved. }
25     { Contributor(s): Jeff Overcash }
26     { }
27     {************************************************************************}
28    
29     unit IBStoredProc;
30    
31     interface
32    
33     uses Windows, SysUtils, Graphics, Classes, Controls, Db, StdVCL, IB,
34     IBDatabase, IBCustomDataSet, IBHeader, IBSQL, IBUtils;
35    
36     { TIBStoredProc }
37     type
38    
39     TIBStoredProc = class(TIBCustomDataSet)
40     private
41     FIBLoaded: Boolean;
42     FStmtHandle: TISC_STMT_HANDLE;
43     FProcName: string;
44     FParams: TParams;
45     FPrepared: Boolean;
46     FNameList: TStrings;
47     procedure SetParamsList(Value: TParams);
48     procedure FreeStatement;
49     function GetStoredProcedureNames: TStrings;
50     procedure GetStoredProcedureNamesFromServer;
51     procedure CreateParamDesc;
52     procedure SetParams;
53     procedure SetParamsFromCursor;
54     procedure GenerateSQL;
55     procedure FetchDataIntoOutputParams;
56     procedure ReadParamData(Reader: TReader);
57     procedure WriteParamData(Writer: TWriter);
58    
59     protected
60     { IProviderSupport }
61     procedure PSExecute; override;
62     function PSGetTableName: string; override;
63     function PSGetParams: TParams; override;
64     procedure PSSetCommandText(const CommandText: string); override;
65     procedure PSSetParams(AParams: TParams); override;
66    
67     procedure DefineProperties(Filer: TFiler); override;
68     procedure SetFiltered(Value: Boolean); override;
69     function GetParamsCount: Word;
70     procedure SetPrepared(Value: Boolean);
71     procedure SetPrepare(Value: Boolean);
72     procedure SetProcName(Value: string);
73     procedure Disconnect; override;
74     procedure InternalOpen; override;
75    
76     public
77     constructor Create(AOwner: TComponent); override;
78     destructor Destroy; override;
79     procedure CopyParams(Value: TParams);
80     procedure ExecProc;
81     function ParamByName(const Value: string): TParam;
82     procedure Prepare;
83     procedure UnPrepare;
84     property ParamCount: Word read GetParamsCount;
85     property StmtHandle: TISC_STMT_HANDLE read FStmtHandle;
86     property Prepared: Boolean read FPrepared write SetPrepare;
87     property StoredProcedureNames: TStrings read GetStoredProcedureNames;
88    
89     published
90     property StoredProcName: string read FProcName write SetProcName;
91     property Params: TParams read FParams write SetParamsList;
92     property Filtered;
93    
94     property BeforeDatabaseDisconnect;
95     property AfterDatabaseDisconnect;
96     property DatabaseFree;
97     property BeforeTransactionEnd;
98     property AfterTransactionEnd;
99     property TransactionFree;
100     property OnFilterRecord;
101     end;
102    
103     implementation
104    
105     uses
106     IBIntf;
107    
108     { TIBStoredProc }
109    
110     constructor TIBStoredProc.Create(AOwner: TComponent);
111     begin
112     inherited Create(AOwner);
113     FIBLoaded := False;
114     CheckIBLoaded;
115     FIBLoaded := True;
116     FParams := TParams.Create (self);
117     FNameList := TStringList.Create;
118     end;
119    
120     destructor TIBStoredProc.Destroy;
121     begin
122     if FIBLoaded then
123     begin
124     Destroying;
125     Disconnect;
126     FParams.Free;
127     FNameList.Destroy;
128     end;
129     inherited Destroy;
130     end;
131    
132     procedure TIBStoredProc.Disconnect;
133     begin
134     Close;
135     UnPrepare;
136     end;
137    
138     procedure TIBStoredProc.ExecProc;
139     var
140     DidActivate: Boolean;
141     begin
142     CheckInActive;
143     if StoredProcName = '' then
144     IBError(ibxeNoStoredProcName, [nil]);
145     ActivateConnection;
146     DidActivate := ActivateTransaction;
147     try
148     SetPrepared(True);
149     if DataSource <> nil then SetParamsFromCursor;
150     if FParams.Count > 0 then SetParams;
151     InternalExecQuery;
152     FetchDataIntoOutputParams;
153     finally
154     if DidActivate then
155     DeactivateTransaction;
156     end;
157     end;
158    
159     procedure TIBStoredProc.SetProcName(Value: string);
160     begin
161     if not (csReading in ComponentState) then
162     begin
163     CheckInactive;
164     if Value <> FProcName then
165     begin
166     FProcName := Value;
167     FreeStatement;
168     FParams.Clear;
169     if (Value <> '') and
170     (Database <> nil) then
171     GenerateSQL;
172     end;
173     end else begin
174     FProcName := Value;
175     if (Value <> '') and
176     (Database <> nil) then
177     GenerateSQL;
178     end;
179     end;
180    
181     function TIBStoredProc.GetParamsCount: Word;
182     begin
183     Result := FParams.Count;
184     end;
185    
186     procedure TIBStoredProc.SetFiltered(Value: Boolean);
187     begin
188     if(Filtered <> Value) then
189     begin
190     inherited SetFiltered(value);
191     if Active then
192     begin
193     Close;
194     Open;
195     end;
196     end
197     else
198     inherited SetFiltered(value);
199     end;
200    
201     procedure TIBStoredProc.GenerateSQL;
202     var
203     Query : TIBSQL;
204     input : string;
205     begin
206     ActivateConnection;
207     Database.InternalTransaction.StartTransaction;
208     Query := TIBSQL.Create(self);
209     try
210     Query.Database := DataBase;
211     Query.Transaction := Database.InternalTransaction;
212     Query.SQL.Text := 'SELECT RDB$PARAMETER_NAME, RDB$PARAMETER_TYPE ' + {do not localize}
213     'FROM RDB$PROCEDURE_PARAMETERS ' + {do not localize}
214     'WHERE RDB$PROCEDURE_NAME = ' + {do not localize}
215     '''' + FormatIdentifierValue(Database.SQLDialect, FProcName) + '''' +
216     ' ORDER BY RDB$PARAMETER_NUMBER'; {do not localize}
217     Query.Prepare;
218     Query.GoToFirstRecordOnExecute := False;
219     Query.ExecQuery;
220     while (not Query.EOF) and (Query.Next <> nil) do begin
221     if (Query.Current.ByName('RDB$PARAMETER_TYPE').AsInteger = 0) then begin {do not localize}
222     if (input <> '') then
223     input := input + ', :' +
224     FormatIdentifier(Database.SQLDialect, Query.Current.ByName('RDB$PARAMETER_NAME').AsString) else {do not localize}
225     input := ':' +
226     FormatIdentifier(Database.SQLDialect, Query.Current.ByName('RDB$PARAMETER_NAME').AsString); {do not localize}
227     end
228     end;
229     SelectSQL.Text := 'Execute Procedure ' + {do not localize}
230     FormatIdentifier(Database.SQLDialect, FProcName) + ' ' + input;
231     finally
232     Query.Free;
233     Database.InternalTransaction.Commit;
234     end;
235     end;
236    
237     procedure TIBStoredProc.CreateParamDesc;
238     var
239     i : integer;
240     DataType : TFieldType;
241     begin
242     DataType := ftUnknown;
243     for i := 0 to QSelect.Current.Count - 1 do begin
244     case QSelect.Fields[i].SQLtype of
245     SQL_TYPE_DATE: DataType := ftDate;
246     SQL_TYPE_TIME: DataType := ftTime;
247     SQL_TIMESTAMP: DataType := ftDateTime;
248     SQL_SHORT:
249     if ((QSelect.Fields[i].AsXSQLVar)^.sqlscale = 0) then
250     DataType := ftSmallInt
251     else
252     DataType := ftBCD;
253     SQL_LONG:
254     if ((QSelect.Fields[i].AsXSQLVar)^.sqlscale = 0) then
255     DataType := ftInteger
256     else if ((QSelect.Fields[i].AsXSQLVar)^.sqlscale >= (-4)) then
257     DataType := ftBCD
258     else
259     DataType := ftFloat;
260     SQL_INT64:
261     if ((QSelect.Fields[i].AsXSQLVar)^.sqlscale = 0) then
262     DataType := ftLargeInt
263     else if ((QSelect.Fields[i].AsXSQLVar)^.sqlscale >= (-4)) then
264     DataType := ftBCD
265     else
266     DataType := ftFloat;
267     SQL_DOUBLE, SQL_FLOAT, SQL_D_FLOAT: DataType := ftFloat;
268     SQL_TEXT: DataType := ftString;
269     SQL_VARYING:
270     if ((QSelect.Fields[i].AsXSQLVar)^.sqllen < 1024) then
271     DataType := ftString
272     else DataType := ftBlob;
273     SQL_BLOB, SQL_ARRAY, SQL_QUAD: DataType := ftBlob;
274     end;
275     FParams.CreateParam(DataType, Trim(QSelect.Fields[i].Name), ptOutput);
276     end;
277    
278     DataType := ftUnknown;
279     for i := 0 to QSelect.Params.Count - 1 do begin
280     case QSelect.Params[i].SQLtype of
281     SQL_TYPE_DATE: DataType := ftDate;
282     SQL_TYPE_TIME: DataType := ftTime;
283     SQL_TIMESTAMP: DataType := ftDateTime;
284     SQL_SHORT:
285     if ((QSelect.Params[i].AsXSQLVar)^.sqlscale = 0) then
286     DataType := ftSmallInt
287     else
288     DataType := ftBCD;
289     SQL_LONG:
290     if ((QSelect.Params[i].AsXSQLVar)^.sqlscale = 0) then
291     DataType := ftInteger
292     else if ((QSelect.Params[i].AsXSQLVar)^.sqlscale >= (-4)) then
293     DataType := ftBCD
294     else DataType := ftFloat;
295     SQL_INT64:
296     if ((QSelect.Params[i].AsXSQLVar)^.sqlscale = 0) then
297     DataType := ftLargeInt
298     else if ((QSelect.Params[i].AsXSQLVar)^.sqlscale >= (-4)) then
299     DataType := ftBCD
300     else DataType := ftFloat;
301     SQL_DOUBLE, SQL_FLOAT, SQL_D_FLOAT: DataType := ftFloat;
302     SQL_TEXT: DataType := ftString;
303     SQL_VARYING:
304     if ((QSelect.Params[i].AsXSQLVar)^.sqllen < 1024) then
305     DataType := ftString
306     else DataType := ftBlob;
307     SQL_BLOB, SQL_ARRAY, SQL_QUAD: DataType := ftBlob;
308     end;
309     FParams.CreateParam(DataType, Trim(QSelect.Params[i].Name), ptInput);
310     end;
311     end;
312    
313     procedure TIBStoredProc.SetPrepared(Value: Boolean);
314     begin
315     if Prepared <> Value then
316     begin
317     if Value then
318     try
319     if SelectSQL.Text = '' then GenerateSQL;
320     InternalPrepare;
321     if FParams.Count = 0 then CreateParamDesc;
322     FPrepared := True;
323     except
324     FreeStatement;
325     raise;
326     end
327     else FreeStatement;
328     end;
329    
330     end;
331    
332     procedure TIBStoredProc.Prepare;
333     begin
334     SetPrepared(True);
335     end;
336    
337     procedure TIBStoredProc.UnPrepare;
338     begin
339     SetPrepared(False);
340     end;
341    
342     procedure TIBStoredProc.FreeStatement;
343     begin
344     InternalUnPrepare;
345     FPrepared := False;
346     end;
347    
348     procedure TIBStoredProc.SetPrepare(Value: Boolean);
349     begin
350     if Value then Prepare
351     else UnPrepare;
352     end;
353    
354     procedure TIBStoredProc.CopyParams(Value: TParams);
355     begin
356     if not Prepared and (FParams.Count = 0) then
357     try
358     Prepare;
359     Value.Assign(FParams);
360     finally
361     UnPrepare;
362     end else
363     Value.Assign(FParams);
364     end;
365    
366     procedure TIBStoredProc.SetParamsList(Value: TParams);
367     begin
368     CheckInactive;
369     if Prepared then
370     begin
371     SetPrepared(False);
372     FParams.Assign(Value);
373     SetPrepared(True);
374     end else
375     FParams.Assign(Value);
376     end;
377    
378     function TIBStoredProc.ParamByName(const Value: string): TParam;
379     begin
380     Result := FParams.ParamByName(Value);
381     end;
382    
383     function TIBStoredProc.GetStoredProcedureNames: TStrings;
384     begin
385     FNameList.clear;
386     GetStoredProcedureNamesFromServer;
387     Result := FNameList;
388     end;
389    
390     procedure TIBStoredProc.GetStoredProcedureNamesFromServer;
391     var
392     Query : TIBSQL;
393     begin
394     if not (csReading in ComponentState) then begin
395     ActivateConnection;
396     Database.InternalTransaction.StartTransaction;
397     Query := TIBSQL.Create(self);
398     try
399     Query.GoToFirstRecordOnExecute := False;
400     Query.Database := DataBase;
401     Query.Transaction := Database.InternalTransaction;
402     Query.SQL.Text := 'Select RDB$PROCEDURE_NAME from RDB$PROCEDURES'; {do not localize}
403     Query.Prepare;
404     Query.ExecQuery;
405     while (not Query.EOF) and (Query.Next <> nil) do
406     FNameList.Add(TrimRight(Query.Current.ByName('RDB$PROCEDURE_NAME').AsString)); {do not localize}
407     finally
408     Query.Free;
409     Database.InternalTransaction.Commit;
410     end;
411     end;
412     end;
413    
414     procedure TIBStoredProc.SetParams;
415     var
416     i : integer;
417     j: integer;
418     begin
419     i := 0;
420     for j := 0 to FParams.Count - 1 do
421     begin
422     if (Params[j].ParamType <> ptInput) then
423     continue;
424     if not Params[j].Bound then
425     IBError(ibxeRequiredParamNotSet, [nil]);
426     if Params[j].IsNull then
427     SQLParams[i].IsNull := True
428     else begin
429     SQLParams[i].IsNull := False;
430     case Params[j].DataType of
431     ftString:
432     SQLParams[i].AsString := Params[j].AsString;
433     ftBoolean, ftSmallint, ftWord:
434     SQLParams[i].AsShort := Params[j].AsSmallInt;
435     ftInteger:
436     SQLParams[i].AsLong := Params[j].AsInteger;
437     { ftLargeInt:
438     SQLParams[i].AsInt64 := Params[j].AsLargeInt; }
439     ftFloat, ftCurrency:
440     SQLParams[i].AsDouble := Params[j].AsFloat;
441     ftBCD:
442     SQLParams[i].AsCurrency := Params[j].AsCurrency;
443     ftDate:
444     SQLParams[i].AsDate := Params[j].AsDateTime;
445     ftTime:
446     SQLParams[i].AsTime := Params[j].AsDateTime;
447     ftDateTime:
448     SQLParams[i].AsDateTime := Params[j].AsDateTime;
449     ftBlob, ftMemo:
450     SQLParams[i].AsString := Params[j].AsString;
451     else
452     IBError(ibxeNotSupported, [nil]);
453     end;
454     end;
455     Inc(i);
456     end;
457     end;
458    
459     procedure TIBStoredProc.SetParamsFromCursor;
460     var
461     I: Integer;
462     DataSet: TDataSet;
463     begin
464     if DataSource <> nil then
465     begin
466     DataSet := DataSource.DataSet;
467     if DataSet <> nil then
468     begin
469     DataSet.FieldDefs.Update;
470     for I := 0 to FParams.Count - 1 do
471     with FParams[I] do
472     if (not Bound) and
473     ((ParamType = ptInput) or (ParamType = ptInputOutput)) then
474     AssignField(DataSet.FieldByName(Name));
475     end;
476     end;
477     end;
478    
479     procedure TIBStoredProc.FetchDataIntoOutputParams;
480     var
481     i,j : Integer;
482     begin
483     j := 0;
484     for i := 0 to FParams.Count - 1 do
485     with Params[I] do
486     if ParamType = ptOutput then begin
487     Value := QSelect.Fields[j].Value;
488     Inc(j);
489     end;
490     end;
491    
492     procedure TIBStoredProc.InternalOpen;
493     begin
494     IBError(ibxeIsAExecuteProcedure,[nil]);
495     end;
496    
497     procedure TIBStoredProc.DefineProperties(Filer: TFiler);
498    
499     function WriteData: Boolean;
500     begin
501     if Filer.Ancestor <> nil then
502     Result := not FParams.IsEqual(TIBStoredProc(Filer.Ancestor).FParams) else
503     Result := FParams.Count > 0;
504     end;
505    
506     begin
507     inherited DefineProperties(Filer);
508     Filer.DefineProperty('ParamData', ReadParamData, WriteParamData, WriteData); {do not localize}
509     end;
510    
511     procedure TIBStoredProc.WriteParamData(Writer: TWriter);
512     begin
513     Writer.WriteCollection(Params);
514     end;
515    
516     procedure TIBStoredProc.ReadParamData(Reader: TReader);
517     begin
518     Reader.ReadValue;
519     Reader.ReadCollection(Params);
520     end;
521    
522     { TIBStoredProc IProviderSupport }
523    
524     function TIBStoredProc.PSGetParams: TParams;
525     begin
526     Result := Params;
527     end;
528    
529     procedure TIBStoredProc.PSSetParams(AParams: TParams);
530     begin
531     if AParams.Count > 0 then
532     Params.Assign(AParams);
533     Close;
534     end;
535    
536     function TIBStoredProc.PSGetTableName: string;
537     begin
538     { ! }
539     end;
540    
541     procedure TIBStoredProc.PSExecute;
542     begin
543     ExecProc;
544     end;
545    
546     procedure TIBStoredProc.PSSetCommandText(const CommandText: string);
547     begin
548     if CommandText <> '' then
549     StoredProcName := CommandText;
550     end;
551    
552     end.