Subject | KeyLinks and KeyLinksAutoDefine |
---|---|
Author | Martijn Tonies |
Post date | 2002-02-08T18:51:57Z |
Hi,
I'm using KeyLinksAutoDefine = True to make a dataset editale (I cannot set
the keylinks myself). But if a query is done that doesn't include a key
column, this will fail with 'invalid keylinks entry'.... I've been tracing
this a bit and the keylinks are assembled from a method:
function TIB_Dataset.GetKeyLinks: TIB_StringList;
begin
...
IB_Connection.SchemaCache.GetTableKeys( TableName, FKeyLinks );
...
here, it finds a primary key column (which is not included in the SELECT
part of the query) -> hence, there are keylinks but not in the select part,
so it fails with an 'invalid key links entry'. That makes sense. But there's
another part:
...
if not KeyLinksExist then
begin
FKeyLinks.Add( TableName + '.' + IB_RDB + IB_DB_KEY );
FKeyLinksAreDBKEY := true;
end;
...
Now, that does make sense to me -> no keylinks, use RDB$DB_KEY to give it a
try...
(below is the complete method)
Is there a way (or a change) so that if there is a primary key column, but
the column isn't in the SELECT clause, it will also add the RDB$DB_KEY part
to the select and use this as key links?
Comments?
==
function TIB_Dataset.GetKeyLinks: TIB_StringList;
var
TableName: string;
SQLSelectStr: string;
tmpStr: string;
tmpPos: integer;
ii: integer;
begin
Result := FKeyLinks;
if flag_keylinks = 0 then
begin
// For some reason Delphi 5 Object inspector causes a reentrance problem
here.
Inc( flag_keylinks );
try
if PreparingSQL and
KeyLinksAutoDefine and
not KeyLinksExist and
not Assigned( FBindingCursor ) and
not SQLIsAggregate and
not SQLIsSelectProc and
not ( SQLUnion.Count > 0 ) then
begin
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 );
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;
end;
finally
Dec( flag_keylinks );
end;
end;
end;
===
--
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'm using KeyLinksAutoDefine = True to make a dataset editale (I cannot set
the keylinks myself). But if a query is done that doesn't include a key
column, this will fail with 'invalid keylinks entry'.... I've been tracing
this a bit and the keylinks are assembled from a method:
function TIB_Dataset.GetKeyLinks: TIB_StringList;
begin
...
IB_Connection.SchemaCache.GetTableKeys( TableName, FKeyLinks );
...
here, it finds a primary key column (which is not included in the SELECT
part of the query) -> hence, there are keylinks but not in the select part,
so it fails with an 'invalid key links entry'. That makes sense. But there's
another part:
...
if not KeyLinksExist then
begin
FKeyLinks.Add( TableName + '.' + IB_RDB + IB_DB_KEY );
FKeyLinksAreDBKEY := true;
end;
...
Now, that does make sense to me -> no keylinks, use RDB$DB_KEY to give it a
try...
(below is the complete method)
Is there a way (or a change) so that if there is a primary key column, but
the column isn't in the SELECT clause, it will also add the RDB$DB_KEY part
to the select and use this as key links?
Comments?
==
function TIB_Dataset.GetKeyLinks: TIB_StringList;
var
TableName: string;
SQLSelectStr: string;
tmpStr: string;
tmpPos: integer;
ii: integer;
begin
Result := FKeyLinks;
if flag_keylinks = 0 then
begin
// For some reason Delphi 5 Object inspector causes a reentrance problem
here.
Inc( flag_keylinks );
try
if PreparingSQL and
KeyLinksAutoDefine and
not KeyLinksExist and
not Assigned( FBindingCursor ) and
not SQLIsAggregate and
not SQLIsSelectProc and
not ( SQLUnion.Count > 0 ) then
begin
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 );
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;
end;
finally
Dec( flag_keylinks );
end;
end;
end;
===
--
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."