The secret NewRecord command
by, 8-Feb-2010 at 08:00 AM (3584 Views)
A well known old trick in DataFlex is the Move 0 to Recnum trick. It's been used with character mode DataFlex and Visual DataFlex for so long that nobody probably remembers where it came from, and I'm not sure it was ever really a documented or intended feature in the beginning. Nonetheless it became a fully supported technique at some point.
Basically, if you ever wanted to create a new record loosely based on data from an existing record, you could use this trick to simplify code and save temporary variables. To create a new record you typically do a Clear MyTable, but by doing so you'll of course lose the existing values in the buffer (it's clearing the buffer). So instead of doing a Clear, you can simply Move 0 to Recnum, which clears out the reference to the existing record, so it effectively has to create a new record when saving, while leaving the rest of the buffer intact. Voila!
This technique turned out to be so common that even the SQL/CK drivers had to implement special code to support it in such a way that it worked the same as with the DataFlex database. Although use of DF_FILE_STATUS was considered the better approach for the SQL drivers.
Later on when RowID and non-recnum tables were introduced, this old technique could no longer be used. If you have a non-recnum table, there's no Recnum, and without that it's obviously a bit of a challenge to Move 0 to Recnum... Quickly it was suggested that you could use the DF_FILE_STATUS attribute instead, as it would work with non-recnum tables. It usually works with the SQL drivers and recnum-enabled tables as well.
The gotcha there was that setting DF_FILE_STATUS didn't always work as a proper replacement for the Move 0 to Recnum trick with the DataFlex database. You see, the DataFlex database has an old optimization strategy where it defers fetching all the fields after an indexed Find. Only the data present in the specified index is available in memory immediately after a Find. If you then touch the buffer, it fetches the whole record. So if you Move 0 to Recnum, it will first make sure the whole record is in memory. As you might guess, setting DF_FILE_STATUS doesn't do this extra check to fetch the whole record, so when you later saved, you ended up with missing data for parts of the record, which was not very good. Of course, you can still use Move 0 to Recnum with the DataFlex database, as it's always recnum-enabled. But if you need generic code that works across different databases and with non-recnum tables, that's not an ideal solution.
At first it was suggested that DF_FILE_STATUS should be changed to load the whole record in memory. As you might guess, DF_FILE_STATUS is also used in many other situations that have very little to do with the Move 0 to Recnum trick. And as often happens when changing existing generic code that's used in many different situations, to better suit a very specific situation, it wreaked havoc and we got all sorts of weird problem reports. Luckily this got caught very early on, and was never formally released.
So the solution then was to step back and formalize the whole Move 0 to Recnum trick into a new command. This new command now clearly separates the specific clone-record technique from any unrelated use of DF_FILE_STATUS, and also removes any confusion and sense of bad trick with the old Move 0 to Recnum technique.
This new command is aptly named, NewRecord, and it simply prepares for saving a new record, just like Clear, except it doesn't actually clear the record buffer. If you find it confusing, you can think of Clear as performing two separate operations. First preparing the buffer so that a subsequent SaveRecord will create a new record instead of modifying an existing one, and then clearing all columns in the record buffer. The NewRecord command essentially does the first part, but skips the second part. Obviously the NewRecord command also makes sure the whole record is in memory first, which it can safely do since its dedicated and exclusive use is for the clone-record technique (no compatibility issues with existing code).
You use it directly in place of Move 0 to Recnum, which means it's a straightforward and simple code change. The command was first introduced in Visual DataFlex 12.0, and it's the official replacement for the Move 0 to Recnum trick. It works with both recnum tables and non-recnum tables, with the DataFlex database and any other CK drivers.
You'll notice that you get proper syntax highlighting in the Studio for NewRecord, and it even assists with CodeSense and everything. The only trouble is, while it was carefully designed and implemented in VDF 12.0, it was apparently never documented... Well, if nothing else, it gave me a reason to write up this article.Code:... //Move 0 to MyTable.Recnum NewRecord MyTable ... SaveRecord MyTable