This topic describes the StreamBase expression language and each of the built-in functions that you can use with StreamBase applications. In EventFlow applications, you use StreamBase functions in operators that take expressions. You can also use StreamBase expressions in statements in StreamSQL applications, as described in the StreamSQL Guide.
Reference Pages
| StreamBase Environment Variables |
| StreamBase Java System Properties |
| StreamBase Expression Language Functions |
This topic provides reference information for the StreamBase expression language.
StreamBase provides two types of functions:
- Simple Functions
-
The majority of functions in the StreamBase expression language are simple functions, which operate on a single tuple field at a time. You can use simple functions in expressions for any StreamBase operator (except the Heartbeat, Metronome, and Union operators, which do not accept expressions).
- Aggregate Functions
-
Aggregate functions are used on sets of data to return a single result. Aggregate functions evaluate columns of data from windows or tables. In EventFlow applications, aggregate functions can only be used:
-
In aggregate expressions in Aggregate operators
-
In output expressions in Query Operators that perform read operations
In StreamSQL applications, aggregate functions can be used in SELECT statements related to aggregate or query read operations.
-
StreamBase provides sample applications that feature custom functions for you to load into StreamBase Studio to see how they are built and configured. The custom sample applications are listed in Extending StreamBase Samples.
StreamBase Studio provides the following user assistance features to aid writing expressions:
- Expression Auto-completion
-
When the cursor is in a field in the Properties view that accepts expressions, press Ctrl+Space to open a command-completion dialog. Type a few letters to show the expression language functions that begin with those letters. Select a function to see its syntax and description in a separate pane. Press Enter to finish typing from the selected function. See Expression Auto-Completion and Content Assistance for more on auto-completion.
- Functions Tab in Properties View
-
The Functions tab shows a categorized list of all expression language functions. Type a regular expression in the filter box to narrow the selection to matching functions. Double-click a function name to see its syntax and description in the Detail sub-tab.
- Expression QuickRef Tab in Properties View
-
The Expression QuickRef tab shows a summary of the features of the expression language. Click one of the Show in Help links to open the corresponding section of this page in the Help window.
See Properties View for more information on these features.
If you do not find a built-in function that you need, you can use the StreamBase custom function APIs to implement your own function and configure your application to use it. Your custom functions can be written by extending the StreamBase APIs for Java or C++. For details on writing your own functions, see these topics in the API Guide:
You can call your custom functions in expressions by calling a function alias you have declared in the server configuration file, or by using calljava() or callcpp().
You can define aliases for your custom functions using the custom-function element in the StreamBase
Server configuration file. This allows you to reference your custom
functions directly, without using a calljava() or
callcpp() function. For example:
myCustomFunction(x, y)
See <custom-functions> for instructions on defining aliases for your custom functions.
Use the sbd --eval command to evaluate and test your expressions at the command prompt before using them in your StreamBase applications. sbd --eval works with simple functions, but not with aggregate functions. You must evaluate aggregate functions using other methods, such as running a test application and checking the results.
On Windows, be sure to run sbd --eval from the StreamBase Command Prompt, not a standard Windows command prompt.
Note
Some functions in the StreamBase expression language do not work with
sbd --eval because the
--eval option causes sbd to run with a limited environment and immediately
exit after the function evaluation. This includes any function that requests the
status of the server or its environment, or that requests a further function
evaluation.
The following expression language functions are not expected to work with sbd --eval: get_conf_param(), get_boolean_conf_param(), get_inf_conf_param(), get_long_conf_param(), get_double_conf_param(), getClientIP(), getContainer(), getLeadeshipStatus(), getNodeName(), getParallelRoot(), getPath(), getServerURI(), securitytag(), and eval().
The following examples show how to use sbd --eval. These examples work as shown at the StreamBase Command Prompt on Windows and at the Bash prompt on Linux. See Using Quotes in Expressions for further details on the quoting rules for StreamBase expressions.
-
You can evaluate any expression, whether or not it contains an expression language function. For example:
sbd --eval "1e1 * (15 % -4)"
returns:
(double) 30.0
-
For Windows, you must surround with double quotes the entire expression you are testing. For Bash, you can use either double or single quotes, but using double quotes is recommended. The next example tests the cube root function:
sbd --eval "cbrt(27)"
which returns:
(double) 3.0
-
If you need to quote strings in your expression, you can either escape the extra double quotes with a backslash or use single quotes inside the surrounding double quotes. For example, the following commands are interpreted the same:
sbd --eval "list('alpha', 'beta', 'gamma')" sbd --eval "list(\"alpha\", \"beta\", \"gamma\")"Both commands return:
(list(string)) [alpha, beta, gamma]
Note
See Using Quotes in Expressions for further details on using quotes in expressions.
-
For another example of quote escaping, consider the following format_time() function. Both of these versions work on both Windows and Linux:
sbd --eval "format_time(now(), 'EEEE, MMM d, yyyy HH:mm zzzz')" sbd --eval "format_time(now(), \"EEEE, MMM d, yyyy HH:mm zzzz\")"
Both versions return the current time, formatted like this example:
(string) Tuesday, Feb 24, 2009 17:17 GMT-05:00
-
You can use sbd --eval to generate the correct CSV tuple format to use as input for sbc enqueue. For example, when defining a complex tuple that contains nested tuples, use syntax like the following for sbd --eval. (This command is a single unbroken line, shown on two lines for publication clarity):
sbd --eval "tuple(3.14159 as Math, tuple('IBM' as Stock, tuple(1 as X, 2 as Y, 3 as Z) as Inner) as Outer)"This returns:
((double, (string, (int, int, int)))) 3.14159,"IBM,""1,2,3"""
Now use the returned value to enter this tuple for sbc enqueue:
3.14159,"IBM,""1,2,3""" -
With typing patience and some trial and error, you can test any expression with sbd --eval, however complex. The following example tests the example shown in this Guide for the zip() function. First, build the example tuple with the tuple() function. (This command is a single unbroken line, shown on two lines for publication clarity):
sbd --eval "tuple( list(102.51, 96.82, 36.33) as prices, list('AAPL', 'IBM', 'HPQ') as symbols )"This returns:
((list(double), list(string))) "[102.51,96.82,36.33]","[AAPL,IBM,HPQ]"
Once you have the tuple() function returning a valid value, surround it with the zip() function:
sbd --eval "zip(tuple( list(102.51, 96.82, 36.33) as prices, list('AAPL', 'IBM', 'HPQ') as symbols ) )"This returns:
(list((double, string))) [102.51,AAPL, 96.82,IBM, 36.33,HPQ]
Expressions often need quotes around string values to designate those values as strings. The StreamBase expression language is agnostic about whether to use double or single quotes in expressions. For example, StreamBase interprets the following expressions identically when used in an expression in an operator or adapter in StreamBase Studio or in a StreamSQL statement:
strftime("Traded on %b %d, %Y at %H:%M", now())
strftime('Traded on %b %d, %Y at %H:%M', now())
The only rule is that you must escape any instance of the same quote mark if you need to use it again inside a pair of quote marks. You can escape a quote mark with a preceding backslash, or you can surround it with the opposite quote mark. For example, StreamBase interprets the following lines identically in Studio or in StreamSQL:
strftime('Traded at Miller\'s Crossing on %b %d, %Y at %H:%M', now())
strftime("Traded at Miller's Crossing on %b %d, %Y at %H:%M", now())
The simple rules for using quote marks in StreamBase expressions in Studio are complicated by the shell's quoting rules when testing expressions at the command prompt with sbd --eval.
On Windows, when using the StreamBase Command Prompt, you must surround the entire
expression with double quotes when using sbd
--eval. This is a requirement of the cmd.exe shell, not StreamBase. You can still use
either backslash escaping or single quotes inside the surrounding double quotes.
For example, StreamBase resolves the following example commands
identically at the StreamBase Command Prompt:
Works on Windows:
sbd --eval "strftime(\"Traded on %b %d, %Y at %H:%M\", now())"
sbd --eval "strftime('Traded on %b %d, %Y at %H:%M', now())"
The Bash shell is more forgiving, both under Linux and under Cygwin on Windows. Bash accepts either double or single quotes surrounding the argument to sbd --eval. For example, StreamBase resolves the following commands identically at the Bash prompt:
Works on Bash under Linux or Cygwin:
sbd --eval "strftime(\"Traded on %b %d, %Y at %H:%M\", now())"
sbd --eval "strftime('Traded on %b %d, %Y at %H:%M', now())"
sbd --eval 'strftime("Traded on %b %d, %Y at %H:%M", now())'
However, Bash does not allow the following version:
Does NOT work on Bash:
sbd --eval 'strftime(\'Traded on %b %d, %Y at %H:%M\', now())'
You may have to experiment with different quoting styles and quote escaping styles to get a complex command to run with sbd --eval.
Expressions use the StreamBase static data types:
| blob | long |
| bool | string |
| double | timestamp |
| int | tuple |
| list |
These data types are described in detail in StreamBase Data Types.
To recast data types, use one of the StreamBase type
conversion functions. For example, to cast a value to a double in an expression,
use the double() function. To cast a value to a string,
use the string() function, and so on. Casting may not
be necessary if type coercion is supported for the data types, as described in the
next section.
Some StreamBase functions support data type coercion of input arguments
from long to double data types. Type coercion is the
implicit conversion of a value from one data type to another. For example, the
floor() function is listed in this reference as taking a double
argument. However, you can enter an integer or long value instead, and the function
implicitly converts the value to its double equivalent.
The following are the supported data type coercions:
| Input data type | Converts to |
|---|---|
| int | long |
| int | double |
| long | double |
| list(int) | list(long) |
| list(int) | list(double) |
| list(long) | list(double) |
| list(tuple) merging with different list(tuple) | list(tuple), if a valid supertype of the two tuples can be found |
| sub-tuple field with unmatched schema | sub-tuple field with unioned schema |
Observe the following rules for coercion:
-
For long-to-double coercion where the precision of the long cannot be preserved in the double, Java rounding rules apply.
-
When entering data to a stream whose schema contains a field of type tuple, StreamBase attempts to coerce the data into the sub-tuple fields using the same rules as for a loose union in the Union operator.
-
Coercion rules do not apply to output streams with declared, explicit schemas.
Expressions are case sensitive. Function names are usually all lowercase, with a few exceptions. If you add custom functions, follow the lowercase convention.
StreamBase identifier naming rules apply to the name you assign to any StreamBase component, including schemas, fields, operators, tables, modules, containers, and data source names. The rules are:
-
Use only alphabetic characters, numbers, and underscores.
-
The first character must be alphabetic or an underscore.
-
Do not use hyphens or other special characters.
Note
StreamBase may create internal identifiers that include colons, but you cannot use colons in your identifiers.
StreamBase supports a syntax for escaping identifier names that contain reserved characters. If you enter a name that does not follow the above rules, StreamBase automatically stores the name with escaped identifier syntax. StreamBase Studio shows a warning when it needs to change a name you entered to use the alternate syntax.
The escaped identifier syntax is #", a pound or hash symbol, with
the string in double quotes. Escaped identifiers work throughout
StreamBase for the names of all components. You can use this syntax to
name a field the same as a StreamBase reserved word, such as
name"#"AS".
Identifier names can include Unicode characters as long as Unicode support is enabled for both Studio and Server, as described in Unicode Support.
When you name fields, do not use the following words, which are reserved for use in the expression language:
| and | as | between |
| else | false | if |
| or | not | null |
| then | true |
In EventFlow applications, StreamBase Studio does not prevent you from naming a field with a reserved word in an input stream's Properties view. However, a schema that contains a reserved word causes one or more typecheck errors in downstream components. The error message in the Typecheck view identifies the offending field's name. To correct the typecheck error, rename the field in the input stream's Properties view.
In StreamSQL applications, Studio prevents you from using a reserved word as a field name when defining schemas, or as a field in an index specification, order-by specification, or gather key.
Although the names of StreamBase data types are not reserved words, StreamBase Systems recommends that you do not use data type names as field names, for clarity when developing and debugging your applications. The data type names are listed in Data Types.
The StreamSQL language has an additional list of reserved words, as shown in StreamSQL Reserved Words.
If a name conflict occurs in a field name that is used in an expression within an operator instance, you can qualify the name to clarify the inbound stream you mean.
For example, in the Properties view for a Gather operator, you can qualify the fields
as input[port-number].field-name.
Example: input1.is_alarm, input2.is_alarm,
input3.is_alarm.
In the Properties view for a Join operator, you can qualify the fields in the two
input streams as input1.field-name and
input2.field-name. The input1.field-name refers to a field in the stream
arriving at the top port (#1). The input2.field-name refers to a field in the stream
arriving at the bottom port (#2).
Examples:
input1.SKU input2.SKU
In the Properties view for a Query operator, you can qualify the fields in the two
input streams as input.field-name and
old.field-name. The input.field-name refers to the current input tuple,
while old.field-name refers to the field's
prior value.
Examples:
Table1_current_Name Nasdaq100Table_old_Symbol
Important
In any expression anywhere in StreamBase, unqualified names are
resolved first against the names of any dynamic variables in the current module,
and then against the names of fields in currently available streams. This means
that a dynamic variable named foo can mask a field
also named foo, depending on the context.
One consequence of this rule: If you use the same name for a dynamic variable and
for its updating expression field, StreamBase Studio issues a
typecheck warning. To distinguish a dynamic variable from the same-named field in
the updating stream, qualify the field name with input., or just
rename the field.
fieldname
You can use +, –, *, /, and %. The ^ expression is not supported.
For example, in the Compliance sample provided in the StreamBase
installation, the is_alarm field is a bool. In one of
the Compliance application's Map operators, we use the following expression for the
is_alarm check on each tuple:
((((sector_in_fund_value_t + (shares_traded * price_at_trade)) * 100) / fund_value_t) > 25)
This expression is designed to execute the 25% sector test, where one sector is not
allowed to be more than 25% of the total fund value. is_alarm is set to true if the test
fails.
The modulus operator (%) finds the remainder of a division operation. Division and
modulus are always related such that a/b*b+(a%b) ==
a, where a/b is an integer
division. For example, 15%4 can be resolved as follows:
as:
15 / 4 * 4 + MOD == 15 3 * 4 + MOD = 15 12 + MOD = 15 MOD = 3
This relationship is preserved with negative divisors. As a result, whenever the quotient is negative, the modulus is negative. For example:
15 % 4 = 3 15 % -4 = 3 -15 % 4 = -3 -15% -4 = -3
Also note that if you divide a smaller number by a larger number, the modulus is always the smaller number. For example:
4 % 15 = 4
This behavior may be different than modulus in some programming languages.
Tip
The easiest way to understand StreamBase modulus operations is to try out different expressions using the sbd --eval command as described in Evaluating Expressions with sbd --eval.
Unary operators act on only one operand in an expression. –a is valid for integer, double, and long types. !a is valid for the bool type. +a is
not supported.
You can use the <, <=, = or ==, >, >=, and != relational operators. The relational operator <> is not supported.
StreamBase data types are comparable with relational operators in different ways, as listed in the entry for each data type on StreamBase Data Types.
You can use && or AND, || or OR, and !.
| Logical Operator | Meaning |
|---|---|
| && or AND | AND |
| || or OR | OR |
| ! | NOT |
Note
The evaluation of expressions using && and || will short-circuit. This means that after StreamBase encounters the first term that evaluates as false, no other terms in a statement using && are evaluated. Similarly, evaluation of a statement using || stops after the first true term.
For related information on Boolean logic and nulls, see Using Nulls.
The precedence order of mathematical operators in expressions, from highest to lowest, is as follows:
-
Unary operators: ! and –
The logical negation operator, !, reverses the meaning of its operand.
The unary negation operator, –, produces the negative of its operand.
-
Multiplicative operators: * and / and %
Multiplication: *
Division: /
Modulus, the remainder from division: %
-
Additive operators: + and –
Addition: +
Subtraction: –
-
Relational operators: < and <= and > and >=
Less than: <
Less than or equal to: <=
Greater than: >
Greater than or equal to: >=
-
Equality operator: == or =
-
Not equal: !=
-
Logical AND: && or AND
-
Logical OR: || or OR
You can use parentheses in expressions to override the default precedence.
You can add comments to your expressions using either C-style comments or StreamSQL-style comments:
-
StreamSQL comments begin with two hyphens and extend to the end of the same line.
-
C-style comments being with slash-asterisk and end with asterisk-slash. You can insert C-style comments anywhere in the expression, including the middle of a line, and they can extend over multiple lines.
The following sample expression illustrates several uses of comments:
/* handle special APPL case */ if (input1.symbol=="APPL.N") then input2.symbol == "APPL" /* handle special IBM case */ else if (input1.symbol=="IBM.L") then input2.symbol == "IBM" else input2.symbol == input1.symbol -- accept the rest as given
This section describes how to specify literals in expressions, for each data type. (For information about the data types themselves, see StreamBase Data Types.)
- blob
-
Use the StreamBase blob() function, which converts a string to a blob.
Example:
blob("abcde")creates a blob containing the bytes representing the string"abcde". - bool
-
Use the literals
trueandfalse. - int
-
Enter a number that is in the range of the int data type.
Examples:
0and31337are both ints - double
-
Enter a number using a decimal point, or using scientific notation.
Examples:
10.0and1e1are both doubles. - long
-
Enter a number that is in the range of the long data type, appending L to the number.
Examples:
100Land3147483650Lare both longs.Note
If the L is omitted, StreamBase interprets your number as an int no matter how large the value is.
- list
-
Use the list() function to create a list from its arguments.
Examples:
list(23, 46, 889)returns(list(int)) [23, 46, 889].list("IBM", "AAPL", "ORCL")returns(list(string)) [IBM, AAPL, ORCL].Also see the range() function.
- string
-
You can use single quotes (
'string') or double quotes ("string") around strings. Escape characters are supported, as follows:Character Results in \" Double quotation mark \' Single quotation mark \n Newline \t Tab \b Backspace \r Carriage return \f Form feed \\ Backslash \u XXXXUnicode character with hex code point XXXXExamples:
String Literal Results in "He said, \"Hello.\"" He said, "Hello." 'She said, \'Hello.\' ' She said, 'Hello.' "A\tB" A<tab>B "A\nB" A<newline>B "C:\\WINDOWS" C:\WINDOWS "Copyright \u00A9 2050" Copyright © 2050 - timestamp
-
You cannot enter timestamp literals directly in expressions. Instead, use the StreamBase timestamp() function, which converts a string in a particular format to a timestamp. The string argument must be in the form of a time format pattern as defined in the
java.text.SimpleDateFormatclass described in the Sun Java Platform SE reference documentation. See timestamp() for examples.Also see the format_time(), parse_time() and format() functions. The maximum precision for timestamps is milliseconds.
- tuple
-
In expressions, define a single tuple using this syntax:
tuple (
valueASfieldname[,...]) [AStuplename]The tuple schema, delimited by parentheses, consists of one or more field specifications separated by commas. Each field name resolves to an instance of a StreamBase data type (including another tuple).
Use the AS keyword to specify field names in the result. Omit the outermost
ASin EventFlow expressions, where the tuple field's name is specified in StreamBase Studio. The outermost AS is required in StreamSQL.tuplenameTo cast a set of values as a tuple that conforms to an existing named schema, use the tuple() function.
You can use nulls in the StreamBase expression language, one for each of the simple data types:
blob(null) bool(null) double(null) int(null) long(null) string(null) timestamp(null)
The data type of a null is never implicit. You must specify the data type of any null you are using in the expression.
In general, when you apply any arithmetic operator or function with data-type(null) as one of the arguments, the result
is null. Three exceptions are the isnull() and
notnull() functions, which test whether an expression
evaluates to null, and the coalesce() and coalesce_tuples() functions, which select a non-null value from a
set of potentially null arguments.
| Expression Example | Result |
|---|---|
| 3 + int(null) | A null int |
| int(null) + int(null) | A null int |
| int(null) + bool(null) | A typecheck error. You cannot add an int and a bool. |
| if bool(null) then 3 else 4 | A null int |
| int(null) == int(null) | A null bool, because null is not equal to itself |
| int(null) != int(null) | A null bool, because null is not equal to itself |
| isnull(int(null)) | A bool that evaluates to true |
| notnull(int(null)) | A bool that evaluates to false |
To specify a null list, use the nulllist() function. See Null Lists for a discussion
of null lists compared to empty lists.
To specify a null tuple that uses a named schema, specify the name of the schema with
empty parentheses. For example, for the schema named nyse_data, the expression nyse_data()
creates a null tuple. See Null Tuples for a discussion of null tuples compared to empty tuples.
For more detailed information, see Using Nulls.
In an expression such as: if p then e1 else
e2, p must be a valid bool expression, and
both e1 and e2 must be
expressions that have the same type. If p is true, then e1 is evaluated and the
result returned. If p is false, e2 is evaluated and the result returned. In either case, the other
sub-expression is not evaluated.
Note
In the StreamBase expression language, each if clause must have a
pair of explicit then and else clauses. Should you create compound if clauses, to avoid ambiguity, remember to specify the
then and else clauses for
each if clause. For an example, see the next section.
You can use combinations of if-then and else-if-then statements to form compound conditional expressions.
For example:
if i==0 then "Buy" else if i==1 then "Sell" else if
i==2 then "Hold" else "None of the above"
Here is a second example, indented for clarity, where we nest an if then else in a then clause:
if p1
then
if p2
then A
else B
else
if p3
then C
else D
Notice how each if clause contains a then clause and an else clause.
You can enter an expression that performs concatenation. For a string variable, the concatenation expression is
stringvar1+stringvar2
For a numeric variable with a static string, the concatenation expression is
"staticstring" +numvar
For example: "foo" + a.
For two variables, the concatenation expression is
stringvar+numvar
For example: b+a.
When used with comparison operators ( == != > < <= >= ) you must compare time interval-to-interval, or timestamp-to-timestamp. You cannot use the comparison operators with interval-to-timestamp.
To express constant intervals, you can use the seconds() and minutes() functions.
For example, if you want to add 60 seconds to a timestamp, enter expressions such as:
t + seconds(60) t + minutes(1)
For more on comparing timestamp expressions, see timestamp Data Type.
You can declare global parameters in the StreamBase Server configuration
file, usually named sbd.sbconf, and can define module
parameters in the Parameters tab of the EventFlow Editor. You can reference either
parameter type in StreamBase expressions. See Constants, Variables,
and Parameters for more on the difference between global and module parameters.
To reference a parameter in an expression, wrap the parameter name in braces and
prefix the open brace with a dollar sign: ${parameter}. If you are referencing a parameter
that is defined as a string, use quotes around the entire reference: "${parameter}"
StreamBase Server Configuration File XML Reference explains how to declare global parameters. For example, consider a server configuration file that defines the following two global parameters:
<operator-parameters>
<operator-parameter name="MyInt" value="2"/>
<operator-parameter name="MyString" value="somestring"/>
</operator-parameters>
You could reference the first parameter (for example, in an output field) using an
expression like 35 * ${myInt}. The
expression would evaluate at run time to 70. The
following StreamSQL statement references the second parameter:
SELECT * FROM InputStream1 "${MyString}" AS
source
Notice the quotation marks, which are needed so that the expression is resolved as a string.
Note
Expression parameters can be referenced in both EventFlow and StreamSQL applications. However, if you convert an EventFlow application file to a StreamSQL file, any expression parameters in the EventFlow module are resolved during the conversion, and the value of the parameter is copied to the StreamSQL file. The parameter itself is not preserved.
