/** * parseClause * * @param string $alias component alias * @param string $field the field name * @param mixed $value the value of the field * @return void */ public function parseClause($alias, $field, $value) { $parts = Doctrine_Tokenizer::quoteExplode($value, ' AND '); if (count($parts) > 1) { $ret = array(); foreach ($parts as $part) { $ret[] = $this->parseSingle($alias, $field, $part); } $r = implode(' AND ', $ret); } else { $parts = Doctrine_Tokenizer::quoteExplode($value, ' OR '); if (count($parts) > 1) { $ret = array(); foreach ($parts as $part) { $ret[] = $this->parseClause($alias, $field, $part); } $r = implode(' OR ', $ret); } else { $ret = $this->parseSingle($alias, $field, $parts[0]); return $ret; } } return '(' . $r . ')'; }
/** * getLimitSubquery * this is method is used by the record limit algorithm * * when fetching one-to-many, many-to-many associated data with LIMIT clause * an additional subquery is needed for limiting the number of returned records instead * of limiting the number of sql result set rows * * @return string the limit subquery */ public function getLimitSubquery() { $map = reset($this->_aliasMap); $table = $map['table']; $componentAlias = key($this->_aliasMap); // get short alias $alias = $this->getTableAlias($componentAlias); $primaryKey = $alias . '.' . $table->getIdentifier(); // initialize the base of the subquery $subquery = 'SELECT DISTINCT ' . $this->_conn->quoteIdentifier($primaryKey); $driverName = $this->_conn->getAttribute(Doctrine::ATTR_DRIVER_NAME); // pgsql needs the order by fields to be preserved in select clause if ($driverName == 'pgsql') { foreach ($this->parts['orderby'] as $part) { $part = trim($part); $e = Doctrine_Tokenizer::bracketExplode($part, ' '); $part = trim($e[0]); if (strpos($part, '.') === false) { continue; } // don't add functions if (strpos($part, '(') !== false) { continue; } // don't add primarykey column (its already in the select clause) if ($part !== $primaryKey) { $subquery .= ', ' . $part; } } } if ($driverName == 'mysql' || $driverName == 'pgsql') { foreach ($this->_expressionMap as $dqlAlias => $expr) { if (isset($expr[1])) { $subquery .= ', ' . $expr[0] . ' AS ' . $this->aggregateMap[$dqlAlias]; } } } $subquery .= ' FROM'; foreach ($this->parts['from'] as $part) { // preserve LEFT JOINs only if needed if (substr($part, 0, 9) === 'LEFT JOIN') { $e = explode(' ', $part); if (empty($this->parts['orderby']) && empty($this->parts['where'])) { continue; } } $subquery .= ' ' . $part; } // all conditions must be preserved in subquery $subquery .= !empty($this->parts['where']) ? ' WHERE ' . implode(' AND ', $this->parts['where']) : ''; $subquery .= !empty($this->parts['groupby']) ? ' GROUP BY ' . implode(', ', $this->parts['groupby']) : ''; $subquery .= !empty($this->parts['having']) ? ' HAVING ' . implode(' AND ', $this->parts['having']) : ''; $subquery .= !empty($this->parts['orderby']) ? ' ORDER BY ' . implode(', ', $this->parts['orderby']) : ''; // add driver specific limit clause $subquery = $this->_conn->modifyLimitQuery($subquery, $this->parts['limit'], $this->parts['offset']); $parts = Doctrine_Tokenizer::quoteExplode($subquery, ' ', "'", "'"); foreach ($parts as $k => $part) { if (strpos($part, ' ') !== false) { continue; } $part = trim($part, "\"'`"); if ($this->hasTableAlias($part)) { $parts[$k] = $this->_conn->quoteIdentifier($this->generateNewTableAlias($part)); continue; } if (strpos($part, '.') === false) { continue; } preg_match_all("/[a-zA-Z0-9_]+\\.[a-z0-9_]+/i", $part, $m); foreach ($m[0] as $match) { $e = explode('.', $match); $e[0] = $this->generateNewTableAlias($e[0]); $parts[$k] = str_replace($match, implode('.', $e), $parts[$k]); } } if ($driverName == 'mysql' || $driverName == 'pgsql') { foreach ($parts as $k => $part) { if (strpos($part, "'") !== false) { continue; } if (strpos($part, '__') == false) { continue; } preg_match_all("/[a-zA-Z0-9_]+\\_\\_[a-z0-9_]+/i", $part, $m); foreach ($m[0] as $match) { $e = explode('__', $match); $e[0] = $this->generateNewTableAlias($e[0]); $parts[$k] = str_replace($match, implode('__', $e), $parts[$k]); } } } $subquery = implode(' ', $parts); return $subquery; }