Subject | Re: [IBO] KeyLinks error |
---|---|
Author | Martijn Tonies |
Post date | 2002-03-08T13:08:16Z |
Hi Jason,
I quoted (part of) the original conversation below.
===
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 :)
===
Hope this helps,
--
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."
I quoted (part of) the original conversation below.
===
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 :)
===
Hope this helps,
--
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."
> I don't have any specific recollection. I would have to dig things up onit.
>error
> Jason Wharton
> CPS - Mesa AZ
> http://www.ibobjects.com
>
>
> > Hi Jason, Geoff,
> >
> > Some time ago, I reported an error with KeyLinksAutoDefine with a
> > reproducable piece of DDL and so on...
> >
> > We had quite some discussion on how to do what and why and how to solve
> this
> > error. I was wondering if there was any progress or talk about this
> in
> > order to get to a solution for this problem.
> >
> > Thanks,
> > --
> > Martijn Tonies
> > Upscene Productions
> >
> > InterBase Workbench - The Developer Tool for InterBase
> > http://www.interbaseworkbench.com
> >
> > "Experience is what you get when you didn't get what you wanted"
>
>
>