Delphi Examples: DbiDoRestructure

<< Click to Display Table of Contents >>

Navigation:  »No topics above this level«

Delphi Examples: DbiDoRestructure

Return to chapter overview

Example 1: Add a validity check to the specified field.

The field must be a longint, and the TTable must be open.

This example uses the following input:

 fDbiDoRestructure(Table4, Table4.Fields[0], @Min, @Max, nil, True);

 

(This input works for the EMPLOYEE.DB table.)

procedure fDbiDoRestructure(Tbl: TTable; Field: TField; MinVal, MaxVal, DefVal: pLongint; Required: Boolean);

var

 hDb: hDbiDb;

 TblDesc: CRTblDesc;

 VChk: pVChkDesc;

 Dir: string;

 NumVChks: Word;

 OpType: CROpType;

begin

 NumVChks := 0;

 SetLength(Dir, dbiMaxNameLen + 1);

 Check(DbiGetDirectory(Tbl.DBHandle, False, PChar(Dir)));

 SetLength(Dir, StrLen(PChar(Dir)));

 VChk := AllocMem(sizeof(VChkDesc));

try

   FillChar(TblDesc, sizeof(CRTblDesc), #0);

   VChk.iFldNum := Field.Index + 1;

   Tbl.DisableControls;

   Tbl.Close;

   Check(DbiOpenDatabase(nil, nil, dbiReadWrite, dbiOpenExcl, nil, 0, nil, nil,

     hDb));

   Check(DbiSetDirectory(hDb, PChar(Dir)));

  with VChk^ do begin

     bRequired := Required;

    if (MinVal <> nil) then begin

       Inc(NumVChks);

       bHasMinVal := True;

       move(MinVal^, aMinVal, sizeof(MinVal^));

    end

    else

       bHasMinVal := False;

    if (MaxVal <> nil) then begin

       Inc(NumVChks);

       bHasMaxVal := True;

       move(MaxVal^, aMaxVal, sizeof(MaxVal^));

    end

    else

       bHasMaxVal := False;

    if (DefVal <> nil) then begin

       Inc(NumVChks);

       bHasDefVal := True;

       move(DefVal^, aDefVal, sizeof(DefVal^));

    end

    else

       bHasDefVal := False;

  end;

   TblDesc.iValChkCount := NumVChks;

   TblDesc.pVChkDesc := VChk;

   OpType := crADD;

   TblDesc.pecrValChkOp := @OpType;

   StrPCopy(TblDesc.szTblName, Tbl.TableName);

   StrCopy(TblDesc.szTblType, szParadox);

   Check(DbiDoRestructure(hDb, 1, @TblDesc, nil, nil, nil, False));

finally

   Check(DbiCloseDatabase(hDb));

   FreeMem(VChk, sizeof(VChkDesc));

   Tbl.EnableControls;

   Tbl.Open;

end;

end;

 

Example 2: Pack a Paradox (with DbiDoRestructure) or dBASE table.

 

This example will pack a Paradox or dBASE table therefore removing already deleted rows in a table. This function will also regenerate all out-of-date indexes (maintained indexes). This example uses the following input:

 PackTable(Table1)

 

The function is defined as follows:

 

// Pack a Paradox or dBASE table

// The table must be opened execlusively before calling this function...

procedure PackTable(Table: TTable);

var

 Props: CURProps;

 hDb: hDBIDb;

 TableDesc: CRTblDesc;

begin

 // Make sure the table is open exclusively so we can get the db handle...

if not Table.Active then

  raise EDatabaseError.Create('Table must be opened to pack');

if not Table.Exclusive then

  raise EDatabaseError.Create('Table must be opened exclusively to pack');

 

 // Get the table properties to determine table type...

 Check(DbiGetCursorProps(Table.Handle, Props));

 

 // If the table is a Paradox table, you must call DbiDoRestructure...

if (Props.szTableType = szPARADOX) then begin

   // Blank out the structure...

   FillChar(TableDesc, sizeof(TableDesc), 0);

   // Get the database handle from the table's cursor handle...

   Check(DbiGetObjFromObj(hDBIObj(Table.Handle), objDATABASE, hDBIObj(hDb)));

   // Put the table name in the table descriptor...

   StrPCopy(TableDesc.szTblName, Table.TableName);

   // Put the table type in the table descriptor...

   StrPCopy(TableDesc.szTblType, Props.szTableType);

   // Set the Pack option in the table descriptor to TRUE...

   TableDesc.bPack := True;

   // Close the table so the restructure can complete...

   Table.Close;

   // Call DbiDoRestructure...

   Check(DbiDoRestructure(hDb, 1, @TableDesc, nil, nil, nil, False));

end

else

   // If the table is a dBASE table, simply call DbiPackTable...

  if (Props.szTableType = szDBASE) then

     Check(DbiPackTable(Table.DBHandle, Table.Handle, nil, szDBASE, True))

  else

     // Pack only works on PAradox or dBASE; nothing else...

    raise EDatabaseError.Create('Table must be either of Paradox or dBASE ' +

       'type to pack');

 

 Table.Open;

end;

 

Example 3: Alter a field in a Paradox or dBASE table.

 

This example will alter an existing field in a Paradox or dBASE table. NOTE: You must fill in all options in the ChangeRec with 0 or '' if the option is not used in the restructure. FillChar can be used to do this:

Fillchar(MyChangeRec, sizeof(MyChangeRec), 0);

This example uses the following input:

 ChangeField(Table1, Table1.FieldByName('FOO'), MyChangeRec)

 

ChangeRec is defined as follows:

type

 ChangeRec = packed record

   szName: DBINAME;

   iType: Word;

   iSubType: Word;

   iLength: Word;

   iPrecision: Byte;

  end;

 

The function is defined as follows:

procedure ChangeField(Table: TTable; Field: TField; Rec: ChangeRec);

var

 Props: CURProps;

 hDb: hDBIDb;

 TableDesc: CRTblDesc;

 pFields: pFLDDesc;

 pOp: pCROpType;

 B: Byte;

begin

 // Initialize the pointers...

 pFields := nil;

 pOp := nil;

 // Make sure the table is open exclusively so we can get the db handle...

if not Table.Active then

  raise EDatabaseError.Create('Table must be opened to restructure');

if not Table.Exclusive then

  raise EDatabaseError.Create('Table must be opened exclusively' +

    'to restructure');

 Check(DbiSetProp(hDBIObj(Table.Handle), curxltMODE, Integer(xltNONE)));

 // Get the table properties to determine table type...

 Check(DbiGetCursorProps(Table.Handle, Props));

 // Make sure the table is either Paradox or dBASE...

if (Props.szTableType <> szPARADOX) and (Props.szTableType <> szDBASE) then

  raise EDatabaseError.Create('Field altering can only occur on Paradox' +

     ' or dBASE tables');

 // Allocate memory for the field descriptor...

 pFields := AllocMem(Table.FieldCount * sizeof(FLDDesc));

 // Allocate memory for the operation descriptor...

 pOp := AllocMem(Table.FieldCount * sizeof(CROpType));

try

   // Set the pointer to the index in the operation descriptor to put

   // crMODIFY (This means a modification to the record is going to happen)...

   Inc(pOp, Field.Index);

   pOp^ := crMODIFY;

   Dec(pOp, Field.Index);

   // Fill the field descriptor with the existing field information...

   Check(DbiGetFieldDescs(Table.Handle, pFields));

   // Set the pointer to the index in the field descriptor to make the

   // midifications to the field

   Inc(pFields, Field.Index);

   // If the szName portion of the ChangeRec has something in it, change it...

  if (Length(Rec.szName) > 0) then

     pFields^.szName := Rec.szName;

   // If the iType portion of the ChangeRec has something in it, change it...

  if (Rec.iType > 0) then

     pFields^.iFldType := Rec.iType;

   // If the iSubType portion of the ChangeRec has something in it, change it...

  if (Rec.iSubType > 0) then

     pFields^.iSubType := Rec.iSubType;

   // If the iLength portion of the ChangeRec has something in it, change it...

  if (Rec.iLength > 0) then

     pFields^.iUnits1 := Rec.iLength;

   // If the iPrecision portion of the ChangeRec has something

   // in it, change it...

  if (Rec.iPrecision > 0) then

     pFields^.iUnits2 := Rec.iPrecision;

   Dec(pFields, Field.Index);

  for B := 1 to Table.FieldCount do begin

     pFields^.iFldNum := B;

     Inc(pFields, 1);

  end;

   Dec(pFields, Table.FieldCount);

                         

   // Blank out the structure...

   FillChar(TableDesc, sizeof(TableDesc), #0);

   //  Get the database handle from the table's cursor handle...

   Check(DbiGetObjFromObj(hDBIObj(Table.Handle), objDATABASE, hDBIObj(hDb)));

   // Put the table name in the table descriptor...

   StrPCopy(TableDesc.szTblName, Table.TableName);

   // Put the table type in the table descriptor...

   StrPCopy(TableDesc.szTblType, Props.szTableType);

   // The following three lines are necessary when doing any field restructure

   // operations on a table...

   

   // Set the field count for the table

   TableDesc.iFldCount := Table.FieldCount;

   // Link the operation descriptor to the table descriptor...

   TableDesc.pecrFldOp := pOp;

   // Link the field descriptor to the table descriptor...

   TableDesc.pFldDesc := pFields;

   // Close the table so the restructure can complete...

   Table.Close;

   // Call DbiDoRestructure...

   Check(DbiDoRestructure(hDb, 1, @TableDesc, nil, nil, nil, False));

finally

  if (pFields <> nil) then

     FreeMem(pFields);

  if (pOp <> nil) then

     FreeMem(pOp);

end;

end;

 

Example 4: Add a master password to a Paradox table.

This example uses the following input:

 AddMasterPassword(Table1, 'MyNewPassword')

 

The procedure is:

procedure AddMasterPassword(Table: TTable; pswd: string);

const

 RESTRUCTURE_TRUE = WordBool(1);

var

 TblDesc: CRTblDesc;

 hDb: hDBIDb;

begin

 { Make sure that the table is opened and is exclusive }

if not Table.Active or not Table.Exclusive then

  raise EDatabaseError.Create('Table must be opened in exclusive ' +

    'mode to add passwords');

 { Initialize the table descriptor }

 FillChar(TblDesc, SizeOf(CRTblDesc), #0);

with TblDesc do begin

   { Place the table name in descriptor }

   StrPCopy(szTblName, Table.TableName);

   { Place the table type in descriptor }

   StrCopy(szTblType, szPARADOX);

   { Master Password, Password }

   StrPCopy(szPassword, pswd);

   { Set bProtected to True }

   bProtected := RESTRUCTURE_TRUE;

end;

 { Get the database handle from the cursor handle }

 Check(DbiGetObjFromObj(hDBIObj(Table.Handle), objDATABASE, hDBIObj(hDb)));

 { Close the table }

 Table.Close;

 { Add the master password to the Paradox table }

 Check(DbiDoRestructure(hDb, 1, @TblDesc, nil, nil, nil, False));

 { Add the new password to the session }

 Session.AddPassword(pswd);

 { Re-Open the table }

 Table.Open;

end;