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

# Content
1 {************************************************************************}
2 { }
3 { Borland Delphi Visual Component Library }
4 { InterBase Express core components }
5 { }
6 { Copyright (c) 1998-2000 Inprise Corporation }
7 { }
8 { InterBase Express is based in part on the product }
9 { Free IB Components, written by Gregory H. Deatz for }
10 { Hoagland, Longo, Moran, Dunst & Doukas Company. }
11 { Free IB Components is used under license. }
12 { }
13 { The contents of this file are subject to the InterBase }
14 { Public License Version 1.0 (the "License"); you may not }
15 { use this file except in compliance with the License. You }
16 { may obtain a copy of the License at http://www.Inprise.com/IPL.html }
17 { Software distributed under the License is distributed on }
18 { an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either }
19 { express or implied. See the License for the specific language }
20 { governing rights and limitations under the License. }
21 { The Original Code was created by InterBase Software Corporation }
22 { and its successors. }
23 { Portions created by Inprise Corporation are Copyright (C) Inprise }
24 { Corporation. All Rights Reserved. }
25 { Contributor(s): Jeff Overcash }
26 { }
27 { 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 IBHeader, IB, IBCustomDataSet, IBSQL, IBSQLParser;
48
49 type
50
51 { TIBQuery }
52
53 TIBQuery = class(TIBParserDataSet)
54 private
55 FSQL: TStrings;
56 FPrepared: Boolean;
57 FParams: TParams;
58 FText: string;
59 FRowsAffected: Integer;
60 FCheckRowsAffected: Boolean;
61 FSQLUpdating: boolean;
62 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 function CreateParser: TSelectSQLParser; override;
84 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 property BaseSQLSelect;
110
111 published
112 property Active;
113 property BufferChunks;
114 property CachedUpdates;
115 property DataSource read GetDataSource write SetDataSource;
116 property GenerateParamNames;
117 // property Constraints stored ConstraintsStored;
118 property GeneratorField;
119 property ParamCheck;
120 property SQL: TStrings read FSQL write SetQuery;
121 property Params: TParams read FParams write SetParamsList;
122 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 QSelect.GenerateParamNames := GenerateParamNames;
168 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 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 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
275 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 SQLParam: TIBXSQLVAR;
396
397 begin
398 for I := 0 to FParams.Count - 1 do
399 begin
400 SQLParam := SQLParams.ByName(Params[i].Name);
401 if Params[i].IsNull then
402 SQLParam.IsNull := True
403 else begin
404 SQLParam.IsNull := False;
405 case Params[i].DataType of
406 ftBytes:
407 begin
408 GetMem(Buffer,Params[i].GetDataSize);
409 try
410 Params[i].GetData(Buffer);
411 SQLParam.AsPointer := Buffer;
412 finally
413 FreeMem(Buffer);
414 end;
415 end;
416 ftString:
417 SQLParam.AsString := Params[i].AsString;
418 ftBoolean, ftSmallint, ftWord:
419 SQLParam.AsShort := Params[i].AsSmallInt;
420 ftInteger:
421 SQLParam.AsLong := Params[i].AsInteger;
422 ftLargeInt:
423 SQLParam.AsInt64 := Params[i].AsLargeInt;
424 ftFloat:
425 SQLParam.AsDouble := Params[i].AsFloat;
426 ftBCD, ftCurrency:
427 SQLParam.AsCurrency := Params[i].AsCurrency;
428 ftDate:
429 SQLParam.AsDate := Params[i].AsDateTime;
430 ftTime:
431 SQLParam.AsTime := Params[i].AsDateTime;
432 ftDateTime:
433 SQLParam.AsDateTime := Params[i].AsDateTime;
434 ftBlob, ftMemo:
435 SQLParam.AsString := Params[i].AsString;
436 else
437 IBError(ibxeNotSupported, [nil]);
438 end;
439 end;
440 end;
441 end;
442
443 procedure TIBQuery.PrepareSQL(Value: PChar);
444 begin
445 QSelect.GenerateParamNames := GenerateParamNames;
446 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 function TIBQuery.CreateParser: TSelectSQLParser;
488 begin
489 Result := inherited CreateParser;
490 Result.OnSQLChanging := QueryChanged;
491 end;
492
493 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