ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/runtime/IBQuery.pas
Revision: 21
Committed: Thu Feb 26 10:33:34 2015 UTC (9 years, 9 months ago) by tony
Content type: text/x-pascal
File size: 14573 byte(s)
Log Message:
Committing updates for Release R1-2-0

File Contents

# User Rev Content
1 tony 17 {************************************************************************}
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 IBQuery;
35    
36     interface
37    
38     {$Mode Delphi}
39    
40     uses
41     {$IFDEF WINDOWS }
42     Windows,
43     {$ELSE}
44     unix,
45     {$ENDIF}
46     SysUtils, Graphics, Classes, Controls, Db,
47 tony 21 IBHeader, IB, IBCustomDataSet, IBSQL, IBSQLParser;
48 tony 17
49     type
50    
51     { TIBQuery }
52    
53 tony 21 TIBQuery = class(TIBParserDataSet)
54 tony 17 private
55     FSQL: TStrings;
56     FPrepared: Boolean;
57     FParams: TParams;
58     FText: string;
59     FRowsAffected: Integer;
60     FCheckRowsAffected: Boolean;
61 tony 21 FSQLUpdating: boolean;
62 tony 17 function GetRowsAffected: Integer;
63     procedure PrepareSQL(Value: PChar);
64     procedure QueryChanged(Sender: TObject);
65     procedure ReadParamData(Reader: TReader);
66     procedure SetQuery(Value: TStrings);
67     procedure SetParamsList(Value: TParams);
68     procedure SetParams;
69     procedure SetParamsFromCursor;
70     procedure SetPrepared(Value: Boolean);
71     procedure SetPrepare(Value: Boolean);
72     procedure WriteParamData(Writer: TWriter);
73     function GetStmtHandle: TISC_STMT_HANDLE;
74    
75     protected
76     { IProviderSupport }
77     (* procedure PSExecute; override;
78     function PSGetParams: TParams; override;
79     function PSGetTableName: string; override;
80     procedure PSSetCommandText(const CommandText: string); override;
81     procedure PSSetParams(AParams: TParams); override; *)
82    
83 tony 21 function CreateParser: TSelectSQLParser; override;
84 tony 17 procedure DefineProperties(Filer: TFiler); override;
85     procedure InitFieldDefs; override;
86     procedure InternalOpen; override;
87     procedure Disconnect; override;
88     function GetParamsCount: Word;
89     function GenerateQueryForLiveUpdate : Boolean;
90     procedure SetFiltered(Value: Boolean); override;
91    
92     public
93     constructor Create(AOwner: TComponent); override;
94     destructor Destroy; override;
95     procedure BatchInput(InputObject: TIBBatchInput);
96     procedure BatchOutput(OutputObject: TIBBatchOutput);
97     procedure ExecSQL;
98     procedure GetDetailLinkFields(MasterFields, DetailFields: TList);(* override;*)
99     function ParamByName(const Value: string): TParam;
100     procedure Prepare;
101     procedure UnPrepare;
102     property Prepared: Boolean read FPrepared write SetPrepare;
103     property ParamCount: Word read GetParamsCount;
104     property StmtHandle: TISC_STMT_HANDLE read GetStmtHandle;
105     property StatementType;
106     property Text: string read FText;
107     property RowsAffected: Integer read GetRowsAffected;
108     // property Params: TParams read FParams write SetParamsList;
109 tony 21 property BaseSQLSelect;
110 tony 17
111     published
112     property Active;
113     property BufferChunks;
114     property CachedUpdates;
115     property DataSource read GetDataSource write SetDataSource;
116 tony 19 property GenerateParamNames;
117 tony 17 // property Constraints stored ConstraintsStored;
118     property GeneratorField;
119     property ParamCheck;
120     property SQL: TStrings read FSQL write SetQuery;
121 tony 19 property Params: TParams read FParams write SetParamsList;
122 tony 17 property UniDirectional default False;
123     property UpdateObject;
124     property Filtered;
125    
126     property BeforeDatabaseDisconnect;
127     property AfterDatabaseDisconnect;
128     property DatabaseFree;
129     property BeforeTransactionEnd;
130     property AfterTransactionEnd;
131     property TransactionFree;
132     property OnFilterRecord;
133     end;
134    
135     implementation
136    
137     { TIBQuery }
138    
139     constructor TIBQuery.Create(AOwner: TComponent);
140     begin
141     inherited Create(AOwner);
142     FSQL := TStringList.Create;
143     TStringList(SQL).OnChange := QueryChanged;
144     FParams := TParams.Create(Self);
145     ParamCheck := True;
146     FRowsAffected := -1;
147     end;
148    
149     destructor TIBQuery.Destroy;
150     begin
151     Destroying;
152     Disconnect;
153     SQL.Free;
154     FParams.Free;
155     inherited Destroy;
156     end;
157    
158     procedure TIBQuery.InitFieldDefs;
159     begin
160     inherited InitFieldDefs;
161     end;
162    
163     procedure TIBQuery.InternalOpen;
164     begin
165     ActivateConnection();
166     ActivateTransaction;
167 tony 19 QSelect.GenerateParamNames := GenerateParamNames;
168 tony 17 SetPrepared(True);
169     if DataSource <> nil then
170     SetParamsFromCursor;
171     SetParams;
172     inherited InternalOpen;
173     end;
174    
175     procedure TIBQuery.Disconnect;
176     begin
177     Close;
178     UnPrepare;
179     end;
180    
181     procedure TIBQuery.SetPrepare(Value: Boolean);
182     begin
183     if Value then
184     Prepare
185     else
186     UnPrepare;
187     end;
188    
189     procedure TIBQuery.Prepare;
190     begin
191     SetPrepared(True);
192     end;
193    
194     procedure TIBQuery.UnPrepare;
195     begin
196     SetPrepared(False);
197     end;
198    
199     procedure TIBQuery.SetQuery(Value: TStrings);
200     begin
201     if SQL.Text <> Value.Text then
202     begin
203     Disconnect;
204     SQL.BeginUpdate;
205     try
206     SQL.Assign(Value);
207     finally
208     SQL.EndUpdate;
209     end;
210     end;
211     end;
212    
213     procedure TIBQuery.QueryChanged(Sender: TObject);
214     var
215     List: TParams;
216     begin
217     if not (csReading in ComponentState) then
218     begin
219     Disconnect;
220 tony 21 if HasParser and not FSQLUpdating then
221     begin
222     FSQLUpdating := true;
223     try
224     SQL.Text := Parser.SQLText;
225     finally
226     FSQLUpdating := false
227     end;
228     end;
229 tony 17 if ParamCheck or (csDesigning in ComponentState) then
230     begin
231     List := TParams.Create(Self);
232     try
233     FText := List.ParseSQL(SQL.Text, True);
234     List.AssignValues(FParams);
235     FParams.Clear;
236     FParams.Assign(List);
237     finally
238     List.Free;
239     end;
240     end else
241     FText := SQL.Text;
242     DataEvent(dePropertyChange, 0);
243     end else
244     FText := FParams.ParseSQL(SQL.Text, true);
245     SelectSQL.Assign(SQL);
246     end;
247    
248     procedure TIBQuery.SetParamsList(Value: TParams);
249     begin
250     FParams.AssignValues(Value);
251     end;
252    
253     function TIBQuery.GetParamsCount: Word;
254     begin
255     Result := FParams.Count;
256     end;
257    
258     procedure TIBQuery.DefineProperties(Filer: TFiler);
259    
260     function WriteData: Boolean;
261     begin
262     {The following results in a stream read error with nested frames. Hence commented out until
263     someone fixes the LCL }
264     { if Filer.Ancestor <> nil then
265     Result := not FParams.IsEqual(TIBQuery(Filer.Ancestor).FParams) else}
266     Result := FParams.Count > 0;
267     end;
268    
269     begin
270     inherited DefineProperties(Filer);
271     Filer.DefineProperty('ParamData', ReadParamData, WriteParamData, WriteData); {do not localize}
272     end;
273    
274 tony 21
275 tony 17 procedure TIBQuery.ReadParamData(Reader: TReader);
276     begin
277     FParams.Clear;
278     Reader.ReadValue;
279     Reader.ReadCollection(FParams);
280     end;
281    
282     procedure TIBQuery.WriteParamData(Writer: TWriter);
283     begin
284     Writer.WriteCollection(Params);
285     end;
286    
287     procedure TIBQuery.SetPrepared(Value: Boolean);
288     begin
289     CheckDatasetClosed;
290     if Value <> Prepared then
291     begin
292     if Value then
293     begin
294     FRowsAffected := -1;
295     FCheckRowsAffected := True;
296     if Length(Text) > 1 then PrepareSQL(PChar(Text))
297     else IBError(ibxeEmptySQLStatement, [nil]);
298     end
299     else
300     begin
301     if FCheckRowsAffected then
302     FRowsAffected := RowsAffected;
303     InternalUnPrepare;
304     end;
305     FPrepared := Value;
306     end;
307     end;
308    
309     procedure TIBQuery.SetParamsFromCursor;
310     var
311     I: Integer;
312     DataSet: TDataSet;
313     Field: TField;
314    
315     procedure CheckRequiredParams;
316     var
317     I: Integer;
318     begin
319     for I := 0 to FParams.Count - 1 do
320     with FParams[I] do
321     if not Bound then
322     IBError(ibxeRequiredParamNotSet, [nil]);
323     end;
324    
325     begin
326     if DataSource <> nil then
327     begin
328     DataSet := DataSource.DataSet;
329     if DataSet <> nil then
330     begin
331     DataSet.FieldDefs.Update;
332     for I := 0 to FParams.Count - 1 do
333     if not FParams[I].Bound then
334     begin
335     Field := DataSet.FindField(FParams[I].Name);
336     if assigned(Field) then
337     begin
338     FParams[I].AssignField(Field);
339     FParams[I].Bound := False;
340     end;
341     end;
342     end
343     else
344     CheckRequiredParams;
345     end
346     else
347     CheckRequiredParams;
348     end;
349    
350    
351     function TIBQuery.ParamByName(const Value: string): TParam;
352     begin
353     Result := FParams.ParamByName(Value);
354     end;
355    
356     procedure TIBQuery.BatchInput(InputObject: TIBBatchInput);
357     begin
358     InternalBatchInput(InputObject);
359     end;
360    
361     procedure TIBQuery.BatchOutput(OutputObject: TIBBatchOutput);
362     begin
363     InternalBatchOutput(OutputObject);
364     end;
365    
366     procedure TIBQuery.ExecSQL;
367     var
368     DidActivate: Boolean;
369     begin
370     CheckInActive;
371     if SQL.Count <= 0 then
372     begin
373     FCheckRowsAffected := False;
374     IBError(ibxeEmptySQLStatement, [nil]);
375     end;
376     ActivateConnection();
377     DidActivate := ActivateTransaction;
378     try
379     SetPrepared(True);
380     if DataSource <> nil then SetParamsFromCursor;
381     if FParams.Count > 0 then SetParams;
382     InternalExecQuery;
383     finally
384     if DidActivate then
385     DeactivateTransaction;
386     FCheckRowsAffected := True;
387     end;
388     end;
389    
390     procedure TIBQuery.SetParams;
391    
392     var
393     i : integer;
394     Buffer: Pointer;
395 tony 21 SQLParam: TIBXSQLVAR;
396 tony 17
397     begin
398     for I := 0 to FParams.Count - 1 do
399     begin
400 tony 21 SQLParam := SQLParams.ByName(Params[i].Name);
401 tony 17 if Params[i].IsNull then
402 tony 21 SQLParam.IsNull := True
403 tony 17 else begin
404 tony 21 SQLParam.IsNull := False;
405 tony 17 case Params[i].DataType of
406     ftBytes:
407     begin
408     GetMem(Buffer,Params[i].GetDataSize);
409     try
410     Params[i].GetData(Buffer);
411 tony 21 SQLParam.AsPointer := Buffer;
412 tony 17 finally
413     FreeMem(Buffer);
414     end;
415     end;
416     ftString:
417 tony 21 SQLParam.AsString := Params[i].AsString;
418 tony 17 ftBoolean, ftSmallint, ftWord:
419 tony 21 SQLParam.AsShort := Params[i].AsSmallInt;
420 tony 17 ftInteger:
421 tony 21 SQLParam.AsLong := Params[i].AsInteger;
422 tony 19 ftLargeInt:
423 tony 21 SQLParam.AsInt64 := Params[i].AsLargeInt;
424 tony 17 ftFloat:
425 tony 21 SQLParam.AsDouble := Params[i].AsFloat;
426 tony 17 ftBCD, ftCurrency:
427 tony 21 SQLParam.AsCurrency := Params[i].AsCurrency;
428 tony 17 ftDate:
429 tony 21 SQLParam.AsDate := Params[i].AsDateTime;
430 tony 17 ftTime:
431 tony 21 SQLParam.AsTime := Params[i].AsDateTime;
432 tony 17 ftDateTime:
433 tony 21 SQLParam.AsDateTime := Params[i].AsDateTime;
434 tony 17 ftBlob, ftMemo:
435 tony 21 SQLParam.AsString := Params[i].AsString;
436 tony 17 else
437     IBError(ibxeNotSupported, [nil]);
438     end;
439     end;
440     end;
441     end;
442    
443     procedure TIBQuery.PrepareSQL(Value: PChar);
444     begin
445 tony 19 QSelect.GenerateParamNames := GenerateParamNames;
446 tony 17 InternalPrepare;
447     end;
448    
449    
450     function TIBQuery.GetRowsAffected: Integer;
451     begin
452     Result := -1;
453     if Prepared then
454     Result := QSelect.RowsAffected
455     end;
456    
457    
458     procedure TIBQuery.GetDetailLinkFields(MasterFields, DetailFields: TList);
459    
460     function AddFieldToList(const FieldName: string; DataSet: TDataSet;
461     List: TList): Boolean;
462     var
463     Field: TField;
464     begin
465     Field := DataSet.FindField(FieldName);
466     if (Field <> nil) then
467     List.Add(Field);
468     Result := Field <> nil;
469     end;
470    
471     var
472     i: Integer;
473     begin
474     MasterFields.Clear;
475     DetailFields.Clear;
476     if (DataSource <> nil) and (DataSource.DataSet <> nil) then
477     for i := 0 to Params.Count - 1 do
478     if AddFieldToList(Params[i].Name, DataSource.DataSet, MasterFields) then
479     AddFieldToList(Params[i].Name, Self, DetailFields);
480     end;
481    
482     function TIBQuery.GetStmtHandle: TISC_STMT_HANDLE;
483     begin
484     Result := SelectStmtHandle;
485     end;
486    
487 tony 21 function TIBQuery.CreateParser: TSelectSQLParser;
488     begin
489     Result := inherited CreateParser;
490     Result.OnSQLChanging := QueryChanged;
491     end;
492    
493 tony 17 function TIBQuery.GenerateQueryForLiveUpdate : Boolean;
494     begin
495     Result := False;
496     end;
497    
498     procedure TIBQuery.SetFiltered(Value: Boolean);
499     begin
500     if(Filtered <> Value) then
501     begin
502     inherited SetFiltered(value);
503     if Active then
504     begin
505     Close;
506     Open;
507     end;
508     end
509     else
510     inherited SetFiltered(value);
511     end;
512    
513     { TIBQuery IProviderSupport }
514     (*
515     function TIBQuery.PSGetParams: TParams;
516     begin
517     Result := Params;
518     end;
519    
520     procedure TIBQuery.PSSetParams(AParams: TParams);
521     begin
522     if AParams.Count <> 0 then
523     Params.Assign(AParams);
524     Close;
525     end;
526    
527     function TIBQuery.PSGetTableName: string;
528     begin
529     Result := inherited PSGetTableName;
530     end;
531    
532     procedure TIBQuery.PSExecute;
533     begin
534     ExecSQL;
535     end;
536    
537     procedure TIBQuery.PSSetCommandText(const CommandText: string);
538     begin
539     if CommandText <> '' then
540     SQL.Text := CommandText;
541     end;
542     *)
543     end.
544 tony 19