From: <fas...@us...> - 2006-11-29 03:32:02
|
Revision: 724 http://svn.sourceforge.net/instantobjects/revision/?rev=724&view=rev Author: fastbike2 Date: 2006-11-28 19:30:29 -0800 (Tue, 28 Nov 2006) Log Message: ----------- Fix [ 1603022] Evolve DB chokes on IBX Currency Type Refactor IB/FB catalog to: - display more info for unknown field types - match column types on RDB$FIELDS which is always complete (rather than RDB$TYPES which lacks some entries on some servers) - comments at end of file detailing SQL scripts that can be run to extract "Test" meta data - fieldscale checked for currency to ensure data accuracy is not lost Modified Paths: -------------- trunk/Source/Catalogs/IBFb/InstantIBFbCatalog.pas Modified: trunk/Source/Catalogs/IBFb/InstantIBFbCatalog.pas =================================================================== --- trunk/Source/Catalogs/IBFb/InstantIBFbCatalog.pas 2006-11-28 10:51:28 UTC (rev 723) +++ trunk/Source/Catalogs/IBFb/InstantIBFbCatalog.pas 2006-11-29 03:30:29 UTC (rev 724) @@ -24,7 +24,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): - * Steven Mitchell + * Steven Mitchell, David Moorhouse * * ***** END LICENSE BLOCK ***** *) @@ -51,12 +51,12 @@ procedure AddIndexMetadatas(TableMetadata: TInstantTableMetadata); procedure AddTableMetadatas(TableMetadatas: TInstantTableMetadatas); // Returns True if the TInstantDataType value that matches the supplied - // combination of ColumnType, BlobSubType and FieldScale is found. If + // combination of ColumnType, ColumnSubType and FieldScale is found. If // more than one datatypes apply, alternate data types are returned in // AlternateDataTypes, otherwise AlternateDataTypes is [] on exit. - function ColumnTypeToDataType(const ColumnType: string; - const BlobSubType, FieldScale: Integer; out DataType: TInstantDataType; - out AlternateDataTypes: TInstantDataTypes): Boolean; + function ColumnTypeToDataType(const ColumnType: Integer; + const ColumnSubType, FieldScale: Integer; out DataType: TInstantDataType; + out AlternateDataTypes: TInstantDataTypes): Boolean; function GetSelectFieldsSQL(const ATableName: string): string; function GetSelectIndexesSQL(const ATableName: string): string; function GetSelectIndexFieldsSQL(const AIndexName: string): string; @@ -70,7 +70,7 @@ uses SysUtils, Classes, DB, InstantConsts; - + { TInstantIBFbCatalog } procedure TInstantIBFbCatalog.AddIndexMetadatas( @@ -141,6 +141,7 @@ FieldMetadata: TInstantFieldMetadata; AlternateDataTypes: TInstantDataTypes; FieldMetaDataType: TInstantDataType; + FieldTypeName: string; begin Fields := Broker.AcquireDataSet(GetSelectFieldsSQL(TableMetadata.Name)); try @@ -151,7 +152,7 @@ FieldMetadata := TableMetadata.FieldMetadatas.Add; FieldMetadata.Name := Trim(Fields.FieldByName('RDB$FIELD_NAME').AsString); if ColumnTypeToDataType( - Trim(Fields.FieldByName('RDB$TYPE_NAME').AsString), + Fields.FieldByName('RDB$FIELD_TYPE').AsInteger, Fields.FieldByName('RDB$FIELD_SUB_TYPE').AsInteger, Fields.FieldByName('RDB$FIELD_SCALE').AsInteger, FieldMetaDataType, @@ -170,9 +171,15 @@ FieldMetadata.Size := Fields.FieldByName('RDB$FIELD_LENGTH').AsInteger; end else - DoWarning(Format(SUnsupportedColumnSkipped, - [TableMetadata.Name, FieldMetadata.Name, - Trim(Fields.FieldByName('RDB$TYPE_NAME').AsString)])); + begin + FieldTypeName := Trim (Fields.FieldByName('RDB$TYPE_NAME').AsString); + if FieldTypeName = '' then + FieldTypeName := Format('[FieldType=%s FieldSubType=%s]', + [Fields.FieldByName('RDB$FIELD_TYPE').AsString, + Fields.FieldByName('RDB$FIELD_SUB_TYPE').AsString]); + DoWarning(Format(SUnsupportedColumnSkipped, + [TableMetadata.Name, FieldMetadata.Name, FieldTypeName])); + end; Fields.Next; end; finally @@ -211,38 +218,47 @@ end; end; -function TInstantIBFbCatalog.ColumnTypeToDataType(const ColumnType: string; - const BlobSubType, FieldScale: Integer; out DataType: TInstantDataType; - out AlternateDataTypes: TInstantDataTypes): Boolean; +function TInstantIBFbCatalog.ColumnTypeToDataType(const ColumnType: Integer; + const ColumnSubType, FieldScale: Integer; out DataType: TInstantDataType; + out AlternateDataTypes: TInstantDataTypes): Boolean; begin +{RDB$FIELDS.RDB$FIELD_TYPE values +\x95 BLOB - 261 \x95 BLOB_ID - 45 \x95 BOOLEAN - 17 \x95 CHAR - 14 \x95 CSTRING - 40 +\x95 D_FLOAT - 11 \x95 DOUBLE - 27 \x95 FLOAT - 10 \x95 INT64 - 16 \x95 INTEGER - 8 +\x95 QUAD - 9 \x95 SMALLINT - 7 \x95 DATE - 12 (dialect 3 DATE) \x95 TIME - 13 +\x95 TIMESTAMP - 35 \x95 VARCHAR - 37 +These values are always present in table metadata, +RDB$TYPES.RDB$TYPE_NAME is not always defined for all types } + AlternateDataTypes := []; Result := True; - { TODO : How to use FieldScale? } - if SameText(ColumnType, 'TEXT') or SameText(ColumnType, 'VARYING') then - DataType := dtString - else if SameText(ColumnType, 'SHORT') then - begin - DataType := dtBoolean; - Include(AlternateDataTypes, dtInteger); - end - else if SameText(ColumnType, 'LONG') then - DataType := dtInteger - else if SameText(ColumnType, 'FLOAT') or SameText(ColumnType, 'DOUBLE') then - DataType := dtFloat - else if SameText(ColumnType, 'TIMESTAMP') or SameText(ColumnType, 'DATE') - or SameText(ColumnType, 'TIME')then - DataType := dtDateTime - else if SameText(ColumnType, 'BLOB') then - begin - if BlobSubType = 1 then - DataType := dtMemo + case ColumnType of + 7: // SHORT/SMALLINT + begin + DataType := dtBoolean; + Include(AlternateDataTypes, dtInteger); + end; + 8: // INTEGER + DataType := dtInteger; + 10, 27: //FLOAT, DOUBLE + DataType := dtFloat; + 12,13,35: // DATE, TIME, TIMESTAMP - will need refactoring to support proposed TDate and TTime types + DataType := dtDateTime; + 14, 37: // TEXT, VARYING + DataType := dtString; + 16: // INT64 + if (ColumnSubType = 2) and (FieldScale >= -4) then + DataType := dtCurrency + else + Result := False; + 261: // BLOB + if ColumnSubType = 1 then + DataType := dtMemo + else + DataType := dtBlob; else - DataType := dtBlob; - end - else if SameText(ColumnType, 'INT64') then - DataType := dtCurrency - else - Result := False; + Result := False; + end; end; function TInstantIBFbCatalog.GetSelectFieldsSQL( @@ -251,7 +267,8 @@ Result := 'select ' + ' RF.RDB$FIELD_NAME, RF.RDB$NULL_FLAG, ' + - ' T.RDB$TYPE_NAME, F.RDB$FIELD_SUB_TYPE, F.RDB$FIELD_LENGTH, ' + + ' T.RDB$TYPE_NAME, ' + + ' F.RDB$FIELD_TYPE, F.RDB$FIELD_SUB_TYPE, F.RDB$FIELD_LENGTH, ' + ' F.RDB$FIELD_SCALE, F.RDB$CHARACTER_LENGTH ' + 'from ' + ' RDB$RELATION_FIELDS RF ' + @@ -259,7 +276,7 @@ ' RDB$FIELDS F ' + 'on ' + ' RF.RDB$FIELD_SOURCE = F.RDB$FIELD_NAME ' + - 'join ' + + 'left join ' + //Fix [ 1603022] ' RDB$TYPES T ' + 'on ' + ' F.RDB$FIELD_TYPE = T.RDB$TYPE ' + @@ -319,4 +336,62 @@ AddTableMetadatas(ATableMetadatas); end; + +{ A. test table definition + +CREATE TABLE "Test" +( + "Class" VARCHAR(32) NOT NULL, + "Id" VARCHAR(32) NOT NULL, + "UpdateCount" INTEGER, + "StringAttr" VARCHAR(256), + "BlobAttr" BLOB, + "BooleanAttr" SMALLINT, + "CurrencyAttr" DECIMAL(14,4), + "DateTimeAttr" TIMESTAMP, + "FloatAttr" DOUBLE PRECISION, + "GraphicAttr" BLOB, + "IntegerAttr" INTEGER, + "MemoAttr" BLOB SUB_TYPE 1, + "ReferenceAttributeClass" VARCHAR(32), + "ReferenceAttributeId" VARCHAR(32), + "EmbeddedPartsAtttribute" BLOB, + "EmbeddedPartAttribute" BLOB, + "ExternalPartAttributeClass" VARCHAR(32), + "ExternalPartAttributeId" VARCHAR(32), + "EmbeddedReferencesAtttribute" BLOB, + "DateAttr" DATE, + "TimeAttr" TIME, + PRIMARY KEY ("Class", "Id") +); + +B. Result of "GetSelectFieldsSQL" method - run against IB 7.1 Win32 server + +RDB$FIELD_NAME RDB$NULL_FLAG RDB$TYPE_NAME RDB$FIELD_TYPE RDB$FIELD_SUB_TYPE RDB$FIELD_LENGTH RDB$FIELD_SCALE RDB$CHARACTER_LENGTH +=============================== ============= =============================== ============== ================== ================ =============== ==================== +Class 1 VARYING 37 32 0 32 +Id 1 VARYING 37 32 0 32 +UpdateCount LONG 8 4 0 +StringAttr VARYING 37 256 0 256 +BlobAttr BLOB 261 0 8 0 +BooleanAttr SHORT 7 2 0 +CurrencyAttr 16 2 8 -4 +DateTimeAttr TIMESTAMP 35 8 0 +FloatAttr DOUBLE 27 8 0 +GraphicAttr BLOB 261 0 8 0 +IntegerAttr LONG 8 4 0 +MemoAttr BLOB 261 1 8 0 +ReferenceAttributeClass VARYING 37 32 0 32 +ReferenceAttributeId VARYING 37 32 0 32 +EmbeddedPartsAtttribute BLOB 261 0 8 0 +EmbeddedPartAttribute BLOB 261 0 8 0 +ExternalPartAttributeClass VARYING 37 32 0 32 +ExternalPartAttributeId VARYING 37 32 0 32 +EmbeddedReferencesAtttribute BLOB 261 0 8 0 +DateAttr DATE 12 4 0 +TimeAttr TIME 13 4 0 + +} + + end. |