/* 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 * - 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] {JoinVariableDeclaration}* JoinVariableDeclaration ::= Join [IndexBy] RangeVariableDeclaration ::= identifier {"." identifier}* [["AS"] IdentificationVariable] VariableDeclaration ::= identifier [["AS"] IdentificationVariable] IdentificationVariable ::= identifier 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 SelectExpression ::= (PathExpressionEndingWithAsterisk | Expression | "(" Subselect ")" ) [["AS"] FieldIdentificationVariable] PathExpression ::= identifier {"." identifier}* PathExpressionEndingWithAsterisk ::= {identifier "."}* "*" FieldIdentificationVariable ::= identifier 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}*] ")"