DECLARE statement

The DECLARE statement defines a variable, the data type of the variable and, optionally, its initial value.

SYNTAX

  1. The SHARED keyword is not allowed within a function or procedure.
  2. You cannot specify SHARED with a DataType of REFERENCE. (To store a message tree in a shared variable, use the ROW data type.)
  3. EXTERNAL variables are implicitly constant.
  4. It is good programming practice to give an EXTERNAL variable an initial value.
  5. If you specify a DataType of REFERENCE, you must specify an initial value (of either a variable or a tree) in InitialValueExpression.
  6. When the NAMESPACE and NAME clauses are used the values are implicitly constant and of type CHARACTER.

Types of variable

You can use the DECLARE statement to define three types of variable:
External
External variables (defined with the EXTERNAL keyword) are also known as user-defined properties (UDPs): see User-defined properties in ESQL. They exist for the entire lifetime of a message flow and are visible to all messages passing through the flow. Their initial values (optionally set by the DECLARE statement) can be modified, at design time, by the Message Flow editor, or, at deployment time, by the BAR editor. Their values cannot be modified by ESQL.
Normal
"Normal" variables have a lifetime of just one message passing through a node. They are visible to that message only. To define a "normal" variable, omit both the EXTERNAL and SHARED keywords.
Shared
Shared variables can be used to implement an in-memory cache in the message flow, see Optimizing message flow response times. Shared variables have a long lifetime and are visible to multiple messages passing through a flow, see Long-lived variables. They exist for the lifetime of the execution group process, the lifetime of the flow or node, or the lifetime of the node’s SQL that declares the variable (whichever is the shortest). They are initialized when the first message passes through the flow or node after each broker start up.

See also the ATOMIC option of the BEGIN ... END statement. The BEGIN ATOMIC construct is useful when a number of changes need to be made to a shared variable and it is important to prevent other instances seeing the intermediate states of the data.

CONSTANT

Use CONSTANT to define a constant. You can declare constants within schemas, modules, routines, or compound statements (both implicit and explicit). The behavior of these cases is as follows:

A constant or variable declared within a routine overlays any parameters of the same name, and all constants and variables of the same name declared in a containing module or schema.

DataType

The possible values that you can specify for DataType are:
  • BOOL
  • BOOLEAN
  • INT
  • INTEGER
  • FLOAT
  • DEC
  • DECIMAL
  • DATE
  • TIME
  • TIMESTAMP
  • GMTTIME
  • GMTTIMESTAMP
  • INTERVAL: does not apply to external variables (EXTERNAL option specified)
  • CHAR
  • CHARACTER
  • BLOB
  • BIT
  • ROW: does not apply to external variables (EXTERNAL option specified)
  • REF: does not apply to external or shared variables (EXTERNAL or SHARED option specified)
  • REFERENCE-TO: does not apply to external or shared variables (EXTERNAL or SHARED option specified)
Note: If you specify a DataType of REFERENCE, you must also specify InitialValueExpression.

EXTERNAL

Use EXTERNAL to denote a user-defined property (UDP). A UDP is a user-defined constant whose initial value (optionally set by the DECLARE statement) can be modified, at design time, by the Message Flow editor, or overridden, at deployment time, by the Broker Archive editor. Its value cannot be modified by ESQL.

For an overview of UDPs, see User-defined properties in ESQL.

When a UDP is given an initial value on the DECLARE statement this becomes its default. However, any value specified by the Message Flow editor at design time, or by the BAR editor at deployment time (even a zero length string) overrides any initial value coded on the DECLARE statement.

All UDPs in a message flow must have a value, given either on the DECLARE statement or by the Message Flow or BAR editor; otherwise a deployment-time error occurs. At run time, after the UDP has been declared its value can be queried by subsequent ESQL statements but not modified.

The advantage of UDPs is that their values can be changed by operational staff at deployment time. If, for example, you use the UDPs to hold configuration data, it means that you can configure a message flow for a particular machine, task, or environment at deployment time, without having to change the code at the node level.

You can declare UDPs only in modules or schemas.

The following types of broker node are capable of accessing UDPs:
  • Compute
  • Database
  • Filter
  • Nodes derived from these node-types

Take care when specifying the data type of a UDP, because a CAST occurs to cast to the requested DataType.

Example 1

DECLARE mycolour EXTERNAL CHARACTER ‘blue'; 

Example 2

DECLARE TODAYSCOLOR EXTERNAL CHARACTER;
SET COLOR = TODAYSCOLOR;
where TODAYSCOLOR is a user-defined property that has a TYPE of CHARACTER and a VALUE set by the Message Flow Editor.

NAME

Use NAME to define an alias (another name) by which a variable can be known.

Example 1

-- The following statement gives Schema1 an alias of 'Joe'.
DECLARE Schema1 NAME 'Joe';  
-- The following statement produces a field called 'Joe'.
SET OutputRoot.XML.Data.Schema1 = 42; 
 
-- The following statement inserts a value into a table called Table1 
-- in the schema called 'Joe'.
INSERT INTO Database.Schema1.Table1 (Answer) VALUES 42; 

Example 2

DECLARE Schema1 EXTERNAL NAME;

CREATE FIRSTCHILD OF OutputRoot.XML.TestCase.Schema1 Domain('XML') 
                     NAME 'Node1' VALUE '1';

-- If Schema1 has been given the value 'red', the result would be:
<xml version="1.0"?>
<TestCase>
  <red>
    <Node1>1</Node1>
  </red>

NAMESPACE

Use NAMESPACE to define an alias (another name) by which a namespace can be known.

Example

This example illustrates a namespace declaration, its use as a SpaceId in a path, and its use as a character constant in a namespace expression:

       DECLARE prefixOne NAMESPACE 'http://www.example.com/PO1';

       -- On the right hand side of the assignment a namespace constant
       -- is being used as such while, on the left hand side, one is 
       -- being used as an ordinary constant (that is, in an expression).

       SET OutputRoot.XML.{prefixOne}:{'PurchaseOrder'} = 
                      InputRoot.XML.prefixOne:PurchaseOrder;

SHARED

Use SHARED to define a shared variable. Shared variables are private to the flow (if declared within a schema) or node (if declared within a module) but are shared between instances of the flow (threads). There is no type of variable that is visible more widely than at the flow level. For example, you cannot share variables across execution groups.

Shared variables can be used to implement an in-memory cache in the message flow, see Optimizing message flow response times. Shared variables have a long lifetime and are visible to multiple messages passing through a flow, see Long-lived variables. They exist for the lifetime of the execution group process, the lifetime of the flow or node, or the lifetime of the node’s SQL that declares the variable (whichever is the shortest). They are initialized when the first message passes through the flow or node after each broker start up.

You cannot define a shared variable within a function or procedure.

The advantages of shared variables, relative to a databases, are that:
  • Write access is very much faster.
  • Read access to small data structures is faster.
  • Access is direct. That is, there is no need to use a special function (SELECT) to get data, or special statements (INSERT, UPDATE, or DELETE) to modify data. Instead, you can refer to the data directly in expressions.
The advantages of databases, relative to shared variables, are that:
  • The data is persistent.
  • The data is changed transactionally.

These read-write variables, with a life greater than that of one message but which perform better than a database, are ideal for users prepared to sacrifice the persistence and transactional advantages of databases in order to obtain better performance.

With flow-shared variables (that is, those defined at the schema level), take care when multiple flows can update the variables, especially if the variable is being used as a counter. Likewise, with node-shared variables (that is, those defined at the module level), take care when multiple instances can update the variables.

Shared row variables allow a user program to make an efficient read/write copy of an input node’s message. This is generally useful and, in particular, simplifies the technique for handling large messages.

"There is a restriction that subtrees cannot be directly copied from one shared row variable to another shared row variable. Subtrees can be indirectly copied by using a non-shared row variable. Scalar values extracted from one shared row variable (using the FIELDVALUE function) can be copied to another shared row variable.

Example

For an example of the use of shared variables, see the "Message routing" sample program, which shows how to use both shared and external variables. The "Message routing" sample is in the Samples Gallery in the Message Brokers Toolkit.

Related concepts
ESQL overview
User-defined properties in ESQL
Related tasks
Developing ESQL
Creating dynamic field references
Configuring a message flow at deployment time using UDPs
Related reference
Syntax diagrams: available types
ESQL statements
ESQL data types in message flows
Message Flow editor
FIELDVALUE function