Access Firebird domain descriptions

Discussion of open issues, suggestions and bugs regarding IBDAC (InterBase Data Access Components) for Delphi, C++Builder, Lazarus (and FPC)
Post Reply
Roaster2
Posts: 51
Joined: Mon 13 Oct 2008 19:29

Access Firebird domain descriptions

Post by Roaster2 » Fri 12 Dec 2008 11:13

Hi,

you kindly added the DESCRIPTION field to the metadata component of IbDac in the latest build - thanks for this again!

I previously use the ZEOS library which I'm now replacing. The ZEOS metadata component was capable of fetching the DESCRIPTION of fields from the appropriate domain (if one exist).

This means I always got a description back no matter if I added one to the field itself or to its domain.
Why would I do this? The idea behind is to build up many domains with descriptions and linke one domain to a field. When altering the description each field automatically updated when fetching the DESCRTPTION via the ZEOS metadata component.

Using now IbDac this does not work anymore since the component just fetches the description from the field itself and not (additionally) from the appropriate domains.

Is there an easy way to get the same in IbDac again? Perhaps add a metadata kind 'domains' and a function to link the columns and domains metadata together to get the description of the domain?

cu,
Michael

Plash
Devart Team
Posts: 2844
Joined: Wed 10 May 2006 07:09

Post by Plash » Mon 15 Dec 2008 08:49

We have changed the TIBCMetaData component to take a description of the domain if field description is empty. This fix will be included in the next IBDAC build. You can also use your own queries to system tables instead of TIBCMetaData. For example:

Code: Select all

SELECT RF.RDB$RELATION_NAME, RF.RDB$FIELD_NAME,
  RF.RDB$FIELD_POSITION, F.RDB$FIELD_TYPE, F.RDB$FIELD_SUB_TYPE,
  F.RDB$FIELD_LENGTH, F.RDB$FIELD_PRECISION, F.RDB$FIELD_SCALE,
  RF.RDB$NULL_FLAG, RF.RDB$DEFAULT_VALUE,
  CASE WHEN RF.RDB$DESCRIPTION IS NOT NULL THEN RF.RDB$DESCRIPTION ELSE F.RDB$DESCRIPTION END
FROM RDB$RELATION_FIELDS RF
  INNER JOIN RDB$FIELDS F ON (RF.RDB$FIELD_SOURCE = F.RDB$FIELD_NAME)
WHERE RF.RDB$RELATION_NAME = 'TEST10'
ORDER BY RF.RDB$FIELD_POSITION

Roaster2
Posts: 51
Joined: Mon 13 Oct 2008 19:29

Post by Roaster2 » Mon 15 Dec 2008 09:12

Thanks Plash for this coding and good news!

I know I can use a query like the one from the ZEOS source, however I rather would see this in the TIBCMetadata component and to be officially supported :lol:
I guess that others would benefit from this change, too.

Any chance to send me this update via PM to my forum account?

cu,
Michael

Roaster2
Posts: 51
Joined: Mon 13 Oct 2008 19:29

Post by Roaster2 » Thu 18 Dec 2008 09:12

Plash,

I've now inserted the line

Code: Select all

CASE WHEN RF.RDB$DESCRIPTION IS NOT NULL THEN RF.RDB$DESCRIPTION ELSE F.RDB$DESCRIPTION END 
into the SQL statement, IbDac uses when fetching metadata in unit IBClasses, function TGDSMetaData.GetColumns(Restrictions: _TStrings): TData;
I recompiled IbDac using the make.bat.

I'm using packages (ibdac100.bpl) in my application and now encounter an AV when executing this piece of code:

Code: Select all

    
var
  MetaData : TIBCMetaData;
  S : string;
begin
  MetaData := TIBCMetaData.Create(Nil);
  MetaData.Connection := FConnection;
  MetaData.MetaDataKind := 'Columns';
  MetaData.Restrictions.Values['TABLE_NAME'] := TableName;
  MetaData.Active := True;
  while not MetaData.Eof do
  begin
    S := MetaData.FieldByName('DESCRIPTION').AsString;
    MetaData.Next;
  end;
end;
The AV happens when setting MetaData.Active to True. The call stack is as follows:

Code: Select all

main thread ($5c4):
51f2415e +0b6 rtl100.bpl       system          3707  +75 System.Move
00345e5f +063 ibdac100.bpl     Ibccall                   StringToPtrGDS
00352854 +218 ibdac100.bpl     Ibcclasses                TGDSRecordSet.InternalInitFields
005faa93 +01f dac100.bpl       Memdata                   TData.InitFields
00602789 +005 dac100.bpl       Memdata                   TMemData.InitFields
0035291f +007 ibdac100.bpl     Ibcclasses                TGDSRecordSet.InitFields
00350d6c +0bc ibdac100.bpl     Ibcclasses                TGDSRecordSet.ExecFetch
0060ca53 +02f dac100.bpl       Craccess                  TCRRecordSet.InternalOpen
00350b7f +007 ibdac100.bpl     Ibcclasses                TGDSRecordSet.InternalOpen
005fa361 +035 dac100.bpl       Memdata                   TData.Open
00602720 +000 dac100.bpl       Memdata                   TMemData.Open
0060cb84 +000 dac100.bpl       Craccess                  TCRRecordSet.Open
003556c1 +0cd ibdac100.bpl     Ibcclasses                TGDSMetaData.GetColumns
0060e6fc +08c dac100.bpl       Craccess                  TCRMetaData.InternalGetMetaData
00354ddc +028 ibdac100.bpl     Ibcclasses                TGDSMetaData.InternalGetMetaData
0060e63c +054 dac100.bpl       Craccess                  TCRMetaData.GetMetaData
0063ae1d +03d dac100.bpl       Dbaccess                  TDAMetaData.InternalOpen
5233f069 +019 dbrtl100.bpl     DB              9259   +2 DB.TDataSet.DoInternalOpen
5233f122 +01e dbrtl100.bpl     DB              9288   +4 DB.TDataSet.OpenCursor
00614dbe +00a dac100.bpl       Memds                     TMemDataSet.OpenCursor
0063ad3d +07d dac100.bpl       Dbaccess                  TDAMetaData.OpenCursor
5233efdd +055 dbrtl100.bpl     DB              9241  +12 DB.TDataSet.SetActive
036be577 +0ab CustomerEdit.bpl uDBDescription   211   +9 uDBDescription.TDBDescription.DBFetchColumnMetaData
FYI when not using packages this works without any AV. When removing the new SQL line, no AVs either. So this happens only when using packages with this new line.

So why does this happen?

Roaster2
Posts: 51
Joined: Mon 13 Oct 2008 19:29

Post by Roaster2 » Thu 18 Dec 2008 09:46

Plash,

it seems that this is not related to this new SQL line but to the Unicode settings I've done.
I've set TIBConnection.Options.Charset to UTF8 and TIBConnection.Options.UseUnicode to True.

The AV occurs in

Code: Select all

procedure GetBlobCharset(Field: TIBCFieldDesc; const FldTableName: _string); 
at this line:

Code: Select all

TableName := StringToPtrGDS(FldTableName, FConnection.FUseUnicode);
or better at this line:

Code: Select all

function StringToPtrGDS(const S: _string; UseUnicode: boolean): PStr;
{$IFNDEF CLR}
var
  Size: integer;
  Str: AnsiString;
{$ENDIF}
begin
  if UseUnicode then begin
  {$IFNDEF CLR}
    Str := UTF8Encode(S);
    Size := Length(Str) + 1;
    GetMem(Result, Size);
    Move(Str[1], Result^, Size); <<< Here I get the AV
At the time when the AV occurs, FldTableName is initial. There is no content in this var. I guess this is more or less a problem that a parser does not recognize that 'CASE WHEN...' are no SQL statements at all.

So could you please tell me how to fix this? I guess I need a different SQL statement for fetching the descriptions of the domains at the end.

Thanks!

Plash
Devart Team
Posts: 2844
Joined: Wed 10 May 2006 07:09

Post by Plash » Thu 18 Dec 2008 11:24

We have fixed this problem. The fix will be included in the next build of IBDAC.

Roaster2
Posts: 51
Joined: Mon 13 Oct 2008 19:29

Post by Roaster2 » Thu 18 Dec 2008 11:45

Thanks again - have a nice day!

Roaster2
Posts: 51
Joined: Mon 13 Oct 2008 19:29

Post by Roaster2 » Wed 07 Jan 2009 09:19

Hi Plash,

is the fix for this already included in the latest build 44?

Plash
Devart Team
Posts: 2844
Joined: Wed 10 May 2006 07:09

Post by Plash » Thu 08 Jan 2009 08:40

Yes, the fix is included in IBDAC 2.70.0.44.

Post Reply