DEFINE DATASET statement

Defines a ProDataSet object that is created at compile time, and allows you to identify the temp-table buffers it incorporates and define the data relations between those buffers. This statement defines the ProDataSet for use in one or more external procedures, or within a single class or class hierarchy.

Syntax

DEFINE {[[ NEW ] SHARED ]|[ PRIVATE | PROTECTED ][ STATIC ]
   [ SERIALIZABLE ]} DATASET dataset-name 
  [ NAMESPACE-URI namespace][ NAMESPACE-PREFIX prefix]
  [ XML-NODE-NAME node-name][ SERIALIZE-NAME serialize-name ] 
  [ XML-NODE-TYPE node-type ][ SERIALIZE-HIDDEN ]
  [ REFERENCE-ONLY ] FOR buffer-name [ , buffer-name]...
  [ DATA-RELATION [data-rel-name ] FOR data-rel-spec ]...
  [ PARENT-ID-RELATION [data-rel-name] FOR parent-id-rel-spec]...
NEW SHARED DATASET dataset-name

Defines and identifies a ProDataSet object that can be shared by one or more procedures called directly or indirectly by the current procedure. The ProDataSet object remains available to other procedures until the procedure that defined it ends. The called procedures must define the same ProDataSet object name as SHARED. For shared ProDataSet objects, each buffer-name must be the name of a shared buffer.

Note: Because a static SHARED TEMP-TABLE cannot have a BEFORE-TABLE, you cannot track changes on a static SHARED DATASET.
SHARED DATASET dataset-name

Defines and identifies a ProDataSet object that was initially defined by another procedure as NEW SHARED. For shared ProDataSet objects, each buffer-name must be the name of a shared buffer.

The procedure that initially defines the object determines the name. The procedures that share the object must define the object with the same name.

[ PRIVATE | PROTECTED ][ STATIC ][ SERIALIZABLE ] DATASET dataset-name

Defines and identifies a ProDataSet object as a data member of a class, and optionally specifies an access mode (PRIVATE or PROTECTED) and scope (instance or STATIC) for that data member, as well as whether or not the ProDataSet object will participate in serialization (SERIALIZABLE). You cannot specify any of these options for a ProDataSet defined in an interface type definition (INTERFACE statement block) or when defining a ProDataSet as a data element of a procedure. For a data member ProDataSet, each buffer-name must be the name of a compatible data member buffer (see the FOR option).

Note: The specified options are applicable only when defining a data member for a class in a class definition (.cls) file. The PRIVATE/PROTECTED modifier and the STATIC modifier can appear in either order, e.g., DEFINE STATIC PRIVATE DATASET myDataSet... is valid syntax. You cannot shadow (override) the definition of a given ProDataSet data member in a class hierarchy.

PRIVATE ProDataSet data members can be accessed by the defining class. An instance can access a private ProDataSet data member of another instance if both instances are of the same class. PROTECTED ProDataSet data members can be accessed by the defining class and any of its derived classes. An instance can accesses a protected ProDataSet data member of a second instance of a class that is at the same level or higher in the class hierarchy. The default access mode is PRIVATE.

A ProDataSet defined with the STATIC option is a static data member of the class type for which it is defined, and it is scoped to the ABL session where it is referenced. ABL creates one copy of the specified class static ProDataSet on first reference to the class type, and ABL creates only one such copy for any number of instances of the class that you create. You cannot specify STATIC if you specify the REFERENCE-ONLY option. You can directly reference an accessible static ProDataSet data member from any other static or instance class member defined in the same class or class hierarchy.

Without the STATIC option, ABL creates an instance ProDataSet data member that is scoped to a single instance of the class where it is defined. ABL creates one copy of the specified instance ProDataSet for each such class instance that you create. You cannot directly reference an instance ProDataSet data member from a STATIC class member definition defined within the same class or class hierarchy.

Class-based objects that are defined as serializable (using the SERIALIZABLE option in the CLASS statement) can be serialized to binary or JSON format. By default, serializing an object to binary via the Progress.IO.BinarySerializer class includes all data members regardless of access mode. However, for JSON serialization via Progress.IO.JsonSerializer, only public data members are serialized. To include a protected or private ProDataSet object during JSON serialization, SERIALIZABLE must be added to the definition. See Serialize( ) method (JsonSerializer) for more information.

For more information on accessing ProDataSets of different access modes and scopes, see the reference entry for Class-based data member access.

Note: Members of a class are grouped into six namespaces, including buffers/temp-tables, methods, variables/properties/events, ProDataSets, queries, and data-sources. ProDataSets defined as members of a class share the same namespace. There can be only one class member in this namespace with a given name.

For more information on where and how to define data members in a class, see the CLASS statement reference entry.

DATASET dataset-name
Defines and identifies a ProDataSet object in an interface, or for access only within the current external procedure or as a data member of the current class.
NAMESPACE-URI namespace
An optional CHARACTER constant that specifies the URI for the namespace of the ProDataSet object.
NAMESPACE-PREFIX prefix
An optional CHARACTER constant that specifies the namespace prefix associated with the NAMESPACE-URI.
XML-NODE-NAME node-name

An optional CHARACTER constant that specifies the name of the XML element representing the ProDataSet in an XML Document. The default is dataset-name. Use this option when the serialized name either contains invalid characters for an ABL name or the serialized name is an ABL keyword.

Note: If you set SERIALIZE-NAME but do not set XML-NODE-NAME, the AVM sets XML-NODE-NAME equal to SERIALIZE-NAME.
XML-NODE-TYPE node-type
An optional CHARACTER constant that specifies the XML node type of the ProDataSet element represented in XML. The valid option values are "ELEMENT" and "HIDDEN". The default value is "ELEMENT".
SERIALIZE-HIDDEN

Indicates that the ProDataSet name is not written when the ProDataSet data or schema is serialized to JSON or XML.

This will support the WRITE-JSON( )and WRITE-XML( ) methods in case the root of the JSON string or XML document maps to a temp-table. For XML, the XML-NODE-TYPE attribute takes precedence over SERIALIZE-HIDDEN attribute.

SERIALIZE-NAME serialize-name
An optional CHARACTER constant that specifies the name of the ProDataSet as it should appear when serialized, for example into JSON or XML. The default is dataset-name. Use this option when the serialized name either contains invalid characters for an ABL name or the serialized name is an ABL keyword.
REFERENCE-ONLY

Specifies that the procedure or class defining this ProDataSet object is using the object definition only as a reference to a ProDataSet object that is defined and instantiated in another procedure or class, and specified as a parameter in the invocation of a RUN statement, a method in a class, or a user-defined function, using either the BY-REFERENCE or BIND option. The AVM does not instantiate the reference-only object. You cannot specify REFERENCE-ONLY if you specify the STATIC option.

Passing a reference-only ProDataSet object parameter to a local routine, using either the BY-REFERENCE or BIND option allows the calling routine and the called routine to access the same object instance (instead of deep-copying the parameter).

Note: If you pass the parameter to a remote procedure, the AVM deep-copies the parameter on OUTPUT and the reference-only parameter is bound to that copy.

When you pass a ProDataSet parameter to a local routine using the BY-REFERENCE option, both the calling and called routines access the calling routine's object instance (and ignore the called routine's object instance). Since the called routine's object instance is ignored, you should define the object as a reference-only object. When you define a reference-only ProDataSet object in the called routine and receive it from the calling routine using the BY-REFERENCE option, the AVM binds the definition of the object in the called routine to the object instance in the calling routine for the duration of the called routine. You cannot define a reference-only ProDataSet object in the calling routine and pass it to the called routine using the BY-REFERENCE option.

When you pass a ProDataSet parameter to a local routine using the BIND option, you can define a reference-only ProDataSet object in either the calling routine or the called routine as follows:

  • When you define a reference-only ProDataSet object in the calling routine and pass it to the called routine using the BIND option, the AVM binds the calling routine to the object instance in the called routine. The reference-only object definition remains bound to the object instance until the routine containing the reference-only object definition is deleted or terminates. The parameter must be an OUTPUT parameter.

    Note: If you also define the ProDataSet object instance in the called routine as a reference-only object, you must bind the object in the called routine before returning to the calling routine.
  • When you define a reference-only ProDataSet object in the called routine and receive it from the calling routine using the BIND option, the AVM binds the called routine to the object instance in the calling routine. The reference-only object definition remains bound to the object instance until the routine containing the reference-only object definition is deleted or terminates. The parameter must be an INPUT or INPUT-OUTPUT parameter.

In either case, you must specify the BIND option for the parameter in both the invocation of a RUN statement, a method in a class, or a user-defined function, and in the DEFINE PARAMETER statement.

Caution:
Do not delete the object or routine to which a reference-only ProDataSet object is bound, or you might be left with references to an object that no longer exists.

When you define a ProDataSet object as reference-only, you must also define all member temp-tables as such. A temp-table object defined as reference-only can be a member of a reference-only ProDataSet object or a standard ProDataSet object. However, if you define a reference-only temp-table in a standard ProDataSet object, you cannot use the ProDataSet object until you bind the reference-only temp-table.

FOR buffer-name [ , buffer-name]...

Specifies the name of compile-time defined temp-table buffer that is scoped to the procedure or class in which the ProDataSet object is defined. For a shared ProDataSet, each buffer-name must be a shared buffer. If the ProDataSet is a data member of a class, you must specify the name of a compatible buffer data member. Thus, if the ProDataSet is a static data member, the buffer must also be a static data member; if the ProDataSet is PROTECTED, the buffer must also be defined as PROTECTED or inherited from a super class; and if the ProDataSet is PRIVATE, the buffer can be defined as either PRIVATE or PROTECTED. If the ProDataSet is a PRIVATE instance data member, you can also specify a default database table buffer; you cannot specify a default database buffer for a ProDataSet data member defined with any other combination of access mode and scope.

Note: ABL defines the default buffer for every database table that you access in a class as a PRIVATE instance buffer data member.
DATA-RELATION [data-rel-name ] FOR data-rel-spec

Specifies an optional data-relation object.

The data-rel-name argument lets you name the data-relation object. You can use this name to obtain the object's handle at run time. This argument is optional. The default name is Relationn (where n starts at 1 for each ProDataSet object).

Thedata-rel-spec argument specifies a pair of parent and child buffers for the data-relation object using the following syntax:

parent-buffer-name, child-buffer-name field-mapping-phrase
[ REPOSITION ][ NESTED [ FOREIGN-KEY-HIDDEN ]][ NOT-ACTIVE ] 
[ RECURSIVE ]
parent-buffer-name
The parent buffer in the data-relation object. This must be one of the buffers identified by buffer-name.
child-buffer-name
The child buffer in the data-relation object. This must be one of the buffers identified by buffer-name.
field-mapping-phrase

Specifies the fields in the relation using the following syntax:

RELATION-FIELDS ( parent-field1 , child-field1 
  [ , parent-fieldn , child-fieldn]... ) 

The first field in the pair is from the parent buffer, the second field is from the child buffer. When filling the ProDataSet object, the AVM retrieves data for the child buffer based on an equality match between all pairs of fields unless the Data-Relation is deactivated or there is an explicit query definition for the data source of the child buffer.

You can define a query for the data source of the child buffer, or supply custom logic in response to FILL events that take over complete responsibility for filling one level of the ProDataSet object. In these cases, the field-mapping-phrase is not used.

When navigating the ProDataSet object, the AVM filters the data in the child buffer to include only children of the current parent.

REPOSITION

Specifies the relation mode as REPOSITION. The relation mode is SELECTION, by default.

When the relation mode is SELECTION, the ProDataSet object fills the child temp-table of the relation with all records related to the current parent. When the relation mode is REPOSITION, the relation is effectively ignored during a FILL, and the child of the relation is treated as if it were a top-level buffer.

When navigating a filled ProDataSet object with a SELECTION relation, related data is filtered as it is browsed. This means the child query of the relation is filtered to make available only children of the current parent, and the query is re-opened each time the parent table is repositioned. When navigating a filled ProDataSet object with a REPOSITION relation, the child table query is always set to match all the rows in the child table, and is not re-opened when the parent changes. Only the buffer for the child is repositioned to the matching child for the current parent.

A data-relation defined with REPOSITION or SELECTION is overridden if a query is defined for a child relation data-source. Normally, if REPOSITION is not specified, the child query selects the children of the parent. Coding a query for the child data-source overrides whether or not a SELECTION or REPOSITION relation mode was defined. By removing the query of the child data-source, the default child table load occurs.

NESTED

Specifies that child rows of a ProDataSet buffer are nested within their parent rows when writing a JSON representation of data or an XML representation of data or schema. This also causes the XML Schema definitions for the related temp-tables to be nested.

Note: If you do not nest child tables, the JSON string loses the data relation information. The serialization process also loses any information about key columns.
FOREIGN-KEY-HIDDEN

Specifies that foreign key fields in nested data relations are omitted when writing JSON or XML data, and that foreign key fields are optional in the XML Schema representation of the child table definition. This option can only be specified if the NESTED option is also specified.

When working with large ProDataSets, omitting foreign keys in nested child records can yield smaller JSON strings and XML documents, more efficient network transfers, and performance gains with the READ-*( ) and WRITE-*( ) methods.

Think carefully before deciding to use this feature. The READ-*( ) methods automatically populate foreign keys in nested child records with the value in the outer parent record when the foreign key is omitted from the serialized data. Unless you are sure that the data's receiver will do the same, you should not specify FOREIGN-KEY-HIDDEN in your nested data-relations.

For example, while .NET can read this XML document and populate an ADO .NET Dataset, it will create rows in the child DataTable with a null value for the foreign key field. This is because it does not recognize the data-relation definition in the XML Schema as NESTED. ABL uses the prodata:nested attribute in the XML Schema. .NET only recognizes its own msdata:IsNested attribute.

NOT-ACTIVE
Specifies that the data-relation is inactive. For example, this allows you to have two relations between the same two ProDataSet temp-table buffers, but only have one relation active at a time.
RECURSIVE
Instructs the ProDataSet FILL to load self-referencing elements, such as bill-of-materials parent/child tables or organization chart manager/employee tables. Support is provided for a recursive data-relation during a FILL for a ProDataSet or temp-table buffer. Navigation is not supported, but can be done normally through .NET, Java, or a recursive ABL procedure.
PARENT-ID-RELATION [ data-rel-name ] FOR parent-id-rel-spec

Specifies that:

  • The relationship between the parent and child buffer is based on the RECID of the parent record when reading from or writing to an XML document or JSON string.
  • The child rows of a ProDataSet buffer are nested within their parent rows when the ProDataSet data or schema is rendered to an XML document or JSON string.
  • The child RECID field is not serialized.
data-rel-name
An optional argument that lets you name the data-relation. You can use this name to obtain the PARENT-ID-RELATION's handle at run time. The default value is Relationn (where n starts at 1 for each ProDataSet).
parent-id-rel-spec

Specifies a pair of parent and child buffers for the PARENT-ID-RELATION, the RECID field in the child buffer, and the XML and JSON serialization order for parent record fields using the following syntax:

parent-buffer-name, child-buffer-name PARENT-ID-FIELD id-field
[ PARENT-FIELDS-BEFORE ( parent-field1
  [ , parent-field2]... )]
[ PARENT-FIELDS-AFTER ( parent-field1
  [ , parent-field2]... )]
parent-buffer-name
Specifies the name of the parent buffer in PARENT-ID-RELATION. This is one of the buffers identified by buffer-name.
child-buffer-name
Specifies the child buffer in PARENT-ID-RELATION. This is one of the buffers identified by buffer-name.
PARENT-ID-FIELD id-field
Specifies the RECID field in child-buffer-name. When writing records from the parent-buffer-name temp-table to XML or JSON, child-buffer-name records whose id-field's value is equal to the RECID of the parent record will be nested within the parent record's XML node or JSON string.
PARENT-FIELDS-BEFORE ( parent-field1[ , parent-field2]... )
An optional phrase that specifies the fields from the parent-buffer-name temp-table record that are to be written to XML before any child-buffer-name temp-table records.
PARENT-FIELDS-AFTER ( parent-field1[ , parent-field2]... )
An optional phrase that specifies the fields from the parent-buffer-name temp-table record that are to be written to XML after all child-buffer-name temp-table records.

When neither PARENT-FIELDS-BEFORE or PARENT-FIELDS-AFTER are specified, the default behavior is to write all the fields from the parent record to XML before any nested child records.

If a PARENT-ID-RELATION contains PARENT-FIELDS-BEFORE or PARENT-FIELDS-AFTER, then all the fields from the parent buffer that have XML-NODE-TYPE as ELEMENT must be listed among the PARENT-ID-RELATIONs containing the buffer as parent-buffer-name. Else, the AVM raises a compiler error. The compiler also checks for duplicate entries.

Notes

Example

For examples of ProDataSet definitions and usage, see OpenEdge Development: ProDataSets.

For examples of instance and static ProDataSet data member definitions, see the descriptions of r-CustObj.cls, r-CustObjStatic.cls, and r-CustObjAbstract.cls in the CLASS statement reference entry.

Notes

See also

Buffer object handle, Class-based data member access, CREATE DATASET statement, Data-relation object handle, DEFINE QUERY statement, DEFINE TEMP-TABLE statement, GET-TOP-BUFFER( ) method, NUM-REFERENCES attribute, OPEN QUERY statement, ProDataSet object handle, RECURSIVE attribute