View Issue Details

IDProjectCategoryView StatusLast Update
0027766FPCFCLpublic2019-09-09 09:16
ReporterTony WhymanAssigned ToMichael Van Canneyt 
PrioritynormalSeverityminorReproducibilityhave not tried
Status resolvedResolutionfixed 
PlatformAMD64OSLinux MintOS Version17
Product Version2.6.4Product Build 
Target VersionFixed in Version3.3.1 
Summary0027766: TFieldDef does not support Multibyte character sets
DescriptionTField.DisplayWidth provides the actual character width for displaying a field (e.g. a string) as distinct from TField.Size which is the storage size for the string. With multibyte character sets, Display Width should typically be the Field Size divided by the max. number of bytes per character.

However, TFieldDef only supports the field size and not the display width or bytes per character. There is thus no direct means for a database driver to communicate the use of multibyte character sets to a TField e.g. when it is created by TFieldDef.CreateField.
Steps To ReproduceThe attached patch adds a new property to TFieldDef and TStringField This is CharSetWidth. This is the number of bytes per character and defaults to 1.When TFieldDef.CreateField creates a TStringField, it passes the property value on to the TStringField.

For TStringField, the DefaultWidth is the calculated as FSize div FCharSetWidth unless explicitly set by the user.
Additional InformationThis problem can be worked around. For example, in IBX i have experimented with encoding both field size and char width in the TFieldDef.Size then decoding it in TIBStringField. However, a clean way to do this is very desirable.
TagsNo tags attached.
Fixed in Revision
FPCOldBugId
FPCTarget3.2.0
Attached Files
  • TFieldDef.patch (3,138 bytes)
    diff -rupN fpc-2.6.4/packages/fcl-db/src/base/db.pas fpc-2.6.4.update/packages/fcl-db/src/base/db.pas
    --- fpc-2.6.4/packages/fcl-db/src/base/db.pas	2013-11-18 09:48:30.000000000 +0000
    +++ fpc-2.6.4.update/packages/fcl-db/src/base/db.pas	2015-04-01 09:57:30.323605845 +0100
    @@ -174,9 +174,11 @@ type
         FPrecision : Longint;
         FRequired : Boolean;
         FSize : Integer;
    +    FCharSetWidth: Integer;
         FAttributes : TFieldAttributes;
         Function GetFieldClass : TFieldClass;
         procedure SetAttributes(AValue: TFieldAttributes);
    +    procedure SetCharSetWidth(AValue: Integer);
         procedure SetDataType(AValue: TFieldType);
         procedure SetPrecision(const AValue: Longint);
         procedure SetSize(const AValue: Integer);
    @@ -197,6 +199,7 @@ type
         property DataType: TFieldType read FDataType write SetDataType;
         property Precision: Longint read FPrecision write SetPrecision;
         property Size: Integer read FSize write SetSize;
    +    property CharSetWidth: Integer read FCharSetWidth write SetCharSetWidth default 1;
       end;
     
     { TFieldDefs }
    @@ -453,6 +456,7 @@ type
       private
         FFixedChar     : boolean;
         FTransliterate : Boolean;
    +    FCharSetWidth  : Integer;
       protected
         class procedure CheckTypeSize(AValue: Longint); override;
         function GetAsBoolean: Boolean; override;
    @@ -480,6 +484,7 @@ type
       published
         property EditMask;
         property Size default 20;
    +    property CharSetWidth: Integer read FCharSetWidth write FCharSetWidth default 1;
       end;
     
     { TWideStringField }
    diff -rupN fpc-2.6.4/packages/fcl-db/src/base/fields.inc fpc-2.6.4.update/packages/fcl-db/src/base/fields.inc
    --- fpc-2.6.4/packages/fcl-db/src/base/fields.inc	2013-09-12 13:06:07.000000000 +0100
    +++ fpc-2.6.4.update/packages/fcl-db/src/base/fields.inc	2015-04-01 09:58:27.367218836 +0100
    @@ -33,6 +33,7 @@ Constructor TFieldDef.Create(ACollection
     begin
       Inherited create(ACollection);
       FFieldNo:=Index+1;
    +  FCharSetWidth := 1;
     end;
     
     Constructor TFieldDef.Create(AOwner: TFieldDefs; const AName: string;
    @@ -48,6 +49,7 @@ begin
       FSize:=ASize;
       FRequired:=ARequired;
       FPrecision:=-1;
    +  FCharSetWidth := 1;
       FFieldNo:=AFieldNo;
     end;
     
    @@ -111,6 +113,8 @@ begin
           TBCDField(Result).Precision:=FPrecision;
         if (Result is TFmtBCDField) then
           TFmtBCDField(Result).Precision:=FPrecision;
    +    if Result is TStringField then
    +      TStringField(Result).CharSetWidth := FCharSetWidth;
       except
         Result.Free;
         Raise;
    @@ -124,6 +128,12 @@ begin
       Changed(False);
     end;
     
    +procedure TFieldDef.SetCharSetWidth(AValue: Integer);
    +begin
    +  FCharSetWidth := AValue;
    +  Changed(False);
    +end;
    +
     procedure TFieldDef.SetDataType(AValue: TFieldType);
     begin
       FDataType := AValue;
    @@ -1016,6 +1026,7 @@ begin
       FFixedChar := False;
       FTransliterate := False;
       FSize:=20;
    +  FCharSetWidth := 1;
     end;
     
     procedure TStringField.SetFieldType(AValue: TFieldType);
    @@ -1089,7 +1100,7 @@ end;
     function TStringField.GetDefaultWidth: Longint;
     
     begin
    -  result:=Size;
    +  result:=Size div FCharSetWidth;
     end;
     
     Procedure TStringField.GetText(var AText: string; ADisplayText: Boolean);
    
    TFieldDef.patch (3,138 bytes)

Relationships

related to 0025801 resolvedMichael Van Canneyt TStringField may return wrong size for TStringField.DataSize 

Activities

Tony Whyman

2015-04-01 11:06

reporter  

TFieldDef.patch (3,138 bytes)
diff -rupN fpc-2.6.4/packages/fcl-db/src/base/db.pas fpc-2.6.4.update/packages/fcl-db/src/base/db.pas
--- fpc-2.6.4/packages/fcl-db/src/base/db.pas	2013-11-18 09:48:30.000000000 +0000
+++ fpc-2.6.4.update/packages/fcl-db/src/base/db.pas	2015-04-01 09:57:30.323605845 +0100
@@ -174,9 +174,11 @@ type
     FPrecision : Longint;
     FRequired : Boolean;
     FSize : Integer;
+    FCharSetWidth: Integer;
     FAttributes : TFieldAttributes;
     Function GetFieldClass : TFieldClass;
     procedure SetAttributes(AValue: TFieldAttributes);
+    procedure SetCharSetWidth(AValue: Integer);
     procedure SetDataType(AValue: TFieldType);
     procedure SetPrecision(const AValue: Longint);
     procedure SetSize(const AValue: Integer);
@@ -197,6 +199,7 @@ type
     property DataType: TFieldType read FDataType write SetDataType;
     property Precision: Longint read FPrecision write SetPrecision;
     property Size: Integer read FSize write SetSize;
+    property CharSetWidth: Integer read FCharSetWidth write SetCharSetWidth default 1;
   end;
 
 { TFieldDefs }
@@ -453,6 +456,7 @@ type
   private
     FFixedChar     : boolean;
     FTransliterate : Boolean;
+    FCharSetWidth  : Integer;
   protected
     class procedure CheckTypeSize(AValue: Longint); override;
     function GetAsBoolean: Boolean; override;
@@ -480,6 +484,7 @@ type
   published
     property EditMask;
     property Size default 20;
+    property CharSetWidth: Integer read FCharSetWidth write FCharSetWidth default 1;
   end;
 
 { TWideStringField }
diff -rupN fpc-2.6.4/packages/fcl-db/src/base/fields.inc fpc-2.6.4.update/packages/fcl-db/src/base/fields.inc
--- fpc-2.6.4/packages/fcl-db/src/base/fields.inc	2013-09-12 13:06:07.000000000 +0100
+++ fpc-2.6.4.update/packages/fcl-db/src/base/fields.inc	2015-04-01 09:58:27.367218836 +0100
@@ -33,6 +33,7 @@ Constructor TFieldDef.Create(ACollection
 begin
   Inherited create(ACollection);
   FFieldNo:=Index+1;
+  FCharSetWidth := 1;
 end;
 
 Constructor TFieldDef.Create(AOwner: TFieldDefs; const AName: string;
@@ -48,6 +49,7 @@ begin
   FSize:=ASize;
   FRequired:=ARequired;
   FPrecision:=-1;
+  FCharSetWidth := 1;
   FFieldNo:=AFieldNo;
 end;
 
@@ -111,6 +113,8 @@ begin
       TBCDField(Result).Precision:=FPrecision;
     if (Result is TFmtBCDField) then
       TFmtBCDField(Result).Precision:=FPrecision;
+    if Result is TStringField then
+      TStringField(Result).CharSetWidth := FCharSetWidth;
   except
     Result.Free;
     Raise;
@@ -124,6 +128,12 @@ begin
   Changed(False);
 end;
 
+procedure TFieldDef.SetCharSetWidth(AValue: Integer);
+begin
+  FCharSetWidth := AValue;
+  Changed(False);
+end;
+
 procedure TFieldDef.SetDataType(AValue: TFieldType);
 begin
   FDataType := AValue;
@@ -1016,6 +1026,7 @@ begin
   FFixedChar := False;
   FTransliterate := False;
   FSize:=20;
+  FCharSetWidth := 1;
 end;
 
 procedure TStringField.SetFieldType(AValue: TFieldType);
@@ -1089,7 +1100,7 @@ end;
 function TStringField.GetDefaultWidth: Longint;
 
 begin
-  result:=Size;
+  result:=Size div FCharSetWidth;
 end;
 
 Procedure TStringField.GetText(var AText: string; ADisplayText: Boolean);
TFieldDef.patch (3,138 bytes)

Michael Van Canneyt

2019-09-09 09:16

administrator   ~0118002

I noticed this bug is still open.

This has meanwhile been resolved differently by adding a CodePage property to TFieldDef and TStringField - it was needed to handle codepages correctly.
The new CharSize property of TFieldDef is not settable but is calculated and takes into account the codepage for single byte strings.

Issue History

Date Modified Username Field Change
2015-04-01 11:06 Tony Whyman New Issue
2015-04-01 11:06 Tony Whyman File Added: TFieldDef.patch
2015-04-06 15:24 Michael Van Canneyt Assigned To => Michael Van Canneyt
2015-04-06 15:24 Michael Van Canneyt Status new => assigned
2015-04-06 18:40 Michael Van Canneyt Relationship added related to 0025801
2019-09-09 09:16 Michael Van Canneyt Status assigned => resolved
2019-09-09 09:16 Michael Van Canneyt Resolution open => fixed
2019-09-09 09:16 Michael Van Canneyt Fixed in Version => 3.3.1
2019-09-09 09:16 Michael Van Canneyt FPCTarget => 3.2.0
2019-09-09 09:16 Michael Van Canneyt Note Added: 0118002