This topic discusses the use of dynamic variables in EventFlow applications. For related information about using dynamic variables in StreamSQL applications, see the DECLARE Statement topic in the StreamSQL Guide.
A dynamic variable is a variable you can declare for a StreamBase module that can thereafter be referenced by name in expressions in operators and adapters in that module. In the declaration, you can link each dynamic variable to an input or output stream in the containing module. You can also define dynamic variables before creating a stream.
A dynamic variable's value is updated when a tuple is received on the linked input stream or when a tuple is emitted from the linked output stream. For both EventFlow and StreamSQL applications, the scope of a dynamic variable is the containing module.
The value stored in a dynamic variable is obtained from a value in a tuple enqueued to the application. This tuple can be one of the tuples submitted to the application for processing, or it can be a control tuple, submitted to the application for the sole purpose of changing the application's configuration. The distinguishing characteristic of a dynamic variable is that its value can change while the application runs.
For example, your application might maintain a threshold value that is compared to a field value in each tuple processed. If the tuple field value is less than the threshold value, your application performs one set of operations. If the tuple field value is greater than or equal to the threshold value, your application performs a different set of operations.
If you do not provide an updating expression, the initial value you supply for that dynamic variable will be used at run time. However, if you do not supply an expression or if your application has no reason to change the threshold value while it runs, there is no reason to create a dynamic variable, and you can hard-code the desired value into the application. But if you want to have the capability of changing the threshold value while the application runs, then use a dynamic variable.
StreamBase infers the data type of dynamic variables based on the initial value, so use an explicit initial value. For example,
the initial values 100
, 100.0
, and 100L
declare variables of types int, double, and long, respectively. In some cases, you may need to use a casting function, such
as int(), double(), or long() to cast the initial value to the desired data type.
As a consequence of inferring the variable's data type from its initial value, you might encounter a typecheck message when
opening an application in Studio that was created with an earlier StreamBase release (where dynamic variables were scoped
per operator, not per module). The typecheck message includes text similar to: cannot convert expression
. Previous releases determined the data type of dynamic variables by testing the update expression. Now that the data type
is determined from the initial value, you may need to use a casting function in the initial value expression to allow a migrated
application to pass typechecking.
expr-name
of type double to type int
If you associate a dynamic variable to an output stream, and then disable the output stream on the canvas, the dynamic variable no longer updates.
The icons for input and output streams that are used to update dynamic variables are shown with (x)=
in the upper right of the icon.
The EventFlow tutorial in this section shows you how to define, initialize, and update a dynamic variable. The tutorial takes prices from an input stream and sends them to two output streams: one for prices above a certain threshold; another for prices below that threshold.
To split the prices, we use a Filter operator whose predicate compares each incoming price to the threshold, and we define the threshold as a dynamic variable. The application will have two input streams: one to accept a stream of price data, and a second input stream used to change the value of our threshold value as the application runs.
Follow these steps:
-
Create a new EventFlow application in StreamBase Studio, using
→ → . -
With your new application open in the EventFlow Editor, first add an input stream that can be used to update the dynamic variable:
-
Drag an input stream from the Palette to the canvas, and open the input stream's Properties view.
-
In the General tab, change the Name field to
UpdateVariable
. -
In the Edit Schema tab, add a double field named
NewThreshold
.
Note that while placing a stream on the canvas before creating a dynamic variable is normal practice, it is not a requirement. Updating streams do not need to be connected to any other component, but can be used on their own to update dynamic variables. In the event you do not want a dynamic variable to be updated by any stream, leave the input stream field empty.
-
-
Select the Dynamic Variables tab of the EventFlow Editor. Add a dynamic variable by clicking the plus button. Fill in the columns as follows:
Variable Name Updating Stream Updating Expression Initial Value Threshold UpdateVariable NewThreshold 100.0 This defines a dynamic variable called
Threshold
whose initial value (100.0
) is used when the application starts. After that, the value of Threshold is reset to the value of theNewThreshold
field whenever a tuple arrives on theUpdateVariable
stream.Tip
If you use the same name for a dynamic variable and for its updating expression field, Studio issues a typecheck warning. You can use the same name in both places if you qualify the field name with
input.
to distinguish the field name from the variable name.fieldname
You must do this because unqualified names in any expression are first resolved against the names of the module's dynamic variables, and only then against the names of fields in available streams. Using a qualified field name removes the equivocation and specifies that the updating expression is based on the field name, not the dynamic variable that happens to share the name.
-
Next, add another input stream to receive price data, and rename it
PricesIn
. In the Edit Schema tab, add a double field namedPrice
. -
Drag a Filter operator from the Palette to the canvas, and connect the
PricesIn
stream to it. -
In the Filter operator's Predicate Settings tab in its Properties view:
-
Enable the Create output port for non-matching tuples option.
-
For Output Port 1, enter this Predicate expression:
Price <= Threshold
This adds a second output port to the Filter operator, and sets up the operator to evaluate each arriving tuple. If the expression resolves to
true
(that is, ifPrice
is less than or equal to theThreshold
value), then output is emitted on output port 1. If the expression resolves tofalse
, output is emitted on port 2. -
-
Drag two output streams to the canvas. Name them
LowPricesOut
andHighPricesOut
. Connect these streams to the top and bottom output ports, respectively, of the Filter operator. -
Your application should now pass typechecking. Save the application.
-
Now run this application in Studio and manually enqueue values on the input stream, to observe what values get output on which streams. Then manually input a new threshold value on the
UpdateVariable
stream and confirm that the Filter's behavior has changed.
Any input or output stream can update a dynamic variable. A more advanced use of dynamic variables is to create an output
stream at any point in your application, resulting in a kind of feedback. As an example, you could make the output stream
of the Filter's second port be the updating stream, using an updating expression of NewThreshold * 2
. This would double the threshold every time a value exceeded the threshold.
When defining a dynamic variable, your updating expression might need to refer to more than one field in the updating stream
to build your expression. You can qualify such field names with input.
instead of repeating the updating stream's name. Thus, for a dynamic variable that updates from the sum of two fields, alpha
and beta
, in an updating input stream named UpdateVariable
, you can specify either of the following as your updating expression:
UpdateVariable.alpha + UpdateVariable.beta
input.alpha + input.beta
If the updating expression refers to a field with the same name as the dynamic variable, the field name in the updating expression
must be qualified with the name of the updating stream to distinguish the field from the dynamic variable itself. For example,
it is reasonable to have an expression dynvar + 1
to increment the dynamic variable dynvar
itself. However, if you intend to derive the expression value from the UpdateVariable
stream's field named dynvar
, then the expression must be UpdateVariable.dynvar + 1
.