diff --git a/lib/Doctrine/Query/From.php b/lib/Doctrine/Query/From.php index 120173f0c..e5247c3c8 100644 --- a/lib/Doctrine/Query/From.php +++ b/lib/Doctrine/Query/From.php @@ -73,13 +73,14 @@ class Doctrine_Query_From extends Doctrine_Query_Part foreach (Doctrine_Tokenizer::bracketExplode($part, ',') as $reference) { $reference = trim($reference); - $e = explode('.', $reference); + $e = explode(' ', $reference); + $e2 = explode('.', $e[0]); if ($operator) { - $reference = array_shift($e) . $operator . implode('.', $e); + $e[0] = array_shift($e2) . $operator . implode('.', $e2); } - $table = $this->query->load($reference); + $table = $this->query->load(implode(' ', $e)); } $operator = ($last == 'INNER') ? ':' : '.'; diff --git a/lib/Doctrine/Query/JoinCondition.php b/lib/Doctrine/Query/JoinCondition.php index 472856791..1add247c6 100644 --- a/lib/Doctrine/Query/JoinCondition.php +++ b/lib/Doctrine/Query/JoinCondition.php @@ -58,7 +58,7 @@ class Doctrine_Query_JoinCondition extends Doctrine_Query_Condition if (substr($trimmed, 0, 4) == 'FROM' || substr($trimmed, 0, 6) == 'SELECT') { // subquery found - $q = new Doctrine_Query(); + $q = $this->query->createSubquery(); $value = '(' . $q->parseQuery($trimmed)->getQuery() . ')'; } elseif (substr($trimmed, 0, 4) == 'SQL:') { $value = '(' . substr($trimmed, 4) . ')'; diff --git a/lib/Doctrine/Query/Where.php b/lib/Doctrine/Query/Where.php index 85fc52541..586ac90ff 100644 --- a/lib/Doctrine/Query/Where.php +++ b/lib/Doctrine/Query/Where.php @@ -32,166 +32,110 @@ Doctrine::autoload('Doctrine_Query_Condition'); */ class Doctrine_Query_Where extends Doctrine_Query_Condition { - /** - * load - * returns the parsed query part - * - * @param string $where - * @return string - */ - public function load($where) + public function load($where) { - $where = trim($where); + $where = Doctrine_Tokenizer::bracketTrim(trim($where)); $conn = $this->query->getConnection(); + $terms = Doctrine_Tokenizer::sqlExplode($where); - $e = Doctrine_Tokenizer::sqlExplode($where); - - if (count($e) > 1) { - $tmp = $e[0] . ' ' . $e[1]; - - if (substr($tmp, 0, 6) == 'EXISTS') { + if (count($terms) > 1) { + if (substr($where, 0, 6) == 'EXISTS') { return $this->parseExists($where, true); } elseif (substr($where, 0, 10) == 'NOT EXISTS') { return $this->parseExists($where, false); } } - if (count($e) < 3) { - $e = Doctrine_Tokenizer::sqlExplode($where, array('=', '<', '>', '!=')); + if (count($terms) < 3) { + $terms = Doctrine_Tokenizer::sqlExplode($where, array('=', '<', '<>', '>', '!=')); } - $r = array_shift($e); - $a = explode('.', $r); + if (count($terms) > 1) { + $first = array_shift($terms); + $value = array_pop($terms); + $operator = trim(substr($where, strlen($first), -strlen($value))); + $table = null; + $field = null; - if (count($a) > 1) { - $field = array_pop($a); - $count = count($e); - $slice = array_slice($e, -1, 1); - $value = implode('', $slice); - $operator = trim(substr($where, strlen($r), -strlen($value))); - - $reference = implode('.', $a); - $count = count($a); - - $pos = strpos($field, '('); - - if ($pos !== false) { - $func = substr($field, 0, $pos); - $value = trim(substr($field, ($pos + 1), -1)); - - $values = Doctrine_Query::sqlExplode($value, ','); - - $field = array_pop($a); - $reference = implode('.', $a); - $table = $this->query->load($reference, false); - $field = $table->getColumnName($field); - - array_pop($a); - - $reference2 = implode('.', $a); - - $alias = $this->query->getTableAlias($reference2); - - $stack = $this->query->getRelationStack(); - $relation = end($stack); - - $stack = $this->query->getTableStack(); - - switch ($func) { - case 'contains': - case 'regexp': - case 'like': - $operator = $this->getOperator($func); - - if (empty($relation)) { - throw new Doctrine_Query_Exception('DQL functions contains/regexp/like can only be used for fields of related components'); - } - $where = array(); - foreach ($values as $value) { - $where[] = $conn->quoteIdentifier($alias . '.' . $relation->getLocal()) - . ' IN (SELECT ' . $conn->quoteIdentifier($relation->getForeign()) - . ' FROM ' . $conn->quoteIdentifier($relation->getTable()->getTableName()) - . ' WHERE ' . $field . $operator . $value . ')'; - } - $where = implode(' AND ', $where); - break; - default: - throw new Doctrine_Query_Exception('Unknown DQL function: '.$func); - } - } else { + if (strpos($first, "'") === false && strpos($first, '(') === false) { + // normal field reference found + $a = explode('.', $first); + + $field = array_pop($a); + $reference = implode('.', $a); $map = $this->query->load($reference, false); - + $alias = $this->query->getTableAlias($reference); $table = $map['table']; + + $first = $conn->quoteIdentifier($alias) + . '.' + . $conn->quoteIdentifier($table->getColumnName($field)); + } else { + $first = $this->query->parseClause($first); + } + $sql = $first . ' ' . $operator . ' ' . $this->parseValue($value, $table, $field); + + return $sql; + } else { - $field = $table->getColumnName($field); - // check if value is enumerated value - $enumIndex = $table->enumIndex($field, trim($value, "'")); + } + } - if (substr($value, 0, 1) == '(') { - // trim brackets - $trimmed = Doctrine_Tokenizer::bracketTrim($value); + public function parseValue($value, Doctrine_Table $table = null, $field = null) + { + if (substr($value, 0, 1) == '(') { + // trim brackets + $trimmed = Doctrine_Tokenizer::bracketTrim($value); - if (substr($trimmed, 0, 4) == 'FROM' || substr($trimmed, 0, 6) == 'SELECT') { - // subquery found - $q = new Doctrine_Query(); - $value = '(' . $q->isSubquery(true)->parseQuery($trimmed)->getQuery() . ')'; + if (substr($trimmed, 0, 4) == 'FROM' || + substr($trimmed, 0, 6) == 'SELECT') { - } elseif (substr($trimmed, 0, 4) == 'SQL:') { - $value = '(' . substr($trimmed, 4) . ')'; - } else { - // simple in expression found - $e = Doctrine_Tokenizer::sqlExplode($trimmed, ','); + // subquery found + $q = new Doctrine_Query(); + $value = '(' . $q->isSubquery(true)->parseQuery($trimmed)->getQuery() . ')'; - $value = array(); - foreach ($e as $part) { - $index = $table->enumIndex($field, trim($part, "'")); + } elseif (substr($trimmed, 0, 4) == 'SQL:') { + $value = '(' . substr($trimmed, 4) . ')'; + } else { + // simple in expression found + $e = Doctrine_Tokenizer::sqlExplode($trimmed, ','); - if ($index !== false) { - $value[] = $index; - } else { - $value[] = $this->parseLiteralValue($part); - } - } - $value = '(' . implode(', ', $value) . ')'; + $value = array(); + + $index = false; + + foreach ($e as $part) { + if (isset($table) && isset($field)) { + $index = $table->enumIndex($field, trim($part, "'")); } - } elseif(substr($value, 0, 1) == ':' || $value === '?') { - // placeholder found - if ($table->getTypeOf($field) == 'enum') { - $this->query->addEnumParam($value, $table, $field); + + if ($index !== false) { + $value[] = $index; } else { - $this->query->addEnumParam($value, null, null); - } - } else { - if ($enumIndex !== false) { - $value = $enumIndex; - } else { - $value = $this->parseLiteralValue($value); + $value[] = $this->parseLiteralValue($part); } } + $value = '(' . implode(', ', $value) . ')'; + } + } elseif(substr($value, 0, 1) == ':' || $value === '?') { + // placeholder found + if (isset($table) && isset($field) && $table->getTypeOf($field) == 'enum') { + $this->query->addEnumParam($value, $table, $field); + } else { + $this->query->addEnumParam($value, null, null); + } + } else { + // check if value is enumerated value + $enumIndex = $table->enumIndex($field, trim($value, "'")); - switch ($operator) { - case '<': - case '>': - case '=': - case '!=': - if ($enumIndex !== false) { - $value = $enumIndex; - } - default: - - if ($this->query->getType() === Doctrine_Query::SELECT) { - $fieldname = $alias ? $conn->quoteIdentifier($alias . '.' . $field) : $field; - } else { - $fieldname = $field; - } - - $where = $fieldname . ' ' - . $operator . ' ' . $value; - } + if ($enumIndex !== false) { + $value = $enumIndex; + } else { + $value = $this->parseLiteralValue($value); } } - return $where; + return $value; } /** * parses an EXISTS expression @@ -207,32 +151,11 @@ class Doctrine_Query_Where extends Doctrine_Query_Condition $pos = strpos($where, '('); if ($pos == false) { - throw new Doctrine_Query_Exception("Unknown expression, expected '('"); + throw new Doctrine_Query_Exception('Unknown expression, expected a subquery with () -marks'); } $sub = Doctrine_Tokenizer::bracketTrim(substr($where, $pos)); return $operator . ' (' . $this->query->createSubquery()->parseQuery($sub, false)->getQuery() . ')'; } - /** - * getOperator - * - * @param string $func - * @return string - */ - public function getOperator($func) - { - switch ($func) { - case 'contains': - $operator = ' = '; - break; - case 'regexp': - $operator = $this->query->getConnection()->getRegexpOperator(); - break; - case 'like': - $operator = ' LIKE '; - break; - } - return $operator; - } }