Skip to content

Commit

Permalink
Zend\Db: Fix for ZF2-386 - Proper handling of single character safe w…
Browse files Browse the repository at this point in the history
…ords in platforms, also, feature for expressions in join ON clause.
  • Loading branch information
Ralph Schindler committed Jul 11, 2012
1 parent 26896dc commit c094d5b
Show file tree
Hide file tree
Showing 12 changed files with 84 additions and 12 deletions.
2 changes: 1 addition & 1 deletion library/Zend/Db/Adapter/Platform/Mysql.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public function getIdentifierSeparator()
*/
public function quoteIdentifierInFragment($identifier, array $safeWords = array())
{
$parts = preg_split('#([\.\s])#', $identifier, -1, PREG_SPLIT_DELIM_CAPTURE);
$parts = preg_split('#([\.\s\W])#', $identifier, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach($parts as $i => $part) {
if ($safeWords && in_array($part, $safeWords)) {
continue;
Expand Down
2 changes: 1 addition & 1 deletion library/Zend/Db/Adapter/Platform/Postgresql.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public function getIdentifierSeparator()
*/
public function quoteIdentifierInFragment($identifier, array $safeWords = array())
{
$parts = preg_split('#([\.\s])#', $identifier, -1, PREG_SPLIT_DELIM_CAPTURE);
$parts = preg_split('#([\.\s\W])#', $identifier, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach($parts as $i => $part) {
if ($safeWords && in_array($part, $safeWords)) {
continue;
Expand Down
5 changes: 4 additions & 1 deletion library/Zend/Db/Adapter/Platform/Sql92.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,13 @@ public function getIdentifierSeparator()
*/
public function quoteIdentifierInFragment($identifier, array $safeWords = array())
{
$parts = preg_split('#([\.\s])#', $identifier, -1, PREG_SPLIT_DELIM_CAPTURE);
$parts = preg_split('#([\.\s\W])#', $identifier, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);

foreach($parts as $i => $part) {
if ($safeWords && in_array($part, $safeWords)) {
continue;
}

switch ($part) {
case ' ':
case '.':
Expand All @@ -136,6 +138,7 @@ public function quoteIdentifierInFragment($identifier, array $safeWords = array(
$parts[$i] = '"' . str_replace('"', '\\' . '"', $part) . '"';
}
}

return implode('', $parts);
}

Expand Down
2 changes: 1 addition & 1 deletion library/Zend/Db/Adapter/Platform/SqlServer.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public function getIdentifierSeparator()
*/
public function quoteIdentifierInFragment($identifier, array $safeWords = array())
{
$parts = preg_split('#([\.\s])#', $identifier, -1, PREG_SPLIT_DELIM_CAPTURE);
$parts = preg_split('#([\.\s\W])#', $identifier, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach($parts as $i => $part) {
if ($safeWords && in_array($part, $safeWords)) {
continue;
Expand Down
2 changes: 1 addition & 1 deletion library/Zend/Db/Adapter/Platform/Sqlite.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public function getIdentifierSeparator()
*/
public function quoteIdentifierInFragment($identifier, array $safeWords = array())
{
$parts = preg_split('#([\.\s])#', $identifier, -1, PREG_SPLIT_DELIM_CAPTURE);
$parts = preg_split('#([\.\s\W])#', $identifier, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach($parts as $i => $part) {
if ($safeWords && in_array($part, $safeWords)) {
continue;
Expand Down
17 changes: 14 additions & 3 deletions library/Zend/Db/Sql/Select.php
Original file line number Diff line number Diff line change
Expand Up @@ -517,11 +517,22 @@ protected function processJoin(PlatformInterface $platform, Adapter $adapter = n
$joinSpecArgArray = array();
foreach ($this->joins as $j => $join) {
$joinSpecArgArray[$j] = array();
$joinSpecArgArray[$j][] = strtoupper($join['type']); // type
// type
$joinSpecArgArray[$j][] = strtoupper($join['type']);
// table name
$joinSpecArgArray[$j][] = (is_array($join['name']))
? $platform->quoteIdentifier(current($join['name'])) . ' AS ' . $platform->quoteIdentifier(key($join['name']))
: $platform->quoteIdentifier($join['name']); // table
$joinSpecArgArray[$j][] = $platform->quoteIdentifierInFragment($join['on'], array('=', 'AND', 'OR', '(', ')', 'BETWEEN')); // on
: $platform->quoteIdentifier($join['name']);
// on expression
$joinSpecArgArray[$j][] = ($join['on'] instanceof ExpressionInterface)
? $this->processExpression($join['on'], $platform, ($adapter) ? $adapter->getDriver() : null, 'join')
: $platform->quoteIdentifierInFragment($join['on'], array('=', 'AND', 'OR', '(', ')', 'BETWEEN')); // on
if (is_array($joinSpecArgArray[$j][2])) {
if (count($joinSpecArgArray[$j][2]['parameters']) > 0) {
$parameterContainer->merge($joinSpecArgArray[$j][2]['parameters']);
}
$joinSpecArgArray[$j][2] = $joinSpecArgArray[$j][2]['sql'];
}
}

return array($joinSpecArgArray);
Expand Down
9 changes: 9 additions & 0 deletions tests/Zend/Db/Adapter/Platform/MysqlTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,13 @@ public function testQuoteIdentifierInFragment()
$this->assertEquals('`foo`.`bar`', $this->platform->quoteIdentifierInFragment('foo.bar'));
$this->assertEquals('`foo` as `bar`', $this->platform->quoteIdentifierInFragment('foo as bar'));
}

/**
* @group ZF2-386
* @covers Zend\Db\Adapter\Platform\Mysql::quoteIdentifierInFragment
*/
public function testQuoteIdentifierInFragmentIgnoresSingleCharSafeWords()
{
$this->assertEquals('(`foo`.`bar` = `boo`.`baz`)', $this->platform->quoteIdentifierInFragment('(foo.bar = boo.baz)', array('(', ')', '=')));
}
}
9 changes: 9 additions & 0 deletions tests/Zend/Db/Adapter/Platform/PostgresqlTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,13 @@ public function testQuoteIdentifierInFragment()
$this->assertEquals('"foo"."bar"', $this->platform->quoteIdentifierInFragment('foo.bar'));
$this->assertEquals('"foo" as "bar"', $this->platform->quoteIdentifierInFragment('foo as bar'));
}

/**
* @group ZF2-386
* @covers Zend\Db\Adapter\Platform\Postgresql::quoteIdentifierInFragment
*/
public function testQuoteIdentifierInFragmentIgnoresSingleCharSafeWords()
{
$this->assertEquals('("foo"."bar" = "boo"."baz")', $this->platform->quoteIdentifierInFragment('(foo.bar = boo.baz)', array('(', ')', '=')));
}
}
10 changes: 10 additions & 0 deletions tests/Zend/Db/Adapter/Platform/Sql92Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,14 @@ public function testQuoteIdentifierInFragment()
$this->assertEquals('"foo"."bar"', $this->platform->quoteIdentifierInFragment('foo.bar'));
$this->assertEquals('"foo" as "bar"', $this->platform->quoteIdentifierInFragment('foo as bar'));
}

/**
* @group ZF2-386
* @covers Zend\Db\Adapter\Platform\Sql92::quoteIdentifierInFragment
*/
public function testQuoteIdentifierInFragmentIgnoresSingleCharSafeWords()
{
$this->assertEquals('("foo"."bar" = "boo"."baz")', $this->platform->quoteIdentifierInFragment('(foo.bar = boo.baz)', array('(', ')', '=')));
}

}
9 changes: 9 additions & 0 deletions tests/Zend/Db/Adapter/Platform/SqlServerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,13 @@ public function testQuoteIdentifierInFragment()
$this->assertEquals('[foo].[bar]', $this->platform->quoteIdentifierInFragment('foo.bar'));
$this->assertEquals('[foo] as [bar]', $this->platform->quoteIdentifierInFragment('foo as bar'));
}

/**
* @group ZF2-386
* @covers Zend\Db\Adapter\Platform\SqlServer::quoteIdentifierInFragment
*/
public function testQuoteIdentifierInFragmentIgnoresSingleCharSafeWords()
{
$this->assertEquals('([foo].[bar] = [boo].[baz])', $this->platform->quoteIdentifierInFragment('(foo.bar = boo.baz)', array('(', ')', '=')));
}
}
12 changes: 11 additions & 1 deletion tests/Zend/Db/Adapter/Platform/SqliteTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,14 @@ public function testQuoteIdentifierInFragment()
$this->assertEquals('"foo"."bar"', $this->platform->quoteIdentifierInFragment('foo.bar'));
$this->assertEquals('"foo" as "bar"', $this->platform->quoteIdentifierInFragment('foo as bar'));
}
}

/**
* @group ZF2-386
* @covers Zend\Db\Adapter\Platform\Postgresql::quoteIdentifierInFragment
*/
public function testQuoteIdentifierInFragmentIgnoresSingleCharSafeWords()
{
$this->assertEquals('("foo"."bar" = "boo"."baz")', $this->platform->quoteIdentifierInFragment('(foo.bar = boo.baz)', array('(', ')', '=')));
}

}
17 changes: 14 additions & 3 deletions tests/Zend/Db/Sql/SelectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -620,12 +620,12 @@ public function providerData()

// joins with a few keywords in the on clause
$select28 = new Select;
$select28->from('foo')->join('zac', 'm = n AND c.x BETWEEN x AND y.z');
$select28->from('foo')->join('zac', '(m = n AND c.x) BETWEEN x AND y.z');
$sqlPrep28 = // same
$sqlStr28 = 'SELECT "foo".*, "zac".* FROM "foo" INNER JOIN "zac" ON "m" = "n" AND "c"."x" BETWEEN "x" AND "y"."z"';
$sqlStr28 = 'SELECT "foo".*, "zac".* FROM "foo" INNER JOIN "zac" ON ("m" = "n" AND "c"."x") BETWEEN "x" AND "y"."z"';
$internalTests28 = array(
'processSelect' => array(array(array('"foo".*'), array('"zac".*')), '"foo"'),
'processJoin' => array(array(array('INNER', '"zac"', '"m" = "n" AND "c"."x" BETWEEN "x" AND "y"."z"')))
'processJoin' => array(array(array('INNER', '"zac"', '("m" = "n" AND "c"."x") BETWEEN "x" AND "y"."z"')))
);

// order with compound name
Expand All @@ -648,6 +648,16 @@ public function providerData()
'processGroup' => array(array('"c1"."d2"'))
);

// join with expression in ON part
$select31 = new Select;
$select31->from('foo')->join('zac', new Expression('(m = n AND c.x) BETWEEN x AND y.z'));
$sqlPrep31 = // same
$sqlStr31 = 'SELECT "foo".*, "zac".* FROM "foo" INNER JOIN "zac" ON (m = n AND c.x) BETWEEN x AND y.z';
$internalTests31 = array(
'processSelect' => array(array(array('"foo".*'), array('"zac".*')), '"foo"'),
'processJoin' => array(array(array('INNER', '"zac"', '(m = n AND c.x) BETWEEN x AND y.z')))
);

/**
* $select = the select object
* $sqlPrep = the sql as a result of preparation
Expand Down Expand Up @@ -688,6 +698,7 @@ public function providerData()
array($select28, $sqlPrep28, array(), $sqlStr28, $internalTests28),
array($select29, $sqlPrep29, array(), $sqlStr29, $internalTests29),
array($select30, $sqlPrep30, array(), $sqlStr30, $internalTests30),
array($select31, $sqlPrep31, array(), $sqlStr31, $internalTests31),
);
}

Expand Down

0 comments on commit c094d5b

Please sign in to comment.