informix
Informix DataBlade API Programmer's Manual
Accessing SQL Data Types

Varying-Length Data Structures

A varying-length data structure can hold data whose length varies from one instance to the next. The database server uses the varying-length structure extensively to manage data transfer for DataBlade API modules. This chapter provides the following information about varying-length data structure:

Using a Varying-Length Structure

The DataBlade API provides the following data types to support varying-length data.

DataBlade API Data Type SQL Varying-Length Data Type For More Information
mi_lvarchar LVARCHAR mi_lvarchar Data Type, Input and Output Support Functions
mi_bitvarying None mi_bitvarying Data Type
mi_sendrecv SENDRECV Send and Receive Support Functions
mi_impexp IMPEXP Writing Support Functions
mi_impexpbin IMPEXPBIN Writing Support Functions

All these DataBlade API data types have the same underlying structure. For more information about the structure of a varying-length data type, see Creating a Varying-Length Structure.

Tip: The mi_lvarchar data type is not the same as the Illustra mi_varlena data type. The mi_varlena data type is a public structure whose members developers could access. The mi_lvarchar data type is an opaque C structure.

In addition, the mi_varlena data type is a contiguous structure that holds the varying-length data. The mi_lvarchar data type is a varying-length structure, which holds only a pointer to the actual data. For portability of Illustra applications that use mi_varlena, do not access mi_varlena directly. Instead, use the access macros (such as MI_GET_VARLEN and MI_GET_VARDATA), which the DataBlade API maps to the appropriate varying-length accessor functions.

These varying-length data types (mi_lvarchar, mi_bitvarying, mi_sendrecv, mi_impexp, mi_impexpbin, and varying-length opaque types) cannot fit into an MI_DATUM. Therefore, they must be passed by reference to and from C user-defined routines.

All data types, including mi_lvarchar, must be passed by reference within client LIBMI applications.

Managing Memory for a Varying-Length Structure

The following table summarizes the memory operations for a varying-length structure.

Default Memory Duration Memory Operation Function Name
Current memory duration Constructor mi_new_var(), mi_string_to_lvarchar(), mi_var_copy()
Destructor mi_var_free()

This section describes the DataBlade API functions that allocate and deallocate a varying-length structure.

Important: Do not use either the DataBlade API memory-management functions (such as mi_alloc() and mi_free()) or the operating-system memory-management functions (such as malloc() and free()) to handle allocation of varying-length structures.

Creating a Varying-Length Structure

Figure 2-5 lists the DataBlade API functions that create a varying-length structure. These functions are constructor functions for a varying-length structure.

Figure 2-5
DataBlade API Allocation Functions for Varying-Length Structures

Accessor Function Name Description
mi_new_var() Creates a new varying-length structure with a data portion of the specified size.
mi_string_to_lvarchar() Creates a new varying-length structure and puts the specified null-terminated string into the data portion. The data does not contain a null terminator once it is copied to the data portion.
mi_var_copy() Allocates and creates a copy of an existing varying-length structure. The copy contains its own data portion with the same varying-length data as the original varying-length structure.

The varying-length structure is not contiguous. The allocation functions in Figure 2-5 allocate this structure in two parts:

For example, suppose you call the mi_new_var() function that Figure 2-6 shows.

Figure 2-6
A Sample mi_new_var() Call

Figure 2-7 shows the varying-length structure that this mi_new_var() call allocates. This structure consists of both a descriptor and a data portion of 200 bytes. The mi_new_var() function returns a pointer to this structure, which the code in Figure 2-6 assigns to the new_lvarch variable.

Figure 2-7
Memory Allocated for a
Varying-Length Structure

The allocation functions in Figure 2-5 on page 2-21 allocate the varying-length structure with the current memory duration. By default, the current memory duration is PER_ROUTINE. For PER_ROUTINE memory, the database server automatically deallocates a varying-length structure at the end of the user-defined routine in which it was allocated. If your varying-length structure requires a longer memory duration, call the mi_switch_mem_duration() function before the call to one of the allocation functions in Figure 2-5 on page 2-21.

The allocation functions in Figure 2-5 on page 2-21 return the newly allocated varying-length structure as a pointer to an mi_lvarchar data type. For example, the call to mi_new_var() in Figure 2-6 on page 2-22 allocates a new mi_lvarchar structure with a data portion of 200 bytes.

To allocate other varying-length data types, cast the mi_lvarchar pointer that the allocation function returns to the appropriate varying-length data type. For example, the following call to mi_new_var() allocates a new mi_sendrecv varying-length structure with a data portion of 30 bytes:

This cast is not strictly required, but many compilers recommend it and it does improve clarity of purpose.

Deallocating a Varying-Length Structure

A varying-length structure has a default memory duration of the current memory duration. To conserve resources, use the mi_var_free() function to explicitly deallocate the varying-length structure once your DataBlade API module no longer needs it. The mi_var_free() function is the destructor function for a varying-length structure. It frees both parts of a varying-length structure: the varying-length descriptor and the data portion.

Important: Do not use the DataBlade API memory-management function mi_free() to deallocate a varying-length structure. The mi_free() function does not deallocate both parts of a varying-length structure.

Use mi_var_free() to deallocate varying-length structures that you have allocated with mi_new_var() or mi_var_copy(). Do not use it to deallocate any varying-length structure that the DataBlade API has allocated.

The mi_var_free() function accepts as an argument a pointer to an mi_lvarchar. The following call to mi_var_free() deallocates the mi_lvarchar varying-length structure that Figure 2-6 on page 2-22 allocates:

To deallocate other varying-length data types, cast the mi_lvarchar argument of mi_var_free() to the appropriate varying-length type, as the following code fragment shows:

This cast is not strictly required, but many compilers recommend it and it does improve clarity of purpose.

Accessing a Varying-Length Structure

The varying-length structure contains the following information:

Once you have allocated a varying-length structure, you can access the public members of this structure with the DataBlade API accessor functions in Figure 2-8.

Figure 2-8
Varying-Length Accessor Functions

Accessor Function Name Description
mi_get_varlen() Obtains from the varying-length descriptor the length of the varying-length data.
mi_get_vardata() Obtains from the varying-length descriptor the data pointer to the data contained in the data portion.
mi_get_vardata_align() Obtains from the varying-length descriptor the data pointer to the data contained in the data portion, adjusting for any initial padding required to align the data on a specified byte boundary.
mi_set_varlen() Sets the length of the varying-length data in the varying-length descriptor.
mi_set_vardata() Sets the data in the data portion of the varying-length structure.
mi_set_vardata_align() Sets the data in the data portion of the varying-length structure, adding any initial padding required to align the data on a specified byte boundary.
mi_set_varptr() Sets the data pointer in the varying-length descriptor to the location of a data portion that you allocate.

Important: To a DataBlade API module, the varying-length structure is an opaque C data structure. Do not access its internal fields directly. Informix does not guarantee that the internal structure of the varying-length structure will not change in future releases. Therefore, to create portable code, always use the accessor functions for this structure to obtain and store values.

Varying-Length Data and Null Termination

When you work with varying-length data, keep the following restrictions in mind:

Instead, always use the data length (which you can obtain with the mi_get_varlen() function) for all operations on varying-length data.

The varying-length accessor functions in Figure 2-8 on page 2-25 do not automatically interpret a null-terminator character. Instead, they transfer the number of bytes that the data length in the varying-length descriptor specifies, as follows:

To convert between null-terminated strings and an mi_lvarchar structure, use the mi_string_to_lvarchar() and mi_lvarchar_to_string() functions. For more information, see DataBlade API Functions for String Conversion.

Storing Varying-Length Data

This section provides the following information about how to store varying-length data:

Storing the Data

The mi_set_vardata() and mi_set_vardata_align() functions copy data into an existing data portion of a varying-length structure. These functions assume that the data portion is large enough to hold the data being copied. The code fragment in Figure 2-9 uses mi_set_vardata() to store data in the existing data portion of the varying-length structure that new_lvarch references.

Figure 2-9
Storing Data in a
Varying-Length Structure

In Figure 2-9, the call to mi_new_var() creates a new varying-length structure and sets the length field to 200. This call also allocates the 200-byte data portion (see Figure 2-7 on page 2-22).

Figure 2-10 shows the format of the varying-length structure that new_lvarch references after the call to mi_set_vardata() successfully completes.

Figure 2-10
Storing Data in a
Varying-Length Structure

The mi_set_vardata() function copies from the local_var buffer the number of bytes that the data length specifies. Your code must ensure that the data-length field contains the number of bytes you want to copy. In the code fragment in Figure 2-9 on page 2-27, the data-length field was last set by the call to mi_set_varlen() to 110 bytes. However, if the mi_set_varlen() function executed after the mi_set_vardata() call, the data length would still have been 200 bytes (set by mi_new_var()). In this case, mi_set_vardata() would try to copy 200 bytes starting at the location of the local_var variable. Because the actual local_var data only occupies 110 bytes of memory, 90 unused bytes remain in the data portion.

The mi_set_vardata() function aligns the data that it copies on 4-byte boundaries. If this alignment is not appropriate for your varying-length data, use the mi_set_vardata_align() function to store data on a byte boundary that you specify. For example, the following call to mi_set_vardata_align() copies data into the var_struc varying-length structure and aligns this data on 8-byte boundaries:

You can determine the alignment of a data type from its type descriptor with the mi_type_align() function.

Tip: You can also store data in a varying-length structure through the data pointer that you obtain with the mi_get_vardata() or mi_get_vardata_align() function. For more information, see Obtaining the Data Pointer.

The mi_set_vardata_align() function copies the number of bytes that the data-length field specifies.

Storing a Null-Terminated String

The mi_string_to_lvarchar() function copies a null-terminated string into a varying-length structure that it creates. This function performs the following steps:

  1. Allocate a new varying-length structure.
  2. The mi_string_to_lvarchar() function allocates the varying-length descriptor, setting the data length and data pointer appropriately. Both the data length and the size of the data portion are the length of the null-terminated string without its null terminator.

    The mi_string_to_lvarchar() function allocates the varying-length structure that it creates with the current memory duration.

  3. Copy the data of the null-terminated string into the newly allocated data portion.
  4. The mi_string_to_lvarchar() function does not copy the null terminator of the string.

  5. Pass back a pointer to the newly allocated varying-length structure as the second argument.

The following code fragment uses mi_string_to_lvarchar() to store a null-terminated string in the data portion of a new varying-length structure:

Figure 2-11 shows the format of the varying-length structure that lvarch references after the preceding call to mi_string_to_lvarchar() successfully completes.

Figure 2-11
Copying a
Null-Terminated String into a
Varying-Length Structure

The lvarch varying-length structure in Figure 2-11 has a data length of 110. The null terminator is not included in the data length because the mi_string_to_lvarchar() function does not copy the null terminator into the data portion.

If your DataBlade API module needs to store a null terminator as part of the varying-length data, you can take the following steps:

  1. Increment the data length accordingly and save it in the varying-length descriptor with the mi_set_varlen() function.
  2. Copy the data, including the null terminator, into the varying-length structure with the mi_set_vardata() or mi_set_vardata_align() function.
  3. These functions copy in the null terminator because the data length includes the null-terminator byte in its count. These functions assume that the data portion is large enough to hold the string and any null terminator.

Once you have performed these steps, you can obtain the null terminator as part of the varying-length data.

Important: If you choose to store null terminators as part of your varying-length data, your code must keep track that this data is null-terminated. The DataBlade API functions that handle varying-length structures do not assume the presence of a null terminator.

The following code fragment stores a string plus a null terminator in the varying-length structure that lvarch references:

Figure 2-12 shows the format of this varying-length structure after the preceding call to mi_set_vardata() successfully completes.

Figure 2-12
Copying a
Null-Terminated String into a
Varying-Length Structure

Setting the Data Pointer

The mi_set_varptr() function allows you to set the data pointer in a varying-length structure to memory that you allocate. The following code fragment creates an empty varying-length structure, which is a varying-length structure that has no data portion allocated:

Figure 2-13 shows the format of the varying-length structure that new_lvarch references after the fill_buffer() function successfully completes.

Figure 2-13
An Empty
Varying-Length Structure

The varying-length structure in Figure 2-13 is empty because it has:

Once you have an empty varying-length structure, you can use the mi_set_varptr() function to set the data pointer to the PER_COMMAND memory, as the following code fragment shows:

The preceding call to mi_set_varlen() updates the length in the varying-length structure to the length of 20 bytes. Figure 2-14 shows the format of the varying-length structure that new_lvarch references after the preceding call to mi_set_varptr() successfully completes.

Figure 2-14
Setting the Data-Portion Pointer
in a
Varying-Length Structure

Make sure that you allocate the data-portion buffer with a memory duration appropriate to the use of the data portion.

Obtaining Varying-Length Data

Use the following DataBlade API accessor functions to obtain information from a varying-length structure.

Varying-Length Information DataBlade API Accessor Function
Length of varying-length data mi_get_varlen()
Data portion mi_lvarchar_to_string(), mi_var_to_buffer(), mi_var_copy()
Data pointer mi_get_vardata(), mi_get_vardata_align()

Obtaining the Data Length

The mi_get_varlen() function returns the data length from a varying-length descriptor. Keep in mind the following restrictions about data length:

For the varying-length structure in Figure 2-7 on page 2-22, a call to mi_get_varlen() returns 200. For the varying-length structure that Figure 2-10 on page 2-28 shows, a call to mi_get_varlen() returns 110.

Obtaining Data as a Null-Terminated String

The mi_lvarchar_to_string() function obtains the data from a varying-length structure and converts it to a null-terminated string. This function performs the following steps:

  1. Allocate a new buffer to hold the null-terminated string.
  2. The mi_lvarchar_to_string() function allocates the string that it creates with the current memory duration.

  3. Copy the data in the data portion of the varying-length structure to the newly allocated buffer.
  4. The mi_lvarchar_to_string() function automatically copies the number of bytes that the data length in the varying-length descriptor specifies. It then appends a null terminator to the string.

  5. Return a pointer to the newly allocated null-terminated string.

Suppose you have the varying-length structure that Figure 2-11 on page 2-30 shows. The following code fragment uses the mi_lvarchar_to_string() function to obtain this varying-length data as a null-terminated string:

The code fragment does not need to allocate memory for the var_str string because the mi_lvarchar_to_string() function allocates memory for the new string. After the call to mi_lvarchar_to_string() completes successfully, the var_str variable contains the following null-terminated string:

Copying Data into a User-Allocated Buffer

The mi_var_to_buffer() function copies the data of an existing varying-length structure into a user-allocated buffer. The function copies data up to the data length specified in the varying-length descriptor. You can obtain the current data length with the mi_get_varlen() function.

The following code fragment copies the contents of the varying-length structure in Figure 2-11 on page 2-30 into the my_buffer user-allocated buffer:

After the successful completion of mi_var_to_buffer(), the my_buffer variable points to the following string, which is not null-terminated:

Important: Do not assume that the data in the user-allocated buffer is null-terminated. The mi_var_to_buffer() function does not append a null terminator to the data in the character buffer.

Copying Data into a New Varying-Length Structure

The mi_var_copy() function copies data from an existing varying-length structure into a new varying-length structure. This function performs the following steps:

  1. Allocate a new varying-length structure.
  2. For the new varying-length structure, the mi_var_copy() function allocates a data portion whose size is that of the data in the existing varying-length structure.

    The mi_var_copy() function allocates the varying-length structure that it creates with the current memory duration.

  3. Copy the data in the data portion of the existing varying-length structure to the data portion of the newly allocated varying-length structure.
  4. The mi_var_copy() function automatically copies the number of bytes that the data length in the existing varying-length descriptor specifies.

  5. Return a pointer to the newly allocated varying-length structure as a pointer to an mi_lvarchar.

Suppose you have the varying-length structure that Figure 2-11 on page 2-30 shows. The following code fragment uses the mi_var_copy() function to create a copy of this varying-length structure:

After the call to mi_var_copy() completes successfully, the lvarch_copy variable points to a new varying-length structure, as Figure 2-15 shows. The varying-length structure that lvarch_copy references is a completely separate structure from the structure that lvarch references.

Figure 2-15
Copying a
Varying-Length Structure

Obtaining the Data Pointer

The mi_get_vardata() and mi_get_vardata_align() functions obtain the actual data pointer from the varying-length descriptor. Through this data pointer, you can directly access the varying-length data.

The following code fragment uses the mi_get_vardata() function to obtain the data pointer from the varying-length structure in Figure 2-10 on page 2-28:

Figure 2-16 shows the format of the varying-length structure that new_lvarch references after the preceding call to mi_get_vardata() successfully completes.

Figure 2-16
Getting the
Data Pointer
from a
Varying-Length Structure

You can then access the data through the var_ptr data pointer, as the following code fragment shows:

The database server passes text data to a user-defined routine as an mi_lvarchar structure. Figure 12-3 on page 12-11 shows the implementation of a user-defined function called initial_cap(), which ensures that the first letter of a character string is uppercase and that subsequent letters are lowercase.

The initial_cap() function uses mi_get_vardata() to obtain each character from the data portion of the varying-length structure. This data portion contains the character value that the function receives as an argument. The function checks each letter to ensure that it has the correct case. If the case is incorrect, initial_cap() uses the data pointer to update the appropriate letter. The function then returns a new mi_lvarchar structure that holds the result. For more information, see Handling Character Arguments.

The varying-length structure aligns data on 4-byte boundaries. If this alignment is not appropriate for your varying-length data, use the mi_get_vardata_align() function to obtain the data aligned on a byte boundary that you specify. You can determine the alignment of a data type from its type descriptor with the mi_type_align() function.

Tip: When you obtain aligned data from a varying-length structure that is associated with an extended data type, specify an alignment value to mi_get_vardata_align() that is appropriate for the extended data type. For more information, see Memory Alignment.

The mi_get_vardata_align() function obtains the number of bytes that the data-length field specifies.


Informix DataBlade API Programmer's Manual, Version 9.2
Copyright © 1999, Informix Software, Inc. All rights reserved