ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/runtime/IBStoredProc.pas
Revision: 5
Committed: Fri Feb 18 16:26:16 2011 UTC (13 years, 2 months ago) by tony
Content type: text/x-pascal
File size: 14890 byte(s)
Log Message:
Committing updates for Release pre-release

File Contents

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