. */ Doctrine::autoload('Doctrine_Query_Condition'); /** * Doctrine_Query_Where * * @package Doctrine * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @category Object Relational Mapping * @link www.phpdoctrine.com * @since 1.0 * @version $Revision$ * @author Konsta Vesterinen */ class Doctrine_Query_Where extends Doctrine_Query_Condition { public function load($where) { $where = Doctrine_Tokenizer::bracketTrim(trim($where)); $conn = $this->query->getConnection(); $terms = Doctrine_Tokenizer::sqlExplode($where); 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($terms) < 3) { $terms = Doctrine_Tokenizer::sqlExplode($where, array('=', '<', '<>', '>', '!=')); } 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 (strpos($first, "'") === false && strpos($first, '(') === false) { // normal field reference found $a = explode('.', $first); $field = array_pop($a); $reference = implode('.', $a); if (empty($reference)) { $map = $this->query->getRootDeclaration(); $alias = $this->query->getTableAlias($this->query->getRootAlias()); $table = $map['table']; } else { $map = $this->query->load($reference, false); $alias = $this->query->getTableAlias($reference); $table = $map['table']; } if ($this->query->getType() === Doctrine_Query::SELECT) { $first = $conn->quoteIdentifier($alias) . '.' . $conn->quoteIdentifier($table->getColumnName($field)); } else { $first = $conn->quoteIdentifier($table->getColumnName($field)); } } else { $first = $this->query->parseClause($first); } $sql = $first . ' ' . $operator . ' ' . $this->parseValue($value, $table, $field); return $sql; } else { } } 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() . ')'; } elseif (substr($trimmed, 0, 4) == 'SQL:') { $value = '(' . substr($trimmed, 4) . ')'; } else { // simple in expression found $e = Doctrine_Tokenizer::sqlExplode($trimmed, ','); $value = array(); $index = false; foreach ($e as $part) { if (isset($table) && isset($field)) { $index = $table->enumIndex($field, trim($part, "'")); } if ($index !== false) { $value[] = $index; } else { $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 { $enumIndex = false; if (isset($table) && isset($field)) { // check if value is enumerated value $enumIndex = $table->enumIndex($field, trim($value, "'")); } if ($enumIndex !== false) { $value = $enumIndex; } else { $value = $this->parseLiteralValue($value); } } return $value; } /** * parses an EXISTS expression * * @param string $where query where part to be parsed * @param boolean $negation whether or not to use the NOT keyword * @return string */ public function parseExists($where, $negation) { $operator = ($negation) ? 'EXISTS' : 'NOT EXISTS'; $pos = strpos($where, '('); if ($pos == false) { 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() . ')'; } }