Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Record numbers changing without reason 2

Status
Not open for further replies.

mmerlinn

Programmer
May 20, 2005
747
US
In FoxPro 2.6 this is happening to me:

? RECNO('a') && Returns 1578
? RECNO('b') && Returns 341
? RECNO('c') && Returns 1531

CREATE VIEW temp
SET VIEW TO temp

? RECNO('a') && Returns 1
? RECNO('b') && Returns 340
? RECNO('c') && Returns 1530

Needless to say, keeping record pointers correct is a royal pain.

Any suggestions on why this is happening and what I can do about it?



mmerlinn

"Political correctness is the BADGE of a COWARD!"

 
Are there relations set in your view?
Moving a pointer in one dbf will then cause a pointer movement in a related table to preserve the relationsip.
SET VIEW TO temp will open with relationships set when the view was saved, and record pointer at record 1 of the selected database when saved.
 
cricket:

There are relationships set before saving the vue file.

If I read you correctly, saving a view does NOT save record pointers in force at the time I save the view. In other words, I must save my own pointers and restore them myself after restoring the previous vue file. Correct?

I have lost lots of data over the last three years because of this, and just today I was able to narrow it down to the vue files. Arggggggh!

Since I already have procedures {Wyn_Push() and Wyn_Pull()} to save all active record pointers in a particular window, I will just have to use them more often.

Thanks,





mmerlinn

"Political correctness is the BADGE of a COWARD!"

 
I know it's a later version, but according to the VFP6 help system -

The information saved in a view file includes:

All tables, index, alternate files, and format files currently open in all work areas

All fields contained in the SET FIELDS list

All established relations between open tables

All filters in effect for open tables

The DEFAULT and PATH settings

The procedure file setting

The current Help file

The current resource file

The SET SKIP status

The status bar state (ON or OFF)


Nothing about saving pointer positions. My experience with everything from dBaseIII+ to Visual FoxPro 6 tells that SET VIEW TO is similar to USE xxx SET INDEX TO xxx, which places pointers at the first record in the index, not where you left the pointer when executing SAVE VIEW command.

dennis
 
1oldfoxman:

Well, considering the results I am getting, I have to assume that the VFP6 information you list is probably correct for most if not all earlier versions. I just wish that I could have narrowed down this 'random' loss of information earlier so I would still have some hair left.

I will assume that record pointers must be manually tracked both before and after using view files and revise my programming accordingly.

Once this is done, I will be back with another issue in a new thread about some record pointers that refuse to remain where I put them. Fortunately, those are not random, and I can reproduce them at will.


mmerlinn

"Political correctness is the BADGE of a COWARD!"

 
Mike:

Now that I think about it, since the view files are not saving the record pointers, which is the main reason I thought I needed them, I don't think I need view files at all.

They were being used as an 'easy' way to temporarily save my table info between read levels. Since all of the table setup code is already in the various screen programs, it looks like I can jetison the use of view files entirely, and just save the record pointers in a separate table. Then when I need to, just reconstruct the tables, relations, indices, skips, etc using existing code and then reset the record pointers.








mmerlinn

"Political correctness is the BADGE of a COWARD!"

 
Mike:

Didn't mean physical reconstruction of the indices, only restoring everything, including indices, back to a previous known state.

Sorry for the confusion.






mmerlinn

"Political correctness is the BADGE of a COWARD!"

 
After much consideration, I have decided to keep saving/restoring views states using the CREATE and SET VIEW commands. Reason being is that it seems to be the easiest way to save/restore view states without having to create and maintain a whole new bunch of code for each screen in the project.

As for the record pointers, the only apparent solution is to save them in a separate table/cursor every time they change for whatever reason, and restore them every time a READ is activated, every time just prior to saving edits, and every time an action is canceled. Nothing else seems to be able to stop table corruption caused by incorrect record pointers that quite often are not where they belong.


a


mmerlinn

"Political correctness is the BADGE of a COWARD!"

 
I think we would if we were expecting the record pointer positions to be restored to their previous state as mmerlin had been previously. [smile]

MMerlin, it may be simpler and/or faster to use the SAVE TO and RESTORE FROM commands to create and use .mem files to store your record pointer values in variables, but storing in tables will also work as you've outlined. Just a thought.

dennis
 
I was having problems with record pointers long long before I started using VUE files. At this point in time I have had no problems with corruption of VUE files. Of course, VUE files are only used for temporarily saving table states. They are never used as templates to intialize tables - each screen does all of its own inltializing of tables when the screen is initially activated.

I am actually having two totally different issues with record pointers.

One, restoration to a previous state, is addressed here.

The other, record pointers moving from correct record to correct record then for some unknown reason moving to a different record, was not addressed here. This happens in programs as well as when moving through records in open tables using SKIP in the command window. I can open tables, set orders, set relationships, set many-to-one, then use SKIP to move through records. Most of the time, SKIP does what it is supposed to do, move ONE record. Other times, SKIP will move one record, then IMMEDIATELY move one or more additional records right before my eyes. Very frustrating to say the least.

Both problems within programs seem to be solved by manually tracking records as the pointers change, and always restoring them to correct state just prior to saving newly edited information. Not restoring them just prior to saving many times results in overwriting a different record.

Supposedly FoxPro should be tracking record numbers, but any time I have two or more related tables, I cannot count on FoxPro to work as expected.

I chose tables to store record pointers because I already had a table set up to track critical information on each screen. It was simple to add one more field, write three short functions to save/restore record pointers, then insert hooks to those functions in my screen setup [SCRNSETUP()], read activate [READON()], read deactivate [READOFF()], and navigation button [NB_VALID()] functions. Since these are called by every screen and they never change, once I get them working correctly I can forget about them. I am sure there is a time penalty in tracking my own record pointers, but I doubt that anyone will notice since most tracking is done during data input.

Thanks everyone for the input. It sure is appreciated. Makes life so much easier having people to bounce problems off of versus banging my head against walls looking for solutions.


mmerlinn

"Political correctness is the BADGE of a COWARD!"

 
Mike:

Record pointers are not being moved by my code. That is the first place I looked.

I can make the record pointers move in the command window by using a simple SKIP -1 command ONCE and watch the pointers move ONE record or MANY records, seemingly at random. Apparently my expectations of the SKIP -1 command always moving the record pointer ONE record is false. That is why I am forced to track my own pointers.




mmerlinn

"Political correctness is the BADGE of a COWARD!"

 
Filters are on. No deleted records in DBFs. Skips within valid filtered records. Will do same thing if I put all valid records in another set of DBFs containing only valid records and turn filters off, but setting everything else up the same way.

Example: Goes to correct record, I scatter info, moves zero or more valid records and rests on a valid incorrect record.

Example: I have open filtered tables, pointer first goes to correct record, then jumps to another valid record in the open filtered tables. Only command used to move pointer in the command window is one SKIP -1.

Example in flat file format:

A. Parent_1, Child_11, Gchild_111

B. Parent_2, Child_21, Gchild_211

C. Parent_3, Child_31, Gchild_311 && Many-to-one
D. Parent_3, Child_31, Gchild_312
E. Parent_3, Child_31, Gchild_313

F. Parent_4, Child_41, Gchild_411 && Many-to-one
G. Parent_4, Child_41, Gchild_412

H. Parent_5, Child_51, Gchild_511

I. Parent_6, Child_61, Gchild_611


When pointers are at (I) SKIP -1 moves to (H) and stays at (H)
When pointers are at (H) SKIP -1 moves to (G) and then moves to (F)
Pointer NEVER stays on (G)
When pointers are at (F) SKIP -1 moves to (E) and then jumps to (C)
Pointer NEVER stays on (E)
Pointer NEVER goes to (D)
When pointers are at (C) SKIP -1 moves to (B) and stays at (B)
When pointers are at (B) SKIP -1 moves to (A) and stays at (A)
When pointers are at (A) SKIP -1 sets BOF()


Something similar happens with SKIP 1, but I have not been able to determine exactly what happens when. I just know that all many-to-one relationships have an issue with record pointers resting on proper records.

If there is something that I am doing or not doing that would solve this, I would be extremely grateful to learn what it is.


mmerlinn

"Political correctness is the BADGE of a COWARD!"

 
mmerlin,
if your wish is see all records, try add command
set skip to child
Tesar
 
You mentioned early on that you have relationships set. If the index on the related file doesn't include all the records you expect to see, could it be because the index is UNIQUE and therefore the pointer is skipping to the first physical record meeting the expression because it's the only one in the index?

Also, it's not quite clear which .dbf you're SKIP-1 is being executed in? If it's in the parent record then your experience is exactly as expected. You'd need to SKIP-1 in the child table to see all the child records. Probably you're doing this, but I had to ask. :)
 
Looks to me look you're skipping in the parent and you haven't SET SKIP TO the grandchild. Sounds like the expected behavior.

Tamar
 
I will check to make sure I am SKIPping in the GChild records. I believe I am because when I use SKIP 1, I can access and SCATTER all possible combinations of related records in the proper order, and when using SKIP -1 I can do the same most of the time. The problem arises in that the record pointers don't stay on the correct record, so when I edit any grandchild record (except the first one in each relationship) and save it, the edited record always overwrites the first grandchild record in the relationship.

For example, if I load and edit (D) or (E) above, then save it, (C) is overwritten instead of (D) or (E). Editing then saving (G) overwrites (F) instead of (G). All other records (those without many-to-one relationships) save to the same record that is edited as is expected.

It looks like I will have to put together a short program to demonstrate the problem. I will have to think about how to do it so it is short enough to post here.

Now that I think about it, maybe I should insert some error trapping code throughout the record moving process to save expected pointers side by side with actual pointers as the program is being used. Then review the results to see if I can find the pattern to the problems. I have already done a lot of error trapping related to this issue, but not exactly that way.



mmerlinn

"Political correctness is the BADGE of a COWARD!"

 
From your most recent description, it sounds like something in your code is changing work areas and perhaps skipping backward in that work area, after you've SCATTERed.

The easiest way to catch this is to put RECNO("the table") into the Debug window and set a breakpoint. Then run the code and see where the record pointer moves.

Tamar
 
Here is an example of the problems I am having with the record pointers.

First make a table named 'Table_A' with one column named 'Col_A' containing the following info in this order:

A_1, B_2, C_3, D_4, E_5

Then make another table named 'Table_B' with two columns named 'Col_A' and 'Col_B' and populate them with this info in this order:

A_1, AA_11
B_2, BB_22
C_3, CC_33
C_3, CC_44
C_3, CC_55
D_4, DD_66
E_5, EE_77

In command window:

SELECT Table_B
INDEX ON Col_B TAG Col_B ADDITIVE
SELECT Table_A
INDEX ON Col_A TAG Col_A ADDITIVE
SET RELATION TO Col_A INTO Table_B ADDITIVE
SET SKIP TO Table_A
SELECT Table_B
BROWSE LAST
SELECT Table_A
BROWSE LAST

Now alternating focus between command window and Table_A, do the following:

SKIP
Focus Table_A and note position of record pointer

Repeat to end of table. Note that the record pointer moves to the correct record and remains there every time.

Now repeat the process using SKIP -1. Note that when record pointer moves from E_5 to D_5, C_3 to B_2, and B_2 to A_1 the record pointer moves to the correct record and remains there. However, when you move from D_4 to C_3, the record pointer moves to C_3, CC_55 correctly, then jumps to C_3, CC_33 and remains there. It does NOT remain on the correct record (C_3, CC_55) NOR does it EVER go to C_3, CC_44.

I am having this exact same issue within my programs and it is driving me batty. I can move the record pointer to a record and load the correct record set. But, when I edit that record set and save it, the edited record OVERWRITES a different record. Needless to say, that destroys the underlying record and gives me two similar records, one correct and one incorrect. Short of tracking the record numbers myself, or setting up a master cursor with all currently needed table data in it, I don't know what to do about this.

Tracking the record numbers myself seems simple enough at the moment, although there might be some issues with doing it myself that I am currently not aware of.

Using a flat file type cursor seems like a lot of extra coding to handle data changes to/from the underlying tables. And since there are potentially millions of combinations between the four tables of data being used, the cursor could get quite large and create other issues. Currently those four tables have 5066, 4928, 5755, & 13888 records in them, but all will easily top 1 million each eventually, so it would seem to me that the cursor idea would eventually crash.

So what can I do about this? What are my best long-term options?



mmerlinn

"Political correctness is the BADGE of a COWARD!"

 
Code:
SELECT Table_B
INDEX ON Col_B TAG Col_B ADDITIVE
SELECT Table_A
INDEX ON Col_A TAG Col_A ADDITIVE
SET RELATION TO Col_A INTO Table_B ADDITIVE
SET SKIP TO Table_A      && This line errors
SELECT Table_B
BROWSE LAST
SELECT Table_A
BROWSE LAST
I tried your example but hit an error on the SET SKIP line. Table A is already selected so I can't SET SKIP into it.

Geoff Franklin
 
I'd avoid SET SKIP too but I would avoid it in a different way. I'd create a cursor from both tables:
[TT]
SELECT Table_A.Col_A, Table_B.Col_B ;
FROM Table_A LEFT OUTER JOIN Table_B ;
ON Table_A.Col_A = Table_B.Col_A
[/TT]
and navigate though that if the user insisted on having a step-by-step navigate feature.

Geoff Franklin
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top