Global functions
Rell has a diverse collection of built-in functions that you can use to perform common tasks and write efficient Rell code.
Essential calculations
abs(value: integer): integer
Gets the absolute value of an integer.
Parameters:
value: integer
- The integer for which to calculate the absolute value.
Returns:
- The absolute value of the input
value
as an integer.
abs(value: big_integer): big_integer
Gets the absolute value of a big integer.
Parameters:
value: big_integer
- The big integer for which to calculate the absolute value.
Returns:
- The absolute value of the input
value
as a big integer.
abs(value: decimal): decimal
Gets the absolute value of a decimal.
Parameters:
value: decimal
- The decimal for which to calculate the absolute value.
Returns:
- The absolute value of the input
value
as a decimal.
function max(value1: integer, value2: integer): integer
Identifies the larger of two integer values.
Parameters:
value1: integer
- The first integer to compare.value2: integer
- The second integer to compare.
Returns:
- The larger of the two input integers.
function max(value1: big_integer, value2: big_integer): big_integer
Determines the larger of two big integer values.
Parameters:
value1: big_integer
- The first big integer to compare.value2: big_integer
- The second big integer to compare.
Returns:
- The larger of the two input big integers.
function max(value1: decimal, value2: decimal): decimal
Determines the larger of two decimal values.
Parameters:
value1: decimal
- The first decimal to compare.value2: decimal
- The second decimal to compare.
Returns:
- The larger of the two input decimals.
function min(value1: integer, value2: integer): integer
Determine the smaller of two integer values.
Parameters:
value1: integer
- The first integer to compare.value2: integer
- The second integer to compare.
Returns:
- The smaller of the two input integers.
function min(value1: big_integer, value2: big_integer): big_integer
Identify the smaller of two big integer values.
Parameters:
value1: big_integer
- The first big integer to compare.value2: big_integer
- The second big integer to compare.
Returns:
- The smaller of the two input big integers.
function min(value1: decimal, value2: decimal): decimal
Pinpoint the smaller of two decimal values.
Parameters:
value1: decimal
- The first decimal to compare.value2: decimal
- The second decimal to compare.
Returns:
- The smaller of the two input decimals.
Collection checks
empty(value: T?): boolean
Determines if a value is null or an empty collection.
Parameters:
value: T?
- The value to check for emptiness, which can be any nullable type.
Returns:
True
if the value is null or an empty collection,False
otherwise.
empty(list: list<T>): boolean
Specifically checks if a list is empty.
Parameters:
list: list<T>
- The list to check for emptiness.
Returns:
True
if the list contains no elements,False
otherwise.
empty(set: set<T>): boolean
Verifies if a set is empty.
Parameters:
set: set<T>
- The set to check for emptiness.
Returns:
True
if the set contains no elements,False
otherwise.
empty(map: map<K, V>): boolean
Checks if a map is empty.
Parameters:
map: map<K, V>
- The map to check for emptiness.
Returns:
True
if the map contains no key-value pairs,False
otherwise.
Nested at-expressions
with empty()
The empty()
function supports nested at-expressions
, allowing them to access entities from an outer at-expression
.
This enhancement enables more complex and efficient database queries.
Example:
user @* {
empty(company @* { .city == user.city })
}
Translated SQL query:
SELECT U."name"
FROM "c0.user" U
WHERE NOT EXISTS(
SELECT C."rowid"
FROM "c0.company" C
WHERE C."city" = U."city"
)
Usage in update
and delete
statements:
delete user @* { empty( company @* { .city == user.city } ) } ;
Notes on cardinality:
- Use
@*
in nestedat-expressions
to ensure the entire query is executed as a single SQL query. - Using operators
@+
,@?
, or@
will result in independent SQL queries, potentially reducing performance due to loading the entire result set into memory.
Simplified attribute matching:
- In the
where
part of a nestedat-expression
, you can useouter_entity.attribute
directly.
Example:
user @* {
empty(company @* { user.city })
}
exists(value: T?): boolean
Confirms the presence of a value.
Parameters:
value: T?
- The value to check for existence, which can be any nullable type.
Returns:
True
if the value is not null and contains elements (for collections),False
otherwise.
exists(list: list<T>): boolean
Specifically verifies if a list contains elements.
Parameters:
list: list<T>
- The list to check for the existence of elements.
Returns:
True
if the list has at least one element,False
if it's empty.
exists(set: set<T>): boolean
Determines if a set contains elements.
Parameters:
set: set<T>
- The set to check for the existence of elements.
Returns:
True
if the set has at least one element,False
if it's empty.
exists(map: map<K, V>): boolean
Checks if a map contains key-value pairs.
Parameters:
map: map<K, V>
- The map to check for the existence of key-value pairs.
Returns:
True
if the map has at least one key-value pair,False
if it's empty.
Nested at-expressions
with exists()
The exists()
function supports nested at-expressions
, allowing them to access entities from an outer
at-expression
. This enhancement enables more complex and efficient database queries.
Example:
user @* {
exists(company @* { .city == user.city })
}
Translated SQL query:
SELECT U."name"
FROM "c0.user" U
WHERE EXISTS(
SELECT C."rowid"
FROM "c0.company" C
WHERE C."city" = U."city"
)
Usage in update
and delete
statements:
delete user @* { not exists( company @* { .city == user.city } ) } ;
Notes on cardinality:
- Use
@*
in nestedat-expressions
to ensure the entire query is executed as a single SQL query. - Using operators
@+
,@?
, or@
will result in independent SQL queries, potentially reducing performance due to loading the entire result set into memory.
Simplified attribute matching:
- In the
where
part of a nestedat-expression
, you can useouter_entity.attribute
directly.
Example:
user @* {
empty(company @* { .city == user.city })
}
Output and logging
function print(...)
Prints a message to STDOUT
.
Example:
print()
- prints an empty line.print('Hello', 123)
- prints "Hello 123".
Parameters:
...
: Accepts any number of arguments to be printed, including strings, numbers, variables, and expressions.
Returns:
None
(no explicit return value).
function log(...)
Generates a detailed record of program execution for debugging and analysis purposes.
Parameters:
...
: Accepts any number of arguments to be logged, similar toprint
.
Returns:
None
(no explicit return value).
Cryptographic hashes
function keccak256(byte_array: byte_array): byte_array
Produces a 32-byte Keccak256 hash from a given byte array.
Parameters:
byte_array: byte_array
- The byte array to be hashed.
Returns:
- A 32-byte byte array representing the Keccak256 hash of the input
byte_array
.
function sha256(byte_array: byte_array): byte_array
Generates a 32-byte SHA-256 hash from a provided byte array.
Parameters:
byte_array: byte_array
- The byte array to be hashed.
Returns:
- A 32-byte byte array representing the SHA-256 hash of the input
byte_array
.
Signature verification
function verify_signature(message: byte_array, pubkey: pubkey, signature: byte_array): boolean
Verifies the authenticity of a given signature, ensuring data integrity and non-repudiation.
Parameters:
message: byte_array
- The original message that was signed.pubkey: pubkey
- The public key allegedly used for signing.signature: byte_array
- The signature to be verified.
Returns:
True
if the signature is valid for the given message and public key,False
otherwise.
Ethereum public key recovery
function eth_ecrecover(r: byte_array, s: byte_array, rec_id: integer, hash: byte_array): byte_array
Derives the Ethereum public key from a signature and hash, enabling identity recovery in blockchain transactions.
Parameters:
r: byte_array
- The R component of the elliptic curve signature.s: byte_array
- The S component of the elliptic curve signature.rec_id: integer
- The recovery ID, indicating which signature variant was used.hash: byte_array
- The hash of the message that was signed.
Returns:
- The 64-byte Ethereum public key recovered from the provided signature and hash components.
Error handling with try_call
function try_call()
Catches exceptions within a function call, providing graceful error handling and fallback mechanisms.
Variants:
try_call(f: ()->T): T?
- Calls the function
f
. - Returns the result of
f
on success ornull
if an exception occurs.
- Calls the function
try_call(f: ()->unit): boolean
- Calls the function
f
that doesn't return a value. - Returns
true
on success orfalse
if an exception occurs.
- Calls the function
try_call(f: ()->T, fallback: T): T
- Calls the function
f
. - Returns the result of
f
on success or the specifiedfallback
value if an exception occurs.
- Calls the function
The try_call
method restores the state of a program in the event of a failure.
This means that even if the program writes data to the database, all changes will be reverted in case of an error.
Examples:
val int_or_null = try_call(integer.from_hex(s, *));
- converts the hexadecimal strings
to an integer and assigns it toint_or_null
, or assignsNone
if the conversion fails.val int_or_default = try_call(integer.from_hex(s, *), -1);
- converts the hexadecimal strings
to an integer and assigns it toint_or_default
, or assigns-1
if the conversion fails.val l = try_call(list<integer>.from_gtv(my_gtv, *));
- converts the GTVmy_gtv
to a list of integers and assigns it tol
or assignsNone
if the conversion fails.
Text pattern matching with text.like
text.like(pattern: text): boolean
The text.like()
function provides a simple way to perform pattern matching, similar to the SQL LIKE
clause. It
operates consistently in both interpreted expressions and at-expressions.
Parameters:
pattern: text
- The pattern to match against the text, incorporating wildcards for flexibility.
Returns:
True
if the text matches the pattern,False
otherwise.
Special Characters:
_
: Matches any single character, similar to the SQL LIKE clause.%
: Matches any string of zero or more characters, enabling broader matching capabilities.
Examples:
-
Basic pattern matching:
print(name.like(% von %))
- returns all names that have a von inside. -
Pattern matching in collections:
user @* { .name.like('% von %') }
- returns all users whose names contain the substring " von ". -
Escaping special characters: To match the special characters
_
or%
, you need to escape them with a backslash (\
). Note that in string literals, you must use a double backslash (\\
) to produce a single backslash at runtime.title.like('string\\_with\\_underscores')
- this matches the stringstring_with_underscores
where_
is treated as a literal underscore rather than a wildcard.