The Database Managers, Inc.

Contact The Database Managers, Inc.

Use an RSS enabled news reader to read these articles.Use an RSS enabled news reader to read these articles.

DataFlex Decompiler

Log All Save and Delete Transactions

by Curtis Krauskopf

One of the most difficult types of problems to debug is trying to find out why records are mysteriously being deleted or overwritten.

Your users come to you swearing up and down that they know they saved a record but now they can't find it. They might even have documentation that the record existed at one point but now it's no longer there.

So, you try the obvious things:

  • reindexing the datafile
  • writing a small program to examine every record for some unique piece of information
  • doing a code-walk of every and routine
  • randomly poking around in the source code to see if there might be something obviously wrong

When the problem is important enough, at some stage, the finger pointing starts happening. You blame the DataFlex runtime. Data Access Corporation says that their runtime doesn't lose records. You blame a faulty network card or router. The network administrator says all the network cards test fine and besides, if it was a network issue, why does it only happen on that one datafile? You blame a hypothetical malicious user of deleting the record intentionally. And the finger pointing goes on and on.

What you really need is some way of being able to log every datafile SAVE and DELETE transaction so that you can find out, retroactively, what happened when the record mysteriously disappeared. The logging needs to be multiuser compatible because the problem might manifest itself only in a multiuser situation.

At this point you start groaning because you'll have to go into every program that opens the datafile in question and manually add code that logs the saves and deletes. On top of that, you might need to deal with legacy macro code written by somebody else that is also doing saves and deletes deep inside of custom-written macros. And if that wasn't enough, you have to make all of these modifications and not break any of the working code -- a concept known as making things worse.

You might even be tempted to take a shortcut and say "there's no way any of these lookup programs could be saving or deleting records so I'll just skip those." Well, that could be an unfortunate assumption because that might be exactly where the problem is at.

A Solution

To help solve these problems, I created a module to help a DataFlex developer discover why records are being mysteriously deleted or overwritten. It does this by logging the key fields and other important information when a record in a specific datafile is saved or deleted. This solution is only suitable for character-mode DataFlex.

This solution falls under the category of "desperate times call for desperate measures". You really should only do this if you have exhausted every other avenue available to solve the problem. The good news is that every time I've used this technique, I've been able to find the problem as soon as a user caused the problem to occur.

The overall scheme of this technique is to insert some code into an FMAC macro that saves and deletes records. The code will log, to a DataFlex datafile, each time a record is created or updated for a specific file. Because the code is inserted at the macro level, every source file, module, package, and include file anywhere in the application that uses SAVE, SAVERECORD and DELETE on the monitored file will have the transaction logged.

This solution is compatible with every known technique (both documented and undocumented) for saving and deleting records:

  • Save filename
  • Save (integer)
  • Save indirect_file.recnum
  • SaveRecord filename
  • SaveRecord (integer)
  • SaveRecord indirect_file.recnum
  • Delete filename
  • Delete (integer)
  • Delete indirect_file.recnum

Because the log file is a DataFlex datafile, it's automatically multiuser compatible. The log file doesn't require any indexes and each record is small, so the logging of saves and deletes will have a minimal impact on the system throughput even when used in a tight loop.

Where to Start

This solution is designed to require a minimum number of changes to the source code. Three lines are required to be inserted at the top of each source file (macro files and include files don't need the three lines). The lines are simple enough that a DataFlex program could be written to do this insertion, or if you're handy with PERL, AWK or your editor's macro language, you could use any of those techniques to insert those lines too.

Other macros, such as the ENTER macro, will need to be slightly modified to log saves in those macros too. Detailed instructions for modifying the ENTER macro (and custom macros similar to the ENTER macro) are provided in the readme.txt file in the distribution file (see below). If none of your programs use an ENTER macro or use custom macros, then you can skip that part.

What Is The Result?

The log file will contain a list of SAVE and DELETE transactions that occurred in chronological order. An example of one line from the log file is:

invoice, S, 01/27/2004, 1315, 4115, jim, 12345, 5, 1500

In the above line, 'invoice' is the name of the program that saved ('S') the record #1500 on 01/27/2004 at 1:13pm (1315). The user's name was jim and the save occurred in the invoice program on line 4115 (see invoice.prn to correlate this number with an actual source code line number). The key fields for the record affected are 12345 and 5.

Later, if users complain that a record with a key 12345-5 is missing, you can search for it in the log file and find the above record. Now that you know it was saved to record 1500, you can then search for other transactions that occurred to record 1500. You might find this line:

invmaint, D, 01/27/2004, 1317, 1277, sally, 12345, 5, 1500

It looks like sally accidentally or otherwise deleted that record at 1:17pm (1317) in the invmaint program. The exact line number that caused the deletion is line number 1277. You can use the INVMAINT.PRN file to find out which source line was actually involved with the deletion. Mystery solved.

Or maybe you'll see:

inv_lkup, S, 01/28/2004, 1015, 5523, joe, 12377, 2, 1500

That line says that the inv_lkup program overwrote ('S') record 1500 with line item 12377-2 at 10:15am the next day. I don't know why a lookup program would be doing that, but line 5523 in the INV_LKUP.PRN file is the place to start trying to figure out why it happened.

The important point here is that once you know the record number of the missing data, you can then find out what other programs edited, deleted or overwrote that record.


Complete installation instructions are provided in the readme.txt file that is located in the distribution file (see below). Be warned, though, that a certain level of experience with the DataFlex language is required to be able to install these changes and that even though the readme.txt provides instructions that cover most situations (and all of the common ones), that it can't handle every situation.

The Database Managers, Inc. is providing this file as a service to the DataFlex community. If you're able to use this technique to find and solve your problem, then we know you're happy and we're happy along with you.

If the programming involved is beyond your capabilities or you just want to off-load the entire project to someone else, then The Database Managers will be glad to help you examine your source files, look for anomalies and to incorporate this solution into your project. Please contact us to find out our rates for doing this kind of work. Depending on what needs to be done, the price will range from a few hundred dollars to a few thousand dollars. (11k)

readme.txt (in HTML, view in your browser)

Finally, good luck and I hope that you can solve your missing record mysteries.

This article was written by Curtis Krauskopf (email at ).

Curtis Krauskopf is a software engineer and the president of The Database Managers ( He has been writing code professionally for over 25 years. His prior projects include multiple web e-commerce applications, decompilers for the DataFlex language, aircraft simulators, an automated Y2K conversion program for over 3,000,000 compiled DataFlex programs, and inventory control projects. Curtis has spoken at many domestic and international DataFlex developer conferences and has been published in FlexLines Online, JavaPro Magazine, C/C++ Users Journal and C++ Builder Developer's Journal.

The Database Managers helps companies to:
  •  become more profitable
  •  grow their business
  •  fix programs that are behaving badly
  •  write new programs to solve business problems
  • do more with fewer resources
Email them at to find out how to make your company more successful.

Other Popular DataFlex topics at The Database Managers, Inc.:

DataFlex: Tips | Freeware | WebApp Server | Books | Links
Services | Programming | Contact Us | Recent Updates

Send feedback to: