Subject | Re: [IBO] KeyLinks and KeyLinksAutoDefine |
---|---|
Author | Martijn Tonies |
Post date | 2002-02-10T11:50:01Z |
Hi Geoff,
to me. However, just selecting FIRST_NAME from EMPLOYEE
seems to work fine... I have no idea (yet) why this case is so different.
ok - while writing this email - I did some debugging and I found where
it went wrong... I think there's a bit of a combination of factors here...
First, here's the DDL for the table that's giving the error:
CREATE TABLE IA_REPORT_RELOAD
(
ID INTEGER NOT NULL,
IA_REPORT_ID INTEGER NOT NULL,
RELOAD_ID INTEGER,
CONSTRAINT IA_REPORT_RELOAD PRIMARY KEY (ID)
)
Here's the statement that gives the problem:
SELECT RELOAD_ID FROM IA_REPORT_RELOAD
In the above table, you can see ID being the primary key column. In
IBA_Dataset.IMP, the method
function TIB_Dataset.GetKeyLinks: TIB_StringList;
seems to be the error...
In the below part some comments by me are added
===
TableName := SysKeyRelation;
if TableName <> '' then
begin
IB_Connection.SchemaCache.GetTableKeys( TableName, FKeyLinks );
if KeyLinksExist then
begin
SQLSelectStr := UpperCase(
StripLitsAndRounds(
StripComments( SQLSelect.Text ), SQLDialect ));
if Pos( '*', SQLSelectStr ) = 0 then
for ii := 0 to FKeyLinks.Count - 1 do
begin
tmpStr := UpperCase( FKeyLinks.IndexNames[ii] );
tmpPos := getLitSafePos( '.', tmpStr, 1 );
if tmpPos > 0 then
tmpStr := Copy( tmpStr, tmpPos + 1, MaxInt );
{
for employee, tmpStr will turn up EMP_NO - if I select FIRST_NAME,
there's no way that pos(tmpStr, SQLSelectStr) = 0 -> so, keylinks
get cleared, DB_KEY gets added
But, for SELECT RELOAD_ID FROM IA_REPORT_RELOAD -
tmpStr will become ID (PK column) and Pos(tmpStr, SQLSelectStr) gives
pos > 0 ----> no keylinks clear, no DB_KEY added --> error...
}
if Pos( tmpStr, SQLSelectStr ) = 0 then
begin
FKeyLinks.Clear;
Break;
end;
end;
end;
if not KeyLinksExist then
begin
FKeyLinks.Add( TableName + '.' + IB_RDB + IB_DB_KEY );
FKeyLinksAreDBKEY := true;
end;
FKeyLinksAutoDefined := KeyLinksExist;
end;
===
So I guess I can conclude in saying that the Pos function isn't the best way
to test here. The error seems to happen when you have a primary key column
(tmpStr) that has a name that's part of another column (SQLSelectStr) -
because Pos will find it, it assumes that this is the keylink. Wrong... But
I cannot think of an easy way to change it yet :)
Geoff, I hope you can reproduce the error as easy as me with the above DDL
and we both get the error at the same position in code - I guess we can find
a way to fix it now...
Thanks for your time,
Martijn Tonies
InterBase Workbench - the developer tool for InterBase and Firebird
http://www.interbaseworkbench.com
Upscene Productions
http://www.upscene.com
"This is an object-oriented system.
If we change anything, the users object."
> > You know what they say about 'assuming'? You make an 'ass' outThere's really not much to it - the problem seemed easy reproducable
> > of 'u' and 'me'... :) (ok, no offence)
>
> None taken, of course with limited information provided I either have
> to make assumptions or not bother answering.
to me. However, just selecting FIRST_NAME from EMPLOYEE
seems to work fine... I have no idea (yet) why this case is so different.
ok - while writing this email - I did some debugging and I found where
it went wrong... I think there's a bit of a combination of factors here...
First, here's the DDL for the table that's giving the error:
CREATE TABLE IA_REPORT_RELOAD
(
ID INTEGER NOT NULL,
IA_REPORT_ID INTEGER NOT NULL,
RELOAD_ID INTEGER,
CONSTRAINT IA_REPORT_RELOAD PRIMARY KEY (ID)
)
Here's the statement that gives the problem:
SELECT RELOAD_ID FROM IA_REPORT_RELOAD
In the above table, you can see ID being the primary key column. In
IBA_Dataset.IMP, the method
function TIB_Dataset.GetKeyLinks: TIB_StringList;
seems to be the error...
In the below part some comments by me are added
===
TableName := SysKeyRelation;
if TableName <> '' then
begin
IB_Connection.SchemaCache.GetTableKeys( TableName, FKeyLinks );
if KeyLinksExist then
begin
SQLSelectStr := UpperCase(
StripLitsAndRounds(
StripComments( SQLSelect.Text ), SQLDialect ));
if Pos( '*', SQLSelectStr ) = 0 then
for ii := 0 to FKeyLinks.Count - 1 do
begin
tmpStr := UpperCase( FKeyLinks.IndexNames[ii] );
tmpPos := getLitSafePos( '.', tmpStr, 1 );
if tmpPos > 0 then
tmpStr := Copy( tmpStr, tmpPos + 1, MaxInt );
{
for employee, tmpStr will turn up EMP_NO - if I select FIRST_NAME,
there's no way that pos(tmpStr, SQLSelectStr) = 0 -> so, keylinks
get cleared, DB_KEY gets added
But, for SELECT RELOAD_ID FROM IA_REPORT_RELOAD -
tmpStr will become ID (PK column) and Pos(tmpStr, SQLSelectStr) gives
pos > 0 ----> no keylinks clear, no DB_KEY added --> error...
}
if Pos( tmpStr, SQLSelectStr ) = 0 then
begin
FKeyLinks.Clear;
Break;
end;
end;
end;
if not KeyLinksExist then
begin
FKeyLinks.Add( TableName + '.' + IB_RDB + IB_DB_KEY );
FKeyLinksAreDBKEY := true;
end;
FKeyLinksAutoDefined := KeyLinksExist;
end;
===
So I guess I can conclude in saying that the Pos function isn't the best way
to test here. The error seems to happen when you have a primary key column
(tmpStr) that has a name that's part of another column (SQLSelectStr) -
because Pos will find it, it assumes that this is the keylink. Wrong... But
I cannot think of an easy way to change it yet :)
Geoff, I hope you can reproduce the error as easy as me with the above DDL
and we both get the error at the same position in code - I guess we can find
a way to fix it now...
Thanks for your time,
Martijn Tonies
InterBase Workbench - the developer tool for InterBase and Firebird
http://www.interbaseworkbench.com
Upscene Productions
http://www.upscene.com
"This is an object-oriented system.
If we change anything, the users object."