|
To create a smart large object and save its LO handle in the database, take the following steps:
Figure 6-7 shows the first six of these steps that a DataBlade API module uses to insert the smart-large-object data into the emp_picture column of the employee table (Figure 6-3 on page 6-16).
Before you create a new smart large object, obtain a valid LO-specification structure to hold its storage characteristics. You can obtain an LO-specification structure in either of the following ways:
The mi_lo_spec_init() function is the constructor for the LO-specification structure. It performs the following tasks:
Important: Do not handle memory allocation for an LO-specification structure with system memory-allocation routines (such as malloc() or mi_alloc()) or by direct declaration. You must use the LO-specification constructor, mi_lo_spec_init(), to allocate a new LO-specification structure.
When you pass a NULL-valued pointer as the second argument of the mi_lo_spec_init() function, this function allocates an LO-specification structure.
This new LO-specification structure has the current memory duration.
The following code fragment declares a pointer called myspec and initializes this pointer to NULL:
After the execution of mi_lo_spec_init(), the myspec variable points to the newly allocated LO-specification structure. For more information on how to use an LO-specification structure to create a new smart large object, see Choosing Storage Characteristics.
If you provide a second argument that does not point to NULL, the mi_lo_spec_init() function assumes that this pointer references an existing LO-specification structure that a previous call to mi_lo_spec_init() has allocated. An LO-specification pointer that is not NULL allows a DataBlade API module to reuse an LO-specification structure. The following code fragment reuses the LO-specification structure that the LO_spec pointer references when the first_time flag is false:
Important: Before you use an LO-specification structure, make sure that you either call mi_lo_spec_init() with the LO-specification pointer set to NULL, or that you have initialized this pointer with a previous call to mi_lo_spec_init().
Once you have a valid LO-specification structure, you can use the accessor functions to obtain the storage characteristics from this LO-specification structure. For more information, see Defining User-Specified Storage Characteristics. For the syntax of the mi_lo_spec_init() function, see its description in Chapter 15, DataBlade API Function Descriptions.
Initializing an LO-Specification StructureThe mi_lo_spec_init() function initializes the LO-specification structure with values that obtain the system-specified storage characteristics. The system-specified storage characteristics are the defaults that the database server uses. They are the storage characteristics at the bottom of the storage-characteristics hierarchy.
After this initialization, you can change the values in the LO-specification structure so that:
For more information on storage characteristics and the storage-characteristics hierarchy, see Choosing Storage Characteristics.
The mi_lo_stat_cspec() function copies the storage characteristics from an existing smart large object to an LO-specification structure. This function performs the following tasks:
The LO-status structure holds status information for an existing smart large object. You initialize an LO-status structure with the mi_lo_stat() function. For more information on an LO-status structure, see Obtaining the Status of a Smart Large Object.
The following code fragment assumes that the old_LOfd variable has already been initialized as the LO file descriptor of an existing smart large object. This code fragment uses the storage characteristics of the existing smart large object (which the mi_lo_stat() function puts into the LO-specification structure that LO_spec specifies) as the storage characteristics for the new smart large object (which the mi_lo_create() function creates).
Once you initialize an LO-specification structure, you must ensure that this structure contains the desired storage characteristics. You want the LO-specification structure to contain the appropriate values for the storage characteristics you want the new smart large object to have. You then pass this LO-specification structure to one of the smart-large-object creation functions (Figure 6-5 on page 6-25) so that the smart-large-object optimizer can obtain the storage characteristics to use for the new smart large object.
You can choose the following storage characteristics for a new smart large object:
Important: For most applications, Informix recommends that you use the system-specified values for the disk-storage information. Most DataBlade API modules only need to ensure correct storage characteristics for an sbspace name (the location of the smart large object) and for the smart-large-object attributes.
For more smart large objects, you can use the following steps to obtain storage characteristics:
You can modify the storage characteristics that these steps obtain if:
Dynamic Server uses the storage-characteristics hierarchy, which Figure 6-8 shows, to obtain the storage characteristics for a new smart large object.
For a given storage characteristic, any value defined at the column level overrides the system-specified value, and any user-level value overrides the column-level value. Figure 6-9 summarizes the ways to specify disk-storage information for a smart large object.
Figure 6-9
For more information on any of the disk-storage information in Figure 6-9, see Disk-Storage Information.
Figure 6-10 summarizes the ways to specify attribute information for a smart large object.
Figure 6-10
For more information on any of the attributes in Figure 6-10, see Attribute Information.
Using System-Specified Storage CharacteristicsThe Database Administrator (DBA) establishes system-specified storage characteristics when he or she initializes the database server and creates an sbspace with the onspaces utility, as follows:
The system-specified storage characteristics apply to all smart large objects that are stored in the sbspace, unless a smart large object specifically overrides them with column-level or user-specified storage characteristics.
The onspaces utility establishes storage characteristics for an sbspace. For the storage characteristics that onspaces can set as well as the system defaults, see Figure 6-9 on page 6-42 and Figure 6-10 on page 6-43. For example, the following call to the onspaces utility creates an sbspace called sb1 in the /dev/sbspace1 partition:
Figure 6-11 shows the system-specified storage characteristics for all smart large objects in the sb1 sbspace.
Figure 6-11
For a smart large object that has system-specified storage characteristics, the smart-large-object optimizer calculates values for all disk-storage information except the sbspace name. The DBA can specify a default sbspace name with the SBSPACENAME configuration parameter in the ONCONFIG file. However, you must ensure that the location (the name of the sbspace) is correct for the smart large object that you create. If you do not specify an sbspace name for a new smart large object, the database server stores it in this default sbspace. This arrangement can quickly lead to space constraints.
Important: For new smart large objects, Informix recommends that you use the system-specified values of all disk-storage information except the sbspace name. The smart-large-object optimizer can best determine most of the values of the storage characteristics. Most applications only need to specify an sbspace name for their disk-storage information. Obtaining Column-Level Storage Characteristics
The DBA can establish column-level storage characteristics when he or she creates a database table with the CREATE TABLE statement. If the table contains a CLOB or BLOB column, the PUT clause of CREATE TABLE can specify the storage characteristics that Figure 6-9 on page 6-42 and Figure 6-10 on page 6-43 show. This statement stores column-level storage characteristics in the syscolattribs system catalog table.
The column-level storage characteristics apply to all smart large objects whose LO handles are stored in the column, unless a smart large object specifically overrides them with user-specified storage characteristics. Column-level storage characteristics override any corresponding system-specified storage characteristics.
For example, if the sb1 sbspace was defined as Figure 6-11 on page 6-44 shows, the following CREATE TABLE statement specifies column-level storage characteristics of a location and last-access time for the cat_descr column:
Figure 6-12 shows the storage characteristics for all smart large objects in the cat_descr column.
Figure 6-12
For more information on the syntax of the CREATE TABLE statement, see its description in the Informix Guide to SQL: Syntax.
The following DataBlade API functions obtain column-level storage characteristics for a specified CLOB or BLOB column:
Both these functions store the column-level storage characteristics for the specified column in an existing LO-specification structure. When a smart-large-object creation function receives this LO-specification structure, it creates a new smart-large-object instance that has these column-level storage characteristics.
Tip: When you use the column-level storage characteristics, you do not usually need to override the name of the sbspace for the smart large object. The sbspace name is specified in the PUT clause of the CREATE TABLE statement.
For example, the following code fragment obtains the column-level storage characteristics for the emp_picture column of the employee table (Figure 6-3 on page 6-16) and puts them in the LO-specification structure that LO_spec references:
The call to mi_lo_colinfo_by_name() overwrites the system-specified storage characteristics that the call to mi_lo_spec_init() put in the LO-specification structure. The LO-specification structure that LO_spec references now contains the column-level storage characteristics for the emp_picture column.
Defining User-Specified Storage CharacteristicsYou can establish user-specified storage characteristics when you create a new smart large object. DataBlade API functions can specify the storage characteristics that Figure 6-9 on page 6-42 and Figure 6-10 on page 6-43 show. The user-specified storage characteristics apply only to the particular smart-large-object instance that is being created. They override any corresponding column-level or system-specified storage characteristics.
Once you have an allocated LO-specification structure, you can use the appropriate LO-specification accessor functions to set fields of this structure. When a smart-large-object creation function receives this LO-specification structure, it creates a new smart-large-object instance that has these user-specified storage characteristics.
Important: The LO-specification structure, MI_LO_SPEC, is an opaque structure to DataBlade API modules. Do not access its internal structure directly. Informix does not guarantee that the internal structure of MI_LO_SPEC will not change in future releases. Therefore, to create portable code, always use the LO-specification accessor functions to obtain and store values from this structure.
The following sections describe how to access each group of storage characteristics in the LO-specification structure.
Accessing Disk-Storage InformationFigure 6-13 shows the disk-storage information along with the corresponding LO-specification accessor functions.
Figure 6-13
For most applications, Informix recommends that you use the values for the disk-storage information that the smart-large-object optimizer determines. If you know the size of the smart large object, Informix recommends that you specify this size in the mi_lo_specset_estbytes() function instead of in the onspaces utility or the CREATE TABLE or the ALTER TABLE statement. This mi_lo_specset_estbytes() function (and the corresponding ESQL/C ifx_lo_specset_estbytes() function) is the best way to set the extent size because the database server allocates the entire smart large object as one extent.
For more information on the disk-storage information, see Disk-Storage Information. You can also refer to the description of the appropriate LO-specification accessor function in Chapter 15, DataBlade API Function Descriptions.
Accessing AttributesThe LO-specification structure uses a bitmask flag, called an attributes flag, to specify the attributes of a smart large object. Figure 6-14 shows the attribute constants of an LO-specification structure.
Figure 6-14
Use the mi_lo_specset_flags() function to override system-specified or column-level attributes in the LO-specification structure and the mi_lo_specget_flags() function to retrieve the attributes flag from the LO-specification structure.
The milo.h header file defines the attribute constants: MI_LO_ATTR_LOG, MI_LO_ATTR_NO_LOG, MI_LO_ATTR_KEEP_LASTACCESS_TIME, and MI_LO_ATTR_NOKEEP_LASTACCESS_TIME.
Masking mutually exclusive flags results in an error. If you do not specify a value for a particular attribute, the database server uses the storage-characteristics hierarchy to determine this information.
For example, the following code fragment specifies the constants to enable logging the last-access time for the attributes flag in the LO-specification structure that LO_spec identifies:
For more information on the attributes of a smart large object, see Attribute Information. You can also refer to descriptions of the mi_lo_specset_flags() and mi_lo_specget_flags() functions in Chapter 15, DataBlade API Function Descriptions.
Once you have an LO-specification structure that describes the storage characteristics for the new smart large object, you can create the smart large object with one of the smart-large-object creation functions: mi_lo_copy(), mi_lo_create(), mi_lo_expand(), or mi_lo_from_file(). These smart-large-object creation functions perform the following tasks to create a new smart large object:
These smart-large-object creation functions initialize the following data structures for a smart large object:
A DataBlade API module can obtain an LO handle with any of the following methods:
Any of the smart-large-object creation functions (Figure 6-5 on page 6-25) can allocate memory for an LO handle when you specify a NULL-valued pointer for the last argument. For example, the code fragment declares a pointer to an LO handle, called LO_hdl, initializes it to NULL, and then calls the mi_lo_create() function to allocate memory for this LO handle:
After the execution of mi_lo_create(), the LO_hdl variable is a pointer to the new LO handle, which identifies the location of the new smart large object.
This new LO handle has a default memory duration of PER_ROUTINE. If you switch the memory duration, the creation function uses the current memory duration for the LO handle that it allocates.
If you provide an LO-handle pointer that does not point to NULL, the smart-large-object creation function assumes that memory has already been allocated for the LO handle and it uses the LO handle that you provide.
You can explicitly allocate an LO handle in either of the following ways:
However, this LO handle is still an opaque C data structure; that is, it is declared as a flat array of undifferentiated bytes and its fields are not available to the DataBlade API module.
Important: The LO handle structure is the only smart-large-object structure that a DataBlade API module can allocate directly. You must allocate other smart-large-object data structures, such as the LO-specification structure and the LO-status structure, with the appropriate DataBlade API constructor function.
Obtaining an LO File Descriptor
The smart-large-object creation functions (Figure 6-5 on page 6-25) return an LO file descriptor for a smart large object. The LO file descriptor is needed for most subsequent operations on the smart large object. However, this LO file descriptor is only valid within the current database connection.
The following code fragment uses the mi_lo_create() function to generate an LO file descriptor for a new smart large object:
Tip: A return value of zero (0) from a smart-large-object creation function does not indicate an error. The value zero (0) is a valid LO file descriptor.
Writing Data to a Smart Large Object
To write data to the sbspace of a smart large object, use one of the following smart-large-object functions:
These functions both write a specified number of bytes from a user-defined character buffer to the open smart large object that an LO file descriptor identifies. The smart-large-object optimizer determines the default extent size for the smart large object based on the amount of data that you write. Therefore, try to maximum the amount of data you write in a single call to mi_lo_write() or mi_lo_writewithseek().
Important: An attempt to write data to an sbspace that does not exist results in an error.
For more information on the syntax of the mi_lo_write() and mi_lo_writewithseek() functions, see their descriptions in Chapter 15, DataBlade API Function Descriptions.
In addition to a write operation, you might also need to perform the following operations on the open smart large object.
The INSERT or UPDATE statement can store the LO handle of a smart large object into the CLOB, BLOB, or opaque-type column. To store a smart large object in the database, follow these steps:
Tip: The data of the smart large object is stored when you write it to the sbspace of the smart large object.
When you save the LO handle in the CLOB or BLOB column, the smart-large-object optimizer increments the reference count of the smart large object by one. When you save the LO handle in an opaque-type column, the assign() support function for the opaque type must increment the reference count.
If you create a new smart large object but do not store it in a database column, the smart large object is a temporary smart large object. The database server does not guarantee that temporary smart large objects remain valid once they are closed. When all references to the smart large objects are deleted, the database server deletes the smart large object. For more information, see Deleting a Smart Large Object.
For more information on how to execute an INSERT or UPDATE statement, see Chapter 8, Executing SQL Statements.
Once you have stored the new smart large object in the database, make sure that any resources you no longer need are freed. When you create a new smart large object, you might need to free resources of the following data structures:
If any of the smart-large-object data structures have a memory duration of PER_ROUTINE, the database server automatically frees the structure when the user-defined routine completes.
The mi_lo_spec_init() function allocates an LO-specification structure in the current memory duration. Therefore, if an LO-specification structure has a memory duration of PER_ROUTINE, the database server automatically frees it when the user-defined routine completes.
To explicitly free the resources assigned to an LO-specification structure, use the mi_lo_spec_free() function. The mi_lo_spec_free() function is the destructor function for the LO-specification structure. When these resources are freed, they can be reallocated to other structures that your program needs.
The LO handle structure is allocated with the current memory duration. Therefore, if it has a memory duration of PER_ROUTINE, the database server automatically frees it when the user-defined routine completes.
To explicitly free the resources assigned to an LO handle, you can use:
When these resources are freed, they can be reallocated to other structures that your program needs.
Suppose you want to create a new smart large object for the cat_descr column in the catalog2 table that contains the following data:
The following code fragment creates a new smart large object, which assumes the storage characteristics of its column, cat_descr, and then modifies the logging behavior.
After the mi_lo_create() function executes:
Figure 6-15
Storage Characteristics for the New Smart Large Object
Figure 6-12 on page 6-46 shows the column-level storage characteristics for the cat_descr column and Figure 6-11 on page 6-44 shows the system-specified storage characteristics for the sb1 sbspace.
The mi_lo_writewithseek() function writes the buf data to the smart large object that lofd identifies. When the write operation is successful, the descrip LO handle is ready to be stored in the CLOB column with the INSERT statement.
For more information on how to insert a value into a column, see Chapter 8, Executing SQL Statements.