January 5, 2025
+ 12
A description of SQL++ for Capella columnar expressions.

An expression is a language fragment that SQL++ evaluates to return a value. For example, the expression 2 + 3 returns the value 5. You use expressions as building blocks for constructing queries. SQL++ for Capella columnar supports nearly all of the kinds of expressions in SQL, and adds some new kinds as well.

SQL++ is an orthogonal language, which means that expressions can serve as operands of higher-level expressions. By nesting expressions inside other expressions, you can build up complex queries. You can enclose any expression in parentheses to establish operator precedence.

This topic introduces the SQL++ for Capella columnar expressions.

Expr
Expr

Operator Expressions

Operators perform a specific operation on the input values or expressions. The syntax of an operator expression follows.

OperatorExpr
OperatorExpr

SQL++ for Capella columnar provides a full set of operators that you can use in statements. Operators are categorized as follows:

The following table summarizes the precedence, in descending order, of the major unary and binary operators:

Operator Operation

EXISTS, NOT EXISTS

Collection emptiness testing

^

Exponentiation

*, /, DIV, MOD (%)

Multiplication, division, modulo

+, -

Addition, subtraction

||

String concatenation

IS NULL, IS NOT NULL, IS MISSING, IS NOT MISSING, IS UNKNOWN, IS NOT UNKNOWN, IS VALUED, IS NOT VALUED

Unknown value comparison

BETWEEN, NOT BETWEEN

Range comparison (inclusive on both sides)

=, !=, <>, <, >, <=, >=, LIKE, NOT LIKE, IN, NOT IN, IS DISTINCT FROM, IS NOT DISTINCT FROM

Comparison

NOT

Logical negation

AND

Conjunction

OR

Disjunction

In general, if any operand evaluates to a MISSING value, the enclosing operator returns MISSING. If none of the operands evaluates to a MISSING value but there is an operand that evaluates to a NULL value, the enclosing operator returns NULL. For information about exceptions to these results, see comparison operators and logical operators.

Arithmetic Operators

You use arithmetic operators to add, subtract, multiply, divide, and exponentiate numeric values, or to concatenate string values.

Operator Purpose Example

+, -

As unary operators, denote a positive or negative expression

SELECT VALUE -1; returns [ -1 ]

+, -

As binary operators, add or subtract

SELECT VALUE 1 + 2; returns [ 3 ]

*

Multiply

SELECT VALUE 4 * 2; returns [ 8 ]

/

Float division, returns a value of type double

SELECT VALUE 5 / 2; returns [ 2.5 ]

DIV

Integer division, returns a value of type bigint

SELECT VALUE 5 DIV 2; returns [ 2 ]

MOD (%)

Modulo, returns the remainder of a division

SELECT VALUE 5 % 2; returns [ 1 ]

^

Exponentiation

SELECT VALUE 2^3; returns [ 8 ]

||

String concatenation

SELECT VALUE "ab"||"c"||"d"; returns [ "abcd" ]

Collection Operators

You use collection operators for membership tests (IN, NOT IN) or empty collection tests (EXISTS, NOT EXISTS).

Operator Purpose Example

IN

Membership test

FROM customers AS c
WHERE c.address.zipcode IN ["02340", "02115"]
SELECT *;

NOT IN

Non-membership test

FROM customers AS c
WHERE c.address.zipcode NOT IN ["02340", "02115"]
SELECT *;

EXISTS

Check whether a collection is not empty

FROM orders AS o
WHERE EXISTS o.items
SELECT *;

NOT EXISTS

Check whether a collection is empty

FROM orders AS o
WHERE NOT EXISTS o.items
SELECT *;

Comparison Operators

You use comparison operators to compare values. The comparison operators fall into one of two sub-categories: missing value comparisons and regular value comparisons.

In an object, SQL++ for Capella columnar can represent missing information in two different ways:

  • The presence of the field with a NULL for its value, as in SQL.

  • The absence of the field, as permitted by JSON.

For example, the first of the following objects represents Jack, who has a friend, Jill. In the other objects, Jake is friendless in SQL fashion, with a friend field with a value of NULL, while Joe is friendless in JSON fashion: by not having a friend field at all.

Examples
{"name": "Jack", "friend": "Jill"}
{"name": "Jake", "friend": NULL}
{"name": "Joe"}

The following table lists all of the comparison operators available in SQL++ for Capella columnar.

Operator Purpose Example

IS NULL

Test if a value is NULL

FROM customers AS c
WHERE c.name IS NULL
SELECT *;

IS NOT NULL

Test if a value is not NULL

FROM customers AS c
WHERE c.name IS NOT NULL
SELECT *;

IS MISSING

Test if a value is MISSING

FROM customers AS c
WHERE c.name IS MISSING
SELECT *;

IS NOT MISSING

Test if a value is not MISSING

FROM customers AS c
WHERE c.name IS NOT MISSING
SELECT *;

IS UNKNOWN

Test if a value is NULL or MISSING

FROM customers AS c
WHERE c.name IS UNKNOWN
SELECT *;

IS NOT UNKNOWN

Test if a value is neither NULL nor MISSING

FROM customers AS c
WHERE c.name IS NOT UNKNOWN
SELECT *;

IS KNOWN (IS VALUED)

Test if a value is neither NULL nor MISSING

FROM customers AS c
WHERE c.name IS KNOWN
SELECT *;

IS NOT KNOWN (IS NOT VALUED)

Test if a value is NULL or MISSING

FROM customers AS c
WHERE c.name IS NOT KNOWN
SELECT *;

BETWEEN

Test if a value is between a start value and an end value, inclusive of both the start and end values.

FROM customers AS c WHERE c.rating BETWEEN 600 AND 700 SELECT *;

=

Equality test

FROM customers AS c
WHERE c.rating = 640
SELECT *;

!=

Inequality test

FROM customers AS c
WHERE c.rating != 640
SELECT *;

<>

Inequality test

FROM customers AS c
WHERE c.rating <> 640
SELECT *;

<

Less than

FROM customers AS c
WHERE c.rating < 640
SELECT *;

>

Greater than

FROM customers AS c
WHERE c.rating > 640
SELECT *;

<=

Less than or equal to

FROM customers AS c
WHERE c.rating <= 640
SELECT *;

>=

Greater than or equal to

FROM customers AS c
WHERE c.rating >= 640
SELECT *;

LIKE

Test if the left side matches a pattern defined on the right side; in the pattern, % matches any string while _ matches any character.

FROM customers AS c WHERE c.name LIKE "%Dodge%" SELECT *;

NOT LIKE

Test if the left side does not match a pattern defined on the right side; in the pattern, % matches any string while _ matches any character.

FROM customers AS c WHERE c.name NOT LIKE "%Dodge%" SELECT *;

IS DISTINCT FROM

Inequality test that treats NULL values as equal to each other and MISSING values as equal to each other

FROM orders AS o
WHERE o.order_date IS DISTINCT FROM o.ship_date
SELECT *;

IS NOT DISTINCT FROM

Equality test that treats NULL values as equal to each other and MISSING values as equal to each other

FROM orders AS o
WHERE o.order_date IS NOT DISTINCT FROM o.ship_date
SELECT *;

The following table summarizes how the missing value comparison operators work.

Operator Non-NULL/Non-MISSING value NULL value MISSING value

IS NULL

FALSE

TRUE

MISSING

IS NOT NULL

TRUE

FALSE

MISSING

IS MISSING

FALSE

FALSE

TRUE

IS NOT MISSING

TRUE

TRUE

FALSE

IS UNKNOWN

FALSE

TRUE

TRUE

IS NOT UNKNOWN

TRUE

FALSE

FALSE

IS KNOWN (IS VALUED)

TRUE

FALSE

FALSE

IS NOT KNOWN (IS NOT VALUED)

FALSE

TRUE

TRUE

Logical Operators

Logical operators perform logical NOT, AND, and OR operations over Boolean values (TRUE and FALSE) plus NULL and MISSING.

Operator Purpose Example

NOT

Returns true if the following condition is false, otherwise returns false

SELECT VALUE NOT 1 = 1;
Returns FALSE

AND

Returns true if both branches are true, otherwise returns false

SELECT VALUE 1 = 2 AND 1 = 1;
Returns FALSE

OR

Returns true if one branch is true, otherwise returns false

SELECT VALUE 1 = 2 OR 1 = 1;
Returns TRUE

The truth table for AND and OR follows.

A B A AND B A OR B

TRUE

TRUE

TRUE

TRUE

TRUE

FALSE

FALSE

TRUE

TRUE

NULL

NULL

TRUE

TRUE

MISSING

MISSING

TRUE

FALSE

FALSE

FALSE

FALSE

FALSE

NULL

FALSE

NULL

FALSE

MISSING

FALSE

MISSING

NULL

NULL

NULL

NULL

NULL

MISSING

MISSING

NULL

MISSING

MISSING

MISSING

MISSING

The following table demonstrates the results of NOT on all possible inputs.

A NOT A

TRUE

FALSE

FALSE

TRUE

NULL

NULL

MISSING

MISSING

Quantified Expressions

QuantifiedExpr
QuantifiedExpr

Synonym for SOME: ANY

You use quantified expressions to express existential or universal predicates involving the elements of a collection.

In the following examples, quantified expressions test whether every element in a set of integers is less than 3, and then whether some of the elements are less than 3.

Examples
EVERY x IN [ 1, 2, 3 ] SATISFIES x < 3 -- ➊
SOME x IN [ 1, 2, 3 ] SATISFIES x < 3  -- ➋

➀ Returns FALSE
➁ Returns TRUE

If the set in these examples is empty [ ], the first expression yields TRUE because every value in an empty set satisfies the condition of less than 3. The second expression yields FALSE because there are no values in the set, there aren’t some, or any, values that are less than 3. To express a universal predicate that yields FALSE with the empty set, you use the quantifier SOME AND EVERY in place of EVERY.

A quantified expression returns NULL or MISSING if the first expression in it evaluates to NULL or MISSING. Otherwise, a type error results if the first expression in a quantified expression does not return a collection.

Path Expressions

PathExpr
PathExpr

You use path expressions to access the components of complex types in the data model. You can apply path access to the result of a query expression that yields an instance of a complex type, for example, an object or an array instance.

For objects, path access is based on field names, and it accesses the field with the specified name.

For arrays, path access is based on zero-based array-style indexing. You can use array indexes to retrieve either a single element from an array or a whole subset of an array.

  • To access a single element you provide a single index argument (zero-based element position).

  • To obtain a subset of an array, you provide the start and end (zero-based) index positions. The returned subset is from position start to position end - 1. The end position argument is optional. If you supply a negative position argument, SQL++ for Capella columnar counts the element position from the end of the array: -1 addresses the last element, -2 next to last, and so on.

Multisets have similar behavior to arrays, except for retrieving arbitrary items as the order of items is not fixed in multisets.

Attempts to access non-existent fields or out-of-bound array elements produce the special value MISSING. Inappropriate use of a path expression, such as applying a field accessor to a numeric value, results in a type error.

The following examples show field access for an object, index-based element access or subset retrieval of an array, and also a composition thereof.

Examples
({"name": "MyABCs", "array": [ "a", "b", "c"]}).array    -- ➊
(["a", "b", "c"])[2]                                     -- ➋
(["a", "b", "c"])[-1]                                    -- ➌
({"name": "MyABCs", "array": [ "a", "b", "c"]}).array[2] -- ➍
(["a", "b", "c"])[0:2]                                   -- ➎
(["a", "b", "c"])[0:]                                    -- ➏
(["a", "b", "c"])[-2:-1]                                 -- ➐

➀ Returns [["a", "b", "c"]]
➁ Returns ["c"]
➂ Returns ["c"]
➃ Returns ["c"]
➄ Returns [["a", "b"]]
➅ Returns [["a", "b", "c"]]
➆ Returns [["b"]]

Primary Expressions

PrimaryExpr
PrimaryExpr

The most basic building block for any expression in SQL++ for Capella columnar is Primary Expression. This can be a simple literal (constant) value, a reference to a query variable that is in scope, a parenthesized expression, a function call, or a newly constructed instance of the data model (such as a newly constructed object, array, or multiset of data model instances).

Literals

Literal
Literal

The simplest kind of expression is a literal that directly represents a value in JSON format. Examples follow.

-42
"Hello"
true
false
null

Numeric literals can include a sign and an optional decimal point. You can also write them in exponential notation, like this:

5e2
-4.73E-2

You enclose string literals in either single ' ' or double " " quotes. For a string literal that includes single or double quote characters, you must escape the character with a backward slash \, as in these examples:

"I read \"War and Peace\" today."
'I don\'t believe everything I read.'

The table that follows shows how to escape characters in SQL++ for Capella columnar.

Character Name Escape Method

Single Quote

\'

Double Quote

\"

Backslash

\\

Slash

\/

Backspace

\b

Formfeed

\f

Newline

\n

CarriageReturn

\r

EscapeTab

\t

Identifiers and Variable References

Like SQL, SQL++ makes use of a language construct called an identifier. See the Requirements for Identifiers. To use an identifier that is the same as a reserved keyword in a query, you must escape that identifier with backtick (``) characters. Identifiers enclosed by backticks are known as delimited identifiers.

You use identifiers in variable names, path expressions, and in other places in SQL++ for Capella columnar syntax. Examples of identifiers follow.

X
customer_name
`SELECT`
`spaces in here`
`@&#`

A very simple kind of SQL++ for Capella columnar expression is a variable, which is simply an identifier. As in SQL, a variable can be bound to a value, which can be an input dataset, some intermediate result during processing of a query, or the final result of a query. For more information about variables, see sqlpp:3_query.adoc#Select_clauses.

SQL++ for Capella columnar has different rules for delimiting strings and identifiers than the SQL rules. In SQL, you use single quotes to enclose strings, and double quotes to enclose delimited identifiers.

Parameter References

A parameter reference is an external variable. You provide its value using the query options feature in the UI. See Set Query Options.

Parameter references come in two forms, named parameter references and positional parameter references.

  • Named parameter references consist of the $ symbol followed by an identifier or delimited identifier.

  • Positional parameter references can be either a $ symbol followed by one or more digits or a ? symbol. If numbered, positional parameters start at 1. SQL++ for Capella columnar interprets ? parameters as $1 to $N based on the order in which they appear in the statement.

Parameter references can appear as shown in the following examples:

Examples
$id
$1
?

An error results if the parameter is not bound at query execution time.

Parenthesized Expressions

ParenthesizedExpr
ParenthesizedExpr
Subquery
Subquery

You can parenthesize an expression to control the precedence order or otherwise clarify a query. You can also enclose a subquery (nested selection) in parentheses.

The following expression evaluates to the value 2.

Example
( 1 + 1 )

Function Calls

FunctionCall
FunctionCall
OrdinaryFunctionCall
OrdinaryFunctionCall
AggregateFunctionCall
Identifier "(" ("DISTINCT")? Expr ")" ("FILTER" "(" "WHERE" Expr ")")?
DatabaseAndScopeName
(Identifier ".")? Identifier

SQL++ for Capella columnar, like most languages, provides functions to package or componentize complicated or reusable computations. A function call is a legal query expression that represents the value resulting from the evaluation of its body expression with the given parameter bindings. The parameter value bindings can themselves be any expressions in SQL++ for Capella columnar.

In the following example, the value of the function call expression is 8.

Example
length('a string')

Case Expressions

CaseExpr
CaseExpr
SimpleCaseExpr
SimpleCaseExpr
SearchedCaseExpr
SearchedCaseExpr

In an uncomplicated CASE expression, the query evaluator searches for the first WHEN …​ THEN pair in which the WHEN expression is equal to the expression following CASE and returns the expression following THEN. If none of the WHEN …​ THEN pairs meet this condition, and an ELSE branch exists, it returns the ELSE expression. Otherwise, it returns NULL.

In a searched CASE expression, the query evaluator searches from left to right until it finds a WHEN expression that evaluates to TRUE, and then returns its corresponding THEN expression. If no condition evaluates to TRUE, and an ELSE branch exists, it returns the ELSE expression. Otherwise, it returns NULL.

The following example illustrates the form of a case expression.

Example
CASE (2 < 3) WHEN true THEN "yes" ELSE "no" END

Constructors

Constructor
Constructor
ObjectConstructor
ObjectConstructor
ArrayConstructor
ArrayConstructor
MultisetConstructor
MultisetConstructor

You can use constructors to represent structured JSON values, as in these examples:

{ "name": "Bill", "age": 42 } -- ➊
[ 1, 2, "Hello", null ]       -- ➋

➀ An object
➁ An array

In a constructed object:

  • The names of the fields must be either literal strings or computed strings

  • An object cannot contain any duplicate names

Structured literals can be nested, as in this example:

[ {"name": "Bill",
   "address":
      {"street": "25 Main St.",
       "city": "Cincinnati, OH"
      }
  },
  {"name": "Mary",
   "address":
      {"street": "107 Market St.",
       "city": "St. Louis, MO"
      }
   }
]

You can use expressions to represent the array items in an array constructor and the field-names and field-values in an object constructor.

For example, suppose that the variables firstname, lastname, salary, and bonus are bound to appropriate values. You might construct structured values by the following expressions:

An object:

{
  "name": firstname || " " || lastname,
  "income": salary + bonus
}

An array:

["1984", lastname, salary + bonus, null]

If only one expression is specified instead of the field-name/field-value pair in an object constructor then this expression is supposed to provide the field value. The field name is then automatically generated based on the kind of the value expression as in the example that follows:

  • If it is a variable reference expression then the generated field name is the name of that variable.

  • If it is a field access expression then the generated field name is the last identifier in that expression.

  • For all other cases, a compilation error results.

Example
FROM customers AS c
WHERE c.custid = "C47"
SELECT VALUE {c.name, c.rating};

This query returns:

[
    {
        "name": "S. Logan",
        "rating": 625
    }
]