Enterprise Edition Home | Express Edition Home | Previous Page | Next Page   Data Manipulation > Using Complex Data Types > Collections >

Accessing Elements of a Collection

The DataBlade API provides the following functions for accessing collection data types.

DataBlade API Collection Function Description
mi_collection_copy( ) Creates a copy of an existing open collection
mi_collection_delete( ) Deletes an element from a collection
mi_collection_fetch( ) Fetches an element from a collection
mi_collection_insert( ) Inserts a new element into an open collection
mi_collection_update( ) Updates an element in an open collection

Positioning the Cursor

When you open a collection cursor with mi_collection_open( ), the cursor position points to the first element of the collection. The cursor position identifies the current element in the collection cursor. The DataBlade API functions that access a collection must specify where in the collection to perform the operation. To specify location, these functions all have an action argument of type MI_CURSOR_ACTION, which supports the cursor-action constants in Table 21.

Table 21. Valid Cursor-Action Constants
Cursor Movement Cursor-Action Constant Valid Cursor Types
Sequential Scroll
Move the cursor position one element forward within the cursor MI_CURSOR_NEXT Yes Yes
Move the cursor position one element backward within the cursor MI_CURSOR_PRIOR No Yes
Move the cursor position to the beginning of the cursor, at the first element MI_CURSOR_FIRST Only if the cursor position does not move backward Yes
Move the cursor position to the end of the cursor, at the last element MI_CURSOR_LAST Yes Yes
Move the cursor to the absolute position within the cursor, where the first element in the cursor is at position 1. MI_CURSOR_ABSOLUTE Yes Yes
As long as collection is a LIST because only LISTs have ordered elements
Move the cursor forward or back a specified number of elements from the current position. MI_CURSOR_RELATIVE Only if relative position is a positive value Yes

Relative position can be a negative or positive value

As long as collection is a LIST because only LISTs have ordered elements
Leave the cursor position at its current location. MI_CURSOR_CURRENT Yes Yes

The following code fragment uses the mi_collection_fetch( ) function to fetch a VARCHAR element from a collection:

/*
 * Fetch next VARCHAR( ) element from a collection.
 */

   MI_CONNECTION *conn;
   MI_COLL_DESC *colldesc;
   MI_ROW_DESC  *rowdesc;
   MI_COLLECTION *nest_collp;
   MI_DATUM value;
   mi_integer ret_code, ret_len;
   char *buf;

   /* Fetch a VARCHAR( ) type */
   ret_code = mi_collection_fetch(conn, colldesc,
      MI_CURSOR_NEXT, 0, &value, &ret_len);

   switch ( ret_code )
   {
   case MI_NORMAL_VALUE:
      buf = mi_get_vardata((mi_lvarchar *)value);
      DPRINTF("trace_class", 15, ("Value: %s", buf));
      break;

   case MI_NULL_VALUE:
      DPRINTF("trace_class", 15, ("NULL"));
      break;

   case MI_ROW_VALUE:
      rowdesc = (MI_ROW_DESC *)value;
      break;

   case MI_COLLECTION_VALUE:
      nested_collp = (MI_COLLECTION *)value;
      break;

   case MI_END_OF_DATA:
      DPRINTF("trace_class", 15, 
         ("End of collection reached"));
      return (100);
   }

Inserting an Element

You insert an element into an open collection with the mi_collection_insert( ) function. You can perform an insert operation only on a read/write cursor. An insert is not valid on a read-only cursor.

The mi_collection_insert( ) function uses an MI_DATUM value to represent an element that it inserts into a collection. The contents of the MI_DATUM structure depend on the passing mechanism that the function used, as follows:

The mi_collection_insert( ) function inserts the new element at the location in the collection cursor that its action argument specifies. For a list of valid cursor-action flags, see Table 21.

Server Only

The following call to mi_collection_insert( ) can pass in an actual value because it inserts an INTEGER element into a LIST collection and integer values are passed by value in a C UDR:

MI_CONNECTION *conn;
MI_DATUM datum;
MI_COLL_DESC *colldesc;

datum=6;
mi_collection_insert(conn, colldesc, datum, 
   MI_CURSOR_ABSOLUTE, 1);

datum=3;
mi_collection_insert(conn, colldesc, datum, 
   MI_CURSOR_ABSOLUTE, 2);

datum=15;
mi_collection_insert(conn, colldesc, datum, 
   MI_CURSOR_ABSOLUTE, 3);

datum=1;
mi_collection_insert(conn, colldesc, datum, 
   MI_CURSOR_ABSOLUTE, 4);

datum=4;
mi_collection_insert(conn, colldesc, datum, 
   MI_CURSOR_ABSOLUTE, 5);

datum=8;
mi_collection_insert(conn, colldesc, datum, 
   MI_CURSOR_ABSOLUTE, 6);
End of Server Only

Figure 17 shows the cursor position after the preceding calls to mi_collection_insert( ) complete.

Figure 17. Collection Cursor After Inserts Complete
begin figure description - This figure is described in the surrounding text. - end figure description

These mi_collection_insert( ) calls specify absolute addressing (MI_CURSOR_ABSOLUTE) for the collection because the collection is defined as a LIST. Only LIST collections have ordered position assigned to their elements. SET and MULTISET collections do not have ordered position of elements.

Fetching an Element

You fetch an element from an open collection with the mi_collection_fetch( ) function. You can perform a fetch operation on a read/write or a read-only cursor. To fetch a collection element, you must specify:

Moving Through a Cursor

The mi_collection_fetch( ) function obtains the element specified by its action argument from the collection cursor. For a list of valid cursor-action flags, see Table 21. You can move the cursor position back to the beginning of the cursor with the mi_collection_fetch( ) function, as the following example shows:

mi_collection_fetch(conn, coll_desc, MI_CURSOR_FIRST, 0,
   coll_element, element_len);

if ( ((mi_integer)coll_element != 1) || 
      (element_len != sizeof(mi_integer)) )
    /* raise an error */

This function moves the cursor position backward with respect to its position after a call to mi_collection_insert( ) (Figure 17). The mi_collection_fetch( ) function is valid only for the following kinds of cursors:

Figure 18 shows the cursor position and coll_element value after the preceding call to mi_collection_fetch( ).

Figure 18. Collection Cursor After Fetch First
begin figure description - This figure is described in the surrounding text. - end figure description

Figure 19 shows the cursor position and value of coll_element after the following mi_collection_fetch( ) call:

mi_collection_fetch(conn, coll_desc, MI_CURSOR_NEXT, 0,
   coll_element, element_len); 

Figure 19. Collection Cursor After Fetch Next
begin figure description - This figure is described in the surrounding text. - end figure description

Figure 20 shows the cursor position and value of coll_element after the following mi_collection_fetch( ) call:

mi_collection_fetch(conn, coll_desc, MI_CURSOR_RELATIVE, 3,
   coll_element, element_len);

Figure 20. Collection Cursor After Fetch Relative 3
begin figure description - This figure is described in the surrounding text. - end figure description

The preceding mi_collection_fetch( ) call is valid only if the collection is a LIST. Only LIST collections are ordered. Therefore relative fetches, which specify the number of elements to move forward or backward, can only be used on LIST collections. If you try to perform a relative fetch on a SET or MULTISET, mi_collection_fetch( ) generates an error.

Figure 21 shows the cursor position and value of coll_element after the following mi_collection_fetch( ) call:

mi_collection_fetch(conn, coll_desc, MI_CURSOR_RELATIVE, -2,
   coll_element, element_len);

Figure 21. Collection Cursor After Fetch Relative -2
begin figure description - This figure is described in the surrounding text. - end figure description

Because the preceding mi_collection_fetch( ) call moves the cursor position backward, the call is valid only if the collection cursor is a scroll cursor. When you open a collection with mi_collection_open( ), you get a read/write scroll collection cursor. However, if you open the collection with mi_collection_open_with_options( ) and the MI_COLL_NOSCROLL option, mi_collection_fetch( ) generates an error.

Figure 22 shows the cursor position and value of coll_element after the following mi_collection_fetch( ) call:

mi_collection_fetch(conn, coll_desc, MI_CURSOR_ABSOLUTE, 6,
   coll_element, element_len);

Figure 22. Collection Cursor After Fetch Absolute 6
begin figure description - This figure is described in the surrounding text. - end figure description

The preceding mi_collection_fetch( ) call is valid only if the collection is a LIST. Because absolute fetches specify a position within the collection by number, they can only be used on an ordered collection (a LIST). If you try to perform an absolute fetch on a SET or MULTISET, mi_collection_fetch( ) generates an error.

Because only six elements are in this collection, the absolute fetch of 6 positions the cursor on the last element in the collection. This result is the same as if you had issued the following mi_collection_fetch( ):

mi_collection_fetch(conn, coll_desc, MI_CURSOR_LAST, 0,
   coll_element, element_len);

The fetch last is useful when you do not know the number of elements in a collection and want to obtain the last one.

Obtaining the Element Value

The mi_collection_fetch( ) function uses an MI_DATUM value to represent an element that it fetches from a collection. You must pass in a pointer to the value buffer in which mi_collection_fetch( ) puts the element value. However, you do not have to allocate memory for this buffer. The mi_collection_fetch( ) function handles memory allocation for the MI_DATUM value that it passes back.

The contents of the MI_DATUM structure that holds the retrieved element depends on the passing mechanism that the function used, as follows:

Important:
The difference in behavior of mi_collection_fetch( ) between C UDRs and client LIBMI applications means that collection-retrieval code is not completely portable between these two types of DataBlade API modules. When you move your DataBlade API code from one of these uses to another, you must change the collection-retrieval code to use the appropriate passing mechanism for element values that mi_collection_fetch( ) returns.

You declare a value buffer for the fetched element and pass in the address of this buffer to mi_collection_fetch( ). You can declare the buffer in either of the following ways:

Figures Figure 18 through Figure 22 fetch elements from a LIST collection of INTEGER values. To fetch elements from this LIST, you can declare the value buffer as follows:

mi_integer *coll_element;
Server Only

Because you can pass INTEGER values by value in a C UDR, you access the MI_DATUM structure that these calls to mi_collection_fetch( ) pass back as the actual value, as follows:

int_element = (mi_integer)coll_element;

If the element type is a data type that must be passed by reference, the contents of the MI_DATUM structure that mi_collection_fetch( ) passes back is a pointer to the actual value. The following call to mi_collection_fetch( ) also passes in the value buffer as a pointer. However, it passes back an MI_DATUM value that contains a pointer to a FLOAT (mi_double_precision) value:

mi_double_precision *coll_element, flt_element;
...
/* Fetch a FLOAT value in a C UDR */
mi_collection_fetch(conn, coll_desc, action, jump,
   &coll_element, &retlen);
flt_element = *coll_element;
End of Server Only
Client Only

For the fetches in Figures Figure 18 through Figure 22, a client LIBMI application declares the value buffer in the same way as a C UDR. However, because all data types are passed back by reference, the MI_DATUM structure that mi_collection_fetch( ) passes back contains a pointer to the INTEGER value, not the actual value itself:

mi_integer *coll_element, int_element;
...
/* Fetch an INTEGER value in a client LIBMI application */
mi_collection_fetch(conn, coll_desc, action, jump,
   &coll_element, &retlen);
int_element = *coll_element;
End of Client Only

Updating a Collection

You update an element in an open collection with the mi_collection_update( ) function. You can perform an update operation only on a read/write cursor. An update is not valid on a read-only cursor.

The mi_collection_update( ) function uses an MI_DATUM value to represent the new value for the element it updates in a collection. The contents of this MI_DATUM structure depend on the passing mechanism that the function used, as follows:

The mi_collection_update( ) function updates the element at the location in the collection cursor that its action argument specifies. For a list of valid cursor-action flags, see Table 21.

Server Only

The following code shows an example of using the mi_collection_update( ) function to update the first element in a collection:

/*
 * Update position 1 in the collection to contain 3.0
 * Note that single-precision value is passed by REFERENCE.
 */
   MI_CONNECTION *conn;
   MI_COLL_DESC *colldesc;
   MI_DATUM val;
   mi_integer ret, jump;
   mi_real value;

   /* Update 1st element to 3.0 */
   value = 3.0;
   val = (MI_DATUM)&value;
   jump = 1;
   DPRINTF("trc_class", 11, 
      ("Update set value %d @%d", value, jump));

   /* Pass single-precision values by reference */
   ret = mi_collection_update(conn, colldesc, val,
      MI_CURSOR_ABSOLUTE, jump);

   if ( ret != MI_OK )
      {
      DPRINTF("trc_class", 11, 
         ("Update @%d value %d MI_CURSOR_ABSOLUTE\
          failed", jump, value));
      }
End of Server Only

Deleting an Element

You delete an element from an open collection with the mi_collection_delete( ) function. You can perform a delete operation only on a read/write cursor. A delete is not valid on a read-only cursor.

The mi_collection_delete( ) function deletes the element at the location in the collection cursor that its action argument specifies. For a list of valid cursor-action flags, see Table 21.

The following code shows an example of using the mi_collection_delete( ) function to delete the last element of a collection:

/*
 * Delete last element in the collection
 */
   MI_CONNECTION *conn;
   MI_COLL_DESC *coll_desc;
   mi_integer ret;

   ret = mi_collection_delete(conn, coll_desc,
      MI_CURSOR_LAST, 0);

Determining the Cardinality of a Collection

The DataBlade API provides the mi_collection_card( ) function for obtaining the number of elements in a collection (its cardinality). The following code fragment uses the mi_collection_card( ) function to perform separate actions based on whether a collection is NULL or has elements (possibly 0 elements):

MI_COLLECTION *collp;
mi_integer cardinality;
mi_boolean isnull;


/* Attach collp to a collection */


cardinality = mi_collection_card(collp, &isnull);
if ( isnull == MI_TRUE )
   {
   mi_db_error_raise(conn, MI_MESSAGE, "Warning: Collection is NULL.");
   }
else
   {
   if ( cardinality > 0 )
      {
      /*  Open collection and perform action on individual elements */
      }
   }
Enterprise Edition Home | Express Edition Home | [ Top of Page | Previous Page | Next Page | Contents | Index ]