protected function lookForBaseExpression($sql, &$charPos, &$parsed, $key, &$backtracking)
{
if (!is_numeric($key)) {
if ($key === 'UNION' || $key === 'UNION ALL' || $key === 'expr_type' && isset($this->flippedBacktrackingTypes[$parsed]) || $key === 'select-option' && $parsed !== false || $key === 'alias' && $parsed !== false) {
// we hold the current position and come back after the next base_expr
// we do this, because the next base_expr contains the complete expression/subquery/record
// and we have to look into it too
$backtracking[] = $charPos;
} elseif (($key === 'ref_clause' || $key === 'columns') && $parsed !== false) {
// we hold the current position and come back after n base_expr(s)
// there is an array of sub-elements before (!) the base_expr clause of the current element
// so we go through the sub-elements and must come at the end
$backtracking[] = $charPos;
for ($i = 1; $i < count($parsed); $i++) {
$backtracking[] = false;
// backtracking only after n base_expr!
}
} elseif ($key === 'sub_tree' && $parsed !== false || $key === 'options' && $parsed !== false) {
// we prevent wrong backtracking on subtrees (too much array_pop())
// there is an array of sub-elements after(!) the base_expr clause of the current element
// so we go through the sub-elements and must not come back at the end
for ($i = 1; $i < count($parsed); $i++) {
$backtracking[] = false;
}
} elseif ($key === 'TABLE' || $key === 'create-def' && $parsed !== false) {
// do nothing
} else {
// move the current pos after the keyword
// SELECT, WHERE, INSERT etc.
if (PHPSQLParserConstants::getInstance()->isReserved($key)) {
$charPos = stripos($sql, $key, $charPos);
$charPos += strlen($key);
}
}
}
if (!is_array($parsed)) {
return;
}
foreach ($parsed as $key => $value) {
if ($key === 'base_expr') {
//$this->printPos("0", $sql, $charPos, $key, $value, $backtracking);
$subject = substr($sql, $charPos);
$pos = $this->findPositionWithinString($subject, $value, isset($parsed['expr_type']) ? $parsed['expr_type'] : 'alias');
if ($pos === false) {
throw new UnableToCalculatePositionException($value, $subject);
}
$parsed['position'] = $charPos + $pos;
$charPos += $pos + strlen($value);
//$this->printPos("1", $sql, $charPos, $key, $value, $backtracking);
$oldPos = array_pop($backtracking);
if (isset($oldPos) && $oldPos !== false) {
$charPos = $oldPos;
}
//$this->printPos("2", $sql, $charPos, $key, $value, $backtracking);
} else {
$this->lookForBaseExpression($sql, $charPos, $parsed[$key], $key, $backtracking);
}
}
}