referential integrity problem using DbiDoRestructure

i'm using DbiDoRestructure to add referential integrity to paradox
tables. there's no problem if some RI has previously been defined (say,
using Database Desktop), or more specifically, if the *.X02, *.X03 etc.
files already exist .

but if it's the first time i try to create a RI, nothing happens (no error, no
RI created, nothing). can anybody guess what's going on?

if Master.Exclusive = False then
raise EDatabaseError.Create('Table: ' + Master.TableName +
' must be opened exclusively');
if Detail.Exclusive = False then
raise EDatabaseError.Create('Table: ' + Detail.TableName +
' must be opened exclusively');

// Make sure the tables are opened with an index and get their descriptors...
FillChar(DIndex, sizeof(DIndex), 0);
FillChar(MIndex, sizeof(MIndex), 0);
Check(DbiGetIndexDesc(Detail.Handle, 0, DIndex));
Check(DbiGetIndexDesc(Master.Handle, 0, MIndex));

// If the table is not a Paradox table, raise an error...
if (MasterProps.szTableType <> szPARADOX) and
(MasterProps.szTableType <> szDBASE) then
raise EDatabaseError.Create('Master table: ' + Master.TableName +
' must be a Paradox or dBASE table type');
if (DetailProps.szTableType <> szPARADOX) and
(DetailProps.szTableType <> szDBASE) then
raise EDatabaseError.Create('Detail table: ' + Detail.TableName +
' must be a Paradox or dBASE table type');
if MasterProps.szTableType <> DetailProps.szTableType then
raise EDatabaseError.Create('Master and Detail tables must be of same type');

// Blank out the structures...
FillChar(TableDesc, sizeof(TableDesc), 0);
FillChar(RInt, sizeof(RInt), 0);
// Get the database handle from the table's cursor handle...
Check(DbiGetObjFromObj(hDBIObj(Master.Handle), objDATABASE, hDBIObj(hDb)));
// Put the table name in the table descriptor...
StrPCopy(TableDesc.szTblName, Detail.TableName);
// Put the table type in the table descriptor...
TableDesc.szTblType := MasterProps.szTableType;
// Set the operation type...
Op := crADD;
TableDesc.pecrRintOp := @Op;
// Set the amount of new RI descriptors...
TableDesc.iRintCount := 1;
// Connect the table descriptor to the RI descriptor...
TableDesc.printDesc := @RInt;
// Setup the RI descriptor...
// Put in the name of the RI...
StrPCopy(RInt.szRintName, RIName);
// Do the restructure on the dependent (detail) table...
RInt.eType := rintDEPENDENT;
// Add the master table name...
StrPCopy(RInt.szTblName, Master.TableName);
// Modify operations will be restricted (this can be changed to rintCASCADE)...
RInt.eModOp := ModOp;
// Delete operations will be restricted (NOTE: rintCASCADE will not work)...
RInt.eDelOp := DelOp;
// Only one field in link...
RInt.iFldCount := high(MFields) + 1;
// If the tables are Paradox, then put the associated field numbers in the descriptor...
if (MasterProps.szTableType = szPARADOX) then
begin
//
if RInt.eDelOp = rintCASCADE then
raise EDatabaseError.Create('Cannot use cascading delete RI with Paradox tables');
// Put the detail field index in the array...
// RInt.aiThisTabFld := DIndex.aiKeyFld;
for i := low(DFields) to High(DFields) do
RInt.aiThisTabFld[I] := DFields[I];
// Put the master field index in the array...
// RInt.aiOthTabFld := MIndex.aiKeyFld;
for i := low(MFields) to High(MFields) do
RInt.aiOthTabFld[I] := MFields[I];
RInt.iRintNum := RINTNum;
end;

// If the tables are dBASE, then put the sequence number in the descriptor...
if MasterProps.szTableType = szDBASE then
begin
Check(DbiGetIndexSeqNo(Master.Handle, MIndex.szName, MIndex.szTagName, 0, MNo));
Check(DbiGetIndexSeqNo(Detail.Handle, DIndex.szName, DIndex.szTagName, 0, DNo));
// Put the detail field index in the array...
RInt.aiThisTabFld[0] := DNo;
// Put the master field index in the array...
RInt.aiOthTabFld[0] := MNo;
end;

Master, Detail: TTable -> must be opened exclusive
MFields, DFields : Array of word -> Field Number(s), not zeroBased,
count must be the same
RIName: string -> unique name of the Referential Integrity
ModOp, DelOp: RINTQual -> rintRESTRICT or rintCASCADE (delOp can only be
rintRESTRICT)
RINTNum : Word -> Index of the Referential Integrity (zeroBased) -> can
allways be zero

following restrictions i have checked out

the field(s) on the detailtable must be primary or secondary indexed

if there are more Referential Integrities as one then the other dependend tables must be closed before adding the new Referential Integrity.

thanks for the example, meikl. it's very similar to the code i converted from delphi...

ok, the real problem appears to be the secondary index business. but i'd prefer not to constrain myself with that, since it means that i'll have to create the secondary index in run-time, too, which doesn't make life easier; the software refuses to issue the AddIndex() method. so bde API seems to have a general trouble in creating indexes in run-time. if databse desktop can do it, why can't i?

so let's change the question to: "given field and foreign key definitions, create two paradox tables and necessary RI's."

the creation part is no problem, but it's a prerequisite. any suggestions?

thanks for the example, meikl. it's very similar to the code i converted from delphi...

ok, the real problem appears to be the secondary index business. but i'd prefer not to constrain myself with that, since it means that i'll have to create the secondary index in run-time, too, which doesn't make life easier; the software refuses to issue the AddIndex() method. so bde API seems to have a general trouble in creating indexes in run-time. if databse desktop can do it, why can't i?

so let's change the question to: "given field and foreign key definitions, create two paradox tables and necessary RI's."

the creation part is no problem, but it's a prerequisite. any suggestions?

A lot of questions regard threads in Delphi.
One of the more specific questions is how to show progress of the thread.
Updating a progressbar from inside a thread is a mistake.
A solution to this would be to send a synchronized message to the…

Creating an auto free TStringList
The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list.
In such cases, you have to…

In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…