Oracle9i OLAP Developer's Guide to the OLAP API Release 2 (9.2) Part Number A95297-01 |
|
Understanding Cursor Classes and Concepts, 5 of 6
A Cursor
has one or more positions. The current position of a Cursor
is the position that is currently active in the Cursor
. To move the current position of a Cursor
call the setPosition
or next
methods on the Cursor
.
Oracle OLAP does not validate the position that you set on the Cursor
until you attempt an operation on the Cursor
, such as calling the getCurrentValue
method. If you set the current position to a negative value or to a value that is greater than the number of positions in the Cursor
and then attempt a Cursor
operation, the Cursor
throws a PositionOutOfBoundsException
.
The extent of a Cursor is described in "What is the Extent of a Cursor?" .
The current position of a ValueCursor
specifies a value, which you can retrieve. For example, productSel
, a derived Source
described in "Structure of a Cursor" , is a selection of three products from a primary Source
that specifies a dimension of products and their hierarchical groupings. The ValueCursor
for productSel
has three elements. The following example gets the position of each element of the ValueCursor
, and displays the value at that position. The output
object is a PrintWriter
.
// productSelValCursor is the ValueCursor for productSel do { output.print(productSelValCursor.getPosition + " : "); output.println(productSelValCursor.getCurrentValue); } while(productSelValCursor.next());
The preceding example displays the following:
1 : 815 2 : 1050 3 : 2055
The following example sets the current position of productSelValCursor
to 2 and retrieves the value at that position.
productSelValCursor.setPosition(2); output.println(productSelValCursor.getCurrentValue);
The preceding example displays the following:
1050
For more examples of getting the current value of a ValueCursor
, see Chapter 9.
A CompoundCursor
has one position for each set of the elements of its descendent ValueCursor
objects. The current position of the CompoundCursor
specifies one of those sets.
For example, unitPriceByDay
, the Source
described in "Structure of a Cursor" , has values from a measure, unitPrice
. The values are the prices of product units at different times. The outputs of unitPriceByDay
are Source
objects that represent selections of four day values from a time dimension and three product values from a product dimension.
The result set for unitPriceByDay
has one measure value for each tuple (each set of output values), so the total number of values is twelve (one value for each of the three products for each of the four days). Therefore, the queryCursor
CompoundCursor
created for unitPriceByDay
has twelve positions.
Each position of queryCursor
specifies one set of positions of its outputs and its base ValueCursor
. For example, position 1 of queryCursor
defines the following set of positions for its outputs and its base ValueCursor
:
ValueCursor
for timeSel
)ValueCursor
for productSel
)ValueCursor
for queryCursor
(This position has the value from the unitPrice
measure that is specified by the values of the outputs.)Figure 8-4 illustrates the positions of queryCursor
CompoundCursor
, its base ValueCursor
, and its outputs.
The ValueCursor
for queryCursor
has only one position because only one value of unitPrice
is specified by any one set of values of the outputs. For a query like unitPriceByDay
, the ValueCursor
of its Cursor
has only one value, and therefore only one position, at a time for any one position of the root CompoundCursor
.
The following table illustrates one possible display of the data from queryCursor
. It is a crosstab view with four columns and five rows. In the left column are the day values. In the top row are the product values. In each of the intersecting cells of the crosstab is the price of the product on the day.
A CompoundCursor
coordinates the positions of its ValueCursor
objects relative to each other. The current position of the CompoundCursor
specifies the current positions of its descendent ValueCursor
objects. Example 8-1 sets the position of queryCursor
and then gets the current values and the positions of the child Cursor
objects.
CompoundCursor rootCursor = (CompoundCursor) queryCursor; ValueCursor baseValueCursor = rootCursor.getValueCursor(); List outputs = rootCursor.getOutputs(); ValueCursor output1 = (ValueCursor) outputs.get(0); ValueCursor output2 = (ValueCursor) outputs.get(1); int pos = 5; root.setPosition(pos); System.out.println("CompoundCursor position set to " + pos + "."); System.out.println("CC position = " + rootCursor.getPosition() + "."); System.out.println("Output 1 position = " + output1.getPosition() + ", value = " + output1.getCurrentValue()); System.out.println("Output 2 position = " + output2.getPosition() + ", value = " + output2.getCurrentValue()); System.out.println("VC position = " + baseValueCursor.getPosition() + ", value = " + baseValueCursor.getCurrentValue());
Example 8-1 displays the following:
CompoundCursor position set to 5. CC position = 5. Output 1 position = 2, value = 01-APR-00 Output 2 position = 2, value = 1050 VC position = 1, value = 24
The positions of queryCursor
are symmetric in that the result set for unitPriceByDay
always has three product values for each time value. The ValueCursor
for productSel
, therefore, always has three positions for each value of the timeSel
ValueCursor
. The timeSel
output ValueCursor
is slower varying than the productSel
ValueCursor
.
In an asymmetric case, however, the number of positions in a ValueCursor
is not always the same relative to its slower varying output. For example, if the price of units for product 2055 on October 1, 2000 were null because that product was no longer being purchased by that date, and if null values were suppressed in the query, then queryCursor
would only have eleven positions. The ValueCursor
for productSel
would only have two positions when the position of the ValueCursor
for timeSel
was 4.
Example 8-2 produces an asymmetric result set by using a revision of the query from "Structure of a Cursor". The result set of the revised query specifies products by price on a day. The base values of productByPriceOnDay
are the values from productSel
as specified by the values of unitPrice
and timeSel
.
Because productByPriceOnDay
is a derived Source
, this example prepares and commits the current Transaction
. The TransactionProvider
in the example is tp
. For information on Transaction
objects, see Chapter 7.
The example creates a Cursor
for productByPriceOnDay
, loops through the positions of the CompoundCursor
, gets the position and current value of each child ValueCursor
object, and displays the positions and values.
// Create the query productByPriceOnDay = productSel.join(unitPrice).join(timeSel); //Prepare and commit the current Transaction. try{ tp.prepareCurrentTransaction(); } catch(NotCommittableException e){ output.println("Caught exception " + e + "."); } tp.commitCurrentTransaction(); // Create the Cursor. The DataProvider is dp. CursorManagerSpecification cursorMngrSpec = dp.createCursorManagerSpecification(productByPriceOnDay); CursorManager cursorManager = dp.createCursorManager(cursorMngrSpec); Cursor queryCursor2 = cursorManager.createCursor(); // Get the ValueCursor and the outputs CompoundCursor rootCursor = (CompoundCursor) queryCursor2; ValueCursor baseValueCursor = rootCursor.getValueCursor(); List outputs = rootCursor.getOutputs(); ValueCursor output1 = (ValueCursor) outputs.get(0); ValueCursor output2 = (ValueCursor) outputs.get(1); // Get the positions and values and display them. System.out.println(" CC \t\tOutput 1 \tOutput 2 \tVC"); System.out.println("position \tposition:value " + "\tposition:value \tposition:value"); do { System.out.println(" " + root.getPosition() + "\t\t " + output1.getPosition() + " : " + output1.getCurrentValue() + "\t " + output2.getPosition() + " : " + output2.getCurrentValue() + "\t " + baseValueCursor.getPosition() + " : " + baseValueCursor.getCurrentValue()); } while(queryCursor2.next();
Example 8-2 displays the following:
CC Output 1 Output 2 VC position position:value position:value position:value 1 1 : 01-JAN-00 1 : 58 1 : 815 2 1 : 01-JAN-00 2 : 24 1 : 1050 3 1 : 01-JAN-00 2 : 24 2 : 2055 4 2 : 01-APR-00 1 : 59 1 : 815 5 2 : 01-APR-00 2 : 24 1 : 1050 6 2 : 01-APR-00 3 : 25 1 : 2055 7 3 : 01-JUL-00 1 : 59 1 : 815 8 3 : 01-JUL-00 2 : 25 1 : 1050 9 3 : 01-JUL-00 2 : 25 2 : 2055 10 4 : 01-OCT-00 1 : 61 1 : 815 11 4 : 01-OCT-00 2 : 25 1 : 1050 12 4 : 01-OCT-00 3 : 26 1 : 2055
The ValueCursor
with unitPrice
values (output 2) has only two positions for 01-JAN-00 and 01-JUL-00 because it has only two different values for those days. The prices of two of the products are the same on those two days: 24 for products 1050 and 2055 on January 1, 2000 and 25 for those same two products on July 1, 2000. The base ValueCursor
for queryCursor2
has two positions when the timeSel
value is 01-JAN-00 or 01-JUL-00 because each of the unitPrice
values for those days is not unique.
To effectively manage the display of the data that you get from a CompoundCursor
, you sometimes need to know how many faster varying values exist for the current slower varying value. For example, suppose that you are displaying in a crosstab one row of values from an edge of a cube, then you might want to know how many columns to draw in the display for the row.
To determine how many faster varying values exist for the current value of a child Cursor
, you find the starting and ending positions of that current value in the parent Cursor
. Subtract the starting position from the ending position and then add 1, as in the following.
long span = (cursor.getParentEnd() - cursor.getParentStart()) + 1;
The result is the span of the current value of the child Cursor
in its parent Cursor
, which tells you how many values of the fastest varying child Cursor
exist for the current value. Calculating the starting and ending positions is costly in time and computing resources, so you should only specify that you want those calculations performed when your application needs the information.
An Oracle OLAP API Cursor
enables your application to have only the data that it is currently displaying actually present on the client computer. For information on specifying the amount of data for a Cursor
, see "About Fetch Sizes and Fetch Blocks".
From the data on the client computer, however, you cannot determine at what position of its parent Cursor
the current value of a child Cursor
begins or ends. To get that information, you use the getParentStart
and getParentEnd
methods of a Cursor
.
For example, suppose your application has a Source
named cube
that represents a cube that has an asymmetric edge. The cube has four outputs. The cube
Source
defines products with sales amounts greater than $5,000 purchased by customers in certain cities during the first three months of the calendar year 2000. The products were sold through the direct sales channel (S) during a television promotion (TV).
You create a Cursor
for that Source
and call it cubeCursor
. The CompoundCursor
cubeCursor
has the following child Cursor
objects:
ValueCursor
for the promotion valuesValueCursor
for the channel valuesValueCursor
for the time valuesValueCursor
for the customer valuesValueCursor
, which has values that are the products with sales amounts over $5,000.Figure 8-5 illustrates the parent, cubeCursor
, with the values of its child Cursor
objects layered horizontally. The slowest varying output, with the promotion values, is at the top and the fastest varying child, with the product values, is at the bottom. The only portion of the edge that you are currently displaying in the user interface is the block between positions 7 and 9 of cubeCursor
, which is shown within the bold border. The positions, 1 through 10, of cubeCursor
appear above the top row.
The current value of the output ValueCursor
for the time Source
is 2000-02. You cannot determine from the data within the block that the starting and ending positions of the current value, 2000-02, in the parent, cubeCursor
, are 4 and 7, respectively.
The cubeCursor
from the previous figure is shown again in Figure 8-6, this time with the range of the positions of the parent, cubeCursor
, for each of the values of the child Cursor
objects. By subtracting the smaller value from the larger value and adding one, you can compute the span of each value. For example, the span of the time value 2000-02 is (7 - 4 + 1) = 4.
To specify that you want Oracle OLAP to calculate the starting and ending positions of a value of a child Cursor
in its parent Cursor
, call the setParentStartCalculationSpecified
and setParentEndCalculationSpecified
methods on the CursorSpecification
corresponding to the Cursor
. You can determine whether calculating the starting or ending positions is specified by calling the isParentStartCalculationSpecified
or isParentEndCalculationSpecified
methods on the CursorSpecification
. For an example of specifying these calculations, see Chapter 9.
The extent of a Cursor
is the total number of elements it contains relative to any slower varying outputs. Figure 8-7 illustrates the number of positions of each child Cursor
of cubeCursor
relative to the value of its slower varying output. The child Cursor
objects are layered horizontally with the slowest varying output at the top.
The total number of elements in cubeCursor
is 10 so the extent of cubeCursor
is therefore 10. That number is above the top row of the figure. The top row is the ValueCursor
for the promotion value and the next row down is the ValueCursor
for the channel value. The extent of each of those ValueCursor
objects is 1 because they each have only one value.
The third row down represents the time values. Its extent is 3, since there are 3 months values. The next row down is the ValueCursor
for the customers by city. The extent of its elements depends on the value of the slower varying output, which is time. The extent of the customers ValueCursor
for the first month is 2, for the second month it is 3, and for the third month it is 2.
The bottom row is the base ValueCursor
for the cubeCursor
CompoundCursor
. Its values are products. The extent of the elements of the products ValueCursor
depends on the values of the customers ValueCursor
and the time ValueCursor
. For example, since two products values are specified by the first set of month and city values (1050 and 2055 for Bonn in 2000-01), the extent of the products ValueCursor
for that set is 2. For the second set of values for customers and times (2000-10, London), the extent of the products ValueCursor
is 1, and so on.
The extent is information that you can use, for example, to display the correct number of columns or correctly-sized scroll bars. The extent, however, can be expensive to calculate. For example, a Source
that represents a cube might have four outputs. Each output might have hundreds of values. If all null values and zero values of the measure for the sets of outputs are eliminated from the result set, then to calculate the extent of the CompoundCursor
for the Source
, Oracle OLAP must traverse the entire result space before it creates the CompoundCursor
. If you do not specify that you wants the extent calculated, then Oracle OLAP only needs to traverse the sets of elements defined by the outputs of the cube as specified by the fetch size of the Cursor
and as needed by your application.
To specify that you want Oracle OLAP to calculate the extent for a Cursor
, call the setExtentCalculationSpecified
method on the CursorSpecification
corresponding to the Cursor
. You can determine whether calculating the extent is specified by calling the isExtentCalculationSpecified
method on the CursorSpecification
. For an example of specifying the calculation of the extent of a Cursor
, see Chapter 9.
|
Copyright © 2000, 2002 Oracle Corporation. All Rights Reserved. |
|