0% found this document useful (0 votes)
5 views

3.2_language_changes

DataFlex 3.2 introduces significant changes to support both legacy character mode and new OOP style applications, requiring code updates for compatibility with VDF 6 standards. Key improvements include stricter syntax checking, simplified command syntax, and the identification of obsolete commands, with a strong recommendation for developers to update their code. The document outlines specific changes in syntax and error checking to enhance programming efficiency and reduce ambiguity in code.

Uploaded by

Roberto
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views

3.2_language_changes

DataFlex 3.2 introduces significant changes to support both legacy character mode and new OOP style applications, requiring code updates for compatibility with VDF 6 standards. Key improvements include stricter syntax checking, simplified command syntax, and the identification of obsolete commands, with a strong recommendation for developers to update their code. The document outlines specific changes in syntax and error checking to enhance programming efficiency and reduce ambiguity in code.

Uploaded by

Roberto
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 16

Language Changes in DataFlex 3.

DataFlex 3.2 contains two sets of packages and FMAC/FLEX.CFL files; one to support legacy
character mode applications (like those you would create with DataFlex 3.1d, including both OOP
and Procedural styles) and one to support OOP style applications that would share DDO's with
Visual DataFlex and WebApp applications.

If you choose to use the new DDO style for your applications, you will need to make changes to
existing character mode application source code to bring it up to the standards set in VDF 6. We
have taken the section on Language Changes from the VDF 6 documentation for you to use as a
basic reference to the types of changes that may be involved.

Please note that not all of the information in this document is applicable to DataFlex 3.2.

If you are not using the new DDO style for your applications, using the traditional setpath.bat will
use the appropriate packages (for OOP style) and FMAC/FLEX.CFL (for both OOP and
procedural styles) and no application code changes are required.

Note: There are no plans to attempt support for hybrid mixes of the DDO and non-DDO packages
and FMAC/FLEX.CFL files. Do not attempt to mix these.

One of the goals of VDF 6 was to make the programming language easier to use. To achieve this
goal, four major changes were made:
1. A suggested syntax has been created for all commands: In cases where multiple
methods exist to accomplish the same goal, we now present a single “suggested”
approach. For example, when commands and functions exist that accomplish the same
thing (e.g., the Left command and function) we advise that you always use the function.

2. Stricter syntax checking is now enforced: Previous versions of DataFlex supported very
relaxed compiler syntax checking. This made the language confusing and made it much
harder to distinguish bad code from unusual code. We now enforce stricter and
consequently much more sophisticated syntax error checking. For example, the “to”
keyword is now required in any Set or Get statement. By requiring this keyword we can
now check that the “to” keyword is included, that it is included in the proper position and
that it is only included once.

3. A simplified syntax has been created: Some command syntax changes will make
programs easier to type, easier to read and less prone to error. For example, the Local
keyword is no longer required within a method. If a variable is declared within a method, it
is local. Another example of simplification is object referencing. You may now reference
an object by its simple name (e.g., Get piProp of oMyform to iVar) instead of it’s
expression access method (e.g., Get piProp of (oMyform(self)) to iVar)

4. We’ve identified many commands and techniques as being obsolete: We have identified
over 100 commands and numerous programming techniques as being obsolete and we
advise that you no longer use them. Note that these commands do not have removed
from existing programs – existing programs that use these commands will continue to run
properly. Documentation for obsolete commands has been moved into a section of the
Language Guide named Obsolete Commands, functions and other symbols. Each
obsolete command will contain a link to the command that should be used in its place.
You will find the advantages of these changes to be significant. It is possible that some existing
VDF programs will not compiler properly in VDF 6. In many cases, you will discover you’ve made
a programming error (and you will welcome the notification). In some cases older style coding,
while correct, will now be considered improper. While we provide a method to disable the new
changes allowing you to compile “old style” we encourage you in the strongest possible terms to
correct your programs and bring them up to date. We’ve performed this update on great deal of
internal code and have found the process to be relatively fast and easy.

To find out more about these changes you should refer to following VDF 6 documents:
• The Language Guide presents an overview of the DataFlex Language and should be
reviewed by all developers. This guide will be particularly useful to new developers.

• The Language Reference contains a section titled Obsolete Commands, Functions and
Other Symbols. Refer to this to see what commands are now obsolete and what
commands should be used in their place.

Simplified, Consistant Command Syntax


Several changes were made in the DataFlex command language. These changes attempted to
improve on syntax that was either clumsy, hard to remember, or error prone. The complete list of
changes is contained within this document. The most significant changes are:

• Variables are intelligently scoped to determine if they are local or global. The Local
keyword is no longer required inside of methods.

• The keyword Self should be used in place of Current_object

• The object referencing parameter in Get/Set/Send commands allows you to use a simple
naming syntax of ObjectName instead of (ObjectName(Self)).

• A simplified and consistent message sending syntax is now:


Get msg {of obj} {param1...paramx} to Val
Set msg {of obj} {param1...paramx} to Val
Send msg {of obj} {param1...paramx}

• A Case command is now supported

Obsolete Commands and Techniques


A number of commands and techniques are now considered to be obsolete. You will not need to
go and change your existing programs – the old commands will still work.

Here is an example of some of the commands and techniques that are now considered obsolete.
These are accompanied by their suggested replacement commands and techniques.

Command vs. Functions

In DataFlex, there are numerous commands and functions that do the same thing (e.g., Left,
Right, Append, Pos). We recommend that you always use functions instead of commands.
Not: Left sText 20 to sValue
Use: Move (left(sText,20)) to sValue

Not: Append sVar1 sVar2


Use: Move (Append(sVar1,svar2)) to sVar1

Expressions

The use of logical operators is an area where there are many ways to accomplish the same
things. Below is some useful expression information and programming guidelines.
• In all cases expressions will evaluate to zero (false) or non-zero (true).

• If (expression); Expressions belong in parenthesis (see next item for exception)


If (x=7) ….
If (x=7 and y>z) ….
If not (x=7 and y>z) ….
If ( MyFunct(self,var) or GlblFunct(var) ) ….

• If IntegerVariable; Parenthesis are not required for single operand expressions. The
single operand is usually an integer. If it’s zero, it is false. If it is non-zero, it is true.
If var….
If not var

• Use of indicators; Only use indicators when you must: Found, SeqEof, Err. Indicators can
be used in expressions but they must be enclosed within their own set of parenthesis.
If (found) ….
If ( (found) and (err) ) ….
If ( (found) and changed_state(self) and sVal<>””)

• Be aware of expression short circuit capability (it’s powerful).

• Avoid global variables; Whenever possible use local variables within expressions and not
globals and particularly not indicators. Local integers can be used in place of indicators.
If you need to create a “variable” that is global to an entire object, define and use a
property – that’s what they are there for. Properties can be defined within objects and
within classes.

• The If statement can be followed by a single command or, if multiple commands are
needed, a Begin/End construct. The following does not require a Begin/End block
(although you may create one if desired):
If (SomeValue > SomeOtherValue) ;
Move SomeValue to SomeOtherValue

• Note that the use of the semi-colon as a command line separator is a valid and useful
technique.

Obsolete methods of use (Do not use)

• Do not use EQ, GT, LT, etc


Not: If x eq 7
Use: If (x=7)

Not: If (x eq 7)
Use: If (x=7)

• Do not use multiple IFs if not needed:


Not: If x eq 7 If y eq 8…
Use: If (x=7 and y=8)…

Not: If (x=7) Begin


If (x=8) Begin
Use: If (x=7 and y=8) Begin

• Do not use indicators. Use integers. If an integer evaluates to zero it is false, if non-zero it
is true.
Not: [IndOk] Move x to y
Use: If IntOk Move x to y

Not: [IndOk][Ind2Ok] Move x to y


Use: If (IntOk and Int2Ok) Move x to y

Not: [IndOk] Move x to y


[IndOk] Move y to z
Use: If IntOk Begin
Move x to y
Move y to z
End

Improved Syntax and Construct Checking


Previous versions of the compiler did not do a very thorough job of checking for obvious errors.
The compiler took the attitude of “when in doubt, don’t report an error.” This has changed. If
syntax or command placement is doubtful, an error will be reported.

This should greatly reduce development time. Now, instead of tracking down problems within a
running program, you will have a much greater chance that the error will be reported at compile
time. The following sample should prove this point:
Class MyArray is An Array
Property Integer IsBusy public False
Object OldVals is an Array
End_Object
End_Class

Object MyObject is an Array


Local Integer OldValue
Procedure Construct_Object
Forward Send Construct_Object
Property Integer IntProp public 0
End_Procedure

Procedure Add_Items integer i1 string s1


Integer iCnt
If i1 eq 0 Begin
Send delete_data
return
end
Get (Item_Count(self)) to iCnt
Set value iCnt s1
End_Procedure
End_Object

Send Add_items 1 "John" (MyObject(self))

How many errors can you see? In previous versions of Visual DataFlex, this sample will compile.
It might even run. Just about everything in it is wrong. Here are the problems:

1. Within a class you should only define properties within a method – usually construct
object.

2. Within a class you should only define objects within a method.


3. You cannot place construct_object within an object. It never gets called.
4. You should not define properties within methods within an object – it should be directly
within the object.

5. You cannot create local variables outside of methods.


6. A global variable, iCnt was created within Add_items when a local was wanted (we forgot
the Local keyword).

7. Return was used in the procedure instead of procedure_return.


8. Get (ItemCount(Self)) is wrong. Get followed by an expression is almost always wrong.
9. The “set value iCnt s1” command is ambiguous and will not work. It will attempt to set the
value of the current_item with the value in iCnt.

10. The send Add_items syntax is wrong. The parameters belong after the object name.
The new compiler/fmac will catch all of these problems. In addition, changes have been made to
allow for simpler command syntax. The proper VDF6 code for the above example should be:
Class MyArray is An Array
Procedure Construct_Object
Forward Send Construct_Object
Property Integer pbIsBusy False
Object oOldVals is an Array
End_Object
End_Procedure
End_Class

Object oMyObject is an Array


Property Integer piOldValue 0
Property Integer piIntProp 0
Procedure Add_Items integer i1 string s1
Integer iCnt
If (i1=0) Begin
Send delete_data
Procedure_return
End
Move Item_Count to iCnt
Set value iCnt to s1
End_Procedure
End_Object

Send Add_items of oMyObject 1 "John"

Relaxing the Compiler Checking


In some cases, this new stricter syntax will catch errors that the previous DataFlex compiler did
not. In other cases, the stricter syntax will report errors that, while not truly an error, represents
unusual, ambiguous or bad coding. In both cases, you will want to correct this code as quickly as
possible.

The reporting of some errors can be relaxed. Items in this list marked with <Warning!> can be
relaxed by placing using the command Compiler_Warnings. This command can be used to turn
relaxed compiler checking on and off. The command is passed the parameter ON or OFF to
indicate if the compiler should relax its checking. Therefore placing the command
Compiler_Warning OFF at the top of a program will make it work the way it always did.

For example, it is possible, although highly unlikely, that the following syntax might be correct:
Procedure Add_Items
Integer iCnt
Get (MyProp(Self) to iCnt
:
End_Procedure

If this is the case, you could tell the compiler to allow this syntax by adding the command
“Compiler_Warning OFF” to the top of the program. Even better would be to surround the code as
follows:
Procedure Add_Items
Integer iCnt
Compiler_Warnings Off
Get (MyProp(Self) to iCnt
Compiler_Warnings On
:
End_Procedure

A better and recommended alternative would be to create syntax that is more clearly intentional.
The following code does not require relaxed error checking and it more clearly reflects the intent
of the programmer (even without comments).
Procedure Add_Items
Integer iCnt iMessage
Get MyProp to iMessage
Get iMessage to iCnt
:
End_Procedure

Even with Compiler_Warnings disabled, some new errors may be reported. These are errors that
are so serious that they can not be relaxed. They should be corrected immediately.

Compiler Changes in Error Checking and Syntax


The following lists all compiler and syntax changes in VDF6.

Classes: Class / End_Class Commands

• The newly defined class must not yet exist

• Super-Class must already exist

• Classes cannot be nested within classes

• Classes cannot be nested within methods (use the commands


Create_base_class/End_base_Class for this very advanced feature).

• End_Class must have a corresponding class

• End_Class not valid if unresolved method (missing end_procedure / end_function)

• End_Class not valid if unresolved objects (missing end_object)

• A class should only contain methods and import_class_protocol command. Creating a


property, sending a message or creating an object directly within a class generates an
error. <Warning!>

Objects: Object/End_Object Commands

• If created in a class, it must be inside a procedure or function. <Warning!>

• End_Object must have a corresponding object

• If in method, end_object must have a paired object within the method.

• The method construct_object not allowed within an object (only classes)

Procedures & Functions

• Cannot nest methods


• Methods are not allowed within objects that are defined in a method.

• If at desktop, it is a method of the Object class. In other words all objects will understand
the message via inheritance, not delegation. Same as “For BaseClass”. If you want an
method to reside on the desktop (and resolve via delegation) use “For DFDesktop”

• The same function name (get_xxxx) cannot be used for cross types
(internal/global/class/object-access). <Warning!>

• The same function name cannot be used with different parameter lists and types.

• End_Function / End_procedure must have a corresponding procedure/function

• End_Function / End_procedure checks for unmatched Begin/end blocks within the


method.

• End_Function / End_procedure checks for improperly nested child objects within the
method.

• Procedure_Return / Function_return must be within a procedure or function

• A Return command inside a method will generate an error. If you must do this use the
command Gosub_return. <Warning!>

• Globals variables cannot be created within methods. The compiler will assume the
variable is local. If you must create a global within a method, use the new command
Global_Variable (e.g., Global_Variable Integer x). <Warning!>

Properties

• Properties can only be defined within a class or object

• If defined within a class, property must be within a method <Warning!>

• If defined within an object, property must not be within in a method. <Warning!>

• Not allowed within an object that is defined within a method

• Check that name is valid. It cannot be used for other function type (internal/global/object-
access). If a class function, must have same parameter types

• Syntax of Private/Public is optional (e.g., Property Integer MyVal 10). This is a


documentation issue. We don’t really use private properties and the overhead makes
properties seem much more complicated.

• Property integer Name {PUBLIC|PRIVATE} {Val}

Sending Messages: Send/Set/Get Commands

• Error if sent directly within a class (and not within method in the class) <Warning!>

• Error if message is an expression (e.g., Get (myobject(self)) to x) <Warning!>

• We now use a stricter syntax checking) <Warning!>

1. To parameter is required with Get and Set commands


2. Get syntax expects a single parameter following the To.
3. Set syntax expects at least one parameter following the To. Multiple
parameters are allowed in order to support legacy messages (e.g., set
location, set size). They are strongly discouraged for new usage.

4. Of parameter can be used with Send message in place of To. This


creates a consistent syntax with Get and Set

5. Location of the Of parameter is checked. If present it must immediately


follow the message

6. Item Parameter is not required to precede the item value. Note that in
previous revisions of DataFlex the Item keyword was required for some
item based messages (e.g., value) but not for others (password_state). It
is now never required.

7. Item and Form based properties will provide a default item value (either
Current or 0) if the index parameter is omitted. This is discussed in
greater detail under Default Index values in Messages

• A simpler object naming syntax is supported. You may use ObjectName in place of
(ObjectName(self))

Expected Syntax:
Get msg {of obj} {{Field|File_field} param1...paramx} to Val
Set msg {of obj} {{Field|File_field} param1...paramx} to Val
Send msg {of obj} {param1...paramx}

Tolerated Syntax:
Get msg {of obj} {{Field|File_field|item} param1...paramx} to Val
Set msg {of obj} {{Field|File_field|item} param1...paramx} to Val...Valxx
Send msg {of|to obj} {param1...paramx}

Variables

• The local keyword is now optional. Variables declared within a method are local. If you
must place a global within a method use new command Global_Variable. <Warning!>

• If a local variable is declared outside of a method, an error is generated. <Warning!>

• If you already have variables declared within a method and you have not used the Local
keyword, it is really not clear what your intentions were. Most likely, you wanted this
variable to be local and you forgot the word local. Less likely, you actually wanted a
global variable. That variable will now be local. If you really wanted that variable to be
global you will receive a compiler error when you attempt to use the variable outside of
the method. This error will be your clue that you’ve declared your global variable within a
method. We advise you to move the variable outside of the method. Or, if you must,
preface the command with the global_variable keyword.

Object Name Syntax in Messages

• The keyword self can now be used in place of current_object. The word self is more
commonly used across other object-oriented languages and it’s easier to type.
• An object name must uniquely identify an object. You cannot use the same name for a
function (either object function, global function, or built in function). If you try to use the
same name for cross purposes you will get an error. Previously you did not get errors for
this, but you should have - it was and is an error. <Warning!>

• Object may be named the same as variables. See below.

• When object name follows an “of” keyword (or “to” for send) the simple name of the
object can be used in place of the expression access method. The following two lines are
the same:
Get MyProp of oMyObj to iMyVar
Get MyProp of (oMyObj(self)) to iMyVar

The following sample shows how you can now access objects without using the
expression syntax.
Object oMyView is a ReportView

Object oLowRange is a Form


End_object

Object oHiRange is a Form


End_object

Object oMyreport is a SomeReport


End_object

Procedure Doit
integer iLow iHi
Get Value of oLowRange to iLow
Get Value of oHiRange to iHi
Send RunReport of oMyReport iHi iLow
End_procedure

End_Object

In both cases above, the object oMyObj must be defined before it can be used. It
can be defined by creating the object or by using the register_object command.

• Object names within expression must still be entered as an expression.


Move (MyProp(oMyObj)) to iMyVar // this is not legal
Move (MyProp(oMyobj(self))) to iMyVar // this is allowed
Get MyProp of oMyObj to iMyVar // this is allowed

• The move command allows you to move an object Id to a variable without needing to
place the object within an expression. The following two lines are the same:
Move oMyObj to hoMyObj
Move (oMyObj(self)) to hoMyObj

• If oMyObj is both the name of an object and the name of a variable (presumably a local
variable that is in scope) the variable name will have precedence. For example:
Object oObj1 is an Array
End_Object

Object oObj2 is an Array


Procedure Proc1
Send MyMsg to oObj1 // will send to object Obj1
End_Procedure
Procedure Proc1
integer oObj1
Move Self to oObj1
Send MyMsg of oObj1 // will send to oObj2
// this is very poor coding!!
End_Procedure
End_Object

• The simpler object addressing construct is handled by the compiler. The compiled result
of hObj and (hObj(self)) are identical. Both are access expressions. If you are going to
send a message to the same object many times within a method it is more efficient to
move the object handle to a variable (which is one evaluation) and to use the variable as
the message’s object handle.
Procedure Proc1
Integer hoArray
Integer iVal
Move oArray to hoArray // move object handle to variable
For iVal from 1 to 10000
Set value of hoArray iVal to “test Data”
Loop
End_Procedure

• You can only use this simplified syntax with the move command and with the object
handle of a message. You cannot use this syntax with parameters – you must use the full
expression syntax:

Set Main_DD to Customer_DD // this is not allowed!


Set Main_DD to (Customer_DD(Self)) // this is the proper syntax

Default Index Values in Messages

Note: Character-mode DataFlex does not use the “form_xxxx” interface described below
and does not support as many single-item entry objects (i.e. most entry forms and tables
are multi-item). Therefore in character mode DataFlex you are encouraged to always
provide the explicit item parameter in appropriate messages.

DataFlex has a number of messages that require an index parameter. These are often referred
to as “item based properties” where an item number (an index) is required to identify which item
data value should be queried. A better term for these item based properties would be collections.

A number of these messages have been turned into “auto-index” messages. If an index
parameter is not passed, a default value is provided. This was originally done to make it easy to
refer to the “current item” and was a feature of dubious value. This technique was applied to
much greater advantage in VDF where objects existed that internally were multi-item but from a
usage (and interface) point of view were always single item (item 0). It was not intuitive to have to
apply index values when there was always one and just one value, and its index was always
zero.

In VDF4 and 5, some multi-item messages (e.g., get/set Value) were auto-indexed and did not
require an index parameter (e.g., Get Value of hoMyForm to sVar). While other multi-item
messages were not and did require an index parameter (e.g., Set password_state of hoMyForm
to True). This inconsistency created confusion and errors.

In VDF6 a more consistent set of auto-index properties has been defined and is listed below. If an
index parameter is omitted a default value (usually 0) will be provided. This means that the
following two code lines are identical:
Set Value of oForm to sValue // suggested
Set Value of oForm 0 to sValue
In the above example, a form is a single item based object so you are encouraged to not use an
explicit index value. The following example shows two identical code lines. Since the array is
multi-item based, you are encouraged to always use explicit index values:
Set Value of oArray to sValue
Set Value of oArray 0 to sValue // suggested

We suggest that you apply the following standards to your programs:

• Single item objects (e.g., Form, Checkbox, ComboForm, dbForm) should never pass an
index number as a parameter. Allow VDF to provide index 0 for you.

• Multi item objects (e.g., Arrays, Grids, dbGrids) should always pass an index number.
Even if you know the value is zero or current_item explicitly pass the value. Never allow
VDF to apply a value for you.

• Since character mode DataFlex almost always uses multi-item objects,


you should always explicitly pass the index item value.
The compiler must explicitly recognize that a message requires an index parameter. Special
compiler commands are created to identify these messages. The indexed messages identified as
current-item based, which means that current_item is used if the index parameter is omitted, are:

Value Message Aux_Value


Shadow_State Select_State Checkbox_Item_State
Autoclear_State Center_State Entry_State
Item_Changed_State Item_Entry_Msg Item_Exit_Msg
Item_Validate_Msg Data_File Data_Field
Data_Window Item_Options Item_Option
Prompt_Object Zoom_Object

The difference between current-item based and form based messages are historical. Since we
only recommend that you omit the index parameter on single item objects the current-item should
always be zero. This means that both types of messages should be treated the same.

To allow the compiler to perform maximal error checking it is assumed that all of the above
messages will support one and only one parameter to the left of the To keyword. This allows the
compiler to recognize compiler errors in all of the following statements:
Set Value of oArray to 7 “My Value” // index in wrong location
Set Value of oArray 8 “My Value” // missing To
Set Value of oArray iVal // is iVal index or value?
Set Value 0 to iVal of oArray // object id in wrong place
Set Value oArray iVal “test” // what does this mean

The older compiler would permit most of the constructs creating programs that were quite difficult
to maintain.

A couple of messages are exceptions to this rule. The following index messages requires two
parameters to the right of the To keyword. They exist for historical reasons only. No new
messages will be created in this style. Those messages are: Item_Option, Form_Color,
Form_Style, and Form_Extended_Style.

Finally, note that the use of messages with optional parameters is an internal technique. Do not
extend this technique to your own custom messages.

Case Statement
DataFlex case statement has been shipped with DataFlex since version 3.1. It was not
documented and the package “case.mac” had to be used in a program to access it. It is now part
of the precompiled packages. The syntax is discussed elsewhere (see Language Guide and
Reference).

If you are using some other case command in your programs you are encouraged to change your
applications and use the official command provided with the product.

If you must use some other case command, you can disable the DataFlex case command by
commenting out the line “use case.mac” in dfbase.pkg and pre-compiling. This should be a
temporary solution. Next revision this disabling feature will not be supported.

Runtime and Package Changes


A number of bug fixes have been made in the runtime and the packages. A list of these can be
found at www.dataaccess.com/visualdataflex/updates. By recompiling your programs and running
them under the VDF6 runtime the bug fixes will immediately applied to you programs. There
several changes that may required changes in your programs.

Data Dictionary Changes


Changes were made in the Data Dictionaries to better support batch processes – in particular,
processes generated by the DataFlex WebApp Server. Most of these changes were made to be
invisible to existing applications. The most important changes are:

• The DDO’s field validations did not perform Required and Find_Req validations. In visual
views, the DEO would normally perform these operations but in batch processes these
validations were skipped. The validation now occurs as expected. This has caused a
certain amount of confusion, which is discussed below.

• The new message File_Field_Entry was created that moves data into the DDO’s field
buffer in much the same way keyboard entry does. It properly disables entry into fields
that are No_Put (both regular and foreign field), it performs capslocks as needed, and it
performs autofinds as needed. In some batch processing situations you would want to
use this message instead of set File_Field_current_value.

• The new message File_field_Find was created which performs a find similar to the
Item_Find message except that data for the find is moved into the DDO buffer and not
the DEO buffer.

• Extended Fields are not supported in DataFlex 3.2: The messages


DefineExtendedField and DefineAllExtendedFields can be used to create DDO support
for text and binary fields. This feature was added primarily for batch processing. Once
created the messages get/set File_field_current_value, get/set field_current_value, set
file_field_changed_value, set field_changed_value, and set file_field_entry can be used
to modify text fields. Again, this should really only be used with batch processes. Other
extended field messages have been created but they are considered advanced and
should be used with care.

• A new property, allow_foreign_new_save_state, makes it easier to save new parent


records when a child record is being saved. For example, you may wish to save a header
(parent) record the first time the detail (child) record is saved. In such a case, the parent
record should not behave as a foreign file and its allow_foreign_new_save_state should
be set True.
• Changed the way errors are reported when the DD encounters field_current_value
messages for extended and overlapped fields. In 5.0.6 we started reporting errors that
were ignored in prior revisions. This has caused a great deal of confusion.

• Within data dictionary objects, the message OnConstrain should be used in place of the
Begin_Constraints/End_Constraints command (or the Constrain procedure).

IMPORTANT: In VDF, the data dictionary objects only directly support date, string and numeric
fields. Text, binary and overlap fields are not supported and attempting to access them from
within the DD is an error. The most likely improper use of this would be to get or set the field
value with the field_current_value message. In previous versions of the DD packages these
errors were handled by ignoring the message and doing nothing. While the error was not
reported, the DDO was definitely not doing what you wanted it do. The right thing to do was to
report the error so in revision 5.0.6, these errors were reported as “Extended Field not defined”
errors. This caused confusion because programs that previously appeared to be working now
generated error messages. These errors occurred under the following conditions:

1. You attempted to access a text or binary field with the messages Get/Set
Current_field_value, Get/Set File_field_current_value or Get Field_changed_value. Since
these fields are not supported, in all cases, this is an error. You should look at your code
and make the required corrections.

2. You are improperly using overlap fields. You should not directly access overlap fields with
DDO messages. It is expected that you will use the underlying (primary) fields that make
up the overlap. In particular:

• You should not access overlaps with the field_current_value,


file_field_current_value or field_changed_value messages.

• You should never mark any overlap fields as a Key-field. It doesn’t work.
Instead, you should mark each underlying field as a key-field. A key field
can consist of multiple fields.

• You should not use overlap fields with field options, validation tables,
entry, exit or validation messages. You should use the underlying fields
instead.

Because this has caused so much confusion, the packages have been changed, so that a new
runtime error message will be generated if you attempt to improperly use an overlap field. The
reported error will be “999 - Invalid use of overlap with DD.” When displayed, the overlap file and
field number will also be displayed. This is a bug in your program that must be fixed. In most
cases, you will fix this by loading the Data Dictionary Builder, removing the DD field settings from
the overlap field and adding the field setting to the underlying fields.

If you have been improperly accessing text or binary fields you will receive the error message
“999 - Extended Field not defined in DD”. The offending file and field will also be reported with the
error. You will want to fix this error in your code.

IMPORTANT: In previous versions of VDF, Required and Find_Required validations were not
performed if the field needing the validation was not visually represented in a view. This validation
loophole has now been closed. This has caused some problems with existing programs. The
mostly likely cause of these problems and their solutions are:

• When a child field relates to a parent field, the required and find_req should always be
applied to the parent and not the child field. Setting the child-field is an error. In previous
versions of VDF this error went undetected. In VDF6 you will want to correct this.
• You should never set overlap fields as required or find_req.

• Do not set overlap fields as key-fields. Instead, you should set each underlying field that
makes up the overlap as a key field.

• If you are saving a new parent record at the same time you are trying to save a new child
record you may receive a required validation error. This occurs because the parent is
now treated as a foreign file. If any of the parent’s foreign validations are required or
find_req (and they probably are) you will get an error message when you attempt to save
the child record (which is attempting to also save a new parent record). The solution is to
set the parent’s allow_foreign_new_save_state to true. This tells the parent DDO that it
should not treat the file as a foreign file.

Changes to Existing Behaviors


A number of internal changes were made to data-dictionaries to support advanced batch
processing required for the DataFlex WebApp Server. These changes are private and should
have no effect on current programs. They are presented here in detail for completeness.

Function Field_Validate / Request_Validate

Field_Validate now performs a Required and Findreq validation as needed. Previously data-entry
objects only performed these validations which presented a problem with batch processing. Two
new private functions Valdiate_Required and Validate_FindReq were created to support this
change.

IMPORTANT: It is possible that the change in Field_Validate may alter the way your program
works. This most likely change will be that you will see a required or find-required error occur
when previously none occurred. In previous revisions of the data-dictionary required and find-
required validations were not performed unless a DEO existed for the field within the view. This
was a defect. It meant that these validation tests were never performed during batch processes
and that they might not be performed during normal data entry (if the field were not present as a
visual DEO item).

If you start encountering errors, you may wish to check your DD field settings. Your logic may be
incorrect. Find_Required is most often used with foreign files (parent files). If you are
encountering new validation problems with find_required keep in mind that setting the
Validate_Foreign_File_state property to false can disable the foreign (parent) field validation. This
property is normally set within a DD object and not class and is set in the main DDO and not the
parent DDO. It can be set for an entire view or could be set conditionally by augmenting the
function Request_Validate.

Function Validate_data_Sets / Function Validate_Fields

These functions are now passed an additional integer parameter (bNoStop) which determines if
the validation should end when the first error is encountered. These are private messages, which
should not be sent or augmented, and therefore this change should be transparent to all
applications. If you have used these messages you will need to change your code.

Function Data_Set

Previously this function only traversed upwards when looking for the DDO owner of the passed
file. This has been changed. If the owner DDO is not found during the upward sweep it will
traverse in a downward direction. Since DDOs are almost always found in an upwards sweep,
this should have no impact on applications.

Get/Set File_Field_Current_Value / Field_Current_Value


These messages may be used with extended DDO fields (text and binary). This allows you to
move text fields in and out of strings. This is only supported if extended fields are supported, if the
extended field has been created for the DDO, and the maximum string length is large enough to
hold the extended value. If any of these conditions are not met, an error will occur.

It is only expected that you will use these messages during batch processing.

Changes in the Error Report Message


A bug in the previous error handler caused errors in lines about 64K to not be properly displayed.
The fix for this required that an additional required parameter be passed to the Error_Report
message. If your programs do not directly send or augment the error_report message (and most
programs do not) you will not need to make any changes in your program. If your programs do
send or augment this message, you will need to make the changes described below.

The error object handler processes errors by sending the message Error_report. In previous
runtimes, two parameters were passed to this procedure, errorInfo (integer) and errorText
(string). ErrorInfo was a complex integer containing both error number and line number. This
“packing” scheme only works with programs with fewer than 64k lines. When programs contain
more than 64k lines error will not be properly reported.

This has been fixed in the runtime. The Error_report message now receives three (non-packed)
variables. The new format for error_report is:
procedure Error_Report integer iErrNum integer iErrLine string sErrMsg

IMPORTANT: If you have created any augmentations of Error_report you must change your
programs. Your procedure must now receive three parameters and you must make sure you
forward three parameters. For example, assume that you had the following procedure:
Procedure Error_Report integer iErrInfo string sErrMsg
integer hErr
integer iErrNum iErrLine
If (error_processing_state(self)=False) Begin
Set Error_processing_State to True // prevents recursion
Move (Hi(iErrInfo)) to iErrNum
Move (Low(iErrInfo)) to iErrLine
Send Log_this_Error iErrNum iErrLine iErrMsg
Get Old_Error_Object_Id to hErr
Send Error_Report to hErr iErrInfo sErrMsg
Set Error_processing_State to False
End
End_procedure

It would be changed as follows:


Procedure Error_Report integer iErrNum integer iErrLine string sErrMsg
handle hErr
If (error_processing_state(self)=False) Begin
Set Error_processing_State to True // prevents recursion
Send Log_this_Error iErrNum iErrLine iErrMsg
Get Old_Error_Object_Id to hErr
Send Error_Report to hErr iErrNum iErrLine sErrMsg
Set Error_processing_State to False
End
End_procedure

If you are sending the message Error_report to trigger an error you will also need to change your
parameter list. However, you should not be using the technique at all! If you wish to generate an
error you should do so with the Error command. The message error_report should only ever be
sent within the error_report procedure. Some developers have been using this improper
technique as a means on generating errors within text longer than 40 characters. Now that this
40-character limit has been removed you should no longer need to use this technique.
IMPORTANT: If you find that you are encountering nonsense error messages such as error
numbers of 0 and error text that makes no sense, then your program probably contains calls to
error_report or augmentations of error_report, and you did not change your source to handle the
additional parameter.
Back to Runtime and Package Changes

Changes in the Error Command


The error command now supports text string of more than 40 characters. The new limit is 2,048.
This allows you to pass much longer error messages in the error command. For example:
Error 300 “This string can now be MUCH longer than 40 characters”

You might also like