ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/runtime/IBStoredProc.pas
(Generate patch)

Comparing ibx/trunk/runtime/IBStoredProc.pas (file contents):
Revision 5 by tony, Fri Feb 18 16:26:16 2011 UTC vs.
Revision 17 by tony, Sat Dec 28 19:22:24 2013 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines