Every EdgeQL command is composed of a sequence of tokens, terminated by
a semicolon (;
). The types of valid tokens as well as their order
is determined by the syntax of the particular command.
EdgeQL is case sensistive except for keywords (in the examples the keywords are written in upper case as a matter of convention).
There are several kinds of tokens: keywords, identifiers, literals (constants) and symbols (operators and punctuation).
Tokens are normally separated by whitespace (space, tab, newline) or comments.
There are two ways of writing identifiers in EdgeQL: plain and quoted.
The plain identifiers are similar to many other languages, they are
alphanumeric with underscores and cannot start with a digit. The
quoted identifiers start and end with a backtick
`quoted.identifier`
and can contain any characters inside with a
few exceptions. They must not start with an ampersand (@
) or
contain a double colon (::
). If there’s a need to include a backtick
character as part of the identifier name a double-backtick sequence
(``
) should be used: `quoted``identifier`
will result in the
actual identifier being quoted`identifier
.
identifier | ::= |
plain_ident | quoted_ident |
plain_ident | ::= |
ident_first
ident_rest * |
ident_first | ::= | <any letter, underscore> |
ident_rest | ::= | <any letter, digits, underscore> |
quoted_ident | ::= | "`" qident_first
qident_rest * "`" |
qident_first | ::= | <any character except "@"> |
qident_rest | ::= | <any character> |
Quoted identifiers are usually needed to represent module names that
contain a dot (.
) or to distinguish names from reserved keywords
(for instance to allow referring to a link named “order” as `order`
).
There are a number of reserved and unreserved keywords in EdgeQL. Every identifier that is not a reserved keyword is a valid name. Names are used to refer to concepts, links, link properties, etc.
short_name | ::= |
not_keyword_ident | quoted_ident |
not_keyword_ident | ::= | <any plain_ident except for keyword > |
keyword | ::= |
reserved_keyword | unreserved_keyword |
reserved_keyword | ::= | case insensitive sequence matching any of the following "AGGREGATE" | "ALTER" | "AND" | "ANY" | "COMMIT" | "CREATE" | "DELETE" | "DETACHED" | "DISTINCT" | "DROP" | "ELSE" | "EMPTY" | "EXISTS" | "FALSE" | "FILTER" | "FUNCTION" | "GET" | "GROUP" | "IF" | "ILIKE" | "IN" | "INSERT" | "IS" | "LIKE" | "LIMIT" | "MODULE" | "NOT" | "OFFSET" | "OR" | "ORDER" | "OVER" | "PARTITION" | "ROLLBACK" | "SELECT" | "SET" | "SINGLETON" | "START" | "TRUE" | "UPDATE" | "UNION" | "WITH" |
unreserved_keyword | ::= | case insensitive sequence matching any of the following "ABSTRACT" | "ACTION" | "AFTER" | "ARRAY" | "AS" | "ASC" | "ATOM" | "ANNOTATION" | "BEFORE" | "BY" | "CONCEPT" | "CONSTRAINT" | "DATABASE" | "DESC" | "EVENT" | "EXTENDING" | "FINAL" | "FIRST" | "FOR" | "FROM" | "INDEX" | "INITIAL" | "LAST" | "LINK" | "MAP" | "MIGRATION" | "OF" | "ON" | "POLICY" | "PROPERTY" | "REQUIRED" | "RENAME" | "TARGET" | "THEN" | "TO" | "TRANSACTION" | "TUPLE" | "VALUE" | "VIEW" |
Fully-qualified names consist of a module, ::
, and a short name.
They can be used in most places where a short name can appear (such as
paths and shapes).
name | ::= |
short_name | fq_name |
fq_name | ::= |
short_name "::" short_name |
short_name "::" unreserved_keyword |
A number of scalar types have literal constant expressions.
Production rules for str
literals:
string | ::= |
str | raw_str |
str | ::= | "'" str_content * "'" | '"' str_content * '"' |
raw_str | ::= | "r'" raw_content * "'" |
'r"' raw_content * '"' |
dollar_quote
raw_content * dollar_quote |
raw_content | ::= | <any character different from delimiting quote> |
dollar_quote | ::= | "$" q_char0 ? q_char * "$" |
q_char0 | ::= | "A"..."Z" | "a"..."z" | "_" |
q_char | ::= | "A"..."Z" | "a"..."z" | "_" | "0"..."9" |
str_content | ::= | <newline> | unicode | str_escapes |
unicode | ::= | <any printable unicode character not preceded by "\"> |
str_escapes | ::= | <see below for details> |
The inclusion of “high ASCII” character in q_char
in
practice reflects the ability to use some of the letters with
diacritics like ò
or ü
in the dollar-quote delimiter.
Here’s a list of valid str_escapes
:
Escape Sequence |
Meaning |
---|---|
|
Backslash and all whitespace up to next non-whitespace character is ignored |
|
Backslash (\) |
|
Single quote (‘) |
|
Double quote (“) |
|
ASCII backspace ( |
|
ASCII form feed ( |
|
ASCII newline ( |
|
ASCII carriage return ( |
|
ASCII tabulation ( |
|
Character with hex value hh |
|
Character with 16-bit hex value hhhh |
|
Character with 32-bit hex value hhhhhhhh |
Here’s some examples of regular strings using escape sequences
db> ...
SELECT 'hello
world';
{'hello world'}
db>
SELECT "hello\nworld";
{'hello world'}
db> ...
SELECT 'hello \
world';
{'hello world'}
db> ... ...
SELECT 'https://edgedb.com/\
docs/edgeql/lexical\
#constants';
{'https://edgedb.com/docs/edgeql/lexical#constants'}
db>
SELECT 'hello \\ world';
{'hello \ world'}
db>
SELECT 'hello \'world\'';
{"hello 'world'"}
db>
SELECT 'hello \x77orld';
{'hello world'}
db>
SELECT 'hello \u0077orld';
{'hello world'}
Raw strings don’t have any specially interpreted symbols; they contain all the symbols between the quotes exactly as typed.
db>
SELECT r'hello \\ world';
{'hello \\ world'}
db> ...
SELECT r'hello \
world';
{'hello \ world'}
db> ...
SELECT r'hello
world';
{'hello world'}
A special case of raw strings are dollar-quoted strings. They allow
using either kind of quote symbols '
or "
as part of the
string content without the quotes terminating the string. In fact,
because the dollar-quote delimiter sequences can have arbitrary
alphanumeric additional fillers, it is always possible to surround any
content with dollar-quotes in an unambiguous manner:
db> ...
SELECT $$hello
world$$;
{'hello world'}
db>
SELECT $$hello\nworld$$;
{'hello\nworld'}
db>
SELECT $$"hello" 'world'$$;
{"\"hello\" 'world'"}
db>
SELECT $a$hello$$world$$$a$;
{'hello$$world$$'}
More specifically, a delimiter:
Must start with an ASCII letter or underscore
Has following characters that can be digits 0-9, underscores or ASCII letters
Production rules for bytes
literals:
bytes | ::= | "b'" bytes_content * "'" | 'b"' bytes_content * '"' |
bytes_content | ::= | <newline> | ascii | bytes_escapes |
ascii | ::= | <any printable ascii character not preceded by "\"> |
bytes_escapes | ::= | <see below for details> |
Here’s a list of valid bytes_escapes
:
Escape Sequence |
Meaning |
---|---|
|
Backslash (\) |
|
Single quote (‘) |
|
Double quote (“) |
|
ASCII backspace ( |
|
ASCII form feed ( |
|
ASCII newline ( |
|
ASCII carriage return ( |
|
ASCII tabulation ( |
|
Character with hex value hh |
There are two kinds of integer constants: limited size
(int64
) and unlimited size (bigint
). Unlimited
size integer bigint
literals are similar to a regular
integer literals with an n
suffix. The production rules are as
follows:
By default all integer literals are interpreted as int64
,
while an explicit cast can be used to convert them to int16
or int32
:
db>
SELECT 0;
{0}
db>
SELECT 123;
{123}
db>
SELECT <int16>456;
{456}
db>
SELECT <int32>789;
{789}
Examples of bigint
literals:
db>
SELECT 123n;
{123n}
db>
SELECT 12345678901234567890n;
{12345678901234567890n}
Just as for integers, there are two kinds of real number constants:
limited precision (float64
) and unlimited precision
(decimal
). The decimal
constants have the same
lexical structure as float64
, but with an n
suffix:
decimal | ::= |
float "n" |
float | ::= |
float_wo_dec | float_w_dec |
float_wo_dec | ::= |
integer_part
exp |
float_w_dec | ::= |
integer_part "." decimal_part ? exp ? |
integer_part | ::= | "0" | non_zero
digit * |
decimal_part | ::= |
digit + |
exp | ::= | "e" ("+" | "-")? digit + |
non_zero | ::= | "1"..."9" |
digit | ::= | "0"..."9" |
By default all float literals are interpreted as float64
,
while an explicit cast can be used to convert them to float32
:
db>
SELECT 0.1;
{0.1}
db>
SELECT 12.3;
{12.3}
db>
SELECT 1e3;
{1000.0}
db>
SELECT 1.2e-3;
{0.0012}
db>
SELECT <float32>12.3;
{12.3}
Examples of decimal
literals:
db>
SELECT 12.3n;
{12.3n}
db>
SELECT 12345678901234567890.12345678901234567890n;
{12345678901234567890.12345678901234567890n}
db>
SELECT 12345678901234567890.12345678901234567890e-3n;
{12345678901234567.89012345678901234567890n}
Comments
Comments start with a
#
character that is not otherwise part of a string literal and end at the end of line. Semantically, a comment is equivalent to whitespace.