UEL
The Unscrambl Chai Expression Language (UEL)
Introduction
The Unscrambl Chai Expression Language (UEL) is a simple expression language used to specify derived attribute expressions. It is based on the Drive UEL.
Types
An expression in UEL can have one of the following primitive types: String
(a string), Bool
(a Boolean),
Int16
(a 16-bit integer), Int32
(a 32-bit integer), Int64
(a 64-bit integer), or Double
(a double
precision floating point number). It can also have a list type, where the element type of the list is one of the
primitive types: List(String)
, List(Bool)
, List(Int16)
, List(Int32)
, List(Int64)
, List(Double)
.
It can also have a temporal type where the element type of the expression can be DateTime
.
Literals
Bool
, Double
, Int32
, Int64
, and String
literals can be present in an expression.
A
Bool
literal can be eithertrue
orfalse
.A
Double
literal is a decimal number that either contains the decimal separator (for example,3.5
,.5
,3.
) or is given in the scientific notation (for example,1e-4
,1.5e3
). ADouble
literal must be between(2 - 2 ^ -52) * 2 ^ 1023
(~ 1.79 * 10 ^ 308
) and-(2 - 2 ^ -52) * 2 ^ 1023
(~ -1.79 * 10 ^ 308
). The magnitude of a literal cannot be less than2 ^ -1074
(~ 4.94 * 10 ^ -324
).Integer literals without a suffix are of the
Int32
type (e.g.,14
). AnInt32
literal must be between2 ^ 31 - 1
(= 2147483647
) and-2 ^ 31
(= -2147483648
).The
L
suffix is used to createInt64
literals (e.g.,14L
). AnInt64
literal must be between2 ^ 63 - 1
(= 9223372036854775807L
) and-2 ^ 63
(= -9223372036854775808L
).A
String
literal appears within double quotes, as in"I'm a string literal"
. The escape character\
can be used to represent new line (\n
), tab (\t
), double quote (\"
) characters, as well as the escape character itself (\\
).
Arithmetic operations
An expression in UEL can contain the basic arithmetic operations: addition (+
), subtraction (-
), multiplication
(*
), and division (/
), and modulo (%
) with the usual semantics. These are binary operations that expect
sub-expressions on each side. An expression in UEL can also contain the unary minus (-
) operation that expects a
sub-expression on the right. Parentheses (()
) are used for adjusting precedence.
Addition operation corresponds to concatenation for the String
type and is the only available operation on this
type. Bool
type does not support arithmetic operations. Division applies integer division on integer types and
floating point division on Double
types.
Examples:
A simple arithmetic expression:
(3 + 4 * 5.0) / 2
A simple expression involving a
String
literal:"area code\tcountry"
A unary minus expression:
-(3 + 5.0)
Comparison operations
An expression in UEL can contain the basic comparison operations: greater than (>
), greater than or equal (>=
),
less than (<
), less than or equal (<=
), equals (==
), and not equals (!=
) with the usual semantics.
These are binary operations. With the exception of equals and not equals, they expect sub-expressions of numerical types
or strings on each side. For strings, the comparison is based on lexicographic order. For equals and not equals, the
left and the right sub-expressions must be of compatible types with respect to UEL coercion rules. The result of the
comparison is always of type Bool
.
Examples:
An expression using comparisons:
3 > 5
An expression using String comparisons:
"abc" < "def"
An expression using inequality comparison:
"abc" != "def"
Logical operations
An expression in UEL can contain the basic logical operations: logical and (&&
) and logical or (||
) with the
usual semantics. These are binary operations that expect sub-expressions of type Bool
on each side. Shortcutting is
used to evaluate the logical operations. For logical and, if the sub-expression on the left evaluates to false
,
then the sub-expression on the right is not evaluated and the result is false
. For logical or, if the
sub-expression on the left evaluates to true
, then the sub-expression on the right is not evaluated and the result
is true
. An expression in UEL can also contain the not (!
) operator, which is a unary operator that expects a
sub-expression of type Bool
on the right.
Examples:
A simple logical expression:
3 > 5 || 2 < 4
A logical expression that uses not:
! (3 > 5)
Ternary operation
An expression in UEL can make use of the the ternary operation: condition ? choice1 : choice2
. The condition of the
ternary operation is expected to be of type Bool
and the two choices are expected to be sub-expressions with
compatible types. The ternary operation is lazily evaluated. If the condition evaluates to true
, then the result is
the first choice, without the sub- expression for the second choice being evaluated. If the condition evaluates to
false
, then the result is the second choice, without the sub-expression for the first choice being evaluated.
Examples:
A simple ternary operation:
3 < 10 ? "smallerThan10" : "notSmallerThan10"
List Operations
A list is constructed by specifying a sequence of comma (,
) separated values of the element type, surrounded by
brackets ([]
) . For instance, an example literal for List(Double)
is [3.5, 6.7, 8.3]
and an example for
List(String)
is ["Unscrambl", "Drive"]
. An empty list requires casting to define its type. As an example, an
empty List(String)
can be specified as List(String)([])
.
An expression in UEL can contain a few basic list operations: containment (in
), non-containment (not in
).
Containment yields a Boolean answer, identifying whether an element is contained within a list. For instance, 3 in [2,
5, 3]
yields true
, whereas 8 in [2, 5, 3]
yields false
. Non-containment is the negated version of the
containment. For instance, 3 not in [2, 5, 3]
yields false
, whereas 8 not in [2, 5, 3]
yields true
.
Precedence and Associativity of Operations
Operations |
Associativity |
---|---|
|
|
|
|
unary |
|
|
left |
|
left |
|
left |
|
left |
|
|
|
left |
|
left |
|
Attributes
Expressions in UEL can also contain attributes. Attributes are identifiers that are defined in the Querybot Entity Relationship Model. Each attribute has a type and can appear in anywhere a sub-expression of that type is expected.
Attribute names that contain alpha-numeric characters and underscores can be used as is in the expression. Attributes
names that contain spaces or any other unicode characters have to be enclosed in an attribute identifier
$"attribute with spaces"
.
Examples:
A string formed by concatenating an attribute named
first name
and an attribute namedlast name
from the current entity:$"first name" + $"last name"
An arithmetic expression involving an attribute and
Int32
literals:numSeconds / (24 * 60 * 60)
A floating-point arithmetic expression, where the floating point literal is of type
Double
:cost / 1000.0
A Boolean expression checking if a
String
literal is found in an attribute namedplaces
of typeList(String)
:"airport" in places
A ternary expression indicating if the
cost
of a product is high or lowcost < 100 ? "Low" : "High"
Null values
Attributes in UEL are nullable, that is, attributes can take null values. To denote a null value, the null
keyword is used.
Only the following actions are legal on the expressions with null values:
Built-in function calls: A nullable function parameter can take a null value. E.g.: the first parameter in the
string.concat(null)
callTernary operations: The values returned from choices can be null. E.g.:
amount > 100 ? "High" : null
whereamount
is an attribute of theString
typeList items: Null values can be list items. E.g.:
[null, 3, 5, 6, null]
List containment check operations: Null values can be used on the left hand side. However, the result will be
null
independent of the contents of the list. E.g.:null not in [null, 3, 5, 6, null]
Equality check operations: Null values can be compared for equality and non-equality. E.g.:
$"purchase notes" == null
wherepurchase notes
is an attribute. (Note: For comparisons with null values, theisNull
operator can also be used. Examples:isNull(null)
yieldstrue
isNull($"purchase notes")
yieldsfalse
if thepurchase notes
attribute is not null)
Database specific behaviors
String concatenation: The
string.concat
function and the string addition operation can output different results for inputs containingNULL
database values. Some databases flag this operation as invalid and returnNULL
. Other databases discard theNULL
values and concatenate the remaining strings. E.g.:"string" + null + "concatenation"
yields eitherstringconcatenation
orNULL
E.g.:name + "," + $"nullable profession"
. Whennullable profession
attribute is notNULL
the result is the same for all databases E.g.Tom Hanks,Actor
. Whennullable profession
attribute isNULL
the result can either beNULL
orTom Hanks,
Modulo operator:
The modulo operation yields the remainder from the division of the first operand by the second. If both operands have the same sign, then the result is the same for all databases. E.g.:
11 % 4 = 3
and-11 % -4 = -3
If the operands have opposite signs, then the result may differ across databases. E.g.:11 % -4
may either be3
or-1
.-11 % 4
may either be-3
or2
Some databases support using floating point data types for the modulo operator. Others disallow this behavior and throw an error.
For modulo by zero case, most databases throw division by zero error. Other databases may return
NULL
or the first argument.
datetime.add: Adding or subtracting months from a date or date-time value is almost the same for all databases. E.g.:
"2010-03-01" + 1 month = "2010-04-01"
and"2010-03-31" + 1 month = "2010-04-30"
If the initial date or date-time value is the last day of the month, some databases skip to the last day of the resulting month. E.g.:"2010-04-30" + 1 month
is either2010-05-31
or2010-05-30
Rounding: The
number.round
function can output different results in case of the supplied value is halfway between two integers (E.g.-0.5
,1.5
). Some databases round halves to the nearest even integer (E.g.-0.5 -> 0
,1.5 -> 2
), and some databases round halves away from zero (E.g.-0.5 -> -1
,1.5 -> 2
). Some databases choose different strategies depending on the input data type. The behavior of this function matches the behavior of the underlying database.