Linux Advantage Database Server/TdaMetaCache.GetFields error
Hi,
I hope this help somebody...
This post regards the TdaMetaCache.GetFields error that some people have
reported. This error occurs when trying to preview reports with AutoSearch
fields and without a data dictionary. It has bearing on some configurations
of the Advantage Database Server for Linux.
I had various problems and I think found what the problem is. The interface
daADS.pas which handles the Advantage support has a function procedure
TdaADSSession.GetTableNames(const aDatabaseName: String; aList: TStrings)
which tries to build a list of the table names (which is then used by the
ReportBuilder's metacache). It does this by determining the actual physical
location of the data and then filling a stringlist with the results of a
FindFirst/FindNext. If it cannot read the physical location properly then
this will fail and the list of tables will be empty.
In short, I think the usual problem is that client machines don't have
access to the directory where the data is located.
This problem re-emerges with the new Linux ADS. There are new ways of
specifying the server connection in ads.ini such as specifying the port
within the UNC, e.g., MyData=\\10.0.0.1:6010\mydata. daADS.pas will then
try to do a directory listing of \\10.0.0.1:6010\mydata which will fail
because the port number is in there. One solution is to specify the
connection as follows (in ads.ini):
[Databases]
MyData=\\mylinux\mydata;A
[mylinux]
LAN_IP=10.0.0.1
LAN_PORT=6010
Another solution is to replace the TdaADSSession.GetTableNames procedure
with the following which tries various methods in an effort to catch most
configuration possibilities. It tries to ask the server with GetTableNames.
If that fails then it tries to modify the connection path to remove any port
specifications before building the list as before.
procedure TdaADSSession.GetTableNames(const aDatabaseName: String; aList:
TStrings);
var
lsPath: string;
lType: TAdsTableTypes;
liFind: Integer;
liIndex: integer;
lSearchRec: TSearchRec;
lsAlias: String;
lADSConnection: TADSConnection;
iPos: Integer;
lsNewPath: AnsiString;
begin
{this function has been rewritten by ra 11JAN2002 to handle Linux server
better}
aList.Clear;
{get the Alias for this database name}
lsAlias := daGetADSAliasForDatabaseName(aDatabaseName);
{get the path information for the database}
if not daGetADSDatabaseInfo(lsAlias, lsPath, lType) then
begin
lsPath:= aDatabaseName;
lType:= ttADSAdt;
end;
lsPath:= daAddBackSlash(lsPath);
{try asking the server}
lADSConnection := daGetADSConnectionForName(aDatabaseName);
lAdsConnection.Connect;
lAdsConnection.GetTableNames(aList, '');
if aList.Count > 0 then
begin
for liFind := 0 to aList.Count - 1 do
begin
liIndex := pos('.', aList[liFind]);
if liIndex > 0 then
aList[liFind] := (Copy(aList[liFind], 1, liIndex-1) );
end;
end
else
begin
{if that didn't work, try modifying the path to cater for Linux server
port format}
iPos := Pos(':', lsPath);
if ((Pos('\\', lsPath) = 1) or (Pos('//', lsPath) = 1)) and (iPos > 2)
then
begin
lsNewPath := Copy(lsPath, 1, iPos - 1);
lsPath := Copy(lsPath, 3, Length(lsPath));
iPos := Pos('\', lsPath);
if iPos = 0 then
iPos := Pos('/', lsPath);
lsNewPath := lsNewPath + Copy(lsPath, iPos, Length(lsPath));
lsPath := lsNewPath;
if not DirectoryExists(lsPath) then
raise Exception.Create('ADS/ReportBuilder problem trying to list the
databases on the server' + #13#10 + 'Could not get access to ' + lsPath);
end;
{now find the files the hard way}
if lType = ttAdsADT then
lsPath := lsPath+'*.ADT'
else
lsPath := lsPath+'*.DBF';
{build list of the files in the directory}
liFind := FindFirst(lsPath, 0, lSearchRec);
while (liFind = 0) do
begin
liIndex := pos('.', lSearchRec.name);
if liIndex >0 then
aList.Append(Copy(lSearchRec.name, 1, liIndex-1) )
else
aList.Append(lSearchRec.name);
liFind := FindNext(lSearchRec);
end;
end;
end; {procedure, GetTableNames}
I hope this help somebody...
This post regards the TdaMetaCache.GetFields error that some people have
reported. This error occurs when trying to preview reports with AutoSearch
fields and without a data dictionary. It has bearing on some configurations
of the Advantage Database Server for Linux.
I had various problems and I think found what the problem is. The interface
daADS.pas which handles the Advantage support has a function procedure
TdaADSSession.GetTableNames(const aDatabaseName: String; aList: TStrings)
which tries to build a list of the table names (which is then used by the
ReportBuilder's metacache). It does this by determining the actual physical
location of the data and then filling a stringlist with the results of a
FindFirst/FindNext. If it cannot read the physical location properly then
this will fail and the list of tables will be empty.
In short, I think the usual problem is that client machines don't have
access to the directory where the data is located.
This problem re-emerges with the new Linux ADS. There are new ways of
specifying the server connection in ads.ini such as specifying the port
within the UNC, e.g., MyData=\\10.0.0.1:6010\mydata. daADS.pas will then
try to do a directory listing of \\10.0.0.1:6010\mydata which will fail
because the port number is in there. One solution is to specify the
connection as follows (in ads.ini):
[Databases]
MyData=\\mylinux\mydata;A
[mylinux]
LAN_IP=10.0.0.1
LAN_PORT=6010
Another solution is to replace the TdaADSSession.GetTableNames procedure
with the following which tries various methods in an effort to catch most
configuration possibilities. It tries to ask the server with GetTableNames.
If that fails then it tries to modify the connection path to remove any port
specifications before building the list as before.
procedure TdaADSSession.GetTableNames(const aDatabaseName: String; aList:
TStrings);
var
lsPath: string;
lType: TAdsTableTypes;
liFind: Integer;
liIndex: integer;
lSearchRec: TSearchRec;
lsAlias: String;
lADSConnection: TADSConnection;
iPos: Integer;
lsNewPath: AnsiString;
begin
{this function has been rewritten by ra 11JAN2002 to handle Linux server
better}
aList.Clear;
{get the Alias for this database name}
lsAlias := daGetADSAliasForDatabaseName(aDatabaseName);
{get the path information for the database}
if not daGetADSDatabaseInfo(lsAlias, lsPath, lType) then
begin
lsPath:= aDatabaseName;
lType:= ttADSAdt;
end;
lsPath:= daAddBackSlash(lsPath);
{try asking the server}
lADSConnection := daGetADSConnectionForName(aDatabaseName);
lAdsConnection.Connect;
lAdsConnection.GetTableNames(aList, '');
if aList.Count > 0 then
begin
for liFind := 0 to aList.Count - 1 do
begin
liIndex := pos('.', aList[liFind]);
if liIndex > 0 then
aList[liFind] := (Copy(aList[liFind], 1, liIndex-1) );
end;
end
else
begin
{if that didn't work, try modifying the path to cater for Linux server
port format}
iPos := Pos(':', lsPath);
if ((Pos('\\', lsPath) = 1) or (Pos('//', lsPath) = 1)) and (iPos > 2)
then
begin
lsNewPath := Copy(lsPath, 1, iPos - 1);
lsPath := Copy(lsPath, 3, Length(lsPath));
iPos := Pos('\', lsPath);
if iPos = 0 then
iPos := Pos('/', lsPath);
lsNewPath := lsNewPath + Copy(lsPath, iPos, Length(lsPath));
lsPath := lsNewPath;
if not DirectoryExists(lsPath) then
raise Exception.Create('ADS/ReportBuilder problem trying to list the
databases on the server' + #13#10 + 'Could not get access to ' + lsPath);
end;
{now find the files the hard way}
if lType = ttAdsADT then
lsPath := lsPath+'*.ADT'
else
lsPath := lsPath+'*.DBF';
{build list of the files in the directory}
liFind := FindFirst(lsPath, 0, lSearchRec);
while (liFind = 0) do
begin
liIndex := pos('.', lSearchRec.name);
if liIndex >0 then
aList.Append(Copy(lSearchRec.name, 1, liIndex-1) )
else
aList.Append(lSearchRec.name);
liFind := FindNext(lSearchRec);
end;
end;
end; {procedure, GetTableNames}
This discussion has been closed.
Comments
Cheers,
Jim Bennett
Digital Metaphors
http://www.digital-metaphors.com
info@digital-metaphors.com