Build Application With REI3
Build Application With REI3
Updated 2024-07-21
Table of contents
1. Introduction
2. The Builder
3. Getting started
1. Installing applications as reference
2. Creating your own applications
4. Data storage
1. Relations
2. Attributes
3. Relationships
4. Presets
5. Indexing
1. Text indexing
6. Triggers
7. Policies
8. Change logs
5. Roles and access management
6. Presentation and user interfaces
1. Forms
1. Form layouts
2. Field settings
3. Data display fields
4. Form states
2. Queries
1. Query filters
3. Columns
4. Help articles
5. Translations
6. IconsFeatures
Home Applications Demo Services FAQ
7. Menus Docs
Comparisons News Contact Download
8. Login forms
7. Functions
1. Frontend functions
2. Backend functions
8. APIs
1. Calling APIs
9. Collections
10. Client-Events
11. End-to-end encryption
1. How to use
2. Encrypt for multiple users
3. Encrypt for groups
4. Limitations
12. Building on applications
1. Extension scenarios
1. Accessing shared components
2. Implementing small changes
2. Important considerations
1. User access
2. Deletions
13. Application transfers
1. Exporting applications
2. Importing applications
3. Hosting a repository
14. Optimizing for mobile devices
15. Working with emails
16. Date and time management
17. CSV import and export
18. Troubleshooting
Introduction
This isHome
the documentation for building
Features Applications Demo REI3 applications.
Services FAQ REI3 is a free to
use, open-source business
Comparisons application
Docs News Contactplatform,
Downloadwhich can run on-premise
or from the cloud, on Windows and Linux. To learn how to setup and admin‐
istrate REI3, please refer to the admin documentation.
REI3´s primary purpose is to fulfill business software requirements. Simple
applications, like a system that manages company event attendance, can be
built within an hour. More complex requirements, like tracking and managing
employee absence or executing mail campaigns, can also be fulfilled.
Organizations using REI3 can save time and money by reducing their depen‐
dency on costly software solutions for simple tasks, while cheaply address‐
ing complex, niche requirements that no fitting solution is available for.
Most people with IT administration skills can use REI3 to address their soft‐
ware needs; it is however very useful to know relational databases to make
use of all features. REI3 provides access to low-level entities, such as data‐
base indexes, triggers, sub queries, functions and so on. With some back‐
ground knowledge, complex relationships, business logic, access control as
well as performance tuning can be implemented to build powerful, fast and
scalable applications.
The Builder
REI3 applications are created and updated with a graphical utility, called
'Builder'. The Builder is included in all releases of REI3 and can be enabled
by an admin user.
Finished applications can be exported and then imported into other REI3 in‐
stances, to deploy changes to production systems or to share applications
with others. There is a dedicated REI3 application available (REI3
Repository) to host and distribute other REI3 applications publicly or inside
internal networks.
Be aware: Changing an application with the Builder can result in changes to
the underlying data structure, potentially deleting data in the instance but
also inHome
other Features
instances when transferring
Applications an application.
Demo Services FAQ Precautions must
be taken Comparisons
accordingly:Docs News Contact Download
NEVER use the Builder in productive instances. To build, use the portable version of
REI3 or run a separate REI3 instance. For critical instances, it is smart to run a copy of
a productive system to confirm application changes before deploying to the final, pro‐
ductive instance.
DO NOT make changes to applications from other authors - these are deleted when
the application is updated. You can expand existing applications safely by adding cus‐
tom data & user interfaces on top of them inside your own applications. Please refer
to Building on applications to learn more.
ALWAYS consider carefully when deciding to delete data structures
(relations/attributes). This will affect target instances and, if other applications build
on yours, affect other applications as well. Renaming data structures is safe however.
To enable the Builder, you need to log into a running REI3 instance with an
admin user. After enabling the maintenance mode, which will kick all non-ad‐
min users from the system, the Builder can be switched on. Once activated,
the Builder can be accessed from its icon on the top-left corner of the main
menu.
Getting started
To start, you can either directly create your own application, or install exist‐
ing ones from the public repository.
Home Features Applications Demo Services FAQ
Some options depend on other entities being created first (other applica‐
tions to build on, forms to select as start form, icons to show). When creat‐
ing an application these can be skipped and updated later.
In addition, a couple of non-editable fields are shown. These are set when an
application is exported. Please refer to Application transfers for more
details.
Release date: Current date when exported.
Application version: Incremented by 1 when exported.
Platform version: Version of the REI3 instance when exported.
Data storage
Applications that work with data usually need some sort of long-term data
storage. REI3 is built on the well-established, relational database manage‐
ment system postgreSQL.
To store data in a relational database system, 'relations' are created in the
form of database tables. Relations contain records for named entities (for
example students and classes of a school) and can be used to implement
relationships between
Home Features them (which
Applications studentsFAQattend which classes).
Demo Services
Relations,Comparisons
their attributes
Docs and,
News byContact
extension, relationships work the same
Download
way in REI3 as they would when building an application with any common re‐
lational database system.
Relations and attributes are referenced in forms to display, create or update
data in lists, fields, calendars and so on. They are also accessible in backend
functions for complex data manipulation, calculations or other data related
actions.
Relations
Relations are used to store data in the form of records. Records can be any‐
thing, from company contacts, students, vehicles, locations - to invoices and
workflows. By creating multiple relations, you can store any data your appli‐
cation needs.
Relations are central to managing data in REI3. They contain all records,
their values (following their attributes), indexes (mostly for performance tun‐
ing), presets (predefined records) and triggers (automatically executed back‐
end functions).
Attributes
Once a relation has been created, you can create attributes for it. An attri‐
bute is a data field, which is available to every record in a relation. A relation
called 'contacts' might have attributes such as 'email', 'phone_number' and
'works_at_company'.
By default, an attribute with the name 'id' exists for each relation and cannot
be deleted. This is its primary key. A primary key serves to reference each
specific record by a unique value - in this case, its an automatically created
number (auto-incremented integer).
Other attributes can also be used as keys, for example when using unique
names or reference numbers.
Relationships
Two relations can be in a relationship by creating a 'relationship attribute' on
either one of them, which refers to the other. You can choose a 1:1 (one-to-
one) or N:1 (many-to-one) relationship. Some examples:
1:1 - one-to-one
Relation 1: asset (contains asset details like a unique asset number)
Relation 2: asset_purchase (contains purchasing details for one asset like its in‐
voice number and paid price)
-> TheFeatures
Home relationship attribute can
Applications be on Services
Demo either relation
FAQ 1 or 2. Only one asset can
have the specific asset purchasing details (1 'asset' record is connected to 1
Comparisons Docs News Contact Download
'asset_purchase' record - 1:1).
N:1 - many-to-one
Relation 1: asset (contains asset details like a unique asset number)
Relation 2: product (contains product details, like model name, manufacturer)
-> The relationship attribute (as in N:1 'asset_product') must be on relation 1.
Multiple assets can be the same product (many asset records are connected to 1
product record - N:1).
Presets
Presets are predefined records that are shipped with your application. A pre‐
set consists of a name as well as attribute values. The preset name only
serves as reference inside the Builder - it is not visible to any end user. When
your application is transferred to a target instance, one record for each pre‐
set is created in the corresponding relation. All defined attribute values are
applied to this record.
When you define a preset, you can choose to protect it and/or its attribute
values. Protecting the preset itself, blocks deletion of its associated record,
while protecting attribute values blocks updating these values. The protec‐
tion settings can be mixed to serve different purposes:
Protected record & protected values. For records that must stay a certain way for your
application to work properly; this can be useful for workflow states.
Protected record & unprotected values. Useful for central configuration records with
customizable options.
Unprotected record &Applications
Home Features protected values.
DemoUseful for cases
Services FAQin which a record is optional,
but its values need to stay a certain way to be sensible.
Comparisons Docs News Contact Download
Unprotected record & unprotected values. Useful for sample data - can be overwritten,
changed or deleted at will.
Indexing
Indexes are defined on relations. They serve to improve the speed, in which
data can be looked up from the database, which leads to a better user expe‐
rience. They are optional for smaller relations but become very relevant,
when records inside a relation keep growing in number.
Standard principles of indexing, which is part of any relational database
management system, can directly be applied. Here are some basics - for
more details, please lookup
Home Features other resources
Applications on database
Demo Services FAQ indexing:
Comparisons
Indexes Docs system
help the database News find
Contact Download
specific records without having to scan all
records in a relation.
Indexes can have a big impact on performance - especially on larger relations. A good
index can speed up data retrieval a thousand-fold.
As indexes serve to find records by certain criteria, attributes that are used in filters
benefit from indexing a lot.
Having indexes for specific attributes is important for good database performance;
creating indexes for all attributes is a bad idea however. The more indexes exist, the
slower changes to records become as indexes must be updated as well. In addition,
each index has storage overhead, adding to the database size.
Unique indexes can be used to enforce unique values in all kinds of attributes (unique
names/numbers/dates/...). This is one use-case for indexing besides performance.
Indexes can be used to enforce unique, composite keys by using multiple attributes to
form a unique index.
Text indexing
REI3 offers a default index, which works on almost all attribute types, like
numbers, dates or names, to quickly find specific data. It is however limited
when it comes to larger text values, such as articles.
When text attribute values become too large (more than a few paragraphs)
the default index does not work anymore as its not designed to work with
large texts. Its also very inefficient to scan for specific characters in a grow‐
ing number of large texts.
For this situation, REI3 offers a dedicated text index option. A text index
does not index every character, but instead breaks down the text content to
its components. This gives us full-text search capabilities, which offer very
fast, mult-word lookups. To use a text index, just select the option when
adding a new index on a relation.
There is however another benefit with text indexes: Language specific
lookups. If its possible to know the language of a text, full-text search can
also break down words to their stems and remove stop-words. This enables
lookups for words
Home Features ofApplications
the same Demo
stem Services
as well as
FAQ further improve perfor‐
mance. To enable this
Comparisons Docsoption,
News the relation
Contact on which the text attribute is
Download
stored, requires a dictionary attribute. This attribute is used to store the lan‐
guage of a text. If a dictionary attribute is used and given a value, lookups
take into account specifics of the defined language to better find results.
Triggers
Triggers are an advanced feature, reacting to changed records inside your
relations (on creation, update or deletion). They are usually used for com‐
plex or event driven business logic.
A trigger calls a pre-existing backend function and executes the code inside
of it. To create a trigger, you start with a backend function with the type 'trig‐
ger'. Once created, you can create a trigger event for the backend function
on any relation inside the current application or any that your application
builds on. You can also create a trigger from inside a relation, by selecting
an existing trigger backend function.
You can also execute a single trigger function for multiple events. With the
variale TG_OP you can check, which event occurred, such as:
IF TG_OP = 'INSERT'
THEN my_var := 123;
ELSE my_var := 456;
END IF;
For more details about triggers, you can lookup the PostgreSQL trigger
documentation.
Policies
A relation policy can limit what specific records are accessible to a logged in
user via their role memberships. This is done by using backend functions
that serve as filter for specific actions. While forms, data display fields and
other frontend elements
Home Features can alsoDemo
Applications filter records,
Services relation
FAQ policies are applied
globally and cannot be
Comparisons circumvented
Docs by changing
News Contact Downloadthe frontend.
Depending on the action, the frontend will either not show records (no se‐
lect), disable inputs (select but no update) or block record deletion (no
delete). Regardless of the frontend, relation policies will always be enforced
on the backend.
Change logs
When data is changed in REI3 you can choose to automatically keep copies
of these changes. These change retention settings are defined for relations.
If nothing is set, no data changes are kept. Every relation has 2 settings for
defining data change retention:
1. Keep a number of changes. Change log keeps at least the specified amount of
changes.
2. Keep changes for a number of days. Change log keeps all changes for the specified
amount of days.
A system task regularly deletes older changes, when the retention settings
are satisfied. If both settings are used (number and days of changes), the
more conservative setting wins. Example: 30 changes should be kept for 90
days. If there are more than 30 changes, they are all still being kept if they
occurred within the last 90 days. If there are changes after 90 days, but still
less than 30, they are also being kept.
Changes are visible to users in forms that access corresponding relations
via the change log window. This will show all changes corresponding to
joined relations (see Queries), but only for attributes that are accessible to
the user via data input fields. If a user has access to a data field, and
changes are available, they will be visible without further permissions being
required.
Roles in REI3 are cumulative; the more roles a user has, the more access is
available. There is no 'deny' option; when you need to deny a group of users
access, you remove the corresponding access from the role and create a
second one, granting this specific access.
When creating a role, you need to choose a unique role name within your ap‐
plication. Titles, descriptions and role types serve to explain the role to ad‐
ministrators of REI3 instances as they will be shown in the admin UI. The
role type is purely descriptive and only serves to make role assignment
quicker.
Roles can be members of other roles. This enables access inheritance with
no fixed limit on how many levels of inheritance are allowed. A user logging
in, receives access following assigned roles and the memberships of these
roles (and the memberships of those roles, and so on).
The role 'everyone' is pre-defined and available in all applications. Anything
assigned to this role is assigned to all users that can login into REI3, regard‐
less of what other roles they might have. This role should primarily be used
during development or when access does not need to be limited at all.
Before an application is released into production, assigned permissions to
'everyone' should be moved to other roles, based on required access.
When Home
applications
Featuresbuild on otherDemo
Applications applications
Services usually
FAQ some access to the
other application´s
Comparisons data
Docsis News
necessary.
ContactThis is solved by making your roles
Download
members of roles from other applications. In many cases data access is de‐
sired but users from one application should not see user interfaces from the
other; this is addressed by creating 'data only' roles with no assigned menu
entries.
Lastly, the option 'assignable' controls whether a role is directly assignable
to a user. If set to 'false' the specific role is hidden in the admin UI and can
only be assigned indirectly via membership of other roles. This can be useful
for 'data only' roles or for complex role hierarchies.
Forms
Forms serve to display and manipulate data. They can also be used to exe‐
cute actions or react to user inputs via frontend functions.
Once created, you can start designing your form. Generally, forms can be
separated into two types:
Data: You define a query to create, update or delete relation records (inside the form
content tab). This will give you access to attribute input fields from the selected and
joined relations.
Non-data: You do not define a query. This type of forms usually serve purposes other
than record manipulation. Some examples:
Showing a full page data display field to view and navigate to records.
Showing a dashboard of multiple lists and buttons to reach different parts of
your application.
Forms are designed by adding and configuring fields. Fields serve to create
layouts, manipulate data, execute actions and more. Available fields are
shown in the sidebar, depending on what the form has access to. These
types of fields exist:
Container: These construct the layout of your form. Containers 'contain' other fields, in‐
cluding other containers to create simple or complex layouts.
Tabs:
HomeA field consisting
Features of one or more
Applications tabs,Services
Demo which then
FAQcontain other fields. Useful to
separate UI elements, hide seldom used fields or improve usability of very large forms.
Comparisons Docs News Contact Download
To add layouts inside tab fields, you can use container fields.
Data display field: A field showing records from other relations. Can be used to show
or create associated/child records. Also often used as jumping off point to other
forms. Depending on the chosen type, records can be presented as list, calendar, Gantt
plan, Kanban board and so on.
Label: Can either show a simple line of text with a fixed size and icon (useful for head‐
ings) or any HTML value.
Button: Actions that a user can execute (see Button fields).
Data input (data forms only): Dependent on the defined query, attribute input fields are
available to view and manipulate record values. They are labeled by the relation index,
the relation name and the attribute name, as in '0 employee.forename'. Depending on
the attribute type, fields will behave differently and offer different settings.
Data input by referring relationship: Like data fields but for N:1 & N:M relationships.
With these fields users can see and manipulate multiple relationship references at
once. Depending on the field settings, they can be displayed as multi-input dropdowns
or checkboxes.
Form layouts
REI3´s form layouts are primarily based on the CSS standard 'Flexbox'. Every
container field in REI3 is a flexbox container, which configures its own size
as well as layout characteristics for its children.
Home Features Applications Demo Services FAQ
The most important concept is the flex flow. Every container decides,
whether its contained fields (children) will 'flow' in a row (from left to right)
or in a column (from top to bottom). In addition to the flow direction, the
container decides whether its children will 'wrap', meaning they will move
into a new row or column if the available space is insufficient. Disabling
wrapping will result in fields needing to shrink their sizes or expand their par‐
ents size resulting in compact fields or scrolling, depending on the parents
configuration.
To create specific layouts, row and column containers are usually mixed. An
example: To create a form with 3 columns next to each other, with multiple
fields in each column, the following containers can be used:
1 parent Container with a 'row' layout, containing 3 child containers, 1 for each col‐
umn. Wrapping is enabled so that if the form is too small, the 3 column containers
move underneath each other to properly display their content without horizontal
scrolling.
3 child containers each having a 'column' layout, meaning that their children fields are
displayed underneath each other. Wrapping is disabled, as forms are usually designed
to be scrolled vertically.
Home Features Applications Demo Services FAQ
If you are inexperienced with Flexbox, it is best to play around with contain‐
ers in the form builder. Basically any layout can be created by mixing con‐
tainer configurations. Important to note: Non-container fields do not have
layout configuration. If you need to specifically change the layout of a single
non-container field (its size for example), you place your single field inside a
new container field and change the container layout. This is done to keep
layout options and complexity to container fields only.
When editing a container field, the following options are available:
Show in mobile view: If disabled, this field (and its children) are not visible when ac‐
cessing REI3 via a mobile device.
Base size: Initial size of the container (width if inside row layout, height if inside col‐
umn layout) in pixels. Is affected by its grow/shrink factors (see below).
Grow/shrink factor: A number compared between all children inside the same con‐
tainer. A field with a factor of 3 will grow/shrink 3 times more than a field with a factor
of 1. Growing and shrinking occur when more/less space is available than the field
requires.
Grows/shrinks to: Percentage value of the maximum/minimum size (from the base
size) a container will grow/shrink to. Ignored if the base size is set to 'auto'.
Wrap content: Move children fields to a new line (row/column) if space is insufficient.
If disabled, fields are shrunk, parents expanded or scrolling used, depending on the
configuration of the parent and its available space.
Direction: Place children in a row (left-to-right) or column (top-to-bottom) layout.
Justify content: Defines the alignment of children on the main axis (row: x, column: y).
Align items: Defines the alignment of children on the cross axis (row: y, column: x).
Align
Homecontent: Only relevant
Features if a rowDemo
Applications or column has more
Services than one line (wrapping en‐
FAQ
abled). Defines the alignment of children with the lines.
Comparisons Docs News Contact Download
Field settings
These fields serve to present and/or make accessible data from multiple
records. Currently, these data display fields exist:
List: A regular list of records. Has many options for data presentation and access.
Calendar: Presents time-related records on different calendar views (month, full week,
etc.). Very useful for viewing, creating or updating time-based records.
Gantt: Presents time-related records as a Gantt plan, grouped by associated entities
(owners, states, etc.).
Kanban:
Home Presents
Featuresrecords as Kanban
Applications cards,Services
Demo with the option
FAQ to drag&drop them be‐
tween Kanban columns (and optionally rows) for reassignment to things like people or
Comparisons Docs News Contact Download
states.
Chart: Presents record values as charts or diagrams.
In general, all data display fields can be placed on any form. When placed on
a data form, which handles creation of specific records, they can serve to
display related data (child or associated records). They can also be used to
navigate to other forms/records.
When placing a single data display field on a form by itself, it becomes a full
page field. This not only makes the field more usable (more available space)
but also enables full page navigation and hotkeys. Most often, full page
fields are used as starting points to access top-level records, with child-
records being shown inside data forms with smaller data display fields.
Data display fields use queries to access data - these can be configued in
the field content tab. Once the query has been defined with at least one rela‐
tion, columns can be added; column values are then shown as part of the
field.
Depending on the type of data display field, different field options are
available:
Lists
Display: Table or card layout. The default view is the table; showing records, one
per row, with columns separating the record values. The card view is an alterna‐
tive that shows each record as a separate card, with values being placed verti‐
cally inside it.
Result count: The default page result limit. If more results are available, the user
needs to navigate between pages. Can be overwritten by the user.
CSV import/export
Quick filter: A simple text box with which a user can filter the entire list.
Inefficient, as all visible attribute values are being looked through. Advisable only
for lists handling limited data or when all shown attributes are indexed. Useful for
sub lists that are already being filtered by a currently open form record.
Calendar/Gantt
Date Features
Home from/to: Attributes that define
Applications Demo theServices
date/timeFAQ
of shown records on the calen‐
dar / Gantt. Given attribute values must be date or datetime and must not be
Comparisons Docs News Contact Download
mixed. If date values are used, only full day entries are shown on the calendar; if
datetime values are used, both full day as well as non-full day entries are
displayed.
Color: (Optional) attribute value that is used to color the date entries.
Calendar
iCAL subscriptions: This feature allows users to subscribe to a calendar with
their personal devices. If enabled, how far the calendar data is provided
(before/after the current date), can be defined in days.
Default view / users can change view: Controls what calendar view is shown as
default and whether or not users can change this setting for themselves.
Gantt
Gantt interval / interval toggle: Controls what Gantt interval is used by default
(days/hours) and whether users can change this setting for themselves.
Gantt fields in general require some data to be used for grouping, because each
line of a Gantt plan displays date values of a specific entity. This can be a person,
a task, project or whatever else. Gantt fields automatically use all values within
the first column batch to populate the Gantt group - so multiple columns can be
used to describe the entity of a Gantt line. Example: Portrait, forename + sure‐
name of a task owner.
Form states
Form states serve to change the behavior of fields and tabs; this is done by
applying effects based on form state conditions. Multiple form states can
be used and will work in parallel.
SimilarHome
to query filtersApplications
Features having oneDemo
or many filter lines,
Services FAQ form states have con‐
ditions. Each condition
Comparisons contains
Docs News aContact
connector (AND/OR), comparison criteria
Download
(field value, user role, etc.), an operator (equals, greater than, etc.) as well as
brackets to facility grouped comparisons.
When conditions of a form state are met, its effects are applied to specified
fields. Currently available effects are:
Hidden: Available for all field types. If set, field is not shown. If field is a container or
tab, all its children are hidden as well.
Default: Field is managed automatically. If it is an attribute input field and not set to
'nullable', it is shown as 'required'. If the user is missing write permissions to the un‐
derlying attribute or record (see relation policies), it is shown as 'readonly'.
Optional: Only attribute input fields. Field is optional.
Readonly: Only attribute input fields. Field is readonly.
Required: Only attribute input fields. Field is writable and required.
If multiple states would apply to the same field the last one is used. Form
states are executed in order of their description, so numbered prefixes can
be used to achieve a desired state execution order.
Queries
To show or manipulate data, REI3 components (like forms, data display
fields or APIs) need to know how to access data. This is done by defining
data access queries or 'queries' for short. Queries control how data is re‐
trieved and (if desired) updated or deleted.
To define a query, you start by selecting a relation - this is the 'base relation'
or relation index 0. A relation index is a number, that uniquely identifies a
specific relation within a query. Once a base relation is set, we can connect
or 'join' multiple relations if they are linked with relationship attributes, with
each receiving a unique index number.
Home Features Applications Demo Services FAQ
Query filters
Query filters serve to filter query results. They are used by frontend compo‐
nents like forms, data display fields, data input fields showing relationship
attributes, collections and so on.
Filters are made up from filter lines. Each line contains an AND/OR connec‐
tor (first line is always AND), two filter criteria (to compare them) and a com‐
parison operator (equals, greater than, etc.). Additionally, filter lines can be
grouped with left and right brackets to create more complex AND/OR
conditions.
Query Home
filters can be defined
Features in twoDemo
Applications ways: Services FAQ
Comparisons
(Regular) Docs News
filters: Automatically Contact
applied on anyDownload
data access. Depending on filter condi‐
tions, different data can be shown in different contexts (logged in user, role member‐
ship, active interface language, and so on).
Filter sets: A named set of filter conditions, from which a user can choose from to cus‐
tomize the output. Multiple filter sets can be defined for a query. Filter sets can serve
different purposes:
Sub selections: Wherever filter sets can be used (lists, calendars, Gantt, ...), if at
least 2 sets are defined, users can choose between them. This enables result
subsets in lists (like only 'active', 'closed' or 'records in recycle bin') and in input
dropdowns ('show only colleagues in my department' or 'in entire company'). The
first filter set is active by default. If multiple sets are desired but everything
should be shown by default, create the first filter set without any filter lines.
Input only filters: Relationship inputs can be filtered with user context dependent
conditions (login/roles). Using regular filters will affect the current field value
without user action (if login condition results in different/less data). Using a filter
set, enables filtering to be limited to the value input (dropdowns usually) and will
not affect existing field values. If a single filter set is defined, the user will not be
presented with a choice between filter sets.
Since the frontend is running on a users device (e. g. browser), its code can
be manipulated and query filters overwritten or removed; to limit access to
sensitive data to specific individuals, relation policies can be used to safely
filter data on the backend.
Columns
Columns are used to choose data to be retrieved from a query when working
with things like data display fields, APIs or collections.
There are two types of columns:
Attribute columns: These are available automatically, based on the selected relations
from the query. They display the value for the selected attribute for each record.
Sub query columns: These can show data outside the main query. Sub queries can
show data from any accessible relation, but are usually filtered by attribute values
from the main query. By creating corresponding filters on the sub query, aggregation
functions can do things like 'show totals' or 'display averages' for sub entities of the
current record. Sub queries can use other sub queries to filter themselves and also be
used as filters inside the query itself.
Home Features Applications Demo Services FAQ
Help articles
Sometimes it becomes necessary to explain concepts, data structures or
workflows to application users. Besides titles and small help texts next to in‐
put fields, application authors can create help articles that go into more de‐
tail. A help article is a piece of richtext that can include descriptions, tables,
bullet-point lists, images, external links and so on.
After creating a help article, you can assign it to different places:
1. Application help page - a globally accessible documentation for your application.
2. Form context help - accessible when a user is on a specific form.
Translations
REI3 is a multi language system. By adding translations, you expand the
number of available languages that your application can support. However,
adding a language requires you to provide translations for affected entities.
For some entities, REI3 can use fallbacks - it is however important to test
your application thoroughly when adding a new translation.
The following entities are translatable:
Application title: Shown
Home Features in the mainDemo
Applications header and start page
Services FAQ of REI3. Configured in the
application settings.
Comparisons Docs News Contact Download
Attribute title: Shown as filter criteria in lists and as fallback for data field & column ti‐
tles if these are not set.
Role title & description: Shown in admin UI. Serves to explain role usage to
administrators.
Form title: Shown in form header. Can fallback to menu title if not set and if form is
opened via a menu entry.
Form context help: Shown in the help page if the specific form is open. Serves as con‐
textual help for a form.
Field title: Shown in form over a field. If it is a data field and has no title, it uses the at‐
tribute title as fallback.
Field help text: Shown in form under a field. Additional context help for how to use a
data field.
Column title: Shown in data display fields. Describes the content of a column. Can fall‐
back to attribute title if not set. If column batches are used, only the title of the first
column is used.
Menu title: Shown in application menu. Can be used as fallback for form titles if these
are not set.
Application help page: Shown in the help page, independent of which form is open.
Icons
Icons serve to help users recognize entities or navigate the application in dif‐
ferent user interfaces:
Application: Assigned in application overview (Builder start page). Shown in all places
the application itself is referenced (home page, admin panel, Builder).
Menu: Shown before each menu entry. Also shown before the form title, if no form
icon is set and the form is opened by this menu entry.
Form: Shown before the form title.
Attribute: Default icon for attribute input, shown if a field is handling attribute data and
no other field icon is set.
Field: Depending on the field type, usually shown before an input.
Icons must be added as PNG files with at most 64kb. The system expects
icons to have equal height/width - other ratios are possible but may not be
displayed correctly. To achieve non-squared icons, the icon image can use
paddings with transparent background.
When Building on applications, you can re-use icons from other applications
to refer to foreign entities. Re-using icons can help users to understand what
entities are being handled.
Menus
Menus serve to navigate between and inside applications in REI3. Two types
of menus exist:
Main menu: Shown at the top of the page and on the start page for each user.
Automatically created by resolving accessible applications for the current login. The
header menu shows the top level of applications as well as a second level of assigned
to applications (child applications). Currently only 2 levels of hierarchy are supported.
The display order can be defined in the application overview (Builder start page) with
the default position; this option can be overwritten in a target instance inside the ad‐
min panel. An application is only shown in the main menu, when a start form has been
defined and a user has access to it; this includes admin users.
Application menu: This
Home Features can directly Demo
Applications be defined in the Builder
Services FAQ with unlimited levels of hi‐
erarchy; we recommend to keep the menu hierarchy to at most 3 levels for usability
Comparisons Docs News Contact Download
reasons. Each menu entry can optionally open a form and/or contain sub menu en‐
tries. When sub entries are defined, you can choose whether these entries are shown
by default or must be toggled first by opening the parent menu entry. The translatable
menu title as well as menu icon are applied to an opened form if the form does not de‐
fine its own title/icon.
When Building on applications, you can choose to copy the entire menu
structure from another application. This is can be useful when you intent to
extend another application; you copy the original menu structure, change tar‐
get forms and add your own, custom menu entries.
Login forms
Sometimes it is useful to connect the currently logged in user to a record
from within your application. To assign a personal, employee or a customer
contact record for example.
Home Features Applications Demo Services FAQ
Functions
With functions, authors can greatly expand the capabilities of their applica‐
tions. Basically, functions are executing pre-defined code that the applica‐
tion author prepared. Depending on the type and trigger of the function, they
can do different things. In general, REI3 supports 2 function types:
Frontend
Home functions:
Features Functions that are
Applications Demoexecuted on theFAQ
Services 'frontend', e. g. where REI3 is
shown to the user. This is the browser that a user opens to access the REI3 applica‐
Comparisons Docs News Contact Download
tion. Frontend functions can run calculations, update input fields, navigate the user to
different places and more.
Backend functions: Functions that are executed on the 'backend', e. g. where REI3 is
hosted. This is the server that REI3´s database is run from. Backend functions are
used to update data, block invalid inputs, enforce standards and so on.
Frontend functions
Frontend functions execute JavaScript within the user´s browser. How
JavaScript works and how it is written is not part of this documentation -
please refer to documentation for this language. For examples of how these
frontend functions are written, you can install other REI3 applications as
reference.
By using frontend functions, applications can execute logic based on front‐
end events. Some examples:
User opens a form.
User saves changes to a record.
User changes the value of a field.
Frontend functions can be used in a 'global context', which means that they
can be used and reused throughout the application. This is useful for gen‐
eral helper functions, like validating inputs, logging access or converting val‐
ues (like time conversions or Markdown to HTML).
You can however
Home alsoApplications
Features bind a frontend
Demo function
Services toFAQ
a form. This means that it
can only Comparisons
be used in the
Docscontext
News of the form,
Contact but can therefore access form
Download
entities like input fields. These functions are usually used for data
manipulation/validation purposes.
Within the function code, dynamic placeholders are used to reference other
entities like other functions, input fields and so on. Placeholders are impor‐
tant as they protect your function when you make changes to referenced
entities.
Frontend functions can also call 'instance functions'; these are functions
that can be accessed to interact with the REI3 system directly. Instance
function can check a user´s role membership, navigate the user to different
places, copy values to the users clipboard, execute backend functions, and
more. To learn more about specific instance functions, you can read the con‐
textual help that each function provides.
Backend functions
Backend functions in REI3 are PL/pgSQL functions. PL/pgSQL (Procedural
Language/PostgreSQL) is a programming language of the underlying data‐
base system that REI3 is running on (PostgreSQL). To learn more about writ‐
ing PL/pgSQL, please refer to documentation for this language. To start
with, you can install other REI3 applications as reference.
By using backend functions, complex data manipulation tasks can be
achieved, invalid inputs blocked and standards enforced. Backend functions
can be triggered by relation triggers and called from other backend or front‐
end functions. They can also be regularly executed via schedules.
Home Features Applications Demo Services FAQ
Within the function code, placeholders are used to reference application en‐
tities (relations, attributes and other backend functions). This ensures that
changes are upgrade safe: Referenced entities can be renamed safely, while
deletion is blocked. Using these placeholders, your functions are protected
against breaking changes, while you work on your application.
Backend functions also have access to 'instance functions'. These expose
data or features from the REI3 system. They can be used to read configura‐
tion settings (like the public hostname), get context information (like the lo‐
gin ID used to access the database) or execute tasks (like sending emails).
To learn more about specific instance functions, you can read the contextual
help that each function provides.
APIs
Application authors can create REST APIs to enable creation, retrieval, up‐
date or deletion of data from outside the system. APIs use queries to define
what can be accessed or manipulated. As with CSV imports and exports,
multiple relations can be joined to show or manipulate multiple records and
their values at the same time.
Home Features Applications Demo Services FAQ
REI3 APIs follow the REST model with the following calls being available:
POST /api/auth
GET /api/[application_name]/[api_name]/v[api_version]/[optional_record_id]
POST /api/[application_name]/[api_name]/v[api_version]
DELETE /api/[application_name]/[api_name]/v[api_version]/[record_id]
Examples, of how these calls are executed and what they return are shown
live inside the API editor. A session token is returned after a successful au‐
thentication call (see first call above) and must be included in all successive
calls to the API as Bearer Token. The session length follows the maximum
login session length set in the REI3 admin interface.
There is no defined limit in the amount of APIs an application can offer - only
the API names must be unique within the application. To update an API with‐
out breaking existing calls, a new version can be created. The new version
will be identical to the previous iteration but have a version counter incre‐
mented by one. After applying the desired changes to the new version, both
old and new API versions can be used simultaneously. API versions can also
be separately deleted when they are no longer needed.
Some considerations:
APIs use the same roles, policies and so on, that regular logins use; the same options
to give and restrict access to relations and specific records are therefore available.
Sub queries can be used in GET calls but will cause POST calls to fail.
To affect any record on any relation, the corresponding options
(CREATE/UPDATE/DELETE) must be enabled for relations in the API query.
When
Home API Features
calls affectApplications
records, relation
Demotriggers will fireFAQ
Services accordingly. It is not relevant to
the system whether changes are made by a user on a form or by an external
Comparisons Docs News Contact Download
script/system via API.
To update existing records or resolve records for joined relations, a record lookup
must be defined for each relation in the API query. Record lookups work the same as
in CSV imports - any attribute with a unique index can be used to identify a record. The
attribute values used as record lookups must be part of the API call.
Calling APIs
REI3 can either serve APIs as a server (s. APIs above) or execute API calls
against an external REST server. Calling APIs can be done in either frontend
functions or backend functions.
Calling REST APIs on the frontend is just JavaScript, so any tutorial on how to execute
REST calls in JavaScript can be used. Frontend functions can call backend functions
to retrieve things like credentials or tokens, stored in relations.
Calling REST APIs on the backend is done by the REI3 server. When creating new back‐
end functions you can select from a list of templates, which includes examples of
REST calls for authentication, sending data with authentication headers and how to
handle JSON responses. REST calls are executed asynchronously so a callback func‐
tion (e. g. another backend function) is used to handle REST responses if needed.
REI3 instances can exchange data, with one instance offering APIs as server
with the other calling these APIs as client to receive or update records.
Collections
A collection is a data store that is available on the frontend, which can be ac‐
cessed by other frontend elements (like form fields or frontend-functions). It
contains data based on a defined query. Depending on the selected columns
and filters, a collection will retrieve records and their values.
Collections are retrieved when a user logs into the system and updated
when user permissions change; collections can also be updated directly by
executing a function. When updating a collection via a frontend function,
only the current user will be affected - updating from a backend function can
however affect one, many or all users.
Some use cases for collections are:
AsHome
filter criteria in field
Features query filters:Demo
Applications When complex
Servicesor FAQ
expensive filter criteria are
needed in a list view (for example, using multiple conditions and sub queries) it can be
Comparisons Docs News Contact Download
very useful to use a collection instead. Collections are retrieved once, expensive
lookups are therefore not repeated on every list view. It also removes the need to re‐
peat complex filters on other but similar views; the same collection can be referenced
multiple times.
As user filter for data input fields: Once a collection is defined within a query filter for a
data input field, they can be used to offer additional user filter inputs, in which a user
can select from existing collection values to filter the current view.
As default value for data input fields: Collections can also be used as default values
for data input fields, like adding values to a relationship input field based on the logged
in user´s team memberships. They can also be used to support user configuration op‐
tions for default inputs.
As input to a condition of a form state: Form states control how form fields behave -
with collections, application authors can use configurations independent of the current
record to show/hide/force field inputs depending on global or user-based settings.
As a notification, shown in the header menu (top header bar): Any collection value can
also be shown in the header menu to serve as a notification. Showing values like the
number of open requests to be approved, it can also be used to navigate to another
form showing data connected to the notification.
As a notification, shown within a menu entry: Menu entries can reference collection
values to show context-relevant data, like counters reflecting the total number of items
on a list that the menu entry would show.
Collections can offer any data from the database, to be used on the front‐
end, regardless of context. They have downsides however. As they are not
regularly updated during a user´s session, their values might be outdated.
When manipulating data affecting a collection, the user would need to re‐
fresh the page or a function would need to trigger a collection update.
Depending on the contents of the collection, this limitation may not be rele‐
vant or might be easily addressable by rare, event-driven updates.
Client events
REI3 includes the optional REI3 client software, which can be installed by
users from their personal settings. This piece of software runs on Windows,
Linux (X11 only) and MacOS. It was created to enable interactions between
the REI3 webFeatures
Home application (runningDemo
Applications in a browser
Services or via progressive web app)
FAQ
and the user´s computer.
Comparisons Docs News Contact Download
A client event is a definition of what should occur, when the REI3 client rec‐
ognizes a specific event. It´s defined in the Builder, in the application setting
page and can react to:
The REI3 client connecting to or disconnecting from the REI3 server. This can be use‐
ful for logging or for running data preparation scripts (for things like reporting) based
on the connecting user.
The REI3 client recognizing pressed hotkeys on the user´s computer. This is likely the
most common use case for client events, allowing for interactions with REI3, without it
needing to be in the foreground.
An example: A REI3 application could define a hotkey client event. When the
user presses the hotkey, the REI3 client sends the contents of the clipboard
to a frontend function, which looks up relevant data inside the REI3 applica‐
tion and opens a corresponding form. This way, users could copy some text
like an invoice number or email address and push a hotkey to find corre‐
sponding data inside REI3.
Each client event can execute either a back- or frontend function and can
then provide one or more arguments. These can be things like the currently
open window title or the contents of the user´s clipboard.
When using frontend functions, an active REI3 session must be running on
the same computer as the REI3 client - events are only forwarded to the
same origin point. Backend functions directly interact with the REI3 server,
only requiring that the REI3 client is connected to it.
Hotkeys for client events must be enabled by each individual user in their
personal settings and can be re-assigned there as well.
End-to-end encryption
Encryption can be used to protect sensitive data. Various forms of encryp‐
tion exist to address different scenarios and risk levels. End-to-end encryp‐
tion (or E2EE) is especially useful as it protects data whether or not the sys‐
tem isHome
running and independent
Features Applications of the Services
Demo privilege FAQ
level of a bad actor. What
makes E2EE so powerful
Comparisons Docs is News
that data is being
Contact encrypted for only the individu‐
Download
als that may access that data - not even the server itself can read or act on
the data.
Usually, end-to-end encryption is harder to implement as it can be complex;
with REI3, its integrated into the platform and can be used by any REI3 appli‐
cation with little effort. However, some limitations exist as encrypted data is
not accessible to REI3 on the backend (server side).
For more information on how end-to-end encryption is implemented in REI3,
please take a look at the concept document.
Beware! Because E2EE blocks even the system itself from reading the data,
only users that already have access to it may read or re-encrypt the data for
others. Neither administrators, nor the REI3 developers can access en‐
crypted data for which privileged users have lost access to.
How to use
Application authors can enable E2EE for a new relation within the Builder.
With encryption enabled, new attributes of a relation can be set to be en‐
crypted. After that, data will be automatically encrypted for the current login
when saved on data forms and decrypted when accessed by things like lists.
For E2EE to work, users that work with encrypted data need to setup their
personal encryption once for their login inside the user settings interface. If
they attempt to work with encrypted data without that setup, an error mes‐
sage will be shown.
Home Features Applications Demo Services FAQ
When a user attempts to read encrypted data that was not encrypted for it,
an error message is shown. It is up to the application author to filter records,
based on things like record ownership or group membership, to make data
accessible to only privileged users.
Limitations
Because E2EE only allows specific individuals to access encrypted data, the
REI3 system itself cannot use it for things like filtering or sorting. Full-text
search over encrypted data is possible with the use of both backend func‐
tions to retrieve and frontend functions to decrypt and then search through
plain data. It is however necessary that the user executing those functions is
privileged to access that data; without it being encrypted for this particular
user, the data cannot be decrypted and therefore not processed.
Additionally, E2EE in REI3 requires additional overhead in the form of compu‐
tation time for the en-/decryption itself, as well as space to store individual
user´s decryption keys.
Because of the given limitations, E2EE should only be enabled were neces‐
sary - enabling it for everything will result in worse system performance and
user experience.
Building on applications
A major feature
Home of REI3
Features is the ability
Applications DemotoServices
build onFAQ
other applications. To ac‐
cess data, user interfaces,
Comparisons Docs roles
News and more Download
Contact to extend functionality or to better
meet niche requirements. Building on applications enables anyone to re-use
parts of applications while adding their own, unique features. No license or
permission is required to extend an existing application. Multiple applica‐
tions can build on the same, original application, using the same or different
sets of components.
If you want to extend another application, you create a new application that
has access to the application you want to extend. This is done in the Builder
start page by selecting a dependency with 'Depends on' when
creating/updating an application. This enables access to different parts of
the original, dependent upon application - to keep things simple, we will call
this the 'parent application' from here on.
Extending applications means that every new version of your application re‐
quires the parent application to be installed as well. When exporting your ap‐
plication, dependencies (parent applications) will be included automatically.
NEVER make changes to parent applications directly. The Builder will not
prevent this, but all changes will be removed when an update to the parent
application is installed. To build on other applications, you make changes to
your own application that can show and reference parts of its parent
application(s).
Once your application has a parent, you can access the following
components:
Data (relations & attributes): Access to parent relations in relationships within the
child application; effectively extending these directly (with 1:1 relationships) or creat‐
ing new data structures attached to the parent relations. Parent relations & attributes
can also be accessed in queries, enabling access to these as if they were part of the
child application.
Forms: Access to forms from the parent application as targets in data display fields,
buttons or within menus. This allows for re-use of existing user interfaces.
Menus: Access to menus from the parent application. It is also possible to copy an en‐
tire menu structure of an application to quickly recreate the parent, while making de‐
sired changes
Home to specific
Features menu entries.
Applications Demo Services FAQ
Functions: Parent functions (backend & frontend) can be accessed directly, while ac‐
Comparisons Docs News Contact Download
cess to entities from within functions in the child application is also enabled. To keep
applications upgrade safe, always use the provided placeholders when referencing en‐
tities in functions. This will not protect against deletions (see below) but will keep your
application running when entities are renamed.
Extension scenarios
Depending on the specific case, different approaches to application exten‐
sion are possible.
Deletions
Application transfers
An application transfer is the process of exporting a signed and compressed
version of an application from one REI3 instance and importing it into an‐
other. Any installed application can be exported from any REI3 instance with
the Builder. It does not matter if the application was originally built inside the
running REI3 instance or was imported. It is also irrelevant who the original
author was. There is no encryption or obfuscation added at any point.
To protect against unknown sources, REI3 instances employ a list of trusted
public keys. The public key of the central REI3 repository is included in all in‐
stances by default. To export applications, you need to provide your own pri‐
vate key for signing them. The Builder includes tools to create new RSA key
pairs for convenience. The private key should be considered highly sensitive.
If you are
HomenotFeatures
familiar Applications
with handling secure
Demo key pairs,
Services FAQ please refer to external
resources to learn more.
Comparisons Docs News Contact Download
Exporting applications
Applications are exported on the Builder start page. To start the export
process you select the desired application and run an export check. This
check will compare the current state of the application to the last known ver‐
sion. If any changes exist, a new version must be created before an export is
possible. By creating a new version target instances understand that there
are changes to apply. In order to export any changes, an application must be
set to 'export changes' in the admin UI for applications. You should only do
this for your own applications.
Important notice: When you build on applications from other authors, these
are dependencies that are automatically exported together with your appli‐
cation. To protect against accidentally making changes to applications from
others, all applications are in the state 'do not export changes' by default.
While in this state, the last imported version of the application is exported
and not the potentially changed version, accessible in the Builder. If you de‐
cide to export new versions for applications built by others, you potentially
risk loss of your changes as well as data loss, when a new version from the
original author is installed. You can safely build on other applications with‐
out making direct changes.
Ultimately, the export will generate a compressed zip file, which includes
your application and all its dependencies. Within the zip file, each applica‐
tion is represented as a *.json file, which contains the corresponding appli‐
cation structure and a signature, created with your private key. Applications
that were not changed are exported as they were with their original
signature.
Importing applications
Applications can be imported to REI3 instances in two ways:
ByHome
importing an application
Features package
Applications file.
Demo Services FAQ
By importing an application
Docs from a repository.
Comparisons News Contact Download
When you attempt to import your application into another REI3 instance, the
signature of the application is checked against a list of trusted public keys.
Only applications which signature can be successfully compared to these
trusted public keys can be imported. You can add your public key to any
REI3 instance within the admin UI.
Applications are either installed or updated when they are imported. All
changes made to the applications or their dependencies are automatically
applied by REI3. Should there be a problem, the entire import process is re‐
verted even if multiple applications were affected. Import issues can be
checked inside the admin UI by increasing the log level for 'transfers' and re‐
peating the import.
Hosting a repository
When running many local or offline REI3 instances, it can be sensible to host
your own REI3 application repository. It is also possible to host your own
repository in the cloud, accessible to anyone. This is done by setting up a
REI3 instance and installing the 'REI3 repository' application; this is the same
application we use to host the central REI3 repository.
Once running and reachable on a network, the repository must be added to
target REI3 instances as well as the public signing key(s) for corresponding
applications. After that the repository meta data will be pulled from con‐
nected instances and applications will be available for install/update.
Sending an email
The instance function 'instance.mail_send()' can be called from any backend
function from any application. Specific parameters include mail related meta
data (like recipient, subject line and mail body) as well as optional parame‐
ters for attaching files from file attributes and for using a specific mail ac‐
count to send with. Each time this function is called, a single email is cre‐
ated. More details can be found in the help text for this function in the
Builder.
The mail spooler periodically dispatches emails - if no account is specified,
a random account is used. HTML emails can also be sent; usually created
from the value of a record´s text attribute, filled by a richtext field input on an
email send form.
Receiving emails
If receiving mail accounts are specified, the mail spooler periodically fetches
emails and their attachments. With the instance function
'instance.mail_get_next()', any application can request the next available
email from the mail spooler, optionally filtered to a specific account. The
idea is to call this function in a loop until all emails are processed; this func‐
tion returns NULL when no more emails are available. Once an email is pro‐
cessed, it should immediately be deleted; if this is not done, it might be pro‐
cessed twice. Because of that 'instance.mail_get_next()' will return the same
message again if it was not deleted. More details can be found in the help
text for this function in the Builder.
To delete a processed email, two options exist:
1. Delete it right away with 'instance.mail_delete()'. Used when no attachments are to be
handled. Email is immediately deleted and attachments (if there) are lost.
2. Order REI3 to copy the email attachments and then delete it with
'instance.mail_delete_after_attach()'. Used when a record exists (or was created) with
anHome
files attribute that Applications
Features should receiveDemo
the email attachments.
Services FAQ REI3 will then transfer
these files and update the record´s files attribute value accordingly - after which the
Comparisons Docs News Contact Download
email is deleted. This process runs in the background and might take some time de‐
pending on schedulers and attachment size; 'instance.mail_get_next()' will skip emails
marked as such and return the next, unmarked email from the spooler.
Troubleshooting
Application fails to import in target instance
Many potential import issues are considered and automatically handled by
REI3. If the import still fails however, you can increase the log level for trans‐
fers and repeat the import attempt; this will generate usable logs. To trou‐
bleshoot, here are some pointers:
The import process is handled sequentially. First relations then attributes and so on. In
some cases, entities can cross-reference (like form fields referencing other fields or
presets referencing other presets). In these cases, the import process will skip the
problematic entity and finish others first. It will then repeat the import process, skip‐
ping already imported entities. Import tasks rely on deferring constraints to allow for
cyclical references. It will ultimately fail, if any issues still exist at the end of at most
10 loops.
Some imports fail, because the application was released for an older version of REI3.
Older applications can generally be imported without issues - but in some cases, very
old applications might have trouble with current releases. In this case, you can import
the application in an older version of REI3 and then upgrade the instance to your target
version. During platform updates, applications are automatically updated as well. If
you are the author of the application in question, you can then export your application
from the newer release to avoid import issues for others. If you are not the author,
please contact the author and ask for an updated version for your release.
Some issues are not solvable because changes are just invalid in target instances.
Examples:
Adding a not-nullable attribute to an existing relation without default value. If
your application is imported to an instance where an older version of your appli‐
cation already existed, the import can fail because adding such an attribute is in‐
valid Features
Home for existingApplications
records. The Demo
attributeServices
must either
FAQbe nullable or provide a de‐
fault value to update existing records.
Comparisons Docs News Contact Download
Application causes SQL errors
The Builder guides an application author to create valid data
retrieval/manipulation logic so SQL errors usually do not happen. Due to the
available range of options, some logic errors cannot completely be avoided
however. Examples:
Using 'GROUP BY' on some list columns, while others are not grouped or aggregated.
This is generally nonsensical - if this issue occurs you must change these settings.
You can also use the SQL preview in the form-builder UI to check/test the resulting
SQL against your database.
Using invalid operators, like comparing strings with 'larger than'.
Having logic errors in functions. Besides offering placeholders for upgrade safe ac‐
cess to existing entities, the Builder will deliver an error if the function has invalid syn‐
tax. Logic errors however will not be caught. Please test your functions thoroughly.