[fpc-devel] TFieldDef.Size vs TField.Size

LacaK lacak at zoznam.sk
Thu Feb 24 10:59:40 CET 2011


>
>> Hi,
>> I am writting here to discuss bug 
>> http://bugs.freepascal.org/view.php?id=17268
>> (I do not want reopen bug and writte there because I am not sure 
>> about my arguments)
>>
>> IMHO root of problem is in different definition of TFieldDef.Size and 
>> TField.Size
>> Documentation says, that
>> 1. TFieldDef.Size should be "For string and byte fields, *Size* is 
>> the number of bytes reserved "
>>   http://docwiki.embarcadero.com/VCL/en/DB.TFieldDef.Size
>> 2. TField.Size should be "the maximum number of characters in the 
>> string" (for ftString and I guess that also for ftWideString)
>>   http://docwiki.embarcadero.com/VCL/en/DB.TField.Size
>>   http://docwiki.embarcadero.com/VCL/en/DB.TStringField.Size
>>
>> And now let's go look into fields.inc:
>> 1. Function TFieldDef.CreateField copies Result.Size:=FSize (so 
>> TField.Size:=TFieldDef.Size)
>> 2. function TStringField.GetDataSize returns for ftString ... Size+1
>> 3. function TWideStringField.GetDataSize returns for ftWideString ... 
>> (Size + 1) * 2
>>
>> Points 2,3 are clear Size is expected to be number of characters, 
>> DataSize number of bytes.
>> But point 1 says, that TFieldDef.Size and TField.Size should be the same
>>
>> And now let's go look into bufdataset.pas:
>> 4. function TCustomBufDataset.GetFieldSize works with TFieldDef and 
>> returns number of bytes needed in record buffer
>> case FieldDef.DataType of
>>   ftString, ftGuid, ftFixedChar: result := FieldDef.Size + 1;
>>   ftFixedWideChar, ftWideString:result := (FieldDef.Size + 1)*2;
>>   ...
>> So also here we can see, that FieldDef.Size is expected to be number 
>> of characters not bytes.
>>
>> So IMHO logical conclusion will be say, that TFieldDef.Size for 
>> string fields has same menaing as Field.Size, so it is number of 
>> characters
>
> Correct, if you assume 1 char = 1 byte.
>
>> (so documentation is wrong in this case ... also fast test in Delphi 
>> shows, that FieldDef.Size=Field.Size=number of characters)
>
> Your story is confusing to me. Where do you see a problem ?
See please 
http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/packages/fcl-db/src/sqldb/odbc/odbcconn.pas?r1=16094&r2=16988
And look at ftWideString, ftFixedWideChar cases
What happens if we have NVARCHAR(20) column on MS SQL Server (uses UCS-2 
1char=2bytes):
1. in AddFieldDefs method is created TFieldDef object with Size=20*2 
(because FieldSize:=ColumnSize*sizeof(Widechar))
2. later when TField objects are created in TFieldDef.CreateField 
method, TWideString object is created with Size=40 (because Size is 
copied from TFieldDef object) ... and this is wrong, because:
  2.1 TWideString.Size should IMO return max.number of characters ... 
Size is used for example in data-aware controls to limit MaxLength
  2.2 TWideStringField.GetDataSize will return 82, which is also wrong 
(because (40+1)*2)
  2.3 in record buffer will be allocated also 82 bytes (because of 
TCustomBufDataset.GetFieldSize)

So IMO correct will be in step 1 FieldSize:=ColumnSize not 
FieldSize:=ColumnSize*sizeof(WideChar)
(like in my original fix in bug report)

Note also, that Size is used (also in Delphi) to limit the number of 
characters in data-aware controls (for ftString, ftWideString), so it 
must be number of characters in both cases.

>
> Do you see an implementation problem or a documentation problem ?
Implementation problem at first
but also Documentation is confusing, because do not clearly says about 
menaing of TWideStringField.Size (only indirect guess can be done, that 
it is inherited from TStringField.Size, so it is number of characters)
See, that also other users are confusing by it 
https://forums.embarcadero.com/thread.jspa?messageID=188792

>
> Note that nowhere in the documentation pages you mention, widestrings are
> mentioned (which is convenient, since that's where 1 char <> 1 byte).
>
Yes, but in Delphi6 help is for TWideStringField.DataSize:
"Inspect DataSize to determine the number of bytes required to store the 
fields value. Use DataSize to determine the size needed for a buffer 
when working with the GetData and SetData methods.
For wide string fields, DataSize is the value of the Size property plus 
one (for the trailing NULL character), multiplied by two."

So we can estimate, that Size is number of characters, while 
DataSize=(Size+1)*2

Laco.




More information about the fpc-devel mailing list