浏览代码

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;
     sqlTrans:= Rec.SQLTrans;
     sqEditTable.DataBase:= ibConnection;
     sqEditTable.DataBase:= ibConnection;
   end;
   end;
-  //todo: deal with quoted identifiers in ATableName here and elsewhere
   sqEditTable.SQL.Text:= 'select * from ' + ATableName;
   sqEditTable.SQL.Text:= 'select * from ' + ATableName;
   sqEditTable.Open; // need to have open query in order to access fields below
   sqEditTable.Open; // need to have open query in order to access fields below
 
 

+ 36 - 37
main.pas

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

+ 4 - 2
newgen.pas

@@ -96,12 +96,14 @@ begin
     cbFields.Clear;
     cbFields.Clear;
     while not fmMain.SQLQuery1.EOF do
     while not fmMain.SQLQuery1.EOF do
     begin
     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_sub_type').AsInteger,
         fmMain.SQLQuery1.FieldByName('field_length').AsInteger,
         fmMain.SQLQuery1.FieldByName('field_length').AsInteger,
         fmMain.SQLQuery1.FieldByName('field_precision').AsInteger,
         fmMain.SQLQuery1.FieldByName('field_precision').AsInteger,
         fmMain.SQLQuery1.FieldByName('field_scale').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
       if (FType = 'INTEGER') or (FType = 'BIGINT') or (FType = 'SMALLINT') then
         cbFields.Items.Add(Trim(fmMain.SQLQuery1.FieldByName('Field_Name').AsString));
         cbFields.Items.Add(Trim(fmMain.SQLQuery1.FieldByName('Field_Name').AsString));
       fmMain.SQLQuery1.Next;
       fmMain.SQLQuery1.Next;

+ 1 - 1
newtable.pas

@@ -280,7 +280,7 @@ begin
       List.Text:= GenerateCreateSQL(KeyField, GeneratorName);
       List.Text:= GenerateCreateSQL(KeyField, GeneratorName);
       if cxCreateGen.Checked then
       if cxCreateGen.Checked then
       begin;
       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('');
         List.Add('-- Generator');
         List.Add('-- Generator');
         List.Add('create generator ' + GeneratorName + ';');
         List.Add('create generator ' + GeneratorName + ';');

+ 0 - 1
querywindow.pas

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

+ 20 - 20
scriptdb.pas

@@ -31,14 +31,15 @@ function ScriptAllSecIndices(dbIndex: Integer; var List: TStringList): Boolean;
 
 
 // Scripts check constraints for all tables
 // Scripts check constraints for all tables
 function ScriptAllCheckConstraints(dbIndex: Integer; var List: TStringList): Boolean;
 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:
 There are 5 kind of constraints:
     NOT NULL
     NOT NULL
     PRIMARY KEY
     PRIMARY KEY
     UNIQUE
     UNIQUE
     FOREIGN KEY
     FOREIGN KEY
     CHECK
     CHECK
+This function only covers foreign keys; the other constraints are covered elsewhere
 }
 }
 function ScriptAllConstraints(dbIndex: Integer; var List: TStringList): Boolean;
 function ScriptAllConstraints(dbIndex: Integer; var List: TStringList): Boolean;
 function ScriptObjectPermission(dbIndex: Integer; ObjName, UserName: string; var ObjType: Integer;
 function ScriptObjectPermission(dbIndex: Integer; ObjName, UserName: string; var ObjType: Integer;
@@ -57,10 +58,11 @@ implementation
 uses SysTables, Main;
 uses SysTables, Main;
 
 
 // Tries to guess if a constraint name is system-generated.
 // 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
 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);
   result:=(pos('INTEG_',uppercase(Trim(ConstraintName)))=1);
 end;
 end;
 
 
@@ -72,7 +74,7 @@ var
   i: Integer;
   i: Integer;
 begin
 begin
   List.CommaText:= dmSysTables.GetDBObjectNames(dbIndex, 9, Count);
   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
   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
   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
   to do it in execute block with error handling or
@@ -173,7 +175,6 @@ var
   CheckConstraint: string;
   CheckConstraint: string;
   DefaultValue: string;
   DefaultValue: string;
 begin
 begin
-  //todo: script domains: add support for character set
   List.CommaText:= dmSysTables.GetDBObjectNames(dbIndex, 8, Count);
   List.CommaText:= dmSysTables.GetDBObjectNames(dbIndex, 8, Count);
   // Get domains in dependency order (if dependencies can exist between domains)
   // Get domains in dependency order (if dependencies can exist between domains)
   dmSysTables.SortDependencies(List);
   dmSysTables.SortDependencies(List);
@@ -225,8 +226,8 @@ begin
     while not EOF do
     while not EOF do
     begin
     begin
       Skipped:= False;
       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
        (Trim(FieldByName('Field_Collation').AsString) = 'NONE') or
        (FieldByName('Field_Collation').IsNull)) then
        (FieldByName('Field_Collation').IsNull)) then
       begin
       begin
@@ -235,20 +236,20 @@ begin
 
 
         if (FieldByName('field_source').IsNull) or
         if (FieldByName('field_source').IsNull) or
           (trim(FieldByName('field_source').AsString)='') or
           (trim(FieldByName('field_source').AsString)='') or
-          (SystemGeneratedFieldDomain(trim(FieldByname('field_source').AsString))) then
+          (IsFieldDomainSystemGenerated(trim(FieldByname('field_source').AsString))) then
         begin
         begin
           // Field type is not based on a domain but a standard SQL type
           // Field type is not based on a domain but a standard SQL type
           // Field 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_Sub_Type').AsInteger,
             FieldByName('Field_Length').AsInteger,
             FieldByName('Field_Length').AsInteger,
             FieldByName('Field_Precision').AsInteger,
             FieldByName('Field_Precision').AsInteger,
             FieldByName('Field_Scale').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 + ') ';
             FieldLine:= FieldLine + '(' + FieldByName('CharacterLength').AsString + ') ';
 
 
-          if (FieldByName('Field_Type_Int').AsInteger = BlobType) then
+          if (FieldByName('field_type_int').AsInteger = BlobType) then
           begin
           begin
             BlobSubType:= fmMain.GetBlobSubTypeName(FieldByName('Field_Sub_Type').AsInteger);
             BlobSubType:= fmMain.GetBlobSubTypeName(FieldByName('Field_Sub_Type').AsInteger);
             if BlobSubType<>'' then
             if BlobSubType<>'' then
@@ -258,8 +259,8 @@ begin
           // Rudimentary support for array datatypes (only covers 0 dimension types):
           // Rudimentary support for array datatypes (only covers 0 dimension types):
           {todo: expand to proper array type detection (low priority as arrays are
           {todo: expand to proper array type detection (low priority as arrays are
            virtually unused}
            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
         end
         else
         else
         begin
         begin
@@ -285,9 +286,9 @@ begin
       end;
       end;
 
 
       // Computed Fields
       // Computed Fields
-      if FieldByName('Computed_Source').AsString <> '' then
+      if FieldByName('computed_source').AsString <> '' then
         CalculatedList.Add('ALTER TABLE ' + ATableName + ' ADD ' +
         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;
       Next;
 
 
@@ -313,7 +314,7 @@ begin
       fmMain.GetConstraintFields(ATableName, PKeyIndexName, PKFieldsList);
       fmMain.GetConstraintFields(ATableName, PKeyIndexName, PKFieldsList);
       // Follow isql -x (not FlameRobin) by omitting system-generated
       // Follow isql -x (not FlameRobin) by omitting system-generated
       // constraint names and let the system generate its own names
       // constraint names and let the system generate its own names
-      if SystemGeneratedConstraint(ConstraintName) then
+      if IsConstraintSystemGenerated(ConstraintName) then
         FieldLine:= ' primary key ('
         FieldLine:= ' primary key ('
       else // User-specified, so explicilty mention constraint name
       else // User-specified, so explicilty mention constraint name
         FieldLine:= 'constraint ' + ConstraintName + ' primary key (';
         FieldLine:= 'constraint ' + ConstraintName + ' primary key (';
@@ -515,7 +516,6 @@ end;
 
 
 function ScriptAllCheckConstraints(dbIndex: Integer; var List: TStringList
 function ScriptAllCheckConstraints(dbIndex: Integer; var List: TStringList
   ): Boolean;
   ): Boolean;
-  //todo: get check constraints for domains
 begin
 begin
   dmSysTables.ScriptCheckConstraints(dbIndex,List);
   dmSysTables.ScriptCheckConstraints(dbIndex,List);
 end;
 end;
@@ -560,7 +560,7 @@ var
   var
   var
     Line: string;
     Line: string;
   begin
   begin
-    if SystemGeneratedConstraint(ConstraintName) then
+    if IsConstraintSystemGenerated(ConstraintName) then
     begin
     begin
       // If system-generated, don't specify constraint name
       // If system-generated, don't specify constraint name
       Line:= format(TemplateNoName,[TableName,CurrentFieldName,
       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$Character_LENGTH AS Characterlength, ' + {character_length seems a reserved word }
     ' f.RDB$FIELD_PRECISION AS field_precision, ' +
     ' f.RDB$FIELD_PRECISION AS field_precision, ' +
     ' f.RDB$FIELD_SCALE AS field_scale, ' +
     ' 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, ' +
     ' f.RDB$FIELD_SUB_TYPE AS field_sub_type, ' +
     ' coll.RDB$COLLATION_NAME AS field_collation, ' +
     ' coll.RDB$COLLATION_NAME AS field_collation, ' +
     ' cset.RDB$CHARACTER_SET_NAME AS field_charset, ' +
     ' 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} +
     ' r.RDB$FIELD_SOURCE AS field_source ' {domain if field based on domain} +
     ' FROM RDB$RELATION_FIELDS r ' +
     ' FROM RDB$RELATION_FIELDS r ' +
     ' LEFT JOIN RDB$FIELDS f ON r.RDB$FIELD_SOURCE = f.RDB$FIELD_NAME ' +
     ' LEFT JOIN RDB$FIELDS f ON r.RDB$FIELD_SOURCE = f.RDB$FIELD_NAME ' +
@@ -917,10 +917,10 @@ begin
     begin
     begin
       if (FieldByName('field_source').IsNull) or
       if (FieldByName('field_source').IsNull) or
         (trim(FieldByName('field_source').AsString)='') or
         (trim(FieldByName('field_source').AsString)='') or
-        (SystemGeneratedFieldDomain(trim(FieldByname('field_source').AsString))) then
+        (IsFieldDomainSystemGenerated(trim(FieldByname('field_source').AsString))) then
       begin
       begin
         // Field type is not based on a domain but a standard SQL type
         // 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_sub_type').AsInteger,
           FieldByName('field_length').AsInteger,
           FieldByName('field_length').AsInteger,
           FieldByName('field_precision').AsInteger,
           FieldByName('field_precision').AsInteger,
@@ -928,12 +928,12 @@ begin
         // Array should really be [lowerbound:upperbound] (if dimension is 0)
         // Array should really be [lowerbound:upperbound] (if dimension is 0)
         // but for now don't bother as arrays are not supported anyway
         // but for now don't bother as arrays are not supported anyway
         // Assume 0 dimension, 1 lower bound; just fill in upper bound
         // 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 +
           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
           FieldSize:= FieldByName('CharacterLength').AsInteger
         else
         else
           FieldSize:= FieldByName('Field_Length').AsInteger;
           FieldSize:= FieldByName('Field_Length').AsInteger;
@@ -1117,20 +1117,23 @@ begin
       ' f.RDB$FIELD_LENGTH AS field_length, ' +
       ' f.RDB$FIELD_LENGTH AS field_length, ' +
       ' f.RDB$FIELD_PRECISION AS field_precision, ' +
       ' f.RDB$FIELD_PRECISION AS field_precision, ' +
       ' f.RDB$FIELD_SCALE AS field_scale, ' +
       ' 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, ' +
       ' f.RDB$FIELD_SUB_TYPE AS field_sub_type, ' +
       ' coll.RDB$COLLATION_NAME AS field_collation, ' +
       ' coll.RDB$COLLATION_NAME AS field_collation, ' +
       ' cset.RDB$CHARACTER_SET_NAME AS field_charset, ' +
       ' 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 ' +
       ' FROM RDB$RELATION_FIELDS r ' +
       ' LEFT JOIN RDB$FIELDS f ON r.RDB$FIELD_SOURCE = f.RDB$FIELD_NAME ' +
       ' 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$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$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 + '''  ' +
       ' WHERE r.RDB$RELATION_NAME=''' + ATableName + '''  ' +
       ' ORDER BY r.RDB$FIELD_POSITION;';
       ' ORDER BY r.RDB$FIELD_POSITION;';
   sqQuery.Open;
   sqQuery.Open;
   FieldsList.Clear;
   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
   while not sqQuery.EOF do
   begin
   begin
     FieldName:= Trim(sqQuery.FieldByName('field_name').AsString);
     FieldName:= Trim(sqQuery.FieldByName('field_name').AsString);

+ 2 - 1
topologicalsort.pas

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