Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

Commit

Permalink
Merge branch 'hotfix/289'
Browse files Browse the repository at this point in the history
Close #289
Fixes #288
  • Loading branch information
weierophinney committed Dec 7, 2017
2 parents 9f589dd + 1a37459 commit 14c5f0b
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 38 deletions.
14 changes: 13 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,24 @@

All notable changes to this project will be documented in this file, in reverse chronological order by release.

## 2.9.1 - TBD
## 2.9.1 - 2017-12-07

### Added

- Nothing.

### Changed

- [#289](https://github.com/zendframework/zend-db/pull/289) reverts a change
introduced in 2.9.0 and modifies the behavior of the PDO adapter slightly
to remove a regression. In 2.9.0, when binding parameters with names that
contained characters not supported by PDO, we would pass the parameter names
to `md5()`; this caused a regression, as the SQL string containing the
parameter name was not also updated.

This patch modifies the behavior during a bind-operation to instead raise an
exception if a parameter name contains characters not supported by PDO.

### Deprecated

- Nothing.
Expand Down
12 changes: 10 additions & 2 deletions src/Adapter/Driver/Pdo/Pdo.php
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,16 @@ public function getPrepareType()
public function formatParameterName($name, $type = null)
{
if ($type === null && ! is_numeric($name) || $type == self::PARAMETERIZATION_NAMED) {
// using MD5 because of the PDO restriction [A-Za-z0-9_] for bindParam name
return ':' . md5($name);
// @see https://bugs.php.net/bug.php?id=43130
if (preg_match('/[^a-zA-Z0-9_]/', $name)) {
throw new Exception\RuntimeException(sprintf(
'The PDO param %s contains invalid characters.'
. ' Only alphabetic characters, digits, and underscores (_)'
. ' are allowed.',
$name
));
}
return ':' . $name;
}

return '?';
Expand Down
37 changes: 28 additions & 9 deletions test/Adapter/Driver/Pdo/PdoTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,16 @@ public function testGetDatabasePlatformName()
public function getParamsAndType()
{
return [
[ 'foo', null, ':' . md5('foo')],
[ 'foo-', null, ':' . md5('foo-')],
[ 'foo$', null, ':' . md5('foo$')],
[ 'foo', null, ':foo' ],
[ 'foo_bar', null, ':foo_bar' ],
[ '123foo', null, ':123foo' ],
[ 1, null, '?' ],
[ '1', null, '?'],
[ 'foo', Pdo::PARAMETERIZATION_NAMED, ':' . md5('foo')],
[ 'foo-', Pdo::PARAMETERIZATION_NAMED, ':' . md5('foo-')],
[ 'foo$', Pdo::PARAMETERIZATION_NAMED, ':' . md5('foo$')],
[ 1, Pdo::PARAMETERIZATION_NAMED, ':' . md5('1')],
[ '1', Pdo::PARAMETERIZATION_NAMED, ':' . md5('1')],
[ '1', null, '?' ],
[ 'foo', Pdo::PARAMETERIZATION_NAMED, ':foo' ],
[ 'foo_bar', Pdo::PARAMETERIZATION_NAMED, ':foo_bar' ],
[ '123foo', Pdo::PARAMETERIZATION_NAMED, ':123foo' ],
[ 1, Pdo::PARAMETERIZATION_NAMED, ':1' ],
[ '1', Pdo::PARAMETERIZATION_NAMED, ':1' ],
];
}

Expand All @@ -64,4 +64,23 @@ public function testFormatParameterName($name, $type, $expected)
$result = $this->pdo->formatParameterName($name, $type);
$this->assertEquals($expected, $result);
}

public function getInvalidParamName()
{
return [
[ 'foo%' ],
[ 'foo-' ],
[ 'foo$' ],
[ 'foo0!' ]
];
}

/**
* @dataProvider getInvalidParamName
* @expectedException Zend\Db\Exception\RuntimeException
*/
public function testFormatParameterNameWithInvalidCharacters($name)
{
$this->pdo->formatParameterName($name);
}
}
4 changes: 2 additions & 2 deletions test/Adapter/Driver/Pdo/StatementIntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ protected function tearDown()
public function testStatementExecuteWillConvertPhpBoolToPdoBoolWhenBinding()
{
$this->pdoStatementMock->expects($this->any())->method('bindParam')->with(
$this->equalTo(':' . md5('foo')),
$this->equalTo(':foo'),
$this->equalTo(false),
$this->equalTo(\PDO::PARAM_BOOL)
);
Expand All @@ -65,7 +65,7 @@ public function testStatementExecuteWillConvertPhpBoolToPdoBoolWhenBinding()
public function testStatementExecuteWillUsePdoStrByDefaultWhenBinding()
{
$this->pdoStatementMock->expects($this->any())->method('bindParam')->with(
$this->equalTo(':' . md5('foo')),
$this->equalTo(':foo'),
$this->equalTo('bar'),
$this->equalTo(\PDO::PARAM_STR)
);
Expand Down
24 changes: 0 additions & 24 deletions test/Adapter/Driver/Pdo/StatementTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,28 +128,4 @@ public function testExecute()
$this->statement->prepare('SELECT 1');
self::assertInstanceOf('Zend\Db\Adapter\Driver\Pdo\Result', $this->statement->execute());
}

/**
* @see https://github.com/zendframework/zend-db/pull/224
*/
public function testExecuteWithSpecialCharInBindParam()
{
$testSqlite = new TestAsset\SqliteMemoryPdo('CREATE TABLE test (text_ TEXT, text$ TEXT);');
$this->statement->setDriver(new Pdo(new Connection($testSqlite)));
$this->statement->initialize($testSqlite);

$this->statement->prepare(sprintf(
'INSERT INTO test (text_, text$) VALUES (:%s, :%s)',
md5('text_'),
md5('text$')
));
$result = $this->statement->execute([ 'text_' => 'foo', 'text$' => 'bar']);
$this->assertInstanceOf(Result::class, $result);
$this->assertTrue($result->valid());

$result = $testSqlite->query('SELECT * FROM test');
$values = $result->fetch();
$this->assertEquals('foo', $values['text_']);
$this->assertEquals('bar', $values['text$']);
}
}

0 comments on commit 14c5f0b

Please sign in to comment.