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

Postgresql indexes #163

Open
wants to merge 38 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
10b115c
Add PostgreSQL platform.
alextech Sep 3, 2016
7a2b9bb
Add CreateTableDecorator. Change ends of commands with ';'
alextech Sep 3, 2016
0c5845d
Index constructor signature does not follow docs and the overridden C…
alextech Sep 3, 2016
030fbeb
Add Postgres Index Decorator. Modifies specification to eventually co…
alextech Sep 3, 2016
5706b0c
Process indexes separately from constraints, after CreateTable specif…
alextech Sep 3, 2016
4a3c918
Add AlterTableDecorator to PostgreSQL platform.
alextech Sep 3, 2016
7a0bd3b
styles
alextech Sep 3, 2016
334685e
Add support for index creation in PostgreSQL AlterTableDecorator
alextech Sep 5, 2016
ccaa6bf
Keep expected strings together with test API stubs.
alextech Sep 5, 2016
2803f4e
dropConstraint() now supports index-related constraints.
alextech Sep 5, 2016
8b3e1d4
code sniffer rules
alextech Sep 6, 2016
d5272e8
code sniffer rules
alextech Sep 6, 2016
6866a6b
Merge branch 'brettmc-sqlsrv-integration-params'
ezimuel Dec 4, 2017
ab1f2e8
Fixed CS issues
ezimuel Dec 5, 2017
6113b68
Merge branch 'develop'
ezimuel Dec 6, 2017
b67f2d1
Merge branch 'release/2.9.0'
ezimuel Dec 6, 2017
9f589dd
Updated CHANGELOG
ezimuel Dec 6, 2017
fec7d8c
Revert PR #224 due to issue like #288
ezimuel Dec 7, 2017
43104a8
Throw Exception for invalid PDO param name
ezimuel Dec 7, 2017
400a890
Merge pull request #289 from ezimuel/fix/revert-224
weierophinney Dec 7, 2017
e59f2d8
Updates to exception message introduced in #289
weierophinney Dec 7, 2017
1a37459
Adds CHANGELOG entry for #289
weierophinney Dec 7, 2017
14c5f0b
Merge branch 'hotfix/289'
weierophinney Dec 7, 2017
4d691cf
Bumped to next dev version (2.9.2)
weierophinney Dec 7, 2017
69118aa
Bumped version
weierophinney Dec 7, 2017
128913a
Add PostgreSQL platform.
alextech Sep 3, 2016
c37d3e5
Add CreateTableDecorator. Change ends of commands with ';'
alextech Sep 3, 2016
05ff2d5
Index constructor signature does not follow docs and the overridden C…
alextech Sep 3, 2016
25da6e9
Add Postgres Index Decorator. Modifies specification to eventually co…
alextech Sep 3, 2016
8bd2b48
Process indexes separately from constraints, after CreateTable specif…
alextech Sep 3, 2016
c506e15
Add AlterTableDecorator to PostgreSQL platform.
alextech Sep 3, 2016
3df0204
styles
alextech Sep 3, 2016
fef4634
Add support for index creation in PostgreSQL AlterTableDecorator
alextech Sep 5, 2016
7772e19
Keep expected strings together with test API stubs.
alextech Sep 5, 2016
737ec63
dropConstraint() now supports index-related constraints.
alextech Sep 5, 2016
379defc
code sniffer rules
alextech Sep 6, 2016
7af3bfa
code sniffer rules
alextech Sep 6, 2016
2a4a313
Merge remote-tracking branch 'fork/postgresql_indexes' into postgresq…
alextech Dec 8, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,58 @@

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

## 2.9.2 - TBD

### Added

- Nothing.

### Changed

- Nothing.

### Deprecated

- Nothing.

### Removed

- Nothing.

### Fixed

- Nothing.

## 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.

### Removed

- Nothing.

### Fixed

- Nothing.

## 2.9.0 - 2017-12-06

### Added
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
2 changes: 1 addition & 1 deletion src/Sql/Ddl/Index/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Index extends AbstractIndex
* @param null|string $name
* @param array $lengths
*/
public function __construct($columns, $name = null, array $lengths = [])
public function __construct($columns = null, $name = null, array $lengths = [])
{
$this->setColumns($columns);

Expand Down
24 changes: 13 additions & 11 deletions src/Sql/Platform/Platform.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,19 @@ public function __construct(AdapterInterface $adapter)
{
$this->defaultPlatform = $adapter->getPlatform();

$mySqlPlatform = new Mysql\Mysql();
$sqlServerPlatform = new SqlServer\SqlServer();
$oraclePlatform = new Oracle\Oracle();
$ibmDb2Platform = new IbmDb2\IbmDb2();
$sqlitePlatform = new Sqlite\Sqlite();

$this->decorators['mysql'] = $mySqlPlatform->getDecorators();
$this->decorators['sqlserver'] = $sqlServerPlatform->getDecorators();
$this->decorators['oracle'] = $oraclePlatform->getDecorators();
$this->decorators['ibmdb2'] = $ibmDb2Platform->getDecorators();
$this->decorators['sqlite'] = $sqlitePlatform->getDecorators();
$mySqlPlatform = new Mysql\Mysql();
$sqlServerPlatform = new SqlServer\SqlServer();
$oraclePlatform = new Oracle\Oracle();
$ibmDb2Platform = new IbmDb2\IbmDb2();
$sqlitePlatform = new Sqlite\Sqlite();
$postgresqlPlatform = new Postgresql\Postgresql();

$this->decorators['mysql'] = $mySqlPlatform->getDecorators();
$this->decorators['sqlserver'] = $sqlServerPlatform->getDecorators();
$this->decorators['oracle'] = $oraclePlatform->getDecorators();
$this->decorators['ibmdb2'] = $ibmDb2Platform->getDecorators();
$this->decorators['sqlite'] = $sqlitePlatform->getDecorators();
$this->decorators['postgresql'] = $postgresqlPlatform->getDecorators();
}

/**
Expand Down
195 changes: 195 additions & 0 deletions src/Sql/Platform/Postgresql/Ddl/AlterTableDecorator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2016 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace Zend\Db\Sql\Platform\Postgresql\Ddl;

use Zend\Db\Adapter\Driver\DriverInterface;
use Zend\Db\Adapter\ParameterContainer;
use Zend\Db\Adapter\Platform\PlatformInterface;
use Zend\Db\Sql\Ddl\AlterTable;
use Zend\Db\Sql\Ddl\Index\Index;
use Zend\Db\Sql\Platform\PlatformDecoratorInterface;
use Zend\Db\Sql\Platform\Postgresql\Ddl\Index\IndexDecorator;

class AlterTableDecorator extends AlterTable implements PlatformDecoratorInterface
{
const ADD_INDEXES = 'addIndexes';
const DROP_INDEXES = 'dropIndexes';

/**
* @var AlterTable
*/
protected $subject;

/**
* @var IndexDecorator[]
*/
protected $addIndexes = [];

/**
* @var string[]
*/
protected $dropIndexes = [];

/**
* @var bool
*/
private $hasCreateTable = true;

/**
* Compensate for dropConstraint() interface not distinguishing between string and index object.
* Add IF EXISTS for safety to handle either until/if new signature is approved.
*
* @var array
*/
protected $dropConstraintSpecification = [
"%1\$s" => [
[1 => "DROP CONSTRAINT IF EXISTS %1\$s,\n", 'combinedby' => ""],
]
];

protected $indexSpecification = [
'statementEnd' => '%1$s',
self::ADD_INDEXES => [
"%1\$s" => [
[1 => '%1$s;', 'combinedby' => "\n"]
]
],
self::DROP_INDEXES => [
"%1\$s" => [
[1 => 'DROP INDEX IF EXISTS %1$s;', 'combinedby' => "\n"]
]
]
];

/**
* @inheritDoc
*/
public function setSubject($subject)
{
$this->subject = $subject;

$this->specifications[self::DROP_CONSTRAINTS] = $this->dropConstraintSpecification;
$this->subject->specifications = $this->specifications;

return $this;
}

/**
* @inheritDoc
*/
protected function buildSqlString(
PlatformInterface $platform,
DriverInterface $driver = null,
ParameterContainer $parameterContainer = null
) {
$this->separateIndexesFromConstraints();
$this->duplicateDropConstraintToDropIndex();
$this->deleteUnneededSpecification();

// unlike CreateTableDecorator where CREATE TABLE is always present for new tables, regardless of Incex creation
// PostgreSQL does not use ALTER TABLE to add/drop indexes to existing tables.
// Therefore, if the only change is index related, DDL would have dangling ALTER TABLE.
// Consequently, table alterations outside of ALTER TABLE syntax get processed as whole different specification chunk
$alterTable = '';
if ($this->hasCreateTable) {
$alterTable = parent::buildSqlString($platform, $driver, $parameterContainer);
$this->subject->specifications = $this->specifications = $this->indexSpecification;
}

$indexes = parent::buildSqlString($platform, $driver, $parameterContainer);
return $alterTable.$indexes;
}

private function separateIndexesFromConstraints()
{
// take advantage of PHP's ability to access protected properties of different instances created from same class
$this->addIndexes = array_filter($this->subject->addConstraints, function ($constraint) {
return $constraint instanceof Index;
});

$filteredConstraints = array_filter($this->subject->addConstraints, function ($constraint) {
return !($constraint instanceof Index);
});

$this->subject->addConstraints = $filteredConstraints;

array_walk($this->addIndexes, function (&$index, $key) {
$indexDecorator = new IndexDecorator();
$indexDecorator->setSubject($index);
$indexDecorator->setTable($this->subject->table);
$index = $indexDecorator;
});
}

/**
* DROP CONSTRAINT always with DROP INDEX to compensate for dropConstraint() interface
* only accepting strings, not inspectable objects.
* @TODO if new signature removeConstraint(string|AbstractConstraint) gets approved, delete this method
*/
private function duplicateDropConstraintToDropIndex()
{
$this->dropIndexes = $this->subject->dropConstraints;
}

/**
* @param PlatformInterface|null $adapterPlatform
* @return array|void
*/
protected function processAddIndexes(PlatformInterface $adapterPlatform = null)
{
if (!$this->addIndexes) {
return;
}

$sqls = [];

foreach ($this->addIndexes as $index) {
$sqls[] = $this->processExpression($index, $adapterPlatform);
}

return [$sqls];
}

protected function processDropIndexes(PlatformInterface $adapterPlatform = null)
{
if (!$this->dropIndexes) {
return;
}

$sqls = [];

foreach ($this->dropIndexes as $index) {
$sqls[] = $adapterPlatform->quoteIdentifier($index);
}

return [$sqls];
}

/**
* @param PlatformInterface|null $adapterPlatform
* @return array|void
*/
protected function processStatementEnd(PlatformInterface $adapterPlatform = null)
{
return [";\n"];
}

private function deleteUnneededSpecification()
{
$subject = $this->subject;
if (!($subject->addColumns || $subject->changeColumns || $subject->dropColumns
|| $subject->addConstraints || $subject->dropConstraints)) {
$this->hasCreateTable = false;

unset($this->indexSpecification['statementEnd']);
$this->subject->specifications = $this->specifications = $this->indexSpecification;
}
}
}
Loading