Table of Contents Previous Next
Logo
FreezeScript : 41.6 Database Inspection
Copyright © 2003-2009 ZeroC, Inc.

41.6 Database Inspection

The FreezeScript tool dumpdb is used to examine a Freeze database. Its simplest invocation displays every record of the database, but the tool also supports more selective activities. In fact, dumpdb supports a scripted mode that shares many of the same XML descriptors as transformdb (see Section 41.4), enabling sophisticated filtering and reporting.

41.6.1 Descriptor Overview

A dumpdb descriptor file has a well-defined structure. The top-level descriptor in the file is <dumpdb>. A <database> descriptor must be present within <dumpdb> to define the key and value types used by the database. Inside <database>, the <record> descriptor triggers database traversal. Shown below is an example that demonstrates the structure of a minimal descriptor file:
<dumpdb>
    <database key="string" value="::Employee">
        <record>
            <echo message="Key: " value="key"/>
            <echo message="Value: " value="value"/>
        </record>
    </database>
</dumpdb>
During traversal, type-specific actions are supported by the <dump> descriptor, which is a child of <dumpdb>. One <dump> descriptor may be defined for each type in the Slice definitions. Each time dumpdb encounters an instance of a type, the <dump> descriptor for the type is executed.
The <database>, <record>, and <dump> descriptors may contain general-purpose action descriptors such as <if> and <echo>. These actions resemble statements in programming languages like C++ and Java, in that they are executed in the order of definition and their effects are cumulative. Actions make use of the expression language described in Section 41.8.
Although dumpdb descriptors are not allowed to modify the database, they can still define local symbols for scripting purposes. Once a symbol is defined by the <define> descriptor, other descriptors such as <set>, <add>, and <remove> can be used to manipulate the symbol’s value.

41.6.2 Flow of Execution

The descriptors are executed as described below.
• <database> is executed first. Each child descriptor of <database> is executed in the order of definition. If a <record> descriptor is present, database traversal occurs at that point. Any child descriptors of <database> that follow <record> are not executed until traversal completes.
• For each record, dumpdb interprets the key and value, invoking <dump> descriptors for each type it encounters. For example, if the value type of the database is a struct, then dumpdb first attempts to invoke a <dump> descriptor for the structure type, and then recursively interprets the structure’s members in the same fashion.
See Section 41.6.4 for detailed information on the dumpdb descriptors.

41.6.3 Scopes

The <database> descriptor creates a global scope, allowing child descriptors of <database> to define symbols that are accessible in any descriptor1. Furthermore, certain other descriptors create local scopes that exist only for the duration of the descriptor’s execution. For example, the <dump> descriptor creates a local scope and defines the symbol value to represent a value of the specified type. Child descriptors of <dump> can also define new symbols in the local scope, as long as those symbols do not clash with an existing symbol in that scope. It is legal to add a new symbol with the same name as a symbol in an outer scope, but the outer symbol will not be accessible during the descriptor’s execution.
The global scope is useful in many situations. For example, suppose you want to track the number of times a certain value was encountered during database traversal. This can be accomplished as shown below:
<dumpdb>
    <database key="string" value="::Ice::Identity">
        <define name="categoryCount" type="int" value="0"/>
        <record/>
        <echo message="categoryCount = " value="categoryCount"/>
    </database>
    <dump type="::Ice::Identity">
        <if test="value.category == `Accounting'">
            <set target="categoryCount"
                value="categoryCount + 1"/>
        </if>
    </dump>
</dumpdb>
In this example, the <define> descriptor introduces the symbol categoryCount into the global scope, defining it as type int with an initial value of zero. Next, the <record> descriptor causes traversal to proceed. Each occurrence of the type Ice::Identity causes its <dump> descriptor to be executed, which examines the category member and increases categoryCount if necessary. Finally, after traversal completes, the <echo> descriptor displays the final value of categoryCount.
To reinforce the relationships between descriptors and scopes, consider the diagram in Figure 41.2. Several descriptors are shown, including the symbols they define in their local scopes. In this example, the <iterate> descriptor has a dictionary target and therefore the default symbol for the element value, value, hides the symbol of the same name in the parent <dump> descriptor’s scope2. In addition to symbols in the <iterate> scope, child descriptors of <iterate> can also refer to symbols from the <dump> and <database> scopes.
Figure 41.2. Relationship between descriptors and scopes.

41.6.4 Descriptor Reference

<dumpdb>

The top-level descriptor in a descriptor file. It requires one child descriptor, <database>, and supports any number of <dump> descriptors. This descriptor has no attributes.

<database>

The attributes of this descriptor define the key and value types of the database. It supports any number of child descriptors, but at most one <record> descriptor. The <database> descriptor also creates a global scope for user-defined symbols (see Section 41.6.3).
The attributes supported by the <database> descriptor are described in Table 41.13.
Table 41.13. Attributes for <database> descriptor.
As an example, consider the following <database> descriptor. In this case, the Freeze map to be examined has key type int and value type ::Employee:
<database key="int" value="::Employee">

<record>

Commences the database traversal. Child descriptors are executed for each record in the database, but after any <dump> descriptors are executed. The <record> descriptor introduces the read-only symbols key, value and facet into a local scope. These symbols are accessible to child descriptors, but not to <dump> descriptors. The facet symbol is a string indicating the facet name of the object in the current record, and is only relevant for Freeze evictor databases.
Note that database traversal only occurs if a <record> descriptor is present.

<dump>

Executed for all instances of a Slice type. Only one <dump> descriptor can be specified for a type, but a <dump> descriptor is not required for every type. The read-only symbol value is introduced into a local scope. The attributes supported by this descriptor are described in Table 41.14.
Table 41.14. Attributes for <dump> descriptor.
If type denotes a Slice class, this attribute determines whether the <dump> descriptor of the base class is invoked. If true, the base class descriptor is invoked after executing the child descriptors. If not specified, the default value is true.
For class and struct types, this attribute determines whether descriptors are executed for members of the value. For sequence and dictionary types, this attribute determines whether descriptors are executed for elements. If not specified, the default value is true.
Below is an example of a <dump> descriptor that searches for certain products:
<dump type="::Product">
    <if test="value.description.find(`scanner') != 1">
        <echo message="Scanner SKU: " value="value.SKU"/>
    </if>
</dump>
For class types, dumpdb first attempts to locate a <dump> descriptor for the object’s most-derived type. If no descriptor is found, dumpdb proceeds up the class hierarchy in an attempt to find a descriptor. The base object type, Object, is the root of every class hierarchy and is included in the search for descriptors. It is therefore possible to define a <dump> descriptor for type Object, which will be invoked for every class instance.
Note that <dump> descriptors are executed recursively. For example, consider the following Slice definitions:
struct Inner {
    int sum;
};
struct Outer {
    Inner i;
};
When dumpdb is interpreting a value of type Outer, it executes the <dump> descriptor for Outer, then recursively executes the <dump> descriptor for the Inner member, but only if the contents attribute of the Outer descriptor has the value true.

<iterate>

Iterates over a dictionary or sequence, executing child descriptors for each element. The symbol names selected to represent the element information may conflict with existing symbols in the enclosing scope, in which case those outer symbols are not accessible to child descriptors. The attributes supported by this descriptor are described in Table 41.15.
Table 41.15. Attributes for <iterate> descriptor.
Shown below is an example of an <iterate> descriptor that displays the name of an employee if the employee’s salary is greater than $3000.
<iterate target="value.employeeMap" key="id" value="emp">
    <if test="emp.salary > 3000">
        <echo message="Employee: " value="emp.name"/>
    </if>
</iterate>

<if>

Conditionally executes child descriptors. The attributes supported by this descriptor are described in Table 41.16.
Table 41.16. Attributes for <if> descriptor.
See Section 41.8 for more information on the descriptor expression language.

<set>

Modifies a value. The value and type attributes are mutually exclusive. If target denotes a dictionary element, that element must already exist (i.e., <set> cannot be used to add an element to a dictionary). The attributes supported by this descriptor are described in Table 41.17.
Table 41.17. Attributes for <set> descriptor.
An integer expression representing the desired new length of a sequence. If the new length is less than the current size of the sequence, elements are removed from the end of the sequence. If the new length is greater than the current size, new elements are added to the end of the sequence. If value or type is also specified, it is used to initialize each new element.
If true, additional type conversions are supported: between integer and floating point, and between integer and enumeration. Transformation fails immediately if a range error occurs. If not specified, the default value is false.
The <set> descriptor below modifies a member of a dictionary element:
<set target="new.parts['P105J3'].cost"
      value="new.parts['P105J3'].cost * 1.05"/>
This <set> descriptor adds an element to a sequence and initializes its value:
<set target="new.partsList" length="new.partsList.length + 1"
     value="'P105J3'"/>

<add>

Adds a new element to a sequence or dictionary. It is legal to add an element while traversing the sequence or dictionary using <iterate>, however the traversal order after the addition is undefined. The key and index attributes are mutually exclusive, as are the value and type attributes. If neither value nor type is specified, the new element is initialized with a default value. The attributes supported by this descriptor are described in Table 41.18.
Table 41.18. Attributes for <add> descriptor.
An expression that must evaluate to an integer value representing the insertion position. The new element is inserted before index. The value must not exceed the length of the target sequence.
An expression that must evaluate to a value compatible with the target dictionary’s value type, or the target sequence’s element type.
The Slice type id of a class to be instantiated. The class must be compatible with the target dictionary’s value type, or the target sequence’s element type.
If true, additional type conversions are supported: between integer and floating point, and between integer and enumeration. Transformation fails immediately if a range error occurs. If not specified, the default value is false.
Below is an example of an <add> descriptor that adds a new dictionary element and then initializes its member:
<add target="new.parts" key="'P105J4'"/>
<set target="new.parts['P105J4'].cost" value="3.15"/>

<define>

Defines a new symbol in the current scope. The attributes supported by this descriptor are described in Table 41.19.
Table 41.19. Attributes for <define> descriptor.
The name of the new symbol. An error occurs if the name matches an existing symbol in the current scope.
If true, additional type conversions are supported: between integer and floating point, and between integer and enumeration. Execution fails immediately if a range error occurs. If not specified, the default value is false.
Below are two examples of the <define> descriptor. The first example defines the symbol identity to have type Ice::Identity, and proceeds to initialize its members using <set>:
<define name="identity" type="::Ice::Identity"/>
<set target="identity.name" value="steve"/>
<set target="identity.category" value="Admin"/>
The second example uses the enumeration we first saw in Section 41.3.5 to define the symbol manufacturer and assign it a default value:
<define name="manufacturer" type="::BigThree"
    value="::DaimlerChrysler"/>

<remove>

Removes an element from a sequence or dictionary. It is legal to remove an element while traversing a sequence or dictionary using <iterate>, however the traversal order after removal is undefined. The attributes supported by this descriptor are described in Table 41.20.
Table 41.20. Attributes for <remove> descriptor.
An expression that must evaluate to an integer value representing the index of the sequence element to be removed.

<fail>

Causes transformation to fail immediately. If test is specified, transformation fails only if the expression evaluates to true. The attributes supported by this descriptor are described in Table 41.21.
Table 41.21. Attributes for <fail> descriptor.
The following <fail> descriptor terminates the transformation if a range error is detected:
<fail message="range error occurred in ticket count!"
      test="value.ticketCount > 32767"/>

<echo>

Displays values and informational messages. If no attributes are specified, only a newline is printed. The attributes supported by this descriptor are described in Table 41.22.
Table 41.22. Attributes for <echo> descriptor.
Shown below is an <echo> descriptor that uses both message and value attributes:
<if test="value.ticketCount > 32767">
    <echo message="range error occurred in ticket count: "
          value="value.ticketCount"/>
</if>

1
In order for a global symbol to be available to a <dump> descriptor, the symbol must be defined before the <record> descriptor is executed.

2
This situation can be avoided by assigning a different symbol name to the element value.

Table of Contents Previous Next
Logo