query-language.txt 3.96 KB
Newer Older
romanb's avatar
romanb committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
/* Context-free grammar for Doctrine Query Language
 *
 * Document syntax:
 *  - non-terminals begin with an upper case character
 *  - terminals begin with a lower case character
 *  - parentheses (...) are used for grouping
 *  - square brackets [...] are used for defining an optional part, eg. zero or
 *    one time time
 *  - curly brackets {...} are used for repetion, eg. zero or more times
 *  - double quotation marks "..." define a terminal string
 *  - a vertical bar | represents an alternative
 *
 * At a first glance we'll support SQL-99 based queries
 * Initially Select and Sub-select DQL will not support LIMIT and OFFSET (due to limit-subquery algorithm)
 */

QueryLanguage   = SelectStatement | UpdateStatement | DeleteStatement

SelectStatement = SelectClause FromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause]
UpdateStatement = UpdateClause [WhereClause]
DeleteStatement = DeleteClause [WhereClause]

Subselect       = SimpleSelectClause FromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause]
SelectClause    = "SELECT" ["ALL" | "DISTINCT"] SelectExpression {"," SelectExpression}
SimpleSelectClause = "SELECT" ["ALL" | "DISTINCT"] SelectExpression
DeleteClause    = "DELETE" ["FROM"] VariableDeclaration
WhereClause     = "WHERE" ConditionalExpression
FromClause      = "FROM" IdentificationVariableDeclaration {"," IdentificationVariableDeclaration}
HavingClause    = "HAVING" ConditionalExpression
GroupByClause   = "GROUP" "BY" GroupByItem {"," GroupByItem}
OrderByClause   = "ORDER" "BY" OrderByItem {"," OrderByItem}
LimitClause     = "LIMIT" integer
OffsetClause    = "OFFSET" integer
UpdateClause    = "UPDATE" VariableDeclaration "SET" UpdateItem {"," UpdateItem}

OrderByItem = Expression ["ASC" | "DESC"]
GroupByItem = PathExpression
UpdateItem = PathExpression "=" (Expression | "NULL")

IdentificationVariableDeclaration = RangeVariableDeclaration [IndexBy] {Join [IndexBy]}
RangeVariableDeclaration = identifier {"." identifier} [["AS"] IdentificationVariable]
VariableDeclaration = identifier [["AS"] IdentificationVariable]
43
IdentificationVariable = identifier
romanb's avatar
romanb committed
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

Join = ["LEFT" | "INNER"] "JOIN" RangeVariableDeclaration [("ON" | "WITH") ConditionalExpression]
IndexBy = "INDEX" "BY" identifier

ConditionalExpression = ConditionalTerm {"OR" ConditionalTerm}
ConditionalTerm       = ConditionalFactor {"AND" ConditionalFactor}
ConditionalFactor     = ["NOT"] ConditionalPrimary
ConditionalPrimary    = SimpleConditionalExpression | "(" ConditionalExpression ")"
SimpleConditionalExpression
                      = Expression (ComparisonExpression | BetweenExpression | LikeExpression
                      | InExpression | NullComparisonExpression) | ExistsExpression

Atom = string | integer | float | boolean | input_parameter

Expression = Term {("+" | "-") Term}
Term       = Factor {("*" | "/") Factor}
Factor     = [("+" | "-")] Primary
Primary    = PathExpression | Atom | "(" Expression ")" | Function | AggregateExpression

63
SelectExpression  = (PathExpressionEndingWithAsterisk | Expression | "(" Subselect ")" ) [["AS"] FieldIdentificationVariable]
romanb's avatar
romanb committed
64 65
PathExpression = identifier {"." identifier}
PathExpressionEndingWithAsterisk = {identifier "."} "*"
66
FieldIdentificationVariable = identifier
romanb's avatar
romanb committed
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81

AggregateExpression = ("AVG" | "MAX" | "MIN" | "SUM") "(" ["DISTINCT"] Expression ")"
                    | "COUNT" "(" ["DISTINCT"] (Expression | "*") ")"

QuantifiedExpression     = ("ALL" | "ANY" | "SOME") "(" Subselect ")"
BetweenExpression        = ["NOT"] "BETWEEN" Expression "AND" Expression
ComparisonExpression     = ComparisonOperator ( QuantifiedExpression | Expression | "(" Subselect ")" )
InExpression             = ["NOT"] "IN" "(" (Atom {"," Atom} | Subselect) ")"
LikeExpression           = ["NOT"] "LIKE" Expression ["ESCAPE" string]
NullComparisonExpression = "IS" ["NOT"] "NULL"
ExistsExpression         = "EXISTS" "(" Subselect ")"

ComparisonOperator = "=" | "<" | "<=" | "<>" | ">" | ">=" | "!="

Function = identifier "(" [Expression {"," Expression}] ")"