Products Support Documentation Download
Source Code Changes

The "struct" definitions generated by v12 ddlp are used by functions like d_fillnew and d_recread. These structures are also available in v14. While the v12 header file name is dbname.h, the v14 header file name is dbname_structs.h. This name must be changed in source files that reference the file.

Note that the procedure in step 4 above will automatically make many of the required source code changes.

The following trivial schema can be used to illustrate the differences, with v12 on the left and v14 on the right:

v12: school.ddl
database school
{
record class {
char title[15];
}
record student {
char last_name[15];
char first_name[15];
}
set students {
order ascending;
owner class;
member student by last_name;
}
}
v14: school.sdl
create table class (
title char(14) primary key
);
create table student (
last_name char(14),
first_name char (14),
students char(14)
references class(title)
);
Compilation procedure:
Important Note About Record Structures

Please note that the v14 structure definitions contain more fields than their v12 counterparts. These have two purposes. The first purpose is to contain a foreign key value that doesn't actually reside in the record - it's a virtual field. For example, the v14 students[15] field in the STUDENT record is a foreign key value. It exists to represent the set relationship between class and student. When a student is in a class set, the title of the class is "stored" in the students field as a reference to the class record.

The second purpose of the additional fields is to indicate whether nullable fields are null or not. In the above example, the CLASS title is a primary key can cannot be nullable. The fields in the STUDENT record may be null. if any of the _*_has_value fields are "RDM_COL_HAS_VALUE", the data in the corresponding fields is valid. This goes for both reading and writing the data.

Non-null foreign keys are used to indicate set membership. Null foreign keys indicate that the record is not connected to that set.

These changes in the structure definitions have implications on existing application code. If a d_recread function is called, followed by changes to individual field values, followed by d_recwrite, the additional fields will be correct. However, if d_fillnew is used, it is very important to initialize the _has_value and foreign key fields.

To be compatible with v12 initially, the v14 program should initialize all _has_value fields to "RDM_COL_HAS_VALUE" except for foreign key fields, which should be null. This is because the v12 record creation concept is to create the record first, then connect it to any sets. For example, to create a student record, the following code should be used:

v12
struct student studentRec;
strcpy(studentRec.last_name, last_name);
strcpy(studentRec.first_name, first_name);
rc = d_fillnew(STUDENT, &studentRec, task, 0);
rc = d_connect(STUDENTS, task, 0);
v14
STUDENT studentRec;
memset(&studentRec, 0, sizeof(STUDENT));
strcpy(studentRec.last_name, last_name);
strcpy(studentRec.first_name, first_name);
studentRec.students_has_value = RDM_COL_HAS_VALUE;
rc = d_fillnew(STUDENT, &studentRec, task, 0);
rc = d_connect(STUDENTS, task, 0);

The above code presumes that the current owner is set, so that the d_connect will make the new student record a part of its set.

The recommended v14 coding style will be to create and connect in the same function. This is done by setting the foreign key value and making it non-null:

STUDENT studentRec;

strcpy(studentRec.last_name, last_name);
strcpy(studentRec.first_name, first_name);
strcpy(studentRec.students, class_title);
rc = d_fillnew(STUDENT, &studentRec, task, 0);

The v14 procedure does not require the current owner to be established prior to the connection, potentially saving a step.