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 16bit integer), Int32
(a 32bit integer), Int64
(a 64bit 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,1e4
,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
) and2 ^ 31
(= 2147483648
).The
L
suffix is used to createInt64
literals (e.g.,14L
). AnInt64
literal must be between2 ^ 63  1
(= 9223372036854775807L
) and2 ^ 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
subexpressions on each side. An expression in UEL can also contain the unary minus (
) operation that expects a
subexpression 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 subexpressions 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 subexpressions 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 subexpressions of type Bool
on each side. Shortcutting is
used to evaluate the logical operations. For logical and, if the subexpression on the left evaluates to false
,
then the subexpression on the right is not evaluated and the result is false
. For logical or, if the
subexpression on the left evaluates to true
, then the subexpression 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
subexpression 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 subexpressions 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 subexpression 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
), noncontainment (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
. Noncontainment 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 subexpression of that type is expected.
Attribute names that contain alphanumeric 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 floatingpoint 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:
Builtin 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 nonequality. 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
and11 % 4 = 3
If the operands have opposite signs, then the result may differ across databases. E.g.:11 % 4
may either be3
or1
.11 % 4
may either be3
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 datetime value is almost the same for all databases. E.g.:
"20100301" + 1 month = "20100401"
and"20100331" + 1 month = "20100430"
If the initial date or datetime value is the last day of the month, some databases skip to the last day of the resulting month. E.g.:"20100430" + 1 month
is either20100531
or20100530
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.