diff --git a/draft/Doctrine/Query/Parser.php b/draft/Doctrine/Query/Parser.php index 739ff6cdd..94e4abdc5 100644 --- a/draft/Doctrine/Query/Parser.php +++ b/draft/Doctrine/Query/Parser.php @@ -28,7 +28,7 @@ * @subpackage Query * @author Janne Vanhala * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.phpdoctrine.org + * @link http://www.phpdoctrine.org * @since 1.0 * @version $Revision$ */ @@ -111,11 +111,22 @@ class Doctrine_Query_Parser $this->_conn = $conn; } + /** + * Returns the connection object used by the query. + * + * @return Doctrine_Connection + */ public function getConnection() { return $this->_conn; } + /** + * Returns a production object with the given name. + * + * @param string $name production name + * @return Doctrine_Query_Production + */ public function getProduction($name) { if ( ! isset($this->_productions[$name])) { @@ -154,12 +165,17 @@ class Doctrine_Query_Parser public function logError($message = '') { if ($message === '') { - $message = 'Unexpected "' . $this->lookahead['value'] . '"'; + if ($this->lookahead === null) { + $message = 'Unexpected end of string.'; + } else { + $message = 'Unexpected "' . $this->lookahead['value'] . '"'; + } } if ($this->_errorDistance >= self::MIN_ERROR_DISTANCE) { - $message .= 'at line ' . $this->lookahead['line'] - . ', column ' . $this->lookahead['column']; + if ($this->lookahead !== null) { + $message .= ' at position ' . $this->lookahead['position']; + } $this->_errors[] = $message; } @@ -176,6 +192,11 @@ class Doctrine_Query_Parser return $this->_scanner; } + /** + * Returns the parse tree printer object associated with this object. + * + * @return Doctrine_Query_Printer + */ public function getPrinter() { return $this->_printer; @@ -193,11 +214,11 @@ class Doctrine_Query_Parser $this->getProduction('QueryLanguage')->execute(); if ($this->lookahead !== null) { - $this->_error('End of string expected.'); + $this->logError('End of string expected'); } if (count($this->_errors)) { - $msg = 'Query string parsing failed (' + $msg = 'Errors were detected during the query parsing (' . implode('; ', $this->_errors) . ').'; throw new Doctrine_Query_Parser_Exception($msg); } diff --git a/draft/Doctrine/Query/Printer.php b/draft/Doctrine/Query/Printer.php index 220abbf26..d68cc5fc6 100644 --- a/draft/Doctrine/Query/Printer.php +++ b/draft/Doctrine/Query/Printer.php @@ -1,26 +1,91 @@ . + */ + +/** + * A parse tree printer for Doctrine Query Language parser. + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ + */ class Doctrine_Query_Printer { + /** + * Current indentation level + * + * @var int + */ protected $_indent = 0; + + /** + * Defines whether parse tree is printed (default, false) or not (true). + * + * @var bool + */ protected $_silent; + /** + * Constructs a new parse tree printer. + * + * @param bool $silent Parse tree will not be printed if true. + */ public function __construct($silent = false) { $this->_silent = $silent; } + /** + * Prints an opening parenthesis followed by production name and increases + * indentation level by one. + * + * This method is called before executing a production. + * + * @param string $name production name + */ public function startProduction($name) { $this->println('(' . $name); $this->_indent++; } + /** + * Decreases indentation level by one and prints a closing parenthesis. + * + * This method is called after executing a production. + */ public function endProduction() { $this->_indent--; $this->println(')'); } + /** + * Prints text indented with spaces depending on current indentation level. + * + * @param string $str text + */ public function println($str) { if ( ! $this->_silent) { diff --git a/draft/Doctrine/Query/Production.php b/draft/Doctrine/Query/Production.php index c6382349f..7e86e0228 100644 --- a/draft/Doctrine/Query/Production.php +++ b/draft/Doctrine/Query/Production.php @@ -27,7 +27,7 @@ * @subpackage Query * @author Janne Vanhala * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.phpdoctrine.org + * @link http://www.phpdoctrine.org * @since 1.0 * @version $Revision$ */ @@ -66,7 +66,7 @@ abstract class Doctrine_Query_Production */ public function __call($method, $args) { - $this->_parser->getPrinter()->startProduction($name); + $this->_parser->getPrinter()->startProduction($method); $retval = $this->_parser->getProduction($method)->execute($args); $this->_parser->getPrinter()->endProduction(); diff --git a/draft/Doctrine/Query/Production/AbstractSchemaName.php b/draft/Doctrine/Query/Production/AbstractSchemaName.php deleted file mode 100644 index 9e9d78294..000000000 --- a/draft/Doctrine/Query/Production/AbstractSchemaName.php +++ /dev/null @@ -1,62 +0,0 @@ -. - */ - -/** - * This class represents the AbstractSchemaName production in DQL grammar. - * - * - * AbstractSchemaName = identifier - * - * - * @package Doctrine - * @subpackage Query - * @author Janne Vanhala - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.phpdoctrine.org - * @since 1.0 - * @version $Revision$ - */ -class Doctrine_Query_Production_AbstractSchemaName extends Doctrine_Query_Production -{ - /** - * Executes the AbstractSchemaName production. - * - * - * AbstractSchemaName = identifier - * - * - * @param array $params This production does not take any parameters. - * @return Doctrine_Table|null the table object corresponding the identifier - * name - */ - public function execute(array $params = array()) - { - $token = $this->_parser->lookahead; - - if ($token['type'] === Doctrine_Query_Token::T_IDENTIFIER) { - $this->_parser->match(Doctrine_Query_Token::T_IDENTIFIER); - } else { - $this->_parser->logError('Identifier expected'); - } - - return $token; - } -} diff --git a/draft/Doctrine/Query/Production/Atom.php b/draft/Doctrine/Query/Production/Atom.php index 6c36e6d2b..d0ab05d9c 100644 --- a/draft/Doctrine/Query/Production/Atom.php +++ b/draft/Doctrine/Query/Production/Atom.php @@ -1,6 +1,34 @@ . + */ + /** * Atom = string | numeric | input_parameter + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_Atom extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/BetweenExpression.php b/draft/Doctrine/Query/Production/BetweenExpression.php index c8598faf6..50c1c9bf6 100644 --- a/draft/Doctrine/Query/Production/BetweenExpression.php +++ b/draft/Doctrine/Query/Production/BetweenExpression.php @@ -1,6 +1,34 @@ . + */ + /** * BetweenExpression = ["NOT"] "BETWEEN" Expression "AND" Expression + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_BetweenExpression extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/ComparisonExpression.php b/draft/Doctrine/Query/Production/ComparisonExpression.php index 1a93cce97..4e8b56482 100644 --- a/draft/Doctrine/Query/Production/ComparisonExpression.php +++ b/draft/Doctrine/Query/Production/ComparisonExpression.php @@ -1,6 +1,34 @@ . + */ + /** * ComparisonExpression = ComparisonOperator ( QuantifiedExpression | Expression | "(" Subselect ")" ) + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_ComparisonExpression extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/ComparisonOperator.php b/draft/Doctrine/Query/Production/ComparisonOperator.php index 315a0e4a1..8b62f2fc0 100644 --- a/draft/Doctrine/Query/Production/ComparisonOperator.php +++ b/draft/Doctrine/Query/Production/ComparisonOperator.php @@ -1,6 +1,34 @@ . + */ + /** * ComparisonOperator = "=" | "<" | "<=" | "<>" | ">" | ">=" + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_ComparisonOperator extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/ConditionalExpression.php b/draft/Doctrine/Query/Production/ConditionalExpression.php index 407e0a069..ac1246164 100644 --- a/draft/Doctrine/Query/Production/ConditionalExpression.php +++ b/draft/Doctrine/Query/Production/ConditionalExpression.php @@ -1,6 +1,34 @@ . + */ + /** * ConditionalExpression = ConditionalTerm {"OR" ConditionalTerm} + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_ConditionalExpression extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/ConditionalFactor.php b/draft/Doctrine/Query/Production/ConditionalFactor.php index 577b0dba8..464867b08 100644 --- a/draft/Doctrine/Query/Production/ConditionalFactor.php +++ b/draft/Doctrine/Query/Production/ConditionalFactor.php @@ -1,6 +1,34 @@ . + */ + /** * ConditionalFactor = ["NOT"] ConditionalPrimary + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_ConditionalFactor extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/ConditionalPrimary.php b/draft/Doctrine/Query/Production/ConditionalPrimary.php index ed93b9e45..05f79b43c 100644 --- a/draft/Doctrine/Query/Production/ConditionalPrimary.php +++ b/draft/Doctrine/Query/Production/ConditionalPrimary.php @@ -1,6 +1,34 @@ . + */ + /** * ConditionalPrimary = SimpleConditionalExpression | "(" ConditionalExpression ")" + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_ConditionalPrimary extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/ConditionalTerm.php b/draft/Doctrine/Query/Production/ConditionalTerm.php index dc354a923..88312ddf7 100644 --- a/draft/Doctrine/Query/Production/ConditionalTerm.php +++ b/draft/Doctrine/Query/Production/ConditionalTerm.php @@ -1,6 +1,34 @@ . + */ + /** * ConditionalTerm = ConditionalFactor {"AND" ConditionalFactor} + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_ConditionalTerm extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/DeleteClause.php b/draft/Doctrine/Query/Production/DeleteClause.php index 698efc359..3542a6dc7 100644 --- a/draft/Doctrine/Query/Production/DeleteClause.php +++ b/draft/Doctrine/Query/Production/DeleteClause.php @@ -1,6 +1,34 @@ . + */ + /** * DeleteClause = "DELETE" "FROM" RangeVariableDeclaration + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_DeleteClause extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/DeleteStatement.php b/draft/Doctrine/Query/Production/DeleteStatement.php index 56d0223cd..58b9a65ae 100644 --- a/draft/Doctrine/Query/Production/DeleteStatement.php +++ b/draft/Doctrine/Query/Production/DeleteStatement.php @@ -1,6 +1,34 @@ . + */ + /** * DeleteStatement = DeleteClause [WhereClause] [OrderByClause] [LimitClause] + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_DeleteStatement extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/Expression.php b/draft/Doctrine/Query/Production/Expression.php index 84b99e2e0..ee309f4a7 100644 --- a/draft/Doctrine/Query/Production/Expression.php +++ b/draft/Doctrine/Query/Production/Expression.php @@ -1,6 +1,34 @@ . + */ + /** * Expression = Term {("+" | "-") Term} + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_Expression extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/Factor.php b/draft/Doctrine/Query/Production/Factor.php index d3fedea09..7beb75a40 100644 --- a/draft/Doctrine/Query/Production/Factor.php +++ b/draft/Doctrine/Query/Production/Factor.php @@ -1,6 +1,34 @@ . + */ + /** * Factor = [("+" | "-")] Primary + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_Factor extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/FromClause.php b/draft/Doctrine/Query/Production/FromClause.php index 8ceab3572..384a5123f 100644 --- a/draft/Doctrine/Query/Production/FromClause.php +++ b/draft/Doctrine/Query/Production/FromClause.php @@ -1,6 +1,34 @@ . + */ + /** * FromClause = "FROM" IdentificationVariableDeclaration {"," IdentificationVariableDeclaration} + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_FromClause extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/GroupByClause.php b/draft/Doctrine/Query/Production/GroupByClause.php index 741dfa197..64d72e429 100644 --- a/draft/Doctrine/Query/Production/GroupByClause.php +++ b/draft/Doctrine/Query/Production/GroupByClause.php @@ -1,6 +1,34 @@ . + */ + /** * GroupByClause = "GROUP" "BY" GroupByItem {"," GroupByItem} + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_GroupByClause extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/GroupByItem.php b/draft/Doctrine/Query/Production/GroupByItem.php index 1a04b47be..336d8f493 100644 --- a/draft/Doctrine/Query/Production/GroupByItem.php +++ b/draft/Doctrine/Query/Production/GroupByItem.php @@ -1,6 +1,34 @@ . + */ + /** * OrderByItem = PathExpression + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_GroupByItem extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/HavingClause.php b/draft/Doctrine/Query/Production/HavingClause.php index cf13dfbf1..b28df6837 100644 --- a/draft/Doctrine/Query/Production/HavingClause.php +++ b/draft/Doctrine/Query/Production/HavingClause.php @@ -1,6 +1,34 @@ . + */ + /** * HavingClause = "HAVING" ConditionalExpression + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_HavingClause extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/IdentificationVariable.php b/draft/Doctrine/Query/Production/IdentificationVariable.php index b92c9c85c..b92865d1e 100644 --- a/draft/Doctrine/Query/Production/IdentificationVariable.php +++ b/draft/Doctrine/Query/Production/IdentificationVariable.php @@ -1,6 +1,34 @@ . + */ + /** * IdentificationVariable = identifier + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_IdentificationVariable extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/IdentificationVariableDeclaration.php b/draft/Doctrine/Query/Production/IdentificationVariableDeclaration.php index 3e1b9ea8d..e5543f220 100644 --- a/draft/Doctrine/Query/Production/IdentificationVariableDeclaration.php +++ b/draft/Doctrine/Query/Production/IdentificationVariableDeclaration.php @@ -1,6 +1,34 @@ . + */ + /** * IdentificationVariableDeclaration = RangeVariableDeclaration {Join} + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_IdentificationVariableDeclaration extends Doctrine_Query_Production { @@ -11,7 +39,7 @@ class Doctrine_Query_Production_IdentificationVariableDeclaration extends Doctri while ($this->_isNextToken(Doctrine_Query_Token::T_LEFT) || $this->_isNextToken(Doctrine_Query_Token::T_INNER) || $this->_isNextToken(Doctrine_Query_Token::T_JOIN)) { - + $this->Join(); } } diff --git a/draft/Doctrine/Query/Production/Join.php b/draft/Doctrine/Query/Production/Join.php index 13aaabb35..c4e86523a 100644 --- a/draft/Doctrine/Query/Production/Join.php +++ b/draft/Doctrine/Query/Production/Join.php @@ -1,6 +1,34 @@ . + */ + /** * Join = ["LEFT" ["OUTER"] | "INNER"] "JOIN" PathExpression "AS" identifier + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_Join extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/OrderByClause.php b/draft/Doctrine/Query/Production/OrderByClause.php index 3a3cc0b62..63b72c5b1 100644 --- a/draft/Doctrine/Query/Production/OrderByClause.php +++ b/draft/Doctrine/Query/Production/OrderByClause.php @@ -1,6 +1,34 @@ . + */ + /** * OrderByClause = "ORDER" "BY" OrderByItem {"," OrderByItem} + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_OrderByClause extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/OrderByItem.php b/draft/Doctrine/Query/Production/OrderByItem.php index a41ea93a7..6eadffdd5 100644 --- a/draft/Doctrine/Query/Production/OrderByItem.php +++ b/draft/Doctrine/Query/Production/OrderByItem.php @@ -1,6 +1,34 @@ . + */ + /** * OrderByItem = PathExpression ["ASC" | "DESC"] + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_OrderByItem extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/PathExpression.php b/draft/Doctrine/Query/Production/PathExpression.php index 109269765..282ac0e71 100644 --- a/draft/Doctrine/Query/Production/PathExpression.php +++ b/draft/Doctrine/Query/Production/PathExpression.php @@ -1,6 +1,34 @@ . + */ + /** * PathExpression = identifier { "." identifier } + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_PathExpression extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/PathExpressionEndingWithAsterisk.php b/draft/Doctrine/Query/Production/PathExpressionEndingWithAsterisk.php index 70c4541f4..9744bb74d 100644 --- a/draft/Doctrine/Query/Production/PathExpressionEndingWithAsterisk.php +++ b/draft/Doctrine/Query/Production/PathExpressionEndingWithAsterisk.php @@ -1,6 +1,34 @@ . + */ + /** * PathExpressionEndingWithAsterisk = {identifier "."} "*" + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_PathExpressionEndingWithAsterisk extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/Primary.php b/draft/Doctrine/Query/Production/Primary.php index 87de3028b..66a985205 100644 --- a/draft/Doctrine/Query/Production/Primary.php +++ b/draft/Doctrine/Query/Production/Primary.php @@ -1,7 +1,35 @@ . + */ + /** * Primary = PathExpression | Atom | "(" Expression ")" | Function | * AggregateExpression + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_Primary extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/QuantifiedExpression.php b/draft/Doctrine/Query/Production/QuantifiedExpression.php index 9023c7689..2229fecc5 100644 --- a/draft/Doctrine/Query/Production/QuantifiedExpression.php +++ b/draft/Doctrine/Query/Production/QuantifiedExpression.php @@ -1,6 +1,34 @@ . + */ + /** * QuantifiedExpression = ("ALL" | "ANY" | "SOME") "(" Subselect ")" + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_QuantifiedExpression extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/QueryLanguage.php b/draft/Doctrine/Query/Production/QueryLanguage.php index 306b14825..f5565a5cf 100644 --- a/draft/Doctrine/Query/Production/QueryLanguage.php +++ b/draft/Doctrine/Query/Production/QueryLanguage.php @@ -1,6 +1,34 @@ . + */ + /** * QueryLanguage = SelectStatement | UpdateStatement | DeleteStatement + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_QueryLanguage extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/RangeVariableDeclaration.php b/draft/Doctrine/Query/Production/RangeVariableDeclaration.php index 74a7df0f8..a54df966e 100644 --- a/draft/Doctrine/Query/Production/RangeVariableDeclaration.php +++ b/draft/Doctrine/Query/Production/RangeVariableDeclaration.php @@ -1,20 +1,46 @@ . + */ + /** - * RangeVariableDeclaration = AbstractSchemaName ["AS"] IdentificationVariable + * RangeVariableDeclaration = PathExpression [["AS"] IdentificationVariable] + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_RangeVariableDeclaration extends Doctrine_Query_Production { public function execute(array $params = array()) { - $abstractSchemaName = $this->AbstractSchemaName(); + $this->PathExpression(); if ($this->_isNextToken(Doctrine_Query_Token::T_AS)) { $this->_parser->match(Doctrine_Query_Token::T_AS); + $this->IdentificationVariable(); + } elseif ($this->_isNextToken(Doctrine_Query_Token::T_IDENTIFIER)) { + $this->IdentificationVariable(); } - - $identifier = $this->IdentificationVariable(); - - return array('abstractSchemaName' => $abstractSchemaName, - 'identifier' => $identifier); } } diff --git a/draft/Doctrine/Query/Production/SelectClause.php b/draft/Doctrine/Query/Production/SelectClause.php index 5b14a897c..f6b0b535b 100644 --- a/draft/Doctrine/Query/Production/SelectClause.php +++ b/draft/Doctrine/Query/Production/SelectClause.php @@ -1,6 +1,34 @@ . + */ + /** * SelectClause = "SELECT" ["DISTINCT"] SelectExpression {"," SelectExpression} + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_SelectClause extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/SelectExpression.php b/draft/Doctrine/Query/Production/SelectExpression.php index a125b40bd..029c8b80c 100644 --- a/draft/Doctrine/Query/Production/SelectExpression.php +++ b/draft/Doctrine/Query/Production/SelectExpression.php @@ -1,7 +1,35 @@ . + */ + /** * SelectExpression = (PathExpressionEndingWithAsterisk | Expression | "(" Subselect ")") * [["AS"] IdentificationVariable] + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_SelectExpression extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/SelectStatement.php b/draft/Doctrine/Query/Production/SelectStatement.php index c89c3cf8a..3c9e2a7a9 100644 --- a/draft/Doctrine/Query/Production/SelectStatement.php +++ b/draft/Doctrine/Query/Production/SelectStatement.php @@ -1,7 +1,35 @@ . + */ + /** * SelectStatement = [SelectClause] FromClause [WhereClause] [GroupByClause] * [HavingClause] [OrderByClause] [LimitClause] + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_SelectStatement extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/SimpleConditionalExpression.php b/draft/Doctrine/Query/Production/SimpleConditionalExpression.php index 417c455c5..7b4c1ae4d 100644 --- a/draft/Doctrine/Query/Production/SimpleConditionalExpression.php +++ b/draft/Doctrine/Query/Production/SimpleConditionalExpression.php @@ -1,9 +1,37 @@ . + */ + /** * SimpleConditionalExpression = * Expression (ComparisonExpression | BetweenExpression | LikeExpression | * InExpression | NullComparisonExpression | QuantifiedExpression) | * ExistsExpression + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_SimpleConditionalExpression extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/Term.php b/draft/Doctrine/Query/Production/Term.php index a68bf65d6..707c8e14c 100644 --- a/draft/Doctrine/Query/Production/Term.php +++ b/draft/Doctrine/Query/Production/Term.php @@ -1,6 +1,34 @@ . + */ + /** * Term = Factor {("*" | "/") Factor} + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_Term extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/UpdateClause.php b/draft/Doctrine/Query/Production/UpdateClause.php index 200666038..d1e2b31da 100644 --- a/draft/Doctrine/Query/Production/UpdateClause.php +++ b/draft/Doctrine/Query/Production/UpdateClause.php @@ -1,6 +1,34 @@ . + */ + /** * UpdateClause = "UPDATE" RangeVariableDeclaration "SET" UpdateItem {"," UpdateItem} + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_UpdateClause extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/UpdateStatement.php b/draft/Doctrine/Query/Production/UpdateStatement.php index b25e4ecf0..27d53783c 100644 --- a/draft/Doctrine/Query/Production/UpdateStatement.php +++ b/draft/Doctrine/Query/Production/UpdateStatement.php @@ -1,6 +1,34 @@ . + */ + /** * UpdateStatement = UpdateClause [WhereClause] [OrderByClause] [LimitClause] + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_UpdateStatement extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Production/WhereClause.php b/draft/Doctrine/Query/Production/WhereClause.php index b95f42c15..4ad76e9cb 100644 --- a/draft/Doctrine/Query/Production/WhereClause.php +++ b/draft/Doctrine/Query/Production/WhereClause.php @@ -1,6 +1,34 @@ . + */ + /** * WhereClause = "WHERE" ConditionalExpression + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ */ class Doctrine_Query_Production_WhereClause extends Doctrine_Query_Production { diff --git a/draft/Doctrine/Query/Scanner.php b/draft/Doctrine/Query/Scanner.php index 42eca3544..33a330778 100644 --- a/draft/Doctrine/Query/Scanner.php +++ b/draft/Doctrine/Query/Scanner.php @@ -20,7 +20,7 @@ */ /** - * ... + * Scans a DQL query for tokens. * * @package Doctrine * @subpackage Query @@ -39,7 +39,7 @@ class Doctrine_Query_Scanner */ protected $_tokens = array(); - protected $_nextToken = 0; + protected $_position = 0; protected $_peek = 0; @@ -122,7 +122,7 @@ class Doctrine_Query_Scanner public function peek() { - return $this->_tokens[$this->_nextToken + $this->_peek++]; + return $this->_tokens[$this->_position + $this->_peek++]; } public function resetPeek() @@ -144,7 +144,12 @@ class Doctrine_Query_Scanner public function next() { $this->_peek = 0; - return $this->_tokens[$this->_nextToken++]; + + if (isset($this->_tokens[$this->_position])) { + return $this->_tokens[$this->_position++]; + } else { + return null; + } } diff --git a/draft/Doctrine/Query/Token.php b/draft/Doctrine/Query/Token.php index e4f6ccb7f..efddce1bf 100644 --- a/draft/Doctrine/Query/Token.php +++ b/draft/Doctrine/Query/Token.php @@ -1,4 +1,35 @@ . + */ + +/** + * Container for token type constants of Doctrine Query Language. + * + * @package Doctrine + * @subpackage Query + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link http://www.phpdoctrine.org + * @since 1.0 + * @version $Revision$ + */ final class Doctrine_Query_Token { const T_NONE = 1; diff --git a/draft/query-language.txt b/draft/query-language.txt index bf2ecfab3..75ca9105d 100644 --- a/draft/query-language.txt +++ b/draft/query-language.txt @@ -29,12 +29,12 @@ OrderByClause = "ORDER" "BY" OrderByItem {"," OrderByItem} LimitClause = "LIMIT" Expression ["OFFSET" Expression] UpdateClause = "UPDATE" RangeVariableDeclaration "SET" UpdateItem {"," UpdateItem} -OrderByItem = PathExpression ["ASC" | "DESC"] +OrderByItem = Expression ["ASC" | "DESC"] GroupByItem = PathExpression UpdateItem = PathExpression "=" (Expression | "NULL") IdentificationVariableDeclaration = RangeVariableDeclaration {Join} -RangeVariableDeclaration = AbstractSchemaName ["AS"] IdentificationVariable +RangeVariableDeclaration = PathExpression [["AS"] IdentificationVariable] Join = ["LEFT" | "INNER"] "JOIN" RangeVariableDeclaration [("ON" | "WITH") ConditionalExpression] [IndexBy] IndexBy = "INDEX" "BY" PathExpression diff --git a/draft/tests/DoctrineTest.php b/draft/tests/DoctrineTest.php deleted file mode 100644 index aa97df69d..000000000 --- a/draft/tests/DoctrineTest.php +++ /dev/null @@ -1,257 +0,0 @@ -. - */ - -/** - * Doctrine_UnitTestCase - * - * @package Doctrine - * @author Konsta Vesterinen - * @author Bjarte S. Karlsen - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @category Object Relational Mapping - * @link www.phpdoctrine.com - * @since 1.0 - * @version $Revision$ - */ - -require_once dirname(__FILE__) . '/DoctrineTest/UnitTestCase.php'; -require_once dirname(__FILE__) . '/DoctrineTest/GroupTest.php'; -require_once dirname(__FILE__) . '/DoctrineTest/Doctrine_UnitTestCase.php'; -require_once dirname(__FILE__) . '/DoctrineTest/Reporter.php'; - -class DoctrineTest -{ - - protected $testGroup; // the default test group - protected $groups; - - public function __construct() - { - $this->requireModels(); - $this->testGroup = new GroupTest('Doctrine Framework Unit Tests', 'main'); - } - - /** - * Add a test to be run. - * - * This is a thin wrapper around GroupTest that also store the testcase in - * this class so that it is easier to create custom groups - * - * @param UnitTestCase A test case - */ - public function addTestCase($testCase){ - $this->groups[$testCase->getName()] = $testCase; - $this->testGroup->addTestCase($testCase); - } - - /** - * Run the tests - * - * This method will run the tests with the correct Reporter. It will run - * grouped tests if asked to and filter results. It also has support for - * running coverage report. - * - */ - public function run(){ - $testGroup = $this->testGroup; - if (PHP_SAPI === 'cli') { - require_once(dirname(__FILE__) . '/DoctrineTest/Reporter/Cli.php'); - $reporter = new DoctrineTest_Reporter_Cli(); - $argv = $_SERVER['argv']; - array_shift($argv); - $options = $this->parseOptions($argv); - } else { - require_once(dirname(__FILE__) . '/DoctrineTest/Reporter/Html.php'); - $options = $_GET; - if(isset($options["filter"])){ - $options["filter"] = explode(",", $options["filter"]); - } - if(isset($options["group"])){ - $options["group"] = explode(",", $options["group"]); - } - $reporter = new DoctrineTest_Reporter_Html(); - } - - //replace global group with custom group if we have group option set - if (isset($options['group'])) { - $testGroup = new GroupTest('Doctrine Framework Custom test', 'custom'); - foreach($options['group'] as $group) { - if (isset($this->groups[$group])) { - $testGroup->addTestCase($this->groups[$group]); - } else if (class_exists($group)) { - $testGroup->addTestCase(new $group); - } else { - die($group . " is not a valid group or doctrine test class\n "); - } - } - } - - $filter = ''; - if (isset($options['filter'])) { - $filter = $options['filter']; - } - - //show help text - if (isset($options['help'])) { - echo "Doctrine test runner help\n"; - echo "===========================\n"; - echo " To run all tests simply run this script without arguments. \n"; - echo "\n Flags:\n"; - echo " -coverage will generate coverage report data that can be viewed with the cc.php script in this folder. NB! This takes time. You need xdebug to run this\n"; - echo " -group Use this option to run just a group of tests or tests with a given classname. Groups are currently defined as the variable name they are called in this script.\n"; - echo " -filter case insensitive strings that will be applied to the className of the tests. A test_classname must contain all of these strings to be run\n"; - echo "\nAvailable groups:\n tickets, transaction, driver, data_dict, sequence, export, import, expression, core, relation, data_types, utility, db, event_listener, query_tests, record, cache\n"; - die(); - } - - //generate coverage report - if (isset($options['coverage'])) { - - /* - * The below code will not work for me (meus). It would be nice if - * somebody could give it a try. Just replace this block of code - * with the one below - * - define('PHPCOVERAGE_HOME', dirname(dirname(__FILE__)) . '/vendor/spikephpcoverage'); - require_once PHPCOVERAGE_HOME . '/CoverageRecorder.php'; - require_once PHPCOVERAGE_HOME . '/reporter/HtmlCoverageReporter.php'; - - $covReporter = new HtmlCoverageReporter('Doctrine Code Coverage Report', '', 'coverage2'); - - $includePaths = array('../lib'); - $excludePaths = array(); - $cov = new CoverageRecorder($includePaths, $excludePaths, $covReporter); - - $cov->startInstrumentation(); - $testGroup->run($reporter, $filter); - $cov->stopInstrumentation(); - - $cov->generateReport(); - $covReporter->printTextSummary(); - */ - xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE); - $testGroup->run($reporter, $filter); - $result['coverage'] = xdebug_get_code_coverage(); - xdebug_stop_code_coverage(); - file_put_contents(dirname(__FILE__) . '/coverage/coverage.txt', serialize($result)); - require_once dirname(__FILE__) . '/DoctrineTest/Coverage.php'; - $coverageGeneration = new DoctrineTest_Coverage(); - $coverageGeneration->generateReport(); - return; - // */ - - } - $testGroup->run($reporter, $filter); - } - - - /** - * Require all the models needed in the tests - * - */ - public function requireModels() - { - $models = new DirectoryIterator(dirname(__FILE__) . '/../../models/'); - foreach($models as $key => $file) { - if ($file->isFile() && ! $file->isDot()) { - $e = explode('.', $file->getFileName()); - if (end($e) === 'php') { - require_once $file->getPathname(); - } - } - } - } - - /** - * Parse Options from cli into an associative array - * - * @param array $array An argv array from cli - * @return array An array with options - */ - public function parseOptions($array) { - $currentName=''; - $options=array(); - foreach($array as $name) { - if (strpos($name,'-')===0) { - $name=str_replace('-','',$name); - $currentName=$name; - if ( ! isset($options[$currentName])) { - $options[$currentName]=array(); - } - } else { - $values=$options[$currentName]; - array_push($values,$name); - $options[$currentName]=$values; - } - } - return $options; - } - - /** - * Autoload test cases - * - * Will create test case if it does not exist - * - * @param string $class The name of the class to autoload - * @return boolean True - */ - public static function autoload($class) - { - if (strpos($class, 'TestCase') === false) { - return false; - } - - $e = explode('_', $class); - $count = count($e); - - $prefix = array_shift($e); - - if ($prefix !== 'Doctrine') { - return false; - } - - $dir = array_shift($e); - - $file = $dir . '_' . substr(implode('_', $e), 0, -(strlen('_TestCase'))) . 'TestCase.php'; - - if ( $count > 3) { - $file = str_replace('_', DIRECTORY_SEPARATOR, $file); - } else { - $file = str_replace('_', '', $file); - } - - // create a test case file if it doesn't exist - - if ( ! file_exists($file)) { - $contents = file_get_contents('template.tpl'); - $contents = sprintf($contents, $class, $class); - - if ( ! file_exists($dir)) { - mkdir($dir, 0777); - } - - file_put_contents($file, $contents); - } - require_once($file); - - return true; - } -} diff --git a/draft/tests/Query/LanguageRecognitionTestCase.php b/draft/tests/Query/LanguageRecognitionTestCase.php new file mode 100644 index 000000000..97cbe23cf --- /dev/null +++ b/draft/tests/Query/LanguageRecognitionTestCase.php @@ -0,0 +1,52 @@ +parse(); + $this->pass(); + } catch (Exception $e) { + $this->fail($e->getMessage()); + } + } + + public function assertInvalidDql($dql) + { + $parser = new Doctrine_Query_Parser($dql); + + try { + $parser->parse(); + $this->fail(); + } catch (Exception $e) { + $this->pass(); + } + } + + public function testPlainFromClauseWithoutAlias() + { + $this->assertValidDql('FROM User'); + } + + public function testPlainFromClauseWithAlias() + { + $this->assertValidDql('FROM User u'); + } + + public function testSelectSingleComponentWithAsterisk() + { + $this->assertValidDql('SELECT u.* FROM User u'); + } + + public function testSelectSingleComponentWithMultipleColumns() + { + $this->assertValidDql('SELECT u.name, u.type FROM User u'); + } + + public function testSelectMultipleComponentsWithAsterisk() + { + $this->assertValidDql('SELECT u.*, p.* FROM User u, u.Phonenumber p'); + } +} diff --git a/draft/tests/Query/ScannerTestCase.php b/draft/tests/Query/ScannerTestCase.php index f945d790b..c09ee02ae 100644 --- a/draft/tests/Query/ScannerTestCase.php +++ b/draft/tests/Query/ScannerTestCase.php @@ -1,105 +1,176 @@ scan(); - $this->assertEquals(Doctrine_Query_Token::T_IDENTIFIER, $token->getType()); - $this->assertEquals('u', $token->getValue()); + $token = $scanner->next(); + $this->assertEqual(Doctrine_Query_Token::T_IDENTIFIER, $token['type']); + $this->assertEqual('u', $token['value']); } public function testScannerRecognizesIdentifierConsistingOfLetters() { $scanner = new Doctrine_Query_Scanner('someIdentifier'); - $token = $scanner->scan(); - $this->assertEquals(Doctrine_Query_Token::T_IDENTIFIER, $token->getType()); - $this->assertEquals('someIdentifier', $token->getValue()); + $token = $scanner->next(); + $this->assertEqual(Doctrine_Query_Token::T_IDENTIFIER, $token['type']); + $this->assertEqual('someIdentifier', $token['value']); } public function testScannerRecognizesIdentifierIncludingDigits() { $scanner = new Doctrine_Query_Scanner('s0m31d3nt1f13r'); - $token = $scanner->scan(); - $this->assertEquals(Doctrine_Query_Token::T_IDENTIFIER, $token->getType()); - $this->assertEquals('s0m31d3nt1f13r', $token->getValue()); + $token = $scanner->next(); + $this->assertEqual(Doctrine_Query_Token::T_IDENTIFIER, $token['type']); + $this->assertEqual('s0m31d3nt1f13r', $token['value']); } public function testScannerRecognizesIdentifierIncludingUnderscore() { $scanner = new Doctrine_Query_Scanner('some_identifier'); - $token = $scanner->scan(); - $this->assertEquals(Doctrine_Query_Token::T_IDENTIFIER, $token->getType()); - $this->assertEquals('some_identifier', $token->getValue()); + $token = $scanner->next(); + $this->assertEqual(Doctrine_Query_Token::T_IDENTIFIER, $token['type']); + $this->assertEqual('some_identifier', $token['value']); } public function testScannerRecognizesDecimalInteger() { $scanner = new Doctrine_Query_Scanner('1234'); - $token = $scanner->scan(); - $this->assertEquals(Doctrine_Query_Token::T_NUMERIC, $token->getType()); - $this->assertEquals(1234, $token->getValue()); - } - - public function testScannerRecognizesNegativeDecimalInteger() - { - $scanner = new Doctrine_Query_Scanner('-123'); - - $token = $scanner->scan(); - $this->assertEquals(Doctrine_Query_Token::T_NUMERIC, $token->getType()); - $this->assertEquals(-123, $token->getValue()); + $token = $scanner->next(); + $this->assertEqual(Doctrine_Query_Token::T_NUMERIC, $token['type']); + $this->assertEqual(1234, $token['value']); } public function testScannerRecognizesFloat() { $scanner = new Doctrine_Query_Scanner('1.234'); - $token = $scanner->scan(); - $this->assertEquals(Doctrine_Query_Token::T_NUMERIC, $token->getType()); - $this->assertEquals(1.234, $token->getValue()); + $token = $scanner->next(); + $this->assertEqual(Doctrine_Query_Token::T_NUMERIC, $token['type']); + $this->assertEqual(1.234, $token['value']); } public function testScannerRecognizesFloatWithExponent() { $scanner = new Doctrine_Query_Scanner('1.2e3'); - $token = $scanner->scan(); - $this->assertEquals(Doctrine_Query_Token::T_NUMERIC, $token->getType()); - $this->assertEquals(1.2e3, $token->getValue()); + $token = $scanner->next(); + $this->assertEqual(Doctrine_Query_Token::T_NUMERIC, $token['type']); + $this->assertEqual(1.2e3, $token['value']); } public function testScannerRecognizesFloatWithNegativeExponent() { $scanner = new Doctrine_Query_Scanner('7E-10'); - $token = $scanner->scan(); - $this->assertEquals(Doctrine_Query_Token::T_NUMERIC, $token->getType()); - $this->assertEquals(7E-10, $token->getValue()); + $token = $scanner->next(); + $this->assertEqual(Doctrine_Query_Token::T_NUMERIC, $token['type']); + $this->assertEqual(7E-10, $token['value']); } public function testScannerRecognizesStringContainingWhitespace() { $scanner = new Doctrine_Query_Scanner("'This is a string.'"); - $token = $scanner->scan(); - $this->assertEquals(Doctrine_Query_Token::T_STRING, $token->getType()); - $this->assertEquals("'This is a string.'", $token->getValue()); + $token = $scanner->next(); + $this->assertEqual(Doctrine_Query_Token::T_STRING, $token['type']); + $this->assertEqual("'This is a string.'", $token['value']); } public function testScannerRecognizesStringContainingSingleQuotes() { $scanner = new Doctrine_Query_Scanner("'abc''defg'''"); - $token = $scanner->scan(); - $this->assertEquals(Doctrine_Query_Token::T_STRING, $token->getType()); - $this->assertEquals("'abc''defg'''", $token->getValue()); + $token = $scanner->next(); + $this->assertEqual(Doctrine_Query_Token::T_STRING, $token['type']); + $this->assertEqual("'abc''defg'''", $token['value']); } + public function testScannerTokenizesASimpleQueryCorrectly() + { + $dql = "SELECT u.* FROM User u WHERE u.name = 'Jack O''Neil'"; + $scanner = new Doctrine_Query_Scanner($dql); + + $tokens = array( + array( + 'value' => 'SELECT', + 'type' => Doctrine_Query_Token::T_SELECT, + 'position' => 0 + ), + array( + 'value' => 'u', + 'type' => Doctrine_Query_Token::T_IDENTIFIER, + 'position' => 7 + ), + array( + 'value' => '.', + 'type' => Doctrine_Query_Token::T_NONE, + 'position' => 8 + ), + array( + 'value' => '*', + 'type' => Doctrine_Query_Token::T_NONE, + 'position' => 9 + ), + array( + 'value' => 'FROM', + 'type' => Doctrine_Query_Token::T_FROM, + 'position' => 11 + ), + array( + 'value' => 'User', + 'type' => Doctrine_Query_Token::T_IDENTIFIER, + 'position' => 16 + ), + array( + 'value' => 'u', + 'type' => Doctrine_Query_Token::T_IDENTIFIER, + 'position' => 21 + ), + array( + 'value' => 'WHERE', + 'type' => Doctrine_Query_Token::T_WHERE, + 'position' => 23 + ), + array( + 'value' => 'u', + 'type' => Doctrine_Query_Token::T_IDENTIFIER, + 'position' => 29 + ), + array( + 'value' => '.', + 'type' => Doctrine_Query_Token::T_NONE, + 'position' => 30 + ), + array( + 'value' => 'name', + 'type' => Doctrine_Query_Token::T_IDENTIFIER, + 'position' => 31 + ), + array( + 'value' => '=', + 'type' => Doctrine_Query_Token::T_NONE, + 'position' => 36 + ), + array( + 'value' => "'Jack O''Neil'", + 'type' => Doctrine_Query_Token::T_STRING, + 'position' => 38 + ) + ); + + foreach ($tokens as $expected) { + $actual = $scanner->next(); + $this->assertEqual($expected['value'], $actual['value']); + $this->assertEqual($expected['type'], $actual['type']); + $this->assertEqual($expected['position'], $actual['position']); + } + + $this->assertNull($scanner->next()); + } } diff --git a/draft/tests/QueryScannerTestCase.php b/draft/tests/QueryScannerTestCase.php deleted file mode 100644 index f945d790b..000000000 --- a/draft/tests/QueryScannerTestCase.php +++ /dev/null @@ -1,105 +0,0 @@ -scan(); - $this->assertEquals(Doctrine_Query_Token::T_IDENTIFIER, $token->getType()); - $this->assertEquals('u', $token->getValue()); - } - - public function testScannerRecognizesIdentifierConsistingOfLetters() - { - $scanner = new Doctrine_Query_Scanner('someIdentifier'); - - $token = $scanner->scan(); - $this->assertEquals(Doctrine_Query_Token::T_IDENTIFIER, $token->getType()); - $this->assertEquals('someIdentifier', $token->getValue()); - } - - public function testScannerRecognizesIdentifierIncludingDigits() - { - $scanner = new Doctrine_Query_Scanner('s0m31d3nt1f13r'); - - $token = $scanner->scan(); - $this->assertEquals(Doctrine_Query_Token::T_IDENTIFIER, $token->getType()); - $this->assertEquals('s0m31d3nt1f13r', $token->getValue()); - } - - public function testScannerRecognizesIdentifierIncludingUnderscore() - { - $scanner = new Doctrine_Query_Scanner('some_identifier'); - - $token = $scanner->scan(); - $this->assertEquals(Doctrine_Query_Token::T_IDENTIFIER, $token->getType()); - $this->assertEquals('some_identifier', $token->getValue()); - } - - public function testScannerRecognizesDecimalInteger() - { - $scanner = new Doctrine_Query_Scanner('1234'); - - $token = $scanner->scan(); - $this->assertEquals(Doctrine_Query_Token::T_NUMERIC, $token->getType()); - $this->assertEquals(1234, $token->getValue()); - } - - public function testScannerRecognizesNegativeDecimalInteger() - { - $scanner = new Doctrine_Query_Scanner('-123'); - - $token = $scanner->scan(); - $this->assertEquals(Doctrine_Query_Token::T_NUMERIC, $token->getType()); - $this->assertEquals(-123, $token->getValue()); - } - - public function testScannerRecognizesFloat() - { - $scanner = new Doctrine_Query_Scanner('1.234'); - - $token = $scanner->scan(); - $this->assertEquals(Doctrine_Query_Token::T_NUMERIC, $token->getType()); - $this->assertEquals(1.234, $token->getValue()); - } - - public function testScannerRecognizesFloatWithExponent() - { - $scanner = new Doctrine_Query_Scanner('1.2e3'); - - $token = $scanner->scan(); - $this->assertEquals(Doctrine_Query_Token::T_NUMERIC, $token->getType()); - $this->assertEquals(1.2e3, $token->getValue()); - } - - public function testScannerRecognizesFloatWithNegativeExponent() - { - $scanner = new Doctrine_Query_Scanner('7E-10'); - - $token = $scanner->scan(); - $this->assertEquals(Doctrine_Query_Token::T_NUMERIC, $token->getType()); - $this->assertEquals(7E-10, $token->getValue()); - } - - public function testScannerRecognizesStringContainingWhitespace() - { - $scanner = new Doctrine_Query_Scanner("'This is a string.'"); - - $token = $scanner->scan(); - $this->assertEquals(Doctrine_Query_Token::T_STRING, $token->getType()); - $this->assertEquals("'This is a string.'", $token->getValue()); - } - - public function testScannerRecognizesStringContainingSingleQuotes() - { - $scanner = new Doctrine_Query_Scanner("'abc''defg'''"); - - $token = $scanner->scan(); - $this->assertEquals(Doctrine_Query_Token::T_STRING, $token->getType()); - $this->assertEquals("'abc''defg'''", $token->getValue()); - } - -} diff --git a/draft/tests/run.php b/draft/tests/run.php index d13e951f3..4ffc95f49 100644 --- a/draft/tests/run.php +++ b/draft/tests/run.php @@ -2,35 +2,46 @@ error_reporting(E_ALL | E_STRICT); ini_set('max_execution_time', 900); ini_set('date.timezone', 'GMT+0'); + +set_include_path( + dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR . 'tests' . + PATH_SEPARATOR . get_include_path() +); -require_once(dirname(__FILE__) . '/DoctrineTest.php'); +require_once 'DoctrineTest.php'; require_once dirname(__FILE__) . '/../../lib/Doctrine.php'; -spl_autoload_register(array('Doctrine', 'autoload')); -spl_autoload_register(array('DoctrineTest','autoload')); -function autoload($className) -{ - $class = dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR - . str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php'; - print $class; - if (file_exists($class)) { - require_once($class); - - return true; - } - - return false; -} - + +function autoload($className) +{ + if (class_exists($className, false)) { + return false; + } + + $class = dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR + . str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php'; + + if (file_exists($class)) { + require_once($class); + + return true; + } + + return false; +} + spl_autoload_register('autoload'); +spl_autoload_register(array('Doctrine', 'autoload')); +spl_autoload_register(array('DoctrineTest','autoload')); $test = new DoctrineTest(); //TICKET test cases $queryTests = new GroupTest('Query tests', 'queries'); $queryTests->addTestCase(new Doctrine_Query_Scanner_TestCase()); +$queryTests->addTestCase(new Doctrine_Query_LanguageRecognition_TestCase()); $test->addTestCase($queryTests); $test->run(); -echo memory_get_peak_usage() / 1024 . "\n"; +echo memory_get_peak_usage() / 1024 . "\n";