Literals

Discover the different literals available in CQL.

When writing queries using CQL, you can use different types of literals to represent constant values. These include strings, numbers, booleans, and more.

This reference covers all the literals available in CQL, from the basic types like strings and numbers to more advanced types like regular expressions and collections.

Null

Null is a special literal that represents the lack of a value. It is often used to indicate that a variable or attribute has no value.

For example, we use null to represent the initial value of optional attributes, like the user's name, age, or email.

This is how you specify a null value:

Booleans

Booleans are simple literals that represent binary values, such as true/false, yes/no, or on/off. They are commonly used in conditionals, filters, and other places where you need to make a decision.

To write a boolean literal, simply write true or false in your query:

true // or false
Try in Playground

Because CQL is case-insensitive, there is no distinction between true and TRUE. You can use whichever one you prefer.

Numbers

CQL supports both whole and real numbers, which include integers and numbers with a fractional part. In most cases, you do not need to worry about selecting the appropriate type, as CQL automatically chooses the most suitable one.

Unlike other languages, CQL does not adopt floats as its default numeric type. Instead, it uses integers or decimals, depending on whether the number has a fractional part. This is because floats are approximations and may not always yield the expected results.

For example, let's say you add 0.1 and 0.2. You might expect the result to be 0.3, but with floating-point numbers, it's actually 0.30000000000000004. This is because floats are represented in binary, and 0.1 cannot be represented accurately as a floating-point number.

Croct's mascot buggy
Wait, what?

Yes, we know it's weird. But sometimes, computers favor speed over precision. If you want to learn more about this, check out this page.

To mitigate this problem, CQL uses decimals for fractional numbers by default. This ensures that your results in CQL match what you learned in math class. And if you need to use floats, you can still do so by adding the f suffix to the number.

Integers

Integers are whole numbers, either positive or negative, that have no fractional part. To express an integer literal, simply write the number without a decimal point:

For those familiar with the technical terminology, the underlying type is a 64-bit signed integer. This means that the highest value allowed is 9223372036854775807, while the lowest is -9223372036854775808. Specifying a value outside this range will result in an error.

Real numbers

Real numbers consist of integers and numbers with a fractional part. These are commonly used to represent continuous values, such as lengths, weights, and other quantities.

CQL supports two types of real numbers: decimals, which have maximum precision, and floats, which are approximate.

Both decimal and float literals support exponential notation. This allows you to represent very large or very small numbers in a more compact way.

In exponential notation, you write a real number as the product of two numbers: a coefficient and an exponent. The e or E indicate that the number is multiplied by 10 raised to the power of the exponent.

For example, the number 3.0e2 represents 3.0 * (10 ** 2), which is equal to 300.0, and 1.5e-3 represents 1.5 * (10 ** -3), which is equal to 0.0015.

Let's take a look at each of these types in more detail.

Decimals

Decimal is the type used to represent fractional numbers in CQL. Because they are precise, they avoid many pitfalls of floating-point arithmetic.

Unlike integers, decimal numbers do not have a maximum or minimum value. However, they do have a maximum precision of 28 digits. Precision refers to the number of significant digits in the number, excluding any leading zeros.

For example, the number 123.456 has 6 significant digits, 0.02001 has 4, and 0.000001 has only 1.

To write a decimal literal, simply write the number with a decimal point, followed by the digits of the fractional part:

You can also represent a whole number as a decimal by adding a .0 to the end:

And you can use exponential notation to represent very large numbers:

3.0e2 // 300.0
Try in Playground

Or very small numbers:

1.5e-3 // 0.0015
Try in Playground

For fractions, you can skip the whole part and start with the decimal:

.5 // This is equivalent to 0.5
Try in Playground

Keep in mind that although decimals are suitable for most use cases, they might not be the best choice for representing approximate values such as measurements, scores, or ratings. For these cases, consider using floats instead.

Floats

Floats are commonly used to represent continuous values that do not need to be precise. They are approximate real numbers that trade accuracy for the speed of computational operations.

Use floats when you need to represent approximate values, such as geo-coordinates, ratios, or probabilities.

To specify a float literal, add the f suffix to the number:

You can also use exponential notation to represent very large numbers:

3.0e2f // 300.0f
Try in Playground

Or very small numbers:

1.5e-3f // 0.0015f
Try in Playground

For fractions, you can skip the whole part and start with the decimal:

.5f // This is equivalent to 0.5f
Try in Playground

The underlying float type is a 64-bit floating-point number, equivalent to the double type in other languages. It can only accurately represent integers in the range -9007199254740991 to 9007199254740991 and a subset of decimal numbers.

As mentioned earlier, floats are approximate and may not always yield the expected results. If you need to perform precise calculations, consider using decimals instead.

Ordinals

Ordinals are a convenient and more natural alternative to using numerical indices, which are zero-based and sometimes confusing.

In English, you add the suffixes st, nd, rd, and th to indicate position, as in 1st, 2nd, 3rd, and 4th. This is exactly how you use ordinals in CQL.

Croct's mascot neutral
Can I use ordinals everywhere?

You can use ordinals only where explicitly indicated in the documentation. Attempting to use them in other situations will result in a syntax error.

One of the primary use cases of ordinals in CQL is when accessing items from collections. For example, the following expression returns the first item the user added to their cart:

cart.items[1st]
Try in Playground

In some instances, you can also express ordinal numbers using words such as first, second, third, through twelfth to indicate a position. Yet, not all places where you can use ordinals support the word form, so check the relevant documentation for specific cases.

For a practical use case of ordinals, see the Ordinal selector documentation.

Strings

Strings are sequences of characters that represent text. They can include letters, numbers, punctuation marks, and even special symbols, such as emoji or Unicode characters. In CQL, you can create strings using either single or double quotes.

Single-quoted strings

Single-quoted strings are a simpler form of strings where all characters are interpreted as they are written, without any processing or interpretation.

You can create a single-quoted string by enclosing the text in single quotes:

'This is a single-quoted string'
Try in Playground

If you need to include a single quote character in your string, you can escape it with a backslash:

'It\'s a beautiful day 🏖️' // It's a beautiful day 🏖️
Try in Playground

Double-quoted strings

Double-quoted strings are more powerful and versatile than single-quoted strings, as they allow the use of escape sequences.

You can create a double-quoted string by enclosing the text in double quotes:

"This is a double-quoted string"
Try in Playground

In some cases, you may need to include a double quote in your string. This is where escape sequences come in handy.

Escape sequences

Escape sequences are special character combinations that begin with a backslash (\) and are followed by one or more characters. They are used to represent characters that cannot be typed directly, control the formatting of the string, or include special symbols.

Here are some common escape sequences and their meanings:

  • \\ represents a single backslash (\)
  • \" represents a double quote (")
  • \' represents a single quote (')
  • \n represents a newline character (a line break)
  • \t represents a tab character

For example, to represent a string with a quote and a newline, you could write:

"Say \"Hello, CQL!\"\nWelcome to the world of strings."
Try in Playground

This string would be rendered as:

Say "Hello, CQL!"
Welcome to the world of strings.

Unicode characters

Strings in CQL are encoded in UTF-8, meaning you can use any Unicode character directly in your strings, including emoji and other special symbols.

For example, to include a big smiley face in a string, you could write:

"Who doesn't like emoji? 😃"
Try in Playground

However, some characters are difficult to type or are not displayed correctly in text editors. In such situations, you can use the \u escape sequence followed by the character's Unicode code point to represent it in your string.

Croct's mascot neutral
What is a code point?

A code point is a number that uniquely identifies a character in the Unicode standard. For example, the code point for the letter A is U+0041.

For example, you can represent the summation symbol ∑ (U+2211) as follows:

"Summation: \u2211" // Summation: ∑
Try in Playground

For a complete list of Unicode characters and their code points, check out this page.

Regex

Regular expressions, or regexes for short, provide a powerful and flexible way to match patterns in strings.

CQL supports the PCRE variant, which is widely used and known for its rich feature set and strong performance.

A regular expression literal is expressed using the ~/ delimiter, followed by the pattern, a slash /, and optionally one or more modifiers.

Here is a basic example with all the parts:

In this example, the regular expression [a-z] matches any lowercase letter from a to z. The i modifier indicates that the match should be case-insensitive, allowing it to also match uppercase letters from A to Z. See this page for a detailed tutorial on regular expressions.

Finally, if you want to check whether a string matches a regular expression, you can use the matches test.

Collections

Collection literals provide a flexible and unified syntax for representing lists, sets, maps, and potentially other types of collections.

The reason for this flexibility is that they are represented as ordered maps, where each element in the collection has a specific key. If you omit the keys, the collection behaves like a list, with sequential numeric indexes as keys.

Let's look at each of these collection types in more detail.

Lists

A list is a collection of ordered elements that do not require explicit keys. Instead, the keys are automatically generated as sequential numeric indices, starting from zero.

To define a list, enclose the items in square brackets separated by a comma:

let list = [1, 2, 3, 4];
Try in Playground

The above example creates a list with four elements. You can access the elements by their index using the square bracket notation:

list[0] // 1
Try in Playground

Note that the index starts from zero and the elements are listed in the order in which they were defined. So, the first element has an index of 0, the second element has an index of 1, and so on.

Sets

A set is a collection of unique elements. In other words, each item in a set appears only once, meaning no duplicates exist.

Even though CQL has no specific syntax for sets, any collection without duplicates can be considered a set. Therefore, you can use lists to represent sets as well.

For example, although the following variable is technically a list, it can also be considered a set of emojis since each emoji appears only once:

let set = ['👻', '🎃', '👽'];
Try in Playground

You can also use the without duplicates modifier to turn any collection into a set:

let list = ['a', 'b', 'c', 'b'];
list without duplicates // ['a', 'b', 'c']
Try in Playground

This modifier removes duplicate elements in a collection, leaving only the first occurrence of each element.

Maps

A map is a collection where each element has an explicit key that you can use to access it. You can think of an ordered map as a key-value store, where each key is associated with a value.

To create a map, simply enclose the key-value pairs in square brackets. Use a comma to separate each pair and a colon to separate the key and value:

let map = ["yes": "👍", "no": "👎"];
Try in Playground

In a map, keys can be either strings or integers. You can also use variables or expressions as keys:

let three = 3;
[1: "a", "2": "b", three: "c", (3 + 1): "d"]
Try in Playground

Notice that string keys representing integer values are automatically converted to integers. Also, when using variables or expressions as keys, any non-string value is converted to a string.

You can access the elements of a map using the square bracket notation:

map["yes"] // 👍
Try in Playground

An important thing to remember is that maps are arranged in the same order as you define their elements. This is especially relevant when using order-dependent expressions, like ordinal accessors.