ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/runtime/IBTable.pas
Revision: 39
Committed: Tue May 17 08:14:52 2016 UTC (7 years, 10 months ago) by tony
Content type: text/x-pascal
File size: 44902 byte(s)
Log Message:
Committing updates for Release R1-4-1

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 IBTable;
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, IBCustomDataSet,
45 IBSQL, IBUtils;
46
47 type
48
49 { TIBTable }
50
51 TIBTableType = (ttSystem, ttView);
52 TIBTableTypes = set of TIBTableType;
53 TIndexName = String;
54
55 TIBTable = class;
56
57 TIBTable = class(TIBCustomDataSet)
58 private
59 FSystemTable: Boolean;
60 FMultiTableView: Boolean;
61 FMasterLink: TMasterDataLink;
62 FMasterFieldsList: TStringList;
63 FDetailFieldsList: TStringList;
64 FStoreDefs: Boolean;
65 FIndexDefs: TIndexDefs;
66 FDefaultIndex: Boolean;
67 FReadOnly: Boolean;
68 FFieldsIndex: Boolean;
69 FTableName: String;
70 FIndexName: TIndexName;
71 FRegenerateSQL: Boolean;
72 FNameList: TStrings;
73 FSwitchingIndex: Boolean;
74 FPrimaryIndexFields: string;
75 FTableTypes: TIBTableTypes;
76 WhereAllRefreshSQL: TStrings;
77 WhereDBKeyRefreshSQL: TStrings;
78 WherePrimaryRefreshSQL: TStrings;
79
80 function GetIndexFieldCount: Integer;
81 function GetIndexField(Index: Integer): TField;
82 procedure MasterChanged(Sender: TObject);
83 procedure MasterDisabled(Sender: TObject);
84 procedure SetDataSource(Value: TDataSource);
85 procedure SetIndexField(Index: Integer; Value: TField);
86 procedure SetIndexFieldNames(const Value: string);
87 procedure GenerateSQL;
88 procedure GenerateUpdateSQL;
89 procedure SwitchToIndex();
90 procedure InternalTableRefresh();
91 function GetTableNames: TStrings;
92 procedure GetTableNamesFromServer;
93 procedure SetTableTypes(
94 const Value: TIBTableTypes);
95 function InternalGotoDBKey(DBKey: TIBDBKey): Boolean;
96 function FormatFieldsList(Value: string): string;
97 function GetCurrentDBKey: TIBDBKey;
98 function InternalGetUpdatable: Boolean;
99 function GetExists: Boolean;
100 procedure SetIndexDefs(Value: TIndexDefs);
101 procedure ExtractLinkFields;
102 function FieldDefsStored: Boolean;
103 function IndexDefsStored: Boolean;
104 function GetMasterFields: string;
105 procedure SetMasterFields(const Value: string);
106 function GetIndexFieldNames: string;
107 function GetIndexName: string;
108 procedure SetIndexName(const Value: string);
109 procedure SetParams;
110 procedure SetReadOnly(Value: Boolean);
111 procedure SetTableName(Value: String);
112 procedure SetIndex(const Value: string; FieldsIndex: Boolean);
113 procedure ResetSQLStatements;
114 procedure Reopen;
115
116 protected
117
118 procedure DoOnNewRecord; override;
119 procedure GetIndexParams(const IndexName: string; FieldsIndex: Boolean;
120 var IndexedName: string);
121 function GetCanModify: Boolean; override;
122 procedure UpdateIndexDefs; override;
123 procedure DataEvent(Event: TDataEvent; Info: Ptrint); override;
124 procedure DefChanged(Sender: TObject); virtual;
125 function GetDataSource: TDataSource; override;
126 procedure InitFieldDefs; override;
127 procedure InternalClose; override;
128 procedure InternalOpen; override;
129 procedure InternalRefresh; override;
130 procedure SetFiltered(Value: Boolean); override;
131 procedure SetFilterText(const Value: string); override;
132 procedure SetFilterOptions(Value: TFilterOptions); override;
133 procedure InternalRefreshRow; override;
134
135 public
136 constructor Create(AOwner: TComponent); override;
137 destructor Destroy; override;
138 procedure AddIndex(const Name, Fields: string; Options: TIndexOptions;
139 const DescFields: string = '');
140 procedure CreateTable;
141 procedure DeleteIndex(const Name: string);
142 procedure DeleteTable;
143 procedure EmptyTable;
144 procedure GetDetailLinkFields(MasterFields, DetailFields: TList); virtual;
145 procedure GetIndexNames(List: TStrings);
146 procedure GotoCurrent(Table: TIBTable);
147 property CurrentDBKey: TIBDBKey read GetCurrentDBKey;
148 property Exists: Boolean read GetExists;
149 property IndexFieldCount: Integer read GetIndexFieldCount;
150 property IndexFields[Index: Integer]: TField read GetIndexField write SetIndexField;
151 property TableNames: TStrings read GetTableNames;
152
153 published
154 property AutoCommit;
155 property Active;
156 property BufferChunks;
157 property CachedUpdates;
158 property DataSetCloseAction;
159 // property Constraints stored ConstraintsStored;
160 property DefaultIndex: Boolean read FDefaultIndex write FDefaultIndex default True;
161 property FieldDefs stored FieldDefsStored;
162 property Filter;
163 property Filtered;
164 property IndexDefs: TIndexDefs read FIndexDefs write SetIndexDefs stored IndexDefsStored;
165 property IndexFieldNames: string read GetIndexFieldNames write SetIndexFieldNames;
166 property IndexName: string read GetIndexName write SetIndexName;
167 property MasterFields: string read GetMasterFields write SetMasterFields;
168 property MasterSource: TDataSource read GetDataSource write SetDataSource;
169 property ReadOnly: Boolean read FReadOnly write SetReadOnly default False;
170 property StoreDefs: Boolean read FStoreDefs write FStoreDefs default False;
171 property TableName: String read FTableName write SetTableName;
172 property TableTypes: TIBTableTypes read FTableTypes write SetTableTypes default [];
173 property UpdateObject;
174 property UniDirectional;
175
176 property BeforeDatabaseDisconnect;
177 property AfterDatabaseDisconnect;
178 property DatabaseFree;
179 property BeforeTransactionEnd;
180 property AfterTransactionEnd;
181 property TransactionFree;
182 property OnFilterRecord;
183 end;
184
185 implementation
186
187 { TIBTable }
188
189 constructor TIBTable.Create(AOwner: TComponent);
190 begin
191 inherited Create(AOwner);
192 FNameList := TStringList.Create;
193 FSwitchingIndex := False;
194 FIndexDefs := TIndexDefs.Create(Self);
195 WhereAllRefreshSQL := TStringList.Create;
196 WhereDBKeyRefreshSQL := TStringList.Create;
197 WherePrimaryRefreshSQL := TStringList.Create;
198 FDefaultIndex := True;
199 FRegenerateSQL := True;
200 FMasterFieldsList := TStringList.Create;
201 FDetailFieldsList := TStringList.Create;
202 FMasterLink := TMasterDataLink.Create(Self);
203 FMasterLink.OnMasterChange := MasterChanged;
204 FMasterLink.OnMasterDisable := MasterDisabled;
205 QRefresh.OnSQLChanging := nil;
206 QDelete.OnSQLChanging := nil;
207 QInsert.OnSQLChanging := nil;
208 QModify.OnSQLChanging := nil;
209 end;
210
211 destructor TIBTable.Destroy;
212 begin
213 FNameList.Free;
214 FIndexDefs.Free;
215 FMasterFieldsList.Free;
216 FDetailFieldsList.Free;
217 FMasterLink.Free;
218 WhereAllRefreshSQL.Free;
219 WhereDBKeyRefreshSQL.Free;
220 WherePrimaryRefreshSQL.Free;
221 inherited Destroy;
222 end;
223
224 procedure TIBTable.InternalClose;
225 begin
226 DataEvent(dePropertyChange, 0);
227 inherited InternalClose;
228 end;
229
230 procedure TIBTable.InternalOpen;
231 begin
232 if FTableName = '' then IBError(ibxeNoTableName, [nil]);
233 ActivateConnection;
234 ActivateTransaction;
235 if FRegenerateSQL then
236 begin
237 InternalUnprepare;
238 GenerateSQL;
239 if not FReadOnly then
240 GenerateUpdateSQL;
241 FRegenerateSQL := False;
242 end;
243 { writeln(SelectSQL.Text);
244 writeln(InsertSQL.Text);
245 writeln(DeleteSQL.Text);
246 writeln(ModifySQL.Text); }
247 SetParams;
248 inherited InternalOpen;
249 end;
250
251 procedure TIBTable.InternalRefresh;
252 var
253 DBKey: TIBDBKey;
254 begin
255 DBKey := CurrentDBKey;
256 Reopen;
257 if DBKey.DBKey[0] <> 0 then
258 InternalGotoDBKey(DBKey);
259 end;
260
261 procedure TIBTable.SetFiltered(Value: Boolean);
262 begin
263 if(Filtered <> Value) then
264 begin
265 inherited SetFiltered(value);
266 if Active then
267 InternalTableRefresh;
268 end
269 else
270 inherited SetFiltered(value);
271 end;
272
273 procedure TIBTable.SetFilterText(const Value: string);
274 begin
275 if Filtered and (Value <> Filter) then
276 begin
277 inherited SetFilterText(value);
278 InternalTableRefresh;
279 end
280 else
281 inherited SetFilterText(value);
282 end;
283
284 procedure TIBTable.SetFilterOptions(Value: TFilterOptions);
285 begin
286 if Value <> [] then
287 IBError(ibxeNotSupported, [nil]);
288 end;
289
290 procedure TIBTable.InternalRefreshRow;
291 begin
292 if CurrentDBKey.DBKey[0] <> 0 then
293 QRefresh.SQL.Assign(WhereDBKeyRefreshSQL)
294 else if WherePrimaryRefreshSQL.Text <> '' then
295 QRefresh.SQL.Assign(WherePrimaryRefreshSQL)
296 else
297 QRefresh.SQL.Assign(WhereAllRefreshSQL);
298 inherited InternalRefreshRow;
299 end;
300
301 procedure TIBTable.DefChanged(Sender: TObject);
302 begin
303 StoreDefs := True;
304 end;
305
306 procedure TIBTable.InitFieldDefs;
307 var
308 DidActivate: Boolean;
309 Query: TIBSQL;
310 begin
311 if FTableName = '' then IBError(ibxeNoTableName, [nil]);
312 if (InternalPrepared) then
313 InternalInitFieldDefs
314 else
315 begin
316 {Get the field defs from a simple query on the table}
317 ActivateConnection;
318 Query := TIBSQL.Create(self);
319 try
320 Query.Database := DataBase;
321 Query.Transaction := Database.InternalTransaction;
322 DidActivate := false;
323 Query.SQL.Text := 'Select * from ' + QuoteIdentifier(DataBase.SQLDialect, FTableName);
324 with Query.Transaction do
325 begin
326 if not InTransaction then
327 begin
328 StartTransaction;
329 DidActivate := true
330 end;
331 end;
332 Query.Prepare;
333 if DidActivate then
334 Query.Transaction.Rollback;
335 FieldDefsFromQuery(Query);
336 finally
337 Query.Free;
338 end;
339 end;
340 end;
341
342 { Index / Ranges / Keys }
343
344 procedure TIBTable.AddIndex(const Name, Fields: string; Options: TIndexOptions;
345 const DescFields: string);
346 var
347 Query: TIBSQL;
348 FieldList: string;
349 begin
350 FieldDefs.Update;
351 if Active then begin
352 CheckBrowseMode;
353 CursorPosChanged;
354 end;
355 Query := TIBSQL.Create(self);
356 try
357 Query.Database := DataBase;
358 Query.Transaction := Transaction;
359 FieldList := FormatFieldsList(Fields);
360 if (ixPrimary in Options) then
361 begin
362 Query.SQL.Text := 'Alter Table ' + {do not localize}
363 QuoteIdentifier(Database.SQLDialect, FTableName) +
364 ' Add CONSTRAINT ' + {do not localize}
365 QuoteIdentifier(Database.SQLDialect, Name)
366 + ' Primary Key (' + {do not localize}
367 FormatFieldsList(Fields) +
368 ')';
369 end
370 else if ([ixUnique, ixDescending] * Options = [ixUnique, ixDescending]) then
371 Query.SQL.Text := 'Create unique Descending Index ' + {do not localize}
372 QuoteIdentifier(Database.SQLDialect, Name) +
373 ' on ' + {do not localize}
374 QuoteIdentifier(Database.SQLDialect, FTableName) +
375 ' (' + FieldList + ')'
376 else if (ixUnique in Options) then
377 Query.SQL.Text := 'Create unique Index ' + {do not localize}
378 QuoteIdentifier(Database.SQLDialect, Name) +
379 ' on ' + {do not localize}
380 QuoteIdentifier(Database.SQLDialect, FTableName) +
381 ' (' + FieldList + ')'
382 else if (ixDescending in Options) then
383 Query.SQL.Text := 'Create Descending Index ' + {do not localize}
384 QuoteIdentifier(Database.SQLDialect, Name) +
385 ' on ' + {do not localize}
386 QuoteIdentifier(Database.SQLDialect, FTableName) +
387 ' (' + FieldList + ')'
388 else
389 Query.SQL.Text := 'Create Index ' + {do not localize}
390 QuoteIdentifier(Database.SQLDialect, Name) +
391 ' on ' + {do not localize}
392 QuoteIdentifier(Database.SQLDialect, FTableName) +
393 ' (' + FieldList + ')';
394 Query.Prepare;
395 Query.ExecQuery;
396 IndexDefs.Updated := False;
397 finally
398 Query.free
399 end;
400 end;
401
402 procedure TIBTable.DeleteIndex(const Name: string);
403 var
404 Query: TIBSQL;
405
406 procedure DeleteByIndex;
407 begin
408 Query := TIBSQL.Create(self);
409 try
410 Query.Database := DataBase;
411 Query.Transaction := Transaction;
412 Query.SQL.Text := 'Drop index ' + {do not localize}
413 QuoteIdentifier(Database.SQLDialect, Name);
414 Query.Prepare;
415 Query.ExecQuery;
416 IndexDefs.Updated := False;
417 finally
418 Query.Free;
419 end;
420 end;
421
422 function DeleteByConstraint: Boolean;
423 begin
424 Result := False;
425 Query := TIBSQL.Create(self);
426 try
427 Query.Database := DataBase;
428 Query.Transaction := Transaction;
429 Query.SQL.Text := 'Select ''foo'' from RDB$RELATION_CONSTRAINTS ' +
430 'where RDB$RELATION_NAME = ' +
431 '''' +
432 FormatIdentifierValue(Database.SQLDialect,
433 QuoteIdentifier(DataBase.SQLDialect, FTableName)) +
434 ''' ' +
435 ' AND RDB$CONSTRAINT_NAME = ' +
436 '''' +
437 FormatIdentifierValue(Database.SQLDialect,
438 QuoteIdentifier(DataBase.SQLDialect, Name)) +
439 ''' ' +
440 'AND RDB$CONSTRAINT_TYPE = ''PRIMARY KEY''';
441 Query.Prepare;
442 Query.ExecQuery;
443 if not Query.EOF then
444 begin
445 Query.Close;
446 Query.SQL.Text := 'Alter Table ' + {do not localize}
447 QuoteIdentifier(DataBase.SQLDialect, FTableName) +
448 ' Drop Constraint ' +
449 QuoteIdentifier(DataBase.SQLDialect, Name);
450 Query.Prepare;
451 Query.ExecQuery;
452 IndexDefs.Updated := False;
453 Result := True;
454 end;
455 finally
456 Query.Free;
457 end;
458 end;
459
460 procedure DeleteByKey;
461 begin
462 Query := TIBSQL.Create(self);
463 try
464 Query.Database := DataBase;
465 Query.Transaction := Transaction;
466 Query.SQL.Text := 'Select RDB$CONSTRAINT_NAME from RDB$RELATION_CONSTRAINTS ' +
467 'where RDB$RELATION_NAME = ' +
468 '''' +
469 FormatIdentifierValue(Database.SQLDialect,
470 QuoteIdentifier(DataBase.SQLDialect, FTableName)) +
471 ''' ' +
472 'AND RDB$INDEX_NAME = ' +
473 '''' +
474 FormatIdentifierValue(Database.SQLDialect,
475 QuoteIdentifier(DataBase.SQLDialect, Name)) +
476 ''' ' +
477 'AND RDB$CONSTRAINT_TYPE = ''PRIMARY KEY''';
478 Query.Prepare;
479 Query.ExecQuery;
480 if not Query.EOF then
481 begin
482 Query.Close;
483 Query.SQL.Text := 'Alter Table ' + {do not localize}
484 QuoteIdentifier(DataBase.SQLDialect, FTableName) +
485 ' Drop Constraint ' +
486 QuoteIdentifier(DataBase.SQLDialect, Query.Current.ByName('RDB$CONSTRAINT_NAME').AsString);
487 Query.Prepare;
488 Query.ExecQuery;
489 IndexDefs.Updated := False;
490 end;
491 finally
492 Query.Free;
493 end;
494 end;
495
496 begin
497 if Active then
498 CheckBrowseMode;
499 IndexDefs.Update;
500 if (Pos('RDB$PRIMARY', Name) <> 0 ) then {do not localize} {mbcs ok}
501 DeleteByKey
502 else if not DeleteByConstraint then
503 DeleteByIndex;
504 end;
505
506 function TIBTable.GetIndexFieldNames: string;
507 begin
508 if FFieldsIndex then Result := FIndexName else Result := '';
509 end;
510
511 function TIBTable.GetIndexName: string;
512 begin
513 if FFieldsIndex then Result := '' else Result := FIndexName;
514 end;
515
516 procedure TIBTable.GetIndexNames(List: TStrings);
517 begin
518 IndexDefs.Update;
519 IndexDefs.GetItemNames(List);
520 end;
521
522 procedure TIBTable.GetIndexParams(const IndexName: string;
523 FieldsIndex: Boolean; var IndexedName: string);
524 var
525 IndexStr: TIndexName;
526 begin
527 if IndexName <> '' then
528 begin
529 IndexDefs.Update;
530 IndexStr := IndexName;
531 if FieldsIndex then
532 IndexStr := IndexDefs.FindIndexForFields(IndexName).Name;
533 end;
534 IndexedName := IndexStr;
535 end;
536
537 procedure TIBTable.SetIndexDefs(Value: TIndexDefs);
538 begin
539 IndexDefs.Assign(Value);
540 end;
541
542 procedure TIBTable.SetIndex(const Value: string; FieldsIndex: Boolean);
543 begin
544 if Active then CheckBrowseMode;
545 if (FIndexName <> Value) or (FFieldsIndex <> FieldsIndex) then
546 begin
547 FIndexName := Value;
548 FFieldsIndex := FieldsIndex;
549 if Active then
550 begin
551 SwitchToIndex;
552 end;
553 end;
554 end;
555
556 procedure TIBTable.SetIndexFieldNames(const Value: string);
557 begin
558 SetIndex(Value, Value <> '');
559 end;
560
561 procedure TIBTable.SetIndexName(const Value: string);
562 begin
563 SetIndex(Value, False);
564 end;
565
566 procedure TIBTable.UpdateIndexDefs;
567 var
568 Opts: TIndexOptions;
569 Flds: string;
570 Query, SubQuery: TIBSQL;
571 fn: string;
572 aField: TFieldDef;
573 begin
574 if not (csReading in ComponentState) then begin
575 if not Active and not FSwitchingIndex then
576 FieldDefs.Update;
577 IndexDefs.Clear;
578 Database.InternalTransaction.StartTransaction;
579 Query := TIBSQL.Create(self);
580 try
581 FPrimaryIndexFields := '';
582 Query.GoToFirstRecordOnExecute := False;
583 Query.Database := DataBase;
584 Query.Transaction := Database.InternalTransaction;
585 Query.SQL.Text :=
586 'Select I.RDB$INDEX_NAME, I.RDB$UNIQUE_FLAG, I.RDB$INDEX_TYPE, ' + {do not localize}
587 'I.RDB$SEGMENT_COUNT, S.RDB$FIELD_NAME from RDB$INDICES I, ' + {do not localize}
588 'RDB$INDEX_SEGMENTS S where I.RDB$INDEX_NAME = S.RDB$INDEX_NAME '+ {do not localize}
589 'and I.RDB$RELATION_NAME = ' + '''' + {do not localize}
590 FormatIdentifierValue(Database.SQLDialect,
591 QuoteIdentifier(DataBase.SQLDialect, FTableName)) + '''';
592 Query.Prepare;
593 Query.ExecQuery;
594 while (not Query.EOF) and (Query.Next <> nil) do
595 begin
596 with IndexDefs.AddIndexDef do
597 begin
598 Name := TrimRight(Query.Current.ByName('RDB$INDEX_NAME').AsString); {do not localize}
599 Opts := [];
600 if Pos ('RDB$PRIMARY', Name) = 1 then Include(Opts, ixPrimary); {do not localize} {mbcs ok}
601 if Query.Current.ByName('RDB$UNIQUE_FLAG').AsInteger = 1 then Include(Opts, ixUnique); {do not localize}
602 if Query.Current.ByName('RDB$INDEX_TYPE').AsInteger = 2 then Include(Opts, ixDescending); {do not localize}
603 Options := Opts;
604 if (Query.Current.ByName('RDB$SEGMENT_COUNT').AsInteger = 1) then {do not localize}
605 begin
606 fn := Trim(Query.Current.ByName('RDB$FIELD_NAME').AsString); {do not localize}
607 aField := GetFieldDefFromAlias(fn);
608 if assigned(aField) then
609 Fields := aField.Name
610 else
611 Fields := fn;
612 end
613 else begin
614 SubQuery := TIBSQL.Create(self);
615 try
616 SubQuery.GoToFirstRecordOnExecute := False;
617 SubQuery.Database := DataBase;
618 SubQuery.Transaction := Database.InternalTransaction;
619 SubQuery.SQL.Text :=
620 'Select RDB$FIELD_NAME from RDB$INDEX_SEGMENTS where RDB$INDEX_NAME = ' + {do not localize}
621 '''' +
622 FormatIdentifierValue(Database.SQLDialect,
623 QuoteIdentifier(DataBase.SQLDialect, Name)) +
624 '''' + 'ORDER BY RDB$FIELD_POSITION'; {do not localize}
625 SubQuery.Prepare;
626 SubQuery.ExecQuery;
627 Flds := '';
628 while (not SubQuery.EOF) and (SubQuery.Next <> nil) do
629 begin
630 fn := TrimRight(SubQuery.Current.ByName('RDB$FIELD_NAME').AsString); {do not localize}
631 aField := GetFieldDefFromAlias(fn);
632 if assigned(aField) then
633 fn := aField.Name;
634 if (Flds = '') then
635 Flds := fn
636 else begin
637 Query.Next;
638 Flds := Flds + ';' + fn;
639 end;
640 end;
641 Fields := Flds;
642 finally
643 SubQuery.Free;
644 end;
645 end;
646 if (ixDescending in Opts) then
647 DescFields := Fields;
648 if ixPrimary in Opts then
649 FPrimaryIndexFields := Fields;
650 end;
651 end;
652 finally
653 Query.Free;
654 Database.InternalTransaction.Commit;
655 end;
656 end;
657 end;
658
659 function TIBTable.GetExists: Boolean;
660 var
661 Query: TIBSQL;
662 begin
663 Result := Active;
664 if Result or (TableName = '') then Exit;
665 Database.InternalTransaction.StartTransaction;
666 Query := TIBSQL.Create(self);
667 try
668 Query.Database := DataBase;
669 Query.Transaction := Database.InternalTransaction;
670 Query.SQL.Text :=
671 'Select USER from RDB$RELATIONS where RDB$RELATION_NAME = ' + {do not localize}
672 '''' +
673 FormatIdentifierValue(Database.SQLDialect,
674 QuoteIdentifier(DataBase.SQLDialect, FTableName)) + '''';
675 Query.Prepare;
676 Query.ExecQuery;
677 Result := not Query.EOF;
678 finally
679 Query.Free;
680 Database.InternalTransaction.Commit;
681 end;
682 end;
683
684 procedure TIBTable.GotoCurrent(Table: TIBTable);
685 begin
686 CheckBrowseMode;
687 Table.CheckBrowseMode;
688 if (Database <> Table.Database) or
689 (CompareText(TableName, Table.TableName) <> 0) then
690 IBError(ibxeTableNameMismatch, [nil]);
691 Table.UpdateCursorPos;
692 InternalGotoDBKey(Table.CurrentDBKey);
693 DoBeforeScroll;
694 Resync([rmExact, rmCenter]);
695 DoAfterScroll;
696 end;
697
698
699 procedure TIBTable.CreateTable;
700 var
701 FieldList: string;
702
703 procedure InitFieldsList;
704 var
705 I: Integer;
706 begin
707 InitFieldDefsFromFields;
708 for I := 0 to FieldDefs.Count - 1 do begin
709 if ( I > 0) then
710 FieldList := FieldList + ', ';
711 with FieldDefs[I] do
712 begin
713 case DataType of
714 ftString:
715 FieldList := FieldList +
716 QuoteIdentifier(DataBase.SQLDialect, Name) +
717 ' VARCHAR(' + IntToStr(Size) + ')'; {do not localize}
718 ftFixedChar:
719 FieldList := FieldList +
720 QuoteIdentifier(DataBase.SQLDialect, Name) +
721 ' CHAR(' + IntToStr(Size) + ')'; {do not localize}
722 ftBoolean:
723 FieldList := FieldList +
724 QuoteIdentifier(DataBase.SQLDialect, Name) +
725 ' BOOLEAN'; {do not localize}
726 ftSmallint, ftWord:
727 FieldList := FieldList +
728 QuoteIdentifier(DataBase.SQLDialect, Name) +
729 ' SMALLINT'; {do not localize}
730 ftInteger:
731 FieldList := FieldList +
732 QuoteIdentifier(DataBase.SQLDialect, Name) +
733 ' INTEGER'; {do not localize}
734 ftFloat, ftCurrency:
735 FieldList := FieldList +
736 QuoteIdentifier(DataBase.SQLDialect, Name) +
737 ' DOUBLE PRECISION'; {do not localize}
738 ftBCD: begin
739 if (Database.SQLDialect = 1) then begin
740 if (Precision > 9) then
741 IBError(ibxeFieldUnsupportedType,[nil]);
742 if (Precision <= 4) then
743 Precision := 9;
744 end;
745 if (Precision <= 4 ) then
746 FieldList := FieldList +
747 QuoteIdentifier(DataBase.SQLDialect, Name) +
748 ' Numeric(18, 4)' {do not localize}
749 else
750 FieldList := FieldList +
751 QuoteIdentifier(DataBase.SQLDialect, Name) +
752 ' Numeric(' + IntToStr(Precision) + ', 4)'; {do not localize}
753 end;
754 ftDate:
755 FieldList := FieldList +
756 QuoteIdentifier(DataBase.SQLDialect, Name) +
757 ' DATE'; {do not localize}
758 ftTime:
759 FieldList := FieldList +
760 QuoteIdentifier(DataBase.SQLDialect, Name) +
761 ' TIME'; {do not localize}
762 ftDateTime:
763 if (Database.SQLDialect = 1) then
764 FieldList := FieldList +
765 QuoteIdentifier(DataBase.SQLDialect, Name) +
766 ' DATE' {do not localize}
767 else
768 FieldList := FieldList +
769 QuoteIdentifier(DataBase.SQLDialect, Name) +
770 ' TIMESTAMP'; {do not localize}
771 ftLargeInt:
772 if (Database.SQLDialect = 1) then
773 IBError(ibxeFieldUnsupportedType,[nil])
774 else
775 FieldList := FieldList +
776 QuoteIdentifier(DataBase.SQLDialect, Name) +
777 ' Numeric(18, 0)'; {do not localize}
778 ftBlob, ftMemo:
779 FieldList := FieldList +
780 QuoteIdentifier(DataBase.SQLDialect, Name) +
781 ' BLOB SUB_TYPE 1'; {do not localize}
782 ftBytes, ftVarBytes, ftGraphic..ftTypedBinary:
783 FieldList := FieldList +
784 QuoteIdentifier(DataBase.SQLDialect, Name) +
785 ' BLOB SUB_TYPE 0'; {do not localize}
786 ftUnknown, ftADT, ftArray, ftReference, ftDataSet,
787 ftCursor, ftWideString, ftAutoInc:
788 IBError(ibxeFieldUnsupportedType,[nil]);
789 else
790 IBError(ibxeFieldUnsupportedType,[nil]);
791 end;
792 if faRequired in Attributes then
793 FieldList := FieldList + ' NOT NULL'; {do not localize}
794 end;
795 end;
796 end;
797
798 procedure InternalCreateTable;
799 var
800 I: Integer;
801 Query: TIBSQL;
802 begin
803 if (FieldList = '') then
804 IBError(ibxeFieldUnsupportedType,[nil]);
805 Query := TIBSQL.Create(self);
806 try
807 Query.Database := Database;
808 Query.transaction := Transaction;
809 Query.SQL.Text := 'Create Table ' +
810 QuoteIdentifier(DataBase.SQLDialect, FTableName) +
811 ' (' + FieldList; {do not localize}
812 for I := 0 to IndexDefs.Count - 1 do
813 with IndexDefs[I] do
814 if ixPrimary in Options then
815 begin
816 Query.SQL.Text := Query.SQL.Text + ', CONSTRAINT ' +
817 QuoteIdentifier(DataBase.SQLDialect, Name) +
818 ' Primary Key (' +
819 FormatFieldsList(Fields) +
820 ')';
821 end;
822 Query.SQL.Text := Query.SQL.Text + ')';
823 Query.Prepare;
824 Query.ExecQuery;
825 finally
826 Query.Free;
827 end;
828 end;
829
830 procedure InternalCreateIndex;
831 var
832 I: Integer;
833 begin
834 for I := 0 to IndexDefs.Count - 1 do
835 with IndexDefs[I] do
836 if not (ixPrimary in Options) then
837 AddIndex(Name, Fields, Options);
838 end;
839
840 begin
841 CheckInactive;
842 InitFieldsList;
843 InternalCreateTable;
844 InternalCreateIndex;
845 end;
846
847 procedure TIBTable.DeleteTable;
848 var
849 Query: TIBSQL;
850 begin
851 CheckInactive;
852 Query := TIBSQL.Create(self);
853 try
854 Query.Database := DataBase;
855 Query.Transaction := Transaction;
856 Query.SQL.Text := 'drop table ' + {do not localize}
857 QuoteIdentifier(DataBase.SQLDialect, FTableName);
858 Query.Prepare;
859 Query.ExecQuery;
860 finally
861 Query.Free;
862 end;
863 end;
864
865 procedure TIBTable.EmptyTable;
866 var
867 Query: TIBSQL;
868 begin
869 if Active then
870 CheckBrowseMode;
871 Query := TIBSQL.Create(self);
872 try
873 Query.Database := DataBase;
874 Query.Transaction := Transaction;
875 Query.SQL.Text := 'delete from ' + {do not localize}
876 QuoteIdentifier(DataBase.SQLDialect, FTableName);
877 Query.Prepare;
878 Query.ExecQuery;
879 if Active then
880 begin
881 ClearBuffers;
882 DataEvent(deDataSetChange, 0);
883 end;
884 finally
885 Query.Free;
886 end;
887 end;
888
889 procedure TIBTable.DataEvent(Event: TDataEvent; Info: Ptrint);
890 begin
891 if Event = dePropertyChange then begin
892 IndexDefs.Updated := False;
893 FRegenerateSQL := True;
894 end;
895 inherited DataEvent(Event, Info);
896 end;
897
898 { Informational & Property }
899
900 function TIBTable.GetCanModify: Boolean;
901 begin
902 Result := True;
903 if (FTableName = '') or FReadOnly
904 or FSystemTable or FMultiTableView then
905 Result := False;
906 end;
907
908 function TIBTable.InternalGetUpdatable: Boolean;
909 var
910 Query : TIBSQL;
911 begin
912 Database.InternalTransaction.StartTransaction;
913 Query := TIBSQL.Create(self);
914 try
915 Query.Database := DataBase;
916 Query.Transaction := Database.InternalTransaction;
917 Query.SQL.Text := 'Select RDB$SYSTEM_FLAG, RDB$DBKEY_LENGTH ' + {do not localize}
918 'from RDB$RELATIONS where RDB$RELATION_NAME = ' + {do not localize}
919 '''' +
920 FormatIdentifierValue(Database.SQLDialect,
921 QuoteIdentifier(DataBase.SQLDialect, FTableName)) + '''';
922 Query.Prepare;
923 Query.ExecQuery;
924 if (Query.Current[0].AsInteger <> 0) or
925 (Query.Current[1].AsInteger <> 8) then
926 Result := False
927 else
928 Result := True;
929 finally
930 Query.Free;
931 Database.InternalTransaction.Commit;
932 end;
933 end;
934
935 function TIBTable.FieldDefsStored: Boolean;
936 begin
937 Result := StoreDefs and (FieldDefs.Count > 0);
938 end;
939
940 function TIBTable.IndexDefsStored: Boolean;
941 begin
942 Result := StoreDefs and (IndexDefs.Count > 0);
943 end;
944
945 procedure TIBTable.SetParams;
946 var
947 i: Integer;
948 begin
949 if (MasterSource = nil) or (MasterSource.DataSet = nil) or
950 (not MasterSource.DataSet.Active) or (FMasterFieldsList.Count = 0) then
951 exit;
952 for i := 0 to FMasterFieldsList.Count - 1 do
953 QSelect.Params.ByName(FMasterFieldsList.Strings[i]).Value :=
954 MasterSource.DataSet.FieldByName(FMasterFieldsList.Strings[i]).Value;
955 end;
956
957 procedure TIBTable.MasterChanged(Sender: TObject);
958 begin
959 CheckBrowseMode;
960 SetParams;
961 ReQuery;
962 end;
963
964 procedure TIBTable.MasterDisabled(Sender: TObject);
965 begin
966 DataEvent(dePropertyChange, 0);
967 ReQuery;
968 end;
969
970 function TIBTable.GetDataSource: TDataSource;
971 begin
972 Result := FMasterLink.DataSource;
973 end;
974
975 procedure TIBTable.SetDataSource(Value: TDataSource);
976 begin
977 if IsLinkedTo(Value) then IBError(ibxeCircularDataLink, [Self]);
978 if FMasterLink.DataSource <> Value then
979 DataEvent(dePropertyChange, 0);
980 FMasterLink.DataSource := Value;
981 end;
982
983 function TIBTable.GetMasterFields: string;
984 begin
985 Result := FMasterLink.FieldNames;
986 end;
987
988 procedure TIBTable.SetMasterFields(const Value: string);
989 begin
990 if FMasterLink.FieldNames <> Value then
991 DataEvent(dePropertyChange, 0);
992 FMasterLink.FieldNames := Value;
993 end;
994
995 procedure TIBTable.DoOnNewRecord;
996 var
997 I: Integer;
998 begin
999 if FMasterLink.Active and (FMasterLink.Fields.Count > 0) then
1000 for I := 0 to FMasterLink.Fields.Count - 1 do
1001 IndexFields[I] := TField(FMasterLink.Fields[I]);
1002 inherited DoOnNewRecord;
1003 end;
1004
1005 function TIBTable.FormatFieldsList(Value: String): String;
1006 var
1007 FieldName: string;
1008 i: Integer;
1009 begin
1010 if Database.SQLDialect = 1 then begin
1011 Value := QuoteIdentifier(Database.SQLDialect, Value);
1012 Result := StringReplace (Value, ';', ', ', [rfReplaceAll]);
1013 end
1014 else begin
1015 i := 1;
1016 Result := '';
1017 while i <= Length(Value) do
1018 begin
1019 FieldName := ExtractFieldName(Value, i);
1020 if Result = '' then
1021 Result := QuoteIdentifier(Database.SQLDialect, FieldName)
1022 else
1023 Result := Result + ', ' + QuoteIdentifier(Database.SQLDialect, FieldName);
1024 end;
1025 end;
1026 end;
1027
1028 procedure TIBTable.ExtractLinkFields;
1029 var
1030 i: Integer;
1031 DetailFieldNames: String;
1032 begin
1033 FMasterFieldsList.Clear;
1034 FDetailFieldsList.Clear;
1035 i := 1;
1036 while i <= Length(MasterFields) do
1037 FMasterFieldsList.Add(ExtractFieldName(MasterFields, i));
1038 i := 1;
1039 if IndexFieldNames = '' then
1040 DetailFieldNames := FPrimaryIndexFields
1041 else
1042 DetailFieldNames := IndexFieldNames;
1043 while i <= Length(DetailFieldNames) do
1044 FDetailFieldsList.Add(ExtractFieldName(DetailFieldNames, i));
1045 end;
1046
1047 procedure TIBTable.GetDetailLinkFields(MasterFields, DetailFields: TList);
1048 var
1049 i: Integer;
1050 Idx: TIndexDef;
1051 begin
1052 MasterFields.Clear;
1053 DetailFields.Clear;
1054 if (MasterSource <> nil) and (MasterSource.DataSet <> nil) and
1055 (Self.MasterFields <> '') then
1056 begin
1057 Idx := nil;
1058 MasterSource.DataSet.GetFieldList(MasterFields, Self.MasterFields);
1059 UpdateIndexDefs;
1060 if IndexName <> '' then
1061 Idx := IndexDefs.Find(IndexName)
1062 else if IndexFieldNames <> '' then
1063 Idx := IndexDefs.GetIndexForFields(IndexFieldNames, False)
1064 else
1065 for i := 0 to IndexDefs.Count - 1 do
1066 if ixPrimary in IndexDefs[i].Options then
1067 begin
1068 Idx := IndexDefs[i];
1069 break;
1070 end;
1071 if Idx <> nil then
1072 GetFieldList(DetailFields, Idx.Fields);
1073 end;
1074 end;
1075
1076 procedure TIBTable.SetReadOnly(Value: Boolean);
1077 begin
1078 CheckInactive;
1079 FReadOnly := Value;
1080 end;
1081
1082 procedure TIBTable.SetTableName(Value: String);
1083 begin
1084 if not (csReading in ComponentState) then
1085 begin
1086 CheckInactive;
1087 if Value <> FTableName then
1088 begin
1089 ResetSQLStatements;
1090 FRegenerateSQL := True;
1091 FTableName := Value;
1092 IndexName := '';
1093 IndexFieldNames := '';
1094 FPrimaryIndexFields := '';
1095 DataEvent(dePropertyChange, 0);
1096 end;
1097 end
1098 else if Value <> FTableName then
1099 FTableName := Value;
1100 end;
1101
1102 function TIBTable.GetIndexField(Index: Integer): TField;
1103 var
1104 I, Count: Integer;
1105 FieldNames, FieldName: String;
1106 begin
1107 Result := nil;
1108 FieldName := '';
1109 FieldNames := IndexFieldNames;
1110 if FieldNames = '' then
1111 begin
1112 for I := 0 to IndexDefs.Count - 1 do
1113 if (IndexDefs[i].Name = FIndexName) then
1114 begin
1115 FieldNames := IndexDefs[i].Fields;
1116 break;
1117 end;
1118 end;
1119 for I := 0 to Index do
1120 begin
1121 Count := Pos(';', FieldNames); {mbcs OK}
1122 if Count = 0 then
1123 FieldName := FieldNames
1124 else begin
1125 FieldName := Copy(FieldNames, 0, Count - 1);
1126 System.Delete(FieldNames, 1, Count);
1127 end;
1128 end;
1129 if FieldName <> '' then
1130 Result := FieldByName(FieldName)
1131 else
1132 IBError(ibxeIndexFieldMissing, [nil]);
1133 end;
1134
1135
1136 procedure TIBTable.SetIndexField(Index: Integer; Value: TField);
1137 begin
1138 GetIndexField(Index).Assign(Value);
1139 end;
1140
1141 function TIBTable.GetIndexFieldCount: Integer;
1142 var
1143 I, Index: Integer;
1144 FieldNames: String;
1145 done: Boolean;
1146 begin
1147 FieldNames := IndexFieldNames;
1148 if FieldNames = '' then
1149 begin
1150 for I := 0 to IndexDefs.Count - 1 do
1151 if (IndexDefs[i].Name = FIndexName) then
1152 begin
1153 FieldNames := IndexDefs[i].Fields;
1154 break;
1155 end;
1156 end;
1157 if FieldNames = '' then
1158 Result := 0
1159 else
1160 begin
1161 done := False;
1162 Result := 1;
1163 while not done do
1164 begin
1165 Index := Pos(';', FieldNames); {mbcs ok}
1166 if Index <> 0 then
1167 begin
1168 System.Delete(FieldNames, 1, Index);
1169 Inc(Result);
1170 end else
1171 done := True;
1172 end;
1173 end;
1174 end;
1175
1176 function TIBTable.GetTableNames: TStrings;
1177 begin
1178 FNameList.clear;
1179 GetTableNamesFromServer;
1180 Result := FNameList;
1181 end;
1182
1183 procedure TIBTable.GetTableNamesFromServer;
1184 var
1185 Query : TIBSQL;
1186 begin
1187 if not (csReading in ComponentState) then begin
1188 ActivateConnection;
1189 Database.InternalTransaction.StartTransaction;
1190 Query := TIBSQL.Create(self);
1191 try
1192 Query.GoToFirstRecordOnExecute := False;
1193 Query.Database := DataBase;
1194 Query.Transaction := Database.InternalTransaction;
1195 if (TableTypes * [ttSystem, ttView] = [ttSystem, ttView]) then
1196 Query.SQL.Text := 'Select RDB$RELATION_NAME from RDB$RELATIONS' {do not localize}
1197 else if ttSystem in TableTypes then
1198 Query.SQL.Text := 'Select RDB$RELATION_NAME from RDB$RELATIONS' + {do not localize}
1199 ' where RDB$VIEW_BLR is NULL' {do not localize}
1200 else if ttView in TableTypes then
1201 Query.SQL.Text := 'Select RDB$RELATION_NAME from RDB$RELATIONS' + {do not localize}
1202 ' where RDB$SYSTEM_FLAG = 0' {do not localize}
1203 else
1204 Query.SQL.Text := 'Select RDB$RELATION_NAME from RDB$RELATIONS' + {do not localize}
1205 ' where RDB$VIEW_BLR is NULL and RDB$SYSTEM_FLAG = 0'; {do not localize}
1206 Query.Prepare;
1207 Query.ExecQuery;
1208 while (not Query.EOF) and (Query.Next <> nil) do
1209 FNameList.Add (TrimRight(Query.Current[0].AsString));
1210 finally
1211 Query.Free;
1212 Database.InternalTransaction.Commit;
1213 end;
1214 end;
1215 end;
1216
1217 procedure TIBTable.SwitchToIndex();
1218 begin
1219 FSwitchingIndex := True;
1220 InternalTableRefresh;
1221 FSwitchingIndex := False;
1222 end;
1223
1224 procedure TIBTable.InternalTableRefresh();
1225 var
1226 DBKey: TIBDBKey;
1227 begin
1228 CheckActive;
1229 DBKey := CurrentDBKey;
1230 FRegenerateSQL := True;
1231 Reopen;
1232 if DBKey.DBKey[0] <> 0 then
1233 InternalGotoDBKey(DBKey);
1234 end;
1235
1236 procedure TIBTable.GenerateSQL;
1237 var
1238 i: Integer;
1239 SQL: TStrings;
1240 OrderByStr: string;
1241 bWhereClausePresent: Boolean;
1242 fn: string;
1243 aField: TFieldDef;
1244 begin
1245 bWhereClausePresent := False;
1246 Database.CheckActive;
1247 Transaction.CheckInTransaction;
1248 if IndexDefs.Updated = False then
1249 IndexDefs.Update;
1250 if IndexFieldNames <> '' then
1251 OrderByStr := FormatFieldsList(IndexFieldNames)
1252 else if IndexName <> '' then
1253 OrderByStr := FormatFieldsList(IndexDefs[IndexDefs.Indexof (IndexName)].Fields)
1254 else if FDefaultIndex and (FPrimaryIndexFields <> '') then
1255 OrderByStr := FormatFieldsList(FPrimaryIndexFields);
1256 SQL := TStringList.Create;
1257 SQL.Text := 'select ' + {do not localize}
1258 QuoteIdentifier(DataBase.SQLDialect, FTableName) + '.*, ' {do not localize}
1259 + 'RDB$DB_KEY as IBX_INTERNAL_DBKEY from ' {do not localize}
1260 + QuoteIdentifier(DataBase.SQLDialect, FTableName);
1261 if Filtered and (Filter <> '') then
1262 begin
1263 SQL.Text := SQL.Text + ' where ' + Filter; {do not localize}
1264 bWhereClausePresent := True;
1265 end;
1266 if (MasterSource <> nil) and (MasterSource.DataSet <> nil) and (MasterFields <> '') then
1267 begin
1268 if bWhereClausePresent then
1269 SQL.Text := SQL.Text + ' AND ' {do not localize}
1270 else
1271 SQL.Text := SQL.Text + ' WHERE '; {do not localize}
1272 ExtractLinkfields;
1273 if FDetailFieldsList.Count < FMasterFieldsList.Count then
1274 IBError(ibxeUnknownError, [nil]);
1275 for i := 0 to FMasterFieldsList.Count - 1 do
1276 begin
1277 if i > 0 then
1278 SQL.Text := SQL.Text + 'AND ';
1279 aField := FieldDefs.Find(FDetailFieldsList.Strings[i]);
1280 if assigned(aField) then
1281 fn := GetDBAliasName(aField.FieldNo)
1282 else
1283 fn := FDetailFieldsList.Strings[i]; {something wrong if we get here - but should word}
1284 SQL.Text := SQL.Text +
1285 QuoteIdentifier(DataBase.SQLDialect, fn) + ' = :' + FMasterFieldsList.Strings[i];
1286 end;
1287 end;
1288 if OrderByStr <> '' then
1289 SQL.Text := SQL.Text + ' order by ' + OrderByStr; {do not localize}
1290 SelectSQL.Assign(SQL);
1291 RefreshSQL.Text := 'select ' + {do not localize}
1292 QuoteIdentifier(DataBase.SQLDialect, FTableName) + '.*, ' {do not localize}
1293 + 'RDB$DB_KEY as IBX_INTERNAL_DBKEY from ' {do not localize}
1294 + QuoteIdentifier(DataBase.SQLDialect, FTableName) +
1295 ' where RDB$DB_KEY = :IBX_INTERNAL_DBKEY'; {do not localize}
1296 WhereDBKeyRefreshSQL.Assign(RefreshSQL);
1297 InternalPrepare;
1298 SQL.Free;
1299 end;
1300
1301 procedure TIBTable.GenerateUpdateSQL;
1302 var
1303 InsertFieldList, InsertParamList, UpdateFieldList: string;
1304 WherePrimaryFieldList, WhereAllFieldList: string;
1305
1306 procedure GenerateFieldLists;
1307 var
1308 I: Integer;
1309 begin
1310 for I := 0 to FieldDefs.Count - 1 do begin
1311 with FieldDefs[I] do begin
1312 if not (InternalCalcField or (faReadOnly in Attributes) or
1313 (DataType = ftUnknown)) then
1314 begin
1315 if ( InsertFieldList <> '' ) then begin
1316 InsertFieldList := InsertFieldList + ', ';
1317 InsertParamList := InsertParamList + ', ';
1318 UpdateFieldList := UpdateFieldList + ', ';
1319 if (DataType <> ftBlob) and (DataType <>ftMemo) then
1320 WhereAllFieldList := WhereAllFieldList + ' AND ';
1321 end;
1322 InsertFieldList := InsertFieldList +
1323 QuoteIdentifier(DataBase.SQLDialect, GetDBAliasName(FieldNo));
1324 InsertParamList := InsertParamList + ':' + Name;
1325 UpdateFieldList := UpdateFieldList +
1326 QuoteIdentifier(DataBase.SQLDialect, GetDBAliasName(FieldNo)) +
1327 ' = :' + Name;
1328 if (DataType <> ftBlob) and (DataType <>ftMemo) then
1329 WhereAllFieldList := WhereAllFieldList +
1330 QuoteIdentifier(DataBase.SQLDialect, GetDBAliasName(FieldNo)) + ' = :' + Name;
1331 end;
1332 end;
1333 end;
1334 end;
1335
1336 procedure GenerateWherePrimaryFieldList;
1337 var
1338 i: Integer;
1339 tmp, fn: String;
1340 aField: TFieldDef;
1341 begin
1342 i := 1;
1343 while i <= Length(FPrimaryIndexFields) do
1344 begin
1345 tmp := ExtractFieldName(FPrimaryIndexFields, i);
1346 aField := FieldDefs.Find(tmp);
1347 if assigned(aField) then
1348 fn := GetDBAliasName(aField.FieldNo)
1349 else
1350 fn := tmp; {something wrong if we get here - but will work in most cases}
1351 tmp :=
1352 QuoteIdentifier(DataBase.SQLDialect, fn) + ' = :' +
1353 QuoteIdentifier(DataBase.SQLDialect, tmp);{do not localize}
1354 if WherePrimaryFieldList <> '' then
1355 WherePrimaryFieldList :=
1356 WherePrimaryFieldList + ' AND ' + tmp
1357 else
1358 WherePrimaryFieldList := tmp;
1359 end;
1360 end;
1361
1362 begin
1363 if InternalGetUpdatable = False then
1364 FReadOnly := True
1365 else
1366 begin
1367 DeleteSQL.Text := 'delete from ' + {do not localize}
1368 QuoteIdentifier(DataBase.SQLDialect, FTableName) +
1369 ' where RDB$DB_KEY = ' + ':IBX_INTERNAL_DBKEY'; {do not localize}
1370 GenerateFieldLists;
1371 InsertSQL.Text := 'insert into ' + {do not localize}
1372 QuoteIdentifier(DataBase.SQLDialect, FTableName) +
1373 ' (' + InsertFieldList + {do not localize}
1374 ') values (' + InsertParamList + ')'; {do not localize}
1375 ModifySQL.Text := 'update ' +
1376 QuoteIdentifier(DataBase.SQLDialect, FTableName) +
1377 ' set ' + UpdateFieldList + {do not localize}
1378 ' where RDB$DB_KEY = :IBX_INTERNAL_DBKEY'; {do not localize}
1379 WhereAllRefreshSQL.Text := 'select ' + {do not localize}
1380 QuoteIdentifier(DataBase.SQLDialect, FTableName) + '.*, '
1381 + 'RDB$DB_KEY as IBX_INTERNAL_DBKEY from ' {do not localize}
1382 + QuoteIdentifier(DataBase.SQLDialect, FTableName) +
1383 ' where ' + WhereAllFieldList; {do not localize}
1384 if FPrimaryIndexFields <> '' then
1385 begin
1386 GenerateWherePrimaryFieldList;
1387 WherePrimaryRefreshSQL.Text := 'select ' + {do not localize}
1388 QuoteIdentifier(DataBase.SQLDialect, FTableName) + '.*, ' {do not localize}
1389 + 'RDB$DB_KEY as IBX_INTERNAL_DBKEY from ' {do not localize}
1390 + QuoteIdentifier(DataBase.SQLDialect, FTableName) +
1391 ' where ' + WherePrimaryFieldList; {do not localize}
1392 end;
1393 try
1394 InternalPrepare;
1395 except
1396 FReadonly := True;
1397 end;
1398 end;
1399 end;
1400
1401 procedure TIBTable.ResetSQLStatements;
1402 begin
1403 SelectSQL.Text := '';
1404 DeleteSQL.Text := '';
1405 InsertSQL.Text := '';
1406 ModifySQL.Text := '';
1407 RefreshSQL.Text := '';
1408 end;
1409
1410 procedure TIBTable.SetTableTypes(
1411 const Value: TIBTableTypes);
1412 begin
1413 FTableTypes := Value;
1414 end;
1415
1416 function TIBTable.InternalGotoDBKey(DBKey: TIBDBKey): Boolean;
1417
1418 function DBKeyCompare (DBKey1, DBKey2: TIBDBKey): Boolean;
1419 var
1420 I: Integer;
1421 begin
1422 for I := 0 to 7 do
1423 if (DBKey1.DBKey[i] <> DBKey2.DBKey[i]) then begin
1424 result := False;
1425 exit;
1426 end;
1427 result := True;
1428 end;
1429 begin
1430 CheckActive;
1431 DisableControls;
1432 try
1433 result := False;
1434 First;
1435 while ((not result) and (not EOF)) do begin
1436 if (DBKeyCompare (DBKey, PRecordData(GetActiveBuf)^.rdDBKey)) then
1437 result := True
1438 else
1439 Next;
1440 end;
1441 if not result then
1442 First
1443 else
1444 CursorPosChanged;
1445 finally
1446 EnableControls;
1447 end;
1448 end;
1449
1450 function TIBTable.GetCurrentDBKey: TIBDBKey;
1451 var
1452 Buf: pChar;
1453 begin
1454 CheckActive;
1455 buf := GetActiveBuf;
1456 if Buf <> nil then
1457 Result := PRecordData(Buf)^.rdDBKey
1458 else
1459 Result.DBKey[0] := 0;
1460 end;
1461
1462 procedure TIBTable.Reopen;
1463 begin
1464 DisableControls;
1465 try
1466 if Active then
1467 begin
1468 SetState(dsInactive);
1469 CloseCursor;
1470 OpenCursor(false);
1471 SetState(dsBrowse);
1472 end;
1473 finally
1474 EnableControls;
1475 end;
1476 end;
1477
1478 end.