louis wrote: ↑25.09.2023, 11:59
Bookmarks are not safe for my needs but RDB$DB_KEY seems safe to me:
It is persistent in the tables until backup/restore and is unique in the table. Sure, it can be reused after the garbage collector cleans up the data, but when i need DB_KEY there is ever a live transaction that the GC can't clean up then:
Before modifying a record I can try to locate a record that contains an RDB$DB_KEY to see if it still exists.
You might want to be careful. This is what
IBPhoenix has to say about the life time of RDB$DB_KEY:
wrote:The duration of db_keys is a point that's not very clear in the manuals unless you read with sharp eye the API Reference Guide. By default, a db_key is valid only for the duration of the current transaction. After you use Commit or Rollback, the db_key values you had are inaccurate. If you are using auto-commit, you still can use db_keys because this mode uses an implicit CommitRetaining, that means the transaction context is retained, so garbage collection cannot proceed and hence, the db_keys used remain valid until you do a "hard" Commit.
So - if you see changes to the database, you also might see the RDB$DB_KEY value change if a record changes - because the adddress in the database changes.
louis wrote: ↑25.09.2023, 11:59
Now do I have to edit all queries by adding ", RDB$.DB_KEY" or is there a function in Zeos that returns the DBKey of each record like the "RecNo" tables in Paradox?
There is no magic bullet here. Zeos doesn't automagically extend your query to include RDB$DB_KEY. Even if it did, there would be ambiguities as soon as you do a join. So if you want to use RDB$DB_KEY, you will have to extend your queries.
Another option might be to determine the primary key for the data you have. TZQuery.DbcResultSet.GetMetadata.GetTableName() will help you in identifying the table(s) for your current query. Use TZSQLMetadata to fetch the primary key of that table. Then use that information for checking if the record still exists.
Something like this can get you started:
Code: Select all
uses ZAbstractRODataset, ZDBCIntfs;
function GetTableName(Query: TZAbstractRODataset): String;
var
MD: IZResultSetMetadata;
TableName: String;
x: Integer;
begin
MD := Query.DbcResultSet.GetMetadata;
TableName := '';
for x := FirstDbcIndex to MD.GetColumnCount - FirstDbcIndex do begin
if TableName = '' then begin; //no table name found yet
TableName := MD.GetTableName(x);
end else begin // table name found. Make sure, it is only one table.
if (TableName <> MD.GetTableName(x)) and (MD.GetTableName(x) <> '') then
raise Exception.Create('Cannot determine primary key. More than one table name found in Query: ' + TableName + ' and ' + MD.GetTableName(x));
end;
end;
end;