16 |
|
{ IBX Version 4.2 or higher required } |
17 |
|
{ Contributor(s): Jeff Overcash } |
18 |
|
{ } |
19 |
+ |
{ IBX For Lazarus (Firebird Express) } |
20 |
+ |
{ Contributor: Tony Whyman, MWA Software http://www.mwasoftware.co.uk } |
21 |
+ |
{ Portions created by MWA Software are copyright McCallum Whyman } |
22 |
+ |
{ Associates Ltd 2011 } |
23 |
+ |
{ } |
24 |
|
{************************************************************************} |
25 |
|
|
26 |
+ |
{ Syntax Enhancements Supported: |
27 |
+ |
|
28 |
+ |
Multi-action triggers (1.5) |
29 |
+ |
CREATE SEQUENCE (2.0) |
30 |
+ |
Database Triggers (2.1) |
31 |
+ |
Global Temporary Tables (2.1) |
32 |
+ |
Boolean Type (3.0) |
33 |
+ |
Identity Column Type (3.0) |
34 |
+ |
} |
35 |
+ |
|
36 |
|
unit IBExtract; |
37 |
|
|
38 |
|
{$Mode Delphi} |
39 |
+ |
{$codepage UTF8} |
40 |
|
|
41 |
|
interface |
42 |
|
|
43 |
|
uses |
44 |
< |
{$IFDEF LINUX } |
29 |
< |
unix, |
30 |
< |
{$ELSE} |
44 |
> |
{$IFDEF WINDOWS } |
45 |
|
Windows, |
46 |
+ |
{$ELSE} |
47 |
+ |
unix, |
48 |
|
{$ENDIF} |
49 |
< |
Messages, SysUtils, Classes, IBDatabase, IBDatabaseInfo, |
50 |
< |
IBSQL, IBUtils, IBHeader, IB, IBIntf; |
49 |
> |
SysUtils, Classes, IBDatabase, IBDatabaseInfo, |
50 |
> |
IBSQL, IBUtils, IBHeader, IB; |
51 |
|
|
52 |
|
type |
53 |
|
TExtractObjectTypes = |
61 |
|
|
62 |
|
TExtractTypes = Set of TExtractType; |
63 |
|
|
64 |
+ |
{ TIBExtract } |
65 |
+ |
|
66 |
|
TIBExtract = class(TComponent) |
67 |
|
private |
68 |
|
FDatabase : TIBDatabase; |
74 |
|
function GetDatabase: TIBDatabase; |
75 |
|
function GetIndexSegments ( indexname : String) : String; |
76 |
|
function GetTransaction: TIBTransaction; |
77 |
+ |
function GetTriggerType(TypeID: integer): string; |
78 |
|
procedure SetDatabase(const Value: TIBDatabase); |
79 |
|
procedure SetTransaction(const Value: TIBTransaction); |
80 |
|
function PrintValidation(ToValidate : String; flag : Boolean) : String; |
83 |
|
procedure GetProcedureArgs(Proc : String); |
84 |
|
protected |
85 |
|
function ExtractDDL(Flag : Boolean; TableName : String) : Boolean; |
86 |
< |
function ExtractListTable(RelationName, NewName : String; DomainFlag : Boolean) : Boolean; |
86 |
> |
function ExtractListTable(RelationName, NewName: String; DomainFlag: Boolean): Boolean; |
87 |
|
procedure ExtractListView (ViewName : String); |
88 |
|
procedure ListData(ObjectName : String); |
89 |
|
procedure ListRoles(ObjectName : String = ''); |
90 |
|
procedure ListGrants; |
91 |
|
procedure ListProcs(ProcedureName : String = ''); |
92 |
|
procedure ListAllTables(flag : Boolean); |
93 |
< |
procedure ListTriggers(ObjectName : String = ''; ExtractType : TExtractType = etTrigger); |
93 |
> |
procedure ListTriggers(AlterTrigger, IncludeBody: boolean; ObjectName : String = ''; ExtractType : TExtractType = etTrigger); |
94 |
|
procedure ListCheck(ObjectName : String = ''; ExtractType : TExtractType = etCheck); |
95 |
|
function PrintSet(var Used : Boolean) : String; |
96 |
|
procedure ListCreateDb(TargetDb : String = ''); |
135 |
|
PrivString : String; |
136 |
|
end; |
137 |
|
|
138 |
< |
TSQLTypes = Array[0..13] of TSQLType; |
138 |
> |
TSQLTypes = Array[0..14] of TSQLType; |
139 |
|
|
140 |
|
const |
141 |
|
|
169 |
|
(SqlType : blr_sql_time; TypeName : 'TIME'), { NTX: keyword } |
170 |
|
(SqlType : blr_sql_date; TypeName : 'DATE'), { NTX: keyword } |
171 |
|
(SqlType : blr_timestamp; TypeName : 'TIMESTAMP'), { NTX: keyword } |
172 |
< |
(SqlType : blr_int64; TypeName : 'INT64')); |
172 |
> |
(SqlType : blr_int64; TypeName : 'INT64'), |
173 |
> |
(SqlType : blr_bool; TypeName : 'BOOLEAN')); |
174 |
|
|
175 |
|
SubTypes : Array[0..8] of String = ( |
176 |
|
'UNKNOWN', { NTX: keyword } |
183 |
|
'TRANSACTION_DESCRIPTION', { NTX: keyword } |
184 |
|
'EXTERNAL_FILE_DESCRIPTION'); { NTX: keyword } |
185 |
|
|
166 |
– |
TriggerTypes : Array[0..6] of String = ( |
167 |
– |
'', |
168 |
– |
'BEFORE INSERT', { NTX: keyword } |
169 |
– |
'AFTER INSERT', { NTX: keyword } |
170 |
– |
'BEFORE UPDATE', { NTX: keyword } |
171 |
– |
'AFTER UPDATE', { NTX: keyword } |
172 |
– |
'BEFORE DELETE', { NTX: keyword } |
173 |
– |
'AFTER DELETE'); { NTX: keyword } |
174 |
– |
|
186 |
|
IntegralSubtypes : Array[0..2] of String = ( |
187 |
|
'UNKNOWN', { Defined type, NTX: keyword } |
188 |
|
'NUMERIC', { NUMERIC, NTX: keyword } |
233 |
|
|
234 |
|
implementation |
235 |
|
|
236 |
+ |
uses FBMessages; |
237 |
+ |
|
238 |
|
const |
239 |
|
NEWLINE = #13#10; |
240 |
|
TERM = ';'; |
278 |
|
qryArray : TIBSQL; |
279 |
|
begin |
280 |
|
qryArray := TIBSQL.Create(FDatabase); |
281 |
< |
Result := '['; |
281 |
> |
Result := ''; |
282 |
|
qryArray.SQL.Add(ArraySQL); |
283 |
|
qryArray.Params.ByName('FieldName').AsString := FieldName; |
284 |
|
qryArray.ExecQuery; |
285 |
|
|
286 |
|
{ Format is [lower:upper, lower:upper,..] } |
287 |
|
|
288 |
< |
while not qryArray.Eof do |
288 |
> |
if not qryArray.Eof then |
289 |
|
begin |
290 |
< |
if (qryArray.FieldByName('RDB$DIMENSION').AsInteger > 0) then |
291 |
< |
Result := Result + ', '; |
292 |
< |
Result := Result + qryArray.FieldByName('RDB$LOWER_BOUND').AsString + ':' + |
293 |
< |
qryArray.FieldByName('RDB$UPPER_BOUND').AsString; |
294 |
< |
qryArray.Next; |
290 |
> |
Result := '['; |
291 |
> |
while not qryArray.Eof do |
292 |
> |
begin |
293 |
> |
if (qryArray.FieldByName('RDB$DIMENSION').AsInteger > 0) then |
294 |
> |
Result := Result + ', '; |
295 |
> |
Result := Result + qryArray.FieldByName('RDB$LOWER_BOUND').AsString + ':' + |
296 |
> |
qryArray.FieldByName('RDB$UPPER_BOUND').AsString; |
297 |
> |
qryArray.Next; |
298 |
> |
end; |
299 |
> |
Result := Result + '] '; |
300 |
|
end; |
301 |
|
|
284 |
– |
Result := Result + '] '; |
302 |
|
qryArray.Free; |
303 |
|
|
304 |
|
end; |
338 |
|
end; |
339 |
|
|
340 |
|
FMetaData.Add(Format('SET SQL DIALECT %d;', [FDatabase.SQLDialect])); |
341 |
+ |
FMetaData.Add('SET AUTODDL ON;'); |
342 |
|
FMetaData.Add(''); |
343 |
|
|
344 |
|
if not FTransaction.Active then |
365 |
|
ListViews; |
366 |
|
ListCheck; |
367 |
|
ListException; |
368 |
+ |
ListTriggers(false,false); |
369 |
|
ListProcs; |
370 |
< |
ListTriggers; |
370 |
> |
ListTriggers(true,true); |
371 |
|
ListGrants; |
372 |
|
end; |
373 |
|
|
389 |
|
domain_flag -- extract needed domains before the table } |
390 |
|
|
391 |
|
function TIBExtract.ExtractListTable(RelationName, NewName: String; |
392 |
< |
DomainFlag: Boolean) : Boolean; |
392 |
> |
DomainFlag: Boolean): Boolean; |
393 |
|
const |
394 |
|
TableListSQL = |
395 |
|
'SELECT * FROM RDB$RELATIONS REL JOIN RDB$RELATION_FIELDS RFR ON ' + {Do Not Localize} |
416 |
|
' RELC.RDB$RELATION_NAME = :RELATIONNAME ' + |
417 |
|
'ORDER BY RELC.RDB$CONSTRAINT_NAME'; |
418 |
|
|
419 |
+ |
GetGeneratorSQL = |
420 |
+ |
'SELECT * FROM RDB$GENERATORS WHERE RDB$GENERATOR_NAME = :GENERATOR'; |
421 |
+ |
|
422 |
|
var |
423 |
|
Collation, CharSetId : integer; |
424 |
|
i : integer; |
425 |
|
ColList, Column, Constraint : String; |
426 |
|
SubType : integer; |
427 |
|
IntChar : integer; |
428 |
< |
qryTables, qryPrecision, qryConstraints, qryRelConstraints : TIBSQL; |
428 |
> |
qryTables, qryPrecision, qryConstraints, qryRelConstraints, qryGenerators : TIBSQL; |
429 |
|
PrecisionKnown, ValidRelation : Boolean; |
430 |
|
FieldScale, FieldType : Integer; |
431 |
+ |
CreateTable: string; |
432 |
+ |
TableType: integer; |
433 |
|
begin |
434 |
|
Result := true; |
435 |
|
ColList := ''; |
442 |
|
qryPrecision := TIBSQL.Create(FDatabase); |
443 |
|
qryConstraints := TIBSQL.Create(FDatabase); |
444 |
|
qryRelConstraints := TIBSQL.Create(FDatabase); |
445 |
+ |
qryGenerators := TIBSQL.Create(FDatabase); |
446 |
|
try |
447 |
|
qryTables.SQL.Add(TableListSQL); |
448 |
|
qryTables.Params.ByName('RelationName').AsString := RelationName; |
450 |
|
qryPrecision.SQL.Add(PrecisionSQL); |
451 |
|
qryConstraints.SQL.Add(ConstraintSQL); |
452 |
|
qryRelConstraints.SQL.Add(RelConstraintsSQL); |
453 |
+ |
qryGenerators.SQL.Add(GetGeneratorSQL); |
454 |
|
if not qryTables.Eof then |
455 |
|
begin |
456 |
|
ValidRelation := true; |
457 |
+ |
TableType := qryTables.FieldByName('RDB$RELATION_TYPE').AsInteger; |
458 |
|
if (not qryTables.FieldByName('RDB$OWNER_NAME').IsNull) and |
459 |
|
(Trim(qryTables.FieldByName('RDB$OWNER_NAME').AsString) <> '') then |
460 |
|
FMetaData.Add(Format('%s/* Table: %s, Owner: %s */%s', |
461 |
|
[NEWLINE, RelationName, |
462 |
|
qryTables.FieldByName('RDB$OWNER_NAME').AsString, NEWLINE])); |
463 |
+ |
if TableType > 3 then |
464 |
+ |
CreateTable := 'CREATE GLOBAL TEMPORARY TABLE' |
465 |
+ |
else |
466 |
+ |
CreateTable := 'CREATE TABLE'; |
467 |
|
if NewName <> '' then |
468 |
< |
FMetaData.Add(Format('CREATE TABLE %s ', [QuoteIdentifier(FDatabase.SQLDialect,NewName)])) |
468 |
> |
FMetaData.Add(Format('%s %s ', [CreateTable,QuoteIdentifier(FDatabase.SQLDialect,NewName)])) |
469 |
|
else |
470 |
< |
FMetaData.Add(Format('CREATE TABLE %s ', [QuoteIdentifier(FDatabase.SQLDialect,RelationName)])); |
470 |
> |
FMetaData.Add(Format('%s %s ', [CreateTable,QuoteIdentifier(FDatabase.SQLDialect,RelationName)])); |
471 |
|
if not qryTables.FieldByName('RDB$EXTERNAL_FILE').IsNull then |
472 |
|
FMetaData.Add(Format('EXTERNAL FILE %s ', |
473 |
|
[QuotedStr(qryTables.FieldByName('RDB$EXTERNAL_FILE').AsString)])); |
569 |
|
|
570 |
|
{ Catch arrays after printing the type } |
571 |
|
|
572 |
< |
if not qryTables.FieldByName('RDB$DIMENSIONS').IsNull then |
573 |
< |
Column := column + GetArrayField(qryTables.FieldByName('RDB$FIELD_NAME').AsString); |
572 |
> |
if not qryTables.FieldByName('RDB$DIMENSIONS').IsNull and (qryTables.FieldByName('RDB$DIMENSIONS').AsInteger > 0) then |
573 |
> |
Column := column + GetArrayField(qryTables.FieldByName('RDB$FIELD_SOURCE').AsString); |
574 |
|
|
575 |
|
if FieldType = blr_blob then |
576 |
|
begin |
601 |
|
end; |
602 |
|
end; |
603 |
|
|
604 |
+ |
{Firebird 3 introduces IDENTITY columns. We need to check for them here} |
605 |
+ |
if qryTables.HasField('RDB$GENERATOR_NAME') then |
606 |
+ |
begin |
607 |
+ |
qryGenerators.ParamByName('GENERATOR').AsString := qryTables.FieldByName('RDB$GENERATOR_NAME').AsString; |
608 |
+ |
qryGenerators.ExecQuery; |
609 |
+ |
if not qryGenerators.Eof then |
610 |
+ |
begin |
611 |
+ |
Column := Column + Format(' GENERATED BY DEFAULT AS IDENTITY START WITH %d', |
612 |
+ |
[qryGenerators.FieldByName('RDB$INITIAL_VALUE').AsInteger]); |
613 |
+ |
end; |
614 |
+ |
qryGenerators.Close; |
615 |
+ |
end; |
616 |
+ |
|
617 |
|
{ Handle defaults for columns } |
618 |
|
{ Originally This called PrintMetadataTextBlob, |
619 |
|
should no longer need } |
700 |
|
qryRelConstraints.Next; |
701 |
|
end; |
702 |
|
if ValidRelation then |
703 |
< |
FMetaData.Add(')' + Term); |
703 |
> |
begin |
704 |
> |
FMetaData.Add(') '); |
705 |
> |
if TableType = 4 then |
706 |
> |
FMetaData.Add('ON COMMIT PRESERVE ROWS '); |
707 |
> |
FMetaData.Add(Term); |
708 |
> |
end; |
709 |
|
finally |
710 |
|
qryTables.Free; |
711 |
|
qryPrecision.Free; |
712 |
|
qryConstraints.Free; |
713 |
|
qryRelConstraints.Free; |
714 |
+ |
qryGenerators.Free; |
715 |
|
end; |
716 |
|
end; |
717 |
|
|
785 |
|
CharSetSQL : TIBSQL; |
786 |
|
DidActivate : Boolean; |
787 |
|
begin |
788 |
+ |
Result := ''; |
789 |
|
if not FTransaction.Active then |
790 |
|
begin |
791 |
|
FTransaction.StartTransaction; |
842 |
|
Functional description |
843 |
|
returns the list of columns in an index. } |
844 |
|
|
845 |
< |
function TIBExtract.GetIndexSegments(IndexName: String): String; |
845 |
> |
function TIBExtract.GetIndexSegments(indexname: String): String; |
846 |
|
const |
847 |
|
IndexNamesSQL = |
848 |
|
'SELECT * FROM RDB$INDEX_SEGMENTS SEG ' + |
879 |
|
Result := FTransaction; |
880 |
|
end; |
881 |
|
|
882 |
+ |
function TIBExtract.GetTriggerType(TypeID: integer): string; |
883 |
+ |
var separator: string; |
884 |
+ |
begin |
885 |
+ |
if TypeID and $2000 <> 0 then |
886 |
+ |
{database trigger} |
887 |
+ |
begin |
888 |
+ |
Result := 'ON '; |
889 |
+ |
case TypeID of |
890 |
+ |
$2000: |
891 |
+ |
Result += 'CONNECT '; |
892 |
+ |
$2001: |
893 |
+ |
Result += 'DISCONNECT '; |
894 |
+ |
$2002: |
895 |
+ |
Result +='TRANSACTION START '; |
896 |
+ |
$2003: |
897 |
+ |
Result += 'TRANSACTION COMMIT '; |
898 |
+ |
$2004: |
899 |
+ |
Result += 'TRANSACTION ROLLBACK '; |
900 |
+ |
end; |
901 |
+ |
end |
902 |
+ |
else |
903 |
+ |
begin |
904 |
+ |
Inc(TypeID); |
905 |
+ |
if TypeID and $01 <> 0 then |
906 |
+ |
Result := 'AFTER ' |
907 |
+ |
else |
908 |
+ |
Result := 'BEFORE '; |
909 |
+ |
TypeID := TypeID shr 1; |
910 |
+ |
separator := ''; |
911 |
+ |
repeat |
912 |
+ |
Result += separator; |
913 |
+ |
separator := ' or '; |
914 |
+ |
case TypeID and $03 of |
915 |
+ |
1: |
916 |
+ |
Result += 'INSERT'; |
917 |
+ |
2: |
918 |
+ |
Result += 'UPDATE'; |
919 |
+ |
3: |
920 |
+ |
Result += 'DELETE'; |
921 |
+ |
end; |
922 |
+ |
TypeID := TypeID shr 2; |
923 |
+ |
until TypeID = 0; |
924 |
+ |
end; |
925 |
+ |
end; |
926 |
+ |
|
927 |
|
{ ListAllGrants |
928 |
|
Functional description |
929 |
|
Print the permissions on all user tables. |
1128 |
|
Lists triggers in general on non-system |
1129 |
|
tables with sql source only. } |
1130 |
|
|
1131 |
< |
procedure TIBExtract.ListTriggers(ObjectName : String; ExtractType : TExtractType); |
1131 |
> |
procedure TIBExtract.ListTriggers(AlterTrigger, IncludeBody: boolean; |
1132 |
> |
ObjectName: String; ExtractType: TExtractType); |
1133 |
|
const |
1134 |
|
{ Query gets the trigger info for non-system triggers with |
1135 |
|
source that are not part of an SQL constraint } |
1215 |
|
if qryTriggers.FieldByName('RDB$FLAGS').AsInteger <> 1 then |
1216 |
|
SList.Add('/* '); |
1217 |
|
|
1218 |
< |
SList.Add(Format('CREATE TRIGGER %s FOR %s %s%s %s POSITION %d', |
1218 |
> |
if AlterTrigger then |
1219 |
> |
SList.Add(Format('Alter TRIGGER %s ',[QuoteIdentifier(FDatabase.SQLDialect, TriggerName)])) |
1220 |
> |
else |
1221 |
> |
SList.Add(Format('CREATE TRIGGER %s FOR %s %s%s %s POSITION %d', |
1222 |
|
[QuoteIdentifier(FDatabase.SQLDialect, TriggerName), |
1223 |
|
QuoteIdentifier(FDatabase.SQLDialect, RelationName), |
1224 |
|
NEWLINE, InActive, |
1225 |
< |
TriggerTypes[qryTriggers.FieldByName('RDB$TRIGGER_TYPE').AsInteger], |
1225 |
> |
GetTriggerType(qryTriggers.FieldByName('RDB$TRIGGER_TYPE').AsInteger), |
1226 |
|
qryTriggers.FieldByName('RDB$TRIGGER_SEQUENCE').AsInteger])); |
1227 |
< |
if not qryTriggers.FieldByName('RDB$TRIGGER_SOURCE').IsNull then |
1227 |
> |
if IncludeBody and not qryTriggers.FieldByName('RDB$TRIGGER_SOURCE').IsNull then |
1228 |
|
SList.Text := SList.Text + |
1229 |
< |
qryTriggers.FieldByName('RDB$TRIGGER_SOURCE').AsString; |
1229 |
> |
qryTriggers.FieldByName('RDB$TRIGGER_SOURCE').AsString |
1230 |
> |
else |
1231 |
> |
SList.Text := SList.Text + 'AS BEGIN EXIT; END'; |
1232 |
|
SList.Add(' ' + ProcTerm + NEWLINE); |
1233 |
|
if qryTriggers.FieldByName('RDB$FLAGS').AsInteger <> 1 then |
1234 |
|
SList.Add(' */'); |
1337 |
|
CharInfoSQL = |
1338 |
|
'SELECT * FROM RDB$DATABASE DBP ' + |
1339 |
|
'WHERE NOT DBP.RDB$CHARACTER_SET_NAME IS NULL ' + |
1340 |
< |
' AND DBP.RDB$CHARACTER_SET_NAME != '' '''; |
1340 |
> |
' AND DBP.RDB$CHARACTER_SET_NAME <> '' '''; |
1341 |
|
|
1342 |
|
FilesSQL = |
1343 |
|
'select * from RDB$FILES ' + |
1354 |
|
FileFlags, FileLength, FileSequence, FileStart : Integer; |
1355 |
|
|
1356 |
|
function GetLongDatabaseInfo(DatabaseInfoCommand: Integer): LongInt; |
1255 |
– |
var |
1256 |
– |
local_buffer: array[0..IBLocalBufferLength - 1] of Char; |
1257 |
– |
length: Integer; |
1258 |
– |
_DatabaseInfoCommand: Char; |
1357 |
|
begin |
1358 |
< |
_DatabaseInfoCommand := Char(DatabaseInfoCommand); |
1359 |
< |
FDatabaseInfo.Call(isc_database_info(StatusVector, @FDatabase.Handle, 1, @_DatabaseInfoCommand, |
1360 |
< |
IBLocalBufferLength, local_buffer), True); |
1361 |
< |
length := isc_vax_integer(@local_buffer[1], 2); |
1362 |
< |
result := isc_vax_integer(@local_buffer[3], length); |
1358 |
> |
with Database.Attachment.GetDBInformation([DatabaseInfoCommand]) do |
1359 |
> |
if (Count > 0) and (Items[0].GetItemType = DatabaseInfoCommand) then |
1360 |
> |
Result := Items[0].AsInteger |
1361 |
> |
else |
1362 |
> |
IBError(ibxeUnexpectedDatabaseInfoResp,[nil]); |
1363 |
|
end; |
1364 |
|
|
1365 |
|
begin |
1366 |
< |
NoDb := FALSE; |
1366 |
> |
NoDb := FALSE; |
1367 |
|
First := TRUE; |
1368 |
|
FirstFile := TRUE; |
1369 |
|
HasWal := FALSE; |
1385 |
|
qryDB.SQL.Text := CharInfoSQL; |
1386 |
|
qryDB.ExecQuery; |
1387 |
|
|
1388 |
< |
Buffer := Format(' DEFAULT CHARACTER SET %s', |
1389 |
< |
[qryDB.FieldByName('RDB$CHARACTER_SET_NAME').AsString]); |
1388 |
> |
if not qryDB.EOF then |
1389 |
> |
Buffer := Format(' DEFAULT CHARACTER SET %s', |
1390 |
> |
[qryDB.FieldByName('RDB$CHARACTER_SET_NAME').AsString]); |
1391 |
|
if NoDB then |
1392 |
< |
Buffer := Buffer + ' */' |
1392 |
> |
Buffer := Buffer + Term + ' */' |
1393 |
|
else |
1394 |
|
Buffer := Buffer + Term; |
1395 |
|
FMetaData.Add(Buffer); |
1661 |
|
Result := Result + GetCharacterSets(qryDomains.FieldByName('RDB$CHARACTER_SET_ID').AsInteger, |
1662 |
|
0, FALSE); |
1663 |
|
if not qryDomains.FieldByName('RDB$DIMENSIONS').IsNull then |
1664 |
< |
Result := GetArrayField(FieldName); |
1664 |
> |
Result := GetArrayField(qryDomains.FieldByName('RDB$FIELD_SOURCE').AsString); |
1665 |
|
|
1666 |
|
if not qryDomains.FieldByName('RDB$DEFAULT_SOURCE').IsNull then |
1667 |
|
Result := Result + Format('%s%s %s', [NEWLINE, TAB, |
1988 |
|
procedure TIBExtract.ListFunctions(FunctionName : String = ''); |
1989 |
|
const |
1990 |
|
FunctionSQL = |
1991 |
< |
'SELECT * FROM RDB$FUNCTIONS ' + |
1991 |
> |
'SELECT * FROM RDB$FUNCTIONS WHERE RDB$SYSTEM_FLAG = 0 ' + |
1992 |
|
'ORDER BY RDB$FUNCTION_NAME'; |
1993 |
|
|
1994 |
|
FunctionNameSQL = |
2226 |
|
qryGenerator.Next; |
2227 |
|
continue; |
2228 |
|
end; |
2229 |
< |
FMetaData.Add(Format('CREATE GENERATOR %s%s', |
2229 |
> |
FMetaData.Add(Format('CREATE SEQUENCE %s%s', |
2230 |
|
[QuoteIdentifier(FDatabase.SQLDialect, GenName), |
2231 |
|
Term])); |
2232 |
|
qryGenerator.Next; |
2539 |
|
if etCheck in ExtractTypes then |
2540 |
|
ListCheck(ObjectName, etTable); |
2541 |
|
if etTrigger in ExtractTypes then |
2542 |
< |
ListTriggers(ObjectName, etTable); |
2542 |
> |
ListTriggers(false,true,ObjectName, etTable); |
2543 |
|
if etGrant in ExtractTypes then |
2544 |
|
ShowGrants(ObjectName, Term); |
2545 |
|
if etData in ExtractTypes then |
2548 |
|
else |
2549 |
|
ListAllTables(true); |
2550 |
|
end; |
2551 |
< |
eoView : ListViews(ObjectName); |
2551 |
> |
eoView : |
2552 |
> |
begin |
2553 |
> |
ListViews(ObjectName); |
2554 |
> |
if ObjectName <> '' then |
2555 |
> |
begin |
2556 |
> |
if etTrigger in ExtractTypes then |
2557 |
> |
ListTriggers(false,true,ObjectName, etTable); |
2558 |
> |
end; |
2559 |
> |
end; |
2560 |
|
eoProcedure : ListProcs(ObjectName); |
2561 |
|
eoFunction : ListFunctions(ObjectName); |
2562 |
|
eoGenerator : ListGenerators(ObjectName); |
2565 |
|
eoRole : ListRoles(ObjectName); |
2566 |
|
eoTrigger : |
2567 |
|
if etTable in ExtractTypes then |
2568 |
< |
ListTriggers(ObjectName, etTable) |
2568 |
> |
ListTriggers(false,true,ObjectName, etTable) |
2569 |
|
else |
2570 |
< |
ListTriggers(ObjectName); |
2570 |
> |
ListTriggers(false,true,ObjectName); |
2571 |
|
eoForeign : |
2572 |
|
if etTable in ExtractTypes then |
2573 |
|
ListForeign(ObjectName, etTable) |
2652 |
|
It must extract granted privileges on tables/views to users, |
2653 |
|
- these may be compound, so put them on the same line. |
2654 |
|
Grant execute privilege on procedures to users |
2655 |
< |
Grant various privilegs to procedures. |
2655 |
> |
Grant various privileges to procedures. |
2656 |
|
All privileges may have the with_grant option set. } |
2657 |
|
|
2658 |
< |
procedure TIBExtract.ShowGrants(MetaObject, Terminator: String); |
2658 |
> |
procedure TIBExtract.ShowGrants(MetaObject: String; Terminator: String); |
2659 |
|
const |
2660 |
|
{ This query only finds tables, eliminating owner privileges } |
2661 |
|
OwnerPrivSQL = |
2705 |
|
var |
2706 |
|
i : Integer; |
2707 |
|
begin |
2708 |
+ |
Result := ''; |
2709 |
|
for i := Low(PrivTypes) to High(PrivTypes) do |
2710 |
|
begin |
2711 |
|
if (cflags and PrivTypes[i].PrivFlag) <> 0 then |
3133 |
|
while not qrySelect.Eof do |
3134 |
|
begin |
3135 |
|
Line := 'INSERT INTO ' + QuoteIdentifier(FDatabase.SQLDialect, ObjectName) + ' ('; |
3136 |
< |
for i := 0 to qrySelect.Current.Count - 1 do |
3136 |
> |
for i := 0 to qrySelect.FieldCount - 1 do |
3137 |
|
if (qrySelect.Fields[i].SQLType <> SQL_ARRAY) and |
3138 |
|
(qrySelect.Fields[i].SQLType <> SQL_BLOB) then |
3139 |
|
begin |
3140 |
|
Line := Line + QuoteIdentifier(FDatabase.SQLDialect, qrySelect.Fields[i].Name); |
3141 |
< |
if i <> (qrySelect.Current.Count - 1) then |
3141 |
> |
if i <> (qrySelect.FieldCount - 1) then |
3142 |
|
Line := Line + ', '; |
3143 |
|
end; |
3144 |
|
Line := Line + ') VALUES ('; |
3145 |
< |
for i := 0 to qrySelect.Current.Count - 1 do |
3145 |
> |
for i := 0 to qrySelect.FieldCount - 1 do |
3146 |
|
begin |
3147 |
|
if qrySelect.Fields[i].IsNull and |
3148 |
|
(qrySelect.Fields[i].SQLType <> SQL_ARRAY) and |
3149 |
|
(qrySelect.Fields[i].SQLType <> SQL_BLOB) then |
3150 |
|
begin |
3151 |
|
Line := Line + 'NULL'; |
3152 |
< |
if i <> (qrySelect.Current.Count - 1) then |
3152 |
> |
if i <> (qrySelect.FieldCount - 1) then |
3153 |
|
Line := Line + ', '; |
3154 |
|
end |
3155 |
|
else |
3158 |
|
SQL_TYPE_TIME, SQL_TIMESTAMP : |
3159 |
|
begin |
3160 |
|
Line := Line + QuotedStr(qrySelect.Fields[i].AsString); |
3161 |
< |
if i <> (qrySelect.Current.Count - 1) then |
3161 |
> |
if i <> (qrySelect.FieldCount - 1) then |
3162 |
|
Line := Line + ', '; |
3163 |
|
end; |
3164 |
|
SQL_SHORT, SQL_LONG, SQL_INT64, |
3165 |
< |
SQL_DOUBLE, SQL_FLOAT, SQL_D_FLOAT: |
3165 |
> |
SQL_DOUBLE, SQL_FLOAT, SQL_D_FLOAT, SQL_BOOLEAN: |
3166 |
|
begin |
3167 |
|
Line := Line + qrySelect.Fields[i].AsString; |
3168 |
< |
if i <> (qrySelect.Current.Count - 1) then |
3168 |
> |
if i <> (qrySelect.FieldCount - 1) then |
3169 |
|
Line := Line + ', '; |
3170 |
|
end; |
3171 |
|
SQL_ARRAY, SQL_BLOB : ; |
3185 |
|
procedure TIBExtract.ListRoles(ObjectName: String); |
3186 |
|
const |
3187 |
|
RolesSQL = |
3188 |
< |
'select * from RDB$ROLES ' + |
3188 |
> |
'select * from RDB$ROLES WHERE RDB$SYSTEM_FLAG = 0 ' + |
3189 |
|
'order by RDB$ROLE_NAME'; |
3190 |
|
|
3191 |
|
RolesByNameSQL = |