Переглянути джерело

Fields GUI query: add support for detecting domain based datatypes, array datatyes. Cosmetic: some renames, updated todo list.

Reinier Olislagers 11 роки тому
батько
коміт
24a375e6e4
8 змінених файлів з 77 додано та 74 видалено
  1. 0 1
      edittable.pas
  2. 36 37
      main.pas
  3. 4 2
      newgen.pas
  4. 1 1
      newtable.pas
  5. 0 1
      querywindow.pas
  6. 20 20
      scriptdb.pas
  7. 14 11
      systables.pas
  8. 2 1
      topologicalsort.pas

+ 0 - 1
edittable.pas

@@ -105,7 +105,6 @@ begin
     sqlTrans:= Rec.SQLTrans;
     sqEditTable.DataBase:= ibConnection;
   end;
-  //todo: deal with quoted identifiers in ATableName here and elsewhere
   sqEditTable.SQL.Text:= 'select * from ' + ATableName;
   sqEditTable.Open; // need to have open query in order to access fields below
 

+ 36 - 37
main.pas

@@ -13,7 +13,7 @@ uses
 
 const
   // Some field types used in e.g. RDB$FIELDS
-  //todo: perhaps move to enumeration with fixed constant values
+  //todo (low priority): perhaps move to enumeration with fixed constant values
   BlobType = 261;
   CharType = 14;
   CStringType = 40; // probably null-terminated string used for UDFs
@@ -272,7 +272,7 @@ var
   fmMain: TfmMain;
 
 // Tries to guess if an RDB$RELATION_FIELDS.RDB$FIELD_SOURCE domain name for a column is system-generated.
-function SystemGeneratedFieldDomain(FieldSource: string): boolean;
+function IsFieldDomainSystemGenerated(FieldSource: string): boolean;
 
 implementation
 
@@ -285,7 +285,7 @@ uses CreateDb, ViewView, ViewTrigger, ViewSProc, ViewGen, NewTable, NewGen,
      PermissionManage, CopyTable, About, NewEditField, dbInfo, Comparison;
 
 
-function SystemGeneratedFieldDomain(FieldSource: string): boolean;
+function IsFieldDomainSystemGenerated(FieldSource: string): boolean;
 begin
   // Unfortunately there does not seem to be a way to search the system tables to find out
   // if the constraint name is system-generated
@@ -1244,11 +1244,11 @@ begin
       clbFields.Clear;
       while not EOF do
       begin
-        if (not(FieldByName('Field_Type_Int').AsInteger in [CStringType,CharType,VarCharType])) or
+        if (not(FieldByName('field_type_int').AsInteger in [CStringType,CharType,VarCharType])) or
          (Trim(FieldByName('Field_Collation').AsString) = 'NONE') or
          (FieldByName('Field_Collation').IsNull) then
         begin
-          if (FieldByName('Field_Type_Int').AsInteger <> BlobType) then
+          if (FieldByName('field_type_int').AsInteger <> BlobType) then
             clbFields.Items.Add(FieldByName('Field_Name').AsString);
         end;
         Next;
@@ -1530,7 +1530,6 @@ var
   i: Integer;
   SizeStarted: Boolean;
 begin
-  //todo: verify if this still works after the scripting fixes
   SizeStarted:= False;
   if (Pos('(', Body) > 0) and (Pos('(', Body) < Pos(')', Body)) then
   for i:= 1 to Length(Body) do
@@ -1960,8 +1959,8 @@ begin
     while not EOF do
     begin
       Skipped:= False;
-      if (FieldByName('Computed_Source').AsString = '') and { any of the following conditions }
-          ((not(FieldByName('Field_Type_Int').AsInteger in [CStringType,CharType,VarCharType])) or
+      if (FieldByName('computed_source').AsString = '') and { any of the following conditions }
+          ((not(FieldByName('field_type_int').AsInteger in [CStringType,CharType,VarCharType])) or
           (Trim(FieldByName('Field_Collation').AsString) = 'NONE') or
           (FieldByName('Field_Collation').IsNull)) then
       begin
@@ -1969,12 +1968,12 @@ begin
         ParamNames:= ParamNames + ':' + Trim(FieldByName('Field_Name').AsString);
         FieldLine:= Trim(FieldByName('Field_Name').AsString) + ' ';
         FieldLine:= FieldLine +
-          GetFBTypeName(SQLQuery1.FieldByName('Field_Type_Int').AsInteger,
+          GetFBTypeName(SQLQuery1.FieldByName('field_type_int').AsInteger,
             SQLQuery1.FieldByName('field_sub_type').AsInteger,
             SQLQuery1.FieldByName('field_length').AsInteger,
             SQLQuery1.FieldByName('field_precision').AsInteger,
             SQLQuery1.FieldByName('field_scale').AsInteger);
-        if FieldByName('Field_Type_Int').AsInteger in [CStringType,CharType,VarCharType] then
+        if FieldByName('field_type_int').AsInteger in [CStringType,CharType,VarCharType] then
           FieldLine:= FieldLine + '(' + FieldByName('CharacterLength').AsString + ') ';
       end
       else
@@ -2192,20 +2191,20 @@ begin
     while not EOF do
     begin
       Skipped:= False;
-      if (FieldByName('Computed_Source').AsString = '') and {any of the following conditions }
-         ((not(FieldByName('Field_Type_Int').AsInteger in [CStringType,CharType,VarCharType])) or
+      if (FieldByName('computed_source').AsString = '') and {any of the following conditions }
+         ((not(FieldByName('field_type_int').AsInteger in [CStringType,CharType,VarCharType])) or
          (Trim(FieldByName('Field_Collation').AsString) = 'NONE') or
          (FieldByName('Field_Collation').IsNull)) then
       begin
         AFieldName:= Trim(SQLQuery1.FieldByName('Field_Name').AsString);
         ParamAndValue:= ParamAndValue + AFieldName + ' = :' + AFieldName;
         FieldLine:= AFieldName + ' ';
-        FieldLine:= FieldLine + GetFBTypeName(SQLQuery1.FieldByName('Field_Type_Int').AsInteger,
+        FieldLine:= FieldLine + GetFBTypeName(SQLQuery1.FieldByName('field_type_int').AsInteger,
           SQLQuery1.FieldByName('field_sub_type').AsInteger,
           SQLQuery1.FieldByName('field_length').AsInteger,
           SQLQuery1.FieldByName('field_precision').AsInteger,
           SQLQuery1.FieldByName('field_scale').AsInteger);
-        if FieldByName('Field_Type_Int').AsInteger in [CStringType,CharType,VarCharType] then
+        if FieldByName('field_type_int').AsInteger in [CStringType,CharType,VarCharType] then
           FieldLine:= FieldLine + '(' + FieldByName('CharacterLength').AsString + ') ';
       end
       else
@@ -2483,12 +2482,12 @@ const
     ' f.RDB$CHARACTER_LENGTH AS characterlength, ' + {character_length seems a reserved word}
     ' f.RDB$FIELD_PRECISION AS field_precision, ' +
     ' f.RDB$FIELD_SCALE AS field_scale, ' +
-    ' f.RDB$FIELD_TYPE as Field_Type_Int, ' +
+    ' f.RDB$FIELD_TYPE as field_type_int, ' +
     ' f.RDB$FIELD_SUB_TYPE AS field_sub_type, ' +
     ' coll.RDB$COLLATION_NAME AS field_collation, ' +
     ' cset.RDB$CHARACTER_SET_NAME AS field_charset, ' +
-    ' f.RDB$COMPUTED_Source AS Computed_Source, ' +
-    ' dim.RDB$UPPER_BOUND AS Array_Upper_Bound, ' +
+    ' f.RDB$computed_source AS computed_source, ' +
+    ' dim.RDB$UPPER_BOUND AS array_upper_bound, ' +
     ' r.RDB$FIELD_SOURCE AS field_source ' {domain if field based on domain}+
     ' FROM RDB$RELATION_FIELDS r ' +
     ' LEFT JOIN RDB$FIELDS f ON r.RDB$FIELD_SOURCE = f.RDB$FIELD_NAME ' +
@@ -2767,14 +2766,16 @@ begin
     SetConnection(DatabaseIndex);
 
     SQLQuery1.Close;
-    SQLQuery1.SQL.Text:= 'SELECT * FROM RDB$FUNCTIONS WHERE RDB$FUNCTION_NAME = ''' + UDFName + '''';
+    SQLQuery1.SQL.Text:= Format('SELECT * FROM RDB$FUNCTIONS WHERE RDB$FUNCTION_NAME = ''%s'' ',[UDFName]);
     SQLQuery1.Open;
     ModuleName:= Trim(SQLQuery1.FieldByName('RDB$MODULE_NAME').AsString);
     EntryPoint:= Trim(SQLQuery1.FieldByName('RDB$ENTRYPOINT').AsString);
 
+    //todo: (low priority) probably domain based datatypes should be supported for input and output params in UDF declarations
+
     // input Params
     SQLQuery1.Close;
-    SQLQuery1.SQL.Text:= 'SELECT * FROM RDB$FUNCTION_ARGUMENTS where RDB$FUNCTION_Name = ''' +
+    SQLQuery1.SQL.Text:= 'SELECT * FROM RDB$FUNCTION_ARGUMENTS WHERE RDB$FUNCTION_Name = ''' +
      UDFName + ''' and RDB$MECHANISM = 1';
     SQLQuery1.Open;
     Params:= '';
@@ -2794,11 +2795,9 @@ begin
     SQLQuery1.Close;
     Params:= Params + ')' + LineEnding + LineEnding + 'Returns ';
 
-    {todo: return values can't be determined}
-
     // Result Params
-    SQLQuery1.SQL.Text:= 'SELECT * FROM RDB$FUNCTION_ARGUMENTS where RDB$FUNCTION_Name = ''' +
-     UDFName + ''' and RDB$MECHANISM = 0';
+    SQLQuery1.SQL.Text:= Format('SELECT * FROM RDB$FUNCTION_ARGUMENTS '+
+      'where RDB$FUNCTION_Name = ''%s'' and RDB$MECHANISM = 0',[UDFName]);
     SQLQuery1.Open;
     while not SQLQuery1.EOF do
     begin
@@ -2807,7 +2806,7 @@ begin
         SQLQuery1.FieldByName('RDB$FIELD_LENGTH').AsInteger,
         SQLQuery1.FieldByName('RDB$FIELD_PRECISION').AsInteger,
         SQLQuery1.FieldByName('RDB$FIELD_SCALE').AsInteger);
-      if SQLQuery1.FieldByName('Field_Type_Int').AsInteger in [CharType, CStringType, VarCharType] then
+      if SQLQuery1.FieldByName('field_type_int').AsInteger in [CharType, CStringType, VarCharType] then
         Params:= Params + '(' + SQLQuery1.FieldByName('RDB$Character_LENGTH').AsString + ')';
       SQLQuery1.Next;
       if not SQLQuery1.EOF then
@@ -3113,7 +3112,7 @@ begin
     with AStringGrid, SQLQuery1 do
     while not EOF do
     begin
-      if (not (FieldByName('Field_Type_Int').AsInteger in [CStringType,CharType,VarCharType])) or
+      if (not (FieldByName('field_type_int').AsInteger in [CStringType,CharType,VarCharType])) or
        (Trim(FieldByName('Field_Collation').AsString) = 'NONE') or
        (FieldByName('Field_Collation').IsNull) then
       begin
@@ -3123,7 +3122,7 @@ begin
         Cells[1, RowCount - 1]:= Trim(FieldByName('Field_Name').AsString);
 
         // Field Type
-        Cells[2, RowCount - 1]:= GetFBTypeName(FieldByName('Field_Type_Int').AsInteger,
+        Cells[2, RowCount - 1]:= GetFBTypeName(FieldByName('field_type_int').AsInteger,
           FieldByName('Field_Sub_Type').AsInteger,
           FieldByName('Field_Length').AsInteger,
           FieldByName('Field_Precision').AsInteger,
@@ -3133,18 +3132,18 @@ begin
         // Array should really be [upper_bound dim0,upperbound dim1,..]
         // but for now don't bother as arrays are not supported anyway
         // Assume dimension 0, just fill in upper bound
-        if not(FieldByName('Array_Upper_Bound').IsNull) then
+        if not(FieldByName('array_upper_bound').IsNull) then
           Cells[2, RowCount - 1]:=Cells[2, RowCount - 1] +
             ' [' +
-            SQLQuery1.FieldByName('Array_Upper_Bound').AsString +
+            SQLQuery1.FieldByName('array_upper_bound').AsString +
             ']';
 
         // Computed fields (Calculated)
-        if FieldByName('Computed_Source').AsString <> '' then
-          Cells[2, RowCount - 1]:= FieldByName('Computed_Source').AsString;
+        if FieldByName('computed_source').AsString <> '' then
+          Cells[2, RowCount - 1]:= FieldByName('computed_source').AsString;
 
         // Field Size
-        if FieldByName('Field_Type_Int').AsInteger in [CharType,CStringType,VarCharType] then
+        if FieldByName('field_type_int').AsInteger in [CharType,CStringType,VarCharType] then
           Cells[3, RowCount - 1]:= FieldByName('CharacterLength').AsString
         else
           Cells[3, RowCount - 1]:= FieldByName('Field_Length').AsString;
@@ -3269,17 +3268,17 @@ begin
       while not EOF do
       begin
         AFieldName:= Trim(FieldByName('Field_Name').AsString);
-        if (not (FieldByName('Field_Type_Int').AsInteger in [CStringType,CharType,VarCharType])) or
+        if (not (FieldByName('field_type_int').AsInteger in [CStringType,CharType,VarCharType])) or
          (Trim(FieldByName('Field_Collation').AsString) = 'NONE') or
          (FieldByName('Field_Collation').IsNull) then
          begin
-           if (FieldByName('Field_Type_Int').AsInteger) in [CharType, CStringType, VarCharType] then
+           if (FieldByName('field_type_int').AsInteger) in [CharType, CStringType, VarCharType] then
              LenStr:= FieldByName('CharacterLength').AsString
            else
              LenStr:= FieldByName('Field_Length').AsString;
 
           FieldTitle:= AFieldName + '   ' +
-            GetFBTypeName(SQLQuery1.FieldByName('Field_Type_Int').AsInteger,
+            GetFBTypeName(SQLQuery1.FieldByName('field_type_int').AsInteger,
               SQLQuery1.FieldByName('field_sub_type').AsInteger,
               SQLQuery1.FieldByName('field_length').AsInteger,
               SQLQuery1.FieldByName('field_precision').AsInteger,
@@ -4151,7 +4150,7 @@ function TfmMain.GetFBTypeName(Index: Integer;
   Precision: integer=-1; Scale: integer=-1
   ): string;
 begin
-  //todo (low priority): add Firebird 3.0 beta BOOLEAN datatype number
+  //todo: (low priority) add Firebird 3.0 beta BOOLEAN datatype number
   case Index of
     // See also
     // http://firebirdsql.org/manual/migration-mssql-data-types.html
@@ -4161,11 +4160,11 @@ begin
     CStringType : Result:= 'CSTRING'; // probably null-terminated string used for UDFs
     12 : Result:= 'DATE';
     11 : Result:= 'D_FLOAT';
-    16 : Result:= 'BIGINT'; // Probably int64 in Interbase. Further processed below
+    16 : Result:= 'BIGINT'; // Further processed below
     27 : Result:= 'DOUBLE PRECISION';
     10 : Result:= 'FLOAT';
     8  : Result:= 'INTEGER'; // further processed below
-    9  : Result:= 'QUAD';
+    9  : Result:= 'QUAD'; // unknown what this is=> see IB6 Language Reference RDB$FIELD_TYPE
     7  : Result:= 'SMALLINT'; // further processed below
     13 : Result:= 'TIME';
     35 : Result:= 'TIMESTAMP';

+ 4 - 2
newgen.pas

@@ -96,12 +96,14 @@ begin
     cbFields.Clear;
     while not fmMain.SQLQuery1.EOF do
     begin
-      FType:= fmMain.GetFBTypeName(fmMain.SQLQuery1.FieldByName('Field_Type_Int').AsInteger,
+      FType:= fmMain.GetFBTypeName(fmMain.SQLQuery1.FieldByName('field_type_int').AsInteger,
         fmMain.SQLQuery1.FieldByName('field_sub_type').AsInteger,
         fmMain.SQLQuery1.FieldByName('field_length').AsInteger,
         fmMain.SQLQuery1.FieldByName('field_precision').AsInteger,
         fmMain.SQLQuery1.FieldByName('field_scale').AsInteger);
-      //todo: verify whether this still works. Also what about other integer types?
+
+      // Only show field name if they are numeric/suitable for generators
+      // In practice, integer type fields are probably always used
       if (FType = 'INTEGER') or (FType = 'BIGINT') or (FType = 'SMALLINT') then
         cbFields.Items.Add(Trim(fmMain.SQLQuery1.FieldByName('Field_Name').AsString));
       fmMain.SQLQuery1.Next;

+ 1 - 1
newtable.pas

@@ -280,7 +280,7 @@ begin
       List.Text:= GenerateCreateSQL(KeyField, GeneratorName);
       if cxCreateGen.Checked then
       begin;
-        //todo: move this generator/trigger creation to a utility function somewhere
+        //todo: move this generator/trigger creation to a utility function somewhere; likewise for other create/alter DDL code
         List.Add('');
         List.Add('-- Generator');
         List.Add('create generator ' + GeneratorName + ';');

+ 0 - 1
querywindow.pas

@@ -299,7 +299,6 @@ begin
       RealStartLine:= i;
       MultiComment:= False;
       Comment:= False;
-      //todo: verify check of -- regarding string literals below.
       if (i = QueryList.Count - 1) or
          ((Trim(QueryList[i + 1]) <> '') and  (Pos('/*', Trim(QueryList[i + 1])
            ) <> 1) and

+ 20 - 20
scriptdb.pas

@@ -31,14 +31,15 @@ function ScriptAllSecIndices(dbIndex: Integer; var List: TStringList): Boolean;
 
 // Scripts check constraints for all tables
 function ScriptAllCheckConstraints(dbIndex: Integer; var List: TStringList): Boolean;
-// Scripts all constraints (e.g. foreign key constraints) for tables in a database
-{ For now, seems to only cover foreign keys. Todo: verify/confirm
+// Scripts all foreign key constraints for tables in a database
+{
 There are 5 kind of constraints:
     NOT NULL
     PRIMARY KEY
     UNIQUE
     FOREIGN KEY
     CHECK
+This function only covers foreign keys; the other constraints are covered elsewhere
 }
 function ScriptAllConstraints(dbIndex: Integer; var List: TStringList): Boolean;
 function ScriptObjectPermission(dbIndex: Integer; ObjName, UserName: string; var ObjType: Integer;
@@ -57,10 +58,11 @@ implementation
 uses SysTables, Main;
 
 // Tries to guess if a constraint name is system-generated.
-{ todo: find a way to search the system tables and make sure the constraint name
-is system-generated}
-function SystemGeneratedConstraint(ConstraintName: string): boolean;
+function IsConstraintSystemGenerated(ConstraintName: string): boolean;
 begin
+  { Unfortunately there does not seem to be a way to search the system tables
+  and make sure the constraint name is system-generated - we have to guess based
+  on the name}
   result:=(pos('INTEG_',uppercase(Trim(ConstraintName)))=1);
 end;
 
@@ -72,7 +74,7 @@ var
   i: Integer;
 begin
   List.CommaText:= dmSysTables.GetDBObjectNames(dbIndex, 9, Count);
-  { todo: wrap create role RDB$Admin statement - in FB 2.5+ this role is present
+  { todo: (low priority) wrap create role RDB$Admin statement - in FB 2.5+ this role is present
   by default, in lower dbs it isn't. No way to find out in advance when writing
   a script. No support in FB yet for CREATE OR UPDATE ROLE so probably best
   to do it in execute block with error handling or
@@ -173,7 +175,6 @@ var
   CheckConstraint: string;
   DefaultValue: string;
 begin
-  //todo: script domains: add support for character set
   List.CommaText:= dmSysTables.GetDBObjectNames(dbIndex, 8, Count);
   // Get domains in dependency order (if dependencies can exist between domains)
   dmSysTables.SortDependencies(List);
@@ -225,8 +226,8 @@ begin
     while not EOF do
     begin
       Skipped:= False;
-      if (FieldByName('Computed_Source').AsString = '') and {any of the following }
-       ((not (FieldByName('Field_Type_Int').AsInteger in [CStringType,CharType,VarCharType])) or
+      if (FieldByName('computed_source').AsString = '') and {any of the following }
+       ((not (FieldByName('field_type_int').AsInteger in [CStringType,CharType,VarCharType])) or
        (Trim(FieldByName('Field_Collation').AsString) = 'NONE') or
        (FieldByName('Field_Collation').IsNull)) then
       begin
@@ -235,20 +236,20 @@ begin
 
         if (FieldByName('field_source').IsNull) or
           (trim(FieldByName('field_source').AsString)='') or
-          (SystemGeneratedFieldDomain(trim(FieldByname('field_source').AsString))) then
+          (IsFieldDomainSystemGenerated(trim(FieldByname('field_source').AsString))) then
         begin
           // Field type is not based on a domain but a standard SQL type
           // Field type
-          FieldLine:= FieldLine + fmMain.GetFBTypeName(FieldByName('Field_Type_Int').AsInteger,
+          FieldLine:= FieldLine + fmMain.GetFBTypeName(FieldByName('field_type_int').AsInteger,
             FieldByName('Field_Sub_Type').AsInteger,
             FieldByName('Field_Length').AsInteger,
             FieldByName('Field_Precision').AsInteger,
             FieldByName('Field_Scale').AsInteger);
 
-          if (FieldByName('Field_Type_Int').AsInteger) in [CharType, CStringType, VarCharType] then
+          if (FieldByName('field_type_int').AsInteger) in [CharType, CStringType, VarCharType] then
             FieldLine:= FieldLine + '(' + FieldByName('CharacterLength').AsString + ') ';
 
-          if (FieldByName('Field_Type_Int').AsInteger = BlobType) then
+          if (FieldByName('field_type_int').AsInteger = BlobType) then
           begin
             BlobSubType:= fmMain.GetBlobSubTypeName(FieldByName('Field_Sub_Type').AsInteger);
             if BlobSubType<>'' then
@@ -258,8 +259,8 @@ begin
           // Rudimentary support for array datatypes (only covers 0 dimension types):
           {todo: expand to proper array type detection (low priority as arrays are
            virtually unused}
-          if not(FieldByName('Array_Upper_Bound').IsNull) then
-            FieldLine:= FieldLine + ' [' + FieldByName('Array_Upper_Bound').AsString + '] ';
+          if not(FieldByName('array_upper_bound').IsNull) then
+            FieldLine:= FieldLine + ' [' + FieldByName('array_upper_bound').AsString + '] ';
         end
         else
         begin
@@ -285,9 +286,9 @@ begin
       end;
 
       // Computed Fields
-      if FieldByName('Computed_Source').AsString <> '' then
+      if FieldByName('computed_source').AsString <> '' then
         CalculatedList.Add('ALTER TABLE ' + ATableName + ' ADD ' +
-          Trim(FieldByName('Field_Name').AsString) + ' COMPUTED BY ' + FieldByName('Computed_Source').AsString + ';');
+          Trim(FieldByName('Field_Name').AsString) + ' COMPUTED BY ' + FieldByName('computed_source').AsString + ';');
 
       Next;
 
@@ -313,7 +314,7 @@ begin
       fmMain.GetConstraintFields(ATableName, PKeyIndexName, PKFieldsList);
       // Follow isql -x (not FlameRobin) by omitting system-generated
       // constraint names and let the system generate its own names
-      if SystemGeneratedConstraint(ConstraintName) then
+      if IsConstraintSystemGenerated(ConstraintName) then
         FieldLine:= ' primary key ('
       else // User-specified, so explicilty mention constraint name
         FieldLine:= 'constraint ' + ConstraintName + ' primary key (';
@@ -515,7 +516,6 @@ end;
 
 function ScriptAllCheckConstraints(dbIndex: Integer; var List: TStringList
   ): Boolean;
-  //todo: get check constraints for domains
 begin
   dmSysTables.ScriptCheckConstraints(dbIndex,List);
 end;
@@ -560,7 +560,7 @@ var
   var
     Line: string;
   begin
-    if SystemGeneratedConstraint(ConstraintName) then
+    if IsConstraintSystemGenerated(ConstraintName) then
     begin
       // If system-generated, don't specify constraint name
       Line:= format(TemplateNoName,[TableName,CurrentFieldName,

+ 14 - 11
systables.pas

@@ -895,12 +895,12 @@ begin
     ' f.RDB$Character_LENGTH AS Characterlength, ' + {character_length seems a reserved word }
     ' f.RDB$FIELD_PRECISION AS field_precision, ' +
     ' f.RDB$FIELD_SCALE AS field_scale, ' +
-    ' f.RDB$FIELD_TYPE as Field_Type_Int, ' +
+    ' f.RDB$FIELD_TYPE as field_type_int, ' +
     ' f.RDB$FIELD_SUB_TYPE AS field_sub_type, ' +
     ' coll.RDB$COLLATION_NAME AS field_collation, ' +
     ' cset.RDB$CHARACTER_SET_NAME AS field_charset, ' +
-    ' f.RDB$COMPUTED_Source AS Computed_Source, ' +
-    ' dim.RDB$UPPER_BOUND AS Array_Upper_Bound, ' +
+    ' f.RDB$computed_source AS computed_source, ' +
+    ' dim.RDB$UPPER_BOUND AS array_upper_bound, ' +
     ' r.RDB$FIELD_SOURCE AS field_source ' {domain if field based on domain} +
     ' FROM RDB$RELATION_FIELDS r ' +
     ' LEFT JOIN RDB$FIELDS f ON r.RDB$FIELD_SOURCE = f.RDB$FIELD_NAME ' +
@@ -917,10 +917,10 @@ begin
     begin
       if (FieldByName('field_source').IsNull) or
         (trim(FieldByName('field_source').AsString)='') or
-        (SystemGeneratedFieldDomain(trim(FieldByname('field_source').AsString))) then
+        (IsFieldDomainSystemGenerated(trim(FieldByname('field_source').AsString))) then
       begin
         // Field type is not based on a domain but a standard SQL type
-        FieldType:= fmMain.GetFBTypeName(FieldByName('Field_Type_Int').AsInteger,
+        FieldType:= fmMain.GetFBTypeName(FieldByName('field_type_int').AsInteger,
           FieldByName('field_sub_type').AsInteger,
           FieldByName('field_length').AsInteger,
           FieldByName('field_precision').AsInteger,
@@ -928,12 +928,12 @@ begin
         // Array should really be [lowerbound:upperbound] (if dimension is 0)
         // but for now don't bother as arrays are not supported anyway
         // Assume 0 dimension, 1 lower bound; just fill in upper bound
-        if not(FieldByName('Array_Upper_Bound').IsNull) then
+        if not(FieldByName('array_upper_bound').IsNull) then
           FieldType := FieldType +
             ' [' +
-            FieldByName('Array_Upper_Bound').AsString +
+            FieldByName('array_upper_bound').AsString +
             ']';
-        if FieldByName('Field_Type_int').AsInteger = VarCharType then
+        if FieldByName('field_type_int').AsInteger = VarCharType then
           FieldSize:= FieldByName('CharacterLength').AsInteger
         else
           FieldSize:= FieldByName('Field_Length').AsInteger;
@@ -1117,20 +1117,23 @@ begin
       ' f.RDB$FIELD_LENGTH AS field_length, ' +
       ' f.RDB$FIELD_PRECISION AS field_precision, ' +
       ' f.RDB$FIELD_SCALE AS field_scale, ' +
-      ' f.RDB$FIELD_TYPE as Field_Type_Int, ' +
+      ' f.RDB$FIELD_TYPE as field_type_int, ' +
       ' f.RDB$FIELD_SUB_TYPE AS field_sub_type, ' +
       ' coll.RDB$COLLATION_NAME AS field_collation, ' +
       ' cset.RDB$CHARACTER_SET_NAME AS field_charset, ' +
-      ' f.RDB$COMPUTED_Source AS Computed_Source ' +
+      ' f.RDB$computed_source AS computed_source, ' +
+      ' dim.RDB$UPPER_BOUND AS array_upper_bound, ' +
+      ' r.RDB$FIELD_SOURCE AS field_source ' {domain if field based on domain} +
       ' FROM RDB$RELATION_FIELDS r ' +
       ' LEFT JOIN RDB$FIELDS f ON r.RDB$FIELD_SOURCE = f.RDB$FIELD_NAME ' +
       ' LEFT JOIN RDB$COLLATIONS coll ON f.RDB$COLLATION_ID = coll.RDB$COLLATION_ID ' +
       ' LEFT JOIN RDB$CHARACTER_SETS cset ON f.RDB$CHARACTER_SET_ID = cset.RDB$CHARACTER_SET_ID ' +
+      ' LEFT JOIN RDB$FIELD_DIMENSIONS dim on f.RDB$FIELD_NAME = dim.RDB$FIELD_NAME '+
       ' WHERE r.RDB$RELATION_NAME=''' + ATableName + '''  ' +
       ' ORDER BY r.RDB$FIELD_POSITION;';
   sqQuery.Open;
   FieldsList.Clear;
-  // Todo: add support for array datatype (see other code referencing RDB$FIELD_DIMENSIONS table)
+  //todo: add support for array datatype, domain-based fields in gui using field_source and IsFieldDomainSystemGenerated
   while not sqQuery.EOF do
   begin
     FieldName:= Trim(sqQuery.FieldByName('field_name').AsString);

+ 2 - 1
topologicalsort.pas

@@ -88,7 +88,7 @@ begin
 end;
 
 function TTopologicalSort.SearchIndex(NodeID: integer): String;
-  //Look up name for the index
+  // Look up name for the index
 begin
   if (NodeID > 0) and (NodeID <= High(Nodes)) then
   begin
@@ -262,6 +262,7 @@ begin
         end; //Invalid Dep
       end; //Invalid Node
     end; //Count
+
     // Done with the first batch, so we can increase the sort order:
     OutputSortOrder := OutputSortOrder + 1;
     {$IFDEF TOPODEBUG}