The principle syntax is SET RELATION TO expression INTO work area/alias name. This means you're setting a relation via the FIELD footprint into the TABLE tw_base. The source table of that relation is the currently selected alias, and from the code I see that is tw_base itself, so you're self referencing.
So your code does not exactly look correct, as said about the relation you setup there, looks wrong. There is no second alias from which the relation begins, at least you don't set it as the active alias.
If this is still shortened code, please make sure it's reflecting the essence correctly.
I wonder if the pack may be failing because of the relation being set.
If you delete records they are only marked deleted in dbfs, you will know this Still no SQL, APPEND FROM or whatever command reading a dbf in VFP will read and output these records, which are marked deleted, as long as SET("DELETED") is "ON".
If some other program still sees them in the dbf without packing, then that program is working in SET("DELETED")="OFF" mode, which would be a bad design.
The main pint is, taht PACK is meant to fail in concurrent and frequent use, if the concurrent pack comes in the moment the original file is gone and the temp file is not renamed back to the original one.
You could try and replace the pack with this code, which does act within the exact same file. It does also create a temp file for security (to be able to reconstruct data in case of a failure), but it will then not delete the original and rename the copy, but fill in the original after zapping it and delete the copy.
You may try myPack() instead of the native PACK.
Bye, Olaf.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
|
* testing with three aliases: a cursor curTest and a table tabTest
Create Cursor curTest (cTest C(10))
Append Blank
Append Blank
Delete Next 1
myPack()
Create Table tabTest Free (cTest C(10))
Append Blank
Append Blank
Delete Next 1
myPack()
* an unpacked cursor as reference
Create Cursor curTest2 (cTest C(10))
Append Blank
Append Blank
Delete Next 1
Set Deleted off
Set
* take a look at the difference between curTest2 and the other two aliases.
* the core procedure to pack within the same dbf file:
Procedure myPack(tcAlias)
Local llShared, lcTempDBC, lcTempDBF
If Empty(tcAlias)
tcAlias = Alias()
EndIf
If Not IsExclusive(tcAlias)
llShared = .T.
Try
Select (tcAlias)
Use Dbf(tcAlias) Exclusive
Catch
*
EndTry
EndIf
If Not IsExclusive(tcAlias)
Return .F.
EndIf
lcTempDBC = Addbs(GetEnv("TEMP"))+Sys(2015)+".dbc"
lcTempDBF = ForceExt(lcTempDBC,"dbf")
Create Database (lcTempDBC)
Select (tcAlias)
* during this copy data in lcTempDBF grows,
* tcAlias has all data in it in any moment
Copy To (lcTempDBF) Database (lcTempDBC) For NOT Deleted(tcAlias)
* at this point the data of tcAlias exists twice,
* first still within tcAlias, second in lcTempDBF
Zap In (tcAlias)
* now data only exists in lcTempDBF
* this has truncated the dbf, fpt and the cdx of tcAlias
Select (tcAlias)
* during this append data in the original tcAlias file grows again,
* lcTEmpDBF has all data in it in any moment
Append From (lcTempDBF)
* now the data again exists twice in lcTempDBF and tcAlias, without any deleted records,
* cdx and fpt also is rebuilt from scratch.
* so we can safely close and delete lcTempDBF and the lcTempDBC
Set Database To (lcTempDBC)
Close Database
Delete Database (lcTempDBC) DeleteTables && delete
If llShared
Select (tcAlias)
Use Dbf(tcAlias) Shared
EndIf
Return .T.
EndProc
|