/**
* Validates the order of the clauses in parsed statement
* Ideally this should be called after successfully
* completing the parsing of each statement
*
* @param Parser $parser The instance that requests parsing.
* @param TokensList $list The list of tokens to be parsed.
*
* @return boolean
*/
public function validateClauseOrder($parser, $list)
{
$clauses = array_flip(array_keys($this->getClauses()));
if (empty($clauses) || count($clauses) == 0) {
return true;
}
$minIdx = -1;
/**
* For tracking JOIN clauses in a query
* 0 - JOIN not found till now
* 1 - JOIN has been found
* 2 - A Non-JOIN clause has been found
* after a previously found JOIN clause
*
* @var int $joinStart
*/
$joinStart = 0;
$error = 0;
foreach ($clauses as $clauseType => $index) {
$clauseStartIdx = Utils\Query::getClauseStartOffset($this, $list, $clauseType);
// Handle ordering of Multiple Joins in a query
if ($clauseStartIdx != -1) {
if ($joinStart == 0 && stripos($clauseType, 'JOIN')) {
$joinStart = 1;
} elseif ($joinStart == 1 && !stripos($clauseType, 'JOIN')) {
$joinStart = 2;
} elseif ($joinStart == 2 && stripos($clauseType, 'JOIN')) {
$error = 1;
}
}
if ($clauseStartIdx != -1 && $clauseStartIdx < $minIdx) {
if ($joinStart == 0 || $joinStart == 2 && ($error = 1)) {
$token = $list->tokens[$clauseStartIdx];
$parser->error(__('Unexpected ordering of clauses.'), $token);
return false;
} else {
$minIdx = $clauseStartIdx;
}
} elseif ($clauseStartIdx != -1) {
$minIdx = $clauseStartIdx;
}
}
return true;
}