Home | Previous Page | Next Page   Creating User-Defined Routines > Extending Data Types > Creating an Opaque Data Type >

Designing an Opaque Data Type

As with most data types, an opaque data type can have two representations for its data:

To design an opaque data type, you must determine these representations for the opaque-type data.

Determining External Representation

The external representation of an opaque data type is a character string. This string is the literal value for the opaque-type data. A literal value can appear in SQL statements most anywhere that the binary value can appear. For your opaque-type data to be valid as a literal value in SQL statements, you must define its external representation. It is important that the external representation be reasonably intuitive and easy to enter.

Tip:
The external representation of an opaque data type is its ASCII representation.

Suppose you need to create an opaque type that holds information about a circle. You could create the external representation that Figure 112 shows for this circle.

Figure 112. External Representation of the circle Opaque Data Type
begin figure description - This figure is described in the surrounding text. - end figure description

With the external representation in Figure 112, an INSERT statement can specify a literal value for a column of type circle with the following format:

INSERT INTO tab1 (id_col, circle_col) VALUES (1, "(2, 3, 9)");

Similarly, when an opaque type has an external representation, a client application such as DB–Access (which displays results as character data) can display a retrieved opaque-type value as part of the output of the following query:

SELECT circle_col FROM tab1 WHERE id_col = 1;

In DB–Access, the results of this query would display as follows:

(2, 3, 9)

Tip:
The external representation of an opaque data type is handled by its input and output support functions. For more information, see Input and Output Support Functions.

Determining Internal Representation

The internal representation of an opaque data type is a C data structure that holds the information that the opaque type needs. The internal representation of an opaque type that is stored in a database is called its server internal representation. Inside this internal C structure, use the platform-independent DataBlade API data types (such as mi_integer and mi_real) to improve the portability of the opaque data type.

Tip:
The internal representation of an opaque data type is a binary format that might not match the external binary format surfaced to the client.

For example, Figure 113 shows the circle_t data structure, which holds the values for the circle opaque data type.

Figure 113. Internal Representation of the circle Opaque Data Type
typedef struct 
   {
   mi_double_precision    x;
   mi_double_precision    y;
   } point_t;

typedef struct
   {
   point_t                center;
   mi_double_precision    radius;
   } circle_t;

The CREATE OPAQUE TYPE statement uniquely names the opaque data type. It is recommended that you develop a unique prefix for the name of an opaque data type. If your DataBlade module uses a prefix, such as USR, you could begin the names of opaque types with this prefix. For example, you might use the prefix USR on all database objects that your DataBlade module creates. The preceding circle_t opaque type could be named USR_circle_t to ensure that it does not conflict with opaque types that other DataBlade modules might create.

You register the opaque data type with the CREATE OPAQUE TYPE statement, which stores information about the opaque type in the sysxtdtypes system catalog table. When you register an opaque data type, you provide the following information about the internal representation of an opaque type:

Determining the Size of an Opaque Type

To save space in the database, you should lay out the internal representation of the opaque type as compactly as possible. The database server stores values in its internal representation, so any C-language structure with padding between entries consumes unnecessary space. You must also decide whether your opaque data type is to be of fixed length or varying length. The following sections briefly describe each of these kinds of opaque types.

Fixed-Length Opaque Data Type

If the C structure that holds your opaque type is always the same size, regardless of the data it holds, you can declare the opaque type as a fixed-length opaque type. You tell the database server that an opaque type is fixed length when you register the opaque type. In the CREATE OPAQUE TYPE statement, you must include the INTERNALLENGTH modifier to specify the fixed size of the C structure. The database server stores the value of the INTERNALLENGTH modifier in the length column of the sysxtdtypes system catalog table.

The circle_t C structure (which Figure 113 defines) is a fixed-length structure because all of its member fields have a constant size. Therefore, the following CREATE OPAQUE TYPE statement registers a fixed-length opaque type named circle for the circle_t structure:

CREATE OPAQUE TYPE circle (INTERNALLENGTH = 24);

The size of a fixed-length opaque data type must match the value that the C-language sizeof directive returns for the C structure. On most compilers, the sizeof( ) directive performs cast promotion to the nearest four-byte size to ensure that the pointer match on arrays of structures works correctly. However, you do not need to round up for the size of a fixed-length opaque data type. Instead you can specify alignment for the opaque data type with the ALIGNMENT modifier. For more information, see Specifying the Memory Alignment of an Opaque Type.

Important:
The routine manager does perform cast promotion on argument values smaller than the size of the MI_DATUM data type when it pushes routine arguments onto the stack. On some platforms, small values can create problems with pointer matching. For more information, see Pushing Arguments Onto the Stack.

The size of the fixed-length opaque type determines the passing mechanism for the opaque type. For more information, see Determining the Passing Mechanism for an Opaque Type.

You can obtain information about support functions for the circle fixed-length opaque type in Writing Opaque-Type Support Functions. The following table lists the circle support functions that this section declares.

Support Function for
circle Opaque Type
Where to Find Declaration
Input Figure 117
Output Figure 120
Receive Figure 123
Send Figure 126
Import Figure 129
Export Figure 132
Importbin Figure 135
Exportbin Figure 138
Varying-Length Opaque Data Type

If the C structure that holds your opaque type can vary in size depending on the data it holds, you must declare the opaque type as a varying-length opaque type. The opaque type can contain character strings. Each instance of the opaque type can contain a character string with a different size. When you define the internal representation of a varying-length opaque, make sure that only the last member of the C structure is of varying size.

Figure 114 shows the internal representation for a varying-length opaque data type named image.

Figure 114. Internal Representation for the image Opaque Data Type
typedef struct 
   {
   mi_integer         img_id;
   mi_integer         img_thresh_trck;
   mi_integer         img_thresh;
   mi_date            img_date;
   mi_integer         img_flags;
   mi_lvarchar   img_data;
   } image_t;

You tell the database server that an opaque type is varying length when you register the opaque type. In the CREATE OPAQUE TYPE statement, you must include the INTERNALLENGTH modifier with the VARIABLE keyword.

The CREATE OPAQUE TYPE statement in Figure 115 registers the image opaque type (which Figure 114 defines) as a varying-length opaque type.

Figure 115. Registration of the image Opaque Data Type
CREATE OPAQUE TYPE image 
   (INTERNALLENGTH = VARIABLE);

The database server stores the value of the INTERNALLENGTH modifier in the length column of the sysxtdtypes system catalog table. For varying-length opaque types, this column holds a value of zero (0).

You can obtain information about support functions for the image varying-length opaque type in Writing Opaque-Type Support Functions. The following table lists the image support functions that this section declares.

Support Function for
image Opaque Type
Where to Find Declaration
Input Figure 119
Output Figure 122
Receive Figure 125
Send Figure 128
Import Figure 131
Export Figure 134
Importbin Figure 137
Exportbin Figure 140

The database server requires you to store the C data structure for a varying-length opaque type in an mi_lvarchar structure. To store varying-length data in the mi_lvarchar structure, you need to code support functions. The size limitations of a varying-length structure apply to a varying-length opaque type as follows:

For example, the following CREATE OPAQUE TYPE statement defines a varying-length opaque type named var_type whose maximum size is four kilobytes:

CREATE OPAQUE TYPE var_type 
   (INTERNALLENGTH=VARIABLE, MAXLEN=4096);

Because the database server uses mi_lvarchar to transfer varying-length data, the passing mechanism for a varying-length opaque type is always by reference. For more information, see Determining the Passing Mechanism for an Opaque Type.

Specifying the Memory Alignment of an Opaque Type

When the database server passes an opaque data type to a UDR, it aligns the data on a certain byte boundary. By default, the database server uses a four-byte alignment for the internal representation of an opaque type. Four bytes is the standard alignment for 32-bit platforms.

64-bit

On 64-bit platforms, alignment should usually be eight bytes.

End of 64-bit

You can specify a different memory-alignment requirement for your opaque type with the ALIGNMENT modifier of the CREATE OPAQUE TYPE statement. The database server stores the value of the ALIGNMENT modifier in the align column of the sysxtdtypes system catalog table.

Actual alignment requirements depend on the C definition of the opaque type and on the system (hardware and compiler) on which the opaque data type is compiled. The following table summarizes valid alignment values for some C data types.

Value for
ALIGNMENT
Modifier
Meaning Purpose
1 Align structure on one-byte boundary Structures that begin with one-byte quantities
2 Align structure on two-byte boundary Structures that begin with two-byte quantities, such as mi_unsigned_smallint
4 (default) Align structure on four-byte boundary Structures that begin with four-byte quantities, such as mi_real or mi_unsigned_integer
8 Align structure on eight-byte boundary Structures that contain members of the mi_double_precision data type

Arrays of a data type must follow the same alignment restrictions as the data type itself. However, structures that begin with single-byte characters (such as mi_boolean or mi_char) can be aligned anywhere.

When you obtain aligned data for an opaque data type from a varying-length structure, use the mi_get_vardata_align( ) function. Make sure that the align argument of mi_get_vardata_align( ) matches the value of the align column in the sysxtdtypes system catalog table for the opaque type. For example, the mi_double_precision data type is aligned on an eight-byte boundary. If an opaque type contains an array of mi_double_precision values, use mi_get_vardata_align( ) with an align value of 8 to access the data portion of the mi_double_precision array.

The following call to mi_get_vardata_align( ) obtains data that is aligned on eight-byte boundaries from the var_struc varying-length structure:

opaque_type_t *buff;
mi_lvarchar *var_struc;
...
buff = (opaque_type_t *)mi_get_vardata_align(var_struc, 8);
Determining the Passing Mechanism for an Opaque Type

The way that the DataBlade API passes the internal representation of an opaque type in an MI_DATUM structure depends on the kind of opaque type, as follows:

Important:
Only a fixed-length opaque value of a data type that can always fit into an MI_DATUM structure can be passed by value.

If the internal representation of a fixed-length opaque type can fit into an MI_DATUM structure, the routine manager can pass the internal representation by value. Suppose you have the declaration in Figure 116 for a fixed-length opaque type named two_bytes.

Figure 116. Internal Representation for the two_bytes Opaque Data Type
typedef two_bytes_t mi_smallint;

The following CREATE OPAQUE TYPE statement specifies that the two_bytes fixed-length opaque type can be passed by value:

CREATE OPAQUE TYPE two_bytes (INTERNALLENGTH=2, 
   ALIGNMENT=2, PASSEDBYVALUE);

Figure 121 declares the output support function for the two_bytes fixed-length opaque type. The intrnl_format parameter in this declaration is passed by value. In contrast, the circle fixed-length opaque type (which Figure 113 declares) cannot fit into an MI_DATUM structure. Therefore, its output support function must declare its intrnl_format parameter as passed by reference, as Figure 120 shows.

When the routine manager receives data from a varying-length opaque type, it passes the data to the C UDR in an mi_lvarchar varying-length structure that the UDR allocates. The routine manager also passes a pointer to this mi_lvarchar structure as the MI_DATUM structure for the UDR argument. Therefore, a C UDR must have its parameter declared as a pointer to an mi_lvarchar structure when the parameter accepts data from varying-length opaque types. Figure 122 shows the declaration of the output support function for the image varying-length opaque type.

Home | [ Top of Page | Previous Page | Next Page | Contents | Index ]