fixed identifier quoting
This commit is contained in:
parent
7cfbd7481b
commit
56768b613f
@ -388,7 +388,7 @@ final class Doctrine
|
|||||||
*/
|
*/
|
||||||
public static function getPath()
|
public static function getPath()
|
||||||
{
|
{
|
||||||
if (! self::$path) {
|
if ( ! self::$path) {
|
||||||
self::$path = dirname(__FILE__);
|
self::$path = dirname(__FILE__);
|
||||||
}
|
}
|
||||||
return self::$path;
|
return self::$path;
|
||||||
|
@ -62,6 +62,16 @@ abstract class Doctrine_Configurable extends Doctrine_Object
|
|||||||
*/
|
*/
|
||||||
public function setAttribute($attribute,$value)
|
public function setAttribute($attribute,$value)
|
||||||
{
|
{
|
||||||
|
if (is_string($attribute)) {
|
||||||
|
$upper = strtoupper($attribute);
|
||||||
|
|
||||||
|
$const = 'Doctrine::ATTR_' . $attribute;
|
||||||
|
if (defined($const)) {
|
||||||
|
$this->_state = constant($const);
|
||||||
|
} else {
|
||||||
|
throw new Doctrine_Exception('Unknown attribute ' . $attribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
switch ($attribute) {
|
switch ($attribute) {
|
||||||
case Doctrine::ATTR_FETCHMODE:
|
case Doctrine::ATTR_FETCHMODE:
|
||||||
if ($value < 0) {
|
if ($value < 0) {
|
||||||
|
@ -881,11 +881,13 @@ class Doctrine_Hydrate extends Doctrine_Object implements Serializable
|
|||||||
foreach ($maps as $map) {
|
foreach ($maps as $map) {
|
||||||
$b = array();
|
$b = array();
|
||||||
foreach ($map as $field => $value) {
|
foreach ($map as $field => $value) {
|
||||||
|
$identifier = $this->_conn->quoteIdentifier($tableAlias . $field);
|
||||||
|
|
||||||
if ($index > 0) {
|
if ($index > 0) {
|
||||||
$b[] = '(' . $tableAlias . $field . ' = ' . $value
|
$b[] = '(' . $identifier . ' = ' . $value
|
||||||
. ' OR ' . $tableAlias . $field . ' IS NULL)';
|
. ' OR ' . $identifier . ' IS NULL)';
|
||||||
} else {
|
} else {
|
||||||
$b[] = $tableAlias . $field . ' = ' . $value;
|
$b[] = $identifier . ' = ' . $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,7 +368,9 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
|
|||||||
foreach ($fields as $name) {
|
foreach ($fields as $name) {
|
||||||
$name = $table->getColumnName($name);
|
$name = $table->getColumnName($name);
|
||||||
|
|
||||||
$this->parts['select'][] = $tableAlias . '.' .$name . ' AS ' . $tableAlias . '__' . $name;
|
$this->parts['select'][] = $this->_conn->quoteIdentifier($tableAlias . '.' . $name)
|
||||||
|
. ' AS '
|
||||||
|
. $this->_conn->quoteIdentifier($tableAlias . '__' . $name);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->neededTables[] = $tableAlias;
|
$this->neededTables[] = $tableAlias;
|
||||||
@ -520,7 +522,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
|
|||||||
|
|
||||||
$sqlAlias = $tableAlias . '__' . count($this->aggregateMap);
|
$sqlAlias = $tableAlias . '__' . count($this->aggregateMap);
|
||||||
|
|
||||||
$this->parts['select'][] = '(' . $sql . ') AS ' . $sqlAlias;
|
$this->parts['select'][] = '(' . $sql . ') AS ' . $this->_conn->quoteIdentifier($sqlAlias);
|
||||||
|
|
||||||
$this->aggregateMap[$alias] = $sqlAlias;
|
$this->aggregateMap[$alias] = $sqlAlias;
|
||||||
$this->_aliasMap[$componentAlias]['agg'][] = $alias;
|
$this->_aliasMap[$componentAlias]['agg'][] = $alias;
|
||||||
@ -568,7 +570,9 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
|
|||||||
$tableAliases[$tableAlias] = true;
|
$tableAliases[$tableAlias] = true;
|
||||||
|
|
||||||
// build sql expression
|
// build sql expression
|
||||||
$expression = str_replace($component, $tableAlias . '.' . $field, $expression);
|
|
||||||
|
$identifier = $this->_conn->quoteIdentifier($tableAlias . '.' . $field);
|
||||||
|
$expression = str_replace($component, $identifier, $expression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,7 +582,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
|
|||||||
}
|
}
|
||||||
|
|
||||||
$index = count($this->aggregateMap);
|
$index = count($this->aggregateMap);
|
||||||
$sqlAlias = $tableAlias . '__' . $index;
|
$sqlAlias = $this->_conn->quoteIdentifier($tableAlias . '__' . $index);
|
||||||
|
|
||||||
$this->parts['select'][] = $expression . ' AS ' . $sqlAlias;
|
$this->parts['select'][] = $expression . ' AS ' . $sqlAlias;
|
||||||
|
|
||||||
@ -804,7 +808,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
|
|||||||
|
|
||||||
// only append the subquery if it actually contains something
|
// only append the subquery if it actually contains something
|
||||||
if ($subquery !== '') {
|
if ($subquery !== '') {
|
||||||
array_unshift($this->parts['where'], $field. ' IN (' . $subquery . ')');
|
array_unshift($this->parts['where'], $this->_conn->quoteIdentifier($field) . ' IN (' . $subquery . ')');
|
||||||
}
|
}
|
||||||
|
|
||||||
$modifyLimit = false;
|
$modifyLimit = false;
|
||||||
@ -853,7 +857,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
|
|||||||
$primaryKey = $alias . '.' . $table->getIdentifier();
|
$primaryKey = $alias . '.' . $table->getIdentifier();
|
||||||
|
|
||||||
// initialize the base of the subquery
|
// initialize the base of the subquery
|
||||||
$subquery = 'SELECT DISTINCT ' . $primaryKey;
|
$subquery = 'SELECT DISTINCT ' . $this->_conn->quoteIdentifier($primaryKey);
|
||||||
|
|
||||||
$driverName = $this->_conn->getAttribute(Doctrine::ATTR_DRIVER_NAME);
|
$driverName = $this->_conn->getAttribute(Doctrine::ATTR_DRIVER_NAME);
|
||||||
|
|
||||||
@ -917,14 +921,16 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
|
|||||||
$subquery = $this->_conn->modifyLimitQuery($subquery, $this->parts['limit'], $this->parts['offset']);
|
$subquery = $this->_conn->modifyLimitQuery($subquery, $this->parts['limit'], $this->parts['offset']);
|
||||||
|
|
||||||
$parts = Doctrine_Tokenizer::quoteExplode($subquery, ' ', "'", "'");
|
$parts = Doctrine_Tokenizer::quoteExplode($subquery, ' ', "'", "'");
|
||||||
//print_r($parts);
|
|
||||||
foreach ($parts as $k => $part) {
|
foreach ($parts as $k => $part) {
|
||||||
if (strpos($part, "'") !== false) {
|
if (strpos($part, ' ') !== false) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$part = trim($part, "\"'`");
|
||||||
|
|
||||||
if ($this->hasTableAlias($part)) {
|
if ($this->hasTableAlias($part)) {
|
||||||
$parts[$k] = $this->generateNewTableAlias($part);
|
$parts[$k] = $this->_conn->quoteIdentifier($this->generateNewTableAlias($part));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1153,8 +1159,13 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
|
|||||||
|
|
||||||
$localAlias = $this->getTableAlias($parent, $table->getTableName());
|
$localAlias = $this->getTableAlias($parent, $table->getTableName());
|
||||||
$foreignAlias = $this->getTableAlias($componentAlias, $relation->getTable()->getTableName());
|
$foreignAlias = $this->getTableAlias($componentAlias, $relation->getTable()->getTableName());
|
||||||
$localSql = $this->_conn->quoteIdentifier($table->getTableName()) . ' ' . $localAlias;
|
$localSql = $this->_conn->quoteIdentifier($table->getTableName())
|
||||||
$foreignSql = $this->_conn->quoteIdentifier($relation->getTable()->getTableName()) . ' ' . $foreignAlias;
|
. ' '
|
||||||
|
. $this->_conn->quoteIdentifier($localAlias);
|
||||||
|
|
||||||
|
$foreignSql = $this->_conn->quoteIdentifier($relation->getTable()->getTableName())
|
||||||
|
. ' '
|
||||||
|
. $this->_conn->quoteIdentifier($foreignAlias);
|
||||||
|
|
||||||
$map = $relation->getTable()->inheritanceMap;
|
$map = $relation->getTable()->inheritanceMap;
|
||||||
|
|
||||||
@ -1192,22 +1203,29 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
|
|||||||
if ($relation->isEqual()) {
|
if ($relation->isEqual()) {
|
||||||
$queryPart .= '(';
|
$queryPart .= '(';
|
||||||
}
|
}
|
||||||
$queryPart .= $foreignAlias . '.'
|
$queryPart .= $this->_conn->quoteIdentifier($foreignAlias . '.' . $relation->getTable()->getIdentifier())
|
||||||
. $relation->getTable()->getIdentifier() . ' = '
|
. ' = '
|
||||||
. $assocAlias . '.' . $relation->getForeign();
|
. $this->_conn->quoteIdentifier($assocAlias . '.' . $relation->getForeign());
|
||||||
|
|
||||||
if ($relation->isEqual()) {
|
if ($relation->isEqual()) {
|
||||||
$queryPart .= ' OR ' . $foreignAlias . '.' . $table->getIdentifier()
|
$queryPart .= ' OR '
|
||||||
. ' = ' . $assocAlias . '.' . $relation->getLocal()
|
. $this->_conn->quoteIdentifier($foreignAlias . '.' . $table->getIdentifier())
|
||||||
. ') AND ' . $foreignAlias . '.' . $table->getIdentifier()
|
. ' = '
|
||||||
. ' != ' . $localAlias . '.' . $table->getIdentifier();
|
. $this->_conn->quoteIdentifier($assocAlias . '.' . $relation->getLocal())
|
||||||
|
. ') AND '
|
||||||
|
. $this->_conn->quoteIdentifier($foreignAlias . '.' . $table->getIdentifier())
|
||||||
|
. ' != '
|
||||||
|
. $this->_conn->quoteIdentifier($localAlias . '.' . $table->getIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
$queryPart = $join . $foreignSql
|
$queryPart = $join . $foreignSql
|
||||||
. ' ON ' . $localAlias . '.'
|
. ' ON '
|
||||||
. $relation->getLocal() . ' = ' . $foreignAlias . '.' . $relation->getForeign();
|
. $this->_conn->quoteIdentifier($localAlias . '.' . $relation->getLocal())
|
||||||
|
. ' = '
|
||||||
|
. $this->_conn->quoteIdentifier($foreignAlias . '.' . $relation->getForeign());
|
||||||
|
|
||||||
}
|
}
|
||||||
$this->parts['from'][$componentAlias] = $queryPart;
|
$this->parts['from'][$componentAlias] = $queryPart;
|
||||||
if ( ! empty($joinCondition)) {
|
if ( ! empty($joinCondition)) {
|
||||||
@ -1262,7 +1280,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
|
|||||||
$queryPart = $this->_conn->quoteIdentifier($tableName);
|
$queryPart = $this->_conn->quoteIdentifier($tableName);
|
||||||
|
|
||||||
if ($this->type === self::SELECT) {
|
if ($this->type === self::SELECT) {
|
||||||
$queryPart .= ' ' . $tableAlias;
|
$queryPart .= ' ' . $this->_conn->quoteIdentifier($tableAlias);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->parts['from'][] = $queryPart;
|
$this->parts['from'][] = $queryPart;
|
||||||
|
@ -42,6 +42,7 @@ class Doctrine_Query_Where extends Doctrine_Query_Condition
|
|||||||
public function load($where)
|
public function load($where)
|
||||||
{
|
{
|
||||||
$where = trim($where);
|
$where = trim($where);
|
||||||
|
$conn = $this->query->getConnection();
|
||||||
|
|
||||||
$e = Doctrine_Tokenizer::sqlExplode($where);
|
$e = Doctrine_Tokenizer::sqlExplode($where);
|
||||||
|
|
||||||
@ -107,9 +108,9 @@ class Doctrine_Query_Where extends Doctrine_Query_Condition
|
|||||||
}
|
}
|
||||||
$where = array();
|
$where = array();
|
||||||
foreach ($values as $value) {
|
foreach ($values as $value) {
|
||||||
$where[] = $alias . '.' . $relation->getLocal()
|
$where[] = $conn->quoteIdentifier($alias . '.' . $relation->getLocal())
|
||||||
. ' IN (SELECT '.$relation->getForeign()
|
. ' IN (SELECT ' . $conn->quoteIdentifier($relation->getForeign())
|
||||||
. ' FROM ' . $relation->getTable()->getTableName()
|
. ' FROM ' . $conn->quoteIdentifier($relation->getTable()->getTableName())
|
||||||
. ' WHERE ' . $field . $operator . $value . ')';
|
. ' WHERE ' . $field . $operator . $value . ')';
|
||||||
}
|
}
|
||||||
$where = implode(' AND ', $where);
|
$where = implode(' AND ', $where);
|
||||||
@ -126,7 +127,7 @@ class Doctrine_Query_Where extends Doctrine_Query_Condition
|
|||||||
$field = $table->getColumnName($field);
|
$field = $table->getColumnName($field);
|
||||||
// check if value is enumerated value
|
// check if value is enumerated value
|
||||||
$enumIndex = $table->enumIndex($field, trim($value, "'"));
|
$enumIndex = $table->enumIndex($field, trim($value, "'"));
|
||||||
|
|
||||||
if (substr($value, 0, 1) == '(') {
|
if (substr($value, 0, 1) == '(') {
|
||||||
// trim brackets
|
// trim brackets
|
||||||
$trimmed = Doctrine_Tokenizer::bracketTrim($value);
|
$trimmed = Doctrine_Tokenizer::bracketTrim($value);
|
||||||
@ -180,7 +181,7 @@ class Doctrine_Query_Where extends Doctrine_Query_Condition
|
|||||||
default:
|
default:
|
||||||
|
|
||||||
if ($this->query->getType() === Doctrine_Query::SELECT) {
|
if ($this->query->getType() === Doctrine_Query::SELECT) {
|
||||||
$fieldname = $alias ? $alias . '.' . $field : $field;
|
$fieldname = $alias ? $conn->quoteIdentifier($alias . '.' . $field) : $field;
|
||||||
} else {
|
} else {
|
||||||
$fieldname = $field;
|
$fieldname = $field;
|
||||||
}
|
}
|
||||||
|
@ -578,17 +578,12 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
|
|||||||
}
|
}
|
||||||
} elseif (is_string($state)) {
|
} elseif (is_string($state)) {
|
||||||
$upper = strtoupper($state);
|
$upper = strtoupper($state);
|
||||||
switch ($upper) {
|
|
||||||
case 'DIRTY':
|
$const = 'Doctrine_Record::STATE_' . $upper;
|
||||||
case 'CLEAN':
|
if (defined($const)) {
|
||||||
case 'TDIRTY':
|
$this->_state = constant($const);
|
||||||
case 'TCLEAN':
|
} else {
|
||||||
case 'PROXY':
|
$err = true;
|
||||||
case 'DELETED':
|
|
||||||
$this->_state = constant('Doctrine_Record::STATE_' . $upper);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$err = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,34 +33,53 @@
|
|||||||
* @since 1.0
|
* @since 1.0
|
||||||
* @version $Revision$
|
* @version $Revision$
|
||||||
*/
|
*/
|
||||||
class Doctrine_Query_IdentifierQuoting_TestCase extends Doctrine_UnitTestCase {
|
class Doctrine_Query_IdentifierQuoting_TestCase extends Doctrine_UnitTestCase
|
||||||
public function prepareTables() { }
|
{
|
||||||
public function prepareData() { }
|
public function prepareTables()
|
||||||
public function testQuerySupportsIdentifierQuoting() {
|
{ }
|
||||||
|
|
||||||
|
public function prepareData()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public function testQuerySupportsIdentifierQuoting()
|
||||||
|
{
|
||||||
$this->conn->setAttribute(Doctrine::ATTR_QUOTE_IDENTIFIER, true);
|
$this->conn->setAttribute(Doctrine::ATTR_QUOTE_IDENTIFIER, true);
|
||||||
|
|
||||||
$q = new Doctrine_Query();
|
$q = new Doctrine_Query();
|
||||||
|
|
||||||
$q->parseQuery('SELECT MAX(u.id), MIN(u.name) FROM User u');
|
$q->parseQuery('SELECT MAX(u.id), MIN(u.name) FROM User u');
|
||||||
|
|
||||||
$this->assertEqual($q->getQuery(), 'SELECT MAX(e.id) AS e__0, MIN(e.name) AS e__1 FROM "entity" e WHERE (e.type = 0)');
|
$this->assertEqual($q->getQuery(), 'SELECT MAX("e.id") AS "e__0", MIN("e.name") AS "e__1" FROM "entity" "e" WHERE ("e.type" = 0)');
|
||||||
|
|
||||||
}
|
}
|
||||||
public function testQuerySupportsIdentifierQuotingWithJoins() {
|
|
||||||
|
public function testQuerySupportsIdentifierQuotingInWherePart()
|
||||||
|
{
|
||||||
|
$q = new Doctrine_Query();
|
||||||
|
|
||||||
|
$q->parseQuery('SELECT u.name FROM User u WHERE u.id = 3');
|
||||||
|
|
||||||
|
$this->assertEqual($q->getQuery(), 'SELECT "e.id" AS "e__id", "e.name" AS "e__name" FROM "entity" "e" WHERE "e.id" = 3 AND ("e.type" = 0)');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testQuerySupportsIdentifierQuotingWithJoins()
|
||||||
|
{
|
||||||
$q = new Doctrine_Query();
|
$q = new Doctrine_Query();
|
||||||
|
|
||||||
$q->parseQuery('SELECT u.name FROM User u LEFT JOIN u.Phonenumber p');
|
$q->parseQuery('SELECT u.name FROM User u LEFT JOIN u.Phonenumber p');
|
||||||
|
|
||||||
$this->assertEqual($q->getQuery(), 'SELECT e.id AS e__id, e.name AS e__name FROM "entity" e LEFT JOIN "phonenumber" p ON e.id = p.entity_id WHERE (e.type = 0)');
|
$this->assertEqual($q->getQuery(), 'SELECT "e.id" AS "e__id", "e.name" AS "e__name" FROM "entity" "e" LEFT JOIN "phonenumber" "p" ON "e.id" = "p.entity_id" WHERE ("e.type" = 0)');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testLimitSubqueryAlgorithmSupportsIdentifierQuoting() {
|
public function testLimitSubqueryAlgorithmSupportsIdentifierQuoting()
|
||||||
|
{
|
||||||
$q = new Doctrine_Query();
|
$q = new Doctrine_Query();
|
||||||
|
|
||||||
$q->parseQuery('SELECT u.name FROM User u INNER JOIN u.Phonenumber p')->limit(5);
|
$q->parseQuery('SELECT u.name FROM User u INNER JOIN u.Phonenumber p')->limit(5);
|
||||||
|
|
||||||
$this->assertEqual($q->getQuery(), 'SELECT e.id AS e__id, e.name AS e__name FROM "entity" e INNER JOIN "phonenumber" p ON e.id = p.entity_id WHERE e.id IN (SELECT DISTINCT e2.id FROM "entity" e2 INNER JOIN "phonenumber" p2 ON e2.id = p2.entity_id WHERE (e2.type = 0) LIMIT 5) AND (e.type = 0)');
|
$this->assertEqual($q->getQuery(), 'SELECT "e.id" AS "e__id", "e.name" AS "e__name" FROM "entity" "e" INNER JOIN "phonenumber" "p" ON "e.id" = "p.entity_id" WHERE "e.id" IN (SELECT DISTINCT "e2.id" FROM "entity" "e2" INNER JOIN "phonenumber" "p2" ON "e2.id" = "p2.entity_id" WHERE ("e2.type" = 0) LIMIT 5) AND ("e.type" = 0)');
|
||||||
|
|
||||||
$this->conn->setAttribute(Doctrine::ATTR_QUOTE_IDENTIFIER, false);
|
$this->conn->setAttribute(Doctrine::ATTR_QUOTE_IDENTIFIER, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user