+++ Literals

**Strings**

A string literal is enclosed in single quotes; for example: 'literal'. A string literal that includes a single quote is represented by two single quotes; for example: 'literal''s'.

<code>
FROM User WHERE User.name = 'Vincent'
</code>

**Integers**

Integer literals support the use of PHP integer literal syntax.

<code>
FROM User WHERE User.id = 4
</code>

**Floats**

Float literals support the use of PHP float literal syntax.

<code>
FROM Account WHERE Account.amount = 432.123
</code>

**Booleans**

The boolean literals are true and false.

<code>
FROM User WHERE User.admin = true

FROM Session WHERE Session.is_authed = false
</code>

**Enums**

The enumerated values work in the same way as string literals.

<code>
FROM User WHERE User.type = 'admin'
</code>

Predefined reserved literals are case insensitive, although its a good standard to write them in uppercase.


+++ Input parameters

<code type="php">

// POSITIONAL PARAMETERS:
$users = $conn->query("FROM User WHERE User.name = ?", array('Arnold'));

$users = $conn->query("FROM User WHERE User.id > ? AND User.name LIKE ?", array(50, 'A%'));


// NAMED PARAMETERS:

$users = $conn->query("FROM User WHERE User.name = :name", array(':name' => 'Arnold'));

$users = $conn->query("FROM User WHERE User.id > :id AND User.name LIKE :name", array(':id' => 50, ':name' => 'A%'));
</code>


+++ Operators and operator precedence

The operators are listed below in order of decreasing precedence.

||~ Operator ||~ Description        ||
|| .         || Navigation operator ||
||           || //Arithmetic operators: // ||
|| +, -      || unary               ||
|| *, /      || multiplication and division || 
|| +, -      || addition and subtraction    || 
|| =, >, >=, <, <=, <> (not equal), || Comparison operators ||
|| [NOT] LIKE, [NOT] IN, IS [NOT] NULL, IS [NOT] EMPTY || ||
||           || //Logical operators: // ||
|| NOT       || || 
|| AND       || || 
|| OR        || ||


+++ Between expressions


+++ In expressions

Syntax:

<code>
<operand> IN (<subquery>|<value list>)
</code>

An IN conditional expression returns true if the //operand// is found from result of the //subquery// or if its in the specificied comma separated //value list//, hence the IN expression is always false if the result of the subquery is empty.

When //value list// is being used there must be at least one element in that list.

<code>
FROM C1 WHERE C1.col1 IN (FROM C2(col1));

FROM User WHERE User.id IN (1,3,4,5)
</code>

The keyword IN is an alias for = ANY. Thus, these two statements are equal:

<code>
FROM C1 WHERE C1.col1 = ANY (FROM C2(col1));
FROM C1 WHERE C1.col1 IN    (FROM C2(col1));
</code>


+++ Like Expressions

Syntax:

<code>
string_expression [NOT] LIKE pattern_value [ESCAPE escape_character]
</code>

The string_expression must have a string value. The pattern_value is a string literal or a string-valued input parameter in which an underscore (_) stands for any single character, a percent (%) character stands for any sequence of characters (including the empty sequence), and all other characters stand for themselves. The optional escape_character is a single-character string literal or a character-valued input parameter (i.e., char or Character) and is used to escape the special meaning of the underscore and percent characters in pattern_value.

Examples:

* address.phone LIKE '12%3' is true for '123' '12993' and false for '1234'
* asentence.word LIKE 'l_se' is true for 'lose' and false for 'loose'
* aword.underscored LIKE '\_%' ESCAPE '\' is true for '_foo' and false for 'bar'
* address.phone NOT LIKE '12%3' is false for '123' and '12993' and true for '1234'

If the value of the string_expression or pattern_value is NULL or unknown, the value of the LIKE expression is unknown. If the escape_characteris specified and is NULL, the value of the LIKE expression is unknown.

<code type="php">

// finding all users whose email ends with '@gmail.com'
$users = $conn->query("FROM User u, u.Email e WHERE e.address LIKE '%@gmail.com'");

// finding all users whose name starts with letter 'A'
$users = $conn->query("FROM User u WHERE u.name LIKE 'A%'");
</code>


+++ Null Comparison Expressions
+++ Empty Collection Comparison Expressions
+++ Collection Member Expressions


+++ Exists Expressions

Syntax:

<code>
<operand> [NOT ]EXISTS (<subquery>)
</code>
The EXISTS operator returns TRUE if the subquery returns one or more rows and FALSE otherwise. 

The NOT EXISTS operator returns TRUE if the subquery returns 0 rows and FALSE otherwise.

Finding all articles which have readers:

<code>
FROM Article a
  WHERE EXISTS (SELECT r.id FROM ReaderLog r
                WHERE r.article_id = a.id)
</code>

Finding all articles which don't have readers:

<code>
FROM Article a
  WHERE NOT EXISTS (SELECT r.id FROM ReaderLog r
                WHERE r.article_id = a.id)
</code>     


+++ All and Any Expressions

Syntax:

<code>
operand comparison_operator ANY (subquery)
operand comparison_operator SOME (subquery)
operand comparison_operator ALL (subquery)
</code>

An ALL conditional expression returns true if the comparison operation is true for all values in the result of the subquery or the result of the subquery is empty. An ALL conditional expression is false if the result of the comparison is false for at least one row, and is unknown if neither true nor false.

<code>
FROM C WHERE C.col1 < ALL (FROM C2(col1))
</code>

An ANY conditional expression returns true if the comparison operation is true for some value in the result of the subquery. An ANY conditional expression is false if the result of the subquery is empty or if the comparison operation is false for every value in the result of the subquery, and is unknown if neither true nor false. 

<code>
FROM C WHERE C.col1 > ANY (FROM C2(col1))
</code>

The keyword SOME is an alias for ANY.
 
<code>
FROM C WHERE C.col1 > SOME (FROM C2(col1))
</code>

The comparison operators that can be used with ALL or ANY conditional expressions are =, <, <=, >, >=, <>. The result of the subquery must be same type with the conditional expression.

NOT IN is an alias for <> ALL. Thus, these two statements are equal:

<code>
FROM C WHERE C.col1 <> ALL (FROM C2(col1));
FROM C WHERE C.col1 NOT IN (FROM C2(col1));
</code>


+++ Subqueries

A subquery can contain any of the keywords or clauses that an ordinary SELECT query can contain.

Some advantages of the subqueries:

* They allow queries that are structured so that it is possible to isolate each part of a statement.
* They provide alternative ways to perform operations that would otherwise require complex joins and unions.
* They are, in many people's opinion, readable. Indeed, it was the innovation of subqueries that gave people the original idea of calling the early SQL "Structured Query Language."

<code type="php">
// finding all users which don't belong to any group 1
$query = "FROM User WHERE User.id NOT IN 
                        (SELECT u.id FROM User u 
                         INNER JOIN u.Group g WHERE g.id = ?)";
                         
$users = $conn->query($query, array(1));

// finding all users which don't belong to any groups
// Notice: 
// the usage of INNER JOIN
// the usage of empty brackets preceding the Group component

$query = "FROM User WHERE User.id NOT IN 
                        (SELECT u.id FROM User u 
                         INNER JOIN u.Group g)";

$users = $conn->query($query);
</code>
