ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/runtime/IBQuery.pas
Revision: 23
Committed: Fri Mar 13 10:26:52 2015 UTC (9 years, 8 months ago) by tony
Content type: text/x-pascal
File size: 14663 byte(s)
Log Message:
Committing updates for Release R1-2-1

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