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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines