StreamBase Expression Language and Functions

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 (except Heartbeat, Metronome, Split, and Union, which do not take an expression). You can also use StreamBase expressions in statements in StreamSQL applications, as described in the StreamSQL Guide.

Pointer to StreamBase Functions

For information on the functions provided by StreamBase, start with StreamBase Functions.

Also see the Alphabetical Index of StreamBase Functions.

Evaluating Expressions

A useful tool for understanding and testing simple expressions is the sbd --eval command, documented in the sbd help topic. Use sbd --eval to test the results of simple expressions as you read this topic, and before using them in your StreamBase applications. For example:

$ sbd --eval "1e1 * (15 % -4)"

(double) 30.0

sbd --eval does not work with aggregate functions. You must evaluate aggregate functions using other methods, such as running a test application and checking the results.

Back to Top ^

Data Types

Expressions use the StreamBase static data types. The currently supported types are:

blob

Represents binary data, such as multimedia objects.

bool

Evaluates to true or false.

int

A 4-byte signed integer in the range -2147483648 to 2147483647.

double

An 8-byte double-precision numeric value.

long

An 8-byte signed integer in the range -9,223,372,036,854,775,808 [-263] to +9,223,372,036,854,775,807 [263 -1].

string

A text field whose size (up to 2 gigabytes) must be declared.

timestamp

A date and time representation in the format YYYY-MM-DD hh:mm:ss[.sss][+TTTT]. The maximum precision is milliseconds.

tuple

An ordered collection of fields, each of which has a name and a data type. The fields in the collection must be defined by a schema, and can be of any StreamBase data type, including other tuples. The size of a tuple depends on the aggregate size of its fields.

See StreamBase Data Types for details.

Case Sensitivity

Expressions are case sensitive. Function names should be all lowercase.

Identifiers

StreamBase identifier naming rules apply to the name you assign to any StreamBase component, including schemas, fields, operators, tables, lock sets, modules, 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 creates internal identifiers that include colons, but you cannot use colons in your identifiers.

Reserved Words

When you name fields, do not use the following reserved words:

  • blob

  • bool

  • double

  • else

  • false

  • if

  • int

  • long

  • null

  • string

  • then

  • timestamp

  • then

  • true

  • tuple

In an Input Stream's Properties view, StreamBase Studio does not prevent you from specifying a reserved word for a field name. However, a schema that contains reserved words causes one or more typecheck errors in the connected downstream components. The error message in the Typecheck view identifies the offending field's name. Rename the field in the input stream's Properties view.

Back to Top ^

Qualifying Field Names

If a name conflict occurs in a field name that's used in an expression within an operator instance, you can qualify them 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 old (prior) value.

Examples:

Table1_current_Name
Nasdaq100Table_old_Symbol

Arithmetic Operators

You can use +, –, *, /, and %. The ^ expression is not supported.

For example, in the Compliance sample provided with the StreamBase kit, the is_alarm field is a bool. In one of the Compliance application's Map operators, we use this 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.

Modulus Operators

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.

Back to Top ^

Unary Operators

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.

Relational Operators

You can use the <, <=, = or ==, >, >=, and != relational operators. The relational operator <> is not supported.

Logical Operators

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.

Precedence Order

The precedence order of mathematical operators in expressions, from highest to lowest, is as follows:

  1. Unary operators: ! and –

    The logical negation operator, !, reverses the meaning of its operand.

    The unary negation operator, –, produces the negative of its operand.

  2. Multiplicative operators: * and / and %

    Multiplication: *

    Division: /

    Modulus, the remainder from division: %

  3. Additive operators: + and –

    Addition: +

    Subtraction: –

  4. Relational operators: < and <= and > and >=

    Less than: <

    Less than or equal to: <=

    Greater than: >

    Greater than or equal to: >=

  5. Equality operator: == or =

  6. Not equal: !=

  7. Logical AND: && or AND

  8. Logical OR: || or OR

You can use parentheses in expressions to override the default precedence.

Back to Top ^

Casting

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. See the next section.

Data Type Coercion

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: the function implicitly converts the value to its double equivalent.

There are only two possible data type coercions:

Input data type Converts to
int long
long double

Observe the following rules for coercion:

  • You can supply an int value for a double argument: the intermediate coercion to long happens implicitly.

  • For long-to-double coercion where the precision of the long cannot be preserved in the double, Java rounding rules apply.

White Space

The StreamBase parser ignores any spaces, new lines, and tab characters in expressions.

Back to Top ^

Specifying Literals in Expressions

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 true and false.

int

Enter a number that is in the range of the int data type.

Examples: 0 and 31337 are both ints

double

Enter a number using a decimal point, or using scientific notation.

Examples: 10.0 and 1e1 are both doubles.

long

Enter a number that is in the range of the long data type, appending L to the number.

Examples: 100L and 3147483650L are both longs.

Note

If the L is omitted, StreamBase interprets your number as an int no matter how large the value is.

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
\\ Backslash

Examples:

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
timestamp

You cannot enter timestamp literals directly in expressions. Instead, use the StreamBase timestamp() function, which converts a string in the following format to a timestamp:

YYYY-MM-DD hh:mm:ss[.sss][+TTTT]

Also see the format_time(), parse_time() and format() functions. The maximum precision for timestamps is milliseconds.

Examples:

"2005-10-08" Implicit time of "00:00:00", local time zone
"2005-10-08 13:17" Implicit seconds of "00", local time zone
"2005-10-08 13:17:23" Local time zone
"2005-10-08 13:17:23.12355" Fractional seconds
"2005-10-08 13:17:23" == "2005-10-08 13:17:23"
"2005-10-08 24:00:00" == "2005-10-09 00:00:00"
"2005-10-08 13:17:23-0500" Explicit time zone (EST in this case)
"2005-10-08 13:17-05:00" Explicit time zone, implicit seconds
tuple

Define a tuple using this syntax:

tuple (field_identifier AS alias[,...]) [AS alias]

The tuple schema, delimited by parentheses, consists of one or more fields separated by commas. Each field identifier resolves to an instance of a StreamBase data type (including another tuple).

Use the AS method to set an alias in the result; however, it can be omitted in anonymous schemas when the field name can be implied from the expression. Omit the outermost alias in EventFlows, where the field name is specified in the GUI. It is required in StreamSQL.

  • This StreamSQL statement defines an output tuple field (named top) that contains a nested tuple:

    SELECT tuple(x AS x, tuple(a AS a, b AS b) AS my_nestedtuple) AS top FROM in INTO out;
    

    To define the same output field in an EventFlow, enter top as the field name in the Properties view table. Enter the same tuple expression, but omit the AS top clause.

  • Named schemas can be referenced as nested tuples. In this example, assume that a schema named point has already been defined in the application:

    tuple(x AS x, point AS point) AS pointref 
    
  • Fields from named schemas can be referenced in expressions using a dotted notation, like this:

    tuple(point.x + point.y) AS pointsum
    
  • In tuples with anonymous schemas, you can omit field names for direct selection. For example, these two expressions are equivalent:

    tuple(x, point.y)
    tuple(x AS x, point.y AS y)
    
  • Tuple fields can be useful for grouping fields from various sources. For example, consider this StreamSQL fragment:

    CREATE SCHEMA point(x double, y double);
    CREATE INPUT STREAM input (tag string(12), point);
    SELECT tuple(tag, point.x AS p) AS mixed FROM input;
    

    The first two statements define a named schema and an input stream that includes it. The last statement defines a nested tuple that includes the tag field and a single field from the point schema. It also renames the x field. The expression is equivalent to this:

    (tag string(12), p double)
    

To cast a set of values as a tuple that conforms to an existing, named schema, use the tuple(e[,...]) function.

Back to Top ^

Null Literals

You can use nulls in the StreamBase expression language, one for each data type:

blob(null)
bool(null)
int(null)
double(null)
long(null)
string(null)
timestamp(null)

Each null literal is case sensitive; for example, Int(NULL) is invalid. The data type of each null is never implicit: you must specify which type of 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() function, which selects a non-null value from a list 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

For related information, please see Using Nulls.

Back to Top ^

Conditional Expressions

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 will be evaluated and the result returned. If p is false, e2 will be 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, please see the next section.

Back to Top ^

Compound Conditional Expressions

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 1
            else 2
else
        if p2
            then 3
            else 4

Notice how each if clause contains a then clause and an else clause.

Back to Top ^

Concatenation in Expressions

You can enter an expression that performs concatenation. For a string variable, the concatenation expression is

stringvar + x

For example: b + 25. 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. Note that when you use an expression to concatenate a number to a string, the total size becomes the original string size + 12.

Back to Top ^

Timestamp Expressions

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, you can enter expressions such as:

t + seconds(60)
t + minutes(1)

Back to Top ^

Parameters in Expressions

You can declare operator-parameters in the sbd.sbconf file, and then use them as parameters within StreamBase expressions. StreamBase Server Configuration XML explains how to declare operator-parameters.

To then reference a parameter in an expression, wrap the operator-parameter name in braces and prefix the open brace with a dollar sign. If you are referencing an operator-parameter that is defined as a string, use quotes around the entire reference.

For example, consider an sbd.sbconf file that defines these two operator-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. This StreamSQL statement references the second parameter:

SELECT * FROM InputStream1 "${MyString}" AS source

Notice the quotation marks: they are needed so that the expression is resolved as a string.

Note

Expression parameters are distinct from both module parameters, which are described in Using Module Parameters, and StreamSQL CREATE PARAMETER statements:

  • A module parameter is defined only for a parameterized module (or, in StreamSQL, a Java operator or an embedded Java adapter), not globally in the sbd configuration.

  • If you use an expression parameter and a module parameter with the same name, the module parameter value takes precedence.

  • Expression parameters can only be used within expressions. StreamSQL parameters are more flexible: they can be used to represent expressions as well as other parts of a statement.

Note

Expression parameters can be referenced in both EventFlows and StreamSQL applications. However, if you convert an EventFlow application file to a StreamSQL file, any expression parameters are resolved during the conversion; the parameter itself is not preserved.

Back to Top ^

StreamBase Functions

This section provides reference information for all the StreamBase functions. You can also get help on functions directly in StreamBase Studio when you edit an expression: In the Properties view, the Functions tab shows the syntax of each function and provides editing shortcuts. See Properties View for details.

StreamBase provides two types of functions:

Simple functions are evaluated over one set of arguments, and return a single result. The strlen() function is an example of a simple function. Simple functions can be used in expressions for any StreamBase operator, except Heartbeat, Metronome, and Union, which do not use an expression.

Aggregate functions are evaluated over multiple sets of arguments and return a single result. In StreamBase applications, aggregate functions are used only in Aggregate operators and in Query operators that do query read operations. The avg() function, which calculates an average value for tuples in an Aggregate window, is an example of an aggregate function.

function_name(arg1,arg2,arg3,...)

StreamBase provides several sample applications that feature custom functions for you to load in StreamBase Studio to see how they are built and configured. The custom sample applications are listed in Extending StreamBase Samples.

Back to Top ^

Using Custom Functions in Expressions

In addition to the built-in functions provided with StreamBase, you can call custom functions that you have created by extending the StreamBase API for Java, C++, or .NET API. (See Developing Custom Functions to learn how.) After creating a custom function and configuring it in your project, you can call it in an expression using the calljava() or callcpp() functions. For example, the following expression uses calljava() to call a custom class and its arguments:

calljava(myCustomFunction, x, y)

Back to Top ^

Function Aliases

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.

Alphabetical Index of StreamBase Functions

For your convenience, here is a complete, alphabetized index into the available functions provided by StreamBase, with links to the function descriptions in this section. As described in the preceding section, if you do not find a built-in function that you need here, you can use the StreamBase custom function APIs to implement your own function and configure your application to use it. For details, please see these topics in the API Guide:

Function Name and Link to Section Category Simple or Aggregate Function
abs Math Simple function
acos Math Simple function
alpha Statistical calculations Aggregate function
avg Statistical calculations Aggregate function
asin Math Simple function
atan Math Simple function
atan2 Math Simple function
beta Statistical calculations Aggregate function
black_scholes Financial Simple function
blob Type conversions Simple function
bool Type conversions Simple function
callcpp (simple) C++ API call (simple) Simple function
callcpp (aggregate) C++ API call (aggregate) Aggregate function
calljava (simple) Java API call (simple) Simple function
calljava (aggregate) Java API call (aggregate) Aggregate function
catchexception Error checking Simple function
cbrt Math Simple function
ceil Math Simple function
closeval Windowing Aggregate function
coalesce Working with nulls Simple function
coalesce_tuples Working with nulls Simple function
compound_interest Financial Simple function
correlation_coefficient Statistical calculations Aggregate function
correlation_coefficientp Statistical calculations Aggregate function
cos Math Simple function
cosh Math Simple function
count Statistical calculations Aggregate function
count_distinct Statistical calculations Aggregate function
covariance Statistical calculations Aggregate function
covariancep Statistical calculations Aggregate function
date Timestamps Simple function
days Timestamps Simple function
double Type conversions Simple function
error Error checking Simple function
exp Math Simple function
exp_moving_avg Statistical calculations Aggregate function
expm1 Math Simple function
firstval Windowing Aggregate function
floor Math Simple function
format Strings Simple function
format_time Timestamps Simple function
from_gmtime Timestamps Simple function
from_localtime Timestamps Simple function
getContainer Java API call Simple function
getNodeName Java API call Simple function
get_day_of_week Timestamps Simple function
getLeadershipStatus Java API call Simple function
get_day_of_month Timestamps Simple function
get_hour Timestamps Simple function
get_minute Timestamps Simple function
get_month Timestamps Simple function
getPath Java API call Simple function
get_second Timestamps Simple function
get_year Timestamps Simple function
hash Type conversions Simple function
hours Timestamps Simple function
indexof Strings Simple function
inet_aton Internet Simple function
inet_ntoa Internet Simple function
int Type conversions Simple function
intercept Statistical calculations Aggregate function
interval Timestamps Simple function
isnan NaN (not a number) Simple function
isnull Working with nulls Simple function
lastindexof Strings Simple function
lastval Windowing Aggregate function
ln Math Simple function
log1p Math Simple function
log10 Math Simple function
long Type conversions Simple function
lower Strings Simple function
ltrim Strings Simple function
max (simple) Math Simple function
max (aggregate) Statistical calculations Aggregate function
median Statistical calculations Aggregate function
min (simple) Math Simple function
min (aggregate) Statistical calculations Aggregate function
minutes Timestamps Simple function
new_tuple Type conversions Simple function
not