Structured Types

The Data Access type system can be extended beyond the basic data types described in the previous sections. This occurs automatically when structured values are obtained from a database system such as Oracle 9i (or later) or Informix 9.x.

Each structured type has an associated schema that can be obtained as follows:

void DescribeStructuredType(const IliDatatype* type) {

if (type->isStructuredType()) {

const IliSchema* schema = type->getNestedSchema();

IlvPrint("Type %s manages tables with %ld columns",

schema->getName(),

(long)schema->getColumnsCount());

}

else

IlvPrint("Not a structured type !");

}

A structured type manages IliValue objects that contain a pointer to an IliTable object.

The following code sample shows how an IliValue object can be initialized with an IliTable object:

IliValue MakeStructuredValue(const IliDatatype* type) {

if (type->isStructuredType()) {

IliValue value(type);

IliTable* table = type->makeTable();

table->lock();

value.importTable(table);

table->unLock();

return value;

}

else {

IlvPrint("Not a structured type !");

return IliValue();

}

}

This example uses the makeTable member function to create an IliTable object whose schema is identical to the schema returned by the IliDatatype::getNestedSchema member function.

The table returned by IliDatatype::makeTable is really an IliMemoryTable object. Consequently, all row management member functions (insertRow, updateRow, and so on) can be called to fill this table. Note, however, that structured types fall into two categories: object types and table types. They differ in that an object types expects to manage a table that contains at most one row, whereas table types manage tables with many rows. The isObjectType and isTableType member functions can be used to distinguish between object and table types.

It is important to understand how the IliValue class manages IliTable objects. When an IliValue object is copied into another, the nested IliTable object is shared between both IliValue objects as shown by the following code excerpt:

const IliDatatype* type = ...;

IliValue firstVal = MakeStructuredValue(type);

IliValue secondVal = firstVal;

assert(firstVal.asTable() == secondVal.asTable());

As a consequence, you should not directly alter the table contained in an IliValue object. Instead, a copy of the table should be made, altered, and then assigned back to the IliValue objects in the following code excerpt:

IliValue value = ...;

const IliTable* table = value.asTable();

if (table != NULL) {

IliTable* tempTable = table->copyTable();

tempTable->lock();

// alter tempTable in some way ...

tempTable->sortRows();

value.importTable(tempTable);

tempTable->unLock();

}