Enums

So far all the fields you've seen hold plain scalar values like integers and strings. Enums let you define a field whose value must be one of a fixed set of named variants.

Let's say users can have one of three roles. First, define the enum type:

create type main.Role enum { Admin, Moderator, Member };

Then create a main.User struct that includes it as a field:

create type main.User struct { id: Int64, name: String, role: main.Role };
create table main.users : main.User { primary key (id) };

When inserting, reference a variant using the fully qualified name TypeName.Variant:

insert into main.users { id: 1, name: "Alice", role: main.Role.Admin };
insert into main.users { id: 2, name: "Bob", role: main.Role.Member };
insert into main.users { id: 3, name: "Charlie", role: main.Role.Moderator };

Querying by Variant

To filter on an enum field, use is instead of =:

select * from main.users where role is main.Role.Admin;

This returns only Alice. The same works with delete:

delete from main.users where role is main.Role.Moderator;

The Built-in Option Type

TempestDB ships with a global Option[T] enum that represents a value that may or may not be present - similar to nullable fields in other databases, but explicit about it in the type system:

create type main.Profile struct { id: Int64, bio: Option[String] };
create table main.profiles : main.Profile { primary key (id) };

Use Option.None for absent values and Option.Some(value) for present ones:

insert into main.profiles { id: 1, bio: Option.None };
insert into main.profiles { id: 2, bio: Option.Some("TempestDB enthusiast") };

Filtering works the same way with is:

select * from main.profiles where bio is Option.None;