Data Services Developer's Guide
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Liquid Data services provide a framework for creation and maintenance of functions that access and transform available data. You can use the Liquid Data XQuery Editor to create such functions.
A valid query function is always associated with a return type. In Source View a return type is described for each function. It typically matches the XML type — or schema — that defines the shape of your data service.
Once created, your query functions can be called by client applications. Details on the various methods of invoking Liquid Data functions can be found in the Client Application Developer's Guide.
You can also use the XQuery Editor to create standalone, ad hoc queries that can be run in Test View (see Testing Query Functions and Viewing Query Plans).
Topics discussed in this chapter include:
Using the XQuery Editor you can create query functions using an intuitive, drag-and-drop approach. During the creation process you can easily move back and forth between the editor to Source View.
Figure 6-1 Sample Parameterized Function in the XQuery Editor
The XQuery Editor relies on data services functions for the metadata necessary to represent various types of data. (For detailed information on importing metadata see Obtaining Enterprise Metadata.)
A data service may represent a physical data source or it may represent logical data that has previously been created. Data service and custom XQuery library functions are both represented from the Liquid Data Palette (Figure 6-2), a Workshop pane available when XQuery Editor View is active.
Figure 6-2 Data Service Functions Available from the Liquid Data Palette
Notice in Figure 6-2 that there are two different type of function representations: Functions represent by a straight (green) arrow are read functions, while functions represented by a more stylized (blue) arrow are navigation functions.
Essentially you create a query function by:
As you work graphically you are automatically creating an XQuery in Source View.
Once created, you can execute your function using Test View (see Testing Query Functions and Viewing Query Plans). When you execute your query function, underlying data sources are accessed and the results appear. If you have appropriate permissions, data can be updated directly after the query is run.
Metadata representations of source are available to the XQuery Editor from the Liquid Data Palette. The Liquid Data Palette lists available data services and their read and relationship functions. Any such function can be dragged into the XQuery Editor work area where it will be transformed into a for clause.
Figure 6-3 Example of the Liquid Data Palette
Read functions and web services often have input parameters. For example, the logical data service Customer (customer.ds
) can be represented in the XQuery Editor by its read functions: getCustomer() and getPaymentList(). If you drag the getCustomer() item from the Liquid Data Palette to the XQuery Editor, the source representation shown in Figure 6-4 appears in the work area.
Figure 6-4 Data Service Function From the Liquid Data Palette
In some cases you may want to use a physical or logical data source representation several times in a query.
See Obtaining Enterprise Metadata and Using Data Services Design View for details on creating physical and logical data services.
When you create a new function in your data service and then click on the name of your new function (Figure 6-1), you will automatically be placed in the XQuery Editor. Alternatively, click the XQuery Editor View tab and select your function from the drop-down menu. Initially your XQuery will have only a return type, assuming that your data service is associated with an XML type (see Associating an XML Type).
Figure 6-5 Right-click Menu Options in the XQuery Editor
Several right-click menu options are available when you click in any unoccupied part of the work area.
Opens Source View to the section containing the currently selected function. |
|
The elements in the XQuery Editor are rearranged according to a pre-established formula including docking the return type to the right side of the work area. |
|
Adds a simple or complex parameter to your work area. Complex parameters require you to select a schema file and global type. See Parameter Nodes. |
|
Hides/displays lines that identify conditions such as where clause predicates. By default condition lines are shown. |
|
Collapses all nodes in the work area including the return type. |
|
Creating a data service — as you will if you follow the steps in this section — is a good way to get the feel of what it is like to work with the XQuery Editor, as well as other aspects of the data service creating system provided with Liquid Data.
Through Source View you can quickly see how changes in the XQuery Editor are translated into XQuery code. Similarly any changes you make in Source View will be immediately reflected in the XQuery Editor work area. (See Using Source View.)
Note: There are a number of examples of query building in the XQuery Editor and Source View in the Liquid Data Samples Tutorial.
To access the tutorial see the Liquid Data edocs page:
http://download.oracle.com/docs/cd/E13190_01/liquiddata/docs85/index.html
The goal is to quickly create a logical data service from scratch, including creating an XML type for your data service, using the XQuery Editor. In this example you create a logical data service by first building up a return type from several physical data services and then making that the type of your data service.
Note: The easiest way to change something you have done in the XQuery Editor is to use the Edit
Using Liquid Data sample data, the following steps illustrate one way to create a logical data service, including a return type.
Create a new Liquid Data application, called myLogical.
Figure 6-6 XQuery Editor With Two Data Sources and an Empty Return Type
The existence of the two unmapped for clauses, $CUSTOMER and $CUSTOMER_ORDER is accounted for by the return type's list of two empty elements.
Next you need to populate the return type. In this case CUSTOMER_ORDER should be set up as a child of the CUSTOMER complex element so that information will be return in the following shape:
Customer1
..
Order1
..
Order2
..
Customer2
..
Figure 6-7 Return Type After An Induced Mapping of the Customer For Node
As this report also must list each customer's orders, you will need to create a second for clause. One way to do this is to simply add the CUSTOMER_ORDER type as a subordinate to CUSTOMER, as shown in the next step.
Figure 6-8 Append Mapping of the $CUSTOMER_ORDER to the Return Type
The CUSTOMER_ORDER elements will appear as subordinate to CUSTOMER.
Figure 6-9 Subordinate Node Added to the Return Type
If you try to run a query at this point it will fail for several reasons:
Figure 6-10 Creating a Zone Supporting CUSTOMER_ORDER
Note: Since the proposed qualified namespace of your new XML Type is identical to the qualified name of your CUSTOMER data service, a type conflict will occur if you try to complete this operation. The solution is to modify either the namespace or the root name.
Figure 6-11 Save and Associate XML Type Dialog
Although there are several ways to go about accomplishing the same task, it is also important to be aware that there were points along the way where an effort to build or deploy your application would not have been successful because the query or the return type was not fully formed. Thus the order in which steps are accomplished is often important.
The following terms and concepts are introduced in this section:
Liquid Data supports multiple data sources including:
For details on importing data source metadata from these sources into Liquid Data-based projects see Obtaining Enterprise Metadata.
The XQuery Editor uses XML schema representations as:
For more information see XML Types and Return Types.
Using the XQuery Editor, query functions can be built-up graphically using a combination of graphical gestures and functions, including:
The following topics describe XQuery clauses as rendered in the Liquid Data XQuery Editor. (For information on the XQuery engine used by Liquid Data and specific uses of XQuery in Source View see the Liquid Data XQuery Developer's Guide. This document also contains references to the most up-to-state XQuery W3C specifications.)
Query functions always map to a single return type. If your data service is associated with a return type, that type will appear in the Return node.
Figure 6-13 Sample Return Type
The return type can be thought of as extending the XML type to in support of:
When you click on a simple element in the return type, the expression on that element's constructor appears.
A for clause node represents a named XQuery for clause construct. For and let clause nodes are always based data service functions.
Figure 6-14 Sample For Statement Node
By default, whenever you add a data service to the XQuery Editor work area, it is represented in a for node. The for node typically represents looping over a query function using either:
A for node, representing a parameterized query function, provides both Input and Output sections. As you would expect, parameters are mapped to the Input elements while Output elements either serve as input to other nodes or to the return type.
Figure 6-15 Example of Parameterized For Node
Several options are available when you right-click on the title of a for
node.
Brings up a dialog which allows you to rename your node. Names cannot contain spaces. |
|
Removes the node and any mappings in or out of the node from the work area. |
|
Changes the clause from a for to a let. This operation is reversible. |
|
Relationship functions associated with the data service are listed. Selecting a relationship function allows your for or let node to serve as input for the relationship. See Adding Relationship Functions to Existing Data Service for an illustration and code sample. |
|
For and let clauses (see Let Statement Nodes) have many interchangeable characteristics.
The following code shows the conversion of the DataServices/RTLServices/Case/getCaseByCustID() function expression from a for clause:
declare function ns1:getCaseByCustID($cust_id as xs:string) as element(ns0:CASE)* {
for $x0 in ns1:getCase()
where $cust_id eq $x0/CustomerID
return $x0
};
declare function ns1:getCaseByCustID($cust_id as xs:string) as element(ns0:CASE)* {
let $x0 := ns1:getCase()
where $cust_id eq $x0/CustomerID
return $x0
};
A let clause binds a sequence of elements (graphically contained in a node) to a variable that in turn becomes available to the FLWR expression.
Options available for use with for clauses are also available for let clauses.
Figure 6-16 Let Statement in the RTLServices/OrderSummaryView Data Service
When examining a let clause, you can read the assign string (:=) as the "be bound to". For example, in the following let clause:
let $x := (1, 2, 3)
Can be read as "let the variable named x be bound to the sequence containing the items 1, 2, and 3."
See also Converting Between For and Let Clauses.
Parameter nodes enable you to associate a parameter with a for or let clause. Parameter nodes are created in the XQuery Editor work area (Figure 6-5). Three right-click menu options are available: Rename, Delete, and View Source.
Figure 6-17 XQuery Editor Add Parameter Dialog Box
You can create parameters that range from simple data elements to elements of any complexity.
You can create a simple type parameter by selecting the type from the drop-down list and clicking Ok.
Figure 6-18 Setting a Simple Parameter Types
The act of mapping a parameter to a for or a let node containing an Input creates a parameterized query and also establishes a where condition. In Figure 6-19 the customer_id string parameter is dragged over the element in the ADDRESS node which is to be associated with the parameter through a where clause.
Figure 6-19 Parameter Mapped to a For Node
The corresponding Source View code highlights the parameter:
declare function ns5:getCaseView($custID as xs:string) as element(ns6:CaseView) {
<ns6:CaseView>
{
<CASE_VIEW>
<CASES>{
for $Case in ns7:getCaseByCustID($custID)
return <CASE>
<CaseID> {fn:data($Case/CaseID)} </CaseID>
<CustomerID>{fn:data($Case/CustomerID)}</CustomerID>
<CaseType> {fn:data($Case/CaseType)} </CaseType>
<ProductID> {fn:data($Case/ProductID)} </ProductID>
<Status> {fn:data($Case/Status)} </Status>
<StatusDate> {fn:data($Case/StatusDate)} </StatusDate>
</CASE>
}
</CASES>
</CASE_VIEW>
}
</ns6:CaseView>
};
When you invoke your function from an application — or execute your function in Test View — you will supply a value for your parameter.
Complex parameters are established by identifying a schema and a global element. Some schemas have only one global element.
Figure 6-20 Setting a Complex Parameter Type
The resulting parameter can be associated with any for or let node. See also Parameterized Input.
You can use the parameter dialog to create a where clause condition simply by dragging the simple or complex parameter over an element in a for or let clause. In Figure 6-21 the newly created parameter productID is mapped to PRODUCT_ID. Since the $PRODUCT for node is selected, the where clause is in scope.
Figure 6-21 Parameterized Where Clause
There are several ways to add relationship functions to existing data services. The recommended way is to use the right-click menu option available from for and let nodes, since this will created more appropriately nested clauses than simply dragging a relationship function from the Liquid Data palette into the work area.
For example, if you want to create a logical data service that was a union of customer order and order line items, you could start with a customer order and add the related line item data.
Figure 6-22 takes the RTLApp DataServices/ApparelDB/CUSTOMER_ORDER() function and shows the process of adding the related getCUSTOMER_ORDER_LINE_ITEM() function.
Figure 6-22 Adding a Relationship Function
The function initially appears as:
declare function tns:newFunction() as element(ns30:CUSTOMER_ORDER9)* {
for $CUSTOMER_ORDER in ns28:CUSTOMER_ORDER()
return $CUSTOMER_ORDER
};
Adding the relationship function changes it to:
declare function tns:newFunction() as element(ns30:CUSTOMER_ORDER9)* {
;
for $CUSTOMER_ORDER in ns28:CUSTOMER_ORDER()
for $CUSTOMER_ORDER_LINE_ITEM in ns28:getCUSTOMER_ORDER_LINE_ITEM($CUSTOMER_ORDER)
return $CUSTOMER_ORDER
}
To complete this simple example you would need to add elements from the related data service to your return type and complete your mappings, as well as any transformations.
The Group By node represents a single group by clause with zero or more grouping expressions. The top part of the Group By node defines variables available to the generated group by expression. The bottom part defines the grouping expression itself.
Group By expressions are often used with aggregation functions such as grouping customers by total sales. A for or let clause supports multiple group by elements.
You can generate a Group By node by right-clicking on any element in a for or let node and selecting Create Group By from the right-click menu.
Figure 6-23 Creating a Group By Expression
In Figure 6-23 output will be grouped by the C_ID (customer ID) element. Once a GroupBy node is created mappings to target objects — such as the return type — are done through the new node.
Figure 6-24 Projecting Total Orders Grouped by Customer ID
The default name of the group by node will be a unique name based on the local name of the for/let node. Thus the CUSTOMER_ORDER for clause becomes the basis for CUSTOMER_ORDER_group0. Group By nodes cannot be renamed from the XQuery Editor.
As seen in Figure 6-24, any node mappings are automatically transferred to the Group By node.
declare function tns:getCustomerOrderAmount() as element(ns5:CUSTOMER_ORDER)* {
for $CUSTOMER_ORDER in ns6:CUSTOMER_ORDER()
group $CUSTOMER_ORDER as $CUSTOMER_ORDER_group by $CUSTOMER_ORDER/C_ID as $C_ID_group
return
<ns5:CUSTOMER_ORDER>
<ORDER_ID></ORDER_ID>
<C_ID>{fn:data($C_ID_group)}</C_ID>
<ORDER_DT></ORDER_DT>
<SHIP_METHOD_DSC></SHIP_METHOD_DSC>
<HANDLING_CHRG_AMT></HANDLING_CHRG_AMT>
<SUBTOTAL_AMT></SUBTOTAL_AMT>
<TOTAL_ORDER_AMT>{fn:sum($CUSTOMER_ORDER_group/TOTAL_ORDER_AMT)}</TOTAL_ORDER_AMT>
<SALE_TAX_AMT></SALE_TAX_AMT>
<SHIP_TO_ID></SHIP_TO_ID>
<SHIP_TO_NM></SHIP_TO_NM>
<BILL_TO_ID></BILL_TO_ID>
<ESTIMATED_SHIP_DT></ESTIMATED_SHIP_DT>
<STATUS></STATUS>
<TRACKING_NO?></TRACKING_NO>
</ns5:CUSTOMER_ORDER>
};
If you delete a Group By node any mappings from the parent node will need to be redrawn.
In the example you can add additional grouping expressions simply by dragging new elements over the "By" separator, (Figure 6-25).
Figure 6-25 Adding a Second Group By Element
The act of dragging the element over an existing group by expression, adds a second group by expression, as shown in Figure 6-26.
Figure 6-26 The New Group By Expression Element
The effect of adding the second group by in the above example is to group total orders by their status value.
<ORDER_ID/>
<C_ID>CUSTOMER0</C_ID>
<TOTAL_ORDER_AMT>1173.2</TOTAL_ORDER_AMT>
<STATUS>CLOSED</STATUS>
</ns0:CUSTOMER_ORDER5>
<ns0:CUSTOMER_ORDER5 xmlns:ns0="ld:DataServices/ApparelDB/CUSTOMER_ORDER5">
<ORDER_ID/>
<C_ID>CUSTOMER0</C_ID>
<TOTAL_ORDER_AMT>436.3</TOTAL_ORDER_AMT>
<STATUS>OPEN</STATUS>
</ns0:CUSTOMER_ORDER5>
<ns0:CUSTOMER_ORDER5 xmlns:ns0="ld:DataServices/ApparelDB/CUSTOMER_ORDER5">
<ORDER_ID/>
You can create additional multiple Group By expressions to enable creation of logic such as:
In order to do this you need to introduce an additional for or let clause to establish the parent-child structure that will support the needed logic.
To creating a second-level group by:
You can use Test View to verify your work.
The Distinct By node represents a single distinct by clause.
Several types of conditions can be graphically applied to for and let clauses. You can create these conditions using a multi-function editor that appears at the bottom of XQuery Editor work area. (Figure 6-27).
Figure 6-27 Multi-function Condition Editor
To add or modify constraints for a for or let node first select the node, then click anywhere in the multi-function editor. Everything but your selected expression will become unavailable, as indicated by the "grayed out" appearance of unselected objects.
Figure 6-28 provides a closer look at the multi-function dialog which includes the ability to:
Functions from the XQuery Function Palatte can be dragged into the multifunction box and then edited.
Figure 6-28 Detail of Multifunction Box
Liquid Data contains a full set of built-in XQuery functions. Most XQuery functions in the XQuery Function Palatte are standard XQuery functions supported by the W3C. However, there are several BEA-specific functions as well as several extensions to the language. (For details on the BEA implementation of the 1.0 XQuery engine see XQuery Developer's Guide. For more detailed information on standard XQuery functions, see the W3C XQuery 1.0 and XPath 2.0 Functions and Operators specification.)
The functions available from the XQuery Functions palette are used to create conditions around for and let clauses. For example, if you wanted to establish a condition related to which customers a query would return you would follow these steps:
fn:string-length() as xs:integer
function from the XQuery Palette into the Where condition.
Where fn:string-length($CUSTOMER/LAST_NAME)
Where fn:string-length($i/ORDERID)
<5
Figure 6-30 Editing an XQuery Function
If you mouse over the title of your for clause, you can see that the condition has been associated with the fragment. You can also verify this change in source view.
Figure 6-31 Mouse-over of Node Title Displays Its Conditions
When you run the function only records with LAST_NAMEs shorter than five characters will appear.
Automatic type casting generally ensures that input parameters used in functions and mappings are appropriate to the function in which they are used.
The where
clause places a condition on a for and/or let clause. A where clause can be any query expression, including another FLWR expression. The where clause typically filters the number of matches in a FLWR loop.
A common use of the where clause is to specify a join between two sources. For example, consider the following query:
<results>
{
for $x in (1, 2, 3), $y in (2, 3, 4)
where $x eq $y
return
<matches>{$x}</matches>
}
</results>
The where clause in this query filters (or joins or constraints) the results that match two sequences specified in the for clause. In this case, the numbers 2 and 3 match, and the query returns the following results:
<results>
<matches>2</matches>
<matches>3</matches>
</results>
To effect this in the XQuery Editor you would select the for or let clause to which the where condition applies. Then, in the where condition field, you enter:
$x eq $y
You can type in the name of an element or drag it from the a node in the work area into the Condition Editor. The eq XQuery operator can be entered directly or selected from the conditional pop-up list.
Figure 6-32 Conditional Operator Selection List
See also Using the Parameter Dialog to Create a WHERE Clause.
The order by clause indicates output order for a given set of data.
Unless otherwise specified, the order data appears will follow the XML tree. This is known as the document order. The order by keyword indicates that the content should be sorted in ascending order by the identified element(s).
XQuery keywords such as descending are supported. For example, an XQuery can be written that orders the customers by last name in descending order:
for $customer in document('customers.xml')//customer
order by last_name descending
return
<customer>
{$customer/first_name}
{$customer/last_name}
</customer>
...
In the XQuery Editor you would select the for or let clause to which the order by condition applies and in the order by condition field enter:
last_name descending
You can type in the name of an element or drag it from the work area into the Condition Editor Figure 6-28.
Join conditions are represented as equality relationships in where clauses. Therefore you can create such an equality relationship by dragging and dropping the eq function onto a row in the Conditions tab and then selecting two source elements/attributes into the same row.
The Expression editor is most commonly used to edit return type expressions. For example, if the return type contains:
ORDERID xsd:int
The Expression Editor could be used to limit the scope of the expression to a single customer:
Expression>{fn:data($o/ORDERID)} eq "1001"
Prototypes of functions available from the XQuery Function Palatte can be dragged into the Expression editor or you can use the build-in line editor to enter them yourself.
Operation of the Expression editor is similar to that for the multifunction box. When you select a element other workspace artifacts are grayed out. However, you can drag elements from any part of the work area into the Expression Editor.
XQuery operators are available as a drop down list, as shown in Figure 6-32, or you can simply type them in.
If you think of selected data elements as nouns (what you want to work on), the functions as verbs (the action), then the mapping among the data elements creates a logical sentence that expresses the query.
Results and query performance can change significantly depending on how you:
Although you can simply type in an XQuery and run it from Test View, the more common way to create a query is build it up through the following operations:
Note: Some operations are not deterministic. For example if a node has elements mapped to a return type, deleting the node before removing the mappings may create error conditions. In Instead you can use Undo and then delete the mappings or your can make the necessary changes in Source View.
Mapping elements involves establishing a visual relationship between data source elements and the return type or an intermediary node requiring input parameters.
There are two types of schema elements: simple and complex. Complex elements contain elements and/or attributes.
Figure 6-34 Expanded Schema Showing Complex and Simple Elements
To expand a complex element, click on the plus sign (+) to the left of its name. (If you double click on the name itself, you will enter edit mode.)
As shown in Creating a New Data Service and an XQuery Function, the XQuery Editor automatically generates queries based on graphical mappings into a return type.
The XQuery Editor supports two types of mappings: value mappings and complex element mappings. Value mappings map (assign) only the value of an element or attribute from a source to the value of its target element or attribute. Element mappings allow mapping source elements (simple or complex) to target.
(For additional background information see XML Types and Return Types and Editing XML Types and Return Types.)
A questionmark symbol [?
] next to an element name represents an optional element, meaning that it is not required by the query. Primary keys are never optional.
You can rapidly map complex elements from source to your return type. This known as an induced mapping is useful where all or part of the return type should match source representations.
There are many situations when you will find it convenient to map elements into your type, including:
If the match is not exact, mapping a complex element to your return type will be appended.
There are several benefits of mapping or projecting elements:
Figure 6-35 shows the results of the mapping of a complex element to a return type.
Figure 6-35 Example of Mapping of a Complex Element
Note: You cannot map multiple elements to a single target element.
Three types of source-to-return type mappings are available:
The following code expresses the results of an induced mapping:
declare function tns:newFunction() as element(ns5:CREDIT_CARD)* {
for $CREDIT_CARD in tns:getCreditCard()
return
$CREDIT_CARD
In many cases an induced mapping is insufficient either for further building your query function or running it. You can always expand complex element mappings by right-clicking on the element and selecting the only available option: Expand Complex Elements. In the above case the source would be correspondingly modified:
declare function tns:newFunction() as element(ns5:CREDIT_CARD)* {
for $CREDIT_CARD in tns:getCreditCard()
return
<ns5:CREDIT_CARD>
<CreditCardID>{fn:data($CREDIT_CARD/CreditCardID)}</CreditCardID>
<CustomerID>{fn:data($CREDIT_CARD/CustomerID)}</CustomerID>
<CustomerName>{fn:data($CREDIT_CARD/CustomerName)}</CustomerName>
<CreditCardType>{fn:data($CREDIT_CARD/CreditCardType)}</CreditCardType>
<CreditCardBrand>{fn:data($CREDIT_CARD/CreditCardBrand)}</CreditCardBrand>
<CreditCardNumber>{fn:data($CREDIT_CARD/CreditCardNumber)}</CreditCardNumber>
<LastDigits>{fn:data($CREDIT_CARD/LastDigits)}</LastDigits>
<ExpirationDate>{fn:data($CREDIT_CARD/ExpirationDate)}</ExpirationDate>
<Status?>{fn:data($CREDIT_CARD/Status)}</Status>
<Alias?>{fn:data($CREDIT_CARD/Alias)}</Alias>
<AddressID>{fn:data($CREDIT_CARD/AddressID)}</AddressID>
</ns5:CREDIT_CARD>
};
Figure 6-36 Expanded Complex Element
Note: Any changes you make to a return type should be propagated to your data services XML type using the Save and Associate XML Type right-mouse option, available from the return type titlebar.
You can delete mappings between elements by selecting the mapping line (link) and pressing Delete. Alternatively, use the Delete key.
The shape of the information returned by your query is determined by its return type. Using a combination of mapping techniques and return type options you can:
You should only modify a return type if you intend to propagate the change to the data service's XML type using the Save and Associate XML Type command, described in Creating a New Data Service and an XQuery Function.
You can edit your return type by right-clicking any element. Editing options for a type in the XQuery Editor are somewhat different options described in Editing an XML Type. For example, in a return type you can create zones automatically add for clauses to your query, allowing for a "master-detail" arrangement of results.
Warning: While it is possible to modify a return type and run a query in an ad hoc manner, problems will likely arise when your application calls a query with a mismatch between the return clause and the XML type of the data service.
Table 6-37 describes notable return type editing options.
Table 6-37 Notable Return Type Options
Allows you to specify a schema and type for a new complex child element. By default, the type is the root element of the schema. If the schema has several global elements, however, you will first need to specify the element that you want to become the root. |
|
Inserts an element named Conditional above the currently selected element and clones the element (and children, if any). Conditional elements can be used in conjunction with if-then-else constructs. Transformational logic can then be developed through the XQuery Editor and mapped to the appropriate branch of the condition. |
|
Duplicates the selected element (and children, if any) to the same level of the schema hierarchy. If you clone a simple element an unmapped, untyped element of the same name will be created. |
|
Sets (or removes) a zone setting for the current element and its children (if any). If the elements are in a zone the query will return them in a master-detail arrangement. See Setting Zones in Your Return Type. |
|
Deletes the selected element and any child elements or attributes. |
|
The Find dialog allows you to search for text strings in the return type with options to match case, match whole words only, use wildcards ( |
A special option, Expand Complex Mappings, is becomes available for use with Induced mappings. See Complex Element Mappings to a Return Type for details.
There are several things to keep in mind when making changes to a return type:
You can add a complex child element to a return type by selecting a schema and identifying a global element (a type). Complex child elements incorporate data service schemas (.xsd
file) into the return type.
To add a complex global element to your return type:
When you add a complex child element it will be place at the end of its peers in the return type.
In Liquid Data return types zones identify how query results will be arranged. Introducing zones using the XQuery Editor is the same as adding a subordinate for clause to your query.
For example in Figure 6-38 the CUSTOMER_ORDER elements for a particular customer will be grouped under that customer.
Figure 6-38 Sample Return Type With Two Zones
By default, return types have only a single zone. However, without additional zones elements simply repeat in their natural order. In the simple example shown in Figure 6-38 this would mean that if a customer had more than one order, both the customer information and the order information would be repeated it your report until all matching orders had appeared.
The following slightly simplified XML illustrates a single-zone approach.
<CUSTOMERID>987655</CUSTOMERID>
<CUSTOMERNAME>Supermart</CUSTOMERNAME>
<ORDER>
<ORDERID>632</ORDERID>
<CUSTOMERID>987655</CUSTOMERID>
<CUSTOMERID>987655</CUSTOMERID>
<CUSTOMERNAME>Supermart</CUSTOMERNAME>
<ORDER>
<ORDERID>888</ORDERID>
<CUSTOMERID>987655</CUSTOMERID>
..
Notice the repetition of CUSTOMERNAME and CUSTOMERID.
The XQuery source clearly shows why this is:
for $o in f2:PO_CUSTOMERS()
where $c/CUSTOMERID eq $o/CUSTOMERID
return
<t1:CUSTOMER>
<CUSTOMERID>{fn:data($c/CUSTOMERID)}</CUSTOMERID>
<CUSTOMERNAME>{fn:data($c/CUSTOMERNAME)}</CUSTOMERNAME>
<ORDER>
<ORDERID>{fn:data($o/ORDERID)}</ORDERID>
<CUSTOMERID>{fn:data($o/CUSTOMERID)}</CUSTOMERID>
{
for $i in f3:PO_ITEMS()
where $o/ORDERID eq $i/ORDERID
return
()
}
</ORDER>
</t1:CUSTOMER>
If you were, however, to create a repeatable zone around the ORDER element, a subordinate for clause will be created.
where $c/CUSTOMERID eq $arg0
return
<t1:CUSTOMER>
<CUSTOMERID>{fn:data($c/CUSTOMERID)}</CUSTOMERID>
<CUSTOMERNAME>{fn:data($c/CUSTOMERNAME)}</CUSTOMERNAME>
{
for $o in f2:PO_CUSTOMERS()
where $c/CUSTOMERID eq $o/CUSTOMERID
return
<ORDER>
<ORDERID>{fn:data($o/ORDERID)}</ORDERID>
<CUSTOMERID>{fn:data($o/CUSTOMERID)}</CUSTOMERID>
{
for $i in f3:PO_ITEMS()
where $o/ORDERID eq $i/ORDERID
return
()
}
</ORDER>
}
</t1:CUSTOMER>
Specifically the highlighted where clause in the second code fragment mandates that all orders be collected under a single instance of customer.
To create a zone simply right-click on an element and select Mark as Zone. Once created, the zone will appear highlighted whenever you move your cursor into areas under its control (Figure 6-38).
In XQuery for, let, and group by clauses can enclose other for, let, or group by clauses. Similarly, nodes representing these constructs can be associated with return type zones using the create zone icon in the titlebar of the node (see Figure 6-10 in the XQuery Editor example at the beginning of this chapter). Simply drag the icon over an existing zone to associate the node with the zone.
To verify that the operation is successful mouse-over the zone icon after the association is complete. If successful, the appropriate zone will be highlighted (see Figure 6-38). Alternatively, look at Source View to verify that your operation has been successful or simply run your query under Test View.
Note: The order in which you create zones and other aspects of your XQuery in the XQuery Editor can be significant. For example, zones should be created before creating a where clause associating two nodes.
To remove a zone, right-click on the parent element in the zone and select the Remove Zone option.
You can make changes in your function's return type and, optimally, bring your data service into conformance with the changes that you have made.
Figure 6-39 Return Type Management Options
Several right-click menu options are available for managing the return type, including:
Notice in the following example that two new child elements have been added to the return type.
Elements differences detected when comparing the return type with the content of the XML type are shown in red. This includes elements you have deleted from the return type as well as those you have added to the return type.
The addition of DESCRIPTION to the return type is shown in blue in Figure 6-40.
Figure 6-40 Return Type With a New Element
The arrows to the left of changed items indicate whether the change is originating locally in the return type (
Figure 6-41 Save and Associate Dialog
This command can also be used to save the revised return type to a schema, schema location, target Namespace, or root name that is different than that used by the containing data service.
When you are building a return type from data service functions it is sometimes necessary to change either the namespace or the root name prior to using the Save and Associate Schema command. This is because the qualified name of your return type will initially be the same as the function used to create the return type.
![]() ![]() |
![]() |
![]() |