ESQL
ESQL
ESQL
ESQL Reference
Version 2.1
SC34-6172-00
WebSphere MQ Integrator Broker
ESQL Reference
Version 2.1
SC34-6172-00
Note!
Before using this information and the product it supports, be sure to read the general information under Appendix D,
“Notices” on page 175.
Contents v
vi WebSphere MQ Integrator Broker ESQL Reference
Figures
1. Using a dynamic reference . . . . . . . 28 10. Tree representation produced by Trace node 150
2. DocType declaration . . . . . . . . . 35 11. Exception list structure . . . . . . . . 157
3. An external stored procedure . . . . . . 60 12. Database exception list structure . . . . . 159
4. An ESQL procedure . . . . . . . . . . 61 13. Conversion exception list structure . . . . 160
5. CREATE PROCEDURE: recursive example 61 14. Parser exception list structure . . . . . . 161
6. CREATE PROCEDURE: results of recursive 15. User exception list structure. . . . . . . 162
example. . . . . . . . . . . . . . 62 16. Retrieving the exception error code . . . . 163
7. Using EVAL to translate XML attributes to tags 68 17. CREATE statement example . . . . . . 164
8. Example using the PROPAGATE statement 77 18. Message flow using tagged or delimited
9. Messages produced on OUT terminal by messages to substitute CR LF pairs for NL
PROPAGATE statement . . . . . . . . 78 characters . . . . . . . . . . . . . 170
All references in this book to Windows NT® are also applicable to Windows® 2000
unless otherwise stated. WebSphere MQ Integrator Broker components that are
installed and operated on Windows NT can also be installed and operated on
Windows 2000.
Statements
An ESQL program consists of a number of statements that are executed in the
order they are written. ESQL has a number of different types of statement that
perform different types of operation. All ESQL statements start with a keyword
that identifies the type of statement and end with a semicolon. As an example,
consider the following ESQL program:
DECLARE x INTEGER;
SET x = 42;
This program consists of two statements. The first starts with the keyword
DECLARE and ends at the first semicolon. The second statement starts with the
keyword SET and ends at the second semicolon. These two statements are written
on separate lines and it is conventional (but not required) that they be so. You will
notice that the language keywords are written in capital letters. This is also the
convention within this book but is not required.
The first statement declares a variable called x of type INTEGER, that is, it reserves
a space in the computer’s memory large enough to hold an integer value and
allows this space to be subsequently referred to in the program by the name x. The
second statement sets the value of the variable x to 42. A number appearing in an
ESQL program without decimal point and not within quotes is known as an
integer literal.
ESQL has a whole range of data types and each has its own way of writing literal
values. These are described in “Data types” on page 5.
For a full description of all the ESQL statements, see Chapter 4, “ESQL statements”
on page 49.
SET Volume =
( (OuterRadius * OuterRadius) -
(InnerRadius * InnerRadius) ) * Length * 3.142;
Here you can see the multiply operator (*) and the subtract operator (-) being used
in conjunction with pairs of brackets to perform a calculation. ESQL is similar to
many other programming languages in the way in handles operators and
expressions. ESQL has a full set of operators; however, not all operators can be
applied to all types of data because some combinations would not lead to a
meaningful operation. See “Operators” on page 11 for information about these.
Some operators return a boolean value. An example of this is the greater than
operator (>), which compares two values and returns the boolean value TRUE if
the first is greater than the second and otherwise returns FALSE. SQL language
documentation often refers to such operators as predicates.
Functions
ESQL provides a number of predefined functions, that is, routines that calculate a
resultant value from a number of given input values. These can be used freely
within expressions. Consider the following ESQL program snippet:
SET Diameter = SQRT(Area / 3.142) * 2;
In this example you can see the function SQRT (square root) being used. It is being
given the value inside the brackets (itself the result of an expression – a divide
operation) and its result is being used in a further expression – a multiply
operation. ESQL has a comprehensive range of predefined functions. See Chapter 5,
“ESQL functions” on page 87 information about all the ESQL functions.
You can also use your own external functions and procedures.
Nested statements
Some statements allow other statements to be nested within them. Consider the
following ESQL program snippet:
IF Size > 100.00 THEN
SET X = 0;
SET Y = 0;
SET REVERSE = FALSE;
ELSE
SET X = 639;
SET Y = 479;
SET REVERSE = TRUE;
END IF;
Many statements can have expressions nested within them, but only a few can
have statements nested within them. The key difference between an expression and
a statement is that an expression calculates a value and demands that it be used
whereas a statement neither produces a value nor requires that one be used.
This program declares an integer variable called Priority and then sets its value to
the value of the Priority field of an MQMD structure within an input message by
using the field reference literal InputRoot.MQMD.Priority. Similarly the ESQL
program:
SET OutputRoot.MQMD.Priority = 7;
sets the value of the Priority Field of an MQMD structure within an output
message to the integer value 7.
The references above are field reference literals. Field references can also exist as
declared variables. Consider the following ESQL program:
DECLARE Priority REFERENCE TO OutputRoot.MQMD.Priority;
SET Priority = 7;
This also sets the Priority Field of an MQMD structure within an output message
to 7. In this case, Priority is a reference variable that has been initialized to point to
a particular message field. Reference variables can also use literal offsets as shown
in the following example:
DECLARE Mqmd REFERENCE TO OutputRoot.MQMD;
SET Mqmd.Priority = 7;
Data types
Within a broker, the fields of a message contain data that has a definite data type.
It is also possible to use intermediate variables to help process a message. All such
variables must be declared with a data type before use. Fields and declared
variables differ in that a variable’s data type is fixed, and attempts to assign values
of a different type will result in either implicit cast or an exception. Message fields
on the other hand do not have a fixed data type, and values of a different type can
be assigned. The field simply adopts the new value and type.
The following sections list all the data types used with ESQL.
Numbers
The INTEGER, FLOAT, and DECIMAL data types are collectively known as
numeric data types.
INTEGER, INT
The INTEGER data type holds an integer number in 64-bit two’s
complement form. This gives a range of values between
-9223372036854775808 and +9223372036854775807. In addition to the
normal integer literal format, integer literals can be written in hexadecimal
notation, for example 0x1234abcd.
The hexadecimal letters A to F can be written in uppercase or lowercase, as
can the 'x' after the initial zero.
For information about numeric functions, see “Numeric functions” on page 90.
There must be an even number of digits in the string, because two digits
are required to define each byte. Each digit can be one of the hexadecimal
digits. Both the initial X and the hexadecimal letters can be specified in
uppercase or lowercase.
BIT The BIT data type holds a variable length string of binary digits. It is
commonly used to represent arbitrary binary data that does not contain an
exact number of bytes. A bit string literal consists of the letter B followed
by a string of binary digits enclosed in single quotes, as in the following
example:
SET X=B'0100101001'
Datetime types
The DATE, TIME, GMTTIME, TIMESTAMP, GMTTIMESTAMP, and INTERVAL data types are
collectively known as datetime data types.
DATE The DATE datatype holds a Gregorian calender date (year, month, and
day). The format of a DATE literal is the word DATE followed by a space,
followed by a date in single quotes in the form ’yyyy-mm-dd’. For
example:
DECLARE MyDate DATE;
SET MyDate = DATE '2000-02-29';
Leading zeroes in the year, month, and day must not be omitted.
TIME The TIME data type holds a time of day in hours, minutes, seconds, and
fractions of a second. The format of a TIME literal is the word TIME
followed by a space, followed by a time in single quotes in the form
’hh:mm:ss.ffffff’. For example:
DECLARE MyTime TIME;
SET MyTime = TIME '11:49:23.656';
Each of the hour, minute and second fields in a TIMESTAMP literal must
always be two digits. The exception is the optional fractional seconds field
which, if present, can be up to 6 digits in length.
GMTTIMESTAMP
The GMTTIMESTAMP data type is similar to the TIMESTAMP data type, except
that the values are interpreted as values in Greenwich Mean Time.
GMTTIMESTAMP values are defined in a similar way to TIMESTAMP values, for
example:
DECLARE GetGMTTimeStamp GMTTIMESTAMP;
SET GetGMTTimeStamp = GMTTIMESTAMP '1999-12-31 23:59:59.999999';
For information about datetime functions, see “Datetime functions” on page 94.
INTERVAL
The INTERVAL data type holds an interval of time. There are two kinds of INTERVAL
values:
v One that is specified in years and months.
v One that is specified in days, hours, minutes and seconds (including fractions of
a second).
The split between months and days arises because the number of days in each
month varies. An interval of one month and a day is not really meaningful, and
certainly cannot be sensibly converted into an equivalent interval in numbers of
days only.
Where an interval contains both a year and a month value, a hyphen is used
between the two values. In this instance, the month value must be within the
range [0, 11]. If an interval contains a month value, and no year value, the month
value is unconstrained.
If an interval contains more than one of HOUR, MINUTE, and SECOND, a colon is
needed between the values. The values of these fields are constrained as follows:
Field Valid values
HOUR 0-23
MINUTE 0-59
SECOND 0-59.999...
BOOLEAN
The BOOLEAN data type holds a Boolean value. It can have the values:
v TRUE
v FALSE
v UNKNOWN. Refer to “IF” on page 69 for information about UNKNOWN.
Boolean literals consist of the keywords TRUE, FALSE, and UNKNOWN. They can
appear in uppercase or lowercase.
REFERENCE
The REFERENCE data type holds the location of a field in a message. A reference
value can point to a declared variable; it can not point to a constant, a database
table, or a database column. A reference literal is an hierarchic path name
consisting of a period (.) separated list of path elements. The first element in the
list is known as a correlation name and identifies the message tree to be accessed
(and in some cases also identifies a position within it). The subsequent elements
identify field type, names and indexes within the message tree.
For example:
InputRoot.MQMD.Priority
is a field reference literal that refers to the Priority field contained within an
MQMD structure within an input message. Individual names can be enclosed
within double quotes to allow names containing blank spaces or primary SQL
keywords to be used. For example :
Environment.Variables."State Data"."Return"
Path elements can also contain a type and an index. These are contained within
round and square brackets respectively. For example, the path:
InputRoot.XML.Data.(XML.Element)Invoice[3].(XML.Attribute)Period
identifies an XML attribute called Period within the third XML tag called Invoice
(indexes start at 1) within the first field (of any type) called Data within the first
field (again of any type) called XML.
NULLs
All ESQL data types (except REFERENCE) support the concept of the null value. A
value of null means that the value is unknown, undefined, or uninitialized. Null
values can arise by referencing message fields that do not exist, accessing database
columns for which no data has ever been supplied, or by using the keyword
NULL, which supplies a null literal value. Note that NULL is a distinct state and is
not the same as any other value. In particular, for integers it is not the same thing
as the value 0 and for character variables it is not the same thing as a string of
zero characters. The rules of ESQL arithmetic fully take null values into account
and users are usually unaware of their existence. Generally (but not always) these
rules mean that if any operand is NULL the result is NULL. This is described in
more detail in later in the book.
Operators
Arithmetic operators
ESQL provides the following numeric operators:
Unary Operator -
The result is the negation of the operand (that is, it has the same
magnitude as the operand but the opposite sign). It is possible to negate
both numeric values (INTEGER, DECIMAL and FLOAT) and intervals
(INTERVAL).
Operator +
The result is the sum of the two operands. It is possible to add numeric
values, to add intervals and also to add an interval to a datetime value
(DATE, TIME, TIMESTAMP, GMTTIME, and GMTTIMESTAMP).
Operator -
The result is the difference of the two operands. It is possible to:
v Subtract one numeric value from another
v Subtract one datetime from another. The result is an interval.
v Subtract one interval from another
v Subtract an interval from a datetime value
Operator *
The result is the product of the two operands. It is possible to multiply
numeric values and also to multiply an interval by a numeric value.
Operator /
The result is the dividend of the two operands. It is possible to divide
numeric values and also to divide an interval by a numeric value.
Operator ||
The result is the concatenation of the two operands. It is possible to
concatenate string values (CHARACTER, BIT and BLOB).
In most cases, if either operand is NULL, the result is NULL. However, in cases
using the || (concatenation) operator, if a valid string has NULL concatenated to
it, the result is the original string. Note that in cases where the operands are
different types, special rules apply. These are described in “Implicit casts” on
page 117.
Adding or subtracting two intervals: Two interval values can be combined using
addition or subtraction. The two interval values must be of compatible types. For
example, it is not valid to add a year-month interval to a day-second interval. So
the following example is not valid:
INTERVAL '1-06' YEAR TO MONTH + INTERVAL '20' DAY
would result in an interval with qualifier DAY TO SECOND, because both day and
second fields are present in at least one of the operand values.
would return the number of days since the 4th July 1776, whereas:
(CURRENT_TIME - TIME '00:00:00') MINUTE TO SECOND
Logical operators
ESQL provides the following logical operators:
Operator AND
The result is the logical AND of the two operands. Both operands must be
boolean values.
Operator OR
The result is the logical OR of the two operands. Both operands must be
boolean values.
Operator NOT
The result is the logical NOT of the operand, which must be a boolean
value.
NULL and UNKNOWN values are handled specially by these operators. The
principles are:
v NULL and UNKNOWN are treated the same.
v If an operand is NULL the result will be NULL unless the operation result is
already dictated by the other parameter.
Comparison operators
ESQL provides the following comparison operators (predicates):
Operator >
The result is TRUE if the value of the first operand is greater than that of
the second. Otherwise the result is FALSE (but see the note on NULL
values below).
Operator <
The result is TRUE if the value of the first operand is less than that of the
second. Otherwise the result is FALSE (but see the note on NULL values
below).
Operator >=
The result is TRUE if the value of the first operand is greater than or is
equal to that of the second. Otherwise the result is FALSE (but see the note
on NULL values below).
Operator <=
The result is TRUE if the value of the first operand is less than or is equal
to that of the second. Otherwise the result is FALSE (but see the note on
NULL values below).
Operator =
The result is TRUE if the value of the first operand is equal to that of the
second. Otherwise the result is FALSE (but see the note on NULL values
below).
Operator <>
The result is TRUE if the value of the first operand is not equal to that of
the second. Otherwise the result is FALSE (but see the note on NULL
values below).
BETWEEN operator
ASYMMETRIC
expression BETWEEN endpoint-1 AND endpoint-2
SYMMETRIC
In all the above cases, if any operand is NULL, the result is UNKNOWN (that is, a
NULL value of type BOOLEAN). Note that in cases where the operands are
different types, special rules apply. These are described in “Implicit casts” on
page 117
Operator IN
The operator IN allows you to test whether a value is equal to one of a list
of values.
IN operator
operand-1 IN ( operand-2 )
The result is TRUE if the left operand is not NULL and is equal to one of
the right operands. The result is FALSE if the left operand is not NULL
and is not equal to any of the right operands none of which have NULL
values. Otherwise the result is UNKNOWN. Note that in cases where the
operands are different types, special rules apply. These are described in
“Implicit casts” on page 117
Operator LIKE
The operator LIKE searches for strings that have a certain pattern. The
standard LIKE predicate for performing simple string-pattern matching is
supported.
The pattern is specified by a string in which the percent (%) and
underscore (_) characters can be used to have special meaning:
If you want to use the percent and underscore characters within the
expressions that are to be matched, you must precede these with an
ESCAPE character, which defaults to the backslash (\) character.
You can specify a different escape character by using the ESCAPE clause
on the LIKE predicate. For example, you could also specify the previous
example like this:
Body.Trade.Company LIKE ‘IBM$_Corp’ ESCAPE ‘$’
Operator IS
The primary purpose of the operator IS is to allow you to test whether a
value is NULL. Note that the comparison operator (=) does not allow this
because the result of comparing with NULL is NULL. It also allows you to
use a more natural English syntax when testing boolean values.
IS operator
TRUE
Operand IS FALSE
NOT UNKNOWN
NULL
The result is TRUE if the value of the left operand is equal (or not equal if
the NOT clause is present) to the specified value (TRUE, FALSE,
UNKNOWN or NULL).
Operator EXISTS
EXISTS(SELECT * FROM something WHERE predicate)
ESQL’s precedence rules require that c is multiplied by d and this result is added
then to b. This rule says that multiplication takes precedence over addition and
thus reordering the expression as follows:
SET a = c * d + b;
would make no difference. ESQL’s precedence rules are set out below but it is
generally considered good practice to use brackets to make the meaning clear. The
order of precedence is:
1. Brackets
2. Unary operators (unary - and NOT)
3. Multiplication and division
4. Concatenation
5. Addition and subtraction
Operations at the same level are evaluated working from left to right.
The two key differences between Filter, Compute, and Database nodes are:
v The number of output terminals they have.
v Whether they propagate their input message to their output terminals or create a
new message and propagate that message.
More specifically:
v The Filter node is a message flow path decision node that cannot update the
WebSphere MQ Integrator Broker message but can update databases.
v The Compute node can update the WebSphere MQ Integrator Broker message
and update databases.
v The Database node cannot update the WebSphere MQ Integrator Broker message
but can update databases.
The database node is the simplest node. It does not create a new message and has
one output terminal only. The operations it can perform are thus somewhat
limited. It can:
v Update a database.
v Update the Environment or LocalEnvironment message trees.
v Propagate the input message to its output terminal.
The following example uses the database node to INSERT, UPDATE, and DELETE.
IF Root.XML.TestCase.Action = ’INSERT’ THEN
INSERT INTO Database.STOCK (STOCK_ID, STOCK_DESC, STOCK_QTY_HELD,
BROKER_BUY_PRICE, BROKER_SELL_PRICE, STOCK_HIGH_PRICE, STOCK_HIGH_DATE,
STOCK_HIGH_TIME) VALUES
(CAST(Root.XML.TestCase.stock_id AS INTEGER),
Root.XML.TestCase.stock_desc,
CAST(Root.XML.TestCase.stock_qty_held AS DECIMAL),
CAST(Root.XML.TestCase.broker_buy_price AS DECIMAL),
CAST(Root.XML.TestCase.broker_sell_price AS DECIMAL),
Root.XML.TestCase.stock_high_price,
CURRENT_DATE,
CURRENT_TIME);
ELSE
IF Root.XML.TestCase.Action = ’DELETE’ THEN
DELETE FROM Database.STOCK WHERE STOCK.STOCK_ID =
CAST(Root.XML.TestCase.stock_id AS INTEGER);
The filter node is also more complex than the database node but in a different way
to the Compute node. It does not create a new message but has four output
terminals. The operations it can perform are:
v Update a database.
v Update the Environment or LocalEnvironment message trees.
v Propagate the incoming message to one of three output terminals.
There are two statements that have different effects when used in the different
node types. The first is the RETURN statement. In all the node types, it is expected
that ESQL execution is ended by a RETURN statement. There might be one
RETURN statement as the very last statement or there might be several RETURN
statements, each of which is reached only under particular conditions (for example,
they are nested inside IF statements). The value returned affects message
propagation to further nodes. In the case of the Database and Compute nodes, the
message is propagated to the output terminal only if the value returned is TRUE.
In the filter node, however, it is propagated to the ″true″ terminal if the return
value is TRUE, to the ″false″ terminal if it is FALSE, and to the ″unknown″
terminal if it is UNKNOWN. In this respect, the behavior of the Database and
Compute nodes is a subset of the behavior of the filter node: their ″out″ terminals
are equivalent to the filter node’s ″true″ terminal. Refer to “RETURN” on page 79
for detailed information about the RETURN statement.
If you decide to use these functions to check the success or failure of the database
calls you make, you must analyze and handle any errors that arise. If you do not
do this when an error occurs, the database might be in an indeterminate state. To
back out a database transaction, use the THROW statement with the exception
type USER.
The second statement that has a different effect when used in the different node
types is the PROPAGATE statement. In Compute node, PROPAGATE causes the
output message to be propagated to further nodes and the message tree to be
cleared ready for reuse. This allows a Compute node to generate and propagate
multiple output messages from one input message. When using PROPAGATE
Correlation names are used in field references to describe standard parts of the tree
formats. The correlation names used differ depending on whether the processing of
the node creates an output message. For example, a Trace node does not alter the
content of the message as it passes through the node, but a Compute node might
construct a new output message.
CorrelationName
.
PathElement
PathElement:
( TypeExpression ) NameIdentifier [ ]
{ NameExpression } IndexExpression
* <
IndexExpression
>
IndexExpression
LAST
[<] and [>] are legitimate. An example using < and > is shown on page 23.
This example causes the broker to start at the location InputRoot (that is, the root
of the input message to a Compute node) and then to perform a sequence of
navigations. Firstly, it navigates from root to the first child field ″XML″, then to the
first child field of the ″XML″ field ″Data″. Finally, the broker navigates to the first
child field of the ″Data″ field ″Invoice″. Whenever this field reference occurs in an
ESQL program, the invoice field is accessed.
This form of field reference is simple, convenient, and is the most commonly used.
However, it does have two limitations. Firstly, because the names used must be
valid ESQL identifiers, you can use names that conform to the rules of ESQL only.
That is, the names can contain alphanumeric characters including underscore only,
the first character can not be numeric and names must be at least one character
long. You can avoid this limitation by enclosing such names in double quotes. For
example:
InputRoot.XML."Customer Data".Invoice
If you need to refer to fields that contain quotation marks, you must use two pairs
of quotation marks around the reference. For example:
Body.Message."""hello"""
The second limitation is that, because the names of the fields appear in the ESQL
program, they have to be known when the program is written. This limitation can
be avoided by using the alternate syntax that uses braces ( ″{ ... }″ ). This syntax
allows you to use any expression that returns a non-null value of type character.
For example:
InputRoot.XML."Customer Data".{’Customer-’ || CurrentCustomer}.Invoice
In this example, the invoices are contained in a folder with a name is formed by
concatenating the character literal ″Customer-″ with the value in
″CurrentCustomer″ (which must be a declared variable of type character).
Enclosing anything in double quotes in ESQL makes it an identifier. Conversely,
enclosing anything is single quotes makes it a character literal.
Each element of a field reference can contain an index clause. These are denoted by
square brackets ( ″[ ... ]″ ) and accept any expression which returns a non-null
value of type integer. This clause identifies which of several fields with the same
name is to be selected. Fields are effectively numbered from the first starting at
one. If this clause is not present, it is assumed that the first field is required. Thus,
the two examples below have exactly the same meaning:
InputRoot.XML.Data[1].Invoice
InputRoot.XML.Data.Invoice[1]
This construct is most commonly used with an index variable so that a loop steps
though all such fields in sequence. For example:
WHILE count < 32 DO
SET TOTAL = TOTAL + InputRoot.XML.Data.Invoice[count].Amount;
END WHILE;
Index expressions can optionally be preceded by a less than sign ( ″<″ ) indicating
that the required field is to be indexed from the last field, not the first. In this case,
the index 1 refers to the last element and the index 2 refers to the penultimate
element. For completeness a greater than sign can be used to indicate counting
from the first field. For example, if there are four fields called ″Invoice″:
InputRoot.XML.Data.Invoice -- Selects the first
InputRoot.XML.Data.Invoice[1] -- Selects the first
InputRoot.XML.Data.Invoice[>] -- Selects the first
InputRoot.XML.Data.Invoice[>1] -- Selects the first
InputRoot.XML.Data.Invoice[>2] -- Selects the second
InputRoot.XML.Data.Invoice[<] -- Selects the fourth
InputRoot.XML.Data.Invoice[<1] -- Selects the fourth
InputRoot.XML.Data.Invoice[<2] -- Selects the third
InputRoot.XML.Data.Invoice[<3] -- Selects the second
An index clause can also consist of an empty pair of square brackets ( ″[ ]″ ). This
indicates that all fields with matching names are to be selected. This construct is
used with functions that expect lists (for example, SELECT or CARDINALITY).
Finally, each element of a field reference can contain a type clause. These are
denoted by round brackets ( ″( )″ ) and accept any expression that returns a
non-null value of type integer. The presence of a type expression restricts the fields
that are selected to those of the matching type. This construct is most commonly
used with generic XML where there are many element types and it is possible for
one XML element to contain both attributes and further XML elements with the
same name. For example:
<Item Value = ’1234’ >
<Value>5678</Value>
</Item>
In this example, the XML element ″Item″ has two child elements both called
″Value″. They can be distinguished by using type clauses:
Item.(XML.Attribute)Value -- Selects the attribute
Item.{0x03000000)Value -- Selects the attribute
Item.(XML.Element)Value -- Selects the Element
In these examples the constants are used but you are not restricted to using
constants.
The array index [1] indicates that it is the first instance of the repeating field that
you are interested in (array indices start at 1). An array index such as this can be
used at any point in a field reference, so you could, for example, filter on:
Body.Invoice."Item"[1].Quantity > 2
If you do not know exactly how many instances of a repeating field there are, you
can look at the last instance, or a relative field (for example, the third field from
the end). You can refer to the last instance of a repeat by using the special LAST
array index, as in:
Body.Invoice."Item"[LAST].Quantity > 2
In this case, the CARDINALITY function is passed a field reference that ends in [].
The meaning of this is "count all instances of the Item field". The [] at the end
appears superfluous, because the context indicates that this is the meaning, but its
presence is required. This makes the syntax consistent with other instances where
it is necessary to refer to "all instances" of something. Remember that array indices
start at 1, so the array index in the above example refers to the third-from-last
instance of the Item field.
Note: If you are using a while loop to process elements of a message, to improve
performance, it is recommend that you set a variable to the value of the
CARDINALITY prior to entering the loop.
For example, you might want to verify that none of the items that were being
ordered had quantity greater than 50. To do this you could write:
FOR ALL Body.Invoice.Purchases."Item"[] AS I (I.Quantity <= 50)
There are several things to note about this example. With the quantified predicate
itself, the first thing to note is the "[]" on the end of the field reference after the
"FOR ALL". The square brackets tell you that you are iterating over all instances of
the Item field.
In some cases, this syntax appears unnecessary because you can get that
information from the context, but it is done for consistency with other pieces of
syntax.
The "AS" clause associates the name I with the current instance of the repeating
field. This is similar to the concept of iterator classes used in some object oriented
languages such as C++. The expression in parentheses is a predicate that is
evaluated for each instance of the Item field.
The above is a description of how the predicate is evaluated if the "ALL" keyword
is used. An alternative is to specify "SOME", or "ANY", which are equivalent. In
this case the quantified predicate returns TRUE if the sub-predicate returns TRUE
for any instance of the repeating field. Only if the sub-predicate returns FALSE for
all instances of the repeating field does the quantified predicate return FALSE. If a
mixture of FALSE and UNKNOWN values are returned from the sub-predicate, an
overall value of UNKNOWN is returned.
To illustrate this, the following examples are based on the message described in
“Message used in this book” on page 147. In the following filter expression
FOR ANY Body.Invoice.Purchases."Item"[] AS I (I.Title = 'The XML Companion')
the sub-predicate evaluates to TRUE, however this next expression returns FALSE:
FOR ANY Body.Invoice.Purchases."Item"[] AS I (I.Title = 'C Primer')
because the ″C Primer″ is not included on this invoice. If in this instance some of
the items in the invoice had not included a book title field, the sub-predicate
would have returned UNKNOWN, and the quantified predicate would have
returned the value UNKNOWN.
Great care must be taken to deal with the possibility of null values appearing. You
are therefore recommended to write this filter with an explicit check on the
existence of the field, as follows:
FOR ANY Body.Invoice.Purchases."Item"[] AS I (I.Book IS NOT NULL AND
I.Book.Title = 'C Primer')
The "IS NOT NULL" predicate ensures that if an Item field does not contain a Book,
a FALSE value is returned from the sub-predicate.
Using the SELECT expression: Another way of dealing with arbitrary repeats of
fields within a message is to use a SELECT expression. This is described in
“Column functions” on page 131.
is a path that identifies the array of all children of InputRoot. This is often used in
conjunction with an array subscript to refer to a particular child of an entity by
position, rather than by name. So, for example:
InputRoot.*[LAST]
Refers to the last child of the root of the input message, that is, the "body"
of the message.
It is useful to be able to find out the name of an entity that has been identified
with a path of this kind. To do this, you can use the FIELDNAME function. This
function takes a path as its only parameter and returns as a string the field name
of the entity to which the path refers. Here are some examples of its usage:
FIELDNAME(InputRoot.XML)
Returns 'XML'.
FIELDNAME(InputBody)
Returns the name of the last child of InputRoot, which could be 'XML'.
FIELDNAME(InputRoot.*[LAST])
Returns the name of the last child of InputRoot, which could be 'XML'.
This example declares a dynamic reference, myref, which points to the first item in
a message array. The value in the first item is incremented by one, and then the
pointer (dynamic reference) is moved to the next item. Once again the item value
is incremented by one. This process continues until the pointer moves outside of
the scope of the message array (all the items in this array have been processed)
and the LASTMOVE function returns FALSE. LASTMOVE is described in
“LASTMOVE” on page 97.
Before you can use a dynamic reference you must first declare it. A dynamic
reference is declared and initialized in a single statement.
The examples below show how to declare a dynamic reference. They are based on
“Message used in this book” on page 147:
DECLARE ref1 REFERENCE TO InputRoot.Invoice.Purchases.Item[1];
In the second example, ref2 points to InputRoot because the specified field does
not exist.
With the exception of the MOVE statement, which changes the position of the
dynamic reference, a dynamic reference can be used anywhere that a static
reference would be. The value of the dynamic reference in any expression or
statement is the value of the field or variable to which it currently points. For
example, using the message in “Message used in this book” on page 147, the value
of Invoice.Customer.FirstName is ’Andrew’. If the dynamic reference myref is set
to point at the FirstName field as follows:
DECLARE myref REFERENCE TO Invoice.Customer.FirstName;
The value of myref is ’Andrew’. It is also possible to extend this dynamic reference
as follows:
SET myref.Billing.Address[1] = ’Oaklands’;
This changes the address in our example to ’Oaklands Hursley Village Hampshire
SO213JR.
To differentiate between these two possible field types, you must insert a value in
front of the referenced field in the MQRFH2 field to identify its type (a value for
the NameValue buffer is not required because this is the default). The value you
must specify for the header structure is (MQRFH2.Field).
For example:
v To create or change an MQRFH2 Format field, specify the following ESQL:
SET OutputRoot.MQRFH2.(MQRFH2.Field)Format = ’MQSTR ’;
v To create or change the psc folder with a topic:
SET OutputRoot.MQRFH2.psc.Topic = ’department’;
v To add an MQRFH2 header to an outgoing message that is to be used to make a
subscription request:
DECLARE I INTEGER;
SET I = 1;
WHILE I < CARDINALITY(InputRoot.*[]) DO
SET OutputRoot.*[I] = InputRoot.*[I];
SET I=I+1;
END WHILE;
SET OutputRoot.MQRFH2.(MQRFH2.Field)Version = 2;
SET OutputRoot.MQRFH2.(MQRFH2.Field)Format = ’MQSTR’;
SET OutputRoot.MQRFH2.(MQRFH2.Field)NameValueCCSID = 1208;
SET OutputRoot.MQRFH2.psc.Command = ’RegSub’;
SET OutputRoot.MQRFH2.psc.Topic = "InputRoot"."MRM"."topel";
SET OutputRoot.MQRFH2.psc.QMgrName = ’DebugQM’;
SET OutputRoot.MQRFH2.psc.QName = ’PUBOUT’;
SET OutputRoot.MQRFH2.psc.RegOpt = ’PersAsPub’;
The generic XML model contains a large number of different syntax elements. The
information contained here is intended as a reference on how to refer to and
manipulate the entire array of these elements. For a more detailed discussion on
what each syntax element is and how they are parsed into a message tree, see the
WebSphere MQ Integrator Broker Working with Messages book.
This example returns the name of the first element in the body of the message
(assuming it is an XML message). The following example of generic XML shows a
case of when it is necessary to use types in paths:
<tag1 attr1=’abc’>
<attr1>123<attr1>
</tag1>
To assign 112233 to <i1>, you need to use the following ESQL expression:
SET OutputRoot.XML.(XML.Element)doc.I1=112233;
This ESQL generates the following XML, which is not well-formed and fails when
written from an MQOutput node :
<Order>
<ItemNo>1</ItemNo>
<Quantity>2</Quantity>
</Order>
<?xml version="1.0"?>
<!DOCTYPE Order SYSTEM "Order.dtd">
XML declaration
Consider the following ESQL in a Compute node :
-- Create an XML Declaration
SET OutputRoot.XML.(XML.XmlDecl) = ’’;
Note that (XML."Encoding") must contain the double quotes because Encoding is a
reserved word in WebSphere MQ Integrator Broker.
For further information on the syntax elements involved in the XML declaration,
see WebSphere MQ Integrator Broker Working with Messages.
-- Create Both types of External Entity, each with a public and system ID
SET OutputRoot.XML.(XML.DocTypeDecl).(XML.IntSubset).(XML.ExternalParameterEntityDecl)extent1 = ’’;
SET OutputRoot.XML.(XML.DocTypeDecl).(XML.IntSubset).(XML.ExternalParameterEntityDecl)extent1.(XML.SystemId) =
’more.txt’;
SET OutputRoot.XML.(XML.DocTypeDecl).(XML.IntSubset).(XML.ExternalParameterEntityDecl)extent1.(XML.PublicId) =
’//this/is/a/URI/extent1’;
SET OutputRoot.XML.(XML.DocTypeDecl).(XML.IntSubset).(XML.ExternalEntityDecl)extent2 = ’’;
SET OutputRoot.XML.(XML.DocTypeDecl).(XML.IntSubset).(XML.ExternalEntityDecl)extent2.(XML.SystemId) = ’more.txt’;
SET OutputRoot.XML.(XML.DocTypeDecl).(XML.IntSubset).(XML.ExternalEntityDecl)extent2.(XML.PublicId) =
’//this/is/a/URI/extent2’;
-- Add a DocTypeComment
SET OutputRoot.XML.(XML.DocTypeDecl).(XML.IntSubset).(XML.DocTypeComment) = ’this is a comment’;
-- Create a variety of Elements
SET OutputRoot.XML.(XML.DocTypeDecl).(XML.IntSubset).(XML.AttributeList)subel1.(XML.AttributeDef)size.
(XML.AttributeDefType) = ’(big | small)’;
-- Create another attribute - this time we specify the DefaultType as being #REQUIRED
SET OutputRoot.XML.(XML.DocTypeDecl).(XML.IntSubset).(XML.AttributeList)subel1.(XML.AttributeDef)shape = ’’;
SET OutputRoot.XML.(XML.DocTypeDecl).(XML.IntSubset).(XML.AttributeList)subel1.(XML.AttributeDef)shape.
(XML.AttributeDefType) = ’(round | square)’;
-- Create another attribute list for element el5 with one attribute, containing CDATA which is #IMPLIED
SET OutputRoot.XML.(XML.DocTypeDecl).(XML.IntSubset).(XML.AttributeList)el5 = ’’;
SET OutputRoot.XML.(XML.DocTypeDecl).(XML.IntSubset).(XML.AttributeList)el5.(XML.AttributeDef)el5satt = ’’;
SET OutputRoot.XML.(XML.DocTypeDecl).(XML.IntSubset).(XML.AttributeList)el5.(XML.AttributeDef)el5satt.
(XML.AttributeDefType)CDATA = ’’;
SET OutputRoot.XML.(XML.DocTypeDecl).(XML.IntSubset).(XML.AttributeList)el5.(XML.AttributeDef)el5satt.
(XML.AttributeDefDefaultType) = ’IMPLIED’;
v “SELECT” on page 100 (used with SET statement) v FROM, AS, ITEM, THE, SUM, COUNT, MAX, MIN
v “BITNOT” on page 91
v “BITOR” on page 91
v “BITXOR” on page 92
General v “ABS” on page 90, ABSVAL –
v “CURRENT_GMTDATE” on page 95
v “CURRENT_TIME” on page 95
v “CURRENT_GMTTIME” on page 95
v “CURRENT_TIMESTAMP” on page 95
v “CURRENT_GMTTIMESTAMP” on page 95
v “LOCAL_TIMEZONE” on page 96
v “EXTRACT” on page 94
Reference
“MOVE” on page 71 TO, PARENT, FIRSTCHILD, LASTCHILD,
PREVIOUSSIBLING, NEXTSIBLING
Flow of control
Conditional statement (within an v IF...THEN...ELSE (see “IF” on page 69) v END
ESQL node)
v WHILE...DO (see “WHILE” on page 85) v END
Exiting an ESQL node v “RETURN” on page 79 USER, EXCEPTION, CATALOGUE, MESSAGE,
VALUES
v “PROPAGATE” on page 77
v “THROW” on page 83
Boolean evaluation for conditional statements
Functions that return a boolean v BETWEEN, see “Comparison operators” on page 13 for SYMMETRIC, ASYMMETRIC, AND
value details.
v EXISTS, see “Comparison operators” on page 13 for
details.
v IN, see “Comparison operators” on page 13 for details.
v LIKE, see “Comparison operators” on page 13 for
details.
v “NULLIF” on page 102
v “LASTMOVE” on page 97
v “SAMEFIELD” on page 97
Operators used in boolean v <, >, =, >=, <=, <> –
expressions.
See “Comparison operators” on page 13 for details.
v NOT, see “Logical operators” on page 12 for details.
v OR, see “Logical operators” on page 12 for details.
An ESQL palette is provided to allow you to select, drag and drop ESQL
statements into the ESQL editor pane. These statements are listed as keywords in
alphabetical order. Each entry in the palette has a string associated with it that
describes the full syntax of the statement. Many statement strings contain
replaceable terms that signify where the user must supply an expression or value.
The palette also contains a list of functions, which can be similarly dragged and
dropped. When dropped onto a replaceable term, the original text is replaced by
the dropped text: the dropped text is not added to the original text. By first
dragging and dropping statements onto the pane and then dropping functions into
the statements, you can write ESQL quickly and without error.
You can also drag elements from the input and output message structure palettes
into statements or functions. If the element that you have chosen is repeatable, for
example an array of order items, a dialog is opened to prompt you for the index
entry of the item you are updating in the array. For more information, see
WebSphere MQ Integrator Broker Using the Control Center.
ESQL conventions
This section describes the following ESQL conventions.
v “Case sensitivity of ESQL syntax”
v “Special characters in ESQL” on page 46
v “Reserved keywords used in ESQL” on page 47
v “Comments”
Comments
ESQL has two types of comment: single line and multiple line. A single line
comment starts with the characters -- and ends at the end of the line.
In arithmetic expressions you must take care not to initiate a line comment
accidentally. For example, consider the expression:
1 - -2
A multiple line comment starts with /* anywhere in ESQL and ends with */.
ATTACH
ATTACH
The ATTACH statement attaches a portion of a message tree into a new position in
the message hierarchy.
The following example illustrates how you could use the ATTACH statement,
together with the DETACH statement described in “DETACH” on page 65 to
modify a message structure. The dynamic reference supplied to the DETACH
statement must point to a modifiable message tree such as Environment,
LocalEnvironment, OutputRoot, OutputExceptionList, or InputLocalEnvironment.
There are some limitations to the use of ATTACH. In general, elements detached
from the output trees of a Compute node might not be attached to the
environment or to input trees. For example, if you take the following message:
<Data>
<Order>
<Item>cheese
<Type>stilton</Type>
</Item>
<Item>bread</Item>
</Order>
<Order>
<Item>garlic</Item>
<Item>wine</Item>
</Order>
</Data>
CALL
CALL
CALL–ProcedureName –( ExpressionList )
ExpressionList:
Expression
The CALL statement calls a named procedure that has been defined using the
CREATE PROCEDURE statement. This procedure can be implemented in ESQL or
externally as a database stored procedure. The CALL statement passes the
parameters into the procedure in the order given to it. Parameters that have been
defined as IN or INOUT are evaluated before the CALL is made, but parameters
defined as OUT are always passed in as NULL parameters of the correct type.
When the procedure has completed any parameters declared as OUT or INOUT
are updated to reflect any changes made to them during the procedure’s execution.
Parameters defined as IN are never changed during the cause of a procedure’s
execution.
The number of and type parameters passed to the procedure must match the
number and type of the parameters as declared in the CREATE PROCEDURE
definition.
For an example of the use of CALL, see the following examples in CREATE
PROCEDURE: Figure 3 on page 60 and Figure 4 on page 61.
COMPOUND
COMPOUND
BEGIN–Statements–END;
The COMPOUND statement defines a new variable name scope and gives the
statements defined within it the status of a single statement. This allows the
statements to become the body of a function or a procedure.
CREATE FIELD
CREATE
FIELD Target
AS Alias values clauses
from clause
FIRSTCHILD OF Target
LASTCHILD AS Alias DOMAIN–expr values clauses
from clause
parse clause
PREVIOUSSIBLING OF Target
NEXTSIBLING AS Alias DOMAIN–expr values clauses
repeat clauses
from clause
parse clause
values clauses:
from clause:
FROM–source
parse clause:
PARSE ( bitstream )
, encoding , ccsid
, message set , message type , message format
repeat clauses:
REPEAT
VALUE–expr
The CREATE statement creates a new message field positioned either at a given
location or relative to a currently existing location. New fields can be created only
when the target field reference points to a modifiable message, for example
Environment, InputLocalEnvironment, OutputLocalEnvironment, OutputRoot, or
OutputExceptionList.
If array indices are used in the target field reference, only one instance of a
particular field can be created. Thus, if you write a SET statement starting:
SET OutputRoot.XML.Message.Structure[2].Field = ...
If present, the AS clause causes the named reference variable to be moved to point
at the newly-created field. This is often useful because having created a field, it is
likely you will want to involve it in some further processing.
If present, the DOMAIN clause causes the new field to belong to a new parser of
the specified type. This clause expects a root field name (for example, XML or
MQRFH2). If the DOMAIN clause is present, but the value supplied is a zero
length character string, a new parser of the same type as the parser that owns the
field specified by ″target″ is created. An exception is thrown if the supplied
domain name is not of the CHARACTER data type or its value is NULL. Note that
the DOMAIN clause cannot be specified when the FIELD clause is used because, in
this case, it is not certain that a new field will be created.
The new field’s type and name can be copied from the target field using the
REPEAT clause. Alternatively, the new field’s type, name, and value can be:
v copied from any existing field (using the FROM clause)
v specified explicitly (using the VALUES clause)
v defined by parsing a bitstream (using the PARSE clause)
In the case of the FROM and PARSE clauses, children of the new field can also be
created. The REPEAT clause allows a target reference variable to be moved to point
at the new field.
For the values clauses, the type, name, and value (or any subset of these) can be
specified by any expression that returns a suitable data type (INTEGER for type,
CHARACTER for name and any scalar type for value). An exception is thrown if
the value supplied for a type or name is NULL.
For the FROM clause, ″source″ must be a field reference. The new field’s type,
name, and value are taken from the source field, any child fields are detached (the
In all cases the new field might belong to a new parser of a type specified by the
optional DOMAIN clause. This expects to be the root field name. If no domain is
specified, the domain is of the same type as the parent field (for example MQMD,
XML, or MRM).
The PARSE clause can be used with one, three or six parameters. These can be any
expression that returns a non-NULL value of a suitable data type:
v The bitstream to be parsed (bit array, byte array, or character)
v The encoding of the bitstream (integer)
v The character code set identifier (CCSID) of the bitstream (integer)
v The message set of the bitstream (character) for MRM messages.
v The message type of the bitstream (character) for MRM messages.
v The message format of the bitstream (character) for MRM messages.
In this case the type, name and value of the new field are determined by the
parser to which the element belongs. Child fields are created as defined by the
given bitstream and the encoding rules built into the parser. The following list
shows the valid values for the encoding clause:
v MQENC_INTEGER_NORMAL (0x00000001L)
v MQENC_INTEGER_REVERSED (0x00000002L)
v MQENC_DECIMAL_NORMAL (0x00000010L)
v MQENC_DECIMAL_REVERSED (0x00000020L)
v MQENC_FLOAT_IEEE_NORMAL (0x00000100L)
v MQENC_FLOAT_IEEE_REVERSED (0x00000200L)
v MQENC_FLOAT_S390 (0x00000300L)
The values used for the CCSID clause follow the normal numbering system. For
example, 1200 = UCS-2, 1208 = UTF-8.
The following example creates a field with no name, type, or value as the first
child of ref1:
CREATE FIRSTCHILD OF ref1;
The following example creates a field using the specified type, name, and value:
CREATE NEXTSIBLING OF ref1 TYPE NameValue NAME ’Price’ VALUE 92.3;
The following example creates a field with a type and name, but no value, that is
added before the sibling indicated by the dynamic reference (ref1):
CREATE PREVIOUSSIBLING OF ref1 TYPE Name NAME ’Quantity’;
The following example creates a new field as the right sibling of the field pointed
to by the reference variable ″targetCursor″ having the same type and name as that
field. The statement then moves ″targetCursor″ to point at the new field:
CREATE NEXTSIBLING OF targetCursor AS targetCursor REPEAT;
CREATE FUNCTION
ParameterList:
Parameter
Parameter:
ParameterName DataType
ESQL functions, unlike ESQL procedures, can have input parameters only.
Functions are local in scope to the current node only. If you want to use the same
function from more that one node, you must define it within each node.
Example
The following example takes any given integer and returns it multiplied by two:
DECLARE X INTEGER;
SET X = 2;
DECLARE Y INTEGER;
SET Y = MultiplyByTwo(X);
CREATE PROCEDURE
ParameterList:
Parameter
Parameter:
IN ParameterName DataType
OUT
INOUT
RoutineBody:
Statement
EXTERNAL NAME ExternalRoutineName
ESQL procedures, unlike ESQL functions can have OUT and INOUT parameters in
addition to IN parameters. This allows them to return values to the caller, although
they have no RETURN value as such.
All procedures (internal or external) are local in scope to the current node only. In
order to use the same procedure from more than one node, you must define it in
each node.
This happens because nullChar was not assigned a value before the CALL.
WHILE LASTMOVE(cursor) DO
CALL navigate(cursor, answer);
MOVE cursor NEXTSIBLING;
END WHILE;
the procedure produces the following output, which has been manually formatted:
Reached Field... Type:16777232: Name:XML: Value :: Field has children... drilling down
Reached Field... Type:16777216: Name:Person: Value :: Field has children... drilling down
Reached Field... Type:16777216: Name:Name: Value :John Smith: Field has children... drilling down
Reached Field... Type:33554432: Name:: Value :John Smith: Listing siblings... Finished siblings... Popping up
Finished siblings... Popping up
Reached Field... Type:16777216: Name:Salary:Value :-1200: Field has children... drilling down
Reached Field... Type:50331648: Name:period: Value :monthly: Listing siblings... Finished siblings... Popping up
Reached Field... Type:50331648: Name:taxable: Value :yes: Listing siblings... Finished siblings... Popping up
Reached Field... Type:33554432: Name:: Value :-1200: Listing siblings... Finished siblings... Popping up
Finished siblings... Popping up
Finished siblings... Popping up
Finished siblings... Popping up
DECLARE
DECLARE statement
The DECLARE statement declares a scalar or reference variable that can be used to
store a temporary value. A variable cannot be used before it has been declared and
a variable name cannot be a reserved word.
Declared scalar variables have a NULL value until they are initialized; reference
variables are always initialized.
DELETE
DELETE statement
AS correlation_name WHERE search_condition
The DELETE statement deletes rows from a table in an external database based on
a search condition.
A correlation name is created that can be used inside the search condition to refer
to the values of columns in the table. This correlation name is either the name of
the table (without the data source qualifier) or the explicit qualifier specified.
Example
If you have a Database node that has been configured with a connection to a table
SHAREHOLDINGS. The following statement could be written to configure the
Database node:
DELETE FROM Database.SHAREHOLDINGS AS H
WHERE H.ACCOUNTNO = Body.AccountNumber;
This removes all rows from the SHAREHOLDINGS table where the ACCOUNTNO
field in the table is equal to the AccountNumber in the message.
DETACH
DETACH
DETACH dynamic_reference
The DETACH statement detaches a portion of a message tree without deleting it. This
portion can be reattached using the ATTACH statement.
EVAL
EVAL expression
EVAL ( SQL_character_value )
The EVAL statement takes a character value, interprets it as an SQL statement, and
executes it.
The very similar EVAL function (also described here) also takes a character value
but interprets it as an ESQL expression, which returns a value.
EVAL takes one parameter in the form of an expression, and evaluates this
expression and casts the resulting value to a character string if it is not one already.
The expression that is passed to EVAL must therefore be able to be represented as
a character string.
After this first stage evaluation is complete, the behavior of EVAL depends on
whether it is being used as a complete ESQL statement, or in place of an
expression that forms part of an ESQL statement:
v If it is a complete ESQL statement, the character string derived from the first
stage evaluation is executed as if it were an ESQL statement.
v If it is an expression that forms part of an ESQL statement, the character string is
evaluated as if it were an ESQL expression and EVAL returns the result.
In the following examples, A and B are integer scalar variables, and scalarVar1 and
OperatorAsString are character string scalar variables.
Variables declared within an EVAL statement do not exist outside that EVAL
statement. In this way EVAL is similar to a function, in which locally-declared
variables are local only and go out of scope when the function is exited.
The real power of EVAL is that it allows you to dynamically construct ESQL
statements or expressions. In the second and third valid examples above, the value
of scalarVar1 or operatorAsString can be set according to the value of an incoming
message field, or other dynamic value, thus allowing you to effectively control
what ESQL is executed without requiring a potentially lengthy IF THEN ladder.
Figure 7 on page 68 shows how to use EVAL to translate XML attributes to tags but
note that this is just an example. The task would be done more efficiently with
field references.
IF
IF
IF
The IF statement executes one set of statements or another based on the result of
evaluating a condition.
or:
IF condition THEN
controlled_statements 1
ELSE
controlled_statements 2
END IF;
INSERT
INSERT statement
VALUES( scalar_expression )
,
( column_name )
The optional column name list identifies a list of columns in the target table into
which values are to be inserted. Any columns not mentioned in the column name
list will have their default values inserted.
A runtime error might be generated if problems occur during the insert operation.
For example, the database table might have constraints defined that the insert
operation might violate. In these cases, an exception is thrown unless the node has
been configured to modify this behavior.
Example
The following example assumes that the dataSource property on the Database node
has been configured and that the database identified by that data source has a
table called "TABLE1" with columns A, B, and C.
the following INSERT statement inserts a new row into the table with the values
(1, 2, 3).
INSERT INTO Database.TABLE1(A, B, C) VALUES (Body.A.B, Body.A.C, Body.A.D);
MOVE
MOVE
The MOVE statement changes the field to which a reference variable identified by
″target″ points.
If a TO clause is present, it changes the target reference to point at the same entity
as that pointed to by ″source″. This can either be a message field or a declared
variable.
If a TYPE clause, NAME clause, or both are present, the target is again moved in
the direction specified (PREVIOUSSIBLING or NEXTSIBLING, or FIRSTCHILD or
LASTCHILD) but to a field with the given type, name, or both. If the specified
move cannot be made (that is, a field with the given type or name does not exist),
the target remains unchanged and the LASTMOVE function returns false. The
TYPE clause, NAME clause, or both clauses can contain any expression that
returns a value of a suitable data type (INTEGER for type and CHARACTER for
name). An exception is thrown if the value supplied is NULL.
Example
MOVE cursor FIRSTCHILD TYPE 0x01000000 NAME ’Field1’;
This example moves the reference variable ″cursor″ to the first child field of the
field to which ″cursor″ is currently pointing and that has the type 0x01000000 and
the name ’Field1’.
For further examples of moving a reference variable, see Figure 1 on page 28.
For more information about reference variables, see “Navigating a message tree
anonymously using dynamic references” on page 28.
PASSTHRU
Use PASSTHRU to write ESQL statements that:
v Bypass the WebSphere MQ Integrator Broker Broker Parser
v Go straight to the configured back-end database
v Execute a coded statement
PASSTHRU can be used as both a statement and a function.
If only one other parameter is passed, that parameter evaluates to one of the
following:
v A single scalar value. If this is the case, it is inserted into the first parameter
marker.
v A list of values. If this is the case, the list items are inserted in order into each of
the parameter markers within the string.
If two or more other parameters are passed, each parameter is bound to the
corresponding question mark in the statement string: that is, the first parameter is
bound to the first question mark, the second parameter is bound to the second
question mark, and so on.
Here are some examples that illustrate different ways of using the PASSTHRU
statement:
SET OutputRoot.XML.Result.Data[] =
PASSTHRU(’SELECT * FROM user1.stocktable’);
PASSTHRU(’DELETE FROM user2.AccountData WHERE AccountId =
?’, InputBody.Data.Account.Id);
SET OutputRoot.XML.Result.Data
= PASSTHRU(’SELECT AccountNum FROM user2.AccountData
WHERE AccountId = ?’, InputBody.Data.Account.Id);
SET OutputRoot.XML.Result.Data[]
= PASSTHRU(’SELECT AccountNum FROM user2.AccountData
WHERE AccountId IN (? , ? , ?)’,
InputBody.Data.Account.Id[]);
However, if a variable is first set and then referenced in the PASSTHRU statement,
quotes are not needed. For example:
SET myVar = ’SELECT * FROM user1.stocktable’;
SET OutputRoot.XML.Data[] = PASSTHRU(myVar);
Only the escape sequence described above is supported for the input parameters
of the PASSTHRU function in WebSphere MQ Integrator Broker.
v Using the SQL CALL facility, a database Stored Procedure can be called. This
procedure behaves as if a sequence of in-line SQL statements are being executed.
v Stored procedures can exist either:
– Individually (supported by both DB2 and Oracle). This would be written as
follows:
PASSTHRU(’{call proc_insert_comp(?,?)}’,InputBody.Test.Company,InputBody.Test.Price);
– As part of a collective that is accessed using a Package mechanism (supported
by Oracle). This would be written as follows:
PASSTHRU(’{call share_management.add_share(?,?)}’,
InputBody.Test.Company,InputBody.Test.Price);
v When writing Stored Procedures they can be either:
Noncommittal
The procedure logic does not take explicit commit and rollback action
(supported by both DB2 and Oracle).
If a message flow is either committed or rolled back, the database
operations are either committed or rolled back. This is consistent with
the behavior of the Database and Warehouse nodes that have a
transaction property of automatic.
Committal
The procedure logic contains explicit commit and rollback actions
(supported by Oracle).
Even if a message flow rollback occurs, the database operations are
committed. This is consistent with the behavior of the Database and
Warehouse nodes that have a transaction property of commit.
For further information about coordinated transactions, see the
WebSphere MQ Integrator Broker Administration Guide.
PROPAGATE
PROPAGATE
PROPAGATE
When used in a Compute node, the PROPAGATE statement finalizes the node’s
output message trees (that is, it fixes their header chains) and propagates to the
downstream nodes within the message flow. The PROPAGATE statement then
clears the output message trees and reclaims the memory ready for further use.
The Environment tree is always propagated. The Local Environment, message, and
exception list trees, which are propagated can be either the input or output trees
under the control of the ″Compute Mode″ property as normal. However, it is the
output trees that are finalized and cleared, regardless of which ones are
propagated.
Although it is legal, you are not recommended to use the PROPAGATE statement
within Filter nodes. It currently has no effect within these nodes but this might not
be true of future releases.
The ESQL in this example produces three messages on the OUT terminal using the
sample message in “Message used in this book” on page 147:
ESQL:
DECLARE i INTEGER;
Set i = 1;
WHILE i <= CARDINALITY(InputRoot.XML.Invoice.Purchases."Item"[]) DO
SET OutputRoot = InputRoot;
SET OutputRoot.XML = NULL;
SET OutputRoot.XML.BookSold."Item" = InputRoot.XML.Invoice.Purchases."Item"[i];
PROPAGATE;
SET i = i+1;
END WHILE;
RETURN FALSE;
<BookSold>
<Item>
<Title Category="Computer" Form="Paperback" Edition="2">The XML Companion </Title>
<ISBN>0201674866</ISBN>
<Author>Neil Bradley</Author>
<Publisher>Addison-Wesley</Publisher>
<PublishDate>October 1999</PublishDate>
<UnitPrice>27.95</UnitPrice>
<Quantity>2</Quantity>
</Item>
</BookSold>
<BookSold>
<Item>
<Title Category="Computer" Form="Paperback" Edition="2">A Complete Guide to DB2 Universal Database</Title>
<ISBN>1558604820</ISBN>
<Author>Don Chamberlin</Author>
<Publisher>Morgan Kaufmann Publishers</Publisher>
<PublishDate>April 1998</PublishDate>
<UnitPrice>42.95</UnitPrice>
<Quantity>1</Quantity>
</Item>
</BookSold>
<BookSold>
<Item>
<Title Category="Computer" Form="Hardcover" Edition="0">JAVA 2 Developers Handbook</Title>
<ISBN>0782121799</ISBN>
<Author>Phillip Heller, Simon Roberts </Author>
<Publisher>Sybex, Inc.</Publisher>
<PublishDate>September 1998</PublishDate> <UnitPrice>59.99</UnitPrice>
<Quantity>1</Quantity>
</Item>
</BookSold>
RETURN
RETURN
RETURN
expression
When used in a function, the RETURN statement causes execution of that function
to cease and control to be returned to the calling expression. The ″expression″
(which must be present) is evaluated and acts as the return value of the function. It
is an error for a function to return by running off the list of statements. It is also an
error for the data type of the returned value to be different to that in the function’s
declaration.
When used in a Filter, Compute, or Database node’s mainline code, the RETURN
statement causes execution of the node’s ESQL to cease and for control to be
passed to the next node. In these cases, if ″expression″ is present, it must evaluate
to a BOOLEAN value. If ″expression″ is not present, a Filter node assumes a value
of UNKNOWN and propagates to its unknown terminal, but Compute and
Database nodes propagate to their out terminals.
The following table describes the differences between the RETURN statement
when used in the Compute, Filter, and Database nodes.
Table 6. Differences in the use of RETURN with the Compute, Filter, and Database nodes
Return value Result
Compute node:
RETURN (TRUE) Propagate message to OUT
terminal.
(FALSE) Does not propagate.
(UNKNOWN) Does not propagate.
RETURN; – Propagate message to OUT
terminal.
Filter node:
RETURN TRUE Propagate message to TRUE
terminal.
FALSE Propagate message to FALSE
terminal.
UNKNOWN Propagate message to
UNKNOWN terminal.
RETURN; Propagate message to
FAILURE terminal.
This statement is especially useful when used in Filter nodes because it allows the
filter decision to be made using the full power of ESQL statements, rather than just
an expression.
-- Initialize values --
SET a = 1;
SET NumItems = 0;
SET PriceTotal = 0.0;
If the average price of items is greater than 42, TRUE is returned; otherwise FALSE
is returned. Thus, a Filter node could route messages describing expensive items
down a different path to messages describing inexpensive items.
See Figure 8 on page 77 for an example of RETURN FALSE to prevent the implicit
PROPAGATE at the end of processing in a Compute node.
SET
SET
The SET statement evaluates ″sourceexpression″ and assigns the resulting value to
the entity identified by ″target″. The target can either be a declared variable or a
field in a message tree that can be modified, for example Environment,
InputLocalEnvironment, OutputLocalEnvironment, OutputRoot, or
OutputExceptionList.
If the target is a declared variable, the TYPE, NAME and VALUE clauses cannot be
present and the source expression must return a scalar value of a type that is the
same as, or is convertible to, the declared data type of the variable. NULL values
are handled in exactly the same way as any other value.
If the target is a field, it is navigated to (creating the fields if necessary) and its
value is set according to a set of rules, which depend on the presence or absence of
TYPE, NAME, or VALUE clauses, and the data type returned by source expression.
If array indices are used in the field reference, only one instance of a particular
field can be created. If you write a SET statement starting:
SET OutputRoot.XML.Message.Structure[2].Field = ...
at least one instance of "Structure" must already exist in the message. That is, the
only fields in the tree that are created are ones on a direct path from the root to the
field identified by the field reference.
If a TYPE clause is present, the type of the target field is changed to that returned
by source expression. An exception is thrown if the result is not scalar, is not of
type INTEGER, or is NULL.
If a NAME clause is present, the name of the target field is changed to that
returned by source expression. An exception is thrown if the result is not scalar, is
not of type CHARACTER, or is NULL.
If a VALUE clause is present, the value of the target field is changed to that
returned by source expression. An exception is thrown if the result is not scalar.
If you do not use TYPE, NAME, or VALUE clauses (the most common case) the
behavior depends on whether source expression evaluates to a scalar, a field
reference, or a list (various kinds) :
v If it is a scalar, the value of the target field is changed to that returned by source
expression. The exception to this is if the result is NULL, the target field is
detached.
v If it is a field reference, the target field’s value is taken from the source field, any
child fields are detached and the new field is given copies of the source field’s
SET statements are particularly useful in Compute nodes that make a modification
to a message, either changing a field, or adding a new field to the original
message. SET statements are also useful in Filter and Database nodes to set
declared variables or the fields in the Environment tree or Local Environment trees.
You can use statements such as these in a Compute node that modifies a message:
SET OutputRoot = InputRoot;
SET OutputRoot.XML.Order.Name = UPPER(InputRoot.XML.Order.Name);
This example simply puts one field in the message into uppercase. The first
statement constructs an output message that is a complete copy of the input
message. The second statement sets the value of the "Order.Name" field (which it
is assumed the message flow writer knows will exist in the input message) to a
new value, as defined by the expression on the right.
If the Order.Name field hadn't existed in the original input message, it won't exist
in the output message as generated by the first statement. The expression on the
right of the second statement will return NULL (because the field referenced inside
the UPPER function call does not exist). Assigning the NULL value to a field has
the effect of deleting it if it already exists, and so the effect is that the second
statement has no effect.
If you wish to assign a NULL value to a field without deleting it, use a statement
like this:
SET OutputRoot.XML.Order.Name VALUE = NULL;
THROW
THROW EXCEPTION
USER SEVERITY expression CATALOG catalog name
MESSAGE message number ,
VALUES ( expression )
SEVERITY is an optional clause that determines the severity associated with the
exception. The clause can contain any expression which returns a non-NULL,
integer value. If the clause is not provided it defaults to 1.
CATALOG is an optional clause and if this value is not provided it defaults to the
WebSphere MQ Integrator Broker version catalog.
MESSAGE is an optional clause and if this value is not provided it defaults to the
first message number of the block of messages provided for the use of THROW
statements in WebSphere MQ Integrator Broker catalog (2949). If you decide to
enter a message number in the THROW statement, message numbers 2949 - 2999
are available for you to use. Alternatively, you can generate your own catalog.
The optional VALUES field is to enable you to insert data into your message. You
can insert any number of pieces of information, but note that the messages
supplied (2949 - 2999) cater for 8 inserts only. For information about SQLSTATE
and SQLCODE, refer to “Database state functions” on page 101.
Here are some examples of how you might use a THROW statement:
v THROW USER EXCEPTION;
You can use the THROW statement at any time: you do not have to use database
state indicators.
For more information about how to throw an exception, and details of SQLSTATE,
SQLCODE, SQLNATIVEERROR, and SQLERRORTEXT, see “Database state functions” on
page 101.
UPDATE
The UPDATE statement updates the values of specified rows and columns in a
table in an external database.
UPDATE statement
SET column_name=expression
WHERE search_condition
Examples
The following example updates the PRICE column of the row in the
STOCKPRICES table whose COMPANY column matched the value given in the
Company field in the message that the Database node is processing.
UPDATE Database.StockPrices AS SP
SET PRICE = Body.Message.StockPrice
WHERE SP.COMPANY =Body.Message.Company
In the following example, the "INV.QUANTITY" in the right hand side of the
assignment refers to the previous value of the column before any updates have
taken place:
UPDATE Database.INVENTORY AS INV
SET QUANTITY = INV.QUANTITY - Body.Message.QuantitySold
WHERE INV.ITEMNUMBER = Body.Message.ItemNumber
Compare the syntax to the way you assign to multiple fields in a Compute node:
SET field = expression;
The form of the assignment; the column on the left of the assignment must be a
single identifier. It must not be qualified with a table name or correlation name. In
contrast, any column references to the right of the assignment must be qualified
with a table name or correlation name.
WHILE
WHILE
The WHILE statement takes the following form (note the position of the
semicolons):
WHILE predicate DO
controlled statements
END WHILE;
For example:
DECLARE I INTEGER;
SET I = 1;
WHILE I <= 10 DO
SET I = I + 1;
END WHILE;
The same caveats apply to using the WHILE statement as apply in any language,
that is, it is up to you to ensure that the loop will terminate. UNKNOWN and
FALSE are treated in the same way: therefore if the control predicate evaluates to
UNKNOWN the loop terminates.
Most of the functions described here impose restrictions on the data types of the
arguments that can be passed to the function. If the values passed to the functions
do not match the required data types, errors are generated at node configuration
time whenever possible. Otherwise runtime errors are generated when the function
is evaluated.
The functions described here are divided into the following categories:
v “Numeric functions” on page 90
v “String manipulation functions”
v “Datetime functions” on page 94
v “Field functions” on page 96
v “Database state functions” on page 101
v Miscellaneous functions:
– “CARDINALITY” on page 96
– “CASE” on page 97
– “COALESCE” on page 102
– “LASTMOVE” on page 97
– “NULLIF” on page 102
– “PASSTHRU” on page 102
– “SAMEFIELD” on page 97
– “SELECT” on page 100
– “UUIDASBLOB” on page 102
– “UUIDASCHAR” on page 103
In these descriptions, the term ’singleton’ is used to refer to a single part (bit, byte,
or character) within a string of that type.
LENGTH
LENGTH(source_string)
The LENGTH function returns an integer value giving the number of singletons in
source_string. If the source_string is NULL, the result is the NULL value.
Examples:
LENGTH('Hello World!'); returns 12.
LENGTH(''); returns 0.
The LOWER and LCASE functions both return a new character string, which is
identical to source_string, except that it has all uppercase letters replaced with the
corresponding lowercase letters. If source_string is NULL, the result is NULL.
For example:
LOWER(’Mr Smith’) returns ’mr smith’
LOWER(’22 Railway Cuttings’) returns ’22 railway cuttings’
LCASE(’ABCD’) returns ’abcd’
LTRIM
LTRIM(source_string)
LTRIM returns a string value of the same data type and content as source_string
but with any leading default singletons removed.
character ’ ’ (space)
byte X’00’
bit B’0’
OVERLAY
The OVERLAY function returns a new string of the same type as the source and is
identical to source string, except that a given substring in the string, starting from
the specified numeric position and of the given length has been replaced
by source_string2. When the length of the substring is zero, nothing is replaced.
OVERLAY(source_string PLACING source_string2 FROM start_position )
OVERLAY(source_string PLACING source_string2 FROM start_position FOR string_length)
If any of the parameters are NULL, the result is a NULL value of the same data
type as source_string. If string_length is not specified, string_length is assumed
to be equal to LENGTH(source_string2).
The POSITION function returns an integer that gives the position of the first
occurrence of one string (search_string) in a second string (source_string). A
position of 1 corresponds to the first character of source_string.
If the value of search_string has a length of zero, the result is one. If the
search_string cannot be found, the result is 0. If any of the parameters to the
POSITION function are NULL, the result is NULL.
For example:
POSITION(’Village’ IN ’Hursley Village’); returns 9
POSITION(’Town’ IN ’Hursley Village’); returns 0
RTRIM
RTRIM(source_string)
RTRIM returns a string value of the same data type and content as source_string
but with any trailing default singletons removed.
character ’ ’ (space)
byte X’00’
bit B’0’
SUBSTRING
SUBSTRING(source_string FROM start_position)
SUBSTRING(source_string FROM start_position FOR string_length)
The SUBSTRING function returns a new string of the same type as the source
string containing one contiguous run of characters extracted from the
source_string as specified by the start_position and length parameters.
If any of the parameters are NULL, the result is a NULL value of the same type as
the source_string. (Note this is not a zero length string).
For example:
SUBSTRING('Hello World!' FROM 7 FOR 4) returns 'Worl'
TRIM
TRIM( trim_specification trim_singleton FROM source_string )
TRIM( trim_specification FROM source_string )
TRIM( trim_singleton FROM source_string )
TRIM( source_string )
The TRIM function returns a new string of the same type source_string, in which
the trim_specification singletons have been removed.
character ’ ’ (space)
byte X’00’
bit B’0’
TRIM returns a string value of the same data type and content as source_string
but with any leading or trailing singletons that are equal to trim_singleton
removed (depending on the value of trim_specification). If any of the parameters
are NULL, the result is a NULL value of the same type as source_string.
The FROM keyword is not required, and is in fact prohibited if neither a trim
specification, for example LEADING or TRAILING, nor a trim singleton, is
specified.
UPPER, UCASE
UPPER(source_string)
UCASE(source_string)
The UPPER and UCASE functions both return a new character string, which is
identical to source string, except that it has all lowercase letters replaced with the
corresponding uppercase letters. If the source string is NULL, the result is NULL.
For example:
UPPER(’ABCD’) returns ’ABCD’
UCASE(’abc123) returns ’ABC123’
Numeric functions
ABS
ABS(source_number)
ABSVAL(source_number)
The ABS function returns the absolute value of the source number, that is, a
number with the same magnitude as the source but without a sign. The parameter
must be a numeric value. If the parameter to the ABS function is NULL, the result
is NULL.
For example:
ABS( -3.7 ) returns 3.7
ABS( 3.7 ) returns 3.7
ABS( 1024 ) returns 1024
The BITAND function takes two or more integer values and returns the result of
performing the bitwise AND on the binary representation of the numbers. If any of
the parameters are NULL, the result is NULL.
For example:
BITAND(12, 7) returns 4
1100 12
AND 0111 7
_________
0100 4
BITNOT
BITNOT(source_integer)
The BITNOT function takes an integer value and returns the result of performing
the bitwise complement on the binary representation of the number. If the
parameter is NULL, the result is NULL.
For example:
BITNOT(7) returns -8
00...0111 7
NOT
_________
11...1000 -8
BITOR
BITOR(source_integer_1, source_integer_2, ...)
The BITOR function takes two or more integer values and returns the result of
performing the bitwise OR on the binary representation of the numbers. If any of
the parameters are NULL, the result is NULL.
For example:
BITOR(12, 7) returns 15
1100 12
OR 0111 7
_________
1111 15
The BITXOR function takes two or more integer values and returns the result of
performing the bitwise XOR on the binary representation of the numbers. If any of
the parameters are NULL, the result is NULL.
For example:
BITXOR(12, 7) returns 11
1100 12
XOR 0111 7
_________
1011 11
CEIL
CEIL(source_number)
CEILING(source_number)
The CEIL function returns the smallest integer value greater than or equal to
source_number. The parameter can be any numeric data type. If the parameter to
the CEIL function is NULL, the result is a NULL value of the same type as the
parameter.
For example:
CEIL(1) returns 1
CEIL(1.2) returns 2.0
CEIL(-1.2) returns -1.0
The FLOOR function returns the largest integer value less than or equal to
source_number. The parameter can be any numeric data type. If the parameter is
NULL, the result is a NULL value of the same type as the parameter.
For example:
FLOOR(1) returns 1
FLOOR(1.2) returns 1.0
FLOOR(-1.2) returns -2.0
MOD
MOD(divided, divider)
The MOD function returns the remainder when the first parameter is divided by
the second parameter. The result is negative only if the first parameter is negative.
Parameters must be integers. The function returns an integer. If any parameter is
NULL, the result is NULL.
For example:
MOD(7, 3) returns 1
MOD(-7, 3) returns -1
MOD(7, -3) returns 1
MOD(6, 3) returns 0
ROUND
ROUND(source_number, precision)
If precision is a positive number, the result of the ROUND function is the source
number rounded to precision places right of the decimal point. If precision is
negative, the result is source_number rounded to the absolute value of precision
places to the left of the decimal point.
For example:
ROUND(27.75, 2) returns 27.75
ROUND(27.75, 1) returns 27.8
ROUND(27.75, 0) returns 28.0
ROUND(27.75, -1) returns 30.0
SQRT
SQRT(source_number)
The SQRT function returns the square root of source_number. The parameter can be
any built-in numeric data type. The result is a FLOAT. If the parameter is NULL,
the result is NULL.
TRUNCATE
TRUNCATE(source_number, precision)
source_number can be any built-in numeric data type. precision must evaluate to
an INTEGER. The result is of the same data type as source_number. If any
parameter is NULL, the result is NULL.
For example:
TRUNCATE(27.75, 2) returns 27.75
TRUNCATE(27.75, 1) returns 27.7
TRUNCATE(27.75, 0) returns 27.0
TRUNCATE(27.75, -1) returns 20.0
Datetime functions
In addition to the functions described here, you can use arithmetic operators to
perform various natural calculations on datetime values. For example, you can use
the – (minus) operator to calculate the difference between two dates as an interval,
or you can add an interval to a timestamp. These are described in “Using
arithmetic operators with datetime functions” on page 11.
EXTRACT
EXTRACT(component FROM datetime_value)
The EXTRACT function extracts individual fields from datetime values and
intervals.
component can be any of the keywords YEAR, MONTH, DAY, HOUR, MINUTE,
and SECOND in the EXTRACT function, but you can only extract a field that is
present in the datetime_value value. Either a parse-time or a runtime error is
generated if the requested field does not exist within the particular data type. For
example:
EXTRACT(YEAR FROM CURRENT_DATE)
EXTRACT(HOUR FROM LOCAL_TIMEZONE)
CURRENT_DATE
CURRENT_DATE
The CURRENT_DATE function returns a DATE value representing the current date
in local time.
Note that, as with all SQL functions that take no parameters, no parentheses are
required or accepted. All calls to CURRENT_DATE within the processing of one
node are guaranteed to return the same value.
The CURRENT_TIME function returns a TIME value representing the current local
time.
Note that, as with all SQL functions that take no parameters, no parentheses are
required or accepted. All calls to CURRENT_TIME within the processing of one
node are guaranteed to return the same value.
CURRENT_TIMESTAMP
CURRENT_TIMESTAMP
Note that, as with all SQL functions that take no parameters, no parentheses are
required or accepted. All calls to CURRENT_TIMESTAMP within the processing of
one node are guaranteed to return the same value.
CURRENT_GMTDATE
CURRENT_GMTDATE
Note that, as with all SQL functions that take no parameters, no parentheses are
required or accepted. All calls to CURRENT_GMTDATE within the processing of
one node are guaranteed to return the same value.
CURRENT_GMTTIME
CURRENT_GMTTIME
Note that, as with all SQL functions that take no parameters, no parentheses are
required or accepted. All calls to CURRENT_GMTTIME within the processing of
one node are guaranteed to return the same value.
CURRENT_GMTTIMESTAMP
CURRENT_GMTTIMESTAMP
Note that, as with all SQL functions that take no parameters, no parentheses are
required or accepted. All calls to CURRENT_GMTTIMESTAMP within the
processing of one node are guaranteed to return the same value.
Note that, as with all SQL functions that take no parameters, no parentheses are
required or accepted. The value returned is an interval in hours and minutes
representing the displacement of the current time zone from Greenwich Mean
Time. The sign of the interval is such that a local time could be converted to a time
in GMT by subtracting the result of the LOCAL_TIMEZONE function.
Field functions
BITSTREAM
BITSTREAM(field_reference)
The BITSTREAM function returns a value of type BLOB representing the bitstream
described by the given field and its children. For incoming messages, the
appropriate portion of the incoming bitstream is used. For messages constructed by
Compute nodes, the following algorithm is used to establish the ENCODING,
CCSID, message set, message type, and message format:
v If the addressed field has a previous sibling and this sibling is the root of a
subtree belonging to a parser capable of providing an ENCODING and CCSID,
these values are obtained and used in the generation of the requested bitstream.
Otherwise the broker’s default ENCODING and CCSID (that is, those of its
queue manager) are used.
v Similarly, if the addressed field has a previous sibling and this sibling is the root
of a subtree belonging to a parser capable of providing a message set, message
type, and message format, these values are obtained and used in the generation
of the requested bitstream. Otherwise, the zero length strings are used.
This function is typically used in message warehouse scenarios, where the bit
stream of a message needs to be stored in a database. The function returns the bit
stream of the physical portion of the incoming message, identified by the
parameter. In some cases it does not return the bit stream representing the actual
field identified. For example the following two calls would return the same value:
BITSTREAM(Root.MQMD);
BITSTREAM(Root.MQMD.UserIdentifier);
CARDINALITY
CARDINALITY(field_reference [])
For more information about the CARDINALITY function, see page 26.
FIELDNAME
FIELDNAME(source_field_reference)
FIELDTYPE
FIELDTYPE(source_field_reference)
LASTMOVE
LASTMOVE(source_dynamic_reference)
The LASTMOVE function returns a boolean value indicating whether the last
MOVE function applied to source_dynamic_reference was successful (TRUE) or
not (FALSE).
For information about dynamic references, including an example of how to use this
function, see “Navigating a message tree anonymously using dynamic references”
on page 28.
SAMEFIELD
SAMEFIELD(source_field_reference1, source_field_reference2)
The SAMEFIELD function returns a BOOLEAN value indicating whether two field
references point to the same target. If they do, SAMEFIELD returns TRUE,
otherwise SAMEFIELD returns FALSE.
Complex functions
CASE
The CASE function returns a value depending on a set of rules defined in WHEN
clauses.
There are two forms, the simple form and the searched forms.
ELSE NULL
CASE searched-when-clause END
simple-when-clause ELSE result-expression
simple-when-clause:
searched-when-clause:
In the simple form, source_value is compared with each test_value until a match
is found. The result of the CASE function is the value of the corresponding
result_value. The data type of source_value must therefore be comparable to the
data type of each test_value.
The CASE function must have at least one WHEN. The ELSE is optional. The
default ELSE expression is NULL. A CASE expression is delimited by END. Note
that unlike many languages there is no requirement for the test values to be literal
values.
The searched-when clause version is similar but has the additional flexibility of
allowing a number of different values to be tested rather than just one value being
tested against a number of values.
The following example shows a CASE function with simple WHEN clause:
CASE CurrentMonth
WHEN ’01’ THEN ’January’
WHEN ’02’ THEN ’February’
WHEN ’03’ THEN ’March’
WHEN ’04’ THEN ’April’
WHEN ’05’ THEN ’May’
WHEN ’06’ THEN ’June’
ELSE ’Second half of year’
END
The following example shows a CASE function with a searched WHEN clause:
SET Month = SUBSTRING(InputBody.Invoice.InvoiceDate FROM 6 FOR 2)
CASE
WHEN Month = ’01’ THEN ’January’
WHEN Month = ’02’ THEN ’February’
WHEN Month = ’03’ THEN ’March’
WHEN Month = ’04’ THEN ’April’
WHEN Month = ’05’ THEN ’May’
WHEN Month = ’06’ THEN ’June’
ELSE ’Second half of year’
END
CAST function
)
CCSID ccsid_expression ENCODING encoding_expression
The CAST function transforms the value of one data type into another data type.
See Chapter 7, “Transforming data from one data type to another (CAST)” on
page 111 for more information about using the CAST function. For a description of
precision, scale, and interval qualifier, see “Numbers” on page 6 and
“INTERVAL” on page 8.
SELECT
)
WHERE Condition
SelectClause:
Expression
AS Target
ITEM Expression
ColumnFunction ( Expression )
(1)
*
ColumnFunction:
COUNT
MAX
MIN
SUM
Notes:
1 Valid with the COUNT function only.
where:
v ″Source″ is a reference to a field, a field array, or a database table
v ″Alias″ is a temporary variable name
v ″Condition″ is any boolean expression
v ″Target″ is a relative path
The SELECT function combines, filters, and reformats complex message and
database data. It is the normal method of message transformation. ESQL SELECT
can be used to:
v Comprehensively reformat messages
v Access database tables
v Make an output array that is a subset of an input array
v Make an output array that contains just the values of an input array
v Count the number of entries in an array
v Select the minimum or maximum value from a number of entries in an array
ESQL SELECT differs from database SQL SELECT in the following ways:
v ESQL can produce tree structured result data but SQL cannot
v ESQL can accept arrays in SELECT clauses but SQL cannot
v ESQL has THE and ITEM but SQL does not
v ESQL has no SELECT ALL
v ESQL has no SELECT DISTINCT
v ESQL has no GROUP BY or HAVING
v ESQL has no AVG column function
For information about using the SELECT function, see Chapter 8, “Using the
SELECT function” on page 125.
The following four database state functions can be used to return the SQLCODE,
SQLSTATE, SQLNATIVEERROR, and SQLERRORTEXT of the DBMS call made in
ESQL. These can be used in conditional statements in current node’s ESQL to
handle possible errors. This means that the exceptions cannot be thrown in these
situations and the THROW statement can be used to throw an exception as before
if a certain SQL return code is not expected. See “THROW” on page 83 for a
description of THROW.
This section describes the four functions that can used to capture database return
codes issued as a result of making a database call:
SQLCODE
Returns an INTEGER data type with a default value of 0 (zero).
SQLERRORTEXT
Returns a CHARACTER data type with a default value of ’’ (empty string).
SQLNATIVEERROR
Returns an INTEGER data type with a default value of 0 (zero).
SQLSTATE
Returns a 5 character data type of CHARACTER with a default value of
’00000’ (five zeros as a string).
The following example shows how you might use these four functions:
--Use the THROW statement to back out the database and issue a user exception--
THROW USER EXCEPTION MESSAGE 2950 VALUES
( ’The SQL State’ , SQLState1 , SQLCode1 , SQLNativeError1 , SQLErrorText1 );
Miscellaneous functions
You can also use the following functions:
COALESCE
COALESCE(source_value1, source_value2...)
The COALESCE function returns the first argument that is not NULL. The
arguments are evaluated in the order in which they are specified, and the result of
the function is the first argument that is not NULL. The result is NULL only if all
the arguments are NULL. The arguments must be compatible.
The COALESCE function can be used to provide a default value for the value of a
field, which might not exist in a message. For example, the expression:
COALESCE(Body.Salary, 0)
would return the value of the Salary field in the message if it existed, or 0 (zero) if
that field did not exist.
NULLIF
The NULLIF function returns a NULL value if the arguments are equal; otherwise,
it returns the value of the first argument. The arguments must be comparable. The
result of using NULLIF(e1,e2) is the same as using the expression:
CASE WHEN e1=e2 THEN NULL ELSE e1 END
Note that when e1=e2 evaluates to unknown (because one or both arguments is
NULL), CASE expressions consider this not true. Therefore, in this situation,
NULLIF returns the value of the first argument.
PASSTHRU
The PASSTHRU statement is identical to the PASSTHRU function, except that it
returns the value returned by the extended SQL. It is described in “PASSTHRU” on
page 73.
UUIDASBLOB
UUIDASBLOB
UUIDASBLOB(source_character_uuid)
UUIDASCHAR
UUIDASCHAR
UUIDASCHAR(source_blob_uuid)
The first form of the UUIDASCHAR function creates a new universally unique
identifier (UUID) as a CHARACTER value.
The second form converts an existing BLOB UUID to the character form.
ROW constructor
Example 1
SET OutputRoot.XML.Data = ROW(’granary’ AS bread,
’riesling’ AS wine,
’stilton’ AS cheese);
produces:
<Data>
<bread>granary</bread>
<wine>riesling</wine>
<cheese>stilton</cheese>
</Data>
Example 2
Given the following XML input message body:
<Proof>
<beer>5</beer>
<wine>12</wine>
<gin>40</gin>
</Proof>
Because the values in this case are derived from field references, which already
have names, it is not necessary to explicitly provide a name for each element of the
row, but you might choose to do so.
In the case of a LIST, there is no explicit name associated with each value. The
values are assigned in sequence to elements of the message field array specified as
the target of the assignment. Note that curly braces rather than parentheses are
used to surround the LIST items.
Example 2
Given the following XML input message body:
<Data>
<Field>Keats</Field>
<Field>Shelley</Field>
<Field>Wordsworth</Field>
<Field>Tennyson</Field>
<Field>Byron</Field>
</Data>
The previous members of the Data.Field[] array have been discarded. Assigning a
new list of values to an already existing message field array causes all the elements
in the existing array to be removed before the new ones are assigned.
A LIST cannot validly be a member of a ROW. Only named scalar values can be
members of a ROW.
Example 1
IF ROW(InputBody.Data.*[1],InputBody.Data.*[2]) =
ROW(’Raf’ AS Name,’25’ AS Age) THEN ...
IF LIST{InputBody.Data.Name, InputBody.Data.Age} = LIST{’Raf’,’25’} THEN ...
The following XML input message body would cause both the IF expressions in
both of the above statements to evaluate to TRUE:
<Data>
<Name>Raf</Name>
<Age>25</Age>
</Data>
In the comparison between ROWs, both the name and the value of each element
are compared, whereas in the comparison between LISTs only the value of each
element is compared. In both cases the cardinality and sequential order of the LIST
or ROW operands being compared must be equal in order for the two operands to
be equal. In other words, all the following are false because either the sequential
order or the cardinality of the operands being compared do not match:
ROW(’alpha’ AS A, ’beta’ AS B) =
ROW(’alpha’ AS A, ’beta’ AS B, ’delta’ AS D)
ROW(’alpha’ AS A, ’beta’ AS B) =
ROW(’beta’ AS B,’alpha’ AS A)
LIST{1,2,3} = LIST{1,2,3,4}
LIST{3,2,1} = LIST{1,2,3}
Example 2
Consider the following ESQL:
IF InputBody.Places =
ROW(’Ken’ AS first, ’Bob’ AS second, ’Kate’ AS third) THEN ...
The following XML input message body would cause the above IF expression to
evaluate to TRUE:
<Places>
<first>Ken</first>
<second>Bob</second>
<third>Kate</third>
</Places>
which compares the value of the FirstDraw and SecondDraw fields, not the names
and values of each of FirstDraw and SecondDraw’s child fields constructed as a
ROW. Thus an XML input message body such as:
<Lottery>
<FirstDraw>wednesday
<ball1>32</ball1>
<ball2>12</ball2>
</FirstDraw>
<SecondDraw>saturday
<ball1>32</ball1>
<ball2>12</ball2>
</SecondDraw>
</Lottery>
would not result in the above IF expression being evaluated as TRUE, because the
values ’wednesday’ and ’saturday’ are being compared, not the names and values
of the ball fields.
Example 3
Consider the following ESQL:
IF InputBody.Cities.City[] = LIST{’Athens’,’Sparta’,’Thebes’} THEN ...
The following XML input message body would cause the IF expression to evaluate
to TRUE:
<Cities>
<City>Athens</City>
<City>Sparta</City>
<City>Thebes</City>
</Cities>
Two message field arrays can be compared together in this way, for example:
IF InputBody.Cities.Mediaeval.City[] =
InputBody.Cities.Modern.City[] THEN ...
IF InputBody.Cities.Mediaeval.(XML.Element)[] =
InputBody.Cities.Modern.(XML.Element)[] THEN ...
The following XML input message body would cause the IF expression of the first
and third of the statements above to evaluate to TRUE:
<Cities>
<Mediaeval>1350
<City>London</City>
<City>Paris</City>
</Mediaeval>
<Modern>1990
<City>London</City>
<City>Paris</City>
</Modern>
</Cities>
Note that the IF expression of the third statement above would evaluate to TRUE
with an XML input message body such as:
<Cities>
<Mediaeval>1350
<Location>London</Location>
<Location>Paris</Location>
</Mediaeval>
<Modern>1990
<City>London</City>
<City>Paris</City>
</Modern>
</Cities>
LISTs are composed of unnamed values. It is the values of the child fields of
Mediaeval and Modern that are compared, not their names.
For example, CAST functions are used often when dealing with generic XML
messages: all fields in a generic XML message have character values, therefore to
perform arithmetic calculations or datetime comparisons (for example), the string
value of the field must first be cast into a value of the appropriate type. If you
wanted to filter on trade messages where the date of the trade was today, you
could write the following expression:
CAST(Body.Trade.Date AS DATE) = CURRENT_DATE
In this example, the string value of the Date field in the message is converted into
a date value, and compared with the current date.
CAST function
)
CCSID ccsid_expression ENCODING encoding_expression
Not all conversions are supported, see “Supported casts” for a full list of
supported conversions.
CCSID
The CCSID clause allows a code page to be specified. It is used for certain
conversions only.
The CCSID expression can be any expression evaluating to a value of type INT. It
is interpreted according to normal WebSphere MQ Integrator Broker rules for
CCSIDs.
ENCODING
The ENCODING clause allows the encoding to be specified. It is used for certain
conversions only. The ENCODING value can be any expression evaluating to a
value of type INT. It is interpreted according to normal WebSphere MQ Integrator
Broker rules for encoding. Valid values are:
v MQENC_NATIVE (0x00000222L)
v MQENC_INTEGER_NORMAL (0x00000001L)
v MQENC_INTEGER_REVERSED (0x00000002L)
v MQENC_DECIMAL_NORMAL (0x00000010L)
v MQENC_DECIMAL_REVERSED (0x00000020L)
v MQENC_FLOAT_IEEE_NORMAL (0x00000100L)
v MQENC_FLOAT_IEEE_REVERSED (0x00000200L)
v MQENC_FLOAT_S390 (0x00000300L)
Supported casts
A CAST is not supported between every combination of data types. Those that are
supported are listed below, along with the effect of the CAST.
Table 7. Supported CASTs
Source data type Target data type Effect
CHARACTER BOOLEAN The character string is interpreted in the same way that a boolean
literal is interpreted. That is, the character string must be one of the
strings TRUE, FALSE, UNKNOWN (in any case combination).
CHARACTER FLOAT The character string is interpreted in the same way as a floating point
literal is interpreted.
CHARACTER DATE The character string must conform to the rules for a date literal or for
the date string. That is, the character string can be either DATE
'2002-10-05' or 2002-10-05.
This function might report conversion errors if the given code page or
encoding are unknown or the given data contains Unicode characters
that cannot be converted to the given code page.
Chapter 7. Transforming data from one data type to another (CAST) 113
Supported casts
Table 7. Supported CASTs (continued)
Source data type Target data type Effect
CHARACTER BLOB The character string must conform to the rules for a binary string
literal or to the rules for the contents of the binary string literal. That
is, the character string can be of the form X'hhhhhh' or hhhhhh (where
'h' can be any hexadecimal digit characters).
This function might report conversion errors if the given code page or
encoding are unknown or the given data contains Unicode characters
that cannot be converted to the given code page.
BOOLEAN CHARACTER If the source value is TRUE, the result is the character string 'TRUE'. If
the source value is FALSE, the result is the character string 'FALSE'.
Because the UNKNOWN boolean value is the same as the NULL
value for booleans, the result is the NULL character string value if the
source value is UNKNOWN.
FLOAT CHARACTER The result is the shortest character string that conforms to the
definition of an approximate numeric literal and whose mantissa
consists of a single digit that is not '0', followed by a period and an
unsigned integer, and whose interpreted value is the value of the float.
DATE CHARACTER The result is a string conforming to the definition of a date literal,
whose interpreted value is the same as the source date value.
For example:
CAST(DATE '2002-10-05' AS CHAR)
would return:
DATE '2002-10-05'
DECIMAL CHARACTER The result is the shortest character string that conforms to the
definition of an exact numeric literal and whose interpreted value is
the value of the decimal.
INTEGER CHARACTER The result is the shortest character string that conforms to the
definition of an exact numeric literal and whose interpreted value is
the value of the integer.
INTERVAL CHARACTER The result is a string conforming to the definition of an INTERVAL
literal, whose interpreted value is the same as the source interval
value.
For example:
CAST(INTERVAL '4' YEARS AS CHAR)
would return:
INTERVAL '4' YEARS
For example:
CAST(TIME '09:24:15' AS CHAR)
would return:
TIME '09:24:15'
TIMESTAMP CHARACTER The result is a string conforming to the definition of a TIMESTAMP
literal, whose interpreted value is the same as the source timestamp
value.
For example:
CAST(TIMESTAMP '2002-10-05 09:24:15' AS CHAR)
would return:
TIMESTAMP '2002-10-05 09:24:15'
GMTTIME CHARACTER The result is a string conforming to the definition of a GMTTIME
literal whose interpreted value is the same as the source value. The
result string will have the form GMTTIME 'hh:mm:ss'.
GMTTIMESTAMP CHARACTER The result is a string conforming to the definition of a
GMTTIMESTAMP literal whose interpreted value is the same as the
source value. The result string will have the form GMTTIMESTAMP
'yyyy-mm-dd hh:mm:ss'.
BIT CHARACTER The result is a string conforming to the definition of a bit string literal
whose interpreted value is the same as the source value. The result
string will have the form B'bbbbbb' (where b is either '0' or '1').
This function might report conversion errors if the given code page or
encoding are unknown, the data supplied is not an integral number of
characters of the given code page or the given data contains characters
that are not valid in the given code page.
Chapter 7. Transforming data from one data type to another (CAST) 115
Supported casts
Table 7. Supported CASTs (continued)
Source data type Target data type Effect
BLOB CHARACTER The result is a string conforming to the definition of a binary string
literal whose interpreted value is the same as the source value. The
result string will have the form X'hhhh' (where h is any hexadecimal
digit character).
This function might report conversion errors if the given code page or
encoding are unknown, the data supplied is not an integral number of
characters of the given code page or the given data contains characters
that are not valid in the given code page.
TIME GMTTIME The result value is the source value minus the local time zone
displacement (as returned by LOCAL_TIMEZONE). The hours field is
calculated modulo 24.
GMTTIME TIME The result value is source value plus the local time zone displacement
(as returned by LOCAL_TIMEZONE). The hours field is calculated
modulo 24.
GMTTIMESTAMP TIMESTAMP The result value is source value plus the local time zone displacement
(as returned by LOCAL_TIMEZONE).
TIMESTAMP GMTTIMESTAMP The result value is the source value minus the local time zone
displacement (as returned by LOCAL_TIMEZONE).
INTEGER or FLOAT The number is converted, with rounding if necessary.
DECIMAL
FLOAT INTEGER or If the conversion would not lead to loss of leading significant digits,
DECIMAL the conversion will happen with the number being rounded as
necessary. If the conversion would lead to loss of leading significant
digits, a runtime error is generated. Loss of significant digits can occur
when converting an approximate numeric value to an integer, or to a
decimal whose precision is not sufficient.
INTEGER or INTEGER or If the conversion would not lead to loss of leading significant digits,
DECIMAL DECIMAL the conversion will happen with the number being rounded as
necessary. If the conversion would lead to loss of leading significant
digits, a runtime error is generated. Loss of significant digits can occur
when converting (say) a decimal to another decimal with insufficient
precision, or an integer to a decimal with insufficient precision.
INTERVAL INTERVAL Year-month intervals are only convertible to year-month intervals, and
day-second intervals are only convertible to day-second intervals. The
conversion is done by converting the source interval into a scalar in
units of the least significant field of the target interval qualifier. This
value is normalized into an interval with the target interval qualifier.
For example, to convert an interval that has the qualifier MINUTE TO
SECOND into an interval with the qualifier DAY TO HOUR, the
source value is converted into a scalar in units of hours, and this value
is normalized into an interval with qualifier DAY TO HOUR.
INTERVAL INTEGER or If the interval value has a qualifier that has only one field, the result is
DECIMAL an exact numeric with that value. If the interval has a qualifier with
more than one field, such as YEAR TO MONTH, a runtime error is
generated.
Refer to “Numbers” on page 6 for information about precision and scale. Refer to
“INTERVAL” on page 8 for information about interval qualifier.
Implicit casts
It is not always necessary to cast values between types. Some casts are done
implicitly. For example, numbers are implicitly cast between the three numeric
types for the purposes of comparison and arithmetic. Character strings are also
implicitly cast to other data types for the purposes of comparison.
There are three situations in which a data value of one type is cast to another type
implicitly. The behavior and restrictions of the implicit cast are the same as
described for the explicit cast function, except where noted in the following
sections.
When the data types of the two values are not the same, one of them can be
implicitly cast to the type of the other to allow the comparison to proceed. In the
table below, the vertical axis represents the left hand operand, the horizontal axis
represents the right hand operand.
Chapter 7. Transforming data from one data type to another (CAST) 117
Implicit casts
An ″L″ means that the right hand operand is cast to the type of the left hand
operand before comparison, an ″R″ means the opposite, an ″X″ means no implicit
casting takes place, and a blank means that comparison between the values of the
two data types is not supported.
Table 8. Implicit CASTs for comparison
ukn bln int float dec char time gtm date ts gts ivl blob bit
ukn
bln X L
int X R R L
float L X L L
dec L R X L
chr R R R R X R R R R R R1 R R
tm L X L
gtm L R X
dt L X R2 R2
ts L L2 X L
2
gts L L R X
1
ivl L X
blb L X
bit L X
Notes:
1. When casting from a character string to an interval, the character string must be of the format ″INTERVAL
’<values>’ <qualifier>″. The format ″<values>″, which is allowable for an explicit CAST, is not allowable here
because no qualifier external to the string is supplied.
2. When casting from a DATE to a TIMESTAMP or GMTTIMESTAMP, the time portion of the TIMESTAMP is set
to all zero values (00:00:00). This is different to the behavior of the explicit cast, which sets the time portion to
the current time.
Numeric types: The comparison operators operate on all three numeric types.
Character strings: You cannot define an alternative collation order that, for
example, collates upper and lowercase characters equally.
When comparing character strings, trailing blanks are not significant so the
comparison 'hello' = 'hello ' returns true.
Datetime values: Datetime values are compared in accordance with the natural
rules of the Gregorian calendar and clock.
You can compare the time zone you are working in with the GMT time zone. The
GMT time zone is converted into a local time zone based on the time zone
difference between your local time zone and the GMT time specified. When you
compare your local time with the GMT time, the comparison is based on the
difference at a given time on a given date.
Booleans: Boolean values can be compared using all or the normal comparison
operators. The TRUE value is defined to be greater than the FALSE value.
Comparing either value to the UNKNOWN boolean value (which is equivalent to
NULL) returns an UNKNOWN result.
Intervals: Intervals are compared by converting the two interval values into
intermediate representations, so that both intervals have the same interval qualifier.
Year-month intervals can be compared only with other year-month intervals, and
day-second intervals can be compared only with other day-second intervals.
The character string on the left would be converted into an integer before the
comparison takes place. This behavior reduces some of the need for explicit CAST
operators when comparing values derived from a generic XML message with
literal values. (For details of explicit casts that are supported, see Table 7 on
page 112.) It is this facility that allows you to write an expression such as:
Body.Trade.Quantity > 5000
In this example, the field reference on the left evaluates to the character string
'1000' and, because this is being compared to an integer, that character string is
converted into an integer before the comparison takes place.
Note that you must still check whether the price field that you want interpreted as
a decimal is greater than a given threshold. You must make sure that the literal
you compare it to is a decimal value and not an integer.
For example:
Body.Trade.Price > 100
would not have the desired effect, because the Price field would be converted into
an integer, and that conversion would fail because the character string contains a
decimal point. However, the following expression will succeed:
Body.Trade.Price > 100.00
Chapter 7. Transforming data from one data type to another (CAST) 119
Implicit casts
Table 9. Implicit CASTs for arithmetic operations
Left operand data type Right operand data type Supported Result data type
operators
INTEGER FLOAT +, -, *, / FLOAT1
INTEGER DECIMAL +, -, *, / DECIMAL1
INTEGER INTERVAL * INTERVAL4
FLOAT INTEGER +, -, *, / FLOAT1
FLOAT DECIMAL +, -, *, / FLOAT1
FLOAT INTERVAL * INTERVAL4
DECIMAL INTEGER +, -, *, / DECIMAL1
DECIMAL FLOAT +, -, *, / FLOAT1
DECIMAL INTERVAL * INTERVAL4
TIME TIME - INTERVAL2
TIME GMTTIME - INTERVAL2
TIME INTERVAL +, - TIME3
GMTTIME TIME - INTERVAL2
GMTTIME GMTTIME - INTERVAL2
GMTTIME INTERVAL +, - GMTTIME3
DATE DATE - INTERVAL2
DATE INTERVAL +, - DATE3
TIMESTAMP TIMESTAMP - INTERVAL2
TIMESTAMP GMTTIMESTAMP - INTERVAL2
TIMESTAMP INTERVAL +, - TIMESTAMP3
GMTTIMESTAMP TIMESTAMP - INTERVAL2
GMTTIMESTAMP GMTTIMESTAMP - INTERVAL2
GMTTIMESTAMP INTERVAL +, - GMTTIMESTAMP3
INTERVAL INTEGER *, / INTERVAL4
INTERVAL FLOAT *, / INTERVAL4
INTERVAL DECIMAL *, / INTERVAL4
INTERVAL TIME + TIME3
INTERVAL GMTTIME + GMTTIME3
INTERVAL DATE + DATE3
INTERVAL TIMESTAMP + TIMESTAMP3
INTERVAL GMTTIMESTAMP + GMTTIMESTAMP3
Chapter 7. Transforming data from one data type to another (CAST) 121
Implicit casts
Table 10. Conversions from WebSphere MQ Integrator Broker to SQL data
types (continued)
WebSphere MQ Integrator Broker data type SQL data type
BLOB SQL_C_BINARY
BIT Not supported2
Notes:
1. For convenience, DECIMAL values are passed to the DBMS in character form.
2. There is no suitable standard SQL C data type for INTERVAL or BIT. These must be
cast to another data type, such as CHARACTER, if it is necessary to assign them to a
database field.
A scalar variable
When assigning to a scalar variable, if the data type of the value being
assigned and that of the target variable data type are different, an implicit
cast is attempted with exactly the same restrictions and behavior as
specified for the explicit CAST function. The only exception is when the
data type of the variable is INTERVAL or DECIMAL.
In both these cases, the value being assigned is first cast to a CHARACTER
value, an attempt is made to cast the CHARACTER value to an INTERVAL
or DECIMAL. The reason for this is that INTERVAL requires a qualifier
and DECIMAL requires a precision and scale, these must be specified in
the explicit cast, but must be obtained from the character string when
implicitly casting. Therefore a further restriction is that when implicitly
casting to an INTERVAL variable, the character string must be of the form
″INTERVAL ’<values>’ <qualifier>″. The shortened ″<values>″ form that is
acceptable for the explicit cast is not acceptable here.
The ESQL data type of message fields depends on the type of the message (XML
for example), and the parser used to parse it. The ESQL data type of the value
returned by a database column reference depends on the data type of the column
in the database.
Table 11 shows which ESQL data types the various built-in DBMS data types (for
DB2 (version shipped with the product), SQL Server Version 7.0, Sybase Version
12.0, and Oracle Version 8.1.5) are cast to when they are accessed by WebSphere
MQ Integrator Broker.
Table 11. Implicit CASTS for database data types to WebSphere MQ Integrator Broker types
WebSphere MQ DB2 SQL Server and Sybase Oracle
Integrator Broker
BOOLEAN BIT
INTEGER SMALLINT, INTEGER, INT, SMALLINT, TINYINT
BIGINT
FLOAT REAL, DOUBLE FLOAT, REAL NUMBER()1
DECIMAL DECIMAL DECIMAL, NUMERIC, MONEY, NUMBER(P)1,
SMALLMONEY NUMBER(P,S)1
where Database.personnel resolves to a TINYINT column in a SQL Server database table, results in a list of
ESQL INTEGER values being assigned to OutputRoot.xxx.
Chapter 7. Transforming data from one data type to another (CAST) 123
Data types of values from external sources
Consider what happens when the following message is processed by this ESQL:
<Data>
<Input>
<Field0>Value00</Field0>
<Field1>Value10</Field1>
<Field2>Value20</Field2>
</Input>
<Input>
<Field2>Value21</Field2>
<Field1>Value11</Field1>
<Field0>Value01</Field0>
</Input>
</Data>
There are two ″Output″ fields, one for each ″Input″ field. This is because, by
default, SELECT creates an item in its result list for each item described by its
FROM list. Within each ″Output″ field, there is a Field for each field named in the
SELECT clause and these are in the order they are specified within the SELECT,
not their order in the incoming message. The ″R″ introduced by the final AS
keyword is known as a correlation name. It is a local variable that represents in
turn each of the fields addressed by the FROM clause. There is no significance to
the name chosen. In summary, this simple transform does two things:
1. It discards unwanted fields (the Field0’s)
2. It guarantees the order of the fields
It might help understanding to see the same transform implemented by a
procedural algorithm:
DECLARE i INTEGER;
DECLARE count INTEGER;
SET i = 1;
SET count = CARDINALITY(InputRoot.XML.Data.Input[]);
These examples show the SELECT version of the transform is much more concise.
It also executes faster. The following is a slightly more advanced transformation:
SET OutputRoot.XML.Data.Output[] =
(SELECT R.Field1 AS Field.F1, R.Field2 AS Field.F2
FROMInputRoot.XML.Data.Input[] AS R);
In this transform, there is an AS clause associated with each item in the SELECT
clause. This gives each field in the result an explicit name rather than their names
simply being inherited from the input. These names can be paths (that is, a dot
separated list of names), as shown in the example. Thus, the output message’s
structure can be arbitrarily different from the input message’s. Using the same
input message, the result in this case is:
<Data>
<Output>
<Field>
<F1>Value10</F1>
<F2>Value20</F2>
</Field>
</Output>
<Output>
<Field>
<F1>Value11</F1>
<F2>Value21</F2>
</Field>
</Output>
</Data>
The expressions in the SELECT clause can be of any complexity and there are no
special restrictions. They can include operators, functions, literals, refer to
variables, or to fields not related to the correlation name. The following example
shows more complex expressions being used:
SET OutputRoot.XML.Data.Output[] = (SELECT
’Start’ As Header,
’Prefix:’ || R.Field1 AS Field.F1,
R.Field2 || ’:Suffix’ AS Field.F2,
’End’ AS Trailer
FROM InputRoot.XML.Data.Input[] AS R);
Using the same input message, the result in this case is:
<Data>
<Output>
<Header>Start</Header>
<Field>
<F1>Prefix:Value10</F1>
<F2>Value20:Suffix</F2>
</Field>
<Trailer>End</Trailer>
</Output>
<Output>
<Header>Start</Header>
<Field>
<F1>Prefix:Value11</F1>
<F2>Value21:Suffix</F2>
</Field><Trailer>End</Trailer>
</Output>
</Data>
Using the same input message, the result in this case is:
<Data>
<Output>
<Field A1="Value10" A2="Value20"/>
</Output>
<Output>
<Field A1="Value11" A2="Value21"/>
</Output>
</Data>
Finally, a WHERE clause can be used to eliminate some of the results. In the
following example a WHERE clause is used to remove results in which a specific
criterion is met. Note that an entire result is either included or excluded:
SET OutputRoot.XML.Data.Output[] = (SELECT
R.Field1 AS Field.F1,
R.Field2 AS Field.F2
FROM InputRoot.XML.Data.Input[] AS R
WHERE R.Field2 = ’Value21’);
Using the same input message, the result in this case is:
<Data>
<Output>
<Field>
<F1>Value11</F1>
<F2>Value21</F2>
</Field>
</Output>
</Data>
What is key about this transform is that it has two SELECT’s nested inside each
other. The outer one operates on the list of Invoices. The inner one operates on the
list of Items. Note particularly that the AS clause associated with the inner SELECT
is expecting an array:
(SELECT
II.Description AS Desc,
CAST(II.Price AS FLOAT) * 1.6 AS Cost,
II.Quantity AS Qty
FROM I.Item[] AS II
WHERE II.Price > 0.0 ) AS Purchases.Article[], <== NB: [ ]
This tells the inner SELECT to work with the current Invoice’s Items. Both
SELECTs contain WHERE clauses. The outer one uses one criterion to discard
certain Invoices and the inner one uses a different criterion to discard certain
Items. The example also shows the use of COALESCE to prevent missing input
fields causing the corresponding output field to be missing. Finally, it also uses the
column function SUM to add together the value of all Items in each Invoice.
Column functions are discussed in “Column functions”.
Column functions
A column function is a function that takes the values of a single column in all the
selected rows of a table or message and returns a single scalar result.
Suppose that you want to perform a special action on invoices that have a total
order value greater than a certain amount. In order to calculate the total order
value of an Invoice field, you must multiply the Price fields by the Quantity
fields in all of the Items in the message, and total the result. You can do this using
a SELECT expression as follows:
(
SELECT SUM( CAST(I.Price AS DECIMAL) * CAST(I.Quantity AS INTEGER) )
FROM Body.Invoice."Item"[] AS I
)
The example assumes that it is necessary to use CAST expressions to cast the
string values of the fields Price and Quantity into the correct data types. The cast
of the Price field into a decimal produces a decimal value with the "natural" scale
and precision, that is, whatever scale and precision is necessary to represent the
number. These CASTs would not be necessary if the data were already in an
appropriate data type.
The SELECT expression works in a similar way to the quantified predicate, and
works in much the same way that a SELECT works in standard database SQL. The
FROM clause specifies what is being iterated, in this case, all Item fields in
Invoice, and establishes that the current instance of Item can be referred to using
"I". This form of SELECT involves a column function, in this case the SUM
function, so the SELECT is evaluated by adding together the results of evaluating
the expression inside the SUM function for each Item field in the Invoice. As with
standard SQL, NULL values are ignored by column functions, with the exception
of the COUNT column function explained below, and a NULL value is returned by
the column function only if there are no non-NULL values to combine.
The other column functions that are provided are MAX, MIN, and COUNT. The
COUNT function has two forms that work in different ways with regard to
NULLs. In the first form you use it much like the SUM function above, so, for
example:
This expression returns the number of Item fields for which the Quantity field is
non-NULL. That is, the COUNT function counts non-NULL values, in the same
way that the SUM function adds non-NULL values. The alternative way of using
the COUNT function is as follows:
SELECT COUNT(*)
FROM Body.Invoice."Item"[] AS I
Using COUNT(*) counts the total number of Item fields, regardless of whether any
of the fields is NULL. The above example is in fact equivalent to using the
CARDINALITY function, as in:
CARDINALITY(Body.Invoice."Item"[])
In all of the examples of SELECT given here, just as in standard SQL, a WHERE
clause could have been specified to provide filtering on the fields.
Sending the same trigger message will result in a message on the output queue
that looks like this:
<Test>
<Result>value1</Result>
<Result>value5</Result>
</Test>
Comparing this message to the one that is produced if the ITEM keyword is
omitted:
<Test>
<Result>
<Field1>value1</Field1>
</Result>
<Result>
<Field1>value5</Field1>
</Result>
</Test>
you can see the effect of the ITEM keyword. With the ITEM keyword, the result is
a list of scalar values rather than a list of fields (name-value pairs).
The two previous examples both specified a list as the source of the SELECT in the
FROM clause (so the field reference had a [] at the end), and so in general the
SELECT will generate a list of results. Because of this it was necessary to specify a
list as the target of the assignment (thus the "Result[]" as the target of the
assignment). However, often you know that the WHERE clause that you specify as
The following example shows the effect of using the THE keyword:
SET OutputRoot.MQMD = InputRoot.MQMD;
SET OutputRoot.XML.Test.Result =
THE (SELECT T.Field4, T.Structure1 FROM InputBody.Test.Input[]
AS T WHERE T.Field1 = 'value1');
The THE keyword means that the target of the assignment becomes
OutputRoot.XML.Test.Result (the "[]" is no longer necessary, or even allowed). This
results in the following message:
<Test>
<Result>
<Field4>value4</Field4>
<Structure1>
<Field2>value2</Field2>
<Field3>value3</Field3>
</Structure1>
</Result>
</Test>
The message has two sections: the first is a list of items in which each item has a
catalogue number and a description. The second is another list referring to the
same items but containing a price for each item. Using the following transform:
SET OutputRoot.XML.Results.Items.Item[] =
(SELECT D.CatNo, D.Short, P.Number, P.Selling
FROM
InputRoot.XML.Data.Descriptions.Description[] As D,
InputRoot.XML.Data.Prices.Price[] As P
);
There are nine results, that is the number of descriptions in the first list (three)
multiplied by the number of prices in the second (three). The results systematically
work through all the combinations of the two lists. You can see this by looking at
the CatNo and Number fields selected from each result:
CatNo 1000 Number 1000
CatNo 1000 Number 1001
CatNo 1000 Number 1002
CatNo 1001 Number 1000
CatNo 1001 Number 1001
CatNo 1001 Number 1002
CatNo 1002 Number 1000
CatNo 1002 Number 1001
CatNo 1002 Number 1002
This is a useful because by applying a where clause, which selects only the useful
combinations, the two lists can be intelligently merged. Now consider the
following transform:
SET OutputRoot.XML.Results.SaleItems.Item[] =
(SELECT D.CatNo AS Catalogue, D.Short AS Description, P.Selling AS Price
FROM
InputRoot.XML.Data.Descriptions.Description[] As D,
InputRoot.XML.Data.Prices.Price[] As P
WHERE D.CatNo = P.Number
);
The addition of the where clause causes results to be produced for those items
only that have similar catalogue numbers. The result with this transform is:
<SaleItems>
<Item>
<Catalogue>1000</Catalogue>
<Description>Milk Chocolate Bar</Description>
<Price>26</Price>
</Item>
<Item>
<Catalogue>1001</Catalogue>
<Description>Chocolate Bar</Description>
<Price>27</Price>
</Item>
<Item>
<Catalogue>1002</Catalogue>
<Description>Chocolate</Description>
<Price>28</Price>
</Item>
</SaleItems>
There are just three results, each of which contains data from both of the original
lists. Each Item has a description taken from the first list and a price taken from
the second.
Confectionary 2000
NewsPapers 3000
Hardware 4000
Again the message has two sections: the first is a list of items in which each item
has a catalogue number and a type. The second is a translate table between
English type names and numeric type codes. Given the following transform:
SET OutputRoot.XML.Result.Items.Item[] =
(SELECT I.Cat, I.Description, T.Number As Type
FROM
InputRoot.XML.Data.Items.Item[] As I,
InputRoot.XML.Data.TranslateTable.Translate[] As T
WHERE I.Type = T.Name
);
In the result, each type name has been converted to its corresponding code. Both
the data and the translate table were in the same message tree, however it is not a
requirement that are in the same message tree.
Note the location of the "[]" in each case. Any number of items can be specified in
the FROM list, not just one or two. If any of the items specify "[]" to indicate a list
of items, the SELECT generates a list of results (the list might contain only one
item, but the SELECT can potentially return a list of items). The target of the
assignment must specify a list (so must end in "[]" or the THE keyword must be
used if you know that the WHERE clause guarantees only one combination is
matched.
The connection to the database is performed using the database user ID and
password supplied on the mqsicreatebroker command that created the individual
broker. The WebSphere MQ Integrator Broker or database administrator must
therefore ensure that user has sufficient database privileges to query the required
database tables. If not, a runtime error is generated by the broker when it attempts
to process a message and attempts to connect to the database for the first time.
While the standard SQL SELECT syntax is supported for queries to an external
database, there are a number of points to be borne in mind. It is necessary to prefix
the name of the table with the keyword "Database" in order to indicate that the
SELECT is to be targeted at the external database, rather than at a repeating
structure in the message.
where SCHEMA is the name of the schema in which the table TABLE1 is defined.
References to column names must be qualified with either the table name or the
correlation name defined for the table by the FROM clause. So, where you could
normally execute a query such as:
SELECT column1, column2 FROM table1
The following examples illustrate how the results sets of external database queries
are represented in WebSphere MQ Integrator Broker. The results of database
queries are assigned to fields in a message using a Compute node.
For more information on how to use the Database node, see WebSphere MQ
Integrator Broker Using the Control Center.
Create a database table called USERTABLE with two char(6) data type columns (or
equivalent), called Column1 and Column2. Insert two rows into the table so that it
looks like this:
Column1 Column2
Row 1 value1 value3
Row 2 value2 value4
Add a database table input to the Compute node by clicking the Add input button
on the properties pane of the node and entering the ODBC Data Source Name and
table name. The user database ID and password specified when you created the
broker are used for accessing the database, therefore you must ensure that this ID
and password pair have appropriate permissions within the DBMS.
You are also recommended to ensure that you include the schema name when you
create a table as the second component of the database table reference (for
example, Database.user1.USERTABLE) in the Compute node ESQL you specify. This
avoids potential confusion that some databases might encounter.
For example, if you create your database table as user ID user1, but specified user
ID user2 when you created the broker, you might find that the broker attempts to
access table user2.USERTABLE, which does not exist, rather than user1.USERTABLE,
which does.
You can vary the names of the fields produced by explicitly listing the columns
that you want to extract. How you do this depends partly on your database
To trigger the SELECT, you must send in a trigger message with an XML body that
is of the following form:
<Test>
<Result>
<Column1>value1</Column1>
<Column2>value2</Column2>
</Result>
<Result>
<Column1>value3</Column1>
<Column2>value4</Column2>
</Result>
</Test>
The exact structure of the XML is not important, but the enclosing tag must be
<Test>. If it is not, the ESQL statements results in top-level enclosing tags being
formed, which is not valid XML.
<Test>
<Result>
<Column1>value1</Column1>
</Result>
<Result>
<Column1>value3</Column1>
</Result>
</Test>
Comparing these two messages illustrates the effect of the ITEM keyword. The
evaluation of the ESQL expressions happens independently of any information
about the schema of the target message. In the case of generating a generic XML
message, there is no message schema for the message being generated, so the
structure of the message that is generated must be defined entirely by the ESQL.
The first option is the default and the result is that the ESQL processing in the
current node is abandoned. The exception is then propagated backwards up the
message flow until an enclosing catch node or the flow’s input node is reached. If
the flow’s input node is reached, any transaction is rolled back.
The indicators contain information only when an error (not a warning) occurs,
unless you have the ″TreatWarningsAsErrors″ property checked. In the case of
″successful″ and ″success with information″ database operations, the indicators
contain their default ″success″ values, as described in“Database state functions” on
page 101.
If you are attempting inline error processing, you must check the state indicators
after each database statement is executed to avoid missing any errors. When
processing the indicators, if you meet an error that you cannot handle inline, you
might wish to raise a new exception either to deal with it ‘upstream’ in a catch
node or to let it through to the input node so that the transaction is rolled back.
This can be accomplished by using the ESQL THROW statement, see “THROW”
on page 83 for a description.
For example, if you were to receive a simple XML message on a WebSphere MQ®
queue, whose message originated in the message flow from an MQInput node, and
which had an MQRFH2 header like the message below:
<Trade type='buy'
Company='IBM'
Price='200.20'
Date='2000-01-01'
Quantity='1000'/>
Root
Properties
CreationTime=GMTTIMESTAMP '1999-11-24 13:10:00'
(a GMT timestamp field)
MQMD
PutDate=DATE '19991124'
(a date field)
PutTime=GMTTIME '131000'
(a GMTTIME field)
MQRFH
mcd
msd='xml'
(a character string field)
XML
Trade
type='buy'
(a character string field)
Company='IBM'
(a character string field)
Price='200'
(a character string field)
Date='2000-01-01'
(a character string field)
Quantity='1000'
(a character string field)
To trace particular variables in the variables folder of the environment tree, you
can use the following pattern: ${Environment.Variables.MyVariable1}, which
returns the value only (for example 3).
A variable length BLOB message is received and some of the fields need to be
parsed in MRM format in order to route the message to the right queue. Because
the message is in BLOB format and contains imbedded NULLs (’x00’), the message
cannot be defined as null terminated.
This example also shows how to convert the BLOB message to CWF format,
process the message and strip off the added length field.
Note: You will need to change the queue manager name within the message flow
to the name of your queue manager.
Create subflow
The purpose of this subflow is to output the message in its original form. To do
this, the message has to be converted back to BLOB from MRM and the four bytes
that were added (field B_LEN) are removed.
This Compute node will remove the four bytes that were added at the
beginning of the BLOB message in order to be able to manipulate it
5. Connect the out terminal of the Compute node to an MQOutput node.
6. Create an MQOutput Node. The properties Queue Manager Name and Queue
Name in the MQOutput node can be promoted so they can be specified in the
main flow, node SUBFLOW.
Exception lists
Figure 11 illustrates one way in which an exception list can be constructed.
ExceptionList {
RecoverableException = { 1
File = ’f:/build/argo/src/DataFlowEngine/ImbDataFlowNode.cpp’
Line = 538
Function = ’ImbDataFlowNode::createExceptionList’
Type = ’ComIbmComputeNode’
Name = ’0e416632-de00-0000-0080-bdb4d59524d5’
Label = ’mf1.Compute1’
Text = ’Node throwing exception’
Catalog = ’WebSphere MQ Integrator Broker2’
Severity = 3
Number = 2230
RecoverableException = { 2
File = ’f:/build/argo/src/DataFlowEngine/ImbRdlBinaryExpression.cpp’
Line = 231
Function = ’ImbRdlBinaryExpression::scalarEvaluate’
Type = ’ComIbmComputeNode’
Name = ’0e416632-de00-0000-0080-bdb4d59524d5’
Label = ’mf1.Compute1’
Text = ’error evaluating expression’
Catalog = ’WebSphere MQ Integrator Broker2’
Severity = 2
Number = 2439
Insert = {
Type = 2
Text = ’2’
}
Insert = {
Type = 2
Text = ’30’
}
RecoverableException = { 3
File = ’f:/build/argo/src/DataFlowEngine/ImbRdlValueOperations.cpp’
Line = 257
Function = ’intDivideInt’
Type = ’ComIbmComputeNode’
Name = ’0e416632-de00-0000-0080-bdb4d59524d5’
Label = ’mf1.Compute1’
Text = ’Divide by zero calculating ’%1 / %2’’
Catalog = ’WebSphere MQ Integrator Broker2’
Severity = 2
Number = 2450
Insert = }
Type = 5
Text = ’100 / 0’
}
}
}
}
}
Notes:
1. The first exception description 1 is a child of the root. This identifies error
number 2230, indicating an exception has been thrown. The node that has
thrown the exception is also identified (mf1.Compute1).
ExceptionList = (
(0x1000000)RecoverableException = (
(0x3000000)File = ’F:\build\S000_D\src\DataFlowEngine\ImbComputeNode.cpp’
(0x3000000)Line = 402
(0x3000000)Function = ’ImbComputeNode::evaluate’
(0x3000000)Type = ’ComIbmComputeNode’
(0x3000000)Name = ’acd8f35d-e700-0000-0080-b78796c5e70d’
(0x3000000)Label = ’esql_13485_check_defect.Compute1’
(0x3000000)Text = ’Caught exception and rethrowing’
(0x3000000)Catalog = ’WMQIv210’
(0x3000000)Severity = 3
(0x3000000)Number = 2230
(0x1000000)RecoverableException = (
(0x3000000)File = ’F:\build\S000_D\src\DataFlowEngine\ImbRdl\ImbRdlExternalDb.cpp’
(0x3000000)Line = 278
(0x3000000)Function = ’SqlExternalDbStmt::executeStmt’
(0x3000000)Type = ’ComIbmComputeNode’
(0x3000000)Name = ’acd8f35d-e700-0000-0080-b78796c5e70d’
(0x3000000)Label = ’esql_13485_check_defect.Compute1’
(0x3000000)Text = ’The following error occurred execution SQL statement &3. inserts where &4’
(0x3000000)Catalog = ’WMQIv210’
(0x3000000)Severity = 3
(0x3000000)Number = 2519
(0x1000000)Insert = (
(0x3000000)Type = 2
(0x3000000)Text = ’1’
)
(0x1000000)Insert = (
(0x3000000)Type = 2
(0x3000000)Text = ’1’
)
(0x1000000)Insert = (
(0x3000000)Type = 5
(0x3000000)Text = ’USERDB’
)
(0x1000000)Insert = (
(0x3000000)Type = 5
(0x3000000)Text = ’DELETE FROM DB2ADMIN.STOCK WHERE (STOCK_ID)=(?)’
)
(0x1000000)Insert = (
(0x3000000)Type = 5
(0x3000000)Text = ’500027, ’
)
(0x1000000)DatabaseException = (
(0x3000000)File = ’F:\build\S000_D\src\DataFlowEngine\ImbOdbc.cpp’
(0x3000000)Line = 153
(0x3000000)Function = ’ImbOdbcHandle::checkRcInner’
(0x3000000)Type = ’’
(0x3000000)Name = ’’
(0x3000000)Label = ’’
(0x3000000)Text = ’Root SQL exception’
(0x3000000)Catalog = ’WMQIv210’
(0x3000000)Severity = 3
(0x3000000)Number = 2321
(0x1000000)Insert = (
(0x3000000)Type = 2
(0x3000000)Text = ’100’
)
)
)
)
)
ExceptionList = (
(0x1000000)RecoverableException = (
(0x3000000)File = ’F:\build\S000_D\src\DataFlowEngine\ImbComputeNode.cpp’
(0x3000000)Line = 402
(0x3000000)Function = ’ImbComputeNode::evaluate’
(0x3000000)Type = ’ComIbmComputeNode’
(0x3000000)Name = ’acd8f35d-e700-0000-0080-b78796c5e70d’
(0x3000000)Label = ’esql_13485_check_defect.Compute1’
(0x3000000)Text = ’Caught exception and rethrowing’
(0x3000000)Catalog = ’WMQIv210’
(0x3000000)Severity = 3
(0x3000000)Number = 2230
(0x1000000)RecoverableException = (
(0x3000000)File = ’F:\build\S000_D\src\DataFlowEngine\ImbRdl\ImbRdlTypeCast.cpp’
(0x3000000)Line = 163
(0x3000000)Function = ’SqlTypeCast::evaluate’
(0x3000000)Type = ’’
(0x3000000)Name = ’’
(0x3000000)Label = ’’
(0x3000000)Text = ’Error casting from %3 to %4’
(0x3000000)Catalog = ’WMQIv210’
(0x3000000)Severity = 3
(0x3000000)Number = 2521
(0x1000000)Insert = (
(0x3000000)Type = 2
(0x3000000)Text = ’12’
)
(0x1000000)Insert = (
(0x3000000)Type = 2
(0x3000000)Text = ’28’
)
(0x1000000)Insert = (
(0x3000000)Type = 5
(0x3000000)Text = ’CHARACTER’
)
(0x1000000)Insert = (
(0x3000000)Type = 5
(0x3000000)Text = ’INTEGER’
)
(0x1000000)ConversionException = (
(0x3000000)File = ’F:\build\S000_D\src\CommonServices\ImbUtility.cpp’
(0x3000000)Line = 195
(0x3000000)Function = ’imbWcsToInt64’
(0x3000000)Type = ’’
(0x3000000)Name = ’’
(0x3000000)Label = ’’
(0x3000000)Text = ’Invalid characters’
(0x3000000)Catalog = ’WMQIv210’
(0x3000000)Severity = 3
(0x3000000)Number = 2595
(0x1000000)Insert = (
(0x3000000)Type = 5
(0x3000000)Text = ’fred’
)
)
)
)
)
ExceptionList = (
(0x1000000)RecoverableException = (
(0x3000000)File = ’F:\build\S000_D\src\DataFlowEngine\ImbMqOutputNode.cpp’
(0x3000000)Line = 1444
(0x3000000)Function = ’ImbMqOutputNode::evaluate’
(0x3000000)Type = ’ComIbmMQOutputNode’
(0x3000000)Name = ’c76eb6cd-e600-0000-0080-b78796c5e70d’
(0x3000000)Label = ’esql_13485_check_defect.OUT’
(0x3000000)Text = ’Caught exception and rethrowing’
(0x3000000)Catalog = ’WMQIv210’
(0x3000000)Severity = 3
(0x3000000)Number = 2230
(0x1000000)ParserException = (
(0x3000000)File = ’F:\build\S000_D\src\MTI\MTIforBroker\GenXmlParser2\XmlImbParser.cpp’
(0x3000000)Line = 210
(0x3000000)Function = ’XmlImbParser::refreshBitStreamFromElements’
(0x3000000)Type = ’ComIbmMQInputNode’
(0x3000000)Name = ’ce64b6cd-e600-0000-0080-b78796c5e70d’
(0x3000000)Label = ’esql_13485_check_defect.IN’
(0x3000000)Text = ’XML Writing Errors have occurred’
(0x3000000)Catalog = ’WMQIv210’
(0x3000000)Severity = 3
(0x3000000)Number = 5010
(0x1000000)ParserException = (
(0x3000000)File = ’F:\build\S000_D\src\MTI\MTIforBroker\GenXmlParser2\XmlImbParser.cpp’
(0x3000000)Line = 551
(0x3000000)Function = ’XmlImbParser::checkForBodyElement’
(0x3000000)Type = ’’
(0x3000000)Name = ’’
(0x3000000)Label = ’’
(0x3000000)Text = ’No valid body of the document could be found.’
(0x3000000)Catalog = ’WMQIv210’
(0x3000000)Severity = 3
(0x3000000)Number = 5005
)
)
)
)
ExceptionList = (
(0x1000000)RecoverableException = (
(0x3000000)File = ’F:\build\S000_D\src\DataFlowEngine\ImbComputeNode.cpp’
(0x3000000)Line = 402
(0x3000000)Function = ’ImbComputeNode::evaluate’
(0x3000000)Type = ’ComIbmComputeNode’
(0x3000000)Name = ’acd8f35d-e700-0000-0080-b78796c5e70d’
(0x3000000)Label = ’esql_13485_check_defect.Compute1’
(0x3000000)Text = ’Caught exception and rethrowing’
(0x3000000)Catalog = ’WMQIv210’
(0x3000000)Severity = 3
(0x3000000)Number = 2230
(0x1000000)UserException = (
(0x3000000)File = ’F:\build\S000_D\src\DataFlowEngine\ImbRdl\ImbRdlThrowExceptionStatements.cpp’
(0x3000000)Line = 148
(0x3000000)Function = ’SqlThrowExceptionStatement::execute’
(0x3000000)Type = ’ComIbmComputeNode’
(0x3000000)Name = ’acd8f35d-e700-0000-0080-b78796c5e70d’
(0x3000000)Label = ’esql_13485_check_defect.Compute1’
(0x3000000)Text = ’User Generated SQL ’USER’ exception’
(0x3000000)Catalog = ’WMQIv210’
(0x3000000)Severity = 1
(0x3000000)Number = 2949
(0x1000000)Insert = (
(0x3000000)Type = 5
(0x3000000)Text = ’USER’
)
(0x1000000)Insert = (
(0x3000000)Type = 5
(0x3000000)Text = ’Insert1’
)
(0x1000000)Insert = (
(0x3000000)Type = 5
(0x3000000)Text = ’Insert2’
)
(0x1000000)Insert = (
(0x3000000)Type = 5
(0x3000000)Text = ’etc’
)
(0x1000000)Insert = (
(0x3000000)Type = 5
(0x3000000)Text = ’’
)
(0x1000000)Insert = (
(0x3000000)Type = 5
(0x3000000)Text = ’’
)
(0x1000000)Insert = (
(0x3000000)Type = 5
(0x3000000)Text = ’’
)
(0x1000000)Insert = (
(0x3000000)Type = 5
(0x3000000)Text = ’’
)
(0x1000000)Insert = (
(0x3000000)Type = 5
(0x3000000)Text = ’’
)
)
)
)
Figure 16 illustrates an extract of ESQL that shows how you can set up a Compute
node to use the exception list. The ESQL loops through the exception list to the last
(nested) exception description, and extracts the error number. This error relates to
the original cause of the problem and normally provides the most precise
information. Subsequent action taken by the message flow can be decided by the
error number retrieved in this way.
ESQL:
/* copy headers */
DECLARE i INTEGER;
DECLARE numHeaders INT;
SET i = 1;
SET numHeaders = CARDINALITY(InputRoot.*[]);
WHILE i < numHeaders DO
SET OutputRoot.*[i] = InputRoot.*[i];
SET i = i + 1;
END WHILE;
Output Message:
The Compute node and the Filter node share a common expression syntax. In its
simplest form, a Compute node provides a way of building up a new message
using a set of assignment statements. The expressions that appear on the right
hand side of the assignment, that is, the source expressions, are expressions of
exactly the same form as can appear in a Filter node. But they are not restricted to
returning single boolean values in the same way that a filter expression is.
Because there are two messages involved in a Compute node, it is not sufficient to
refer to "Root" as can be done in a Filter node where there is only one message.
Instead you must refer to "InputRoot" and "OutputRoot" in a Compute node. You
can also refer to "InputBody" in a Compute node in the same way that you can
refer to "Body" in a Filter node, though you cannot refer to "OutputBody", because
there is no fixed concept of what the "body" of the output message is until the
output message has been fully constructed.
The above example causes a complete copy of the input message to be propagated
to the output terminal of the Compute node because when the right hand side of
an assignment statement consists of a field reference, a complete recursive tree
copy is performed to duplicate the tree representation of the input message. For
more information about how you might use a Compute node see WebSphere MQ
Integrator Broker Using the Control Center.
For the destination list to be migrated from the input to the output, the
InputLocalEnvironment must be copied to the OutputLocalEnvironment in the
ESQL section of the node.
Like parsers
Where both the source and target messages have the same folder structure at root
level, a like-parser-copy is performed. For example:
SET OutputRoot.MQMD = InputRoot.MQMD;
will result in all the children in the MQMD folder of the input message being
copied to the MQMD folder of the output message.
Unlike parsers
Where the source and target messages have different folder structures at root level,
it is not possible to make an exact copy of the message source. Instead, the
unlike-parser-copy views the source message as a set of nested folders terminated
by a leaf name-value pair. For example, copying the following message from XML
to MRM:
<Name3><Name31>Value31</Name31>Value32</Name3>
Note: The second XML pcdata (Value32) cannot be represented and is discarded.
The unlike-parser-copy scans the source tree, and copies folders, also known as
name elements, and leaf name-value pairs. Everything else, including elements
flagged as ″special″ by the source parser, will not be copied.
Note: If the algorithm used to make an unlike-parser-copy does not suit your tree
structure, it might be necessary to further qualify the source field to restrict
the amount of tree copied.
The following example illustrates what is required for a CWF message to pass
from WebSphere MQ Integrator Broker to IMS™ on OS/390.
1. You have defined the input message in XML and are using an MQRFH2
header. The header must be removed before the message is passed to IMS.
2. The message passed to IMS must have MQIIH header, and must be in the
OS/390 code page. This message is defined in the MRM and has identifier
m_IMS1. The PIC X fields in this message must be defined as logical type
string for EBCDIC <-> ASCII conversion to take place. If they are logical type
binary, no data conversion occurs.
3. The message received from IMS is also defined in the MRM and has identifier
m_IMS2. The PIC X fields in this message must be defined as logical type
string for EBCDIC <-> ASCII conversion to take place. If they are logical type
binary, no data conversion occurs.
4. The reply message must be converted to the Windows NT codepage. The
MQIIH header is retained on this message.
5. You have created a message flow that contains:
a. The outbound flow, MQInput1 —> Compute1 —> MQOutput1.
b. The inbound flow, MQInput2 —> Compute2 —> MQOutput2.
You do not have to set any specific values for the MQInput1 node properties
because the message and message set are identified in the MQRFH2 header, and
no conversion is required.
You must set values for Domain, set, type and format in the MQInput node for the
inbound message flow (MQInput2). You do not need to set conversion parameters.
For example, if you want to transform a generic XML message into an MRM
message, you can:
1. Add the MRM message to Output Messages on the basic tab of the Compute
node properties dialog.
2. If you want to retain the headers of the message, select Copy message headers.
3. Select the Use as message body check box. This generates ESQL similar to:
SET OutputRoot.Properties.MessageSet = ’DHOP5F709S001’;
SET OutputRoot.Properties.MessageType = ’test_message’;
Note that it is the message identifier that is required in the MessageType field.
4. Specify the output format of the message (this must be one of CWF, PDF, or
XML). For example:
SET OutputRoot.Properties.MessageFormat = ’CWF’;
5. Specify the new message domain (in this transformation, this step is not
necessary because MRM is the default, but you are recommended to include
this for completeness):
SET OutputRoot.Properties.MessageDomain = ’MRM’;
6. Create ESQL statements to populate your output message, either manually or
by using drag and drop to generate automatic mappings.
Figure 18. Message flow using tagged or delimited messages to substitute CR LF pairs for
NL characters
In this example, the input is treated as BLOB format; this is passed into a
ResetContentDescriptor node to reset the data to an MRM message called ″msg_nl″
(a set of repeating string elements delimited by EBCDIC NL characters); a
Compute node is then used to create an output based on an MRM message
The following detailed instructions show how to create the messages and then how
to configure a message flow.
Each syntax diagram begins with a double right arrow and ends with a right and
left arrow pair. Lines beginning with a single right arrow are continuation lines.
You read a syntax diagram from left to right and from top to bottom, following the
direction of the arrows.
You may specify value A. Optional values are shown below the main
line of a syntax diagram.
A
A
The syntax fragment Name is shown separately from the main syntax
Name diagram.
Name:
A
B
IBM may have patents or pending patent applications covering subject matter
described in this information. The furnishing of this information does not give you
any license to these patents. You can send license inquiries, in writing, to:
IBM Director of Licensing
IBM Corporation
North Castle Drive
Armonk, NY 10504-1785
U.S.A.
For license inquiries regarding double-byte (DBCS) information, contact the IBM
Intellectual Property Department in your country or send inquiries, in writing, to:
IBM World Trade Asia Corporation
Licensing
2-31 Roppongi 3-chome, Minato-ku
Tokyo 106, Japan
The following paragraph does not apply to the United Kingdom or any other
country where such provisions are inconsistent with local law:
INTERNATIONAL BUSINESS MACHINES CORPORATION PROVIDES THIS
PUBLICATION “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS
FOR A PARTICULAR PURPOSE. Some states do not allow disclaimer of express or
implied warranties in certain transactions, therefore this statement may not apply
to you.
Any references in this information to non-IBM Web sites are provided for
convenience only and do not in any manner serve as an endorsement of those Web
sites. The materials at those Web sites are not part of the materials for this IBM
product and use of those Web sites is at your own risk.
IBM may use or distribute any of the information you supply in any way it
believes appropriate without incurring any obligation to you.
The licensed program described in this information and all licensed material
available for it are provided by IBM under terms of the IBM Customer Agreement,
IBM International Programming License Agreement, or any equivalent agreement
between us.
Trademarks
The following terms are trademarks of International Business Machines
Corporation in the United States, other countries, or both:
Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the
United States, other countries, or both.
UNIX is a registered trademark of The Open Group in the United States and other
countries.
AMI. Application Messaging Interface. configuration repository. Persistent storage for broker
configuration and topology definition.
Application Messaging Interface (AMI). The
programming interface provided by MQSeries that connector. See message processing node connector.
defines a high level interface to message queuing
content-based filter. An expression that is applied to
services. See also MQI and JMS.
the content of a message to determine how the message
is to be processed.
B
context tag. See element qualifier.
BLOB. Binary Large OBject. A block of bytes of data
Control Center. The graphical interface that provides
(for example, the body of a message) that has no
facilities for defining, configuring, deploying, and
discernible meaning, but is treated as one solid entity
monitoring resources of the WebSphere MQ Integrator
that cannot be interpreted.
Broker network.
broker. See message broker.
callback function. See implementation function. debugger. A facility on the Message Flows view in the
Control Center that enables message flows to be
category. An optional grouping of messages that are debugged.
related in some way. For example, messages that relate
to a particular application. deploy. Make operational the configuration and
topology of the broker domain.
DTD. Document Type Definition. filter. An expression that is applied to the content of a
message to determine how the message is to be
processed.
E
format. A format defines the internal structure of a
e-business. A term describing the commercial use of message, in terms of the fields and order of those
the Internet and World Wide Web to conduct business fields. A format can be self-defining, in which case the
(short for electronic-business). message is interpreted dynamically when read.
execution group. A named grouping of message flows implementation function. Function written by a
that have been assigned to a broker. The broker is third-party developer for a plug-in node or parser. Also
guaranteed to enforce some degree of isolation between known as a callback function.
message flows in distinct execution groups by ensuring
that they execute in separate address spaces, or as input node. A message flow node that represents a
unique processes. source of messages for the message flow.
Extended SQL. A specialized set of SQL functions and installation mode. The installation mode can be Full,
statements based on regular SQL, extended with Custom, or Broker only. The mode defines the
functions and statements unique to WebSphere MQ components of the product installed by the installation
Integrator Broker. process on Windows NT systems.
messages. Entities exchanged between a broker and its message type. The logical structure of the data within
clients. a message. For example, the number and location of
character strings.
W
warehouse. A persistent, historical datastore for events
(or messages). The Warehouse node within a message
flow supports the recording of information in a
database for subsequent retrieval and processing by
other applications.
X
XML. Extensible Markup Language.
Bibliography 185
MQSeries on the Internet
Index 189
repeats (continued)
quantified predicate 26
statements (continued)
SELECT 105
U
RETURN 79 ROW and LIST constructors 105 UCASE, string manipulation function 90
RETURNS 57 SET 81 universally unique identifier (UUID)
Root 23 THROW 83 create as a BLOB 102
ROUND, numeric function 93 UPDATE 84 create as a CHAR 103
ROW and LIST constructors 105 WHILE 85 UPDATE 84
ROW constructor 105 statements and expressions UPPER, string manipulation function 90
rows and lists in the SELECT EVAL 66 use of keyword ALL 26
statement 105 PASSTHRU USER 83
RTRIM, string manipulation function 89 limitations when calling stored UUID
procedures 76 create as a BLOB 102
stop node processing 79 create as a CHAR 103
UUIDASBLOB function 102
S string
convert to lower case 88 UUIDASCHAR function 103
SAMEFIELD 97
convert to upper case 90
samples 147, 167
extract substring 89
scalar variable
declare 63
locate substring 89 V
overlay 88 VALUE 53
scaling intervals 12
trim 88, 89 VALUES 83
SELECT 100
string manipulation variable
effects of the THE keyword 132
LCASE function 88 declare 63
joining items in the FROM
LENGTH function 87
clause 137
LOWER function 88
multiple items in the FROM
clause 133
LTRIM function 88
OVERLAY function 88
W
selecting from a list of scalars 137 WebSphere MQ Integrator Broker on the
POSITION function 89
simple message transformation 125, Internet 185
RTRIM function 89
128 WebSphere MQ Integrator Broker
SUBSTRING function 89
use of the ITEM keyword 132 publications 183
TRIM function 89
using SELECT to return a scalar national language 184
UCASE function 90
value 133 platform–specific 183
UPPER function 90
SELECTs, rows and lists 105 WHERE 64
strings
SET 81 WHILE 85
data type 7
use of SET 81 Windows 2000 xi
SUBSTRING, string manipulation
used in a Compute node 167
function 89
SET NAME 81
subtracting two datetime values 12
SET TYPE 81
SET VALUE 81
supported casts 112 X
supported CASTS 112 XML attributes
SEVERITY 83
SupportPac 185 translating to tags 68
softcopy books 184
syntax XML parser field types 30
SOME
case sensitivity of ESQL 45
using keyword 27
expression type checking 5
source expression
in CAST 112
SQLCODE 101
SQLERRORTEXT 101 T
SQLNATIVEERROR 101 THE keyword
SQLSTATE 101 used in SELECT 132
SQRT, numeric function 93 THROW 83
statements TIME 63
assignments 81 time, current 95
ATTACH 50 TIME, datetime data type 7
CALL STATEMENT 51 times
COMPOUND 52 using arithmetic operators 11
CREATE FIELD 53 TIMESTAMP 63
CREATE FUNCTION 57 timestamp, current 95
CREATE PROCEDURE 58 TIMESTAMP, datetime data type 8
DECLARE 63 timezone, local 96
DELETE 64 trace
DETACH 65 using, to view a message
IF 69 structure 149
INSERT 70 transforming data from one data type to
MOVE 71 another (CAST) 111
overview 3, 4 TRIM, string manipulation function 89
PASSTHRU 73 TRUNCATE, numeric function 94
PROPAGATE 77 TYPE 53, 71
RETURN 79
Feel free to comment on what you regard as specific errors or omissions, and on
the accuracy, organization, subject matter, or completeness of this book.
Please limit your comments to the information in this book and the way in which
the information is presented.
To make comments about the functions of IBM products or systems, talk to your
IBM representative or to your IBM authorized remarketer.
When you send comments to IBM, you grant IBM a nonexclusive right to use or
distribute your comments in any way it believes appropriate, without incurring
any obligation to you.
You can send your comments to IBM in any of the following ways:
v By mail, to this address:
User Technologies Department (MP095)
IBM United Kingdom Laboratories
Hursley Park
WINCHESTER,
Hampshire
SO21 2JN
United Kingdom
v By fax:
– From outside the U.K., after your international access code use
44–1962–816151
– From within the U.K., use 01962–816151
v Electronically, use the appropriate network ID:
– IBM Mail Exchange: GBIBM2Q9 at IBMMAIL
– IBMLink: HURSLEY(IDRCF)
– Internet: [email protected]
Printed in U.S.A.
SC34-6172-00
Spine information:
WebSphere MQ Integrator Broker WebSphere MQ Integrator Broker ESQL Reference Version 2.1