Boolean Functions and Operators
Boolean type | |
Evaluates true if either boolean is true. | |
Evaluates true if both booleans are true. | |
Logically negates a given boolean value. | |
Comparison operators | |
Returns true if none of the values in the given set are false. | |
Returns true if any of the values in the given set is true. | |
Checks that the input bool is true. |
A boolean type of either true
or false
.
EdgeQL has case-insensitive keywords and that includes the boolean literals:
db>
select (True, true, TRUE);
{(true, true, true)}
db>
select (False, false, FALSE);
{(false, false, false)}
These basic operators will always result in a boolean type value (although, for some of them, that value may be the empty set if an operand is the empty set):
These operators will result in a boolean type value even if the right operand is the empty set:
These operators will always result in a boolean true
or false
value, even if either operand is the empty set:
These operators will produce the empty set if either operand is the empty set:
If you need to use these operators and it’s possible one or both operands
will be the empty set, you can ensure a bool
product by
coalescing
. With =
and !=
, you can use their
respective dedicated coalescing operators, ?=
and ?!=
. See each
individual operator for an example.
Some boolean operator examples:
db>
select true and 2 < 3;
{true}
db>
select '!' IN {'hello', 'world'};
{false}
It’s possible to get a boolean by casting a str
or
json
value into it:
db>
select <bool>('true');
{true}
db>
select <bool>to_json('false');
{false}
Filter clauses must always evaluate to a boolean:
select User
filter .name ilike 'alice';
Evaluates true
if either boolean is true
.
db>
select false or true;
{true}
When either operand in an or
is an empty set, the result will not
be a bool
but instead an empty set.
db>
select true or <bool>{};
{}
If one of the operands in an or
operation could be an empty set,
you may want to use the coalesce
operator (??
) on that
side to ensure you will still get a bool
result.
db>
select true or (<bool>{} ?? false);
{true}
Evaluates true
if both booleans are true
.
db>
select false and true;
{false}
When either operand in an and
is an empty set, the result will not
be a bool
but instead an empty set.
db>
select true and <bool>{};
{}
If one of the operands in an and
operation could be an empty set,
you may want to use the coalesce
operator (??
) on that
side to ensure you will still get a bool
result.
db>
select true and (<bool>{} ?? false);
{false}
Logically negates a given boolean value.
db>
select not false;
{true}
When the operand in a not
is an empty set, the result will not be a
bool
but instead an empty set.
db>
select not <bool>{};
{}
If the operand in a not
operation could be an empty set, you may
want to use the coalesce
operator (??
) on that side to
ensure you will still get a bool
result.
db>
select not (<bool>{} ?? false);
{true}
The and
and or
operators are commutative.
The truth tables are as follows:
a |
b |
a |
a |
|
---|---|---|---|---|
true |
true |
true |
true |
false |
true |
false |
false |
true |
false |
false |
true |
false |
true |
true |
false |
false |
false |
false |
true |
The operators and
/or
and the functions all()
/any()
differ in the way they handle an empty set ({}
). Both and
and or
operators apply to the cross-product of their operands. If either operand is
an empty set, the result will also be an empty set. For example:
db>
select {true, false} and <bool>{};
{}
db>
select true and <bool>{};
{}
Operating on an empty set with all()
/any()
does not
return an empty set:
db>
select all(<bool>{});
{true}
db>
select any(<bool>{});
{false}
all()
returns true
because the empty set contains no false
values.
any()
returns false
because the empty set contains no
true values.
The all()
and any()
functions are generalized to apply to
sets of values, including {}
. Thus they have the following truth
table:
a |
b |
|
|
---|---|---|---|
true |
true |
true |
true |
true |
false |
false |
true |
{} |
true |
true |
true |
{} |
false |
false |
false |
false |
true |
false |
true |
false |
false |
false |
false |
true |
{} |
true |
true |
false |
{} |
false |
false |
{} |
{} |
true |
false |
Since all()
and any()
apply to sets as a whole,
missing values (represented by {}
) are just that - missing. They
don’t affect the overall result.
To understand the last line in the above truth table it’s useful to
remember that all({a, b}) = all(a) and all(b)
and any({a, b}) =
any(a) or any(b)
.
For more customized handling of {}
, use the ??
operator.
Checks that the input bool is true
.
If the input bool is false
, assert
raises a
QueryAssertionError
. Otherwise, this function returns true
.
db>
select assert(true);
{true}
db>
select assert(false);
edgedb error: QueryAssertionError: assertion failed
db>
select assert(false, message := 'value is not true');
edgedb error: QueryAssertionError: value is not true
assert
can be used in triggers to create more powerful constraints. In
this schema, the Person
type has both friends
and enemies
links. You may not want a Person
to be both a friend and an enemy of
the same Person
. assert
can be used inside a trigger to easily
prohibit this.
type Person {
required name: str;
multi friends: Person;
multi enemies: Person;
trigger prohibit_frenemies after insert, update for each do (
assert(
not exists (__new__.friends intersect __new__.enemies),
message := "Invalid frenemies",
)
)
}
With this trigger in place, it is impossible to link the same Person
as
both a friend and an enemy of any other person.
db>
insert Person {name := 'Quincey Morris'};
{default::Person {id: e4a55480-d2de-11ed-93bd-9f4224fc73af}}
db>
insert Person {name := 'Dracula'};
{default::Person {id: e7f2cff0-d2de-11ed-93bd-279780478afb}}
db> ... ... ... ... ... ...
update Person
filter .name = 'Quincey Morris'
set {
enemies := (
select detached Person filter .name = 'Dracula'
)
};
{default::Person {id: e4a55480-d2de-11ed-93bd-9f4224fc73af}}
db> ... ... ... ... ... ...
update Person
filter .name = 'Quincey Morris'
set {
friends := (
select detached Person filter .name = 'Dracula'
)
};
edgedb error: EdgeDBError: Invalid frenemies
In the following examples, the size
properties of the File
objects
are 1024
, 1024
, and 131,072
.
db> ...
for obj in (select File)
union (assert(obj.size <= 128*1024, message := 'file too big'));
{true, true, true}
db> ...
for obj in (select File)
union (assert(obj.size <= 64*1024, message := 'file too big'));
edgedb error: QueryAssertionError: file too big
You may call assert
in the order by
clause of your select
statement. This will ensure it is called only on objects that pass your
filter.
db> ...
select File { name, size }
order by assert(.size <= 128*1024, message := "file too big");
{ default::File {name: 'File 2', size: 1024}, default::File {name: 'Asdf 3', size: 1024}, default::File {name: 'File 1', size: 131072}, }
db> ...
select File { name, size }
order by assert(.size <= 64*1024, message := "file too big");
edgedb error: QueryAssertionError: file too big
db> ... ...
select File { name, size }
filter .size <= 64*1024
order by assert(.size <= 64*1024, message := "file too big");
{ default::File {name: 'File 2', size: 1024}, default::File {name: 'Asdf 3', size: 1024} }