Просмотр исходного кода

Harmonize field type detection (take it out of query); deal uniformly with cstring/char/varchar length

Reinier Olislagers 11 лет назад
Родитель
Сommit
33514dc412
4 измененных файлов с 113 добавлено и 146 удалено
  1. 65 70
      main.pas
  2. 5 1
      newgen.pas
  3. 7 5
      scriptdb.pas
  4. 36 70
      systables.pas

+ 65 - 70
main.pas

@@ -1265,7 +1265,7 @@ begin
       clbFields.Clear;
       clbFields.Clear;
       while not EOF do
       while not EOF do
       begin
       begin
-        if (Pos('CHAR', Trim(FieldByName('Field_Type_Str').AsString)) = 0) 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
@@ -1925,7 +1925,6 @@ var
   SelNode: TTreeNode;
   SelNode: TTreeNode;
   QWindow: TfmQueryWindow;
   QWindow: TfmQueryWindow;
   ATableName: string;
   ATableName: string;
-  i: Integer;
   ConstraintsList: TStringList;
   ConstraintsList: TStringList;
   PKFieldsList: TStringList;
   PKFieldsList: TStringList;
   FieldLine: string;
   FieldLine: string;
@@ -1952,18 +1951,21 @@ begin
     while not EOF do
     while not EOF do
     begin
     begin
       Skipped:= False;
       Skipped:= False;
-      if (FieldByName('Computed_Source').AsString = '') and
-          ((Pos('CHAR', Trim(FieldByName('Field_Type_Str').AsString)) = 0) 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
         FieldNames:= FieldNames + Trim(FieldByName('Field_Name').AsString);
         FieldNames:= FieldNames + Trim(FieldByName('Field_Name').AsString);
         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 + Trim(FieldByName('Field_Type_Str').AsString);
-        //todo: verify if cstring fields also should be included
-        if Pos('char', LowerCase(FieldByName('Field_Type_Str').AsString)) > 0 then
-          FieldLine:= FieldLine + '(' + FieldByName('Character_Leng').AsString + ') ';
+        FieldLine:= FieldLine +
+          GetFBTypeName(SQLQuery1.FieldByName('Field_Type_Int').AsInteger,
+            SQLQuery1.FieldByName('field_sub_type').AsInteger,
+            SQLQuery1.FieldByName('field_length').AsInteger,
+            SQLQuery1.FieldByName('field_scale').AsInteger);
+        if FieldByName('Field_Type_Int').AsInteger in [CStringType,CharType,VarCharType] then
+          FieldLine:= FieldLine + '(' + FieldByName('Character_Length').AsString + ') ';
       end
       end
       else
       else
         Skipped:= True;
         Skipped:= True;
@@ -2180,17 +2182,20 @@ begin
     while not EOF do
     while not EOF do
     begin
     begin
       Skipped:= False;
       Skipped:= False;
-      if (FieldByName('Computed_Source').AsString = '') and
-         ((Pos('CHAR', FieldByName('Field_Type_Str').AsString) = 0) or
-          (Trim(FieldByName('Field_Collation').AsString) = 'NONE') or
-          (FieldByName('Field_Collation').IsNull)) then
+      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
       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 + Trim(FieldByName('Field_Type_Str').AsString);
-        if Pos('char', LowerCase(FieldByName('Field_Type_Str').AsString)) > 0 then
-          FieldLine:= FieldLine + '(' + FieldByName('Character_Leng').AsString + ') ';
+        FieldLine:= FieldLine + GetFBTypeName(SQLQuery1.FieldByName('Field_Type_Int').AsInteger,
+          SQLQuery1.FieldByName('field_sub_type').AsInteger,
+          SQLQuery1.FieldByName('field_length').AsInteger,
+          SQLQuery1.FieldByName('field_scale').AsInteger);
+        if FieldByName('Field_Type_Int').AsInteger in [CStringType,CharType,VarCharType] then
+          FieldLine:= FieldLine + '(' + FieldByName('Character_Length').AsString + ') ';
       end
       end
       else
       else
         Skipped:= True;
         Skipped:= True;
@@ -2463,43 +2468,26 @@ begin
   SetConnection(DatabaseIndex);
   SetConnection(DatabaseIndex);
   sqlTransaction.Commit;
   sqlTransaction.Commit;
   SQLQuery1.SQL.Text:= 'SELECT r.RDB$FIELD_NAME AS field_name, ' +
   SQLQuery1.SQL.Text:= 'SELECT r.RDB$FIELD_NAME AS field_name, ' +
-      '  r.RDB$DESCRIPTION AS field_description, ' +
-      '  r.RDB$DEFAULT_SOURCE AS field_default_value, ' +
-      '  r.RDB$NULL_FLAG AS field_not_null_constraint, ' +
-      '  f.RDB$FIELD_LENGTH AS field_length, ' +
-      '  f.RDB$Character_LENGTH AS character_leng, ' +
-      '  f.RDB$FIELD_PRECISION AS field_precision, ' +
-      '  f.RDB$FIELD_SCALE AS field_scale, ' +
-      '  f.RDB$FIELD_TYPE as Field_Type_Int, ' +
-      '  CASE f.RDB$FIELD_TYPE ' +
-      '    WHEN 261 THEN ''BLOB'' ' +
-      '    WHEN 14 THEN ''CHAR'' ' +
-      '    WHEN 40 THEN ''CSTRING''  ' +  // probably null-terminated string used for UDFs
-      '    WHEN 11 THEN ''D_FLOAT'' ' +
-      '    WHEN 27 THEN ''DOUBLE PRECISION'' ' +
-      '    WHEN 10 THEN ''FLOAT'' ' +
-      '    WHEN 16 THEN ''BIGINT'' ' +
-      '    WHEN 8 THEN ''INTEGER'' ' +
-      '    WHEN 9 THEN ''QUAD'' ' +
-      '    WHEN 7 THEN ''SMALLINT'' ' +
-      '    WHEN 12 THEN ''DATE'' ' +
-      '    WHEN 13 THEN ''TIME'' ' +
-      '    WHEN 35 THEN ''TIMESTAMP'' ' +
-      '    WHEN 37 THEN ''VARCHAR'' ' +
-      '    ELSE ''UNKNOWN'' ' +
-      '  END AS field_type_Str, ' +
-      '  f.RDB$FIELD_SUB_TYPE AS field_subtype, ' +
-      '  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 ' +
-      ' 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;';
+    ' r.RDB$DESCRIPTION AS field_description, ' +
+    ' r.RDB$DEFAULT_SOURCE AS field_default_value, ' +
+    ' r.RDB$NULL_FLAG AS field_not_null_constraint, ' +
+    ' f.RDB$FIELD_LENGTH AS field_length, ' +
+    ' f.RDB$Character_LENGTH AS character_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_SUB_TYPE AS field_subtype, ' +
+    ' 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 ' +
+    ' 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;';
   SQLQuery1.Open;
   SQLQuery1.Open;
   // Fill field list if needed
   // Fill field list if needed
   if FieldsList <> nil then
   if FieldsList <> nil then
@@ -2771,9 +2759,11 @@ begin
     Params:= '';
     Params:= '';
     while not SQLQuery1.EOF do
     while not SQLQuery1.EOF do
     begin
     begin
-      Params:= Params + #10 + GetFBTypeName(SQLQuery1.FieldByName('RDB$FIELD_TYPE').AsInteger);
-      //todo: verify if getfbtypename needs more parameters here
-      if SQLQuery1.FieldByName('RDB$FIELD_TYPE').AsInteger in [14, 37, 40] then
+      Params:= Params + #10 + GetFBTypeName(SQLQuery1.FieldByName('RDB$FIELD_TYPE').AsInteger,
+        SQLQuery1.FieldByName('RDB$FIELD_SUB_TYPE').AsInteger,
+        SQLQuery1.FieldByName('RDB$FIELD_LENGTH').AsInteger,
+        SQLQuery1.FieldByName('RDB$FIELD_SCALE').AsInteger);
+      if SQLQuery1.FieldByName('RDB$FIELD_TYPE').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
@@ -2790,9 +2780,11 @@ begin
     SQLQuery1.Open;
     SQLQuery1.Open;
     while not SQLQuery1.EOF do
     while not SQLQuery1.EOF do
     begin
     begin
-      //todo: verify if getfbtypename needs more parameters here
-      Params:= Params + #10 + GetFBTypeName(SQLQuery1.FieldByName('RDB$FIELD_TYPE').AsInteger);
-      if SQLQuery1.FieldByName('RDB$FIELD_TYPE').AsInteger in [14, 37, 40] then
+      Params:= Params + #10 + GetFBTypeName(SQLQuery1.FieldByName('RDB$FIELD_TYPE').AsInteger,
+        SQLQuery1.FieldByName('RDB$FIELD_SUB_TYPE').AsInteger,
+        SQLQuery1.FieldByName('RDB$FIELD_LENGTH').AsInteger,
+        SQLQuery1.FieldByName('RDB$FIELD_SCALE').AsInteger);
+      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
@@ -3100,7 +3092,7 @@ begin
     with AStringGrid, SQLQuery1 do
     with AStringGrid, SQLQuery1 do
     while not EOF do
     while not EOF do
     begin
     begin
-      if (Pos('CHAR', Trim(FieldByName('Field_Type_Str').AsString)) = 0) 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
@@ -3130,9 +3122,8 @@ begin
           Cells[2, RowCount - 1]:= FieldByName('Computed_Source').AsString;
           Cells[2, RowCount - 1]:= FieldByName('Computed_Source').AsString;
 
 
         // Field Size
         // Field Size
-        // todo: shouldn't char and cstring - types 14,40 be included? investigate
-        if FieldByName('Field_Type_Int').AsInteger in [37] then
-          Cells[3, RowCount - 1]:= FieldByName('Character_Leng').AsString
+        if FieldByName('Field_Type_Int').AsInteger in [CharType,CStringType,VarCharType] then
+          Cells[3, RowCount - 1]:= FieldByName('Character_Length').AsString
         else
         else
           Cells[3, RowCount - 1]:= FieldByName('Field_Length').AsString;
           Cells[3, RowCount - 1]:= FieldByName('Field_Length').AsString;
 
 
@@ -3257,17 +3248,21 @@ begin
       while not EOF do
       while not EOF do
       begin
       begin
         AFieldName:= Trim(FieldByName('Field_Name').AsString);
         AFieldName:= Trim(FieldByName('Field_Name').AsString);
-        if (Pos('CHAR', Trim(FieldByName('Field_Type_Str').AsString)) = 0) 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
-           // todo: shouldn't char and cstring - types 14,40 be included? investigate
-           if FieldByName('Field_type_int').AsInteger = 37 then
-             LenStr:= FieldByName('Character_Leng').AsString
+           if (FieldByName('Field_Type_Int').AsInteger) in [CharType, CStringType, VarCharType] then
+             LenStr:= FieldByName('Character_Length').AsString
            else
            else
              LenStr:= FieldByName('Field_Length').AsString;
              LenStr:= FieldByName('Field_Length').AsString;
 
 
-          FieldTitle:= AFieldName + '   ' + Trim(FieldByName('Field_Type_str').AsString) + ' ' + LenStr;
+          FieldTitle:= AFieldName + '   ' +
+            GetFBTypeName(SQLQuery1.FieldByName('Field_Type_Int').AsInteger,
+              SQLQuery1.FieldByName('field_sub_type').AsInteger,
+              SQLQuery1.FieldByName('field_length').AsInteger,
+              SQLQuery1.FieldByName('field_scale').AsInteger) +
+            ' ' + LenStr;
           FieldNode:= tvMain.Items.AddChild(Node, FieldTitle);
           FieldNode:= tvMain.Items.AddChild(Node, FieldTitle);
           FieldNode.OverlayIndex:= i;
           FieldNode.OverlayIndex:= i;
           if PKFieldsList.IndexOf(AFieldname) <> -1 then // Primary key
           if PKFieldsList.IndexOf(AFieldname) <> -1 then // Primary key
@@ -4136,9 +4131,9 @@ begin
     // See also
     // See also
     // http://firebirdsql.org/manual/migration-mssql-data-types.html
     // http://firebirdsql.org/manual/migration-mssql-data-types.html
     // http://stackoverflow.com/questions/12070162/how-can-i-get-the-table-description-fields-and-types-from-firebird-with-dbexpr
     // http://stackoverflow.com/questions/12070162/how-can-i-get-the-table-description-fields-and-types-from-firebird-with-dbexpr
-    261 : Result:= 'BLOB';
+    BlobType : Result:= 'BLOB';
     14 : Result:= 'CHAR';
     14 : Result:= 'CHAR';
-    40 : 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'; // Probably int64 in Interbase. Further processed below
@@ -4149,7 +4144,7 @@ begin
     7  : Result:= 'SMALLINT'; // further processed below
     7  : Result:= 'SMALLINT'; // further processed below
     13 : Result:= 'TIME';
     13 : Result:= 'TIME';
     35 : Result:= 'TIMESTAMP';
     35 : Result:= 'TIMESTAMP';
-    37 : Result:= 'VARCHAR';
+    VarCharType : Result:= 'VARCHAR';
   else
   else
     Result:= 'Unknown Type';
     Result:= 'Unknown Type';
   end;
   end;

+ 5 - 1
newgen.pas

@@ -96,7 +96,11 @@ begin
     cbFields.Clear;
     cbFields.Clear;
     while not fmMain.SQLQuery1.EOF do
     while not fmMain.SQLQuery1.EOF do
     begin
     begin
-      FType:= Trim(fmMain.SQLQuery1.FieldByName('Field_Type_Str').AsString);
+      FType:= fmMain.GetFBTypeName(fmMain.SQLQuery1.FieldByName('Field_Type').AsInteger,
+        fmMain.SQLQuery1.FieldByName('field_sub_type').AsInteger,
+        fmMain.SQLQuery1.FieldByName('field_length').AsInteger,
+        fmMain.SQLQuery1.FieldByName('field_scale').AsInteger);
+      //todo: verify whether this still works. Also what about other integer types?
       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;

+ 7 - 5
scriptdb.pas

@@ -14,6 +14,7 @@ function ScriptAllDomains(dbIndex: Integer; var List: TStringList): Boolean;
 function ScriptAllGenerators(dbIndex: Integer; var List: TStringList): Boolean;
 function ScriptAllGenerators(dbIndex: Integer; var List: TStringList): Boolean;
 // Scripts a single table as CREATE TABLE DDL
 // Scripts a single table as CREATE TABLE DDL
 procedure ScriptTableAsCreate(dbIndex: Integer; ATableName: string; ScriptList: TStringList);
 procedure ScriptTableAsCreate(dbIndex: Integer; ATableName: string; ScriptList: TStringList);
+// Scripts all tables calling ScriptTableAsCreate for each table
 function ScriptAllTables(dbIndex: Integer; var List: TStringList): Boolean;
 function ScriptAllTables(dbIndex: Integer; var List: TStringList): Boolean;
 // Scripts all stored procedures
 // Scripts all stored procedures
 function ScriptAllProcedureTemplates(dbIndex: Integer; var List: TStringList): Boolean;
 function ScriptAllProcedureTemplates(dbIndex: Integer; var List: TStringList): Boolean;
@@ -162,8 +163,8 @@ begin
     while not EOF do
     while not EOF do
     begin
     begin
       Skipped:= False;
       Skipped:= False;
-      if (FieldByName('Computed_Source').AsString = '') and
-       ((Pos('CHAR', Trim(FieldByName('Field_Type_Str').AsString)) = 0) 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
@@ -176,11 +177,12 @@ begin
           FieldByName('Field_Length').AsInteger,
           FieldByName('Field_Length').AsInteger,
           FieldByName('Field_Scale').AsInteger);
           FieldByName('Field_Scale').AsInteger);
 
 
-        if Pos('char', LowerCase(FieldByName('Field_Type_Str').AsString)) > 0 then
-          FieldLine:= FieldLine + '(' + FieldByName('Character_Leng').AsString + ') ';
+        if (FieldByName('Field_Type_Int').AsInteger) in [CharType, CStringType, VarCharType] then
+          FieldLine:= FieldLine + '(' + FieldByName('Character_Length').AsString + ') ';
 
 
         // 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)
+        // todo: expand to proper array type detection (low priority as arrays are
+        // virtually unused)
         if not(FieldByName('Array_Upper_Bound').IsNull) then
         if not(FieldByName('Array_Upper_Bound').IsNull) then
           FieldLine:= FieldLine + ' [' + FieldByName('Array_Upper_Bound').AsString + '] ';
           FieldLine:= FieldLine + ' [' + FieldByName('Array_Upper_Bound').AsString + '] ';
 
 

+ 36 - 70
systables.pas

@@ -792,51 +792,36 @@ function TdmSysTables.GetFieldInfo(dbIndex: Integer; TableName, FieldName: strin
 begin
 begin
   Init(dbIndex);
   Init(dbIndex);
   sqQuery.SQL.Text:= 'SELECT r.RDB$FIELD_NAME AS field_name, ' +
   sqQuery.SQL.Text:= 'SELECT r.RDB$FIELD_NAME AS field_name, ' +
-      '  r.RDB$DESCRIPTION AS field_description, ' +
-      '  r.RDB$DEFAULT_SOURCE AS field_default_value, ' +
-      '  r.RDB$NULL_FLAG AS field_not_null_constraint, ' +
-      '  f.RDB$FIELD_LENGTH AS field_length, ' +
-      '  f.RDB$Character_LENGTH AS Character_leng, ' +
-      '  f.RDB$FIELD_PRECISION AS field_precision, ' +
-      '  f.RDB$FIELD_SCALE AS field_scale, ' +
-      '  f.RDB$FIELD_TYPE as Field_Type_Int, ' +
-      '  CASE f.RDB$FIELD_TYPE ' +
-      '    WHEN 261 THEN ''BLOB'' ' +
-      '    WHEN 14 THEN ''CHAR'' ' +
-      '    WHEN 40 THEN ''CSTRING''  ' + // probably null-terminated string used for UDFs
-      '    WHEN 11 THEN ''D_FLOAT'' ' +
-      '    WHEN 27 THEN ''DOUBLE PRECISION'' ' +
-      '    WHEN 10 THEN ''FLOAT'' ' +
-      '    WHEN 16 THEN ''BIGINT'' ' +
-      '    WHEN 8 THEN ''INTEGER'' ' +
-      '    WHEN 9 THEN ''QUAD'' ' +
-      '    WHEN 7 THEN ''SMALLINT'' ' +
-      '    WHEN 12 THEN ''DATE'' ' +
-      '    WHEN 13 THEN ''TIME'' ' +
-      '    WHEN 35 THEN ''TIMESTAMP'' ' +
-      '    WHEN 37 THEN ''VARCHAR'' ' +
-      '    ELSE ''UNKNOWN'' ' +
-      '  END AS field_type_Str, ' +
-      ' f.RDB$FIELD_SUB_TYPE AS field_subtype, ' +
-      ' 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 ' +
-      ' 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=''' + TableName + '''  and Trim(r.RDB$FIELD_NAME) = ''' + UpperCase(FieldName) + ''' ' +
-      ' ORDER BY r.RDB$FIELD_POSITION ';
+    ' r.RDB$DESCRIPTION AS field_description, ' +
+    ' r.RDB$DEFAULT_SOURCE AS field_default_value, ' +
+    ' r.RDB$NULL_FLAG AS field_not_null_constraint, ' +
+    ' f.RDB$FIELD_LENGTH AS field_length, ' +
+    ' f.RDB$Character_LENGTH AS Character_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_SUB_TYPE AS field_subtype, ' +
+    ' 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 ' +
+    ' 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=''' + TableName + '''  and Trim(r.RDB$FIELD_NAME) = ''' + UpperCase(FieldName) + ''' ' +
+    ' ORDER BY r.RDB$FIELD_POSITION ';
   sqQuery.Open;
   sqQuery.Open;
   Result:= sqQuery.RecordCount > 0;
   Result:= sqQuery.RecordCount > 0;
   if Result then
   if Result then
   begin
   begin
     with sqQuery do
     with sqQuery do
     begin
     begin
-      // to do: rewrite using function
-      FieldType:= Trim(FieldByName('Field_Type_Str').AsString);
+      FieldType:= fmMain.GetFBTypeName(FieldByName('Field_Type').AsInteger,
+        FieldByName('field_sub_type').AsInteger,
+        FieldByName('field_length').AsInteger,
+        FieldByName('field_scale').AsInteger);
       // 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
@@ -845,8 +830,8 @@ begin
           ' [' +
           ' [' +
           FieldByName('Array_Upper_Bound').AsString +
           FieldByName('Array_Upper_Bound').AsString +
           ']';
           ']';
-      if FieldByName('Field_Type_int').AsInteger = 37 then // VarChar
-        FieldSize:= FieldByName('Character_Leng').AsInteger
+      if FieldByName('Field_Type_int').AsInteger = VarCharType then
+        FieldSize:= FieldByName('Character_Length').AsInteger
       else
       else
         FieldSize:= FieldByName('Field_Length').AsInteger;
         FieldSize:= FieldByName('Field_Length').AsInteger;
       NotNull:= FieldByName('Field_not_null_constraint').AsString = '1';
       NotNull:= FieldByName('Field_not_null_constraint').AsString = '1';
@@ -1017,36 +1002,17 @@ var
   FieldName: string;
   FieldName: string;
 begin
 begin
   Init(dbIndex);
   Init(dbIndex);
-  //todo: check all references to this query and rewrite using function for field type
-  //instead of field_type_str
   sqQuery.SQL.Text:= 'SELECT r.RDB$FIELD_NAME AS field_name, ' +
   sqQuery.SQL.Text:= 'SELECT r.RDB$FIELD_NAME AS field_name, ' +
-      '  r.RDB$DESCRIPTION AS field_description, ' +
-      '  r.RDB$DEFAULT_SOURCE AS field_default_value, ' +
-      '  r.RDB$NULL_FLAG AS field_not_null_constraint, ' +
-      '  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, ' +
-      '  CASE f.RDB$FIELD_TYPE ' +
-      '    WHEN 261 THEN ''BLOB'' ' +
-      '    WHEN 14 THEN ''CHAR'' ' +
-      '    WHEN 40 THEN ''CSTRING''  ' + // probably null-terminated string used for UDFs
-      '    WHEN 12 THEN ''DATE'' ' +
-      '    WHEN 11 THEN ''D_FLOAT'' ' +
-      '    WHEN 27 THEN ''DOUBLE PRECISION'' ' +
-      '    WHEN 10 THEN ''FLOAT'' ' +
-      '    WHEN 16 THEN ''BIGINT'' ' +
-      '    WHEN 8 THEN ''INTEGER'' ' +
-      '    WHEN 9 THEN ''QUAD'' ' +
-      '    WHEN 7 THEN ''SMALLINT'' ' +
-      '    WHEN 13 THEN ''TIME'' ' +
-      '    WHEN 35 THEN ''TIMESTAMP'' ' +
-      '    WHEN 37 THEN ''VARCHAR'' ' +
-      '    ELSE ''UNKNOWN'' ' +
-      '  END AS field_type_Str, ' +
-      '  f.RDB$FIELD_SUB_TYPE AS field_subtype, ' +
-      '  coll.RDB$COLLATION_NAME AS field_collation, ' +
-      '  cset.RDB$CHARACTER_SET_NAME AS field_charset, ' +
+      ' r.RDB$DESCRIPTION AS field_description, ' +
+      ' r.RDB$DEFAULT_SOURCE AS field_default_value, ' +
+      ' r.RDB$NULL_FLAG AS field_not_null_constraint, ' +
+      ' 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_SUB_TYPE AS field_subtype, ' +
+      ' 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 ' +
       ' 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 ' +