From b328d08c0b0ee3e37e9e0613cd9118980423b70a Mon Sep 17 00:00:00 2001 From: turrsis Date: Thu, 30 Jul 2015 19:25:10 +0300 Subject: [PATCH 01/30] fix CS --- .../Driver/Pdo/AbstractIntegrationTest.php | 32 ------------------- test/Adapter/Driver/Pdo/ResultTest.php | 1 - test/TestAsset/PdoStubDriver.php | 3 +- 3 files changed, 2 insertions(+), 34 deletions(-) delete mode 100644 test/Adapter/Driver/Pdo/AbstractIntegrationTest.php diff --git a/test/Adapter/Driver/Pdo/AbstractIntegrationTest.php b/test/Adapter/Driver/Pdo/AbstractIntegrationTest.php deleted file mode 100644 index 53ece0ce4b..0000000000 --- a/test/Adapter/Driver/Pdo/AbstractIntegrationTest.php +++ /dev/null @@ -1,32 +0,0 @@ -variables as $name => $value) { -// if (!getenv($value)) { -// $this->markTestSkipped('Missing required variable ' . $value . ' from phpunit.xml for this integration test'); -// } -// $this->variables[$name] = getenv($value); -// } -// -// if (!extension_loaded('sqlsrv')) { -// $this->fail('The phpunit group integration-sqlsrv was enabled, but the extension is not loaded.'); -// } -// } -//} diff --git a/test/Adapter/Driver/Pdo/ResultTest.php b/test/Adapter/Driver/Pdo/ResultTest.php index edda281648..dfd4334175 100644 --- a/test/Adapter/Driver/Pdo/ResultTest.php +++ b/test/Adapter/Driver/Pdo/ResultTest.php @@ -20,7 +20,6 @@ */ class ResultTest extends \PHPUnit_Framework_TestCase { - /** * Tests current method returns same data on consecutive calls. * diff --git a/test/TestAsset/PdoStubDriver.php b/test/TestAsset/PdoStubDriver.php index 0df0db55a6..886324f653 100644 --- a/test/TestAsset/PdoStubDriver.php +++ b/test/TestAsset/PdoStubDriver.php @@ -14,7 +14,8 @@ public function commit() } public function __construct($dsn, $user, $password) - {} + { + } public function rollBack() { From 298b1aea8d19ddf73eac2566a2b5cb0e95872e09 Mon Sep 17 00:00:00 2001 From: turrsis Date: Thu, 9 Jul 2015 10:44:54 +0300 Subject: [PATCH 02/30] architecture 01: change namespaces --- src/Sql/AbstractExpression.php | 6 +- ...ql.php => AbstractPreparableSqlObject.php} | 2 +- ...{AbstractSql.php => AbstractSqlObject.php} | 4 +- .../AbstractBuilder.php} | 20 +- .../Platform.php => Builder/Builder.php} | 51 +++-- .../IbmDb2/SelectBuilder.php} | 6 +- .../Mysql/Ddl/AlterTableBuilder.php} | 6 +- .../Mysql/Ddl/CreateTableBuilder.php} | 6 +- .../Mysql/SelectBuilder.php} | 6 +- .../Oracle/SelectBuilder.php} | 6 +- .../PlatformDecoratorInterface.php | 2 +- .../SqlServer/Ddl/CreateTableBuilder.php} | 6 +- .../SqlServer/SelectBuilder.php} | 6 +- .../Sqlite/SelectBuilder.php} | 10 +- src/Sql/Combine.php | 2 +- src/Sql/Ddl/AlterTable.php | 4 +- src/Sql/Ddl/CreateTable.php | 4 +- src/Sql/Ddl/DropTable.php | 4 +- ...qlInterface.php => SqlObjectInterface.php} | 4 +- src/Sql/Delete.php | 2 +- src/Sql/Insert.php | 2 +- src/Sql/Platform/IbmDb2/IbmDb2.php | 23 -- src/Sql/Platform/Mysql/Mysql.php | 22 -- src/Sql/Platform/Oracle/Oracle.php | 20 -- src/Sql/Platform/SqlServer/SqlServer.php | 21 -- src/Sql/Platform/Sqlite/Sqlite.php | 25 -- ...e.php => PreparableSqlObjectInterface.php} | 2 +- src/Sql/Select.php | 2 +- src/Sql/Sql.php | 18 +- ...qlInterface.php => SqlObjectInterface.php} | 2 +- src/Sql/Update.php | 2 +- ...tSqlTest.php => AbstractSqlObjectTest.php} | 12 +- .../AllBuildersTest.php} | 216 +++++++++--------- .../BuilderTest.php} | 14 +- .../IbmDb2/SelectBuilderTest.php} | 10 +- .../Mysql/Ddl/CreateTableBuilderTest.php} | 10 +- .../Mysql/SelectBuilderTest.php} | 18 +- .../Oracle/SelectBuilderTest.php} | 20 +- .../SqlServer/Ddl/CreateTableBuilderTest.php} | 10 +- .../SqlServer/SelectBuilderTest.php} | 22 +- .../Sqlite/SelectBuilderTest.php} | 10 +- test/Sql/Platform/Mysql/MysqlTest.php | 29 --- test/Sql/Platform/Oracle/OracleTest.php | 29 --- test/Sql/Platform/SqlServer/SqlServerTest.php | 29 --- test/Sql/Platform/Sqlite/SqliteTest.php | 29 --- ...{DeleteDecorator.php => DeleteBuilder.php} | 2 +- ...{InsertDecorator.php => InsertBuilder.php} | 2 +- ...{UpdateDecorator.php => SelectBuilder.php} | 2 +- ...{SelectDecorator.php => UpdateBuilder.php} | 2 +- 49 files changed, 272 insertions(+), 490 deletions(-) rename src/Sql/{AbstractPreparableSql.php => AbstractPreparableSqlObject.php} (91%) rename src/Sql/{AbstractSql.php => AbstractSqlObject.php} (99%) rename src/Sql/{Platform/AbstractPlatform.php => Builder/AbstractBuilder.php} (75%) rename src/Sql/{Platform/Platform.php => Builder/Builder.php} (73%) rename src/Sql/{Platform/IbmDb2/SelectDecorator.php => Builder/IbmDb2/SelectBuilder.php} (96%) rename src/Sql/{Platform/Mysql/Ddl/AlterTableDecorator.php => Builder/Mysql/Ddl/AlterTableBuilder.php} (97%) rename src/Sql/{Platform/Mysql/Ddl/CreateTableDecorator.php => Builder/Mysql/Ddl/CreateTableBuilder.php} (96%) rename src/Sql/{Platform/Mysql/SelectDecorator.php => Builder/Mysql/SelectBuilder.php} (92%) rename src/Sql/{Platform/Oracle/SelectDecorator.php => Builder/Oracle/SelectBuilder.php} (96%) rename src/Sql/{Platform => Builder}/PlatformDecoratorInterface.php (93%) rename src/Sql/{Platform/SqlServer/Ddl/CreateTableDecorator.php => Builder/SqlServer/Ddl/CreateTableBuilder.php} (84%) rename src/Sql/{Platform/SqlServer/SelectDecorator.php => Builder/SqlServer/SelectBuilder.php} (96%) rename src/Sql/{Platform/Sqlite/SelectDecorator.php => Builder/Sqlite/SelectBuilder.php} (87%) rename src/Sql/Ddl/{SqlInterface.php => SqlObjectInterface.php} (73%) delete mode 100644 src/Sql/Platform/IbmDb2/IbmDb2.php delete mode 100644 src/Sql/Platform/Mysql/Mysql.php delete mode 100644 src/Sql/Platform/Oracle/Oracle.php delete mode 100644 src/Sql/Platform/SqlServer/SqlServer.php delete mode 100644 src/Sql/Platform/Sqlite/Sqlite.php rename src/Sql/{PreparableSqlInterface.php => PreparableSqlObjectInterface.php} (94%) rename src/Sql/{SqlInterface.php => SqlObjectInterface.php} (95%) rename test/Sql/{AbstractSqlTest.php => AbstractSqlObjectTest.php} (94%) rename test/Sql/{SqlFunctionalTest.php => Builder/AllBuildersTest.php} (84%) rename test/Sql/{Platform/PlatformTest.php => Builder/BuilderTest.php} (92%) rename test/Sql/{Platform/IbmDb2/SelectDecoratorTest.php => Builder/IbmDb2/SelectBuilderTest.php} (96%) rename test/Sql/{Platform/Mysql/Ddl/CreateTableDecoratorTest.php => Builder/Mysql/Ddl/CreateTableBuilderTest.php} (85%) rename test/Sql/{Platform/Mysql/SelectDecoratorTest.php => Builder/Mysql/SelectBuilderTest.php} (86%) rename test/Sql/{Platform/Oracle/SelectDecoratorTest.php => Builder/Oracle/SelectBuilderTest.php} (88%) rename test/Sql/{Platform/SqlServer/Ddl/CreateTableDecoratorTest.php => Builder/SqlServer/Ddl/CreateTableBuilderTest.php} (79%) rename test/Sql/{Platform/SqlServer/SelectDecoratorTest.php => Builder/SqlServer/SelectBuilderTest.php} (88%) rename test/Sql/{Platform/Sqlite/SelectDecoratorTest.php => Builder/Sqlite/SelectBuilderTest.php} (93%) delete mode 100644 test/Sql/Platform/Mysql/MysqlTest.php delete mode 100644 test/Sql/Platform/Oracle/OracleTest.php delete mode 100644 test/Sql/Platform/SqlServer/SqlServerTest.php delete mode 100644 test/Sql/Platform/Sqlite/SqliteTest.php rename test/TestAsset/{DeleteDecorator.php => DeleteBuilder.php} (84%) rename test/TestAsset/{InsertDecorator.php => InsertBuilder.php} (84%) rename test/TestAsset/{UpdateDecorator.php => SelectBuilder.php} (84%) rename test/TestAsset/{SelectDecorator.php => UpdateBuilder.php} (84%) diff --git a/src/Sql/AbstractExpression.php b/src/Sql/AbstractExpression.php index 3fbee7c1c6..b5a4a9fa8e 100644 --- a/src/Sql/AbstractExpression.php +++ b/src/Sql/AbstractExpression.php @@ -33,7 +33,7 @@ abstract class AbstractExpression implements ExpressionInterface */ protected function normalizeArgument($argument, $defaultType = self::TYPE_VALUE) { - if ($argument instanceof ExpressionInterface || $argument instanceof SqlInterface) { + if ($argument instanceof ExpressionInterface || $argument instanceof SqlObjectInterface) { return $this->buildNormalizedArgument($argument, self::TYPE_VALUE); } @@ -44,7 +44,7 @@ protected function normalizeArgument($argument, $defaultType = self::TYPE_VALUE) if (is_array($argument)) { $value = current($argument); - if ($value instanceof ExpressionInterface || $value instanceof SqlInterface) { + if ($value instanceof ExpressionInterface || $value instanceof SqlObjectInterface) { return $this->buildNormalizedArgument($value, self::TYPE_VALUE); } @@ -63,7 +63,7 @@ protected function normalizeArgument($argument, $defaultType = self::TYPE_VALUE) 'scalar', 'array', 'Zend\Db\Sql\ExpressionInterface', - 'Zend\Db\Sql\SqlInterface', + 'Zend\Db\Sql\SqlObjectInterface', is_object($argument) ? get_class($argument) : gettype($argument) )); } diff --git a/src/Sql/AbstractPreparableSql.php b/src/Sql/AbstractPreparableSqlObject.php similarity index 91% rename from src/Sql/AbstractPreparableSql.php rename to src/Sql/AbstractPreparableSqlObject.php index 6d95f90d84..63842bc9df 100644 --- a/src/Sql/AbstractPreparableSql.php +++ b/src/Sql/AbstractPreparableSqlObject.php @@ -13,7 +13,7 @@ use Zend\Db\Adapter\AdapterInterface; use Zend\Db\Adapter\ParameterContainer; -abstract class AbstractPreparableSql extends AbstractSql implements PreparableSqlInterface +abstract class AbstractPreparableSqlObject extends AbstractSqlObject implements PreparableSqlObjectInterface { /** * {@inheritDoc} diff --git a/src/Sql/AbstractSql.php b/src/Sql/AbstractSqlObject.php similarity index 99% rename from src/Sql/AbstractSql.php rename to src/Sql/AbstractSqlObject.php index f7d1d42e82..64a2fb414e 100644 --- a/src/Sql/AbstractSql.php +++ b/src/Sql/AbstractSqlObject.php @@ -12,10 +12,10 @@ use Zend\Db\Adapter\Driver\DriverInterface; use Zend\Db\Adapter\ParameterContainer; use Zend\Db\Adapter\Platform\PlatformInterface; -use Zend\Db\Sql\Platform\PlatformDecoratorInterface; +use Zend\Db\Sql\Builder\PlatformDecoratorInterface; use Zend\Db\Adapter\Platform\Sql92 as DefaultAdapterPlatform; -abstract class AbstractSql implements SqlInterface +abstract class AbstractSqlObject implements SqlObjectInterface { /** * Specifications for Sql String generation diff --git a/src/Sql/Platform/AbstractPlatform.php b/src/Sql/Builder/AbstractBuilder.php similarity index 75% rename from src/Sql/Platform/AbstractPlatform.php rename to src/Sql/Builder/AbstractBuilder.php index 55411d7d33..33145d4e1f 100644 --- a/src/Sql/Platform/AbstractPlatform.php +++ b/src/Sql/Builder/AbstractBuilder.php @@ -7,16 +7,16 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace Zend\Db\Sql\Platform; +namespace Zend\Db\Sql\Builder; use Zend\Db\Adapter\AdapterInterface; use Zend\Db\Adapter\Platform\PlatformInterface; use Zend\Db\Adapter\StatementContainerInterface; use Zend\Db\Sql\Exception; -use Zend\Db\Sql\PreparableSqlInterface; -use Zend\Db\Sql\SqlInterface; +use Zend\Db\Sql\PreparableSqlObjectInterface; +use Zend\Db\Sql\SqlObjectInterface; -class AbstractPlatform implements PlatformDecoratorInterface, PreparableSqlInterface, SqlInterface +class AbstractBuilder implements PlatformDecoratorInterface, PreparableSqlObjectInterface, SqlObjectInterface { /** * @var object|null @@ -50,8 +50,8 @@ public function setTypeDecorator($type, PlatformDecoratorInterface $decorator) } /** - * @param PreparableSqlInterface|SqlInterface $subject - * @return PlatformDecoratorInterface|PreparableSqlInterface|SqlInterface + * @param PreparableSqlObjectInterface|SqlObjectInterface $subject + * @return PlatformDecoratorInterface|PreparableSqlObjectInterface|SqlObjectInterface */ public function getTypeDecorator($subject) { @@ -81,8 +81,8 @@ public function getDecorators() */ public function prepareStatement(AdapterInterface $adapter, StatementContainerInterface $statementContainer) { - if (! $this->subject instanceof PreparableSqlInterface) { - throw new Exception\RuntimeException('The subject does not appear to implement Zend\Db\Sql\PreparableSqlInterface, thus calling prepareStatement() has no effect'); + if (! $this->subject instanceof PreparableSqlObjectInterface) { + throw new Exception\RuntimeException('The subject does not appear to implement Zend\Db\Sql\PreparableSqlObjectInterface, thus calling prepareStatement() has no effect'); } $this->getTypeDecorator($this->subject)->prepareStatement($adapter, $statementContainer); @@ -97,8 +97,8 @@ public function prepareStatement(AdapterInterface $adapter, StatementContainerIn */ public function getSqlString(PlatformInterface $adapterPlatform = null) { - if (! $this->subject instanceof SqlInterface) { - throw new Exception\RuntimeException('The subject does not appear to implement Zend\Db\Sql\SqlInterface, thus calling prepareStatement() has no effect'); + if (! $this->subject instanceof SqlObjectInterface) { + throw new Exception\RuntimeException('The subject does not appear to implement Zend\Db\Sql\SqlObjectInterface, thus calling prepareStatement() has no effect'); } return $this->getTypeDecorator($this->subject)->getSqlString($adapterPlatform); diff --git a/src/Sql/Platform/Platform.php b/src/Sql/Builder/Builder.php similarity index 73% rename from src/Sql/Platform/Platform.php rename to src/Sql/Builder/Builder.php index ad375d5d71..dcd517432b 100644 --- a/src/Sql/Platform/Platform.php +++ b/src/Sql/Builder/Builder.php @@ -7,16 +7,16 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace Zend\Db\Sql\Platform; +namespace Zend\Db\Sql\Builder; use Zend\Db\Adapter\AdapterInterface; use Zend\Db\Adapter\Platform\PlatformInterface; use Zend\Db\Adapter\StatementContainerInterface; use Zend\Db\Sql\Exception; -use Zend\Db\Sql\PreparableSqlInterface; -use Zend\Db\Sql\SqlInterface; +use Zend\Db\Sql\PreparableSqlObjectInterface; +use Zend\Db\Sql\SqlObjectInterface; -class Platform extends AbstractPlatform +class Builder extends AbstractBuilder { /** * @var AdapterInterface @@ -32,17 +32,26 @@ 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(); + $this->decorators = [ + 'mysql' => [ + 'Zend\Db\Sql\Select' => new Mysql\SelectBuilder(), + 'Zend\Db\Sql\Ddl\CreateTable' => new Mysql\Ddl\CreateTableBuilder(), + 'Zend\Db\Sql\Ddl\AlterTable' => new Mysql\Ddl\AlterTableBuilder(), + ], + 'sqlserver' => [ + 'Zend\Db\Sql\Select' => new SqlServer\SelectBuilder(), + 'Zend\Db\Sql\Ddl\CreateTable' => new SqlServer\Ddl\CreateTableBuilder(), + ], + 'oracle' => [ + 'Zend\Db\Sql\Select' => new Oracle\SelectBuilder(), + ], + 'ibmdb2' => [ + 'Zend\Db\Sql\Select' => new IbmDb2\SelectBuilder(), + ], + 'sqlite' => [ + 'Zend\Db\Sql\Select' => new Sqlite\SelectBuilder(), + ], + ]; } /** @@ -57,9 +66,9 @@ public function setTypeDecorator($type, PlatformDecoratorInterface $decorator, $ } /** - * @param PreparableSqlInterface|SqlInterface $subject + * @param PreparableSqlObjectInterface|SqlObjectInterface $subject * @param AdapterInterface|PlatformInterface|null $adapterOrPlatform - * @return PlatformDecoratorInterface|PreparableSqlInterface|SqlInterface + * @return PlatformDecoratorInterface|PreparableSqlObjectInterface|SqlObjectInterface */ public function getTypeDecorator($subject, $adapterOrPlatform = null) { @@ -93,8 +102,8 @@ public function getDecorators() */ public function prepareStatement(AdapterInterface $adapter, StatementContainerInterface $statementContainer) { - if (! $this->subject instanceof PreparableSqlInterface) { - throw new Exception\RuntimeException('The subject does not appear to implement Zend\Db\Sql\PreparableSqlInterface, thus calling prepareStatement() has no effect'); + if (! $this->subject instanceof PreparableSqlObjectInterface) { + throw new Exception\RuntimeException('The subject does not appear to implement Zend\Db\Sql\PreparableSqlObjectInterface, thus calling prepareStatement() has no effect'); } $this->getTypeDecorator($this->subject, $adapter)->prepareStatement($adapter, $statementContainer); @@ -109,8 +118,8 @@ public function prepareStatement(AdapterInterface $adapter, StatementContainerIn */ public function getSqlString(PlatformInterface $adapterPlatform = null) { - if (! $this->subject instanceof SqlInterface) { - throw new Exception\RuntimeException('The subject does not appear to implement Zend\Db\Sql\SqlInterface, thus calling prepareStatement() has no effect'); + if (! $this->subject instanceof SqlObjectInterface) { + throw new Exception\RuntimeException('The subject does not appear to implement Zend\Db\Sql\SqlObjectInterface, thus calling prepareStatement() has no effect'); } $adapterPlatform = $this->resolvePlatform($adapterPlatform); diff --git a/src/Sql/Platform/IbmDb2/SelectDecorator.php b/src/Sql/Builder/IbmDb2/SelectBuilder.php similarity index 96% rename from src/Sql/Platform/IbmDb2/SelectDecorator.php rename to src/Sql/Builder/IbmDb2/SelectBuilder.php index 28602b20e4..f011dad0c0 100644 --- a/src/Sql/Platform/IbmDb2/SelectDecorator.php +++ b/src/Sql/Builder/IbmDb2/SelectBuilder.php @@ -7,15 +7,15 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace Zend\Db\Sql\Platform\IbmDb2; +namespace Zend\Db\Sql\Builder\IbmDb2; use Zend\Db\Adapter\Driver\DriverInterface; use Zend\Db\Adapter\ParameterContainer; use Zend\Db\Adapter\Platform\PlatformInterface; -use Zend\Db\Sql\Platform\PlatformDecoratorInterface; +use Zend\Db\Sql\Builder\PlatformDecoratorInterface; use Zend\Db\Sql\Select; -class SelectDecorator extends Select implements PlatformDecoratorInterface +class SelectBuilder extends Select implements PlatformDecoratorInterface { /** * @var bool diff --git a/src/Sql/Platform/Mysql/Ddl/AlterTableDecorator.php b/src/Sql/Builder/Mysql/Ddl/AlterTableBuilder.php similarity index 97% rename from src/Sql/Platform/Mysql/Ddl/AlterTableDecorator.php rename to src/Sql/Builder/Mysql/Ddl/AlterTableBuilder.php index 538f0b35f4..d8fc403168 100644 --- a/src/Sql/Platform/Mysql/Ddl/AlterTableDecorator.php +++ b/src/Sql/Builder/Mysql/Ddl/AlterTableBuilder.php @@ -7,13 +7,13 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace Zend\Db\Sql\Platform\Mysql\Ddl; +namespace Zend\Db\Sql\Builder\Mysql\Ddl; use Zend\Db\Adapter\Platform\PlatformInterface; use Zend\Db\Sql\Ddl\AlterTable; -use Zend\Db\Sql\Platform\PlatformDecoratorInterface; +use Zend\Db\Sql\Builder\PlatformDecoratorInterface; -class AlterTableDecorator extends AlterTable implements PlatformDecoratorInterface +class AlterTableBuilder extends AlterTable implements PlatformDecoratorInterface { /** * @var AlterTable diff --git a/src/Sql/Platform/Mysql/Ddl/CreateTableDecorator.php b/src/Sql/Builder/Mysql/Ddl/CreateTableBuilder.php similarity index 96% rename from src/Sql/Platform/Mysql/Ddl/CreateTableDecorator.php rename to src/Sql/Builder/Mysql/Ddl/CreateTableBuilder.php index b8f7df5f58..b3ef0a4301 100644 --- a/src/Sql/Platform/Mysql/Ddl/CreateTableDecorator.php +++ b/src/Sql/Builder/Mysql/Ddl/CreateTableBuilder.php @@ -7,13 +7,13 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace Zend\Db\Sql\Platform\Mysql\Ddl; +namespace Zend\Db\Sql\Builder\Mysql\Ddl; use Zend\Db\Adapter\Platform\PlatformInterface; use Zend\Db\Sql\Ddl\CreateTable; -use Zend\Db\Sql\Platform\PlatformDecoratorInterface; +use Zend\Db\Sql\Builder\PlatformDecoratorInterface; -class CreateTableDecorator extends CreateTable implements PlatformDecoratorInterface +class CreateTableBuilder extends CreateTable implements PlatformDecoratorInterface { /** * @var CreateTable diff --git a/src/Sql/Platform/Mysql/SelectDecorator.php b/src/Sql/Builder/Mysql/SelectBuilder.php similarity index 92% rename from src/Sql/Platform/Mysql/SelectDecorator.php rename to src/Sql/Builder/Mysql/SelectBuilder.php index 37f5b6cead..04ab66f55b 100644 --- a/src/Sql/Platform/Mysql/SelectDecorator.php +++ b/src/Sql/Builder/Mysql/SelectBuilder.php @@ -7,15 +7,15 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace Zend\Db\Sql\Platform\Mysql; +namespace Zend\Db\Sql\Builder\Mysql; use Zend\Db\Adapter\Driver\DriverInterface; use Zend\Db\Adapter\ParameterContainer; use Zend\Db\Adapter\Platform\PlatformInterface; -use Zend\Db\Sql\Platform\PlatformDecoratorInterface; +use Zend\Db\Sql\Builder\PlatformDecoratorInterface; use Zend\Db\Sql\Select; -class SelectDecorator extends Select implements PlatformDecoratorInterface +class SelectBuilder extends Select implements PlatformDecoratorInterface { /** * @var Select diff --git a/src/Sql/Platform/Oracle/SelectDecorator.php b/src/Sql/Builder/Oracle/SelectBuilder.php similarity index 96% rename from src/Sql/Platform/Oracle/SelectDecorator.php rename to src/Sql/Builder/Oracle/SelectBuilder.php index 9961b4dcf9..7949fb040d 100644 --- a/src/Sql/Platform/Oracle/SelectDecorator.php +++ b/src/Sql/Builder/Oracle/SelectBuilder.php @@ -7,15 +7,15 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace Zend\Db\Sql\Platform\Oracle; +namespace Zend\Db\Sql\Builder\Oracle; use Zend\Db\Adapter\Driver\DriverInterface; use Zend\Db\Adapter\ParameterContainer; use Zend\Db\Adapter\Platform\PlatformInterface; -use Zend\Db\Sql\Platform\PlatformDecoratorInterface; +use Zend\Db\Sql\Builder\PlatformDecoratorInterface; use Zend\Db\Sql\Select; -class SelectDecorator extends Select implements PlatformDecoratorInterface +class SelectBuilder extends Select implements PlatformDecoratorInterface { /** * @var Select diff --git a/src/Sql/Platform/PlatformDecoratorInterface.php b/src/Sql/Builder/PlatformDecoratorInterface.php similarity index 93% rename from src/Sql/Platform/PlatformDecoratorInterface.php rename to src/Sql/Builder/PlatformDecoratorInterface.php index f06c4340d2..8c66e4c39f 100644 --- a/src/Sql/Platform/PlatformDecoratorInterface.php +++ b/src/Sql/Builder/PlatformDecoratorInterface.php @@ -7,7 +7,7 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace Zend\Db\Sql\Platform; +namespace Zend\Db\Sql\Builder; interface PlatformDecoratorInterface { diff --git a/src/Sql/Platform/SqlServer/Ddl/CreateTableDecorator.php b/src/Sql/Builder/SqlServer/Ddl/CreateTableBuilder.php similarity index 84% rename from src/Sql/Platform/SqlServer/Ddl/CreateTableDecorator.php rename to src/Sql/Builder/SqlServer/Ddl/CreateTableBuilder.php index 9a72b2c7d6..0c8df0e70b 100644 --- a/src/Sql/Platform/SqlServer/Ddl/CreateTableDecorator.php +++ b/src/Sql/Builder/SqlServer/Ddl/CreateTableBuilder.php @@ -7,13 +7,13 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace Zend\Db\Sql\Platform\SqlServer\Ddl; +namespace Zend\Db\Sql\Builder\SqlServer\Ddl; use Zend\Db\Adapter\Platform\PlatformInterface; use Zend\Db\Sql\Ddl\CreateTable; -use Zend\Db\Sql\Platform\PlatformDecoratorInterface; +use Zend\Db\Sql\Builder\PlatformDecoratorInterface; -class CreateTableDecorator extends CreateTable implements PlatformDecoratorInterface +class CreateTableBuilder extends CreateTable implements PlatformDecoratorInterface { /** * @var CreateTable diff --git a/src/Sql/Platform/SqlServer/SelectDecorator.php b/src/Sql/Builder/SqlServer/SelectBuilder.php similarity index 96% rename from src/Sql/Platform/SqlServer/SelectDecorator.php rename to src/Sql/Builder/SqlServer/SelectBuilder.php index aef0540f0c..070dd9827d 100644 --- a/src/Sql/Platform/SqlServer/SelectDecorator.php +++ b/src/Sql/Builder/SqlServer/SelectBuilder.php @@ -7,15 +7,15 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace Zend\Db\Sql\Platform\SqlServer; +namespace Zend\Db\Sql\Builder\SqlServer; use Zend\Db\Adapter\Driver\DriverInterface; use Zend\Db\Adapter\ParameterContainer; use Zend\Db\Adapter\Platform\PlatformInterface; -use Zend\Db\Sql\Platform\PlatformDecoratorInterface; +use Zend\Db\Sql\Builder\PlatformDecoratorInterface; use Zend\Db\Sql\Select; -class SelectDecorator extends Select implements PlatformDecoratorInterface +class SelectBuilder extends Select implements PlatformDecoratorInterface { /** * @var Select diff --git a/src/Sql/Platform/Sqlite/SelectDecorator.php b/src/Sql/Builder/Sqlite/SelectBuilder.php similarity index 87% rename from src/Sql/Platform/Sqlite/SelectDecorator.php rename to src/Sql/Builder/Sqlite/SelectBuilder.php index e875dc740f..387d032abf 100644 --- a/src/Sql/Platform/Sqlite/SelectDecorator.php +++ b/src/Sql/Builder/Sqlite/SelectBuilder.php @@ -7,15 +7,15 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace Zend\Db\Sql\Platform\Sqlite; +namespace Zend\Db\Sql\Builder\Sqlite; use Zend\Db\Adapter\Driver\DriverInterface; use Zend\Db\Adapter\ParameterContainer; use Zend\Db\Adapter\Platform\PlatformInterface; -use Zend\Db\Sql\Platform\PlatformDecoratorInterface; +use Zend\Db\Sql\Builder\PlatformDecoratorInterface; use Zend\Db\Sql\Select; -class SelectDecorator extends Select implements PlatformDecoratorInterface +class SelectBuilder extends Select implements PlatformDecoratorInterface { /** * @var Select @@ -43,11 +43,11 @@ protected function localizeVariables() parent::localizeVariables(); $this->specifications[self::COMBINE] = '%1$s %2$s'; } - + /** * {@inheritDoc} */ - protected function processStatementStart(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) + protected function processStatementStart(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) { return ''; } diff --git a/src/Sql/Combine.php b/src/Sql/Combine.php index 5d9f96f040..3e540993e2 100644 --- a/src/Sql/Combine.php +++ b/src/Sql/Combine.php @@ -16,7 +16,7 @@ /** * Combine SQL statement - allows combining multiple select statements into one */ -class Combine extends AbstractPreparableSql +class Combine extends AbstractPreparableSqlObject { const COLUMNS = 'columns'; const COMBINE = 'combine'; diff --git a/src/Sql/Ddl/AlterTable.php b/src/Sql/Ddl/AlterTable.php index 3daba72eb8..381f35d677 100644 --- a/src/Sql/Ddl/AlterTable.php +++ b/src/Sql/Ddl/AlterTable.php @@ -10,9 +10,9 @@ namespace Zend\Db\Sql\Ddl; use Zend\Db\Adapter\Platform\PlatformInterface; -use Zend\Db\Sql\AbstractSql; +use Zend\Db\Sql\AbstractSqlObject; -class AlterTable extends AbstractSql implements SqlInterface +class AlterTable extends AbstractSqlObject implements SqlObjectInterface { const ADD_COLUMNS = 'addColumns'; const ADD_CONSTRAINTS = 'addConstraints'; diff --git a/src/Sql/Ddl/CreateTable.php b/src/Sql/Ddl/CreateTable.php index 12f94ab03b..e05e7905af 100644 --- a/src/Sql/Ddl/CreateTable.php +++ b/src/Sql/Ddl/CreateTable.php @@ -10,9 +10,9 @@ namespace Zend\Db\Sql\Ddl; use Zend\Db\Adapter\Platform\PlatformInterface; -use Zend\Db\Sql\AbstractSql; +use Zend\Db\Sql\AbstractSqlObject; -class CreateTable extends AbstractSql implements SqlInterface +class CreateTable extends AbstractSqlObject implements SqlObjectInterface { const COLUMNS = 'columns'; const CONSTRAINTS = 'constraints'; diff --git a/src/Sql/Ddl/DropTable.php b/src/Sql/Ddl/DropTable.php index ecf5e5f5db..970f72d69b 100644 --- a/src/Sql/Ddl/DropTable.php +++ b/src/Sql/Ddl/DropTable.php @@ -10,9 +10,9 @@ namespace Zend\Db\Sql\Ddl; use Zend\Db\Adapter\Platform\PlatformInterface; -use Zend\Db\Sql\AbstractSql; +use Zend\Db\Sql\AbstractSqlObject; -class DropTable extends AbstractSql implements SqlInterface +class DropTable extends AbstractSqlObject implements SqlObjectInterface { const TABLE = 'table'; diff --git a/src/Sql/Ddl/SqlInterface.php b/src/Sql/Ddl/SqlObjectInterface.php similarity index 73% rename from src/Sql/Ddl/SqlInterface.php rename to src/Sql/Ddl/SqlObjectInterface.php index 0f8660f452..d6d41b2155 100644 --- a/src/Sql/Ddl/SqlInterface.php +++ b/src/Sql/Ddl/SqlObjectInterface.php @@ -9,8 +9,8 @@ namespace Zend\Db\Sql\Ddl; -use Zend\Db\Sql\SqlInterface as BaseSqlInterface; +use Zend\Db\Sql\SqlObjectInterface as BaseSqlObjectInterface; -interface SqlInterface extends BaseSqlInterface +interface SqlObjectInterface extends BaseSqlObjectInterface { } diff --git a/src/Sql/Delete.php b/src/Sql/Delete.php index 6c81efd48b..9a6dbda2fc 100644 --- a/src/Sql/Delete.php +++ b/src/Sql/Delete.php @@ -17,7 +17,7 @@ * * @property Where $where */ -class Delete extends AbstractPreparableSql +class Delete extends AbstractPreparableSqlObject { /**@#+ * @const diff --git a/src/Sql/Insert.php b/src/Sql/Insert.php index 891f59906b..17d0f5cc5d 100644 --- a/src/Sql/Insert.php +++ b/src/Sql/Insert.php @@ -13,7 +13,7 @@ use Zend\Db\Adapter\ParameterContainer; use Zend\Db\Adapter\Platform\PlatformInterface; -class Insert extends AbstractPreparableSql +class Insert extends AbstractPreparableSqlObject { /**#@+ * Constants diff --git a/src/Sql/Platform/IbmDb2/IbmDb2.php b/src/Sql/Platform/IbmDb2/IbmDb2.php deleted file mode 100644 index 35ddc2c768..0000000000 --- a/src/Sql/Platform/IbmDb2/IbmDb2.php +++ /dev/null @@ -1,23 +0,0 @@ -setTypeDecorator('Zend\Db\Sql\Select', ($selectDecorator) ?: new SelectDecorator()); - } -} diff --git a/src/Sql/Platform/Mysql/Mysql.php b/src/Sql/Platform/Mysql/Mysql.php deleted file mode 100644 index 3e1611b87f..0000000000 --- a/src/Sql/Platform/Mysql/Mysql.php +++ /dev/null @@ -1,22 +0,0 @@ -setTypeDecorator('Zend\Db\Sql\Select', new SelectDecorator()); - $this->setTypeDecorator('Zend\Db\Sql\Ddl\CreateTable', new Ddl\CreateTableDecorator()); - $this->setTypeDecorator('Zend\Db\Sql\Ddl\AlterTable', new Ddl\AlterTableDecorator()); - } -} diff --git a/src/Sql/Platform/Oracle/Oracle.php b/src/Sql/Platform/Oracle/Oracle.php deleted file mode 100644 index bf1dc31df5..0000000000 --- a/src/Sql/Platform/Oracle/Oracle.php +++ /dev/null @@ -1,20 +0,0 @@ -setTypeDecorator('Zend\Db\Sql\Select', ($selectDecorator) ?: new SelectDecorator()); - } -} diff --git a/src/Sql/Platform/SqlServer/SqlServer.php b/src/Sql/Platform/SqlServer/SqlServer.php deleted file mode 100644 index 0dc383d0be..0000000000 --- a/src/Sql/Platform/SqlServer/SqlServer.php +++ /dev/null @@ -1,21 +0,0 @@ -setTypeDecorator('Zend\Db\Sql\Select', ($selectDecorator) ?: new SelectDecorator()); - $this->setTypeDecorator('Zend\Db\Sql\Ddl\CreateTable', new Ddl\CreateTableDecorator()); - } -} diff --git a/src/Sql/Platform/Sqlite/Sqlite.php b/src/Sql/Platform/Sqlite/Sqlite.php deleted file mode 100644 index 00712dded1..0000000000 --- a/src/Sql/Platform/Sqlite/Sqlite.php +++ /dev/null @@ -1,25 +0,0 @@ -setTypeDecorator('Zend\Db\Sql\Select', new SelectDecorator()); - } -} diff --git a/src/Sql/PreparableSqlInterface.php b/src/Sql/PreparableSqlObjectInterface.php similarity index 94% rename from src/Sql/PreparableSqlInterface.php rename to src/Sql/PreparableSqlObjectInterface.php index f937e07b7b..2be162ee83 100644 --- a/src/Sql/PreparableSqlInterface.php +++ b/src/Sql/PreparableSqlObjectInterface.php @@ -12,7 +12,7 @@ use Zend\Db\Adapter\AdapterInterface; use Zend\Db\Adapter\StatementContainerInterface; -interface PreparableSqlInterface +interface PreparableSqlObjectInterface { /** * @param AdapterInterface $adapter diff --git a/src/Sql/Select.php b/src/Sql/Select.php index b4aac3ad29..8a88122b90 100644 --- a/src/Sql/Select.php +++ b/src/Sql/Select.php @@ -18,7 +18,7 @@ * @property Where $where * @property Having $having */ -class Select extends AbstractPreparableSql +class Select extends AbstractPreparableSqlObject { /**#@+ * Constant diff --git a/src/Sql/Sql.php b/src/Sql/Sql.php index 053dfe72b7..346602c5da 100644 --- a/src/Sql/Sql.php +++ b/src/Sql/Sql.php @@ -29,13 +29,13 @@ class Sql * @param null|string|array|TableIdentifier $table * @param null|Platform\AbstractPlatform $sqlPlatform @deprecated since version 3.0 */ - public function __construct(AdapterInterface $adapter, $table = null, Platform\AbstractPlatform $sqlPlatform = null) + public function __construct(AdapterInterface $adapter, $table = null, Builder\AbstractBuilder $sqlPlatform = null) { $this->adapter = $adapter; if ($table) { $this->setTable($table); } - $this->sqlPlatform = $sqlPlatform ?: new Platform\Platform($adapter); + $this->sqlPlatform = $sqlPlatform ?: new Builder\Builder($adapter); } /** @@ -116,13 +116,13 @@ public function delete($table = null) } /** - * @param PreparableSqlInterface $sqlObject + * @param PreparableSqlObjectInterface $sqlObject * @param StatementInterface $statement * @param AdapterInterface $adapter * * @return StatementInterface */ - public function prepareStatementForSqlObject(PreparableSqlInterface $sqlObject, StatementInterface $statement = null, AdapterInterface $adapter = null) + public function prepareStatementForSqlObject(PreparableSqlObjectInterface $sqlObject, StatementInterface $statement = null, AdapterInterface $adapter = null) { $adapter = $adapter ?: $this->adapter; $statement = $statement ?: $adapter->getDriver()->createStatement(); @@ -133,28 +133,28 @@ public function prepareStatementForSqlObject(PreparableSqlInterface $sqlObject, /** * Get sql string using platform or sql object * - * @param SqlInterface $sqlObject + * @param SqlObjectInterface $sqlObject * @param PlatformInterface|null $platform * * @return string * * @deprecated Deprecated in 2.4. Use buildSqlString() instead */ - public function getSqlStringForSqlObject(SqlInterface $sqlObject, PlatformInterface $platform = null) + public function getSqlStringForSqlObject(SqlObjectInterface $sqlObject, PlatformInterface $platform = null) { $platform = ($platform) ?: $this->adapter->getPlatform(); return $this->sqlPlatform->setSubject($sqlObject)->getSqlString($platform); } /** - * @param SqlInterface $sqlObject - * @param AdapterInterface $adapter + * @param SqlObjectInterface $sqlObject + * @param AdapterInterface $adapter * * @return string * * @throws Exception\InvalidArgumentException */ - public function buildSqlString(SqlInterface $sqlObject, AdapterInterface $adapter = null) + public function buildSqlString(SqlObjectInterface $sqlObject, AdapterInterface $adapter = null) { return $this ->sqlPlatform diff --git a/src/Sql/SqlInterface.php b/src/Sql/SqlObjectInterface.php similarity index 95% rename from src/Sql/SqlInterface.php rename to src/Sql/SqlObjectInterface.php index 551a458c98..fb646a7638 100644 --- a/src/Sql/SqlInterface.php +++ b/src/Sql/SqlObjectInterface.php @@ -11,7 +11,7 @@ use Zend\Db\Adapter\Platform\PlatformInterface; -interface SqlInterface +interface SqlObjectInterface { /** * Get SQL string for statement diff --git a/src/Sql/Update.php b/src/Sql/Update.php index d88156b32e..ccec9c62b1 100644 --- a/src/Sql/Update.php +++ b/src/Sql/Update.php @@ -18,7 +18,7 @@ * * @property Where $where */ -class Update extends AbstractPreparableSql +class Update extends AbstractPreparableSqlObject { /**@#++ * @const diff --git a/test/Sql/AbstractSqlTest.php b/test/Sql/AbstractSqlObjectTest.php similarity index 94% rename from test/Sql/AbstractSqlTest.php rename to test/Sql/AbstractSqlObjectTest.php index c8ea320a77..12fa6d4488 100644 --- a/test/Sql/AbstractSqlTest.php +++ b/test/Sql/AbstractSqlObjectTest.php @@ -17,7 +17,7 @@ use ZendTest\Db\TestAsset\TrustingSql92Platform; use Zend\Db\Adapter\ParameterContainer; -class AbstractSqlTest extends \PHPUnit_Framework_TestCase +class AbstractSqlObjectTest extends \PHPUnit_Framework_TestCase { /** * @var \PHPUnit_Framework_MockObject_MockObject @@ -28,7 +28,7 @@ class AbstractSqlTest extends \PHPUnit_Framework_TestCase public function setup() { - $this->abstractSql = $this->getMockForAbstractClass('Zend\Db\Sql\AbstractSql'); + $this->abstractSql = $this->getMockForAbstractClass('Zend\Db\Sql\AbstractSqlObject'); $this->mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); $this->mockDriver @@ -44,7 +44,7 @@ public function setup() } /** - * @covers Zend\Db\Sql\AbstractSql::processExpression + * @covers Zend\Db\Sql\AbstractSqlObject::processExpression */ public function testProcessExpressionWithoutParameterContainer() { @@ -55,7 +55,7 @@ public function testProcessExpressionWithoutParameterContainer() } /** - * @covers Zend\Db\Sql\AbstractSql::processExpression + * @covers Zend\Db\Sql\AbstractSqlObject::processExpression */ public function testProcessExpressionWithParameterContainerAndParameterizationTypeNamed() { @@ -90,7 +90,7 @@ public function testProcessExpressionWithParameterContainerAndParameterizationTy } /** - * @covers Zend\Db\Sql\AbstractSql::processExpression + * @covers Zend\Db\Sql\AbstractSqlObject::processExpression */ public function testProcessExpressionWorksWithExpressionContainingStringParts() { @@ -103,7 +103,7 @@ public function testProcessExpressionWorksWithExpressionContainingStringParts() } /** - * @covers Zend\Db\Sql\AbstractSql::processExpression + * @covers Zend\Db\Sql\AbstractSqlObject::processExpression */ public function testProcessExpressionWorksWithExpressionContainingSelectObject() { diff --git a/test/Sql/SqlFunctionalTest.php b/test/Sql/Builder/AllBuildersTest.php similarity index 84% rename from test/Sql/SqlFunctionalTest.php rename to test/Sql/Builder/AllBuildersTest.php index 628ee74848..60b5da20a2 100644 --- a/test/Sql/SqlFunctionalTest.php +++ b/test/Sql/Builder/AllBuildersTest.php @@ -7,7 +7,7 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace ZendTest\Db\Sql; +namespace ZendTest\Db\Sql\Builder; use Zend\Db\Sql; use Zend\Db\Adapter; @@ -21,7 +21,7 @@ * @method \Zend\Db\Sql\Ddl\CreateTable createTable(null|string $table) * @method \Zend\Db\Sql\Ddl\Column\Column createColumn(null|string $name) */ -class SqlFunctionalTest extends \PHPUnit_Framework_TestCase +class AllBuildersTest extends \PHPUnit_Framework_TestCase { protected function dataProvider_CommonProcessMethods() { @@ -302,7 +302,7 @@ protected function dataProvider_CommonProcessMethods() ]; } - protected function dataProvider_Decorators() + protected function dataProvider_Builders() { return [ 'RootDecorators::Select' => [ @@ -310,163 +310,163 @@ protected function dataProvider_Decorators() 'expected' => [ 'sql92' => [ 'decorators' => [ - 'Zend\Db\Sql\Select' => new TestAsset\SelectDecorator, + 'Zend\Db\Sql\Select' => new TestAsset\SelectBuilder, ], 'string' => 'SELECT "foo".* FROM "foo" WHERE "x" = (SELECT "bar".* FROM "bar")', ], 'MySql' => [ 'decorators' => [ - 'Zend\Db\Sql\Select' => new TestAsset\SelectDecorator, + 'Zend\Db\Sql\Select' => new TestAsset\SelectBuilder, ], 'string' => 'SELECT `foo`.* FROM `foo` WHERE `x` = (SELECT `bar`.* FROM `bar`)', ], 'Oracle' => [ 'decorators' => [ - 'Zend\Db\Sql\Select' => new TestAsset\SelectDecorator, + 'Zend\Db\Sql\Select' => new TestAsset\SelectBuilder, ], 'string' => 'SELECT "foo".* FROM "foo" WHERE "x" = (SELECT "bar".* FROM "bar")', ], 'SqlServer' => [ 'decorators' => [ - 'Zend\Db\Sql\Select' => new TestAsset\SelectDecorator, + 'Zend\Db\Sql\Select' => new TestAsset\SelectBuilder, ], 'string' => 'SELECT [foo].* FROM [foo] WHERE [x] = (SELECT [bar].* FROM [bar])', ], ], ], /* TODO - should be implemeted - 'RootDecorators::Insert' => array( + 'RootDecorators::Insert' => [ 'sqlObject' => $this->insert('foo')->select($this->select()), - 'expected' => array( - 'sql92' => array( - 'decorators' => array( + 'expected' => [ + 'sql92' => [ + 'decorators' => [ 'Zend\Db\Sql\Insert' => new TestAsset\InsertDecorator, // Decorator for root sqlObject - 'Zend\Db\Sql\Select' => array('Zend\Db\Sql\Platform\Mysql\SelectDecorator', '{=SELECT_Sql92=}') - ), + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Mysql\SelectBuilder', '{=SELECT_Sql92=}'] + ], 'string' => 'INSERT INTO "foo" {=SELECT_Sql92=}', - ), - 'MySql' => array( - 'decorators' => array( + ], + 'MySql' => [ + 'decorators' => [ 'Zend\Db\Sql\Insert' => new TestAsset\InsertDecorator, // Decorator for root sqlObject - 'Zend\Db\Sql\Select' => array('Zend\Db\Sql\Platform\Mysql\SelectDecorator', '{=SELECT_MySql=}') - ), + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Mysql\SelectBuilder', '{=SELECT_MySql=}'] + ], 'string' => 'INSERT INTO `foo` {=SELECT_MySql=}', - ), - 'Oracle' => array( - 'decorators' => array( + ], + 'Oracle' => [ + 'decorators' => [ 'Zend\Db\Sql\Insert' => new TestAsset\InsertDecorator, // Decorator for root sqlObject - 'Zend\Db\Sql\Select' => array('Zend\Db\Sql\Platform\Oracle\SelectDecorator', '{=SELECT_Oracle=}') - ), + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Oracle\SelectBuilder', '{=SELECT_Oracle=}'] + ], 'string' => 'INSERT INTO "foo" {=SELECT_Oracle=}', - ), - 'SqlServer' => array( - 'decorators' => array( + ], + 'SqlServer' => [ + 'decorators' => [ 'Zend\Db\Sql\Insert' => new TestAsset\InsertDecorator, // Decorator for root sqlObject - 'Zend\Db\Sql\Select' => array('Zend\Db\Sql\Platform\SqlServer\SelectDecorator', '{=SELECT_SqlServer=}') - ), + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\SqlServer\SelectBuilder', '{=SELECT_SqlServer=}'] + ], 'string' => 'INSERT INTO [foo] {=SELECT_SqlServer=}', - ), - ), - ), - 'RootDecorators::Delete' => array( - 'sqlObject' => $this->delete('foo')->where(array('x'=>$this->select('foo'))), - 'expected' => array( - 'sql92' => array( - 'decorators' => array( + ], + ], + ], + 'RootDecorators::Delete' => [ + 'sqlObject' => $this->delete('foo')->where(['x'=>$this->select('foo')]), + 'expected' => [ + 'sql92' => [ + 'decorators' => [ 'Zend\Db\Sql\Delete' => new TestAsset\DeleteDecorator, - 'Zend\Db\Sql\Select' => array('Zend\Db\Sql\Platform\Mysql\SelectDecorator', '{=SELECT_Sql92=}') - ), + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Mysql\SelectBuilder', '{=SELECT_Sql92=}'] + ], 'string' => 'DELETE FROM "foo" WHERE "x" = ({=SELECT_Sql92=})', - ), - 'MySql' => array( - 'decorators' => array( + ], + 'MySql' => [ + 'decorators' => [ 'Zend\Db\Sql\Delete' => new TestAsset\DeleteDecorator, - 'Zend\Db\Sql\Select' => array('Zend\Db\Sql\Platform\Mysql\SelectDecorator', '{=SELECT_MySql=}') - ), + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Mysql\SelectBuilder', '{=SELECT_MySql=}'] + ], 'string' => 'DELETE FROM `foo` WHERE `x` = ({=SELECT_MySql=})', - ), - 'Oracle' => array( - 'decorators' => array( + ], + 'Oracle' => [ + 'decorators' => [ 'Zend\Db\Sql\Delete' => new TestAsset\DeleteDecorator, - 'Zend\Db\Sql\Select' => array('Zend\Db\Sql\Platform\Oracle\SelectDecorator', '{=SELECT_Oracle=}') - ), + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Oracle\SelectBuilder', '{=SELECT_Oracle=}'] + ], 'string' => 'DELETE FROM "foo" WHERE "x" = ({=SELECT_Oracle=})', - ), - 'SqlServer' => array( - 'decorators' => array( + ], + 'SqlServer' => [ + 'decorators' => [ 'Zend\Db\Sql\Delete' => new TestAsset\DeleteDecorator, - 'Zend\Db\Sql\Select' => array('Zend\Db\Sql\Platform\SqlServer\SelectDecorator', '{=SELECT_SqlServer=}') - ), + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\SqlServer\SelectBuilder', '{=SELECT_SqlServer=}'] + ], 'string' => 'DELETE FROM [foo] WHERE [x] = ({=SELECT_SqlServer=})', - ), - ), - ), - 'RootDecorators::Update' => array( - 'sqlObject' => $this->update('foo')->where(array('x'=>$this->select('foo'))), - 'expected' => array( - 'sql92' => array( - 'decorators' => array( + ], + ], + ], + 'RootDecorators::Update' => [ + 'sqlObject' => $this->update('foo')->where(['x'=>$this->select('foo')]), + 'expected' => [ + 'sql92' => [ + 'decorators' => [ 'Zend\Db\Sql\Update' => new TestAsset\UpdateDecorator, - 'Zend\Db\Sql\Select' => array('Zend\Db\Sql\Platform\Mysql\SelectDecorator', '{=SELECT_Sql92=}') - ), + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Mysql\SelectBuilder', '{=SELECT_Sql92=}'] + ], 'string' => 'UPDATE "foo" SET WHERE "x" = ({=SELECT_Sql92=})', - ), - 'MySql' => array( - 'decorators' => array( + ], + 'MySql' => [ + 'decorators' => [ 'Zend\Db\Sql\Update' => new TestAsset\UpdateDecorator, - 'Zend\Db\Sql\Select' => array('Zend\Db\Sql\Platform\Mysql\SelectDecorator', '{=SELECT_MySql=}') - ), + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Mysql\SelectBuilder', '{=SELECT_MySql=}'] + ], 'string' => 'UPDATE `foo` SET WHERE `x` = ({=SELECT_MySql=})', - ), - 'Oracle' => array( - 'decorators' => array( + ], + 'Oracle' => [ + 'decorators' => [ 'Zend\Db\Sql\Update' => new TestAsset\UpdateDecorator, - 'Zend\Db\Sql\Select' => array('Zend\Db\Sql\Platform\Oracle\SelectDecorator', '{=SELECT_Oracle=}') - ), + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Oracle\SelectBuilder', '{=SELECT_Oracle=}'] + ], 'string' => 'UPDATE "foo" SET WHERE "x" = ({=SELECT_Oracle=})', - ), - 'SqlServer' => array( - 'decorators' => array( + ], + 'SqlServer' => [ + 'decorators' => [ 'Zend\Db\Sql\Update' => new TestAsset\UpdateDecorator, - 'Zend\Db\Sql\Select' => array('Zend\Db\Sql\Platform\SqlServer\SelectDecorator', '{=SELECT_SqlServer=}') - ), + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\SqlServer\SelectBuilder', '{=SELECT_SqlServer=}'] + ], 'string' => 'UPDATE [foo] SET WHERE [x] = ({=SELECT_SqlServer=})', - ), - ), - ), - 'DecorableExpression()' => array( - 'sqlObject' => $this->update('foo')->where(array('x'=>new Sql\Expression('?', array($this->select('foo'))))), - 'expected' => array( - 'sql92' => array( - 'decorators' => array( + ], + ], + ], + 'DecorableExpression()' => [ + 'sqlObject' => $this->update('foo')->where(['x'=>new Sql\Expression('?', [$this->select('foo')])]), + 'expected' => [ + 'sql92' => [ + 'decorators' => [ 'Zend\Db\Sql\Expression' => new TestAsset\DecorableExpression, - 'Zend\Db\Sql\Select' => array('Zend\Db\Sql\Platform\Mysql\SelectDecorator', '{=SELECT_Sql92=}') - ), + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Mysql\SelectBuilder', '{=SELECT_Sql92=}'] + ], 'string' => 'UPDATE "foo" SET WHERE "x" = {decorate-({=SELECT_Sql92=})-decorate}', - ), - 'MySql' => array( - 'decorators' => array( + ], + 'MySql' => [ + 'decorators' => [ 'Zend\Db\Sql\Expression' => new TestAsset\DecorableExpression, - 'Zend\Db\Sql\Select' => array('Zend\Db\Sql\Platform\Mysql\SelectDecorator', '{=SELECT_MySql=}') - ), + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Mysql\SelectBuilder', '{=SELECT_MySql=}'] + ], 'string' => 'UPDATE `foo` SET WHERE `x` = {decorate-({=SELECT_MySql=})-decorate}', - ), - 'Oracle' => array( - 'decorators' => array( + ], + 'Oracle' => [ + 'decorators' => [ 'Zend\Db\Sql\Expression' => new TestAsset\DecorableExpression, - 'Zend\Db\Sql\Select' => array('Zend\Db\Sql\Platform\Oracle\SelectDecorator', '{=SELECT_Oracle=}') - ), + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Oracle\SelectBuilder', '{=SELECT_Oracle=}'] + ], 'string' => 'UPDATE "foo" SET WHERE "x" = {decorate-({=SELECT_Oracle=})-decorate}', - ), - 'SqlServer' => array( - 'decorators' => array( + ], + 'SqlServer' => [ + 'decorators' => [ 'Zend\Db\Sql\Expression' => new TestAsset\DecorableExpression, - 'Zend\Db\Sql\Select' => array('Zend\Db\Sql\Platform\SqlServer\SelectDecorator', '{=SELECT_SqlServer=}') - ), + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\SqlServer\SelectBuilder', '{=SELECT_SqlServer=}'] + ], 'string' => 'UPDATE [foo] SET WHERE [x] = {decorate-({=SELECT_SqlServer=})-decorate}', - ), - ), - ),*/ + ], + ], + ],*/ ]; } @@ -474,7 +474,7 @@ public function dataProvider() { $data = array_merge( $this->dataProvider_CommonProcessMethods(), - $this->dataProvider_Decorators() + $this->dataProvider_Builders() ); $res = []; @@ -528,7 +528,7 @@ protected function resolveDecorator($decorator) $decoratorMock->expects($this->any())->method('buildSqlString')->will($this->returnValue($decorator[1])); return $decoratorMock; } - if ($decorator instanceof Sql\Platform\PlatformDecoratorInterface) { + if ($decorator instanceof Sql\Builder\PlatformDecoratorInterface) { return $decorator; } return; diff --git a/test/Sql/Platform/PlatformTest.php b/test/Sql/Builder/BuilderTest.php similarity index 92% rename from test/Sql/Platform/PlatformTest.php rename to test/Sql/Builder/BuilderTest.php index 2f23ce2c3b..32d2608f81 100644 --- a/test/Sql/Platform/PlatformTest.php +++ b/test/Sql/Builder/BuilderTest.php @@ -7,20 +7,20 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace ZendTest\Db\Sql\Platform; +namespace ZendTest\Db\Sql\Builder; use ReflectionMethod; use Zend\Db\Adapter\StatementContainer; use ZendTest\Db\TestAsset; -use Zend\Db\Sql\Platform\Platform; +use Zend\Db\Sql\Builder\Builder; use Zend\Db\Adapter\Adapter; -class PlatformTest extends \PHPUnit_Framework_TestCase +class BuilderTest extends \PHPUnit_Framework_TestCase { public function testResolveDefaultPlatform() { $adapter = $this->resolveAdapter('sql92'); - $platform = new Platform($adapter); + $platform = new Builder($adapter); $reflectionMethod = new ReflectionMethod($platform, 'resolvePlatform'); @@ -31,7 +31,7 @@ public function testResolveDefaultPlatform() public function testResolvePlatformName() { - $platform = new Platform($this->resolveAdapter('sql92')); + $platform = new Builder($this->resolveAdapter('sql92')); $reflectionMethod = new ReflectionMethod($platform, 'resolvePlatformName'); @@ -53,7 +53,7 @@ public function testAbstractPlatformCrashesGracefullyOnMissingDefaultPlatform() $reflectionProperty->setAccessible(true); $reflectionProperty->setValue($adapter, null); - $platform = new Platform($adapter); + $platform = new Builder($adapter); $reflectionMethod = new ReflectionMethod($platform, 'resolvePlatform'); $reflectionMethod->setAccessible(true); @@ -73,7 +73,7 @@ public function testAbstractPlatformCrashesGracefullyOnMissingDefaultPlatformWit $reflectionProperty->setAccessible(true); $reflectionProperty->setValue($adapter, null); - $platform = new Platform($adapter); + $platform = new Builder($adapter); $reflectionMethod = new ReflectionMethod($platform, 'resolvePlatform'); $reflectionMethod->setAccessible(true); diff --git a/test/Sql/Platform/IbmDb2/SelectDecoratorTest.php b/test/Sql/Builder/IbmDb2/SelectBuilderTest.php similarity index 96% rename from test/Sql/Platform/IbmDb2/SelectDecoratorTest.php rename to test/Sql/Builder/IbmDb2/SelectBuilderTest.php index 4c9e939d06..730660f0e8 100644 --- a/test/Sql/Platform/IbmDb2/SelectDecoratorTest.php +++ b/test/Sql/Builder/IbmDb2/SelectBuilderTest.php @@ -7,16 +7,16 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace ZendTest\Db\Sql\Platform\IbmDb2; +namespace ZendTest\Db\Sql\Builder\IbmDb2; -use Zend\Db\Sql\Platform\IbmDb2\SelectDecorator; +use Zend\Db\Sql\Builder\IbmDb2\SelectBuilder; use Zend\Db\Sql\Select; use Zend\Db\Sql\Where; use Zend\Db\Adapter\ParameterContainer; use Zend\Db\Adapter\Platform\IbmDb2 as IbmDb2Platform; use Zend\Db\Sql\Expression; -class SelectDecoratorTest extends \PHPUnit_Framework_TestCase +class SelectBuilderTest extends \PHPUnit_Framework_TestCase { /** * @testdox integration test: Testing SelectDecorator will use Select to produce properly IBM Db2 dialect prepared sql @@ -45,7 +45,7 @@ public function testPrepareStatement(Select $select, $expectedPrepareSql, $expec $statement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($parameterContainer)); $statement->expects($this->once())->method('setSql')->with($expectedPrepareSql); - $selectDecorator = new SelectDecorator; + $selectDecorator = new SelectBuilder; $selectDecorator->setSubject($select); $selectDecorator->prepareStatement($adapter, $statement); @@ -63,7 +63,7 @@ public function testGetSqlString(Select $select, $ignored0, $ignored1, $expected $statement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); $statement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($parameterContainer)); - $selectDecorator = new SelectDecorator; + $selectDecorator = new SelectBuilder; $selectDecorator->setSubject($select); $this->assertEquals($expectedSql, @$selectDecorator->getSqlString(new IbmDb2Platform)); diff --git a/test/Sql/Platform/Mysql/Ddl/CreateTableDecoratorTest.php b/test/Sql/Builder/Mysql/Ddl/CreateTableBuilderTest.php similarity index 85% rename from test/Sql/Platform/Mysql/Ddl/CreateTableDecoratorTest.php rename to test/Sql/Builder/Mysql/Ddl/CreateTableBuilderTest.php index 2aabba1db9..01830baea8 100644 --- a/test/Sql/Platform/Mysql/Ddl/CreateTableDecoratorTest.php +++ b/test/Sql/Builder/Mysql/Ddl/CreateTableBuilderTest.php @@ -7,22 +7,22 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace ZendTest\Db\Sql\Platform\Mysql\Ddl; +namespace ZendTest\Db\Sql\Builder\Mysql\Ddl; use Zend\Db\Adapter\Platform\Mysql; use Zend\Db\Sql\Ddl\Column\Column; use Zend\Db\Sql\Ddl\Constraint\PrimaryKey; use Zend\Db\Sql\Ddl\CreateTable; -use Zend\Db\Sql\Platform\Mysql\Ddl\CreateTableDecorator; +use Zend\Db\Sql\Builder\Mysql\Ddl\CreateTableBuilder; -class CreateTableDecoratorTest extends \PHPUnit_Framework_TestCase +class CreateTableBuilderTest extends \PHPUnit_Framework_TestCase { /** * @covers Zend\Db\Sql\Platform\Mysql\Ddl\CreateTableDecorator::setSubject */ public function testSetSubject() { - $ctd = new CreateTableDecorator(); + $ctd = new CreateTableBuilder(); $ct = new CreateTable; $this->assertSame($ctd, $ctd->setSubject($ct)); } @@ -32,7 +32,7 @@ public function testSetSubject() */ public function testGetSqlString() { - $ctd = new CreateTableDecorator(); + $ctd = new CreateTableBuilder(); $ct = new CreateTable('foo'); $ctd->setSubject($ct); diff --git a/test/Sql/Platform/Mysql/SelectDecoratorTest.php b/test/Sql/Builder/Mysql/SelectBuilderTest.php similarity index 86% rename from test/Sql/Platform/Mysql/SelectDecoratorTest.php rename to test/Sql/Builder/Mysql/SelectBuilderTest.php index 6cc126d1c9..e44c08a656 100644 --- a/test/Sql/Platform/Mysql/SelectDecoratorTest.php +++ b/test/Sql/Builder/Mysql/SelectBuilderTest.php @@ -7,14 +7,14 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace ZendTest\Db\Sql\Platform\Mysql; +namespace ZendTest\Db\Sql\Builder\Mysql; -use Zend\Db\Sql\Platform\Mysql\SelectDecorator; +use Zend\Db\Sql\Builder\Mysql\SelectBuilder; use Zend\Db\Sql\Select; use Zend\Db\Adapter\ParameterContainer; use Zend\Db\Adapter\Platform\Mysql as MysqlPlatform; -class SelectDecoratorTest extends \PHPUnit_Framework_TestCase +class SelectBuilderTest extends \PHPUnit_Framework_TestCase { /** * @testdox integration test: Testing SelectDecorator will use Select an internal state to prepare a proper limit/offset sql statement @@ -44,7 +44,7 @@ public function testPrepareStatement(Select $select, $expectedSql, $expectedPara $statement->expects($this->once())->method('setSql')->with($expectedSql); - $selectDecorator = new SelectDecorator; + $selectDecorator = new SelectBuilder; $selectDecorator->setSubject($select); $selectDecorator->prepareStatement($adapter, $statement); @@ -52,10 +52,10 @@ public function testPrepareStatement(Select $select, $expectedSql, $expectedPara } /** - * @testdox integration test: Testing SelectDecorator will use Select an internal state to prepare a proper limit/offset sql statement - * @covers Zend\Db\Sql\Platform\Mysql\SelectDecorator::getSqlString - * @covers Zend\Db\Sql\Platform\Mysql\SelectDecorator::processLimit - * @covers Zend\Db\Sql\Platform\Mysql\SelectDecorator::processOffset + * @testdox integration test: Testing SelectBuilder will use Select an internal state to prepare a proper limit/offset sql statement + * @covers Zend\Db\Sql\Builder\Mysql\SelectBuilder::getSqlString + * @covers Zend\Db\Sql\Builder\Mysql\SelectBuilder::processLimit + * @covers Zend\Db\Sql\Builder\Mysql\SelectBuilder::processOffset * @dataProvider dataProvider */ public function testGetSqlString(Select $select, $ignore, $alsoIgnore, $expectedSql) @@ -64,7 +64,7 @@ public function testGetSqlString(Select $select, $ignore, $alsoIgnore, $expected $statement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); $statement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($parameterContainer)); - $selectDecorator = new SelectDecorator; + $selectDecorator = new SelectBuilder; $selectDecorator->setSubject($select); $this->assertEquals($expectedSql, $selectDecorator->getSqlString(new MysqlPlatform)); } diff --git a/test/Sql/Platform/Oracle/SelectDecoratorTest.php b/test/Sql/Builder/Oracle/SelectBuilderTest.php similarity index 88% rename from test/Sql/Platform/Oracle/SelectDecoratorTest.php rename to test/Sql/Builder/Oracle/SelectBuilderTest.php index 0123b22925..8e0feec1ef 100644 --- a/test/Sql/Platform/Oracle/SelectDecoratorTest.php +++ b/test/Sql/Builder/Oracle/SelectBuilderTest.php @@ -7,20 +7,20 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace ZendTest\Db\Sql\Platform\Oracle; +namespace ZendTest\Db\Sql\Builder\Oracle; -use Zend\Db\Sql\Platform\Oracle\SelectDecorator; +use Zend\Db\Sql\Builder\Oracle\SelectBuilder; use Zend\Db\Sql\Select; use Zend\Db\Adapter\ParameterContainer; use Zend\Db\Adapter\Platform\Oracle as OraclePlatform; -class SelectDecoratorTest extends \PHPUnit_Framework_TestCase +class SelectBuilderTest extends \PHPUnit_Framework_TestCase { //@codingStandardsIgnoreStart /** - * @testdox integration test: Testing SelectDecorator will use Select to produce properly Oracle dialect prepared sql - * @covers Zend\Db\Sql\Platform\SqlServer\SelectDecorator::prepareStatement - * @covers Zend\Db\Sql\Platform\SqlServer\SelectDecorator::processLimitOffset + * @testdox integration test: Testing SelectBuilder will use Select to produce properly Oracle dialect prepared sql + * @covers Zend\Db\Sql\Platform\SqlServer\SelectBuilder::prepareStatement + * @covers Zend\Db\Sql\Platform\SqlServer\SelectBuilder::processLimitOffset * @dataProvider dataProvider */ //@codingStandardsIgnoreEnd @@ -54,7 +54,7 @@ public function testPrepareStatement( $statement->expects($this->once())->method('setSql')->with($expectedSql); - $selectDecorator = new SelectDecorator; + $selectDecorator = new SelectBuilder; $selectDecorator->setSubject($select); $selectDecorator->prepareStatement($adapter, $statement); @@ -63,8 +63,8 @@ public function testPrepareStatement( // @codingStandardsIgnoreStart /** - * @testdox integration test: Testing SelectDecorator will use Select to produce properly Oracle dialect sql statements - * @covers Zend\Db\Sql\Platform\Oracle\SelectDecorator::getSqlString + * @testdox integration test: Testing SelectBuilder will use Select to produce properly Oracle dialect sql statements + * @covers Zend\Db\Sql\Platform\Oracle\SelectBuilder::getSqlString * @dataProvider dataProvider */ // @codingStandardsIgnoreEnd @@ -76,7 +76,7 @@ public function testGetSqlString(Select $select, $ignored, $alsoIgnored, $expect ->method('getParameterContainer') ->will($this->returnValue($parameterContainer)); - $selectDecorator = new SelectDecorator; + $selectDecorator = new SelectBuilder; $selectDecorator->setSubject($select); $this->assertEquals($expectedSql, $selectDecorator->getSqlString(new OraclePlatform)); } diff --git a/test/Sql/Platform/SqlServer/Ddl/CreateTableDecoratorTest.php b/test/Sql/Builder/SqlServer/Ddl/CreateTableBuilderTest.php similarity index 79% rename from test/Sql/Platform/SqlServer/Ddl/CreateTableDecoratorTest.php rename to test/Sql/Builder/SqlServer/Ddl/CreateTableBuilderTest.php index 7077f8ff33..31e0c7fe1d 100644 --- a/test/Sql/Platform/SqlServer/Ddl/CreateTableDecoratorTest.php +++ b/test/Sql/Builder/SqlServer/Ddl/CreateTableBuilderTest.php @@ -7,20 +7,20 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace ZendTest\Db\Sql\Platform\SqlServer\Ddl; +namespace ZendTest\Db\Sql\Builder\SqlServer\Ddl; use Zend\Db\Sql\Ddl\CreateTable; -use Zend\Db\Sql\Platform\SqlServer\Ddl\CreateTableDecorator; +use Zend\Db\Sql\Builder\SqlServer\Ddl\CreateTableBuilder; use Zend\Db\Sql\Ddl\Column\Column; -class CreateTableDecoratorTest extends \PHPUnit_Framework_TestCase +class CreateTableBuilderTest extends \PHPUnit_Framework_TestCase { /** - * @covers Zend\Db\Sql\Platform\SqlServer\Ddl\CreateTableDecorator::getSqlString + * @covers Zend\Db\Sql\Platform\SqlServer\Ddl\CreateTableBuilder::getSqlString */ public function testGetSqlString() { - $ctd = new CreateTableDecorator(); + $ctd = new CreateTableBuilder(); $ct = new CreateTable('foo'); $this->assertEquals("CREATE TABLE \"foo\" ( \n)", $ctd->setSubject($ct)->getSqlString()); diff --git a/test/Sql/Platform/SqlServer/SelectDecoratorTest.php b/test/Sql/Builder/SqlServer/SelectBuilderTest.php similarity index 88% rename from test/Sql/Platform/SqlServer/SelectDecoratorTest.php rename to test/Sql/Builder/SqlServer/SelectBuilderTest.php index 6b1d27a89c..a453de3a7d 100644 --- a/test/Sql/Platform/SqlServer/SelectDecoratorTest.php +++ b/test/Sql/Builder/SqlServer/SelectBuilderTest.php @@ -7,20 +7,20 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace ZendTest\Db\Sql\Platform\SqlServer; +namespace ZendTest\Db\Sql\Builder\SqlServer; use Zend\Db\Sql\Expression; -use Zend\Db\Sql\Platform\SqlServer\SelectDecorator; +use Zend\Db\Sql\Builder\SqlServer\SelectBuilder; use Zend\Db\Sql\Select; use Zend\Db\Adapter\ParameterContainer; use Zend\Db\Adapter\Platform\SqlServer as SqlServerPlatform; -class SelectDecoratorTest extends \PHPUnit_Framework_TestCase +class SelectBuilderTest extends \PHPUnit_Framework_TestCase { /** - * @testdox integration test: Testing SelectDecorator will use Select an internal state to prepare a proper limit/offset sql statement - * @covers Zend\Db\Sql\Platform\SqlServer\SelectDecorator::prepareStatement - * @covers Zend\Db\Sql\Platform\SqlServer\SelectDecorator::processLimitOffset + * @testdox integration test: Testing SelectBuilder will use Select an internal state to prepare a proper limit/offset sql statement + * @covers Zend\Db\Sql\Platform\SqlServer\SelectBuilder::prepareStatement + * @covers Zend\Db\Sql\Platform\SqlServer\SelectBuilder::processLimitOffset * @dataProvider dataProvider */ public function testPrepareStatement(Select $select, $expectedSql, $expectedParams, $notUsed, $expectedFormatParamCount) @@ -44,7 +44,7 @@ public function testPrepareStatement(Select $select, $expectedSql, $expectedPara $statement->expects($this->once())->method('setSql')->with($expectedSql); - $selectDecorator = new SelectDecorator; + $selectDecorator = new SelectBuilder; $selectDecorator->setSubject($select); $selectDecorator->prepareStatement($adapter, $statement); @@ -52,9 +52,9 @@ public function testPrepareStatement(Select $select, $expectedSql, $expectedPara } /** - * @testdox integration test: Testing SelectDecorator will use Select an internal state to prepare a proper limit/offset sql statement - * @covers Zend\Db\Sql\Platform\SqlServer\SelectDecorator::getSqlString - * @covers Zend\Db\Sql\Platform\SqlServer\SelectDecorator::processLimitOffset + * @testdox integration test: Testing SelectBuilder will use Select an internal state to prepare a proper limit/offset sql statement + * @covers Zend\Db\Sql\Platform\SqlServer\SelectBuilder::getSqlString + * @covers Zend\Db\Sql\Platform\SqlServer\SelectBuilder::processLimitOffset * @dataProvider dataProvider */ public function testGetSqlString(Select $select, $ignored, $alsoIgnored, $expectedSql) @@ -63,7 +63,7 @@ public function testGetSqlString(Select $select, $ignored, $alsoIgnored, $expect $statement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); $statement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($parameterContainer)); - $selectDecorator = new SelectDecorator; + $selectDecorator = new SelectBuilder; $selectDecorator->setSubject($select); $this->assertEquals($expectedSql, $selectDecorator->getSqlString(new SqlServerPlatform)); } diff --git a/test/Sql/Platform/Sqlite/SelectDecoratorTest.php b/test/Sql/Builder/Sqlite/SelectBuilderTest.php similarity index 93% rename from test/Sql/Platform/Sqlite/SelectDecoratorTest.php rename to test/Sql/Builder/Sqlite/SelectBuilderTest.php index d2620f1261..9485c4654a 100644 --- a/test/Sql/Platform/Sqlite/SelectDecoratorTest.php +++ b/test/Sql/Builder/Sqlite/SelectBuilderTest.php @@ -7,14 +7,14 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace ZendTest\Db\Sql\Platform\Sqlite; +namespace ZendTest\Db\Sql\Builder\Sqlite; -use Zend\Db\Sql\Platform\Sqlite\SelectDecorator; +use Zend\Db\Sql\Builder\Sqlite\SelectBuilder; use Zend\Db\Sql\Select; use Zend\Db\Adapter\ParameterContainer; use Zend\Db\Adapter\Platform\Sqlite as SqlitePlatform; -class SelectDecoratorTest extends \PHPUnit_Framework_TestCase +class SelectBuilderTest extends \PHPUnit_Framework_TestCase { /** * @testdox integration test: Testing SelectDecorator will use Select an internal state to prepare a proper combine @@ -44,7 +44,7 @@ public function testPrepareStatementPreparesUnionSyntaxFromCombine(Select $selec $statement->expects($this->once())->method('setSql')->with($expectedSql); - $selectDecorator = new SelectDecorator; + $selectDecorator = new SelectBuilder; $selectDecorator->setSubject($select); $selectDecorator->prepareStatement($adapter, $statement); @@ -64,7 +64,7 @@ public function testGetSqlStringPreparesUnionSyntaxFromCombine(Select $select, $ $statement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); $statement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($parameterContainer)); - $selectDecorator = new SelectDecorator; + $selectDecorator = new SelectBuilder; $selectDecorator->setSubject($select); $this->assertEquals($expectedSql, $selectDecorator->getSqlString(new SqlitePlatform)); } diff --git a/test/Sql/Platform/Mysql/MysqlTest.php b/test/Sql/Platform/Mysql/MysqlTest.php deleted file mode 100644 index 726138a886..0000000000 --- a/test/Sql/Platform/Mysql/MysqlTest.php +++ /dev/null @@ -1,29 +0,0 @@ -getDecorators(); - - list($type, $decorator) = each($decorators); - $this->assertEquals('Zend\Db\Sql\Select', $type); - $this->assertInstanceOf('Zend\Db\Sql\Platform\Mysql\SelectDecorator', $decorator); - } -} diff --git a/test/Sql/Platform/Oracle/OracleTest.php b/test/Sql/Platform/Oracle/OracleTest.php deleted file mode 100644 index 9d2acda98b..0000000000 --- a/test/Sql/Platform/Oracle/OracleTest.php +++ /dev/null @@ -1,29 +0,0 @@ -getDecorators(); - - list($type, $decorator) = each($decorators); - $this->assertEquals('Zend\Db\Sql\Select', $type); - $this->assertInstanceOf('Zend\Db\Sql\Platform\Oracle\SelectDecorator', $decorator); - } -} diff --git a/test/Sql/Platform/SqlServer/SqlServerTest.php b/test/Sql/Platform/SqlServer/SqlServerTest.php deleted file mode 100644 index 081f21723f..0000000000 --- a/test/Sql/Platform/SqlServer/SqlServerTest.php +++ /dev/null @@ -1,29 +0,0 @@ -getDecorators(); - - list($type, $decorator) = each($decorators); - $this->assertEquals('Zend\Db\Sql\Select', $type); - $this->assertInstanceOf('Zend\Db\Sql\Platform\SqlServer\SelectDecorator', $decorator); - } -} diff --git a/test/Sql/Platform/Sqlite/SqliteTest.php b/test/Sql/Platform/Sqlite/SqliteTest.php deleted file mode 100644 index ea2aac1e72..0000000000 --- a/test/Sql/Platform/Sqlite/SqliteTest.php +++ /dev/null @@ -1,29 +0,0 @@ -getDecorators(); - - list($type, $decorator) = each($decorators); - $this->assertEquals('Zend\Db\Sql\Select', $type); - $this->assertInstanceOf('Zend\Db\Sql\Platform\Sqlite\SelectDecorator', $decorator); - } -} diff --git a/test/TestAsset/DeleteDecorator.php b/test/TestAsset/DeleteBuilder.php similarity index 84% rename from test/TestAsset/DeleteDecorator.php rename to test/TestAsset/DeleteBuilder.php index 13f21def41..f146fe8b2c 100644 --- a/test/TestAsset/DeleteDecorator.php +++ b/test/TestAsset/DeleteBuilder.php @@ -11,7 +11,7 @@ use Zend\Db\Sql; -class DeleteDecorator extends Sql\Delete implements Sql\Platform\PlatformDecoratorInterface +class DeleteBuilder extends Sql\Delete implements Sql\Builder\PlatformDecoratorInterface { protected $subject = null; diff --git a/test/TestAsset/InsertDecorator.php b/test/TestAsset/InsertBuilder.php similarity index 84% rename from test/TestAsset/InsertDecorator.php rename to test/TestAsset/InsertBuilder.php index 7a97ecfa1c..cb7b20b015 100644 --- a/test/TestAsset/InsertDecorator.php +++ b/test/TestAsset/InsertBuilder.php @@ -11,7 +11,7 @@ use Zend\Db\Sql; -class InsertDecorator extends Sql\Insert implements Sql\Platform\PlatformDecoratorInterface +class InsertBuilder extends Sql\Insert implements Sql\Builder\PlatformDecoratorInterface { protected $subject = null; diff --git a/test/TestAsset/UpdateDecorator.php b/test/TestAsset/SelectBuilder.php similarity index 84% rename from test/TestAsset/UpdateDecorator.php rename to test/TestAsset/SelectBuilder.php index 71cc3e6fc1..7430f6736e 100644 --- a/test/TestAsset/UpdateDecorator.php +++ b/test/TestAsset/SelectBuilder.php @@ -11,7 +11,7 @@ use Zend\Db\Sql; -class UpdateDecorator extends Sql\Update implements Sql\Platform\PlatformDecoratorInterface +class SelectBuilder extends Sql\Select implements Sql\Builder\PlatformDecoratorInterface { protected $subject = null; diff --git a/test/TestAsset/SelectDecorator.php b/test/TestAsset/UpdateBuilder.php similarity index 84% rename from test/TestAsset/SelectDecorator.php rename to test/TestAsset/UpdateBuilder.php index bca1dcb7e1..bcfd4c4967 100644 --- a/test/TestAsset/SelectDecorator.php +++ b/test/TestAsset/UpdateBuilder.php @@ -11,7 +11,7 @@ use Zend\Db\Sql; -class SelectDecorator extends Sql\Select implements Sql\Platform\PlatformDecoratorInterface +class UpdateBuilder extends Sql\Update implements Sql\Builder\PlatformDecoratorInterface { protected $subject = null; From fc7fc46f4413d7add7d16435b67eea95211926a4 Mon Sep 17 00:00:00 2001 From: turrsis Date: Thu, 9 Jul 2015 15:21:30 +0300 Subject: [PATCH 03/30] architecture 02: create SqlObject builders --- src/Sql/AbstractPreparableSqlObject.php | 39 - src/Sql/AbstractSqlObject.php | 442 +----- src/Sql/Builder/AbstractBuilder.php | 95 +- src/Sql/Builder/AbstractSqlBuilder.php | 313 ++++ src/Sql/Builder/Builder.php | 261 ++-- src/Sql/Builder/Context.php | 95 ++ src/Sql/Builder/IbmDb2/SelectBuilder.php | 141 +- .../Builder/Mysql/Ddl/AlterTableBuilder.php | 41 +- .../Builder/Mysql/Ddl/CreateTableBuilder.php | 34 +- src/Sql/Builder/Mysql/SelectBuilder.php | 68 +- src/Sql/Builder/Oracle/SelectBuilder.php | 143 +- .../SqlServer/Ddl/CreateTableBuilder.php | 30 +- src/Sql/Builder/SqlServer/SelectBuilder.php | 85 +- src/Sql/Builder/Sqlite/SelectBuilder.php | 62 - src/Sql/Builder/sql92/CombineBuilder.php | 49 + .../Builder/sql92/Ddl/AlterTableBuilder.php | 141 ++ .../Builder/sql92/Ddl/CreateTableBuilder.php | 114 ++ .../Builder/sql92/Ddl/DropTableBuilder.php | 33 + src/Sql/Builder/sql92/DeleteBuilder.php | 56 + src/Sql/Builder/sql92/InsertBuilder.php | 87 ++ src/Sql/Builder/sql92/SelectBuilder.php | 367 +++++ src/Sql/Builder/sql92/UpdateBuilder.php | 89 ++ src/Sql/Combine.php | 95 +- src/Sql/Ddl/AlterTable.php | 136 +- src/Sql/Ddl/CreateTable.php | 126 +- src/Sql/Ddl/DropTable.php | 25 +- src/Sql/Delete.php | 106 +- src/Sql/Insert.php | 180 +-- src/Sql/Predicate/In.php | 9 +- src/Sql/PreparableSqlObjectInterface.php | 12 +- src/Sql/Select.php | 479 +----- ...rInterface.php => SelectableInterface.php} | 10 +- src/Sql/Sql.php | 62 +- src/Sql/SqlObjectInterface.php | 10 - src/Sql/Update.php | 121 +- src/TableGateway/AbstractTableGateway.php | 39 +- .../Feature/MasterSlaveFeature.php | 2 +- src/TableGateway/Feature/SequenceFeature.php | 4 +- test/RowGateway/AbstractRowGatewayTest.php | 5 +- test/Sql/AbstractSqlObjectTest.php | 186 --- test/Sql/Builder/AbstractTestCase.php | 268 ++++ test/Sql/Builder/AllBuildersTest.php | 258 ++-- test/Sql/Builder/BuilderTest.php | 192 ++- test/Sql/Builder/CombineBuilderTest.php | 121 ++ .../Sql/Builder/Ddl/AlterTableBuilderTest.php | 48 + .../Builder/Ddl/CreateTableBuilderTest.php | 136 ++ test/Sql/Builder/Ddl/DropTableBuilderTest.php | 36 + test/Sql/Builder/DeleteBuilderTest.php | 48 + test/Sql/Builder/IbmDb2/SelectBuilderTest.php | 120 -- test/Sql/Builder/InsertBuilderTest.php | 138 ++ .../Mysql/Ddl/CreateTableBuilderTest.php | 54 - test/Sql/Builder/Mysql/SelectBuilderTest.php | 100 -- test/Sql/Builder/Oracle/SelectBuilderTest.php | 144 -- test/Sql/Builder/SelectBuilderTest.php | 861 +++++++++++ .../SqlServer/Ddl/CreateTableBuilderTest.php | 39 - .../Builder/SqlServer/SelectBuilderTest.php | 116 -- test/Sql/Builder/Sqlite/SelectBuilderTest.php | 92 -- test/Sql/Builder/UpdateBuilderTest.php | 99 ++ test/Sql/CombineTest.php | 139 +- test/Sql/Ddl/AlterTableTest.php | 44 +- test/Sql/Ddl/CreateTableTest.php | 52 +- test/Sql/Ddl/DropTableTest.php | 9 +- test/Sql/DeleteTest.php | 189 +-- test/Sql/InsertTest.php | 290 +--- test/Sql/Predicate/InTest.php | 10 + test/Sql/Predicate/PredicateTest.php | 125 ++ test/Sql/SelectTest.php | 1296 +---------------- test/Sql/SqlTest.php | 91 +- test/Sql/UpdateTest.php | 263 +--- .../TableGateway/AbstractTableGatewayTest.php | 145 +- .../Feature/MasterSlaveFeatureTest.php | 10 +- test/TableGateway/TableGatewayTest.php | 15 +- test/TestAsset/DeleteBuilder.php | 11 +- test/TestAsset/InsertBuilder.php | 11 +- test/TestAsset/SelectBuilder.php | 11 +- test/TestAsset/TrustingIbmDb2Platform.php | 20 + test/TestAsset/TrustingSqlitePlatform.php | 23 + test/TestAsset/UpdateBuilder.php | 11 +- 78 files changed, 4233 insertions(+), 5794 deletions(-) delete mode 100644 src/Sql/AbstractPreparableSqlObject.php create mode 100644 src/Sql/Builder/AbstractSqlBuilder.php create mode 100644 src/Sql/Builder/Context.php delete mode 100644 src/Sql/Builder/Sqlite/SelectBuilder.php create mode 100644 src/Sql/Builder/sql92/CombineBuilder.php create mode 100644 src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php create mode 100644 src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php create mode 100644 src/Sql/Builder/sql92/Ddl/DropTableBuilder.php create mode 100644 src/Sql/Builder/sql92/DeleteBuilder.php create mode 100644 src/Sql/Builder/sql92/InsertBuilder.php create mode 100644 src/Sql/Builder/sql92/SelectBuilder.php create mode 100644 src/Sql/Builder/sql92/UpdateBuilder.php rename src/Sql/{Builder/PlatformDecoratorInterface.php => SelectableInterface.php} (64%) delete mode 100644 test/Sql/AbstractSqlObjectTest.php create mode 100644 test/Sql/Builder/AbstractTestCase.php create mode 100644 test/Sql/Builder/CombineBuilderTest.php create mode 100644 test/Sql/Builder/Ddl/AlterTableBuilderTest.php create mode 100644 test/Sql/Builder/Ddl/CreateTableBuilderTest.php create mode 100644 test/Sql/Builder/Ddl/DropTableBuilderTest.php create mode 100644 test/Sql/Builder/DeleteBuilderTest.php delete mode 100644 test/Sql/Builder/IbmDb2/SelectBuilderTest.php create mode 100644 test/Sql/Builder/InsertBuilderTest.php delete mode 100644 test/Sql/Builder/Mysql/Ddl/CreateTableBuilderTest.php delete mode 100644 test/Sql/Builder/Mysql/SelectBuilderTest.php delete mode 100644 test/Sql/Builder/Oracle/SelectBuilderTest.php create mode 100644 test/Sql/Builder/SelectBuilderTest.php delete mode 100644 test/Sql/Builder/SqlServer/Ddl/CreateTableBuilderTest.php delete mode 100644 test/Sql/Builder/SqlServer/SelectBuilderTest.php delete mode 100644 test/Sql/Builder/Sqlite/SelectBuilderTest.php create mode 100644 test/Sql/Builder/UpdateBuilderTest.php create mode 100644 test/TestAsset/TrustingIbmDb2Platform.php create mode 100644 test/TestAsset/TrustingSqlitePlatform.php diff --git a/src/Sql/AbstractPreparableSqlObject.php b/src/Sql/AbstractPreparableSqlObject.php deleted file mode 100644 index 63842bc9df..0000000000 --- a/src/Sql/AbstractPreparableSqlObject.php +++ /dev/null @@ -1,39 +0,0 @@ -getParameterContainer(); - - if (! $parameterContainer instanceof ParameterContainer) { - $parameterContainer = new ParameterContainer(); - - $statementContainer->setParameterContainer($parameterContainer); - } - - $statementContainer->setSql( - $this->buildSqlString($adapter->getPlatform(), $adapter->getDriver(), $parameterContainer) - ); - - return $statementContainer; - } -} diff --git a/src/Sql/AbstractSqlObject.php b/src/Sql/AbstractSqlObject.php index 64a2fb414e..69c0742e53 100644 --- a/src/Sql/AbstractSqlObject.php +++ b/src/Sql/AbstractSqlObject.php @@ -9,448 +9,22 @@ namespace Zend\Db\Sql; -use Zend\Db\Adapter\Driver\DriverInterface; -use Zend\Db\Adapter\ParameterContainer; -use Zend\Db\Adapter\Platform\PlatformInterface; -use Zend\Db\Sql\Builder\PlatformDecoratorInterface; -use Zend\Db\Adapter\Platform\Sql92 as DefaultAdapterPlatform; - abstract class AbstractSqlObject implements SqlObjectInterface { - /** - * Specifications for Sql String generation - * - * @var string[]|array[] - */ - protected $specifications = []; - - /** - * @var string - */ - protected $processInfo = ['paramPrefix' => '', 'subselectCount' => 0]; - - /** - * @var array - */ - protected $instanceParameterIndex = []; - - /** - * {@inheritDoc} - */ - public function getSqlString(PlatformInterface $adapterPlatform = null) - { - $adapterPlatform = ($adapterPlatform) ?: new DefaultAdapterPlatform; - return $this->buildSqlString($adapterPlatform); - } - - /** - * @param PlatformInterface $platform - * @param null|DriverInterface $driver - * @param null|ParameterContainer $parameterContainer - * @return string - */ - protected function buildSqlString( - PlatformInterface $platform, - DriverInterface $driver = null, - ParameterContainer $parameterContainer = null - ) { - $this->localizeVariables(); - - $sqls = []; - $parameters = []; - - foreach ($this->specifications as $name => $specification) { - $parameters[$name] = $this->{'process' . $name}( - $platform, - $driver, - $parameterContainer, - $sqls, - $parameters - ); + protected $__getProperties = []; - if ($specification && is_array($parameters[$name])) { - $sqls[$name] = $this->createSqlFromSpecificationAndParameters($specification, $parameters[$name]); - - continue; - } - - if (is_string($parameters[$name])) { - $sqls[$name] = $parameters[$name]; - } - } - - return rtrim(implode(' ', $sqls), "\n ,"); - } - - /** - * Render table with alias in from/join parts - * - * @todo move TableIdentifier concatination here - * @param string $table - * @param string $alias - * @return string - */ - protected function renderTable($table, $alias = null) + public function __construct() { - return $table . ($alias ? ' AS ' . $alias : ''); - } - - /** - * @staticvar int $runtimeExpressionPrefix - * @param ExpressionInterface $expression - * @param PlatformInterface $platform - * @param null|DriverInterface $driver - * @param null|ParameterContainer $parameterContainer - * @param null|string $namedParameterPrefix - * @return string - * @throws Exception\RuntimeException - */ - protected function processExpression( - ExpressionInterface $expression, - PlatformInterface $platform, - DriverInterface $driver = null, - ParameterContainer $parameterContainer = null, - $namedParameterPrefix = null - ) { - $namedParameterPrefix = ! $namedParameterPrefix - ? $namedParameterPrefix - : $this->processInfo['paramPrefix'] . $namedParameterPrefix; - // static counter for the number of times this method was invoked across the PHP runtime - static $runtimeExpressionPrefix = 0; - - if ($parameterContainer && ((!is_string($namedParameterPrefix) || $namedParameterPrefix == ''))) { - $namedParameterPrefix = sprintf('expr%04dParam', ++$runtimeExpressionPrefix); - } else { - $namedParameterPrefix = preg_replace('/\s/', '__', $namedParameterPrefix); - } - - $sql = ''; - - // initialize variables - $parts = $expression->getExpressionData(); - - if (! isset($this->instanceParameterIndex[$namedParameterPrefix])) { - $this->instanceParameterIndex[$namedParameterPrefix] = 1; - } - - $expressionParamIndex = &$this->instanceParameterIndex[$namedParameterPrefix]; - - foreach ($parts as $part) { - // #7407: use $expression->getExpression() to get the unescaped - // version of the expression - if (is_string($part) && $expression instanceof Expression) { - $sql .= $expression->getExpression(); - continue; - } - - // If it is a string, simply tack it onto the return sql - // "specification" string - if (is_string($part)) { - $sql .= $part; - continue; - } - - if (! is_array($part)) { - throw new Exception\RuntimeException( - 'Elements returned from getExpressionData() array must be a string or array.' - ); - } - - // Process values and types (the middle and last position of the - // expression data) - $values = $part[1]; - $types = isset($part[2]) ? $part[2] : []; - foreach ($values as $vIndex => $value) { - if (!isset($types[$vIndex])) { - continue; - } - $type = $types[$vIndex]; - if ($value instanceof Select) { - // process sub-select - $values[$vIndex] = '(' - . $this->processSubSelect($value, $platform, $driver, $parameterContainer) - . ')'; - } elseif ($value instanceof ExpressionInterface) { - // recursive call to satisfy nested expressions - $values[$vIndex] = $this->processExpression( - $value, - $platform, - $driver, - $parameterContainer, - $namedParameterPrefix . $vIndex . 'subpart' - ); - } elseif ($type == ExpressionInterface::TYPE_IDENTIFIER) { - $values[$vIndex] = $platform->quoteIdentifierInFragment($value); - } elseif ($type == ExpressionInterface::TYPE_VALUE) { - // if prepareType is set, it means that this particular value must be - // passed back to the statement in a way it can be used as a placeholder value - if ($parameterContainer) { - $name = $namedParameterPrefix . $expressionParamIndex++; - $parameterContainer->offsetSet($name, $value); - $values[$vIndex] = $driver->formatParameterName($name); - continue; - } - - // if not a preparable statement, simply quote the value and move on - $values[$vIndex] = $platform->quoteValue($value); - } elseif ($type == ExpressionInterface::TYPE_LITERAL) { - $values[$vIndex] = $value; - } - } - - // After looping the values, interpolate them into the sql string - // (they might be placeholder names, or values) - $sql .= vsprintf($part[0], $values); - } - - return $sql; + $this->__getProperties = array_flip($this->__getProperties); } - /** - * @param string|array $specifications - * @param array $parameters - * - * @return string - * - * @throws Exception\RuntimeException - */ - protected function createSqlFromSpecificationAndParameters($specifications, $parameters) + public function __get($name) { - if (is_string($specifications)) { - return vsprintf($specifications, $parameters); - } - - $parametersCount = count($parameters); - - foreach ($specifications as $specificationString => $paramSpecs) { - if ($parametersCount == count($paramSpecs)) { - break; - } - - unset($specificationString, $paramSpecs); - } - - if (!isset($specificationString)) { - throw new Exception\RuntimeException( - 'A number of parameters was found that is not supported by this specification' + if (!array_key_exists($name, $this->__getProperties)) { + throw new Exception\InvalidArgumentException( + 'Not a valid property "'. $name . '" for this object' ); } - - $topParameters = []; - foreach ($parameters as $position => $paramsForPosition) { - if (isset($paramSpecs[$position]['combinedby'])) { - $multiParamValues = []; - foreach ($paramsForPosition as $multiParamsForPosition) { - $ppCount = count($multiParamsForPosition); - if (!isset($paramSpecs[$position][$ppCount])) { - throw new Exception\RuntimeException(sprintf( - 'A number of parameters (%d) was found that is not supported by this specification', - $ppCount - )); - } - $multiParamValues[] = vsprintf($paramSpecs[$position][$ppCount], $multiParamsForPosition); - } - $topParameters[] = implode($paramSpecs[$position]['combinedby'], $multiParamValues); - } elseif ($paramSpecs[$position] !== null) { - $ppCount = count($paramsForPosition); - if (!isset($paramSpecs[$position][$ppCount])) { - throw new Exception\RuntimeException(sprintf( - 'A number of parameters (%d) was found that is not supported by this specification', - $ppCount - )); - } - $topParameters[] = vsprintf($paramSpecs[$position][$ppCount], $paramsForPosition); - } else { - $topParameters[] = $paramsForPosition; - } - } - return vsprintf($specificationString, $topParameters); - } - - /** - * @param Select $subselect - * @param PlatformInterface $platform - * @param null|DriverInterface $driver - * @param null|ParameterContainer $parameterContainer - * @return string - */ - protected function processSubSelect( - Select $subselect, - PlatformInterface $platform, - DriverInterface $driver = null, - ParameterContainer $parameterContainer = null - ) { - if ($this instanceof PlatformDecoratorInterface) { - $decorator = clone $this; - $decorator->setSubject($subselect); - } else { - $decorator = $subselect; - } - - if ($parameterContainer) { - // Track subselect prefix and count for parameters - $processInfoContext = ($decorator instanceof PlatformDecoratorInterface) ? $subselect : $decorator; - $this->processInfo['subselectCount']++; - $processInfoContext->processInfo['subselectCount'] = $this->processInfo['subselectCount']; - $processInfoContext->processInfo['paramPrefix'] = 'subselect' - . $processInfoContext->processInfo['subselectCount']; - - $sql = $decorator->buildSqlString($platform, $driver, $parameterContainer); - - // copy count - $this->processInfo['subselectCount'] = $decorator->processInfo['subselectCount']; - return $sql; - } - - return $decorator->buildSqlString($platform, $driver, $parameterContainer); - } - - /** - * @param Join[] $joins - * @param PlatformInterface $platform - * @param null|DriverInterface $driver - * @param null|ParameterContainer $parameterContainer - * @return null|string[] Null if no joins present, array of JOIN statements - * otherwise - * @throws Exception\InvalidArgumentException for invalid JOIN table names. - */ - protected function processJoin( - Join $joins, - PlatformInterface $platform, - DriverInterface $driver = null, - ParameterContainer $parameterContainer = null - ) { - if (! $joins->count()) { - return; - } - - // process joins - $joinSpecArgArray = []; - foreach ($joins->getJoins() as $j => $join) { - $joinName = null; - $joinAs = null; - - // table name - if (is_array($join['name'])) { - $joinName = current($join['name']); - $joinAs = $platform->quoteIdentifier(key($join['name'])); - } else { - $joinName = $join['name']; - } - - if ($joinName instanceof Expression) { - $joinName = $joinName->getExpression(); - } elseif ($joinName instanceof TableIdentifier) { - $joinName = $joinName->getTableAndSchema(); - $joinName = ($joinName[1] ? $platform->quoteIdentifier($joinName[1]) . $platform->getIdentifierSeparator() : '') . $platform->quoteIdentifier($joinName[0]); - } elseif ($joinName instanceof Select) { - $joinName = '(' . $this->processSubSelect($joinName, $platform, $driver, $parameterContainer) . ')'; - } elseif (is_string($joinName) || (is_object($joinName) && is_callable([$joinName, '__toString']))) { - $joinName = $platform->quoteIdentifier($joinName); - } else { - throw new Exception\InvalidArgumentException(sprintf('Join name expected to be Expression|TableIdentifier|Select|string, "%s" given', gettype($joinName))); - } - - $joinSpecArgArray[$j] = [ - strtoupper($join['type']), - $this->renderTable($joinName, $joinAs), - ]; - - // on expression - // note: for Expression objects, pass them to processExpression with a prefix specific to each join (used for named parameters) - $joinSpecArgArray[$j][] = ($join['on'] instanceof ExpressionInterface) - ? $this->processExpression($join['on'], $platform, $driver, $parameterContainer, 'join' . ($j+1) . 'part') - : $platform->quoteIdentifierInFragment($join['on'], ['=', 'AND', 'OR', '(', ')', 'BETWEEN', '<', '>']); // on - } - - return [$joinSpecArgArray]; - } - - /** - * @param null|array|ExpressionInterface|Select $column - * @param PlatformInterface $platform - * @param null|DriverInterface $driver - * @param null|string $namedParameterPrefix - * @param null|ParameterContainer $parameterContainer - * @return string - */ - protected function resolveColumnValue( - $column, - PlatformInterface $platform, - DriverInterface $driver = null, - ParameterContainer $parameterContainer = null, - $namedParameterPrefix = null - ) { - $namedParameterPrefix = ! $namedParameterPrefix - ? $namedParameterPrefix - : $this->processInfo['paramPrefix'] . $namedParameterPrefix; - $isIdentifier = false; - $fromTable = ''; - if (is_array($column)) { - if (isset($column['isIdentifier'])) { - $isIdentifier = (bool) $column['isIdentifier']; - } - if (isset($column['fromTable']) && $column['fromTable'] !== null) { - $fromTable = $column['fromTable']; - } - $column = $column['column']; - } - - if ($column instanceof ExpressionInterface) { - return $this->processExpression($column, $platform, $driver, $parameterContainer, $namedParameterPrefix); - } - if ($column instanceof Select) { - return '(' . $this->processSubSelect($column, $platform, $driver, $parameterContainer) . ')'; - } - if ($column === null) { - return 'NULL'; - } - return $isIdentifier - ? $fromTable . $platform->quoteIdentifierInFragment($column) - : $platform->quoteValue($column); - } - - /** - * @param string|TableIdentifier|Select $table - * @param PlatformInterface $platform - * @param DriverInterface $driver - * @param ParameterContainer $parameterContainer - * @return string - */ - protected function resolveTable( - $table, - PlatformInterface $platform, - DriverInterface $driver = null, - ParameterContainer $parameterContainer = null - ) { - $schema = null; - if ($table instanceof TableIdentifier) { - list($table, $schema) = $table->getTableAndSchema(); - } - - if ($table instanceof Select) { - $table = '(' . $this->processSubselect($table, $platform, $driver, $parameterContainer) . ')'; - } elseif ($table) { - $table = $platform->quoteIdentifier($table); - } - - if ($schema && $table) { - $table = $platform->quoteIdentifier($schema) . $platform->getIdentifierSeparator() . $table; - } - return $table; - } - - /** - * Copy variables from the subject into the local properties - */ - protected function localizeVariables() - { - if (! $this instanceof PlatformDecoratorInterface) { - return; - } - - foreach (get_object_vars($this->subject) as $name => $value) { - $this->{$name} = $value; - } + return $this->{$name}; } } diff --git a/src/Sql/Builder/AbstractBuilder.php b/src/Sql/Builder/AbstractBuilder.php index 33145d4e1f..48aa0a4f42 100644 --- a/src/Sql/Builder/AbstractBuilder.php +++ b/src/Sql/Builder/AbstractBuilder.php @@ -9,98 +9,7 @@ namespace Zend\Db\Sql\Builder; -use Zend\Db\Adapter\AdapterInterface; -use Zend\Db\Adapter\Platform\PlatformInterface; -use Zend\Db\Adapter\StatementContainerInterface; -use Zend\Db\Sql\Exception; -use Zend\Db\Sql\PreparableSqlObjectInterface; -use Zend\Db\Sql\SqlObjectInterface; - -class AbstractBuilder implements PlatformDecoratorInterface, PreparableSqlObjectInterface, SqlObjectInterface +abstract class AbstractBuilder { - /** - * @var object|null - */ - protected $subject; - - /** - * @var PlatformDecoratorInterface[] - */ - protected $decorators = []; - - /** - * {@inheritDoc} - */ - public function setSubject($subject) - { - $this->subject = $subject; - - return $this; - } - - /** - * @param string $type - * @param PlatformDecoratorInterface $decorator - * - * @return void - */ - public function setTypeDecorator($type, PlatformDecoratorInterface $decorator) - { - $this->decorators[$type] = $decorator; - } - - /** - * @param PreparableSqlObjectInterface|SqlObjectInterface $subject - * @return PlatformDecoratorInterface|PreparableSqlObjectInterface|SqlObjectInterface - */ - public function getTypeDecorator($subject) - { - foreach ($this->decorators as $type => $decorator) { - if ($subject instanceof $type) { - $decorator->setSubject($subject); - - return $decorator; - } - } - - return $subject; - } - - /** - * @return array|PlatformDecoratorInterface[] - */ - public function getDecorators() - { - return $this->decorators; - } - - /** - * {@inheritDoc} - * - * @throws Exception\RuntimeException - */ - public function prepareStatement(AdapterInterface $adapter, StatementContainerInterface $statementContainer) - { - if (! $this->subject instanceof PreparableSqlObjectInterface) { - throw new Exception\RuntimeException('The subject does not appear to implement Zend\Db\Sql\PreparableSqlObjectInterface, thus calling prepareStatement() has no effect'); - } - - $this->getTypeDecorator($this->subject)->prepareStatement($adapter, $statementContainer); - - return $statementContainer; - } - - /** - * {@inheritDoc} - * - * @throws Exception\RuntimeException - */ - public function getSqlString(PlatformInterface $adapterPlatform = null) - { - if (! $this->subject instanceof SqlObjectInterface) { - throw new Exception\RuntimeException('The subject does not appear to implement Zend\Db\Sql\SqlObjectInterface, thus calling prepareStatement() has no effect'); - } - - return $this->getTypeDecorator($this->subject)->getSqlString($adapterPlatform); - } + abstract protected function buildSqlString($sqlObject, Context $context); } diff --git a/src/Sql/Builder/AbstractSqlBuilder.php b/src/Sql/Builder/AbstractSqlBuilder.php new file mode 100644 index 0000000000..dd01a6a2b2 --- /dev/null +++ b/src/Sql/Builder/AbstractSqlBuilder.php @@ -0,0 +1,313 @@ +platformBuilder = $platformBuilder; + } + + protected function buildSqlString($sqlObject, Context $context) + { + if ($sqlObject instanceof ExpressionInterface) { + return $this->buildExpression($sqlObject, $context); + } + $sqls = []; + $parameters = []; + + foreach ($this->specifications as $name => $specification) { + $parameters[$name] = $this->{'build_' . $name}($sqlObject, $context, $sqls, $parameters); + + if ($specification && is_array($parameters[$name])) { + $sqls[$name] = $this->createSqlFromSpecificationAndParameters($specification, $parameters[$name]); + + continue; + } + + if (is_string($parameters[$name])) { + $sqls[$name] = $parameters[$name]; + } + } + return rtrim(implode(' ', $sqls), "\n ,"); + } + + /** + * @param string|array $specifications + * @param string|array $parameters + * + * @return string + * + * @throws Exception\RuntimeException + */ + protected function createSqlFromSpecificationAndParameters($specifications, $parameters) + { + if (is_string($specifications)) { + return vsprintf($specifications, $parameters); + } + + $parametersCount = count($parameters); + + foreach ($specifications as $specificationString => $paramSpecs) { + if ($parametersCount == count($paramSpecs)) { + break; + } + + unset($specificationString, $paramSpecs); + } + + if (!isset($specificationString)) { + throw new Exception\RuntimeException( + 'A number of parameters was found that is not supported by this specification' + ); + } + + $topParameters = []; + foreach ($parameters as $position => $paramsForPosition) { + if (isset($paramSpecs[$position]['combinedby'])) { + $multiParamValues = []; + foreach ($paramsForPosition as $multiParamsForPosition) { + $ppCount = count($multiParamsForPosition); + if (!isset($paramSpecs[$position][$ppCount])) { + throw new Exception\RuntimeException(sprintf( + 'A number of parameters (%d) was found that is not supported by this specification', $ppCount + )); + } + $multiParamValues[] = vsprintf($paramSpecs[$position][$ppCount], $multiParamsForPosition); + } + $topParameters[] = implode($paramSpecs[$position]['combinedby'], $multiParamValues); + } elseif ($paramSpecs[$position] !== null) { + $ppCount = count($paramsForPosition); + if (!isset($paramSpecs[$position][$ppCount])) { + throw new Exception\RuntimeException(sprintf( + 'A number of parameters (%d) was found that is not supported by this specification', $ppCount + )); + } + $topParameters[] = vsprintf($paramSpecs[$position][$ppCount], $paramsForPosition); + } else { + $topParameters[] = $paramsForPosition; + } + } + return vsprintf($specificationString, $topParameters); + } + + /** + * @param string|TableIdentifier|Select $table + * @param Context $context + * @return string + */ + protected function resolveTable($table, Context $context) + { + $schema = null; + if ($table instanceof TableIdentifier) { + list($table, $schema) = $table->getTableAndSchema(); + } + + if ($table instanceof SelectableInterface) { + $table = '(' . $this->buildSubSelect($table, $context) . ')'; + } elseif ($table) { + $table = $context->getPlatform()->quoteIdentifier($table); + } + + if ($schema && $table) { + $table = $context->getPlatform()->quoteIdentifier($schema) . $context->getPlatform()->getIdentifierSeparator() . $table; + } + return $table; + } + + protected function buildSubSelect(SelectableInterface $subselect, Context $context) + { + $context->startPrefix('subselect'); + + $builder = $this->platformBuilder->getPlatformBuilder($subselect, $context->getPlatform()); + $result = $builder->buildSqlString($subselect, $context); + + $context->endPrefix(); + + return $result; + } + + private function buildExpression(ExpressionInterface $expression, Context $context) + { + $sql = ''; + + $parts = $expression->getExpressionData(); + + foreach ($parts as $part) { + // #7407: use $expression->getExpression() to get the unescaped + // version of the expression + if (is_string($part) && $expression instanceof Expression) { + $sql .= $expression->getExpression(); + + continue; + } + + // if it is a string, simply tack it onto the return sql + // "specification" string + if (is_string($part)) { + $sql .= $part; + + continue; + } + + if (! is_array($part)) { + throw new Exception\RuntimeException( + 'Elements returned from getExpressionData() array must be a string or array.' + ); + } + + // build_ values and types (the middle and last position of the + // expression data) + $values = $part[1]; + $types = isset($part[2]) ? $part[2] : []; + foreach ($values as $vIndex => $value) { + if (!isset($types[$vIndex])) { + continue; + } + $type = $types[$vIndex]; + if ($value instanceof SelectableInterface) { + // build_ sub-select + $values[$vIndex] = '(' . $this->buildSubSelect($value, $context) . ')'; + } elseif ($value instanceof ExpressionInterface) { + // recursive call to satisfy nested expressions + $values[$vIndex] = $this->buildSqlString($value, $context); + } elseif ($type == ExpressionInterface::TYPE_IDENTIFIER) { + $values[$vIndex] = $context->getPlatform()->quoteIdentifierInFragment($value); + } elseif ($type == ExpressionInterface::TYPE_VALUE) { + // if prepareType is set, it means that this particular value must be + // passed back to the statement in a way it can be used as a placeholder value + if ($context->getParameterContainer()) { + $name = $context->getNestedAlias('expr'); + $context->getParameterContainer()->offsetSet($name, $value); + $values[$vIndex] = $context->getDriver()->formatParameterName($name); + continue; + } + + // if not a preparable statement, simply quote the value and move on + $values[$vIndex] = $context->getPlatform()->quoteValue($value); + } elseif ($type == ExpressionInterface::TYPE_LITERAL) { + $values[$vIndex] = $value; + } + } + + // after looping the values, interpolate them into the sql string + // (they might be placeholder names, or values) + $sql .= vsprintf($part[0], $values); + } + + return $sql; + } + + /** + * @param string|array $column + * @param Context $context + * @return string + */ + protected function resolveColumnValue($column, Context $context) + { + $isIdentifier = false; + $fromTable = ''; + if (is_array($column)) { + if (isset($column['isIdentifier'])) { + $isIdentifier = (bool) $column['isIdentifier']; + } + if (isset($column['fromTable']) && $column['fromTable'] !== null) { + $fromTable = $column['fromTable']; + } + $column = $column['column']; + } + + if ($column instanceof ExpressionInterface) { + return $this->buildSqlString($column, $context); + } + if ($column instanceof SelectableInterface) { + return '(' . $this->buildSubSelect($column, $context) . ')'; + } + if ($column === null) { + return 'NULL'; + } + return $isIdentifier + ? $fromTable . $context->getPlatform()->quoteIdentifierInFragment($column) + : $context->getPlatform()->quoteValue($column); + } + + protected function renderTable($table, $alias = null) + { + return $table . ($alias ? ' AS ' . $alias : ''); + } + + /** + * @param SqlObjectInterface $sqlObject + * @param Context $context + * @return array|null + */ + protected function build_Joins(SqlObjectInterface $sqlObject, Context $context) + { + if (!$sqlObject->joins || $sqlObject->joins->count() == 0) { + return; + } + + // build_ joins + $joinSpecArgArray = []; + foreach ($sqlObject->joins as $j => $join) { + $context->startPrefix('join'); + $joinName = null; + $joinAs = null; + + // table name + if (is_array($join['name'])) { + $joinName = current($join['name']); + $joinAs = $context->getPlatform()->quoteIdentifier(key($join['name'])); + } else { + $joinName = $join['name']; + } + if ($joinName instanceof ExpressionInterface) { + $joinName = $joinName->getExpression(); + } elseif ($joinName instanceof TableIdentifier) { + $joinName = $joinName->getTableAndSchema(); + $joinName = ($joinName[1] ? $context->getPlatform()->quoteIdentifier($joinName[1]) . $context->getPlatform()->getIdentifierSeparator() : '') . $context->getPlatform()->quoteIdentifier($joinName[0]); + } elseif ($joinName instanceof SelectableInterface) { + $joinName = '(' . $this->buildSubSelect($joinName, $context) . ')'; + } elseif (is_string($joinName) || (is_object($joinName) && is_callable([$joinName, '__toString']))) { + $joinName = $context->getPlatform()->quoteIdentifier($joinName); + } else { + throw new Exception\InvalidArgumentException(sprintf('Join name expected to be Expression|TableIdentifier|Select|string, "%s" given', gettype($joinName))); + } + $joinSpecArgArray[$j] = [ + strtoupper($join['type']), + $this->renderTable($joinName, $joinAs), + ]; + $joinSpecArgArray[$j][] = ($join['on'] instanceof ExpressionInterface) + ? $this->buildSqlString($join['on'], $context, 'join' . ($j+1) . 'part') + : $context->getPlatform()->quoteIdentifierInFragment($join['on'], ['=', 'AND', 'OR', '(', ')', 'BETWEEN', '<', '>']); // on + $context->endPrefix(); + } + + return [$joinSpecArgArray]; + } +} diff --git a/src/Sql/Builder/Builder.php b/src/Sql/Builder/Builder.php index dcd517432b..ca3da5e2e8 100644 --- a/src/Sql/Builder/Builder.php +++ b/src/Sql/Builder/Builder.php @@ -9,168 +9,211 @@ namespace Zend\Db\Sql\Builder; -use Zend\Db\Adapter\AdapterInterface; +use Zend\Db\Adapter; use Zend\Db\Adapter\Platform\PlatformInterface; -use Zend\Db\Adapter\StatementContainerInterface; use Zend\Db\Sql\Exception; -use Zend\Db\Sql\PreparableSqlObjectInterface; -use Zend\Db\Sql\SqlObjectInterface; class Builder extends AbstractBuilder { /** - * @var AdapterInterface + * @var Adapter\AdapterInterface */ - protected $adapter = null; + protected $defaultAdapter; + + protected $buildersInstances = []; + + protected $concreteBuilders = []; + + protected $inheritableBuilders = [ + 'Zend\Db\Sql\Combine' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\CombineBuilder', + ], + 'Zend\Db\Sql\Delete' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\DeleteBuilder', + ], + 'Zend\Db\Sql\Insert' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\InsertBuilder', + ], + 'Zend\Db\Sql\Select' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\SelectBuilder', + 'mysql' => 'Zend\Db\Sql\Builder\MySql\SelectBuilder', + 'ibmdb2' => 'Zend\Db\Sql\Builder\IbmDb2\SelectBuilder', + 'oracle' => 'Zend\Db\Sql\Builder\Oracle\SelectBuilder', + 'sqlserver' => 'Zend\Db\Sql\Builder\SqlServer\SelectBuilder', + ], + 'Zend\Db\Sql\Update' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\UpdateBuilder', + ], + + 'Zend\Db\Sql\Ddl\AlterTable' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\AlterTableBuilder', + 'mysql' => 'Zend\Db\Sql\Builder\MySql\Ddl\AlterTableBuilder', + ], + 'Zend\Db\Sql\Ddl\CreateTable' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\CreateTableBuilder', + 'mysql' => 'Zend\Db\Sql\Builder\MySql\Ddl\CreateTableBuilder', + 'sqlserver' => 'Zend\Db\Sql\Builder\SqlServer\Ddl\CreateTableBuilder', + ], + 'Zend\Db\Sql\Ddl\DropTable' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\DropTableBuilder', + ], + ]; /** - * @var PlatformInterface|null + * @param Adapter\AdapterInterface $adapter */ - protected $defaultPlatform; - - public function __construct(AdapterInterface $adapter) + public function __construct(Adapter\AdapterInterface $adapter = null) { - $this->defaultPlatform = $adapter->getPlatform(); - - $this->decorators = [ - 'mysql' => [ - 'Zend\Db\Sql\Select' => new Mysql\SelectBuilder(), - 'Zend\Db\Sql\Ddl\CreateTable' => new Mysql\Ddl\CreateTableBuilder(), - 'Zend\Db\Sql\Ddl\AlterTable' => new Mysql\Ddl\AlterTableBuilder(), - ], - 'sqlserver' => [ - 'Zend\Db\Sql\Select' => new SqlServer\SelectBuilder(), - 'Zend\Db\Sql\Ddl\CreateTable' => new SqlServer\Ddl\CreateTableBuilder(), - ], - 'oracle' => [ - 'Zend\Db\Sql\Select' => new Oracle\SelectBuilder(), - ], - 'ibmdb2' => [ - 'Zend\Db\Sql\Select' => new IbmDb2\SelectBuilder(), - ], - 'sqlite' => [ - 'Zend\Db\Sql\Select' => new Sqlite\SelectBuilder(), - ], - ]; + $this->defaultAdapter = $adapter; } /** - * @param string $type - * @param PlatformDecoratorInterface $decorator - * @param AdapterInterface|PlatformInterface $adapterOrPlatform + * @return Adapter\AdapterInterface */ - public function setTypeDecorator($type, PlatformDecoratorInterface $decorator, $adapterOrPlatform = null) + public function setDefaultAdapter($adapter) { - $platformName = $this->resolvePlatformName($adapterOrPlatform); - $this->decorators[$platformName][$type] = $decorator; + $this->defaultAdapter = $adapter; + return $this; } /** - * @param PreparableSqlObjectInterface|SqlObjectInterface $subject - * @param AdapterInterface|PlatformInterface|null $adapterOrPlatform - * @return PlatformDecoratorInterface|PreparableSqlObjectInterface|SqlObjectInterface + * @return Adapter\AdapterInterface */ - public function getTypeDecorator($subject, $adapterOrPlatform = null) + public function getDefaultAdapter() { - $platformName = $this->resolvePlatformName($adapterOrPlatform); - - if (isset($this->decorators[$platformName])) { - foreach ($this->decorators[$platformName] as $type => $decorator) { - if ($subject instanceof $type && is_a($decorator, $type, true)) { - $decorator->setSubject($subject); - return $decorator; - } - } - } - - return $subject; + return $this->defaultAdapter; } /** - * @return array|PlatformDecoratorInterface[] + * @param string|Context|PlatformInterface|Adapter\AdapterInterface $platform + * @param string $objectClass + * @param string $builderClass + * @return self */ - public function getDecorators() + public function setPlatformBuilder($platform, $objectClass, $builderClass) { - $platformName = $this->resolvePlatformName($this->getDefaultPlatform()); - return $this->decorators[$platformName]; + $platform = $this->resolvePlatformName($platform); + if ($builderClass instanceof AbstractSqlBuilder) { + $builder = get_class($builderClass); + $this->buildersInstances[$builder] = $builderClass; + } elseif (is_string($builderClass)) { + $builder = $builderClass; + } else { + throw new Exception\InvalidArgumentException(sprintf( + '$builderClass should be %s or %s instance', + 'string', + 'Zend\Db\Sql\Builder\AbstractSqlBuilder' + )); + } + $this->inheritableBuilders[$objectClass][$platform] = $builder; + return $this; } /** - * {@inheritDoc} - * + * @param SqlObjectInterface $sqlObject + * @param string|Context|PlatformInterface|Adapter\AdapterInterface $platform + * @return AbstractSqlBuilder * @throws Exception\RuntimeException */ - public function prepareStatement(AdapterInterface $adapter, StatementContainerInterface $statementContainer) + public function getPlatformBuilder($sqlObject, $platform = 'sql92') { - if (! $this->subject instanceof PreparableSqlObjectInterface) { - throw new Exception\RuntimeException('The subject does not appear to implement Zend\Db\Sql\PreparableSqlObjectInterface, thus calling prepareStatement() has no effect'); + $platform = $this->resolvePlatformName($platform); + + $mapName = $platform . '-' . get_class($sqlObject); + if (array_key_exists($mapName, $this->concreteBuilders)) { + $builder = $this->concreteBuilders[$mapName]; + if ($builder === false) { + throw new Exception\RuntimeException(sprintf( + 'Builder for "%s" not found', + get_class($sqlObject) + )); + } + if (!isset($this->buildersInstances[$builder])) { + $this->buildersInstances[$builder] = new $builder($this); + } + return $this->buildersInstances[$builder]; } - $this->getTypeDecorator($this->subject, $adapter)->prepareStatement($adapter, $statementContainer); + foreach ($this->inheritableBuilders as $type => $builders) { + if (!$sqlObject instanceof $type) { + continue; + } + if (!isset($builders[$platform])) { + break; + } + $builder = $builders[$platform]; + if (!isset($this->concreteBuilders[$mapName])) { + $this->concreteBuilders[$mapName] = $builder; + } + if (!isset($this->buildersInstances[$builder])) { + $this->buildersInstances[$builder] = new $builder($this); + } + return $this->buildersInstances[$builder]; + } - return $statementContainer; + if ($platform == 'sql92') { + throw new Exception\RuntimeException(sprintf( + 'Builder for "%s" not found', + get_class($sqlObject) + )); + } + return $this->getPlatformBuilder($sqlObject); } /** - * {@inheritDoc} - * - * @throws Exception\RuntimeException + * @param SqlObjectInterface|ExpressionInterface $object + * @param null|Adapter\AdapterInterface $adapter + * @return string */ - public function getSqlString(PlatformInterface $adapterPlatform = null) + public function getSqlString($object, Adapter\AdapterInterface $adapter = null) { - if (! $this->subject instanceof SqlObjectInterface) { - throw new Exception\RuntimeException('The subject does not appear to implement Zend\Db\Sql\SqlObjectInterface, thus calling prepareStatement() has no effect'); - } - - $adapterPlatform = $this->resolvePlatform($adapterPlatform); - - return $this->getTypeDecorator($this->subject, $adapterPlatform)->getSqlString($adapterPlatform); + $adapter = $adapter ?: $this->defaultAdapter; + return $this->buildSqlString($object, new Context($adapter)); } - protected function resolvePlatformName($adapterOrPlatform) - { - $platformName = $this->resolvePlatform($adapterOrPlatform)->getName(); - return str_replace([' ', '_'], '', strtolower($platformName)); - } /** - * @param null|PlatformInterface|AdapterInterface $adapterOrPlatform - * - * @return PlatformInterface - * - * @throws Exception\InvalidArgumentException + * @param SqlObjectInterface|ExpressionInterface $object + * @param null|Adapter\AdapterInterface $adapter + * @return \Zend\Db\Adapter\Driver\StatementInterface */ - protected function resolvePlatform($adapterOrPlatform) + public function prepareStatement($object, Adapter\AdapterInterface $adapter = null) { - if (! $adapterOrPlatform) { - return $this->getDefaultPlatform(); - } - - if ($adapterOrPlatform instanceof AdapterInterface) { - return $adapterOrPlatform->getPlatform(); + $adapter = $adapter ?: $this->defaultAdapter; + $statement = $adapter->getDriver()->createStatement(); + if (!$statement->getParameterContainer()) { + $statement->setParameterContainer(new Adapter\ParameterContainer); } + $statement->setSql( + $this->buildSqlString($object, new Context($adapter, $statement->getParameterContainer())) + ); - if ($adapterOrPlatform instanceof PlatformInterface) { - return $adapterOrPlatform; - } + return $statement; + } - throw new Exception\InvalidArgumentException(sprintf( - '$adapterOrPlatform should be null, %s, or %s', - 'Zend\Db\Adapter\AdapterInterface', - 'Zend\Db\Adapter\Platform\PlatformInterface' - )); + /** + * @param SqlObjectInterface $sqlObject + * @param Context $context + * @return string + */ + protected function buildSqlString($sqlObject, Context $context) + { + $builder = $this->getPlatformBuilder($sqlObject, $context); + return $builder->buildSqlString($sqlObject, $context); } /** - * @return PlatformInterface - * - * @throws Exception\RuntimeException + * @param string|Context|PlatformInterface|Adapter\AdapterInterface $platform + * @return string */ - protected function getDefaultPlatform() + protected function resolvePlatformName($platform) { - if (! $this->defaultPlatform) { - throw new Exception\RuntimeException('$this->defaultPlatform was not set'); + if ($platform instanceof Context) { + $platform = $platform->getPlatform()->getName(); + } elseif ($platform instanceof PlatformInterface) { + $platform = $platform->getName(); + } elseif ($platform instanceof Adapter\AdapterInterface) { + $platform = $platform->getPlatform()->getName(); } - - return $this->defaultPlatform; + return str_replace(' ', '', strtolower($platform)); } } diff --git a/src/Sql/Builder/Context.php b/src/Sql/Builder/Context.php new file mode 100644 index 0000000000..5680e7e55e --- /dev/null +++ b/src/Sql/Builder/Context.php @@ -0,0 +1,95 @@ + '', + 'suffixIndex' => 0, + ]]; + + public function __construct(Adapter\Adapter $adapter, Adapter\ParameterContainer $parameterContainer = null) + { + $this->adapter = $adapter; + $this->platform = $adapter->getPlatform(); + $this->driver = $adapter->getDriver(); + $this->parameterContainer = $parameterContainer; + } + + /** + * @return Adapter\Adapter + */ + public function getAdapter() + { + return $this->adapter; + } + + /** + * @return Adapter\Platform\PlatformInterface + */ + public function getPlatform() + { + return $this->platform; + } + + /** + * @return Adapter\Driver\DriverInterface + */ + public function getDriver() + { + return $this->driver; + } + + /** + * @return Adapter\ParameterContainer + */ + public function getParameterContainer() + { + return $this->parameterContainer; + } + + /** + * @param string $name + */ + public function startPrefix($name) + { + if (!isset($this->prefixCounter[$name])) { + $this->prefixCounter[$name] = 0; + } + $this->prefixCurrent[] = [ + 'prefix' => $name . ++$this->prefixCounter[$name], + 'suffixIndex' => 0, + ]; + } + + public function endPrefix() + { + array_pop($this->prefixCurrent); + } + + /** + * @param string $suffix + * @return string + */ + public function getNestedAlias($suffix) + { + $curr = &$this->prefixCurrent[count($this->prefixCurrent) - 1]; + return $curr['prefix'] . $suffix . ++$curr['suffixIndex']; + } +} diff --git a/src/Sql/Builder/IbmDb2/SelectBuilder.php b/src/Sql/Builder/IbmDb2/SelectBuilder.php index f011dad0c0..15d887adfe 100644 --- a/src/Sql/Builder/IbmDb2/SelectBuilder.php +++ b/src/Sql/Builder/IbmDb2/SelectBuilder.php @@ -9,48 +9,12 @@ namespace Zend\Db\Sql\Builder\IbmDb2; -use Zend\Db\Adapter\Driver\DriverInterface; -use Zend\Db\Adapter\ParameterContainer; -use Zend\Db\Adapter\Platform\PlatformInterface; -use Zend\Db\Sql\Builder\PlatformDecoratorInterface; use Zend\Db\Sql\Select; +use Zend\Db\Sql\Builder\sql92\SelectBuilder as BaseBuilder; +use Zend\Db\Sql\Builder\Context; -class SelectBuilder extends Select implements PlatformDecoratorInterface +class SelectBuilder extends BaseBuilder { - /** - * @var bool - */ - protected $isSelectContainDistinct= false; - - /** - * @var Select - */ - protected $subject = null; - - /** - * @return bool - */ - public function getIsSelectContainDistinct() - { - return $this->isSelectContainDistinct; - } - - /** - * @param boolean $isSelectContainDistinct - */ - public function setIsSelectContainDistinct($isSelectContainDistinct) - { - $this->isSelectContainDistinct = $isSelectContainDistinct; - } - - /** - * @param Select $select - */ - public function setSubject($select) - { - $this->subject = $select; - } - /** * @see Select::renderTable */ @@ -59,38 +23,28 @@ protected function renderTable($table, $alias = null) return $table . ' ' . $alias; } - protected function localizeVariables() + protected function build_Limit(Select $sqlObject, Context $context) { - parent::localizeVariables(); - // set specifications - unset($this->specifications[self::LIMIT]); - unset($this->specifications[self::OFFSET]); - - $this->specifications['LIMITOFFSET'] = null; + return; } - /** - * @param PlatformInterface $platform - * @param DriverInterface $driver - * @param ParameterContainer $parameterContainer - * @param array $sqls - * @param array $parameters - */ - protected function processLimitOffset(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null, &$sqls, &$parameters) + protected function build_Offset(Select $sqlObject, Context $context, &$sqls = null, &$parameters = null) { - if ($this->limit === null && $this->offset === null) { + $LIMIT = $sqlObject->limit; + $OFFSET = $sqlObject->offset; + if ($LIMIT === null && $OFFSET === null) { return; } - $selectParameters = $parameters[self::SELECT]; + $selectParameters = $parameters[self::SPECIFICATION_SELECT]; - $starSuffix = $platform->getIdentifierSeparator() . self::SQL_STAR; + $starSuffix = $context->getPlatform()->getIdentifierSeparator() . Select::SQL_STAR; foreach ($selectParameters[0] as $i => $columnParameters) { - if ($columnParameters[0] == self::SQL_STAR - || (isset($columnParameters[1]) && $columnParameters[1] == self::SQL_STAR) + if ($columnParameters[0] == Select::SQL_STAR + || (isset($columnParameters[1]) && $columnParameters[1] == Select::SQL_STAR) || strpos($columnParameters[0], $starSuffix) ) { - $selectParameters[0] = [[self::SQL_STAR]]; + $selectParameters[0] = [[Select::SQL_STAR]]; break; } @@ -102,63 +56,42 @@ protected function processLimitOffset(PlatformInterface $platform, DriverInterfa // first, produce column list without compound names (using the AS portion only) array_unshift($sqls, $this->createSqlFromSpecificationAndParameters( - ['SELECT %1$s FROM (' => current($this->specifications[self::SELECT])], + ['SELECT %1$s FROM (' => current($this->specifications[self::SPECIFICATION_SELECT])], $selectParameters )); - if (preg_match('/DISTINCT/i', $sqls[0])) { - $this->setIsSelectContainDistinct(true); - } - - if ($parameterContainer) { - // create bottom part of query, with offset and limit using row_number - $limitParamName = $driver->formatParameterName('limit'); - $offsetParamName = $driver->formatParameterName('offset'); - - array_push($sqls, sprintf( - ") AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN %s AND %s", - $offsetParamName, - $limitParamName - )); - - if ((int) $this->offset > 0) { - $parameterContainer->offsetSet('offset', (int) $this->offset + 1); - } else { - $parameterContainer->offsetSet('offset', (int) $this->offset); - } + $offset = ((int) $OFFSET > 0) ? (int) $OFFSET + 1 : (int) $OFFSET; + $limit = (int) $LIMIT + (int) $OFFSET; - $parameterContainer->offsetSet('limit', (int) $this->limit + (int) $this->offset); - } else { - if ((int) $this->offset > 0) { - $offset = (int) $this->offset + 1; - } else { - $offset = (int) $this->offset; - } + if ($context->getParameterContainer()) { + $context->getParameterContainer()->offsetSet('offset', $offset); + $context->getParameterContainer()->offsetSet('limit', $limit); - array_push($sqls, sprintf( - ") AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN %d AND %d", - $offset, - (int) $this->limit + (int) $this->offset - )); + $limit = $context->getDriver()->formatParameterName('limit'); + $offset = $context->getDriver()->formatParameterName('offset'); } - if (isset($sqls[self::ORDER])) { - $orderBy = $sqls[self::ORDER]; - unset($sqls[self::ORDER]); + array_push($sqls, sprintf( + ") AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN %s AND %s", + $offset, + $limit + )); + + if (isset($sqls[self::SPECIFICATION_ORDER])) { + $orderBy = $sqls[self::SPECIFICATION_ORDER]; + unset($sqls[self::SPECIFICATION_ORDER]); } else { $orderBy = ''; } // add a column for row_number() using the order specification //dense_rank() - if ($this->getIsSelectContainDistinct()) { - $parameters[self::SELECT][0][] = ['DENSE_RANK() OVER (' . $orderBy . ')', 'ZEND_DB_ROWNUM']; - } else { - $parameters[self::SELECT][0][] = ['ROW_NUMBER() OVER (' . $orderBy . ')', 'ZEND_DB_ROWNUM']; - } + $parameters[self::SPECIFICATION_SELECT][0][] = (preg_match('/DISTINCT/i', $sqls[0])) + ? ['DENSE_RANK() OVER (' . $orderBy . ')', 'ZEND_DB_ROWNUM'] + : ['ROW_NUMBER() OVER (' . $orderBy . ')', 'ZEND_DB_ROWNUM']; - $sqls[self::SELECT] = $this->createSqlFromSpecificationAndParameters( - $this->specifications[self::SELECT], - $parameters[self::SELECT] + $sqls[self::SPECIFICATION_SELECT] = $this->createSqlFromSpecificationAndParameters( + $this->specifications[self::SPECIFICATION_SELECT], + $parameters[self::SPECIFICATION_SELECT] ); } } diff --git a/src/Sql/Builder/Mysql/Ddl/AlterTableBuilder.php b/src/Sql/Builder/Mysql/Ddl/AlterTableBuilder.php index d8fc403168..b3b973d55b 100644 --- a/src/Sql/Builder/Mysql/Ddl/AlterTableBuilder.php +++ b/src/Sql/Builder/Mysql/Ddl/AlterTableBuilder.php @@ -9,20 +9,12 @@ namespace Zend\Db\Sql\Builder\Mysql\Ddl; -use Zend\Db\Adapter\Platform\PlatformInterface; +use Zend\Db\Sql\Builder\Ddl\AlterTableBuilder as BaseBuilder; +use Zend\Db\Sql\Builder\Context; use Zend\Db\Sql\Ddl\AlterTable; -use Zend\Db\Sql\Builder\PlatformDecoratorInterface; -class AlterTableBuilder extends AlterTable implements PlatformDecoratorInterface +class AlterTableBuilder extends BaseBuilder { - /** - * @var AlterTable - */ - protected $subject; - - /** - * @var int[] - */ protected $columnOptionSortOrder = [ 'unsigned' => 0, 'zerofill' => 1, @@ -35,17 +27,6 @@ class AlterTableBuilder extends AlterTable implements PlatformDecoratorInterface 'storage' => 5, ]; - /** - * @param AlterTable $subject - * @return \Zend\Db\Sql\Platform\PlatformDecoratorInterface - */ - public function setSubject($subject) - { - $this->subject = $subject; - - return $this; - } - /** * @param string $sql * @return array @@ -84,12 +65,12 @@ protected function getSqlInsertOffsets($sql) * @param PlatformInterface $adapterPlatform * @return array */ - protected function processAddColumns(PlatformInterface $adapterPlatform = null) + protected function build_AddColumns(AlterTable $sqlObject, Context $context) { $sqls = []; - foreach ($this->addColumns as $i => $column) { - $sql = $this->processExpression($column, $adapterPlatform); + foreach ($sqlObject->addColumns as $i => $column) { + $sql = $this->buildSqlString($column, $context); $insertStart = $this->getSqlInsertOffsets($sql); $columnOptions = $column->getOptions(); @@ -118,7 +99,7 @@ protected function processAddColumns(PlatformInterface $adapterPlatform = null) $j = 1; break; case 'comment': - $insert = ' COMMENT ' . $adapterPlatform->quoteValue($coValue); + $insert = ' COMMENT ' . $context->getPlatform()->quoteValue($coValue); $j = 2; break; case 'columnformat': @@ -150,11 +131,11 @@ protected function processAddColumns(PlatformInterface $adapterPlatform = null) * @param PlatformInterface $adapterPlatform * @return array */ - protected function processChangeColumns(PlatformInterface $adapterPlatform = null) + protected function build_ChangeColumns(AlterTable $sqlObject, Context $context) { $sqls = []; - foreach ($this->changeColumns as $name => $column) { - $sql = $this->processExpression($column, $adapterPlatform); + foreach ($sqlObject->changeColumns as $name => $column) { + $sql = $this->buildSqlString($column, $context); $insertStart = $this->getSqlInsertOffsets($sql); $columnOptions = $column->getOptions(); @@ -183,7 +164,7 @@ protected function processChangeColumns(PlatformInterface $adapterPlatform = nul $j = 1; break; case 'comment': - $insert = ' COMMENT ' . $adapterPlatform->quoteValue($coValue); + $insert = ' COMMENT ' . $context->getPlatform()->quoteValue($coValue); $j = 2; break; case 'columnformat': diff --git a/src/Sql/Builder/Mysql/Ddl/CreateTableBuilder.php b/src/Sql/Builder/Mysql/Ddl/CreateTableBuilder.php index b3ef0a4301..c28de15dae 100644 --- a/src/Sql/Builder/Mysql/Ddl/CreateTableBuilder.php +++ b/src/Sql/Builder/Mysql/Ddl/CreateTableBuilder.php @@ -9,17 +9,12 @@ namespace Zend\Db\Sql\Builder\Mysql\Ddl; -use Zend\Db\Adapter\Platform\PlatformInterface; +use Zend\Db\Sql\Builder\sql92\Ddl\CreateTableBuilder as BaseBuilder; +use Zend\Db\Sql\Builder\Context; use Zend\Db\Sql\Ddl\CreateTable; -use Zend\Db\Sql\Builder\PlatformDecoratorInterface; -class CreateTableBuilder extends CreateTable implements PlatformDecoratorInterface +class CreateTableBuilder extends BaseBuilder { - /** - * @var CreateTable - */ - protected $subject; - /** * @var int[] */ @@ -35,18 +30,6 @@ class CreateTableBuilder extends CreateTable implements PlatformDecoratorInterfa 'storage' => 5, ]; - /** - * @param CreateTable $subject - * - * @return self - */ - public function setSubject($subject) - { - $this->subject = $subject; - - return $this; - } - /** * @param string $sql * @return array @@ -84,16 +67,17 @@ protected function getSqlInsertOffsets($sql) /** * {@inheritDoc} */ - protected function processColumns(PlatformInterface $platform = null) + protected function build_Columns(CreateTable $sqlObject, Context $context) { - if (! $this->columns) { + $COLUMNS = $sqlObject->columns; + if (! $COLUMNS) { return; } $sqls = []; - foreach ($this->columns as $i => $column) { - $sql = $this->processExpression($column, $platform); + foreach ($COLUMNS as $i => $column) { + $sql = $this->buildSqlString($column, $context); $insertStart = $this->getSqlInsertOffsets($sql); $columnOptions = $column->getOptions(); @@ -122,7 +106,7 @@ protected function processColumns(PlatformInterface $platform = null) $j = 1; break; case 'comment': - $insert = ' COMMENT ' . $platform->quoteValue($coValue); + $insert = ' COMMENT ' . $context->getPlatform()->quoteValue($coValue); $j = 2; break; case 'columnformat': diff --git a/src/Sql/Builder/Mysql/SelectBuilder.php b/src/Sql/Builder/Mysql/SelectBuilder.php index 04ab66f55b..8f6aa54a5c 100644 --- a/src/Sql/Builder/Mysql/SelectBuilder.php +++ b/src/Sql/Builder/Mysql/SelectBuilder.php @@ -9,61 +9,51 @@ namespace Zend\Db\Sql\Builder\Mysql; -use Zend\Db\Adapter\Driver\DriverInterface; -use Zend\Db\Adapter\ParameterContainer; -use Zend\Db\Adapter\Platform\PlatformInterface; -use Zend\Db\Sql\Builder\PlatformDecoratorInterface; use Zend\Db\Sql\Select; +use Zend\Db\Adapter; +use Zend\Db\Sql\Builder\sql92\SelectBuilder as BaseBuilder; +use Zend\Db\Sql\Builder\Context; -class SelectBuilder extends Select implements PlatformDecoratorInterface +class SelectBuilder extends BaseBuilder { /** - * @var Select + * @param Select $sqlObject + * @param Context $context + * @return null|array */ - protected $subject = null; - - /** - * @param Select $select - */ - public function setSubject($select) + protected function build_Limit(Select $sqlObject, Context $context) { - $this->subject = $select; - } - - protected function localizeVariables() - { - parent::localizeVariables(); - if ($this->limit === null && $this->offset !== null) { - $this->specifications[self::LIMIT] = 'LIMIT 18446744073709551615'; + $limit = $sqlObject->limit; + if ($limit === null) { + return $sqlObject->offset === null + ? null + : ['18446744073709551615']; } - } - protected function processLimit(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - if ($this->limit === null && $this->offset !== null) { - return ['']; - } - if ($this->limit === null) { - return; - } - if ($parameterContainer) { - $parameterContainer->offsetSet('limit', $this->limit, ParameterContainer::TYPE_INTEGER); - return [$driver->formatParameterName('limit')]; + if ($context->getParameterContainer()) { + $context->getParameterContainer()->offsetSet('limit', $limit, Adapter\ParameterContainer::TYPE_INTEGER); + $limit = $context->getDriver()->formatParameterName('limit'); } - return [$this->limit]; + return [$limit]; } - protected function processOffset(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) + /** + * @param Select $sqlObject + * @param Context $context + * @return null|array + */ + protected function build_Offset(Select $sqlObject, Context $context) { - if ($this->offset === null) { + $offset = $sqlObject->offset; + if ($offset === null) { return; } - if ($parameterContainer) { - $parameterContainer->offsetSet('offset', $this->offset, ParameterContainer::TYPE_INTEGER); - return [$driver->formatParameterName('offset')]; + if ($context->getParameterContainer()) { + $context->getParameterContainer()->offsetSet('offset', $offset, Adapter\ParameterContainer::TYPE_INTEGER); + $offset = $context->getDriver()->formatParameterName('offset'); } - return [$this->offset]; + return [$offset]; } } diff --git a/src/Sql/Builder/Oracle/SelectBuilder.php b/src/Sql/Builder/Oracle/SelectBuilder.php index 7949fb040d..eac29cce59 100644 --- a/src/Sql/Builder/Oracle/SelectBuilder.php +++ b/src/Sql/Builder/Oracle/SelectBuilder.php @@ -9,27 +9,12 @@ namespace Zend\Db\Sql\Builder\Oracle; -use Zend\Db\Adapter\Driver\DriverInterface; -use Zend\Db\Adapter\ParameterContainer; -use Zend\Db\Adapter\Platform\PlatformInterface; -use Zend\Db\Sql\Builder\PlatformDecoratorInterface; use Zend\Db\Sql\Select; +use Zend\Db\Sql\Builder\sql92\SelectBuilder as BaseBuilder; +use Zend\Db\Sql\Builder\Context; -class SelectBuilder extends Select implements PlatformDecoratorInterface +class SelectBuilder extends BaseBuilder { - /** - * @var Select - */ - protected $subject = null; - - /** - * @param Select $select - */ - public function setSubject($select) - { - $this->subject = $select; - } - /** * @see \Zend\Db\Sql\Select::renderTable */ @@ -38,118 +23,72 @@ protected function renderTable($table, $alias = null) return $table . ($alias ? ' ' . $alias : ''); } - protected function localizeVariables() + protected function build_Limit(Select $sqlObject, Context $context) { - parent::localizeVariables(); - unset($this->specifications[self::LIMIT]); - unset($this->specifications[self::OFFSET]); - - $this->specifications['LIMITOFFSET'] = null; + return; } - /** - * @param PlatformInterface $platform - * @param DriverInterface $driver - * @param ParameterContainer $parameterContainer - * @param array $sqls - * @param array $parameters - * @return null - */ - protected function processLimitOffset( - PlatformInterface $platform, - DriverInterface $driver = null, - ParameterContainer $parameterContainer = null, - &$sqls = [], - &$parameters = [] - ) { - if ($this->limit === null && $this->offset === null) { + protected function build_Offset(Select $sqlObject, Context $context, &$sqls = null, &$parameters = null) + { + $LIMIT = $sqlObject->limit; + $OFFSET = $sqlObject->offset; + if ($LIMIT === null && $OFFSET === null) { return; } - $selectParameters = $parameters[self::SELECT]; - $starSuffix = $platform->getIdentifierSeparator() . self::SQL_STAR; + $selectParameters = $parameters[self::SPECIFICATION_SELECT]; + $starSuffix = $context->getPlatform()->getIdentifierSeparator() . Select::SQL_STAR; foreach ($selectParameters[0] as $i => $columnParameters) { - if ($columnParameters[0] == self::SQL_STAR - || (isset($columnParameters[1]) && $columnParameters[1] == self::SQL_STAR) - || strpos($columnParameters[0], $starSuffix) - ) { - $selectParameters[0] = [[self::SQL_STAR]]; + if ($columnParameters[0] == Select::SQL_STAR || (isset($columnParameters[1]) && $columnParameters[1] == Select::SQL_STAR) || strpos($columnParameters[0], $starSuffix)) { + $selectParameters[0] = [[Select::SQL_STAR]]; break; } - if (isset($columnParameters[1])) { array_shift($columnParameters); $selectParameters[0][$i] = $columnParameters; } } - if ($this->offset === null) { - $this->offset = 0; + if ($OFFSET === null) { + $OFFSET = 0; } // first, produce column list without compound names (using the AS portion only) - array_unshift($sqls, $this->createSqlFromSpecificationAndParameters([ - 'SELECT %1$s FROM (SELECT b.%1$s, rownum b_rownum FROM (' => current($this->specifications[self::SELECT]), - ], $selectParameters)); - - if ($parameterContainer) { - $number = $this->processInfo['subselectCount'] ? $this->processInfo['subselectCount'] : ''; - - if ($this->limit === null) { - array_push( - $sqls, - ') b ) WHERE b_rownum > (:offset' . $number . ')' - ); - $parameterContainer->offsetSet( - 'offset' . $number, - $this->offset, - $parameterContainer::TYPE_INTEGER - ); + array_unshift($sqls, $this->createSqlFromSpecificationAndParameters( + ['SELECT %1$s FROM (SELECT b.%1$s, rownum b_rownum FROM (' => current($this->specifications[self::SPECIFICATION_SELECT])], $selectParameters + )); + + if ($context->getParameterContainer()) { + $parameterContainer = $context->getParameterContainer(); + if ($LIMIT === null) { + array_push($sqls, ') b ) WHERE b_rownum > (:offset)'); + $parameterContainer->offsetSet('offset', $OFFSET, $parameterContainer::TYPE_INTEGER); } else { // create bottom part of query, with offset and limit using row_number - array_push( - $sqls, - ') b WHERE rownum <= (:offset' - . $number - . '+:limit' - . $number - . ')) WHERE b_rownum >= (:offset' - . $number - . ' + 1)' - ); - $parameterContainer->offsetSet( - 'offset' . $number, - $this->offset, - $parameterContainer::TYPE_INTEGER - ); - $parameterContainer->offsetSet( - 'limit' . $number, - $this->limit, - $parameterContainer::TYPE_INTEGER - ); + array_push($sqls, ') b WHERE rownum <= (:offset+:limit)) WHERE b_rownum >= (:offset + 1)'); + $parameterContainer->offsetSet('offset', $OFFSET, $parameterContainer::TYPE_INTEGER); + $parameterContainer->offsetSet('limit', $LIMIT, $parameterContainer::TYPE_INTEGER); } - $this->processInfo['subselectCount']++; } else { - if ($this->limit === null) { - array_push($sqls, ') b ) WHERE b_rownum > (' . (int) $this->offset . ')'); + if ($LIMIT === null) { + array_push($sqls, ') b ) WHERE b_rownum > ('. (int) $OFFSET. ')' + ); } else { - array_push( - $sqls, - ') b WHERE rownum <= (' - . (int) $this->offset - . '+' - . (int) $this->limit - . ')) WHERE b_rownum >= (' - . (int) $this->offset - . ' + 1)' + array_push($sqls, ') b WHERE rownum <= (' + . (int) $OFFSET + . '+' + . (int) $LIMIT + . ')) WHERE b_rownum >= (' + . (int) $OFFSET + . ' + 1)' ); } } - $sqls[self::SELECT] = $this->createSqlFromSpecificationAndParameters( - $this->specifications[self::SELECT], - $parameters[self::SELECT] + $sqls[self::SPECIFICATION_SELECT] = $this->createSqlFromSpecificationAndParameters( + $this->specifications[self::SPECIFICATION_SELECT], + $parameters[self::SPECIFICATION_SELECT] ); } } diff --git a/src/Sql/Builder/SqlServer/Ddl/CreateTableBuilder.php b/src/Sql/Builder/SqlServer/Ddl/CreateTableBuilder.php index 0c8df0e70b..ec767e3e47 100644 --- a/src/Sql/Builder/SqlServer/Ddl/CreateTableBuilder.php +++ b/src/Sql/Builder/SqlServer/Ddl/CreateTableBuilder.php @@ -9,37 +9,23 @@ namespace Zend\Db\Sql\Builder\SqlServer\Ddl; -use Zend\Db\Adapter\Platform\PlatformInterface; +use Zend\Db\Sql\Builder\sql92\Ddl\CreateTableBuilder as BaseBuilder; +use Zend\Db\Sql\Builder\Context; use Zend\Db\Sql\Ddl\CreateTable; -use Zend\Db\Sql\Builder\PlatformDecoratorInterface; -class CreateTableBuilder extends CreateTable implements PlatformDecoratorInterface +class CreateTableBuilder extends BaseBuilder { /** - * @var CreateTable - */ - protected $subject; - - /** - * @param CreateTable $subject - * @return self - */ - public function setSubject($subject) - { - $this->subject = $subject; - return $this; - } - - /** - * @param PlatformInterface $adapterPlatform + * @param CreateTable $sqlObject + * @param Context $context * @return array */ - protected function processTable(PlatformInterface $adapterPlatform = null) + protected function build_Table(CreateTable $sqlObject, Context $context) { - $table = ($this->isTemporary ? '#' : '') . ltrim($this->table, '#'); + $table = ($sqlObject->isTemporary ? '#' : '') . ltrim($sqlObject->table, '#'); return [ '', - $adapterPlatform->quoteIdentifier($table), + $context->getPlatform()->quoteIdentifier($table), ]; } } diff --git a/src/Sql/Builder/SqlServer/SelectBuilder.php b/src/Sql/Builder/SqlServer/SelectBuilder.php index 070dd9827d..31e1f81ee6 100644 --- a/src/Sql/Builder/SqlServer/SelectBuilder.php +++ b/src/Sql/Builder/SqlServer/SelectBuilder.php @@ -9,52 +9,26 @@ namespace Zend\Db\Sql\Builder\SqlServer; -use Zend\Db\Adapter\Driver\DriverInterface; -use Zend\Db\Adapter\ParameterContainer; -use Zend\Db\Adapter\Platform\PlatformInterface; -use Zend\Db\Sql\Builder\PlatformDecoratorInterface; +use Zend\Db\Sql\Builder\sql92\SelectBuilder as BaseBuilder; +use Zend\Db\Sql\Builder\Context; use Zend\Db\Sql\Select; -class SelectBuilder extends Select implements PlatformDecoratorInterface +class SelectBuilder extends BaseBuilder { - /** - * @var Select - */ - protected $subject = null; - - /** - * @param Select $select - */ - public function setSubject($select) + protected function build_Limit(Select $sqlObject, Context $context) { - $this->subject = $select; - } - - protected function localizeVariables() - { - parent::localizeVariables(); - // set specifications - unset($this->specifications[self::LIMIT]); - unset($this->specifications[self::OFFSET]); - - $this->specifications['LIMITOFFSET'] = null; + return; } - /** - * @param PlatformInterface $platform - * @param DriverInterface $driver - * @param ParameterContainer $parameterContainer - * @param $sqls - * @param $parameters - * @return null - */ - protected function processLimitOffset(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null, &$sqls, &$parameters) + protected function build_Offset(Select $sqlObject, Context $context, &$sqls = null, &$parameters = null) { - if ($this->limit === null && $this->offset === null) { + $LIMIT = $sqlObject->limit; + $OFFSET = $sqlObject->offset; + if ($LIMIT === null && $OFFSET === null) { return; } - $selectParameters = $parameters[self::SELECT]; + $selectParameters = $parameters[self::SPECIFICATION_SELECT]; /** if this is a DISTINCT query then real SELECT part goes to second element in array **/ $parameterIndex = 0; @@ -64,10 +38,10 @@ protected function processLimitOffset(PlatformInterface $platform, DriverInterfa $parameterIndex = 1; } - $starSuffix = $platform->getIdentifierSeparator() . self::SQL_STAR; + $starSuffix = $context->getPlatform()->getIdentifierSeparator() . Select::SQL_STAR; foreach ($selectParameters[0] as $i => $columnParameters) { - if ($columnParameters[0] == self::SQL_STAR || (isset($columnParameters[1]) && $columnParameters[1] == self::SQL_STAR) || strpos($columnParameters[0], $starSuffix)) { - $selectParameters[0] = [[self::SQL_STAR]]; + if ($columnParameters[0] == Select::SQL_STAR || (isset($columnParameters[1]) && $columnParameters[1] == Select::SQL_STAR) || strpos($columnParameters[0], $starSuffix)) { + $selectParameters[0] = [[Select::SQL_STAR]]; break; } if (isset($columnParameters[1])) { @@ -78,40 +52,41 @@ protected function processLimitOffset(PlatformInterface $platform, DriverInterfa // first, produce column list without compound names (using the AS portion only) array_unshift($sqls, $this->createSqlFromSpecificationAndParameters( - ['SELECT %1$s FROM (' => current($this->specifications[self::SELECT])], + ['SELECT %1$s FROM (' => current($this->specifications[self::SPECIFICATION_SELECT])], $selectParameters )); - if ($parameterContainer) { + if ($context->getParameterContainer()) { + $parameterContainer = $context->getParameterContainer(); // create bottom part of query, with offset and limit using row_number - $limitParamName = $driver->formatParameterName('limit'); - $offsetParamName = $driver->formatParameterName('offset'); - $offsetForSumParamName = $driver->formatParameterName('offsetForSum'); + $limitParamName = $context->getDriver()->formatParameterName('limit'); + $offsetParamName = $context->getDriver()->formatParameterName('offset'); + $offsetForSumParamName = $context->getDriver()->formatParameterName('offsetForSum'); array_push($sqls, ') AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ' . $offsetParamName . '+1 AND ' . $limitParamName . '+' . $offsetForSumParamName); - $parameterContainer->offsetSet('offset', $this->offset); - $parameterContainer->offsetSet('limit', $this->limit); + $parameterContainer->offsetSet('offset', $OFFSET); + $parameterContainer->offsetSet('limit', $LIMIT); $parameterContainer->offsetSetReference('offsetForSum', 'offset'); } else { array_push($sqls, ') AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ' - . (int) $this->offset . '+1 AND ' - . (int) $this->limit . '+' . (int) $this->offset + . (int) $OFFSET . '+1 AND ' + . (int) $LIMIT . '+' . (int) $OFFSET ); } - if (isset($sqls[self::ORDER])) { - $orderBy = $sqls[self::ORDER]; - unset($sqls[self::ORDER]); + if (isset($sqls[self::SPECIFICATION_ORDER])) { + $orderBy = $sqls[self::SPECIFICATION_ORDER]; + unset($sqls[self::SPECIFICATION_ORDER]); } else { $orderBy = 'ORDER BY (SELECT 1)'; } // add a column for row_number() using the order specification - $parameters[self::SELECT][$parameterIndex][] = ['ROW_NUMBER() OVER (' . $orderBy . ')', '[__ZEND_ROW_NUMBER]']; + $parameters[self::SPECIFICATION_SELECT][$parameterIndex][] = ['ROW_NUMBER() OVER (' . $orderBy . ')', '[__ZEND_ROW_NUMBER]']; - $sqls[self::SELECT] = $this->createSqlFromSpecificationAndParameters( - $this->specifications[self::SELECT], - $parameters[self::SELECT] + $sqls[self::SPECIFICATION_SELECT] = $this->createSqlFromSpecificationAndParameters( + $this->specifications[self::SPECIFICATION_SELECT], + $parameters[self::SPECIFICATION_SELECT] ); } } diff --git a/src/Sql/Builder/Sqlite/SelectBuilder.php b/src/Sql/Builder/Sqlite/SelectBuilder.php deleted file mode 100644 index 387d032abf..0000000000 --- a/src/Sql/Builder/Sqlite/SelectBuilder.php +++ /dev/null @@ -1,62 +0,0 @@ -subject = $select; - - return $this; - } - - /** - * {@inheritDoc} - */ - protected function localizeVariables() - { - parent::localizeVariables(); - $this->specifications[self::COMBINE] = '%1$s %2$s'; - } - - /** - * {@inheritDoc} - */ - protected function processStatementStart(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - return ''; - } - - /** - * {@inheritDoc} - */ - protected function processStatementEnd(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - return ''; - } -} diff --git a/src/Sql/Builder/sql92/CombineBuilder.php b/src/Sql/Builder/sql92/CombineBuilder.php new file mode 100644 index 0000000000..cad88b084f --- /dev/null +++ b/src/Sql/Builder/sql92/CombineBuilder.php @@ -0,0 +1,49 @@ + '%1$s (%2$s) ', + ]; + + /** + * @param \Zend\Db\Sql\Combine $sqlObject + * @param Context $context + * @return string + */ + protected function buildSqlString($sqlObject, Context $context) + { + $COMBINE = $sqlObject->combine; + if (!$COMBINE) { + return; + } + + $sql = ''; + foreach ($COMBINE as $i => $combine) { + $type = $i == 0 + ? '' + : strtoupper($combine['type'] . ($combine['modifier'] ? ' ' . $combine['modifier'] : '')); + $select = $this->buildSubSelect($combine['select'], $context); + $sql .= sprintf( + $this->specifications[self::SPECIFICATION_COMBINE], + $type, + $select + ); + } + return trim($sql, ' '); + } +} diff --git a/src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php b/src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php new file mode 100644 index 0000000000..3be4a88f10 --- /dev/null +++ b/src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php @@ -0,0 +1,141 @@ + "ALTER TABLE %1\$s\n", + self::SPECIFICATION_ADD_COLUMNS => [ + "%1\$s" => [ + [1 => "ADD COLUMN %1\$s,\n", 'combinedby' => ""] + ] + ], + self::SPECIFICATION_CHANGE_COLUMNS => [ + "%1\$s" => [ + [2 => "CHANGE COLUMN %1\$s %2\$s,\n", 'combinedby' => ""], + ] + ], + self::SPECIFICATION_DROP_COLUMNS => [ + "%1\$s" => [ + [1 => "DROP COLUMN %1\$s,\n", 'combinedby' => ""], + ] + ], + self::SPECIFICATION_ADD_CONSTRAINTS => [ + "%1\$s" => [ + [1 => "ADD %1\$s,\n", 'combinedby' => ""], + ] + ], + self::SPECIFICATION_DROP_CONSTRAINTS => [ + "%1\$s" => [ + [1 => "DROP CONSTRAINT %1\$s,\n", 'combinedby' => ""], + ] + ] + ]; + + /** + * @param AlterTable $sqlObject + * @param Context $context + * @return array + */ + protected function build_Table(AlterTable $sqlObject, Context $context) + { + return [$context->getPlatform()->quoteIdentifier($sqlObject->table)]; + } + + /** + * @param AlterTable $sqlObject + * @param Context $context + * @return array + */ + protected function build_AddColumns(AlterTable $sqlObject, Context $context) + { + $sqls = []; + foreach ($sqlObject->addColumns as $column) { + $sqls[] = $this->buildSqlString($column, $context); + } + + return [$sqls]; + } + + /** + * @param AlterTable $sqlObject + * @param Context $context + * @return array + */ + protected function build_ChangeColumns(AlterTable $sqlObject, Context $context) + { + $sqls = []; + foreach ($sqlObject->changeColumns as $name => $column) { + $sqls[] = [ + $context->getPlatform()->quoteIdentifier($name), + $this->buildSqlString($column, $context) + ]; + } + + return [$sqls]; + } + + /** + * @param AlterTable $sqlObject + * @param Context $context + * @return array + */ + protected function build_DropColumns(AlterTable $sqlObject, Context $context) + { + $sqls = []; + foreach ($sqlObject->dropColumns as $column) { + $sqls[] = $context->getPlatform()->quoteIdentifier($column); + } + + return [$sqls]; + } + + /** + * @param AlterTable $sqlObject + * @param Context $context + * @return array + */ + protected function build_AddConstraints(AlterTable $sqlObject, Context $context) + { + $sqls = []; + foreach ($sqlObject->addConstraints as $constraint) { + $sqls[] = $this->buildSqlString($constraint, $context); + } + + return [$sqls]; + } + + /** + * @param AlterTable $sqlObject + * @param Context $context + * @return array + */ + protected function build_DropConstraints(AlterTable $sqlObject, Context $context) + { + $sqls = []; + foreach ($sqlObject->dropConstraints as $constraint) { + $sqls[] = $context->getPlatform()->quoteIdentifier($constraint); + } + + return [$sqls]; + } +} diff --git a/src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php b/src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php new file mode 100644 index 0000000000..478dc1bd3f --- /dev/null +++ b/src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php @@ -0,0 +1,114 @@ + 'CREATE %1$sTABLE %2$s (', + self::SPECIFICATION_COLUMNS => [ + "\n %1\$s" => [ + [1 => '%1$s', 'combinedby' => ",\n "] + ] + ], + 'combinedBy' => ",", + self::SPECIFICATION_CONSTRAINTS => [ + "\n %1\$s" => [ + [1 => '%1$s', 'combinedby' => ",\n "] + ] + ], + 'statementEnd' => '%1$s', + ]; + + /** + * @param CreateTable $sqlObject + * @param Context $context + * @return array + */ + protected function build_Table(CreateTable $sqlObject, Context $context) + { + return [ + $sqlObject->isTemporary ? 'TEMPORARY ' : '', + $context->getPlatform()->quoteIdentifier($sqlObject->table), + ]; + } + + /** + * @param CreateTable $sqlObject + * @param Context $context + * @return array + */ + protected function build_Columns(CreateTable $sqlObject, Context $context) + { + $COLUMNS = $sqlObject->columns; + if (! $COLUMNS) { + return; + } + + $sqls = []; + + foreach ($COLUMNS as $column) { + $sqls[] = $this->buildSqlString($column, $context); + } + + return [$sqls]; + } + + /** + * @param CreateTable $sqlObject + * @param Context $context + * @return string + */ + protected function build_Combinedby(CreateTable $sqlObject, Context $context) + { + if ($sqlObject->constraints && $sqlObject->columns) { + return $this->specifications['combinedBy']; + } + } + + /** + * @param CreateTable $sqlObject + * @param Context $context + * @return null|array + */ + protected function build_Constraints(CreateTable $sqlObject, Context $context) + { + $CONSTRAINTS = $sqlObject->constraints; + if (!$CONSTRAINTS) { + return; + } + + $sqls = []; + + foreach ($CONSTRAINTS as $constraint) { + $sqls[] = $this->buildSqlString($constraint, $context); + } + + return [$sqls]; + } + + /** + * @param CreateTable $sqlObject + * @param Context $context + * @return string + */ + protected function build_StatementEnd(CreateTable $sqlObject, Context $context) + { + return ["\n)"]; + } +} diff --git a/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php b/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php new file mode 100644 index 0000000000..e190bd97a2 --- /dev/null +++ b/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php @@ -0,0 +1,33 @@ + 'DROP TABLE %1$s' + ]; + + /** + * @param DropTable $sqlObject + * @param Context $context + * @return array + */ + protected function build_Table(DropTable $sqlObject, Context $context) + { + return [$context->getPlatform()->quoteIdentifier($sqlObject->table)]; + } +} diff --git a/src/Sql/Builder/sql92/DeleteBuilder.php b/src/Sql/Builder/sql92/DeleteBuilder.php new file mode 100644 index 0000000000..e0f35f74d0 --- /dev/null +++ b/src/Sql/Builder/sql92/DeleteBuilder.php @@ -0,0 +1,56 @@ + 'DELETE FROM %1$s', + self::SPECIFICATION_WHERE => 'WHERE %1$s' + ]; + + /** + * @param Delete $sqlObject + * @param Context $context + * @return array + */ + protected function build_Delete(Delete $sqlObject, Context $context) + { + return sprintf( + $this->specifications[self::SPECIFICATION_DELETE], + $this->resolveTable($sqlObject->table, $context) + ); + } + + /** + * @param Delete $sqlObject + * @param Context $context + * @return array + */ + protected function build_Where(Delete $sqlObject, Context $context) + { + $WHERE = $sqlObject->where; + if ($WHERE->count() == 0) { + return; + } + + return sprintf( + $this->specifications[self::SPECIFICATION_WHERE], + $this->buildSqlString($WHERE, $context) + ); + } +} diff --git a/src/Sql/Builder/sql92/InsertBuilder.php b/src/Sql/Builder/sql92/InsertBuilder.php new file mode 100644 index 0000000000..4ec73ab5b7 --- /dev/null +++ b/src/Sql/Builder/sql92/InsertBuilder.php @@ -0,0 +1,87 @@ + 'INSERT INTO %1$s (%2$s) VALUES (%3$s)', + self::SPECIFICATION_SELECT => 'INSERT INTO %1$s %2$s %3$s', + ]; + + /** + * @param Insert $sqlObject + * @param Context $context + * @return null|string + * @throws Exception\InvalidArgumentException + */ + protected function build_Insert(Insert $sqlObject, Context $context) + { + if ($sqlObject->select) { + return; + } + + if (!$sqlObject->columns) { + throw new Exception\InvalidArgumentException('values or select should be present'); + } + + $columns = []; + $values = []; + foreach (array_combine($sqlObject->columns, $sqlObject->values) as $column=>$value) { + $columns[] = $context->getPlatform()->quoteIdentifier($column); + if (is_scalar($value) && $context->getParameterContainer()) { + $values[] = $context->getDriver()->formatParameterName($column); + $context->getParameterContainer()->offsetSet($column, $value); + } else { + $values[] = $this->resolveColumnValue($value, $context); + } + } + + return sprintf( + $this->specifications[self::SPECIFICATION_INSERT], + $this->resolveTable($sqlObject->table, $context), + implode(', ', $columns), + implode(', ', $values) + ); + } + + /** + * @param Insert $sqlObject + * @param Context $context + * @return null|array + */ + protected function build_Select(Insert $sqlObject, Context $context) + { + if (!$sqlObject->select) { + return; + } + $selectSql = $this->buildSubSelect($sqlObject->select, $context); + + $columns = array_map([$context->getPlatform(), 'quoteIdentifier'], $sqlObject->columns); + $columns = implode(', ', $columns); + + return sprintf( + $this->specifications[self::SPECIFICATION_SELECT], + $this->resolveTable($sqlObject->table, $context), + $columns ? "($columns)" : "", + $selectSql + ); + } +} diff --git a/src/Sql/Builder/sql92/SelectBuilder.php b/src/Sql/Builder/sql92/SelectBuilder.php new file mode 100644 index 0000000000..b257cbb453 --- /dev/null +++ b/src/Sql/Builder/sql92/SelectBuilder.php @@ -0,0 +1,367 @@ + '%1$s', + self::SPECIFICATION_SELECT => [ + 'SELECT %1$s FROM %2$s' => [ + [1 => '%1$s', 2 => '%1$s AS %2$s', 'combinedby' => ', '], + null + ], + 'SELECT %1$s %2$s FROM %3$s' => [ + null, + [1 => '%1$s', 2 => '%1$s AS %2$s', 'combinedby' => ', '], + null + ], + 'SELECT %1$s' => [ + [1 => '%1$s', 2 => '%1$s AS %2$s', 'combinedby' => ', '], + ], + ], + self::SPECIFICATION_JOINS => [ + '%1$s' => [ + [3 => '%1$s JOIN %2$s ON %3$s', 'combinedby' => ' '] + ] + ], + self::SPECIFICATION_WHERE => 'WHERE %1$s', + self::SPECIFICATION_GROUP => [ + 'GROUP BY %1$s' => [ + [1 => '%1$s', 'combinedby' => ', '] + ] + ], + self::SPECIFICATION_HAVING => 'HAVING %1$s', + self::SPECIFICATION_ORDER => [ + 'ORDER BY %1$s' => [ + [1 => '%1$s', 2 => '%1$s %2$s', 'combinedby' => ', '] + ] + ], + self::SPECIFICATION_LIMIT => 'LIMIT %1$s', + self::SPECIFICATION_OFFSET => 'OFFSET %1$s', + 'statementEnd' => '%1$s', + self::SPECIFICATION_COMBINE => '%1$s ( %2$s )', + ]; + + /** + * @param Select $sqlObject + * @param Context $context + * @return array|null + */ + protected function build_StatementStart($sqlObject, Context $context) + { + if ($sqlObject->combine !== []) { + return ['(']; + } + } + + /** + * @param Select $sqlObject + * @param Context $context + * @return array|null + */ + protected function build_StatementEnd($sqlObject, Context $context) + { + if ($sqlObject->combine !== []) { + return [')']; + } + } + + /** + * @param Select $sqlObject + * @param Context $context + * @return array + */ + protected function build_Select(Select $sqlObject, Context $context) + { + list($table, $fromTable) = $this->resolveTable($sqlObject->table, $context, $sqlObject); + // build_ table columns + $columns = []; + foreach ($sqlObject->columns as $columnIndexOrAs => $column) { + if ($column === Select::SQL_STAR) { + $columns[] = [$fromTable . Select::SQL_STAR]; + continue; + } + + $columnName = $this->resolveColumnValue( + [ + 'column' => $column, + 'fromTable' => $fromTable, + 'isIdentifier' => true, + ], + $context + ); + // build_ As portion + if (is_string($columnIndexOrAs)) { + $columnAs = $context->getPlatform()->quoteIdentifier($columnIndexOrAs); + } elseif (stripos($columnName, ' as ') === false) { + $columnAs = (is_string($column)) ? $context->getPlatform()->quoteIdentifier($column) : $context->getNestedAlias('column'); + } + $columns[] = (isset($columnAs)) ? [$columnName, $columnAs] : [$columnName]; + } + + // build_ join columns + foreach ($sqlObject->joins as $join) { + $joinName = parent::resolveTable( + is_array($join['name']) ? key($join['name']) : $join['name'], + $context + ); + + foreach ($join['columns'] as $jKey => $jColumn) { + $jColumns = []; + $jFromTable = is_scalar($jColumn) + ? $joinName . $context->getPlatform()->getIdentifierSeparator() + : ''; + $jColumns[] = $this->resolveColumnValue( + [ + 'column' => $jColumn, + 'fromTable' => $jFromTable, + 'isIdentifier' => true, + ], + $context + ); + if (is_string($jKey)) { + $jColumns[] = $context->getPlatform()->quoteIdentifier($jKey); + } elseif ($jColumn !== Select::SQL_STAR) { + $jColumns[] = $context->getPlatform()->quoteIdentifier($jColumn); + } + $columns[] = $jColumns; + } + } + + if ($quantifier = $sqlObject->quantifier) { + $quantifier = ($quantifier instanceof ExpressionInterface) + ? $this->buildSqlString($quantifier, $context) + : $quantifier; + } + + if (!isset($table)) { + return [$columns]; + } elseif (isset($quantifier)) { + return [$quantifier, $columns, $table]; + } else { + return [$columns, $table]; + } + } + + /** + * @param Select $sqlObject + * @param Context $context + * @return array|null + */ + protected function build_Where(Select $sqlObject, Context $context) + { + if ($sqlObject->where->count() == 0) { + return; + } + return [ + $this->buildSqlString($sqlObject->where, $context) + ]; + } + + /** + * @param Select $sqlObject + * @param Context $context + * @return array|null + */ + protected function build_Group(Select $sqlObject, Context $context) + { + if ($sqlObject->group === null) { + return; + } + // build_ table columns + $groups = []; + foreach ($sqlObject->group as $column) { + $groups[] = $this->resolveColumnValue( + [ + 'column' => $column, + 'isIdentifier' => true, + ], + $context + ); + } + return [$groups]; + } + + /** + * @param Select $sqlObject + * @param Context $context + * @return array|null + */ + protected function build_Having(Select $sqlObject, Context $context) + { + if ($sqlObject->having->count() == 0) { + return; + } + return [ + $this->buildSqlString($sqlObject->having, $context) + ]; + } + + /** + * @param Select $sqlObject + * @param Context $context + * @return array|null + */ + protected function build_Order(Select $sqlObject, Context $context) + { + if (!$sqlObject->order) { + return; + } + $orders = []; + foreach ($sqlObject->order as $k => $v) { + if ($v instanceof ExpressionInterface) { + $orders[] = [ + $this->buildSqlString($v, $context) + ]; + continue; + } + if (is_int($k)) { + if (strpos($v, ' ') !== false) { + list($k, $v) = preg_split('# #', $v, 2); + } else { + $k = $v; + $v = Select::ORDER_ASCENDING; + } + } + if (strtoupper($v) == Select::ORDER_DESCENDING) { + $orders[] = [$context->getPlatform()->quoteIdentifierInFragment($k), Select::ORDER_DESCENDING]; + } else { + $orders[] = [$context->getPlatform()->quoteIdentifierInFragment($k), Select::ORDER_ASCENDING]; + } + } + return [$orders]; + } + + /** + * @param Select $sqlObject + * @param Context $context + * @return array|null + */ + protected function build_Limit(Select $sqlObject, Context $context) + { + $limit = $sqlObject->limit; + if ($limit === null) { + return; + } + if ($context->getParameterContainer()) { + $context->getParameterContainer()->offsetSet('limit', $limit, Adapter\ParameterContainer::TYPE_INTEGER); + return [$context->getDriver()->formatParameterName('limit')]; + } + return [$context->getPlatform()->quoteValue($limit)]; + } + + /** + * @param Select $sqlObject + * @param Context $context + * @return array|null + */ + protected function build_Offset(Select $sqlObject, Context $context) + { + $offset = $sqlObject->offset; + if ($offset === null) { + return; + } + if ($context->getParameterContainer()) { + $context->getParameterContainer()->offsetSet('offset', $offset, Adapter\ParameterContainer::TYPE_INTEGER); + return [$context->getDriver()->formatParameterName('offset')]; + } + + return [$context->getPlatform()->quoteValue($offset)]; + } + + /** + * @param Select $sqlObject + * @param Context $context + * @return array|null + */ + protected function build_Combine(Select $sqlObject, Context $context) + { + $COMBINE = $sqlObject->combine; + if ($COMBINE == []) { + return; + } + + $type = $COMBINE['type']; + if ($COMBINE['modifier']) { + $type .= ' ' . $COMBINE['modifier']; + } + + return [ + strtoupper($type), + $this->buildSubSelect($COMBINE['select'], $context), + ]; + } + + /** + * @param array|string|TableIdentifier|Select $table + * @param Context $context + * @param mixed $object + * @return array + */ + protected function resolveTable($table, Context $context, $object = null) + { + $alias = null; + + if (is_array($table)) { + $alias = key($table); + $table = current($table); + } + + $table = parent::resolveTable($table, $context); + + if ($alias) { + $fromTable = $context->getPlatform()->quoteIdentifier($alias); + $table = $this->renderTable($table, $fromTable); + } else { + $fromTable = $table; + } + + if ($object->prefixColumnsWithTable && $fromTable) { + $fromTable .= $context->getPlatform()->getIdentifierSeparator(); + } else { + $fromTable = ''; + } + + return [ + $table, + $fromTable + ]; + } + + /** + * @param string $table + * @param null|string $alias + * @return string + */ + protected function renderTable($table, $alias = null) + { + return $table . ($alias ? ' AS ' . $alias : ''); + } +} diff --git a/src/Sql/Builder/sql92/UpdateBuilder.php b/src/Sql/Builder/sql92/UpdateBuilder.php new file mode 100644 index 0000000000..a1b65a6b5f --- /dev/null +++ b/src/Sql/Builder/sql92/UpdateBuilder.php @@ -0,0 +1,89 @@ + 'UPDATE %1$s', + self::SPECIFICATION_JOIN => [ + '%1$s' => [ + [3 => '%1$s JOIN %2$s ON %3$s', 'combinedby' => ' '] + ] + ], + self::SPECIFICATION_SET => 'SET %1$s', + self::SPECIFICATION_WHERE => 'WHERE %1$s', + ]; + + /** + * @param Update $sqlObject + * @param Context $context + * @return string + */ + protected function build_Update(Update $sqlObject, Context $context) + { + return sprintf( + $this->specifications[static::SPECIFICATION_UPDATE], + $this->resolveTable($sqlObject->table, $context) + ); + } + + /** + * @param Update $sqlObject + * @param Context $context + * @return string + */ + protected function build_Set(Update $sqlObject, Context $context) + { + $setSql = []; + foreach ($sqlObject->set as $column => $value) { + $prefix = $context->getPlatform()->quoteIdentifier($column) . ' = '; + if (is_scalar($value) && $context->getParameterContainer()) { + $setSql[] = $prefix . $context->getDriver()->formatParameterName($column); + $context->getParameterContainer()->offsetSet($column, $value); + } else { + $setSql[] = $prefix . $this->resolveColumnValue( + $value, + $context + ); + } + } + + return sprintf( + $this->specifications[self::SPECIFICATION_SET], + implode(', ', $setSql) + ); + } + + /** + * @param Update $sqlObject + * @param Context $context + * @return string|null + */ + protected function build_Where(Update $sqlObject, Context $context) + { + if ($sqlObject->where->count() == 0) { + return; + } + return sprintf( + $this->specifications[self::SPECIFICATION_WHERE], + $this->buildSqlString($sqlObject->where, $context) + ); + } +} diff --git a/src/Sql/Combine.php b/src/Sql/Combine.php index 3e540993e2..3d875578ac 100644 --- a/src/Sql/Combine.php +++ b/src/Sql/Combine.php @@ -9,32 +9,28 @@ namespace Zend\Db\Sql; -use Zend\Db\Adapter\Platform\PlatformInterface; -use Zend\Db\Adapter\Driver\DriverInterface; -use Zend\Db\Adapter\ParameterContainer; - /** * Combine SQL statement - allows combining multiple select statements into one + * + * @property array $columns + * @property SelectableInterface[][] $combine */ -class Combine extends AbstractPreparableSqlObject +class Combine extends AbstractSqlObject implements PreparableSqlObjectInterface, SelectableInterface { - const COLUMNS = 'columns'; - const COMBINE = 'combine'; const COMBINE_UNION = 'union'; const COMBINE_EXCEPT = 'except'; const COMBINE_INTERSECT = 'intersect'; - /** - * @var string[] - */ - protected $specifications = [ - self::COMBINE => '%1$s (%2$s) ', - ]; /** - * @var Select[][] + * @var SelectableInterface[][] */ - private $combine = []; + protected $combine = []; + + protected $__getProperties = [ + 'combine', + 'columns' + ]; /** * @param Select|array|null $select @@ -43,6 +39,7 @@ class Combine extends AbstractPreparableSqlObject */ public function __construct($select = null, $type = self::COMBINE_UNION, $modifier = '') { + parent::__construct(); if ($select) { $this->combine($select, $type, $modifier); } @@ -51,7 +48,7 @@ public function __construct($select = null, $type = self::COMBINE_UNION, $modifi /** * Create combine clause * - * @param Select|array $select + * @param SelectableInterface|array $select * @param string $type * @param string $modifier * @@ -61,7 +58,7 @@ public function combine($select, $type = self::COMBINE_UNION, $modifier = '') { if (is_array($select)) { foreach ($select as $combine) { - if ($combine instanceof Select) { + if ($combine instanceof SelectableInterface) { $combine = [$combine]; } @@ -74,7 +71,7 @@ public function combine($select, $type = self::COMBINE_UNION, $modifier = '') return $this; } - if (! $select instanceof Select) { + if (! $select instanceof SelectableInterface) { throw new Exception\InvalidArgumentException(sprintf( '$select must be a array or instance of Select, "%s" given', is_object($select) ? get_class($select) : gettype($select) @@ -92,7 +89,7 @@ public function combine($select, $type = self::COMBINE_UNION, $modifier = '') /** * Create union clause * - * @param Select|array $select + * @param SelectableInterface|array $select * @param string $modifier * * @return self @@ -105,7 +102,7 @@ public function union($select, $modifier = '') /** * Create except clause * - * @param Select|array $select + * @param SelectableInterface|array $select * @param string $modifier * * @return self @@ -118,7 +115,7 @@ public function except($select, $modifier = '') /** * Create intersect clause * - * @param Select|array $select + * @param SelectableInterface|array $select * @param string $modifier * @return self */ @@ -127,36 +124,6 @@ public function intersect($select, $modifier = '') return $this->combine($select, self::COMBINE_INTERSECT, $modifier); } - /** - * Build sql string - * - * @param PlatformInterface $platform - * @param DriverInterface $driver - * @param ParameterContainer $parameterContainer - * - * @return string - */ - protected function buildSqlString(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - if (!$this->combine) { - return; - } - - $sql = ''; - foreach ($this->combine as $i => $combine) { - $type = $i == 0 - ? '' - : strtoupper($combine['type'] . ($combine['modifier'] ? ' ' . $combine['modifier'] : '')); - $select = $this->processSubSelect($combine['select'], $platform, $driver, $parameterContainer); - $sql .= sprintf( - $this->specifications[self::COMBINE], - $type, - $select - ); - } - return trim($sql, ' '); - } - /** * @return $this */ @@ -170,12 +137,12 @@ public function alignColumns() foreach ($this->combine as $combine) { $allColumns = array_merge( $allColumns, - $combine['select']->getRawState(self::COLUMNS) + $combine['select']->columns ); } foreach ($this->combine as $combine) { - $combineColumns = $combine['select']->getRawState(self::COLUMNS); + $combineColumns = $combine['select']->columns; $aligned = []; foreach ($allColumns as $alias => $column) { $aligned[$alias] = isset($combineColumns[$alias]) @@ -187,21 +154,13 @@ public function alignColumns() return $this; } - /** - * Get raw state - * - * @param string $key - * - * @return array - */ - public function getRawState($key = null) + public function __get($name) { - $rawState = [ - self::COMBINE => $this->combine, - self::COLUMNS => $this->combine - ? $this->combine[0]['select']->getRawState(self::COLUMNS) - : [], - ]; - return (isset($key) && array_key_exists($key, $rawState)) ? $rawState[$key] : $rawState; + if ($name == 'columns') { + return $this->combine + ? $this->combine[0]['select']->columns + : []; + } + return parent::__get($name); } } diff --git a/src/Sql/Ddl/AlterTable.php b/src/Sql/Ddl/AlterTable.php index 381f35d677..cf156dae31 100644 --- a/src/Sql/Ddl/AlterTable.php +++ b/src/Sql/Ddl/AlterTable.php @@ -9,18 +9,18 @@ namespace Zend\Db\Sql\Ddl; -use Zend\Db\Adapter\Platform\PlatformInterface; use Zend\Db\Sql\AbstractSqlObject; -class AlterTable extends AbstractSqlObject implements SqlObjectInterface +/** + * @property null|string|array|TableIdentifier $table + * @property array $addColumns + * @property array $dropColumns + * @property array $changeColumns + * @property array $addConstraints + * @property array $dropConstraints + */ +class AlterTable extends AbstractSqlObject { - const ADD_COLUMNS = 'addColumns'; - const ADD_CONSTRAINTS = 'addConstraints'; - const CHANGE_COLUMNS = 'changeColumns'; - const DROP_COLUMNS = 'dropColumns'; - const DROP_CONSTRAINTS = 'dropConstraints'; - const TABLE = 'table'; - /** * @var array */ @@ -46,49 +46,27 @@ class AlterTable extends AbstractSqlObject implements SqlObjectInterface */ protected $dropConstraints = []; - /** - * Specifications for Sql String generation - * @var array - */ - protected $specifications = [ - self::TABLE => "ALTER TABLE %1\$s\n", - self::ADD_COLUMNS => [ - "%1\$s" => [ - [1 => "ADD COLUMN %1\$s,\n", 'combinedby' => ""] - ] - ], - self::CHANGE_COLUMNS => [ - "%1\$s" => [ - [2 => "CHANGE COLUMN %1\$s %2\$s,\n", 'combinedby' => ""], - ] - ], - self::DROP_COLUMNS => [ - "%1\$s" => [ - [1 => "DROP COLUMN %1\$s,\n", 'combinedby' => ""], - ] - ], - self::ADD_CONSTRAINTS => [ - "%1\$s" => [ - [1 => "ADD %1\$s,\n", 'combinedby' => ""], - ] - ], - self::DROP_CONSTRAINTS => [ - "%1\$s" => [ - [1 => "DROP CONSTRAINT %1\$s,\n", 'combinedby' => ""], - ] - ] - ]; /** * @var string */ protected $table = ''; + protected $__getProperties = [ + 'table', + 'addColumns', + 'dropColumns', + 'changeColumns', + 'addConstraints', + 'dropConstraints', + ]; + /** * @param string $table */ public function __construct($table = '') { + parent::__construct(); ($table) ? $this->setTable($table) : null; } @@ -158,80 +136,4 @@ public function addConstraint(Constraint\ConstraintInterface $constraint) return $this; } - - /** - * @param string|null $key - * @return array - */ - public function getRawState($key = null) - { - $rawState = [ - self::TABLE => $this->table, - self::ADD_COLUMNS => $this->addColumns, - self::DROP_COLUMNS => $this->dropColumns, - self::CHANGE_COLUMNS => $this->changeColumns, - self::ADD_CONSTRAINTS => $this->addConstraints, - self::DROP_CONSTRAINTS => $this->dropConstraints, - ]; - - return (isset($key) && array_key_exists($key, $rawState)) ? $rawState[$key] : $rawState; - } - - protected function processTable(PlatformInterface $adapterPlatform = null) - { - return [$adapterPlatform->quoteIdentifier($this->table)]; - } - - protected function processAddColumns(PlatformInterface $adapterPlatform = null) - { - $sqls = []; - foreach ($this->addColumns as $column) { - $sqls[] = $this->processExpression($column, $adapterPlatform); - } - - return [$sqls]; - } - - protected function processChangeColumns(PlatformInterface $adapterPlatform = null) - { - $sqls = []; - foreach ($this->changeColumns as $name => $column) { - $sqls[] = [ - $adapterPlatform->quoteIdentifier($name), - $this->processExpression($column, $adapterPlatform) - ]; - } - - return [$sqls]; - } - - protected function processDropColumns(PlatformInterface $adapterPlatform = null) - { - $sqls = []; - foreach ($this->dropColumns as $column) { - $sqls[] = $adapterPlatform->quoteIdentifier($column); - } - - return [$sqls]; - } - - protected function processAddConstraints(PlatformInterface $adapterPlatform = null) - { - $sqls = []; - foreach ($this->addConstraints as $constraint) { - $sqls[] = $this->processExpression($constraint, $adapterPlatform); - } - - return [$sqls]; - } - - protected function processDropConstraints(PlatformInterface $adapterPlatform = null) - { - $sqls = []; - foreach ($this->dropConstraints as $constraint) { - $sqls[] = $adapterPlatform->quoteIdentifier($constraint); - } - - return [$sqls]; - } } diff --git a/src/Sql/Ddl/CreateTable.php b/src/Sql/Ddl/CreateTable.php index e05e7905af..d0adb0de26 100644 --- a/src/Sql/Ddl/CreateTable.php +++ b/src/Sql/Ddl/CreateTable.php @@ -9,15 +9,16 @@ namespace Zend\Db\Sql\Ddl; -use Zend\Db\Adapter\Platform\PlatformInterface; use Zend\Db\Sql\AbstractSqlObject; -class CreateTable extends AbstractSqlObject implements SqlObjectInterface +/** + * @property null|string|array|TableIdentifier $table + * @property array $columns + * @property array $constraints + * @property bool $isTemporary + */ +class CreateTable extends AbstractSqlObject { - const COLUMNS = 'columns'; - const CONSTRAINTS = 'constraints'; - const TABLE = 'table'; - /** * @var Column\ColumnInterface[] */ @@ -33,23 +34,11 @@ class CreateTable extends AbstractSqlObject implements SqlObjectInterface */ protected $isTemporary = false; - /** - * {@inheritDoc} - */ - protected $specifications = [ - self::TABLE => 'CREATE %1$sTABLE %2$s (', - self::COLUMNS => [ - "\n %1\$s" => [ - [1 => '%1$s', 'combinedby' => ",\n "] - ] - ], - 'combinedBy' => ",", - self::CONSTRAINTS => [ - "\n %1\$s" => [ - [1 => '%1$s', 'combinedby' => ",\n "] - ] - ], - 'statementEnd' => '%1$s', + protected $__getProperties = [ + 'table', + 'columns', + 'constraints', + 'isTemporary', ]; /** @@ -63,6 +52,7 @@ class CreateTable extends AbstractSqlObject implements SqlObjectInterface */ public function __construct($table = '', $isTemporary = false) { + parent::__construct(); $this->table = $table; $this->setTemporary($isTemporary); } @@ -114,94 +104,4 @@ public function addConstraint(Constraint\ConstraintInterface $constraint) $this->constraints[] = $constraint; return $this; } - - /** - * @param string|null $key - * @return array - */ - public function getRawState($key = null) - { - $rawState = [ - self::COLUMNS => $this->columns, - self::CONSTRAINTS => $this->constraints, - self::TABLE => $this->table, - ]; - - return (isset($key) && array_key_exists($key, $rawState)) ? $rawState[$key] : $rawState; - } - - /** - * @param PlatformInterface $adapterPlatform - * - * @return string[] - */ - protected function processTable(PlatformInterface $adapterPlatform = null) - { - return [ - $this->isTemporary ? 'TEMPORARY ' : '', - $adapterPlatform->quoteIdentifier($this->table), - ]; - } - - /** - * @param PlatformInterface $adapterPlatform - * - * @return string[][]|null - */ - protected function processColumns(PlatformInterface $adapterPlatform = null) - { - if (! $this->columns) { - return; - } - - $sqls = []; - - foreach ($this->columns as $column) { - $sqls[] = $this->processExpression($column, $adapterPlatform); - } - - return [$sqls]; - } - - /** - * @param PlatformInterface $adapterPlatform - * - * @return array|string - */ - protected function processCombinedby(PlatformInterface $adapterPlatform = null) - { - if ($this->constraints && $this->columns) { - return $this->specifications['combinedBy']; - } - } - - /** - * @param PlatformInterface $adapterPlatform - * - * @return string[][]|null - */ - protected function processConstraints(PlatformInterface $adapterPlatform = null) - { - if (!$this->constraints) { - return; - } - - $sqls = []; - - foreach ($this->constraints as $constraint) { - $sqls[] = $this->processExpression($constraint, $adapterPlatform); - } - - return [$sqls]; - } - - /** - * @param PlatformInterface $adapterPlatform - * - * @return string[] - */ - protected function processStatementEnd(PlatformInterface $adapterPlatform = null) - { - return ["\n)"]; - } } diff --git a/src/Sql/Ddl/DropTable.php b/src/Sql/Ddl/DropTable.php index 970f72d69b..a6964324f6 100644 --- a/src/Sql/Ddl/DropTable.php +++ b/src/Sql/Ddl/DropTable.php @@ -9,35 +9,28 @@ namespace Zend\Db\Sql\Ddl; -use Zend\Db\Adapter\Platform\PlatformInterface; use Zend\Db\Sql\AbstractSqlObject; -class DropTable extends AbstractSqlObject implements SqlObjectInterface +/** + * @property null|string|array|TableIdentifier $table + */ +class DropTable extends AbstractSqlObject { - const TABLE = 'table'; - - /** - * @var array - */ - protected $specifications = [ - self::TABLE => 'DROP TABLE %1$s' - ]; - /** * @var string */ protected $table = ''; + protected $__getProperties = [ + 'table', + ]; + /** * @param string $table */ public function __construct($table = '') { + parent::__construct(); $this->table = $table; } - - protected function processTable(PlatformInterface $adapterPlatform = null) - { - return [$adapterPlatform->quoteIdentifier($this->table)]; - } } diff --git a/src/Sql/Delete.php b/src/Sql/Delete.php index 9a6dbda2fc..ffb7f62f39 100644 --- a/src/Sql/Delete.php +++ b/src/Sql/Delete.php @@ -9,51 +9,27 @@ namespace Zend\Db\Sql; -use Zend\Db\Adapter\ParameterContainer; -use Zend\Db\Adapter\Platform\PlatformInterface; -use Zend\Db\Adapter\Driver\DriverInterface; - /** - * + * @property null|string|array|TableIdentifier $table * @property Where $where */ -class Delete extends AbstractPreparableSqlObject +class Delete extends AbstractSqlObject implements PreparableSqlObjectInterface { - /**@#+ - * @const - */ - const SPECIFICATION_DELETE = 'delete'; - const SPECIFICATION_WHERE = 'where'; - /**@#-*/ - - /** - * {@inheritDoc} - */ - protected $specifications = [ - self::SPECIFICATION_DELETE => 'DELETE FROM %1$s', - self::SPECIFICATION_WHERE => 'WHERE %1$s' - ]; - /** * @var string|TableIdentifier */ protected $table = ''; - /** - * @var bool - */ - protected $emptyWhereProtection = true; - - /** - * @var array - */ - protected $set = []; - /** * @var null|string|Where */ protected $where = null; + protected $__getProperties = [ + 'table', + 'where', + ]; + /** * Constructor * @@ -61,6 +37,7 @@ class Delete extends AbstractPreparableSqlObject */ public function __construct($table = null) { + parent::__construct(); if ($table) { $this->from($table); } @@ -79,22 +56,6 @@ public function from($table) return $this; } - /** - * @param null $key - * - * @return mixed - */ - public function getRawState($key = null) - { - $rawState = [ - 'emptyWhereProtection' => $this->emptyWhereProtection, - 'table' => $this->table, - 'set' => $this->set, - 'where' => $this->where - ]; - return (isset($key) && array_key_exists($key, $rawState)) ? $rawState[$key] : $rawState; - } - /** * Create where clause * @@ -112,55 +73,4 @@ public function where($predicate, $combination = Predicate\PredicateSet::OP_AND) } return $this; } - - /** - * @param PlatformInterface $platform - * @param DriverInterface|null $driver - * @param ParameterContainer|null $parameterContainer - * - * @return string - */ - protected function processDelete(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - return sprintf( - $this->specifications[static::SPECIFICATION_DELETE], - $this->resolveTable($this->table, $platform, $driver, $parameterContainer) - ); - } - - /** - * @param PlatformInterface $platform - * @param DriverInterface|null $driver - * @param ParameterContainer|null $parameterContainer - * - * @return null|string - */ - protected function processWhere(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - if ($this->where->count() == 0) { - return; - } - - return sprintf( - $this->specifications[static::SPECIFICATION_WHERE], - $this->processExpression($this->where, $platform, $driver, $parameterContainer, 'where') - ); - } - - /** - * Property overloading - * - * Overloads "where" only. - * - * @param string $name - * - * @return Where|null - */ - public function __get($name) - { - switch (strtolower($name)) { - case 'where': - return $this->where; - } - } } diff --git a/src/Sql/Insert.php b/src/Sql/Insert.php index 17d0f5cc5d..02b01f8d13 100644 --- a/src/Sql/Insert.php +++ b/src/Sql/Insert.php @@ -9,30 +9,15 @@ namespace Zend\Db\Sql; -use Zend\Db\Adapter\Driver\DriverInterface; -use Zend\Db\Adapter\ParameterContainer; -use Zend\Db\Adapter\Platform\PlatformInterface; - -class Insert extends AbstractPreparableSqlObject +/** + * @property null|string|array|TableIdentifier $table + * @property array $columns + * @property null|Select $select + */ +class Insert extends AbstractSqlObject implements PreparableSqlObjectInterface { - /**#@+ - * Constants - * - * @const - */ - const SPECIFICATION_INSERT = 'insert'; - const SPECIFICATION_SELECT = 'select'; const VALUES_MERGE = 'merge'; const VALUES_SET = 'set'; - /**#@-*/ - - /** - * @var array Specification array - */ - protected $specifications = [ - self::SPECIFICATION_INSERT => 'INSERT INTO %1$s (%2$s) VALUES (%3$s)', - self::SPECIFICATION_SELECT => 'INSERT INTO %1$s %2$s %3$s', - ]; /** * @var string|TableIdentifier @@ -45,6 +30,12 @@ class Insert extends AbstractPreparableSqlObject */ protected $select = null; + protected $__getProperties = [ + 'table', + 'columns', + 'select', + ]; + /** * Constructor * @@ -52,6 +43,7 @@ class Insert extends AbstractPreparableSqlObject */ public function __construct($table = null) { + parent::__construct(); if ($table) { $this->into($table); } @@ -84,17 +76,17 @@ public function columns(array $columns) /** * Specify values to insert * - * @param array|Select $values + * @param array|SelectableInterface $values * @param string $flag one of VALUES_MERGE or VALUES_SET; defaults to VALUES_SET * @throws Exception\InvalidArgumentException * @return Insert */ public function values($values, $flag = self::VALUES_SET) { - if ($values instanceof Select) { + if ($values instanceof SelectableInterface) { if ($flag == self::VALUES_MERGE) { throw new Exception\InvalidArgumentException( - 'A Zend\Db\Sql\Select instance cannot be provided with the merge flag' + 'A Zend\Db\Sql\SelectableInterface instance cannot be provided with the merge flag' ); } $this->select = $values; @@ -103,13 +95,13 @@ public function values($values, $flag = self::VALUES_SET) if (!is_array($values)) { throw new Exception\InvalidArgumentException( - 'values() expects an array of values or Zend\Db\Sql\Select instance' + 'values() expects an array of values or Zend\Db\Sql\SelectableInterface instance' ); } if ($this->select && $flag == self::VALUES_MERGE) { throw new Exception\InvalidArgumentException( - 'An array of values cannot be provided with the merge flag when a Zend\Db\Sql\Select instance already exists as the value source' + 'An array of values cannot be provided with the merge flag when a Zend\Db\Sql\SelectableInterface instance already exists as the value source' ); } @@ -141,142 +133,22 @@ private function isAssocativeArray(array $array) /** * Create INTO SELECT clause * - * @param Select $select + * @param SelectableInterface $select * @return self */ - public function select(Select $select) + public function select(SelectableInterface $select) { return $this->values($select); } - /** - * Get raw state - * - * @param string $key - * @return mixed - */ - public function getRawState($key = null) - { - $rawState = [ - 'table' => $this->table, - 'columns' => array_keys($this->columns), - 'values' => array_values($this->columns) - ]; - return (isset($key) && array_key_exists($key, $rawState)) ? $rawState[$key] : $rawState; - } - - protected function processInsert(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - if ($this->select) { - return; - } - if (!$this->columns) { - throw new Exception\InvalidArgumentException('values or select should be present'); - } - - $columns = []; - $values = []; - - foreach ($this->columns as $column => $value) { - $columns[] = $platform->quoteIdentifier($column); - if (is_scalar($value) && $parameterContainer) { - $values[] = $driver->formatParameterName($column); - $parameterContainer->offsetSet($column, $value); - } else { - $values[] = $this->resolveColumnValue( - $value, - $platform, - $driver, - $parameterContainer - ); - } - } - return sprintf( - $this->specifications[static::SPECIFICATION_INSERT], - $this->resolveTable($this->table, $platform, $driver, $parameterContainer), - implode(', ', $columns), - implode(', ', $values) - ); - } - - protected function processSelect(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - if (!$this->select) { - return; - } - $selectSql = $this->processSubSelect($this->select, $platform, $driver, $parameterContainer); - - $columns = array_map([$platform, 'quoteIdentifier'], array_keys($this->columns)); - $columns = implode(', ', $columns); - - return sprintf( - $this->specifications[static::SPECIFICATION_SELECT], - $this->resolveTable($this->table, $platform, $driver, $parameterContainer), - $columns ? "($columns)" : "", - $selectSql - ); - } - - /** - * Overloading: variable setting - * - * Proxies to values, using VALUES_MERGE strategy - * - * @param string $name - * @param mixed $value - * @return Insert - */ - public function __set($name, $value) - { - $this->columns[$name] = $value; - return $this; - } - - /** - * Overloading: variable unset - * - * Proxies to values and columns - * - * @param string $name - * @throws Exception\InvalidArgumentException - * @return void - */ - public function __unset($name) - { - if (!array_key_exists($name, $this->columns)) { - throw new Exception\InvalidArgumentException('The key ' . $name . ' was not found in this objects column list'); - } - - unset($this->columns[$name]); - } - - /** - * Overloading: variable isset - * - * Proxies to columns; does a column of that name exist? - * - * @param string $name - * @return bool - */ - public function __isset($name) - { - return array_key_exists($name, $this->columns); - } - - /** - * Overloading: variable retrieval - * - * Retrieves value by column name - * - * @param string $name - * @throws Exception\InvalidArgumentException - * @return mixed - */ public function __get($name) { - if (!array_key_exists($name, $this->columns)) { - throw new Exception\InvalidArgumentException('The key ' . $name . ' was not found in this objects column list'); + if ($name == 'columns') { + return array_keys($this->columns); + } + if ($name == 'values') { + return array_values($this->columns); } - return $this->columns[$name]; + return parent::__get($name); } } diff --git a/src/Sql/Predicate/In.php b/src/Sql/Predicate/In.php index 46ba61b62c..4f5ec49aaf 100644 --- a/src/Sql/Predicate/In.php +++ b/src/Sql/Predicate/In.php @@ -11,6 +11,7 @@ use Zend\Db\Sql\Exception; use Zend\Db\Sql\Select; +use Zend\Db\Sql\SelectableInterface; use Zend\Db\Sql\AbstractExpression; class In extends AbstractExpression implements PredicateInterface @@ -64,15 +65,15 @@ public function getIdentifier() /** * Set set of values for IN comparison * - * @param array|Select $valueSet + * @param array|SelectableInterface $valueSet * @throws Exception\InvalidArgumentException * @return In */ public function setValueSet($valueSet) { - if (!is_array($valueSet) && !$valueSet instanceof Select) { + if (!is_array($valueSet) && !$valueSet instanceof SelectableInterface) { throw new Exception\InvalidArgumentException( - '$valueSet must be either an array or a Zend\Db\Sql\Select object, ' . gettype($valueSet) . ' given' + '$valueSet must be either an array or a Zend\Db\Sql\SelectableInterface object, ' . gettype($valueSet) . ' given' ); } $this->valueSet = $valueSet; @@ -111,7 +112,7 @@ public function getExpressionData() $types = [self::TYPE_IDENTIFIER]; } - if ($values instanceof Select) { + if ($values instanceof SelectableInterface) { $specification = vsprintf( $this->specification, [$identifierSpecFragment, '%s'] diff --git a/src/Sql/PreparableSqlObjectInterface.php b/src/Sql/PreparableSqlObjectInterface.php index 2be162ee83..0d81be3ff9 100644 --- a/src/Sql/PreparableSqlObjectInterface.php +++ b/src/Sql/PreparableSqlObjectInterface.php @@ -9,16 +9,6 @@ namespace Zend\Db\Sql; -use Zend\Db\Adapter\AdapterInterface; -use Zend\Db\Adapter\StatementContainerInterface; - -interface PreparableSqlObjectInterface +interface PreparableSqlObjectInterface extends SqlObjectInterface { - /** - * @param AdapterInterface $adapter - * @param StatementContainerInterface $statementContainer - * - * @return void - */ - public function prepareStatement(AdapterInterface $adapter, StatementContainerInterface $statementContainer); } diff --git a/src/Sql/Select.php b/src/Sql/Select.php index 8a88122b90..8fb257b920 100644 --- a/src/Sql/Select.php +++ b/src/Sql/Select.php @@ -9,32 +9,23 @@ namespace Zend\Db\Sql; -use Zend\Db\Adapter\Driver\DriverInterface; -use Zend\Db\Adapter\ParameterContainer; -use Zend\Db\Adapter\Platform\PlatformInterface; - /** * + * @property null|string|array|TableIdentifier $table + * @property string|Expression $quantifier DISTINCT|ALL + * @property array $columns + * @property $joins * @property Where $where + * @property string|array $order + * @property $group * @property Having $having + * @property int $limit + * @property int $offset + * @property $combine + * @property $prefixColumnsWithTable */ -class Select extends AbstractPreparableSqlObject +class Select extends AbstractSqlObject implements PreparableSqlObjectInterface, SelectableInterface { - /**#@+ - * Constant - * @const - */ - const SELECT = 'select'; - const QUANTIFIER = 'quantifier'; - const COLUMNS = 'columns'; - const TABLE = 'table'; - const JOINS = 'joins'; - const WHERE = 'where'; - const GROUP = 'group'; - const HAVING = 'having'; - const ORDER = 'order'; - const LIMIT = 'limit'; - const OFFSET = 'offset'; const QUANTIFIER_DISTINCT = 'DISTINCT'; const QUANTIFIER_ALL = 'ALL'; const JOIN_INNER = Join::JOIN_INNER; @@ -50,59 +41,10 @@ class Select extends AbstractPreparableSqlObject const COMBINE_UNION = 'union'; const COMBINE_EXCEPT = 'except'; const COMBINE_INTERSECT = 'intersect'; - /**#@-*/ - - /** - * @deprecated use JOIN_LEFT_OUTER instead - */ - const JOIN_OUTER_LEFT = 'outer left'; - - /** - * @deprecated use JOIN_LEFT_OUTER instead - */ - const JOIN_OUTER_RIGHT = 'outer right'; /** * @var array Specifications */ - protected $specifications = [ - 'statementStart' => '%1$s', - self::SELECT => [ - 'SELECT %1$s FROM %2$s' => [ - [1 => '%1$s', 2 => '%1$s AS %2$s', 'combinedby' => ', '], - null - ], - 'SELECT %1$s %2$s FROM %3$s' => [ - null, - [1 => '%1$s', 2 => '%1$s AS %2$s', 'combinedby' => ', '], - null - ], - 'SELECT %1$s' => [ - [1 => '%1$s', 2 => '%1$s AS %2$s', 'combinedby' => ', '], - ], - ], - self::JOINS => [ - '%1$s' => [ - [3 => '%1$s JOIN %2$s ON %3$s', 'combinedby' => ' '] - ] - ], - self::WHERE => 'WHERE %1$s', - self::GROUP => [ - 'GROUP BY %1$s' => [ - [1 => '%1$s', 'combinedby' => ', '] - ] - ], - self::HAVING => 'HAVING %1$s', - self::ORDER => [ - 'ORDER BY %1$s' => [ - [1 => '%1$s', 2 => '%1$s %2$s', 'combinedby' => ', '] - ] - ], - self::LIMIT => 'LIMIT %1$s', - self::OFFSET => 'OFFSET %1$s', - 'statementEnd' => '%1$s', - self::COMBINE => '%1$s ( %2$s )', - ]; /** * @var bool @@ -164,6 +106,20 @@ class Select extends AbstractPreparableSqlObject */ protected $offset = null; + protected $__getProperties = [ + 'table', + 'quantifier', + 'columns', + 'joins', + 'where', + 'order', + 'group', + 'having', + 'limit', + 'offset', + 'combine', + 'prefixColumnsWithTable', + ]; /** * @var array */ @@ -176,6 +132,7 @@ class Select extends AbstractPreparableSqlObject */ public function __construct($table = null) { + parent::__construct(); if ($table) { $this->from($table); $this->tableReadOnly = true; @@ -212,8 +169,9 @@ public function from($table) } /** - * @param string|Expression $quantifier DISTINCT|ALL - * @return Select + * @param string|ExpressionInterface $quantifier DISTINCT|ALL + * @return self + * @throws Exception\InvalidArgumentException */ public function quantifier($quantifier) { @@ -242,7 +200,7 @@ public function quantifier($quantifier) * * @param array $columns * @param bool $prefixColumnsWithTable - * @return Select + * @return self */ public function columns(array $columns, $prefixColumnsWithTable = true) { @@ -254,12 +212,12 @@ public function columns(array $columns, $prefixColumnsWithTable = true) /** * Create join clause * - * @param string|array $name - * @param string $on - * @param string|array $columns + * @param string|array $name + * @param string $on + * @param string|array $columns * @param string $type one of the JOIN_* constants + * @return self * @throws Exception\InvalidArgumentException - * @return Select */ public function join($name, $on, $columns = self::SQL_STAR, $type = self::JOIN_INNER) { @@ -274,7 +232,7 @@ public function join($name, $on, $columns = self::SQL_STAR, $type = self::JOIN_I * @param Where|\Closure|string|array|Predicate\PredicateInterface $predicate * @param string $combination One of the OP_* constants from Predicate\PredicateSet * @throws Exception\InvalidArgumentException - * @return Select + * @return self */ public function where($predicate, $combination = Predicate\PredicateSet::OP_AND) { @@ -286,6 +244,10 @@ public function where($predicate, $combination = Predicate\PredicateSet::OP_AND) return $this; } + /** + * @param string|array $group + * @return self + */ public function group($group) { if (is_array($group)) { @@ -301,9 +263,9 @@ public function group($group) /** * Create having clause * - * @param Where|\Closure|string|array $predicate + * @param Having|\Closure|string|array $predicate * @param string $combination One of the OP_* constants from Predicate\PredicateSet - * @return Select + * @return self */ public function having($predicate, $combination = Predicate\PredicateSet::OP_AND) { @@ -317,7 +279,7 @@ public function having($predicate, $combination = Predicate\PredicateSet::OP_AND /** * @param string|array $order - * @return Select + * @return self */ public function order($order) { @@ -342,7 +304,8 @@ public function order($order) /** * @param int $limit - * @return Select + * @return self + * @throws Exception\InvalidArgumentException */ public function limit($limit) { @@ -360,7 +323,8 @@ public function limit($limit) /** * @param int $offset - * @return Select + * @return self + * @throws Exception\InvalidArgumentException */ public function offset($offset) { @@ -377,13 +341,13 @@ public function offset($offset) } /** - * @param Select $select + * @param SelectableInterface $select * @param string $type * @param string $modifier - * @return Select + * @return self * @throws Exception\InvalidArgumentException */ - public function combine(Select $select, $type = self::COMBINE_UNION, $modifier = '') + public function combine(SelectableInterface $select, $type = self::COMBINE_UNION, $modifier = '') { if ($this->combine !== []) { throw new Exception\InvalidArgumentException('This Select object is already combined and cannot be combined with multiple Selects objects'); @@ -396,15 +360,11 @@ public function combine(Select $select, $type = self::COMBINE_UNION, $modifier = return $this; } - /** - * @param string $part - * @return Select - * @throws Exception\InvalidArgumentException - */ - public function reset($part) + + public function __unset($name) { - switch ($part) { - case self::TABLE: + switch ($name) { + case 'table': if ($this->tableReadOnly) { throw new Exception\InvalidArgumentException( 'Since this object was created with a table and/or schema in the constructor, it is read only.' @@ -412,67 +372,47 @@ public function reset($part) } $this->table = null; break; - case self::QUANTIFIER: + case 'quantifier': $this->quantifier = null; break; - case self::COLUMNS: - $this->columns = []; + case 'columns': + $this->columns = [self::SQL_STAR]; break; - case self::JOINS: + case 'joins': $this->joins = new Join; break; - case self::WHERE: + case 'where': $this->where = new Where; break; - case self::GROUP: + case 'group': $this->group = null; break; - case self::HAVING: + case 'having': $this->having = new Having; break; - case self::LIMIT: + case 'limit': $this->limit = null; break; - case self::OFFSET: + case 'offset': $this->offset = null; break; - case self::ORDER: + case 'order': $this->order = []; break; - case self::COMBINE: + case 'prefixColumnsWithTable' : + $this->prefixColumnsWithTable = true; + break; + case 'combine': $this->combine = []; break; + default : + throw new Exception\InvalidArgumentException( + 'Not a valid property "' . $name . '" for this object' + ); } return $this; } - public function setSpecification($index, $specification) - { - if (!method_exists($this, 'process' . $index)) { - throw new Exception\InvalidArgumentException('Not a valid specification name.'); - } - $this->specifications[$index] = $specification; - return $this; - } - - public function getRawState($key = null) - { - $rawState = [ - self::TABLE => $this->table, - self::QUANTIFIER => $this->quantifier, - self::COLUMNS => $this->columns, - self::JOINS => $this->joins, - self::WHERE => $this->where, - self::ORDER => $this->order, - self::GROUP => $this->group, - self::HAVING => $this->having, - self::LIMIT => $this->limit, - self::OFFSET => $this->offset, - self::COMBINE => $this->combine - ]; - return (isset($key) && array_key_exists($key, $rawState)) ? $rawState[$key] : $rawState; - } - /** * Returns whether the table is read only or not. * @@ -483,246 +423,6 @@ public function isTableReadOnly() return $this->tableReadOnly; } - protected function processStatementStart(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - if ($this->combine !== []) { - return ['(']; - } - } - - protected function processStatementEnd(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - if ($this->combine !== []) { - return [')']; - } - } - - /** - * Process the select part - * - * @param PlatformInterface $platform - * @param DriverInterface $driver - * @param ParameterContainer $parameterContainer - * @return null|array - */ - protected function processSelect(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - $expr = 1; - - list($table, $fromTable) = $this->resolveTable($this->table, $platform, $driver, $parameterContainer); - // process table columns - $columns = []; - foreach ($this->columns as $columnIndexOrAs => $column) { - if ($column === self::SQL_STAR) { - $columns[] = [$fromTable . self::SQL_STAR]; - continue; - } - - $columnName = $this->resolveColumnValue( - [ - 'column' => $column, - 'fromTable' => $fromTable, - 'isIdentifier' => true, - ], - $platform, - $driver, - $parameterContainer, - (is_string($columnIndexOrAs) ? $columnIndexOrAs : 'column') - ); - // process As portion - if (is_string($columnIndexOrAs)) { - $columnAs = $platform->quoteIdentifier($columnIndexOrAs); - } elseif (stripos($columnName, ' as ') === false) { - $columnAs = (is_string($column)) ? $platform->quoteIdentifier($column) : 'Expression' . $expr++; - } - $columns[] = (isset($columnAs)) ? [$columnName, $columnAs] : [$columnName]; - } - - // process join columns - foreach ($this->joins->getJoins() as $join) { - $joinName = (is_array($join['name'])) ? key($join['name']) : $join['name']; - $joinName = parent::resolveTable($joinName, $platform, $driver, $parameterContainer); - - foreach ($join['columns'] as $jKey => $jColumn) { - $jColumns = []; - $jFromTable = is_scalar($jColumn) - ? $joinName . $platform->getIdentifierSeparator() - : ''; - $jColumns[] = $this->resolveColumnValue( - [ - 'column' => $jColumn, - 'fromTable' => $jFromTable, - 'isIdentifier' => true, - ], - $platform, - $driver, - $parameterContainer, - (is_string($jKey) ? $jKey : 'column') - ); - if (is_string($jKey)) { - $jColumns[] = $platform->quoteIdentifier($jKey); - } elseif ($jColumn !== self::SQL_STAR) { - $jColumns[] = $platform->quoteIdentifier($jColumn); - } - $columns[] = $jColumns; - } - } - - if ($this->quantifier) { - $quantifier = ($this->quantifier instanceof ExpressionInterface) - ? $this->processExpression($this->quantifier, $platform, $driver, $parameterContainer, 'quantifier') - : $this->quantifier; - } - - if (!isset($table)) { - return [$columns]; - } elseif (isset($quantifier)) { - return [$quantifier, $columns, $table]; - } else { - return [$columns, $table]; - } - } - - protected function processJoins(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - return $this->processJoin($this->joins, $platform, $driver, $parameterContainer); - } - - protected function processWhere(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - if ($this->where->count() == 0) { - return; - } - return [ - $this->processExpression($this->where, $platform, $driver, $parameterContainer, 'where') - ]; - } - - protected function processGroup(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - if ($this->group === null) { - return; - } - // process table columns - $groups = []; - foreach ($this->group as $column) { - $groups[] = $this->resolveColumnValue( - [ - 'column' => $column, - 'isIdentifier' => true, - ], - $platform, - $driver, - $parameterContainer, - 'group' - ); - } - return [$groups]; - } - - protected function processHaving(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - if ($this->having->count() == 0) { - return; - } - return [ - $this->processExpression($this->having, $platform, $driver, $parameterContainer, 'having') - ]; - } - - protected function processOrder(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - if (empty($this->order)) { - return; - } - $orders = []; - foreach ($this->order as $k => $v) { - if ($v instanceof ExpressionInterface) { - $orders[] = [ - $this->processExpression($v, $platform, $driver, $parameterContainer) - ]; - continue; - } - if (is_int($k)) { - if (strpos($v, ' ') !== false) { - list($k, $v) = preg_split('# #', $v, 2); - } else { - $k = $v; - $v = self::ORDER_ASCENDING; - } - } - if (strtoupper($v) == self::ORDER_DESCENDING) { - $orders[] = [$platform->quoteIdentifierInFragment($k), self::ORDER_DESCENDING]; - } else { - $orders[] = [$platform->quoteIdentifierInFragment($k), self::ORDER_ASCENDING]; - } - } - return [$orders]; - } - - protected function processLimit(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - if ($this->limit === null) { - return; - } - if ($parameterContainer) { - $parameterContainer->offsetSet('limit', $this->limit, ParameterContainer::TYPE_INTEGER); - return [$driver->formatParameterName('limit')]; - } - return [$platform->quoteValue($this->limit)]; - } - - protected function processOffset(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - if ($this->offset === null) { - return; - } - if ($parameterContainer) { - $parameterContainer->offsetSet('offset', $this->offset, ParameterContainer::TYPE_INTEGER); - return [$driver->formatParameterName('offset')]; - } - - return [$platform->quoteValue($this->offset)]; - } - - protected function processCombine(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - if ($this->combine == []) { - return; - } - - $type = $this->combine['type']; - if ($this->combine['modifier']) { - $type .= ' ' . $this->combine['modifier']; - } - - return [ - strtoupper($type), - $this->processSubSelect($this->combine['select'], $platform, $driver, $parameterContainer), - ]; - } - - /** - * Variable overloading - * - * @param string $name - * @throws Exception\InvalidArgumentException - * @return mixed - */ - public function __get($name) - { - switch (strtolower($name)) { - case 'where': - return $this->where; - case 'having': - return $this->having; - case 'joins': - return $this->joins; - default: - throw new Exception\InvalidArgumentException('Not a valid magic property for this object'); - } - } - /** * __clone * @@ -736,41 +436,4 @@ public function __clone() $this->joins = clone $this->joins; $this->having = clone $this->having; } - - /** - * @param string|TableIdentifier|Select $table - * @param PlatformInterface $platform - * @param DriverInterface $driver - * @param ParameterContainer $parameterContainer - * @return string - */ - protected function resolveTable($table, PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - $alias = null; - - if (is_array($table)) { - $alias = key($table); - $table = current($table); - } - - $table = parent::resolveTable($table, $platform, $driver, $parameterContainer); - - if ($alias) { - $fromTable = $platform->quoteIdentifier($alias); - $table = $this->renderTable($table, $fromTable); - } else { - $fromTable = $table; - } - - if ($this->prefixColumnsWithTable && $fromTable) { - $fromTable .= $platform->getIdentifierSeparator(); - } else { - $fromTable = ''; - } - - return [ - $table, - $fromTable - ]; - } } diff --git a/src/Sql/Builder/PlatformDecoratorInterface.php b/src/Sql/SelectableInterface.php similarity index 64% rename from src/Sql/Builder/PlatformDecoratorInterface.php rename to src/Sql/SelectableInterface.php index 8c66e4c39f..dee352ba24 100644 --- a/src/Sql/Builder/PlatformDecoratorInterface.php +++ b/src/Sql/SelectableInterface.php @@ -7,14 +7,8 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -namespace Zend\Db\Sql\Builder; +namespace Zend\Db\Sql; -interface PlatformDecoratorInterface +interface SelectableInterface extends SqlObjectInterface { - /** - * @param $subject - * - * @return self - */ - public function setSubject($subject); } diff --git a/src/Sql/Sql.php b/src/Sql/Sql.php index 346602c5da..0026d715c8 100644 --- a/src/Sql/Sql.php +++ b/src/Sql/Sql.php @@ -11,7 +11,6 @@ use Zend\Db\Adapter\AdapterInterface; use Zend\Db\Adapter\Driver\StatementInterface; -use Zend\Db\Adapter\Platform\PlatformInterface; class Sql { @@ -21,21 +20,21 @@ class Sql /** @var string|array|TableIdentifier */ protected $table = null; - /** @var Platform\Platform */ - protected $sqlPlatform = null; + /** @var Builder\Builder */ + protected $builder = null; /** - * @param AdapterInterface $adapter + * @param null|AdapterInterface $adapter * @param null|string|array|TableIdentifier $table - * @param null|Platform\AbstractPlatform $sqlPlatform @deprecated since version 3.0 + * @param null|Builder\Builder $platformBuilder */ - public function __construct(AdapterInterface $adapter, $table = null, Builder\AbstractBuilder $sqlPlatform = null) + public function __construct(AdapterInterface $adapter = null, $table = null, Builder\Builder $builder = null) { $this->adapter = $adapter; if ($table) { $this->setTable($table); } - $this->sqlPlatform = $sqlPlatform ?: new Builder\Builder($adapter); + $this->builder = $builder ?: new Builder\Builder($adapter); } /** @@ -46,6 +45,9 @@ public function getAdapter() return $this->adapter; } + /** + * @return bool + */ public function hasTable() { return ($this->table !== null); @@ -66,9 +68,12 @@ public function getTable() return $this->table; } - public function getSqlPlatform() + /** + * @return Builder\Builder + */ + public function getBuilder() { - return $this->sqlPlatform; + return $this->builder; } public function select($table = null) @@ -117,38 +122,21 @@ public function delete($table = null) /** * @param PreparableSqlObjectInterface $sqlObject - * @param StatementInterface $statement - * @param AdapterInterface $adapter + * @param null|AdapterInterface $adapter * * @return StatementInterface */ - public function prepareStatementForSqlObject(PreparableSqlObjectInterface $sqlObject, StatementInterface $statement = null, AdapterInterface $adapter = null) + public function prepareStatementForSqlObject(PreparableSqlObjectInterface $sqlObject, AdapterInterface $adapter = null) { - $adapter = $adapter ?: $this->adapter; - $statement = $statement ?: $adapter->getDriver()->createStatement(); - - return $this->sqlPlatform->setSubject($sqlObject)->prepareStatement($adapter, $statement); + return $this->builder->prepareStatement( + $sqlObject, + $adapter ?: $this->adapter + ); } /** - * Get sql string using platform or sql object - * * @param SqlObjectInterface $sqlObject - * @param PlatformInterface|null $platform - * - * @return string - * - * @deprecated Deprecated in 2.4. Use buildSqlString() instead - */ - public function getSqlStringForSqlObject(SqlObjectInterface $sqlObject, PlatformInterface $platform = null) - { - $platform = ($platform) ?: $this->adapter->getPlatform(); - return $this->sqlPlatform->setSubject($sqlObject)->getSqlString($platform); - } - - /** - * @param SqlObjectInterface $sqlObject - * @param AdapterInterface $adapter + * @param null|AdapterInterface $adapter * * @return string * @@ -156,9 +144,9 @@ public function getSqlStringForSqlObject(SqlObjectInterface $sqlObject, Platform */ public function buildSqlString(SqlObjectInterface $sqlObject, AdapterInterface $adapter = null) { - return $this - ->sqlPlatform - ->setSubject($sqlObject) - ->getSqlString($adapter ? $adapter->getPlatform() : $this->adapter->getPlatform()); + return $this->builder->getSqlString( + $sqlObject, + $adapter ?: $this->adapter + ); } } diff --git a/src/Sql/SqlObjectInterface.php b/src/Sql/SqlObjectInterface.php index fb646a7638..63f6ac3cd5 100644 --- a/src/Sql/SqlObjectInterface.php +++ b/src/Sql/SqlObjectInterface.php @@ -9,16 +9,6 @@ namespace Zend\Db\Sql; -use Zend\Db\Adapter\Platform\PlatformInterface; - interface SqlObjectInterface { - /** - * Get SQL string for statement - * - * @param null|PlatformInterface $adapterPlatform - * - * @return string - */ - public function getSqlString(PlatformInterface $adapterPlatform = null); } diff --git a/src/Sql/Update.php b/src/Sql/Update.php index ccec9c62b1..63d1c5e3c2 100644 --- a/src/Sql/Update.php +++ b/src/Sql/Update.php @@ -9,50 +9,23 @@ namespace Zend\Db\Sql; -use Zend\Db\Adapter\ParameterContainer; -use Zend\Db\Adapter\Platform\PlatformInterface; -use Zend\Db\Adapter\Driver\DriverInterface; use Zend\Stdlib\PriorityList; /** - * + * @property null|string|array|TableIdentifier $table + * @property PriorityList $set * @property Where $where */ -class Update extends AbstractPreparableSqlObject +class Update extends AbstractSqlObject implements PreparableSqlObjectInterface { - /**@#++ - * @const - */ - const SPECIFICATION_UPDATE = 'update'; - const SPECIFICATION_SET = 'set'; - const SPECIFICATION_WHERE = 'where'; - const SPECIFICATION_JOIN = 'joins'; - const VALUES_MERGE = 'merge'; const VALUES_SET = 'set'; - /**@#-**/ - - protected $specifications = [ - self::SPECIFICATION_UPDATE => 'UPDATE %1$s', - self::SPECIFICATION_JOIN => [ - '%1$s' => [ - [3 => '%1$s JOIN %2$s ON %3$s', 'combinedby' => ' '] - ] - ], - self::SPECIFICATION_SET => 'SET %1$s', - self::SPECIFICATION_WHERE => 'WHERE %1$s', - ]; /** * @var string|TableIdentifier */ protected $table = ''; - /** - * @var bool - */ - protected $emptyWhereProtection = true; - /** * @var PriorityList */ @@ -63,6 +36,13 @@ class Update extends AbstractPreparableSqlObject */ protected $where = null; + protected $__getProperties = [ + 'table', + 'set', + 'where', + 'joins', + ]; + /** * @var null|Join */ @@ -75,6 +55,7 @@ class Update extends AbstractPreparableSqlObject */ public function __construct($table = null) { + parent::__construct(); if ($table) { $this->table($table); } @@ -88,7 +69,7 @@ public function __construct($table = null) * Specify table for statement * * @param string|TableIdentifier $table - * @return Update + * @return self */ public function table($table) { @@ -102,7 +83,7 @@ public function table($table) * @param array $values Associative array of key values * @param string $flag One of the VALUES_* constants * @throws Exception\InvalidArgumentException - * @return Update + * @return self */ public function set(array $values, $flag = self::VALUES_SET) { @@ -129,7 +110,7 @@ public function set(array $values, $flag = self::VALUES_SET) * @param Where|\Closure|string|array $predicate * @param string $combination One of the OP_* constants from Predicate\PredicateSet * @throws Exception\InvalidArgumentException - * @return Update + * @return self */ public function where($predicate, $combination = Predicate\PredicateSet::OP_AND) { @@ -157,80 +138,6 @@ public function join($name, $on, $type = Join::JOIN_INNER) return $this; } - public function getRawState($key = null) - { - $rawState = [ - 'emptyWhereProtection' => $this->emptyWhereProtection, - 'table' => $this->table, - 'set' => $this->set->toArray(), - 'where' => $this->where, - 'joins' => $this->joins - ]; - return (isset($key) && array_key_exists($key, $rawState)) ? $rawState[$key] : $rawState; - } - - protected function processUpdate(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - return sprintf( - $this->specifications[static::SPECIFICATION_UPDATE], - $this->resolveTable($this->table, $platform, $driver, $parameterContainer) - ); - } - - protected function processSet(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - $setSql = []; - foreach ($this->set as $column => $value) { - $prefix = $platform->quoteIdentifier($column) . ' = '; - if (is_scalar($value) && $parameterContainer) { - $setSql[] = $prefix . $driver->formatParameterName($column); - $parameterContainer->offsetSet($column, $value); - } else { - $setSql[] = $prefix . $this->resolveColumnValue( - $value, - $platform, - $driver, - $parameterContainer - ); - } - } - - return sprintf( - $this->specifications[static::SPECIFICATION_SET], - implode(', ', $setSql) - ); - } - - protected function processWhere(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - if ($this->where->count() == 0) { - return; - } - return sprintf( - $this->specifications[static::SPECIFICATION_WHERE], - $this->processExpression($this->where, $platform, $driver, $parameterContainer, 'where') - ); - } - - protected function processJoins(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null) - { - return $this->processJoin($this->joins, $platform, $driver, $parameterContainer); - } - - /** - * Variable overloading - * - * Proxies to "where" only - * - * @param string $name - * @return mixed - */ - public function __get($name) - { - if (strtolower($name) == 'where') { - return $this->where; - } - } /** * __clone diff --git a/src/TableGateway/AbstractTableGateway.php b/src/TableGateway/AbstractTableGateway.php index a27d50756f..4f2fe5e73e 100644 --- a/src/TableGateway/AbstractTableGateway.php +++ b/src/TableGateway/AbstractTableGateway.php @@ -216,17 +216,17 @@ public function selectWith(Select $select) */ protected function executeSelect(Select $select) { - $selectState = $select->getRawState(); - if ($selectState['table'] != $this->table - && (is_array($selectState['table']) - && end($selectState['table']) != $this->table) + $selectTable = $select->table; + if ($selectTable != $this->table + && (is_array($selectTable) + && end($selectTable) != $this->table) ) { throw new Exception\RuntimeException( 'The table name of the provided Select object must match that of the table' ); } - if ($selectState['columns'] == [Select::SQL_STAR] + if ($select->columns == [Select::SQL_STAR] && $this->columns !== []) { $select->columns($this->columns); } @@ -285,8 +285,7 @@ public function insertWith(Insert $insert) */ protected function executeInsert(Insert $insert) { - $insertState = $insert->getRawState(); - if ($insertState['table'] != $this->table) { + if ($insert->table != $this->table) { throw new Exception\RuntimeException( 'The table name of the provided Insert object must match that of the table' ); @@ -298,10 +297,10 @@ protected function executeInsert(Insert $insert) // Most RDBMS solutions do not allow using table aliases in INSERTs // See https://github.com/zendframework/zf2/issues/7311 $unaliasedTable = false; - if (is_array($insertState['table'])) { - $tableData = array_values($insertState['table']); - $unaliasedTable = array_shift($tableData); - $insert->into($unaliasedTable); + if (is_array($insert->table)) { + $unaliasedTable = $insert->table; + $tableData = array_values($insert->table); + $insert->into(array_shift($tableData)); } $statement = $this->sql->prepareStatementForSqlObject($insert); @@ -313,7 +312,7 @@ protected function executeInsert(Insert $insert) // Reset original table information in Insert instance, if necessary if ($unaliasedTable) { - $insert->into($insertState['table']); + $insert->into($unaliasedTable); } return $result->getAffectedRows(); @@ -370,8 +369,7 @@ public function updateWith(Update $update) */ protected function executeUpdate(Update $update) { - $updateState = $update->getRawState(); - if ($updateState['table'] != $this->table) { + if ($update->table != $this->table) { throw new Exception\RuntimeException( 'The table name of the provided Update object must match that of the table' ); @@ -381,10 +379,10 @@ protected function executeUpdate(Update $update) $this->featureSet->apply(EventFeatureEventsInterface::EVENT_PRE_UPDATE, [$update]); $unaliasedTable = false; - if (is_array($updateState['table'])) { - $tableData = array_values($updateState['table']); - $unaliasedTable = array_shift($tableData); - $update->table($unaliasedTable); + if (is_array($update->table)) { + $unaliasedTable = $update->table; + $tableData = array_values($update->table); + $update->table(array_shift($tableData)); } $statement = $this->sql->prepareStatementForSqlObject($update); @@ -395,7 +393,7 @@ protected function executeUpdate(Update $update) // Reset original table information in Update instance, if necessary if ($unaliasedTable) { - $update->table($updateState['table']); + $update->table($unaliasedTable); } return $result->getAffectedRows(); @@ -440,8 +438,7 @@ public function deleteWith(Delete $delete) */ protected function executeDelete(Delete $delete) { - $deleteState = $delete->getRawState(); - if ($deleteState['table'] != $this->table) { + if ($delete->table != $this->table) { throw new Exception\RuntimeException( 'The table name of the provided Delete object must match that of the table' ); diff --git a/src/TableGateway/Feature/MasterSlaveFeature.php b/src/TableGateway/Feature/MasterSlaveFeature.php index 07d36f954d..ab04f74f29 100644 --- a/src/TableGateway/Feature/MasterSlaveFeature.php +++ b/src/TableGateway/Feature/MasterSlaveFeature.php @@ -66,7 +66,7 @@ public function postInitialize() $this->slaveSql = new Sql( $this->slaveAdapter, $this->tableGateway->sql->getTable(), - $this->tableGateway->sql->getSqlPlatform() + $this->tableGateway->sql->getBuilder() ); } } diff --git a/src/TableGateway/Feature/SequenceFeature.php b/src/TableGateway/Feature/SequenceFeature.php index 3c72fd3b6f..11633346b0 100644 --- a/src/TableGateway/Feature/SequenceFeature.php +++ b/src/TableGateway/Feature/SequenceFeature.php @@ -47,8 +47,8 @@ public function __construct($primaryKeyField, $sequenceName) */ public function preInsert(Insert $insert) { - $columns = $insert->getRawState('columns'); - $values = $insert->getRawState('values'); + $columns = $insert->columns; + $values = $insert->values; $key = array_search($this->primaryKeyField, $columns); if ($key !== false) { $this->sequenceValue = $values[$key]; diff --git a/test/RowGateway/AbstractRowGatewayTest.php b/test/RowGateway/AbstractRowGatewayTest.php index d9bdeb9763..6dc3d32f3c 100644 --- a/test/RowGateway/AbstractRowGatewayTest.php +++ b/test/RowGateway/AbstractRowGatewayTest.php @@ -10,6 +10,8 @@ namespace ZendTest\Db\RowGateway; use Zend\Db\RowGateway\RowGateway; +use Zend\Db\Adapter\ParameterContainer; +use ZendTest\Db\TestAsset\TrustingSql92Platform; class AbstractRowGatewayTest extends \PHPUnit_Framework_TestCase { @@ -28,13 +30,14 @@ public function setup() $this->mockResult = $mockResult; $mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); $mockStatement->expects($this->any())->method('execute')->will($this->returnValue($mockResult)); + $mockStatement->expects($this->any())->method('getParameterContainer')->will($this->returnValue(new ParameterContainer)); $mockConnection = $this->getMock('Zend\Db\Adapter\Driver\ConnectionInterface'); $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); $mockDriver->expects($this->any())->method('createStatement')->will($this->returnValue($mockStatement)); $mockDriver->expects($this->any())->method('getConnection')->will($this->returnValue($mockConnection)); // setup mock adapter - $this->mockAdapter = $this->getMock('Zend\Db\Adapter\Adapter', null, [$mockDriver]); + $this->mockAdapter = $this->getMock('Zend\Db\Adapter\Adapter', null, [$mockDriver, new TrustingSql92Platform]); $this->rowGateway = $this->getMockForAbstractClass('Zend\Db\RowGateway\AbstractRowGateway'); diff --git a/test/Sql/AbstractSqlObjectTest.php b/test/Sql/AbstractSqlObjectTest.php deleted file mode 100644 index 12fa6d4488..0000000000 --- a/test/Sql/AbstractSqlObjectTest.php +++ /dev/null @@ -1,186 +0,0 @@ -abstractSql = $this->getMockForAbstractClass('Zend\Db\Sql\AbstractSqlObject'); - - $this->mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $this->mockDriver - ->expects($this->any()) - ->method('getPrepareType') - ->will($this->returnValue(DriverInterface::PARAMETERIZATION_NAMED)); - $this->mockDriver - ->expects($this->any()) - ->method('formatParameterName') - ->will($this->returnCallback(function ($x) { - return ':' . $x; - })); - } - - /** - * @covers Zend\Db\Sql\AbstractSqlObject::processExpression - */ - public function testProcessExpressionWithoutParameterContainer() - { - $expression = new Expression('? > ? AND y < ?', ['x', 5, 10], [Expression::TYPE_IDENTIFIER]); - $sqlAndParams = $this->invokeProcessExpressionMethod($expression); - - $this->assertEquals("\"x\" > '5' AND y < '10'", $sqlAndParams); - } - - /** - * @covers Zend\Db\Sql\AbstractSqlObject::processExpression - */ - public function testProcessExpressionWithParameterContainerAndParameterizationTypeNamed() - { - $parameterContainer = new ParameterContainer; - $expression = new Expression('? > ? AND y < ?', ['x', 5, 10], [Expression::TYPE_IDENTIFIER]); - $sqlAndParams = $this->invokeProcessExpressionMethod($expression, $parameterContainer); - - $parameters = $parameterContainer->getNamedArray(); - - $this->assertRegExp('#"x" > :expr\d\d\d\dParam1 AND y < :expr\d\d\d\dParam2#', $sqlAndParams); - - // test keys and values - preg_match('#expr(\d\d\d\d)Param1#', key($parameters), $matches); - $expressionNumber = $matches[1]; - - $this->assertRegExp('#expr\d\d\d\dParam1#', key($parameters)); - $this->assertEquals(5, current($parameters)); - next($parameters); - $this->assertRegExp('#expr\d\d\d\dParam2#', key($parameters)); - $this->assertEquals(10, current($parameters)); - - // ensure next invocation increases number by 1 - $parameterContainer = new ParameterContainer; - $sqlAndParamsNext = $this->invokeProcessExpressionMethod($expression, $parameterContainer); - - $parameters = $parameterContainer->getNamedArray(); - - preg_match('#expr(\d\d\d\d)Param1#', key($parameters), $matches); - $expressionNumberNext = $matches[1]; - - $this->assertEquals(1, (int) $expressionNumberNext - (int) $expressionNumber); - } - - /** - * @covers Zend\Db\Sql\AbstractSqlObject::processExpression - */ - public function testProcessExpressionWorksWithExpressionContainingStringParts() - { - $expression = new Predicate\Expression('x = ?', 5); - - $predicateSet = new Predicate\PredicateSet([new Predicate\PredicateSet([$expression])]); - $sqlAndParams = $this->invokeProcessExpressionMethod($predicateSet); - - $this->assertEquals("(x = '5')", $sqlAndParams); - } - - /** - * @covers Zend\Db\Sql\AbstractSqlObject::processExpression - */ - public function testProcessExpressionWorksWithExpressionContainingSelectObject() - { - $select = new Select(); - $select->from('x')->where->like('bar', 'Foo%'); - $expression = new Predicate\In('x', $select); - - $predicateSet = new Predicate\PredicateSet([new Predicate\PredicateSet([$expression])]); - $sqlAndParams = $this->invokeProcessExpressionMethod($predicateSet); - - $this->assertEquals('("x" IN (SELECT "x".* FROM "x" WHERE "bar" LIKE \'Foo%\'))', $sqlAndParams); - } - - public function testProcessExpressionWorksWithExpressionContainingExpressionObject() - { - $expression = new Predicate\Operator( - 'release_date', - '=', - new Expression('FROM_UNIXTIME(?)', 100000000) - ); - - $sqlAndParams = $this->invokeProcessExpressionMethod($expression); - $this->assertEquals('"release_date" = FROM_UNIXTIME(\'100000000\')', $sqlAndParams); - } - - /** - * @group 7407 - */ - public function testProcessExpressionWorksWithExpressionObjectWithPercentageSigns() - { - $expressionString = 'FROM_UNIXTIME(date, "%Y-%m")'; - $expression = new Expression($expressionString); - $sqlString = $this->invokeProcessExpressionMethod($expression); - - $this->assertSame($expressionString, $sqlString); - } - - public function testProcessExpressionWorksWithNamedParameterPrefix() - { - $parameterContainer = new ParameterContainer(); - $namedParameterPrefix = uniqid(); - $expression = new Expression('FROM_UNIXTIME(?)', [10000000]); - $this->invokeProcessExpressionMethod($expression, $parameterContainer, $namedParameterPrefix); - - $this->assertSame($namedParameterPrefix . '1', key($parameterContainer->getNamedArray())); - } - - public function testProcessExpressionWorksWithNamedParameterPrefixContainingWhitespace() - { - $parameterContainer = new ParameterContainer(); - $namedParameterPrefix = "string\ncontaining white space"; - $expression = new Expression('FROM_UNIXTIME(?)', [10000000]); - $this->invokeProcessExpressionMethod($expression, $parameterContainer, $namedParameterPrefix); - - $this->assertSame('string__containing__white__space1', key($parameterContainer->getNamedArray())); - } - - /** - * @param \Zend\Db\Sql\ExpressionInterface $expression - * @param \Zend\Db\Adapter\ParameterContainer $parameterContainer - * @param string $namedParameterPrefix - * @return \Zend\Db\Adapter\StatementContainer|string - */ - protected function invokeProcessExpressionMethod( - ExpressionInterface $expression, - $parameterContainer = null, - $namedParameterPrefix = null - ) { - $method = new \ReflectionMethod($this->abstractSql, 'processExpression'); - $method->setAccessible(true); - return $method->invoke( - $this->abstractSql, - $expression, - new TrustingSql92Platform, - $this->mockDriver, - $parameterContainer, - $namedParameterPrefix - ); - } -} diff --git a/test/Sql/Builder/AbstractTestCase.php b/test/Sql/Builder/AbstractTestCase.php new file mode 100644 index 0000000000..8e129761b9 --- /dev/null +++ b/test/Sql/Builder/AbstractTestCase.php @@ -0,0 +1,268 @@ += 2) { + foreach (func_get_args() as $i=>$arg) { + if ($i == 0) { + continue; + } + foreach ($arg as $a) { + $data[] = $a; + } + } + } + $res = []; + foreach ($data as $index => $test) { + foreach ($test['expected'] as $platform => $expected) { + $res[$index . '->' . $platform] = [ + 'sqlObject' => $test['sqlObject'], + 'platform' => $platform, + 'expected' => $expected, + ]; + } + } + return $res; + } + + public function assertBuilder($sqlObject, $platform = null, $expected = null) + { + if ($sqlObject instanceof \Closure) { + $sqlObject = call_user_func($sqlObject); + } + $builder = new Builder\Builder(); + $adapter = $this->getAdapterForPlatform($platform); + + if (is_array($expected) && isset($expected['decorators'])) { + foreach ($expected['decorators'] as $type=>$decorator) { + $builder->setPlatformBuilder($platform, $type, $this->resolveDecorator($decorator, $builder)); + } + } + if (is_array($expected) && isset($expected['ExpectedException'])) { + if (is_array($expected['ExpectedException'])) { + $this->setExpectedException( + $expected['ExpectedException'][0], + isset($expected['ExpectedException'][1]) ? $expected['ExpectedException'][1] : '', + isset($expected['ExpectedException'][2]) ? $expected['ExpectedException'][2] : null + ); + } else { + $this->setExpectedException($expected['ExpectedException']); + } + } + + $expectedString = is_string($expected) ? $expected : (isset($expected['string']) ? $expected['string'] : null); + if ($expectedString) { + $actual = $builder->getSqlString($sqlObject, $adapter); + $this->assertEquals($expectedString, $actual, "getSqlString()"); + } + if (is_array($expected) && isset($expected['prepare'])) { + if ($expected['prepare'] === true) { + $expected['prepare'] = $expectedString; + } + $this->useNamedParameters = isset($expected['useNamedParams']) && $expected['useNamedParams']; + + $actual = $builder->prepareStatement($sqlObject, $adapter); + $this->assertEquals($expected['prepare'], $actual->getSql(), "prepareStatement()"); + if (isset($expected['parameters'])) { + $this->assertSame( + $expected['parameters'], + $actual->getParameterContainer()->getNamedArray(), + "parameterContainer()" + ); + } elseif (isset($expected['parametersEquals'])) { + $this->assertEquals( + $expected['parametersEquals'], + $actual->getParameterContainer()->getNamedArray(), + "parameterContainer()" + ); + } + } + } + + protected function getAdapterForPlatform($platformName) + { + $platformName = str_replace(' ', '', strtolower($platformName)); + if (isset($this->adapters[$platformName])) { + return $this->adapters[$platformName]; + } + + switch ($platformName) { + case 'sql92' : $platform = new TestAsset\TrustingSql92Platform(); break; + case 'mysql' : $platform = new TestAsset\TrustingMysqlPlatform(); break; + case 'oracle' : $platform = new TestAsset\TrustingOraclePlatform(); break; + case 'sqlserver' : $platform = new TestAsset\TrustingSqlServerPlatform(); break; + case 'ibmdb2' : $platform = new TestAsset\TrustingIbmDb2Platform(); break; + case 'sqlite' : $platform = new TestAsset\TrustingSqlitePlatform(); break; + default : $platform = null; + } + + $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); + $mockDriver->expects($this->any())->method('formatParameterName')->will($this->returnCallback( + function ($name) { return (($this->useNamedParameters) ? ':' . $name : '?'); } + )); + $mockDriver->expects($this->any())->method('createStatement')->will($this->returnCallback(function () { + $mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); + $setSql = $this->returnCallback(function ($sql = null) { + static $thisSql; + if ($sql === null) { + return $thisSql; + } + $thisSql = $sql; + }); + $setParameterContainer = $this->returnCallback(function ($parameterContainer = null) { + static $thisParameterContainer; + if ($parameterContainer === null) { + return $thisParameterContainer; + } + $thisParameterContainer = $parameterContainer; + }); + $mockStatement->expects($this->any())->method('setSql')->will($setSql); + $mockStatement->expects($this->any())->method('getSql')->will($setSql); + $mockStatement->expects($this->any())->method('setParameterContainer')->will($setParameterContainer); + $mockStatement->expects($this->any())->method('getParameterContainer')->will($setParameterContainer); + return $mockStatement; + })); + + $this->adapters[$platformName] = new Adapter\Adapter($mockDriver, $platform); + return $this->adapters[$platformName]; + } + + protected function resolveDecorator($decorator, $builder) + { + if (!is_array($decorator)) { + return $decorator; + } + $decoratorMock = $this->getMock($decorator[0], ['buildSqlString'], [$builder]); + $decoratorMock->expects($this->any())->method('buildSqlString')->will($this->returnValue($decorator[1])); + return $decoratorMock; + } + + public function __call($name, $arguments) + { + $aliasMap = [ + 'select' => 'Zend\Db\Sql\Select', + 'delete' => 'Zend\Db\Sql\Delete', + 'update' => 'Zend\Db\Sql\Update', + 'insert' => 'Zend\Db\Sql\Insert', + 'combine' => 'Zend\Db\Sql\Combine', + 'dropTable' => 'Zend\Db\Sql\Ddl\DropTable', + 'alterTable' => 'Zend\Db\Sql\Ddl\AlterTable', + 'createTable' => 'Zend\Db\Sql\Ddl\CreateTable', + 'createColumn' => 'Zend\Db\Sql\Ddl\Column\Column', + + 'expression' => 'Zend\Db\Sql\Expression', + + 'predicate_Between' => 'Zend\Db\Sql\Predicate\Between', + 'predicate_NotBetween' => 'Zend\Db\Sql\Predicate\NotBetween', + 'predicate_Expression' => 'Zend\Db\Sql\Predicate\Expression', + 'predicate_In' => 'Zend\Db\Sql\Predicate\In', + 'predicate_IsNotNull' => 'Zend\Db\Sql\Predicate\IsNotNull', + 'predicate_IsNull' => 'Zend\Db\Sql\Predicate\IsNull', + 'predicate_Like' => 'Zend\Db\Sql\Predicate\Like', + 'predicate_Literal' => 'Zend\Db\Sql\Predicate\Literal', + 'predicate_NotIn' => 'Zend\Db\Sql\Predicate\NotIn', + 'predicate_NotLike' => 'Zend\Db\Sql\Predicate\NotLike', + 'predicate_Operator' => 'Zend\Db\Sql\Predicate\Operator', + 'predicate_Predicate' => 'Zend\Db\Sql\Predicate\Predicate', + 'predicate_PredicateSet'=> 'Zend\Db\Sql\Predicate\PredicateSet', + + 'index_Index' => 'Zend\Db\Sql\Ddl\Index\Index', + + 'constraint_Check' => 'Zend\Db\Sql\Ddl\Constraint\Check', + 'constraint_ForeignKey' => 'Zend\Db\Sql\Ddl\Constraint\ForeignKey', + 'constraint_PrimaryKey' => 'Zend\Db\Sql\Ddl\Constraint\PrimaryKey', + 'constraint_UniqueKey' => 'Zend\Db\Sql\Ddl\Constraint\UniqueKey', + 'column_BigInteger' => 'Zend\Db\Sql\Ddl\Column\BigInteger', + 'column_Binary' => 'Zend\Db\Sql\Ddl\Column\Binary', + 'column_Blob' => 'Zend\Db\Sql\Ddl\Column\Blob', + 'column_Boolean' => 'Zend\Db\Sql\Ddl\Column\Boolean', + 'column_Char' => 'Zend\Db\Sql\Ddl\Column\Char', + 'column_Column' => 'Zend\Db\Sql\Ddl\Column\Column', + 'column_Date' => 'Zend\Db\Sql\Ddl\Column\Date', + 'column_Datetime' => 'Zend\Db\Sql\Ddl\Column\Datetime', + 'column_Decimal' => 'Zend\Db\Sql\Ddl\Column\Decimal', + 'column_Floating' => 'Zend\Db\Sql\Ddl\Column\Floating', + 'column_Integer' => 'Zend\Db\Sql\Ddl\Column\Integer', + 'column_Text' => 'Zend\Db\Sql\Ddl\Column\Text', + 'column_Time' => 'Zend\Db\Sql\Ddl\Column\Time', + 'column_Timestamp' => 'Zend\Db\Sql\Ddl\Column\Timestamp', + 'column_Varbinary' => 'Zend\Db\Sql\Ddl\Column\Varbinary', + 'column_Varchar' => 'Zend\Db\Sql\Ddl\Column\Varchar', + ]; + if (!isset($aliasMap[$name])) { + throw new \Exception($name . ' method not found'); + } + $refl = new \ReflectionClass($aliasMap[$name]); + return $refl->newInstanceArgs($arguments); + } +} diff --git a/test/Sql/Builder/AllBuildersTest.php b/test/Sql/Builder/AllBuildersTest.php index 60b5da20a2..8cad720bf9 100644 --- a/test/Sql/Builder/AllBuildersTest.php +++ b/test/Sql/Builder/AllBuildersTest.php @@ -10,19 +10,26 @@ namespace ZendTest\Db\Sql\Builder; use Zend\Db\Sql; -use Zend\Db\Adapter; -use ZendTest\Db\TestAsset; -/** - * @method \Zend\Db\Sql\Select select(null|string $table) - * @method \Zend\Db\Sql\Update update(null|string $table) - * @method \Zend\Db\Sql\Delete delete(null|string $table) - * @method \Zend\Db\Sql\Insert insert(null|string $table) - * @method \Zend\Db\Sql\Ddl\CreateTable createTable(null|string $table) - * @method \Zend\Db\Sql\Ddl\Column\Column createColumn(null|string $name) - */ -class AllBuildersTest extends \PHPUnit_Framework_TestCase +class AllBuildersTest extends AbstractTestCase { + /** + * @param type $data + * @dataProvider dataProvider + */ + public function test($sqlObject, $platform, $expected) + { + $this->assertBuilder($sqlObject, $platform, $expected); + } + + public function dataProvider() + { + return $this->prepareDataProvider( + $this->dataProvider_CommonProcessMethods(), + $this->dataProvider_Builders() + ); + } + protected function dataProvider_CommonProcessMethods() { return [ @@ -131,22 +138,22 @@ protected function dataProvider_CommonProcessMethods() 'sql92' => [ 'string' => 'SELECT "a".*, "b".* FROM "a" INNER JOIN (SELECT "c".* FROM "c" WHERE "cc" = \'10\') AS "b" ON "d"="e" WHERE "x" = \'20\'', 'prepare' => 'SELECT "a".*, "b".* FROM "a" INNER JOIN (SELECT "c".* FROM "c" WHERE "cc" = ?) AS "b" ON "d"="e" WHERE "x" = ?', - 'parameters' => ['subselect1where1'=>10, 'where1'=>20], + 'parameters' => ['subselect1expr1'=>10, 'expr1'=>20], ], 'MySql' => [ 'string' => 'SELECT `a`.*, `b`.* FROM `a` INNER JOIN (SELECT `c`.* FROM `c` WHERE `cc` = \'10\') AS `b` ON `d`=`e` WHERE `x` = \'20\'', 'prepare' => 'SELECT `a`.*, `b`.* FROM `a` INNER JOIN (SELECT `c`.* FROM `c` WHERE `cc` = ?) AS `b` ON `d`=`e` WHERE `x` = ?', - 'parameters' => ['subselect2where1'=>10, 'where2'=>20], + 'parameters' => ['subselect1expr1'=>10, 'expr1'=>20], ], 'Oracle' => [ 'string' => 'SELECT "a".*, "b".* FROM "a" INNER JOIN (SELECT "c".* FROM "c" WHERE "cc" = \'10\') "b" ON "d"="e" WHERE "x" = \'20\'', 'prepare' => 'SELECT "a".*, "b".* FROM "a" INNER JOIN (SELECT "c".* FROM "c" WHERE "cc" = ?) "b" ON "d"="e" WHERE "x" = ?', - 'parameters' => ['subselect2where1'=>10, 'where2'=>20], + 'parameters' => ['subselect1expr1'=>10, 'expr1'=>20], ], 'SqlServer' => [ 'string' => 'SELECT [a].*, [b].* FROM [a] INNER JOIN (SELECT [c].* FROM [c] WHERE [cc] = \'10\') AS [b] ON [d]=[e] WHERE [x] = \'20\'', 'prepare' => 'SELECT [a].*, [b].* FROM [a] INNER JOIN (SELECT [c].* FROM [c] WHERE [cc] = ?) AS [b] ON [d]=[e] WHERE [x] = ?', - 'parameters' => ['subselect2where1'=>10, 'where2'=>20], + 'parameters' => ['subselect1expr1'=>10, 'expr1'=>20], ], ], ], @@ -176,22 +183,22 @@ protected function dataProvider_CommonProcessMethods() 'sql92' => [ 'string' => 'SELECT "a".* FROM (SELECT "b".* FROM (SELECT "c".* FROM "c" WHERE "cc" = \'CC\') AS "b" WHERE "bb" = \'BB\') AS "a" WHERE "aa" = \'AA\'', 'prepare' => 'SELECT "a".* FROM (SELECT "b".* FROM (SELECT "c".* FROM "c" WHERE "cc" = ?) AS "b" WHERE "bb" = ?) AS "a" WHERE "aa" = ?', - 'parameters' => ['subselect2where1' => 'CC', 'subselect1where1' => 'BB', 'where1' => 'AA'], + 'parameters' => ['subselect2expr1' => 'CC', 'subselect1expr1' => 'BB', 'expr1' => 'AA'], ], 'MySql' => [ 'string' => 'SELECT `a`.* FROM (SELECT `b`.* FROM (SELECT `c`.* FROM `c` WHERE `cc` = \'CC\') AS `b` WHERE `bb` = \'BB\') AS `a` WHERE `aa` = \'AA\'', 'prepare' => 'SELECT `a`.* FROM (SELECT `b`.* FROM (SELECT `c`.* FROM `c` WHERE `cc` = ?) AS `b` WHERE `bb` = ?) AS `a` WHERE `aa` = ?', - 'parameters' => ['subselect4where1' => 'CC', 'subselect3where1' => 'BB', 'where2' => 'AA'], + 'parameters' => ['subselect2expr1' => 'CC', 'subselect1expr1' => 'BB', 'expr1' => 'AA'], ], 'Oracle' => [ 'string' => 'SELECT "a".* FROM (SELECT "b".* FROM (SELECT "c".* FROM "c" WHERE "cc" = \'CC\') "b" WHERE "bb" = \'BB\') "a" WHERE "aa" = \'AA\'', 'prepare' => 'SELECT "a".* FROM (SELECT "b".* FROM (SELECT "c".* FROM "c" WHERE "cc" = ?) "b" WHERE "bb" = ?) "a" WHERE "aa" = ?', - 'parameters' => ['subselect4where1' => 'CC', 'subselect3where1' => 'BB', 'where2' => 'AA'], + 'parameters' => ['subselect2expr1' => 'CC', 'subselect1expr1' => 'BB', 'expr1' => 'AA'], ], 'SqlServer' => [ 'string' => 'SELECT [a].* FROM (SELECT [b].* FROM (SELECT [c].* FROM [c] WHERE [cc] = \'CC\') AS [b] WHERE [bb] = \'BB\') AS [a] WHERE [aa] = \'AA\'', 'prepare' => 'SELECT [a].* FROM (SELECT [b].* FROM (SELECT [c].* FROM [c] WHERE [cc] = ?) AS [b] WHERE [bb] = ?) AS [a] WHERE [aa] = ?', - 'parameters' => ['subselect4where1' => 'CC', 'subselect3where1' => 'BB', 'where2' => 'AA'], + 'parameters' => ['subselect2expr1' => 'CC', 'subselect1expr1' => 'BB', 'expr1' => 'AA'], ], ], ], @@ -201,22 +208,22 @@ protected function dataProvider_CommonProcessMethods() 'sql92' => [ 'string' => 'DELETE FROM "foo" WHERE "x" = (SELECT "foo".* FROM "foo" WHERE "x" = \'y\')', 'prepare' => 'DELETE FROM "foo" WHERE "x" = (SELECT "foo".* FROM "foo" WHERE "x" = ?)', - 'parameters' => ['subselect1where1' => 'y'], + 'parameters' => ['subselect1expr1' => 'y'], ], 'MySql' => [ 'string' => 'DELETE FROM `foo` WHERE `x` = (SELECT `foo`.* FROM `foo` WHERE `x` = \'y\')', 'prepare' => 'DELETE FROM `foo` WHERE `x` = (SELECT `foo`.* FROM `foo` WHERE `x` = ?)', - 'parameters' => ['subselect2where1' => 'y'], + 'parameters' => ['subselect1expr1' => 'y'], ], 'Oracle' => [ 'string' => 'DELETE FROM "foo" WHERE "x" = (SELECT "foo".* FROM "foo" WHERE "x" = \'y\')', 'prepare' => 'DELETE FROM "foo" WHERE "x" = (SELECT "foo".* FROM "foo" WHERE "x" = ?)', - 'parameters' => ['subselect3where1' => 'y'], + 'parameters' => ['subselect1expr1' => 'y'], ], 'SqlServer' => [ 'string' => 'DELETE FROM [foo] WHERE [x] = (SELECT [foo].* FROM [foo] WHERE [x] = \'y\')', 'prepare' => 'DELETE FROM [foo] WHERE [x] = (SELECT [foo].* FROM [foo] WHERE [x] = ?)', - 'parameters' => ['subselect4where1' => 'y'], + 'parameters' => ['subselect1expr1' => 'y'], ], ], ], @@ -235,22 +242,22 @@ protected function dataProvider_CommonProcessMethods() 'sql92' => [ 'string' => 'INSERT INTO "foo" SELECT "foo".* FROM "foo" WHERE "x" = \'y\'', 'prepare' => 'INSERT INTO "foo" SELECT "foo".* FROM "foo" WHERE "x" = ?', - 'parameters' => ['subselect1where1' => 'y'], + 'parameters' => ['subselect1expr1' => 'y'], ], 'MySql' => [ 'string' => 'INSERT INTO `foo` SELECT `foo`.* FROM `foo` WHERE `x` = \'y\'', 'prepare' => 'INSERT INTO `foo` SELECT `foo`.* FROM `foo` WHERE `x` = ?', - 'parameters' => ['subselect2where1' => 'y'], + 'parameters' => ['subselect1expr1' => 'y'], ], 'Oracle' => [ 'string' => 'INSERT INTO "foo" SELECT "foo".* FROM "foo" WHERE "x" = \'y\'', 'prepare' => 'INSERT INTO "foo" SELECT "foo".* FROM "foo" WHERE "x" = ?', - 'parameters' => ['subselect3where1' => 'y'], + 'parameters' => ['subselect1expr1' => 'y'], ], 'SqlServer' => [ 'string' => 'INSERT INTO [foo] SELECT [foo].* FROM [foo] WHERE [x] = \'y\'', 'prepare' => 'INSERT INTO [foo] SELECT [foo].* FROM [foo] WHERE [x] = ?', - 'parameters' => ['subselect4where1' => 'y'], + 'parameters' => ['subselect1expr1' => 'y'], ], ], ], @@ -260,26 +267,26 @@ protected function dataProvider_CommonProcessMethods() 'sql92' => [ 'string' => 'UPDATE "foo" SET "x" = (SELECT "foo".* FROM "foo" WHERE "x" = \'y\')', 'prepare' => 'UPDATE "foo" SET "x" = (SELECT "foo".* FROM "foo" WHERE "x" = ?)', - 'parameters' => ['subselect1where1' => 'y'], + 'parameters' => ['subselect1expr1' => 'y'], ], 'MySql' => [ 'string' => 'UPDATE `foo` SET `x` = (SELECT `foo`.* FROM `foo` WHERE `x` = \'y\')', 'prepare' => 'UPDATE `foo` SET `x` = (SELECT `foo`.* FROM `foo` WHERE `x` = ?)', - 'parameters' => ['subselect2where1' => 'y'], + 'parameters' => ['subselect1expr1' => 'y'], ], 'Oracle' => [ 'string' => 'UPDATE "foo" SET "x" = (SELECT "foo".* FROM "foo" WHERE "x" = \'y\')', 'prepare' => 'UPDATE "foo" SET "x" = (SELECT "foo".* FROM "foo" WHERE "x" = ?)', - 'parameters' => ['subselect3where1' => 'y'], + 'parameters' => ['subselect1expr1' => 'y'], ], 'SqlServer' => [ 'string' => 'UPDATE [foo] SET [x] = (SELECT [foo].* FROM [foo] WHERE [x] = \'y\')', 'prepare' => 'UPDATE [foo] SET [x] = (SELECT [foo].* FROM [foo] WHERE [x] = ?)', - 'parameters' => ['subselect4where1' => 'y'], + 'parameters' => ['subselect1expr1' => 'y'], ], ], ], - 'Update::processJoins()' => [ + 'Update::processJoins()_1' => [ 'sqlObject' => $this->update('foo')->set(['x' => 'y'])->where(['xx' => 'yy'])->join( 'bar', 'bar.barId = foo.barId' @@ -299,6 +306,33 @@ protected function dataProvider_CommonProcessMethods() ], ], ], + 'Update::processJoins()_2' => [ + 'sqlObject' => $this->update('Document')->set(['x' => 'y']) + ->join( + 'User', // table name + 'User.UserId = Document.UserId' // expression to join on (will be quoted by platform object before insertion), + // default JOIN INNER + ) + ->join( + 'Category', + 'Category.CategoryId = Document.CategoryId', + Sql\Join::JOIN_LEFT // (optional), one of inner, outer, left, right + ), + 'expected' => [ + 'sql92' => [ + 'string' => 'UPDATE "Document" INNER JOIN "User" ON "User"."UserId" = "Document"."UserId" LEFT JOIN "Category" ON "Category"."CategoryId" = "Document"."CategoryId" SET "x" = \'y\'', + ], + 'MySql' => [ + 'string' => 'UPDATE `Document` INNER JOIN `User` ON `User`.`UserId` = `Document`.`UserId` LEFT JOIN `Category` ON `Category`.`CategoryId` = `Document`.`CategoryId` SET `x` = \'y\'', + ], + 'Oracle' => [ + 'string' => 'UPDATE "Document" INNER JOIN "User" ON "User"."UserId" = "Document"."UserId" LEFT JOIN "Category" ON "Category"."CategoryId" = "Document"."CategoryId" SET "x" = \'y\'', + ], + 'SqlServer' => [ + 'string' => 'UPDATE [Document] INNER JOIN [User] ON [User].[UserId] = [Document].[UserId] LEFT JOIN [Category] ON [Category].[CategoryId] = [Document].[CategoryId] SET [x] = \'y\'', + ], + ], + ], ]; } @@ -310,59 +344,58 @@ protected function dataProvider_Builders() 'expected' => [ 'sql92' => [ 'decorators' => [ - 'Zend\Db\Sql\Select' => new TestAsset\SelectBuilder, + 'Zend\Db\Sql\Select' => 'ZendTest\Db\TestAsset\SelectBuilder', ], 'string' => 'SELECT "foo".* FROM "foo" WHERE "x" = (SELECT "bar".* FROM "bar")', ], 'MySql' => [ 'decorators' => [ - 'Zend\Db\Sql\Select' => new TestAsset\SelectBuilder, + 'Zend\Db\Sql\Select' => 'ZendTest\Db\TestAsset\SelectBuilder', ], 'string' => 'SELECT `foo`.* FROM `foo` WHERE `x` = (SELECT `bar`.* FROM `bar`)', ], 'Oracle' => [ 'decorators' => [ - 'Zend\Db\Sql\Select' => new TestAsset\SelectBuilder, + 'Zend\Db\Sql\Select' => 'ZendTest\Db\TestAsset\SelectBuilder', ], 'string' => 'SELECT "foo".* FROM "foo" WHERE "x" = (SELECT "bar".* FROM "bar")', ], 'SqlServer' => [ 'decorators' => [ - 'Zend\Db\Sql\Select' => new TestAsset\SelectBuilder, + 'Zend\Db\Sql\Select' => 'ZendTest\Db\TestAsset\SelectBuilder', ], 'string' => 'SELECT [foo].* FROM [foo] WHERE [x] = (SELECT [bar].* FROM [bar])', ], ], ], - /* TODO - should be implemeted 'RootDecorators::Insert' => [ 'sqlObject' => $this->insert('foo')->select($this->select()), 'expected' => [ 'sql92' => [ 'decorators' => [ - 'Zend\Db\Sql\Insert' => new TestAsset\InsertDecorator, // Decorator for root sqlObject - 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Mysql\SelectBuilder', '{=SELECT_Sql92=}'] + 'Zend\Db\Sql\Insert' => 'ZendTest\Db\TestAsset\InsertBuilder', // Decorator for root sqlObject + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\sql92\SelectBuilder', '{=SELECT_Sql92=}'] ], 'string' => 'INSERT INTO "foo" {=SELECT_Sql92=}', ], 'MySql' => [ 'decorators' => [ - 'Zend\Db\Sql\Insert' => new TestAsset\InsertDecorator, // Decorator for root sqlObject - 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Mysql\SelectBuilder', '{=SELECT_MySql=}'] + 'Zend\Db\Sql\Insert' => 'ZendTest\Db\TestAsset\InsertBuilder', // Decorator for root sqlObject + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\sql92\SelectBuilder', '{=SELECT_MySql=}'] ], 'string' => 'INSERT INTO `foo` {=SELECT_MySql=}', ], 'Oracle' => [ 'decorators' => [ - 'Zend\Db\Sql\Insert' => new TestAsset\InsertDecorator, // Decorator for root sqlObject - 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Oracle\SelectBuilder', '{=SELECT_Oracle=}'] + 'Zend\Db\Sql\Insert' => 'ZendTest\Db\TestAsset\InsertBuilder', // Decorator for root sqlObject + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\sql92\SelectBuilder', '{=SELECT_Oracle=}'] ], 'string' => 'INSERT INTO "foo" {=SELECT_Oracle=}', ], 'SqlServer' => [ 'decorators' => [ - 'Zend\Db\Sql\Insert' => new TestAsset\InsertDecorator, // Decorator for root sqlObject - 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\SqlServer\SelectBuilder', '{=SELECT_SqlServer=}'] + 'Zend\Db\Sql\Insert' => 'ZendTest\Db\TestAsset\InsertBuilder', // Decorator for root sqlObject + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\sql92\SelectBuilder', '{=SELECT_SqlServer=}'] ], 'string' => 'INSERT INTO [foo] {=SELECT_SqlServer=}', ], @@ -373,29 +406,29 @@ protected function dataProvider_Builders() 'expected' => [ 'sql92' => [ 'decorators' => [ - 'Zend\Db\Sql\Delete' => new TestAsset\DeleteDecorator, - 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Mysql\SelectBuilder', '{=SELECT_Sql92=}'] + 'Zend\Db\Sql\Delete' => 'ZendTest\Db\TestAsset\DeleteBuilder', + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\sql92\SelectBuilder', '{=SELECT_Sql92=}'] ], 'string' => 'DELETE FROM "foo" WHERE "x" = ({=SELECT_Sql92=})', ], 'MySql' => [ 'decorators' => [ - 'Zend\Db\Sql\Delete' => new TestAsset\DeleteDecorator, - 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Mysql\SelectBuilder', '{=SELECT_MySql=}'] + 'Zend\Db\Sql\Delete' => 'ZendTest\Db\TestAsset\DeleteBuilder', + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\sql92\SelectBuilder', '{=SELECT_MySql=}'] ], 'string' => 'DELETE FROM `foo` WHERE `x` = ({=SELECT_MySql=})', ], 'Oracle' => [ 'decorators' => [ - 'Zend\Db\Sql\Delete' => new TestAsset\DeleteDecorator, - 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Oracle\SelectBuilder', '{=SELECT_Oracle=}'] + 'Zend\Db\Sql\Delete' => 'ZendTest\Db\TestAsset\DeleteBuilder', + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\sql92\SelectBuilder', '{=SELECT_Oracle=}'] ], 'string' => 'DELETE FROM "foo" WHERE "x" = ({=SELECT_Oracle=})', ], 'SqlServer' => [ 'decorators' => [ - 'Zend\Db\Sql\Delete' => new TestAsset\DeleteDecorator, - 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\SqlServer\SelectBuilder', '{=SELECT_SqlServer=}'] + 'Zend\Db\Sql\Delete' => 'ZendTest\Db\TestAsset\DeleteBuilder', + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\sql92\SelectBuilder', '{=SELECT_SqlServer=}'] ], 'string' => 'DELETE FROM [foo] WHERE [x] = ({=SELECT_SqlServer=})', ], @@ -406,62 +439,63 @@ protected function dataProvider_Builders() 'expected' => [ 'sql92' => [ 'decorators' => [ - 'Zend\Db\Sql\Update' => new TestAsset\UpdateDecorator, - 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Mysql\SelectBuilder', '{=SELECT_Sql92=}'] + 'Zend\Db\Sql\Update' => 'ZendTest\Db\TestAsset\UpdateBuilder', + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\Mysql\SelectBuilder', '{=SELECT_Sql92=}'] ], 'string' => 'UPDATE "foo" SET WHERE "x" = ({=SELECT_Sql92=})', ], 'MySql' => [ 'decorators' => [ - 'Zend\Db\Sql\Update' => new TestAsset\UpdateDecorator, - 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Mysql\SelectBuilder', '{=SELECT_MySql=}'] + 'Zend\Db\Sql\Update' => 'ZendTest\Db\TestAsset\UpdateBuilder', + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\Mysql\SelectBuilder', '{=SELECT_MySql=}'] ], 'string' => 'UPDATE `foo` SET WHERE `x` = ({=SELECT_MySql=})', ], 'Oracle' => [ 'decorators' => [ - 'Zend\Db\Sql\Update' => new TestAsset\UpdateDecorator, - 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Oracle\SelectBuilder', '{=SELECT_Oracle=}'] + 'Zend\Db\Sql\Update' => 'ZendTest\Db\TestAsset\UpdateBuilder', + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\Oracle\SelectBuilder', '{=SELECT_Oracle=}'] ], 'string' => 'UPDATE "foo" SET WHERE "x" = ({=SELECT_Oracle=})', ], 'SqlServer' => [ 'decorators' => [ - 'Zend\Db\Sql\Update' => new TestAsset\UpdateDecorator, - 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\SqlServer\SelectBuilder', '{=SELECT_SqlServer=}'] + 'Zend\Db\Sql\Update' => 'ZendTest\Db\TestAsset\UpdateBuilder', + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\SqlServer\SelectBuilder', '{=SELECT_SqlServer=}'] ], 'string' => 'UPDATE [foo] SET WHERE [x] = ({=SELECT_SqlServer=})', ], ], ], + /* TODO - should be implemeted 'DecorableExpression()' => [ 'sqlObject' => $this->update('foo')->where(['x'=>new Sql\Expression('?', [$this->select('foo')])]), 'expected' => [ 'sql92' => [ 'decorators' => [ 'Zend\Db\Sql\Expression' => new TestAsset\DecorableExpression, - 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Mysql\SelectBuilder', '{=SELECT_Sql92=}'] + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\Mysql\SelectBuilder', '{=SELECT_Sql92=}'] ], 'string' => 'UPDATE "foo" SET WHERE "x" = {decorate-({=SELECT_Sql92=})-decorate}', ], 'MySql' => [ 'decorators' => [ 'Zend\Db\Sql\Expression' => new TestAsset\DecorableExpression, - 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Mysql\SelectBuilder', '{=SELECT_MySql=}'] + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\Mysql\SelectBuilder', '{=SELECT_MySql=}'] ], 'string' => 'UPDATE `foo` SET WHERE `x` = {decorate-({=SELECT_MySql=})-decorate}', ], 'Oracle' => [ 'decorators' => [ 'Zend\Db\Sql\Expression' => new TestAsset\DecorableExpression, - 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\Oracle\SelectBuilder', '{=SELECT_Oracle=}'] + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\Oracle\SelectBuilder', '{=SELECT_Oracle=}'] ], 'string' => 'UPDATE "foo" SET WHERE "x" = {decorate-({=SELECT_Oracle=})-decorate}', ], 'SqlServer' => [ 'decorators' => [ 'Zend\Db\Sql\Expression' => new TestAsset\DecorableExpression, - 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Platform\SqlServer\SelectBuilder', '{=SELECT_SqlServer=}'] + 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\SqlServer\SelectBuilder', '{=SELECT_SqlServer=}'] ], 'string' => 'UPDATE [foo] SET WHERE [x] = {decorate-({=SELECT_SqlServer=})-decorate}', ], @@ -469,98 +503,4 @@ protected function dataProvider_Builders() ],*/ ]; } - - public function dataProvider() - { - $data = array_merge( - $this->dataProvider_CommonProcessMethods(), - $this->dataProvider_Builders() - ); - - $res = []; - foreach ($data as $index => $test) { - foreach ($test['expected'] as $platform => $expected) { - $res[$index . '->' . $platform] = [ - 'sqlObject' => $test['sqlObject'], - 'platform' => $platform, - 'expected' => $expected, - ]; - } - } - return $res; - } - - /** - * @param type $sqlObject - * @param type $platform - * @param type $expected - * @dataProvider dataProvider - */ - public function test($sqlObject, $platform, $expected) - { - $sql = new Sql\Sql($this->resolveAdapter($platform)); - - if (is_array($expected) && isset($expected['decorators'])) { - foreach ($expected['decorators'] as $type=>$decorator) { - $sql->getSqlPlatform()->setTypeDecorator($type, $this->resolveDecorator($decorator)); - } - } - - $expectedString = is_string($expected) ? $expected : (isset($expected['string']) ? $expected['string'] : null); - if ($expectedString) { - $actual = $sql->getSqlStringForSqlObject($sqlObject); - $this->assertEquals($expectedString, $actual, "getSqlString()"); - } - if (is_array($expected) && isset($expected['prepare'])) { - $actual = $sql->prepareStatementForSqlObject($sqlObject); - $this->assertEquals($expected['prepare'], $actual->getSql(), "prepareStatement()"); - if (isset($expected['parameters'])) { - $actual = $actual->getParameterContainer()->getNamedArray(); - $this->assertSame($expected['parameters'], $actual, "parameterContainer()"); - } - } - } - - protected function resolveDecorator($decorator) - { - if (is_array($decorator)) { - $decoratorMock = $this->getMock($decorator[0], ['buildSqlString'], [null]); - $decoratorMock->expects($this->any())->method('buildSqlString')->will($this->returnValue($decorator[1])); - return $decoratorMock; - } - if ($decorator instanceof Sql\Builder\PlatformDecoratorInterface) { - return $decorator; - } - return; - } - - protected function resolveAdapter($platform) - { - switch ($platform) { - case 'sql92' : $platform = new TestAsset\TrustingSql92Platform(); break; - case 'MySql' : $platform = new TestAsset\TrustingMysqlPlatform(); break; - case 'Oracle' : $platform = new TestAsset\TrustingOraclePlatform(); break; - case 'SqlServer' : $platform = new TestAsset\TrustingSqlServerPlatform(); break; - default : $platform = null; - } - - $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $mockDriver->expects($this->any())->method('formatParameterName')->will($this->returnValue('?')); - $mockDriver->expects($this->any())->method('createStatement')->will($this->returnCallback(function () {return new Adapter\StatementContainer;})); - - return new Adapter\Adapter($mockDriver, $platform); - } - - public function __call($name, $arguments) - { - $arg0 = isset($arguments[0]) ? $arguments[0] : null; - switch ($name) { - case 'select' : return new Sql\Select($arg0); - case 'delete' : return new Sql\Delete($arg0); - case 'update' : return new Sql\Update($arg0); - case 'insert' : return new Sql\Insert($arg0); - case 'createTable' : return new Sql\Ddl\CreateTable($arg0); - case 'createColumn' : return new Sql\Ddl\Column\Column($arg0); - } - } } diff --git a/test/Sql/Builder/BuilderTest.php b/test/Sql/Builder/BuilderTest.php index 32d2608f81..1ca455908b 100644 --- a/test/Sql/Builder/BuilderTest.php +++ b/test/Sql/Builder/BuilderTest.php @@ -9,112 +9,148 @@ namespace ZendTest\Db\Sql\Builder; -use ReflectionMethod; -use Zend\Db\Adapter\StatementContainer; -use ZendTest\Db\TestAsset; use Zend\Db\Sql\Builder\Builder; -use Zend\Db\Adapter\Adapter; +use Zend\Db\Sql; -class BuilderTest extends \PHPUnit_Framework_TestCase +class BuilderTest extends AbstractTestCase { - public function testResolveDefaultPlatform() - { - $adapter = $this->resolveAdapter('sql92'); - $platform = new Builder($adapter); - - $reflectionMethod = new ReflectionMethod($platform, 'resolvePlatform'); - - $reflectionMethod->setAccessible(true); + /** + * @var Builder + */ + protected $builder; - $this->assertEquals($adapter->getPlatform(), $reflectionMethod->invoke($platform, null)); + public function setUp() + { + $this->builder = new Builder(); + $inheritableBuilders = new \ReflectionProperty($this->builder, 'inheritableBuilders'); + $inheritableBuilders->setAccessible(true); + $inheritableBuilders->setValue($this->builder, [ + 'Zend\Db\Sql\Select' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\SelectBuilder', + 'mysql' => 'Zend\Db\Sql\Builder\MySql\SelectBuilder', + ], + 'Zend\Db\Sql\Ddl\CreateTable' => [ + 'sqlserver' => 'Zend\Db\Sql\Builder\SqlServer\Ddl\CreateTableBuilder', + ], + ]); } - public function testResolvePlatformName() + /** + * @expectedException Zend\Db\Sql\Exception\RuntimeException + */ + public function testGePlatformBuilderForNotExistsObject() { - $platform = new Builder($this->resolveAdapter('sql92')); - - $reflectionMethod = new ReflectionMethod($platform, 'resolvePlatformName'); - - $reflectionMethod->setAccessible(true); - - $this->assertEquals('mysql', $reflectionMethod->invoke($platform, new TestAsset\TrustingMysqlPlatform())); - $this->assertEquals('sqlserver', $reflectionMethod->invoke($platform, new TestAsset\TrustingSqlServerPlatform())); - $this->assertEquals('oracle', $reflectionMethod->invoke($platform, new TestAsset\TrustingOraclePlatform())); - $this->assertEquals('sql92', $reflectionMethod->invoke($platform, new TestAsset\TrustingSql92Platform())); + $this->builder->getPlatformBuilder(new Sql\Insert()); } /** - * @group 6890 + * @expectedException Zend\Db\Sql\Exception\RuntimeException */ - public function testAbstractPlatformCrashesGracefullyOnMissingDefaultPlatform() + public function testGePlatformBuilderForNotExistsPlatform() { - $adapter = $this->resolveAdapter('sql92'); - $reflectionProperty = new \ReflectionProperty($adapter, 'platform'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($adapter, null); - - $platform = new Builder($adapter); - $reflectionMethod = new ReflectionMethod($platform, 'resolvePlatform'); + $this->assertInstanceOf( + 'Zend\Db\Sql\Builder\sql92\SelectBuilder', + $this->builder->getPlatformBuilder(new Sql\Select(), 'NotExistingPlatform') + ); + $this->builder->getPlatformBuilder(new Sql\Ddl\CreateTable(), 'NotExistingPlatform'); + } - $reflectionMethod->setAccessible(true); + public function testGetPlatformBuilder() + { + $this->assertInstanceOf( + 'Zend\Db\Sql\Builder\sql92\SelectBuilder', + $this->builder->getPlatformBuilder(new Sql\Select()) + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Builder\sql92\SelectBuilder', + $this->builder->getPlatformBuilder(new Sql\Select(), 'sql92') + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Builder\MySql\SelectBuilder', + $this->builder->getPlatformBuilder(new Sql\Select(), 'mysql') + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Builder\sql92\SelectBuilder', + $this->builder->getPlatformBuilder(new Sql\Select(), 'sqlserver') + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Builder\SqlServer\Ddl\CreateTableBuilder', + $this->builder->getPlatformBuilder(new Sql\Ddl\CreateTable(), 'sqlserver') + ); + } - $this->setExpectedException('Zend\Db\Sql\Exception\RuntimeException', '$this->defaultPlatform was not set'); + public function testSetPlatformBuilder() + { + $this->builder->setPlatformBuilder('ibmdb2', 'Zend\Db\Sql\Select', 'Zend\Db\Sql\Builder\IbmDb2\SelectBuilder'); + $this->assertInstanceOf( + 'Zend\Db\Sql\Builder\sql92\SelectBuilder', + $this->builder->getPlatformBuilder(new Sql\Select(), 'sql92') + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Builder\IbmDb2\SelectBuilder', + $this->builder->getPlatformBuilder(new Sql\Select(), 'ibmdb2') + ); + + $oracleSelectBuilder = new \Zend\Db\Sql\Builder\Oracle\SelectBuilder($this->builder); + $this->builder->setPlatformBuilder('oracle', 'Zend\Db\Sql\Select', $oracleSelectBuilder); + $this->assertSame( + $oracleSelectBuilder, + $this->builder->getPlatformBuilder(new Sql\Select(), 'oracle') + ); + } - $reflectionMethod->invoke($platform, null); + /** + * @expectedException Zend\Db\Sql\Exception\InvalidArgumentException + */ + public function testSetWrongPlatformBuilder() + { + $this->builder->setPlatformBuilder('oracle', 'Zend\Db\Sql\Select', new \stdClass()); } /** - * @group 6890 + * @covers Zend\Db\Sql\Builder\Builder::setDefaultAdapter + * @covers Zend\Db\Sql\Builder\Builder::getDefaultAdapter */ - public function testAbstractPlatformCrashesGracefullyOnMissingDefaultPlatformWithGetDecorators() + public function testDefaultAdapter() { - $adapter = $this->resolveAdapter('sql92'); - $reflectionProperty = new \ReflectionProperty($adapter, 'platform'); - $reflectionProperty->setAccessible(true); - $reflectionProperty->setValue($adapter, null); + $builder = new Builder(); + $this->assertNull($builder->getDefaultAdapter()); - $platform = new Builder($adapter); - $reflectionMethod = new ReflectionMethod($platform, 'resolvePlatform'); + $adapter = $this->getAdapterForPlatform('sqlserver'); + $builder = new Builder($adapter); + $this->assertSame($adapter, $builder->getDefaultAdapter()); - $reflectionMethod->setAccessible(true); + $adapter = $this->getAdapterForPlatform('sql92'); + $this->assertSame($adapter, $builder->setDefaultAdapter($adapter)->getDefaultAdapter()); - $this->setExpectedException('Zend\Db\Sql\Exception\RuntimeException', '$this->defaultPlatform was not set'); + $adapter = $this->getAdapterForPlatform('mysql'); + $this->assertSame($adapter, $builder->setDefaultAdapter($adapter)->getDefaultAdapter()); + } - $platform->getDecorators(); + /** + * @covers Zend\Db\Sql\Builder\Builder::getSqlString + */ + public function testGetSqlString() + { + $this->assertInternalType( + 'string', + $this->builder->getSqlString( + new Sql\Select('foo'), + $this->getAdapterForPlatform('sql92') + ) + ); } /** - * @param string $platformName - * - * @return Adapter + * @covers Zend\Db\Sql\Builder\Builder::prepareStatement */ - protected function resolveAdapter($platformName) + public function testPrepareStatement() { - $platform = null; - - switch ($platformName) { - case 'sql92' : - $platform = new TestAsset\TrustingSql92Platform(); - break; - case 'MySql' : - $platform = new TestAsset\TrustingMysqlPlatform(); - break; - case 'Oracle' : - $platform = new TestAsset\TrustingOraclePlatform(); - break; - case 'SqlServer' : - $platform = new TestAsset\TrustingSqlServerPlatform(); - break; - } - - /* @var $mockDriver \Zend\Db\Adapter\Driver\DriverInterface|\PHPUnit_Framework_MockObject_MockObject */ - $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - - $mockDriver->expects($this->any())->method('formatParameterName')->will($this->returnValue('?')); - $mockDriver->expects($this->any())->method('createStatement')->will($this->returnCallback(function () { - return new StatementContainer(); - })); - - return new Adapter($mockDriver, $platform); + $statement = $this->builder->prepareStatement( + new Sql\Select('foo'), + $this->getAdapterForPlatform('sql92') + ); + $this->assertInstanceOf('Zend\Db\Adapter\Driver\StatementInterface', $statement); + $this->assertInstanceOf('Zend\Db\Adapter\ParameterContainer', $statement->getParameterContainer()); } } diff --git a/test/Sql/Builder/CombineBuilderTest.php b/test/Sql/Builder/CombineBuilderTest.php new file mode 100644 index 0000000000..8f624e70ac --- /dev/null +++ b/test/Sql/Builder/CombineBuilderTest.php @@ -0,0 +1,121 @@ +assertBuilder($sqlObject, $platform, $expected); + } + + public function dataProvider() + { + return $this->prepareDataProvider([ + [ // testGetSqlStringEmpty() + 'sqlObject' => $this->combine(), + 'expected' => [ + 'sql92' => [ + 'string' => '', + 'prepare' => '' + ], + ], + ], + [ // testGetSqlString() + 'sqlObject' => $this->combine() + ->union($this->select('t1')) + ->intersect($this->select('t2')) + ->except($this->select('t3')) + ->union($this->select('t4')), + 'expected' => [ + 'sql92' => [ + 'string' => '(SELECT "t1".* FROM "t1") INTERSECT (SELECT "t2".* FROM "t2") EXCEPT (SELECT "t3".* FROM "t3") UNION (SELECT "t4".* FROM "t4")', + ], + ], + ], + [ // testGetSqlStringWithModifier() + 'sqlObject' => $this->combine() + ->union($this->select('t1')) + ->union($this->select('t2'), 'ALL'), + 'expected' => [ + 'sql92' => [ + 'string' => '(SELECT "t1".* FROM "t1") UNION ALL (SELECT "t2".* FROM "t2")', + ], + ], + ], + [ + 'sqlObject' => $this->combine([ + [$this->select('t1')], + [$this->select('t2'), Combine::COMBINE_INTERSECT, 'ALL'], + [$this->select('t3'), Combine::COMBINE_EXCEPT], + ]), + 'expected' => [ + 'sql92' => [ + 'string' => '(SELECT "t1".* FROM "t1") INTERSECT ALL (SELECT "t2".* FROM "t2") EXCEPT (SELECT "t3".* FROM "t3")', + ], + ], + ], + [ + 'sqlObject' => $this->combine([ + $this->select('t1'), + $this->select('t2'), + $this->select('t3'), + ]), + 'expected' => [ + 'sql92' => [ + 'string' => '(SELECT "t1".* FROM "t1") UNION (SELECT "t2".* FROM "t2") UNION (SELECT "t3".* FROM "t3")', + ], + ], + ], + [ + 'sqlObject' => $this->combine([ + $this->select('t1')->where(['x1'=>10]), + $this->select('t2')->where(['x2'=>20]) + ]), + 'expected' => [ + 'sql92' => [ + 'string' => '(SELECT "t1".* FROM "t1" WHERE "x1" = \'10\') UNION (SELECT "t2".* FROM "t2" WHERE "x2" = \'20\')', + 'prepare' => '(SELECT "t1".* FROM "t1" WHERE "x1" = ?) UNION (SELECT "t2".* FROM "t2" WHERE "x2" = ?)' + ], + ], + ], + [ + 'sqlObject' => $this->combine($this->combine([ + $this->select('t1'), + $this->select('t2'), + ])), + 'expected' => [ + 'sql92' => [ + 'string' => '((SELECT "t1".* FROM "t1") UNION (SELECT "t2".* FROM "t2"))', + 'prepare' => '((SELECT "t1".* FROM "t1") UNION (SELECT "t2".* FROM "t2"))' + ], + ], + ], + [ + 'sqlObject' => $this->combine($this->combine([ + $this->select('foo'), + $this->select('foo'), + ])), + 'expected' => [ + 'sqlite' => [ + 'string' => '((SELECT "foo".* FROM "foo") UNION (SELECT "foo".* FROM "foo"))', + 'prepare' => '((SELECT "foo".* FROM "foo") UNION (SELECT "foo".* FROM "foo"))' + ], + ], + ], + ]); + } +} diff --git a/test/Sql/Builder/Ddl/AlterTableBuilderTest.php b/test/Sql/Builder/Ddl/AlterTableBuilderTest.php new file mode 100644 index 0000000000..b58f012fe1 --- /dev/null +++ b/test/Sql/Builder/Ddl/AlterTableBuilderTest.php @@ -0,0 +1,48 @@ +assertBuilder($sqlObject, $platform, $expected); + } + + public function dataProvider() + { + return $this->prepareDataProvider([ + [ + 'sqlObject' => $this->alterTable('foo') + ->addColumn(new Column\Varchar('another', 255)) + ->changeColumn('name', new Column\Varchar('new_name', 50)) + ->dropColumn('foo') + ->addConstraint(new Constraint\ForeignKey('my_fk', 'other_id', 'other_table', 'id', 'CASCADE', 'CASCADE')) + ->dropConstraint('my_index'), + 'expected' => [ + 'sql92' => 'ALTER TABLE "foo" + ADD COLUMN "another" VARCHAR(255) NOT NULL, + CHANGE COLUMN "name" "new_name" VARCHAR(50) NOT NULL, + DROP COLUMN "foo", + ADD CONSTRAINT "my_fk" FOREIGN KEY ("other_id") REFERENCES "other_table" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + DROP CONSTRAINT "my_index"', + ], + ], + ]); + } +} diff --git a/test/Sql/Builder/Ddl/CreateTableBuilderTest.php b/test/Sql/Builder/Ddl/CreateTableBuilderTest.php new file mode 100644 index 0000000000..a51ecae5ed --- /dev/null +++ b/test/Sql/Builder/Ddl/CreateTableBuilderTest.php @@ -0,0 +1,136 @@ +assertBuilder($sqlObject, $platform, $expected); + } + + public function dataProvider() + { + return $this->prepareDataProvider( + $this->dataProvider_SQL92(), + $this->dataProvider_Mysql(), + $this->dataProvider_SqlServer() + ); + } + + public function dataProvider_SqlServer() + { + return [ + [ + 'sqlObject' => $this->createTable('foo'), + 'expected' => [ + 'SqlServer' => "CREATE TABLE [foo] ( \n)", + ], + ], + [ + 'sqlObject' => $this->createTable('foo', true), + 'expected' => [ + 'SqlServer' => "CREATE TABLE [#foo] ( \n)", + ], + ], + [ + 'sqlObject' => $this->createTable('foo')->addColumn(new Column('bar')), + 'expected' => [ + 'SqlServer' => "CREATE TABLE [foo] ( \n [bar] INTEGER NOT NULL \n)", + ], + ], + [ + 'sqlObject' => $this->createTable('foo', true)->addColumn(new Column('bar')), + 'expected' => [ + 'SqlServer' => "CREATE TABLE [#foo] ( \n [bar] INTEGER NOT NULL \n)", + ], + ], + ]; + } + + public function dataProvider_Mysql() + { + return [ + [ + 'sqlObject' => function () { + $col = new Column('bar'); + $col->setOption('zerofill', true); + $col->setOption('unsigned', true); + $col->setOption('identity', true); + $col->setOption('column-format', 'FIXED'); + $col->setOption('storage', 'memory'); + $col->setOption('comment', 'baz'); + $col->addConstraint(new Constraint\PrimaryKey()); + + return $this->createTable('foo')->addColumn($col); + }, + 'expected' => [ + 'mysql' => "CREATE TABLE `foo` ( \n `bar` INTEGER UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'baz' COLUMN_FORMAT FIXED STORAGE MEMORY \n)", + ], + ], + ]; + } + + public function dataProvider_SQL92() + { + return [ + [ + 'sqlObject' => $this->createTable('foo'), + 'expected' => [ + 'sql92' => "CREATE TABLE \"foo\" ( \n)", + ], + ], + [ + 'sqlObject' => $this->createTable('foo', true), + 'expected' => [ + 'sql92' => "CREATE TEMPORARY TABLE \"foo\" ( \n)", + ], + ], + [ + 'sqlObject' => $this->createTable('foo')->addColumn(new Column('bar')), + 'expected' => [ + 'sql92' => "CREATE TABLE \"foo\" ( \n \"bar\" INTEGER NOT NULL \n)", + ], + ], + [ + 'sqlObject' => $this->createTable('foo', true)->addColumn(new Column('bar')), + 'expected' => [ + 'sql92' => "CREATE TEMPORARY TABLE \"foo\" ( \n \"bar\" INTEGER NOT NULL \n)", + ], + ], + [ + 'sqlObject' => $this->createTable('foo', true)->addColumn(new Column('bar'))->addColumn(new Column('baz')), + 'expected' => [ + 'sql92' => "CREATE TEMPORARY TABLE \"foo\" ( \n \"bar\" INTEGER NOT NULL,\n \"baz\" INTEGER NOT NULL \n)", + ], + ], + [ + 'sqlObject' => $this->createTable('foo')->addColumn(new Column('bar'))->addConstraint(new Constraint\PrimaryKey('bat')), + 'expected' => [ + 'sql92' => "CREATE TABLE \"foo\" ( \n \"bar\" INTEGER NOT NULL , \n PRIMARY KEY (\"bat\") \n)", + ], + ], + [ + 'sqlObject' => $this->createTable('foo')->addConstraint(new Constraint\PrimaryKey('bar'))->addConstraint(new Constraint\PrimaryKey('bat')), + 'expected' => [ + 'sql92' => "CREATE TABLE \"foo\" ( \n PRIMARY KEY (\"bar\"),\n PRIMARY KEY (\"bat\") \n)", + ], + ], + ]; + } +} diff --git a/test/Sql/Builder/Ddl/DropTableBuilderTest.php b/test/Sql/Builder/Ddl/DropTableBuilderTest.php new file mode 100644 index 0000000000..fc90dba352 --- /dev/null +++ b/test/Sql/Builder/Ddl/DropTableBuilderTest.php @@ -0,0 +1,36 @@ +assertBuilder($sqlObject, $platform, $expected); + } + + public function dataProvider() + { + return $this->prepareDataProvider([ + [ + 'sqlObject' => $this->dropTable('foo'), + 'expected' => [ + 'sql92' => 'DROP TABLE "foo"', + ], + ], + ]); + } +} diff --git a/test/Sql/Builder/DeleteBuilderTest.php b/test/Sql/Builder/DeleteBuilderTest.php new file mode 100644 index 0000000000..94e7a3e25d --- /dev/null +++ b/test/Sql/Builder/DeleteBuilderTest.php @@ -0,0 +1,48 @@ +assertBuilder($sqlObject, $platform, $expected); + } + + public function dataProvider() + { + return $this->prepareDataProvider([ + [ // testPrepareStatement(), testGetSqlString() + 'sqlObject' => $this->delete()->from('foo')->where('x = y'), + 'expected' => [ + 'sql92' => [ + 'string' => 'DELETE FROM "foo" WHERE x = y', + 'prepare' => true, + ], + ], + ], + [ // testPrepareStatement(), testGetSqlString() // with TableIdentifier + 'sqlObject' => $this->delete()->from(new TableIdentifier('foo', 'sch'))->where('x = y'), + 'expected' => [ + 'sql92' => [ + 'string' => 'DELETE FROM "sch"."foo" WHERE x = y', + 'prepare' => true, + ], + ], + ], + ]); + } +} diff --git a/test/Sql/Builder/IbmDb2/SelectBuilderTest.php b/test/Sql/Builder/IbmDb2/SelectBuilderTest.php deleted file mode 100644 index 730660f0e8..0000000000 --- a/test/Sql/Builder/IbmDb2/SelectBuilderTest.php +++ /dev/null @@ -1,120 +0,0 @@ -getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $driver->expects($this->any())->method('formatParameterName')->will($this->returnValue('?')); - - // test - $adapter = $this->getMock( - 'Zend\Db\Adapter\Adapter', - null, - [ - $driver, - new IbmDb2Platform() - ] - ); - - $parameterContainer = new ParameterContainer; - $statement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - - $statement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($parameterContainer)); - $statement->expects($this->once())->method('setSql')->with($expectedPrepareSql); - - $selectDecorator = new SelectBuilder; - $selectDecorator->setSubject($select); - $selectDecorator->prepareStatement($adapter, $statement); - - $this->assertEquals($expectedParams, $parameterContainer->getNamedArray()); - } - - /** - * @testdox integration test: Testing SelectDecorator will use Select to produce properly Ibm DB2 dialect sql statements - * @covers Zend\Db\Sql\Platform\IbmDb2\SelectDecorator::getSqlString - * @dataProvider dataProvider - */ - public function testGetSqlString(Select $select, $ignored0, $ignored1, $expectedSql) - { - $parameterContainer = new ParameterContainer; - $statement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $statement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($parameterContainer)); - - $selectDecorator = new SelectBuilder; - $selectDecorator->setSubject($select); - - $this->assertEquals($expectedSql, @$selectDecorator->getSqlString(new IbmDb2Platform)); - } - - /** - * Data provider for testGetSqlString - * - * @return array - */ - public function dataProvider() - { - $select0 = new Select; - $select0->from(['x' => 'foo'])->limit(5); - $expectedParams0 = [ 'limit' => 5, 'offset' => 0 ]; - $expectedPrepareSql0 = 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?'; - $expectedSql0 = 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 0 AND 5'; - - $select1 = new Select; - $select1->from(['x' => 'foo'])->limit(5)->offset(10); - $expectedParams1 = [ 'limit' => 15, 'offset' => 11 ]; - $expectedPrepareSql1 = 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?'; - $expectedSql1 = 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 11 AND 15'; - - $select2 = new Select; - $select2->columns([new Expression('DISTINCT(id) as id')])->from(['x' => 'foo'])->limit(5)->offset(10); - $expectedParams2 = [ 'limit' => 15, 'offset' => 11]; - $expectedPrepareSql2 = 'SELECT DISTINCT(id) as id FROM ( SELECT DISTINCT(id) as id, DENSE_RANK() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?'; - $expectedSql2 = 'SELECT DISTINCT(id) as id FROM ( SELECT DISTINCT(id) as id, DENSE_RANK() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 11 AND 15'; - - $select3 = new Select; - $where3 = new Where(); - $where3->greaterThan('x.id', '10')->AND->lessThan('x.id', '31'); - $select3->from(['x' => 'foo'])->where($where3)->limit(5)->offset(10); - $expectedParams3 = [ 'limit' => 15, 'offset' => 11, 'where1' => '10', 'where2' => '31' ]; - $expectedPrepareSql3 = 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" WHERE "x"."id" > ? AND "x"."id" < ? ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?'; - $expectedSql3 = 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" WHERE "x"."id" > \'10\' AND "x"."id" < \'31\' ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 11 AND 15'; - - $select4 = new Select; - $where4 = $where3; - $select4->from(['x' => 'foo'])->where($where4)->limit(5); - $expectedParams4 = [ 'limit' => 5, 'offset' => 0, 'where1' => 10, 'where2' => 31 ]; - $expectedPrepareSql4 = 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" WHERE "x"."id" > ? AND "x"."id" < ? ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?'; - $expectedSql4 = 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" WHERE "x"."id" > \'10\' AND "x"."id" < \'31\' ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 0 AND 5'; - - return [ - [$select0, $expectedPrepareSql0, $expectedParams0, $expectedSql0], - [$select1, $expectedPrepareSql1, $expectedParams1, $expectedSql1], - [$select2, $expectedPrepareSql2, $expectedParams2, $expectedSql2], - [$select3, $expectedPrepareSql3, $expectedParams3, $expectedSql3], - [$select4, $expectedPrepareSql4, $expectedParams4, $expectedSql4], - ]; - } -} diff --git a/test/Sql/Builder/InsertBuilderTest.php b/test/Sql/Builder/InsertBuilderTest.php new file mode 100644 index 0000000000..789aa140ea --- /dev/null +++ b/test/Sql/Builder/InsertBuilderTest.php @@ -0,0 +1,138 @@ +assertBuilder($sqlObject, $platform, $expected); + } + + public function dataProvider() + { + return $this->prepareDataProvider([ + [ // testPrepareStatement() + 'sqlObject' => $this->insert() + ->into('foo') + ->values([ + 'bar' => 'baz', + 'boo' => new Expression('NOW()'), + ]), + 'expected' => [ + 'sql92' => [ + 'string' => '', + 'prepare' => 'INSERT INTO "foo" ("bar", "boo") VALUES (?, NOW())', + ], + ], + ], + [ // testPrepareStatement() // with TableIdentifier + 'sqlObject' => $this->insert() + ->into(new TableIdentifier('foo', 'sch')) + ->values([ + 'bar' => 'baz', + 'boo' => new Expression('NOW()'), + ]), + 'expected' => [ + 'sql92' => [ + 'string' => '', + 'prepare' => 'INSERT INTO "sch"."foo" ("bar", "boo") VALUES (?, NOW())' + ], + ], + ], + [ // testPrepareStatementWithSelect() + 'sqlObject' => $this->insert() + ->into('foo') + ->columns(['col1']) + ->select($this->select('bar')->where(['x'=>5])), + 'expected' => [ + 'sql92' => [ + 'string' => '', + 'prepare' => 'INSERT INTO "foo" ("col1") SELECT "bar".* FROM "bar" WHERE "x" = ?', + 'parameters' => ['subselect1expr1'=>5], + ], + ], + ], + [ // testGetSqlString() + 'sqlObject' => $this->insert()->into('foo') + ->values([ + 'bar' => 'baz', + 'boo' => new Expression('NOW()'), + 'bam' => null + ]), + 'expected' => [ + 'sql92' => [ + 'string' => 'INSERT INTO "foo" ("bar", "boo", "bam") VALUES (\'baz\', NOW(), NULL)', + ], + ], + ], + [ // testGetSqlString() // with TableIdentifier + 'sqlObject' => $this->insert() + ->into(new TableIdentifier('foo', 'sch')) + ->values([ + 'bar' => 'baz', + 'boo' => new Expression('NOW()'), + 'bam' => null + ]), + 'expected' => [ + 'sql92' => [ + 'string' => 'INSERT INTO "sch"."foo" ("bar", "boo", "bam") VALUES (\'baz\', NOW(), NULL)', + ], + ], + ], + [ // testGetSqlString() // with Select + 'sqlObject' => $this->insert() + ->into('foo') + ->select($this->select()->from('bar')), + 'expected' => [ + 'sql92' => [ + 'string' => 'INSERT INTO "foo" SELECT "bar".* FROM "bar"', + 'prepare' => true, + ], + ], + ], + [ // testGetSqlString() // with Select and columns + 'sqlObject' => $this->insert() + ->into('foo') + ->columns(['col1', 'col2']) + ->select($this->select()->from('bar')), + 'expected' => [ + 'sql92' => [ + 'string' => 'INSERT INTO "foo" ("col1", "col2") SELECT "bar".* FROM "bar"', + 'prepare' => true, + ], + ], + ], + [ // testValuesMerge() + 'sqlObject' => $this->insert() + ->into('foo') + ->values([ + 'bar' => 'baz', + 'boo' => new Expression('NOW()'), + 'bam' => null + ]) + ->values(['qux' => 100], Insert::VALUES_MERGE), + 'expected' => [ + 'sql92' => [ + 'string' => 'INSERT INTO "foo" ("bar", "boo", "bam", "qux") VALUES (\'baz\', NOW(), NULL, \'100\')', + ], + ], + ], + ]); + } +} diff --git a/test/Sql/Builder/Mysql/Ddl/CreateTableBuilderTest.php b/test/Sql/Builder/Mysql/Ddl/CreateTableBuilderTest.php deleted file mode 100644 index 01830baea8..0000000000 --- a/test/Sql/Builder/Mysql/Ddl/CreateTableBuilderTest.php +++ /dev/null @@ -1,54 +0,0 @@ -assertSame($ctd, $ctd->setSubject($ct)); - } - - /** - * @covers Zend\Db\Sql\Platform\Mysql\Ddl\CreateTableDecorator::getSqlString - */ - public function testGetSqlString() - { - $ctd = new CreateTableBuilder(); - $ct = new CreateTable('foo'); - $ctd->setSubject($ct); - - $col = new Column('bar'); - $col->setOption('zerofill', true); - $col->setOption('unsigned', true); - $col->setOption('identity', true); - $col->setOption('column-format', 'FIXED'); - $col->setOption('storage', 'memory'); - $col->setOption('comment', 'baz'); - $col->addConstraint(new PrimaryKey()); - $ct->addColumn($col); - - $this->assertEquals( - "CREATE TABLE `foo` ( \n `bar` INTEGER UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'baz' COLUMN_FORMAT FIXED STORAGE MEMORY \n)", - @$ctd->getSqlString(new Mysql()) - ); - } -} diff --git a/test/Sql/Builder/Mysql/SelectBuilderTest.php b/test/Sql/Builder/Mysql/SelectBuilderTest.php deleted file mode 100644 index e44c08a656..0000000000 --- a/test/Sql/Builder/Mysql/SelectBuilderTest.php +++ /dev/null @@ -1,100 +0,0 @@ -getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $driver->expects($this->any())->method('formatParameterName')->will($this->returnValue('?')); - - // test - $adapter = $this->getMock( - 'Zend\Db\Adapter\Adapter', - null, - [ - $driver, - new MysqlPlatform() - ] - ); - - $parameterContainer = new ParameterContainer; - $statement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $statement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($parameterContainer)); - - $statement->expects($this->once())->method('setSql')->with($expectedSql); - - $selectDecorator = new SelectBuilder; - $selectDecorator->setSubject($select); - $selectDecorator->prepareStatement($adapter, $statement); - - $this->assertEquals($expectedParams, $parameterContainer->getNamedArray()); - } - - /** - * @testdox integration test: Testing SelectBuilder will use Select an internal state to prepare a proper limit/offset sql statement - * @covers Zend\Db\Sql\Builder\Mysql\SelectBuilder::getSqlString - * @covers Zend\Db\Sql\Builder\Mysql\SelectBuilder::processLimit - * @covers Zend\Db\Sql\Builder\Mysql\SelectBuilder::processOffset - * @dataProvider dataProvider - */ - public function testGetSqlString(Select $select, $ignore, $alsoIgnore, $expectedSql) - { - $parameterContainer = new ParameterContainer; - $statement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $statement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($parameterContainer)); - - $selectDecorator = new SelectBuilder; - $selectDecorator->setSubject($select); - $this->assertEquals($expectedSql, $selectDecorator->getSqlString(new MysqlPlatform)); - } - - public function dataProvider() - { - $select0 = new Select; - $select0->from('foo')->limit(5)->offset(10); - $expectedPrepareSql0 = 'SELECT `foo`.* FROM `foo` LIMIT ? OFFSET ?'; - $expectedParams0 = ['offset' => 10, 'limit' => 5]; - $expectedSql0 = 'SELECT `foo`.* FROM `foo` LIMIT 5 OFFSET 10'; - - // offset without limit - $select1 = new Select; - $select1->from('foo')->offset(10); - $expectedPrepareSql1 = 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET ?'; - $expectedParams1 = ['offset' => 10]; - $expectedSql1 = 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET 10'; - - // offset and limit are not type casted when injected into parameter container - $select2 = new Select; - $select2->from('foo')->limit('5')->offset('10000000000000000000'); - $expectedPrepareSql2 = 'SELECT `foo`.* FROM `foo` LIMIT ? OFFSET ?'; - $expectedParams2 = ['offset' => '10000000000000000000', 'limit' => '5']; - $expectedSql2 = 'SELECT `foo`.* FROM `foo` LIMIT 5 OFFSET 10000000000000000000'; - - return [ - [$select0, $expectedPrepareSql0, $expectedParams0, $expectedSql0], - [$select1, $expectedPrepareSql1, $expectedParams1, $expectedSql1], - [$select2, $expectedPrepareSql2, $expectedParams2, $expectedSql2], - ]; - } -} diff --git a/test/Sql/Builder/Oracle/SelectBuilderTest.php b/test/Sql/Builder/Oracle/SelectBuilderTest.php deleted file mode 100644 index 8e0feec1ef..0000000000 --- a/test/Sql/Builder/Oracle/SelectBuilderTest.php +++ /dev/null @@ -1,144 +0,0 @@ -getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $driver->expects($this->exactly($expectedFormatParamCount)) - ->method('formatParameterName') - ->will($this->returnValue('?')); - - // test - $adapter = $this->getMock( - 'Zend\Db\Adapter\Adapter', - null, - [ - $driver, - new OraclePlatform() - ] - ); - - $parameterContainer = new ParameterContainer; - $statement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $statement->expects($this->any()) - ->method('getParameterContainer') - ->will($this->returnValue($parameterContainer)); - - $statement->expects($this->once())->method('setSql')->with($expectedSql); - - $selectDecorator = new SelectBuilder; - $selectDecorator->setSubject($select); - $selectDecorator->prepareStatement($adapter, $statement); - - $this->assertEquals($expectedParams, $parameterContainer->getNamedArray()); - } - - // @codingStandardsIgnoreStart - /** - * @testdox integration test: Testing SelectBuilder will use Select to produce properly Oracle dialect sql statements - * @covers Zend\Db\Sql\Platform\Oracle\SelectBuilder::getSqlString - * @dataProvider dataProvider - */ - // @codingStandardsIgnoreEnd - public function testGetSqlString(Select $select, $ignored, $alsoIgnored, $expectedSql) - { - $parameterContainer = new ParameterContainer; - $statement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $statement->expects($this->any()) - ->method('getParameterContainer') - ->will($this->returnValue($parameterContainer)); - - $selectDecorator = new SelectBuilder; - $selectDecorator->setSubject($select); - $this->assertEquals($expectedSql, $selectDecorator->getSqlString(new OraclePlatform)); - } - - /** - * Data provider for testGetSqlString - * - * @return array - */ - public function dataProvider() - { - $select0 = new Select; - $select0->from(['x' => 'foo']); - $expectedSql0 = 'SELECT "x".* FROM "foo" "x"'; - $expectedFormatParamCount0 = 0; - - $select1a = new Select('test'); - $select1b = new Select(['a' => $select1a]); - $select1 = new Select(['b' => $select1b]); - $expectedSql1 = 'SELECT "b".* FROM (SELECT "a".* FROM (SELECT "test".* FROM "test") "a") "b"'; - $expectedFormatParamCount1 = 0; - - $select2a = new Select('test'); - $select2a->limit(2); - $select2b = new Select(['a' => $select2a]); - $select2 = new Select(['b' => $select2b]); - // @codingStandardsIgnoreStart - $expectedSql2_1 = 'SELECT "b".* FROM (SELECT "a".* FROM (SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "test".* FROM "test" ) b WHERE rownum <= (:offset2+:limit2)) WHERE b_rownum >= (:offset2 + 1)) "a") "b"'; - $expectedSql2_2 = 'SELECT "b".* FROM (SELECT "a".* FROM (SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "test".* FROM "test" ) b WHERE rownum <= (0+2)) WHERE b_rownum >= (0 + 1)) "a") "b"'; - // @codingStandardsIgnoreEnd - $expectedFormatParamCount2 = 0; - $expectedParams2 = ['offset2' => 0, 'limit2' => 2]; - - $select3a = new Select('test'); - $select3a->offset(2); - $select3b = new Select(['a' => $select3a]); - $select3 = new Select(['b' => $select3b]); - // @codingStandardsIgnoreStart - $expectedSql3_1 = 'SELECT "b".* FROM (SELECT "a".* FROM (SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "test".* FROM "test" ) b ) WHERE b_rownum > (:offset2)) "a") "b"'; - $expectedSql3_2 = 'SELECT "b".* FROM (SELECT "a".* FROM (SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "test".* FROM "test" ) b ) WHERE b_rownum > (2)) "a") "b"'; - // @codingStandardsIgnoreEnd - $expectedFormatParamCount3 = 0; - $expectedParams3 = ['offset2' => 2]; - - $select4a = new Select('test'); - $select4a->limit(2); - $select4a->offset(2); - $select4b = new Select(['a' => $select4a]); - $select4 = new Select(['b' => $select4b]); - // @codingStandardsIgnoreStart - $expectedSql4_1 = 'SELECT "b".* FROM (SELECT "a".* FROM (SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "test".* FROM "test" ) b WHERE rownum <= (:offset2+:limit2)) WHERE b_rownum >= (:offset2 + 1)) "a") "b"'; - $expectedSql4_2 = 'SELECT "b".* FROM (SELECT "a".* FROM (SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "test".* FROM "test" ) b WHERE rownum <= (2+2)) WHERE b_rownum >= (2 + 1)) "a") "b"'; - // @codingStandardsIgnoreEnd - $expectedFormatParamCount4 = 0; - $expectedParams4 = ['offset2' => 2, 'limit2' => 2]; - - return [ - [$select0, $expectedSql0, [], $expectedSql0, $expectedFormatParamCount0], - [$select1, $expectedSql1, [], $expectedSql1, $expectedFormatParamCount1], - [$select2, $expectedSql2_1, $expectedParams2, $expectedSql2_2, $expectedFormatParamCount2], - [$select3, $expectedSql3_1, $expectedParams3, $expectedSql3_2, $expectedFormatParamCount3], - [$select4, $expectedSql4_1, $expectedParams4, $expectedSql4_2, $expectedFormatParamCount4], - ]; - } -} diff --git a/test/Sql/Builder/SelectBuilderTest.php b/test/Sql/Builder/SelectBuilderTest.php new file mode 100644 index 0000000000..a93ac9332b --- /dev/null +++ b/test/Sql/Builder/SelectBuilderTest.php @@ -0,0 +1,861 @@ +assertBuilder($sqlObject, $platform, $expected); + } + + public function dataProvider() + { + return $this->prepareDataProvider( + $this->dataProvider_SQL92(), + $this->dataProvider_SqlServer(), + $this->dataProvider_Oracle(), + $this->dataProvider_Mysql(), + $this->dataProvider_IbmDb2(), + $this->dataProvider_ForDifferentAdapters() + ); + } + + /** + * ZendTest\Db\Sql::testForDifferentAdapters() + */ + public function dataProvider_ForDifferentAdapters() + { + $select = $this->select('foo')->offset(10); + return [ + [ + 'sqlObject' => $select, + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" OFFSET \'10\'', + 'prepare' => 'SELECT "foo".* FROM "foo" OFFSET ?', + ], + ], + ], + [ + 'sqlObject' => $select, + 'expected' => [ + 'MySql' => [ + 'string' => 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET 10', + 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET ?', + ], + ], + ], + [ + 'sqlObject' => $select, + 'expected' => [ + 'Oracle' => [ + 'string' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b ) WHERE b_rownum > (10)', + 'prepare' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b ) WHERE b_rownum > (:offset)', + ], + ], + ], + [ + 'sqlObject' => $select, + 'expected' => [ + 'SqlServer' => [ + 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 10+1 AND 0+10', + 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', + ], + ], + ], + ]; + } + + public function dataProvider_IbmDb2() + { + return [ + [ + 'sqlObject' => $this->select()->from(['x' => 'foo'])->limit(5), + 'expected' => [ + 'IbmDb2' => [ + 'string' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 0 AND 5', + 'prepare' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', + 'parameters' => ['offset' => 0, 'limit' => 5], + ], + ], + ], + [ + 'sqlObject' => $this->select()->from(['x' => 'foo'])->limit(5)->offset(10), + 'expected' => [ + 'IbmDb2' => [ + 'string' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 11 AND 15', + 'prepare' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', + 'parameters' => ['offset' => 11, 'limit' => 15], + ], + ], + ], + [ + 'sqlObject' => $this->select()->columns([new Expression('DISTINCT(id) as id')])->from(['x' => 'foo'])->limit(5)->offset(10), + 'expected' => [ + 'IbmDb2' => [ + 'string' => 'SELECT DISTINCT(id) as id FROM ( SELECT DISTINCT(id) as id, DENSE_RANK() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 11 AND 15', + 'prepare' => 'SELECT DISTINCT(id) as id FROM ( SELECT DISTINCT(id) as id, DENSE_RANK() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', + 'parameters' => ['offset' => 11, 'limit' => 15], + ], + ], + ], + [ + 'sqlObject' => function () { + $select = $this->select()->from(['x' => 'foo'])->limit(5)->offset(10); + $select->where->greaterThan('x.id', '10')->AND->lessThan('x.id', '31'); + return $select; + }, + 'expected' => [ + 'IbmDb2' => [ + 'string' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" WHERE "x"."id" > \'10\' AND "x"."id" < \'31\' ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 11 AND 15', + 'prepare' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" WHERE "x"."id" > ? AND "x"."id" < ? ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', + 'parameters' => ['expr1' => '10', 'expr2' => '31', 'offset' => 11, 'limit' => 15], + ], + ], + ], + [ + 'sqlObject' => function () { + $select = $this->select()->from(['x' => 'foo'])->limit(5); + $select->where->greaterThan('x.id', '10')->AND->lessThan('x.id', '31'); + return $select; + }, + 'expected' => [ + 'IbmDb2' => [ + 'string' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" WHERE "x"."id" > \'10\' AND "x"."id" < \'31\' ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 0 AND 5', + 'prepare' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" WHERE "x"."id" > ? AND "x"."id" < ? ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', + 'parameters' => ['expr1' => '10', 'expr2' => '31', 'offset' => 0, 'limit' => 5], + ], + ], + ], + ]; + } + + public function dataProvider_Mysql() + { + return [ + [ + 'sqlObject' => $this->select()->from('foo')->limit(5)->offset(10), + 'expected' => [ + 'Mysql' => [ + 'string' => 'SELECT `foo`.* FROM `foo` LIMIT 5 OFFSET 10', + 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT ? OFFSET ?', + 'parameters' => ['limit' => 5, 'offset' => 10], + ], + ], + ], + [ + 'sqlObject' => $this->select()->from('foo')->offset(10), + 'expected' => [ + 'Mysql' => [ + 'string' => 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET 10', + 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET ?', + 'parameters' => ['offset' => 10], + ], + ], + ], + [ + 'sqlObject' => $this->select()->from('foo')->limit('5')->offset('10000000000000000000'), + 'expected' => [ + 'Mysql' => [ + 'string' => 'SELECT `foo`.* FROM `foo` LIMIT 5 OFFSET 10000000000000000000', + 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT ? OFFSET ?', + 'parameters' => ['limit' => '5', 'offset' => '10000000000000000000'], + ], + ], + ], + ]; + } + + public function dataProvider_Oracle() + { + return [ + [ + 'sqlObject' => $this->select()->from(['x' => 'foo']), + 'expected' => [ + 'Oracle' => [ + 'string' => 'SELECT "x".* FROM "foo" "x"', + 'prepare' => true, + 'parameters' => [], + ], + ], + ], + [ + 'sqlObject' => $this->select(['b' => $this->select(['a' => $this->select('test')])]), + 'expected' => [ + 'Oracle' => [ + 'string' => 'SELECT "b".* FROM (SELECT "a".* FROM (SELECT "test".* FROM "test") "a") "b"', + 'prepare' => true, + 'parameters' => [], + ], + ], + ], + ]; + } + + public function dataProvider_SqlServer() + { + return [ + [ + 'sqlObject' => $this->select()->from('foo')->columns(['bar', 'baz'])->order('bar')->limit(5)->offset(10), + 'expected' => [ + 'SqlServer' => [ + 'string' => 'SELECT [bar], [baz] FROM ( SELECT [foo].[bar] AS [bar], [foo].[baz] AS [baz], ROW_NUMBER() OVER (ORDER BY [bar] ASC) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 10+1 AND 5+10', + 'prepare' => 'SELECT [bar], [baz] FROM ( SELECT [foo].[bar] AS [bar], [foo].[baz] AS [baz], ROW_NUMBER() OVER (ORDER BY [bar] ASC) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', + 'parameters' => ['offset' => 10, 'limit' => 5, 'offsetForSum' => 10], + ], + ], + ], + [ + 'sqlObject' => $this->select()->from('foo')->columns(['bar', 'bam' => 'baz'])->limit(5)->offset(10), + 'expected' => [ + 'SqlServer' => [ + 'string' => 'SELECT [bar], [bam] FROM ( SELECT [foo].[bar] AS [bar], [foo].[baz] AS [bam], ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 10+1 AND 5+10', + 'prepare' => 'SELECT [bar], [bam] FROM ( SELECT [foo].[bar] AS [bar], [foo].[baz] AS [bam], ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', + 'parameters' => ['offset' => 10, 'limit' => 5, 'offsetForSum' => 10], + ], + ], + ], + [ + 'sqlObject' => $this->select()->from('foo')->order('bar')->limit(5)->offset(10), + 'expected' => [ + 'SqlServer' => [ + 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY [bar] ASC) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 10+1 AND 5+10', + 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY [bar] ASC) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', + 'parameters' => ['offset' => 10, 'limit' => 5, 'offsetForSum' => 10], + ], + ], + ], + [ + 'sqlObject' => $this->select()->from('foo'), + 'expected' => [ + 'SqlServer' => [ + 'string' => 'SELECT [foo].* FROM [foo]', + 'prepare' => true, + 'parameters' => [], + ], + ], + ], + ]; + } + + public function dataProvider_SQL92() + { + return [ + [ //testSelectUsingTableIdentifierWithEmptyScheme() + 'sqlObject' => $this->select() + ->from(new TableIdentifier('foo')) + ->join(new TableIdentifier('bar'), 'foo.id = bar.fooid'), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".*, "bar".* FROM "foo" INNER JOIN "bar" ON "foo"."id" = "bar"."fooid"', + ], + ], + ], + [ //basic table + 'sqlObject' => $this->select()->from('foo'), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo"', + 'prepare' => true, + ], + ], + ], + [ // table as TableIdentifier + 'sqlObject' => $this->select()->from(new TableIdentifier('foo', 'bar')), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "bar"."foo".* FROM "bar"."foo"', + 'prepare' => true, + ], + ], + ], + [ // table with alias + 'sqlObject' => $this->select()->from(['f' => 'foo']), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "f".* FROM "foo" AS "f"', + 'prepare' => true, + ], + ], + ], + [ // table with alias with table as TableIdentifier + 'sqlObject' => $this->select()->from(['f' => new TableIdentifier('foo')]), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "f".* FROM "foo" AS "f"', + 'prepare' => true, + ], + ], + ], + [ // columns + 'sqlObject' => $this->select()->from('foo')->columns(['bar', 'baz']), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo"."bar" AS "bar", "foo"."baz" AS "baz" FROM "foo"', + 'prepare' => true, + ], + ], + ], + [ // columns with AS associative array + 'sqlObject' => $this->select()->from('foo')->columns(['bar' => 'baz']), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo"."baz" AS "bar" FROM "foo"', + 'prepare' => true, + ], + ], + ], + [ // columns with AS associative array mixed + 'sqlObject' => $this->select()->from('foo')->columns(['bar' => 'baz', 'bam']), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo"."baz" AS "bar", "foo"."bam" AS "bam" FROM "foo"', + 'prepare' => true, + ], + ], + ], + [ // columns where value is Expression, with AS + 'sqlObject' => $this->select()->from('foo')->columns(['bar' => new Expression('COUNT(some_column)')]), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT COUNT(some_column) AS "bar" FROM "foo"', + 'prepare' => true, + ], + ], + ], + [ // columns where value is Expression + 'sqlObject' => $this->select()->from('foo')->columns([new Expression('COUNT(some_column) AS bar')]), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT COUNT(some_column) AS bar FROM "foo"', + 'prepare' => true, + ], + ], + ], + [ + 'sqlObject' => $this->select() + ->from('foo') + ->columns( + [ + new Expression( + '(COUNT(?) + ?) AS ?', + ['some_column', 5, 'bar'], + [Expression::TYPE_IDENTIFIER, Expression::TYPE_VALUE, Expression::TYPE_IDENTIFIER] + ) + ] + ), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT (COUNT("some_column") + \'5\') AS "bar" FROM "foo"', + 'prepare' => 'SELECT (COUNT("some_column") + ?) AS "bar" FROM "foo"', + ], + ], + ], + [ // joins (plain) + 'sqlObject' => $this->select()->from('foo')->join('zac', 'm = n'), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".*, "zac".* FROM "foo" INNER JOIN "zac" ON "m" = "n"', + 'prepare' => true, + ], + ], + ], + [ // join with columns + 'sqlObject' => $this->select()->from('foo')->join('zac', 'm = n', ['bar', 'baz']), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".*, "zac"."bar" AS "bar", "zac"."baz" AS "baz" FROM "foo" INNER JOIN "zac" ON "m" = "n"', + 'prepare' => true, + ], + ], + ], + [ // join with alternate type + 'sqlObject' => $this->select()->from('foo')->join('zac', 'm = n', ['bar', 'baz'], Select::JOIN_OUTER), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".*, "zac"."bar" AS "bar", "zac"."baz" AS "baz" FROM "foo" OUTER JOIN "zac" ON "m" = "n"', + 'prepare' => true, + ], + ], + ], + [ // join with column aliases + 'sqlObject' => $this->select()->from('foo')->join('zac', 'm = n', ['BAR' => 'bar', 'BAZ' => 'baz']), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".*, "zac"."bar" AS "BAR", "zac"."baz" AS "BAZ" FROM "foo" INNER JOIN "zac" ON "m" = "n"', + 'prepare' => true, + ], + ], + ], + [ // join with table aliases + 'sqlObject' => $this->select()->from('foo')->join(['b' => 'bar'], 'b.foo_id = foo.foo_id'), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".*, "b".* FROM "foo" INNER JOIN "bar" AS "b" ON "b"."foo_id" = "foo"."foo_id"', + 'prepare' => true, + ], + ], + ], + [ // where (simple string) + 'sqlObject' => $this->select()->from('foo')->where('x = 5'), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" WHERE x = 5', + 'prepare' => true, + ], + ], + ], + [ // where (returning parameters) + 'sqlObject' => $this->select()->from('foo')->where(['x = ?' => 5]), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" WHERE x = \'5\'', + 'prepare' => 'SELECT "foo".* FROM "foo" WHERE x = ?', + 'parameters' => ['expr1' => 5], + ], + ], + ], + [ // group + 'sqlObject' => $this->select()->from('foo')->group(['col1', 'col2']), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" GROUP BY "col1", "col2"', + 'prepare' => true, + ], + ], + ], + [ // group + 'sqlObject' => $this->select()->from('foo')->group('col1')->group('col2'), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" GROUP BY "col1", "col2"', + 'prepare' => true, + ], + ], + ], + [ // group + 'sqlObject' => $this->select()->from('foo')->group(new Expression('DAY(?)', ['col1'], [Expression::TYPE_IDENTIFIER])), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" GROUP BY DAY("col1")', + 'prepare' => true, + ], + ], + ], + [ // having (simple string) + 'sqlObject' => $this->select()->from('foo')->having('x = 5'), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" HAVING x = 5', + 'prepare' => true, + ], + ], + ], + [ // having (returning parameters) + 'sqlObject' => $this->select()->from('foo')->having(['x = ?' => 5]), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" HAVING x = \'5\'', + 'prepare' => 'SELECT "foo".* FROM "foo" HAVING x = ?', + 'parameters' => ['expr1' => 5], + ], + ], + ], + [ // order + 'sqlObject' => $this->select()->from('foo')->order('c1'), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" ORDER BY "c1" ASC', + 'prepare' => true, + ], + ], + ], + [ // order + 'sqlObject' => $this->select()->from('foo')->order(['c1', 'c2']), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" ORDER BY "c1" ASC, "c2" ASC', + 'prepare' => true, + ], + ], + ], + [ // order - notice partially lower case ASC + 'sqlObject' => $this->select()->from('foo')->order(['c1' => 'DESC', 'c2' => 'Asc']), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" ORDER BY "c1" DESC, "c2" ASC', + 'prepare' => true, + ], + ], + ], + [ // order + 'sqlObject' => $this->select()->from('foo')->order(['c1' => 'asc'])->order('c2 desc'), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" ORDER BY "c1" ASC, "c2" DESC', + 'prepare' => true, + ], + ], + ], + [ // limit + 'sqlObject' => $this->select()->from('foo')->limit(5), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" LIMIT \'5\'', + 'prepare' => 'SELECT "foo".* FROM "foo" LIMIT ?', + 'parameters' => ['limit' => 5], + ], + ], + ], + [ // limit with offset + 'sqlObject' => $this->select()->from('foo')->limit(5)->offset(10), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" LIMIT \'5\' OFFSET \'10\'', + 'prepare' => 'SELECT "foo".* FROM "foo" LIMIT ? OFFSET ?', + 'parameters' => ['limit' => 5, 'offset' => 10], + ], + ], + ], + [ // joins with a few keywords in the on clause + 'sqlObject' => $this->select()->from('foo')->join('zac', '(m = n AND c.x) BETWEEN x AND y.z OR (c.x < y.z AND c.x <= y.z AND c.x > y.z AND c.x >= y.z)'), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".*, "zac".* FROM "foo" INNER JOIN "zac" ON ("m" = "n" AND "c"."x") BETWEEN "x" AND "y"."z" OR ("c"."x" < "y"."z" AND "c"."x" <= "y"."z" AND "c"."x" > "y"."z" AND "c"."x" >= "y"."z")', + 'prepare' => true, + ], + ], + ], + [ // order with compound name + 'sqlObject' => $this->select()->from('foo')->order('c1.d2'), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" ORDER BY "c1"."d2" ASC', + 'prepare' => true, + ], + ], + ], + [ // group with compound name + 'sqlObject' => $this->select()->from('foo')->group('c1.d2'), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" GROUP BY "c1"."d2"', + 'prepare' => true, + ], + ], + ], + [ // join with expression in ON part + 'sqlObject' => $this->select()->from('foo')->join('zac', new Expression('(m = n AND c.x) BETWEEN x AND y.z')), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".*, "zac".* FROM "foo" INNER JOIN "zac" ON (m = n AND c.x) BETWEEN x AND y.z', + 'prepare' => true, + ], + ], + ], + [ + 'sqlObject' => function () { + $subselect = $this->select(); + $subselect->from('bar')->where->like('y', '%Foo%'); + return $this->select()->from(['x' => $subselect]); + }, + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "x".* FROM (SELECT "bar".* FROM "bar" WHERE "y" LIKE \'%Foo%\') AS "x"', + 'prepare' => 'SELECT "x".* FROM (SELECT "bar".* FROM "bar" WHERE "y" LIKE ?) AS "x"', + ], + ], + ], + [ + 'sqlObject' => $this->select() + ->from('table') + ->columns(['*']) + ->where([ + 'c1' => null, + 'c2' => [1, 2, 3], + new \Zend\Db\Sql\Predicate\IsNotNull('c3') + ]), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "table".* FROM "table" WHERE "c1" IS NULL AND "c2" IN (\'1\', \'2\', \'3\') AND "c3" IS NOT NULL', + 'prepare' => 'SELECT "table".* FROM "table" WHERE "c1" IS NULL AND "c2" IN (?, ?, ?) AND "c3" IS NOT NULL', + ], + ], + ], + [ // @author Demian Katz + 'sqlObject' => $this->select() + ->from('table') + ->order([ + new Expression('isnull(?) DESC', ['name'], [Expression::TYPE_IDENTIFIER]), + 'name' + ]), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "table".* FROM "table" ORDER BY isnull("name") DESC, "name" ASC', + 'prepare' => 'SELECT "table".* FROM "table" ORDER BY isnull("name") DESC, "name" ASC', + ], + ], + ], + [ // join with Expression object in COLUMNS part (ZF2-514) // @co-author Koen Pieters (kpieters) + 'sqlObject' => $this->select()->from('foo')->columns([])->join('bar', 'm = n', ['thecount' => new Expression("COUNT(*)")]), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT COUNT(*) AS "thecount" FROM "foo" INNER JOIN "bar" ON "m" = "n"', + 'prepare' => true, + ], + ], + ], + [ // multiple joins with expressions // reported by @jdolieslager + 'sqlObject' => $this->select() + ->from('foo') + ->join('tableA', new Predicate\Operator('id', '=', 1)) + ->join('tableB', new Predicate\Operator('id', '=', 2)) + ->join('tableC', new Predicate\PredicateSet([ + new Predicate\Operator('id', '=', 3), + new Predicate\Operator('number', '>', 20) + ])), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".*, "tableA".*, "tableB".*, "tableC".* FROM "foo" ' + . 'INNER JOIN "tableA" ON "id" = \'1\' INNER JOIN "tableB" ON "id" = \'2\' ' + . 'INNER JOIN "tableC" ON "id" = \'3\' AND "number" > \'20\'', + 'prepare' => 'SELECT "foo".*, "tableA".*, "tableB".*, "tableC".* FROM "foo"' + . ' INNER JOIN "tableA" ON "id" = :join1expr1 INNER JOIN "tableB" ON "id" = :join2expr1 ' + . 'INNER JOIN "tableC" ON "id" = :join3expr1 AND "number" > :join3expr2', + 'useNamedParams' => true, + ], + ], + ], + [ // @author robertbasic // @link https://github.com/zendframework/zf2/pull/2714 + 'sqlObject' => $this->select()->from('foo')->columns(['bar'], false), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "bar" AS "bar" FROM "foo"', + 'prepare' => true, + ], + ], + ], + [ // Test TableIdentifier In Joins @link https://github.com/zendframework/zf2/issues/3294 + 'sqlObject' => $this->select()->from('foo')->columns([])->join(new TableIdentifier('bar', 'baz'), 'm = n', ['thecount' => new Expression("COUNT(*)")]), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT COUNT(*) AS "thecount" FROM "foo" INNER JOIN "baz"."bar" ON "m" = "n"', + 'prepare' => true, + ], + ], + ], + [ // subselect in join + 'sqlObject' => function () { + $subselect = $this->select(); + $subselect->from('bar')->where->like('y', '%Foo%'); + return $this->select() + ->from('foo') + ->join( + ['z' => $subselect], + 'z.foo = bar.id' + ); + }, + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".*, "z".* FROM "foo" INNER JOIN (SELECT "bar".* FROM "bar" WHERE "y" LIKE \'%Foo%\') AS "z" ON "z"."foo" = "bar"."id"', + 'prepare' => 'SELECT "foo".*, "z".* FROM "foo" INNER JOIN (SELECT "bar".* FROM "bar" WHERE "y" LIKE ?) AS "z" ON "z"."foo" = "bar"."id"', + ], + ], + ], + [ // Test TableIdentifier In Joins, with multiple joins @link https://github.com/zendframework/zf2/issues/3294 + 'sqlObject' => $this->select()->from('foo') + ->join(['a' => new TableIdentifier('another_foo', 'another_schema')], 'a.x = foo.foo_column') + ->join('bar', 'foo.colx = bar.colx'), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".*, "a".*, "bar".* FROM "foo"' + . ' INNER JOIN "another_schema"."another_foo" AS "a" ON "a"."x" = "foo"."foo_column"' + . ' INNER JOIN "bar" ON "foo"."colx" = "bar"."colx"', + 'prepare' => true, + ], + ], + ], + [ + 'sqlObject' => $this->select()->from('foo')->quantifier(Select::QUANTIFIER_DISTINCT), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT DISTINCT "foo".* FROM "foo"', + 'prepare' => true, + ], + ], + ], + [ + 'sqlObject' => $this->select()->from('foo')->quantifier(new Expression('TOP ?', [10])), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT TOP \'10\' "foo".* FROM "foo"', + 'prepare' => 'SELECT TOP ? "foo".* FROM "foo"', + ], + ], + ], + [ + 'sqlObject' => $this->select()->from(['x' => 'foo'])->columns(['bar' => 'foo.bar'], false), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo"."bar" AS "bar" FROM "foo" AS "x"', + 'prepare' => 'SELECT "foo"."bar" AS "bar" FROM "foo" AS "x"', + ], + ], + ], + [ + 'sqlObject' => $this->select() + ->from('foo') + ->where('a = b') + ->combine( + $this->select()->from('bar')->where('c = d'), + Select::COMBINE_UNION, + 'ALL' + ), + 'expected' => [ + 'sql92' => [ + 'string' => '( SELECT "foo".* FROM "foo" WHERE a = b ) UNION ALL ( SELECT "bar".* FROM "bar" WHERE c = d )', + 'prepare' => true, + ], + ], + ], + [ // limit with offset + 'sqlObject' => $this->select()->from('foo')->limit("5")->offset("10"), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" LIMIT \'5\' OFFSET \'10\'', + 'prepare' => 'SELECT "foo".* FROM "foo" LIMIT ? OFFSET ?', + 'parametersEquals' => ['limit' => 5, 'offset' => 10], + ], + ], + ], + [ // functions without table + 'sqlObject' => $this->select() + ->columns([ + new Expression('SOME_DB_FUNCTION_ONE()'), + 'foo' => new Expression('SOME_DB_FUNCTION_TWO()'), + ]), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT SOME_DB_FUNCTION_ONE() AS column1, SOME_DB_FUNCTION_TWO() AS "foo"', + 'prepare' => true, + ], + ], + ], + [ // limit with big offset and limit + 'sqlObject' => $this->select()->from('foo')->limit("10000000000000000000")->offset("10000000000000000000"), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" LIMIT \'10000000000000000000\' OFFSET \'10000000000000000000\'', + 'prepare' => 'SELECT "foo".* FROM "foo" LIMIT ? OFFSET ?', + 'parametersEquals' => ['limit' => 10000000000000000000, 'offset' => 10000000000000000000], + ], + ], + ], + [ // combine and union with order at the end + 'sqlObject' => $this->select() + ->from([ + 'sub' => $this->select() + ->from('foo') + ->where('a = b') + ->combine( + $this->select()->from('bar')->where('c = d') + ) + ]) + ->order('id DESC'), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "sub".* FROM (( SELECT "foo".* FROM "foo" WHERE a = b ) UNION ( SELECT "bar".* FROM "bar" WHERE c = d )) AS "sub" ORDER BY "id" DESC', + 'prepare' => true, + ], + ], + ], + [ //Expression as joinName + 'sqlObject' => $this->select() + ->from(new TableIdentifier('foo')) + ->join(['bar' => new Expression('psql_function_which_returns_table')], 'foo.id = bar.fooid'), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".*, "bar".* FROM "foo" INNER JOIN psql_function_which_returns_table AS "bar" ON "foo"."id" = "bar"."fooid"', + 'prepare' => true, + ], + ], + ], + [ // Test generic predicate is appended with AND + 'sqlObject' => function () { + $select = $this->select(); + $select->from(new TableIdentifier('foo')) + ->where + ->nest + ->isNull('bar') + ->and + ->predicate(new Predicate\Literal('1=1')) + ->unnest; + return $select; + }, + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" WHERE ("bar" IS NULL AND 1=1)', + 'prepare' => true, + ], + ], + ], + [ // Test generic predicate is appended with OR + 'sqlObject' => function () { + $select = $this->select(); + $select->from(new TableIdentifier('foo')) + ->where + ->nest + ->isNull('bar') + ->or + ->predicate(new Predicate\Literal('1=1')) + ->unnest; + return $select; + }, + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" WHERE ("bar" IS NULL OR 1=1)', + 'prepare' => true, + ], + ], + ], + [ // @author Andrzej Lewandowski @link https://github.com/zendframework/zf2/issues/7222 + 'sqlObject' => $this->select()->from('foo')->join('zac', '(catalog_category_website.category_id = catalog_category.category_id)'), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".*, "zac".* FROM "foo" INNER JOIN "zac" ON ("catalog_category_website"."category_id" = "catalog_category"."category_id")', + 'prepare' => true, + ], + ], + ], + [ // Combine + 'sqlObject' => $this->select() + ->from(['foo'=>$this->combine($this->select('bar0'))]) + ->columns(['c1'=>$this->combine($this->select('bar1'))]) + ->where(['c2'=>$this->combine($this->select('bar2'))]) + ->join(['c3'=>$this->combine($this->select('bar3'))], 'xx=yy'), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT ((SELECT "bar1".* FROM "bar1")) AS "c1", "c3".* FROM ((SELECT "bar0".* FROM "bar0")) AS "foo" INNER JOIN ((SELECT "bar3".* FROM "bar3")) AS "c3" ON "xx"="yy" WHERE "c2" = ((SELECT "bar2".* FROM "bar2"))', + ], + ], + ], + ]; + } +} diff --git a/test/Sql/Builder/SqlServer/Ddl/CreateTableBuilderTest.php b/test/Sql/Builder/SqlServer/Ddl/CreateTableBuilderTest.php deleted file mode 100644 index 31e0c7fe1d..0000000000 --- a/test/Sql/Builder/SqlServer/Ddl/CreateTableBuilderTest.php +++ /dev/null @@ -1,39 +0,0 @@ -assertEquals("CREATE TABLE \"foo\" ( \n)", $ctd->setSubject($ct)->getSqlString()); - - $ct = new CreateTable('foo', true); - $this->assertEquals("CREATE TABLE \"#foo\" ( \n)", $ctd->setSubject($ct)->getSqlString()); - - $ct = new CreateTable('foo'); - $ct->addColumn(new Column('bar')); - $this->assertEquals("CREATE TABLE \"foo\" ( \n \"bar\" INTEGER NOT NULL \n)", $ctd->setSubject($ct)->getSqlString()); - - $ct = new CreateTable('foo', true); - $ct->addColumn(new Column('bar')); - $this->assertEquals("CREATE TABLE \"#foo\" ( \n \"bar\" INTEGER NOT NULL \n)", $ctd->setSubject($ct)->getSqlString()); - } -} diff --git a/test/Sql/Builder/SqlServer/SelectBuilderTest.php b/test/Sql/Builder/SqlServer/SelectBuilderTest.php deleted file mode 100644 index a453de3a7d..0000000000 --- a/test/Sql/Builder/SqlServer/SelectBuilderTest.php +++ /dev/null @@ -1,116 +0,0 @@ -getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $driver->expects($this->exactly($expectedFormatParamCount))->method('formatParameterName')->will($this->returnValue('?')); - - // test - $adapter = $this->getMock( - 'Zend\Db\Adapter\Adapter', - null, - [ - $driver, - new SqlServerPlatform() - ] - ); - - $parameterContainer = new ParameterContainer; - $statement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $statement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($parameterContainer)); - - $statement->expects($this->once())->method('setSql')->with($expectedSql); - - $selectDecorator = new SelectBuilder; - $selectDecorator->setSubject($select); - $selectDecorator->prepareStatement($adapter, $statement); - - $this->assertEquals($expectedParams, $parameterContainer->getNamedArray()); - } - - /** - * @testdox integration test: Testing SelectBuilder will use Select an internal state to prepare a proper limit/offset sql statement - * @covers Zend\Db\Sql\Platform\SqlServer\SelectBuilder::getSqlString - * @covers Zend\Db\Sql\Platform\SqlServer\SelectBuilder::processLimitOffset - * @dataProvider dataProvider - */ - public function testGetSqlString(Select $select, $ignored, $alsoIgnored, $expectedSql) - { - $parameterContainer = new ParameterContainer; - $statement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $statement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($parameterContainer)); - - $selectDecorator = new SelectBuilder; - $selectDecorator->setSubject($select); - $this->assertEquals($expectedSql, $selectDecorator->getSqlString(new SqlServerPlatform)); - } - - public function dataProvider() - { - $select0 = new Select; - $select0->from('foo')->columns(['bar', 'baz'])->order('bar')->limit(5)->offset(10); - $expectedPrepareSql0 = 'SELECT [bar], [baz] FROM ( SELECT [foo].[bar] AS [bar], [foo].[baz] AS [baz], ROW_NUMBER() OVER (ORDER BY [bar] ASC) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?'; - $expectedParams0 = ['offset' => 10, 'limit' => 5, 'offsetForSum' => 10]; - $expectedSql0 = 'SELECT [bar], [baz] FROM ( SELECT [foo].[bar] AS [bar], [foo].[baz] AS [baz], ROW_NUMBER() OVER (ORDER BY [bar] ASC) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 10+1 AND 5+10'; - $expectedFormatParamCount0 = 3; - - $select1 = new Select; - $select1->from('foo')->columns(['bar', 'bam' => 'baz'])->limit(5)->offset(10); - $expectedPrepareSql1 = 'SELECT [bar], [bam] FROM ( SELECT [foo].[bar] AS [bar], [foo].[baz] AS [bam], ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?'; - $expectedParams1 = ['offset' => 10, 'limit' => 5, 'offsetForSum' => 10]; - $expectedSql1 = 'SELECT [bar], [bam] FROM ( SELECT [foo].[bar] AS [bar], [foo].[baz] AS [bam], ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 10+1 AND 5+10'; - $expectedFormatParamCount1 = 3; - - $select2 = new Select; - $select2->from('foo')->order('bar')->limit(5)->offset(10); - $expectedPrepareSql2 = 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY [bar] ASC) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?'; - $expectedParams2 = ['offset' => 10, 'limit' => 5, 'offsetForSum' => 10]; - $expectedSql2 = 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY [bar] ASC) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 10+1 AND 5+10'; - $expectedFormatParamCount2 = 3; - - $select3 = new Select; - $select3->from('foo'); - $expectedPrepareSql3 = 'SELECT [foo].* FROM [foo]'; - $expectedParams3 = []; - $expectedSql3 = 'SELECT [foo].* FROM [foo]'; - $expectedFormatParamCount3 = 0; - - $select4 = new Select; - $select4->from('foo')->columns([new Expression('DISTINCT(bar) as bar')])->limit(5)->offset(10); - $expectedPrepareSql4 = 'SELECT DISTINCT(bar) as bar FROM ( SELECT DISTINCT(bar) as bar, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?'; - $expectedParams4 = ['offset' => 10, 'limit' => 5, 'offsetForSum' => 10]; - $expectedSql4 = 'SELECT DISTINCT(bar) as bar FROM ( SELECT DISTINCT(bar) as bar, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 10+1 AND 5+10'; - $expectedFormatParamCount4 = 3; - - return [ - [$select0, $expectedPrepareSql0, $expectedParams0, $expectedSql0, $expectedFormatParamCount0], - [$select1, $expectedPrepareSql1, $expectedParams1, $expectedSql1, $expectedFormatParamCount1], - [$select2, $expectedPrepareSql2, $expectedParams2, $expectedSql2, $expectedFormatParamCount2], - [$select3, $expectedPrepareSql3, $expectedParams3, $expectedSql3, $expectedFormatParamCount3], - [$select4, $expectedPrepareSql4, $expectedParams4, $expectedSql4, $expectedFormatParamCount4], - ]; - } -} diff --git a/test/Sql/Builder/Sqlite/SelectBuilderTest.php b/test/Sql/Builder/Sqlite/SelectBuilderTest.php deleted file mode 100644 index 9485c4654a..0000000000 --- a/test/Sql/Builder/Sqlite/SelectBuilderTest.php +++ /dev/null @@ -1,92 +0,0 @@ -getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $driver->expects($this->any())->method('formatParameterName')->will($this->returnValue('?')); - - // test - $adapter = $this->getMock( - 'Zend\Db\Adapter\Adapter', - null, - [ - $driver, - new SqlitePlatform() - ] - ); - - $parameterContainer = new ParameterContainer; - $statement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $statement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($parameterContainer)); - - $statement->expects($this->once())->method('setSql')->with($expectedSql); - - $selectDecorator = new SelectBuilder; - $selectDecorator->setSubject($select); - $selectDecorator->prepareStatement($adapter, $statement); - - $this->assertEquals($expectedParams, $parameterContainer->getNamedArray()); - } - - /** - * @testdox integration test: Testing SelectDecorator will use Select an internal state to prepare a proper combine - * statement - * @covers Zend\Db\Sql\Platform\Sqlite\SelectDecorator::getSqlString - * @covers Zend\Db\Sql\Platform\Sqlite\SelectDecorator::processCombine - * @dataProvider dataProviderUnionSyntaxFromCombine - */ - public function testGetSqlStringPreparesUnionSyntaxFromCombine(Select $select, $ignore, $alsoIgnore, $expectedSql) - { - $parameterContainer = new ParameterContainer; - $statement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $statement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($parameterContainer)); - - $selectDecorator = new SelectBuilder; - $selectDecorator->setSubject($select); - $this->assertEquals($expectedSql, $selectDecorator->getSqlString(new SqlitePlatform)); - } - - /** - * Create a data provider for union syntax that would come from combine - * - * @return mixed[] - */ - public function dataProviderUnionSyntaxFromCombine() - { - $select0 = new Select; - $select0->from('foo'); - $select1 = clone $select0; - $select0->combine($select1); - - $expectedPrepareSql0 = ' SELECT "foo".* FROM "foo" UNION SELECT "foo".* FROM "foo"'; - $expectedParams0 = []; - $expectedSql0 = ' SELECT "foo".* FROM "foo" UNION SELECT "foo".* FROM "foo"'; - - return [ - [$select0, $expectedPrepareSql0, $expectedParams0, $expectedSql0], - ]; - } -} diff --git a/test/Sql/Builder/UpdateBuilderTest.php b/test/Sql/Builder/UpdateBuilderTest.php new file mode 100644 index 0000000000..e89ccde4fd --- /dev/null +++ b/test/Sql/Builder/UpdateBuilderTest.php @@ -0,0 +1,99 @@ +assertBuilder($sqlObject, $platform, $expected); + } + + public function dataProvider() + { + return $this->prepareDataProvider([ + [ //??? testPassingMultipleKeyValueInWhereClause() + 'sqlObject' => $this->update() + ->table('table') + ->set(['fld1' => 'val1']) + ->where(['id1' => 'val1', 'id2' => 'val2']), + 'expected' => [ + 'sql92' => [ + 'string' => 'UPDATE "table" SET "fld1" = \'val1\' WHERE "id1" = \'val1\' AND "id2" = \'val2\'', + ], + ], + ], + [ // testPrepareStatement(), testGetSqlString() + 'sqlObject' => $this->update() + ->table('foo') + ->set(['bar' => 'baz', 'boo' => new Expression('NOW()'), 'bam' => null]) + ->where('x = y'), + 'expected' => [ + 'sql92' => [ + 'string' => 'UPDATE "foo" SET "bar" = \'baz\', "boo" = NOW(), "bam" = NULL WHERE x = y', + 'prepare' => 'UPDATE "foo" SET "bar" = ?, "boo" = NOW(), "bam" = NULL WHERE x = y', + ], + ], + ], + [ // testPrepareStatement() // with TableIdentifier + 'sqlObject' => $this->update() + ->table(new TableIdentifier('foo', 'sch')) + ->set(['bar' => 'baz', 'boo' => new Expression('NOW()'), 'bam' => null]) + ->where('x = y'), + 'expected' => [ + 'sql92' => [ + 'string' => 'UPDATE "sch"."foo" SET "bar" = \'baz\', "boo" = NOW(), "bam" = NULL WHERE x = y', + 'prepare' => 'UPDATE "sch"."foo" SET "bar" = ?, "boo" = NOW(), "bam" = NULL WHERE x = y', + ], + ], + ], + [ // testGetSqlStringForFalseUpdateValueParameter() + 'sqlObject' => $this->update() + ->table(new TableIdentifier('foo', 'sch')) + ->set(['bar' => false, 'boo' => 'test', 'bam' => true]) + ->where('x = y'), + 'expected' => [ + 'sql92' => [ + 'string' => 'UPDATE "sch"."foo" SET "bar" = \'\', "boo" = \'test\', "bam" = \'1\' WHERE x = y', + 'prepare' => 'UPDATE "sch"."foo" SET "bar" = ?, "boo" = ?, "bam" = ? WHERE x = y', + ], + ], + ], + [ // testCloneUpdate() + 'sqlObject' => function () { + $update1 = clone $this->update(); + $update1->table('foo') + ->set(['bar' => 'baz']) + ->where('x = y'); + + $update2 = clone $this->update(); + $update2->table('foo') + ->set(['bar' => 'baz']) + ->where([ + 'id = ?'=>1 + ]); + return $update2; + }, + 'expected' => [ + 'sql92' => [ + 'string' => 'UPDATE "foo" SET "bar" = \'baz\' WHERE id = \'1\'', + ], + ], + ], + ]); + } +} diff --git a/test/Sql/CombineTest.php b/test/Sql/CombineTest.php index bc9fd0b156..cc9372acd5 100644 --- a/test/Sql/CombineTest.php +++ b/test/Sql/CombineTest.php @@ -9,11 +9,9 @@ namespace ZendTest\Db\Sql; -use Zend\Db\Adapter\ParameterContainer; use Zend\Db\Sql\Combine; use Zend\Db\Sql\Select; use Zend\Db\Sql\Predicate\Expression; -use Zend\Db\Adapter\StatementContainer; class CombineTest extends \PHPUnit_Framework_TestCase { @@ -38,88 +36,6 @@ public function testRejectsInvalidStatement() $this->combine->combine('foo'); } - public function testGetSqlString() - { - $this->combine - ->union(new Select('t1')) - ->intersect(new Select('t2')) - ->except(new Select('t3')) - ->union(new Select('t4')); - - $this->assertEquals( - '(SELECT "t1".* FROM "t1") INTERSECT (SELECT "t2".* FROM "t2") EXCEPT (SELECT "t3".* FROM "t3") UNION (SELECT "t4".* FROM "t4")', - $this->combine->getSqlString() - ); - } - - public function testGetSqlStringWithModifier() - { - $this->combine - ->union(new Select('t1')) - ->union(new Select('t2'), 'ALL'); - - $this->assertEquals( - '(SELECT "t1".* FROM "t1") UNION ALL (SELECT "t2".* FROM "t2")', - $this->combine->getSqlString() - ); - } - - public function testGetSqlStringFromArray() - { - $this->combine->combine([ - [new Select('t1')], - [new Select('t2'), Combine::COMBINE_INTERSECT, 'ALL'], - [new Select('t3'), Combine::COMBINE_EXCEPT], - ]); - - $this->assertEquals( - '(SELECT "t1".* FROM "t1") INTERSECT ALL (SELECT "t2".* FROM "t2") EXCEPT (SELECT "t3".* FROM "t3")', - $this->combine->getSqlString() - ); - - $this->combine = new Combine(); - $this->combine->combine([ - new Select('t1'), - new Select('t2'), - new Select('t3'), - ]); - - $this->assertEquals( - '(SELECT "t1".* FROM "t1") UNION (SELECT "t2".* FROM "t2") UNION (SELECT "t3".* FROM "t3")', - $this->combine->getSqlString() - ); - } - - public function testGetSqlStringEmpty() - { - $this->assertSame( - null, - $this->combine->getSqlString() - ); - } - - public function testPrepareStatementWithModifier() - { - $select1 = new Select('t1'); - $select1->where(['x1'=>10]); - $select2 = new Select('t2'); - $select2->where(['x2'=>20]); - - $this->combine->combine([ - $select1, - $select2 - ]); - - $adapter = $this->getMockAdapter(); - - $statement = $this->combine->prepareStatement($adapter, new StatementContainer); - $this->assertInstanceOf('Zend\Db\Adapter\StatementContainerInterface', $statement); - $this->assertEquals( - '(SELECT "t1".* FROM "t1" WHERE "x1" = ?) UNION (SELECT "t2".* FROM "t2" WHERE "x2" = ?)', - $statement->getSql() - ); - } - public function testAlignColumns() { $select1 = new Select('t1'); @@ -143,7 +59,7 @@ public function testAlignColumns() 'c1' => 'c1', 'c2' => new Expression('NULL'), ], - $select1->getRawState('columns') + $select1->columns ); $this->assertEquals( @@ -152,58 +68,7 @@ public function testAlignColumns() 'c1' => 'c1', 'c2' => 'c2', ], - $select2->getRawState('columns') - ); - } - - public function testGetRawState() - { - $select = new Select('t1'); - $this->combine->combine($select); - $this->assertSame( - [ - 'combine' => [ - [ - 'select' => $select, - 'type' => Combine::COMBINE_UNION, - 'modifier' => '' - ], - ], - 'columns' => [ - '0' => '*', - ], - ], - $this->combine->getRawState() + $select2->columns ); } - - /** - * - * @return \PHPUnit_Framework_MockObject_MockObject|\Zend\Db\Adapter\Adapter - */ - protected function getMockAdapter() - { - $parameterContainer = new ParameterContainer(); - - $mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $mockStatement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($parameterContainer)); - - - $setGetSqlFunction = function ($sql = null) use ($mockStatement) { - static $sqlValue; - if ($sql) { - $sqlValue = $sql; - return $mockStatement; - } - return $sqlValue; - }; - $mockStatement->expects($this->any())->method('setSql')->will($this->returnCallback($setGetSqlFunction)); - $mockStatement->expects($this->any())->method('getSql')->will($this->returnCallback($setGetSqlFunction)); - - $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $mockDriver->expects($this->any())->method('formatParameterName')->will($this->returnValue('?')); - $mockDriver->expects($this->any())->method('createStatement')->will($this->returnValue($mockStatement)); - - return $this->getMock('Zend\Db\Adapter\Adapter', null, [$mockDriver]); - } } diff --git a/test/Sql/Ddl/AlterTableTest.php b/test/Sql/Ddl/AlterTableTest.php index 563b1972d9..8f002b574a 100644 --- a/test/Sql/Ddl/AlterTableTest.php +++ b/test/Sql/Ddl/AlterTableTest.php @@ -10,8 +10,6 @@ namespace ZendTest\Db\Sql\Ddl; use Zend\Db\Sql\Ddl\AlterTable; -use Zend\Db\Sql\Ddl\Column; -use Zend\Db\Sql\Ddl\Constraint; class AlterTableTest extends \PHPUnit_Framework_TestCase { @@ -21,9 +19,9 @@ class AlterTableTest extends \PHPUnit_Framework_TestCase public function testSetTable() { $at = new AlterTable(); - $this->assertEquals('', $at->getRawState('table')); + $this->assertEquals('', $at->table); $this->assertSame($at, $at->setTable('test')); - $this->assertEquals('test', $at->getRawState('table')); + $this->assertEquals('test', $at->table); } /** @@ -35,7 +33,7 @@ public function testAddColumn() /** @var \Zend\Db\Sql\Ddl\Column\ColumnInterface $colMock */ $colMock = $this->getMock('Zend\Db\Sql\Ddl\Column\ColumnInterface'); $this->assertSame($at, $at->addColumn($colMock)); - $this->assertEquals([$colMock], $at->getRawState($at::ADD_COLUMNS)); + $this->assertEquals([$colMock], $at->addColumns); } /** @@ -47,7 +45,7 @@ public function testChangeColumn() /** @var \Zend\Db\Sql\Ddl\Column\ColumnInterface $colMock */ $colMock = $this->getMock('Zend\Db\Sql\Ddl\Column\ColumnInterface'); $this->assertSame($at, $at->changeColumn('newname', $colMock)); - $this->assertEquals(['newname' => $colMock], $at->getRawState($at::CHANGE_COLUMNS)); + $this->assertEquals(['newname' => $colMock], $at->changeColumns); } /** @@ -57,7 +55,7 @@ public function testDropColumn() { $at = new AlterTable(); $this->assertSame($at, $at->dropColumn('foo')); - $this->assertEquals(['foo'], $at->getRawState($at::DROP_COLUMNS)); + $this->assertEquals(['foo'], $at->dropColumns); } /** @@ -67,7 +65,7 @@ public function testDropConstraint() { $at = new AlterTable(); $this->assertSame($at, $at->dropConstraint('foo')); - $this->assertEquals(['foo'], $at->getRawState($at::DROP_CONSTRAINTS)); + $this->assertEquals(['foo'], $at->dropConstraints); } /** @@ -79,34 +77,6 @@ public function testAddConstraint() /** @var \Zend\Db\Sql\Ddl\Constraint\ConstraintInterface $conMock */ $conMock = $this->getMock('Zend\Db\Sql\Ddl\Constraint\ConstraintInterface'); $this->assertSame($at, $at->addConstraint($conMock)); - $this->assertEquals([$conMock], $at->getRawState($at::ADD_CONSTRAINTS)); - } - - /** - * @covers Zend\Db\Sql\Ddl\AlterTable::getSqlString - * @todo Implement testGetSqlString(). - */ - public function testGetSqlString() - { - $at = new AlterTable('foo'); - $at->addColumn(new Column\Varchar('another', 255)); - $at->changeColumn('name', new Column\Varchar('new_name', 50)); - $at->dropColumn('foo'); - $at->addConstraint(new Constraint\ForeignKey('my_fk', 'other_id', 'other_table', 'id', 'CASCADE', 'CASCADE')); - $at->dropConstraint('my_index'); - $expected =<<getSqlString(); - $this->assertEquals( - str_replace(["\r", "\n"], "", $expected), - str_replace(["\r", "\n"], "", $actual) - ); + $this->assertEquals([$conMock], $at->addConstraints); } } diff --git a/test/Sql/Ddl/CreateTableTest.php b/test/Sql/Ddl/CreateTableTest.php index 3189610e2c..9cb0954162 100644 --- a/test/Sql/Ddl/CreateTableTest.php +++ b/test/Sql/Ddl/CreateTableTest.php @@ -9,8 +9,6 @@ namespace ZendTest\Db\Sql\Ddl; -use Zend\Db\Sql\Ddl\Column\Column; -use Zend\Db\Sql\Ddl\Constraint; use Zend\Db\Sql\Ddl\CreateTable; class CreateTableTest extends \PHPUnit_Framework_TestCase @@ -22,7 +20,7 @@ class CreateTableTest extends \PHPUnit_Framework_TestCase public function testObjectConstruction() { $ct = new CreateTable('foo', true); - $this->assertEquals('foo', $ct->getRawState($ct::TABLE)); + $this->assertEquals('foo', $ct->table); $this->assertTrue($ct->isTemporary()); } @@ -38,8 +36,6 @@ public function testSetTemporary() $this->assertTrue($ct->isTemporary()); $ct->setTemporary('yes'); $this->assertTrue($ct->isTemporary()); - - $this->assertStringStartsWith("CREATE TEMPORARY TABLE", $ct->getSqlString()); } /** @@ -59,18 +55,17 @@ public function testIsTemporary() public function testSetTable() { $ct = new CreateTable(); - $this->assertEquals('', $ct->getRawState('table')); + $this->assertEquals('', $ct->table); $ct->setTable('test'); return $ct; } /** - * @covers Zend\Db\Sql\Ddl\CreateTable::getRawState * @depends testSetTable */ public function testRawStateViaTable(CreateTable $ct) { - $this->assertEquals('test', $ct->getRawState('table')); + $this->assertEquals('test', $ct->table); } /** @@ -85,12 +80,11 @@ public function testAddColumn() } /** - * @covers Zend\Db\Sql\Ddl\CreateTable::getRawState * @depends testAddColumn */ public function testRawStateViaColumn(CreateTable $ct) { - $state = $ct->getRawState('columns'); + $state = $ct->columns; $this->assertInternalType('array', $state); $column = array_pop($state); $this->assertInstanceOf('Zend\Db\Sql\Ddl\Column\ColumnInterface', $column); @@ -108,49 +102,13 @@ public function testAddConstraint() } /** - * @covers Zend\Db\Sql\Ddl\CreateTable::getRawState * @depends testAddConstraint */ public function testRawStateViaConstraint(CreateTable $ct) { - $state = $ct->getRawState('constraints'); + $state = $ct->constraints; $this->assertInternalType('array', $state); $constraint = array_pop($state); $this->assertInstanceOf('Zend\Db\Sql\Ddl\Constraint\ConstraintInterface', $constraint); } - - /** - * @covers Zend\Db\Sql\Ddl\CreateTable::getSqlString - */ - public function testGetSqlString() - { - $ct = new CreateTable('foo'); - $this->assertEquals("CREATE TABLE \"foo\" ( \n)", $ct->getSqlString()); - - $ct = new CreateTable('foo', true); - $this->assertEquals("CREATE TEMPORARY TABLE \"foo\" ( \n)", $ct->getSqlString()); - - $ct = new CreateTable('foo'); - $ct->addColumn(new Column('bar')); - $this->assertEquals("CREATE TABLE \"foo\" ( \n \"bar\" INTEGER NOT NULL \n)", $ct->getSqlString()); - - $ct = new CreateTable('foo', true); - $ct->addColumn(new Column('bar')); - $this->assertEquals("CREATE TEMPORARY TABLE \"foo\" ( \n \"bar\" INTEGER NOT NULL \n)", $ct->getSqlString()); - - $ct = new CreateTable('foo', true); - $ct->addColumn(new Column('bar')); - $ct->addColumn(new Column('baz')); - $this->assertEquals("CREATE TEMPORARY TABLE \"foo\" ( \n \"bar\" INTEGER NOT NULL,\n \"baz\" INTEGER NOT NULL \n)", $ct->getSqlString()); - - $ct = new CreateTable('foo'); - $ct->addColumn(new Column('bar')); - $ct->addConstraint(new Constraint\PrimaryKey('bat')); - $this->assertEquals("CREATE TABLE \"foo\" ( \n \"bar\" INTEGER NOT NULL , \n PRIMARY KEY (\"bat\") \n)", $ct->getSqlString()); - - $ct = new CreateTable('foo'); - $ct->addConstraint(new Constraint\PrimaryKey('bar')); - $ct->addConstraint(new Constraint\PrimaryKey('bat')); - $this->assertEquals("CREATE TABLE \"foo\" ( \n PRIMARY KEY (\"bar\"),\n PRIMARY KEY (\"bat\") \n)", $ct->getSqlString()); - } } diff --git a/test/Sql/Ddl/DropTableTest.php b/test/Sql/Ddl/DropTableTest.php index 0d9b028e38..aed0dc90da 100644 --- a/test/Sql/Ddl/DropTableTest.php +++ b/test/Sql/Ddl/DropTableTest.php @@ -13,12 +13,9 @@ class DropTableTest extends \PHPUnit_Framework_TestCase { - /** - * @covers Zend\Db\Sql\Ddl\DropTable::getSqlString - */ - public function testGetSqlString() + public function testObjectConstruction() { - $dt = new DropTable('foo'); - $this->assertEquals('DROP TABLE "foo"', $dt->getSqlString()); + $ct = new DropTable('foo'); + $this->assertEquals('foo', $ct->table); } } diff --git a/test/Sql/DeleteTest.php b/test/Sql/DeleteTest.php index 30d63757b4..933b6a189f 100644 --- a/test/Sql/DeleteTest.php +++ b/test/Sql/DeleteTest.php @@ -10,9 +10,7 @@ namespace ZendTest\Db\Sql; use Zend\Db\Sql\Delete; -use Zend\Db\Sql\Predicate\IsNotNull; use Zend\Db\Sql\TableIdentifier; -use Zend\Db\Sql\Where; class DeleteTest extends \PHPUnit_Framework_TestCase { @@ -30,14 +28,6 @@ protected function setUp() $this->delete = new Delete; } - /** - * Tears down the fixture, for example, closes a network connection. - * This method is called after a test is executed. - */ - protected function tearDown() - { - } - /** * @covers Zend\Db\Sql\Delete::from */ @@ -51,179 +41,12 @@ public function testFrom() $this->assertEquals($tableIdentifier, $this->readAttribute($this->delete, 'table')); } - /** - * @covers Zend\Db\Sql\Delete::where - * - * @todo REMOVE THIS IN 3.x - */ - public function testWhere() - { - $this->delete->where('x = y'); - $this->delete->where(['foo > ?' => 5]); - $this->delete->where(['id' => 2]); - $this->delete->where(['a = b'], Where::OP_OR); - $this->delete->where(['c1' => null]); - $this->delete->where(['c2' => [1, 2, 3]]); - $this->delete->where([new IsNotNull('c3')]); - $this->delete->where(['one' => 1, 'two' => 2]); - $where = $this->delete->where; - - $predicates = $this->readAttribute($where, 'predicates'); - $this->assertEquals('AND', $predicates[0][0]); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\Literal', $predicates[0][1]); - - $this->assertEquals('AND', $predicates[1][0]); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\Expression', $predicates[1][1]); - - $this->assertEquals('AND', $predicates[2][0]); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\Operator', $predicates[2][1]); - - $this->assertEquals('OR', $predicates[3][0]); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\Literal', $predicates[3][1]); - - $this->assertEquals('AND', $predicates[4][0]); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\IsNull', $predicates[4][1]); - - $this->assertEquals('AND', $predicates[5][0]); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\In', $predicates[5][1]); - - $this->assertEquals('AND', $predicates[6][0]); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\IsNotNull', $predicates[6][1]); - - $this->assertEquals('AND', $predicates[7][0]); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\Operator', $predicates[7][1]); - - $this->assertEquals('AND', $predicates[8][0]); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\Operator', $predicates[8][1]); - - $where = new Where; - $this->delete->where($where); - $this->assertSame($where, $this->delete->where); - - $this->delete->where(function ($what) use ($where) { - $this->assertSame($where, $what); - }); - } - - /** - * @covers Zend\Db\Sql\Delete::prepareStatement - */ - public function testPrepareStatement() - { - $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $mockAdapter = $this->getMock('Zend\Db\Adapter\Adapter', null, [$mockDriver]); - - $mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $mockStatement->expects($this->at(2)) - ->method('setSql') - ->with($this->equalTo('DELETE FROM "foo" WHERE x = y')); - - $this->delete->from('foo') - ->where('x = y'); - - $this->delete->prepareStatement($mockAdapter, $mockStatement); - - // with TableIdentifier - $this->delete = new Delete; - $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $mockAdapter = $this->getMock('Zend\Db\Adapter\Adapter', null, [$mockDriver]); - - $mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $mockStatement->expects($this->at(2)) - ->method('setSql') - ->with($this->equalTo('DELETE FROM "sch"."foo" WHERE x = y')); - - $this->delete->from(new TableIdentifier('foo', 'sch')) - ->where('x = y'); - - $this->delete->prepareStatement($mockAdapter, $mockStatement); - } - - /** - * @covers Zend\Db\Sql\Delete::getSqlString - */ - public function testGetSqlString() - { - $this->delete->from('foo') - ->where('x = y'); - $this->assertEquals('DELETE FROM "foo" WHERE x = y', $this->delete->getSqlString()); - - // with TableIdentifier - $this->delete = new Delete; - $this->delete->from(new TableIdentifier('foo', 'sch')) - ->where('x = y'); - $this->assertEquals('DELETE FROM "sch"."foo" WHERE x = y', $this->delete->getSqlString()); - } - - /** - * @coversNothing - */ - public function testSpecificationconstantsCouldBeOverridedByExtensionInPrepareStatement() - { - $deleteIgnore = new DeleteIgnore(); - - $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $mockAdapter = $this->getMock('Zend\Db\Adapter\Adapter', null, [$mockDriver]); - - $mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $mockStatement->expects($this->at(2)) - ->method('setSql') - ->with($this->equalTo('DELETE IGNORE FROM "foo" WHERE x = y')); - - $deleteIgnore->from('foo') - ->where('x = y'); - - $deleteIgnore->prepareStatement($mockAdapter, $mockStatement); - - - - // with TableIdentifier - $deleteIgnore = new DeleteIgnore(); - - $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $mockAdapter = $this->getMock('Zend\Db\Adapter\Adapter', null, [$mockDriver]); - - $mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $mockStatement->expects($this->at(2)) - ->method('setSql') - ->with($this->equalTo('DELETE IGNORE FROM "sch"."foo" WHERE x = y')); - - $deleteIgnore->from(new TableIdentifier('foo', 'sch')) - ->where('x = y'); - - $deleteIgnore->prepareStatement($mockAdapter, $mockStatement); - } - - /** - * @coversNothing - */ - public function testSpecificationconstantsCouldBeOverridedByExtensionInGetSqlString() - { - $deleteIgnore = new DeleteIgnore(); - - $deleteIgnore->from('foo') - ->where('x = y'); - $this->assertEquals('DELETE IGNORE FROM "foo" WHERE x = y', $deleteIgnore->getSqlString()); - - // with TableIdentifier - $deleteIgnore = new DeleteIgnore(); - $deleteIgnore->from(new TableIdentifier('foo', 'sch')) - ->where('x = y'); - $this->assertEquals('DELETE IGNORE FROM "sch"."foo" WHERE x = y', $deleteIgnore->getSqlString()); - } -} - -class DeleteIgnore extends Delete -{ - const SPECIFICATION_DELETE = 'deleteIgnore'; - - protected $specifications = [ - self::SPECIFICATION_DELETE => 'DELETE IGNORE FROM %1$s', - self::SPECIFICATION_WHERE => 'WHERE %1$s', - ]; - - protected function processdeleteIgnore(\Zend\Db\Adapter\Platform\PlatformInterface $platform, \Zend\Db\Adapter\Driver\DriverInterface $driver = null, \Zend\Db\Adapter\ParameterContainer $parameterContainer = null) + public function test__Get() { - return parent::processDelete($platform, $driver, $parameterContainer); + foreach (array_flip($this->readAttribute($this->delete, '__getProperties')) as $name) { + $this->delete->$name; + } + $this->setExpectedException('Zend\Db\Sql\Exception\InvalidArgumentException'); + $this->delete->badPropertyName; } } diff --git a/test/Sql/InsertTest.php b/test/Sql/InsertTest.php index 22647de751..4148ee5b10 100644 --- a/test/Sql/InsertTest.php +++ b/test/Sql/InsertTest.php @@ -11,9 +11,7 @@ use Zend\Db\Sql\Insert; use Zend\Db\Sql\Select; -use Zend\Db\Sql\Expression; use Zend\Db\Sql\TableIdentifier; -use ZendTest\Db\TestAsset\TrustingSql92Platform; class InsertTest extends \PHPUnit_Framework_TestCase { @@ -37,11 +35,11 @@ protected function setUp() public function testInto() { $this->insert->into('table', 'schema'); - $this->assertEquals('table', $this->insert->getRawState('table')); + $this->assertEquals('table', $this->insert->table); $tableIdentifier = new TableIdentifier('table', 'schema'); $this->insert->into($tableIdentifier); - $this->assertEquals($tableIdentifier, $this->insert->getRawState('table')); + $this->assertEquals($tableIdentifier, $this->insert->table); } /** @@ -49,9 +47,8 @@ public function testInto() */ public function testColumns() { - $columns = ['foo', 'bar']; - $this->insert->columns($columns); - $this->assertEquals($columns, $this->insert->getRawState('columns')); + $this->insert->columns(['foo', 'bar']); + $this->assertEquals(['foo', 'bar'], $this->insert->columns); } /** @@ -60,18 +57,18 @@ public function testColumns() public function testValues() { $this->insert->values(['foo' => 'bar']); - $this->assertEquals(['foo'], $this->insert->getRawState('columns')); - $this->assertEquals(['bar'], $this->insert->getRawState('values')); + $this->assertEquals(['foo'], $this->insert->columns); + $this->assertEquals(['bar'], $this->insert->values); // test will merge cols and values of previously set stuff $this->insert->values(['foo' => 'bax'], Insert::VALUES_MERGE); $this->insert->values(['boom' => 'bam'], Insert::VALUES_MERGE); - $this->assertEquals(['foo', 'boom'], $this->insert->getRawState('columns')); - $this->assertEquals(['bax', 'bam'], $this->insert->getRawState('values')); + $this->assertEquals(['foo', 'boom'], $this->insert->columns); + $this->assertEquals(['bax', 'bam'], $this->insert->values); $this->insert->values(['foo' => 'bax']); - $this->assertEquals(['foo'], $this->insert->getRawState('columns')); - $this->assertEquals(['bax'], $this->insert->getRawState('values')); + $this->assertEquals(['foo'], $this->insert->columns); + $this->assertEquals(['bax'], $this->insert->values); } /** @@ -81,7 +78,7 @@ public function testValuesThrowsExceptionWhenNotArrayOrSelect() { $this->setExpectedException( 'Zend\Db\Sql\Exception\InvalidArgumentException', - 'values() expects an array of values or Zend\Db\Sql\Select instance' + 'values() expects an array of values or Zend\Db\Sql\SelectableInterface instance' ); $this->insert->values(5); } @@ -95,7 +92,7 @@ public function testValuesThrowsExceptionWhenSelectMergeOverArray() $this->setExpectedException( 'Zend\Db\Sql\Exception\InvalidArgumentException', - 'A Zend\Db\Sql\Select instance cannot be provided with the merge flag' + 'A Zend\Db\Sql\SelectableInterface instance cannot be provided with the merge flag' ); $this->insert->values(new Select, Insert::VALUES_MERGE); } @@ -109,7 +106,7 @@ public function testValuesThrowsExceptionWhenArrayMergeOverSelect() $this->setExpectedException( 'Zend\Db\Sql\Exception\InvalidArgumentException', - 'An array of values cannot be provided with the merge flag when a Zend\Db\Sql\Select instance already exists as the value source' + 'An array of values cannot be provided with the merge flag when a Zend\Db\Sql\SelectableInterface instance already exists as the value source' ); $this->insert->values(['foo' => 'bar'], Insert::VALUES_MERGE); } @@ -123,265 +120,4 @@ public function testEmptyArrayValues() $this->insert->values([]); $this->assertEquals([], $this->readAttribute($this->insert, 'columns')); } - - /** - * @covers Zend\Db\Sql\Insert::prepareStatement - */ - public function testPrepareStatement() - { - $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $mockDriver->expects($this->any())->method('getPrepareType')->will($this->returnValue('positional')); - $mockDriver->expects($this->any())->method('formatParameterName')->will($this->returnValue('?')); - $mockAdapter = $this->getMock('Zend\Db\Adapter\Adapter', null, [$mockDriver]); - - $mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $pContainer = new \Zend\Db\Adapter\ParameterContainer([]); - $mockStatement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($pContainer)); - $mockStatement->expects($this->at(1)) - ->method('setSql') - ->with($this->equalTo('INSERT INTO "foo" ("bar", "boo") VALUES (?, NOW())')); - - $this->insert->into('foo') - ->values(['bar' => 'baz', 'boo' => new Expression('NOW()')]); - - $this->insert->prepareStatement($mockAdapter, $mockStatement); - - // with TableIdentifier - $this->insert = new Insert; - $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $mockDriver->expects($this->any())->method('getPrepareType')->will($this->returnValue('positional')); - $mockDriver->expects($this->any())->method('formatParameterName')->will($this->returnValue('?')); - $mockAdapter = $this->getMock('Zend\Db\Adapter\Adapter', null, [$mockDriver]); - - $mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $pContainer = new \Zend\Db\Adapter\ParameterContainer([]); - $mockStatement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($pContainer)); - $mockStatement->expects($this->at(1)) - ->method('setSql') - ->with($this->equalTo('INSERT INTO "sch"."foo" ("bar", "boo") VALUES (?, NOW())')); - - $this->insert->into(new TableIdentifier('foo', 'sch')) - ->values(['bar' => 'baz', 'boo' => new Expression('NOW()')]); - - $this->insert->prepareStatement($mockAdapter, $mockStatement); - } - - /** - * @covers Zend\Db\Sql\Insert::prepareStatement - */ - public function testPrepareStatementWithSelect() - { - $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $mockDriver->expects($this->any())->method('getPrepareType')->will($this->returnValue('positional')); - $mockDriver->expects($this->any())->method('formatParameterName')->will($this->returnValue('?')); - $mockAdapter = $this->getMock('Zend\Db\Adapter\Adapter', null, [$mockDriver]); - - $mockStatement = new \Zend\Db\Adapter\StatementContainer(); - - $select = new Select('bar'); - $this->insert - ->into('foo') - ->columns(['col1']) - ->select($select->where(['x'=>5])) - ->prepareStatement($mockAdapter, $mockStatement); - - $this->assertEquals( - 'INSERT INTO "foo" ("col1") SELECT "bar".* FROM "bar" WHERE "x" = ?', - $mockStatement->getSql() - ); - $parameters = $mockStatement->getParameterContainer()->getNamedArray(); - $this->assertSame(['subselect1where1'=>5], $parameters); - } - - /** - * @covers Zend\Db\Sql\Insert::getSqlString - */ - public function testGetSqlString() - { - $this->insert->into('foo') - ->values(['bar' => 'baz', 'boo' => new Expression('NOW()'), 'bam' => null]); - - $this->assertEquals('INSERT INTO "foo" ("bar", "boo", "bam") VALUES (\'baz\', NOW(), NULL)', $this->insert->getSqlString(new TrustingSql92Platform())); - - // with TableIdentifier - $this->insert = new Insert; - $this->insert->into(new TableIdentifier('foo', 'sch')) - ->values(['bar' => 'baz', 'boo' => new Expression('NOW()'), 'bam' => null]); - - $this->assertEquals('INSERT INTO "sch"."foo" ("bar", "boo", "bam") VALUES (\'baz\', NOW(), NULL)', $this->insert->getSqlString(new TrustingSql92Platform())); - - // with Select - $this->insert = new Insert; - $select = new Select(); - $this->insert->into('foo')->select($select->from('bar')); - - $this->assertEquals('INSERT INTO "foo" SELECT "bar".* FROM "bar"', $this->insert->getSqlString(new TrustingSql92Platform())); - - // with Select and columns - $this->insert->columns(['col1', 'col2']); - $this->assertEquals( - 'INSERT INTO "foo" ("col1", "col2") SELECT "bar".* FROM "bar"', - $this->insert->getSqlString(new TrustingSql92Platform()) - ); - } - - public function testGetSqlStringUsingColumnsAndValuesMethods() - { - // With columns() and values() - $this->insert - ->into('foo') - ->columns(['col1', 'col2', 'col3']) - ->values(['val1', 'val2', 'val3']); - $this->assertEquals( - 'INSERT INTO "foo" ("col1", "col2", "col3") VALUES (\'val1\', \'val2\', \'val3\')', - $this->insert->getSqlString(new TrustingSql92Platform()) - ); - } - - /** - * @covers Zend\Db\Sql\Insert::__set - */ - public function test__set() - { - $this->insert->foo = 'bar'; - $this->assertEquals(['foo'], $this->insert->getRawState('columns')); - $this->assertEquals(['bar'], $this->insert->getRawState('values')); - } - - /** - * @covers Zend\Db\Sql\Insert::__unset - */ - public function test__unset() - { - $this->insert->foo = 'bar'; - $this->assertEquals(['foo'], $this->insert->getRawState('columns')); - $this->assertEquals(['bar'], $this->insert->getRawState('values')); - unset($this->insert->foo); - $this->assertEquals([], $this->insert->getRawState('columns')); - $this->assertEquals([], $this->insert->getRawState('values')); - - $this->insert->foo = NULL; - $this->assertEquals(['foo'], $this->insert->getRawState('columns')); - $this->assertEquals([NULL], $this->insert->getRawState('values')); - - unset($this->insert->foo); - $this->assertEquals([], $this->insert->getRawState('columns')); - $this->assertEquals([], $this->insert->getRawState('values')); - } - - /** - * @covers Zend\Db\Sql\Insert::__isset - */ - public function test__isset() - { - $this->insert->foo = 'bar'; - $this->assertTrue(isset($this->insert->foo)); - - $this->insert->foo = NULL; - $this->assertTrue(isset($this->insert->foo)); - } - - /** - * @covers Zend\Db\Sql\Insert::__get - */ - public function test__get() - { - $this->insert->foo = 'bar'; - $this->assertEquals('bar', $this->insert->foo); - - $this->insert->foo = NULL; - $this->assertNull($this->insert->foo); - } - - /** - * @group ZF2-536 - */ - public function testValuesMerge() - { - $this->insert->into('foo') - ->values(['bar' => 'baz', 'boo' => new Expression('NOW()'), 'bam' => null]); - $this->insert->into('foo') - ->values(['qux' => 100], Insert::VALUES_MERGE); - - $this->assertEquals('INSERT INTO "foo" ("bar", "boo", "bam", "qux") VALUES (\'baz\', NOW(), NULL, \'100\')', $this->insert->getSqlString(new TrustingSql92Platform())); - } - - /** - * @coversNothing - */ - public function testSpecificationconstantsCouldBeOverridedByExtensionInPrepareStatement() - { - $replace = new Replace(); - - $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $mockDriver->expects($this->any())->method('getPrepareType')->will($this->returnValue('positional')); - $mockDriver->expects($this->any())->method('formatParameterName')->will($this->returnValue('?')); - $mockAdapter = $this->getMock('Zend\Db\Adapter\Adapter', null, [$mockDriver]); - - $mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $pContainer = new \Zend\Db\Adapter\ParameterContainer([]); - $mockStatement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($pContainer)); - $mockStatement->expects($this->at(1)) - ->method('setSql') - ->with($this->equalTo('REPLACE INTO "foo" ("bar", "boo") VALUES (?, NOW())')); - - $replace->into('foo') - ->values(['bar' => 'baz', 'boo' => new Expression('NOW()')]); - - $replace->prepareStatement($mockAdapter, $mockStatement); - - // with TableIdentifier - $replace = new Replace(); - - $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $mockDriver->expects($this->any())->method('getPrepareType')->will($this->returnValue('positional')); - $mockDriver->expects($this->any())->method('formatParameterName')->will($this->returnValue('?')); - $mockAdapter = $this->getMock('Zend\Db\Adapter\Adapter', null, [$mockDriver]); - - $mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $pContainer = new \Zend\Db\Adapter\ParameterContainer([]); - $mockStatement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($pContainer)); - $mockStatement->expects($this->at(1)) - ->method('setSql') - ->with($this->equalTo('REPLACE INTO "sch"."foo" ("bar", "boo") VALUES (?, NOW())')); - - $replace->into(new TableIdentifier('foo', 'sch')) - ->values(['bar' => 'baz', 'boo' => new Expression('NOW()')]); - - $replace->prepareStatement($mockAdapter, $mockStatement); - } - - /** - * @coversNothing - */ - public function testSpecificationconstantsCouldBeOverridedByExtensionInGetSqlString() - { - $replace = new Replace(); - $replace->into('foo') - ->values(['bar' => 'baz', 'boo' => new Expression('NOW()'), 'bam' => null]); - - $this->assertEquals('REPLACE INTO "foo" ("bar", "boo", "bam") VALUES (\'baz\', NOW(), NULL)', $replace->getSqlString(new TrustingSql92Platform())); - - // with TableIdentifier - $replace = new Replace(); - $replace->into(new TableIdentifier('foo', 'sch')) - ->values(['bar' => 'baz', 'boo' => new Expression('NOW()'), 'bam' => null]); - - $this->assertEquals('REPLACE INTO "sch"."foo" ("bar", "boo", "bam") VALUES (\'baz\', NOW(), NULL)', $replace->getSqlString(new TrustingSql92Platform())); - } -} - -class Replace extends Insert -{ - const SPECIFICATION_INSERT = 'replace'; - - protected $specifications = [ - self::SPECIFICATION_INSERT => 'REPLACE INTO %1$s (%2$s) VALUES (%3$s)', - self::SPECIFICATION_SELECT => 'REPLACE INTO %1$s %2$s %3$s', - ]; - - protected function processreplace(\Zend\Db\Adapter\Platform\PlatformInterface $platform, \Zend\Db\Adapter\Driver\DriverInterface $driver = null, \Zend\Db\Adapter\ParameterContainer $parameterContainer = null) - { - return parent::processInsert($platform, $driver, $parameterContainer); - } } diff --git a/test/Sql/Predicate/InTest.php b/test/Sql/Predicate/InTest.php index 30584f65a5..0d1f1a7967 100644 --- a/test/Sql/Predicate/InTest.php +++ b/test/Sql/Predicate/InTest.php @@ -12,6 +12,7 @@ use PHPUnit_Framework_TestCase as TestCase; use Zend\Db\Sql\Select; use Zend\Db\Sql\Predicate\In; +use Zend\Db\Sql\Combine; class InTest extends TestCase { @@ -80,6 +81,15 @@ public function testGetExpressionDataWithSubselect() [$in::TYPE_IDENTIFIER, $in::TYPE_VALUE] ]]; $this->assertEquals($expected, $in->getExpressionData()); + + $combine = new Combine; + $in = new In('foo', $combine); + $expected = [[ + '%s IN %s', + ['foo', $combine], + [$in::TYPE_IDENTIFIER, $in::TYPE_VALUE] + ]]; + $this->assertEquals($expected, $in->getExpressionData()); } public function testGetExpressionDataWithSubselectAndIdentifier() diff --git a/test/Sql/Predicate/PredicateTest.php b/test/Sql/Predicate/PredicateTest.php index 1e80e5f6c8..7fe353a2ab 100644 --- a/test/Sql/Predicate/PredicateTest.php +++ b/test/Sql/Predicate/PredicateTest.php @@ -13,6 +13,8 @@ use Zend\Db\Sql\Expression; use Zend\Db\Sql\Predicate\IsNull; use Zend\Db\Sql\Predicate\Predicate; +use Zend\Db\Sql\Predicate\Literal as predicateLiteral; +use Zend\Db\Sql\Predicate\Expression as predicateExpression; class PredicateTest extends TestCase { @@ -285,4 +287,127 @@ public function testLiteral() $predicate->getExpressionData() ); } + + /** + * moved from SelectTest + */ + public function testWhereArgument1IsAssociativeArrayContainingReplacementCharacter() + { + $where = new Predicate; + $predicates = $where + ->addPredicates(['foo > ?' => 5]) + ->getPredicates(); + $this->assertEquals(1, count($predicates)); + $this->assertInstanceOf('Zend\Db\Sql\Predicate\Expression', $predicates[0][1]); + $this->assertEquals(Predicate::OP_AND, $predicates[0][0]); + $this->assertEquals('foo > ?', $predicates[0][1]->getExpression()); + $this->assertEquals([5], $predicates[0][1]->getParameters()); + } + + /** + * moved from SelectTest + */ + public function testWhereArgument1IsAssociativeArrayNotContainingReplacementCharacter() + { + $where = new Predicate; + $where->addPredicates(['name' => 'Ralph', 'age' => 33]); + $predicates = $where->getPredicates(); + $this->assertEquals(2, count($predicates)); + + $this->assertInstanceOf('Zend\Db\Sql\Predicate\Operator', $predicates[0][1]); + $this->assertEquals(Predicate::OP_AND, $predicates[0][0]); + $this->assertEquals('name', $predicates[0][1]->getLeft()); + $this->assertEquals('Ralph', $predicates[0][1]->getRight()); + + $this->assertInstanceOf('Zend\Db\Sql\Predicate\Operator', $predicates[1][1]); + $this->assertEquals(Predicate::OP_AND, $predicates[1][0]); + $this->assertEquals('age', $predicates[1][1]->getLeft()); + $this->assertEquals(33, $predicates[1][1]->getRight()); + + $where = new Predicate; + $predicates = $where + ->addPredicates(['x = y']) + ->getPredicates(); + $this->assertInstanceOf('Zend\Db\Sql\Predicate\Literal', $predicates[0][1]); + } + + /** + * moved from SelectTest + */ + public function testWhereArgument1IsAssociativeArrayIsPredicate() + { + $this->setExpectedException('Zend\Db\Sql\Exception\InvalidArgumentException', 'Using Predicate must not use string keys'); + $where = new Predicate; + $where->addPredicates([ + 'name' => new predicateLiteral("name = 'Ralph'"), + 'age' => new predicateExpression('age = ?', 33), + ]); + } + + /** + * moved from SelectTest + */ + public function testWhereArgument1IsIndexedArray() + { + $where = new Predicate; + $predicates = $where + ->addPredicates(['name = "Ralph"']) + ->getPredicates(); + + $this->assertEquals(1, count($predicates)); + $this->assertInstanceOf('Zend\Db\Sql\Predicate\Literal', $predicates[0][1]); + $this->assertEquals(Predicate::OP_AND, $predicates[0][0]); + $this->assertEquals('name = "Ralph"', $predicates[0][1]->getLiteral()); + } + + /** + * moved from SelectTest + */ + public function testWhereArgument1IsIndexedArrayArgument2IsOr() + { + $where = new Predicate; + $predicates = $where + ->addPredicates(['name = "Ralph"'], Predicate::OP_OR) + ->getPredicates(); + + $this->assertEquals(1, count($predicates)); + $this->assertInstanceOf('Zend\Db\Sql\Predicate\Literal', $predicates[0][1]); + $this->assertEquals(Predicate::OP_OR, $predicates[0][0]); + $this->assertEquals('name = "Ralph"', $predicates[0][1]->getLiteral()); + } + + /** + * moved from SelectTest + */ + public function testWhereArgument1IsClosure() + { + $where = new Predicate; + $test = $this; + $where->addPredicates(function ($what) use ($test, $where) { + $test->assertSame($where, $what); + }); + } + + /** + * moved from SelectTest + */ + public function testWhereArgument1IsString() + { + $where = new Predicate; + $predicates = $where + ->addPredicates('x = ?') + ->getPredicates(); + + $this->assertEquals(1, count($predicates)); + $this->assertInstanceOf('Zend\Db\Sql\Predicate\Expression', $predicates[0][1]); + $this->assertEquals(Predicate::OP_AND, $predicates[0][0]); + $this->assertEquals('x = ?', $predicates[0][1]->getExpression()); + + $where = new Predicate; + $predicates = $where + ->addPredicates('x = y') + ->getPredicates(); + + $this->assertInstanceOf('Zend\Db\Sql\Predicate\Literal', $predicates[0][1]); + } } diff --git a/test/Sql/SelectTest.php b/test/Sql/SelectTest.php index d90585f7fe..dfaafb1d39 100644 --- a/test/Sql/SelectTest.php +++ b/test/Sql/SelectTest.php @@ -9,16 +9,10 @@ namespace ZendTest\Db\Sql; -use ReflectionObject; use Zend\Db\Sql\Select; -use Zend\Db\Sql\Expression; use Zend\Db\Sql\Where; use Zend\Db\Sql\Having; use Zend\Db\Sql\Predicate; -use Zend\Db\Sql\TableIdentifier; -use Zend\Db\Adapter\ParameterContainer; -use Zend\Db\Adapter\Platform\Sql92; -use ZendTest\Db\TestAsset\TrustingSql92Platform; class SelectTest extends \PHPUnit_Framework_TestCase { @@ -28,52 +22,48 @@ class SelectTest extends \PHPUnit_Framework_TestCase public function testConstruct() { $select = new Select('foo'); - $this->assertEquals('foo', $select->getRawState('table')); + $this->assertEquals('foo', $select->table); } - /** - * @testdox unit test: Test from() returns Select object (is chainable) - * @covers Zend\Db\Sql\Select::from - */ - public function testFrom() + public function testMethodsReturnSelf() { $select = new Select; - $return = $select->from('foo', 'bar'); - $this->assertSame($select, $return); - - return $return; - } - - /** - * @testdox unit test: Test getRawState() returns information populated via from() - * @covers Zend\Db\Sql\Select::getRawState - * @depends testFrom - */ - public function testGetRawStateViaFrom(Select $select) - { - $this->assertEquals('foo', $select->getRawState('table')); - } - - /** - * @testdox unit test: Test quantifier() returns Select object (is chainable) - * @covers Zend\Db\Sql\Select::quantifier - */ - public function testQuantifier() - { - $select = new Select; - $return = $select->quantifier($select::QUANTIFIER_DISTINCT); - $this->assertSame($select, $return); - return $return; + $this->assertSame($select, $select->from('foo', 'bar')); + $this->assertSame($select, $select->quantifier($select::QUANTIFIER_DISTINCT)); + $this->assertSame($select, $select->columns(['foo', 'bar'])); + $this->assertSame($select, $select->join('foo', 'x = y', Select::SQL_STAR, Select::JOIN_INNER)); + $this->assertSame($select, $select->where('x = y')); + $this->assertSame($select, $select->limit(5)); + $this->assertSame($select, $select->offset(10)); + $this->assertSame($select, $select->group(['col1', 'col2'])); + $this->assertSame($select, $select->having(['x = ?' => 5])); + return $select; } /** - * @testdox unit test: Test getRawState() returns information populated via quantifier() - * @covers Zend\Db\Sql\Select::getRawState - * @depends testQuantifier + * @testdox unit test: Test __get() returns expected objects magically + * @covers Zend\Db\Sql\Select::__get + * @depends testMethodsReturnSelf */ - public function testGetRawStateViaQuantifier(Select $select) + public function testMagicAccessor(Select $select) { - $this->assertEquals(Select::QUANTIFIER_DISTINCT, $select->getRawState('quantifier')); + $this->assertInstanceOf('Zend\Db\Sql\Where', $select->where); + $this->assertEquals(['foo', 'bar'], $select->columns); + $this->assertEquals('foo', $select->table); + $this->assertEquals(['col1', 'col2'], $select->group); + $this->assertEquals( + [[ + 'name' => 'foo', + 'on' => 'x = y', + 'columns' => [Select::SQL_STAR], + 'type' => Select::JOIN_INNER + ]], + $select->joins->getJoins() + ); + $this->assertInstanceOf('Zend\Db\Sql\Having', $select->having); + $this->assertEquals(5, $select->limit); + $this->assertEquals(10, $select->offset); + $this->assertEquals(Select::QUANTIFIER_DISTINCT, $select->quantifier); } /** @@ -87,59 +77,11 @@ public function testQuantifierParameterExpressionInterface() $select->quantifier($expr); $this->assertSame( $expr, - $select->getRawState(Select::QUANTIFIER) + $select->quantifier ); } /** - * @testdox unit test: Test columns() returns Select object (is chainable) - * @covers Zend\Db\Sql\Select::columns - */ - public function testColumns() - { - $select = new Select; - $return = $select->columns(['foo', 'bar']); - $this->assertSame($select, $return); - - return $select; - } - - /** - * @testdox unit test: Test isTableReadOnly() returns correct state for read only - * @covers Zend\Db\Sql\Select::isTableReadOnly - */ - public function testIsTableReadOnly() - { - $select = new Select('foo'); - $this->assertTrue($select->isTableReadOnly()); - - $select = new Select; - $this->assertFalse($select->isTableReadOnly()); - } - - /** - * @testdox unit test: Test getRawState() returns information populated via columns() - * @covers Zend\Db\Sql\Select::getRawState - * @depends testColumns - */ - public function testGetRawStateViaColumns(Select $select) - { - $this->assertEquals(['foo', 'bar'], $select->getRawState('columns')); - } - - /** - * @testdox unit test: Test join() returns same Select object (is chainable) - * @covers Zend\Db\Sql\Select::join - */ - public function testJoin() - { - $select = new Select; - $return = $select->join('foo', 'x = y', Select::SQL_STAR, Select::JOIN_INNER); - $this->assertSame($select, $return); - - return $return; - } - /** * @testdox unit test: Test join() exception with bad join * @covers Zend\Db\Sql\Select::join @@ -151,203 +93,6 @@ public function testBadJoin() $select->join(['foo'], 'x = y', Select::SQL_STAR, Select::JOIN_INNER); } - /** - * @testdox unit test: Test processJoins() exception with bad join name - * @covers Zend\Db\Sql\Select::processJoins - */ - public function testBadJoinName() - { - $mockExpression = $this->getMock('Zend\Db\Sql\ExpressionInterface', [], ['bar']); - $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $mockDriver->expects($this->any())->method('formatParameterName')->will($this->returnValue('?')); - $parameterContainer = new ParameterContainer(); - - $select = new Select; - $select->join(['foo' => $mockExpression], 'x = y', Select::SQL_STAR, Select::JOIN_INNER); - - $sr = new ReflectionObject($select); - - $mr = $sr->getMethod('processJoins'); - - $mr->setAccessible(true); - - $this->setExpectedException('Zend\Db\Sql\Exception\InvalidArgumentException'); - - $mr->invokeArgs($select, [new Sql92, $mockDriver, $parameterContainer]); - } - - /** - * @testdox unit test: Test getRawState() returns information populated via join() - * @covers Zend\Db\Sql\Select::getRawState - * @depends testJoin - */ - public function testGetRawStateViaJoin(Select $select) - { - $this->assertEquals( - [[ - 'name' => 'foo', - 'on' => 'x = y', - 'columns' => [Select::SQL_STAR], - 'type' => Select::JOIN_INNER - ]], - $select->getRawState('joins')->getJoins() - ); - } - - /** - * @testdox unit test: Test where() returns Select object (is chainable) - * @covers Zend\Db\Sql\Select::where - */ - public function testWhereReturnsSameSelectObject() - { - $select = new Select; - $this->assertSame($select, $select->where('x = y')); - } - - /** - * @testdox unit test: Test where() will accept a string for the predicate to create an expression predicate - * @covers Zend\Db\Sql\Select::where - */ - public function testWhereArgument1IsString() - { - $select = new Select; - $select->where('x = ?'); - - /** @var $where Where */ - $where = $select->getRawState('where'); - $predicates = $where->getPredicates(); - $this->assertEquals(1, count($predicates)); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\Expression', $predicates[0][1]); - $this->assertEquals(Where::OP_AND, $predicates[0][0]); - $this->assertEquals('x = ?', $predicates[0][1]->getExpression()); - - $select = new Select; - $select->where('x = y'); - - /** @var $where Where */ - $where = $select->getRawState('where'); - $predicates = $where->getPredicates(); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\Literal', $predicates[0][1]); - } - - /** - * @testdox unit test: Test where() will accept an array with a string key (containing ?) used as an expression with placeholder - * @covers Zend\Db\Sql\Select::where - */ - public function testWhereArgument1IsAssociativeArrayContainingReplacementCharacter() - { - $select = new Select; - $select->where(['foo > ?' => 5]); - - /** @var $where Where */ - $where = $select->getRawState('where'); - $predicates = $where->getPredicates(); - $this->assertEquals(1, count($predicates)); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\Expression', $predicates[0][1]); - $this->assertEquals(Where::OP_AND, $predicates[0][0]); - $this->assertEquals('foo > ?', $predicates[0][1]->getExpression()); - $this->assertEquals([5], $predicates[0][1]->getParameters()); - } - - /** - * @testdox unit test: Test where() will accept any array with string key (without ?) to be used as Operator predicate - * @covers Zend\Db\Sql\Select::where - */ - public function testWhereArgument1IsAssociativeArrayNotContainingReplacementCharacter() - { - $select = new Select; - $select->where(['name' => 'Ralph', 'age' => 33]); - - /** @var $where Where */ - $where = $select->getRawState('where'); - $predicates = $where->getPredicates(); - $this->assertEquals(2, count($predicates)); - - $this->assertInstanceOf('Zend\Db\Sql\Predicate\Operator', $predicates[0][1]); - $this->assertEquals(Where::OP_AND, $predicates[0][0]); - $this->assertEquals('name', $predicates[0][1]->getLeft()); - $this->assertEquals('Ralph', $predicates[0][1]->getRight()); - - $this->assertInstanceOf('Zend\Db\Sql\Predicate\Operator', $predicates[1][1]); - $this->assertEquals(Where::OP_AND, $predicates[1][0]); - $this->assertEquals('age', $predicates[1][1]->getLeft()); - $this->assertEquals(33, $predicates[1][1]->getRight()); - - $select = new Select; - $select->where(['x = y']); - - $where = $select->getRawState('where'); - $predicates = $where->getPredicates(); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\Literal', $predicates[0][1]); - } - - /** - * @testdox unit test: Test where() will accept any array with string key (without ?) with Predicate throw Exception - * @covers Zend\Db\Sql\Select::where - */ - public function testWhereArgument1IsAssociativeArrayIsPredicate() - { - $select = new Select; - $where = [ - 'name' => new Predicate\Literal("name = 'Ralph'"), - 'age' => new Predicate\Expression('age = ?', 33), - ]; - $this->setExpectedException('Zend\Db\Sql\Exception\InvalidArgumentException', 'Using Predicate must not use string keys'); - $select->where($where); - } - - /** - * @testdox unit test: Test where() will accept an indexed array to be used by joining string expressions - * @covers Zend\Db\Sql\Select::where - */ - public function testWhereArgument1IsIndexedArray() - { - $select = new Select; - $select->where(['name = "Ralph"']); - - /** @var $where Where */ - $where = $select->getRawState('where'); - $predicates = $where->getPredicates(); - $this->assertEquals(1, count($predicates)); - - $this->assertInstanceOf('Zend\Db\Sql\Predicate\Literal', $predicates[0][1]); - $this->assertEquals(Where::OP_AND, $predicates[0][0]); - $this->assertEquals('name = "Ralph"', $predicates[0][1]->getLiteral()); - } - - /** - * @testdox unit test: Test where() will accept an indexed array to be used by joining string expressions, combined by OR - * @covers Zend\Db\Sql\Select::where - */ - public function testWhereArgument1IsIndexedArrayArgument2IsOr() - { - $select = new Select; - $select->where(['name = "Ralph"'], Where::OP_OR); - - /** @var $where Where */ - $where = $select->getRawState('where'); - $predicates = $where->getPredicates(); - $this->assertEquals(1, count($predicates)); - - $this->assertInstanceOf('Zend\Db\Sql\Predicate\Literal', $predicates[0][1]); - $this->assertEquals(Where::OP_OR, $predicates[0][0]); - $this->assertEquals('name = "Ralph"', $predicates[0][1]->getLiteral()); - } - - /** - * @testdox unit test: Test where() will accept a closure to be executed with Where object as argument - * @covers Zend\Db\Sql\Select::where - */ - public function testWhereArgument1IsClosure() - { - $select = new Select; - $where = $select->getRawState('where'); - - $select->where(function ($what) use ($where) { - $this->assertSame($where, $what); - }); - } - /** * @testdox unit test: Test where() will accept any Predicate object as-is * @covers Zend\Db\Sql\Select::where @@ -361,12 +106,9 @@ public function testWhereArgument1IsPredicate() ]); $select->where($predicate); - /** @var $where Where */ - $where = $select->getRawState('where'); - $predicates = $where->getPredicates(); + $predicates = $select->where->getPredicates(); $this->assertSame($predicate, $predicates[0][1]); } - /** * @testdox unit test: Test where() will accept a Where object * @covers Zend\Db\Sql\Select::where @@ -375,7 +117,7 @@ public function testWhereArgument1IsWhereObject() { $select = new Select; $select->where($newWhere = new Where); - $this->assertSame($newWhere, $select->getRawState('where')); + $this->assertSame($newWhere, $select->where); } /** @@ -388,61 +130,17 @@ public function testOrder() $select = new Select; $return = $select->order('id DESC'); $this->assertSame($select, $return); // test fluent interface - $this->assertEquals(['id DESC'], $select->getRawState('order')); + $this->assertEquals(['id DESC'], $select->order); $select = new Select; $select->order('id DESC') ->order('name ASC, age DESC'); - $this->assertEquals(['id DESC', 'name ASC', 'age DESC'], $select->getRawState('order')); + $this->assertEquals(['id DESC', 'name ASC', 'age DESC'], $select->order); $select = new Select; $select->order(['name ASC', 'age DESC']); - $this->assertEquals(['name ASC', 'age DESC'], $select->getRawState('order')); - - $select = new Select; - $select->order(new Expression('RAND()')); - $sr = new ReflectionObject($select); - $method = $sr->getMethod('processOrder'); - $method->setAccessible(true); - $this->assertEquals( - [[['RAND()']]], - $method->invokeArgs($select, [new TrustingSql92Platform()]) - ); - - $select = new Select; - $select->order( - $this->getMock('Zend\Db\Sql\Predicate\Operator', null, ['rating', '<', '10']) - ); - $sr = new ReflectionObject($select); - $method = $sr->getMethod('processOrder'); - $method->setAccessible(true); - $this->assertEquals( - [[['"rating" < \'10\'']]], - $method->invokeArgs($select, [new TrustingSql92Platform()]) - ); + $this->assertEquals(['name ASC', 'age DESC'], $select->order); } - - /** - * @testdox: unit test: test limit() - * @covers Zend\Db\Sql\Select::limit - */ - public function testLimit() - { - $select = new Select; - $this->assertSame($select, $select->limit(5)); - return $select; - } - - /** - * @testdox: unit test: Test getRawState() returns information populated via limit() - * @covers Zend\Db\Sql\Select::getRawState - * @depends testLimit - */ - public function testGetRawStateViaLimit(Select $select) - { - $this->assertEquals(5, $select->getRawState($select::LIMIT)); - } - /** * @testdox: unit test: test limit() throws execption when invalid parameter passed * @covers Zend\Db\Sql\Select::limit @@ -454,27 +152,6 @@ public function testLimitExceptionOnInvalidParameter() $select->limit('foobar'); } - /** - * @testdox: unit test: test offset() - * @covers Zend\Db\Sql\Select::offset - */ - public function testOffset() - { - $select = new Select; - $this->assertSame($select, $select->offset(10)); - return $select; - } - - /** - * @testdox: unit test: Test getRawState() returns information populated via offset() - * @covers Zend\Db\Sql\Select::getRawState - * @depends testOffset - */ - public function testGetRawStateViaOffset(Select $select) - { - $this->assertEquals(10, $select->getRawState($select::OFFSET)); - } - /** * @testdox: unit test: test offset() throws exception when invalid parameter passed * @covers Zend\Db\Sql\Select::offset @@ -486,46 +163,6 @@ public function testOffsetExceptionOnInvalidParameter() $select->offset('foobar'); } - - /** - * @testdox unit test: Test group() returns same Select object (is chainable) - * @covers Zend\Db\Sql\Select::group - */ - public function testGroup() - { - $select = new Select; - $return = $select->group(['col1', 'col2']); - $this->assertSame($select, $return); - - return $return; - } - - /** - * @testdox unit test: Test getRawState() returns information populated via group() - * @covers Zend\Db\Sql\Select::getRawState - * @depends testGroup - */ - public function testGetRawStateViaGroup(Select $select) - { - $this->assertEquals( - ['col1', 'col2'], - $select->getRawState('group') - ); - } - - /** - * @testdox unit test: Test having() returns same Select object (is chainable) - * @covers Zend\Db\Sql\Select::having - */ - public function testHaving() - { - $select = new Select; - $return = $select->having(['x = ?' => 5]); - $this->assertSame($select, $return); - - return $return; - } - /** * @testdox unit test: Test having() returns same Select object (is chainable) * @covers Zend\Db\Sql\Select::having @@ -536,176 +173,43 @@ public function testHavingArgument1IsHavingObject() $having = new Having(); $return = $select->having($having); $this->assertSame($select, $return); - $this->assertSame($having, $select->getRawState('having')); + $this->assertSame($having, $select->having); return $return; } - /** - * @testdox unit test: Test getRawState() returns information populated via having() - * @covers Zend\Db\Sql\Select::getRawState - * @depends testHaving - */ - public function testGetRawStateViaHaving(Select $select) - { - $this->assertInstanceOf('Zend\Db\Sql\Having', $select->getRawState('having')); - } - - /** - * @testdox unit test: Test combine() returns same Select object (is chainable) - * @covers Zend\Db\Sql\Select::combine - */ - public function testCombine() - { - $select = new Select; - $combine = new Select; - $return = $select->combine($combine, $select::COMBINE_UNION, 'ALL'); - $this->assertSame($select, $return); - - return $return; - } - - /** - * @testdox unit test: Test getRawState() returns information populated via combine() - * @covers Zend\Db\Sql\Select::getRawState - * @depends testCombine - */ - public function testGetRawStateViaCombine(Select $select) - { - $state = $select->getRawState('combine'); - $this->assertInstanceOf('Zend\Db\Sql\Select', $state['select']); - $this->assertNotSame($select, $state['select']); - $this->assertEquals(Select::COMBINE_UNION, $state['type']); - $this->assertEquals('ALL', $state['modifier']); - } - /** * @testdox unit test: Test reset() resets internal stat of Select object, based on input - * @covers Zend\Db\Sql\Select::reset + * @covers Zend\Db\Sql\Select::__unset */ - public function testReset() + public function testMagicUnset() { $select = new Select; - // table - $select->from('foo'); - $this->assertEquals('foo', $select->getRawState(Select::TABLE)); - $select->reset(Select::TABLE); - $this->assertNull($select->getRawState(Select::TABLE)); - - // columns - $select->columns(['foo']); - $this->assertEquals(['foo'], $select->getRawState(Select::COLUMNS)); - $select->reset(Select::COLUMNS); - $this->assertEmpty($select->getRawState(Select::COLUMNS)); - - // joins - $select->join('foo', 'id = boo'); - $this->assertEquals([['name' => 'foo', 'on' => 'id = boo', 'columns' => ['*'], 'type' => 'inner']], $select->getRawState(Select::JOINS)->getJoins()); - $select->reset(Select::JOINS); - $this->assertEmpty($select->getRawState(Select::JOINS)->getJoins()); - - // where - $select->where('foo = bar'); - $where1 = $select->getRawState(Select::WHERE); - $this->assertEquals(1, $where1->count()); - $select->reset(Select::WHERE); - $where2 = $select->getRawState(Select::WHERE); - $this->assertEquals(0, $where2->count()); - $this->assertNotSame($where1, $where2); - - // group - $select->group(['foo']); - $this->assertEquals(['foo'], $select->getRawState(Select::GROUP)); - $select->reset(Select::GROUP); - $this->assertEmpty($select->getRawState(Select::GROUP)); - - // having - $select->having('foo = bar'); - $having1 = $select->getRawState(Select::HAVING); - $this->assertEquals(1, $having1->count()); - $select->reset(Select::HAVING); - $having2 = $select->getRawState(Select::HAVING); - $this->assertEquals(0, $having2->count()); - $this->assertNotSame($having1, $having2); - - // limit - $select->limit(5); - $this->assertEquals(5, $select->getRawState(Select::LIMIT)); - $select->reset(Select::LIMIT); - $this->assertNull($select->getRawState(Select::LIMIT)); - - // offset - $select->offset(10); - $this->assertEquals(10, $select->getRawState(Select::OFFSET)); - $select->reset(Select::OFFSET); - $this->assertNull($select->getRawState(Select::OFFSET)); - - // order - $select->order('foo asc'); - $this->assertEquals(['foo asc'], $select->getRawState(Select::ORDER)); - $select->reset(Select::ORDER); - $this->assertEmpty($select->getRawState(Select::ORDER)); - } - - /** - * @testdox unit test: Test prepareStatement() will produce expected sql and parameters based on a variety of provided arguments [uses data provider] - * @covers Zend\Db\Sql\Select::prepareStatement - * @dataProvider providerData - */ - public function testPrepareStatement(Select $select, $expectedSqlString, $expectedParameters, $unused1, $unused2, $useNamedParameters = false) - { - $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $mockDriver->expects($this->any())->method('formatParameterName')->will($this->returnCallback( - function ($name) use ($useNamedParameters) { - return (($useNamedParameters) ? ':' . $name : '?'); - } - )); - $mockAdapter = $this->getMock('Zend\Db\Adapter\Adapter', null, [$mockDriver]); - - $parameterContainer = new ParameterContainer(); - - $mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $mockStatement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($parameterContainer)); - $mockStatement->expects($this->any())->method('setSql')->with($this->equalTo($expectedSqlString)); - - $select->prepareStatement($mockAdapter, $mockStatement); - - if ($expectedParameters) { - $this->assertEquals($expectedParameters, $parameterContainer->getNamedArray()); + $originalValues = []; + $clonedSelect = clone $select; + foreach (array_flip($this->readAttribute($clonedSelect, '__getProperties')) as $name) { + $originalValues[$name] = $clonedSelect->$name; } - } - /** - * @group ZF2-5192 - */ - public function testSelectUsingTableIdentifierWithEmptyScheme() - { - $select = new Select; - $select->from(new TableIdentifier('foo')); - $select->join(new TableIdentifier('bar'), 'foo.id = bar.fooid'); - - $this->assertEquals('SELECT "foo".*, "bar".* FROM "foo" INNER JOIN "bar" ON "foo"."id" = "bar"."fooid"', $select->getSqlString(new TrustingSql92Platform())); - } - - /** - * @testdox unit test: Test getSqlString() will produce expected sql and parameters based on a variety of provided arguments [uses data provider] - * @covers Zend\Db\Sql\Select::getSqlString - * @dataProvider providerData - */ - public function testGetSqlString(Select $select, $unused, $unused2, $expectedSqlString) - { - $this->assertEquals($expectedSqlString, $select->getSqlString(new TrustingSql92Platform())); - } - - /** - * @testdox unit test: Test __get() returns expected objects magically - * @covers Zend\Db\Sql\Select::__get - */ - public function testMagicAccessor() - { - $select = new Select; - $this->assertInstanceOf('Zend\Db\Sql\Where', $select->where); + $select + ->from('foo', 'bar') + ->quantifier(Select::QUANTIFIER_DISTINCT) + ->columns(['foo', 'bar'], false) + ->join('foo', 'x = y', Select::SQL_STAR, Select::JOIN_INNER) + ->where('x = y') + ->limit(5) + ->offset(10) + ->group(['col1', 'col2']) + ->having(['x = ?' => 5]) + ->order(Select::ORDER_ASCENDING) + ->combine(new Select('xxx')); + + foreach ($originalValues as $name => $value) { + $this->assertNotEquals($value, $select->$name, 'notEqual : ' . $name); + unset($select->$name); + $this->assertEquals($value, $select->$name, 'Equal : ' . $name); + } } /** @@ -725,676 +229,4 @@ public function testCloning() $this->assertEquals(0, $select->having->count()); $this->assertEquals(1, $select1->having->count()); } - - /** - * @testdox unit test: Text process*() methods will return proper array when internally called, part of extension API - * @dataProvider providerData - * @covers Zend\Db\Sql\Select::processSelect - * @covers Zend\Db\Sql\Select::processJoins - * @covers Zend\Db\Sql\Select::processWhere - * @covers Zend\Db\Sql\Select::processGroup - * @covers Zend\Db\Sql\Select::processHaving - * @covers Zend\Db\Sql\Select::processOrder - * @covers Zend\Db\Sql\Select::processLimit - * @covers Zend\Db\Sql\Select::processOffset - * @covers Zend\Db\Sql\Select::processCombine - */ - public function testProcessMethods(Select $select, $unused, $unused2, $unused3, $internalTests) - { - if (!$internalTests) { - return; - } - - $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $mockDriver->expects($this->any())->method('formatParameterName')->will($this->returnValue('?')); - $parameterContainer = new ParameterContainer(); - - $sr = new ReflectionObject($select); - - foreach ($internalTests as $method => $expected) { - $mr = $sr->getMethod($method); - $mr->setAccessible(true); - $return = $mr->invokeArgs($select, [new Sql92, $mockDriver, $parameterContainer]); - $this->assertEquals($expected, $return); - } - } - - public function providerData() - { - // basic table - $select0 = new Select; - $select0->from('foo'); - $sqlPrep0 = // same - $sqlStr0 = 'SELECT "foo".* FROM "foo"'; - $internalTests0 = [ - 'processSelect' => [[['"foo".*']], '"foo"'] - ]; - - // table as TableIdentifier - $select1 = new Select; - $select1->from(new TableIdentifier('foo', 'bar')); - $sqlPrep1 = // same - $sqlStr1 = 'SELECT "bar"."foo".* FROM "bar"."foo"'; - $internalTests1 = [ - 'processSelect' => [[['"bar"."foo".*']], '"bar"."foo"'] - ]; - - // table with alias - $select2 = new Select; - $select2->from(['f' => 'foo']); - $sqlPrep2 = // same - $sqlStr2 = 'SELECT "f".* FROM "foo" AS "f"'; - $internalTests2 = [ - 'processSelect' => [[['"f".*']], '"foo" AS "f"'] - ]; - - // table with alias with table as TableIdentifier - $select3 = new Select; - $select3->from(['f' => new TableIdentifier('foo')]); - $sqlPrep3 = // same - $sqlStr3 = 'SELECT "f".* FROM "foo" AS "f"'; - $internalTests3 = [ - 'processSelect' => [[['"f".*']], '"foo" AS "f"'] - ]; - - // columns - $select4 = new Select; - $select4->from('foo')->columns(['bar', 'baz']); - $sqlPrep4 = // same - $sqlStr4 = 'SELECT "foo"."bar" AS "bar", "foo"."baz" AS "baz" FROM "foo"'; - $internalTests4 = [ - 'processSelect' => [[['"foo"."bar"', '"bar"'], ['"foo"."baz"', '"baz"']], '"foo"'] - ]; - - // columns with AS associative array - $select5 = new Select; - $select5->from('foo')->columns(['bar' => 'baz']); - $sqlPrep5 = // same - $sqlStr5 = 'SELECT "foo"."baz" AS "bar" FROM "foo"'; - $internalTests5 = [ - 'processSelect' => [[['"foo"."baz"', '"bar"']], '"foo"'] - ]; - - // columns with AS associative array mixed - $select6 = new Select; - $select6->from('foo')->columns(['bar' => 'baz', 'bam']); - $sqlPrep6 = // same - $sqlStr6 = 'SELECT "foo"."baz" AS "bar", "foo"."bam" AS "bam" FROM "foo"'; - $internalTests6 = [ - 'processSelect' => [[['"foo"."baz"', '"bar"'], ['"foo"."bam"', '"bam"'] ], '"foo"'] - ]; - - // columns where value is Expression, with AS - $select7 = new Select; - $select7->from('foo')->columns(['bar' => new Expression('COUNT(some_column)')]); - $sqlPrep7 = // same - $sqlStr7 = 'SELECT COUNT(some_column) AS "bar" FROM "foo"'; - $internalTests7 = [ - 'processSelect' => [[['COUNT(some_column)', '"bar"']], '"foo"'] - ]; - - // columns where value is Expression - $select8 = new Select; - $select8->from('foo')->columns([new Expression('COUNT(some_column) AS bar')]); - $sqlPrep8 = // same - $sqlStr8 = 'SELECT COUNT(some_column) AS bar FROM "foo"'; - $internalTests8 = [ - 'processSelect' => [[['COUNT(some_column) AS bar']], '"foo"'] - ]; - - // columns where value is Expression with parameters - $select9 = new Select; - $select9->from('foo')->columns( - [ - new Expression( - '(COUNT(?) + ?) AS ?', - ['some_column', 5, 'bar'], - [Expression::TYPE_IDENTIFIER, Expression::TYPE_VALUE, Expression::TYPE_IDENTIFIER] - ) - ] - ); - $sqlPrep9 = 'SELECT (COUNT("some_column") + ?) AS "bar" FROM "foo"'; - $sqlStr9 = 'SELECT (COUNT("some_column") + \'5\') AS "bar" FROM "foo"'; - $params9 = ['column1' => 5]; - $internalTests9 = [ - 'processSelect' => [[['(COUNT("some_column") + ?) AS "bar"']], '"foo"'] - ]; - - // joins (plain) - $select10 = new Select; - $select10->from('foo')->join('zac', 'm = n'); - $sqlPrep10 = // same - $sqlStr10 = 'SELECT "foo".*, "zac".* FROM "foo" INNER JOIN "zac" ON "m" = "n"'; - $internalTests10 = [ - 'processSelect' => [[['"foo".*'], ['"zac".*']], '"foo"'], - 'processJoins' => [[['INNER', '"zac"', '"m" = "n"']]] - ]; - - // join with columns - $select11 = new Select; - $select11->from('foo')->join('zac', 'm = n', ['bar', 'baz']); - $sqlPrep11 = // same - $sqlStr11 = 'SELECT "foo".*, "zac"."bar" AS "bar", "zac"."baz" AS "baz" FROM "foo" INNER JOIN "zac" ON "m" = "n"'; - $internalTests11 = [ - 'processSelect' => [[['"foo".*'], ['"zac"."bar"', '"bar"'], ['"zac"."baz"', '"baz"']], '"foo"'], - 'processJoins' => [[['INNER', '"zac"', '"m" = "n"']]] - ]; - - // join with alternate type - $select12 = new Select; - $select12->from('foo')->join('zac', 'm = n', ['bar', 'baz'], Select::JOIN_OUTER); - $sqlPrep12 = // same - $sqlStr12 = 'SELECT "foo".*, "zac"."bar" AS "bar", "zac"."baz" AS "baz" FROM "foo" OUTER JOIN "zac" ON "m" = "n"'; - $internalTests12 = [ - 'processSelect' => [[['"foo".*'], ['"zac"."bar"', '"bar"'], ['"zac"."baz"', '"baz"']], '"foo"'], - 'processJoins' => [[['OUTER', '"zac"', '"m" = "n"']]] - ]; - - // join with column aliases - $select13 = new Select; - $select13->from('foo')->join('zac', 'm = n', ['BAR' => 'bar', 'BAZ' => 'baz']); - $sqlPrep13 = // same - $sqlStr13 = 'SELECT "foo".*, "zac"."bar" AS "BAR", "zac"."baz" AS "BAZ" FROM "foo" INNER JOIN "zac" ON "m" = "n"'; - $internalTests13 = [ - 'processSelect' => [[['"foo".*'], ['"zac"."bar"', '"BAR"'], ['"zac"."baz"', '"BAZ"']], '"foo"'], - 'processJoins' => [[['INNER', '"zac"', '"m" = "n"']]] - ]; - - // join with table aliases - $select14 = new Select; - $select14->from('foo')->join(['b' => 'bar'], 'b.foo_id = foo.foo_id'); - $sqlPrep14 = // same - $sqlStr14 = 'SELECT "foo".*, "b".* FROM "foo" INNER JOIN "bar" AS "b" ON "b"."foo_id" = "foo"."foo_id"'; - $internalTests14 = [ - 'processSelect' => [[['"foo".*'], ['"b".*']], '"foo"'], - 'processJoins' => [[['INNER', '"bar" AS "b"', '"b"."foo_id" = "foo"."foo_id"']]] - ]; - - // where (simple string) - $select15 = new Select; - $select15->from('foo')->where('x = 5'); - $sqlPrep15 = // same - $sqlStr15 = 'SELECT "foo".* FROM "foo" WHERE x = 5'; - $internalTests15 = [ - 'processSelect' => [[['"foo".*']], '"foo"'], - 'processWhere' => ['x = 5'] - ]; - - // where (returning parameters) - $select16 = new Select; - $select16->from('foo')->where(['x = ?' => 5]); - $sqlPrep16 = 'SELECT "foo".* FROM "foo" WHERE x = ?'; - $sqlStr16 = 'SELECT "foo".* FROM "foo" WHERE x = \'5\''; - $params16 = ['where1' => 5]; - $internalTests16 = [ - 'processSelect' => [[['"foo".*']], '"foo"'], - 'processWhere' => ['x = ?'] - ]; - - // group - $select17 = new Select; - $select17->from('foo')->group(['col1', 'col2']); - $sqlPrep17 = // same - $sqlStr17 = 'SELECT "foo".* FROM "foo" GROUP BY "col1", "col2"'; - $internalTests17 = [ - 'processSelect' => [[['"foo".*']], '"foo"'], - 'processGroup' => [['"col1"', '"col2"']] - ]; - - $select18 = new Select; - $select18->from('foo')->group('col1')->group('col2'); - $sqlPrep18 = // same - $sqlStr18 = 'SELECT "foo".* FROM "foo" GROUP BY "col1", "col2"'; - $internalTests18 = [ - 'processSelect' => [[['"foo".*']], '"foo"'], - 'processGroup' => [['"col1"', '"col2"']] - ]; - - $select19 = new Select; - $select19->from('foo')->group(new Expression('DAY(?)', ['col1'], [Expression::TYPE_IDENTIFIER])); - $sqlPrep19 = // same - $sqlStr19 = 'SELECT "foo".* FROM "foo" GROUP BY DAY("col1")'; - $internalTests19 = [ - 'processSelect' => [[['"foo".*']], '"foo"'], - 'processGroup' => [['DAY("col1")']] - ]; - - // having (simple string) - $select20 = new Select; - $select20->from('foo')->having('x = 5'); - $sqlPrep20 = // same - $sqlStr20 = 'SELECT "foo".* FROM "foo" HAVING x = 5'; - $internalTests20 = [ - 'processSelect' => [[['"foo".*']], '"foo"'], - 'processHaving' => ['x = 5'] - ]; - - // having (returning parameters) - $select21 = new Select; - $select21->from('foo')->having(['x = ?' => 5]); - $sqlPrep21 = 'SELECT "foo".* FROM "foo" HAVING x = ?'; - $sqlStr21 = 'SELECT "foo".* FROM "foo" HAVING x = \'5\''; - $params21 = ['having1' => 5]; - $internalTests21 = [ - 'processSelect' => [[['"foo".*']], '"foo"'], - 'processHaving' => ['x = ?'] - ]; - - // order - $select22 = new Select; - $select22->from('foo')->order('c1'); - $sqlPrep22 = // - $sqlStr22 = 'SELECT "foo".* FROM "foo" ORDER BY "c1" ASC'; - $internalTests22 = [ - 'processSelect' => [[['"foo".*']], '"foo"'], - 'processOrder' => [[['"c1"', Select::ORDER_ASCENDING]]] - ]; - - $select23 = new Select; - $select23->from('foo')->order(['c1', 'c2']); - $sqlPrep23 = // same - $sqlStr23 = 'SELECT "foo".* FROM "foo" ORDER BY "c1" ASC, "c2" ASC'; - $internalTests23 = [ - 'processSelect' => [[['"foo".*']], '"foo"'], - 'processOrder' => [[['"c1"', Select::ORDER_ASCENDING], ['"c2"', Select::ORDER_ASCENDING]]] - ]; - - $select24 = new Select; - $select24->from('foo')->order(['c1' => 'DESC', 'c2' => 'Asc']); // notice partially lower case ASC - $sqlPrep24 = // same - $sqlStr24 = 'SELECT "foo".* FROM "foo" ORDER BY "c1" DESC, "c2" ASC'; - $internalTests24 = [ - 'processSelect' => [[['"foo".*']], '"foo"'], - 'processOrder' => [[['"c1"', Select::ORDER_DESCENDING], ['"c2"', Select::ORDER_ASCENDING]]] - ]; - - $select25 = new Select; - $select25->from('foo')->order(['c1' => 'asc'])->order('c2 desc'); // notice partially lower case ASC - $sqlPrep25 = // same - $sqlStr25 = 'SELECT "foo".* FROM "foo" ORDER BY "c1" ASC, "c2" DESC'; - $internalTests25 = [ - 'processSelect' => [[['"foo".*']], '"foo"'], - 'processOrder' => [[['"c1"', Select::ORDER_ASCENDING], ['"c2"', Select::ORDER_DESCENDING]]] - ]; - - // limit - $select26 = new Select; - $select26->from('foo')->limit(5); - $sqlPrep26 = 'SELECT "foo".* FROM "foo" LIMIT ?'; - $sqlStr26 = 'SELECT "foo".* FROM "foo" LIMIT \'5\''; - $params26 = ['limit' => 5]; - $internalTests26 = [ - 'processSelect' => [[['"foo".*']], '"foo"'], - 'processLimit' => ['?'] - ]; - - // limit with offset - $select27 = new Select; - $select27->from('foo')->limit(5)->offset(10); - $sqlPrep27 = 'SELECT "foo".* FROM "foo" LIMIT ? OFFSET ?'; - $sqlStr27 = 'SELECT "foo".* FROM "foo" LIMIT \'5\' OFFSET \'10\''; - $params27 = ['limit' => 5, 'offset' => 10]; - $internalTests27 = [ - 'processSelect' => [[['"foo".*']], '"foo"'], - 'processLimit' => ['?'], - 'processOffset' => ['?'] - ]; - - // 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 OR (c.x < y.z AND c.x <= y.z AND c.x > y.z AND c.x >= y.z)'); - $sqlPrep28 = // same - $sqlStr28 = 'SELECT "foo".*, "zac".* FROM "foo" INNER JOIN "zac" ON ("m" = "n" AND "c"."x") BETWEEN "x" AND "y"."z" OR ("c"."x" < "y"."z" AND "c"."x" <= "y"."z" AND "c"."x" > "y"."z" AND "c"."x" >= "y"."z")'; - $internalTests28 = [ - 'processSelect' => [[['"foo".*'], ['"zac".*']], '"foo"'], - 'processJoins' => [[['INNER', '"zac"', '("m" = "n" AND "c"."x") BETWEEN "x" AND "y"."z" OR ("c"."x" < "y"."z" AND "c"."x" <= "y"."z" AND "c"."x" > "y"."z" AND "c"."x" >= "y"."z")']]] - ]; - - // order with compound name - $select29 = new Select; - $select29->from('foo')->order('c1.d2'); - $sqlPrep29 = // - $sqlStr29 = 'SELECT "foo".* FROM "foo" ORDER BY "c1"."d2" ASC'; - $internalTests29 = [ - 'processSelect' => [[['"foo".*']], '"foo"'], - 'processOrder' => [[['"c1"."d2"', Select::ORDER_ASCENDING]]] - ]; - - // group with compound name - $select30 = new Select; - $select30->from('foo')->group('c1.d2'); - $sqlPrep30 = // same - $sqlStr30 = 'SELECT "foo".* FROM "foo" GROUP BY "c1"."d2"'; - $internalTests30 = [ - 'processSelect' => [[['"foo".*']], '"foo"'], - 'processGroup' => [['"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 = [ - 'processSelect' => [[['"foo".*'], ['"zac".*']], '"foo"'], - 'processJoins' => [[['INNER', '"zac"', '(m = n AND c.x) BETWEEN x AND y.z']]] - ]; - - $select32subselect = new Select; - $select32subselect->from('bar')->where->like('y', '%Foo%'); - $select32 = new Select; - $select32->from(['x' => $select32subselect]); - $sqlPrep32 = 'SELECT "x".* FROM (SELECT "bar".* FROM "bar" WHERE "y" LIKE ?) AS "x"'; - $sqlStr32 = 'SELECT "x".* FROM (SELECT "bar".* FROM "bar" WHERE "y" LIKE \'%Foo%\') AS "x"'; - $internalTests32 = [ - 'processSelect' => [[['"x".*']], '(SELECT "bar".* FROM "bar" WHERE "y" LIKE ?) AS "x"'], - ]; - - $select33 = new Select; - $select33->from('table')->columns(['*'])->where([ - 'c1' => null, - 'c2' => [1, 2, 3], - new \Zend\Db\Sql\Predicate\IsNotNull('c3') - ]); - $sqlPrep33 = 'SELECT "table".* FROM "table" WHERE "c1" IS NULL AND "c2" IN (?, ?, ?) AND "c3" IS NOT NULL'; - $sqlStr33 = 'SELECT "table".* FROM "table" WHERE "c1" IS NULL AND "c2" IN (\'1\', \'2\', \'3\') AND "c3" IS NOT NULL'; - $internalTests33 = [ - 'processSelect' => [[['"table".*']], '"table"'], - 'processWhere' => ['"c1" IS NULL AND "c2" IN (?, ?, ?) AND "c3" IS NOT NULL'] - ]; - - // @author Demian Katz - $select34 = new Select; - $select34->from('table')->order([ - new Expression('isnull(?) DESC', ['name'], [Expression::TYPE_IDENTIFIER]), - 'name' - ]); - $sqlPrep34 = 'SELECT "table".* FROM "table" ORDER BY isnull("name") DESC, "name" ASC'; - $sqlStr34 = 'SELECT "table".* FROM "table" ORDER BY isnull("name") DESC, "name" ASC'; - $internalTests34 = [ - 'processOrder' => [[['isnull("name") DESC'], ['"name"', Select::ORDER_ASCENDING]]] - ]; - - // join with Expression object in COLUMNS part (ZF2-514) - // @co-author Koen Pieters (kpieters) - $select35 = new Select; - $select35->from('foo')->columns([])->join('bar', 'm = n', ['thecount' => new Expression("COUNT(*)")]); - $sqlPrep35 = // same - $sqlStr35 = 'SELECT COUNT(*) AS "thecount" FROM "foo" INNER JOIN "bar" ON "m" = "n"'; - $internalTests35 = [ - 'processSelect' => [[['COUNT(*)', '"thecount"']], '"foo"'], - 'processJoins' => [[['INNER', '"bar"', '"m" = "n"']]] - ]; - - // multiple joins with expressions - // reported by @jdolieslager - $select36 = new Select; - $select36->from('foo') - ->join('tableA', new Predicate\Operator('id', '=', 1)) - ->join('tableB', new Predicate\Operator('id', '=', 2)) - ->join('tableC', new Predicate\PredicateSet([ - new Predicate\Operator('id', '=', 3), - new Predicate\Operator('number', '>', 20) - ])); - $sqlPrep36 = 'SELECT "foo".*, "tableA".*, "tableB".*, "tableC".* FROM "foo"' - . ' INNER JOIN "tableA" ON "id" = :join1part1 INNER JOIN "tableB" ON "id" = :join2part1 ' - . 'INNER JOIN "tableC" ON "id" = :join3part1 AND "number" > :join3part2'; - $sqlStr36 = 'SELECT "foo".*, "tableA".*, "tableB".*, "tableC".* FROM "foo" ' - . 'INNER JOIN "tableA" ON "id" = \'1\' INNER JOIN "tableB" ON "id" = \'2\' ' - . 'INNER JOIN "tableC" ON "id" = \'3\' AND "number" > \'20\''; - $internalTests36 = []; - $useNamedParams36 = true; - - /** - * @author robertbasic - * @link https://github.com/zendframework/zf2/pull/2714 - */ - $select37 = new Select; - $select37->from('foo')->columns(['bar'], false); - $sqlPrep37 = // same - $sqlStr37 = 'SELECT "bar" AS "bar" FROM "foo"'; - $internalTests37 = [ - 'processSelect' => [[['"bar"', '"bar"']], '"foo"'] - ]; - - // @link https://github.com/zendframework/zf2/issues/3294 - // Test TableIdentifier In Joins - $select38 = new Select; - $select38->from('foo')->columns([])->join(new TableIdentifier('bar', 'baz'), 'm = n', ['thecount' => new Expression("COUNT(*)")]); - $sqlPrep38 = // same - $sqlStr38 = 'SELECT COUNT(*) AS "thecount" FROM "foo" INNER JOIN "baz"."bar" ON "m" = "n"'; - $internalTests38 = [ - 'processSelect' => [[['COUNT(*)', '"thecount"']], '"foo"'], - 'processJoins' => [[['INNER', '"baz"."bar"', '"m" = "n"']]] - ]; - - // subselect in join - $select39subselect = new Select; - $select39subselect->from('bar')->where->like('y', '%Foo%'); - $select39 = new Select; - $select39->from('foo')->join(['z' => $select39subselect], 'z.foo = bar.id'); - $sqlPrep39 = 'SELECT "foo".*, "z".* FROM "foo" INNER JOIN (SELECT "bar".* FROM "bar" WHERE "y" LIKE ?) AS "z" ON "z"."foo" = "bar"."id"'; - $sqlStr39 = 'SELECT "foo".*, "z".* FROM "foo" INNER JOIN (SELECT "bar".* FROM "bar" WHERE "y" LIKE \'%Foo%\') AS "z" ON "z"."foo" = "bar"."id"'; - $internalTests39 = [ - 'processJoins' => [[['INNER', '(SELECT "bar".* FROM "bar" WHERE "y" LIKE ?) AS "z"', '"z"."foo" = "bar"."id"']]] - ]; - - // @link https://github.com/zendframework/zf2/issues/3294 - // Test TableIdentifier In Joins, with multiple joins - $select40 = new Select; - $select40->from('foo') - ->join(['a' => new TableIdentifier('another_foo', 'another_schema')], 'a.x = foo.foo_column') - ->join('bar', 'foo.colx = bar.colx'); - $sqlPrep40 = // same - $sqlStr40 = 'SELECT "foo".*, "a".*, "bar".* FROM "foo"' - . ' INNER JOIN "another_schema"."another_foo" AS "a" ON "a"."x" = "foo"."foo_column"' - . ' INNER JOIN "bar" ON "foo"."colx" = "bar"."colx"'; - $internalTests40 = [ - 'processSelect' => [[['"foo".*'], ['"a".*'], ['"bar".*']], '"foo"'], - 'processJoins' => [[ - ['INNER', '"another_schema"."another_foo" AS "a"', '"a"."x" = "foo"."foo_column"'], - ['INNER', '"bar"', '"foo"."colx" = "bar"."colx"'] - ]] - ]; - - $select41 = new Select; - $select41->from('foo')->quantifier(Select::QUANTIFIER_DISTINCT); - $sqlPrep41 = // same - $sqlStr41 = 'SELECT DISTINCT "foo".* FROM "foo"'; - $internalTests41 = [ - 'processSelect' => [SELECT::QUANTIFIER_DISTINCT, [['"foo".*']], '"foo"'], - ]; - - $select42 = new Select; - $select42->from('foo')->quantifier(new Expression('TOP ?', [10])); - $sqlPrep42 = 'SELECT TOP ? "foo".* FROM "foo"'; - $sqlStr42 = 'SELECT TOP \'10\' "foo".* FROM "foo"'; - $internalTests42 = [ - 'processSelect' => ['TOP ?', [['"foo".*']], '"foo"'], - ]; - - $select43 = new Select(); - $select43->from(['x' => 'foo'])->columns(['bar' => 'foo.bar'], false); - $sqlPrep43 = 'SELECT "foo"."bar" AS "bar" FROM "foo" AS "x"'; - $sqlStr43 = 'SELECT "foo"."bar" AS "bar" FROM "foo" AS "x"'; - $internalTests43 = [ - 'processSelect' => [[['"foo"."bar"', '"bar"']], '"foo" AS "x"'] - ]; - - $select44 = new Select; - $select44->from('foo')->where('a = b'); - $select44b = new Select; - $select44b->from('bar')->where('c = d'); - $select44->combine($select44b, Select::COMBINE_UNION, 'ALL'); - $sqlPrep44 = // same - $sqlStr44 = '( SELECT "foo".* FROM "foo" WHERE a = b ) UNION ALL ( SELECT "bar".* FROM "bar" WHERE c = d )'; - $internalTests44 = [ - 'processCombine' => ['UNION ALL', 'SELECT "bar".* FROM "bar" WHERE c = d'] - ]; - - // limit with offset - $select45 = new Select; - $select45->from('foo')->limit("5")->offset("10"); - $sqlPrep45 = 'SELECT "foo".* FROM "foo" LIMIT ? OFFSET ?'; - $sqlStr45 = 'SELECT "foo".* FROM "foo" LIMIT \'5\' OFFSET \'10\''; - $params45 = ['limit' => 5, 'offset' => 10]; - $internalTests45 = [ - 'processSelect' => [[['"foo".*']], '"foo"'], - 'processLimit' => ['?'], - 'processOffset' => ['?'] - ]; - - // functions without table - $select46 = new Select; - $select46->columns([ - new Expression('SOME_DB_FUNCTION_ONE()'), - 'foo' => new Expression('SOME_DB_FUNCTION_TWO()'), - ]); - $sqlPrep46 = 'SELECT SOME_DB_FUNCTION_ONE() AS Expression1, SOME_DB_FUNCTION_TWO() AS "foo"'; - $sqlStr46 = 'SELECT SOME_DB_FUNCTION_ONE() AS Expression1, SOME_DB_FUNCTION_TWO() AS "foo"'; - $params46 = []; - $internalTests46 = []; - - // limit with big offset and limit - $select47 = new Select; - $select47->from('foo')->limit("10000000000000000000")->offset("10000000000000000000"); - $sqlPrep47 = 'SELECT "foo".* FROM "foo" LIMIT ? OFFSET ?'; - $sqlStr47 = 'SELECT "foo".* FROM "foo" LIMIT \'10000000000000000000\' OFFSET \'10000000000000000000\''; - $params47 = ['limit' => 10000000000000000000, 'offset' => 10000000000000000000]; - $internalTests47 = [ - 'processSelect' => [[['"foo".*']], '"foo"'], - 'processLimit' => ['?'], - 'processOffset' => ['?'] - ]; - - //combine and union with order at the end - $select48 = new Select; - $select48->from('foo')->where('a = b'); - $select48b = new Select; - $select48b->from('bar')->where('c = d'); - $select48->combine($select48b); - - $select48combined = new Select(); - $select48 = $select48combined->from(['sub' => $select48])->order('id DESC'); - $sqlPrep48 = // same - $sqlStr48 = 'SELECT "sub".* FROM (( SELECT "foo".* FROM "foo" WHERE a = b ) UNION ( SELECT "bar".* FROM "bar" WHERE c = d )) AS "sub" ORDER BY "id" DESC'; - $internalTests48 = [ - 'processCombine' => null, - ]; - - //Expression as joinName - $select49 = new Select; - $select49->from(new TableIdentifier('foo')) - ->join(['bar' => new Expression('psql_function_which_returns_table')], 'foo.id = bar.fooid'); - $sqlPrep49 = // same - $sqlStr49 = 'SELECT "foo".*, "bar".* FROM "foo" INNER JOIN psql_function_which_returns_table AS "bar" ON "foo"."id" = "bar"."fooid"'; - $internalTests49 = [ - 'processSelect' => [[['"foo".*'], ['"bar".*']], '"foo"'], - 'processJoins' => [[['INNER', 'psql_function_which_returns_table AS "bar"', '"foo"."id" = "bar"."fooid"']]] - ]; - - // Test generic predicate is appended with AND - $select50 = new Select; - $select50->from(new TableIdentifier('foo')) - ->where - ->nest - ->isNull('bar') - ->and - ->predicate(new Predicate\Literal('1=1')) - ->unnest; - $sqlPrep50 = // same - $sqlStr50 = 'SELECT "foo".* FROM "foo" WHERE ("bar" IS NULL AND 1=1)'; - $internalTests50 = []; - - // Test generic predicate is appended with OR - $select51 = new Select; - $select51->from(new TableIdentifier('foo')) - ->where - ->nest - ->isNull('bar') - ->or - ->predicate(new Predicate\Literal('1=1')) - ->unnest; - $sqlPrep51 = // same - $sqlStr51 = 'SELECT "foo".* FROM "foo" WHERE ("bar" IS NULL OR 1=1)'; - $internalTests51 = []; - - /** - * @author Andrzej Lewandowski - * @link https://github.com/zendframework/zf2/issues/7222 - */ - $select52 = new Select; - $select52->from('foo')->join('zac', '(catalog_category_website.category_id = catalog_category.category_id)'); - $sqlPrep52 = // same - $sqlStr52 = 'SELECT "foo".*, "zac".* FROM "foo" INNER JOIN "zac" ON ("catalog_category_website"."category_id" = "catalog_category"."category_id")'; - $internalTests52 = [ - 'processSelect' => [[['"foo".*'], ['"zac".*']], '"foo"'], - 'processJoins' => [[['INNER', '"zac"', '("catalog_category_website"."category_id" = "catalog_category"."category_id")']]] - ]; - - /** - * $select = the select object - * $sqlPrep = the sql as a result of preparation - * $params = the param container contents result of preparation - * $sqlStr = the sql as a result of getting a string back - * $internalTests what the internal functions should return (safe-guarding extension) - */ - - return [ - // $select $sqlPrep $params $sqlStr $internalTests // use named param - [$select0, $sqlPrep0, [], $sqlStr0, $internalTests0], - [$select1, $sqlPrep1, [], $sqlStr1, $internalTests1], - [$select2, $sqlPrep2, [], $sqlStr2, $internalTests2], - [$select3, $sqlPrep3, [], $sqlStr3, $internalTests3], - [$select4, $sqlPrep4, [], $sqlStr4, $internalTests4], - [$select5, $sqlPrep5, [], $sqlStr5, $internalTests5], - [$select6, $sqlPrep6, [], $sqlStr6, $internalTests6], - [$select7, $sqlPrep7, [], $sqlStr7, $internalTests7], - [$select8, $sqlPrep8, [], $sqlStr8, $internalTests8], - [$select9, $sqlPrep9, $params9, $sqlStr9, $internalTests9], - [$select10, $sqlPrep10, [], $sqlStr10, $internalTests10], - [$select11, $sqlPrep11, [], $sqlStr11, $internalTests11], - [$select12, $sqlPrep12, [], $sqlStr12, $internalTests12], - [$select13, $sqlPrep13, [], $sqlStr13, $internalTests13], - [$select14, $sqlPrep14, [], $sqlStr14, $internalTests14], - [$select15, $sqlPrep15, [], $sqlStr15, $internalTests15], - [$select16, $sqlPrep16, $params16, $sqlStr16, $internalTests16], - [$select17, $sqlPrep17, [], $sqlStr17, $internalTests17], - [$select18, $sqlPrep18, [], $sqlStr18, $internalTests18], - [$select19, $sqlPrep19, [], $sqlStr19, $internalTests19], - [$select20, $sqlPrep20, [], $sqlStr20, $internalTests20], - [$select21, $sqlPrep21, $params21, $sqlStr21, $internalTests21], - [$select22, $sqlPrep22, [], $sqlStr22, $internalTests22], - [$select23, $sqlPrep23, [], $sqlStr23, $internalTests23], - [$select24, $sqlPrep24, [], $sqlStr24, $internalTests24], - [$select25, $sqlPrep25, [], $sqlStr25, $internalTests25], - [$select26, $sqlPrep26, $params26, $sqlStr26, $internalTests26], - [$select27, $sqlPrep27, $params27, $sqlStr27, $internalTests27], - [$select28, $sqlPrep28, [], $sqlStr28, $internalTests28], - [$select29, $sqlPrep29, [], $sqlStr29, $internalTests29], - [$select30, $sqlPrep30, [], $sqlStr30, $internalTests30], - [$select31, $sqlPrep31, [], $sqlStr31, $internalTests31], - [$select32, $sqlPrep32, [], $sqlStr32, $internalTests32], - [$select33, $sqlPrep33, [], $sqlStr33, $internalTests33], - [$select34, $sqlPrep34, [], $sqlStr34, $internalTests34], - [$select35, $sqlPrep35, [], $sqlStr35, $internalTests35], - [$select36, $sqlPrep36, [], $sqlStr36, $internalTests36, $useNamedParams36], - [$select37, $sqlPrep37, [], $sqlStr37, $internalTests37], - [$select38, $sqlPrep38, [], $sqlStr38, $internalTests38], - [$select39, $sqlPrep39, [], $sqlStr39, $internalTests39], - [$select40, $sqlPrep40, [], $sqlStr40, $internalTests40], - [$select41, $sqlPrep41, [], $sqlStr41, $internalTests41], - [$select42, $sqlPrep42, [], $sqlStr42, $internalTests42], - [$select43, $sqlPrep43, [], $sqlStr43, $internalTests43], - [$select44, $sqlPrep44, [], $sqlStr44, $internalTests44], - [$select45, $sqlPrep45, $params45, $sqlStr45, $internalTests45], - [$select46, $sqlPrep46, $params46, $sqlStr46, $internalTests46], - [$select47, $sqlPrep47, $params47, $sqlStr47, $internalTests47], - [$select48, $sqlPrep48, [], $sqlStr48, $internalTests48], - [$select49, $sqlPrep49, [], $sqlStr49, $internalTests49], - [$select50, $sqlPrep50, [], $sqlStr50, $internalTests50], - [$select51, $sqlPrep51, [], $sqlStr51, $internalTests51], - [$select52, $sqlPrep52, [], $sqlStr52, $internalTests52], - ]; - } } diff --git a/test/Sql/SqlTest.php b/test/Sql/SqlTest.php index eb24175721..698a73f4d4 100644 --- a/test/Sql/SqlTest.php +++ b/test/Sql/SqlTest.php @@ -64,7 +64,7 @@ public function testSelect() { $select = $this->sql->select(); $this->assertInstanceOf('Zend\Db\Sql\Select', $select); - $this->assertSame('foo', $select->getRawState('table')); + $this->assertSame('foo', $select->table); $this->setExpectedException('Zend\Db\Sql\Exception\InvalidArgumentException', 'This Sql object is intended to work with only the table "foo" provided at construction time.'); @@ -78,7 +78,7 @@ public function testInsert() { $insert = $this->sql->insert(); $this->assertInstanceOf('Zend\Db\Sql\Insert', $insert); - $this->assertSame('foo', $insert->getRawState('table')); + $this->assertSame('foo', $insert->table); $this->setExpectedException('Zend\Db\Sql\Exception\InvalidArgumentException', 'This Sql object is intended to work with only the table "foo" provided at construction time.'); @@ -92,7 +92,7 @@ public function testUpdate() { $update = $this->sql->update(); $this->assertInstanceOf('Zend\Db\Sql\Update', $update); - $this->assertSame('foo', $update->getRawState('table')); + $this->assertSame('foo', $update->table); $this->setExpectedException('Zend\Db\Sql\Exception\InvalidArgumentException', 'This Sql object is intended to work with only the table "foo" provided at construction time.'); @@ -107,7 +107,7 @@ public function testDelete() $delete = $this->sql->delete(); $this->assertInstanceOf('Zend\Db\Sql\Delete', $delete); - $this->assertSame('foo', $delete->getRawState('table')); + $this->assertSame('foo', $delete->table); $this->setExpectedException('Zend\Db\Sql\Exception\InvalidArgumentException', 'This Sql object is intended to work with only the table "foo" provided at construction time.'); @@ -123,87 +123,4 @@ public function testPrepareStatementForSqlObject() $stmt = $this->sql->prepareStatementForSqlObject($insert); $this->assertInstanceOf('Zend\Db\Adapter\Driver\StatementInterface', $stmt); } - - /** - * @group 6890 - */ - public function testForDifferentAdapters() - { - $adapterSql92 = $this->getAdapterForPlatform('sql92'); - $adapterMySql = $this->getAdapterForPlatform('MySql'); - $adapterOracle = $this->getAdapterForPlatform('Oracle'); - $adapterSqlServer = $this->getAdapterForPlatform('SqlServer'); - - $select = $this->sql->select()->offset(10); - - // Default - $this->assertEquals( - 'SELECT "foo".* FROM "foo" OFFSET \'10\'', - $this->sql->buildSqlString($select) - ); - $this->mockAdapter->getDriver()->createStatement()->expects($this->any())->method('setSql') - ->with($this->equalTo('SELECT "foo".* FROM "foo" OFFSET ?')); - $this->sql->prepareStatementForSqlObject($select); - - // Sql92 - $this->assertEquals( - 'SELECT "foo".* FROM "foo" OFFSET \'10\'', - $this->sql->buildSqlString($select, $adapterSql92) - ); - $adapterSql92->getDriver()->createStatement()->expects($this->any())->method('setSql') - ->with($this->equalTo('SELECT "foo".* FROM "foo" OFFSET ?')); - $this->sql->prepareStatementForSqlObject($select, null, $adapterSql92); - - // MySql - $this->assertEquals( - 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET 10', - $this->sql->buildSqlString($select, $adapterMySql) - ); - $adapterMySql->getDriver()->createStatement()->expects($this->any())->method('setSql') - ->with($this->equalTo('SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET ?')); - $this->sql->prepareStatementForSqlObject($select, null, $adapterMySql); - - // Oracle - $this->assertEquals( - 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b ) WHERE b_rownum > (10)', - $this->sql->buildSqlString($select, $adapterOracle) - ); - $adapterOracle->getDriver()->createStatement()->expects($this->any())->method('setSql') - ->with($this->equalTo('SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b ) WHERE b_rownum > (:offset)')); - $this->sql->prepareStatementForSqlObject($select, null, $adapterOracle); - - // SqlServer - $this->assertContains( - 'WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 10+1 AND 0+10', - $this->sql->buildSqlString($select, $adapterSqlServer) - ); - $adapterSqlServer->getDriver()->createStatement()->expects($this->any())->method('setSql') - ->with($this->stringContains('WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?')); - $this->sql->prepareStatementForSqlObject($select, null, $adapterSqlServer); - } - - /** - * Data provider - * - * @param string $platform - * - * @return Adapter - */ - protected function getAdapterForPlatform($platform) - { - switch ($platform) { - case 'sql92' : $platform = new TestAsset\TrustingSql92Platform(); break; - case 'MySql' : $platform = new TestAsset\TrustingMysqlPlatform(); break; - case 'Oracle' : $platform = new TestAsset\TrustingOraclePlatform(); break; - case 'SqlServer' : $platform = new TestAsset\TrustingSqlServerPlatform(); break; - default : $platform = null; - } - - $mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $mockDriver->expects($this->any())->method('formatParameterName')->will($this->returnValue('?')); - $mockDriver->expects($this->any())->method('createStatement')->will($this->returnValue($mockStatement)); - - return new Adapter($mockDriver, $platform); - } } diff --git a/test/Sql/UpdateTest.php b/test/Sql/UpdateTest.php index a2e9b8a3d4..584d945160 100644 --- a/test/Sql/UpdateTest.php +++ b/test/Sql/UpdateTest.php @@ -12,9 +12,7 @@ use Zend\Db\Sql\Join; use Zend\Db\Sql\Update; use Zend\Db\Sql\Where; -use Zend\Db\Sql\Expression; use Zend\Db\Sql\TableIdentifier; -use ZendTest\Db\TestAsset\TrustingSql92Platform; class UpdateTest extends \PHPUnit_Framework_TestCase { @@ -68,7 +66,7 @@ public function testConstruct() public function testSet() { $this->update->set(['foo' => 'bar']); - $this->assertEquals(['foo' => 'bar'], $this->update->getRawState('set')); + $this->assertEquals(['foo' => 'bar'], $this->update->set->toArray()); } /** @@ -88,164 +86,24 @@ public function testSortableSet() 'two' => 'с_two', 'three' => 'с_three', ], - $this->update->getRawState('set') + $this->update->set->toArray() ); } /** - * @covers Zend\Db\Sql\Update::where - */ - public function testWhere() - { - $this->update->where('x = y'); - $this->update->where(['foo > ?' => 5]); - $this->update->where(['id' => 2]); - $this->update->where(['a = b'], Where::OP_OR); - $this->update->where(['c1' => null]); - $this->update->where(['c2' => [1, 2, 3]]); - $this->update->where([new \Zend\Db\Sql\Predicate\IsNotNull('c3')]); - $where = $this->update->where; - - $predicates = $this->readAttribute($where, 'predicates'); - $this->assertEquals('AND', $predicates[0][0]); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\Literal', $predicates[0][1]); - - $this->assertEquals('AND', $predicates[1][0]); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\Expression', $predicates[1][1]); - - $this->assertEquals('AND', $predicates[2][0]); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\Operator', $predicates[2][1]); - - $this->assertEquals('OR', $predicates[3][0]); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\Literal', $predicates[3][1]); - - $this->assertEquals('AND', $predicates[4][0]); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\IsNull', $predicates[4][1]); - - $this->assertEquals('AND', $predicates[5][0]); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\In', $predicates[5][1]); - - $this->assertEquals('AND', $predicates[6][0]); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\IsNotNull', $predicates[6][1]); - - $where = new Where; - $this->update->where($where); - $this->assertSame($where, $this->update->where); - - $this->update->where(function ($what) use ($where) { - $this->assertSame($where, $what); - }); - - $this->setExpectedException('Zend\Db\Sql\Exception\InvalidArgumentException', 'Predicate cannot be null'); - $this->update->where(null); - } - - /** - * @group ZF2-240 - * @covers Zend\Db\Sql\Update::where - */ - public function testPassingMultipleKeyValueInWhereClause() - { - $update = clone $this->update; - $update->table('table'); - $update->set(['fld1' => 'val1']); - $update->where(['id1' => 'val1', 'id2' => 'val2']); - $this->assertEquals('UPDATE "table" SET "fld1" = \'val1\' WHERE "id1" = \'val1\' AND "id2" = \'val2\'', $update->getSqlString(new TrustingSql92Platform())); - } - - /** - * @covers Zend\Db\Sql\Update::getRawState + * @covers Zend\Db\Sql\Update::__get */ - public function testGetRawState() + public function test__Get() { $this->update->table('foo') ->set(['bar' => 'baz']) ->where('x = y'); - $this->assertEquals('foo', $this->update->getRawState('table')); - $this->assertEquals(true, $this->update->getRawState('emptyWhereProtection')); - $this->assertEquals(['bar' => 'baz'], $this->update->getRawState('set')); - $this->assertInstanceOf('Zend\Db\Sql\Where', $this->update->getRawState('where')); - } - - /** - * @covers Zend\Db\Sql\Update::prepareStatement - */ - public function testPrepareStatement() - { - $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $mockDriver->expects($this->any())->method('getPrepareType')->will($this->returnValue('positional')); - $mockDriver->expects($this->any())->method('formatParameterName')->will($this->returnValue('?')); - $mockAdapter = $this->getMock('Zend\Db\Adapter\Adapter', null, [$mockDriver]); - - $mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $pContainer = new \Zend\Db\Adapter\ParameterContainer([]); - $mockStatement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($pContainer)); - - $mockStatement->expects($this->at(1)) - ->method('setSql') - ->with($this->equalTo('UPDATE "foo" SET "bar" = ?, "boo" = NOW() WHERE x = y')); - - $this->update->table('foo') - ->set(['bar' => 'baz', 'boo' => new Expression('NOW()')]) - ->where('x = y'); - - $this->update->prepareStatement($mockAdapter, $mockStatement); - - // with TableIdentifier - $this->update = new Update; - $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $mockDriver->expects($this->any())->method('getPrepareType')->will($this->returnValue('positional')); - $mockDriver->expects($this->any())->method('formatParameterName')->will($this->returnValue('?')); - $mockAdapter = $this->getMock('Zend\Db\Adapter\Adapter', null, [$mockDriver]); - - $mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $pContainer = new \Zend\Db\Adapter\ParameterContainer([]); - $mockStatement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($pContainer)); - - $mockStatement->expects($this->at(1)) - ->method('setSql') - ->with($this->equalTo('UPDATE "sch"."foo" SET "bar" = ?, "boo" = NOW() WHERE x = y')); - - $this->update->table(new TableIdentifier('foo', 'sch')) - ->set(['bar' => 'baz', 'boo' => new Expression('NOW()')]) - ->where('x = y'); - - $this->update->prepareStatement($mockAdapter, $mockStatement); - } - - /** - * @covers Zend\Db\Sql\Update::getSqlString - */ - public function testGetSqlString() - { - $this->update->table('foo') - ->set(['bar' => 'baz', 'boo' => new Expression('NOW()'), 'bam' => null]) - ->where('x = y'); - - $this->assertEquals('UPDATE "foo" SET "bar" = \'baz\', "boo" = NOW(), "bam" = NULL WHERE x = y', $this->update->getSqlString(new TrustingSql92Platform())); - - // with TableIdentifier - $this->update = new Update; - $this->update->table(new TableIdentifier('foo', 'sch')) - ->set(['bar' => 'baz', 'boo' => new Expression('NOW()'), 'bam' => null]) - ->where('x = y'); - - $this->assertEquals('UPDATE "sch"."foo" SET "bar" = \'baz\', "boo" = NOW(), "bam" = NULL WHERE x = y', $this->update->getSqlString(new TrustingSql92Platform())); + $this->assertEquals('foo', $this->update->table); + $this->assertEquals(['bar' => 'baz'], $this->update->set->toArray()); + $this->assertInstanceOf('Zend\Db\Sql\Where', $this->update->where); } - /** - * @group 6768 - * @group 6773 - */ - public function testGetSqlStringForFalseUpdateValueParameter() - { - $this->update = new Update; - $this->update->table(new TableIdentifier('foo', 'sch')) - ->set(['bar' => false, 'boo' => 'test', 'bam' => true]) - ->where('x = y'); - $this->assertEquals('UPDATE "sch"."foo" SET "bar" = \'\', "boo" = \'test\', "bam" = \'1\' WHERE x = y', $this->update->getSqlString(new TrustingSql92Platform())); - } /** * @covers Zend\Db\Sql\Update::__get @@ -261,100 +119,11 @@ public function testGetUpdate() */ public function testGetUpdateFails() { + $this->setExpectedException('Zend\Db\Sql\Exception\InvalidArgumentException'); $getWhat = $this->update->__get('what'); $this->assertNull($getWhat); } - /** - * @covers Zend\Db\Sql\Update::__clone - */ - public function testCloneUpdate() - { - $update1 = clone $this->update; - $update1->table('foo') - ->set(['bar' => 'baz']) - ->where('x = y'); - - $update2 = clone $this->update; - $update2->table('foo') - ->set(['bar' => 'baz']) - ->where([ - 'id = ?'=>1 - ]); - $this->assertEquals('UPDATE "foo" SET "bar" = \'baz\' WHERE id = \'1\'', $update2->getSqlString(new TrustingSql92Platform)); - } - - /** - * @coversNothing - */ - public function testSpecificationconstantsCouldBeOverridedByExtensionInPrepareStatement() - { - $updateIgnore = new UpdateIgnore(); - - $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $mockDriver->expects($this->any())->method('getPrepareType')->will($this->returnValue('positional')); - $mockDriver->expects($this->any())->method('formatParameterName')->will($this->returnValue('?')); - $mockAdapter = $this->getMock('Zend\Db\Adapter\Adapter', null, [$mockDriver]); - - $mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $pContainer = new \Zend\Db\Adapter\ParameterContainer([]); - $mockStatement->expects($this->any())->method('getParameterContainer')->will($this->returnValue($pContainer)); - - $mockStatement->expects($this->at(1)) - ->method('setSql') - ->with($this->equalTo('UPDATE IGNORE "foo" SET "bar" = ?, "boo" = NOW() WHERE x = y')); - - $updateIgnore->table('foo') - ->set(['bar' => 'baz', 'boo' => new Expression('NOW()')]) - ->where('x = y'); - - $updateIgnore->prepareStatement($mockAdapter, $mockStatement); - } - - /** - * @coversNothing - */ - public function testSpecificationconstantsCouldBeOverridedByExtensionInGetSqlString() - { - $this->update = new UpdateIgnore(); - - $this->update->table('foo') - ->set(['bar' => 'baz', 'boo' => new Expression('NOW()'), 'bam' => null]) - ->where('x = y'); - - $this->assertEquals('UPDATE IGNORE "foo" SET "bar" = \'baz\', "boo" = NOW(), "bam" = NULL WHERE x = y', $this->update->getSqlString(new TrustingSql92Platform())); - - // with TableIdentifier - $this->update = new UpdateIgnore(); - $this->update->table(new TableIdentifier('foo', 'sch')) - ->set(['bar' => 'baz', 'boo' => new Expression('NOW()'), 'bam' => null]) - ->where('x = y'); - - $this->assertEquals('UPDATE IGNORE "sch"."foo" SET "bar" = \'baz\', "boo" = NOW(), "bam" = NULL WHERE x = y', $this->update->getSqlString(new TrustingSql92Platform())); - } - - /** - * @covers Zend\Db\Sql\Update::where - */ - public function testJoin() - { - $this->update->table('Document'); - $this->update->set(['x' => 'y']) - ->join( - 'User', // table name - 'User.UserId = Document.UserId' // expression to join on (will be quoted by platform object before insertion), - // default JOIN INNER - ) - ->join( - 'Category', - 'Category.CategoryId = Document.CategoryId', - Join::JOIN_LEFT // (optional), one of inner, outer, left, right - ); - - $this->assertEquals('UPDATE "Document" INNER JOIN "User" ON "User"."UserId" = "Document"."UserId" LEFT JOIN "Category" ON "Category"."CategoryId" = "Document"."CategoryId" SET "x" = \'y\'', - $this->update->getSqlString(new TrustingSql92Platform())); - } - /** * @testdox unit test: Test join() returns Update object (is chainable) * @covers Zend\Db\Sql\Update::join @@ -365,19 +134,3 @@ public function testJoinChainable() $this->assertSame($this->update, $return); } } - -class UpdateIgnore extends Update -{ - const SPECIFICATION_UPDATE = 'updateIgnore'; - - protected $specifications = [ - self::SPECIFICATION_UPDATE => 'UPDATE IGNORE %1$s', - self::SPECIFICATION_SET => 'SET %1$s', - self::SPECIFICATION_WHERE => 'WHERE %1$s' - ]; - - protected function processupdateIgnore(\Zend\Db\Adapter\Platform\PlatformInterface $platform, \Zend\Db\Adapter\Driver\DriverInterface $driver = null, \Zend\Db\Adapter\ParameterContainer $parameterContainer = null) - { - return parent::processUpdate($platform, $driver, $parameterContainer); - } -} diff --git a/test/TableGateway/AbstractTableGatewayTest.php b/test/TableGateway/AbstractTableGatewayTest.php index c6b9305b6f..9f019161fc 100644 --- a/test/TableGateway/AbstractTableGatewayTest.php +++ b/test/TableGateway/AbstractTableGatewayTest.php @@ -11,6 +11,7 @@ use Zend\Db\TableGateway\AbstractTableGateway; use Zend\Db\Sql; +use Zend\Db\Adapter\ParameterContainer; use Zend\Db\ResultSet\ResultSet; /** @@ -23,6 +24,11 @@ class AbstractTableGatewayTest extends \PHPUnit_Framework_TestCase */ protected $mockAdapter = null; + /** + * @var \Zend\Db\Adapter\Driver\StatementInterface + */ + protected $mockStatement; + /** * @var \PHPUnit_Framework_MockObject_Generator */ @@ -43,22 +49,30 @@ protected function setUp() $mockResult = $this->getMock('Zend\Db\Adapter\Driver\ResultInterface'); $mockResult->expects($this->any())->method('getAffectedRows')->will($this->returnValue(5)); - $mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $mockStatement->expects($this->any())->method('execute')->will($this->returnValue($mockResult)); + $this->mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); + $stmtSQL = function ($sql = null) { + static $data; + if ($sql === null) { + return $data; + } + $data = $sql; + }; + + $this->mockStatement->expects($this->any())->method('setSql')->will($this->returnCallback($stmtSQL)); + $this->mockStatement->expects($this->any())->method('getSql')->will($this->returnCallback($stmtSQL)); + $this->mockStatement->expects($this->any())->method('execute')->will($this->returnValue($mockResult)); + $this->mockStatement->expects($this->any())->method('getParameterContainer')->will($this->returnValue(new ParameterContainer)); $mockConnection = $this->getMock('Zend\Db\Adapter\Driver\ConnectionInterface'); $mockConnection->expects($this->any())->method('getLastGeneratedValue')->will($this->returnValue(10)); $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); - $mockDriver->expects($this->any())->method('createStatement')->will($this->returnValue($mockStatement)); + $mockDriver->expects($this->any())->method('createStatement')->will($this->returnValue($this->mockStatement)); $mockDriver->expects($this->any())->method('getConnection')->will($this->returnValue($mockConnection)); + $mockDriver->expects($this->any())->method('formatParameterName')->will($this->returnValue('?')); $this->mockAdapter = $this->getMock('Zend\Db\Adapter\Adapter', null, [$mockDriver]); - $this->mockSql = $this->getMock('Zend\Db\Sql\Sql', ['select', 'insert', 'update', 'delete'], [$this->mockAdapter, 'foo']); - $this->mockSql->expects($this->any())->method('select')->will($this->returnValue($this->getMock('Zend\Db\Sql\Select', ['where', 'getRawSate'], ['foo']))); - $this->mockSql->expects($this->any())->method('insert')->will($this->returnValue($this->getMock('Zend\Db\Sql\Insert', ['prepareStatement', 'values'], ['foo']))); - $this->mockSql->expects($this->any())->method('update')->will($this->returnValue($this->getMock('Zend\Db\Sql\Update', ['where', 'join'], ['foo']))); - $this->mockSql->expects($this->any())->method('delete')->will($this->returnValue($this->getMock('Zend\Db\Sql\Delete', ['where'], ['foo']))); + $this->mockSql = new \Zend\Db\Sql\Sql($this->mockAdapter, 'foo'); $this->table = $this->getMockForAbstractClass( 'Zend\Db\TableGateway\AbstractTableGateway' @@ -136,6 +150,7 @@ public function testSelectWithNoWhere() // check return types $this->assertInstanceOf('Zend\Db\ResultSet\ResultSet', $resultSet); $this->assertNotSame($this->table->getResultSetPrototype(), $resultSet); + $this->assertEquals('SELECT "foo".* FROM "foo"', $this->mockStatement->getSql()); } /** @@ -145,21 +160,9 @@ public function testSelectWithNoWhere() */ public function testSelectWithWhereString() { - $mockSelect = $this->mockSql->select(); - - $mockSelect->expects($this->any()) - ->method('getRawState') - ->will($this->returnValue([ - 'table' => $this->table->getTable(), - ]) - ); - - // assert select::from() is called - $mockSelect->expects($this->once()) - ->method('where') - ->with($this->equalTo('foo')); - - $this->table->select('foo'); + $resultSet = $this->table->select('whereCondition'); + $this->assertInstanceOf('Zend\Db\ResultSet\ResultSet', $resultSet); + $this->assertEquals('SELECT "foo".* FROM "foo" WHERE whereCondition', $this->mockStatement->getSql()); } /** @@ -183,27 +186,18 @@ public function testSelectWithArrayTable() { // Case 1 - $select1 = $this->getMock('Zend\Db\Sql\Select', ['getRawState']); - $select1->expects($this->once()) - ->method('getRawState') - ->will($this->returnValue([ - 'table' => 'foo', // Standard table name format, valid according to Select::from() - 'columns' => null, - ])); + $select1 = new \Zend\Db\Sql\Select('bat'); + $return = $this->table->selectWith($select1); $this->assertNotNull($return); + $this->assertEquals('SELECT "bat".* FROM "bat"', $this->mockStatement->getSql()); // Case 2 - $select1 = $this->getMock('Zend\Db\Sql\Select', ['getRawState']); - $select1->expects($this->once()) - ->method('getRawState') - ->will($this->returnValue([ - 'table' => ['f' => 'foo'], // Alias table name format, valid according to Select::from() - 'columns' => null, - ])); + $select1 = new \Zend\Db\Sql\Select(['f' => 'foo']); $return = $this->table->selectWith($select1); $this->assertNotNull($return); + $this->assertEquals('SELECT "f".* FROM "foo" AS "f"', $this->mockStatement->getSql()); } /** @@ -213,19 +207,9 @@ public function testSelectWithArrayTable() */ public function testInsert() { - $mockInsert = $this->mockSql->insert(); - - $mockInsert->expects($this->once()) - ->method('prepareStatement') - ->with($this->mockAdapter); - - - $mockInsert->expects($this->once()) - ->method('values') - ->with($this->equalTo(['foo' => 'bar'])); - $affectedRows = $this->table->insert(['foo' => 'bar']); $this->assertEquals(5, $affectedRows); + $this->assertEquals('INSERT INTO "foo" ("foo") VALUES (?)', $this->mockStatement->getSql()); } /** @@ -235,15 +219,9 @@ public function testInsert() */ public function testUpdate() { - $mockUpdate = $this->mockSql->update(); - - // assert select::from() is called - $mockUpdate->expects($this->once()) - ->method('where') - ->with($this->equalTo('id = 2')); - $affectedRows = $this->table->update(['foo' => 'bar'], 'id = 2'); $this->assertEquals(5, $affectedRows); + $this->assertEquals('UPDATE "foo" SET "foo" = ? WHERE id = 2', $this->mockStatement->getSql()); } /** @@ -253,8 +231,6 @@ public function testUpdate() */ public function testUpdateWithJoin() { - $mockUpdate = $this->mockSql->update(); - $joins = [ [ 'name' => 'baz', @@ -262,18 +238,9 @@ public function testUpdateWithJoin() 'type' => Sql\Join::JOIN_LEFT ] ]; - - // assert select::from() is called - $mockUpdate->expects($this->once()) - ->method('where') - ->with($this->equalTo('id = 2')); - - $mockUpdate->expects($this->once()) - ->method('join') - ->with($joins[0]['name'], $joins[0]['on'], $joins[0]['type']); - $affectedRows = $this->table->update(['foo.field' => 'bar'], 'id = 2', $joins); $this->assertEquals(5, $affectedRows); + $this->assertEquals('UPDATE "foo" LEFT JOIN "baz" ON "foo"."fooId" = "baz"."fooId" SET "foo.field" = ? WHERE id = 2', $this->mockStatement->getSql()); } /** @@ -283,26 +250,16 @@ public function testUpdateWithJoin() */ public function testUpdateWithJoinDefaultType() { - $mockUpdate = $this->mockSql->update(); - - $joins = [ - [ + $affectedRows = $this->table->update( + ['foo.field' => 'bar'], + 'id = 2', + [[ 'name' => 'baz', 'on' => 'foo.fooId = baz.fooId', - ] - ]; - - // assert select::from() is called - $mockUpdate->expects($this->once()) - ->method('where') - ->with($this->equalTo('id = 2')); - - $mockUpdate->expects($this->once()) - ->method('join') - ->with($joins[0]['name'], $joins[0]['on'], Sql\Join::JOIN_INNER); - - $affectedRows = $this->table->update(['foo.field' => 'bar'], 'id = 2', $joins); + ]] + ); $this->assertEquals(5, $affectedRows); + $this->assertEquals('UPDATE "foo" INNER JOIN "baz" ON "foo"."fooId" = "baz"."fooId" SET "foo.field" = ? WHERE id = 2', $this->mockStatement->getSql()); } /** @@ -312,10 +269,9 @@ public function testUpdateWithJoinDefaultType() */ public function testUpdateWithNoCriteria() { - $mockUpdate = $this->mockSql->update(); - $affectedRows = $this->table->update(['foo' => 'bar']); $this->assertEquals(5, $affectedRows); + $this->assertEquals('UPDATE "foo" SET "foo" = ?', $this->mockStatement->getSql()); } /** @@ -325,15 +281,9 @@ public function testUpdateWithNoCriteria() */ public function testDelete() { - $mockDelete = $this->mockSql->delete(); - - // assert select::from() is called - $mockDelete->expects($this->once()) - ->method('where') - ->with($this->equalTo('foo')); - - $affectedRows = $this->table->delete('foo'); + $affectedRows = $this->table->delete('whereCondition'); $this->assertEquals(5, $affectedRows); + $this->assertEquals('DELETE FROM "foo" WHERE whereCondition', $this->mockStatement->getSql()); } /** @@ -343,6 +293,7 @@ public function testGetLastInsertValue() { $this->table->insert(['foo' => 'bar']); $this->assertEquals(10, $this->table->getLastInsertValue()); + $this->assertEquals('INSERT INTO "foo" ("foo") VALUES (?)', $this->mockStatement->getSql()); } /** @@ -350,11 +301,11 @@ public function testGetLastInsertValue() */ public function test__get() { - $this->table->insert(['foo']); // trigger last insert id update - + $affectedRows = $this->table->insert(['foo' => 'bar']); // trigger last insert id update + $this->assertEquals('INSERT INTO "foo" ("foo") VALUES (?)', $this->mockStatement->getSql()); + $this->assertEquals(5, $affectedRows); $this->assertEquals(10, $this->table->lastInsertValue); $this->assertSame($this->mockAdapter, $this->table->adapter); - //$this->assertEquals('foo', $this->table->table); } /** diff --git a/test/TableGateway/Feature/MasterSlaveFeatureTest.php b/test/TableGateway/Feature/MasterSlaveFeatureTest.php index d66f66a8ad..fa0b9b8298 100644 --- a/test/TableGateway/Feature/MasterSlaveFeatureTest.php +++ b/test/TableGateway/Feature/MasterSlaveFeatureTest.php @@ -28,25 +28,19 @@ class MasterSlaveFeatureTest extends \PHPUnit_Framework_TestCase public function setup() { - $this->mockMasterAdapter = $this->getMock('Zend\Db\Adapter\AdapterInterface'); - $mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); $mockDriver->expects($this->any())->method('createStatement')->will($this->returnValue( $mockStatement )); - $this->mockMasterAdapter->expects($this->any())->method('getDriver')->will($this->returnValue($mockDriver)); - $this->mockMasterAdapter->expects($this->any())->method('getPlatform')->will($this->returnValue(new \Zend\Db\Adapter\Platform\Sql92())); - - $this->mockSlaveAdapter = $this->getMock('Zend\Db\Adapter\AdapterInterface'); + $this->mockMasterAdapter = new \Zend\Db\Adapter\Adapter($mockDriver, new \Zend\Db\Adapter\Platform\Sql92()); $mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); $mockDriver->expects($this->any())->method('createStatement')->will($this->returnValue( $mockStatement )); - $this->mockSlaveAdapter->expects($this->any())->method('getDriver')->will($this->returnValue($mockDriver)); - $this->mockSlaveAdapter->expects($this->any())->method('getPlatform')->will($this->returnValue(new \Zend\Db\Adapter\Platform\Sql92())); + $this->mockSlaveAdapter = new \Zend\Db\Adapter\Adapter($mockDriver, new \Zend\Db\Adapter\Platform\Sql92()); $this->feature = new MasterSlaveFeature($this->mockSlaveAdapter); } diff --git a/test/TableGateway/TableGatewayTest.php b/test/TableGateway/TableGatewayTest.php index b19596a5eb..7e3b334b9c 100644 --- a/test/TableGateway/TableGatewayTest.php +++ b/test/TableGateway/TableGatewayTest.php @@ -163,8 +163,7 @@ public function testInsertShouldResetTableToUnaliasedTable($tableValue, $expecte ->will($this->returnValue($result)); $statementExpectation = function ($insert) use ($phpunit, $expected, $statement) { - $state = $insert->getRawState(); - $phpunit->assertSame($expected, $state['table']); + $phpunit->assertSame($expected, $insert->table); return $statement; }; @@ -194,11 +193,10 @@ public function testInsertShouldResetTableToUnaliasedTable($tableValue, $expecte 'foo' => 'FOO', ]); - $state = $insert->getRawState(); - $this->assertInternalType('array', $state['table']); + $this->assertInternalType('array', $insert->table); $this->assertEquals( $tableValue, - $state['table'] + $insert->table ); } @@ -225,8 +223,7 @@ public function testUpdateShouldResetTableToUnaliasedTable($tableValue, $expecte ->will($this->returnValue($result)); $statementExpectation = function ($update) use ($phpunit, $expected, $statement) { - $state = $update->getRawState(); - $phpunit->assertSame($expected, $state['table']); + $phpunit->assertSame($expected, $update->table); return $statement; }; @@ -258,11 +255,9 @@ public function testUpdateShouldResetTableToUnaliasedTable($tableValue, $expecte 'bar' => 'BAR' ]); - $state = $update->getRawState(); - $this->assertInternalType('array', $state['table']); $this->assertEquals( $tableValue, - $state['table'] + $update->table ); } } diff --git a/test/TestAsset/DeleteBuilder.php b/test/TestAsset/DeleteBuilder.php index f146fe8b2c..ccc8269967 100644 --- a/test/TestAsset/DeleteBuilder.php +++ b/test/TestAsset/DeleteBuilder.php @@ -9,15 +9,6 @@ namespace ZendTest\Db\TestAsset; -use Zend\Db\Sql; - -class DeleteBuilder extends Sql\Delete implements Sql\Builder\PlatformDecoratorInterface +class DeleteBuilder extends \Zend\Db\Sql\Builder\sql92\DeleteBuilder { - protected $subject = null; - - public function setSubject($subject) - { - $this->subject = $subject; - return $this; - } } diff --git a/test/TestAsset/InsertBuilder.php b/test/TestAsset/InsertBuilder.php index cb7b20b015..1bd51c7a98 100644 --- a/test/TestAsset/InsertBuilder.php +++ b/test/TestAsset/InsertBuilder.php @@ -9,15 +9,6 @@ namespace ZendTest\Db\TestAsset; -use Zend\Db\Sql; - -class InsertBuilder extends Sql\Insert implements Sql\Builder\PlatformDecoratorInterface +class InsertBuilder extends \Zend\Db\Sql\Builder\sql92\InsertBuilder { - protected $subject = null; - - public function setSubject($subject) - { - $this->subject = $subject; - return $this; - } } diff --git a/test/TestAsset/SelectBuilder.php b/test/TestAsset/SelectBuilder.php index 7430f6736e..9a87812230 100644 --- a/test/TestAsset/SelectBuilder.php +++ b/test/TestAsset/SelectBuilder.php @@ -9,15 +9,6 @@ namespace ZendTest\Db\TestAsset; -use Zend\Db\Sql; - -class SelectBuilder extends Sql\Select implements Sql\Builder\PlatformDecoratorInterface +class SelectBuilder extends \Zend\Db\Sql\Builder\sql92\SelectBuilder { - protected $subject = null; - - public function setSubject($subject) - { - $this->subject = $subject; - return $this; - } } diff --git a/test/TestAsset/TrustingIbmDb2Platform.php b/test/TestAsset/TrustingIbmDb2Platform.php new file mode 100644 index 0000000000..9543676399 --- /dev/null +++ b/test/TestAsset/TrustingIbmDb2Platform.php @@ -0,0 +1,20 @@ +quoteTrustedValue($value); + } +} diff --git a/test/TestAsset/TrustingSqlitePlatform.php b/test/TestAsset/TrustingSqlitePlatform.php new file mode 100644 index 0000000000..847a35df74 --- /dev/null +++ b/test/TestAsset/TrustingSqlitePlatform.php @@ -0,0 +1,23 @@ +quoteTrustedValue($value); + } +} diff --git a/test/TestAsset/UpdateBuilder.php b/test/TestAsset/UpdateBuilder.php index bcfd4c4967..028747ac89 100644 --- a/test/TestAsset/UpdateBuilder.php +++ b/test/TestAsset/UpdateBuilder.php @@ -9,15 +9,6 @@ namespace ZendTest\Db\TestAsset; -use Zend\Db\Sql; - -class UpdateBuilder extends Sql\Update implements Sql\Builder\PlatformDecoratorInterface +class UpdateBuilder extends \Zend\Db\Sql\Builder\sql92\UpdateBuilder { - protected $subject = null; - - public function setSubject($subject) - { - $this->subject = $subject; - return $this; - } } From 9166f5141b9d073a315a4d17d12f5596dce4d96b Mon Sep 17 00:00:00 2001 From: turrsis Date: Thu, 9 Jul 2015 17:11:55 +0300 Subject: [PATCH 04/30] architecture 03: create Expression builders --- src/Sql/AbstractExpression.php | 93 ---- src/Sql/Builder/AbstractBuilder.php | 21 + src/Sql/Builder/AbstractSqlBuilder.php | 36 +- src/Sql/Builder/Builder.php | 73 ++++ .../Column/AbstractLengthColumnBuilder.php | 32 ++ .../Column/AbstractPrecisionColumnBuilder.php | 22 + .../Column/AbstractTimestampColumnBuilder.php | 56 +++ .../sql92/Ddl/Column/ColumnBuilder.php | 60 +++ .../sql92/Ddl/Column/IntegerBuilder.php | 28 ++ .../sql92/Ddl/Constraint/AbstractBuilder.php | 67 +++ .../sql92/Ddl/Constraint/CheckBuilder.php | 46 ++ .../Ddl/Constraint/ForeignKeyBuilder.php | 58 +++ .../Ddl/Constraint/PrimaryKeyBuilder.php | 18 + .../sql92/Ddl/Constraint/UniqueKeyBuilder.php | 18 + .../Builder/sql92/Ddl/Index/IndexBuilder.php | 47 ++ src/Sql/Builder/sql92/ExpressionBuilder.php | 50 +++ src/Sql/Builder/sql92/LiteralBuilder.php | 30 ++ .../sql92/Predicate/BetweenBuilder.php | 36 ++ src/Sql/Builder/sql92/Predicate/InBuilder.php | 58 +++ .../sql92/Predicate/IsNotNullBuilder.php | 15 + .../Builder/sql92/Predicate/IsNullBuilder.php | 35 ++ .../Builder/sql92/Predicate/LikeBuilder.php | 38 ++ .../sql92/Predicate/NotBetweenBuilder.php | 36 ++ .../Builder/sql92/Predicate/NotInBuilder.php | 15 + .../sql92/Predicate/NotLikeBuilder.php | 15 + .../sql92/Predicate/OperatorBuilder.php | 33 ++ .../sql92/Predicate/PredicateBuilder.php | 14 + .../sql92/Predicate/PredicateSetBuilder.php | 51 +++ src/Sql/Ddl/Column/AbstractLengthColumn.php | 22 - .../Ddl/Column/AbstractPrecisionColumn.php | 12 - .../Ddl/Column/AbstractTimestampColumn.php | 44 -- src/Sql/Ddl/Column/Column.php | 46 +- src/Sql/Ddl/Column/Float.php | 48 --- src/Sql/Ddl/Column/Integer.php | 14 - src/Sql/Ddl/Constraint/AbstractConstraint.php | 47 -- src/Sql/Ddl/Constraint/Check.php | 34 +- src/Sql/Ddl/Constraint/ForeignKey.php | 46 -- src/Sql/Ddl/Constraint/PrimaryKey.php | 4 - src/Sql/Ddl/Constraint/UniqueKey.php | 4 - src/Sql/Ddl/Index/Index.php | 52 +-- src/Sql/Expression.php | 109 +---- src/Sql/ExpressionInterface.php | 21 +- src/Sql/ExpressionParameter.php | 150 +++++++ src/Sql/Literal.php | 12 - src/Sql/Predicate/Between.php | 58 +-- src/Sql/Predicate/Expression.php | 16 +- src/Sql/Predicate/In.php | 75 +--- src/Sql/Predicate/IsNotNull.php | 1 - src/Sql/Predicate/IsNull.php | 50 +-- src/Sql/Predicate/Like.php | 51 +-- src/Sql/Predicate/Literal.php | 2 +- src/Sql/Predicate/NotBetween.php | 1 - src/Sql/Predicate/NotIn.php | 1 - src/Sql/Predicate/NotLike.php | 1 - src/Sql/Predicate/Operator.php | 142 +------ src/Sql/Predicate/Predicate.php | 36 +- src/Sql/Predicate/PredicateSet.php | 29 -- test/Sql/Builder/AllBuildersTest.php | 13 +- .../Builder/Ddl/Column/ColumnBuilderTest.php | 381 +++++++++++++++++ .../Ddl/Constraint/CheckBuilderTest.php | 45 ++ .../Ddl/Constraint/ForeignKeyBuilderTest.php | 47 ++ .../Ddl/Constraint/PrimaryKeyBuilderTest.php | 42 ++ .../Ddl/Constraint/UniqueKeyBuilderTest.php | 43 ++ .../Builder/Ddl/Index/IndexBuilderTest.php | 84 ++++ test/Sql/Builder/ExpressionBuilderTest.php | 107 +++++ test/Sql/Builder/LiteralBuilderTest.php | 58 +++ .../Builder/Predicate/BetweenBuilderTest.php | 68 +++ test/Sql/Builder/Predicate/InBuilderTest.php | 135 ++++++ .../Predicate/IsNotNullBuilderTest.php | 44 ++ .../Sql/Builder/Predicate/LikeBuilderTest.php | 54 +++ .../Predicate/NotBetweenBuilderTest.php | 68 +++ .../Builder/Predicate/NotInBuilderTest.php | 101 +++++ .../Builder/Predicate/NotLikeBuilderTest.php | 43 ++ .../Builder/Predicate/OperatorBuilderTest.php | 47 ++ .../Predicate/PredicateBuilderTest.php | 400 ++++++++++++++++++ .../Predicate/PredicateSetBuilderTest.php | 89 ++++ test/Sql/Builder/SelectBuilderTest.php | 11 +- .../Ddl/Column/AbstractLengthColumnTest.php | 15 - .../Column/AbstractPrecisionColumnTest.php | 15 - test/Sql/Ddl/Column/BigIntegerTest.php | 12 - test/Sql/Ddl/Column/BinaryTest.php | 27 -- test/Sql/Ddl/Column/BlobTest.php | 27 -- test/Sql/Ddl/Column/BooleanTest.php | 12 - test/Sql/Ddl/Column/CharTest.php | 27 -- test/Sql/Ddl/Column/ColumnTest.php | 25 -- test/Sql/Ddl/Column/DateTest.php | 27 -- test/Sql/Ddl/Column/DatetimeTest.php | 27 -- test/Sql/Ddl/Column/DecimalTest.php | 27 -- test/Sql/Ddl/Column/FloatTest.php | 28 -- test/Sql/Ddl/Column/FloatingTest.php | 31 -- test/Sql/Ddl/Column/IntegerTest.php | 24 -- test/Sql/Ddl/Column/TextTest.php | 27 -- test/Sql/Ddl/Column/TimeTest.php | 27 -- test/Sql/Ddl/Column/TimestampTest.php | 27 -- test/Sql/Ddl/Column/VarbinaryTest.php | 27 -- test/Sql/Ddl/Column/VarcharTest.php | 33 -- test/Sql/Ddl/Constraint/CheckTest.php | 31 -- test/Sql/Ddl/Constraint/ForeignKeyTest.php | 16 - test/Sql/Ddl/Constraint/PrimaryKeyTest.php | 31 -- test/Sql/Ddl/Constraint/UniqueKeyTest.php | 31 -- test/Sql/Ddl/Index/IndexTest.php | 63 --- test/Sql/ExpressionTest.php | 78 +--- test/Sql/LiteralTest.php | 18 - test/Sql/Predicate/BetweenTest.php | 70 +-- test/Sql/Predicate/ExpressionTest.php | 120 ++++-- test/Sql/Predicate/InTest.php | 95 +---- test/Sql/Predicate/IsNullTest.php | 29 +- test/Sql/Predicate/LikeTest.php | 30 +- test/Sql/Predicate/LiteralTest.php | 6 - test/Sql/Predicate/NotBetweenTest.php | 60 --- test/Sql/Predicate/NotInTest.php | 66 --- test/Sql/Predicate/NotLikeTest.php | 26 +- test/Sql/Predicate/OperatorTest.php | 64 +-- test/Sql/Predicate/PredicateSetTest.php | 65 --- test/Sql/Predicate/PredicateTest.php | 288 +------------ test/TestAsset/ExpressionBuilder.php | 24 ++ 116 files changed, 3294 insertions(+), 2491 deletions(-) delete mode 100644 src/Sql/AbstractExpression.php create mode 100644 src/Sql/Builder/sql92/Ddl/Column/AbstractLengthColumnBuilder.php create mode 100644 src/Sql/Builder/sql92/Ddl/Column/AbstractPrecisionColumnBuilder.php create mode 100644 src/Sql/Builder/sql92/Ddl/Column/AbstractTimestampColumnBuilder.php create mode 100644 src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php create mode 100644 src/Sql/Builder/sql92/Ddl/Column/IntegerBuilder.php create mode 100644 src/Sql/Builder/sql92/Ddl/Constraint/AbstractBuilder.php create mode 100644 src/Sql/Builder/sql92/Ddl/Constraint/CheckBuilder.php create mode 100644 src/Sql/Builder/sql92/Ddl/Constraint/ForeignKeyBuilder.php create mode 100644 src/Sql/Builder/sql92/Ddl/Constraint/PrimaryKeyBuilder.php create mode 100644 src/Sql/Builder/sql92/Ddl/Constraint/UniqueKeyBuilder.php create mode 100644 src/Sql/Builder/sql92/Ddl/Index/IndexBuilder.php create mode 100644 src/Sql/Builder/sql92/ExpressionBuilder.php create mode 100644 src/Sql/Builder/sql92/LiteralBuilder.php create mode 100644 src/Sql/Builder/sql92/Predicate/BetweenBuilder.php create mode 100644 src/Sql/Builder/sql92/Predicate/InBuilder.php create mode 100644 src/Sql/Builder/sql92/Predicate/IsNotNullBuilder.php create mode 100644 src/Sql/Builder/sql92/Predicate/IsNullBuilder.php create mode 100644 src/Sql/Builder/sql92/Predicate/LikeBuilder.php create mode 100644 src/Sql/Builder/sql92/Predicate/NotBetweenBuilder.php create mode 100644 src/Sql/Builder/sql92/Predicate/NotInBuilder.php create mode 100644 src/Sql/Builder/sql92/Predicate/NotLikeBuilder.php create mode 100644 src/Sql/Builder/sql92/Predicate/OperatorBuilder.php create mode 100644 src/Sql/Builder/sql92/Predicate/PredicateBuilder.php create mode 100644 src/Sql/Builder/sql92/Predicate/PredicateSetBuilder.php delete mode 100644 src/Sql/Ddl/Column/Float.php create mode 100644 src/Sql/ExpressionParameter.php create mode 100644 test/Sql/Builder/Ddl/Column/ColumnBuilderTest.php create mode 100644 test/Sql/Builder/Ddl/Constraint/CheckBuilderTest.php create mode 100644 test/Sql/Builder/Ddl/Constraint/ForeignKeyBuilderTest.php create mode 100644 test/Sql/Builder/Ddl/Constraint/PrimaryKeyBuilderTest.php create mode 100644 test/Sql/Builder/Ddl/Constraint/UniqueKeyBuilderTest.php create mode 100644 test/Sql/Builder/Ddl/Index/IndexBuilderTest.php create mode 100644 test/Sql/Builder/ExpressionBuilderTest.php create mode 100644 test/Sql/Builder/LiteralBuilderTest.php create mode 100644 test/Sql/Builder/Predicate/BetweenBuilderTest.php create mode 100644 test/Sql/Builder/Predicate/InBuilderTest.php create mode 100644 test/Sql/Builder/Predicate/IsNotNullBuilderTest.php create mode 100644 test/Sql/Builder/Predicate/LikeBuilderTest.php create mode 100644 test/Sql/Builder/Predicate/NotBetweenBuilderTest.php create mode 100644 test/Sql/Builder/Predicate/NotInBuilderTest.php create mode 100644 test/Sql/Builder/Predicate/NotLikeBuilderTest.php create mode 100644 test/Sql/Builder/Predicate/OperatorBuilderTest.php create mode 100644 test/Sql/Builder/Predicate/PredicateBuilderTest.php create mode 100644 test/Sql/Builder/Predicate/PredicateSetBuilderTest.php delete mode 100644 test/Sql/Ddl/Column/BinaryTest.php delete mode 100644 test/Sql/Ddl/Column/BlobTest.php delete mode 100644 test/Sql/Ddl/Column/CharTest.php delete mode 100644 test/Sql/Ddl/Column/DateTest.php delete mode 100644 test/Sql/Ddl/Column/DatetimeTest.php delete mode 100644 test/Sql/Ddl/Column/DecimalTest.php delete mode 100644 test/Sql/Ddl/Column/FloatTest.php delete mode 100644 test/Sql/Ddl/Column/FloatingTest.php delete mode 100644 test/Sql/Ddl/Column/TextTest.php delete mode 100644 test/Sql/Ddl/Column/TimeTest.php delete mode 100644 test/Sql/Ddl/Column/TimestampTest.php delete mode 100644 test/Sql/Ddl/Column/VarbinaryTest.php delete mode 100644 test/Sql/Ddl/Column/VarcharTest.php delete mode 100644 test/Sql/Ddl/Constraint/CheckTest.php delete mode 100644 test/Sql/Ddl/Constraint/PrimaryKeyTest.php delete mode 100644 test/Sql/Ddl/Constraint/UniqueKeyTest.php delete mode 100644 test/Sql/Ddl/Index/IndexTest.php delete mode 100644 test/Sql/Predicate/NotBetweenTest.php delete mode 100644 test/Sql/Predicate/NotInTest.php create mode 100644 test/TestAsset/ExpressionBuilder.php diff --git a/src/Sql/AbstractExpression.php b/src/Sql/AbstractExpression.php deleted file mode 100644 index b5a4a9fa8e..0000000000 --- a/src/Sql/AbstractExpression.php +++ /dev/null @@ -1,93 +0,0 @@ -buildNormalizedArgument($argument, self::TYPE_VALUE); - } - - if (is_scalar($argument) || $argument === null) { - return $this->buildNormalizedArgument($argument, $defaultType); - } - - if (is_array($argument)) { - $value = current($argument); - - if ($value instanceof ExpressionInterface || $value instanceof SqlObjectInterface) { - return $this->buildNormalizedArgument($value, self::TYPE_VALUE); - } - - $key = key($argument); - - if (is_integer($key) && ! in_array($value, $this->allowedTypes)) { - return $this->buildNormalizedArgument($value, $defaultType); - } - - return $this->buildNormalizedArgument($key, $value); - } - - throw new Exception\InvalidArgumentException(sprintf( - '$argument should be %s or %s or %s or %s or %s, "%s" given', - 'null', - 'scalar', - 'array', - 'Zend\Db\Sql\ExpressionInterface', - 'Zend\Db\Sql\SqlObjectInterface', - is_object($argument) ? get_class($argument) : gettype($argument) - )); - } - - /** - * @param mixed $argument - * @param string $argumentType - * - * @return array - * - * @throws Exception\InvalidArgumentException - */ - private function buildNormalizedArgument($argument, $argumentType) - { - if (! in_array($argumentType, $this->allowedTypes)) { - throw new Exception\InvalidArgumentException(sprintf( - 'Argument type should be in array(%s)', - implode(',', $this->allowedTypes) - )); - } - - return [ - $argument, - $argumentType, - ]; - } -} diff --git a/src/Sql/Builder/AbstractBuilder.php b/src/Sql/Builder/AbstractBuilder.php index 48aa0a4f42..518a74f484 100644 --- a/src/Sql/Builder/AbstractBuilder.php +++ b/src/Sql/Builder/AbstractBuilder.php @@ -12,4 +12,25 @@ abstract class AbstractBuilder { abstract protected function buildSqlString($sqlObject, Context $context); + + /** + * + * @param mixed $argument + * @param string $class + * @param string $method + * @return null + * @throws \Zend\Db\Sql\Exception\InvalidArgumentException + */ + protected function validateSqlObject($argument, $class, $method) + { + if ($argument instanceof $class) { + return; + } + throw new \Zend\Db\Sql\Exception\InvalidArgumentException(sprintf( + 'Argument 1 passed to %s must be an instance of %s, instance of %s given', + $method . '()', + $class, + is_object($argument) ? get_class($argument) : gettype($argument) + )); + } } diff --git a/src/Sql/Builder/AbstractSqlBuilder.php b/src/Sql/Builder/AbstractSqlBuilder.php index dd01a6a2b2..103dc1bcd2 100644 --- a/src/Sql/Builder/AbstractSqlBuilder.php +++ b/src/Sql/Builder/AbstractSqlBuilder.php @@ -156,7 +156,7 @@ private function buildExpression(ExpressionInterface $expression, Context $conte { $sql = ''; - $parts = $expression->getExpressionData(); + $parts = $this->platformBuilder->getPlatformBuilder($expression, $context)->getExpressionData($expression, $context); foreach ($parts as $part) { // #7407: use $expression->getExpression() to get the unescaped @@ -183,41 +183,29 @@ private function buildExpression(ExpressionInterface $expression, Context $conte // build_ values and types (the middle and last position of the // expression data) - $values = $part[1]; - $types = isset($part[2]) ? $part[2] : []; - foreach ($values as $vIndex => $value) { - if (!isset($types[$vIndex])) { - continue; - } - $type = $types[$vIndex]; + $parameters = $part[1]; + foreach ($parameters as $pIndex => &$parameter) { + $value = $parameter->getValue(); + $type = $parameter->getType(); if ($value instanceof SelectableInterface) { - // build_ sub-select - $values[$vIndex] = '(' . $this->buildSubSelect($value, $context) . ')'; + $parameter = '(' . $this->buildSubSelect($value, $context) . ')'; } elseif ($value instanceof ExpressionInterface) { - // recursive call to satisfy nested expressions - $values[$vIndex] = $this->buildSqlString($value, $context); + $parameter = $this->buildSqlString($value, $context); } elseif ($type == ExpressionInterface::TYPE_IDENTIFIER) { - $values[$vIndex] = $context->getPlatform()->quoteIdentifierInFragment($value); + $parameter = $context->getPlatform()->quoteIdentifierInFragment($value); } elseif ($type == ExpressionInterface::TYPE_VALUE) { - // if prepareType is set, it means that this particular value must be - // passed back to the statement in a way it can be used as a placeholder value + $parameter = $context->getPlatform()->quoteValue($value); if ($context->getParameterContainer()) { $name = $context->getNestedAlias('expr'); $context->getParameterContainer()->offsetSet($name, $value); - $values[$vIndex] = $context->getDriver()->formatParameterName($name); - continue; + $parameter = $context->getDriver()->formatParameterName($name); } - - // if not a preparable statement, simply quote the value and move on - $values[$vIndex] = $context->getPlatform()->quoteValue($value); } elseif ($type == ExpressionInterface::TYPE_LITERAL) { - $values[$vIndex] = $value; + $parameter = $value; } } - // after looping the values, interpolate them into the sql string - // (they might be placeholder names, or values) - $sql .= vsprintf($part[0], $values); + $sql .= vsprintf($part[0], $parameters); } return $sql; diff --git a/src/Sql/Builder/Builder.php b/src/Sql/Builder/Builder.php index ca3da5e2e8..cc01fe1da9 100644 --- a/src/Sql/Builder/Builder.php +++ b/src/Sql/Builder/Builder.php @@ -57,6 +57,79 @@ class Builder extends AbstractBuilder 'Zend\Db\Sql\Ddl\DropTable' => [ 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\DropTableBuilder', ], + + 'Zend\Db\Sql\Predicate\NotBetween' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Predicate\NotBetweenBuilder', + ], + 'Zend\Db\Sql\Predicate\Between' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Predicate\BetweenBuilder', + ], + 'Zend\Db\Sql\Predicate\NotIn' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Predicate\NotInBuilder', + ], + 'Zend\Db\Sql\Predicate\In' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Predicate\InBuilder', + ], + 'Zend\Db\Sql\Predicate\IsNotNull' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Predicate\IsNotNullBuilder', + ], + 'Zend\Db\Sql\Predicate\IsNull' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Predicate\IsNullBuilder', + ], + 'Zend\Db\Sql\Predicate\NotLike' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Predicate\NotLikeBuilder', + ], + 'Zend\Db\Sql\Predicate\Like' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Predicate\LikeBuilder', + ], + 'Zend\Db\Sql\Predicate\Operator' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Predicate\OperatorBuilder', + ], + 'Zend\Db\Sql\Predicate\PredicateSet' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Predicate\PredicateSetBuilder', + ], + 'Zend\Db\Sql\Predicate\Predicate' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Predicate\PredicateBuilder', + ], + 'Zend\Db\Sql\Ddl\Column\AbstractPrecisionColumn' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\Column\AbstractPrecisionColumnBuilder', + ], + 'Zend\Db\Sql\Ddl\Column\AbstractLengthColumn' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\Column\AbstractLengthColumnBuilder', + ], + 'Zend\Db\Sql\Ddl\Column\AbstractTimestampColumn' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\Column\AbstractTimestampColumnBuilder', + ], + 'Zend\Db\Sql\Ddl\Column\Integer' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\Column\IntegerBuilder', + ], + 'Zend\Db\Sql\Ddl\Column\Column' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\Column\ColumnBuilder', + ], + 'Zend\Db\Sql\Ddl\Index\Index' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\Index\IndexBuilder', + ], + 'Zend\Db\Sql\Ddl\Constraint\UniqueKey' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\Constraint\UniqueKeyBuilder', + ], + 'Zend\Db\Sql\Ddl\Constraint\PrimaryKey' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\Constraint\PrimaryKeyBuilder', + ], + 'Zend\Db\Sql\Ddl\Constraint\ForeignKey' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\Constraint\ForeignKeyBuilder', + ], + 'Zend\Db\Sql\Ddl\Constraint\Check' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\Constraint\CheckBuilder', + ], + 'Zend\Db\Sql\Ddl\Constraint\AbstractConstraint' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\Constraint\AbstractBuilder', + ], + 'Zend\Db\Sql\Literal' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\LiteralBuilder', + ], + 'Zend\Db\Sql\Expression' => [ + 'sql92' => 'Zend\Db\Sql\Builder\sql92\ExpressionBuilder', + ], ]; /** diff --git a/src/Sql/Builder/sql92/Ddl/Column/AbstractLengthColumnBuilder.php b/src/Sql/Builder/sql92/Ddl/Column/AbstractLengthColumnBuilder.php new file mode 100644 index 0000000000..d2252eccaf --- /dev/null +++ b/src/Sql/Builder/sql92/Ddl/Column/AbstractLengthColumnBuilder.php @@ -0,0 +1,32 @@ +validateSqlObject($column, 'Zend\Db\Sql\Ddl\Column\AbstractLengthColumn', __METHOD__); + $data = parent::getExpressionData($column, $context); + + if ($this->getLengthExpression($column)) { + $data[0][1][1]->setValue($data[0][1][1]->getValue() . '(' . $this->getLengthExpression($column) . ')'); + } + + return $data; + } + + protected function getLengthExpression($column) + { + return (string) $column->getLength(); + } +} diff --git a/src/Sql/Builder/sql92/Ddl/Column/AbstractPrecisionColumnBuilder.php b/src/Sql/Builder/sql92/Ddl/Column/AbstractPrecisionColumnBuilder.php new file mode 100644 index 0000000000..909edff9e2 --- /dev/null +++ b/src/Sql/Builder/sql92/Ddl/Column/AbstractPrecisionColumnBuilder.php @@ -0,0 +1,22 @@ +getDecimal() !== null) { + return $column->getLength() . ',' . $column->getDecimal(); + } + + return $column->getLength(); + } +} diff --git a/src/Sql/Builder/sql92/Ddl/Column/AbstractTimestampColumnBuilder.php b/src/Sql/Builder/sql92/Ddl/Column/AbstractTimestampColumnBuilder.php new file mode 100644 index 0000000000..7b4614ba18 --- /dev/null +++ b/src/Sql/Builder/sql92/Ddl/Column/AbstractTimestampColumnBuilder.php @@ -0,0 +1,56 @@ +validateSqlObject($column, 'Zend\Db\Sql\Ddl\Column\AbstractTimestampColumn', __METHOD__); + $spec = $this->specification; + + $params = [ + new ExpressionParameter($column->getName(), ExpressionInterface::TYPE_IDENTIFIER), + new ExpressionParameter($column->getType(), ExpressionInterface::TYPE_LITERAL), + ]; + + if (!$column->isNullable()) { + $spec .= ' NOT NULL'; + } + + if ($column->getDefault() !== null) { + $spec .= ' DEFAULT %s'; + $params[] = new ExpressionParameter($column->getDefault(), ExpressionInterface::TYPE_VALUE); + } + + $options = $column->getOptions(); + + if (isset($options['on_update'])) { + $spec .= ' %s'; + $params[] = new ExpressionParameter('ON UPDATE CURRENT_TIMESTAMP', ExpressionInterface::TYPE_LITERAL); + } + + $data = [[ + $spec, + $params, + ]]; + + foreach ($column->getConstraints() as $constraint) { + $data[] = ' '; + $data = array_merge($data, $this->platformBuilder->getPlatformBuilder($constraint, $context)->getExpressionData($constraint, $context)); + } + + return $data; + } +} diff --git a/src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php b/src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php new file mode 100644 index 0000000000..04ff740d17 --- /dev/null +++ b/src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php @@ -0,0 +1,60 @@ +validateSqlObject($column, 'Zend\Db\Sql\Ddl\Column\Column', __METHOD__); + $spec = $this->specification; + + $params = [ + new ExpressionParameter($column->getName(), ExpressionInterface::TYPE_IDENTIFIER), + new ExpressionParameter($column->getType(), ExpressionInterface::TYPE_LITERAL), + ]; + + if (!$column->isNullable()) { + $spec .= ' NOT NULL'; + } + + if ($column->getDefault() !== null) { + $spec .= ' DEFAULT %s'; + $params[] = new ExpressionParameter($column->getDefault(), ExpressionInterface::TYPE_VALUE); + } + + $data = [[ + $spec, + $params, + ]]; + + foreach ($column->getConstraints() as $constraint) { + $data[] = ' '; + $data = array_merge( + $data, + $this->platformBuilder->getPlatformBuilder($constraint, $context)->getExpressionData($constraint, $context) + ); + } + + return $data; + } +} diff --git a/src/Sql/Builder/sql92/Ddl/Column/IntegerBuilder.php b/src/Sql/Builder/sql92/Ddl/Column/IntegerBuilder.php new file mode 100644 index 0000000000..6f61b89578 --- /dev/null +++ b/src/Sql/Builder/sql92/Ddl/Column/IntegerBuilder.php @@ -0,0 +1,28 @@ +validateSqlObject($column, 'Zend\Db\Sql\Ddl\Column\Integer', __METHOD__); + $data = parent::getExpressionData($column, $context); + $options = $column->getOptions(); + + if (isset($options['length'])) { + $data[0][1][1] .= '(' . $options['length'] . ')'; + } + + return $data; + } +} diff --git a/src/Sql/Builder/sql92/Ddl/Constraint/AbstractBuilder.php b/src/Sql/Builder/sql92/Ddl/Constraint/AbstractBuilder.php new file mode 100644 index 0000000000..98840321b8 --- /dev/null +++ b/src/Sql/Builder/sql92/Ddl/Constraint/AbstractBuilder.php @@ -0,0 +1,67 @@ +validateSqlObject($constraint, 'Zend\Db\Sql\Ddl\Constraint\ConstraintInterface', __METHOD__); + $parameters = []; + $spec = ''; + + if ($constraint->getName()) { + $spec .= $this->namedSpecification; + $parameters[] = new ExpressionParameter($constraint->getName(), ExpressionInterface::TYPE_IDENTIFIER); + } + + $spec .= $this->specification; + + if ($constraint->getColumns()) { + foreach ($constraint->getColumns() as $column) { + $parameters[] = new ExpressionParameter($column, ExpressionInterface::TYPE_IDENTIFIER); + } + $spec .= sprintf( + $this->columnSpecification, + rtrim(str_repeat('%s, ', count($constraint->getColumns())), ', ') + ); + } + + return [[ + $spec, + $parameters, + ]]; + } +} diff --git a/src/Sql/Builder/sql92/Ddl/Constraint/CheckBuilder.php b/src/Sql/Builder/sql92/Ddl/Constraint/CheckBuilder.php new file mode 100644 index 0000000000..feb7181dc1 --- /dev/null +++ b/src/Sql/Builder/sql92/Ddl/Constraint/CheckBuilder.php @@ -0,0 +1,46 @@ +validateSqlObject($check, 'Zend\Db\Sql\Ddl\Constraint\Check', __METHOD__); + $values = []; + $spec = ''; + + if ($check->getName()) { + $spec .= $this->namedSpecification; + $values[] = new ExpressionParameter($check->getName(), ExpressionInterface::TYPE_IDENTIFIER); + } + + $values[] = new ExpressionParameter($check->getExpression(), ExpressionInterface::TYPE_LITERAL); + + return [[ + $spec . $this->specification, + $values, + ]]; + } +} diff --git a/src/Sql/Builder/sql92/Ddl/Constraint/ForeignKeyBuilder.php b/src/Sql/Builder/sql92/Ddl/Constraint/ForeignKeyBuilder.php new file mode 100644 index 0000000000..00bbe26578 --- /dev/null +++ b/src/Sql/Builder/sql92/Ddl/Constraint/ForeignKeyBuilder.php @@ -0,0 +1,58 @@ +validateSqlObject($constraint, 'Zend\Db\Sql\Ddl\Constraint\ForeignKey', __METHOD__); + $data = parent::getExpressionData($constraint, $context); + $parameters = &$data[0][1]; + $parameters[] = new ExpressionParameter($constraint->getReferenceTable(), ExpressionInterface::TYPE_IDENTIFIER); + + $spec = ''; + foreach ($constraint->getReferenceColumn() as $refColumn) { + $parameters[] = new ExpressionParameter($refColumn, ExpressionInterface::TYPE_IDENTIFIER); + $spec .= '%s, '; + } + if ($spec) { + $spec = '(' . rtrim($spec, ', ') . ') '; + } + + $data[0][0] .= $this->referenceSpecification[0] . $spec . $this->referenceSpecification[1]; + $parameters[] = new ExpressionParameter($constraint->getOnDeleteRule(), ExpressionInterface::TYPE_LITERAL); + $parameters[] = new ExpressionParameter($constraint->getOnUpdateRule(), ExpressionInterface::TYPE_LITERAL); + + return $data; + } +} diff --git a/src/Sql/Builder/sql92/Ddl/Constraint/PrimaryKeyBuilder.php b/src/Sql/Builder/sql92/Ddl/Constraint/PrimaryKeyBuilder.php new file mode 100644 index 0000000000..4f290f83c5 --- /dev/null +++ b/src/Sql/Builder/sql92/Ddl/Constraint/PrimaryKeyBuilder.php @@ -0,0 +1,18 @@ +validateSqlObject($index, 'Zend\Db\Sql\Ddl\Index\AbstractIndex', __METHOD__); + $properties = [ + new ExpressionParameter($index->getName() ?: '', ExpressionInterface::TYPE_IDENTIFIER) + ]; + + $spec = ''; + foreach ($index->getColumns() as $i => $column) { + $properties[] = new ExpressionParameter($column, ExpressionInterface::TYPE_IDENTIFIER); + $spec .= '%s' . (isset($index->getLengths()[$i]) ? '(' . $index->getLengths()[$i] . ')' : '') . ', '; + } + + return [[ + str_replace('...', rtrim($spec, ', '), $this->specification), + $properties, + ]]; + } +} diff --git a/src/Sql/Builder/sql92/ExpressionBuilder.php b/src/Sql/Builder/sql92/ExpressionBuilder.php new file mode 100644 index 0000000000..4c8c4f13f5 --- /dev/null +++ b/src/Sql/Builder/sql92/ExpressionBuilder.php @@ -0,0 +1,50 @@ +validateSqlObject($expression, 'Zend\Db\Sql\Expression', __METHOD__); + $parameters = (is_scalar($expression->getParameters())) ? [$expression->getParameters()] : $expression->getParameters(); + $parametersCount = count($parameters); + $expression = str_replace('%', '%%', $expression->getExpression()); + + if ($parametersCount == 0) { + return [ + str_ireplace(Expression::PLACEHOLDER, '', $expression) + ]; + } + + // assign locally, escaping % signs + $expression = str_replace(Expression::PLACEHOLDER, '%s', $expression, $count); + // test number of replacements without considering same variable begin used many times first, which is + // faster, if the test fails then resort to regex wich are slow and used rarely + if ($count !== $parametersCount && $parametersCount === preg_match_all('/\:[a-zA-Z0-9_]*/', $expression)) { + throw new Exception\RuntimeException('The number of replacements in the expression does not match the number of parameters'); + } + return [[ + $expression, + $parameters, + ]]; + } +} diff --git a/src/Sql/Builder/sql92/LiteralBuilder.php b/src/Sql/Builder/sql92/LiteralBuilder.php new file mode 100644 index 0000000000..8edc520b7e --- /dev/null +++ b/src/Sql/Builder/sql92/LiteralBuilder.php @@ -0,0 +1,30 @@ +validateSqlObject($expression, 'Zend\Db\Sql\Literal', __METHOD__); + return [[ + str_replace('%', '%%', $expression->getLiteral()), + [], + ]]; + } +} diff --git a/src/Sql/Builder/sql92/Predicate/BetweenBuilder.php b/src/Sql/Builder/sql92/Predicate/BetweenBuilder.php new file mode 100644 index 0000000000..c3400ec8b4 --- /dev/null +++ b/src/Sql/Builder/sql92/Predicate/BetweenBuilder.php @@ -0,0 +1,36 @@ +validateSqlObject($expression, 'Zend\Db\Sql\Predicate\Between', __METHOD__); + return [[ + $this->specification, + [ + $expression->getIdentifier(), + $expression->getMinValue(), + $expression->getMaxValue(), + ], + ]]; + } +} diff --git a/src/Sql/Builder/sql92/Predicate/InBuilder.php b/src/Sql/Builder/sql92/Predicate/InBuilder.php new file mode 100644 index 0000000000..9e9915bae8 --- /dev/null +++ b/src/Sql/Builder/sql92/Predicate/InBuilder.php @@ -0,0 +1,58 @@ +validateSqlObject($expression, 'Zend\Db\Sql\Predicate\In', __METHOD__); + $identifier = $expression->getIdentifier(); + $values = $expression->getValueSet(); + $replacements = []; + + if (is_array($identifier)) { + $identifierSpecFragment = '(' . implode(', ', array_fill(0, count($identifier), '%s')) . ')'; + $replacements = $expression->getIdentifier(); + } else { + $identifierSpecFragment = '%s'; + $replacements[] = $expression->getIdentifier(); + } + + if (is_array($values)) { + $replacements = array_merge($replacements, $values); + $specification = vsprintf( + $this->specification, + [$identifierSpecFragment, '(' . implode(', ', array_fill(0, count($values), '%s')) . ')'] + ); + } else { + $specification = vsprintf( + $this->specification, + [$identifierSpecFragment, '%s'] + ); + $replacements[] = $values; + } + + return [[ + $specification, + $replacements, + ]]; + } +} diff --git a/src/Sql/Builder/sql92/Predicate/IsNotNullBuilder.php b/src/Sql/Builder/sql92/Predicate/IsNotNullBuilder.php new file mode 100644 index 0000000000..6eae0d9b8f --- /dev/null +++ b/src/Sql/Builder/sql92/Predicate/IsNotNullBuilder.php @@ -0,0 +1,15 @@ +validateSqlObject($expression, 'Zend\Db\Sql\Predicate\IsNull', __METHOD__); + return [[ + $this->specification, + [$expression->getIdentifier()], + ]]; + } +} diff --git a/src/Sql/Builder/sql92/Predicate/LikeBuilder.php b/src/Sql/Builder/sql92/Predicate/LikeBuilder.php new file mode 100644 index 0000000000..18cc51754c --- /dev/null +++ b/src/Sql/Builder/sql92/Predicate/LikeBuilder.php @@ -0,0 +1,38 @@ +validateSqlObject($expression, 'Zend\Db\Sql\Predicate\Like', __METHOD__); + return [[ + $this->specification, + [ + $expression->getIdentifier(), + $expression->getLike(), + ], + ]]; + } +} diff --git a/src/Sql/Builder/sql92/Predicate/NotBetweenBuilder.php b/src/Sql/Builder/sql92/Predicate/NotBetweenBuilder.php new file mode 100644 index 0000000000..4d0f845fc6 --- /dev/null +++ b/src/Sql/Builder/sql92/Predicate/NotBetweenBuilder.php @@ -0,0 +1,36 @@ +validateSqlObject($expression, 'Zend\Db\Sql\Predicate\NotBetween', __METHOD__); + return [[ + $this->specification, + [ + $expression->getIdentifier(), + $expression->getMinValue(), + $expression->getMaxValue(), + ], + ]]; + } +} diff --git a/src/Sql/Builder/sql92/Predicate/NotInBuilder.php b/src/Sql/Builder/sql92/Predicate/NotInBuilder.php new file mode 100644 index 0000000000..cb431013b9 --- /dev/null +++ b/src/Sql/Builder/sql92/Predicate/NotInBuilder.php @@ -0,0 +1,15 @@ +validateSqlObject($expression, 'Zend\Db\Sql\Predicate\Operator', __METHOD__); + return [[ + '%s ' . $expression->getOperator() . ' %s', + [ + $expression->getLeft(), + $expression->getRight(), + ], + ]]; + } +} diff --git a/src/Sql/Builder/sql92/Predicate/PredicateBuilder.php b/src/Sql/Builder/sql92/Predicate/PredicateBuilder.php new file mode 100644 index 0000000000..6ec9b0ed9a --- /dev/null +++ b/src/Sql/Builder/sql92/Predicate/PredicateBuilder.php @@ -0,0 +1,14 @@ +validateSqlObject($expression, 'Zend\Db\Sql\Predicate\PredicateSet', __METHOD__); + $predicates = $expression->getPredicates(); + $parts = []; + for ($i = 0, $count = count($predicates); $i < $count; $i++) { + /** @var $predicate PredicateInterface */ + $predicate = $predicates[$i][1]; + + if ($predicate instanceof PredicateSet) { + $parts[] = '('; + } + + $parts = array_merge( + $parts, + $this->platformBuilder->getPlatformBuilder($predicate, $context)->getExpressionData($predicate, $context) + ); + + if ($predicate instanceof PredicateSet) { + $parts[] = ')'; + } + + if (isset($predicates[$i+1])) { + $parts[] = sprintf(' %s ', $predicates[$i+1][0]); + } + } + return $parts; + } +} diff --git a/src/Sql/Ddl/Column/AbstractLengthColumn.php b/src/Sql/Ddl/Column/AbstractLengthColumn.php index 397887acd4..7e5d5532e7 100644 --- a/src/Sql/Ddl/Column/AbstractLengthColumn.php +++ b/src/Sql/Ddl/Column/AbstractLengthColumn.php @@ -47,26 +47,4 @@ public function getLength() { return $this->length; } - - /** - * @return string - */ - protected function getLengthExpression() - { - return (string) $this->length; - } - - /** - * @return array - */ - public function getExpressionData() - { - $data = parent::getExpressionData(); - - if ($this->getLengthExpression()) { - $data[0][1][1] .= '(' . $this->getLengthExpression() . ')'; - } - - return $data; - } } diff --git a/src/Sql/Ddl/Column/AbstractPrecisionColumn.php b/src/Sql/Ddl/Column/AbstractPrecisionColumn.php index bf50c3f62c..7044695afb 100644 --- a/src/Sql/Ddl/Column/AbstractPrecisionColumn.php +++ b/src/Sql/Ddl/Column/AbstractPrecisionColumn.php @@ -65,16 +65,4 @@ public function getDecimal() { return $this->decimal; } - - /** - * {@inheritDoc} - */ - protected function getLengthExpression() - { - if ($this->decimal !== null) { - return $this->length . ',' . $this->decimal; - } - - return $this->length; - } } diff --git a/src/Sql/Ddl/Column/AbstractTimestampColumn.php b/src/Sql/Ddl/Column/AbstractTimestampColumn.php index 8bdda7e94f..e1b1a076a2 100644 --- a/src/Sql/Ddl/Column/AbstractTimestampColumn.php +++ b/src/Sql/Ddl/Column/AbstractTimestampColumn.php @@ -16,48 +16,4 @@ */ abstract class AbstractTimestampColumn extends Column { - /** - * @return array - */ - public function getExpressionData() - { - $spec = $this->specification; - - $params = []; - $params[] = $this->name; - $params[] = $this->type; - - $types = [self::TYPE_IDENTIFIER, self::TYPE_LITERAL]; - - if (!$this->isNullable) { - $spec .= ' NOT NULL'; - } - - if ($this->default !== null) { - $spec .= ' DEFAULT %s'; - $params[] = $this->default; - $types[] = self::TYPE_VALUE; - } - - $options = $this->getOptions(); - - if (isset($options['on_update'])) { - $spec .= ' %s'; - $params[] = 'ON UPDATE CURRENT_TIMESTAMP'; - $types[] = self::TYPE_LITERAL; - } - - $data = [[ - $spec, - $params, - $types, - ]]; - - foreach ($this->constraints as $constraint) { - $data[] = ' '; - $data = array_merge($data, $constraint->getExpressionData()); - } - - return $data; - } } diff --git a/src/Sql/Ddl/Column/Column.php b/src/Sql/Ddl/Column/Column.php index f204db96df..d7e60edd7d 100644 --- a/src/Sql/Ddl/Column/Column.php +++ b/src/Sql/Ddl/Column/Column.php @@ -38,11 +38,6 @@ class Column implements ColumnInterface */ protected $constraints = []; - /** - * @var string - */ - protected $specification = '%s %s'; - /** * @var string */ @@ -80,6 +75,11 @@ public function getName() return $this->name; } + public function getType() + { + return $this->type; + } + /** * @param bool $nullable * @return self @@ -157,40 +157,8 @@ public function addConstraint(ConstraintInterface $constraint) return $this; } - /** - * @return array - */ - public function getExpressionData() + public function getConstraints() { - $spec = $this->specification; - - $params = []; - $params[] = $this->name; - $params[] = $this->type; - - $types = [self::TYPE_IDENTIFIER, self::TYPE_LITERAL]; - - if (!$this->isNullable) { - $spec .= ' NOT NULL'; - } - - if ($this->default !== null) { - $spec .= ' DEFAULT %s'; - $params[] = $this->default; - $types[] = self::TYPE_VALUE; - } - - $data = [[ - $spec, - $params, - $types, - ]]; - - foreach ($this->constraints as $constraint) { - $data[] = ' '; - $data = array_merge($data, $constraint->getExpressionData()); - } - - return $data; + return $this->constraints; } } diff --git a/src/Sql/Ddl/Column/Float.php b/src/Sql/Ddl/Column/Float.php deleted file mode 100644 index a67f857568..0000000000 --- a/src/Sql/Ddl/Column/Float.php +++ /dev/null @@ -1,48 +0,0 @@ -getOptions(); - - if (isset($options['length'])) { - $data[0][1][1] .= '(' . $options['length'] . ')'; - } - - return $data; - } } diff --git a/src/Sql/Ddl/Constraint/AbstractConstraint.php b/src/Sql/Ddl/Constraint/AbstractConstraint.php index 88f3b07744..7ac0dee860 100644 --- a/src/Sql/Ddl/Constraint/AbstractConstraint.php +++ b/src/Sql/Ddl/Constraint/AbstractConstraint.php @@ -11,21 +11,6 @@ abstract class AbstractConstraint implements ConstraintInterface { - /** - * @var string - */ - protected $columnSpecification = ' (%s)'; - - /** - * @var string - */ - protected $namedSpecification = 'CONSTRAINT %s '; - - /** - * @var string - */ - protected $specification = ''; - /** * @var string */ @@ -95,36 +80,4 @@ public function getColumns() { return $this->columns; } - - /** - * {@inheritDoc} - */ - public function getExpressionData() - { - $colCount = count($this->columns); - $newSpecTypes = []; - $values = []; - $newSpec = ''; - - if ($this->name) { - $newSpec .= $this->namedSpecification; - $values[] = $this->name; - $newSpecTypes[] = self::TYPE_IDENTIFIER; - } - - $newSpec .= $this->specification; - - if ($colCount) { - $values = array_merge($values, $this->columns); - $newSpecParts = array_fill(0, $colCount, '%s'); - $newSpecTypes = array_merge($newSpecTypes, array_fill(0, $colCount, self::TYPE_IDENTIFIER)); - $newSpec .= sprintf($this->columnSpecification, implode(', ', $newSpecParts)); - } - - return [[ - $newSpec, - $values, - $newSpecTypes, - ]]; - } } diff --git a/src/Sql/Ddl/Constraint/Check.php b/src/Sql/Ddl/Constraint/Check.php index df3917b0e8..b09937c6f5 100644 --- a/src/Sql/Ddl/Constraint/Check.php +++ b/src/Sql/Ddl/Constraint/Check.php @@ -16,11 +16,6 @@ class Check extends AbstractConstraint */ protected $expression; - /** - * {@inheritDoc} - */ - protected $specification = 'CHECK (%s)'; - /** * @param string|\Zend\Db\Sql\ExpressionInterface $expression * @param null|string $name @@ -32,25 +27,20 @@ public function __construct($expression, $name) } /** - * {@inheritDoc} + * @param string|\Zend\Db\Sql\ExpressionInterface $expression + * @return \Zend\Db\Sql\Ddl\Constraint\Check */ - public function getExpressionData() + public function setExpression($expression) { - $newSpecTypes = [self::TYPE_LITERAL]; - $values = [$this->expression]; - $newSpec = ''; - - if ($this->name) { - $newSpec .= $this->namedSpecification; - - array_unshift($values, $this->name); - array_unshift($newSpecTypes, self::TYPE_IDENTIFIER); - } + $this->expression = $expression; + return $this; + } - return [[ - $newSpec . $this->specification, - $values, - $newSpecTypes, - ]]; + /** + * @return string|\Zend\Db\Sql\ExpressionInterface + */ + public function getExpression() + { + return $this->expression; } } diff --git a/src/Sql/Ddl/Constraint/ForeignKey.php b/src/Sql/Ddl/Constraint/ForeignKey.php index 8a2a44394d..0574f3cee0 100644 --- a/src/Sql/Ddl/Constraint/ForeignKey.php +++ b/src/Sql/Ddl/Constraint/ForeignKey.php @@ -31,19 +31,6 @@ class ForeignKey extends AbstractConstraint */ protected $referenceTable = ''; - /** - * {@inheritDoc} - */ - protected $columnSpecification = 'FOREIGN KEY (%s) '; - - /** - * @var string[] - */ - protected $referenceSpecification = [ - 'REFERENCES %s ', - 'ON DELETE %s ON UPDATE %s' - ]; - /** * @param null|string $name * @param null|string|array $columns @@ -142,37 +129,4 @@ public function getOnUpdateRule() { return $this->onUpdateRule; } - - /** - * @return array - */ - public function getExpressionData() - { - $data = parent::getExpressionData(); - $colCount = count($this->referenceColumn); - $newSpecTypes = [self::TYPE_IDENTIFIER]; - $values = [$this->referenceTable]; - - $data[0][0] .= $this->referenceSpecification[0]; - - if ($colCount) { - $values = array_merge($values, $this->referenceColumn); - $newSpecParts = array_fill(0, $colCount, '%s'); - $newSpecTypes = array_merge($newSpecTypes, array_fill(0, $colCount, self::TYPE_IDENTIFIER)); - - $data[0][0] .= sprintf('(%s) ', implode(', ', $newSpecParts)); - } - - $data[0][0] .= $this->referenceSpecification[1]; - - $values[] = $this->onDeleteRule; - $values[] = $this->onUpdateRule; - $newSpecTypes[] = self::TYPE_LITERAL; - $newSpecTypes[] = self::TYPE_LITERAL; - - $data[0][1] = array_merge($data[0][1], $values); - $data[0][2] = array_merge($data[0][2], $newSpecTypes); - - return $data; - } } diff --git a/src/Sql/Ddl/Constraint/PrimaryKey.php b/src/Sql/Ddl/Constraint/PrimaryKey.php index 9775bb018f..ead9e056da 100644 --- a/src/Sql/Ddl/Constraint/PrimaryKey.php +++ b/src/Sql/Ddl/Constraint/PrimaryKey.php @@ -11,8 +11,4 @@ class PrimaryKey extends AbstractConstraint { - /** - * @var string - */ - protected $specification = 'PRIMARY KEY'; } diff --git a/src/Sql/Ddl/Constraint/UniqueKey.php b/src/Sql/Ddl/Constraint/UniqueKey.php index b46dbd159b..777b4cac14 100644 --- a/src/Sql/Ddl/Constraint/UniqueKey.php +++ b/src/Sql/Ddl/Constraint/UniqueKey.php @@ -11,8 +11,4 @@ class UniqueKey extends AbstractConstraint { - /** - * @var string - */ - protected $specification = 'UNIQUE'; } diff --git a/src/Sql/Ddl/Index/Index.php b/src/Sql/Ddl/Index/Index.php index a0239089a4..4148fe928b 100644 --- a/src/Sql/Ddl/Index/Index.php +++ b/src/Sql/Ddl/Index/Index.php @@ -11,11 +11,6 @@ class Index extends AbstractIndex { - /** - * @var string - */ - protected $specification = 'INDEX %s(...)'; - /** * @var array */ @@ -34,47 +29,14 @@ public function __construct($columns, $name = null, array $lengths = []) $this->lengths = $lengths; } - /** - * - * @return array of array|string should return an array in the format: - * - * array ( - * // a sprintf formatted string - * string $specification, - * - * // the values for the above sprintf formatted string - * array $values, - * - * // an array of equal length of the $values array, with either TYPE_IDENTIFIER or TYPE_VALUE for each value - * array $types, - * ) - * - */ - public function getExpressionData() + public function setLengths($lengths) { - $colCount = count($this->columns); - $values = []; - $values[] = $this->name ?: ''; - $newSpecTypes = [self::TYPE_IDENTIFIER]; - $newSpecParts = []; - - for ($i = 0; $i < $colCount; $i++) { - $specPart = '%s'; - - if (isset($this->lengths[$i])) { - $specPart .= "({$this->lengths[$i]})"; - } - - $newSpecParts[] = $specPart; - $newSpecTypes[] = self::TYPE_IDENTIFIER; - } - - $newSpec = str_replace('...', implode(', ', $newSpecParts), $this->specification); + $this->lengths = $lengths; + return $this; + } - return [[ - $newSpec, - array_merge($values, $this->columns), - $newSpecTypes, - ]]; + public function getLengths() + { + return $this->lengths; } } diff --git a/src/Sql/Expression.php b/src/Sql/Expression.php index 95692a6f5a..939d6a6f1a 100644 --- a/src/Sql/Expression.php +++ b/src/Sql/Expression.php @@ -9,13 +9,10 @@ namespace Zend\Db\Sql; -class Expression extends AbstractExpression -{ - /** - * @const - */ - const PLACEHOLDER = '?'; +use Zend\Stdlib\ArrayUtils; +class Expression implements ExpressionInterface +{ /** * @var string */ @@ -26,44 +23,22 @@ class Expression extends AbstractExpression */ protected $parameters = []; - /** - * @var array - */ - protected $types = []; - /** * @param string $expression - * @param string|array $parameters - * @param array $types @deprecated will be dropped in version 3.0.0 + * @param string|array $valueParameter */ - public function __construct($expression = '', $parameters = null, array $types = []) + public function __construct($expression = '', $valueParameter = null /*[, $valueParameter, ... ]*/) { if ($expression !== '') { $this->setExpression($expression); } - if ($types) { // should be deprecated and removed version 3.0.0 - if (is_array($parameters)) { - foreach ($parameters as $i=>$parameter) { - $parameters[$i] = [ - $parameter => isset($types[$i]) ? $types[$i] : self::TYPE_VALUE, - ]; - } - } elseif (is_scalar($parameters)) { - $parameters = [ - $parameters => $types[0], - ]; - } - } - - if ($parameters) { - $this->setParameters($parameters); - } + $this->setParameters(is_array($valueParameter) ? $valueParameter : array_slice(func_get_args(), 1)); } /** - * @param $expression - * @return Expression + * @param string $expression + * @return self * @throws Exception\InvalidArgumentException */ public function setExpression($expression) @@ -93,7 +68,18 @@ public function setParameters($parameters) if (!is_scalar($parameters) && !is_array($parameters)) { throw new Exception\InvalidArgumentException('Expression parameters must be a scalar or array.'); } - $this->parameters = $parameters; + $this->parameters = []; + + $parameters = (array)$parameters; + if (ArrayUtils::hasStringKeys($parameters)) { + foreach ($parameters as $value => $type) { + $this->parameters[] = new ExpressionParameter($value, $type); + } + } else { + foreach ($parameters as $parameter) { + $this->parameters[] = new ExpressionParameter($parameter, self::TYPE_VALUE); + } + } return $this; } @@ -104,59 +90,4 @@ public function getParameters() { return $this->parameters; } - - /** - * @deprecated - * @param array $types - * @return Expression - */ - public function setTypes(array $types) - { - $this->types = $types; - return $this; - } - - /** - * @deprecated - * @return array - */ - public function getTypes() - { - return $this->types; - } - - /** - * @return array - * @throws Exception\RuntimeException - */ - public function getExpressionData() - { - $parameters = (is_scalar($this->parameters)) ? [$this->parameters] : $this->parameters; - $parametersCount = count($parameters); - $expression = str_replace('%', '%%', $this->expression); - - if ($parametersCount == 0) { - return [ - str_ireplace(self::PLACEHOLDER, '', $expression) - ]; - } - - // assign locally, escaping % signs - $expression = str_replace(self::PLACEHOLDER, '%s', $expression, $count); - - // test number of replacements without considering same variable begin used many times first, which is - // faster, if the test fails then resort to regex wich are slow and used rarely - if ($count !== $parametersCount && $parametersCount === preg_match_all('/\:[a-zA-Z0-9_]*/', $expression)) { - throw new Exception\RuntimeException('The number of replacements in the expression does not match the number of parameters'); - } - - foreach ($parameters as $parameter) { - list($values[], $types[]) = $this->normalizeArgument($parameter, self::TYPE_VALUE); - } - return [[ - $expression, - $values, - $types - ]]; - } } diff --git a/src/Sql/ExpressionInterface.php b/src/Sql/ExpressionInterface.php index 282b408683..3f1f1f92a6 100644 --- a/src/Sql/ExpressionInterface.php +++ b/src/Sql/ExpressionInterface.php @@ -11,27 +11,10 @@ interface ExpressionInterface { + const PLACEHOLDER = '?'; + const TYPE_IDENTIFIER = 'identifier'; const TYPE_VALUE = 'value'; const TYPE_LITERAL = 'literal'; const TYPE_SELECT = 'select'; - - /** - * @abstract - * - * @return array of array|string should return an array in the format: - * - * array ( - * // a sprintf formatted string - * string $specification, - * - * // the values for the above sprintf formatted string - * array $values, - * - * // an array of equal length of the $values array, with either TYPE_IDENTIFIER or TYPE_VALUE for each value - * array $types, - * ) - * - */ - public function getExpressionData(); } diff --git a/src/Sql/ExpressionParameter.php b/src/Sql/ExpressionParameter.php new file mode 100644 index 0000000000..85457c9df6 --- /dev/null +++ b/src/Sql/ExpressionParameter.php @@ -0,0 +1,150 @@ +value = $value->value; + $this->type = $value->type; + $this->name = $value->name; + $this->options = $value->options; + return; + } + + if (is_array($type)) { + $this->options = $type; + $type = ExpressionInterface::TYPE_VALUE; + } + if (is_array($value)) { + if (is_string(key($value))) { + $type = current($value); + $value = key($value); + } elseif (count($value) == 1) { + $type = current($value); + $value = key($value); + } else { + $type = isset($value[1]) ? $value[1] : $type; + $value = $value[0]; + } + } + + if ($value instanceof ExpressionInterface || $value instanceof SqlObjectInterface) { + $type = ExpressionInterface::TYPE_SELECT; + } + + $this->value = $value; + $this->type = $type; + $this->name = $name; + } + + /** + * @param mixed $value + * @return self + */ + public function setValue($value) + { + $this->value = $value; + return $this; + } + + /** + * @return mixed + */ + public function getValue() + { + return $this->value; + } + + /** + * @param string $type + * @return self + */ + public function setType($type) + { + $this->type = $type; + return $this; + } + + /** + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * @param string $name + * @return self + */ + public function setName($name) + { + $this->name = $name; + return $this; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @param string $name + * @param mixed $value + * @return self + */ + public function setOption($name, $value) + { + $this->options[$name] = $value; + return $this; + } + + /** + * @param array $options + * @return self + */ + public function setOptions(array $options) + { + foreach ($options as $name=>$value) { + $this->options[$name] = $value; + } + return $this; + } + + /** + * @param string $name + * @return null|mixed + */ + public function getOption($name) + { + return array_key_exists($name, $this->options) + ? $this->options[$name] + : null; + } +} diff --git a/src/Sql/Literal.php b/src/Sql/Literal.php index d8f8ee5eac..903de07258 100644 --- a/src/Sql/Literal.php +++ b/src/Sql/Literal.php @@ -41,16 +41,4 @@ public function getLiteral() { return $this->literal; } - - /** - * @return array - */ - public function getExpressionData() - { - return [[ - str_replace('%', '%%', $this->literal), - [], - [] - ]]; - } } diff --git a/src/Sql/Predicate/Between.php b/src/Sql/Predicate/Between.php index 99f2573872..61fa8b83f9 100644 --- a/src/Sql/Predicate/Between.php +++ b/src/Sql/Predicate/Between.php @@ -9,11 +9,10 @@ namespace Zend\Db\Sql\Predicate; -use Zend\Db\Sql\AbstractExpression; +use Zend\Db\Sql\ExpressionParameter; -class Between extends AbstractExpression implements PredicateInterface +class Between implements PredicateInterface { - protected $specification = '%1$s BETWEEN %2$s AND %3$s'; protected $identifier = null; protected $minValue = null; protected $maxValue = null; @@ -44,9 +43,9 @@ public function __construct($identifier = null, $minValue = null, $maxValue = nu * @param string $identifier * @return Between */ - public function setIdentifier($identifier) + public function setIdentifier($identifier, $type = self::TYPE_IDENTIFIER) { - $this->identifier = $identifier; + $this->identifier = new ExpressionParameter($identifier, $type); return $this; } @@ -66,9 +65,9 @@ public function getIdentifier() * @param int|float|string $minValue * @return Between */ - public function setMinValue($minValue) + public function setMinValue($minValue, $type = self::TYPE_VALUE) { - $this->minValue = $minValue; + $this->minValue = new ExpressionParameter($minValue, $type); return $this; } @@ -88,9 +87,9 @@ public function getMinValue() * @param int|float|string $maxValue * @return Between */ - public function setMaxValue($maxValue) + public function setMaxValue($maxValue, $type = self::TYPE_VALUE) { - $this->maxValue = $maxValue; + $this->maxValue = new ExpressionParameter($maxValue, $type); return $this; } @@ -103,45 +102,4 @@ public function getMaxValue() { return $this->maxValue; } - - /** - * Set specification string to use in forming SQL predicate - * - * @param string $specification - * @return Between - */ - public function setSpecification($specification) - { - $this->specification = $specification; - return $this; - } - - /** - * Get specification string to use in forming SQL predicate - * - * @return string - */ - public function getSpecification() - { - return $this->specification; - } - - /** - * Return "where" parts - * - * @return array - */ - public function getExpressionData() - { - list($values[], $types[]) = $this->normalizeArgument($this->identifier, self::TYPE_IDENTIFIER); - list($values[], $types[]) = $this->normalizeArgument($this->minValue, self::TYPE_VALUE); - list($values[], $types[]) = $this->normalizeArgument($this->maxValue, self::TYPE_VALUE); - return [ - [ - $this->getSpecification(), - $values, - $types, - ], - ]; - } } diff --git a/src/Sql/Predicate/Expression.php b/src/Sql/Predicate/Expression.php index e9b5363f24..602329afd1 100644 --- a/src/Sql/Predicate/Expression.php +++ b/src/Sql/Predicate/Expression.php @@ -11,20 +11,6 @@ use Zend\Db\Sql\Expression as BaseExpression; -class Expression extends BaseExpression implements PredicateInterface +final class Expression extends BaseExpression implements PredicateInterface { - /** - * Constructor - * - * @param string $expression - * @param int|float|bool|string|array $valueParameter - */ - public function __construct($expression = null, $valueParameter = null /*[, $valueParameter, ... ]*/) - { - if ($expression) { - $this->setExpression($expression); - } - - $this->setParameters(is_array($valueParameter) ? $valueParameter : array_slice(func_get_args(), 1)); - } } diff --git a/src/Sql/Predicate/In.php b/src/Sql/Predicate/In.php index 4f5ec49aaf..e0bdb0e227 100644 --- a/src/Sql/Predicate/In.php +++ b/src/Sql/Predicate/In.php @@ -12,17 +12,13 @@ use Zend\Db\Sql\Exception; use Zend\Db\Sql\Select; use Zend\Db\Sql\SelectableInterface; -use Zend\Db\Sql\AbstractExpression; +use Zend\Db\Sql\ExpressionParameter; -class In extends AbstractExpression implements PredicateInterface +class In implements PredicateInterface { protected $identifier; protected $valueSet; - protected $specification = '%s IN %s'; - - protected $valueSpecSpecification = '%%s IN (%s)'; - /** * Constructor * @@ -45,9 +41,16 @@ public function __construct($identifier = null, $valueSet = null) * @param string|array $identifier * @return In */ - public function setIdentifier($identifier) + public function setIdentifier($identifier, $type = self::TYPE_IDENTIFIER) { - $this->identifier = $identifier; + if (is_array($identifier)) { + $this->identifier = []; + foreach ($identifier as $ident) { + $this->identifier[] = new ExpressionParameter($ident, $type); + } + } else { + $this->identifier = new ExpressionParameter($identifier, $type); + } return $this; } @@ -71,13 +74,18 @@ public function getIdentifier() */ public function setValueSet($valueSet) { - if (!is_array($valueSet) && !$valueSet instanceof SelectableInterface) { + if ($valueSet instanceof SelectableInterface) { + $this->valueSet = new ExpressionParameter($valueSet); + } elseif (is_array($valueSet)) { + $this->valueSet = []; + foreach ($valueSet as $value) { + $this->valueSet[] = new ExpressionParameter($value, self::TYPE_VALUE); + } + } else { throw new Exception\InvalidArgumentException( '$valueSet must be either an array or a Zend\Db\Sql\SelectableInterface object, ' . gettype($valueSet) . ' given' ); } - $this->valueSet = $valueSet; - return $this; } @@ -90,49 +98,4 @@ public function getValueSet() { return $this->valueSet; } - - /** - * Return array of parts for where statement - * - * @return array - */ - public function getExpressionData() - { - $identifier = $this->getIdentifier(); - $values = $this->getValueSet(); - $replacements = []; - - if (is_array($identifier)) { - $identifierSpecFragment = '(' . implode(', ', array_fill(0, count($identifier), '%s')) . ')'; - $types = array_fill(0, count($identifier), self::TYPE_IDENTIFIER); - $replacements = $identifier; - } else { - $identifierSpecFragment = '%s'; - $replacements[] = $identifier; - $types = [self::TYPE_IDENTIFIER]; - } - - if ($values instanceof SelectableInterface) { - $specification = vsprintf( - $this->specification, - [$identifierSpecFragment, '%s'] - ); - $replacements[] = $values; - $types[] = self::TYPE_VALUE; - } else { - foreach ($values as $argument) { - list($replacements[], $types[]) = $this->normalizeArgument($argument, self::TYPE_VALUE); - } - $specification = vsprintf( - $this->specification, - [$identifierSpecFragment, '(' . implode(', ', array_fill(0, count($values), '%s')) . ')'] - ); - } - - return [[ - $specification, - $replacements, - $types, - ]]; - } } diff --git a/src/Sql/Predicate/IsNotNull.php b/src/Sql/Predicate/IsNotNull.php index e42c9aa5b5..518cf520d3 100644 --- a/src/Sql/Predicate/IsNotNull.php +++ b/src/Sql/Predicate/IsNotNull.php @@ -11,5 +11,4 @@ class IsNotNull extends IsNull { - protected $specification = '%1$s IS NOT NULL'; } diff --git a/src/Sql/Predicate/IsNull.php b/src/Sql/Predicate/IsNull.php index cb9c64c55e..77e9377206 100644 --- a/src/Sql/Predicate/IsNull.php +++ b/src/Sql/Predicate/IsNull.php @@ -9,15 +9,10 @@ namespace Zend\Db\Sql\Predicate; -use Zend\Db\Sql\AbstractExpression; +use Zend\Db\Sql\ExpressionParameter; -class IsNull extends AbstractExpression implements PredicateInterface +class IsNull implements PredicateInterface { - /** - * @var string - */ - protected $specification = '%1$s IS NULL'; - /** * @var */ @@ -41,9 +36,9 @@ public function __construct($identifier = null) * @param string $identifier * @return IsNull */ - public function setIdentifier($identifier) + public function setIdentifier($identifier, $type = self::TYPE_IDENTIFIER) { - $this->identifier = $identifier; + $this->identifier = new ExpressionParameter($identifier, $type); return $this; } @@ -56,41 +51,4 @@ public function getIdentifier() { return $this->identifier; } - - /** - * Set specification string to use in forming SQL predicate - * - * @param string $specification - * @return IsNull - */ - public function setSpecification($specification) - { - $this->specification = $specification; - return $this; - } - - /** - * Get specification string to use in forming SQL predicate - * - * @return string - */ - public function getSpecification() - { - return $this->specification; - } - - /** - * Get parts for where statement - * - * @return array - */ - public function getExpressionData() - { - $identifier = $this->normalizeArgument($this->identifier, self::TYPE_IDENTIFIER); - return [[ - $this->getSpecification(), - [$identifier[0]], - [$identifier[1]], - ]]; - } } diff --git a/src/Sql/Predicate/Like.php b/src/Sql/Predicate/Like.php index 457b6596a1..be0599b319 100644 --- a/src/Sql/Predicate/Like.php +++ b/src/Sql/Predicate/Like.php @@ -9,15 +9,10 @@ namespace Zend\Db\Sql\Predicate; -use Zend\Db\Sql\AbstractExpression; +use Zend\Db\Sql\ExpressionParameter; -class Like extends AbstractExpression implements PredicateInterface +class Like implements PredicateInterface { - /** - * @var string - */ - protected $specification = '%1$s LIKE %2$s'; - /** * @var string */ @@ -46,9 +41,9 @@ public function __construct($identifier = null, $like = null) * @param string $identifier * @return self */ - public function setIdentifier($identifier) + public function setIdentifier($identifier, $type = self::TYPE_IDENTIFIER) { - $this->identifier = $identifier; + $this->identifier = new ExpressionParameter($identifier, $type); return $this; } @@ -64,9 +59,9 @@ public function getIdentifier() * @param string $like * @return self */ - public function setLike($like) + public function setLike($like, $type = self::TYPE_VALUE) { - $this->like = $like; + $this->like = new ExpressionParameter($like, $type); return $this; } @@ -77,38 +72,4 @@ public function getLike() { return $this->like; } - - /** - * @param string $specification - * @return self - */ - public function setSpecification($specification) - { - $this->specification = $specification; - return $this; - } - - /** - * @return string - */ - public function getSpecification() - { - return $this->specification; - } - - /** - * @return array - */ - public function getExpressionData() - { - list($values[], $types[]) = $this->normalizeArgument($this->identifier, self::TYPE_IDENTIFIER); - list($values[], $types[]) = $this->normalizeArgument($this->like, self::TYPE_VALUE); - return [ - [ - $this->specification, - $values, - $types, - ] - ]; - } } diff --git a/src/Sql/Predicate/Literal.php b/src/Sql/Predicate/Literal.php index d4b509fc93..58b7beca42 100644 --- a/src/Sql/Predicate/Literal.php +++ b/src/Sql/Predicate/Literal.php @@ -11,6 +11,6 @@ use Zend\Db\Sql\Literal as BaseLiteral; -class Literal extends BaseLiteral implements PredicateInterface +final class Literal extends BaseLiteral implements PredicateInterface { } diff --git a/src/Sql/Predicate/NotBetween.php b/src/Sql/Predicate/NotBetween.php index a448a77e69..30fa1c3beb 100644 --- a/src/Sql/Predicate/NotBetween.php +++ b/src/Sql/Predicate/NotBetween.php @@ -11,5 +11,4 @@ class NotBetween extends Between { - protected $specification = '%1$s NOT BETWEEN %2$s AND %3$s'; } diff --git a/src/Sql/Predicate/NotIn.php b/src/Sql/Predicate/NotIn.php index f1ce87c235..ac0b0a4f01 100644 --- a/src/Sql/Predicate/NotIn.php +++ b/src/Sql/Predicate/NotIn.php @@ -11,5 +11,4 @@ class NotIn extends In { - protected $specification = '%s NOT IN %s'; } diff --git a/src/Sql/Predicate/NotLike.php b/src/Sql/Predicate/NotLike.php index 18d627c551..f82c3045d0 100644 --- a/src/Sql/Predicate/NotLike.php +++ b/src/Sql/Predicate/NotLike.php @@ -11,5 +11,4 @@ class NotLike extends Like { - protected $specification = '%1$s NOT LIKE %2$s'; } diff --git a/src/Sql/Predicate/Operator.php b/src/Sql/Predicate/Operator.php index 5b51c4d61a..eedf3249d3 100644 --- a/src/Sql/Predicate/Operator.php +++ b/src/Sql/Predicate/Operator.php @@ -9,10 +9,9 @@ namespace Zend\Db\Sql\Predicate; -use Zend\Db\Sql\Exception; -use Zend\Db\Sql\AbstractExpression; +use Zend\Db\Sql\ExpressionParameter; -class Operator extends AbstractExpression implements PredicateInterface +class Operator implements PredicateInterface { const OPERATOR_EQUAL_TO = '='; const OP_EQ = '='; @@ -32,14 +31,6 @@ class Operator extends AbstractExpression implements PredicateInterface const OPERATOR_GREATER_THAN_OR_EQUAL_TO = '>='; const OP_GTE = '>='; - /** - * {@inheritDoc} - */ - protected $allowedTypes = [ - self::TYPE_IDENTIFIER, - self::TYPE_VALUE, - ]; - /** * @var int|float|bool|string */ @@ -50,16 +41,6 @@ class Operator extends AbstractExpression implements PredicateInterface */ protected $right; - /** - * @var string - */ - protected $leftType = self::TYPE_IDENTIFIER; - - /** - * @var string - */ - protected $rightType = self::TYPE_VALUE; - /** * @var string */ @@ -71,15 +52,11 @@ class Operator extends AbstractExpression implements PredicateInterface * @param int|float|bool|string $left * @param string $operator * @param int|float|bool|string $right - * @param string $leftType TYPE_IDENTIFIER or TYPE_VALUE by default TYPE_IDENTIFIER {@see allowedTypes} - * @param string $rightType TYPE_IDENTIFIER or TYPE_VALUE by default TYPE_VALUE {@see allowedTypes} */ public function __construct( $left = null, $operator = self::OPERATOR_EQUAL_TO, - $right = null, - $leftType = self::TYPE_IDENTIFIER, - $rightType = self::TYPE_VALUE + $right = null ) { if ($left !== null) { $this->setLeft($left); @@ -92,14 +69,6 @@ public function __construct( if ($right !== null) { $this->setRight($right); } - - if ($leftType !== self::TYPE_IDENTIFIER) { - $this->setLeftType($leftType); - } - - if ($rightType !== self::TYPE_VALUE) { - $this->setRightType($rightType); - } } /** @@ -109,15 +78,9 @@ public function __construct( * * @return Operator */ - public function setLeft($left) + public function setLeft($left, $type = self::TYPE_IDENTIFIER) { - $this->left = $left; - - if (is_array($left)) { - $left = $this->normalizeArgument($left, $this->leftType); - $this->leftType = $left[1]; - } - + $this->left = new ExpressionParameter($left, $type); return $this; } @@ -131,41 +94,6 @@ public function getLeft() return $this->left; } - /** - * Set parameter type for left side of operator - * - * @param string $type TYPE_IDENTIFIER or TYPE_VALUE {@see allowedTypes} - * - * @return Operator - * - * @throws Exception\InvalidArgumentException - */ - public function setLeftType($type) - { - if (!in_array($type, $this->allowedTypes)) { - throw new Exception\InvalidArgumentException(sprintf( - 'Invalid type "%s" provided; must be of type "%s" or "%s"', - $type, - __CLASS__ . '::TYPE_IDENTIFIER', - __CLASS__ . '::TYPE_VALUE' - )); - } - - $this->leftType = $type; - - return $this; - } - - /** - * Get parameter type on left side of operator - * - * @return string - */ - public function getLeftType() - { - return $this->leftType; - } - /** * Set operator string * @@ -196,15 +124,9 @@ public function getOperator() * * @return Operator */ - public function setRight($right) + public function setRight($right, $type = self::TYPE_VALUE) { - $this->right = $right; - - if (is_array($right)) { - $right = $this->normalizeArgument($right, $this->rightType); - $this->rightType = $right[1]; - } - + $this->right = new ExpressionParameter($right, $type); return $this; } @@ -217,54 +139,4 @@ public function getRight() { return $this->right; } - - /** - * Set parameter type for right side of operator - * - * @param string $type TYPE_IDENTIFIER or TYPE_VALUE {@see allowedTypes} - * @throws Exception\InvalidArgumentException - * @return Operator - */ - public function setRightType($type) - { - if (!in_array($type, $this->allowedTypes)) { - throw new Exception\InvalidArgumentException(sprintf( - 'Invalid type "%s" provided; must be of type "%s" or "%s"', - $type, - __CLASS__ . '::TYPE_IDENTIFIER', - __CLASS__ . '::TYPE_VALUE' - )); - } - - $this->rightType = $type; - - return $this; - } - - /** - * Get parameter type on right side of operator - * - * @return string - */ - public function getRightType() - { - return $this->rightType; - } - - /** - * Get predicate parts for where statement - * - * @return array - */ - public function getExpressionData() - { - list($values[], $types[]) = $this->normalizeArgument($this->left, $this->leftType); - list($values[], $types[]) = $this->normalizeArgument($this->right, $this->rightType); - - return [[ - '%s ' . $this->operator . ' %s', - $values, - $types - ]]; - } } diff --git a/src/Sql/Predicate/Predicate.php b/src/Sql/Predicate/Predicate.php index c6f4c3a0d4..4fef03ff77 100644 --- a/src/Sql/Predicate/Predicate.php +++ b/src/Sql/Predicate/Predicate.php @@ -72,14 +72,12 @@ public function unnest() * * @param int|float|bool|string $left * @param int|float|bool|string $right - * @param string $leftType TYPE_IDENTIFIER or TYPE_VALUE by default TYPE_IDENTIFIER {@see allowedTypes} - * @param string $rightType TYPE_IDENTIFIER or TYPE_VALUE by default TYPE_VALUE {@see allowedTypes} * @return Predicate */ - public function equalTo($left, $right, $leftType = self::TYPE_IDENTIFIER, $rightType = self::TYPE_VALUE) + public function equalTo($left, $right) { $this->addPredicate( - new Operator($left, Operator::OPERATOR_EQUAL_TO, $right, $leftType, $rightType), + new Operator($left, Operator::OPERATOR_EQUAL_TO, $right), ($this->nextPredicateCombineOperator) ?: $this->defaultCombination ); $this->nextPredicateCombineOperator = null; @@ -94,14 +92,12 @@ public function equalTo($left, $right, $leftType = self::TYPE_IDENTIFIER, $right * * @param int|float|bool|string $left * @param int|float|bool|string $right - * @param string $leftType TYPE_IDENTIFIER or TYPE_VALUE by default TYPE_IDENTIFIER {@see allowedTypes} - * @param string $rightType TYPE_IDENTIFIER or TYPE_VALUE by default TYPE_VALUE {@see allowedTypes} * @return Predicate */ - public function notEqualTo($left, $right, $leftType = self::TYPE_IDENTIFIER, $rightType = self::TYPE_VALUE) + public function notEqualTo($left, $right) { $this->addPredicate( - new Operator($left, Operator::OPERATOR_NOT_EQUAL_TO, $right, $leftType, $rightType), + new Operator($left, Operator::OPERATOR_NOT_EQUAL_TO, $right), ($this->nextPredicateCombineOperator) ?: $this->defaultCombination ); $this->nextPredicateCombineOperator = null; @@ -116,14 +112,12 @@ public function notEqualTo($left, $right, $leftType = self::TYPE_IDENTIFIER, $ri * * @param int|float|bool|string $left * @param int|float|bool|string $right - * @param string $leftType TYPE_IDENTIFIER or TYPE_VALUE by default TYPE_IDENTIFIER {@see allowedTypes} - * @param string $rightType TYPE_IDENTIFIER or TYPE_VALUE by default TYPE_VALUE {@see allowedTypes} * @return Predicate */ - public function lessThan($left, $right, $leftType = self::TYPE_IDENTIFIER, $rightType = self::TYPE_VALUE) + public function lessThan($left, $right) { $this->addPredicate( - new Operator($left, Operator::OPERATOR_LESS_THAN, $right, $leftType, $rightType), + new Operator($left, Operator::OPERATOR_LESS_THAN, $right), ($this->nextPredicateCombineOperator) ?: $this->defaultCombination ); $this->nextPredicateCombineOperator = null; @@ -138,14 +132,12 @@ public function lessThan($left, $right, $leftType = self::TYPE_IDENTIFIER, $righ * * @param int|float|bool|string $left * @param int|float|bool|string $right - * @param string $leftType TYPE_IDENTIFIER or TYPE_VALUE by default TYPE_IDENTIFIER {@see allowedTypes} - * @param string $rightType TYPE_IDENTIFIER or TYPE_VALUE by default TYPE_VALUE {@see allowedTypes} * @return Predicate */ - public function greaterThan($left, $right, $leftType = self::TYPE_IDENTIFIER, $rightType = self::TYPE_VALUE) + public function greaterThan($left, $right) { $this->addPredicate( - new Operator($left, Operator::OPERATOR_GREATER_THAN, $right, $leftType, $rightType), + new Operator($left, Operator::OPERATOR_GREATER_THAN, $right), ($this->nextPredicateCombineOperator) ?: $this->defaultCombination ); $this->nextPredicateCombineOperator = null; @@ -160,14 +152,12 @@ public function greaterThan($left, $right, $leftType = self::TYPE_IDENTIFIER, $r * * @param int|float|bool|string $left * @param int|float|bool|string $right - * @param string $leftType TYPE_IDENTIFIER or TYPE_VALUE by default TYPE_IDENTIFIER {@see allowedTypes} - * @param string $rightType TYPE_IDENTIFIER or TYPE_VALUE by default TYPE_VALUE {@see allowedTypes} * @return Predicate */ - public function lessThanOrEqualTo($left, $right, $leftType = self::TYPE_IDENTIFIER, $rightType = self::TYPE_VALUE) + public function lessThanOrEqualTo($left, $right) { $this->addPredicate( - new Operator($left, Operator::OPERATOR_LESS_THAN_OR_EQUAL_TO, $right, $leftType, $rightType), + new Operator($left, Operator::OPERATOR_LESS_THAN_OR_EQUAL_TO, $right), ($this->nextPredicateCombineOperator) ?: $this->defaultCombination ); $this->nextPredicateCombineOperator = null; @@ -182,14 +172,12 @@ public function lessThanOrEqualTo($left, $right, $leftType = self::TYPE_IDENTIFI * * @param int|float|bool|string $left * @param int|float|bool|string $right - * @param string $leftType TYPE_IDENTIFIER or TYPE_VALUE by default TYPE_IDENTIFIER {@see allowedTypes} - * @param string $rightType TYPE_IDENTIFIER or TYPE_VALUE by default TYPE_VALUE {@see allowedTypes} * @return Predicate */ - public function greaterThanOrEqualTo($left, $right, $leftType = self::TYPE_IDENTIFIER, $rightType = self::TYPE_VALUE) + public function greaterThanOrEqualTo($left, $right) { $this->addPredicate( - new Operator($left, Operator::OPERATOR_GREATER_THAN_OR_EQUAL_TO, $right, $leftType, $rightType), + new Operator($left, Operator::OPERATOR_GREATER_THAN_OR_EQUAL_TO, $right), ($this->nextPredicateCombineOperator) ?: $this->defaultCombination ); $this->nextPredicateCombineOperator = null; diff --git a/src/Sql/Predicate/PredicateSet.php b/src/Sql/Predicate/PredicateSet.php index 36f1909fe3..57826b78fe 100644 --- a/src/Sql/Predicate/PredicateSet.php +++ b/src/Sql/Predicate/PredicateSet.php @@ -158,35 +158,6 @@ public function andPredicate(PredicateInterface $predicate) return $this; } - /** - * Get predicate parts for where statement - * - * @return array - */ - public function getExpressionData() - { - $parts = []; - for ($i = 0, $count = count($this->predicates); $i < $count; $i++) { - /** @var $predicate PredicateInterface */ - $predicate = $this->predicates[$i][1]; - - if ($predicate instanceof PredicateSet) { - $parts[] = '('; - } - - $parts = array_merge($parts, $predicate->getExpressionData()); - - if ($predicate instanceof PredicateSet) { - $parts[] = ')'; - } - - if (isset($this->predicates[$i+1])) { - $parts[] = sprintf(' %s ', $this->predicates[$i+1][0]); - } - } - return $parts; - } - /** * Get count of attached predicates * diff --git a/test/Sql/Builder/AllBuildersTest.php b/test/Sql/Builder/AllBuildersTest.php index 8cad720bf9..7db53f5c09 100644 --- a/test/Sql/Builder/AllBuildersTest.php +++ b/test/Sql/Builder/AllBuildersTest.php @@ -467,40 +467,39 @@ protected function dataProvider_Builders() ], ], ], - /* TODO - should be implemeted 'DecorableExpression()' => [ - 'sqlObject' => $this->update('foo')->where(['x'=>new Sql\Expression('?', [$this->select('foo')])]), + 'sqlObject' => $this->update('foo')->where(['x'=>$this->expression('?', [$this->select('foo')])]), 'expected' => [ 'sql92' => [ 'decorators' => [ - 'Zend\Db\Sql\Expression' => new TestAsset\DecorableExpression, + 'Zend\Db\Sql\Expression' => 'ZendTest\Db\TestAsset\ExpressionBuilder', 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\Mysql\SelectBuilder', '{=SELECT_Sql92=}'] ], 'string' => 'UPDATE "foo" SET WHERE "x" = {decorate-({=SELECT_Sql92=})-decorate}', ], 'MySql' => [ 'decorators' => [ - 'Zend\Db\Sql\Expression' => new TestAsset\DecorableExpression, + 'Zend\Db\Sql\Expression' => 'ZendTest\Db\TestAsset\ExpressionBuilder', 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\Mysql\SelectBuilder', '{=SELECT_MySql=}'] ], 'string' => 'UPDATE `foo` SET WHERE `x` = {decorate-({=SELECT_MySql=})-decorate}', ], 'Oracle' => [ 'decorators' => [ - 'Zend\Db\Sql\Expression' => new TestAsset\DecorableExpression, + 'Zend\Db\Sql\Expression' => 'ZendTest\Db\TestAsset\ExpressionBuilder', 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\Oracle\SelectBuilder', '{=SELECT_Oracle=}'] ], 'string' => 'UPDATE "foo" SET WHERE "x" = {decorate-({=SELECT_Oracle=})-decorate}', ], 'SqlServer' => [ 'decorators' => [ - 'Zend\Db\Sql\Expression' => new TestAsset\DecorableExpression, + 'Zend\Db\Sql\Expression' => 'ZendTest\Db\TestAsset\ExpressionBuilder', 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\SqlServer\SelectBuilder', '{=SELECT_SqlServer=}'] ], 'string' => 'UPDATE [foo] SET WHERE [x] = {decorate-({=SELECT_SqlServer=})-decorate}', ], ], - ],*/ + ], ]; } } diff --git a/test/Sql/Builder/Ddl/Column/ColumnBuilderTest.php b/test/Sql/Builder/Ddl/Column/ColumnBuilderTest.php new file mode 100644 index 0000000000..1359462277 --- /dev/null +++ b/test/Sql/Builder/Ddl/Column/ColumnBuilderTest.php @@ -0,0 +1,381 @@ +context = new Context($this->getAdapterForPlatform('sql92')); + } + + public function testColumn() + { + $builder = new ColumnBuilder\ColumnBuilder(new Builder); + $column = new Column\Column; + $column->setName('foo'); + $this->assertEquals( + [[ + '%s %s NOT NULL', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('INTEGER', $column::TYPE_LITERAL), + ], + ]], + $builder->getExpressionData($column, $this->context) + ); + + $column->setNullable(true); + $this->assertEquals( + [[ + '%s %s', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('INTEGER', $column::TYPE_LITERAL), + ], + ]], + $builder->getExpressionData($column, $this->context) + ); + + $column->setDefault('bar'); + $this->assertEquals( + [[ + '%s %s DEFAULT %s', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('INTEGER', $column::TYPE_LITERAL), + new ExpressionParameter('bar', $column::TYPE_VALUE), + ], + ]], + $builder->getExpressionData($column, $this->context) + ); + } + + public function testAbstractLengthColumn() + { + $builder = new ColumnBuilder\AbstractLengthColumnBuilder(new Builder); + $column = $this->getMockForAbstractClass('Zend\Db\Sql\Ddl\Column\AbstractLengthColumn', [ + 'foo', 4 + ]); + + $this->assertEquals( + [[ + '%s %s NOT NULL', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('INTEGER(4)', $column::TYPE_LITERAL), + ], + ]], + $builder->getExpressionData($column, $this->context) + ); + } + + public function testAbstractPrecisionColumn() + { + $builder = new ColumnBuilder\AbstractPrecisionColumnBuilder(new Builder); + $column = $this->getMockForAbstractClass('Zend\Db\Sql\Ddl\Column\AbstractPrecisionColumn', [ + 'foo', 10, 5 + ]); + + $this->assertEquals( + [[ + '%s %s NOT NULL', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('INTEGER(10,5)', $column::TYPE_LITERAL), + ], + ]], + $builder->getExpressionData($column, $this->context) + ); + } + + public function testBigInteger() + { + $builder = new ColumnBuilder\IntegerBuilder(new Builder); + $column = new Column\BigInteger('foo'); + $this->assertEquals( + [[ + '%s %s NOT NULL', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('BIGINT', $column::TYPE_LITERAL), + ], + ]], + $builder->getExpressionData($column, $this->context) + ); + } + + public function testBinary() + { + $builder = new ColumnBuilder\AbstractLengthColumnBuilder(new Builder); + $column = new Column\Binary('foo', 10000000); + $this->assertEquals( + [[ + '%s %s NOT NULL', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('BINARY(10000000)', $column::TYPE_LITERAL), + ], + ]], + $builder->getExpressionData($column, $this->context) + ); + } + + public function testBlob() + { + $builder = new ColumnBuilder\AbstractLengthColumnBuilder(new Builder); + $column = new Column\Blob('foo'); + $this->assertEquals( + [[ + '%s %s NOT NULL', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('BLOB', $column::TYPE_LITERAL), + ] + ]], + $builder->getExpressionData($column, $this->context) + ); + } + + public function testBoolean() + { + $builder = new ColumnBuilder\ColumnBuilder(new Builder); + $column = new Column\Boolean('foo'); + $this->assertEquals( + [[ + '%s %s NOT NULL', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('BOOLEAN', $column::TYPE_LITERAL), + ] + ]], + $builder->getExpressionData($column, $this->context) + ); + } + + public function testChar() + { + $builder = new ColumnBuilder\AbstractLengthColumnBuilder(new Builder); + $column = new Column\Char('foo', 20); + $this->assertEquals( + [[ + '%s %s NOT NULL', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('CHAR(20)', $column::TYPE_LITERAL), + ], + ]], + $builder->getExpressionData($column, $this->context) + ); + } + + public function testDate() + { + $builder = new ColumnBuilder\ColumnBuilder(new Builder); + $column = new Column\Date('foo'); + $this->assertEquals( + [[ + '%s %s NOT NULL', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('DATE', $column::TYPE_LITERAL), + ], + ]], + $builder->getExpressionData($column, $this->context) + ); + } + + public function testDatetime() + { + $builder = new ColumnBuilder\ColumnBuilder(new Builder); + $column = new Column\Datetime('foo'); + $this->assertEquals( + [[ + '%s %s NOT NULL', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('DATETIME', $column::TYPE_LITERAL), + ], + ]], + $builder->getExpressionData($column, $this->context) + ); + } + + public function testDecimal() + { + $builder = new ColumnBuilder\AbstractPrecisionColumnBuilder(new Builder); + $column = new Column\Decimal('foo', 10, 5); + $this->assertEquals( + [[ + '%s %s NOT NULL', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('DECIMAL(10,5)', $column::TYPE_LITERAL), + ], + ]], + $builder->getExpressionData($column, $this->context) + ); + } + + public function testFloating() + { + $builder = new ColumnBuilder\AbstractPrecisionColumnBuilder(new Builder); + $column = new Column\Floating('foo', 10, 5); + $this->assertEquals( + [[ + '%s %s NOT NULL', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('FLOAT(10,5)', $column::TYPE_LITERAL), + ], + ]], + $builder->getExpressionData($column, $this->context) + ); + } + + public function testInteger() + { + $builder = new ColumnBuilder\IntegerBuilder(new Builder); + $column = new Column\Integer('foo'); + $this->assertEquals( + [[ + '%s %s NOT NULL', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('INTEGER', $column::TYPE_LITERAL), + ], + ]], + $builder->getExpressionData($column, $this->context) + ); + + $column = new Column\Integer('foo'); + $column->addConstraint(new Constraint\PrimaryKey()); + $this->assertEquals( + [ + [ + '%s %s NOT NULL', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('INTEGER', $column::TYPE_LITERAL), + ], + ], + ' ', + [ + 'PRIMARY KEY', + [], + ] + ], + $builder->getExpressionData($column, $this->context) + ); + } + + public function testText() + { + $builder = new ColumnBuilder\AbstractLengthColumnBuilder(new Builder); + $column = new Column\Text('foo'); + $this->assertEquals( + [[ + '%s %s NOT NULL', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('TEXT', $column::TYPE_LITERAL), + ], + ]], + $builder->getExpressionData($column, $this->context) + ); + } + + public function testTime() + { + $builder = new ColumnBuilder\ColumnBuilder(new Builder); + $column = new Column\Time('foo'); + $this->assertEquals( + [[ + '%s %s NOT NULL', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('TIME', $column::TYPE_LITERAL), + ], + ]], + $builder->getExpressionData($column, $this->context) + ); + } + + public function testTimestamp() + { + $builder = new ColumnBuilder\AbstractTimestampColumnBuilder(new Builder); + $column = new Column\Timestamp('foo'); + $this->assertEquals( + [[ + '%s %s NOT NULL', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('TIMESTAMP', $column::TYPE_LITERAL), + ], + ]], + $builder->getExpressionData($column, $this->context) + ); + } + + public function testVarbinary() + { + $builder = new ColumnBuilder\AbstractLengthColumnBuilder(new Builder); + $column = new Column\Varbinary('foo', 20); + $this->assertEquals( + [[ + '%s %s NOT NULL', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('VARBINARY(20)', $column::TYPE_LITERAL), + ], + ]], + $builder->getExpressionData($column, $this->context) + ); + } + + public function testVarchar() + { + $builder = new ColumnBuilder\AbstractLengthColumnBuilder(new Builder); + $column = new Column\Varchar('foo', 20); + $this->assertEquals( + [[ + '%s %s NOT NULL', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('VARCHAR(20)', $column::TYPE_LITERAL), + ], + ]], + $builder->getExpressionData($column, $this->context) + ); + + $column->setDefault('bar'); + $this->assertEquals( + [[ + '%s %s NOT NULL DEFAULT %s', + [ + new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), + new ExpressionParameter('VARCHAR(20)', $column::TYPE_LITERAL), + new ExpressionParameter('bar', $column::TYPE_VALUE), + ] + ]], + $builder->getExpressionData($column, $this->context) + ); + } +} diff --git a/test/Sql/Builder/Ddl/Constraint/CheckBuilderTest.php b/test/Sql/Builder/Ddl/Constraint/CheckBuilderTest.php new file mode 100644 index 0000000000..0b9d40f15f --- /dev/null +++ b/test/Sql/Builder/Ddl/Constraint/CheckBuilderTest.php @@ -0,0 +1,45 @@ +builder = new CheckBuilder(new Builder); + $this->context = new Context($this->getAdapterForPlatform('sql92')); + } + + public function testGetExpressionData() + { + $check = new Check('id>0', 'foo'); + $this->assertEquals( + [[ + 'CONSTRAINT %s CHECK (%s)', + [ + new ExpressionParameter('foo', $check::TYPE_IDENTIFIER), + new ExpressionParameter('id>0', $check::TYPE_LITERAL), + ], + ]], + $this->builder->getExpressionData($check, $this->context) + ); + } +} diff --git a/test/Sql/Builder/Ddl/Constraint/ForeignKeyBuilderTest.php b/test/Sql/Builder/Ddl/Constraint/ForeignKeyBuilderTest.php new file mode 100644 index 0000000000..3008cfd173 --- /dev/null +++ b/test/Sql/Builder/Ddl/Constraint/ForeignKeyBuilderTest.php @@ -0,0 +1,47 @@ +builder = new ForeignKeyBuilder(new Builder); + $this->context = new Context($this->getAdapterForPlatform('sql92')); + } + + public function testGetExpressionData() + { + $fk = new ForeignKey('foo', 'bar', 'baz', 'bam', 'CASCADE', 'SET NULL'); + $this->assertEquals( + [[ + 'CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s) ON DELETE %s ON UPDATE %s', + [ + new ExpressionParameter('foo', ForeignKey::TYPE_IDENTIFIER), + new ExpressionParameter('bar', ForeignKey::TYPE_IDENTIFIER), + new ExpressionParameter('baz', ForeignKey::TYPE_IDENTIFIER), + new ExpressionParameter('bam', ForeignKey::TYPE_IDENTIFIER), + new ExpressionParameter('CASCADE', ForeignKey::TYPE_LITERAL), + new ExpressionParameter('SET NULL', ForeignKey::TYPE_LITERAL), + ], + ]], + $this->builder->getExpressionData($fk, $this->context) + ); + } +} diff --git a/test/Sql/Builder/Ddl/Constraint/PrimaryKeyBuilderTest.php b/test/Sql/Builder/Ddl/Constraint/PrimaryKeyBuilderTest.php new file mode 100644 index 0000000000..063b371fa6 --- /dev/null +++ b/test/Sql/Builder/Ddl/Constraint/PrimaryKeyBuilderTest.php @@ -0,0 +1,42 @@ +builder = new PrimaryKeyBuilder(new Builder); + $this->context = new Context($this->getAdapterForPlatform('sql92')); + } + + public function testGetExpressionData() + { + $pk = new PrimaryKey('foo'); + $this->assertEquals( + [[ + 'PRIMARY KEY (%s)', + [ + new ExpressionParameter('foo', $pk::TYPE_IDENTIFIER), + ], + ]], + $this->builder->getExpressionData($pk, $this->context) + ); + } +} diff --git a/test/Sql/Builder/Ddl/Constraint/UniqueKeyBuilderTest.php b/test/Sql/Builder/Ddl/Constraint/UniqueKeyBuilderTest.php new file mode 100644 index 0000000000..1299c4a9d3 --- /dev/null +++ b/test/Sql/Builder/Ddl/Constraint/UniqueKeyBuilderTest.php @@ -0,0 +1,43 @@ +builder = new UniqueKeyBuilder(new Builder); + $this->context = new Context($this->getAdapterForPlatform('sql92')); + } + + public function testGetExpressionData() + { + $uk = new UniqueKey('foo', 'my_uk'); + $this->assertEquals( + [[ + 'CONSTRAINT %s UNIQUE (%s)', + [ + new ExpressionParameter('my_uk', $uk::TYPE_IDENTIFIER), + new ExpressionParameter('foo', $uk::TYPE_IDENTIFIER), + ], + ]], + $this->builder->getExpressionData($uk, $this->context) + ); + } +} diff --git a/test/Sql/Builder/Ddl/Index/IndexBuilderTest.php b/test/Sql/Builder/Ddl/Index/IndexBuilderTest.php new file mode 100644 index 0000000000..a13de9280f --- /dev/null +++ b/test/Sql/Builder/Ddl/Index/IndexBuilderTest.php @@ -0,0 +1,84 @@ +builder = new IndexBuilder(new Builder); + $this->context = new Context($this->getAdapterForPlatform('sql92')); + } + + /** + * @covers Zend\Db\Sql\Ddl\Index\Index::getExpressionData + */ + public function testGetExpressionData() + { + $uk = new Index('foo', 'my_uk'); + $this->assertEquals( + [[ + 'INDEX %s(%s)', + [ + new ExpressionParameter('my_uk', $uk::TYPE_IDENTIFIER), + new ExpressionParameter('foo', $uk::TYPE_IDENTIFIER), + ], + ]], + $this->builder->getExpressionData($uk, $this->context) + ); + } + + /** + * @covers Zend\Db\Sql\Ddl\Index\Index::getExpressionData + */ + public function testGetExpressionDataWithLength() + { + $key = new Index(['foo', 'bar'], 'my_uk', [10, 5]); + $this->assertEquals( + [[ + 'INDEX %s(%s(10), %s(5))', + [ + new ExpressionParameter('my_uk', $key::TYPE_IDENTIFIER), + new ExpressionParameter('foo', $key::TYPE_IDENTIFIER), + new ExpressionParameter('bar', $key::TYPE_IDENTIFIER), + ], + ]], + $this->builder->getExpressionData($key, $this->context) + ); + } + + /** + * @covers Zend\Db\Sql\Ddl\Index\Index::getExpressionData + */ + public function testGetExpressionDataWithLengthUnmatched() + { + $key = new Index(['foo', 'bar'], 'my_uk', [10]); + $this->assertEquals( + [[ + 'INDEX %s(%s(10), %s)', + [ + new ExpressionParameter('my_uk', $key::TYPE_IDENTIFIER), + new ExpressionParameter('foo', $key::TYPE_IDENTIFIER), + new ExpressionParameter('bar', $key::TYPE_IDENTIFIER), + ], + ]], + $this->builder->getExpressionData($key, $this->context) + ); + } +} diff --git a/test/Sql/Builder/ExpressionBuilderTest.php b/test/Sql/Builder/ExpressionBuilderTest.php new file mode 100644 index 0000000000..a9c7a9197b --- /dev/null +++ b/test/Sql/Builder/ExpressionBuilderTest.php @@ -0,0 +1,107 @@ +builder = new ExpressionBuilder(new \Zend\Db\Sql\Builder\Builder()); + $this->context = new Context($this->getAdapterForPlatform('sql92')); + } + + public function testRetrievingWherePartsReturnsSpecificationArrayOfLiteralAndParametersAndArrayOfTypes() + { + $expression = new Expression(); + $expression->setExpression('foo.bar = ? AND id != ?') + ->setParameters(['foo', 'bar']); + + $this->assertEquals( + [[ + 'foo.bar = %s AND id != %s', + [ + new ExpressionParameter('foo', Expression::TYPE_VALUE), + new ExpressionParameter('bar', Expression::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($expression, $this->context) + ); + } + + /** + * @covers Zend\Db\Sql\Expression::getExpressionData + */ + public function testGetExpressionData() + { + $expression = new BaseExpression( + 'X SAME AS ? AND Y = ? BUT LITERALLY ?', + [ + ['foo', Expression::TYPE_IDENTIFIER], + [5, Expression::TYPE_VALUE], + ['FUNC(FF%X)', Expression::TYPE_LITERAL], + ] + ); + $this->assertEquals( + [[ + 'X SAME AS %s AND Y = %s BUT LITERALLY %s', + [ + new ExpressionParameter('foo', Expression::TYPE_IDENTIFIER), + new ExpressionParameter(5, Expression::TYPE_VALUE), + new ExpressionParameter('FUNC(FF%X)', Expression::TYPE_LITERAL), + ], + ]], + $this->builder->getExpressionData($expression, $this->context) + ); + + $expression = new BaseExpression( + 'X SAME AS ? AND Y = ? BUT LITERALLY ?', + [ + ['foo' => Expression::TYPE_IDENTIFIER], + [5 => Expression::TYPE_VALUE], + ['FUNC(FF%X)' => Expression::TYPE_LITERAL], + ] + ); + $this->assertEquals( + [[ + 'X SAME AS %s AND Y = %s BUT LITERALLY %s', + [ + new ExpressionParameter('foo', Expression::TYPE_IDENTIFIER), + new ExpressionParameter(5, Expression::TYPE_VALUE), + new ExpressionParameter('FUNC(FF%X)', Expression::TYPE_LITERAL), + ], + ]], + $this->builder->getExpressionData($expression, $this->context) + ); + } + + public function testGetExpressionDataWillEscapePercent() + { + $expression = new BaseExpression('X LIKE "foo%"'); + $this->assertEquals( + ['X LIKE "foo%%"'], + $this->builder->getExpressionData($expression, $this->context) + ); + } + + public function testNumberOfReplacemensConsidersWhenSameVariableIsUsedManyTimes() + { + $expression = new Expression('uf.user_id = :user_id OR uf.friend_id = :user_id', ['user_id' => 1]); + $this->builder->getExpressionData($expression, $this->context); + } +} diff --git a/test/Sql/Builder/LiteralBuilderTest.php b/test/Sql/Builder/LiteralBuilderTest.php new file mode 100644 index 0000000000..60e7f89135 --- /dev/null +++ b/test/Sql/Builder/LiteralBuilderTest.php @@ -0,0 +1,58 @@ +builder = new LiteralBuilder(new \Zend\Db\Sql\Builder\Builder()); + $this->context = new Context($this->getAdapterForPlatform('sql92')); + } + + public function testGetExpressionData() + { + $literal = new Literal('bar'); + $this->assertEquals( + [[ + 'bar', + [], + ]], + $this->builder->getExpressionData($literal, $this->context) + ); + } + + public function testGetExpressionDataWillEscapePercent() + { + $literal = new BaseLiteral('X LIKE "foo%"'); + $this->assertEquals([[ + 'X LIKE "foo%%"', + [], + ]], + $this->builder->getExpressionData($literal, $this->context) + ); + + $literal = new BaseLiteral('bar'); + $this->assertEquals( + [[ + 'bar', + [], + ]], + $this->builder->getExpressionData($literal, $this->context) + ); + } +} diff --git a/test/Sql/Builder/Predicate/BetweenBuilderTest.php b/test/Sql/Builder/Predicate/BetweenBuilderTest.php new file mode 100644 index 0000000000..b7316bd0ce --- /dev/null +++ b/test/Sql/Builder/Predicate/BetweenBuilderTest.php @@ -0,0 +1,68 @@ +expression = new Between; + $this->builder = new BetweenBuilder(new \Zend\Db\Sql\Builder\Builder()); + $this->context = new Context($this->getAdapterForPlatform('sql92')); + } + + /** + * @covers Zend\Db\Sql\Predicate\Between::getExpressionData + */ + public function testRetrievingWherePartsReturnsSpecificationArrayOfIdentifierAndValuesAndArrayOfTypes() + { + $this->expression->setIdentifier('foo.bar') + ->setMinValue(10) + ->setMaxValue(19); + + $this->assertEquals( + [[ + '%1$s BETWEEN %2$s AND %3$s', + [ + new ExpressionParameter('foo.bar', ExpressionInterface::TYPE_IDENTIFIER), + new ExpressionParameter(10, ExpressionInterface::TYPE_VALUE), + new ExpressionParameter(19, ExpressionInterface::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($this->expression, $this->context) + ); + + $this->expression->setIdentifier([10=>Between::TYPE_VALUE]) + ->setMinValue(['foo.bar'=>Between::TYPE_IDENTIFIER]) + ->setMaxValue(['foo.baz'=>Between::TYPE_IDENTIFIER]); + + $this->assertEquals( + [[ + '%1$s BETWEEN %2$s AND %3$s', + [ + new ExpressionParameter(10, Between::TYPE_VALUE), + new ExpressionParameter('foo.bar', Between::TYPE_IDENTIFIER), + new ExpressionParameter('foo.baz', Between::TYPE_IDENTIFIER), + ], + ]], + $this->builder->getExpressionData($this->expression, $this->context) + ); + } +} diff --git a/test/Sql/Builder/Predicate/InBuilderTest.php b/test/Sql/Builder/Predicate/InBuilderTest.php new file mode 100644 index 0000000000..3034aed3ad --- /dev/null +++ b/test/Sql/Builder/Predicate/InBuilderTest.php @@ -0,0 +1,135 @@ +builder = new InBuilder(new \Zend\Db\Sql\Builder\Builder()); + $this->context = new Context($this->getAdapterForPlatform('sql92')); + } + + public function testRetrievingWherePartsReturnsSpecificationArrayOfIdentifierAndValuesAndArrayOfTypes() + { + $in = new In(); + $in->setIdentifier('foo.bar') + ->setValueSet([1, 2, 3]); + + $this->assertEquals( + [[ + '%s IN (%s, %s, %s)', + [ + new ExpressionParameter('foo.bar', In::TYPE_IDENTIFIER), + new ExpressionParameter(1, In::TYPE_VALUE), + new ExpressionParameter(2, In::TYPE_VALUE), + new ExpressionParameter(3, In::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($in, $this->context) + ); + + $in->setIdentifier('foo.bar') + ->setValueSet([ + [1=>In::TYPE_LITERAL], + [2=>In::TYPE_VALUE], + [3=>In::TYPE_LITERAL], + ]); + + $this->assertEquals( + [[ + '%s IN (%s, %s, %s)', + [ + new ExpressionParameter('foo.bar', In::TYPE_IDENTIFIER), + new ExpressionParameter(1, In::TYPE_LITERAL), + new ExpressionParameter(2, In::TYPE_VALUE), + new ExpressionParameter(3, In::TYPE_LITERAL), + ], + ]], + $this->builder->getExpressionData($in, $this->context) + ); + } + + public function testGetExpressionDataWithSubselect() + { + $select = new Select; + $in = new In('foo', $select); + + $this->assertEquals( + [[ + '%s IN %s', + [ + new ExpressionParameter('foo', $in::TYPE_IDENTIFIER), + new ExpressionParameter($select, $in::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($in, $this->context) + ); + + $combine = new Combine; + $in = new In('foo', $combine); + + $this->assertEquals( + [[ + '%s IN %s', + [ + new ExpressionParameter('foo', $in::TYPE_IDENTIFIER), + new ExpressionParameter($combine, $in::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($in, $this->context) + ); + } + + public function testGetExpressionDataWithSubselectAndIdentifier() + { + $select = new Select; + $in = new In('foo', $select); + + $this->assertEquals( + [[ + '%s IN %s', + [ + new ExpressionParameter('foo', $in::TYPE_IDENTIFIER), + new ExpressionParameter($select, $in::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($in, $this->context) + ); + } + + public function testGetExpressionDataWithSubselectAndArrayIdentifier() + { + $select = new Select; + $in = new In(['foo', 'bar'], $select); + + $this->assertEquals( + [[ + '(%s, %s) IN %s', + [ + new ExpressionParameter('foo', $in::TYPE_IDENTIFIER), + new ExpressionParameter('bar', $in::TYPE_IDENTIFIER), + new ExpressionParameter($select, $in::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($in, $this->context) + ); + } +} diff --git a/test/Sql/Builder/Predicate/IsNotNullBuilderTest.php b/test/Sql/Builder/Predicate/IsNotNullBuilderTest.php new file mode 100644 index 0000000000..32e141ebcb --- /dev/null +++ b/test/Sql/Builder/Predicate/IsNotNullBuilderTest.php @@ -0,0 +1,44 @@ +expression = new IsNotNull; + $this->builder = new IsNotNullBuilder(new \Zend\Db\Sql\Builder\Builder()); + $this->context = new Context($this->getAdapterForPlatform('sql92')); + } + + public function testRetrievingWherePartsReturnsSpecificationArrayOfIdentifierAndArrayOfTypes() + { + $this->expression->setIdentifier('foo.bar'); + + $this->assertEquals( + [[ + '%1$s IS NOT NULL', + [ + new ExpressionParameter('foo.bar', IsNotNull::TYPE_IDENTIFIER), + ], + ]], + $this->builder->getExpressionData($this->expression, $this->context) + ); + } +} diff --git a/test/Sql/Builder/Predicate/LikeBuilderTest.php b/test/Sql/Builder/Predicate/LikeBuilderTest.php new file mode 100644 index 0000000000..33cfd89e0b --- /dev/null +++ b/test/Sql/Builder/Predicate/LikeBuilderTest.php @@ -0,0 +1,54 @@ +builder = new LikeBuilder(new \Zend\Db\Sql\Builder\Builder()); + $this->context = new Context($this->getAdapterForPlatform('sql92')); + } + + public function testGetExpressionData() + { + $like = new Like('bar', 'Foo%'); + $this->assertEquals( + [[ + '%1$s LIKE %2$s', + [ + new ExpressionParameter('bar', $like::TYPE_IDENTIFIER), + new ExpressionParameter('Foo%', $like::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($like, $this->context) + ); + + $like = new Like(['Foo%'=>$like::TYPE_VALUE], ['bar'=>$like::TYPE_IDENTIFIER]); + $this->assertEquals( + [[ + '%1$s LIKE %2$s', + [ + new ExpressionParameter('Foo%', $like::TYPE_VALUE), + new ExpressionParameter('bar', $like::TYPE_IDENTIFIER), + ], + ]], + $this->builder->getExpressionData($like, $this->context) + ); + } +} diff --git a/test/Sql/Builder/Predicate/NotBetweenBuilderTest.php b/test/Sql/Builder/Predicate/NotBetweenBuilderTest.php new file mode 100644 index 0000000000..0de99e5d56 --- /dev/null +++ b/test/Sql/Builder/Predicate/NotBetweenBuilderTest.php @@ -0,0 +1,68 @@ +expression = new NotBetween; + $this->builder = new NotBetweenBuilder(new \Zend\Db\Sql\Builder\Builder()); + $this->context = new Context($this->getAdapterForPlatform('sql92')); + } + + /** + * @covers Zend\Db\Sql\Predicate\Between::getExpressionData + */ + public function testRetrievingWherePartsReturnsSpecificationArrayOfIdentifierAndValuesAndArrayOfTypes() + { + $this->expression->setIdentifier('foo.bar') + ->setMinValue(10) + ->setMaxValue(19); + + $this->assertEquals( + [[ + '%1$s NOT BETWEEN %2$s AND %3$s', + [ + new ExpressionParameter('foo.bar', ExpressionInterface::TYPE_IDENTIFIER), + new ExpressionParameter(10, ExpressionInterface::TYPE_VALUE), + new ExpressionParameter(19, ExpressionInterface::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($this->expression, $this->context) + ); + + $this->expression->setIdentifier([10=>NotBetween::TYPE_VALUE]) + ->setMinValue(['foo.bar'=>NotBetween::TYPE_IDENTIFIER]) + ->setMaxValue(['foo.baz'=>NotBetween::TYPE_IDENTIFIER]); + + $this->assertEquals( + [[ + '%1$s NOT BETWEEN %2$s AND %3$s', + [ + new ExpressionParameter(10, NotBetween::TYPE_VALUE), + new ExpressionParameter('foo.bar', NotBetween::TYPE_IDENTIFIER), + new ExpressionParameter('foo.baz', NotBetween::TYPE_IDENTIFIER), + ], + ]], + $this->builder->getExpressionData($this->expression, $this->context) + ); + } +} diff --git a/test/Sql/Builder/Predicate/NotInBuilderTest.php b/test/Sql/Builder/Predicate/NotInBuilderTest.php new file mode 100644 index 0000000000..9905502040 --- /dev/null +++ b/test/Sql/Builder/Predicate/NotInBuilderTest.php @@ -0,0 +1,101 @@ +builder = new NotInBuilder(new \Zend\Db\Sql\Builder\Builder()); + $this->context = new Context($this->getAdapterForPlatform('sql92')); + } + + public function testRetrievingWherePartsReturnsSpecificationArrayOfIdentifierAndValuesAndArrayOfTypes() + { + $in = new NotIn(); + $in->setIdentifier('foo.bar') + ->setValueSet([1, 2, 3]); + + $this->assertEquals( + [[ + '%s NOT IN (%s, %s, %s)', + [ + new ExpressionParameter('foo.bar', NotIn::TYPE_IDENTIFIER), + new ExpressionParameter(1, NotIn::TYPE_VALUE), + new ExpressionParameter(2, NotIn::TYPE_VALUE), + new ExpressionParameter(3, NotIn::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($in, $this->context) + ); + } + + public function testGetExpressionDataWithSubselect() + { + $select = new Select; + $in = new NotIn('foo', $select); + + $this->assertEquals( + [[ + '%s NOT IN %s', + [ + new ExpressionParameter('foo', $in::TYPE_IDENTIFIER), + new ExpressionParameter($select, $in::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($in, $this->context) + ); + } + + public function testGetExpressionDataWithSubselectAndIdentifier() + { + $select = new Select; + $in = new NotIn('foo', $select); + + $this->assertEquals( + [[ + '%s NOT IN %s', + [ + new ExpressionParameter('foo', $in::TYPE_IDENTIFIER), + new ExpressionParameter($select, $in::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($in, $this->context) + ); + } + + public function testGetExpressionDataWithSubselectAndArrayIdentifier() + { + $select = new Select; + $in = new NotIn(['foo', 'bar'], $select); + + $this->assertEquals( + [[ + '(%s, %s) NOT IN %s', + [ + new ExpressionParameter('foo', $in::TYPE_IDENTIFIER), + new ExpressionParameter('bar', $in::TYPE_IDENTIFIER), + new ExpressionParameter($select, $in::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($in, $this->context) + ); + } +} diff --git a/test/Sql/Builder/Predicate/NotLikeBuilderTest.php b/test/Sql/Builder/Predicate/NotLikeBuilderTest.php new file mode 100644 index 0000000000..ffeb32e692 --- /dev/null +++ b/test/Sql/Builder/Predicate/NotLikeBuilderTest.php @@ -0,0 +1,43 @@ +builder = new NotLikeBuilder(new \Zend\Db\Sql\Builder\Builder()); + $this->context = new Context($this->getAdapterForPlatform('sql92')); + } + + public function testGetExpressionData() + { + $notLike = new NotLike('bar', 'Foo%'); + $this->assertEquals( + [[ + '%1$s NOT LIKE %2$s', + [ + new ExpressionParameter('bar', $notLike::TYPE_IDENTIFIER), + new ExpressionParameter('Foo%', $notLike::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($notLike, $this->context) + ); + } +} diff --git a/test/Sql/Builder/Predicate/OperatorBuilderTest.php b/test/Sql/Builder/Predicate/OperatorBuilderTest.php new file mode 100644 index 0000000000..9a7ea883f3 --- /dev/null +++ b/test/Sql/Builder/Predicate/OperatorBuilderTest.php @@ -0,0 +1,47 @@ +expression = new Operator; + $this->builder = new OperatorBuilder(new \Zend\Db\Sql\Builder\Builder()); + $this->context = new Context($this->getAdapterForPlatform('sql92')); + } + + public function testRetrievingWherePartsReturnsSpecificationArrayOfLeftAndRightAndArrayOfTypes() + { + $this->expression->setLeft(['foo', Operator::TYPE_VALUE]) + ->setOperator('>=') + ->setRight(['foo.bar', Operator::TYPE_IDENTIFIER]); + + $this->assertEquals( + [[ + '%s >= %s', + [ + new ExpressionParameter('foo', Operator::TYPE_VALUE), + new ExpressionParameter('foo.bar', Operator::TYPE_IDENTIFIER), + ], + ]], + $this->builder->getExpressionData($this->expression, $this->context) + ); + } +} diff --git a/test/Sql/Builder/Predicate/PredicateBuilderTest.php b/test/Sql/Builder/Predicate/PredicateBuilderTest.php new file mode 100644 index 0000000000..2ea9e610f3 --- /dev/null +++ b/test/Sql/Builder/Predicate/PredicateBuilderTest.php @@ -0,0 +1,400 @@ +expression = new Predicate; + $this->builder = new PredicateBuilder(new \Zend\Db\Sql\Builder\Builder()); + $this->context = new Context($this->getAdapterForPlatform('sql92')); + } + + public function testEqualToCreatesOperatorPredicate() + { + $predicate = new Predicate(); + $predicate->equalTo('foo.bar', 'bar'); + $this->assertEquals( + [[ + '%s = %s', + [ + new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), + new ExpressionParameter('bar', Predicate::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($predicate, $this->context) + ); + } + + public function testNotEqualToCreatesOperatorPredicate() + { + $predicate = new Predicate(); + $predicate->notEqualTo('foo.bar', 'bar'); + $this->assertEquals( + [[ + '%s != %s', + [ + new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), + new ExpressionParameter('bar', Predicate::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($predicate, $this->context) + ); + } + + public function testLessThanCreatesOperatorPredicate() + { + $predicate = new Predicate(); + $predicate->lessThan('foo.bar', 'bar'); + $this->assertEquals( + [[ + '%s < %s', + [ + new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), + new ExpressionParameter('bar', Predicate::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($predicate, $this->context) + ); + } + + public function testGreaterThanCreatesOperatorPredicate() + { + $predicate = new Predicate(); + $predicate->greaterThan('foo.bar', 'bar'); + $this->assertEquals( + [[ + '%s > %s', + [ + new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), + new ExpressionParameter('bar', Predicate::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($predicate, $this->context) + ); + } + + public function testLessThanOrEqualToCreatesOperatorPredicate() + { + $predicate = new Predicate(); + $predicate->lessThanOrEqualTo('foo.bar', 'bar'); + $this->assertEquals( + [[ + '%s <= %s', + [ + new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), + new ExpressionParameter('bar', Predicate::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($predicate, $this->context) + ); + } + + public function testGreaterThanOrEqualToCreatesOperatorPredicate() + { + $predicate = new Predicate(); + $predicate->greaterThanOrEqualTo('foo.bar', 'bar'); + $this->assertEquals( + [[ + '%s >= %s', + [ + new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), + new ExpressionParameter('bar', Predicate::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($predicate, $this->context) + ); + } + + public function testLikeCreatesLikePredicate() + { + $predicate = new Predicate(); + $predicate->like('foo.bar', 'bar%'); + $this->assertEquals( + [[ + '%1$s LIKE %2$s', + [ + new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), + new ExpressionParameter('bar%', Predicate::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($predicate, $this->context) + ); + } + + public function testNotLikeCreatesLikePredicate() + { + $predicate = new Predicate(); + $predicate->notLike('foo.bar', 'bar%'); + $this->assertEquals( + [[ + '%1$s NOT LIKE %2$s', + [ + new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), + new ExpressionParameter('bar%', Predicate::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($predicate, $this->context) + ); + } + + public function testLiteralCreatesLiteralPredicate() + { + $predicate = new Predicate(); + $predicate->literal('foo.bar = ?', 'bar'); + $this->assertEquals( + [[ + 'foo.bar = %s', + [ + new ExpressionParameter('bar', Predicate::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($predicate, $this->context) + ); + } + + public function testIsNullCreatesIsNullPredicate() + { + $predicate = new Predicate(); + $predicate->isNull('foo.bar'); + $this->assertEquals( + [[ + '%1$s IS NULL', + [ + new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), + ], + ]], + $this->builder->getExpressionData($predicate, $this->context) + ); + } + + public function testIsNotNullCreatesIsNotNullPredicate() + { + $predicate = new Predicate(); + $predicate->isNotNull('foo.bar'); + $this->assertEquals( + [[ + '%1$s IS NOT NULL', + [ + new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), + ], + ]], + $this->builder->getExpressionData($predicate, $this->context) + ); + } + + public function testInCreatesInPredicate() + { + $predicate = new Predicate(); + $predicate->in('foo.bar', ['foo', 'bar']); + $this->assertEquals( + [[ + '%s IN (%s, %s)', + [ + new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), + new ExpressionParameter('foo', Predicate::TYPE_VALUE), + new ExpressionParameter('bar', Predicate::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($predicate, $this->context) + ); + } + + public function testNotInCreatesNotInPredicate() + { + $predicate = new Predicate(); + $predicate->notIn('foo.bar', ['foo', 'bar']); + $this->assertEquals( + [[ + '%s NOT IN (%s, %s)', + [ + new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), + new ExpressionParameter('foo', Predicate::TYPE_VALUE), + new ExpressionParameter('bar', Predicate::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($predicate, $this->context) + ); + } + + public function testBetweenCreatesBetweenPredicate() + { + $predicate = new Predicate(); + $predicate->between('foo.bar', 1, 10); + $this->assertEquals( + [[ + '%1$s BETWEEN %2$s AND %3$s', + [ + new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), + new ExpressionParameter(1, Predicate::TYPE_VALUE), + new ExpressionParameter(10, Predicate::TYPE_VALUE), + ], + ]], + $this->builder->getExpressionData($predicate, $this->context) + ); + } + + public function testCanChainPredicateFactoriesBetweenOperators() + { + $predicate = new Predicate(); + $predicate->isNull('foo.bar') + ->or + ->isNotNull('bar.baz') + ->and + ->equalTo('baz.bat', 'foo'); + $this->assertEquals( + [ + [ + '%1$s IS NULL', + [ + new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), + ], + ], + ' OR ', + [ + '%1$s IS NOT NULL', + [ + new ExpressionParameter('bar.baz', Predicate::TYPE_IDENTIFIER), + ], + ], + ' AND ', + [ + '%s = %s', + [ + new ExpressionParameter('baz.bat', Predicate::TYPE_IDENTIFIER), + new ExpressionParameter('foo', Predicate::TYPE_VALUE), + ], + ], + ], + $this->builder->getExpressionData($predicate, $this->context) + ); + } + + public function testCanNestPredicates() + { + $predicate = new Predicate(); + $predicate->isNull('foo.bar') + ->nest() + ->isNotNull('bar.baz') + ->and + ->equalTo('baz.bat', 'foo') + ->unnest(); + $this->assertEquals( + [ + [ + '%1$s IS NULL', + [ + new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), + ], + ], + ' AND ', + '(', + [ + '%1$s IS NOT NULL', + [ + new ExpressionParameter('bar.baz', Predicate::TYPE_IDENTIFIER), + ], + ], + ' AND ', + [ + '%s = %s', + [ + new ExpressionParameter('baz.bat', Predicate::TYPE_IDENTIFIER), + new ExpressionParameter('foo', Predicate::TYPE_VALUE), + ], + ], + ')', + ], + $this->builder->getExpressionData($predicate, $this->context) + ); + } + + /** + * @testdox Unit test: Test expression() is chainable and returns proper values + */ + public function testExpression() + { + $predicate = new Predicate; + + // is chainable + $this->assertSame($predicate, $predicate->expression('foo = ?', 0)); + // with parameter + $this->assertEquals( + [[ + 'foo = %s', + [ + new ExpressionParameter(0, Predicate::TYPE_VALUE) + ] + ]], + $this->builder->getExpressionData($predicate, $this->context) + ); + } + + /** + * @testdox Unit test: Test expression() allows null $parameters + */ + public function testExpressionNullParameters() + { + $predicate = new Predicate; + + $predicate->expression('foo = bar'); + $predicates = $predicate->getPredicates(); + $expression = $predicates[0][1]; + $this->assertEquals( + [new ExpressionParameter(null, Predicate::TYPE_VALUE)], + $expression->getParameters() + ); + } + + /** + * @testdox Unit test: Test literal() is chainable, returns proper values, and is backwards compatible with 2.0.* + */ + public function testLiteral() + { + $predicate = new Predicate; + + // is chainable + $this->assertSame($predicate, $predicate->literal('foo = bar')); + // with parameter + $this->assertEquals( + [['foo = bar', []]], + $this->builder->getExpressionData($predicate, $this->context) + ); + + // test literal() is backwards-compatible, and works with with parameters + $predicate = new Predicate; + $predicate->expression('foo = ?', 'bar'); + // with parameter + $this->assertEquals( + [['foo = %s', [new ExpressionParameter('bar', ExpressionInterface::TYPE_VALUE)]]], + $this->builder->getExpressionData($predicate, $this->context) + ); + + // test literal() is backwards-compatible, and works with with parameters, even 0 which tests as false + $predicate = new Predicate; + $predicate->expression('foo = ?', 0); + // with parameter + $this->assertEquals( + [['foo = %s', [new ExpressionParameter(0, ExpressionInterface::TYPE_VALUE)]]], + $this->builder->getExpressionData($predicate, $this->context) + ); + } +} diff --git a/test/Sql/Builder/Predicate/PredicateSetBuilderTest.php b/test/Sql/Builder/Predicate/PredicateSetBuilderTest.php new file mode 100644 index 0000000000..1aeaba4428 --- /dev/null +++ b/test/Sql/Builder/Predicate/PredicateSetBuilderTest.php @@ -0,0 +1,89 @@ +expression = new PredicateSet; + $this->builder = new PredicateSetBuilder(new \Zend\Db\Sql\Builder\Builder()); + $this->context = new Context($this->getAdapterForPlatform('sql92')); + } + + public function testCombinationIsAndByDefault() + { + $this->expression->addPredicate(new IsNull('foo')) + ->addPredicate(new IsNull('bar')); + $parts = $this->builder->getExpressionData($this->expression, $this->context); + $this->assertEquals(3, count($parts)); + $this->assertContains('AND', $parts[1]); + $this->assertNotContains('OR', $parts[1]); + } + + public function testCanPassPredicatesAndDefaultCombinationViaConstructor() + { + $predicateSet = new PredicateSet([ + new IsNull('foo'), + new IsNull('bar'), + ], 'OR'); + $parts = $this->builder->getExpressionData($predicateSet, $this->context); + $this->assertEquals(3, count($parts)); + $this->assertContains('OR', $parts[1]); + $this->assertNotContains('AND', $parts[1]); + } + + public function testCanPassBothPredicateAndCombinationToAddPredicate() + { + $this->expression->addPredicate(new IsNull('foo'), 'OR') + ->addPredicate(new IsNull('bar'), 'AND') + ->addPredicate(new IsNull('baz'), 'OR') + ->addPredicate(new IsNull('bat'), 'AND'); + $parts = $this->builder->getExpressionData($this->expression, $this->context); + $this->assertEquals(7, count($parts)); + + $this->assertNotContains('OR', $parts[1], var_export($parts, 1)); + $this->assertContains('AND', $parts[1]); + + $this->assertContains('OR', $parts[3]); + $this->assertNotContains('AND', $parts[3]); + + $this->assertNotContains('OR', $parts[5]); + $this->assertContains('AND', $parts[5]); + } + + public function testCanUseOrPredicateAndAndPredicateMethods() + { + $this->expression->orPredicate(new IsNull('foo')) + ->andPredicate(new IsNull('bar')) + ->orPredicate(new IsNull('baz')) + ->andPredicate(new IsNull('bat')); + $parts = $this->builder->getExpressionData($this->expression, $this->context); + $this->assertEquals(7, count($parts)); + + $this->assertNotContains('OR', $parts[1], var_export($parts, 1)); + $this->assertContains('AND', $parts[1]); + + $this->assertContains('OR', $parts[3]); + $this->assertNotContains('AND', $parts[3]); + + $this->assertNotContains('OR', $parts[5]); + $this->assertContains('AND', $parts[5]); + } +} diff --git a/test/Sql/Builder/SelectBuilderTest.php b/test/Sql/Builder/SelectBuilderTest.php index a93ac9332b..03ec5bfe13 100644 --- a/test/Sql/Builder/SelectBuilderTest.php +++ b/test/Sql/Builder/SelectBuilderTest.php @@ -356,8 +356,11 @@ public function dataProvider_SQL92() [ new Expression( '(COUNT(?) + ?) AS ?', - ['some_column', 5, 'bar'], - [Expression::TYPE_IDENTIFIER, Expression::TYPE_VALUE, Expression::TYPE_IDENTIFIER] + [ + ['some_column', Expression::TYPE_IDENTIFIER], + [5, Expression::TYPE_VALUE], + ['bar', Expression::TYPE_IDENTIFIER], + ] ) ] ), @@ -451,7 +454,7 @@ public function dataProvider_SQL92() ], ], [ // group - 'sqlObject' => $this->select()->from('foo')->group(new Expression('DAY(?)', ['col1'], [Expression::TYPE_IDENTIFIER])), + 'sqlObject' => $this->select()->from('foo')->group(new Expression('DAY(?)', [['col1', Expression::TYPE_IDENTIFIER]])), 'expected' => [ 'sql92' => [ 'string' => 'SELECT "foo".* FROM "foo" GROUP BY DAY("col1")', @@ -603,7 +606,7 @@ public function dataProvider_SQL92() 'sqlObject' => $this->select() ->from('table') ->order([ - new Expression('isnull(?) DESC', ['name'], [Expression::TYPE_IDENTIFIER]), + new Expression('isnull(?) DESC', [['name', Expression::TYPE_IDENTIFIER]]), 'name' ]), 'expected' => [ diff --git a/test/Sql/Ddl/Column/AbstractLengthColumnTest.php b/test/Sql/Ddl/Column/AbstractLengthColumnTest.php index 336b69ff40..e3573aee89 100644 --- a/test/Sql/Ddl/Column/AbstractLengthColumnTest.php +++ b/test/Sql/Ddl/Column/AbstractLengthColumnTest.php @@ -34,19 +34,4 @@ public function testGetLength() ]); $this->assertEquals(55, $column->getLength()); } - - /** - * @covers Zend\Db\Sql\Ddl\Column\AbstractLengthColumn::getExpressionData - */ - public function testGetExpressionData() - { - $column = $this->getMockForAbstractClass('Zend\Db\Sql\Ddl\Column\AbstractLengthColumn', [ - 'foo', 4 - ]); - - $this->assertEquals( - [['%s %s NOT NULL', ['foo', 'INTEGER(4)'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL]]], - $column->getExpressionData() - ); - } } diff --git a/test/Sql/Ddl/Column/AbstractPrecisionColumnTest.php b/test/Sql/Ddl/Column/AbstractPrecisionColumnTest.php index 8b2d235155..bc6398758c 100644 --- a/test/Sql/Ddl/Column/AbstractPrecisionColumnTest.php +++ b/test/Sql/Ddl/Column/AbstractPrecisionColumnTest.php @@ -58,19 +58,4 @@ public function testGetDecimal() ]); $this->assertEquals(5, $column->getDecimal()); } - - /** - * @covers Zend\Db\Sql\Ddl\Column\AbstractPrecisionColumn::getExpressionData - */ - public function testGetExpressionData() - { - $column = $this->getMockForAbstractClass('Zend\Db\Sql\Ddl\Column\AbstractPrecisionColumn', [ - 'foo', 10, 5 - ]); - - $this->assertEquals( - [['%s %s NOT NULL', ['foo', 'INTEGER(10,5)'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL]]], - $column->getExpressionData() - ); - } } diff --git a/test/Sql/Ddl/Column/BigIntegerTest.php b/test/Sql/Ddl/Column/BigIntegerTest.php index d2b2d8eb79..255e6f7930 100644 --- a/test/Sql/Ddl/Column/BigIntegerTest.php +++ b/test/Sql/Ddl/Column/BigIntegerTest.php @@ -21,16 +21,4 @@ public function testObjectConstruction() $integer = new BigInteger('foo'); $this->assertEquals('foo', $integer->getName()); } - - /** - * @covers Zend\Db\Sql\Ddl\Column\Column::getExpressionData - */ - public function testGetExpressionData() - { - $column = new BigInteger('foo'); - $this->assertEquals( - [['%s %s NOT NULL', ['foo', 'BIGINT'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL]]], - $column->getExpressionData() - ); - } } diff --git a/test/Sql/Ddl/Column/BinaryTest.php b/test/Sql/Ddl/Column/BinaryTest.php deleted file mode 100644 index a67033a85e..0000000000 --- a/test/Sql/Ddl/Column/BinaryTest.php +++ /dev/null @@ -1,27 +0,0 @@ -assertEquals( - [['%s %s NOT NULL', ['foo', 'BINARY(10000000)'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL]]], - $column->getExpressionData() - ); - } -} diff --git a/test/Sql/Ddl/Column/BlobTest.php b/test/Sql/Ddl/Column/BlobTest.php deleted file mode 100644 index e8ffd4e1ee..0000000000 --- a/test/Sql/Ddl/Column/BlobTest.php +++ /dev/null @@ -1,27 +0,0 @@ -assertEquals( - [['%s %s NOT NULL', ['foo', 'BLOB'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL]]], - $column->getExpressionData() - ); - } -} diff --git a/test/Sql/Ddl/Column/BooleanTest.php b/test/Sql/Ddl/Column/BooleanTest.php index 605c649477..4288f98937 100644 --- a/test/Sql/Ddl/Column/BooleanTest.php +++ b/test/Sql/Ddl/Column/BooleanTest.php @@ -13,18 +13,6 @@ class BooleanTest extends \PHPUnit_Framework_TestCase { - /** - * @covers Zend\Db\Sql\Ddl\Column\Boolean::getExpressionData - */ - public function testGetExpressionData() - { - $column = new Boolean('foo'); - $this->assertEquals( - [['%s %s NOT NULL', ['foo', 'BOOLEAN'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL]]], - $column->getExpressionData() - ); - } - /** * @covers Zend\Db\Sql\Ddl\Column\Boolean * diff --git a/test/Sql/Ddl/Column/CharTest.php b/test/Sql/Ddl/Column/CharTest.php deleted file mode 100644 index f59643c3fb..0000000000 --- a/test/Sql/Ddl/Column/CharTest.php +++ /dev/null @@ -1,27 +0,0 @@ -assertEquals( - [['%s %s NOT NULL', ['foo', 'CHAR(20)'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL]]], - $column->getExpressionData() - ); - } -} diff --git a/test/Sql/Ddl/Column/ColumnTest.php b/test/Sql/Ddl/Column/ColumnTest.php index c44e656dd6..0b4a222e39 100644 --- a/test/Sql/Ddl/Column/ColumnTest.php +++ b/test/Sql/Ddl/Column/ColumnTest.php @@ -99,29 +99,4 @@ public function testGetOptions(Column $column) { $this->assertEquals(['autoincrement' => true], $column->getOptions()); } - - /** - * @covers Zend\Db\Sql\Ddl\Column\Column::getExpressionData - */ - public function testGetExpressionData() - { - $column = new Column; - $column->setName('foo'); - $this->assertEquals( - [['%s %s NOT NULL', ['foo', 'INTEGER'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL]]], - $column->getExpressionData() - ); - - $column->setNullable(true); - $this->assertEquals( - [['%s %s', ['foo', 'INTEGER'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL]]], - $column->getExpressionData() - ); - - $column->setDefault('bar'); - $this->assertEquals( - [['%s %s DEFAULT %s', ['foo', 'INTEGER', 'bar'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL, $column::TYPE_VALUE]]], - $column->getExpressionData() - ); - } } diff --git a/test/Sql/Ddl/Column/DateTest.php b/test/Sql/Ddl/Column/DateTest.php deleted file mode 100644 index f4202182fb..0000000000 --- a/test/Sql/Ddl/Column/DateTest.php +++ /dev/null @@ -1,27 +0,0 @@ -assertEquals( - [['%s %s NOT NULL', ['foo', 'DATE'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL]]], - $column->getExpressionData() - ); - } -} diff --git a/test/Sql/Ddl/Column/DatetimeTest.php b/test/Sql/Ddl/Column/DatetimeTest.php deleted file mode 100644 index 0c47104337..0000000000 --- a/test/Sql/Ddl/Column/DatetimeTest.php +++ /dev/null @@ -1,27 +0,0 @@ -assertEquals( - [['%s %s NOT NULL', ['foo', 'DATETIME'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL]]], - $column->getExpressionData() - ); - } -} diff --git a/test/Sql/Ddl/Column/DecimalTest.php b/test/Sql/Ddl/Column/DecimalTest.php deleted file mode 100644 index c9c9420209..0000000000 --- a/test/Sql/Ddl/Column/DecimalTest.php +++ /dev/null @@ -1,27 +0,0 @@ -assertEquals( - [['%s %s NOT NULL', ['foo', 'DECIMAL(10,5)'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL]]], - $column->getExpressionData() - ); - } -} diff --git a/test/Sql/Ddl/Column/FloatTest.php b/test/Sql/Ddl/Column/FloatTest.php deleted file mode 100644 index b3c2d232f2..0000000000 --- a/test/Sql/Ddl/Column/FloatTest.php +++ /dev/null @@ -1,28 +0,0 @@ -=')) { - $this->markTestSkipped('Cannot test Float column under PHP 7; reserved keyword'); - } - } - - public function testRaisesDeprecationNoticeOnInstantiation() - { - $this->setExpectedException('PHPUnit_Framework_Error_Deprecated'); - new FloatColumn('foo', 10, 5); - } -} diff --git a/test/Sql/Ddl/Column/FloatingTest.php b/test/Sql/Ddl/Column/FloatingTest.php deleted file mode 100644 index 2195e0ccef..0000000000 --- a/test/Sql/Ddl/Column/FloatingTest.php +++ /dev/null @@ -1,31 +0,0 @@ -assertEquals( - [[ - '%s %s NOT NULL', - ['foo', 'FLOAT(10,5)'], - [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL] - ]], - $column->getExpressionData() - ); - } -} diff --git a/test/Sql/Ddl/Column/IntegerTest.php b/test/Sql/Ddl/Column/IntegerTest.php index 37a2f49cd2..7de70cb9e1 100644 --- a/test/Sql/Ddl/Column/IntegerTest.php +++ b/test/Sql/Ddl/Column/IntegerTest.php @@ -10,7 +10,6 @@ namespace ZendTest\Db\Sql\Ddl\Column; use Zend\Db\Sql\Ddl\Column\Integer; -use Zend\Db\Sql\Ddl\Constraint\PrimaryKey; class IntegerTest extends \PHPUnit_Framework_TestCase { @@ -22,27 +21,4 @@ public function testObjectConstruction() $integer = new Integer('foo'); $this->assertEquals('foo', $integer->getName()); } - - /** - * @covers Zend\Db\Sql\Ddl\Column\Column::getExpressionData - */ - public function testGetExpressionData() - { - $column = new Integer('foo'); - $this->assertEquals( - [['%s %s NOT NULL', ['foo', 'INTEGER'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL]]], - $column->getExpressionData() - ); - - $column = new Integer('foo'); - $column->addConstraint(new PrimaryKey()); - $this->assertEquals( - [ - ['%s %s NOT NULL', ['foo', 'INTEGER'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL]], - ' ', - ['PRIMARY KEY', [], []] - ], - $column->getExpressionData() - ); - } } diff --git a/test/Sql/Ddl/Column/TextTest.php b/test/Sql/Ddl/Column/TextTest.php deleted file mode 100644 index c1d09bcc66..0000000000 --- a/test/Sql/Ddl/Column/TextTest.php +++ /dev/null @@ -1,27 +0,0 @@ -assertEquals( - [['%s %s NOT NULL', ['foo', 'TEXT'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL]]], - $column->getExpressionData() - ); - } -} diff --git a/test/Sql/Ddl/Column/TimeTest.php b/test/Sql/Ddl/Column/TimeTest.php deleted file mode 100644 index f071a5a5bc..0000000000 --- a/test/Sql/Ddl/Column/TimeTest.php +++ /dev/null @@ -1,27 +0,0 @@ -assertEquals( - [['%s %s NOT NULL', ['foo', 'TIME'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL]]], - $column->getExpressionData() - ); - } -} diff --git a/test/Sql/Ddl/Column/TimestampTest.php b/test/Sql/Ddl/Column/TimestampTest.php deleted file mode 100644 index 53815e1231..0000000000 --- a/test/Sql/Ddl/Column/TimestampTest.php +++ /dev/null @@ -1,27 +0,0 @@ -assertEquals( - [['%s %s NOT NULL', ['foo', 'TIMESTAMP'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL]]], - $column->getExpressionData() - ); - } -} diff --git a/test/Sql/Ddl/Column/VarbinaryTest.php b/test/Sql/Ddl/Column/VarbinaryTest.php deleted file mode 100644 index d78171ae9e..0000000000 --- a/test/Sql/Ddl/Column/VarbinaryTest.php +++ /dev/null @@ -1,27 +0,0 @@ -assertEquals( - [['%s %s NOT NULL', ['foo', 'VARBINARY(20)'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL]]], - $column->getExpressionData() - ); - } -} diff --git a/test/Sql/Ddl/Column/VarcharTest.php b/test/Sql/Ddl/Column/VarcharTest.php deleted file mode 100644 index 20040d0d52..0000000000 --- a/test/Sql/Ddl/Column/VarcharTest.php +++ /dev/null @@ -1,33 +0,0 @@ -assertEquals( - [['%s %s NOT NULL', ['foo', 'VARCHAR(20)'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL]]], - $column->getExpressionData() - ); - - $column->setDefault('bar'); - $this->assertEquals( - [['%s %s NOT NULL DEFAULT %s', ['foo', 'VARCHAR(20)', 'bar'], [$column::TYPE_IDENTIFIER, $column::TYPE_LITERAL, $column::TYPE_VALUE]]], - $column->getExpressionData() - ); - } -} diff --git a/test/Sql/Ddl/Constraint/CheckTest.php b/test/Sql/Ddl/Constraint/CheckTest.php deleted file mode 100644 index aa5b6e6740..0000000000 --- a/test/Sql/Ddl/Constraint/CheckTest.php +++ /dev/null @@ -1,31 +0,0 @@ -0', 'foo'); - $this->assertEquals( - [[ - 'CONSTRAINT %s CHECK (%s)', - ['foo', 'id>0'], - [$check::TYPE_IDENTIFIER, $check::TYPE_LITERAL] - ]], - $check->getExpressionData() - ); - } -} diff --git a/test/Sql/Ddl/Constraint/ForeignKeyTest.php b/test/Sql/Ddl/Constraint/ForeignKeyTest.php index 1f8dc8452c..d75fd132c2 100644 --- a/test/Sql/Ddl/Constraint/ForeignKeyTest.php +++ b/test/Sql/Ddl/Constraint/ForeignKeyTest.php @@ -107,20 +107,4 @@ public function testGetOnUpdateRule(ForeignKey $fk) { $this->assertEquals('CASCADE', $fk->getOnUpdateRule()); } - - /** - * @covers Zend\Db\Sql\Ddl\Constraint\ForeignKey::getExpressionData - */ - public function testGetExpressionData() - { - $fk = new ForeignKey('foo', 'bar', 'baz', 'bam', 'CASCADE', 'SET NULL'); - $this->assertEquals( - [[ - 'CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s) ON DELETE %s ON UPDATE %s', - ['foo', 'bar', 'baz', 'bam', 'CASCADE', 'SET NULL'], - [$fk::TYPE_IDENTIFIER, $fk::TYPE_IDENTIFIER, $fk::TYPE_IDENTIFIER, $fk::TYPE_IDENTIFIER, $fk::TYPE_LITERAL, $fk::TYPE_LITERAL] - ]], - $fk->getExpressionData() - ); - } } diff --git a/test/Sql/Ddl/Constraint/PrimaryKeyTest.php b/test/Sql/Ddl/Constraint/PrimaryKeyTest.php deleted file mode 100644 index 001ff334d3..0000000000 --- a/test/Sql/Ddl/Constraint/PrimaryKeyTest.php +++ /dev/null @@ -1,31 +0,0 @@ -assertEquals( - [[ - 'PRIMARY KEY (%s)', - ['foo'], - [$pk::TYPE_IDENTIFIER] - ]], - $pk->getExpressionData() - ); - } -} diff --git a/test/Sql/Ddl/Constraint/UniqueKeyTest.php b/test/Sql/Ddl/Constraint/UniqueKeyTest.php deleted file mode 100644 index 5506355d2a..0000000000 --- a/test/Sql/Ddl/Constraint/UniqueKeyTest.php +++ /dev/null @@ -1,31 +0,0 @@ -assertEquals( - [[ - 'CONSTRAINT %s UNIQUE (%s)', - ['my_uk', 'foo'], - [$uk::TYPE_IDENTIFIER, $uk::TYPE_IDENTIFIER] - ]], - $uk->getExpressionData() - ); - } -} diff --git a/test/Sql/Ddl/Index/IndexTest.php b/test/Sql/Ddl/Index/IndexTest.php deleted file mode 100644 index c57aa85635..0000000000 --- a/test/Sql/Ddl/Index/IndexTest.php +++ /dev/null @@ -1,63 +0,0 @@ -assertEquals( - [[ - 'INDEX %s(%s)', - ['my_uk', 'foo'], - [$uk::TYPE_IDENTIFIER, $uk::TYPE_IDENTIFIER] - ]], - $uk->getExpressionData() - ); - } - - /** - * @covers Zend\Db\Sql\Ddl\Index\Index::getExpressionData - */ - public function testGetExpressionDataWithLength() - { - $key = new Index(['foo', 'bar'], 'my_uk', [10, 5]); - $this->assertEquals( - [[ - 'INDEX %s(%s(10), %s(5))', - ['my_uk', 'foo', 'bar'], - [$key::TYPE_IDENTIFIER, $key::TYPE_IDENTIFIER, $key::TYPE_IDENTIFIER] - ]], - $key->getExpressionData() - ); - } - - /** - * @covers Zend\Db\Sql\Ddl\Index\Index::getExpressionData - */ - public function testGetExpressionDataWithLengthUnmatched() - { - $key = new Index(['foo', 'bar'], 'my_uk', [10]); - $this->assertEquals( - [[ - 'INDEX %s(%s(10), %s)', - ['my_uk', 'foo', 'bar'], - [$key::TYPE_IDENTIFIER, $key::TYPE_IDENTIFIER, $key::TYPE_IDENTIFIER] - ]], - $key->getExpressionData() - ); - } -} diff --git a/test/Sql/ExpressionTest.php b/test/Sql/ExpressionTest.php index ac2991c6c5..8677ab3ec9 100644 --- a/test/Sql/ExpressionTest.php +++ b/test/Sql/ExpressionTest.php @@ -10,6 +10,7 @@ namespace ZendTest\Db\Sql; use Zend\Db\Sql\Expression; +use Zend\Db\Sql\ExpressionParameter; /** * This is a unit testing test case. @@ -77,79 +78,18 @@ public function testSetParametersException() * @depends testSetParameters */ public function testGetParameters(Expression $expression) - { - $this->assertEquals('foo', $expression->getParameters()); - } - - /** - * @covers Zend\Db\Sql\Expression::setTypes - */ - public function testSetTypes() - { - $expression = new Expression(); - $return = $expression->setTypes([Expression::TYPE_IDENTIFIER, Expression::TYPE_VALUE, Expression::TYPE_LITERAL]); - $this->assertSame($expression, $return); - return $expression; - } - - /** - * @covers Zend\Db\Sql\Expression::getTypes - * @depends testSetTypes - */ - public function testGetTypes(Expression $expression) { $this->assertEquals( - [Expression::TYPE_IDENTIFIER, Expression::TYPE_VALUE, Expression::TYPE_LITERAL], - $expression->getTypes() + [ + new ExpressionParameter('foo', Expression::TYPE_VALUE) + ], + $expression->getParameters() ); } /** - * @covers Zend\Db\Sql\Expression::getExpressionData + * @covers Zend\Db\Sql\Expression::__construct */ - public function testGetExpressionData() - { - $expression = new Expression( - 'X SAME AS ? AND Y = ? BUT LITERALLY ?', - ['foo', 5, 'FUNC(FF%X)'], - [Expression::TYPE_IDENTIFIER, Expression::TYPE_VALUE, Expression::TYPE_LITERAL] - ); - - $this->assertEquals( - [[ - 'X SAME AS %s AND Y = %s BUT LITERALLY %s', - ['foo', 5, 'FUNC(FF%X)'], - [Expression::TYPE_IDENTIFIER, Expression::TYPE_VALUE, Expression::TYPE_LITERAL] - ]], - $expression->getExpressionData() - ); - $expression = new Expression( - 'X SAME AS ? AND Y = ? BUT LITERALLY ?', - [ - ['foo' => Expression::TYPE_IDENTIFIER], - [5 => Expression::TYPE_VALUE], - ['FUNC(FF%X)' => Expression::TYPE_LITERAL], - ] - ); - - $expected = [[ - 'X SAME AS %s AND Y = %s BUT LITERALLY %s', - ['foo', 5, 'FUNC(FF%X)'], - [Expression::TYPE_IDENTIFIER, Expression::TYPE_VALUE, Expression::TYPE_LITERAL] - ]]; - - $this->assertEquals($expected, $expression->getExpressionData()); - } - - public function testGetExpressionDataWillEscapePercent() - { - $expression = new Expression('X LIKE "foo%"'); - $this->assertEquals( - ['X LIKE "foo%%"'], - $expression->getExpressionData() - ); - } - public function testConstructorWithLiteralZero() { $expression = new Expression('0'); @@ -166,10 +106,4 @@ public function testGetExpressionPreservesPercentageSignInFromUnixtime() $this->assertSame($expressionString, $expression->getExpression()); } - - public function testNumberOfReplacemensConsidersWhenSameVariableIsUsedManyTimes() - { - $expression = new Expression('uf.user_id = :user_id OR uf.friend_id = :user_id', ['user_id' => 1]); - $expression->getExpressionData(); - } } diff --git a/test/Sql/LiteralTest.php b/test/Sql/LiteralTest.php index db0218a714..6c224458da 100644 --- a/test/Sql/LiteralTest.php +++ b/test/Sql/LiteralTest.php @@ -24,22 +24,4 @@ public function testGetLiteral() $literal = new Literal('bar'); $this->assertEquals('bar', $literal->getLiteral()); } - - public function testGetExpressionData() - { - $literal = new Literal('bar'); - $this->assertEquals([['bar', [], []]], $literal->getExpressionData()); - } - - public function testGetExpressionDataWillEscapePercent() - { - $expression = new Literal('X LIKE "foo%"'); - $this->assertEquals([[ - 'X LIKE "foo%%"', - [], - [] - ]], - $expression->getExpressionData() - ); - } } diff --git a/test/Sql/Predicate/BetweenTest.php b/test/Sql/Predicate/BetweenTest.php index 5037fff092..9e480ef844 100644 --- a/test/Sql/Predicate/BetweenTest.php +++ b/test/Sql/Predicate/BetweenTest.php @@ -46,31 +46,21 @@ public function testConstructorYieldsNullIdentifierMinimumAndMaximumValues() public function testConstructorCanPassIdentifierMinimumAndMaximumValues() { $between = new Between('foo.bar', 1, 300); - $this->assertEquals('foo.bar', $between->getIdentifier()); - $this->assertSame(1, $between->getMinValue()); - $this->assertSame(300, $between->getMaxValue()); + $this->assertEquals('foo.bar', $between->getIdentifier()->getValue()); + $this->assertSame(1, $between->getMinValue()->getValue()); + $this->assertSame(300, $between->getMaxValue()->getValue()); $between = new Between('foo.bar', 0, 1); - $this->assertEquals('foo.bar', $between->getIdentifier()); - $this->assertSame(0, $between->getMinValue()); - $this->assertSame(1, $between->getMaxValue()); + $this->assertEquals('foo.bar', $between->getIdentifier()->getValue()); + $this->assertSame(0, $between->getMinValue()->getValue()); + $this->assertSame(1, $between->getMaxValue()->getValue()); $between = new Between('foo.bar', -1, 0); - $this->assertEquals('foo.bar', $between->getIdentifier()); - $this->assertSame(-1, $between->getMinValue()); - $this->assertSame(0, $between->getMaxValue()); + $this->assertEquals('foo.bar', $between->getIdentifier()->getValue()); + $this->assertSame(-1, $between->getMinValue()->getValue()); + $this->assertSame(0, $between->getMaxValue()->getValue()); } - /** - * @covers Zend\Db\Sql\Predicate\Between::getSpecification - */ - public function testSpecificationHasSaneDefaultValue() - { - $this->assertEquals('%1$s BETWEEN %2$s AND %3$s', $this->between->getSpecification()); - } - - - /** * @covers Zend\Db\Sql\Predicate\Between::setIdentifier * @covers Zend\Db\Sql\Predicate\Between::getIdentifier @@ -78,7 +68,7 @@ public function testSpecificationHasSaneDefaultValue() public function testIdentifierIsMutable() { $this->between->setIdentifier('foo.bar'); - $this->assertEquals('foo.bar', $this->between->getIdentifier()); + $this->assertEquals('foo.bar', $this->between->getIdentifier()->getValue()); } /** @@ -88,7 +78,7 @@ public function testIdentifierIsMutable() public function testMinValueIsMutable() { $this->between->setMinValue(10); - $this->assertEquals(10, $this->between->getMinValue()); + $this->assertEquals(10, $this->between->getMinValue()->getValue()); } /** @@ -98,42 +88,6 @@ public function testMinValueIsMutable() public function testMaxValueIsMutable() { $this->between->setMaxValue(10); - $this->assertEquals(10, $this->between->getMaxValue()); - } - - /** - * @covers Zend\Db\Sql\Predicate\Between::setSpecification - * @covers Zend\Db\Sql\Predicate\Between::getSpecification - */ - public function testSpecificationIsMutable() - { - $this->between->setSpecification('%1$s IS INBETWEEN %2$s AND %3$s'); - $this->assertEquals('%1$s IS INBETWEEN %2$s AND %3$s', $this->between->getSpecification()); - } - - /** - * @covers Zend\Db\Sql\Predicate\Between::getExpressionData - */ - public function testRetrievingWherePartsReturnsSpecificationArrayOfIdentifierAndValuesAndArrayOfTypes() - { - $this->between->setIdentifier('foo.bar') - ->setMinValue(10) - ->setMaxValue(19); - $expected = [[ - $this->between->getSpecification(), - ['foo.bar', 10, 19], - [Between::TYPE_IDENTIFIER, Between::TYPE_VALUE, Between::TYPE_VALUE], - ]]; - $this->assertEquals($expected, $this->between->getExpressionData()); - - $this->between->setIdentifier([10=>Between::TYPE_VALUE]) - ->setMinValue(['foo.bar'=>Between::TYPE_IDENTIFIER]) - ->setMaxValue(['foo.baz'=>Between::TYPE_IDENTIFIER]); - $expected = [[ - $this->between->getSpecification(), - [10, 'foo.bar', 'foo.baz'], - [Between::TYPE_VALUE, Between::TYPE_IDENTIFIER, Between::TYPE_IDENTIFIER], - ]]; - $this->assertEquals($expected, $this->between->getExpressionData()); + $this->assertEquals(10, $this->between->getMaxValue()->getValue()); } } diff --git a/test/Sql/Predicate/ExpressionTest.php b/test/Sql/Predicate/ExpressionTest.php index f1833c990f..80f792e02b 100644 --- a/test/Sql/Predicate/ExpressionTest.php +++ b/test/Sql/Predicate/ExpressionTest.php @@ -12,6 +12,7 @@ use PHPUnit_Framework_TestCase as TestCase; use Zend\Db\Sql\Predicate\Expression; use Zend\Db\Sql\Predicate\IsNull; +use Zend\Db\Sql\ExpressionParameter; class ExpressionTest extends TestCase { @@ -29,7 +30,12 @@ public function testCanPassLiteralAndSingleScalarParameterToConstructor() { $expression = new Expression('foo.bar = ?', 'bar'); $this->assertEquals('foo.bar = ?', $expression->getExpression()); - $this->assertEquals(['bar'], $expression->getParameters()); + $this->assertEquals( + [ + new ExpressionParameter('bar', Expression::TYPE_VALUE) + ], + $expression->getParameters() + ); } /** @@ -47,7 +53,12 @@ public function testCanPassNoParameterToConstructor() public function testCanPassSingleNullParameterToConstructor() { $expression = new Expression('?', null); - $this->assertEquals([null], $expression->getParameters()); + $this->assertEquals( + [ + new ExpressionParameter(null, Expression::TYPE_VALUE), + ], + $expression->getParameters() + ); } /** @@ -56,7 +67,12 @@ public function testCanPassSingleNullParameterToConstructor() public function testCanPassSingleZeroParameterValueToConstructor() { $predicate = new Expression('?', 0); - $this->assertEquals([0], $predicate->getParameters()); + $this->assertEquals( + [ + new ExpressionParameter(0, Expression::TYPE_VALUE), + ], + $predicate->getParameters() + ); } /** @@ -66,7 +82,12 @@ public function testCanPassSinglePredicateParameterToConstructor() { $predicate = new IsNull('foo.baz'); $expression = new Expression('?', $predicate); - $this->assertEquals([$predicate], $expression->getParameters()); + $this->assertEquals( + [ + new ExpressionParameter($predicate, Expression::TYPE_LITERAL) + ], + $expression->getParameters() + ); } /** @@ -75,7 +96,13 @@ public function testCanPassSinglePredicateParameterToConstructor() public function testCanPassMultiScalarParametersToConstructor() { $expression = new Expression('? OR ?', 'foo', 'bar'); - $this->assertEquals(['foo', 'bar'], $expression->getParameters()); + $this->assertEquals( + [ + new ExpressionParameter('foo', Expression::TYPE_VALUE), + new ExpressionParameter('bar', Expression::TYPE_VALUE), + ], + $expression->getParameters() + ); } /** @@ -84,7 +111,13 @@ public function testCanPassMultiScalarParametersToConstructor() public function testCanPassMultiNullParametersToConstructor() { $expression = new Expression('? OR ?', null, null); - $this->assertEquals([null, null], $expression->getParameters()); + $this->assertEquals( + [ + new ExpressionParameter(null, Expression::TYPE_VALUE), + new ExpressionParameter(null, Expression::TYPE_VALUE), + ], + $expression->getParameters() + ); } /** @@ -94,7 +127,13 @@ public function testCanPassMultiPredicateParametersToConstructor() { $predicate = new IsNull('foo.baz'); $expression = new Expression('? OR ?', $predicate, $predicate); - $this->assertEquals([$predicate, $predicate], $expression->getParameters()); + $this->assertEquals( + [ + new ExpressionParameter($predicate, Expression::TYPE_LITERAL), + new ExpressionParameter($predicate, Expression::TYPE_LITERAL), + ], + $expression->getParameters() + ); } /** @@ -103,7 +142,12 @@ public function testCanPassMultiPredicateParametersToConstructor() public function testCanPassArrayOfOneScalarParameterToConstructor() { $expression = new Expression('?', ['foo']); - $this->assertEquals(['foo'], $expression->getParameters()); + $this->assertEquals( + [ + new ExpressionParameter('foo', Expression::TYPE_VALUE), + ], + $expression->getParameters() + ); } /** @@ -112,7 +156,13 @@ public function testCanPassArrayOfOneScalarParameterToConstructor() public function testCanPassArrayOfMultiScalarsParameterToConstructor() { $expression = new Expression('? OR ?', ['foo', 'bar']); - $this->assertEquals(['foo', 'bar'], $expression->getParameters()); + $this->assertEquals( + [ + new ExpressionParameter('foo', Expression::TYPE_VALUE), + new ExpressionParameter('bar', Expression::TYPE_VALUE), + ], + $expression->getParameters() + ); } /** @@ -121,7 +171,12 @@ public function testCanPassArrayOfMultiScalarsParameterToConstructor() public function testCanPassArrayOfOneNullParameterToConstructor() { $expression = new Expression('?', [null]); - $this->assertEquals([null], $expression->getParameters()); + $this->assertEquals( + [ + new ExpressionParameter(null, Expression::TYPE_VALUE), + ], + $expression->getParameters() + ); } /** @@ -130,7 +185,13 @@ public function testCanPassArrayOfOneNullParameterToConstructor() public function testCanPassArrayOfMultiNullsParameterToConstructor() { $expression = new Expression('? OR ?', [null, null]); - $this->assertEquals([null, null], $expression->getParameters()); + $this->assertEquals( + [ + new ExpressionParameter(null, Expression::TYPE_VALUE), + new ExpressionParameter(null, Expression::TYPE_VALUE), + ], + $expression->getParameters() + ); } /** @@ -140,7 +201,12 @@ public function testCanPassArrayOfOnePredicateParameterToConstructor() { $predicate = new IsNull('foo.baz'); $expression = new Expression('?', [$predicate]); - $this->assertEquals([$predicate], $expression->getParameters()); + $this->assertEquals( + [ + new ExpressionParameter($predicate, Expression::TYPE_LITERAL), + ], + $expression->getParameters() + ); } /** @@ -150,7 +216,13 @@ public function testCanPassArrayOfMultiPredicatesParameterToConstructor() { $predicate = new IsNull('foo.baz'); $expression = new Expression('? OR ?', [$predicate, $predicate]); - $this->assertEquals([$predicate, $predicate], $expression->getParameters()); + $this->assertEquals( + [ + new ExpressionParameter($predicate, Expression::TYPE_LITERAL), + new ExpressionParameter($predicate, Expression::TYPE_LITERAL), + ], + $expression->getParameters() + ); } public function testLiteralIsMutable() @@ -164,20 +236,12 @@ public function testParameterIsMutable() { $expression = new Expression(); $expression->setParameters(['foo', 'bar']); - $this->assertEquals(['foo', 'bar'], $expression->getParameters()); - } - - public function testRetrievingWherePartsReturnsSpecificationArrayOfLiteralAndParametersAndArrayOfTypes() - { - $expression = new Expression(); - $expression->setExpression('foo.bar = ? AND id != ?') - ->setParameters(['foo', 'bar']); - $expected = [[ - 'foo.bar = %s AND id != %s', - ['foo', 'bar'], - [Expression::TYPE_VALUE, Expression::TYPE_VALUE], - ]]; - $test = $expression->getExpressionData(); - $this->assertEquals($expected, $test, var_export($test, 1)); + $this->assertEquals( + [ + new ExpressionParameter('foo', Expression::TYPE_VALUE), + new ExpressionParameter('bar', Expression::TYPE_VALUE), + ], + $expression->getParameters() + ); } } diff --git a/test/Sql/Predicate/InTest.php b/test/Sql/Predicate/InTest.php index 0d1f1a7967..9ae1e7b208 100644 --- a/test/Sql/Predicate/InTest.php +++ b/test/Sql/Predicate/InTest.php @@ -10,9 +10,8 @@ namespace ZendTest\Db\Sql\Predicate; use PHPUnit_Framework_TestCase as TestCase; -use Zend\Db\Sql\Select; use Zend\Db\Sql\Predicate\In; -use Zend\Db\Sql\Combine; +use Zend\Db\Sql\ExpressionParameter; class InTest extends TestCase { @@ -26,93 +25,33 @@ public function testEmptyConstructorYieldsNullIdentifierAndValueSet() public function testCanPassIdentifierAndValueSetToConstructor() { $in = new In('foo.bar', [1, 2]); - $this->assertEquals('foo.bar', $in->getIdentifier()); - $this->assertEquals([1, 2], $in->getValueSet()); + $this->assertEquals('foo.bar', $in->getIdentifier()->getValue()); + $this->assertEquals( + [ + new ExpressionParameter(1), + new ExpressionParameter(2), + ], + $in->getValueSet() + ); } public function testIdentifierIsMutable() { $in = new In(); $in->setIdentifier('foo.bar'); - $this->assertEquals('foo.bar', $in->getIdentifier()); + $this->assertEquals('foo.bar', $in->getIdentifier()->getValue()); } public function testValueSetIsMutable() { $in = new In(); $in->setValueSet([1, 2]); - $this->assertEquals([1, 2], $in->getValueSet()); - } - - public function testRetrievingWherePartsReturnsSpecificationArrayOfIdentifierAndValuesAndArrayOfTypes() - { - $in = new In(); - $in->setIdentifier('foo.bar') - ->setValueSet([1, 2, 3]); - $expected = [[ - '%s IN (%s, %s, %s)', - ['foo.bar', 1, 2, 3], - [In::TYPE_IDENTIFIER, In::TYPE_VALUE, In::TYPE_VALUE, In::TYPE_VALUE], - ]]; - $this->assertEquals($expected, $in->getExpressionData()); - - $in->setIdentifier('foo.bar') - ->setValueSet([ - [1=>In::TYPE_LITERAL], - [2=>In::TYPE_VALUE], - [3=>In::TYPE_LITERAL], - ]); - $expected = [[ - '%s IN (%s, %s, %s)', - ['foo.bar', 1, 2, 3], - [In::TYPE_IDENTIFIER, In::TYPE_LITERAL, In::TYPE_VALUE, In::TYPE_LITERAL], - ]]; - $qqq = $in->getExpressionData(); - $this->assertEquals($expected, $in->getExpressionData()); - } - - public function testGetExpressionDataWithSubselect() - { - $select = new Select; - $in = new In('foo', $select); - $expected = [[ - '%s IN %s', - ['foo', $select], - [$in::TYPE_IDENTIFIER, $in::TYPE_VALUE] - ]]; - $this->assertEquals($expected, $in->getExpressionData()); - - $combine = new Combine; - $in = new In('foo', $combine); - $expected = [[ - '%s IN %s', - ['foo', $combine], - [$in::TYPE_IDENTIFIER, $in::TYPE_VALUE] - ]]; - $this->assertEquals($expected, $in->getExpressionData()); - } - - public function testGetExpressionDataWithSubselectAndIdentifier() - { - $select = new Select; - $in = new In('foo', $select); - $expected = [[ - '%s IN %s', - ['foo', $select], - [$in::TYPE_IDENTIFIER, $in::TYPE_VALUE] - ]]; - $this->assertEquals($expected, $in->getExpressionData()); - } - - public function testGetExpressionDataWithSubselectAndArrayIdentifier() - { - $select = new Select; - $in = new In(['foo', 'bar'], $select); - $expected = [[ - '(%s, %s) IN %s', - ['foo', 'bar', $select], - [$in::TYPE_IDENTIFIER, $in::TYPE_IDENTIFIER, $in::TYPE_VALUE] - ]]; - $this->assertEquals($expected, $in->getExpressionData()); + $this->assertEquals( + [ + new ExpressionParameter(1), + new ExpressionParameter(2), + ], + $in->getValueSet() + ); } } diff --git a/test/Sql/Predicate/IsNullTest.php b/test/Sql/Predicate/IsNullTest.php index 29b53e196f..ae8576181f 100644 --- a/test/Sql/Predicate/IsNullTest.php +++ b/test/Sql/Predicate/IsNullTest.php @@ -20,42 +20,17 @@ public function testEmptyConstructorYieldsNullIdentifier() $this->assertNull($isNotNull->getIdentifier()); } - public function testSpecificationHasSaneDefaultValue() - { - $isNotNull = new IsNotNull(); - $this->assertEquals('%1$s IS NOT NULL', $isNotNull->getSpecification()); - } - public function testCanPassIdentifierToConstructor() { $isNotNull = new IsNotNull(); $isnull = new IsNotNull('foo.bar'); - $this->assertEquals('foo.bar', $isnull->getIdentifier()); + $this->assertEquals('foo.bar', $isnull->getIdentifier()->getValue()); } public function testIdentifierIsMutable() { $isNotNull = new IsNotNull(); $isNotNull->setIdentifier('foo.bar'); - $this->assertEquals('foo.bar', $isNotNull->getIdentifier()); - } - - public function testSpecificationIsMutable() - { - $isNotNull = new IsNotNull(); - $isNotNull->setSpecification('%1$s NOT NULL'); - $this->assertEquals('%1$s NOT NULL', $isNotNull->getSpecification()); - } - - public function testRetrievingWherePartsReturnsSpecificationArrayOfIdentifierAndArrayOfTypes() - { - $isNotNull = new IsNotNull(); - $isNotNull->setIdentifier('foo.bar'); - $expected = [[ - $isNotNull->getSpecification(), - ['foo.bar'], - [IsNotNull::TYPE_IDENTIFIER], - ]]; - $this->assertEquals($expected, $isNotNull->getExpressionData()); + $this->assertEquals('foo.bar', $isNotNull->getIdentifier()->getValue()); } } diff --git a/test/Sql/Predicate/LikeTest.php b/test/Sql/Predicate/LikeTest.php index af999d5cf2..0d7b982035 100644 --- a/test/Sql/Predicate/LikeTest.php +++ b/test/Sql/Predicate/LikeTest.php @@ -23,45 +23,23 @@ public function testConstructEmptyArgs() public function testConstructWithArgs() { $like = new Like('bar', 'Foo%'); - $this->assertEquals('bar', $like->getIdentifier()); - $this->assertEquals('Foo%', $like->getLike()); + $this->assertEquals('bar', $like->getIdentifier()->getValue()); + $this->assertEquals('Foo%', $like->getLike()->getValue()); } public function testAccessorsMutators() { $like = new Like(); $like->setIdentifier('bar'); - $this->assertEquals('bar', $like->getIdentifier()); + $this->assertEquals('bar', $like->getIdentifier()->getValue()); $like->setLike('foo%'); - $this->assertEquals('foo%', $like->getLike()); - $like->setSpecification('target = target'); - $this->assertEquals('target = target', $like->getSpecification()); - } - - public function testGetExpressionData() - { - $like = new Like('bar', 'Foo%'); - $this->assertEquals( - [ - ['%1$s LIKE %2$s', ['bar', 'Foo%'], [$like::TYPE_IDENTIFIER, $like::TYPE_VALUE]] - ], - $like->getExpressionData() - ); - - $like = new Like(['Foo%'=>$like::TYPE_VALUE], ['bar'=>$like::TYPE_IDENTIFIER]); - $this->assertEquals( - [ - ['%1$s LIKE %2$s', ['Foo%', 'bar'], [$like::TYPE_VALUE, $like::TYPE_IDENTIFIER]] - ], - $like->getExpressionData() - ); + $this->assertEquals('foo%', $like->getLike()->getValue()); } public function testInstanceOfPerSetters() { $like = new Like(); $this->assertInstanceOf('Zend\Db\Sql\Predicate\Like', $like->setIdentifier('bar')); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\Like', $like->setSpecification('%1$s LIKE %2$s')); $this->assertInstanceOf('Zend\Db\Sql\Predicate\Like', $like->setLike('foo%')); } } diff --git a/test/Sql/Predicate/LiteralTest.php b/test/Sql/Predicate/LiteralTest.php index 733a84477c..5698e84352 100644 --- a/test/Sql/Predicate/LiteralTest.php +++ b/test/Sql/Predicate/LiteralTest.php @@ -24,10 +24,4 @@ public function testGetLiteral() $literal = new Literal('bar'); $this->assertEquals('bar', $literal->getLiteral()); } - - public function testGetExpressionData() - { - $literal = new Literal('bar'); - $this->assertEquals([['bar', [], []]], $literal->getExpressionData()); - } } diff --git a/test/Sql/Predicate/NotBetweenTest.php b/test/Sql/Predicate/NotBetweenTest.php deleted file mode 100644 index 5c99087c26..0000000000 --- a/test/Sql/Predicate/NotBetweenTest.php +++ /dev/null @@ -1,60 +0,0 @@ -notBetween = new NotBetween(); - } - - /** - * @covers Zend\Db\Sql\Predicate\NotBetween::getSpecification - */ - public function testSpecificationHasSameDefaultValue() - { - $this->assertEquals('%1$s NOT BETWEEN %2$s AND %3$s', $this->notBetween->getSpecification()); - } - - /** - * @covers Zend\Db\Sql\Predicate\NotBetween::getExpressionData - */ - public function testRetrievingWherePartsReturnsSpecificationArrayOfIdentifierAndValuesAndArrayOfTypes() - { - $this->notBetween->setIdentifier('foo.bar') - ->setMinValue(10) - ->setMaxValue(19); - $expected = [[ - $this->notBetween->getSpecification(), - ['foo.bar', 10, 19], - [NotBetween::TYPE_IDENTIFIER, NotBetween::TYPE_VALUE, NotBetween::TYPE_VALUE], - ]]; - $this->assertEquals($expected, $this->notBetween->getExpressionData()); - - $this->notBetween->setIdentifier([10=>NotBetween::TYPE_VALUE]) - ->setMinValue(['foo.bar'=>NotBetween::TYPE_IDENTIFIER]) - ->setMaxValue(['foo.baz'=>NotBetween::TYPE_IDENTIFIER]); - $expected = [[ - $this->notBetween->getSpecification(), - [10, 'foo.bar', 'foo.baz'], - [NotBetween::TYPE_VALUE, NotBetween::TYPE_IDENTIFIER, NotBetween::TYPE_IDENTIFIER], - ]]; - $this->assertEquals($expected, $this->notBetween->getExpressionData()); - } -} diff --git a/test/Sql/Predicate/NotInTest.php b/test/Sql/Predicate/NotInTest.php deleted file mode 100644 index aa8bdcdd97..0000000000 --- a/test/Sql/Predicate/NotInTest.php +++ /dev/null @@ -1,66 +0,0 @@ -setIdentifier('foo.bar') - ->setValueSet([1, 2, 3]); - $expected = [[ - '%s NOT IN (%s, %s, %s)', - ['foo.bar', 1, 2, 3], - [NotIn::TYPE_IDENTIFIER, NotIn::TYPE_VALUE, NotIn::TYPE_VALUE, NotIn::TYPE_VALUE], - ]]; - $this->assertEquals($expected, $in->getExpressionData()); - } - - public function testGetExpressionDataWithSubselect() - { - $select = new Select; - $in = new NotIn('foo', $select); - $expected = [[ - '%s NOT IN %s', - ['foo', $select], - [$in::TYPE_IDENTIFIER, $in::TYPE_VALUE] - ]]; - $this->assertEquals($expected, $in->getExpressionData()); - } - - public function testGetExpressionDataWithSubselectAndIdentifier() - { - $select = new Select; - $in = new NotIn('foo', $select); - $expected = [[ - '%s NOT IN %s', - ['foo', $select], - [$in::TYPE_IDENTIFIER, $in::TYPE_VALUE] - ]]; - $this->assertEquals($expected, $in->getExpressionData()); - } - - public function testGetExpressionDataWithSubselectAndArrayIdentifier() - { - $select = new Select; - $in = new NotIn(['foo', 'bar'], $select); - $expected = [[ - '(%s, %s) NOT IN %s', - ['foo', 'bar', $select], - [$in::TYPE_IDENTIFIER, $in::TYPE_IDENTIFIER, $in::TYPE_VALUE] - ]]; - $this->assertEquals($expected, $in->getExpressionData()); - } -} diff --git a/test/Sql/Predicate/NotLikeTest.php b/test/Sql/Predicate/NotLikeTest.php index 5dbe3fbaa9..da9b188d33 100644 --- a/test/Sql/Predicate/NotLikeTest.php +++ b/test/Sql/Predicate/NotLikeTest.php @@ -23,41 +23,23 @@ public function testConstructEmptyArgs() public function testConstructWithArgs() { $notLike = new NotLike('bar', 'Foo%'); - $this->assertEquals('bar', $notLike->getIdentifier()); - $this->assertEquals('Foo%', $notLike->getLike()); + $this->assertEquals('bar', $notLike->getIdentifier()->getValue()); + $this->assertEquals('Foo%', $notLike->getLike()->getValue()); } public function testAccessorsMutators() { $notLike = new NotLike(); $notLike->setIdentifier('bar'); - $this->assertEquals('bar', $notLike->getIdentifier()); + $this->assertEquals('bar', $notLike->getIdentifier()->getValue()); $notLike->setLike('foo%'); - $this->assertEquals('foo%', $notLike->getLike()); - $notLike->setSpecification('target = target'); - $this->assertEquals('target = target', $notLike->getSpecification()); - } - - public function testGetExpressionData() - { - $notLike = new NotLike('bar', 'Foo%'); - $this->assertEquals( - [ - [ - '%1$s NOT LIKE %2$s', - ['bar', 'Foo%'], - [$notLike::TYPE_IDENTIFIER, $notLike::TYPE_VALUE] - ] - ], - $notLike->getExpressionData() - ); + $this->assertEquals('foo%', $notLike->getLike()->getValue()); } public function testInstanceOfPerSetters() { $notLike = new NotLike(); $this->assertInstanceOf('Zend\Db\Sql\Predicate\Like', $notLike->setIdentifier('bar')); - $this->assertInstanceOf('Zend\Db\Sql\Predicate\Like', $notLike->setSpecification('%1$s NOT LIKE %2$s')); $this->assertInstanceOf('Zend\Db\Sql\Predicate\Like', $notLike->setLike('foo%')); } } diff --git a/test/Sql/Predicate/OperatorTest.php b/test/Sql/Predicate/OperatorTest.php index 54fbc145a6..97418337e5 100644 --- a/test/Sql/Predicate/OperatorTest.php +++ b/test/Sql/Predicate/OperatorTest.php @@ -11,6 +11,7 @@ use PHPUnit_Framework_TestCase as TestCase; use Zend\Db\Sql\Predicate\Operator; +use Zend\Db\Sql\ExpressionParameter; class OperatorTest extends TestCase { @@ -21,60 +22,38 @@ public function testEmptyConstructorYieldsNullLeftAndRightValues() $this->assertNull($operator->getRight()); } - public function testEmptyConstructorYieldsDefaultsForOperatorAndLeftAndRightTypes() - { - $operator = new Operator(); - $this->assertEquals(Operator::OP_EQ, $operator->getOperator()); - $this->assertEquals(Operator::TYPE_IDENTIFIER, $operator->getLeftType()); - $this->assertEquals(Operator::TYPE_VALUE, $operator->getRightType()); - } - public function testCanPassAllValuesToConstructor() { - $operator = new Operator('bar', '>=', 'foo.bar', Operator::TYPE_VALUE, Operator::TYPE_IDENTIFIER); + $operator = new Operator(['bar', Operator::TYPE_VALUE], '>=', ['foo.bar', Operator::TYPE_IDENTIFIER]); $this->assertEquals(Operator::OP_GTE, $operator->getOperator()); - $this->assertEquals('bar', $operator->getLeft()); - $this->assertEquals('foo.bar', $operator->getRight()); - $this->assertEquals(Operator::TYPE_VALUE, $operator->getLeftType()); - $this->assertEquals(Operator::TYPE_IDENTIFIER, $operator->getRightType()); + $this->assertEquals('bar', $operator->getLeft()->getValue()); + $this->assertEquals('foo.bar', $operator->getRight()->getValue()); + $this->assertEquals(Operator::TYPE_VALUE, $operator->getLeft()->getType()); + $this->assertEquals(Operator::TYPE_IDENTIFIER, $operator->getRight()->getType()); $operator = new Operator(['bar'=>Operator::TYPE_VALUE], '>=', ['foo.bar'=>Operator::TYPE_IDENTIFIER]); $this->assertEquals(Operator::OP_GTE, $operator->getOperator()); - $this->assertEquals(['bar'=>Operator::TYPE_VALUE], $operator->getLeft()); - $this->assertEquals(['foo.bar'=>Operator::TYPE_IDENTIFIER], $operator->getRight()); - $this->assertEquals(Operator::TYPE_VALUE, $operator->getLeftType()); - $this->assertEquals(Operator::TYPE_IDENTIFIER, $operator->getRightType()); + $this->assertEquals(new ExpressionParameter('bar', Operator::TYPE_VALUE), $operator->getLeft()); + $this->assertEquals(new ExpressionParameter('foo.bar', Operator::TYPE_IDENTIFIER), $operator->getRight()); + $this->assertEquals(Operator::TYPE_VALUE, $operator->getLeft()->getType()); + $this->assertEquals(Operator::TYPE_IDENTIFIER, $operator->getRight()->getType()); $operator = new Operator('bar', '>=', 0); - $this->assertEquals(0, $operator->getRight()); + $this->assertEquals(0, $operator->getRight()->getValue()); } public function testLeftIsMutable() { $operator = new Operator(); $operator->setLeft('foo.bar'); - $this->assertEquals('foo.bar', $operator->getLeft()); + $this->assertEquals('foo.bar', $operator->getLeft()->getValue()); } public function testRightIsMutable() { $operator = new Operator(); $operator->setRight('bar'); - $this->assertEquals('bar', $operator->getRight()); - } - - public function testLeftTypeIsMutable() - { - $operator = new Operator(); - $operator->setLeftType(Operator::TYPE_VALUE); - $this->assertEquals(Operator::TYPE_VALUE, $operator->getLeftType()); - } - - public function testRightTypeIsMutable() - { - $operator = new Operator(); - $operator->setRightType(Operator::TYPE_IDENTIFIER); - $this->assertEquals(Operator::TYPE_IDENTIFIER, $operator->getRightType()); + $this->assertEquals('bar', $operator->getRight()->getValue()); } public function testOperatorIsMutable() @@ -83,21 +62,4 @@ public function testOperatorIsMutable() $operator->setOperator(Operator::OP_LTE); $this->assertEquals(Operator::OP_LTE, $operator->getOperator()); } - - public function testRetrievingWherePartsReturnsSpecificationArrayOfLeftAndRightAndArrayOfTypes() - { - $operator = new Operator(); - $operator->setLeft('foo') - ->setOperator('>=') - ->setRight('foo.bar') - ->setLeftType(Operator::TYPE_VALUE) - ->setRightType(Operator::TYPE_IDENTIFIER); - $expected = [[ - '%s >= %s', - ['foo', 'foo.bar'], - [Operator::TYPE_VALUE, Operator::TYPE_IDENTIFIER], - ]]; - $test = $operator->getExpressionData(); - $this->assertEquals($expected, $test, var_export($test, 1)); - } } diff --git a/test/Sql/Predicate/PredicateSetTest.php b/test/Sql/Predicate/PredicateSetTest.php index 52987f357f..7ff9ddbb18 100644 --- a/test/Sql/Predicate/PredicateSetTest.php +++ b/test/Sql/Predicate/PredicateSetTest.php @@ -10,7 +10,6 @@ namespace ZendTest\Db\Sql\Predicate; use PHPUnit_Framework_TestCase as TestCase; -use Zend\Db\Sql\Predicate\IsNull; use Zend\Db\Sql\Predicate\PredicateSet; class PredicateSetTest extends TestCase @@ -21,70 +20,6 @@ public function testEmptyConstructorYieldsCountOfZero() $this->assertEquals(0, count($predicateSet)); } - public function testCombinationIsAndByDefault() - { - $predicateSet = new PredicateSet(); - $predicateSet->addPredicate(new IsNull('foo')) - ->addPredicate(new IsNull('bar')); - $parts = $predicateSet->getExpressionData(); - $this->assertEquals(3, count($parts)); - $this->assertContains('AND', $parts[1]); - $this->assertNotContains('OR', $parts[1]); - } - - public function testCanPassPredicatesAndDefaultCombinationViaConstructor() - { - $predicateSet = new PredicateSet(); - $set = new PredicateSet([ - new IsNull('foo'), - new IsNull('bar'), - ], 'OR'); - $parts = $set->getExpressionData(); - $this->assertEquals(3, count($parts)); - $this->assertContains('OR', $parts[1]); - $this->assertNotContains('AND', $parts[1]); - } - - public function testCanPassBothPredicateAndCombinationToAddPredicate() - { - $predicateSet = new PredicateSet(); - $predicateSet->addPredicate(new IsNull('foo'), 'OR') - ->addPredicate(new IsNull('bar'), 'AND') - ->addPredicate(new IsNull('baz'), 'OR') - ->addPredicate(new IsNull('bat'), 'AND'); - $parts = $predicateSet->getExpressionData(); - $this->assertEquals(7, count($parts)); - - $this->assertNotContains('OR', $parts[1], var_export($parts, 1)); - $this->assertContains('AND', $parts[1]); - - $this->assertContains('OR', $parts[3]); - $this->assertNotContains('AND', $parts[3]); - - $this->assertNotContains('OR', $parts[5]); - $this->assertContains('AND', $parts[5]); - } - - public function testCanUseOrPredicateAndAndPredicateMethods() - { - $predicateSet = new PredicateSet(); - $predicateSet->orPredicate(new IsNull('foo')) - ->andPredicate(new IsNull('bar')) - ->orPredicate(new IsNull('baz')) - ->andPredicate(new IsNull('bat')); - $parts = $predicateSet->getExpressionData(); - $this->assertEquals(7, count($parts)); - - $this->assertNotContains('OR', $parts[1], var_export($parts, 1)); - $this->assertContains('AND', $parts[1]); - - $this->assertContains('OR', $parts[3]); - $this->assertNotContains('AND', $parts[3]); - - $this->assertNotContains('OR', $parts[5]); - $this->assertContains('AND', $parts[5]); - } - /** * @covers Zend\Db\Sql\Predicate\PredicateSet::addPredicates */ diff --git a/test/Sql/Predicate/PredicateTest.php b/test/Sql/Predicate/PredicateTest.php index 7fe353a2ab..be2299c75f 100644 --- a/test/Sql/Predicate/PredicateTest.php +++ b/test/Sql/Predicate/PredicateTest.php @@ -10,284 +10,13 @@ namespace ZendTest\Db\Sql\Predicate; use PHPUnit_Framework_TestCase as TestCase; -use Zend\Db\Sql\Expression; -use Zend\Db\Sql\Predicate\IsNull; use Zend\Db\Sql\Predicate\Predicate; use Zend\Db\Sql\Predicate\Literal as predicateLiteral; use Zend\Db\Sql\Predicate\Expression as predicateExpression; +use Zend\Db\Sql\ExpressionParameter; class PredicateTest extends TestCase { - public function testEqualToCreatesOperatorPredicate() - { - $predicate = new Predicate(); - $predicate->equalTo('foo.bar', 'bar'); - $parts = $predicate->getExpressionData(); - $this->assertEquals(1, count($parts)); - $this->assertContains('%s = %s', $parts[0]); - $this->assertContains(['foo.bar', 'bar'], $parts[0]); - } - - public function testNotEqualToCreatesOperatorPredicate() - { - $predicate = new Predicate(); - $predicate->notEqualTo('foo.bar', 'bar'); - $parts = $predicate->getExpressionData(); - $this->assertEquals(1, count($parts)); - $this->assertContains('%s != %s', $parts[0]); - $this->assertContains(['foo.bar', 'bar'], $parts[0]); - } - - - public function testLessThanCreatesOperatorPredicate() - { - $predicate = new Predicate(); - $predicate->lessThan('foo.bar', 'bar'); - $parts = $predicate->getExpressionData(); - $this->assertEquals(1, count($parts)); - $this->assertContains('%s < %s', $parts[0]); - $this->assertContains(['foo.bar', 'bar'], $parts[0]); - } - - public function testGreaterThanCreatesOperatorPredicate() - { - $predicate = new Predicate(); - $predicate->greaterThan('foo.bar', 'bar'); - $parts = $predicate->getExpressionData(); - $this->assertEquals(1, count($parts)); - $this->assertContains('%s > %s', $parts[0]); - $this->assertContains(['foo.bar', 'bar'], $parts[0]); - } - - public function testLessThanOrEqualToCreatesOperatorPredicate() - { - $predicate = new Predicate(); - $predicate->lessThanOrEqualTo('foo.bar', 'bar'); - $parts = $predicate->getExpressionData(); - $this->assertEquals(1, count($parts)); - $this->assertContains('%s <= %s', $parts[0]); - $this->assertContains(['foo.bar', 'bar'], $parts[0]); - } - - public function testGreaterThanOrEqualToCreatesOperatorPredicate() - { - $predicate = new Predicate(); - $predicate->greaterThanOrEqualTo('foo.bar', 'bar'); - $parts = $predicate->getExpressionData(); - $this->assertEquals(1, count($parts)); - $this->assertContains('%s >= %s', $parts[0]); - $this->assertContains(['foo.bar', 'bar'], $parts[0]); - } - - public function testLikeCreatesLikePredicate() - { - $predicate = new Predicate(); - $predicate->like('foo.bar', 'bar%'); - $parts = $predicate->getExpressionData(); - $this->assertEquals(1, count($parts)); - $this->assertContains('%1$s LIKE %2$s', $parts[0]); - $this->assertContains(['foo.bar', 'bar%'], $parts[0]); - } - - public function testNotLikeCreatesLikePredicate() - { - $predicate = new Predicate(); - $predicate->notLike('foo.bar', 'bar%'); - $parts = $predicate->getExpressionData(); - $this->assertEquals(1, count($parts)); - $this->assertContains('%1$s NOT LIKE %2$s', $parts[0]); - $this->assertContains(['foo.bar', 'bar%'], $parts[0]); - } - - public function testLiteralCreatesLiteralPredicate() - { - $predicate = new Predicate(); - $predicate->literal('foo.bar = ?', 'bar'); - $parts = $predicate->getExpressionData(); - $this->assertEquals(1, count($parts)); - $this->assertContains('foo.bar = %s', $parts[0]); - $this->assertContains(['bar'], $parts[0]); - } - - public function testIsNullCreatesIsNullPredicate() - { - $predicate = new Predicate(); - $predicate->isNull('foo.bar'); - $parts = $predicate->getExpressionData(); - $this->assertEquals(1, count($parts)); - $this->assertContains('%1$s IS NULL', $parts[0]); - $this->assertContains(['foo.bar'], $parts[0]); - } - - public function testIsNotNullCreatesIsNotNullPredicate() - { - $predicate = new Predicate(); - $predicate->isNotNull('foo.bar'); - $parts = $predicate->getExpressionData(); - $this->assertEquals(1, count($parts)); - $this->assertContains('%1$s IS NOT NULL', $parts[0]); - $this->assertContains(['foo.bar'], $parts[0]); - } - - public function testInCreatesInPredicate() - { - $predicate = new Predicate(); - $predicate->in('foo.bar', ['foo', 'bar']); - $parts = $predicate->getExpressionData(); - $this->assertEquals(1, count($parts)); - $this->assertContains('%s IN (%s, %s)', $parts[0]); - $this->assertContains(['foo.bar', 'foo', 'bar'], $parts[0]); - } - - public function testNotInCreatesNotInPredicate() - { - $predicate = new Predicate(); - $predicate->notIn('foo.bar', ['foo', 'bar']); - $parts = $predicate->getExpressionData(); - $this->assertEquals(1, count($parts)); - $this->assertContains('%s NOT IN (%s, %s)', $parts[0]); - $this->assertContains(['foo.bar', 'foo', 'bar'], $parts[0]); - } - - public function testBetweenCreatesBetweenPredicate() - { - $predicate = new Predicate(); - $predicate->between('foo.bar', 1, 10); - $parts = $predicate->getExpressionData(); - $this->assertEquals(1, count($parts)); - $this->assertContains('%1$s BETWEEN %2$s AND %3$s', $parts[0]); - $this->assertContains(['foo.bar', 1, 10], $parts[0]); - } - - public function testBetweenCreatesNotBetweenPredicate() - { - $predicate = new Predicate(); - $predicate->notBetween('foo.bar', 1, 10); - $parts = $predicate->getExpressionData(); - $this->assertEquals(1, count($parts)); - $this->assertContains('%1$s NOT BETWEEN %2$s AND %3$s', $parts[0]); - $this->assertContains(['foo.bar', 1, 10], $parts[0]); - } - - public function testCanChainPredicateFactoriesBetweenOperators() - { - $predicate = new Predicate(); - $predicate->isNull('foo.bar') - ->or - ->isNotNull('bar.baz') - ->and - ->equalTo('baz.bat', 'foo'); - $parts = $predicate->getExpressionData(); - $this->assertEquals(5, count($parts)); - - $this->assertContains('%1$s IS NULL', $parts[0]); - $this->assertContains(['foo.bar'], $parts[0]); - - $this->assertEquals(' OR ', $parts[1]); - - $this->assertContains('%1$s IS NOT NULL', $parts[2]); - $this->assertContains(['bar.baz'], $parts[2]); - - $this->assertEquals(' AND ', $parts[3]); - - $this->assertContains('%s = %s', $parts[4]); - $this->assertContains(['baz.bat', 'foo'], $parts[4]); - } - - public function testCanNestPredicates() - { - $predicate = new Predicate(); - $predicate->isNull('foo.bar') - ->nest() - ->isNotNull('bar.baz') - ->and - ->equalTo('baz.bat', 'foo') - ->unnest(); - $parts = $predicate->getExpressionData(); - - $this->assertEquals(7, count($parts)); - - $this->assertContains('%1$s IS NULL', $parts[0]); - $this->assertContains(['foo.bar'], $parts[0]); - - $this->assertEquals(' AND ', $parts[1]); - - $this->assertEquals('(', $parts[2]); - - $this->assertContains('%1$s IS NOT NULL', $parts[3]); - $this->assertContains(['bar.baz'], $parts[3]); - - $this->assertEquals(' AND ', $parts[4]); - - $this->assertContains('%s = %s', $parts[5]); - $this->assertContains(['baz.bat', 'foo'], $parts[5]); - - $this->assertEquals(')', $parts[6]); - } - - /** - * @testdox Unit test: Test expression() is chainable and returns proper values - */ - public function testExpression() - { - $predicate = new Predicate; - - // is chainable - $this->assertSame($predicate, $predicate->expression('foo = ?', 0)); - // with parameter - $this->assertEquals( - [['foo = %s', [0], [Expression::TYPE_VALUE]]], - $predicate->getExpressionData() - ); - } - - /** - * @testdox Unit test: Test expression() allows null $parameters - */ - public function testExpressionNullParameters() - { - $predicate = new Predicate; - - $predicate->expression('foo = bar'); - $predicates = $predicate->getPredicates(); - $expression = $predicates[0][1]; - $this->assertEquals([null], $expression->getParameters()); - } - - /** - * @testdox Unit test: Test literal() is chainable, returns proper values, and is backwards compatible with 2.0.* - */ - public function testLiteral() - { - $predicate = new Predicate; - - // is chainable - $this->assertSame($predicate, $predicate->literal('foo = bar')); - // with parameter - $this->assertEquals( - [['foo = bar', [], []]], - $predicate->getExpressionData() - ); - - // test literal() is backwards-compatible, and works with with parameters - $predicate = new Predicate; - $predicate->expression('foo = ?', 'bar'); - // with parameter - $this->assertEquals( - [['foo = %s', ['bar'], [Expression::TYPE_VALUE]]], - $predicate->getExpressionData() - ); - - // test literal() is backwards-compatible, and works with with parameters, even 0 which tests as false - $predicate = new Predicate; - $predicate->expression('foo = ?', 0); - // with parameter - $this->assertEquals( - [['foo = %s', [0], [Expression::TYPE_VALUE]]], - $predicate->getExpressionData() - ); - } - /** * moved from SelectTest */ @@ -301,7 +30,12 @@ public function testWhereArgument1IsAssociativeArrayContainingReplacementCharact $this->assertInstanceOf('Zend\Db\Sql\Predicate\Expression', $predicates[0][1]); $this->assertEquals(Predicate::OP_AND, $predicates[0][0]); $this->assertEquals('foo > ?', $predicates[0][1]->getExpression()); - $this->assertEquals([5], $predicates[0][1]->getParameters()); + $this->assertEquals( + [ + new ExpressionParameter(5) + ], + $predicates[0][1]->getParameters() + ); } /** @@ -316,13 +50,13 @@ public function testWhereArgument1IsAssociativeArrayNotContainingReplacementChar $this->assertInstanceOf('Zend\Db\Sql\Predicate\Operator', $predicates[0][1]); $this->assertEquals(Predicate::OP_AND, $predicates[0][0]); - $this->assertEquals('name', $predicates[0][1]->getLeft()); - $this->assertEquals('Ralph', $predicates[0][1]->getRight()); + $this->assertEquals('name', $predicates[0][1]->getLeft()->getValue()); + $this->assertEquals('Ralph', $predicates[0][1]->getRight()->getValue()); $this->assertInstanceOf('Zend\Db\Sql\Predicate\Operator', $predicates[1][1]); $this->assertEquals(Predicate::OP_AND, $predicates[1][0]); - $this->assertEquals('age', $predicates[1][1]->getLeft()); - $this->assertEquals(33, $predicates[1][1]->getRight()); + $this->assertEquals('age', $predicates[1][1]->getLeft()->getValue()); + $this->assertEquals(33, $predicates[1][1]->getRight()->getValue()); $where = new Predicate; $predicates = $where diff --git a/test/TestAsset/ExpressionBuilder.php b/test/TestAsset/ExpressionBuilder.php new file mode 100644 index 0000000000..98c63a47fb --- /dev/null +++ b/test/TestAsset/ExpressionBuilder.php @@ -0,0 +1,24 @@ +getExpression(); + $expression->setExpression('{decorate-' . $expressionString . '-decorate}'); + $result = parent::getExpressionData($expression, $context); + $expression->setExpression($expressionString); + return $result; + } +} From 42c0096b191e6bd44699d86ef6881e6e5cf7d0c7 Mon Sep 17 00:00:00 2001 From: turrsis Date: Thu, 9 Jul 2015 17:40:06 +0300 Subject: [PATCH 05/30] architecture 04: optimize tests for Builders --- test/Sql/Builder/AllBuildersTest.php | 320 +----- test/Sql/Builder/CombineBuilderTest.php | 3 + .../Sql/Builder/Ddl/AlterTableBuilderTest.php | 3 + .../Builder/Ddl/Column/ColumnBuilderTest.php | 478 +++----- .../Ddl/Constraint/CheckBuilderTest.php | 40 +- .../Ddl/Constraint/ForeignKeyBuilderTest.php | 42 +- .../Ddl/Constraint/PrimaryKeyBuilderTest.php | 43 +- .../Ddl/Constraint/UniqueKeyBuilderTest.php | 44 +- .../Builder/Ddl/CreateTableBuilderTest.php | 101 +- test/Sql/Builder/Ddl/DropTableBuilderTest.php | 3 + .../Builder/Ddl/Index/IndexBuilderTest.php | 85 +- test/Sql/Builder/DeleteBuilderTest.php | 70 +- test/Sql/Builder/ExpressionBuilderTest.php | 238 ++-- test/Sql/Builder/InsertBuilderTest.php | 160 +-- test/Sql/Builder/LiteralBuilderTest.php | 71 +- .../Builder/Predicate/BetweenBuilderTest.php | 73 +- test/Sql/Builder/Predicate/InBuilderTest.php | 181 ++- .../Predicate/IsNotNullBuilderTest.php | 43 +- .../Sql/Builder/Predicate/LikeBuilderTest.php | 62 +- .../Predicate/NotBetweenBuilderTest.php | 73 +- .../Builder/Predicate/NotInBuilderTest.php | 122 +- .../Builder/Predicate/NotLikeBuilderTest.php | 42 +- .../Builder/Predicate/OperatorBuilderTest.php | 68 +- .../Predicate/PredicateBuilderTest.php | 554 ++++----- .../Predicate/PredicateSetBuilderTest.php | 172 +-- test/Sql/Builder/SelectBuilderTest.php | 1009 ++++++++++------- test/Sql/Builder/UpdateBuilderTest.php | 185 ++- test/Sql/Predicate/PredicateTest.php | 152 ++- 28 files changed, 2132 insertions(+), 2305 deletions(-) diff --git a/test/Sql/Builder/AllBuildersTest.php b/test/Sql/Builder/AllBuildersTest.php index 7db53f5c09..d1c834e8d9 100644 --- a/test/Sql/Builder/AllBuildersTest.php +++ b/test/Sql/Builder/AllBuildersTest.php @@ -9,8 +9,6 @@ namespace ZendTest\Db\Sql\Builder; -use Zend\Db\Sql; - class AllBuildersTest extends AbstractTestCase { /** @@ -24,321 +22,7 @@ public function test($sqlObject, $platform, $expected) public function dataProvider() { - return $this->prepareDataProvider( - $this->dataProvider_CommonProcessMethods(), - $this->dataProvider_Builders() - ); - } - - protected function dataProvider_CommonProcessMethods() - { - return [ - 'Select::processOffset()' => [ - 'sqlObject' => $this->select('foo')->offset(10), - 'expected' => [ - 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" OFFSET \'10\'', - 'prepare' => 'SELECT "foo".* FROM "foo" OFFSET ?', - 'parameters' => ['offset' => 10], - ], - 'MySql' => [ - 'string' => 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET 10', - 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET ?', - 'parameters' => ['offset' => 10], - ], - 'Oracle' => [ - 'string' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b ) WHERE b_rownum > (10)', - 'prepare' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b ) WHERE b_rownum > (:offset)', - 'parameters' => ['offset' => 10], - ], - 'SqlServer' => [ - 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 10+1 AND 0+10', - 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', - 'parameters' => ['offset' => 10, 'limit' => null, 'offsetForSum' => 10], - ], - ], - ], - 'Select::processLimit()' => [ - 'sqlObject' => $this->select('foo')->limit(10), - 'expected' => [ - 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" LIMIT \'10\'', - 'prepare' => 'SELECT "foo".* FROM "foo" LIMIT ?', - 'parameters' => ['limit' => 10], - ], - 'MySql' => [ - 'string' => 'SELECT `foo`.* FROM `foo` LIMIT 10', - 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT ?', - 'parameters' => ['limit' => 10], - ], - 'Oracle' => [ - 'string' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (0+10)) WHERE b_rownum >= (0 + 1)', - 'prepare' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (:offset+:limit)) WHERE b_rownum >= (:offset + 1)', - 'parameters' => ['offset' => 0, 'limit' => 10], - ], - 'SqlServer' => [ - 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 0+1 AND 10+0', - 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', - 'parameters' => ['offset' => null, 'limit' => 10, 'offsetForSum' => null], - ], - ], - ], - 'Select::processLimitOffset()' => [ - 'sqlObject' => $this->select('foo')->limit(10)->offset(5), - 'expected' => [ - 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" LIMIT \'10\' OFFSET \'5\'', - 'prepare' => 'SELECT "foo".* FROM "foo" LIMIT ? OFFSET ?', - 'parameters' => ['limit' => 10, 'offset' => 5], - ], - 'MySql' => [ - 'string' => 'SELECT `foo`.* FROM `foo` LIMIT 10 OFFSET 5', - 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT ? OFFSET ?', - 'parameters' => ['limit' => 10, 'offset' => 5], - ], - 'Oracle' => [ - 'string' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (5+10)) WHERE b_rownum >= (5 + 1)', - 'prepare' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (:offset+:limit)) WHERE b_rownum >= (:offset + 1)', - 'parameters' => ['offset' => 5, 'limit' => 10], - ], - 'SqlServer' => [ - 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 5+1 AND 10+5', - 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', - 'parameters' => ['offset' => 5, 'limit' => 10, 'offsetForSum' => 5], - ], - ], - ], - // Github issue https://github.com/zendframework/zend-db/issues/98 - 'Select::processJoinNoJoinedColumns()' => [ - 'sqlObject' => $this->select('my_table') - ->join('joined_table2', 'my_table.id = joined_table2.id', $columns=[]) - ->join('joined_table3', 'my_table.id = joined_table3.id', [\Zend\Db\Sql\Select::SQL_STAR]) - ->columns([ - 'my_table_column', - 'aliased_column' => new \Zend\Db\Sql\Expression('NOW()') - ]), - 'expected' => [ - 'sql92' => [ - 'string' => 'SELECT "my_table"."my_table_column" AS "my_table_column", NOW() AS "aliased_column", "joined_table3".* FROM "my_table" INNER JOIN "joined_table2" ON "my_table"."id" = "joined_table2"."id" INNER JOIN "joined_table3" ON "my_table"."id" = "joined_table3"."id"', - ], - 'MySql' => [ - 'string' => 'SELECT `my_table`.`my_table_column` AS `my_table_column`, NOW() AS `aliased_column`, `joined_table3`.* FROM `my_table` INNER JOIN `joined_table2` ON `my_table`.`id` = `joined_table2`.`id` INNER JOIN `joined_table3` ON `my_table`.`id` = `joined_table3`.`id`', - ], - 'Oracle' => [ - 'string' => 'SELECT "my_table"."my_table_column" AS "my_table_column", NOW() AS "aliased_column", "joined_table3".* FROM "my_table" INNER JOIN "joined_table2" ON "my_table"."id" = "joined_table2"."id" INNER JOIN "joined_table3" ON "my_table"."id" = "joined_table3"."id"', - ], - 'SqlServer' => [ - 'string' => 'SELECT [my_table].[my_table_column] AS [my_table_column], NOW() AS [aliased_column], [joined_table3].* FROM [my_table] INNER JOIN [joined_table2] ON [my_table].[id] = [joined_table2].[id] INNER JOIN [joined_table3] ON [my_table].[id] = [joined_table3].[id]', - ] - ] - ], - 'Select::processJoin()' => [ - 'sqlObject' => $this->select('a')->join(['b'=>$this->select('c')->where(['cc'=>10])], 'd=e')->where(['x'=>20]), - 'expected' => [ - 'sql92' => [ - 'string' => 'SELECT "a".*, "b".* FROM "a" INNER JOIN (SELECT "c".* FROM "c" WHERE "cc" = \'10\') AS "b" ON "d"="e" WHERE "x" = \'20\'', - 'prepare' => 'SELECT "a".*, "b".* FROM "a" INNER JOIN (SELECT "c".* FROM "c" WHERE "cc" = ?) AS "b" ON "d"="e" WHERE "x" = ?', - 'parameters' => ['subselect1expr1'=>10, 'expr1'=>20], - ], - 'MySql' => [ - 'string' => 'SELECT `a`.*, `b`.* FROM `a` INNER JOIN (SELECT `c`.* FROM `c` WHERE `cc` = \'10\') AS `b` ON `d`=`e` WHERE `x` = \'20\'', - 'prepare' => 'SELECT `a`.*, `b`.* FROM `a` INNER JOIN (SELECT `c`.* FROM `c` WHERE `cc` = ?) AS `b` ON `d`=`e` WHERE `x` = ?', - 'parameters' => ['subselect1expr1'=>10, 'expr1'=>20], - ], - 'Oracle' => [ - 'string' => 'SELECT "a".*, "b".* FROM "a" INNER JOIN (SELECT "c".* FROM "c" WHERE "cc" = \'10\') "b" ON "d"="e" WHERE "x" = \'20\'', - 'prepare' => 'SELECT "a".*, "b".* FROM "a" INNER JOIN (SELECT "c".* FROM "c" WHERE "cc" = ?) "b" ON "d"="e" WHERE "x" = ?', - 'parameters' => ['subselect1expr1'=>10, 'expr1'=>20], - ], - 'SqlServer' => [ - 'string' => 'SELECT [a].*, [b].* FROM [a] INNER JOIN (SELECT [c].* FROM [c] WHERE [cc] = \'10\') AS [b] ON [d]=[e] WHERE [x] = \'20\'', - 'prepare' => 'SELECT [a].*, [b].* FROM [a] INNER JOIN (SELECT [c].* FROM [c] WHERE [cc] = ?) AS [b] ON [d]=[e] WHERE [x] = ?', - 'parameters' => ['subselect1expr1'=>10, 'expr1'=>20], - ], - ], - ], - 'Ddl::CreateTable::processColumns()' => [ - 'sqlObject' => $this->createTable('foo') - ->addColumn($this->createColumn('col1')->setOption('identity', true)->setOption('comment', 'Comment1')) - ->addColumn($this->createColumn('col2')->setOption('identity', true)->setOption('comment', 'Comment2')), - 'expected' => [ - 'sql92' => "CREATE TABLE \"foo\" ( \n \"col1\" INTEGER NOT NULL,\n \"col2\" INTEGER NOT NULL \n)", - 'MySql' => "CREATE TABLE `foo` ( \n `col1` INTEGER NOT NULL AUTO_INCREMENT COMMENT 'Comment1',\n `col2` INTEGER NOT NULL AUTO_INCREMENT COMMENT 'Comment2' \n)", - 'Oracle' => "CREATE TABLE \"foo\" ( \n \"col1\" INTEGER NOT NULL,\n \"col2\" INTEGER NOT NULL \n)", - 'SqlServer' => "CREATE TABLE [foo] ( \n [col1] INTEGER NOT NULL,\n [col2] INTEGER NOT NULL \n)", - ], - ], - 'Ddl::CreateTable::processTable()' => [ - 'sqlObject' => $this->createTable('foo')->setTemporary(true), - 'expected' => [ - 'sql92' => "CREATE TEMPORARY TABLE \"foo\" ( \n)", - 'MySql' => "CREATE TEMPORARY TABLE `foo` ( \n)", - 'Oracle' => "CREATE TEMPORARY TABLE \"foo\" ( \n)", - 'SqlServer' => "CREATE TABLE [#foo] ( \n)", - ], - ], - 'Select::processSubSelect()' => [ - 'sqlObject' => $this->select(['a' => $this->select(['b' => $this->select('c')->where(['cc'=>'CC'])])->where(['bb'=>'BB'])])->where(['aa'=>'AA']), - 'expected' => [ - 'sql92' => [ - 'string' => 'SELECT "a".* FROM (SELECT "b".* FROM (SELECT "c".* FROM "c" WHERE "cc" = \'CC\') AS "b" WHERE "bb" = \'BB\') AS "a" WHERE "aa" = \'AA\'', - 'prepare' => 'SELECT "a".* FROM (SELECT "b".* FROM (SELECT "c".* FROM "c" WHERE "cc" = ?) AS "b" WHERE "bb" = ?) AS "a" WHERE "aa" = ?', - 'parameters' => ['subselect2expr1' => 'CC', 'subselect1expr1' => 'BB', 'expr1' => 'AA'], - ], - 'MySql' => [ - 'string' => 'SELECT `a`.* FROM (SELECT `b`.* FROM (SELECT `c`.* FROM `c` WHERE `cc` = \'CC\') AS `b` WHERE `bb` = \'BB\') AS `a` WHERE `aa` = \'AA\'', - 'prepare' => 'SELECT `a`.* FROM (SELECT `b`.* FROM (SELECT `c`.* FROM `c` WHERE `cc` = ?) AS `b` WHERE `bb` = ?) AS `a` WHERE `aa` = ?', - 'parameters' => ['subselect2expr1' => 'CC', 'subselect1expr1' => 'BB', 'expr1' => 'AA'], - ], - 'Oracle' => [ - 'string' => 'SELECT "a".* FROM (SELECT "b".* FROM (SELECT "c".* FROM "c" WHERE "cc" = \'CC\') "b" WHERE "bb" = \'BB\') "a" WHERE "aa" = \'AA\'', - 'prepare' => 'SELECT "a".* FROM (SELECT "b".* FROM (SELECT "c".* FROM "c" WHERE "cc" = ?) "b" WHERE "bb" = ?) "a" WHERE "aa" = ?', - 'parameters' => ['subselect2expr1' => 'CC', 'subselect1expr1' => 'BB', 'expr1' => 'AA'], - ], - 'SqlServer' => [ - 'string' => 'SELECT [a].* FROM (SELECT [b].* FROM (SELECT [c].* FROM [c] WHERE [cc] = \'CC\') AS [b] WHERE [bb] = \'BB\') AS [a] WHERE [aa] = \'AA\'', - 'prepare' => 'SELECT [a].* FROM (SELECT [b].* FROM (SELECT [c].* FROM [c] WHERE [cc] = ?) AS [b] WHERE [bb] = ?) AS [a] WHERE [aa] = ?', - 'parameters' => ['subselect2expr1' => 'CC', 'subselect1expr1' => 'BB', 'expr1' => 'AA'], - ], - ], - ], - 'Delete::processSubSelect()' => [ - 'sqlObject' => $this->delete('foo')->where(['x'=>$this->select('foo')->where(['x'=>'y'])]), - 'expected' => [ - 'sql92' => [ - 'string' => 'DELETE FROM "foo" WHERE "x" = (SELECT "foo".* FROM "foo" WHERE "x" = \'y\')', - 'prepare' => 'DELETE FROM "foo" WHERE "x" = (SELECT "foo".* FROM "foo" WHERE "x" = ?)', - 'parameters' => ['subselect1expr1' => 'y'], - ], - 'MySql' => [ - 'string' => 'DELETE FROM `foo` WHERE `x` = (SELECT `foo`.* FROM `foo` WHERE `x` = \'y\')', - 'prepare' => 'DELETE FROM `foo` WHERE `x` = (SELECT `foo`.* FROM `foo` WHERE `x` = ?)', - 'parameters' => ['subselect1expr1' => 'y'], - ], - 'Oracle' => [ - 'string' => 'DELETE FROM "foo" WHERE "x" = (SELECT "foo".* FROM "foo" WHERE "x" = \'y\')', - 'prepare' => 'DELETE FROM "foo" WHERE "x" = (SELECT "foo".* FROM "foo" WHERE "x" = ?)', - 'parameters' => ['subselect1expr1' => 'y'], - ], - 'SqlServer' => [ - 'string' => 'DELETE FROM [foo] WHERE [x] = (SELECT [foo].* FROM [foo] WHERE [x] = \'y\')', - 'prepare' => 'DELETE FROM [foo] WHERE [x] = (SELECT [foo].* FROM [foo] WHERE [x] = ?)', - 'parameters' => ['subselect1expr1' => 'y'], - ], - ], - ], - 'Update::processSubSelect()' => [ - 'sqlObject' => $this->update('foo')->set(['x'=>$this->select('foo')]), - 'expected' => [ - 'sql92' => 'UPDATE "foo" SET "x" = (SELECT "foo".* FROM "foo")', - 'MySql' => 'UPDATE `foo` SET `x` = (SELECT `foo`.* FROM `foo`)', - 'Oracle' => 'UPDATE "foo" SET "x" = (SELECT "foo".* FROM "foo")', - 'SqlServer' => 'UPDATE [foo] SET [x] = (SELECT [foo].* FROM [foo])', - ], - ], - 'Insert::processSubSelect()' => [ - 'sqlObject' => $this->insert('foo')->select($this->select('foo')->where(['x'=>'y'])), - 'expected' => [ - 'sql92' => [ - 'string' => 'INSERT INTO "foo" SELECT "foo".* FROM "foo" WHERE "x" = \'y\'', - 'prepare' => 'INSERT INTO "foo" SELECT "foo".* FROM "foo" WHERE "x" = ?', - 'parameters' => ['subselect1expr1' => 'y'], - ], - 'MySql' => [ - 'string' => 'INSERT INTO `foo` SELECT `foo`.* FROM `foo` WHERE `x` = \'y\'', - 'prepare' => 'INSERT INTO `foo` SELECT `foo`.* FROM `foo` WHERE `x` = ?', - 'parameters' => ['subselect1expr1' => 'y'], - ], - 'Oracle' => [ - 'string' => 'INSERT INTO "foo" SELECT "foo".* FROM "foo" WHERE "x" = \'y\'', - 'prepare' => 'INSERT INTO "foo" SELECT "foo".* FROM "foo" WHERE "x" = ?', - 'parameters' => ['subselect1expr1' => 'y'], - ], - 'SqlServer' => [ - 'string' => 'INSERT INTO [foo] SELECT [foo].* FROM [foo] WHERE [x] = \'y\'', - 'prepare' => 'INSERT INTO [foo] SELECT [foo].* FROM [foo] WHERE [x] = ?', - 'parameters' => ['subselect1expr1' => 'y'], - ], - ], - ], - 'Update::processExpression()' => [ - 'sqlObject' => $this->update('foo')->set(['x'=>new Sql\Expression('?', [$this->select('foo')->where(['x'=>'y'])])]), - 'expected' => [ - 'sql92' => [ - 'string' => 'UPDATE "foo" SET "x" = (SELECT "foo".* FROM "foo" WHERE "x" = \'y\')', - 'prepare' => 'UPDATE "foo" SET "x" = (SELECT "foo".* FROM "foo" WHERE "x" = ?)', - 'parameters' => ['subselect1expr1' => 'y'], - ], - 'MySql' => [ - 'string' => 'UPDATE `foo` SET `x` = (SELECT `foo`.* FROM `foo` WHERE `x` = \'y\')', - 'prepare' => 'UPDATE `foo` SET `x` = (SELECT `foo`.* FROM `foo` WHERE `x` = ?)', - 'parameters' => ['subselect1expr1' => 'y'], - ], - 'Oracle' => [ - 'string' => 'UPDATE "foo" SET "x" = (SELECT "foo".* FROM "foo" WHERE "x" = \'y\')', - 'prepare' => 'UPDATE "foo" SET "x" = (SELECT "foo".* FROM "foo" WHERE "x" = ?)', - 'parameters' => ['subselect1expr1' => 'y'], - ], - 'SqlServer' => [ - 'string' => 'UPDATE [foo] SET [x] = (SELECT [foo].* FROM [foo] WHERE [x] = \'y\')', - 'prepare' => 'UPDATE [foo] SET [x] = (SELECT [foo].* FROM [foo] WHERE [x] = ?)', - 'parameters' => ['subselect1expr1' => 'y'], - ], - ], - ], - 'Update::processJoins()_1' => [ - 'sqlObject' => $this->update('foo')->set(['x' => 'y'])->where(['xx' => 'yy'])->join( - 'bar', - 'bar.barId = foo.barId' - ), - 'expected' => [ - 'sql92' => [ - 'string' => 'UPDATE "foo" INNER JOIN "bar" ON "bar"."barId" = "foo"."barId" SET "x" = \'y\' WHERE "xx" = \'yy\'', - ], - 'MySql' => [ - 'string' => 'UPDATE `foo` INNER JOIN `bar` ON `bar`.`barId` = `foo`.`barId` SET `x` = \'y\' WHERE `xx` = \'yy\'', - ], - 'Oracle' => [ - 'string' => 'UPDATE "foo" INNER JOIN "bar" ON "bar"."barId" = "foo"."barId" SET "x" = \'y\' WHERE "xx" = \'yy\'', - ], - 'SqlServer' => [ - 'string' => 'UPDATE [foo] INNER JOIN [bar] ON [bar].[barId] = [foo].[barId] SET [x] = \'y\' WHERE [xx] = \'yy\'', - ], - ], - ], - 'Update::processJoins()_2' => [ - 'sqlObject' => $this->update('Document')->set(['x' => 'y']) - ->join( - 'User', // table name - 'User.UserId = Document.UserId' // expression to join on (will be quoted by platform object before insertion), - // default JOIN INNER - ) - ->join( - 'Category', - 'Category.CategoryId = Document.CategoryId', - Sql\Join::JOIN_LEFT // (optional), one of inner, outer, left, right - ), - 'expected' => [ - 'sql92' => [ - 'string' => 'UPDATE "Document" INNER JOIN "User" ON "User"."UserId" = "Document"."UserId" LEFT JOIN "Category" ON "Category"."CategoryId" = "Document"."CategoryId" SET "x" = \'y\'', - ], - 'MySql' => [ - 'string' => 'UPDATE `Document` INNER JOIN `User` ON `User`.`UserId` = `Document`.`UserId` LEFT JOIN `Category` ON `Category`.`CategoryId` = `Document`.`CategoryId` SET `x` = \'y\'', - ], - 'Oracle' => [ - 'string' => 'UPDATE "Document" INNER JOIN "User" ON "User"."UserId" = "Document"."UserId" LEFT JOIN "Category" ON "Category"."CategoryId" = "Document"."CategoryId" SET "x" = \'y\'', - ], - 'SqlServer' => [ - 'string' => 'UPDATE [Document] INNER JOIN [User] ON [User].[UserId] = [Document].[UserId] LEFT JOIN [Category] ON [Category].[CategoryId] = [Document].[CategoryId] SET [x] = \'y\'', - ], - ], - ], - ]; - } - - protected function dataProvider_Builders() - { - return [ + return $this->prepareDataProvider([ 'RootDecorators::Select' => [ 'sqlObject' => $this->select('foo')->where(['x'=>$this->select('bar')]), 'expected' => [ @@ -500,6 +184,6 @@ protected function dataProvider_Builders() ], ], ], - ]; + ]); } } diff --git a/test/Sql/Builder/CombineBuilderTest.php b/test/Sql/Builder/CombineBuilderTest.php index 8f624e70ac..861535e199 100644 --- a/test/Sql/Builder/CombineBuilderTest.php +++ b/test/Sql/Builder/CombineBuilderTest.php @@ -11,6 +11,9 @@ use Zend\Db\Sql\Combine; +/** + * @covers Zend\Db\Sql\Builder\sql92\CombineBuilder + */ class CombineBuilderTest extends AbstractTestCase { /** diff --git a/test/Sql/Builder/Ddl/AlterTableBuilderTest.php b/test/Sql/Builder/Ddl/AlterTableBuilderTest.php index b58f012fe1..bf9b7cdc9d 100644 --- a/test/Sql/Builder/Ddl/AlterTableBuilderTest.php +++ b/test/Sql/Builder/Ddl/AlterTableBuilderTest.php @@ -13,6 +13,9 @@ use Zend\Db\Sql\Ddl\Constraint; use ZendTest\Db\Sql\Builder\AbstractTestCase; +/** + * @covers Zend\Db\Sql\Builder\sql92\Ddl\AlterTableBuilder + */ class AlterTableBuilderTest extends AbstractTestCase { /** diff --git a/test/Sql/Builder/Ddl/Column/ColumnBuilderTest.php b/test/Sql/Builder/Ddl/Column/ColumnBuilderTest.php index 1359462277..59569597f2 100644 --- a/test/Sql/Builder/Ddl/Column/ColumnBuilderTest.php +++ b/test/Sql/Builder/Ddl/Column/ColumnBuilderTest.php @@ -9,373 +9,181 @@ namespace ZendTest\Db\Sql\Builder\Ddl\Column; -use Zend\Db\Sql\Builder\Builder; -use Zend\Db\Sql\Builder\sql92\Ddl\Column as ColumnBuilder; -use Zend\Db\Sql\Ddl\Column; -use Zend\Db\Sql\Ddl\Constraint; -use Zend\Db\Sql\ExpressionParameter; -use Zend\Db\Sql\Builder\Context; use ZendTest\Db\Sql\Builder\AbstractTestCase; +/** + * @covers Zend\Db\Sql\Builder\sql92\Ddl\Column\ColumnBuilder + */ class ColumnBuilderTest extends AbstractTestCase { - protected $context; - - public function setUp() + /** + * @param type $data + * @dataProvider dataProvider + */ + public function test($sqlObject, $platform, $expected) { - $this->context = new Context($this->getAdapterForPlatform('sql92')); + $this->assertBuilder($sqlObject, $platform, $expected); } - public function testColumn() + public function dataProvider() { - $builder = new ColumnBuilder\ColumnBuilder(new Builder); - $column = new Column\Column; - $column->setName('foo'); - $this->assertEquals( - [[ - '%s %s NOT NULL', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('INTEGER', $column::TYPE_LITERAL), - ], - ]], - $builder->getExpressionData($column, $this->context) - ); - - $column->setNullable(true); - $this->assertEquals( - [[ - '%s %s', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('INTEGER', $column::TYPE_LITERAL), - ], - ]], - $builder->getExpressionData($column, $this->context) - ); - - $column->setDefault('bar'); - $this->assertEquals( - [[ - '%s %s DEFAULT %s', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('INTEGER', $column::TYPE_LITERAL), - new ExpressionParameter('bar', $column::TYPE_VALUE), - ], - ]], - $builder->getExpressionData($column, $this->context) + return $this->prepareDataProvider( + $this->dataProvider_Column(), + $this->dataProvider_OtherColumns() ); } - public function testAbstractLengthColumn() + public function dataProvider_Column() { - $builder = new ColumnBuilder\AbstractLengthColumnBuilder(new Builder); - $column = $this->getMockForAbstractClass('Zend\Db\Sql\Ddl\Column\AbstractLengthColumn', [ - 'foo', 4 - ]); - - $this->assertEquals( - [[ - '%s %s NOT NULL', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('INTEGER(4)', $column::TYPE_LITERAL), + return [ + [ + 'sqlObject' => $this->column_Column() + ->setName('foo'), + 'expected' => [ + 'sql92' => '"foo" INTEGER NOT NULL', ], - ]], - $builder->getExpressionData($column, $this->context) - ); - } - - public function testAbstractPrecisionColumn() - { - $builder = new ColumnBuilder\AbstractPrecisionColumnBuilder(new Builder); - $column = $this->getMockForAbstractClass('Zend\Db\Sql\Ddl\Column\AbstractPrecisionColumn', [ - 'foo', 10, 5 - ]); - - $this->assertEquals( - [[ - '%s %s NOT NULL', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('INTEGER(10,5)', $column::TYPE_LITERAL), + ], + [ + 'sqlObject' => $this->column_Column() + ->setName('foo') + ->setNullable(true), + 'expected' => [ + 'sql92' => '"foo" INTEGER', ], - ]], - $builder->getExpressionData($column, $this->context) - ); - } - - public function testBigInteger() - { - $builder = new ColumnBuilder\IntegerBuilder(new Builder); - $column = new Column\BigInteger('foo'); - $this->assertEquals( - [[ - '%s %s NOT NULL', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('BIGINT', $column::TYPE_LITERAL), + ], + [ + 'sqlObject' => $this->column_Column() + ->setName('foo') + ->setNullable(true) + ->setDefault('bar'), + 'expected' => [ + 'sql92' => '"foo" INTEGER DEFAULT \'bar\'', ], - ]], - $builder->getExpressionData($column, $this->context) - ); + ], + ]; } - public function testBinary() + public function dataProvider_OtherColumns() { - $builder = new ColumnBuilder\AbstractLengthColumnBuilder(new Builder); - $column = new Column\Binary('foo', 10000000); - $this->assertEquals( - [[ - '%s %s NOT NULL', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('BINARY(10000000)', $column::TYPE_LITERAL), + return [ + [ + 'sqlObject' => $this->getMockForAbstractClass('Zend\Db\Sql\Ddl\Column\AbstractLengthColumn', [ + 'foo', 4 + ]), + 'expected' => [ + 'sql92' => '"foo" INTEGER(4) NOT NULL', ], - ]], - $builder->getExpressionData($column, $this->context) - ); - } - - public function testBlob() - { - $builder = new ColumnBuilder\AbstractLengthColumnBuilder(new Builder); - $column = new Column\Blob('foo'); - $this->assertEquals( - [[ - '%s %s NOT NULL', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('BLOB', $column::TYPE_LITERAL), - ] - ]], - $builder->getExpressionData($column, $this->context) - ); - } - - public function testBoolean() - { - $builder = new ColumnBuilder\ColumnBuilder(new Builder); - $column = new Column\Boolean('foo'); - $this->assertEquals( - [[ - '%s %s NOT NULL', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('BOOLEAN', $column::TYPE_LITERAL), - ] - ]], - $builder->getExpressionData($column, $this->context) - ); - } - - public function testChar() - { - $builder = new ColumnBuilder\AbstractLengthColumnBuilder(new Builder); - $column = new Column\Char('foo', 20); - $this->assertEquals( - [[ - '%s %s NOT NULL', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('CHAR(20)', $column::TYPE_LITERAL), + ], + [ + 'sqlObject' => $this->getMockForAbstractClass('Zend\Db\Sql\Ddl\Column\AbstractPrecisionColumn', [ + 'foo', 10, 5 + ]), + 'expected' => [ + 'sql92' => '"foo" INTEGER(10,5) NOT NULL', ], - ]], - $builder->getExpressionData($column, $this->context) - ); - } - - public function testDate() - { - $builder = new ColumnBuilder\ColumnBuilder(new Builder); - $column = new Column\Date('foo'); - $this->assertEquals( - [[ - '%s %s NOT NULL', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('DATE', $column::TYPE_LITERAL), + ], + [ + 'sqlObject' => $this->column_BigInteger('foo'), + 'expected' => [ + 'sql92' => '"foo" BIGINT NOT NULL', ], - ]], - $builder->getExpressionData($column, $this->context) - ); - } - - public function testDatetime() - { - $builder = new ColumnBuilder\ColumnBuilder(new Builder); - $column = new Column\Datetime('foo'); - $this->assertEquals( - [[ - '%s %s NOT NULL', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('DATETIME', $column::TYPE_LITERAL), + ], + [ + 'sqlObject' => $this->column_Binary('foo', 10000000), + 'expected' => [ + 'sql92' => '"foo" BINARY(10000000) NOT NULL', ], - ]], - $builder->getExpressionData($column, $this->context) - ); - } - - public function testDecimal() - { - $builder = new ColumnBuilder\AbstractPrecisionColumnBuilder(new Builder); - $column = new Column\Decimal('foo', 10, 5); - $this->assertEquals( - [[ - '%s %s NOT NULL', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('DECIMAL(10,5)', $column::TYPE_LITERAL), + ], + [ + 'sqlObject' => $this->column_Blob('foo'), + 'expected' => [ + 'sql92' => '"foo" BLOB NOT NULL', ], - ]], - $builder->getExpressionData($column, $this->context) - ); - } - - public function testFloating() - { - $builder = new ColumnBuilder\AbstractPrecisionColumnBuilder(new Builder); - $column = new Column\Floating('foo', 10, 5); - $this->assertEquals( - [[ - '%s %s NOT NULL', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('FLOAT(10,5)', $column::TYPE_LITERAL), + ], + [ + 'sqlObject' => $this->column_Boolean('foo'), + 'expected' => [ + 'sql92' => '"foo" BOOLEAN NOT NULL', ], - ]], - $builder->getExpressionData($column, $this->context) - ); - } - - public function testInteger() - { - $builder = new ColumnBuilder\IntegerBuilder(new Builder); - $column = new Column\Integer('foo'); - $this->assertEquals( - [[ - '%s %s NOT NULL', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('INTEGER', $column::TYPE_LITERAL), + ], + [ + 'sqlObject' => $this->column_Char('foo', 20), + 'expected' => [ + 'sql92' => '"foo" CHAR(20) NOT NULL', ], - ]], - $builder->getExpressionData($column, $this->context) - ); - - $column = new Column\Integer('foo'); - $column->addConstraint(new Constraint\PrimaryKey()); - $this->assertEquals( + ], [ - [ - '%s %s NOT NULL', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('INTEGER', $column::TYPE_LITERAL), - ], + 'sqlObject' => $this->column_Date('foo'), + 'expected' => [ + 'sql92' => '"foo" DATE NOT NULL', ], - ' ', - [ - 'PRIMARY KEY', - [], - ] ], - $builder->getExpressionData($column, $this->context) - ); - } - - public function testText() - { - $builder = new ColumnBuilder\AbstractLengthColumnBuilder(new Builder); - $column = new Column\Text('foo'); - $this->assertEquals( - [[ - '%s %s NOT NULL', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('TEXT', $column::TYPE_LITERAL), + [ + 'sqlObject' => $this->column_Datetime('foo'), + 'expected' => [ + 'sql92' => '"foo" DATETIME NOT NULL', ], - ]], - $builder->getExpressionData($column, $this->context) - ); - } - - public function testTime() - { - $builder = new ColumnBuilder\ColumnBuilder(new Builder); - $column = new Column\Time('foo'); - $this->assertEquals( - [[ - '%s %s NOT NULL', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('TIME', $column::TYPE_LITERAL), + ], + [ + 'sqlObject' => $this->column_Decimal('foo', 10, 5), + 'expected' => [ + 'sql92' => '"foo" DECIMAL(10,5) NOT NULL', ], - ]], - $builder->getExpressionData($column, $this->context) - ); - } - - public function testTimestamp() - { - $builder = new ColumnBuilder\AbstractTimestampColumnBuilder(new Builder); - $column = new Column\Timestamp('foo'); - $this->assertEquals( - [[ - '%s %s NOT NULL', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('TIMESTAMP', $column::TYPE_LITERAL), + ], + [ + 'sqlObject' => $this->column_Floating('foo', 10, 5), + 'expected' => [ + 'sql92' => '"foo" FLOAT(10,5) NOT NULL', ], - ]], - $builder->getExpressionData($column, $this->context) - ); - } - - public function testVarbinary() - { - $builder = new ColumnBuilder\AbstractLengthColumnBuilder(new Builder); - $column = new Column\Varbinary('foo', 20); - $this->assertEquals( - [[ - '%s %s NOT NULL', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('VARBINARY(20)', $column::TYPE_LITERAL), + ], + [ + 'sqlObject' => $this->column_Integer('foo'), + 'expected' => [ + 'sql92' => '"foo" INTEGER NOT NULL', ], - ]], - $builder->getExpressionData($column, $this->context) - ); - } - - public function testVarchar() - { - $builder = new ColumnBuilder\AbstractLengthColumnBuilder(new Builder); - $column = new Column\Varchar('foo', 20); - $this->assertEquals( - [[ - '%s %s NOT NULL', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('VARCHAR(20)', $column::TYPE_LITERAL), + ], + [ + 'sqlObject' => $this->column_Integer('foo')->addConstraint($this->constraint_PrimaryKey()), + 'expected' => [ + 'sql92' => '"foo" INTEGER NOT NULL PRIMARY KEY', ], - ]], - $builder->getExpressionData($column, $this->context) - ); - - $column->setDefault('bar'); - $this->assertEquals( - [[ - '%s %s NOT NULL DEFAULT %s', - [ - new ExpressionParameter('foo', $column::TYPE_IDENTIFIER), - new ExpressionParameter('VARCHAR(20)', $column::TYPE_LITERAL), - new ExpressionParameter('bar', $column::TYPE_VALUE), - ] - ]], - $builder->getExpressionData($column, $this->context) - ); + ], + [ + 'sqlObject' => $this->column_Text('foo'), + 'expected' => [ + 'sql92' => '"foo" TEXT NOT NULL', + ], + ], + [ + 'sqlObject' => $this->column_Time('foo'), + 'expected' => [ + 'sql92' => '"foo" TIME NOT NULL', + ], + ], + [ + 'sqlObject' => $this->column_Timestamp('foo'), + 'expected' => [ + 'sql92' => '"foo" TIMESTAMP NOT NULL', + ], + ], + [ + 'sqlObject' => $this->column_Varbinary('foo', 20), + 'expected' => [ + 'sql92' => '"foo" VARBINARY(20) NOT NULL', + ], + ], + [ + 'sqlObject' => $this->column_Varchar('foo', 20), + 'expected' => [ + 'sql92' => '"foo" VARCHAR(20) NOT NULL', + ], + ], + [ + 'sqlObject' => $this->column_Varchar('foo', 20)->setDefault('bar'), + 'expected' => [ + 'sql92' => '"foo" VARCHAR(20) NOT NULL DEFAULT \'bar\'', + ], + ], + ]; } } diff --git a/test/Sql/Builder/Ddl/Constraint/CheckBuilderTest.php b/test/Sql/Builder/Ddl/Constraint/CheckBuilderTest.php index 0b9d40f15f..e2d191e831 100644 --- a/test/Sql/Builder/Ddl/Constraint/CheckBuilderTest.php +++ b/test/Sql/Builder/Ddl/Constraint/CheckBuilderTest.php @@ -9,37 +9,31 @@ namespace ZendTest\Db\Sql\Builder\Ddl\Constraint; -use Zend\Db\Sql\Builder\Builder; -use Zend\Db\Sql\Builder\sql92\Ddl\Constraint\CheckBuilder; -use Zend\Db\Sql\Ddl\Constraint\Check; -use Zend\Db\Sql\ExpressionParameter; -use Zend\Db\Sql\Builder\Context; use ZendTest\Db\Sql\Builder\AbstractTestCase; +/** + * @covers Zend\Db\Sql\Builder\sql92\Ddl\Constraint\CheckBuilder + */ class CheckBuilderTest extends AbstractTestCase { - protected $context; - - protected $builder; - - public function setUp() + /** + * @param type $data + * @dataProvider dataProvider + */ + public function test($sqlObject, $platform, $expected) { - $this->builder = new CheckBuilder(new Builder); - $this->context = new Context($this->getAdapterForPlatform('sql92')); + $this->assertBuilder($sqlObject, $platform, $expected); } - public function testGetExpressionData() + public function dataProvider() { - $check = new Check('id>0', 'foo'); - $this->assertEquals( - [[ - 'CONSTRAINT %s CHECK (%s)', - [ - new ExpressionParameter('foo', $check::TYPE_IDENTIFIER), - new ExpressionParameter('id>0', $check::TYPE_LITERAL), + return $this->prepareDataProvider([ + [ + 'sqlObject' => $this->constraint_Check('id>0', 'foo'), + 'expected' => [ + 'sql92' => 'CONSTRAINT "foo" CHECK (id>0)', ], - ]], - $this->builder->getExpressionData($check, $this->context) - ); + ], + ]); } } diff --git a/test/Sql/Builder/Ddl/Constraint/ForeignKeyBuilderTest.php b/test/Sql/Builder/Ddl/Constraint/ForeignKeyBuilderTest.php index 3008cfd173..ca5812af30 100644 --- a/test/Sql/Builder/Ddl/Constraint/ForeignKeyBuilderTest.php +++ b/test/Sql/Builder/Ddl/Constraint/ForeignKeyBuilderTest.php @@ -9,39 +9,31 @@ namespace ZendTest\Db\Sql\Builder\Ddl\Constraint; -use Zend\Db\Sql\Builder\Builder; -use Zend\Db\Sql\Builder\sql92\Ddl\Constraint\ForeignKeyBuilder; -use Zend\Db\Sql\Ddl\Constraint\ForeignKey; -use Zend\Db\Sql\ExpressionParameter; -use Zend\Db\Sql\Builder\Context; use ZendTest\Db\Sql\Builder\AbstractTestCase; +/** + * @covers Zend\Db\Sql\Builder\sql92\Ddl\Constraint\ForeignKeyBuilder + */ class ForeignKeyBuilderTest extends AbstractTestCase { - protected $builder; - - public function setUp() + /** + * @param type $data + * @dataProvider dataProvider + */ + public function test($sqlObject, $platform, $expected) { - $this->builder = new ForeignKeyBuilder(new Builder); - $this->context = new Context($this->getAdapterForPlatform('sql92')); + $this->assertBuilder($sqlObject, $platform, $expected); } - public function testGetExpressionData() + public function dataProvider() { - $fk = new ForeignKey('foo', 'bar', 'baz', 'bam', 'CASCADE', 'SET NULL'); - $this->assertEquals( - [[ - 'CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s) ON DELETE %s ON UPDATE %s', - [ - new ExpressionParameter('foo', ForeignKey::TYPE_IDENTIFIER), - new ExpressionParameter('bar', ForeignKey::TYPE_IDENTIFIER), - new ExpressionParameter('baz', ForeignKey::TYPE_IDENTIFIER), - new ExpressionParameter('bam', ForeignKey::TYPE_IDENTIFIER), - new ExpressionParameter('CASCADE', ForeignKey::TYPE_LITERAL), - new ExpressionParameter('SET NULL', ForeignKey::TYPE_LITERAL), + return $this->prepareDataProvider([ + [ + 'sqlObject' => $this->constraint_ForeignKey('foo', 'bar', 'baz', 'bam', 'CASCADE', 'SET NULL'), + 'expected' => [ + 'sql92' => 'CONSTRAINT "foo" FOREIGN KEY ("bar") REFERENCES "baz" ("bam") ON DELETE CASCADE ON UPDATE SET NULL', ], - ]], - $this->builder->getExpressionData($fk, $this->context) - ); + ], + ]); } } diff --git a/test/Sql/Builder/Ddl/Constraint/PrimaryKeyBuilderTest.php b/test/Sql/Builder/Ddl/Constraint/PrimaryKeyBuilderTest.php index 063b371fa6..f960774b68 100644 --- a/test/Sql/Builder/Ddl/Constraint/PrimaryKeyBuilderTest.php +++ b/test/Sql/Builder/Ddl/Constraint/PrimaryKeyBuilderTest.php @@ -9,34 +9,37 @@ namespace ZendTest\Db\Sql\Builder\Ddl\Constraint; -use Zend\Db\Sql\Builder\Builder; -use Zend\Db\Sql\Builder\sql92\Ddl\Constraint\PrimaryKeyBuilder; -use Zend\Db\Sql\Ddl\Constraint\PrimaryKey; -use Zend\Db\Sql\ExpressionParameter; -use Zend\Db\Sql\Builder\Context; use ZendTest\Db\Sql\Builder\AbstractTestCase; +/** + * @covers Zend\Db\Sql\Builder\sql92\Ddl\Constraint\PrimaryKeyBuilder + */ class PrimaryKeyBuilderTest extends AbstractTestCase { - protected $builder; - - public function setUp() + /** + * @param type $data + * @dataProvider dataProvider + */ + public function test($sqlObject, $platform, $expected) { - $this->builder = new PrimaryKeyBuilder(new Builder); - $this->context = new Context($this->getAdapterForPlatform('sql92')); + $this->assertBuilder($sqlObject, $platform, $expected); } - public function testGetExpressionData() + public function dataProvider() { - $pk = new PrimaryKey('foo'); - $this->assertEquals( - [[ - 'PRIMARY KEY (%s)', - [ - new ExpressionParameter('foo', $pk::TYPE_IDENTIFIER), + return $this->prepareDataProvider([ + [ + 'sqlObject' => $this->constraint_PrimaryKey('foo'), + 'expected' => [ + 'sql92' => 'PRIMARY KEY ("foo")', + ], + ], + [ + 'sqlObject' => $this->constraint_PrimaryKey('foo', 'bar'), + 'expected' => [ + 'sql92' => 'CONSTRAINT "bar" PRIMARY KEY ("foo")', ], - ]], - $this->builder->getExpressionData($pk, $this->context) - ); + ], + ]); } } diff --git a/test/Sql/Builder/Ddl/Constraint/UniqueKeyBuilderTest.php b/test/Sql/Builder/Ddl/Constraint/UniqueKeyBuilderTest.php index 1299c4a9d3..6e8d2747d0 100644 --- a/test/Sql/Builder/Ddl/Constraint/UniqueKeyBuilderTest.php +++ b/test/Sql/Builder/Ddl/Constraint/UniqueKeyBuilderTest.php @@ -9,35 +9,37 @@ namespace ZendTest\Db\Sql\Builder\Ddl\Constraint; -use Zend\Db\Sql\Builder\Builder; -use Zend\Db\Sql\Builder\sql92\Ddl\Constraint\UniqueKeyBuilder; -use Zend\Db\Sql\Ddl\Constraint\UniqueKey; -use Zend\Db\Sql\ExpressionParameter; -use Zend\Db\Sql\Builder\Context; use ZendTest\Db\Sql\Builder\AbstractTestCase; +/** + * @covers Zend\Db\Sql\Builder\sql92\Ddl\Constraint\UniqueKeyBuilder + */ class UniqueKeyBuilderTest extends AbstractTestCase { - protected $builder; - - public function setUp() + /** + * @param type $data + * @dataProvider dataProvider + */ + public function test($sqlObject, $platform, $expected) { - $this->builder = new UniqueKeyBuilder(new Builder); - $this->context = new Context($this->getAdapterForPlatform('sql92')); + $this->assertBuilder($sqlObject, $platform, $expected); } - public function testGetExpressionData() + public function dataProvider() { - $uk = new UniqueKey('foo', 'my_uk'); - $this->assertEquals( - [[ - 'CONSTRAINT %s UNIQUE (%s)', - [ - new ExpressionParameter('my_uk', $uk::TYPE_IDENTIFIER), - new ExpressionParameter('foo', $uk::TYPE_IDENTIFIER), + return $this->prepareDataProvider([ + [ + 'sqlObject' => $this->constraint_UniqueKey('foo', 'my_uk'), + 'expected' => [ + 'sql92' => 'CONSTRAINT "my_uk" UNIQUE ("foo")', + ], + ], + [ + 'sqlObject' => $this->constraint_UniqueKey('foo'), + 'expected' => [ + 'sql92' => 'UNIQUE ("foo")', ], - ]], - $this->builder->getExpressionData($uk, $this->context) - ); + ], + ]); } } diff --git a/test/Sql/Builder/Ddl/CreateTableBuilderTest.php b/test/Sql/Builder/Ddl/CreateTableBuilderTest.php index a51ecae5ed..d2996c5225 100644 --- a/test/Sql/Builder/Ddl/CreateTableBuilderTest.php +++ b/test/Sql/Builder/Ddl/CreateTableBuilderTest.php @@ -13,6 +13,10 @@ use Zend\Db\Sql\Ddl\Constraint; use ZendTest\Db\Sql\Builder\AbstractTestCase; +/** + * @covers Zend\Db\Sql\Builder\sql92\Ddl\CreateTableBuilder + * @covers Zend\Db\Sql\Builder\SqlServer\Ddl\CreateTableBuilder + */ class CreateTableBuilderTest extends AbstractTestCase { /** @@ -27,46 +31,26 @@ public function test($sqlObject, $platform, $expected) public function dataProvider() { return $this->prepareDataProvider( - $this->dataProvider_SQL92(), - $this->dataProvider_Mysql(), - $this->dataProvider_SqlServer() + $this->dataProvider_ColumnsAndConstraint(), + $this->dataProvider_Table() ); } - public function dataProvider_SqlServer() + public function dataProvider_ColumnsAndConstraint() { return [ - [ - 'sqlObject' => $this->createTable('foo'), - 'expected' => [ - 'SqlServer' => "CREATE TABLE [foo] ( \n)", - ], - ], - [ - 'sqlObject' => $this->createTable('foo', true), + 'with options' => [ + 'sqlObject' => $this->createTable('foo') + ->addColumn($this->createColumn('col1')->setOption('identity', true)->setOption('comment', 'Comment1')) + ->addColumn($this->createColumn('col2')->setOption('identity', true)->setOption('comment', 'Comment2')), 'expected' => [ - 'SqlServer' => "CREATE TABLE [#foo] ( \n)", + 'sql92' => "CREATE TABLE \"foo\" ( \n \"col1\" INTEGER NOT NULL,\n \"col2\" INTEGER NOT NULL \n)", + 'MySql' => "CREATE TABLE `foo` ( \n `col1` INTEGER NOT NULL AUTO_INCREMENT COMMENT 'Comment1',\n `col2` INTEGER NOT NULL AUTO_INCREMENT COMMENT 'Comment2' \n)", + 'Oracle' => "CREATE TABLE \"foo\" ( \n \"col1\" INTEGER NOT NULL,\n \"col2\" INTEGER NOT NULL \n)", + 'SqlServer' => "CREATE TABLE [foo] ( \n [col1] INTEGER NOT NULL,\n [col2] INTEGER NOT NULL \n)", ], ], - [ - 'sqlObject' => $this->createTable('foo')->addColumn(new Column('bar')), - 'expected' => [ - 'SqlServer' => "CREATE TABLE [foo] ( \n [bar] INTEGER NOT NULL \n)", - ], - ], - [ - 'sqlObject' => $this->createTable('foo', true)->addColumn(new Column('bar')), - 'expected' => [ - 'SqlServer' => "CREATE TABLE [#foo] ( \n [bar] INTEGER NOT NULL \n)", - ], - ], - ]; - } - - public function dataProvider_Mysql() - { - return [ - [ + 'with options 2' => [ 'sqlObject' => function () { $col = new Column('bar'); $col->setOption('zerofill', true); @@ -83,34 +67,18 @@ public function dataProvider_Mysql() 'mysql' => "CREATE TABLE `foo` ( \n `bar` INTEGER UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'baz' COLUMN_FORMAT FIXED STORAGE MEMORY \n)", ], ], - ]; - } - - public function dataProvider_SQL92() - { - return [ - [ - 'sqlObject' => $this->createTable('foo'), - 'expected' => [ - 'sql92' => "CREATE TABLE \"foo\" ( \n)", - ], - ], - [ - 'sqlObject' => $this->createTable('foo', true), - 'expected' => [ - 'sql92' => "CREATE TEMPORARY TABLE \"foo\" ( \n)", - ], - ], [ 'sqlObject' => $this->createTable('foo')->addColumn(new Column('bar')), 'expected' => [ - 'sql92' => "CREATE TABLE \"foo\" ( \n \"bar\" INTEGER NOT NULL \n)", + 'sql92' => "CREATE TABLE \"foo\" ( \n \"bar\" INTEGER NOT NULL \n)", + 'SqlServer' => "CREATE TABLE [foo] ( \n [bar] INTEGER NOT NULL \n)", ], ], [ 'sqlObject' => $this->createTable('foo', true)->addColumn(new Column('bar')), 'expected' => [ - 'sql92' => "CREATE TEMPORARY TABLE \"foo\" ( \n \"bar\" INTEGER NOT NULL \n)", + 'sql92' => "CREATE TEMPORARY TABLE \"foo\" ( \n \"bar\" INTEGER NOT NULL \n)", + 'SqlServer' => "CREATE TABLE [#foo] ( \n [bar] INTEGER NOT NULL \n)", ], ], [ @@ -133,4 +101,33 @@ public function dataProvider_SQL92() ], ]; } + + public function dataProvider_Table() + { + return [ + 'not temporary' => [ + 'sqlObject' => $this->createTable('foo'), + 'expected' => [ + 'sql92' => "CREATE TABLE \"foo\" ( \n)", + 'SqlServer' => "CREATE TABLE [foo] ( \n)", + ], + ], + 'temporary' => [ + 'sqlObject' => $this->createTable('foo')->setTemporary(true), + 'expected' => [ + 'sql92' => "CREATE TEMPORARY TABLE \"foo\" ( \n)", + 'MySql' => "CREATE TEMPORARY TABLE `foo` ( \n)", + 'Oracle' => "CREATE TEMPORARY TABLE \"foo\" ( \n)", + 'SqlServer' => "CREATE TABLE [#foo] ( \n)", + ], + ], + 'temporary via constructor' => [ + 'sqlObject' => $this->createTable('foo', true), + 'expected' => [ + 'sql92' => "CREATE TEMPORARY TABLE \"foo\" ( \n)", + 'SqlServer' => "CREATE TABLE [#foo] ( \n)", + ], + ], + ]; + } } diff --git a/test/Sql/Builder/Ddl/DropTableBuilderTest.php b/test/Sql/Builder/Ddl/DropTableBuilderTest.php index fc90dba352..05565803a7 100644 --- a/test/Sql/Builder/Ddl/DropTableBuilderTest.php +++ b/test/Sql/Builder/Ddl/DropTableBuilderTest.php @@ -11,6 +11,9 @@ use ZendTest\Db\Sql\Builder\AbstractTestCase; +/** + * @covers Zend\Db\Sql\Builder\sql92\Ddl\DropTableBuilder + */ class DropTableBuilderTest extends AbstractTestCase { /** diff --git a/test/Sql/Builder/Ddl/Index/IndexBuilderTest.php b/test/Sql/Builder/Ddl/Index/IndexBuilderTest.php index a13de9280f..5965ec4a20 100644 --- a/test/Sql/Builder/Ddl/Index/IndexBuilderTest.php +++ b/test/Sql/Builder/Ddl/Index/IndexBuilderTest.php @@ -9,76 +9,43 @@ namespace ZendTest\Db\Sql\Builder\Ddl\Index; -use Zend\Db\Sql\Builder\Builder; -use Zend\Db\Sql\Builder\sql92\Ddl\Index\IndexBuilder; -use Zend\Db\Sql\Ddl\Index\Index; -use Zend\Db\Sql\ExpressionParameter; -use Zend\Db\Sql\Builder\Context; use ZendTest\Db\Sql\Builder\AbstractTestCase; +/** + * @covers Zend\Db\Sql\Builder\sql92\Ddl\Index\IndexBuilder + */ class IndexBuilderTest extends AbstractTestCase { - protected $builder; - - public function setUp() - { - $this->builder = new IndexBuilder(new Builder); - $this->context = new Context($this->getAdapterForPlatform('sql92')); - } - /** - * @covers Zend\Db\Sql\Ddl\Index\Index::getExpressionData + * @param type $data + * @dataProvider dataProvider */ - public function testGetExpressionData() + public function test($sqlObject, $platform, $expected) { - $uk = new Index('foo', 'my_uk'); - $this->assertEquals( - [[ - 'INDEX %s(%s)', - [ - new ExpressionParameter('my_uk', $uk::TYPE_IDENTIFIER), - new ExpressionParameter('foo', $uk::TYPE_IDENTIFIER), - ], - ]], - $this->builder->getExpressionData($uk, $this->context) - ); + $this->assertBuilder($sqlObject, $platform, $expected); } - /** - * @covers Zend\Db\Sql\Ddl\Index\Index::getExpressionData - */ - public function testGetExpressionDataWithLength() + public function dataProvider() { - $key = new Index(['foo', 'bar'], 'my_uk', [10, 5]); - $this->assertEquals( - [[ - 'INDEX %s(%s(10), %s(5))', - [ - new ExpressionParameter('my_uk', $key::TYPE_IDENTIFIER), - new ExpressionParameter('foo', $key::TYPE_IDENTIFIER), - new ExpressionParameter('bar', $key::TYPE_IDENTIFIER), + return $this->prepareDataProvider([ + [ + 'sqlObject' => $this->index_Index('foo', 'my_uk'), + 'expected' => [ + 'sql92' => 'INDEX "my_uk"("foo")', ], - ]], - $this->builder->getExpressionData($key, $this->context) - ); - } - - /** - * @covers Zend\Db\Sql\Ddl\Index\Index::getExpressionData - */ - public function testGetExpressionDataWithLengthUnmatched() - { - $key = new Index(['foo', 'bar'], 'my_uk', [10]); - $this->assertEquals( - [[ - 'INDEX %s(%s(10), %s)', - [ - new ExpressionParameter('my_uk', $key::TYPE_IDENTIFIER), - new ExpressionParameter('foo', $key::TYPE_IDENTIFIER), - new ExpressionParameter('bar', $key::TYPE_IDENTIFIER), + ], + [ + 'sqlObject' => $this->index_Index(['foo', 'bar'], 'my_uk', [10, 5]), + 'expected' => [ + 'sql92' => 'INDEX "my_uk"("foo"(10), "bar"(5))', + ], + ], + [ + 'sqlObject' => $this->index_Index(['foo', 'bar'], 'my_uk', [10]), + 'expected' => [ + 'sql92' => 'INDEX "my_uk"("foo"(10), "bar")', ], - ]], - $this->builder->getExpressionData($key, $this->context) - ); + ], + ]); } } diff --git a/test/Sql/Builder/DeleteBuilderTest.php b/test/Sql/Builder/DeleteBuilderTest.php index 94e7a3e25d..1a8871b696 100644 --- a/test/Sql/Builder/DeleteBuilderTest.php +++ b/test/Sql/Builder/DeleteBuilderTest.php @@ -11,6 +11,9 @@ use Zend\Db\Sql\TableIdentifier; +/** + * @covers Zend\Db\Sql\Builder\sql92\DeleteBuilder + */ class DeleteBuilderTest extends AbstractTestCase { /** @@ -23,26 +26,81 @@ public function test($sqlObject, $platform, $expected) } public function dataProvider() + { + return $this->prepareDataProvider( + $this->dataProvider_From(), + $this->dataProvider_Subselect(), + $this->dataProvider_Where() + ); + } + + public function dataProvider_From() { return $this->prepareDataProvider([ - [ // testPrepareStatement(), testGetSqlString() - 'sqlObject' => $this->delete()->from('foo')->where('x = y'), + [ + 'sqlObject' => $this->delete()->from('foo'), 'expected' => [ 'sql92' => [ - 'string' => 'DELETE FROM "foo" WHERE x = y', + 'string' => 'DELETE FROM "foo"', 'prepare' => true, ], ], ], - [ // testPrepareStatement(), testGetSqlString() // with TableIdentifier - 'sqlObject' => $this->delete()->from(new TableIdentifier('foo', 'sch'))->where('x = y'), + [ + 'sqlObject' => $this->delete()->from(new TableIdentifier('foo', 'sch')), 'expected' => [ 'sql92' => [ - 'string' => 'DELETE FROM "sch"."foo" WHERE x = y', + 'string' => 'DELETE FROM "sch"."foo"', 'prepare' => true, ], ], ], ]); } + + public function dataProvider_Subselect() + { + return [ + [ + 'sqlObject' => $this->delete('foo')->where(['x'=>$this->select('foo')->where(['x'=>'y'])]), + 'expected' => [ + 'sql92' => [ + 'string' => 'DELETE FROM "foo" WHERE "x" = (SELECT "foo".* FROM "foo" WHERE "x" = \'y\')', + 'prepare' => 'DELETE FROM "foo" WHERE "x" = (SELECT "foo".* FROM "foo" WHERE "x" = ?)', + 'parameters' => ['subselect1expr1' => 'y'], + ], + 'MySql' => [ + 'string' => 'DELETE FROM `foo` WHERE `x` = (SELECT `foo`.* FROM `foo` WHERE `x` = \'y\')', + 'prepare' => 'DELETE FROM `foo` WHERE `x` = (SELECT `foo`.* FROM `foo` WHERE `x` = ?)', + 'parameters' => ['subselect1expr1' => 'y'], + ], + 'Oracle' => [ + 'string' => 'DELETE FROM "foo" WHERE "x" = (SELECT "foo".* FROM "foo" WHERE "x" = \'y\')', + 'prepare' => 'DELETE FROM "foo" WHERE "x" = (SELECT "foo".* FROM "foo" WHERE "x" = ?)', + 'parameters' => ['subselect1expr1' => 'y'], + ], + 'SqlServer' => [ + 'string' => 'DELETE FROM [foo] WHERE [x] = (SELECT [foo].* FROM [foo] WHERE [x] = \'y\')', + 'prepare' => 'DELETE FROM [foo] WHERE [x] = (SELECT [foo].* FROM [foo] WHERE [x] = ?)', + 'parameters' => ['subselect1expr1' => 'y'], + ], + ], + ], + ]; + } + + public function dataProvider_Where() + { + return [ + [ // testPrepareStatement(), testGetSqlString() + 'sqlObject' => $this->delete()->from('foo')->where('x = y'), + 'expected' => [ + 'sql92' => [ + 'string' => 'DELETE FROM "foo" WHERE x = y', + 'prepare' => true, + ], + ], + ], + ]; + } } diff --git a/test/Sql/Builder/ExpressionBuilderTest.php b/test/Sql/Builder/ExpressionBuilderTest.php index a9c7a9197b..18bb6018c2 100644 --- a/test/Sql/Builder/ExpressionBuilderTest.php +++ b/test/Sql/Builder/ExpressionBuilderTest.php @@ -9,99 +9,173 @@ namespace ZendTest\Db\Sql\Builder; -use Zend\Db\Sql\Builder\sql92\ExpressionBuilder; -use Zend\Db\Sql\Predicate\Expression; -use Zend\Db\Sql\Expression as BaseExpression; -use Zend\Db\Sql\ExpressionParameter; -use Zend\Db\Sql\Builder\Context; +use Zend\Db\Sql\ExpressionInterface; +/** + * @covers Zend\Db\Sql\Builder\sql92\ExpressionBuilder + */ class ExpressionBuilderTest extends AbstractTestCase { - protected $expression; - protected $builder; - - public function setUp() + /** + * @param type $data + * @dataProvider dataProvider + */ + public function test($sqlObject, $platform, $expected) { - $this->builder = new ExpressionBuilder(new \Zend\Db\Sql\Builder\Builder()); - $this->context = new Context($this->getAdapterForPlatform('sql92')); + $this->assertBuilder($sqlObject, $platform, $expected); } - public function testRetrievingWherePartsReturnsSpecificationArrayOfLiteralAndParametersAndArrayOfTypes() + public function dataProvider() { - $expression = new Expression(); - $expression->setExpression('foo.bar = ? AND id != ?') - ->setParameters(['foo', 'bar']); - - $this->assertEquals( - [[ - 'foo.bar = %s AND id != %s', - [ - new ExpressionParameter('foo', Expression::TYPE_VALUE), - new ExpressionParameter('bar', Expression::TYPE_VALUE), + return $this->prepareDataProvider([ + [ + 'sqlObject' => $this->predicate_Expression()->setExpression('foo.bar = ? AND id != ?')->setParameters(['foo', 'bar']), + 'expected' => [ + 'sql92' => [ + 'string' => 'foo.bar = \'foo\' AND id != \'bar\'', + 'prepare' => 'foo.bar = ? AND id != ?', + 'parameters' => [ + 'expr1' => 'foo', + 'expr2' => 'bar', + ], + ], ], - ]], - $this->builder->getExpressionData($expression, $this->context) - ); - } - - /** - * @covers Zend\Db\Sql\Expression::getExpressionData - */ - public function testGetExpressionData() - { - $expression = new BaseExpression( - 'X SAME AS ? AND Y = ? BUT LITERALLY ?', + ], [ - ['foo', Expression::TYPE_IDENTIFIER], - [5, Expression::TYPE_VALUE], - ['FUNC(FF%X)', Expression::TYPE_LITERAL], - ] - ); - $this->assertEquals( - [[ - 'X SAME AS %s AND Y = %s BUT LITERALLY %s', - [ - new ExpressionParameter('foo', Expression::TYPE_IDENTIFIER), - new ExpressionParameter(5, Expression::TYPE_VALUE), - new ExpressionParameter('FUNC(FF%X)', Expression::TYPE_LITERAL), + 'sqlObject' => $this->expression( + 'X SAME AS ? AND Y = ? BUT LITERALLY ?', + [ + ['foo', ExpressionInterface::TYPE_IDENTIFIER], + [5, ExpressionInterface::TYPE_VALUE], + ['FUNC(FF%X)', ExpressionInterface::TYPE_LITERAL], + ]), + 'expected' => [ + 'sql92' => [ + 'string' => 'X SAME AS "foo" AND Y = \'5\' BUT LITERALLY FUNC(FF%X)', + 'prepare' => 'X SAME AS "foo" AND Y = ? BUT LITERALLY FUNC(FF%X)', + 'parameters' => [ + 'expr1' => 5, + ], + ], ], - ]], - $this->builder->getExpressionData($expression, $this->context) - ); - - $expression = new BaseExpression( - 'X SAME AS ? AND Y = ? BUT LITERALLY ?', + ], [ - ['foo' => Expression::TYPE_IDENTIFIER], - [5 => Expression::TYPE_VALUE], - ['FUNC(FF%X)' => Expression::TYPE_LITERAL], - ] - ); - $this->assertEquals( - [[ - 'X SAME AS %s AND Y = %s BUT LITERALLY %s', - [ - new ExpressionParameter('foo', Expression::TYPE_IDENTIFIER), - new ExpressionParameter(5, Expression::TYPE_VALUE), - new ExpressionParameter('FUNC(FF%X)', Expression::TYPE_LITERAL), + 'sqlObject' => $this->expression('X LIKE "foo%"'), + 'expected' => [ + 'sql92' => [ + 'string' => 'X LIKE "foo%"', + 'prepare' => 'X LIKE "foo%"', + 'parameters' => [], + ], ], - ]], - $this->builder->getExpressionData($expression, $this->context) - ); - } - - public function testGetExpressionDataWillEscapePercent() - { - $expression = new BaseExpression('X LIKE "foo%"'); - $this->assertEquals( - ['X LIKE "foo%%"'], - $this->builder->getExpressionData($expression, $this->context) - ); - } - - public function testNumberOfReplacemensConsidersWhenSameVariableIsUsedManyTimes() - { - $expression = new Expression('uf.user_id = :user_id OR uf.friend_id = :user_id', ['user_id' => 1]); - $this->builder->getExpressionData($expression, $this->context); + ], + [ + 'sqlObject' => $this->expression('? LIKE "foo%"', [['X', 'literal']]), + 'expected' => [ + 'sql92' => [ + 'string' => 'X LIKE "foo%"', + 'prepare' => 'X LIKE "foo%"', + 'parameters' => [], + ], + ], + ], + [ + 'sqlObject' => $this->expression( + '? > ? AND y < ?', + [ + ['x', ExpressionInterface::TYPE_IDENTIFIER], + 5, + 10 + ] + ), + 'expected' => [ + 'sql92' => [ + 'string' => '"x" > \'5\' AND y < \'10\'', + 'prepare' => '"x" > ? AND y < ?', + 'parameters' => [ + 'expr1' => 5, + 'expr2' => 10, + ], + ], + ], + ], + [ + 'sqlObject' => $this->expression( + '? > ? AND y < ?', + [ + ['x', ExpressionInterface::TYPE_IDENTIFIER], + 5, + 10 + ] + ), + 'expected' => [ + 'sql92' => [ + 'string' => '"x" > \'5\' AND y < \'10\'', + 'prepare' => '"x" > :expr1 AND y < :expr2', + 'parameters' => [ + 'expr1' => 5, + 'expr2' => 10, + ], + 'useNamedParams' => true, + ], + ], + ], + [ + 'sqlObject' => $this->predicate_PredicateSet([$this->predicate_PredicateSet([$this->predicate_Expression('x = ?', 5)])]), + 'expected' => [ + 'sql92' => [ + 'string' => "(x = '5')", + 'prepare' => "(x = ?)", + 'parameters' => [ + 'expr1' => 5, + ], + ], + ], + ], + [ + 'sqlObject' => $this->predicate_PredicateSet([ + $this->predicate_PredicateSet([ + $this->predicate_In( + 'x', + $this->select('x')->where($this->predicate_Like('bar', 'Foo%')) + ) + ]) + ]), + 'expected' => [ + 'sql92' => [ + 'string' => '("x" IN (SELECT "x".* FROM "x" WHERE "bar" LIKE \'Foo%\'))', + ], + ], + ], + [ + 'sqlObject' => $this->predicate_Operator( + 'release_date', + '=', + $this->expression('FROM_UNIXTIME(?)', 100000000) + ), + 'expected' => [ + 'sql92' => [ + 'string' => '"release_date" = FROM_UNIXTIME(\'100000000\')', + ], + ], + ], + [ + 'sqlObject' => $this->expression('FROM_UNIXTIME(date, "%Y-%m")'), + 'expected' => [ + 'sql92' => [ + 'string' => 'FROM_UNIXTIME(date, "%Y-%m")', + ], + ], + ], + [ + 'sqlObject' => $this->expression('uf.user_id = :user_id OR uf.friend_id = :user_id', ['user_id' => 1]), + 'expected' => [ + 'sql92' => [ + 'string' => 'uf.user_id = :user_id OR uf.friend_id = :user_id', + 'prepare' => 'uf.user_id = :user_id OR uf.friend_id = :user_id', + ], + ], + ], + ]); } } diff --git a/test/Sql/Builder/InsertBuilderTest.php b/test/Sql/Builder/InsertBuilderTest.php index 789aa140ea..e99feb5458 100644 --- a/test/Sql/Builder/InsertBuilderTest.php +++ b/test/Sql/Builder/InsertBuilderTest.php @@ -13,6 +13,9 @@ use Zend\Db\Sql\Expression; use Zend\Db\Sql\TableIdentifier; +/** + * @covers Zend\Db\Sql\Builder\sql92\InsertBuilder + */ class InsertBuilderTest extends AbstractTestCase { /** @@ -26,113 +29,126 @@ public function test($sqlObject, $platform, $expected) public function dataProvider() { - return $this->prepareDataProvider([ - [ // testPrepareStatement() - 'sqlObject' => $this->insert() - ->into('foo') - ->values([ - 'bar' => 'baz', - 'boo' => new Expression('NOW()'), - ]), - 'expected' => [ - 'sql92' => [ - 'string' => '', - 'prepare' => 'INSERT INTO "foo" ("bar", "boo") VALUES (?, NOW())', - ], - ], - ], - [ // testPrepareStatement() // with TableIdentifier - 'sqlObject' => $this->insert() - ->into(new TableIdentifier('foo', 'sch')) - ->values([ - 'bar' => 'baz', - 'boo' => new Expression('NOW()'), - ]), + return $this->prepareDataProvider( + $this->dataProvider_Into(), + $this->dataProvider_ColumnsAndValues() + ); + } + + public function dataProvider_Into() + { + return [ + 'into_TableIdentifier' => [ + 'sqlObject' => $this->insert()->into(new TableIdentifier('foo', 'schema'))->values(['c1' => 'v1']), 'expected' => [ - 'sql92' => [ - 'string' => '', - 'prepare' => 'INSERT INTO "sch"."foo" ("bar", "boo") VALUES (?, NOW())' - ], + 'sql92' => 'INSERT INTO "schema"."foo" ("c1") VALUES (\'v1\')', ], ], - [ // testPrepareStatementWithSelect() - 'sqlObject' => $this->insert() - ->into('foo') - ->columns(['col1']) - ->select($this->select('bar')->where(['x'=>5])), + 'into_string' => [ + 'sqlObject' => $this->insert()->into('foo')->values(['c1' => 'v1']), 'expected' => [ - 'sql92' => [ - 'string' => '', - 'prepare' => 'INSERT INTO "foo" ("col1") SELECT "bar".* FROM "bar" WHERE "x" = ?', - 'parameters' => ['subselect1expr1'=>5], - ], + 'sql92' => 'INSERT INTO "foo" ("c1") VALUES (\'v1\')', ], ], - [ // testGetSqlString() - 'sqlObject' => $this->insert()->into('foo') + ]; + } + + public function dataProvider_ColumnsAndValues() + { + return [ + 'columns_in_values' => [ + 'sqlObject' => $this->insert('foo') ->values([ 'bar' => 'baz', 'boo' => new Expression('NOW()'), - 'bam' => null + 'bam' => null, + 'bat' => $this->select('bad') ]), 'expected' => [ 'sql92' => [ - 'string' => 'INSERT INTO "foo" ("bar", "boo", "bam") VALUES (\'baz\', NOW(), NULL)', + 'string' => 'INSERT INTO "foo" ("bar", "boo", "bam", "bat") VALUES (\'baz\', NOW(), NULL, (SELECT "bad".* FROM "bad"))', + 'prepare' => 'INSERT INTO "foo" ("bar", "boo", "bam", "bat") VALUES (?, NOW(), NULL, (SELECT "bad".* FROM "bad"))', + 'parameters' => ['bar' => 'baz',], ], ], ], - [ // testGetSqlString() // with TableIdentifier - 'sqlObject' => $this->insert() - ->into(new TableIdentifier('foo', 'sch')) + 'values with merge' => [ + 'sqlObject' => $this->insert('foo') ->values([ 'bar' => 'baz', 'boo' => new Expression('NOW()'), 'bam' => null - ]), + ]) + ->values(['qux' => 100], Insert::VALUES_MERGE), 'expected' => [ 'sql92' => [ - 'string' => 'INSERT INTO "sch"."foo" ("bar", "boo", "bam") VALUES (\'baz\', NOW(), NULL)', + 'string' => 'INSERT INTO "foo" ("bar", "boo", "bam", "qux") VALUES (\'baz\', NOW(), NULL, \'100\')', ], ], ], - [ // testGetSqlString() // with Select - 'sqlObject' => $this->insert() - ->into('foo') - ->select($this->select()->from('bar')), + 'select_with_columns' => [ + 'sqlObject' => $this->insert('foo') + ->columns(['col1', 'col2']) + ->select($this->select()->from('bar')->where(['x'=>5])), 'expected' => [ 'sql92' => [ - 'string' => 'INSERT INTO "foo" SELECT "bar".* FROM "bar"', - 'prepare' => true, + 'string' => 'INSERT INTO "foo" ("col1", "col2") SELECT "bar".* FROM "bar" WHERE "x" = \'5\'', + 'prepare' => 'INSERT INTO "foo" ("col1", "col2") SELECT "bar".* FROM "bar" WHERE "x" = ?', + 'parameters' => ['subselect1expr1'=>5], + ], + 'MySql' => [ + 'string' => 'INSERT INTO `foo` (`col1`, `col2`) SELECT `bar`.* FROM `bar` WHERE `x` = \'5\'', + 'prepare' => 'INSERT INTO `foo` (`col1`, `col2`) SELECT `bar`.* FROM `bar` WHERE `x` = ?', + 'parameters' => ['subselect1expr1' => 5], + ], + 'Oracle' => [ + 'string' => 'INSERT INTO "foo" ("col1", "col2") SELECT "bar".* FROM "bar" WHERE "x" = \'5\'', + 'prepare' => 'INSERT INTO "foo" ("col1", "col2") SELECT "bar".* FROM "bar" WHERE "x" = ?', + 'parameters' => ['subselect1expr1' => 5], + ], + 'SqlServer' => [ + 'string' => 'INSERT INTO [foo] ([col1], [col2]) SELECT [bar].* FROM [bar] WHERE [x] = \'5\'', + 'prepare' => 'INSERT INTO [foo] ([col1], [col2]) SELECT [bar].* FROM [bar] WHERE [x] = ?', + 'parameters' => ['subselect1expr1' => 5], ], ], ], - [ // testGetSqlString() // with Select and columns - 'sqlObject' => $this->insert() - ->into('foo') - ->columns(['col1', 'col2']) - ->select($this->select()->from('bar')), + 'select_without_columns' => [ + 'sqlObject' => $this->insert('foo') + ->select($this->select('bar')->where(['x'=>5])), 'expected' => [ - 'sql92' => [ - 'string' => 'INSERT INTO "foo" ("col1", "col2") SELECT "bar".* FROM "bar"', - 'prepare' => true, + 'sql92' => [ + 'string' => 'INSERT INTO "foo" SELECT "bar".* FROM "bar" WHERE "x" = \'5\'', + 'prepare' => 'INSERT INTO "foo" SELECT "bar".* FROM "bar" WHERE "x" = ?', + 'parameters' => ['subselect1expr1' => 5], + ], + 'MySql' => [ + 'string' => 'INSERT INTO `foo` SELECT `bar`.* FROM `bar` WHERE `x` = \'5\'', + 'prepare' => 'INSERT INTO `foo` SELECT `bar`.* FROM `bar` WHERE `x` = ?', + 'parameters' => ['subselect1expr1' => 5], + ], + 'Oracle' => [ + 'string' => 'INSERT INTO "foo" SELECT "bar".* FROM "bar" WHERE "x" = \'5\'', + 'prepare' => 'INSERT INTO "foo" SELECT "bar".* FROM "bar" WHERE "x" = ?', + 'parameters' => ['subselect1expr1' => 5], + ], + 'SqlServer' => [ + 'string' => 'INSERT INTO [foo] SELECT [bar].* FROM [bar] WHERE [x] = \'5\'', + 'prepare' => 'INSERT INTO [foo] SELECT [bar].* FROM [bar] WHERE [x] = ?', + 'parameters' => ['subselect1expr1' => 5], ], ], ], - [ // testValuesMerge() - 'sqlObject' => $this->insert() - ->into('foo') - ->values([ - 'bar' => 'baz', - 'boo' => new Expression('NOW()'), - 'bam' => null - ]) - ->values(['qux' => 100], Insert::VALUES_MERGE), + 'select_with_combine_in_select' => [ + 'sqlObject' => $this->insert('foo') + ->select($this->combine($this->select('bar'))), 'expected' => [ - 'sql92' => [ - 'string' => 'INSERT INTO "foo" ("bar", "boo", "bam", "qux") VALUES (\'baz\', NOW(), NULL, \'100\')', - ], + 'sql92' => 'INSERT INTO "foo" (SELECT "bar".* FROM "bar")', + 'MySql' => 'INSERT INTO `foo` (SELECT `bar`.* FROM `bar`)', + 'Oracle' => 'INSERT INTO "foo" (SELECT "bar".* FROM "bar")', + 'SqlServer' => 'INSERT INTO [foo] (SELECT [bar].* FROM [bar])', ], ], - ]); + ]; } } diff --git a/test/Sql/Builder/LiteralBuilderTest.php b/test/Sql/Builder/LiteralBuilderTest.php index 60e7f89135..467323e281 100644 --- a/test/Sql/Builder/LiteralBuilderTest.php +++ b/test/Sql/Builder/LiteralBuilderTest.php @@ -9,50 +9,43 @@ namespace ZendTest\Db\Sql\Builder; -use Zend\Db\Sql\Builder\sql92\LiteralBuilder; -use Zend\Db\Sql\Predicate\Literal; -use Zend\Db\Sql\Literal as BaseLiteral; -use Zend\Db\Sql\Builder\Context; - +/** + * @covers Zend\Db\Sql\Builder\sql92\LiteralBuilder + */ class LiteralBuilderTest extends AbstractTestCase { - protected $builder; - - public function setUp() + /** + * @param type $data + * @dataProvider dataProvider + */ + public function test($sqlObject, $platform, $expected) { - $this->builder = new LiteralBuilder(new \Zend\Db\Sql\Builder\Builder()); - $this->context = new Context($this->getAdapterForPlatform('sql92')); + $this->assertBuilder($sqlObject, $platform, $expected); } - public function testGetExpressionData() + public function dataProvider() { - $literal = new Literal('bar'); - $this->assertEquals( - [[ - 'bar', - [], - ]], - $this->builder->getExpressionData($literal, $this->context) - ); - } - - public function testGetExpressionDataWillEscapePercent() - { - $literal = new BaseLiteral('X LIKE "foo%"'); - $this->assertEquals([[ - 'X LIKE "foo%%"', - [], - ]], - $this->builder->getExpressionData($literal, $this->context) - ); - - $literal = new BaseLiteral('bar'); - $this->assertEquals( - [[ - 'bar', - [], - ]], - $this->builder->getExpressionData($literal, $this->context) - ); + return $this->prepareDataProvider([ + [ + 'sqlObject' => $this->predicate_Literal('bar'), + 'expected' => [ + 'sql92' => [ + 'string' => 'bar', + 'prepare' => 'bar', + 'parameters' => [], + ], + ], + ], + [ + 'sqlObject' => $this->predicate_Literal('X LIKE "foo%"'), + 'expected' => [ + 'sql92' => [ + 'string' => 'X LIKE "foo%"', + 'prepare' => 'X LIKE "foo%"', + 'parameters' => [], + ], + ], + ], + ]); } } diff --git a/test/Sql/Builder/Predicate/BetweenBuilderTest.php b/test/Sql/Builder/Predicate/BetweenBuilderTest.php index b7316bd0ce..bcb54385dc 100644 --- a/test/Sql/Builder/Predicate/BetweenBuilderTest.php +++ b/test/Sql/Builder/Predicate/BetweenBuilderTest.php @@ -9,60 +9,45 @@ namespace ZendTest\Db\Sql\Builder\Predicate; -use Zend\Db\Sql\Builder\sql92\Predicate\BetweenBuilder; use Zend\Db\Sql\ExpressionInterface; -use Zend\Db\Sql\Predicate\Between; -use Zend\Db\Sql\ExpressionParameter; -use Zend\Db\Sql\Builder\Context; use ZendTest\Db\Sql\Builder\AbstractTestCase; +/** + * @covers Zend\Db\Sql\Builder\sql92\Predicate\BetweenBuilder + */ class BetweenBuilderTest extends AbstractTestCase { - protected $expression; - protected $builder; - - public function setUp() - { - $this->expression = new Between; - $this->builder = new BetweenBuilder(new \Zend\Db\Sql\Builder\Builder()); - $this->context = new Context($this->getAdapterForPlatform('sql92')); - } - /** - * @covers Zend\Db\Sql\Predicate\Between::getExpressionData + * @param type $data + * @dataProvider dataProvider */ - public function testRetrievingWherePartsReturnsSpecificationArrayOfIdentifierAndValuesAndArrayOfTypes() + public function test($sqlObject, $platform, $expected) { - $this->expression->setIdentifier('foo.bar') - ->setMinValue(10) - ->setMaxValue(19); + $this->assertBuilder($sqlObject, $platform, $expected); + } - $this->assertEquals( - [[ - '%1$s BETWEEN %2$s AND %3$s', - [ - new ExpressionParameter('foo.bar', ExpressionInterface::TYPE_IDENTIFIER), - new ExpressionParameter(10, ExpressionInterface::TYPE_VALUE), - new ExpressionParameter(19, ExpressionInterface::TYPE_VALUE), + public function dataProvider() + { + return $this->prepareDataProvider([ + [ + 'sqlObject' => $this->predicate_Between('foo.bar', 5, 10), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" BETWEEN \'5\' AND \'10\'', + ], ], - ]], - $this->builder->getExpressionData($this->expression, $this->context) - ); - - $this->expression->setIdentifier([10=>Between::TYPE_VALUE]) - ->setMinValue(['foo.bar'=>Between::TYPE_IDENTIFIER]) - ->setMaxValue(['foo.baz'=>Between::TYPE_IDENTIFIER]); - - $this->assertEquals( - [[ - '%1$s BETWEEN %2$s AND %3$s', - [ - new ExpressionParameter(10, Between::TYPE_VALUE), - new ExpressionParameter('foo.bar', Between::TYPE_IDENTIFIER), - new ExpressionParameter('foo.baz', Between::TYPE_IDENTIFIER), + ], + [ + 'sqlObject' => $this->predicate_Between() + ->setIdentifier([10=>ExpressionInterface::TYPE_VALUE]) + ->setMinValue(['foo.bar'=>ExpressionInterface::TYPE_IDENTIFIER]) + ->setMaxValue(['foo.baz'=>ExpressionInterface::TYPE_IDENTIFIER]), + 'expected' => [ + 'sql92' => [ + 'string' => '\'10\' BETWEEN "foo"."bar" AND "foo"."baz"', + ], ], - ]], - $this->builder->getExpressionData($this->expression, $this->context) - ); + ], + ]); } } diff --git a/test/Sql/Builder/Predicate/InBuilderTest.php b/test/Sql/Builder/Predicate/InBuilderTest.php index 3034aed3ad..ae09573a76 100644 --- a/test/Sql/Builder/Predicate/InBuilderTest.php +++ b/test/Sql/Builder/Predicate/InBuilderTest.php @@ -9,127 +9,90 @@ namespace ZendTest\Db\Sql\Builder\Predicate; -use Zend\Db\Sql\Builder\sql92\Predicate\InBuilder; -use Zend\Db\Sql\Predicate\In; -use Zend\Db\Sql\Select; -use Zend\Db\Sql\Combine; -use Zend\Db\Sql\ExpressionParameter; -use Zend\Db\Sql\Builder\Context; +use Zend\Db\Sql\ExpressionInterface; use ZendTest\Db\Sql\Builder\AbstractTestCase; +/** + * @covers Zend\Db\Sql\Builder\sql92\Predicate\InBuilder + */ class InBuilderTest extends AbstractTestCase { - protected $builder; - - public function setUp() + /** + * @param type $data + * @dataProvider dataProvider + */ + public function test($sqlObject, $platform, $expected) { - $this->builder = new InBuilder(new \Zend\Db\Sql\Builder\Builder()); - $this->context = new Context($this->getAdapterForPlatform('sql92')); + $this->assertBuilder($sqlObject, $platform, $expected); } - public function testRetrievingWherePartsReturnsSpecificationArrayOfIdentifierAndValuesAndArrayOfTypes() + public function dataProvider() { - $in = new In(); - $in->setIdentifier('foo.bar') - ->setValueSet([1, 2, 3]); - - $this->assertEquals( - [[ - '%s IN (%s, %s, %s)', - [ - new ExpressionParameter('foo.bar', In::TYPE_IDENTIFIER), - new ExpressionParameter(1, In::TYPE_VALUE), - new ExpressionParameter(2, In::TYPE_VALUE), - new ExpressionParameter(3, In::TYPE_VALUE), + return $this->prepareDataProvider([ + [ + 'sqlObject' => $this->predicate_In() + ->setIdentifier('foo.bar') + ->setValueSet([1, 2, 3]), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" IN (\'1\', \'2\', \'3\')', + 'prepare' => '"foo"."bar" IN (?, ?, ?)', + 'parameters' => [ + 'expr1' => 1, + 'expr2' => 2, + 'expr3' => 3, + ], + ], ], - ]], - $this->builder->getExpressionData($in, $this->context) - ); - - $in->setIdentifier('foo.bar') - ->setValueSet([ - [1=>In::TYPE_LITERAL], - [2=>In::TYPE_VALUE], - [3=>In::TYPE_LITERAL], - ]); - - $this->assertEquals( - [[ - '%s IN (%s, %s, %s)', - [ - new ExpressionParameter('foo.bar', In::TYPE_IDENTIFIER), - new ExpressionParameter(1, In::TYPE_LITERAL), - new ExpressionParameter(2, In::TYPE_VALUE), - new ExpressionParameter(3, In::TYPE_LITERAL), + ], + [ + 'sqlObject' => $this->predicate_In() + ->setIdentifier('foo.bar') + ->setValueSet([ + [1=>ExpressionInterface::TYPE_LITERAL], + [2=>ExpressionInterface::TYPE_VALUE], + [3=>ExpressionInterface::TYPE_LITERAL], + ]), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" IN (1, \'2\', 3)', + 'prepare' => '"foo"."bar" IN (1, ?, 3)', + 'parameters' => [ + 'expr1' => 2, + ], + ], ], - ]], - $this->builder->getExpressionData($in, $this->context) - ); - } - - public function testGetExpressionDataWithSubselect() - { - $select = new Select; - $in = new In('foo', $select); - - $this->assertEquals( - [[ - '%s IN %s', - [ - new ExpressionParameter('foo', $in::TYPE_IDENTIFIER), - new ExpressionParameter($select, $in::TYPE_VALUE), + ], + [ + 'sqlObject' => $this->predicate_In('foo', $this->select('bar')), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo" IN (SELECT "bar".* FROM "bar")', + 'prepare' => '"foo" IN (SELECT "bar".* FROM "bar")', + 'parameters' => [], + ], ], - ]], - $this->builder->getExpressionData($in, $this->context) - ); - - $combine = new Combine; - $in = new In('foo', $combine); - - $this->assertEquals( - [[ - '%s IN %s', - [ - new ExpressionParameter('foo', $in::TYPE_IDENTIFIER), - new ExpressionParameter($combine, $in::TYPE_VALUE), - ], - ]], - $this->builder->getExpressionData($in, $this->context) - ); - } - - public function testGetExpressionDataWithSubselectAndIdentifier() - { - $select = new Select; - $in = new In('foo', $select); - - $this->assertEquals( - [[ - '%s IN %s', - [ - new ExpressionParameter('foo', $in::TYPE_IDENTIFIER), - new ExpressionParameter($select, $in::TYPE_VALUE), + ], + [ + 'sqlObject' => $this->predicate_In('foo', $this->combine([$this->select('bar'), $this->select('baz')])), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo" IN ((SELECT "bar".* FROM "bar") UNION (SELECT "baz".* FROM "baz"))', + 'prepare' => '"foo" IN ((SELECT "bar".* FROM "bar") UNION (SELECT "baz".* FROM "baz"))', + 'parameters' => [], + ], ], - ]], - $this->builder->getExpressionData($in, $this->context) - ); - } - - public function testGetExpressionDataWithSubselectAndArrayIdentifier() - { - $select = new Select; - $in = new In(['foo', 'bar'], $select); - - $this->assertEquals( - [[ - '(%s, %s) IN %s', - [ - new ExpressionParameter('foo', $in::TYPE_IDENTIFIER), - new ExpressionParameter('bar', $in::TYPE_IDENTIFIER), - new ExpressionParameter($select, $in::TYPE_VALUE), + ], + [ + 'sqlObject' => $this->predicate_In(['foo', 'bar'], $this->select('bar')), + 'expected' => [ + 'sql92' => [ + 'string' => '("foo", "bar") IN (SELECT "bar".* FROM "bar")', + 'prepare' => '("foo", "bar") IN (SELECT "bar".* FROM "bar")', + 'parameters' => [], + ], ], - ]], - $this->builder->getExpressionData($in, $this->context) - ); + ], + ]); } } diff --git a/test/Sql/Builder/Predicate/IsNotNullBuilderTest.php b/test/Sql/Builder/Predicate/IsNotNullBuilderTest.php index 32e141ebcb..909ea64f09 100644 --- a/test/Sql/Builder/Predicate/IsNotNullBuilderTest.php +++ b/test/Sql/Builder/Predicate/IsNotNullBuilderTest.php @@ -9,36 +9,35 @@ namespace ZendTest\Db\Sql\Builder\Predicate; -use Zend\Db\Sql\Builder\sql92\Predicate\IsNotNullBuilder; -use Zend\Db\Sql\Predicate\IsNotNull; -use Zend\Db\Sql\ExpressionParameter; -use Zend\Db\Sql\Builder\Context; use ZendTest\Db\Sql\Builder\AbstractTestCase; +/** + * @covers Zend\Db\Sql\Builder\sql92\Predicate\IsNotNullBuilder + */ class IsNotNullBuilderTest extends AbstractTestCase { - protected $expression; - protected $builder; - - public function setUp() + /** + * @param type $data + * @dataProvider dataProvider + */ + public function test($sqlObject, $platform, $expected) { - $this->expression = new IsNotNull; - $this->builder = new IsNotNullBuilder(new \Zend\Db\Sql\Builder\Builder()); - $this->context = new Context($this->getAdapterForPlatform('sql92')); + $this->assertBuilder($sqlObject, $platform, $expected); } - public function testRetrievingWherePartsReturnsSpecificationArrayOfIdentifierAndArrayOfTypes() + public function dataProvider() { - $this->expression->setIdentifier('foo.bar'); - - $this->assertEquals( - [[ - '%1$s IS NOT NULL', - [ - new ExpressionParameter('foo.bar', IsNotNull::TYPE_IDENTIFIER), + return $this->prepareDataProvider([ + [ + 'sqlObject' => $this->predicate_IsNotNull('foo.bar'), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" IS NOT NULL', + 'prepare' => '"foo"."bar" IS NOT NULL', + 'parameters' => [], + ], ], - ]], - $this->builder->getExpressionData($this->expression, $this->context) - ); + ], + ]); } } diff --git a/test/Sql/Builder/Predicate/LikeBuilderTest.php b/test/Sql/Builder/Predicate/LikeBuilderTest.php index 33cfd89e0b..a85a221614 100644 --- a/test/Sql/Builder/Predicate/LikeBuilderTest.php +++ b/test/Sql/Builder/Predicate/LikeBuilderTest.php @@ -9,46 +9,46 @@ namespace ZendTest\Db\Sql\Builder\Predicate; -use Zend\Db\Sql\Builder\sql92\Predicate\LikeBuilder; -use Zend\Db\Sql\Predicate\Like; -use Zend\Db\Sql\ExpressionParameter; -use Zend\Db\Sql\Builder\Context; +use Zend\Db\Sql\ExpressionInterface; use ZendTest\Db\Sql\Builder\AbstractTestCase; +/** + * @covers Zend\Db\Sql\Builder\sql92\Predicate\LikeBuilder + */ class LikeBuilderTest extends AbstractTestCase { - protected $builder; - - public function setUp() + /** + * @param type $data + * @dataProvider dataProvider + */ + public function test($sqlObject, $platform, $expected) { - $this->builder = new LikeBuilder(new \Zend\Db\Sql\Builder\Builder()); - $this->context = new Context($this->getAdapterForPlatform('sql92')); + $this->assertBuilder($sqlObject, $platform, $expected); } - public function testGetExpressionData() + public function dataProvider() { - $like = new Like('bar', 'Foo%'); - $this->assertEquals( - [[ - '%1$s LIKE %2$s', - [ - new ExpressionParameter('bar', $like::TYPE_IDENTIFIER), - new ExpressionParameter('Foo%', $like::TYPE_VALUE), + return $this->prepareDataProvider([ + [ + 'sqlObject' => $this->predicate_Like('bar', 'Foo%'), + 'expected' => [ + 'sql92' => [ + 'string' => '"bar" LIKE \'Foo%\'', + 'prepare' => '"bar" LIKE ?', + 'parameters' => ['expr1' => 'Foo%'], + ], ], - ]], - $this->builder->getExpressionData($like, $this->context) - ); - - $like = new Like(['Foo%'=>$like::TYPE_VALUE], ['bar'=>$like::TYPE_IDENTIFIER]); - $this->assertEquals( - [[ - '%1$s LIKE %2$s', - [ - new ExpressionParameter('Foo%', $like::TYPE_VALUE), - new ExpressionParameter('bar', $like::TYPE_IDENTIFIER), + ], + [ + 'sqlObject' => $this->predicate_Like(['Foo%'=>ExpressionInterface::TYPE_VALUE], ['bar'=>ExpressionInterface::TYPE_IDENTIFIER]), + 'expected' => [ + 'sql92' => [ + 'string' => '\'Foo%\' LIKE "bar"', + 'prepare' => '? LIKE "bar"', + 'parameters' => ['expr1' => 'Foo%'], + ], ], - ]], - $this->builder->getExpressionData($like, $this->context) - ); + ], + ]); } } diff --git a/test/Sql/Builder/Predicate/NotBetweenBuilderTest.php b/test/Sql/Builder/Predicate/NotBetweenBuilderTest.php index 0de99e5d56..0c7b8db339 100644 --- a/test/Sql/Builder/Predicate/NotBetweenBuilderTest.php +++ b/test/Sql/Builder/Predicate/NotBetweenBuilderTest.php @@ -9,60 +9,45 @@ namespace ZendTest\Db\Sql\Builder\Predicate; -use Zend\Db\Sql\Builder\sql92\Predicate\NotBetweenBuilder; use Zend\Db\Sql\ExpressionInterface; -use Zend\Db\Sql\Predicate\NotBetween; -use Zend\Db\Sql\ExpressionParameter; -use Zend\Db\Sql\Builder\Context; use ZendTest\Db\Sql\Builder\AbstractTestCase; +/** + * @covers Zend\Db\Sql\Builder\sql92\Predicate\NotBetweenBuilder + */ class NotBetweenBuilderTest extends AbstractTestCase { - protected $expression; - protected $builder; - - public function setUp() - { - $this->expression = new NotBetween; - $this->builder = new NotBetweenBuilder(new \Zend\Db\Sql\Builder\Builder()); - $this->context = new Context($this->getAdapterForPlatform('sql92')); - } - /** - * @covers Zend\Db\Sql\Predicate\Between::getExpressionData + * @param type $data + * @dataProvider dataProvider */ - public function testRetrievingWherePartsReturnsSpecificationArrayOfIdentifierAndValuesAndArrayOfTypes() + public function test($sqlObject, $platform, $expected) { - $this->expression->setIdentifier('foo.bar') - ->setMinValue(10) - ->setMaxValue(19); + $this->assertBuilder($sqlObject, $platform, $expected); + } - $this->assertEquals( - [[ - '%1$s NOT BETWEEN %2$s AND %3$s', - [ - new ExpressionParameter('foo.bar', ExpressionInterface::TYPE_IDENTIFIER), - new ExpressionParameter(10, ExpressionInterface::TYPE_VALUE), - new ExpressionParameter(19, ExpressionInterface::TYPE_VALUE), + public function dataProvider() + { + return $this->prepareDataProvider([ + [ + 'sqlObject' => $this->predicate_NotBetween('foo.bar', 5, 10), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" NOT BETWEEN \'5\' AND \'10\'', + ], ], - ]], - $this->builder->getExpressionData($this->expression, $this->context) - ); - - $this->expression->setIdentifier([10=>NotBetween::TYPE_VALUE]) - ->setMinValue(['foo.bar'=>NotBetween::TYPE_IDENTIFIER]) - ->setMaxValue(['foo.baz'=>NotBetween::TYPE_IDENTIFIER]); - - $this->assertEquals( - [[ - '%1$s NOT BETWEEN %2$s AND %3$s', - [ - new ExpressionParameter(10, NotBetween::TYPE_VALUE), - new ExpressionParameter('foo.bar', NotBetween::TYPE_IDENTIFIER), - new ExpressionParameter('foo.baz', NotBetween::TYPE_IDENTIFIER), + ], + [ + 'sqlObject' => $this->predicate_NotBetween() + ->setIdentifier([10=>ExpressionInterface::TYPE_VALUE]) + ->setMinValue(['foo.bar'=>ExpressionInterface::TYPE_IDENTIFIER]) + ->setMaxValue(['foo.baz'=>ExpressionInterface::TYPE_IDENTIFIER]), + 'expected' => [ + 'sql92' => [ + 'string' => '\'10\' NOT BETWEEN "foo"."bar" AND "foo"."baz"', + ], ], - ]], - $this->builder->getExpressionData($this->expression, $this->context) - ); + ], + ]); } } diff --git a/test/Sql/Builder/Predicate/NotInBuilderTest.php b/test/Sql/Builder/Predicate/NotInBuilderTest.php index 9905502040..0783451e3f 100644 --- a/test/Sql/Builder/Predicate/NotInBuilderTest.php +++ b/test/Sql/Builder/Predicate/NotInBuilderTest.php @@ -9,93 +9,61 @@ namespace ZendTest\Db\Sql\Builder\Predicate; -use Zend\Db\Sql\Builder\sql92\Predicate\NotInBuilder; -use Zend\Db\Sql\Predicate\NotIn; -use Zend\Db\Sql\Select; -use Zend\Db\Sql\ExpressionParameter; -use Zend\Db\Sql\Builder\Context; use ZendTest\Db\Sql\Builder\AbstractTestCase; +/** + * @covers Zend\Db\Sql\Builder\sql92\Predicate\NotInBuilder + */ class NotInBuilderTest extends AbstractTestCase { - protected $expression; - protected $builder; - - public function setUp() + /** + * @param type $data + * @dataProvider dataProvider + */ + public function test($sqlObject, $platform, $expected) { - $this->builder = new NotInBuilder(new \Zend\Db\Sql\Builder\Builder()); - $this->context = new Context($this->getAdapterForPlatform('sql92')); + $this->assertBuilder($sqlObject, $platform, $expected); } - public function testRetrievingWherePartsReturnsSpecificationArrayOfIdentifierAndValuesAndArrayOfTypes() + public function dataProvider() { - $in = new NotIn(); - $in->setIdentifier('foo.bar') - ->setValueSet([1, 2, 3]); - - $this->assertEquals( - [[ - '%s NOT IN (%s, %s, %s)', - [ - new ExpressionParameter('foo.bar', NotIn::TYPE_IDENTIFIER), - new ExpressionParameter(1, NotIn::TYPE_VALUE), - new ExpressionParameter(2, NotIn::TYPE_VALUE), - new ExpressionParameter(3, NotIn::TYPE_VALUE), + return $this->prepareDataProvider([ + [ + 'sqlObject' => $this->predicate_NotIn('bar') + ->setIdentifier('foo.bar') + ->setValueSet([1, 2, 3]), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" NOT IN (\'1\', \'2\', \'3\')', + 'prepare' => '"foo"."bar" NOT IN (?, ?, ?)', + 'parameters' => [ + 'expr1' => 1, + 'expr2' => 2, + 'expr3' => 3, + ], + ], ], - ]], - $this->builder->getExpressionData($in, $this->context) - ); - } - - public function testGetExpressionDataWithSubselect() - { - $select = new Select; - $in = new NotIn('foo', $select); - - $this->assertEquals( - [[ - '%s NOT IN %s', - [ - new ExpressionParameter('foo', $in::TYPE_IDENTIFIER), - new ExpressionParameter($select, $in::TYPE_VALUE), + ], + [ + 'sqlObject' => $this->predicate_NotIn('foo', $this->select('bar')), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo" NOT IN (SELECT "bar".* FROM "bar")', + 'prepare' => '"foo" NOT IN (SELECT "bar".* FROM "bar")', + 'parameters' => [], + ], ], - ]], - $this->builder->getExpressionData($in, $this->context) - ); - } - - public function testGetExpressionDataWithSubselectAndIdentifier() - { - $select = new Select; - $in = new NotIn('foo', $select); - - $this->assertEquals( - [[ - '%s NOT IN %s', - [ - new ExpressionParameter('foo', $in::TYPE_IDENTIFIER), - new ExpressionParameter($select, $in::TYPE_VALUE), - ], - ]], - $this->builder->getExpressionData($in, $this->context) - ); - } - - public function testGetExpressionDataWithSubselectAndArrayIdentifier() - { - $select = new Select; - $in = new NotIn(['foo', 'bar'], $select); - - $this->assertEquals( - [[ - '(%s, %s) NOT IN %s', - [ - new ExpressionParameter('foo', $in::TYPE_IDENTIFIER), - new ExpressionParameter('bar', $in::TYPE_IDENTIFIER), - new ExpressionParameter($select, $in::TYPE_VALUE), + ], + [ + 'sqlObject' => $this->predicate_NotIn(['foo', 'bar'], $this->select('bar')), + 'expected' => [ + 'sql92' => [ + 'string' => '("foo", "bar") NOT IN (SELECT "bar".* FROM "bar")', + 'prepare' => '("foo", "bar") NOT IN (SELECT "bar".* FROM "bar")', + 'parameters' => [], + ], ], - ]], - $this->builder->getExpressionData($in, $this->context) - ); + ], + ]); } } diff --git a/test/Sql/Builder/Predicate/NotLikeBuilderTest.php b/test/Sql/Builder/Predicate/NotLikeBuilderTest.php index ffeb32e692..fbc8a35f6f 100644 --- a/test/Sql/Builder/Predicate/NotLikeBuilderTest.php +++ b/test/Sql/Builder/Predicate/NotLikeBuilderTest.php @@ -9,35 +9,35 @@ namespace ZendTest\Db\Sql\Builder\Predicate; -use Zend\Db\Sql\Builder\sql92\Predicate\NotLikeBuilder; -use Zend\Db\Sql\Predicate\NotLike; -use Zend\Db\Sql\ExpressionParameter; -use Zend\Db\Sql\Builder\Context; use ZendTest\Db\Sql\Builder\AbstractTestCase; +/** + * @covers Zend\Db\Sql\Builder\sql92\Predicate\NotLikeBuilder + */ class NotLikeBuilderTest extends AbstractTestCase { - protected $expression; - protected $builder; - - public function setUp() + /** + * @param type $data + * @dataProvider dataProvider + */ + public function test($sqlObject, $platform, $expected) { - $this->builder = new NotLikeBuilder(new \Zend\Db\Sql\Builder\Builder()); - $this->context = new Context($this->getAdapterForPlatform('sql92')); + $this->assertBuilder($sqlObject, $platform, $expected); } - public function testGetExpressionData() + public function dataProvider() { - $notLike = new NotLike('bar', 'Foo%'); - $this->assertEquals( - [[ - '%1$s NOT LIKE %2$s', - [ - new ExpressionParameter('bar', $notLike::TYPE_IDENTIFIER), - new ExpressionParameter('Foo%', $notLike::TYPE_VALUE), + return $this->prepareDataProvider([ + [ + 'sqlObject' => $this->predicate_NotLike('bar', 'Foo%'), + 'expected' => [ + 'sql92' => [ + 'string' => '"bar" NOT LIKE \'Foo%\'', + 'prepare' => '"bar" NOT LIKE ?', + 'parameters' => ['expr1' => 'Foo%'], + ], ], - ]], - $this->builder->getExpressionData($notLike, $this->context) - ); + ], + ]); } } diff --git a/test/Sql/Builder/Predicate/OperatorBuilderTest.php b/test/Sql/Builder/Predicate/OperatorBuilderTest.php index 9a7ea883f3..1deae560ff 100644 --- a/test/Sql/Builder/Predicate/OperatorBuilderTest.php +++ b/test/Sql/Builder/Predicate/OperatorBuilderTest.php @@ -9,39 +9,57 @@ namespace ZendTest\Db\Sql\Builder\Predicate; -use Zend\Db\Sql\Builder\sql92\Predicate\OperatorBuilder; -use Zend\Db\Sql\Predicate\Operator; -use Zend\Db\Sql\ExpressionParameter; -use Zend\Db\Sql\Builder\Context; +use Zend\Db\Sql\ExpressionInterface; use ZendTest\Db\Sql\Builder\AbstractTestCase; +/** + * @covers Zend\Db\Sql\Builder\sql92\Predicate\OperatorBuilder + */ class OperatorBuilderTest extends AbstractTestCase { - protected $expression; - protected $builder; - - public function setUp() + /** + * @param type $data + * @dataProvider dataProvider + */ + public function test($sqlObject, $platform, $expected) { - $this->expression = new Operator; - $this->builder = new OperatorBuilder(new \Zend\Db\Sql\Builder\Builder()); - $this->context = new Context($this->getAdapterForPlatform('sql92')); + $this->assertBuilder($sqlObject, $platform, $expected); } - public function testRetrievingWherePartsReturnsSpecificationArrayOfLeftAndRightAndArrayOfTypes() + public function dataProvider() { - $this->expression->setLeft(['foo', Operator::TYPE_VALUE]) - ->setOperator('>=') - ->setRight(['foo.bar', Operator::TYPE_IDENTIFIER]); - - $this->assertEquals( - [[ - '%s >= %s', - [ - new ExpressionParameter('foo', Operator::TYPE_VALUE), - new ExpressionParameter('foo.bar', Operator::TYPE_IDENTIFIER), + return $this->prepareDataProvider([ + [ + 'sqlObject' => $this->predicate_Operator() + ->setLeft(['foo', ExpressionInterface::TYPE_VALUE]) + ->setOperator('>=') + ->setRight(['foo.bar', ExpressionInterface::TYPE_IDENTIFIER]), + 'expected' => [ + 'sql92' => [ + 'string' => '\'foo\' >= "foo"."bar"', + 'prepare' => '? >= "foo"."bar"', + 'parameters' => [ + 'expr1' => 'foo', + ], + ], + ], + ], + [ + 'sqlObject' => $this->predicate_Operator( + 'release_date', + '=', + $this->predicate_Expression('FROM_UNIXTIME(?)', 100000000) + ), + 'expected' => [ + 'sql92' => [ + 'string' => '"release_date" = FROM_UNIXTIME(\'100000000\')', + 'prepare' => '"release_date" = FROM_UNIXTIME(?)', + 'parameters' => [ + 'expr1' => 100000000, + ], + ], ], - ]], - $this->builder->getExpressionData($this->expression, $this->context) - ); + ], + ]); } } diff --git a/test/Sql/Builder/Predicate/PredicateBuilderTest.php b/test/Sql/Builder/Predicate/PredicateBuilderTest.php index 2ea9e610f3..39c55c70fa 100644 --- a/test/Sql/Builder/Predicate/PredicateBuilderTest.php +++ b/test/Sql/Builder/Predicate/PredicateBuilderTest.php @@ -9,392 +9,248 @@ namespace ZendTest\Db\Sql\Builder\Predicate; -use Zend\Db\Sql\Builder\sql92\Predicate\PredicateBuilder; -use Zend\Db\Sql\ExpressionInterface; -use Zend\Db\Sql\Predicate\Predicate; -use Zend\Db\Sql\ExpressionParameter; -use Zend\Db\Sql\Builder\Context; use ZendTest\Db\Sql\Builder\AbstractTestCase; +/** + * @covers Zend\Db\Sql\Builder\sql92\Predicate\PredicateBuilder + */ class PredicateBuilderTest extends AbstractTestCase { - protected $expression; - protected $builder; - - public function setUp() + /** + * @param type $data + * @dataProvider dataProvider + */ + public function test($sqlObject, $platform, $expected) { - $this->expression = new Predicate; - $this->builder = new PredicateBuilder(new \Zend\Db\Sql\Builder\Builder()); - $this->context = new Context($this->getAdapterForPlatform('sql92')); + $this->assertBuilder($sqlObject, $platform, $expected); } - public function testEqualToCreatesOperatorPredicate() + public function dataProvider() { - $predicate = new Predicate(); - $predicate->equalTo('foo.bar', 'bar'); - $this->assertEquals( - [[ - '%s = %s', - [ - new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), - new ExpressionParameter('bar', Predicate::TYPE_VALUE), + return $this->prepareDataProvider([ + [ + 'sqlObject' => $this->predicate_Predicate()->equalTo('foo.bar', 'bar'), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" = \'bar\'', + 'prepare' => '"foo"."bar" = ?', + 'parameters' => ['expr1' => 'bar'], + ], ], - ]], - $this->builder->getExpressionData($predicate, $this->context) - ); - } - - public function testNotEqualToCreatesOperatorPredicate() - { - $predicate = new Predicate(); - $predicate->notEqualTo('foo.bar', 'bar'); - $this->assertEquals( - [[ - '%s != %s', - [ - new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), - new ExpressionParameter('bar', Predicate::TYPE_VALUE), + ], + [ + 'sqlObject' => $this->predicate_Predicate()->notEqualTo('foo.bar', 'bar'), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" != \'bar\'', + 'prepare' => '"foo"."bar" != ?', + 'parameters' => ['expr1' => 'bar'], + ], ], - ]], - $this->builder->getExpressionData($predicate, $this->context) - ); - } - - public function testLessThanCreatesOperatorPredicate() - { - $predicate = new Predicate(); - $predicate->lessThan('foo.bar', 'bar'); - $this->assertEquals( - [[ - '%s < %s', - [ - new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), - new ExpressionParameter('bar', Predicate::TYPE_VALUE), + ], + [ + 'sqlObject' => $this->predicate_Predicate()->lessThan('foo.bar', 'bar'), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" < \'bar\'', + 'prepare' => '"foo"."bar" < ?', + 'parameters' => ['expr1' => 'bar'], + ], ], - ]], - $this->builder->getExpressionData($predicate, $this->context) - ); - } - - public function testGreaterThanCreatesOperatorPredicate() - { - $predicate = new Predicate(); - $predicate->greaterThan('foo.bar', 'bar'); - $this->assertEquals( - [[ - '%s > %s', - [ - new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), - new ExpressionParameter('bar', Predicate::TYPE_VALUE), + ], + [ + 'sqlObject' => $this->predicate_Predicate()->greaterThan('foo.bar', 'bar'), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" > \'bar\'', + 'prepare' => '"foo"."bar" > ?', + 'parameters' => ['expr1' => 'bar'], + ], ], - ]], - $this->builder->getExpressionData($predicate, $this->context) - ); - } - - public function testLessThanOrEqualToCreatesOperatorPredicate() - { - $predicate = new Predicate(); - $predicate->lessThanOrEqualTo('foo.bar', 'bar'); - $this->assertEquals( - [[ - '%s <= %s', - [ - new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), - new ExpressionParameter('bar', Predicate::TYPE_VALUE), + ], + [ + 'sqlObject' => $this->predicate_Predicate()->lessThanOrEqualTo('foo.bar', 'bar'), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" <= \'bar\'', + 'prepare' => '"foo"."bar" <= ?', + 'parameters' => ['expr1' => 'bar'], + ], ], - ]], - $this->builder->getExpressionData($predicate, $this->context) - ); - } - - public function testGreaterThanOrEqualToCreatesOperatorPredicate() - { - $predicate = new Predicate(); - $predicate->greaterThanOrEqualTo('foo.bar', 'bar'); - $this->assertEquals( - [[ - '%s >= %s', - [ - new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), - new ExpressionParameter('bar', Predicate::TYPE_VALUE), + ], + [ + 'sqlObject' => $this->predicate_Predicate()->greaterThanOrEqualTo('foo.bar', 'bar'), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" >= \'bar\'', + 'prepare' => '"foo"."bar" >= ?', + 'parameters' => ['expr1' => 'bar'], + ], ], - ]], - $this->builder->getExpressionData($predicate, $this->context) - ); - } - - public function testLikeCreatesLikePredicate() - { - $predicate = new Predicate(); - $predicate->like('foo.bar', 'bar%'); - $this->assertEquals( - [[ - '%1$s LIKE %2$s', - [ - new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), - new ExpressionParameter('bar%', Predicate::TYPE_VALUE), + ], + [ + 'sqlObject' => $this->predicate_Predicate()->like('foo.bar', 'bar%'), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" LIKE \'bar%\'', + 'prepare' => '"foo"."bar" LIKE ?', + 'parameters' => ['expr1' => 'bar%'], + ], ], - ]], - $this->builder->getExpressionData($predicate, $this->context) - ); - } - - public function testNotLikeCreatesLikePredicate() - { - $predicate = new Predicate(); - $predicate->notLike('foo.bar', 'bar%'); - $this->assertEquals( - [[ - '%1$s NOT LIKE %2$s', - [ - new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), - new ExpressionParameter('bar%', Predicate::TYPE_VALUE), + ], + [ + 'sqlObject' => $this->predicate_Predicate()->notLike('foo.bar', 'bar%'), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" NOT LIKE \'bar%\'', + 'prepare' => '"foo"."bar" NOT LIKE ?', + 'parameters' => ['expr1' => 'bar%'], + ], ], - ]], - $this->builder->getExpressionData($predicate, $this->context) - ); - } - - public function testLiteralCreatesLiteralPredicate() - { - $predicate = new Predicate(); - $predicate->literal('foo.bar = ?', 'bar'); - $this->assertEquals( - [[ - 'foo.bar = %s', - [ - new ExpressionParameter('bar', Predicate::TYPE_VALUE), + ], + [ + 'sqlObject' => $this->predicate_Predicate()->literal('foo.bar = ?', 'bar'), + 'expected' => [ + 'sql92' => [ + 'string' => 'foo.bar = \'bar\'', + 'prepare' => 'foo.bar = ?', + 'parameters' => ['expr1' => 'bar'], + ], ], - ]], - $this->builder->getExpressionData($predicate, $this->context) - ); - } - - public function testIsNullCreatesIsNullPredicate() - { - $predicate = new Predicate(); - $predicate->isNull('foo.bar'); - $this->assertEquals( - [[ - '%1$s IS NULL', - [ - new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), + ], + [ + 'sqlObject' => $this->predicate_Predicate()->isNull('foo.bar'), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" IS NULL', + 'prepare' => '"foo"."bar" IS NULL', + 'parameters' => [], + ], ], - ]], - $this->builder->getExpressionData($predicate, $this->context) - ); - } - - public function testIsNotNullCreatesIsNotNullPredicate() - { - $predicate = new Predicate(); - $predicate->isNotNull('foo.bar'); - $this->assertEquals( - [[ - '%1$s IS NOT NULL', - [ - new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), + ], + [ + 'sqlObject' => $this->predicate_Predicate()->isNotNull('foo.bar'), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" IS NOT NULL', + 'prepare' => '"foo"."bar" IS NOT NULL', + 'parameters' => [], + ], ], - ]], - $this->builder->getExpressionData($predicate, $this->context) - ); - } - - public function testInCreatesInPredicate() - { - $predicate = new Predicate(); - $predicate->in('foo.bar', ['foo', 'bar']); - $this->assertEquals( - [[ - '%s IN (%s, %s)', - [ - new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), - new ExpressionParameter('foo', Predicate::TYPE_VALUE), - new ExpressionParameter('bar', Predicate::TYPE_VALUE), + ], + [ + 'sqlObject' => $this->predicate_Predicate()->in('foo.bar', ['foo', 'bar']), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" IN (\'foo\', \'bar\')', + 'prepare' => '"foo"."bar" IN (?, ?)', + 'parameters' => [ + 'expr1' => 'foo', + 'expr2' => 'bar', + ], + ], ], - ]], - $this->builder->getExpressionData($predicate, $this->context) - ); - } - - public function testNotInCreatesNotInPredicate() - { - $predicate = new Predicate(); - $predicate->notIn('foo.bar', ['foo', 'bar']); - $this->assertEquals( - [[ - '%s NOT IN (%s, %s)', - [ - new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), - new ExpressionParameter('foo', Predicate::TYPE_VALUE), - new ExpressionParameter('bar', Predicate::TYPE_VALUE), + ], + [ + 'sqlObject' => $this->predicate_Predicate()->notIn('foo.bar', ['foo', 'bar']), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" NOT IN (\'foo\', \'bar\')', + 'prepare' => '"foo"."bar" NOT IN (?, ?)', + 'parameters' => [ + 'expr1' => 'foo', + 'expr2' => 'bar', + ], + ], ], - ]], - $this->builder->getExpressionData($predicate, $this->context) - ); - } - - public function testBetweenCreatesBetweenPredicate() - { - $predicate = new Predicate(); - $predicate->between('foo.bar', 1, 10); - $this->assertEquals( - [[ - '%1$s BETWEEN %2$s AND %3$s', - [ - new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), - new ExpressionParameter(1, Predicate::TYPE_VALUE), - new ExpressionParameter(10, Predicate::TYPE_VALUE), + ], + [ + 'sqlObject' => $this->predicate_Predicate()->between('foo.bar', 1, 10), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" BETWEEN \'1\' AND \'10\'', + 'prepare' => '"foo"."bar" BETWEEN ? AND ?', + 'parameters' => [ + 'expr1' => 1, + 'expr2' => 10, + ], + ], ], - ]], - $this->builder->getExpressionData($predicate, $this->context) - ); - } - - public function testCanChainPredicateFactoriesBetweenOperators() - { - $predicate = new Predicate(); - $predicate->isNull('foo.bar') - ->or - ->isNotNull('bar.baz') - ->and - ->equalTo('baz.bat', 'foo'); - $this->assertEquals( + ], [ - [ - '%1$s IS NULL', - [ - new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), + 'sqlObject' => $this->predicate_Predicate()->notBetween('foo.bar', 1, 10), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" NOT BETWEEN \'1\' AND \'10\'', + 'prepare' => '"foo"."bar" NOT BETWEEN ? AND ?', + 'parameters' => [ + 'expr1' => 1, + 'expr2' => 10, + ], ], ], - ' OR ', - [ - '%1$s IS NOT NULL', - [ - new ExpressionParameter('bar.baz', Predicate::TYPE_IDENTIFIER), + ], + [ + 'sqlObject' => $this->predicate_Predicate()->expression('foo = ?', 'bar'), + 'expected' => [ + 'sql92' => [ + 'string' => 'foo = \'bar\'', + 'prepare' => 'foo = ?', + 'parameters' => ['expr1' => 'bar'], ], ], - ' AND ', - [ - '%s = %s', - [ - new ExpressionParameter('baz.bat', Predicate::TYPE_IDENTIFIER), - new ExpressionParameter('foo', Predicate::TYPE_VALUE), + ], + [ + 'sqlObject' => $this->predicate_Predicate()->expression('foo = ?', 0), + 'expected' => [ + 'sql92' => [ + 'string' => 'foo = \'0\'', + 'prepare' => 'foo = ?', + 'parameters' => ['expr1' => 0], ], ], ], - $this->builder->getExpressionData($predicate, $this->context) - ); - } - - public function testCanNestPredicates() - { - $predicate = new Predicate(); - $predicate->isNull('foo.bar') - ->nest() - ->isNotNull('bar.baz') - ->and - ->equalTo('baz.bat', 'foo') - ->unnest(); - $this->assertEquals( [ - [ - '%1$s IS NULL', - [ - new ExpressionParameter('foo.bar', Predicate::TYPE_IDENTIFIER), + 'sqlObject' => $this->predicate_Predicate()->expression('foo = ?'), + 'expected' => [ + 'sql92' => [ + 'string' => 'foo = \'\'', + 'prepare' => 'foo = ?', + 'parameters' => ['expr1' => null], ], ], - ' AND ', - '(', - [ - '%1$s IS NOT NULL', - [ - new ExpressionParameter('bar.baz', Predicate::TYPE_IDENTIFIER), + ], + [ + 'sqlObject' => $this->predicate_Predicate() + ->isNull('foo.bar') + ->or + ->isNotNull('bar.baz') + ->and + ->equalTo('baz.bat', 'foo'), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" IS NULL OR "bar"."baz" IS NOT NULL AND "baz"."bat" = \'foo\'', + 'prepare' => '"foo"."bar" IS NULL OR "bar"."baz" IS NOT NULL AND "baz"."bat" = ?', + 'parameters' => ['expr1' => 'foo'], ], ], - ' AND ', - [ - '%s = %s', - [ - new ExpressionParameter('baz.bat', Predicate::TYPE_IDENTIFIER), - new ExpressionParameter('foo', Predicate::TYPE_VALUE), + ], + [ + 'sqlObject' => $this->predicate_Predicate() + ->isNull('foo.bar') + ->nest() + ->isNotNull('bar.baz') + ->and + ->equalTo('baz.bat', 'foo') + ->unnest(), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo"."bar" IS NULL AND ("bar"."baz" IS NOT NULL AND "baz"."bat" = \'foo\')', + 'prepare' => '"foo"."bar" IS NULL AND ("bar"."baz" IS NOT NULL AND "baz"."bat" = ?)', + 'parameters' => ['expr1' => 'foo'], ], ], - ')', ], - $this->builder->getExpressionData($predicate, $this->context) - ); - } - - /** - * @testdox Unit test: Test expression() is chainable and returns proper values - */ - public function testExpression() - { - $predicate = new Predicate; - - // is chainable - $this->assertSame($predicate, $predicate->expression('foo = ?', 0)); - // with parameter - $this->assertEquals( - [[ - 'foo = %s', - [ - new ExpressionParameter(0, Predicate::TYPE_VALUE) - ] - ]], - $this->builder->getExpressionData($predicate, $this->context) - ); - } - - /** - * @testdox Unit test: Test expression() allows null $parameters - */ - public function testExpressionNullParameters() - { - $predicate = new Predicate; - - $predicate->expression('foo = bar'); - $predicates = $predicate->getPredicates(); - $expression = $predicates[0][1]; - $this->assertEquals( - [new ExpressionParameter(null, Predicate::TYPE_VALUE)], - $expression->getParameters() - ); - } - - /** - * @testdox Unit test: Test literal() is chainable, returns proper values, and is backwards compatible with 2.0.* - */ - public function testLiteral() - { - $predicate = new Predicate; - - // is chainable - $this->assertSame($predicate, $predicate->literal('foo = bar')); - // with parameter - $this->assertEquals( - [['foo = bar', []]], - $this->builder->getExpressionData($predicate, $this->context) - ); - - // test literal() is backwards-compatible, and works with with parameters - $predicate = new Predicate; - $predicate->expression('foo = ?', 'bar'); - // with parameter - $this->assertEquals( - [['foo = %s', [new ExpressionParameter('bar', ExpressionInterface::TYPE_VALUE)]]], - $this->builder->getExpressionData($predicate, $this->context) - ); - - // test literal() is backwards-compatible, and works with with parameters, even 0 which tests as false - $predicate = new Predicate; - $predicate->expression('foo = ?', 0); - // with parameter - $this->assertEquals( - [['foo = %s', [new ExpressionParameter(0, ExpressionInterface::TYPE_VALUE)]]], - $this->builder->getExpressionData($predicate, $this->context) - ); + ]); } } diff --git a/test/Sql/Builder/Predicate/PredicateSetBuilderTest.php b/test/Sql/Builder/Predicate/PredicateSetBuilderTest.php index 1aeaba4428..a6d69b5d14 100644 --- a/test/Sql/Builder/Predicate/PredicateSetBuilderTest.php +++ b/test/Sql/Builder/Predicate/PredicateSetBuilderTest.php @@ -9,81 +9,117 @@ namespace ZendTest\Db\Sql\Builder\Predicate; -use Zend\Db\Sql\Builder\sql92\Predicate\PredicateSetBuilder; -use Zend\Db\Sql\Predicate\PredicateSet; -use Zend\Db\Sql\Predicate\IsNull; -use Zend\Db\Sql\Builder\Context; use ZendTest\Db\Sql\Builder\AbstractTestCase; +/** + * @covers Zend\Db\Sql\Builder\sql92\Predicate\PredicateSetBuilder + */ class PredicateSetBuilderTest extends AbstractTestCase { - protected $expression; - protected $builder; - - public function setUp() - { - $this->expression = new PredicateSet; - $this->builder = new PredicateSetBuilder(new \Zend\Db\Sql\Builder\Builder()); - $this->context = new Context($this->getAdapterForPlatform('sql92')); - } - - public function testCombinationIsAndByDefault() - { - $this->expression->addPredicate(new IsNull('foo')) - ->addPredicate(new IsNull('bar')); - $parts = $this->builder->getExpressionData($this->expression, $this->context); - $this->assertEquals(3, count($parts)); - $this->assertContains('AND', $parts[1]); - $this->assertNotContains('OR', $parts[1]); - } - - public function testCanPassPredicatesAndDefaultCombinationViaConstructor() + /** + * @param type $data + * @dataProvider dataProvider + */ + public function test($sqlObject, $platform, $expected) { - $predicateSet = new PredicateSet([ - new IsNull('foo'), - new IsNull('bar'), - ], 'OR'); - $parts = $this->builder->getExpressionData($predicateSet, $this->context); - $this->assertEquals(3, count($parts)); - $this->assertContains('OR', $parts[1]); - $this->assertNotContains('AND', $parts[1]); + $this->assertBuilder($sqlObject, $platform, $expected); } - public function testCanPassBothPredicateAndCombinationToAddPredicate() + public function dataProvider() { - $this->expression->addPredicate(new IsNull('foo'), 'OR') - ->addPredicate(new IsNull('bar'), 'AND') - ->addPredicate(new IsNull('baz'), 'OR') - ->addPredicate(new IsNull('bat'), 'AND'); - $parts = $this->builder->getExpressionData($this->expression, $this->context); - $this->assertEquals(7, count($parts)); - - $this->assertNotContains('OR', $parts[1], var_export($parts, 1)); - $this->assertContains('AND', $parts[1]); - - $this->assertContains('OR', $parts[3]); - $this->assertNotContains('AND', $parts[3]); - - $this->assertNotContains('OR', $parts[5]); - $this->assertContains('AND', $parts[5]); - } - - public function testCanUseOrPredicateAndAndPredicateMethods() - { - $this->expression->orPredicate(new IsNull('foo')) - ->andPredicate(new IsNull('bar')) - ->orPredicate(new IsNull('baz')) - ->andPredicate(new IsNull('bat')); - $parts = $this->builder->getExpressionData($this->expression, $this->context); - $this->assertEquals(7, count($parts)); - - $this->assertNotContains('OR', $parts[1], var_export($parts, 1)); - $this->assertContains('AND', $parts[1]); - - $this->assertContains('OR', $parts[3]); - $this->assertNotContains('AND', $parts[3]); - - $this->assertNotContains('OR', $parts[5]); - $this->assertContains('AND', $parts[5]); + return $this->prepareDataProvider([ + [ + 'sqlObject' => $this->predicate_PredicateSet() + ->addPredicate($this->predicate_IsNull('foo')) + ->addPredicate($this->predicate_IsNull('bar')), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo" IS NULL AND "bar" IS NULL', + 'prepare' => '"foo" IS NULL AND "bar" IS NULL', + 'parameters' => [], + ], + ], + ], + [ + 'sqlObject' => $this->predicate_PredicateSet( + [ + $this->predicate_IsNull('foo'), + $this->predicate_IsNull('bar'), + ], + 'OR' + ), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo" IS NULL OR "bar" IS NULL', + 'prepare' => '"foo" IS NULL OR "bar" IS NULL', + 'parameters' => [], + ], + ], + ], + [ + 'sqlObject' => $this->predicate_PredicateSet() + ->addPredicate($this->predicate_IsNull('foo'), 'OR') + ->addPredicate($this->predicate_IsNull('bar'), 'AND') + ->addPredicate($this->predicate_IsNull('baz'), 'OR') + ->addPredicate($this->predicate_IsNull('bat'), 'AND'), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo" IS NULL AND "bar" IS NULL OR "baz" IS NULL AND "bat" IS NULL', + 'prepare' => '"foo" IS NULL AND "bar" IS NULL OR "baz" IS NULL AND "bat" IS NULL', + 'parameters' => [], + ], + ], + ], + [ + 'sqlObject' => $this->predicate_PredicateSet() + ->orPredicate($this->predicate_IsNull('foo')) + ->andPredicate($this->predicate_IsNull('bar')) + ->orPredicate($this->predicate_IsNull('baz')) + ->andPredicate($this->predicate_IsNull('bat')), + 'expected' => [ + 'sql92' => [ + 'string' => '"foo" IS NULL AND "bar" IS NULL OR "baz" IS NULL AND "bat" IS NULL', + 'prepare' => '"foo" IS NULL AND "bar" IS NULL OR "baz" IS NULL AND "bat" IS NULL', + 'parameters' => [], + ], + ], + ], + [ + 'sqlObject' => function () { + $select = $this->select()->from('x'); + $select->where->like('bar', 'Foo%'); + return $this->predicate_PredicateSet([ + $this->predicate_PredicateSet([ + $this->predicate_In('x', $select) + ]) + ]); + }, + 'expected' => [ + 'sql92' => [ + 'string' => '("x" IN (SELECT "x".* FROM "x" WHERE "bar" LIKE \'Foo%\'))', + 'prepare' => '("x" IN (SELECT "x".* FROM "x" WHERE "bar" LIKE ?))', + 'parameters' => [ + 'subselect1expr1' => 'Foo%', + ], + ], + ], + ], + [ + 'sqlObject' => $this->predicate_PredicateSet([ + $this->predicate_PredicateSet([ + $this->predicate_Expression('x = ?', 5) + ]) + ]), + 'expected' => [ + 'sql92' => [ + 'string' => "(x = '5')", + 'prepare' => '(x = ?)', + 'parameters' => [ + 'expr1' => 5, + ], + ], + ], + ], + ]); } } diff --git a/test/Sql/Builder/SelectBuilderTest.php b/test/Sql/Builder/SelectBuilderTest.php index 03ec5bfe13..7a21457e38 100644 --- a/test/Sql/Builder/SelectBuilderTest.php +++ b/test/Sql/Builder/SelectBuilderTest.php @@ -14,6 +14,13 @@ use Zend\Db\Sql\Predicate; use Zend\Db\Sql\TableIdentifier; +/** + * @covers Zend\Db\Sql\Builder\IbmDb2\SelectBuilder + * @covers Zend\Db\Sql\Builder\Mysql\SelectBuilder + * @covers Zend\Db\Sql\Builder\Oracle\SelectBuilder + * @covers Zend\Db\Sql\Builder\SqlServer\SelectBuilder + * @covers Zend\Db\Sql\Builder\sql92\SelectBuilder + */ class SelectBuilderTest extends AbstractTestCase { /** @@ -28,577 +35,704 @@ public function test($sqlObject, $platform, $expected) public function dataProvider() { return $this->prepareDataProvider( - $this->dataProvider_SQL92(), - $this->dataProvider_SqlServer(), - $this->dataProvider_Oracle(), - $this->dataProvider_Mysql(), - $this->dataProvider_IbmDb2(), - $this->dataProvider_ForDifferentAdapters() + $this->dataProvider_Columns(), + $this->dataProvider_Combine(), + $this->dataProvider_GroupBy(), + $this->dataProvider_Having(), + $this->dataProvider_Join(), + $this->dataProvider_LimitOffset(), + $this->dataProvider_Order(), + $this->dataProvider_Quantitifier(), + $this->dataProvider_SubSelects(), + $this->dataProvider_Table(), + $this->dataProvider_Where() ); } - /** - * ZendTest\Db\Sql::testForDifferentAdapters() - */ - public function dataProvider_ForDifferentAdapters() + public function dataProvider_Columns() { - $select = $this->select('foo')->offset(10); return [ - [ - 'sqlObject' => $select, + [ // columns + 'sqlObject' => $this->select()->from('foo')->columns(['bar', 'baz']), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" OFFSET \'10\'', - 'prepare' => 'SELECT "foo".* FROM "foo" OFFSET ?', + 'string' => 'SELECT "foo"."bar" AS "bar", "foo"."baz" AS "baz" FROM "foo"', + 'prepare' => true, ], ], ], - [ - 'sqlObject' => $select, + [ // columns with AS associative array + 'sqlObject' => $this->select()->from('foo')->columns(['bar' => 'baz']), 'expected' => [ - 'MySql' => [ - 'string' => 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET 10', - 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET ?', + 'sql92' => [ + 'string' => 'SELECT "foo"."baz" AS "bar" FROM "foo"', + 'prepare' => true, ], ], ], - [ - 'sqlObject' => $select, + [ // columns with AS associative array mixed + 'sqlObject' => $this->select()->from('foo')->columns(['bar' => 'baz', 'bam']), 'expected' => [ - 'Oracle' => [ - 'string' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b ) WHERE b_rownum > (10)', - 'prepare' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b ) WHERE b_rownum > (:offset)', + 'sql92' => [ + 'string' => 'SELECT "foo"."baz" AS "bar", "foo"."bam" AS "bam" FROM "foo"', + 'prepare' => true, ], ], ], - [ - 'sqlObject' => $select, + [ // columns where value is Expression, with AS + 'sqlObject' => $this->select()->from('foo')->columns(['bar' => new Expression('COUNT(some_column)')]), 'expected' => [ - 'SqlServer' => [ - 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 10+1 AND 0+10', - 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', + 'sql92' => [ + 'string' => 'SELECT COUNT(some_column) AS "bar" FROM "foo"', + 'prepare' => true, ], ], ], - ]; - } - - public function dataProvider_IbmDb2() - { - return [ - [ - 'sqlObject' => $this->select()->from(['x' => 'foo'])->limit(5), + [ // columns where value is Expression + 'sqlObject' => $this->select()->from('foo')->columns([new Expression('COUNT(some_column) AS bar')]), 'expected' => [ - 'IbmDb2' => [ - 'string' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 0 AND 5', - 'prepare' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', - 'parameters' => ['offset' => 0, 'limit' => 5], + 'sql92' => [ + 'string' => 'SELECT COUNT(some_column) AS bar FROM "foo"', + 'prepare' => true, ], ], ], [ - 'sqlObject' => $this->select()->from(['x' => 'foo'])->limit(5)->offset(10), + 'sqlObject' => $this->select() + ->from('foo') + ->columns( + [ + new Expression( + '(COUNT(?) + ?) AS ?', + [ + ['some_column', Expression::TYPE_IDENTIFIER], + [5, Expression::TYPE_VALUE], + ['bar', Expression::TYPE_IDENTIFIER], + ] + ) + ] + ), 'expected' => [ - 'IbmDb2' => [ - 'string' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 11 AND 15', - 'prepare' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', - 'parameters' => ['offset' => 11, 'limit' => 15], + 'sql92' => [ + 'string' => 'SELECT (COUNT("some_column") + \'5\') AS "bar" FROM "foo"', + 'prepare' => 'SELECT (COUNT("some_column") + ?) AS "bar" FROM "foo"', ], ], ], [ - 'sqlObject' => $this->select()->columns([new Expression('DISTINCT(id) as id')])->from(['x' => 'foo'])->limit(5)->offset(10), + 'sqlObject' => $this->select()->from(['x' => 'foo'])->columns(['bar' => 'foo.bar'], false), 'expected' => [ - 'IbmDb2' => [ - 'string' => 'SELECT DISTINCT(id) as id FROM ( SELECT DISTINCT(id) as id, DENSE_RANK() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 11 AND 15', - 'prepare' => 'SELECT DISTINCT(id) as id FROM ( SELECT DISTINCT(id) as id, DENSE_RANK() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', - 'parameters' => ['offset' => 11, 'limit' => 15], + 'sql92' => [ + 'string' => 'SELECT "foo"."bar" AS "bar" FROM "foo" AS "x"', + 'prepare' => 'SELECT "foo"."bar" AS "bar" FROM "foo" AS "x"', ], ], ], - [ - 'sqlObject' => function () { - $select = $this->select()->from(['x' => 'foo'])->limit(5)->offset(10); - $select->where->greaterThan('x.id', '10')->AND->lessThan('x.id', '31'); - return $select; - }, + [ // @author robertbasic // @link https://github.com/zendframework/zf2/pull/2714 + 'sqlObject' => $this->select()->from('foo')->columns(['bar'], false), 'expected' => [ - 'IbmDb2' => [ - 'string' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" WHERE "x"."id" > \'10\' AND "x"."id" < \'31\' ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 11 AND 15', - 'prepare' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" WHERE "x"."id" > ? AND "x"."id" < ? ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', - 'parameters' => ['expr1' => '10', 'expr2' => '31', 'offset' => 11, 'limit' => 15], + 'sql92' => [ + 'string' => 'SELECT "bar" AS "bar" FROM "foo"', + 'prepare' => true, ], ], ], [ - 'sqlObject' => function () { - $select = $this->select()->from(['x' => 'foo'])->limit(5); - $select->where->greaterThan('x.id', '10')->AND->lessThan('x.id', '31'); - return $select; - }, + 'sqlObject' => $this->select('table')->columns(['*']), 'expected' => [ - 'IbmDb2' => [ - 'string' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" WHERE "x"."id" > \'10\' AND "x"."id" < \'31\' ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 0 AND 5', - 'prepare' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" WHERE "x"."id" > ? AND "x"."id" < ? ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', - 'parameters' => ['expr1' => '10', 'expr2' => '31', 'offset' => 0, 'limit' => 5], + 'sql92' => [ + 'string' => 'SELECT "table".* FROM "table"', ], ], ], ]; } - public function dataProvider_Mysql() + public function dataProvider_Combine() { return [ [ - 'sqlObject' => $this->select()->from('foo')->limit(5)->offset(10), - 'expected' => [ - 'Mysql' => [ - 'string' => 'SELECT `foo`.* FROM `foo` LIMIT 5 OFFSET 10', - 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT ? OFFSET ?', - 'parameters' => ['limit' => 5, 'offset' => 10], - ], - ], - ], - [ - 'sqlObject' => $this->select()->from('foo')->offset(10), - 'expected' => [ - 'Mysql' => [ - 'string' => 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET 10', - 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET ?', - 'parameters' => ['offset' => 10], - ], - ], - ], - [ - 'sqlObject' => $this->select()->from('foo')->limit('5')->offset('10000000000000000000'), + 'sqlObject' => $this->select() + ->from('foo') + ->where('a = b') + ->combine( + $this->select()->from('bar')->where('c = d'), + Select::COMBINE_UNION, + 'ALL' + ), 'expected' => [ - 'Mysql' => [ - 'string' => 'SELECT `foo`.* FROM `foo` LIMIT 5 OFFSET 10000000000000000000', - 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT ? OFFSET ?', - 'parameters' => ['limit' => '5', 'offset' => '10000000000000000000'], + 'sql92' => [ + 'string' => '( SELECT "foo".* FROM "foo" WHERE a = b ) UNION ALL ( SELECT "bar".* FROM "bar" WHERE c = d )', + 'prepare' => true, ], ], ], - ]; - } - - public function dataProvider_Oracle() - { - return [ - [ - 'sqlObject' => $this->select()->from(['x' => 'foo']), + [ // combine and union with order at the end + 'sqlObject' => $this->select() + ->from([ + 'sub' => $this->select() + ->from('foo') + ->where('a = b') + ->combine( + $this->select()->from('bar')->where('c = d') + ) + ]) + ->order('id DESC'), 'expected' => [ - 'Oracle' => [ - 'string' => 'SELECT "x".* FROM "foo" "x"', - 'prepare' => true, - 'parameters' => [], + 'sql92' => [ + 'string' => 'SELECT "sub".* FROM (( SELECT "foo".* FROM "foo" WHERE a = b ) UNION ( SELECT "bar".* FROM "bar" WHERE c = d )) AS "sub" ORDER BY "id" DESC', + 'prepare' => true, ], ], ], - [ - 'sqlObject' => $this->select(['b' => $this->select(['a' => $this->select('test')])]), + [ // Combine + 'sqlObject' => $this->select() + ->from(['foo'=>$this->combine($this->select('bar0'))]) + ->columns(['c1'=>$this->combine($this->select('bar1'))]) + ->where(['c2'=>$this->combine($this->select('bar2'))]) + ->join(['c3'=>$this->combine($this->select('bar3'))], 'xx=yy'), 'expected' => [ - 'Oracle' => [ - 'string' => 'SELECT "b".* FROM (SELECT "a".* FROM (SELECT "test".* FROM "test") "a") "b"', - 'prepare' => true, - 'parameters' => [], + 'sql92' => [ + 'string' => 'SELECT ((SELECT "bar1".* FROM "bar1")) AS "c1", "c3".* FROM ((SELECT "bar0".* FROM "bar0")) AS "foo" INNER JOIN ((SELECT "bar3".* FROM "bar3")) AS "c3" ON "xx"="yy" WHERE "c2" = ((SELECT "bar2".* FROM "bar2"))', ], ], ], ]; } - public function dataProvider_SqlServer() + public function dataProvider_GroupBy() { return [ - [ - 'sqlObject' => $this->select()->from('foo')->columns(['bar', 'baz'])->order('bar')->limit(5)->offset(10), + [ // group + 'sqlObject' => $this->select()->from('foo')->group(['col1', 'col2']), 'expected' => [ - 'SqlServer' => [ - 'string' => 'SELECT [bar], [baz] FROM ( SELECT [foo].[bar] AS [bar], [foo].[baz] AS [baz], ROW_NUMBER() OVER (ORDER BY [bar] ASC) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 10+1 AND 5+10', - 'prepare' => 'SELECT [bar], [baz] FROM ( SELECT [foo].[bar] AS [bar], [foo].[baz] AS [baz], ROW_NUMBER() OVER (ORDER BY [bar] ASC) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', - 'parameters' => ['offset' => 10, 'limit' => 5, 'offsetForSum' => 10], + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" GROUP BY "col1", "col2"', + 'prepare' => true, ], ], ], - [ - 'sqlObject' => $this->select()->from('foo')->columns(['bar', 'bam' => 'baz'])->limit(5)->offset(10), + [ // group + 'sqlObject' => $this->select()->from('foo')->group('col1')->group('col2'), 'expected' => [ - 'SqlServer' => [ - 'string' => 'SELECT [bar], [bam] FROM ( SELECT [foo].[bar] AS [bar], [foo].[baz] AS [bam], ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 10+1 AND 5+10', - 'prepare' => 'SELECT [bar], [bam] FROM ( SELECT [foo].[bar] AS [bar], [foo].[baz] AS [bam], ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', - 'parameters' => ['offset' => 10, 'limit' => 5, 'offsetForSum' => 10], + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" GROUP BY "col1", "col2"', + 'prepare' => true, ], ], ], - [ - 'sqlObject' => $this->select()->from('foo')->order('bar')->limit(5)->offset(10), + [ // group + 'sqlObject' => $this->select()->from('foo')->group(new Expression('DAY(?)', [['col1', Expression::TYPE_IDENTIFIER]])), 'expected' => [ - 'SqlServer' => [ - 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY [bar] ASC) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 10+1 AND 5+10', - 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY [bar] ASC) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', - 'parameters' => ['offset' => 10, 'limit' => 5, 'offsetForSum' => 10], + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" GROUP BY DAY("col1")', + 'prepare' => true, ], ], ], - [ - 'sqlObject' => $this->select()->from('foo'), + [ // group with compound name + 'sqlObject' => $this->select()->from('foo')->group('c1.d2'), 'expected' => [ - 'SqlServer' => [ - 'string' => 'SELECT [foo].* FROM [foo]', - 'prepare' => true, - 'parameters' => [], + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" GROUP BY "c1"."d2"', + 'prepare' => true, ], ], ], ]; } - public function dataProvider_SQL92() + public function dataProvider_Having() { return [ - [ //testSelectUsingTableIdentifierWithEmptyScheme() - 'sqlObject' => $this->select() - ->from(new TableIdentifier('foo')) - ->join(new TableIdentifier('bar'), 'foo.id = bar.fooid'), + [ // having (simple string) + 'sqlObject' => $this->select()->from('foo')->having('x = 5'), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".*, "bar".* FROM "foo" INNER JOIN "bar" ON "foo"."id" = "bar"."fooid"', + 'string' => 'SELECT "foo".* FROM "foo" HAVING x = 5', + 'prepare' => true, ], ], ], - [ //basic table - 'sqlObject' => $this->select()->from('foo'), + [ // having (returning parameters) + 'sqlObject' => $this->select()->from('foo')->having(['x = ?' => 5]), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo"', - 'prepare' => true, + 'string' => 'SELECT "foo".* FROM "foo" HAVING x = \'5\'', + 'prepare' => 'SELECT "foo".* FROM "foo" HAVING x = ?', + 'parameters' => ['expr1' => 5], ], ], ], - [ // table as TableIdentifier - 'sqlObject' => $this->select()->from(new TableIdentifier('foo', 'bar')), + ]; + } + + public function dataProvider_Join() + { + return [ + [ // joins (plain) + 'sqlObject' => $this->select()->from('foo')->join('zac', 'm = n'), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "bar"."foo".* FROM "bar"."foo"', + 'string' => 'SELECT "foo".*, "zac".* FROM "foo" INNER JOIN "zac" ON "m" = "n"', 'prepare' => true, ], ], ], - [ // table with alias - 'sqlObject' => $this->select()->from(['f' => 'foo']), + [ // join with columns + 'sqlObject' => $this->select()->from('foo')->join('zac', 'm = n', ['bar', 'baz']), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "f".* FROM "foo" AS "f"', + 'string' => 'SELECT "foo".*, "zac"."bar" AS "bar", "zac"."baz" AS "baz" FROM "foo" INNER JOIN "zac" ON "m" = "n"', 'prepare' => true, ], ], ], - [ // table with alias with table as TableIdentifier - 'sqlObject' => $this->select()->from(['f' => new TableIdentifier('foo')]), + [ // join with alternate type + 'sqlObject' => $this->select()->from('foo')->join('zac', 'm = n', ['bar', 'baz'], Select::JOIN_OUTER), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "f".* FROM "foo" AS "f"', + 'string' => 'SELECT "foo".*, "zac"."bar" AS "bar", "zac"."baz" AS "baz" FROM "foo" OUTER JOIN "zac" ON "m" = "n"', 'prepare' => true, ], ], ], - [ // columns - 'sqlObject' => $this->select()->from('foo')->columns(['bar', 'baz']), + [ // join with column aliases + 'sqlObject' => $this->select()->from('foo')->join('zac', 'm = n', ['BAR' => 'bar', 'BAZ' => 'baz']), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo"."bar" AS "bar", "foo"."baz" AS "baz" FROM "foo"', + 'string' => 'SELECT "foo".*, "zac"."bar" AS "BAR", "zac"."baz" AS "BAZ" FROM "foo" INNER JOIN "zac" ON "m" = "n"', 'prepare' => true, ], ], ], - [ // columns with AS associative array - 'sqlObject' => $this->select()->from('foo')->columns(['bar' => 'baz']), + [ // join with table aliases + 'sqlObject' => $this->select()->from('foo')->join(['b' => 'bar'], 'b.foo_id = foo.foo_id'), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo"."baz" AS "bar" FROM "foo"', + 'string' => 'SELECT "foo".*, "b".* FROM "foo" INNER JOIN "bar" AS "b" ON "b"."foo_id" = "foo"."foo_id"', 'prepare' => true, ], ], ], - [ // columns with AS associative array mixed - 'sqlObject' => $this->select()->from('foo')->columns(['bar' => 'baz', 'bam']), + [ // joins with a few keywords in the on clause + 'sqlObject' => $this->select()->from('foo')->join('zac', '(m = n AND c.x) BETWEEN x AND y.z OR (c.x < y.z AND c.x <= y.z AND c.x > y.z AND c.x >= y.z)'), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo"."baz" AS "bar", "foo"."bam" AS "bam" FROM "foo"', + 'string' => 'SELECT "foo".*, "zac".* FROM "foo" INNER JOIN "zac" ON ("m" = "n" AND "c"."x") BETWEEN "x" AND "y"."z" OR ("c"."x" < "y"."z" AND "c"."x" <= "y"."z" AND "c"."x" > "y"."z" AND "c"."x" >= "y"."z")', 'prepare' => true, ], ], ], - [ // columns where value is Expression, with AS - 'sqlObject' => $this->select()->from('foo')->columns(['bar' => new Expression('COUNT(some_column)')]), + [ // join with expression in ON part + 'sqlObject' => $this->select()->from('foo')->join('zac', new Expression('(m = n AND c.x) BETWEEN x AND y.z')), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT COUNT(some_column) AS "bar" FROM "foo"', + 'string' => 'SELECT "foo".*, "zac".* FROM "foo" INNER JOIN "zac" ON (m = n AND c.x) BETWEEN x AND y.z', 'prepare' => true, ], ], ], - [ // columns where value is Expression - 'sqlObject' => $this->select()->from('foo')->columns([new Expression('COUNT(some_column) AS bar')]), + [ // join with Expression object in COLUMNS part (ZF2-514) // @co-author Koen Pieters (kpieters) + 'sqlObject' => $this->select()->from('foo')->columns([])->join('bar', 'm = n', ['thecount' => new Expression("COUNT(*)")]), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT COUNT(some_column) AS bar FROM "foo"', + 'string' => 'SELECT COUNT(*) AS "thecount" FROM "foo" INNER JOIN "bar" ON "m" = "n"', 'prepare' => true, ], ], ], - [ + [ // multiple joins with expressions // reported by @jdolieslager 'sqlObject' => $this->select() ->from('foo') - ->columns( - [ - new Expression( - '(COUNT(?) + ?) AS ?', - [ - ['some_column', Expression::TYPE_IDENTIFIER], - [5, Expression::TYPE_VALUE], - ['bar', Expression::TYPE_IDENTIFIER], - ] - ) - ] - ), + ->join('tableA', new Predicate\Operator('id', '=', 1)) + ->join('tableB', new Predicate\Operator('id', '=', 2)) + ->join('tableC', new Predicate\PredicateSet([ + new Predicate\Operator('id', '=', 3), + new Predicate\Operator('number', '>', 20) + ])), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT (COUNT("some_column") + \'5\') AS "bar" FROM "foo"', - 'prepare' => 'SELECT (COUNT("some_column") + ?) AS "bar" FROM "foo"', + 'string' => 'SELECT "foo".*, "tableA".*, "tableB".*, "tableC".* FROM "foo" ' + . 'INNER JOIN "tableA" ON "id" = \'1\' INNER JOIN "tableB" ON "id" = \'2\' ' + . 'INNER JOIN "tableC" ON "id" = \'3\' AND "number" > \'20\'', + 'prepare' => 'SELECT "foo".*, "tableA".*, "tableB".*, "tableC".* FROM "foo"' + . ' INNER JOIN "tableA" ON "id" = :join1expr1 INNER JOIN "tableB" ON "id" = :join2expr1 ' + . 'INNER JOIN "tableC" ON "id" = :join3expr1 AND "number" > :join3expr2', + 'useNamedParams' => true, ], ], ], - [ // joins (plain) - 'sqlObject' => $this->select()->from('foo')->join('zac', 'm = n'), + [ //Expression as joinName + 'sqlObject' => $this->select() + ->from(new TableIdentifier('foo')) + ->join(['bar' => new Expression('psql_function_which_returns_table')], 'foo.id = bar.fooid'), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".*, "zac".* FROM "foo" INNER JOIN "zac" ON "m" = "n"', + 'string' => 'SELECT "foo".*, "bar".* FROM "foo" INNER JOIN psql_function_which_returns_table AS "bar" ON "foo"."id" = "bar"."fooid"', 'prepare' => true, ], ], ], - [ // join with columns - 'sqlObject' => $this->select()->from('foo')->join('zac', 'm = n', ['bar', 'baz']), + [ // @author Andrzej Lewandowski @link https://github.com/zendframework/zf2/issues/7222 + 'sqlObject' => $this->select()->from('foo')->join('zac', '(catalog_category_website.category_id = catalog_category.category_id)'), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".*, "zac"."bar" AS "bar", "zac"."baz" AS "baz" FROM "foo" INNER JOIN "zac" ON "m" = "n"', + 'string' => 'SELECT "foo".*, "zac".* FROM "foo" INNER JOIN "zac" ON ("catalog_category_website"."category_id" = "catalog_category"."category_id")', 'prepare' => true, ], ], ], - [ // join with alternate type - 'sqlObject' => $this->select()->from('foo')->join('zac', 'm = n', ['bar', 'baz'], Select::JOIN_OUTER), + 'Select::processJoin()' => [ + 'sqlObject' => $this->select('a')->join(['b'=>$this->select('c')->where(['cc'=>10])], 'd=e')->where(['x'=>20]), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".*, "zac"."bar" AS "bar", "zac"."baz" AS "baz" FROM "foo" OUTER JOIN "zac" ON "m" = "n"', - 'prepare' => true, + 'string' => 'SELECT "a".*, "b".* FROM "a" INNER JOIN (SELECT "c".* FROM "c" WHERE "cc" = \'10\') AS "b" ON "d"="e" WHERE "x" = \'20\'', + 'prepare' => 'SELECT "a".*, "b".* FROM "a" INNER JOIN (SELECT "c".* FROM "c" WHERE "cc" = ?) AS "b" ON "d"="e" WHERE "x" = ?', + 'parameters' => ['subselect1expr1'=>10, 'expr1'=>20], ], - ], - ], - [ // join with column aliases - 'sqlObject' => $this->select()->from('foo')->join('zac', 'm = n', ['BAR' => 'bar', 'BAZ' => 'baz']), - 'expected' => [ - 'sql92' => [ - 'string' => 'SELECT "foo".*, "zac"."bar" AS "BAR", "zac"."baz" AS "BAZ" FROM "foo" INNER JOIN "zac" ON "m" = "n"', - 'prepare' => true, + 'MySql' => [ + 'string' => 'SELECT `a`.*, `b`.* FROM `a` INNER JOIN (SELECT `c`.* FROM `c` WHERE `cc` = \'10\') AS `b` ON `d`=`e` WHERE `x` = \'20\'', + 'prepare' => 'SELECT `a`.*, `b`.* FROM `a` INNER JOIN (SELECT `c`.* FROM `c` WHERE `cc` = ?) AS `b` ON `d`=`e` WHERE `x` = ?', + 'parameters' => ['subselect1expr1'=>10, 'expr1'=>20], ], - ], - ], - [ // join with table aliases - 'sqlObject' => $this->select()->from('foo')->join(['b' => 'bar'], 'b.foo_id = foo.foo_id'), - 'expected' => [ - 'sql92' => [ - 'string' => 'SELECT "foo".*, "b".* FROM "foo" INNER JOIN "bar" AS "b" ON "b"."foo_id" = "foo"."foo_id"', - 'prepare' => true, + 'Oracle' => [ + 'string' => 'SELECT "a".*, "b".* FROM "a" INNER JOIN (SELECT "c".* FROM "c" WHERE "cc" = \'10\') "b" ON "d"="e" WHERE "x" = \'20\'', + 'prepare' => 'SELECT "a".*, "b".* FROM "a" INNER JOIN (SELECT "c".* FROM "c" WHERE "cc" = ?) "b" ON "d"="e" WHERE "x" = ?', + 'parameters' => ['subselect1expr1'=>10, 'expr1'=>20], ], - ], - ], - [ // where (simple string) - 'sqlObject' => $this->select()->from('foo')->where('x = 5'), - 'expected' => [ - 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" WHERE x = 5', - 'prepare' => true, + 'SqlServer' => [ + 'string' => 'SELECT [a].*, [b].* FROM [a] INNER JOIN (SELECT [c].* FROM [c] WHERE [cc] = \'10\') AS [b] ON [d]=[e] WHERE [x] = \'20\'', + 'prepare' => 'SELECT [a].*, [b].* FROM [a] INNER JOIN (SELECT [c].* FROM [c] WHERE [cc] = ?) AS [b] ON [d]=[e] WHERE [x] = ?', + 'parameters' => ['subselect1expr1'=>10, 'expr1'=>20], ], ], ], - [ // where (returning parameters) - 'sqlObject' => $this->select()->from('foo')->where(['x = ?' => 5]), - 'expected' => [ + // Github issue https://github.com/zendframework/zend-db/issues/98 + 'Select::processJoinNoJoinedColumns()' => [ + 'sqlObject' => $this->select('my_table') + ->join('joined_table2', 'my_table.id = joined_table2.id', $columns=[]) + ->join('joined_table3', 'my_table.id = joined_table3.id', [\Zend\Db\Sql\Select::SQL_STAR]) + ->columns([ + 'my_table_column', + 'aliased_column' => new \Zend\Db\Sql\Expression('NOW()') + ]), + 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" WHERE x = \'5\'', - 'prepare' => 'SELECT "foo".* FROM "foo" WHERE x = ?', - 'parameters' => ['expr1' => 5], + 'string' => 'SELECT "my_table"."my_table_column" AS "my_table_column", NOW() AS "aliased_column", "joined_table3".* FROM "my_table" INNER JOIN "joined_table2" ON "my_table"."id" = "joined_table2"."id" INNER JOIN "joined_table3" ON "my_table"."id" = "joined_table3"."id"', ], - ], - ], - [ // group - 'sqlObject' => $this->select()->from('foo')->group(['col1', 'col2']), - 'expected' => [ - 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" GROUP BY "col1", "col2"', - 'prepare' => true, + 'MySql' => [ + 'string' => 'SELECT `my_table`.`my_table_column` AS `my_table_column`, NOW() AS `aliased_column`, `joined_table3`.* FROM `my_table` INNER JOIN `joined_table2` ON `my_table`.`id` = `joined_table2`.`id` INNER JOIN `joined_table3` ON `my_table`.`id` = `joined_table3`.`id`', ], - ], + 'Oracle' => [ + 'string' => 'SELECT "my_table"."my_table_column" AS "my_table_column", NOW() AS "aliased_column", "joined_table3".* FROM "my_table" INNER JOIN "joined_table2" ON "my_table"."id" = "joined_table2"."id" INNER JOIN "joined_table3" ON "my_table"."id" = "joined_table3"."id"', + ], + 'SqlServer' => [ + 'string' => 'SELECT [my_table].[my_table_column] AS [my_table_column], NOW() AS [aliased_column], [joined_table3].* FROM [my_table] INNER JOIN [joined_table2] ON [my_table].[id] = [joined_table2].[id] INNER JOIN [joined_table3] ON [my_table].[id] = [joined_table3].[id]', + ] + ] ], - [ // group - 'sqlObject' => $this->select()->from('foo')->group('col1')->group('col2'), + ]; + } + + public function dataProvider_LimitOffset() + { + return [ + 'Offset0' => [ + 'sqlObject' => $this->select('foo')->offset(0), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" GROUP BY "col1", "col2"', - 'prepare' => true, + 'string' => 'SELECT "foo".* FROM "foo" OFFSET \'0\'', + 'prepare' => 'SELECT "foo".* FROM "foo" OFFSET ?', + 'parameters' => ['offset' => 0], + ], + 'MySql' => [ + 'string' => 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET 0', + 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET ?', + 'parameters' => ['offset' => 0], + ], + 'Oracle' => [ + 'string' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b ) WHERE b_rownum > (0)', + 'prepare' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b ) WHERE b_rownum > (:offset)', + 'parameters' => ['offset' => 0], + ], + 'SqlServer' => [ + 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 0+1 AND 0+0', + 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', + 'parameters' => ['offset' => 0, 'limit' => null, 'offsetForSum' => 0], ], ], ], - [ // group - 'sqlObject' => $this->select()->from('foo')->group(new Expression('DAY(?)', [['col1', Expression::TYPE_IDENTIFIER]])), + 'Limit0' => [ + 'sqlObject' => $this->select()->from('foo')->limit(0), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" GROUP BY DAY("col1")', - 'prepare' => true, + 'string' => 'SELECT "foo".* FROM "foo" LIMIT \'0\'', + 'prepare' => 'SELECT "foo".* FROM "foo" LIMIT ?', + 'parameters' => ['limit' => 0], + ], + 'MySql' => [ + 'string' => 'SELECT `foo`.* FROM `foo` LIMIT 0', + 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT ?', + 'parameters' => ['limit' => 0], + ], + 'IbmDb2' => [ + 'string' => 'SELECT * FROM ( SELECT "foo".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 0 AND 0', + 'prepare' => 'SELECT * FROM ( SELECT "foo".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', + 'parameters' => ['offset' => 0, 'limit' => 0], + ], + 'Oracle' => [ + 'string' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (0+0)) WHERE b_rownum >= (0 + 1)', + 'prepare' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (:offset+:limit)) WHERE b_rownum >= (:offset + 1)', + 'parameters' => ['offset' => 0, 'limit' => 0], + ], + 'SqlServer' => [ + 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 0+1 AND 0+0', + 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', + 'parameters' => ['offset' => null, 'limit' => 0, 'offsetForSum' => null], ], ], ], - [ // having (simple string) - 'sqlObject' => $this->select()->from('foo')->having('x = 5'), + 'Offset10' => [ + 'sqlObject' => $this->select('foo')->offset(10), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" HAVING x = 5', - 'prepare' => true, + 'string' => 'SELECT "foo".* FROM "foo" OFFSET \'10\'', + 'prepare' => 'SELECT "foo".* FROM "foo" OFFSET ?', + 'parameters' => ['offset' => 10], + ], + 'MySql' => [ + 'string' => 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET 10', + 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET ?', + 'parameters' => ['offset' => 10], + ], + 'Oracle' => [ + 'string' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b ) WHERE b_rownum > (10)', + 'prepare' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b ) WHERE b_rownum > (:offset)', + 'parameters' => ['offset' => 10], + ], + 'SqlServer' => [ + 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 10+1 AND 0+10', + 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', + 'parameters' => ['offset' => 10, 'limit' => null, 'offsetForSum' => 10], ], ], ], - [ // having (returning parameters) - 'sqlObject' => $this->select()->from('foo')->having(['x = ?' => 5]), + 'Offset10_Limit0' => [ + 'sqlObject' => $this->select('foo')->offset(10)->limit(0), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" HAVING x = \'5\'', - 'prepare' => 'SELECT "foo".* FROM "foo" HAVING x = ?', - 'parameters' => ['expr1' => 5], + 'string' => 'SELECT "foo".* FROM "foo" LIMIT \'0\' OFFSET \'10\'', + 'prepare' => 'SELECT "foo".* FROM "foo" LIMIT ? OFFSET ?', + 'parameters' => ['limit' => 0, 'offset' => 10], + ], + 'MySql' => [ + 'string' => 'SELECT `foo`.* FROM `foo` LIMIT 0 OFFSET 10', + 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT ? OFFSET ?', + 'parameters' => ['limit' => 0, 'offset' => 10], + ], + 'Oracle' => [ + 'string' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (10+0)) WHERE b_rownum >= (10 + 1)', + 'prepare' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (:offset+:limit)) WHERE b_rownum >= (:offset + 1)', + 'parameters' => ['offset' => 10, 'limit' => 0], + ], + 'SqlServer' => [ + 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 10+1 AND 0+10', + 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', + 'parameters' => ['offset' => 10, 'limit' => 0, 'offsetForSum' => 10], ], ], ], - [ // order - 'sqlObject' => $this->select()->from('foo')->order('c1'), + 'Limit10' => [ + 'sqlObject' => $this->select()->from('foo')->limit(10), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" ORDER BY "c1" ASC', - 'prepare' => true, + 'string' => 'SELECT "foo".* FROM "foo" LIMIT \'10\'', + 'prepare' => 'SELECT "foo".* FROM "foo" LIMIT ?', + 'parameters' => ['limit' => 10], + ], + 'MySql' => [ + 'string' => 'SELECT `foo`.* FROM `foo` LIMIT 10', + 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT ?', + 'parameters' => ['limit' => 10], + ], + 'IbmDb2' => [ + 'string' => 'SELECT * FROM ( SELECT "foo".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 0 AND 10', + 'prepare' => 'SELECT * FROM ( SELECT "foo".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', + 'parameters' => ['offset' => 0, 'limit' => 10], + ], + 'Oracle' => [ + 'string' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (0+10)) WHERE b_rownum >= (0 + 1)', + 'prepare' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (:offset+:limit)) WHERE b_rownum >= (:offset + 1)', + 'parameters' => ['offset' => 0, 'limit' => 10], + ], + 'SqlServer' => [ + 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 0+1 AND 10+0', + 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', + 'parameters' => ['offset' => null, 'limit' => 10, 'offsetForSum' => null], ], ], ], - [ // order - 'sqlObject' => $this->select()->from('foo')->order(['c1', 'c2']), + 'Limit10_Offset0' => [ + 'sqlObject' => $this->select('foo')->offset(0)->limit(10), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" ORDER BY "c1" ASC, "c2" ASC', - 'prepare' => true, + 'string' => 'SELECT "foo".* FROM "foo" LIMIT \'10\' OFFSET \'0\'', + 'prepare' => 'SELECT "foo".* FROM "foo" LIMIT ? OFFSET ?', + 'parameters' => ['limit' => 10, 'offset' => 0], + ], + 'MySql' => [ + 'string' => 'SELECT `foo`.* FROM `foo` LIMIT 10 OFFSET 0', + 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT ? OFFSET ?', + 'parameters' => ['limit' => 10, 'offset' => 0], + ], + 'IbmDb2' => [ + 'string' => 'SELECT * FROM ( SELECT "foo".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 0 AND 10', + 'prepare' => 'SELECT * FROM ( SELECT "foo".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', + 'parameters' => ['offset' => 0, 'limit' => 10], + ], + 'Oracle' => [ + 'string' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (0+10)) WHERE b_rownum >= (0 + 1)', + 'prepare' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (:offset+:limit)) WHERE b_rownum >= (:offset + 1)', + 'parameters' => ['offset' => 0, 'limit' => 10], + ], + 'SqlServer' => [ + 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 0+1 AND 10+0', + 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', + 'parameters' => ['offset' => 0, 'limit' => 10, 'offsetForSum' => 0], ], ], ], - [ // order - notice partially lower case ASC - 'sqlObject' => $this->select()->from('foo')->order(['c1' => 'DESC', 'c2' => 'Asc']), + 'Limit10_Offset5' => [ + 'sqlObject' => $this->select('foo')->offset(5)->limit(10), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" ORDER BY "c1" DESC, "c2" ASC', - 'prepare' => true, + 'string' => 'SELECT "foo".* FROM "foo" LIMIT \'10\' OFFSET \'5\'', + 'prepare' => 'SELECT "foo".* FROM "foo" LIMIT ? OFFSET ?', + 'parameters' => ['limit' => 10, 'offset' => 5], + ], + 'MySql' => [ + 'string' => 'SELECT `foo`.* FROM `foo` LIMIT 10 OFFSET 5', + 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT ? OFFSET ?', + 'parameters' => ['limit' => 10, 'offset' => 5], + ], + 'IbmDb2' => [ + 'string' => 'SELECT * FROM ( SELECT "foo".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 6 AND 15', + 'prepare' => 'SELECT * FROM ( SELECT "foo".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', + 'parameters' => ['offset' => 6, 'limit' => 15], + ], + 'Oracle' => [ + 'string' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (5+10)) WHERE b_rownum >= (5 + 1)', + 'prepare' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (:offset+:limit)) WHERE b_rownum >= (:offset + 1)', + 'parameters' => ['offset' => 5, 'limit' => 10], + ], + 'SqlServer' => [ + 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 5+1 AND 10+5', + 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', + 'parameters' => ['offset' => 5, 'limit' => 10, 'offsetForSum' => 5], ], ], ], - [ // order - 'sqlObject' => $this->select()->from('foo')->order(['c1' => 'asc'])->order('c2 desc'), + //================================================================== + 'Limit10_Offset5_WithStringValues' => [ + 'sqlObject' => $this->select()->from('foo')->limit("5")->offset("10"), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" ORDER BY "c1" ASC, "c2" DESC', - 'prepare' => true, + 'string' => 'SELECT "foo".* FROM "foo" LIMIT \'5\' OFFSET \'10\'', + 'prepare' => 'SELECT "foo".* FROM "foo" LIMIT ? OFFSET ?', + 'parametersEquals' => ['limit' => 5, 'offset' => 10], ], ], ], - [ // limit - 'sqlObject' => $this->select()->from('foo')->limit(5), + 'Limit10_Offset5_WithBigStringValues' => [ // limit with big offset and limit + 'sqlObject' => $this->select()->from('foo')->limit("10000000000000000000")->offset("10000000000000000000"), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" LIMIT \'5\'', - 'prepare' => 'SELECT "foo".* FROM "foo" LIMIT ?', - 'parameters' => ['limit' => 5], + 'string' => 'SELECT "foo".* FROM "foo" LIMIT \'10000000000000000000\' OFFSET \'10000000000000000000\'', + 'prepare' => 'SELECT "foo".* FROM "foo" LIMIT ? OFFSET ?', + 'parametersEquals' => ['limit' => 10000000000000000000, 'offset' => 10000000000000000000], + ], + 'Mysql' => [ + 'string' => 'SELECT `foo`.* FROM `foo` LIMIT 10000000000000000000 OFFSET 10000000000000000000', + 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT ? OFFSET ?', + 'parameters' => ['limit' => '10000000000000000000', 'offset' => '10000000000000000000'], ], ], ], - [ // limit with offset - 'sqlObject' => $this->select()->from('foo')->limit(5)->offset(10), + 'LimitOffset_ParametersOrder' => [ + 'sqlObject' => function () { + $select = $this->select()->from(['x' => 'foo'])->limit(5)->offset(10); + $select->where->greaterThan('x.id', '10')->AND->lessThan('x.id', '31'); + return $select; + }, 'expected' => [ - 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" LIMIT \'5\' OFFSET \'10\'', - 'prepare' => 'SELECT "foo".* FROM "foo" LIMIT ? OFFSET ?', - 'parameters' => ['limit' => 5, 'offset' => 10], + 'IbmDb2' => [ + 'string' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" WHERE "x"."id" > \'10\' AND "x"."id" < \'31\' ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 11 AND 15', + 'prepare' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" WHERE "x"."id" > ? AND "x"."id" < ? ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', + 'parameters' => ['expr1' => '10', 'expr2' => '31', 'offset' => 11, 'limit' => 15], ], ], ], - [ // joins with a few keywords in the on clause - 'sqlObject' => $this->select()->from('foo')->join('zac', '(m = n AND c.x) BETWEEN x AND y.z OR (c.x < y.z AND c.x <= y.z AND c.x > y.z AND c.x >= y.z)'), + //================================================================== + // Else + [ + 'sqlObject' => $this->select()->columns([new Expression('DISTINCT(id) as id')])->from(['x' => 'foo'])->limit(5)->offset(10), 'expected' => [ - 'sql92' => [ - 'string' => 'SELECT "foo".*, "zac".* FROM "foo" INNER JOIN "zac" ON ("m" = "n" AND "c"."x") BETWEEN "x" AND "y"."z" OR ("c"."x" < "y"."z" AND "c"."x" <= "y"."z" AND "c"."x" > "y"."z" AND "c"."x" >= "y"."z")', - 'prepare' => true, + 'IbmDb2' => [ + 'string' => 'SELECT DISTINCT(id) as id FROM ( SELECT DISTINCT(id) as id, DENSE_RANK() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 11 AND 15', + 'prepare' => 'SELECT DISTINCT(id) as id FROM ( SELECT DISTINCT(id) as id, DENSE_RANK() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', + 'parameters' => ['offset' => 11, 'limit' => 15], ], ], ], - [ // order with compound name - 'sqlObject' => $this->select()->from('foo')->order('c1.d2'), + ]; + } + + public function dataProvider_Order() + { + return [ + [ // order + 'sqlObject' => $this->select()->from('foo')->order('c1'), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" ORDER BY "c1"."d2" ASC', + 'string' => 'SELECT "foo".* FROM "foo" ORDER BY "c1" ASC', 'prepare' => true, ], ], ], - [ // group with compound name - 'sqlObject' => $this->select()->from('foo')->group('c1.d2'), + [ // order + 'sqlObject' => $this->select()->from('foo')->order(['c1', 'c2']), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" GROUP BY "c1"."d2"', + 'string' => 'SELECT "foo".* FROM "foo" ORDER BY "c1" ASC, "c2" ASC', 'prepare' => true, ], ], ], - [ // join with expression in ON part - 'sqlObject' => $this->select()->from('foo')->join('zac', new Expression('(m = n AND c.x) BETWEEN x AND y.z')), + [ // order - notice partially lower case ASC + 'sqlObject' => $this->select()->from('foo')->order(['c1' => 'DESC', 'c2' => 'Asc']), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".*, "zac".* FROM "foo" INNER JOIN "zac" ON (m = n AND c.x) BETWEEN x AND y.z', + 'string' => 'SELECT "foo".* FROM "foo" ORDER BY "c1" DESC, "c2" ASC', 'prepare' => true, ], ], ], - [ - 'sqlObject' => function () { - $subselect = $this->select(); - $subselect->from('bar')->where->like('y', '%Foo%'); - return $this->select()->from(['x' => $subselect]); - }, + [ // order + 'sqlObject' => $this->select()->from('foo')->order(['c1' => 'asc'])->order('c2 desc'), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "x".* FROM (SELECT "bar".* FROM "bar" WHERE "y" LIKE \'%Foo%\') AS "x"', - 'prepare' => 'SELECT "x".* FROM (SELECT "bar".* FROM "bar" WHERE "y" LIKE ?) AS "x"', + 'string' => 'SELECT "foo".* FROM "foo" ORDER BY "c1" ASC, "c2" DESC', + 'prepare' => true, ], ], ], - [ - 'sqlObject' => $this->select() - ->from('table') - ->columns(['*']) - ->where([ - 'c1' => null, - 'c2' => [1, 2, 3], - new \Zend\Db\Sql\Predicate\IsNotNull('c3') - ]), + [ // order with compound name + 'sqlObject' => $this->select()->from('foo')->order('c1.d2'), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "table".* FROM "table" WHERE "c1" IS NULL AND "c2" IN (\'1\', \'2\', \'3\') AND "c3" IS NOT NULL', - 'prepare' => 'SELECT "table".* FROM "table" WHERE "c1" IS NULL AND "c2" IN (?, ?, ?) AND "c3" IS NOT NULL', + 'string' => 'SELECT "foo".* FROM "foo" ORDER BY "c1"."d2" ASC', + 'prepare' => true, ], ], ], @@ -616,51 +750,43 @@ public function dataProvider_SQL92() ], ], ], - [ // join with Expression object in COLUMNS part (ZF2-514) // @co-author Koen Pieters (kpieters) - 'sqlObject' => $this->select()->from('foo')->columns([])->join('bar', 'm = n', ['thecount' => new Expression("COUNT(*)")]), + ]; + } + + public function dataProvider_Quantitifier() + { + return [ + [ + 'sqlObject' => $this->select()->from('foo')->quantifier(Select::QUANTIFIER_DISTINCT), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT COUNT(*) AS "thecount" FROM "foo" INNER JOIN "bar" ON "m" = "n"', + 'string' => 'SELECT DISTINCT "foo".* FROM "foo"', 'prepare' => true, ], ], ], - [ // multiple joins with expressions // reported by @jdolieslager - 'sqlObject' => $this->select() - ->from('foo') - ->join('tableA', new Predicate\Operator('id', '=', 1)) - ->join('tableB', new Predicate\Operator('id', '=', 2)) - ->join('tableC', new Predicate\PredicateSet([ - new Predicate\Operator('id', '=', 3), - new Predicate\Operator('number', '>', 20) - ])), - 'expected' => [ - 'sql92' => [ - 'string' => 'SELECT "foo".*, "tableA".*, "tableB".*, "tableC".* FROM "foo" ' - . 'INNER JOIN "tableA" ON "id" = \'1\' INNER JOIN "tableB" ON "id" = \'2\' ' - . 'INNER JOIN "tableC" ON "id" = \'3\' AND "number" > \'20\'', - 'prepare' => 'SELECT "foo".*, "tableA".*, "tableB".*, "tableC".* FROM "foo"' - . ' INNER JOIN "tableA" ON "id" = :join1expr1 INNER JOIN "tableB" ON "id" = :join2expr1 ' - . 'INNER JOIN "tableC" ON "id" = :join3expr1 AND "number" > :join3expr2', - 'useNamedParams' => true, - ], - ], - ], - [ // @author robertbasic // @link https://github.com/zendframework/zf2/pull/2714 - 'sqlObject' => $this->select()->from('foo')->columns(['bar'], false), + [ + 'sqlObject' => $this->select()->from('foo')->quantifier(new Expression('TOP ?', [10])), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "bar" AS "bar" FROM "foo"', - 'prepare' => true, + 'string' => 'SELECT TOP \'10\' "foo".* FROM "foo"', + 'prepare' => 'SELECT TOP ? "foo".* FROM "foo"', ], ], ], - [ // Test TableIdentifier In Joins @link https://github.com/zendframework/zf2/issues/3294 - 'sqlObject' => $this->select()->from('foo')->columns([])->join(new TableIdentifier('bar', 'baz'), 'm = n', ['thecount' => new Expression("COUNT(*)")]), + ]; + } + + public function dataProvider_SubSelects() + { + return [ + [ + 'sqlObject' => $this->select(['b' => $this->select(['a' => $this->select('test')])]), 'expected' => [ - 'sql92' => [ - 'string' => 'SELECT COUNT(*) AS "thecount" FROM "foo" INNER JOIN "baz"."bar" ON "m" = "n"', - 'prepare' => true, + 'Oracle' => [ + 'string' => 'SELECT "b".* FROM (SELECT "a".* FROM (SELECT "test".* FROM "test") "a") "b"', + 'prepare' => true, + 'parameters' => [], ], ], ], @@ -682,124 +808,134 @@ public function dataProvider_SQL92() ], ], ], - [ // Test TableIdentifier In Joins, with multiple joins @link https://github.com/zendframework/zf2/issues/3294 - 'sqlObject' => $this->select()->from('foo') - ->join(['a' => new TableIdentifier('another_foo', 'another_schema')], 'a.x = foo.foo_column') - ->join('bar', 'foo.colx = bar.colx'), + 'Select::processSubSelect()' => [ + 'sqlObject' => $this->select(['a' => $this->select(['b' => $this->select('c')->where(['cc'=>'CC'])])->where(['bb'=>'BB'])])->where(['aa'=>'AA']), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".*, "a".*, "bar".* FROM "foo"' - . ' INNER JOIN "another_schema"."another_foo" AS "a" ON "a"."x" = "foo"."foo_column"' - . ' INNER JOIN "bar" ON "foo"."colx" = "bar"."colx"', - 'prepare' => true, + 'string' => 'SELECT "a".* FROM (SELECT "b".* FROM (SELECT "c".* FROM "c" WHERE "cc" = \'CC\') AS "b" WHERE "bb" = \'BB\') AS "a" WHERE "aa" = \'AA\'', + 'prepare' => 'SELECT "a".* FROM (SELECT "b".* FROM (SELECT "c".* FROM "c" WHERE "cc" = ?) AS "b" WHERE "bb" = ?) AS "a" WHERE "aa" = ?', + 'parameters' => ['subselect2expr1' => 'CC', 'subselect1expr1' => 'BB', 'expr1' => 'AA'], + ], + 'MySql' => [ + 'string' => 'SELECT `a`.* FROM (SELECT `b`.* FROM (SELECT `c`.* FROM `c` WHERE `cc` = \'CC\') AS `b` WHERE `bb` = \'BB\') AS `a` WHERE `aa` = \'AA\'', + 'prepare' => 'SELECT `a`.* FROM (SELECT `b`.* FROM (SELECT `c`.* FROM `c` WHERE `cc` = ?) AS `b` WHERE `bb` = ?) AS `a` WHERE `aa` = ?', + 'parameters' => ['subselect2expr1' => 'CC', 'subselect1expr1' => 'BB', 'expr1' => 'AA'], + ], + 'Oracle' => [ + 'string' => 'SELECT "a".* FROM (SELECT "b".* FROM (SELECT "c".* FROM "c" WHERE "cc" = \'CC\') "b" WHERE "bb" = \'BB\') "a" WHERE "aa" = \'AA\'', + 'prepare' => 'SELECT "a".* FROM (SELECT "b".* FROM (SELECT "c".* FROM "c" WHERE "cc" = ?) "b" WHERE "bb" = ?) "a" WHERE "aa" = ?', + 'parameters' => ['subselect2expr1' => 'CC', 'subselect1expr1' => 'BB', 'expr1' => 'AA'], + ], + 'SqlServer' => [ + 'string' => 'SELECT [a].* FROM (SELECT [b].* FROM (SELECT [c].* FROM [c] WHERE [cc] = \'CC\') AS [b] WHERE [bb] = \'BB\') AS [a] WHERE [aa] = \'AA\'', + 'prepare' => 'SELECT [a].* FROM (SELECT [b].* FROM (SELECT [c].* FROM [c] WHERE [cc] = ?) AS [b] WHERE [bb] = ?) AS [a] WHERE [aa] = ?', + 'parameters' => ['subselect2expr1' => 'CC', 'subselect1expr1' => 'BB', 'expr1' => 'AA'], ], ], ], - [ - 'sqlObject' => $this->select()->from('foo')->quantifier(Select::QUANTIFIER_DISTINCT), + ]; + } + + public function dataProvider_Table() + { + return [ + 'without table' => [ + 'sqlObject' => $this->select() + ->columns([ + new Expression('SOME_DB_FUNCTION_ONE()'), + 'foo' => new Expression('SOME_DB_FUNCTION_TWO()'), + ]), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT DISTINCT "foo".* FROM "foo"', + 'string' => 'SELECT SOME_DB_FUNCTION_ONE() AS column1, SOME_DB_FUNCTION_TWO() AS "foo"', 'prepare' => true, ], ], ], - [ - 'sqlObject' => $this->select()->from('foo')->quantifier(new Expression('TOP ?', [10])), + 'string table' => [ + 'sqlObject' => $this->select()->from('foo'), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT TOP \'10\' "foo".* FROM "foo"', - 'prepare' => 'SELECT TOP ? "foo".* FROM "foo"', + 'string' => 'SELECT "foo".* FROM "foo"', + 'prepare' => true, ], - ], - ], - [ - 'sqlObject' => $this->select()->from(['x' => 'foo'])->columns(['bar' => 'foo.bar'], false), - 'expected' => [ - 'sql92' => [ - 'string' => 'SELECT "foo"."bar" AS "bar" FROM "foo" AS "x"', - 'prepare' => 'SELECT "foo"."bar" AS "bar" FROM "foo" AS "x"', + 'SqlServer' => [ + 'string' => 'SELECT [foo].* FROM [foo]', + 'prepare' => true, + 'parameters' => [], ], ], ], - [ - 'sqlObject' => $this->select() - ->from('foo') - ->where('a = b') - ->combine( - $this->select()->from('bar')->where('c = d'), - Select::COMBINE_UNION, - 'ALL' - ), + 'string table with alias' => [ + 'sqlObject' => $this->select()->from(['x' => 'foo']), 'expected' => [ 'sql92' => [ - 'string' => '( SELECT "foo".* FROM "foo" WHERE a = b ) UNION ALL ( SELECT "bar".* FROM "bar" WHERE c = d )', + 'string' => 'SELECT "x".* FROM "foo" AS "x"', 'prepare' => true, ], + 'Oracle' => [ + 'string' => 'SELECT "x".* FROM "foo" "x"', + 'prepare' => true, + 'parameters' => [], + ], ], ], - [ // limit with offset - 'sqlObject' => $this->select()->from('foo')->limit("5")->offset("10"), + 'table as TableIdentifier' => [ // table as TableIdentifier + 'sqlObject' => $this->select()->from(new TableIdentifier('foo', 'bar')), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" LIMIT \'5\' OFFSET \'10\'', - 'prepare' => 'SELECT "foo".* FROM "foo" LIMIT ? OFFSET ?', - 'parametersEquals' => ['limit' => 5, 'offset' => 10], + 'string' => 'SELECT "bar"."foo".* FROM "bar"."foo"', + 'prepare' => true, ], ], ], - [ // functions without table - 'sqlObject' => $this->select() - ->columns([ - new Expression('SOME_DB_FUNCTION_ONE()'), - 'foo' => new Expression('SOME_DB_FUNCTION_TWO()'), - ]), + 'table with alias with table as TableIdentifier' => [ + 'sqlObject' => $this->select()->from(['f' => new TableIdentifier('foo')]), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT SOME_DB_FUNCTION_ONE() AS column1, SOME_DB_FUNCTION_TWO() AS "foo"', + 'string' => 'SELECT "f".* FROM "foo" AS "f"', 'prepare' => true, ], ], ], - [ // limit with big offset and limit - 'sqlObject' => $this->select()->from('foo')->limit("10000000000000000000")->offset("10000000000000000000"), + [ // Test TableIdentifier In Joins @link https://github.com/zendframework/zf2/issues/3294 + 'sqlObject' => $this->select()->from('foo')->columns([])->join(new TableIdentifier('bar', 'baz'), 'm = n', ['thecount' => new Expression("COUNT(*)")]), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".* FROM "foo" LIMIT \'10000000000000000000\' OFFSET \'10000000000000000000\'', - 'prepare' => 'SELECT "foo".* FROM "foo" LIMIT ? OFFSET ?', - 'parametersEquals' => ['limit' => 10000000000000000000, 'offset' => 10000000000000000000], + 'string' => 'SELECT COUNT(*) AS "thecount" FROM "foo" INNER JOIN "baz"."bar" ON "m" = "n"', + 'prepare' => true, ], ], ], - [ // combine and union with order at the end - 'sqlObject' => $this->select() - ->from([ - 'sub' => $this->select() - ->from('foo') - ->where('a = b') - ->combine( - $this->select()->from('bar')->where('c = d') - ) - ]) - ->order('id DESC'), + [ // Test TableIdentifier In Joins, with multiple joins @link https://github.com/zendframework/zf2/issues/3294 + 'sqlObject' => $this->select()->from('foo') + ->join(['a' => new TableIdentifier('another_foo', 'another_schema')], 'a.x = foo.foo_column') + ->join('bar', 'foo.colx = bar.colx'), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "sub".* FROM (( SELECT "foo".* FROM "foo" WHERE a = b ) UNION ( SELECT "bar".* FROM "bar" WHERE c = d )) AS "sub" ORDER BY "id" DESC', + 'string' => 'SELECT "foo".*, "a".*, "bar".* FROM "foo"' + . ' INNER JOIN "another_schema"."another_foo" AS "a" ON "a"."x" = "foo"."foo_column"' + . ' INNER JOIN "bar" ON "foo"."colx" = "bar"."colx"', 'prepare' => true, ], ], ], - [ //Expression as joinName + [ //testSelectUsingTableIdentifierWithEmptyScheme() 'sqlObject' => $this->select() ->from(new TableIdentifier('foo')) - ->join(['bar' => new Expression('psql_function_which_returns_table')], 'foo.id = bar.fooid'), + ->join(new TableIdentifier('bar'), 'foo.id = bar.fooid'), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".*, "bar".* FROM "foo" INNER JOIN psql_function_which_returns_table AS "bar" ON "foo"."id" = "bar"."fooid"', - 'prepare' => true, + 'string' => 'SELECT "foo".*, "bar".* FROM "foo" INNER JOIN "bar" ON "foo"."id" = "bar"."fooid"', ], ], ], + ]; + } + + public function dataProvider_Where() + { + return [ [ // Test generic predicate is appended with AND 'sqlObject' => function () { $select = $this->select(); @@ -838,24 +974,49 @@ public function dataProvider_SQL92() ], ], ], - [ // @author Andrzej Lewandowski @link https://github.com/zendframework/zf2/issues/7222 - 'sqlObject' => $this->select()->from('foo')->join('zac', '(catalog_category_website.category_id = catalog_category.category_id)'), + [ // where (simple string) + 'sqlObject' => $this->select()->from('foo')->where('x = 5'), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "foo".*, "zac".* FROM "foo" INNER JOIN "zac" ON ("catalog_category_website"."category_id" = "catalog_category"."category_id")', + 'string' => 'SELECT "foo".* FROM "foo" WHERE x = 5', 'prepare' => true, ], ], ], - [ // Combine - 'sqlObject' => $this->select() - ->from(['foo'=>$this->combine($this->select('bar0'))]) - ->columns(['c1'=>$this->combine($this->select('bar1'))]) - ->where(['c2'=>$this->combine($this->select('bar2'))]) - ->join(['c3'=>$this->combine($this->select('bar3'))], 'xx=yy'), + [ // where (returning parameters) + 'sqlObject' => $this->select()->from('foo')->where(['x = ?' => 5]), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT ((SELECT "bar1".* FROM "bar1")) AS "c1", "c3".* FROM ((SELECT "bar0".* FROM "bar0")) AS "foo" INNER JOIN ((SELECT "bar3".* FROM "bar3")) AS "c3" ON "xx"="yy" WHERE "c2" = ((SELECT "bar2".* FROM "bar2"))', + 'string' => 'SELECT "foo".* FROM "foo" WHERE x = \'5\'', + 'prepare' => 'SELECT "foo".* FROM "foo" WHERE x = ?', + 'parameters' => ['expr1' => 5], + ], + ], + ], + [ + 'sqlObject' => function () { + $subselect = $this->select(); + $subselect->from('bar')->where->like('y', '%Foo%'); + return $this->select()->from(['x' => $subselect]); + }, + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "x".* FROM (SELECT "bar".* FROM "bar" WHERE "y" LIKE \'%Foo%\') AS "x"', + 'prepare' => 'SELECT "x".* FROM (SELECT "bar".* FROM "bar" WHERE "y" LIKE ?) AS "x"', + ], + ], + ], + [ + 'sqlObject' => $this->select('table') + ->where([ + 'c1' => null, + 'c2' => [1, 2, 3], + new \Zend\Db\Sql\Predicate\IsNotNull('c3') + ]), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "table".* FROM "table" WHERE "c1" IS NULL AND "c2" IN (\'1\', \'2\', \'3\') AND "c3" IS NOT NULL', + 'prepare' => 'SELECT "table".* FROM "table" WHERE "c1" IS NULL AND "c2" IN (?, ?, ?) AND "c3" IS NOT NULL', ], ], ], diff --git a/test/Sql/Builder/UpdateBuilderTest.php b/test/Sql/Builder/UpdateBuilderTest.php index e89ccde4fd..753265b376 100644 --- a/test/Sql/Builder/UpdateBuilderTest.php +++ b/test/Sql/Builder/UpdateBuilderTest.php @@ -11,7 +11,11 @@ use Zend\Db\Sql\Expression; use Zend\Db\Sql\TableIdentifier; +use Zend\Db\Sql\Join; +/** + * @covers Zend\Db\Sql\Builder\sql92\UpdateBuilder + */ class UpdateBuilderTest extends AbstractTestCase { /** @@ -25,55 +29,123 @@ public function test($sqlObject, $platform, $expected) public function dataProvider() { - return $this->prepareDataProvider([ - [ //??? testPassingMultipleKeyValueInWhereClause() + return $this->prepareDataProvider( + $this->dataProvider_Else(), + $this->dataProvider_Set(), + $this->dataProvider_SubSelectAndExpressions(), + $this->dataProvider_Table(), + $this->dataProvider_Where(), + $this->dataProvider_Joins() + ); + } + + public function dataProvider_Set() + { + return [ + [ 'sqlObject' => $this->update() - ->table('table') - ->set(['fld1' => 'val1']) - ->where(['id1' => 'val1', 'id2' => 'val2']), + ->table('foo') + ->set([ + 'bar' => 'baz', + 'boo' => new Expression('NOW()'), + 'bam' => null, + 'false' => false, + 'true' => true, + ]), 'expected' => [ 'sql92' => [ - 'string' => 'UPDATE "table" SET "fld1" = \'val1\' WHERE "id1" = \'val1\' AND "id2" = \'val2\'', + 'string' => 'UPDATE "foo" SET "bar" = \'baz\', "boo" = NOW(), "bam" = NULL, "false" = \'\', "true" = \'1\'', + 'prepare' => 'UPDATE "foo" SET "bar" = ?, "boo" = NOW(), "bam" = NULL, "false" = ?, "true" = ?', + 'parameters' => ['bar' => 'baz', 'false' => false, 'true' => true], ], ], ], - [ // testPrepareStatement(), testGetSqlString() - 'sqlObject' => $this->update() - ->table('foo') - ->set(['bar' => 'baz', 'boo' => new Expression('NOW()'), 'bam' => null]) - ->where('x = y'), + ]; + } + + public function dataProvider_Table() + { + return [ + [ + 'sqlObject' => $this->update('foo')->set(['bar' => 'baz']), 'expected' => [ 'sql92' => [ - 'string' => 'UPDATE "foo" SET "bar" = \'baz\', "boo" = NOW(), "bam" = NULL WHERE x = y', - 'prepare' => 'UPDATE "foo" SET "bar" = ?, "boo" = NOW(), "bam" = NULL WHERE x = y', + 'string' => 'UPDATE "foo" SET "bar" = \'baz\'', + 'prepare' => 'UPDATE "foo" SET "bar" = ?', ], ], ], - [ // testPrepareStatement() // with TableIdentifier - 'sqlObject' => $this->update() - ->table(new TableIdentifier('foo', 'sch')) - ->set(['bar' => 'baz', 'boo' => new Expression('NOW()'), 'bam' => null]) - ->where('x = y'), + [ + 'sqlObject' => $this->update(new TableIdentifier('foo', 'sch'))->set(['bar' => 'baz']), 'expected' => [ 'sql92' => [ - 'string' => 'UPDATE "sch"."foo" SET "bar" = \'baz\', "boo" = NOW(), "bam" = NULL WHERE x = y', - 'prepare' => 'UPDATE "sch"."foo" SET "bar" = ?, "boo" = NOW(), "bam" = NULL WHERE x = y', + 'string' => 'UPDATE "sch"."foo" SET "bar" = \'baz\'', + 'prepare' => 'UPDATE "sch"."foo" SET "bar" = ?', ], ], ], - [ // testGetSqlStringForFalseUpdateValueParameter() - 'sqlObject' => $this->update() - ->table(new TableIdentifier('foo', 'sch')) - ->set(['bar' => false, 'boo' => 'test', 'bam' => true]) - ->where('x = y'), + ]; + } + + public function dataProvider_SubSelectAndExpressions() + { + return [ + [ + 'sqlObject' => $this->update('foo')->set(['x'=>$this->select('foo')]), 'expected' => [ - 'sql92' => [ - 'string' => 'UPDATE "sch"."foo" SET "bar" = \'\', "boo" = \'test\', "bam" = \'1\' WHERE x = y', - 'prepare' => 'UPDATE "sch"."foo" SET "bar" = ?, "boo" = ?, "bam" = ? WHERE x = y', + 'sql92' => 'UPDATE "foo" SET "x" = (SELECT "foo".* FROM "foo")', + 'MySql' => 'UPDATE `foo` SET `x` = (SELECT `foo`.* FROM `foo`)', + 'Oracle' => 'UPDATE "foo" SET "x" = (SELECT "foo".* FROM "foo")', + 'SqlServer' => 'UPDATE [foo] SET [x] = (SELECT [foo].* FROM [foo])', + ], + ], + [ + 'sqlObject' => $this->update('foo')->set(['x'=>new Expression('?', [$this->select('foo')])]), + 'expected' => [ + 'sql92' => 'UPDATE "foo" SET "x" = (SELECT "foo".* FROM "foo")', + 'MySql' => 'UPDATE `foo` SET `x` = (SELECT `foo`.* FROM `foo`)', + 'Oracle' => 'UPDATE "foo" SET "x" = (SELECT "foo".* FROM "foo")', + 'SqlServer' => 'UPDATE [foo] SET [x] = (SELECT [foo].* FROM [foo])', + ], + ], + ]; + } + + public function dataProvider_Where() + { + return [ + [ + 'sqlObject' => $this->update('foo')->set(['bar' => 'baz'])->where(['x'=>'y']), + 'expected' => [ + 'sql92' => [ + 'string' => 'UPDATE "foo" SET "bar" = \'baz\' WHERE "x" = \'y\'', + 'prepare' => 'UPDATE "foo" SET "bar" = ? WHERE "x" = ?', + 'parameters' => ['bar' => 'baz', 'expr1' => 'y'], + ], + 'MySql' => [ + 'string' => 'UPDATE `foo` SET `bar` = \'baz\' WHERE `x` = \'y\'', + 'prepare' => 'UPDATE `foo` SET `bar` = ? WHERE `x` = ?', + 'parameters' => ['bar' => 'baz', 'expr1' => 'y'], + ], + 'Oracle' => [ + 'string' => 'UPDATE "foo" SET "bar" = \'baz\' WHERE "x" = \'y\'', + 'prepare' => 'UPDATE "foo" SET "bar" = ? WHERE "x" = ?', + 'parameters' => ['bar' => 'baz', 'expr1' => 'y'], + ], + 'SqlServer' => [ + 'string' => 'UPDATE [foo] SET [bar] = \'baz\' WHERE [x] = \'y\'', + 'prepare' => 'UPDATE [foo] SET [bar] = ? WHERE [x] = ?', + 'parameters' => ['bar' => 'baz', 'expr1' => 'y'], ], ], ], - [ // testCloneUpdate() + ]; + } + + public function dataProvider_Else() + { + return [ + 'clone' => [ // testCloneUpdate() 'sqlObject' => function () { $update1 = clone $this->update(); $update1->table('foo') @@ -94,6 +166,59 @@ public function dataProvider() ], ], ], - ]); + ]; + } + + public function dataProvider_Joins() + { + return [ + 'Update::processJoins()_1' => [ + 'sqlObject' => $this->update('foo')->set(['x' => 'y'])->where(['xx' => 'yy'])->join( + 'bar', + 'bar.barId = foo.barId' + ), + 'expected' => [ + 'sql92' => [ + 'string' => 'UPDATE "foo" INNER JOIN "bar" ON "bar"."barId" = "foo"."barId" SET "x" = \'y\' WHERE "xx" = \'yy\'', + ], + 'MySql' => [ + 'string' => 'UPDATE `foo` INNER JOIN `bar` ON `bar`.`barId` = `foo`.`barId` SET `x` = \'y\' WHERE `xx` = \'yy\'', + ], + 'Oracle' => [ + 'string' => 'UPDATE "foo" INNER JOIN "bar" ON "bar"."barId" = "foo"."barId" SET "x" = \'y\' WHERE "xx" = \'yy\'', + ], + 'SqlServer' => [ + 'string' => 'UPDATE [foo] INNER JOIN [bar] ON [bar].[barId] = [foo].[barId] SET [x] = \'y\' WHERE [xx] = \'yy\'', + ], + ], + ], + 'Update::processJoins()_2' => [ + 'sqlObject' => $this->update('Document')->set(['x' => 'y']) + ->join( + 'User', // table name + 'User.UserId = Document.UserId' // expression to join on (will be quoted by platform object before insertion), + // default JOIN INNER + ) + ->join( + 'Category', + 'Category.CategoryId = Document.CategoryId', + Join::JOIN_LEFT // (optional), one of inner, outer, left, right + ), + 'expected' => [ + 'sql92' => [ + 'string' => 'UPDATE "Document" INNER JOIN "User" ON "User"."UserId" = "Document"."UserId" LEFT JOIN "Category" ON "Category"."CategoryId" = "Document"."CategoryId" SET "x" = \'y\'', + ], + 'MySql' => [ + 'string' => 'UPDATE `Document` INNER JOIN `User` ON `User`.`UserId` = `Document`.`UserId` LEFT JOIN `Category` ON `Category`.`CategoryId` = `Document`.`CategoryId` SET `x` = \'y\'', + ], + 'Oracle' => [ + 'string' => 'UPDATE "Document" INNER JOIN "User" ON "User"."UserId" = "Document"."UserId" LEFT JOIN "Category" ON "Category"."CategoryId" = "Document"."CategoryId" SET "x" = \'y\'', + ], + 'SqlServer' => [ + 'string' => 'UPDATE [Document] INNER JOIN [User] ON [User].[UserId] = [Document].[UserId] LEFT JOIN [Category] ON [Category].[CategoryId] = [Document].[CategoryId] SET [x] = \'y\'', + ], + ], + ], + ]; } } diff --git a/test/Sql/Predicate/PredicateTest.php b/test/Sql/Predicate/PredicateTest.php index be2299c75f..c2d842865e 100644 --- a/test/Sql/Predicate/PredicateTest.php +++ b/test/Sql/Predicate/PredicateTest.php @@ -18,7 +18,8 @@ class PredicateTest extends TestCase { /** - * moved from SelectTest + * @covers Zend\Db\Sql\Predicate\Predicate::addPredicates + * @covers Zend\Db\Sql\Predicate\Predicate::getPredicates */ public function testWhereArgument1IsAssociativeArrayContainingReplacementCharacter() { @@ -39,13 +40,15 @@ public function testWhereArgument1IsAssociativeArrayContainingReplacementCharact } /** - * moved from SelectTest + * @covers Zend\Db\Sql\Predicate\Predicate::addPredicates + * @covers Zend\Db\Sql\Predicate\Predicate::getPredicates */ public function testWhereArgument1IsAssociativeArrayNotContainingReplacementCharacter() { $where = new Predicate; - $where->addPredicates(['name' => 'Ralph', 'age' => 33]); - $predicates = $where->getPredicates(); + $predicates = $where + ->addPredicates(['name' => 'Ralph', 'age' => 33]) + ->getPredicates(); $this->assertEquals(2, count($predicates)); $this->assertInstanceOf('Zend\Db\Sql\Predicate\Operator', $predicates[0][1]); @@ -66,7 +69,7 @@ public function testWhereArgument1IsAssociativeArrayNotContainingReplacementChar } /** - * moved from SelectTest + * @covers Zend\Db\Sql\Predicate\Predicate::addPredicates */ public function testWhereArgument1IsAssociativeArrayIsPredicate() { @@ -79,7 +82,8 @@ public function testWhereArgument1IsAssociativeArrayIsPredicate() } /** - * moved from SelectTest + * @covers Zend\Db\Sql\Predicate\Predicate::addPredicates + * @covers Zend\Db\Sql\Predicate\Predicate::getPredicates */ public function testWhereArgument1IsIndexedArray() { @@ -95,7 +99,8 @@ public function testWhereArgument1IsIndexedArray() } /** - * moved from SelectTest + * @covers Zend\Db\Sql\Predicate\Predicate::addPredicates + * @covers Zend\Db\Sql\Predicate\Predicate::getPredicates */ public function testWhereArgument1IsIndexedArrayArgument2IsOr() { @@ -111,7 +116,7 @@ public function testWhereArgument1IsIndexedArrayArgument2IsOr() } /** - * moved from SelectTest + * @covers Zend\Db\Sql\Predicate\Predicate::addPredicates */ public function testWhereArgument1IsClosure() { @@ -123,7 +128,8 @@ public function testWhereArgument1IsClosure() } /** - * moved from SelectTest + * @covers Zend\Db\Sql\Predicate\Predicate::addPredicates + * @covers Zend\Db\Sql\Predicate\Predicate::getPredicates */ public function testWhereArgument1IsString() { @@ -144,4 +150,132 @@ public function testWhereArgument1IsString() $this->assertInstanceOf('Zend\Db\Sql\Predicate\Literal', $predicates[0][1]); } + + public function testMethodsIsMutable() + { + $predicate = new Predicate; + + $this->assertSame($predicate, $predicate->equalTo('foo.bar', 'bar')); + $this->assertSame($predicate, $predicate->notEqualTo('foo.bar', 'bar')); + $this->assertSame($predicate, $predicate->lessThan('foo.bar', 'bar')); + $this->assertSame($predicate, $predicate->greaterThan('foo.bar', 'bar')); + $this->assertSame($predicate, $predicate->lessThanOrEqualTo('foo.bar', 'bar')); + $this->assertSame($predicate, $predicate->greaterThanOrEqualTo('foo.bar', 'bar')); + $this->assertSame($predicate, $predicate->like('foo.bar', 'bar%')); + $this->assertSame($predicate, $predicate->notLike('foo.bar', 'bar%')); + $this->assertSame($predicate, $predicate->literal('foo.bar = ?', 'bar')); + $this->assertSame($predicate, $predicate->isNull('foo.bar')); + $this->assertSame($predicate, $predicate->isNotNull('foo.bar')); + $this->assertSame($predicate, $predicate->in('foo.bar', ['foo', 'bar'])); + $this->assertSame($predicate, $predicate->notIn('foo.bar', ['foo', 'bar'])); + $this->assertSame($predicate, $predicate->between('foo.bar', 1, 10)); + $this->assertSame($predicate, $predicate->expression('foo = ?', 'bar')); + $this->assertSame( + $predicate, + $predicate + ->isNull('foo.bar') + ->or + ->isNotNull('bar.baz') + ->and + ->equalTo('baz.bat', 'foo') + ); + $this->assertSame( + $predicate, + $predicate + ->isNull('foo.bar') + ->nest() + ->isNotNull('bar.baz') + ->and + ->equalTo('baz.bat', 'foo') + ->unnest() + ); + } + + /** + * @covers Zend\Db\Sql\Predicate\Predicate::between + * @covers Zend\Db\Sql\Predicate\Predicate::equalTo + * @covers Zend\Db\Sql\Predicate\Predicate::expression + * @covers Zend\Db\Sql\Predicate\Predicate::greaterThan + * @covers Zend\Db\Sql\Predicate\Predicate::greaterThanOrEqualTo + * @covers Zend\Db\Sql\Predicate\Predicate::in + * @covers Zend\Db\Sql\Predicate\Predicate::isNotNull + * @covers Zend\Db\Sql\Predicate\Predicate::isNull + * @covers Zend\Db\Sql\Predicate\Predicate::lessThan + * @covers Zend\Db\Sql\Predicate\Predicate::lessThanOrEqualTo + * @covers Zend\Db\Sql\Predicate\Predicate::like + * @covers Zend\Db\Sql\Predicate\Predicate::literal + * @covers Zend\Db\Sql\Predicate\Predicate::notBetween + * @covers Zend\Db\Sql\Predicate\Predicate::notEqualTo + * @covers Zend\Db\Sql\Predicate\Predicate::notIn + * @covers Zend\Db\Sql\Predicate\Predicate::notLike + */ + public function testPredicatesIsCorrectInstances() + { + $predicate = new Predicate; + + $this->assertInstanceOf( + 'Zend\Db\Sql\Predicate\Between', + $predicate->between('p1', 'p2', 'p3')->getPredicates()[0][1] + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Predicate\Operator', + $predicate->equalTo('p1', 'p2')->getPredicates()[1][1] + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Predicate\Expression', + $predicate->expression('', [])->getPredicates()[2][1] + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Predicate\Operator', + $predicate->greaterThan('p1', 'p2')->getPredicates()[3][1] + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Predicate\Operator', + $predicate->greaterThanOrEqualTo('p1', 'p2')->getPredicates()[4][1] + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Predicate\In', + $predicate->in('p1')->getPredicates()[5][1] + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Predicate\IsNotNull', + $predicate->isNotNull('p1')->getPredicates()[6][1] + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Predicate\IsNull', + $predicate->isNull('p1')->getPredicates()[7][1] + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Predicate\Operator', + $predicate->lessThan('p1', 'p2')->getPredicates()[8][1] + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Predicate\Operator', + $predicate->lessThanOrEqualTo('p1', 'p2')->getPredicates()[9][1] + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Predicate\Like', + $predicate->like('p1', 'p2')->getPredicates()[10][1] + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Predicate\Literal', + $predicate->literal('p1')->getPredicates()[11][1] + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Predicate\NotBetween', + $predicate->notBetween('p1', 'p2', 'p3')->getPredicates()[12][1] + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Predicate\Operator', + $predicate->notEqualTo('p1', 'p2')->getPredicates()[13][1] + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Predicate\NotIn', + $predicate->notIn('p1')->getPredicates()[14][1] + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Predicate\NotLike', + $predicate->notLike('p1', 'p2')->getPredicates()[15][1] + ); + } } From 8b34b4557da64a4f748a932f39d40f7520a13afc Mon Sep 17 00:00:00 2001 From: turrsis Date: Thu, 9 Jul 2015 19:11:19 +0300 Subject: [PATCH 06/30] architecture 05: refactor AbstractBuilder::createSqlFromSpecificationAndParameters() --- src/Sql/Builder/AbstractSqlBuilder.php | 366 ++++++++++-------- src/Sql/Builder/IbmDb2/SelectBuilder.php | 41 +- .../Builder/Mysql/Ddl/AlterTableBuilder.php | 14 +- .../Builder/Mysql/Ddl/CreateTableBuilder.php | 6 +- src/Sql/Builder/Mysql/SelectBuilder.php | 31 +- src/Sql/Builder/Oracle/SelectBuilder.php | 44 ++- .../SqlServer/Ddl/CreateTableBuilder.php | 7 +- src/Sql/Builder/SqlServer/SelectBuilder.php | 64 +-- src/Sql/Builder/sql92/CombineBuilder.php | 37 +- .../Builder/sql92/Ddl/AlterTableBuilder.php | 123 +++--- .../Column/AbstractLengthColumnBuilder.php | 6 +- .../Column/AbstractTimestampColumnBuilder.php | 6 +- .../sql92/Ddl/Column/ColumnBuilder.php | 8 +- .../sql92/Ddl/Column/IntegerBuilder.php | 4 +- .../sql92/Ddl/Constraint/AbstractBuilder.php | 6 +- .../sql92/Ddl/Constraint/CheckBuilder.php | 6 +- .../Ddl/Constraint/ForeignKeyBuilder.php | 8 +- .../Builder/sql92/Ddl/CreateTableBuilder.php | 87 +++-- .../Builder/sql92/Ddl/DropTableBuilder.php | 24 +- .../Builder/sql92/Ddl/Index/IndexBuilder.php | 6 +- src/Sql/Builder/sql92/DeleteBuilder.php | 43 +- src/Sql/Builder/sql92/ExpressionBuilder.php | 12 +- src/Sql/Builder/sql92/InsertBuilder.php | 81 ++-- src/Sql/Builder/sql92/LiteralBuilder.php | 9 +- .../sql92/Predicate/BetweenBuilder.php | 6 +- src/Sql/Builder/sql92/Predicate/InBuilder.php | 10 +- .../Builder/sql92/Predicate/IsNullBuilder.php | 6 +- .../Builder/sql92/Predicate/LikeBuilder.php | 6 +- .../sql92/Predicate/NotBetweenBuilder.php | 6 +- .../sql92/Predicate/OperatorBuilder.php | 6 +- .../sql92/Predicate/PredicateSetBuilder.php | 4 +- src/Sql/Builder/sql92/SelectBuilder.php | 299 ++++++++------ src/Sql/Builder/sql92/UpdateBuilder.php | 95 +++-- test/Sql/Builder/AbstractTestCase.php | 4 +- test/Sql/Builder/AllBuildersTest.php | 16 +- .../Sql/Builder/Ddl/AlterTableBuilderTest.php | 6 +- .../Builder/Ddl/CreateTableBuilderTest.php | 2 +- test/Sql/Builder/InsertBuilderTest.php | 40 +- test/Sql/Builder/SelectBuilderTest.php | 10 +- test/TestAsset/ExpressionBuilder.php | 4 +- 40 files changed, 894 insertions(+), 665 deletions(-) diff --git a/src/Sql/Builder/AbstractSqlBuilder.php b/src/Sql/Builder/AbstractSqlBuilder.php index 103dc1bcd2..36edb9a6f2 100644 --- a/src/Sql/Builder/AbstractSqlBuilder.php +++ b/src/Sql/Builder/AbstractSqlBuilder.php @@ -12,12 +12,13 @@ use Zend\Db\Sql\TableIdentifier; use Zend\Db\Sql\SelectableInterface; use Zend\Db\Sql\ExpressionInterface; -use Zend\Db\Sql\Expression; -use Zend\Db\Sql\Exception; +use Zend\Db\Sql\ExpressionParameter; use Zend\Db\Sql\SqlObjectInterface; abstract class AbstractSqlBuilder extends AbstractBuilder { + protected $implodeGlueKey = 'implode_glue'; + protected $specifications = []; /** @@ -35,182 +36,179 @@ public function __construct(Builder $platformBuilder) protected function buildSqlString($sqlObject, Context $context) { - if ($sqlObject instanceof ExpressionInterface) { - return $this->buildExpression($sqlObject, $context); + if (is_array($sqlObject)) { + return $this->createSqlFromSpecificationAndParameters($sqlObject['spec'], $sqlObject['params'], $context); } - $sqls = []; - $parameters = []; - foreach ($this->specifications as $name => $specification) { - $parameters[$name] = $this->{'build_' . $name}($sqlObject, $context, $sqls, $parameters); + if (!$sqlObject instanceof SqlObjectInterface && !$sqlObject instanceof ExpressionInterface) { + throw new \Zend\Db\Sql\Exception\InvalidArgumentException(sprintf( + 'Argument $sqlObject passed to %s must be an instance of %s, instance of %s given', + __METHOD__ . '()', + 'Zend\Db\Sql\SqlObjectInterface or Zend\Db\Sql\ExpressionInterface', + is_object($sqlObject) ? get_class($sqlObject) : gettype($sqlObject) + )); + } - if ($specification && is_array($parameters[$name])) { - $sqls[$name] = $this->createSqlFromSpecificationAndParameters($specification, $parameters[$name]); + $specAndParams = $this + ->platformBuilder + ->getPlatformBuilder($sqlObject, $context->getAdapter()) + ->build($sqlObject, $context); + + if (isset($specAndParams[$this->implodeGlueKey])) { + $implodeGlue = $specAndParams[$this->implodeGlueKey]; + unset($specAndParams[$this->implodeGlueKey]); + } else { + $implodeGlue = $sqlObject instanceof SqlObjectInterface ? ' ' : ''; + } + $sqls = []; + foreach ($specAndParams as $spec) { + if (!$spec) { continue; } - - if (is_string($parameters[$name])) { - $sqls[$name] = $parameters[$name]; + if (is_scalar($spec)) { + $sqls[] = $spec; + continue; + } + if (is_array($spec)) { + $sqls[] = $this->createSqlFromSpecificationAndParameters($spec['spec'], $spec['params'], $context); + continue; } + $sqls[] = $this->buildSpecificationParameter($spec, $context); } - return rtrim(implode(' ', $sqls), "\n ,"); + + return rtrim(implode($implodeGlue, $sqls), "\n ,"); } - /** - * @param string|array $specifications - * @param string|array $parameters - * - * @return string - * - * @throws Exception\RuntimeException - */ - protected function createSqlFromSpecificationAndParameters($specifications, $parameters) + /* + * $spec = array( + 'format' => ' string format : http://php.net/manual/en/function.sprintf.php', + 'byArgNumber' => array( + 'parameter index' => 'spec for parameter', + ' ... ' => ' ... ', + 'parameter index' => 'spec for parameter', + ), + 'byCount' => array( + -1 => 'spec if count not found or !is_array($args)', + 'count($args)' => 'spec', + ' ... ' => ' .. ', + 'count($args)' => 'spec', + ), + 'implode' => 'is isset - do implode array', + ); + */ + private function createSqlFromSpecificationAndParameters($specification, $args, Context $context = null) { - if (is_string($specifications)) { - return vsprintf($specifications, $parameters); - } - - $parametersCount = count($parameters); - - foreach ($specifications as $specificationString => $paramSpecs) { - if ($parametersCount == count($paramSpecs)) { - break; - } - - unset($specificationString, $paramSpecs); - } - - if (!isset($specificationString)) { - throw new Exception\RuntimeException( - 'A number of parameters was found that is not supported by this specification' + if (is_string($specification)) { + return vsprintf( + $specification, + $this->buildSpecificationParameter($args, $context) ); } - $topParameters = []; - foreach ($parameters as $position => $paramsForPosition) { - if (isset($paramSpecs[$position]['combinedby'])) { - $multiParamValues = []; - foreach ($paramsForPosition as $multiParamsForPosition) { - $ppCount = count($multiParamsForPosition); - if (!isset($paramSpecs[$position][$ppCount])) { - throw new Exception\RuntimeException(sprintf( - 'A number of parameters (%d) was found that is not supported by this specification', $ppCount - )); + foreach ($specification as $specName => $spec) { + if ($specName == 'forEach') { + foreach ($args as $pName => &$param) { + $param = $this->createSqlFromSpecificationAndParameters($spec, $args[$pName], $context); + } + } elseif ($specName == 'byArgNumber') { + $i = 0; + foreach ($args as $pName => &$param) { + if (isset($spec[++$i])) { + $param = $this->createSqlFromSpecificationAndParameters($spec[$i], $args[$pName], $context); } - $multiParamValues[] = vsprintf($paramSpecs[$position][$ppCount], $multiParamsForPosition); } - $topParameters[] = implode($paramSpecs[$position]['combinedby'], $multiParamValues); - } elseif ($paramSpecs[$position] !== null) { - $ppCount = count($paramsForPosition); - if (!isset($paramSpecs[$position][$ppCount])) { - throw new Exception\RuntimeException(sprintf( - 'A number of parameters (%d) was found that is not supported by this specification', $ppCount - )); + } elseif ($specName == 'byCount') { + $pCount = is_array($args) ? count($args) : -1; + if (isset($spec[$pCount])) { + $spec = $spec[$pCount]; + } elseif (isset($spec[-1])) { + $spec = $spec[-1]; + } else { + throw new \Exception('A number of parameters (' . $pCount . ') was found that is not supported by this specification'); } - $topParameters[] = vsprintf($paramSpecs[$position][$ppCount], $paramsForPosition); - } else { - $topParameters[] = $paramsForPosition; + $args = $this->createSqlFromSpecificationAndParameters($spec, $args, $context); + } elseif ($specName == 'implode') { + if (is_array($spec)) { + $prefix = isset($spec['prefix']) ? $spec['prefix'] : ''; + $suffix = isset($spec['suffix']) ? $spec['suffix'] : ''; + $glue = isset($spec['glue']) ? $spec['glue'] : ''; + $args = + $prefix + . implode($glue, $this->buildSpecificationParameter($args, $context)) + . $suffix; + } else { + $args = implode($spec, $this->buildSpecificationParameter($args, $context)); + } + } elseif ($specName == 'format') { + $args = vsprintf( + $spec, + $this->buildSpecificationParameter($args, $context) + ); } } - return vsprintf($specificationString, $topParameters); + return $args; } - /** - * @param string|TableIdentifier|Select $table - * @param Context $context - * @return string - */ - protected function resolveTable($table, Context $context) + protected function nornalizeTable($identifier, Context $context) { - $schema = null; - if ($table instanceof TableIdentifier) { - list($table, $schema) = $table->getTableAndSchema(); + $schema = null; + $name = null; + $alias = null; + $columnAlias = null; + + if ($identifier instanceof TableIdentifier) { + $name = $identifier->getTable(); + $schema = $identifier->getSchema(); + } elseif (is_string($identifier)) { + $name = $identifier; + } elseif (is_array($identifier)) { + if (is_string(key($identifier))) { + $alias = key($identifier); + $name = current($identifier); + } elseif ($name) { + $schema = isset($identifier[0]) ? $identifier[0] : null; + $name = isset($identifier[1]) ? $identifier[1] : null; + $alias = isset($identifier[2]) ? $identifier[2] : null; + } } - if ($table instanceof SelectableInterface) { - $table = '(' . $this->buildSubSelect($table, $context) . ')'; - } elseif ($table) { - $table = $context->getPlatform()->quoteIdentifier($table); + if ($alias) { + $alias = $context->getPlatform()->quoteIdentifier($alias); + $columnAlias = $alias; } - if ($schema && $table) { - $table = $context->getPlatform()->quoteIdentifier($schema) . $context->getPlatform()->getIdentifierSeparator() . $table; + if (is_string($name)) { + $name = $context->getPlatform()->quoteIdentifier($name); + if ($schema) { + $name = $context->getPlatform()->quoteIdentifier($schema) + . $context->getPlatform()->getIdentifierSeparator() + . $name; + } + if (!$columnAlias) { + $columnAlias = $name; + } } - return $table; + + return [ + 'name' => $name, + 'alias' => $alias, + 'columnAlias' => $columnAlias, + ]; } - protected function buildSubSelect(SelectableInterface $subselect, Context $context) + private function buildSubSelect(SelectableInterface $subselect, Context $context) { $context->startPrefix('subselect'); $builder = $this->platformBuilder->getPlatformBuilder($subselect, $context->getPlatform()); - $result = $builder->buildSqlString($subselect, $context); + $result = '(' . $builder->buildSqlString($subselect, $context) . ')'; $context->endPrefix(); return $result; } - private function buildExpression(ExpressionInterface $expression, Context $context) - { - $sql = ''; - - $parts = $this->platformBuilder->getPlatformBuilder($expression, $context)->getExpressionData($expression, $context); - - foreach ($parts as $part) { - // #7407: use $expression->getExpression() to get the unescaped - // version of the expression - if (is_string($part) && $expression instanceof Expression) { - $sql .= $expression->getExpression(); - - continue; - } - - // if it is a string, simply tack it onto the return sql - // "specification" string - if (is_string($part)) { - $sql .= $part; - - continue; - } - - if (! is_array($part)) { - throw new Exception\RuntimeException( - 'Elements returned from getExpressionData() array must be a string or array.' - ); - } - - // build_ values and types (the middle and last position of the - // expression data) - $parameters = $part[1]; - foreach ($parameters as $pIndex => &$parameter) { - $value = $parameter->getValue(); - $type = $parameter->getType(); - if ($value instanceof SelectableInterface) { - $parameter = '(' . $this->buildSubSelect($value, $context) . ')'; - } elseif ($value instanceof ExpressionInterface) { - $parameter = $this->buildSqlString($value, $context); - } elseif ($type == ExpressionInterface::TYPE_IDENTIFIER) { - $parameter = $context->getPlatform()->quoteIdentifierInFragment($value); - } elseif ($type == ExpressionInterface::TYPE_VALUE) { - $parameter = $context->getPlatform()->quoteValue($value); - if ($context->getParameterContainer()) { - $name = $context->getNestedAlias('expr'); - $context->getParameterContainer()->offsetSet($name, $value); - $parameter = $context->getDriver()->formatParameterName($name); - } - } elseif ($type == ExpressionInterface::TYPE_LITERAL) { - $parameter = $value; - } - } - - $sql .= vsprintf($part[0], $parameters); - } - - return $sql; - } - /** * @param string|array $column * @param Context $context @@ -234,7 +232,7 @@ protected function resolveColumnValue($column, Context $context) return $this->buildSqlString($column, $context); } if ($column instanceof SelectableInterface) { - return '(' . $this->buildSubSelect($column, $context) . ')'; + return $this->buildSubSelect($column, $context); } if ($column === null) { return 'NULL'; @@ -244,6 +242,54 @@ protected function resolveColumnValue($column, Context $context) : $context->getPlatform()->quoteValue($column); } + private function buildSpecificationParameter($parameter, Context $context = null) + { + if (is_array($parameter)) { + foreach ($parameter as &$ppp) { + $ppp = $this->buildSpecificationParameter($ppp, $context); + } + return $parameter; + } + + if ($parameter instanceof ExpressionParameter) { + $value = $parameter->getValue(); + $type = $parameter->getType(); + $paramName = $parameter->getName(); + } else { + $value = $parameter; + $type = ExpressionInterface::TYPE_LITERAL; + } + + if ($value instanceof TableIdentifier) { + $parameter = $this->nornalizeTable($value, $context)['name']; + } elseif ($value instanceof SelectableInterface) { + $parameter = $this->buildSubSelect($value, $context); + } elseif ($value instanceof ExpressionInterface) { + $parameter = $this->buildSqlString($value, $context); + } elseif ($type == ExpressionInterface::TYPE_IDENTIFIER) { + $parameter = $context->getPlatform()->quoteIdentifierInFragment($value); + } elseif ($type == ExpressionInterface::TYPE_VALUE) { + if ($context->getParameterContainer()) { + $name = isset($paramName) + ? $paramName + : $context->getNestedAlias('expr'); + if (is_array($name)) { + $context->getParameterContainer()->offsetSet($name[0], $value); + $context->getParameterContainer()->offsetSetReference($name[1], $name[0]); + } else { + $context->getParameterContainer()->offsetSet($name, $value); + } + $parameter = $context->getDriver()->formatParameterName($name); + } else { + $parameter = $context->getPlatform()->quoteValue($value); + } + } elseif ($type == ExpressionInterface::TYPE_LITERAL) { + $parameter = $value; + } + + return $parameter; + } + protected function renderTable($table, $alias = null) { return $table . ($alias ? ' AS ' . $alias : ''); @@ -256,46 +302,32 @@ protected function renderTable($table, $alias = null) */ protected function build_Joins(SqlObjectInterface $sqlObject, Context $context) { - if (!$sqlObject->joins || $sqlObject->joins->count() == 0) { + if (!$sqlObject->joins || !$sqlObject->joins->count()) { return; } // build_ joins $joinSpecArgArray = []; foreach ($sqlObject->joins as $j => $join) { - $context->startPrefix('join'); - $joinName = null; - $joinAs = null; - - // table name - if (is_array($join['name'])) { - $joinName = current($join['name']); - $joinAs = $context->getPlatform()->quoteIdentifier(key($join['name'])); - } else { - $joinName = $join['name']; + $jTable = $this->nornalizeTable($join['name'], $context); + unset($jTable['columnAlias']); + if (!$jTable['alias']) { + unset($jTable['alias']); } - if ($joinName instanceof ExpressionInterface) { - $joinName = $joinName->getExpression(); - } elseif ($joinName instanceof TableIdentifier) { - $joinName = $joinName->getTableAndSchema(); - $joinName = ($joinName[1] ? $context->getPlatform()->quoteIdentifier($joinName[1]) . $context->getPlatform()->getIdentifierSeparator() : '') . $context->getPlatform()->quoteIdentifier($joinName[0]); - } elseif ($joinName instanceof SelectableInterface) { - $joinName = '(' . $this->buildSubSelect($joinName, $context) . ')'; - } elseif (is_string($joinName) || (is_object($joinName) && is_callable([$joinName, '__toString']))) { - $joinName = $context->getPlatform()->quoteIdentifier($joinName); - } else { - throw new Exception\InvalidArgumentException(sprintf('Join name expected to be Expression|TableIdentifier|Select|string, "%s" given', gettype($joinName))); + if (!$jTable['name']) { + $jTable = null; } $joinSpecArgArray[$j] = [ strtoupper($join['type']), - $this->renderTable($joinName, $joinAs), + $jTable, ]; $joinSpecArgArray[$j][] = ($join['on'] instanceof ExpressionInterface) - ? $this->buildSqlString($join['on'], $context, 'join' . ($j+1) . 'part') + ? $join['on'] : $context->getPlatform()->quoteIdentifierInFragment($join['on'], ['=', 'AND', 'OR', '(', ')', 'BETWEEN', '<', '>']); // on - $context->endPrefix(); } - - return [$joinSpecArgArray]; + return [ + 'spec' => $this->joinsSpecification, + 'params' => $joinSpecArgArray + ]; } } diff --git a/src/Sql/Builder/IbmDb2/SelectBuilder.php b/src/Sql/Builder/IbmDb2/SelectBuilder.php index 15d887adfe..f6f980a867 100644 --- a/src/Sql/Builder/IbmDb2/SelectBuilder.php +++ b/src/Sql/Builder/IbmDb2/SelectBuilder.php @@ -11,24 +11,32 @@ use Zend\Db\Sql\Select; use Zend\Db\Sql\Builder\sql92\SelectBuilder as BaseBuilder; +use Zend\Db\Sql\Builder\Builder; use Zend\Db\Sql\Builder\Context; class SelectBuilder extends BaseBuilder { /** - * @see Select::renderTable + * {@inheritDoc} */ - protected function renderTable($table, $alias = null) + public function __construct(Builder $platformBuilder) { - return $table . ' ' . $alias; + parent::__construct($platformBuilder); + $asSpec = [ + 'byCount' => [ + 1 => '%1$s', 2 => '%1$s %2$s' + ], + ]; + $this->selectColumnsTableSpecification['byArgNumber'][2] = $asSpec; + $this->selectFullSpecification['byArgNumber'][3] = $asSpec; } - protected function build_Limit(Select $sqlObject, Context $context) + protected function build_Limit(Select $sqlObject, Context $context, &$sqls = null) { return; } - protected function build_Offset(Select $sqlObject, Context $context, &$sqls = null, &$parameters = null) + protected function build_Offset(Select $sqlObject, Context $context, &$sqls = null) { $LIMIT = $sqlObject->limit; $OFFSET = $sqlObject->offset; @@ -36,7 +44,7 @@ protected function build_Offset(Select $sqlObject, Context $context, &$sqls = nu return; } - $selectParameters = $parameters[self::SPECIFICATION_SELECT]; + $selectParameters = $sqls['select']['params']; $starSuffix = $context->getPlatform()->getIdentifierSeparator() . Select::SQL_STAR; foreach ($selectParameters[0] as $i => $columnParameters) { @@ -55,10 +63,10 @@ protected function build_Offset(Select $sqlObject, Context $context, &$sqls = nu } // first, produce column list without compound names (using the AS portion only) - array_unshift($sqls, $this->createSqlFromSpecificationAndParameters( - ['SELECT %1$s FROM (' => current($this->specifications[self::SPECIFICATION_SELECT])], - $selectParameters - )); + $SSS = $sqls['select']; + $SSS['spec']['format'] = 'SELECT %1$s FROM ('; + $SSS['params'] = $selectParameters; + array_unshift($sqls, $this->buildSqlString($SSS, $context)); $offset = ((int) $OFFSET > 0) ? (int) $OFFSET + 1 : (int) $OFFSET; $limit = (int) $LIMIT + (int) $OFFSET; @@ -77,21 +85,16 @@ protected function build_Offset(Select $sqlObject, Context $context, &$sqls = nu $limit )); - if (isset($sqls[self::SPECIFICATION_ORDER])) { - $orderBy = $sqls[self::SPECIFICATION_ORDER]; - unset($sqls[self::SPECIFICATION_ORDER]); + if (isset($sqls['order'])) { + $orderBy = $sqls['order']; + unset($sqls['order']); } else { $orderBy = ''; } // add a column for row_number() using the order specification //dense_rank() - $parameters[self::SPECIFICATION_SELECT][0][] = (preg_match('/DISTINCT/i', $sqls[0])) + $sqls['select']['params'][0][] = (preg_match('/DISTINCT/i', $sqls[0])) ? ['DENSE_RANK() OVER (' . $orderBy . ')', 'ZEND_DB_ROWNUM'] : ['ROW_NUMBER() OVER (' . $orderBy . ')', 'ZEND_DB_ROWNUM']; - - $sqls[self::SPECIFICATION_SELECT] = $this->createSqlFromSpecificationAndParameters( - $this->specifications[self::SPECIFICATION_SELECT], - $parameters[self::SPECIFICATION_SELECT] - ); } } diff --git a/src/Sql/Builder/Mysql/Ddl/AlterTableBuilder.php b/src/Sql/Builder/Mysql/Ddl/AlterTableBuilder.php index b3b973d55b..80d257023e 100644 --- a/src/Sql/Builder/Mysql/Ddl/AlterTableBuilder.php +++ b/src/Sql/Builder/Mysql/Ddl/AlterTableBuilder.php @@ -124,7 +124,12 @@ protected function build_AddColumns(AlterTable $sqlObject, Context $context) } $sqls[$i] = $sql; } - return [$sqls]; + return [ + 'spec' => $this->specifications[self::SPECIFICATION_ADD_COLUMNS], + 'params' => [ + $sqls, + ], + ]; } /** @@ -193,7 +198,12 @@ protected function build_ChangeColumns(AlterTable $sqlObject, Context $context) ]; } - return [$sqls]; + return [ + 'spec' => $this->specifications[self::SPECIFICATION_CHANGE_COLUMNS], + 'params' => [ + $sqls, + ], + ]; } /** diff --git a/src/Sql/Builder/Mysql/Ddl/CreateTableBuilder.php b/src/Sql/Builder/Mysql/Ddl/CreateTableBuilder.php index c28de15dae..8055463999 100644 --- a/src/Sql/Builder/Mysql/Ddl/CreateTableBuilder.php +++ b/src/Sql/Builder/Mysql/Ddl/CreateTableBuilder.php @@ -132,8 +132,10 @@ protected function build_Columns(CreateTable $sqlObject, Context $context) $sqls[$i] = $sql; } - - return [$sqls]; + return [ + 'spec' => $this->columnsSpecification, + 'params' => $sqls, + ]; } /** diff --git a/src/Sql/Builder/Mysql/SelectBuilder.php b/src/Sql/Builder/Mysql/SelectBuilder.php index 8f6aa54a5c..312b7ba88b 100644 --- a/src/Sql/Builder/Mysql/SelectBuilder.php +++ b/src/Sql/Builder/Mysql/SelectBuilder.php @@ -23,19 +23,22 @@ class SelectBuilder extends BaseBuilder */ protected function build_Limit(Select $sqlObject, Context $context) { - $limit = $sqlObject->limit; - if ($limit === null) { - return $sqlObject->offset === null - ? null - : ['18446744073709551615']; - } - - if ($context->getParameterContainer()) { + $limit = $limitParam = $sqlObject->limit; + if ($limit === null && $sqlObject->offset !== null) { + $limitParam = '18446744073709551615'; + } elseif ($limit === null) { + return; + } elseif ($context->getParameterContainer()) { $context->getParameterContainer()->offsetSet('limit', $limit, Adapter\ParameterContainer::TYPE_INTEGER); - $limit = $context->getDriver()->formatParameterName('limit'); + $limitParam = $context->getDriver()->formatParameterName('limit'); } - return [$limit]; + return [ + 'spec' => $this->limitSpecification, + 'params' => [ + $limitParam, + ], + ]; } /** @@ -53,7 +56,11 @@ protected function build_Offset(Select $sqlObject, Context $context) $context->getParameterContainer()->offsetSet('offset', $offset, Adapter\ParameterContainer::TYPE_INTEGER); $offset = $context->getDriver()->formatParameterName('offset'); } - - return [$offset]; + return [ + 'spec' => $this->offsetSpecification, + 'params' => [ + $offset, + ], + ]; } } diff --git a/src/Sql/Builder/Oracle/SelectBuilder.php b/src/Sql/Builder/Oracle/SelectBuilder.php index eac29cce59..8a4ca6b0a9 100644 --- a/src/Sql/Builder/Oracle/SelectBuilder.php +++ b/src/Sql/Builder/Oracle/SelectBuilder.php @@ -11,24 +11,33 @@ use Zend\Db\Sql\Select; use Zend\Db\Sql\Builder\sql92\SelectBuilder as BaseBuilder; +use Zend\Db\Sql\Builder\Builder; use Zend\Db\Sql\Builder\Context; class SelectBuilder extends BaseBuilder { /** - * @see \Zend\Db\Sql\Select::renderTable + * {@inheritDoc} */ - protected function renderTable($table, $alias = null) + public function __construct(Builder $platformBuilder) { - return $table . ($alias ? ' ' . $alias : ''); + parent::__construct($platformBuilder); + $asSpec = [ + 'byCount' => [ + 1 => '%1$s', 2 => '%1$s %2$s' + ], + ]; + $this->selectColumnsTableSpecification['byArgNumber'][2] = $asSpec; + $this->selectFullSpecification['byArgNumber'][3] = $asSpec; + $this->joinsSpecification['forEach']['byArgNumber'][2] = $asSpec; } - protected function build_Limit(Select $sqlObject, Context $context) + protected function build_Limit(Select $sqlObject, Context $context, &$sqls = null) { return; } - protected function build_Offset(Select $sqlObject, Context $context, &$sqls = null, &$parameters = null) + protected function build_Offset(Select $sqlObject, Context $context, &$sqls = null) { $LIMIT = $sqlObject->limit; $OFFSET = $sqlObject->offset; @@ -36,7 +45,7 @@ protected function build_Offset(Select $sqlObject, Context $context, &$sqls = nu return; } - $selectParameters = $parameters[self::SPECIFICATION_SELECT]; + $selectParameters = $sqls['select']['params']; $starSuffix = $context->getPlatform()->getIdentifierSeparator() . Select::SQL_STAR; foreach ($selectParameters[0] as $i => $columnParameters) { @@ -55,12 +64,15 @@ protected function build_Offset(Select $sqlObject, Context $context, &$sqls = nu } // first, produce column list without compound names (using the AS portion only) - array_unshift($sqls, $this->createSqlFromSpecificationAndParameters( - ['SELECT %1$s FROM (SELECT b.%1$s, rownum b_rownum FROM (' => current($this->specifications[self::SPECIFICATION_SELECT])], $selectParameters - )); + $SSS = $sqls['select']; + $SSS['spec']['format'] = 'SELECT %1$s FROM (SELECT b.%1$s, rownum b_rownum FROM ('; - if ($context->getParameterContainer()) { - $parameterContainer = $context->getParameterContainer(); + array_unshift($sqls, [ + 'spec' => $SSS['spec'], + 'params' => $selectParameters, + ]); + + if ($parameterContainer = $context->getParameterContainer()) { if ($LIMIT === null) { array_push($sqls, ') b ) WHERE b_rownum > (:offset)'); $parameterContainer->offsetSet('offset', $OFFSET, $parameterContainer::TYPE_INTEGER); @@ -85,10 +97,10 @@ protected function build_Offset(Select $sqlObject, Context $context, &$sqls = nu ); } } - - $sqls[self::SPECIFICATION_SELECT] = $this->createSqlFromSpecificationAndParameters( - $this->specifications[self::SPECIFICATION_SELECT], - $parameters[self::SPECIFICATION_SELECT] - ); + $parameters = $sqls['select']['params']; + $sqls['select'] = [ + 'spec' => $sqls['select']['spec'], + 'params' => $parameters, + ]; } } diff --git a/src/Sql/Builder/SqlServer/Ddl/CreateTableBuilder.php b/src/Sql/Builder/SqlServer/Ddl/CreateTableBuilder.php index ec767e3e47..e1f3d7be11 100644 --- a/src/Sql/Builder/SqlServer/Ddl/CreateTableBuilder.php +++ b/src/Sql/Builder/SqlServer/Ddl/CreateTableBuilder.php @@ -24,8 +24,11 @@ protected function build_Table(CreateTable $sqlObject, Context $context) { $table = ($sqlObject->isTemporary ? '#' : '') . ltrim($sqlObject->table, '#'); return [ - '', - $context->getPlatform()->quoteIdentifier($table), + 'spec' => $this->tableSpecification, + 'params' => [ + '', + $context->getPlatform()->quoteIdentifier($table), + ], ]; } } diff --git a/src/Sql/Builder/SqlServer/SelectBuilder.php b/src/Sql/Builder/SqlServer/SelectBuilder.php index 31e1f81ee6..8bcc48b854 100644 --- a/src/Sql/Builder/SqlServer/SelectBuilder.php +++ b/src/Sql/Builder/SqlServer/SelectBuilder.php @@ -15,12 +15,12 @@ class SelectBuilder extends BaseBuilder { - protected function build_Limit(Select $sqlObject, Context $context) + protected function build_Limit(Select $sqlObject, Context $context, &$sqls = null) { return; } - protected function build_Offset(Select $sqlObject, Context $context, &$sqls = null, &$parameters = null) + protected function build_Offset(Select $sqlObject, Context $context, &$sqls = null) { $LIMIT = $sqlObject->limit; $OFFSET = $sqlObject->offset; @@ -28,7 +28,7 @@ protected function build_Offset(Select $sqlObject, Context $context, &$sqls = nu return; } - $selectParameters = $parameters[self::SPECIFICATION_SELECT]; + $selectParameters = $sqls['select']['params']; /** if this is a DISTINCT query then real SELECT part goes to second element in array **/ $parameterIndex = 0; @@ -51,42 +51,54 @@ protected function build_Offset(Select $sqlObject, Context $context, &$sqls = nu } // first, produce column list without compound names (using the AS portion only) - array_unshift($sqls, $this->createSqlFromSpecificationAndParameters( - ['SELECT %1$s FROM (' => current($this->specifications[self::SPECIFICATION_SELECT])], - $selectParameters - )); + $SSS = $sqls['select']; + $SSS['spec']['format'] = 'SELECT %1$s FROM ('; - if ($context->getParameterContainer()) { - $parameterContainer = $context->getParameterContainer(); + array_unshift($sqls, [ + 'spec' => $SSS['spec'], + 'params' => $selectParameters, + ]); + + if ($parameterContainer = $context->getParameterContainer()) { // create bottom part of query, with offset and limit using row_number - $limitParamName = $context->getDriver()->formatParameterName('limit'); - $offsetParamName = $context->getDriver()->formatParameterName('offset'); - $offsetForSumParamName = $context->getDriver()->formatParameterName('offsetForSum'); - array_push($sqls, ') AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ' - . $offsetParamName . '+1 AND ' . $limitParamName . '+' . $offsetForSumParamName); + $sqls[] = + ') AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ' + . $context->getDriver()->formatParameterName('offset') + . '+1 AND ' + . $context->getDriver()->formatParameterName('limit') + . '+' + . $context->getDriver()->formatParameterName('offsetForSum'); + $parameterContainer->offsetSet('offset', $OFFSET); $parameterContainer->offsetSet('limit', $LIMIT); $parameterContainer->offsetSetReference('offsetForSum', 'offset'); } else { - array_push($sqls, ') AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ' - . (int) $OFFSET . '+1 AND ' - . (int) $LIMIT . '+' . (int) $OFFSET - ); + $sqls[] = + ') AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ' + . (int) $OFFSET + . '+1 AND ' + . (int) $LIMIT + . '+' + . (int) $OFFSET; } - if (isset($sqls[self::SPECIFICATION_ORDER])) { - $orderBy = $sqls[self::SPECIFICATION_ORDER]; - unset($sqls[self::SPECIFICATION_ORDER]); + if (isset($sqls['order'])) { + $orderBy = $this->buildSqlString($sqls['order'], $context); + unset($sqls['order']); } else { $orderBy = 'ORDER BY (SELECT 1)'; } // add a column for row_number() using the order specification - $parameters[self::SPECIFICATION_SELECT][$parameterIndex][] = ['ROW_NUMBER() OVER (' . $orderBy . ')', '[__ZEND_ROW_NUMBER]']; + $parameters = $sqls['select']['params']; + $parameters[$parameterIndex][] = [ + 'ROW_NUMBER() OVER (' . $orderBy . ')', + '[__ZEND_ROW_NUMBER]' + ]; - $sqls[self::SPECIFICATION_SELECT] = $this->createSqlFromSpecificationAndParameters( - $this->specifications[self::SPECIFICATION_SELECT], - $parameters[self::SPECIFICATION_SELECT] - ); + $sqls['select'] = [ + 'spec' => $sqls['select']['spec'], + 'params' => $parameters, + ]; } } diff --git a/src/Sql/Builder/sql92/CombineBuilder.php b/src/Sql/Builder/sql92/CombineBuilder.php index cad88b084f..bc1142dc0f 100644 --- a/src/Sql/Builder/sql92/CombineBuilder.php +++ b/src/Sql/Builder/sql92/CombineBuilder.php @@ -14,36 +14,27 @@ class CombineBuilder extends AbstractSqlBuilder { - const SPECIFICATION_COMBINE = 'combine'; - - protected $specifications = [ - self::SPECIFICATION_COMBINE => '%1$s (%2$s) ', - ]; - /** * @param \Zend\Db\Sql\Combine $sqlObject * @param Context $context - * @return string + * @return array */ - protected function buildSqlString($sqlObject, Context $context) + public function build($sqlObject, Context $context) { - $COMBINE = $sqlObject->combine; - if (!$COMBINE) { - return; - } - - $sql = ''; - foreach ($COMBINE as $i => $combine) { + $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Combine', __METHOD__); + $res = []; + foreach ($sqlObject->combine as $i => $combine) { $type = $i == 0 ? '' - : strtoupper($combine['type'] . ($combine['modifier'] ? ' ' . $combine['modifier'] : '')); - $select = $this->buildSubSelect($combine['select'], $context); - $sql .= sprintf( - $this->specifications[self::SPECIFICATION_COMBINE], - $type, - $select - ); + : strtoupper($combine['type'] . ($combine['modifier'] ? ' ' . $combine['modifier'] : '')) . " "; + $res[] = [ + 'spec' => '%1$s%2$s', + 'params' => [ + $type, + $combine['select'] + ], + ]; } - return trim($sql, ' '); + return $res; } } diff --git a/src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php b/src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php index 3be4a88f10..2aa487ab6f 100644 --- a/src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php @@ -15,42 +15,46 @@ class AlterTableBuilder extends AbstractSqlBuilder { - const SPECIFICATION_TABLE = 'table'; - const SPECIFICATION_ADD_COLUMNS = 'addColumns'; - const SPECIFICATION_CHANGE_COLUMNS = 'changeColumns'; - const SPECIFICATION_DROP_COLUMNS = 'dropColumns'; - const SPECIFICATION_ADD_CONSTRAINTS = 'addConstraints'; - const SPECIFICATION_DROP_CONSTRAINTS = 'dropConstraints'; - - protected $specifications = [ - self::SPECIFICATION_TABLE => "ALTER TABLE %1\$s\n", - self::SPECIFICATION_ADD_COLUMNS => [ - "%1\$s" => [ - [1 => "ADD COLUMN %1\$s,\n", 'combinedby' => ""] - ] - ], - self::SPECIFICATION_CHANGE_COLUMNS => [ - "%1\$s" => [ - [2 => "CHANGE COLUMN %1\$s %2\$s,\n", 'combinedby' => ""], - ] - ], - self::SPECIFICATION_DROP_COLUMNS => [ - "%1\$s" => [ - [1 => "DROP COLUMN %1\$s,\n", 'combinedby' => ""], - ] - ], - self::SPECIFICATION_ADD_CONSTRAINTS => [ - "%1\$s" => [ - [1 => "ADD %1\$s,\n", 'combinedby' => ""], - ] - ], - self::SPECIFICATION_DROP_CONSTRAINTS => [ - "%1\$s" => [ - [1 => "DROP CONSTRAINT %1\$s,\n", 'combinedby' => ""], - ] - ] + protected $tableSpecification = "ALTER TABLE %1\$s\n"; + protected $addColumnsSpecification = [ + 'forEach' => "ADD COLUMN %1\$s,\n", + 'implode' => " ", + ]; + protected $changeColumnsSpecification = [ + 'forEach' => "CHANGE COLUMN %1\$s %2\$s,\n", + 'implode' => "", + ]; + protected $dropColumnsSpecification = [ + 'forEach' => "DROP COLUMN %1\$s,\n", + 'implode' => "", + ]; + protected $addConstraintsSpecification = [ + 'forEach' => "ADD %1\$s,\n", + 'implode' => "", + ]; + protected $dropConstraintsSpecification = [ + 'forEach' => "DROP CONSTRAINT %1\$s,\n", + 'implode' => "", ]; + /** + * @param AlterTable $sqlObject + * @param Context $context + * @return array + */ + public function build($sqlObject, Context $context) + { + $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Ddl\AlterTable', __METHOD__); + return [ + $this->build_Table($sqlObject, $context), + $this->build_AddColumns($sqlObject, $context), + $this->build_ChangeColumns($sqlObject, $context), + $this->build_DropColumns($sqlObject, $context), + $this->build_AddConstraints($sqlObject, $context), + $this->build_DropConstraints($sqlObject, $context), + ]; + } + /** * @param AlterTable $sqlObject * @param Context $context @@ -58,7 +62,12 @@ class AlterTableBuilder extends AbstractSqlBuilder */ protected function build_Table(AlterTable $sqlObject, Context $context) { - return [$context->getPlatform()->quoteIdentifier($sqlObject->table)]; + return [ + 'spec' => $this->tableSpecification, + 'params' => [ + $context->getPlatform()->quoteIdentifier($sqlObject->table), + ], + ]; } /** @@ -68,12 +77,10 @@ protected function build_Table(AlterTable $sqlObject, Context $context) */ protected function build_AddColumns(AlterTable $sqlObject, Context $context) { - $sqls = []; - foreach ($sqlObject->addColumns as $column) { - $sqls[] = $this->buildSqlString($column, $context); - } - - return [$sqls]; + return [ + 'spec' => $this->addColumnsSpecification, + 'params' => $sqlObject->addColumns, + ]; } /** @@ -87,11 +94,13 @@ protected function build_ChangeColumns(AlterTable $sqlObject, Context $context) foreach ($sqlObject->changeColumns as $name => $column) { $sqls[] = [ $context->getPlatform()->quoteIdentifier($name), - $this->buildSqlString($column, $context) + $column ]; } - - return [$sqls]; + return [ + 'spec' => $this->changeColumnsSpecification, + 'params' => $sqls, + ]; } /** @@ -101,12 +110,14 @@ protected function build_ChangeColumns(AlterTable $sqlObject, Context $context) */ protected function build_DropColumns(AlterTable $sqlObject, Context $context) { - $sqls = []; + $columns = []; foreach ($sqlObject->dropColumns as $column) { - $sqls[] = $context->getPlatform()->quoteIdentifier($column); + $columns[] = $context->getPlatform()->quoteIdentifier($column); } - - return [$sqls]; + return [ + 'spec' => $this->dropColumnsSpecification, + 'params' => $columns, + ]; } /** @@ -116,12 +127,10 @@ protected function build_DropColumns(AlterTable $sqlObject, Context $context) */ protected function build_AddConstraints(AlterTable $sqlObject, Context $context) { - $sqls = []; - foreach ($sqlObject->addConstraints as $constraint) { - $sqls[] = $this->buildSqlString($constraint, $context); - } - - return [$sqls]; + return [ + 'spec' => $this->addConstraintsSpecification, + 'params' => $sqlObject->addConstraints, + ]; } /** @@ -135,7 +144,9 @@ protected function build_DropConstraints(AlterTable $sqlObject, Context $context foreach ($sqlObject->dropConstraints as $constraint) { $sqls[] = $context->getPlatform()->quoteIdentifier($constraint); } - - return [$sqls]; + return [ + 'spec' => $this->dropConstraintsSpecification, + 'params' => $sqls, + ]; } } diff --git a/src/Sql/Builder/sql92/Ddl/Column/AbstractLengthColumnBuilder.php b/src/Sql/Builder/sql92/Ddl/Column/AbstractLengthColumnBuilder.php index d2252eccaf..f3d91dafcf 100644 --- a/src/Sql/Builder/sql92/Ddl/Column/AbstractLengthColumnBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/Column/AbstractLengthColumnBuilder.php @@ -13,13 +13,13 @@ class AbstractLengthColumnBuilder extends ColumnBuilder { - public function getExpressionData($column, Context $context) + public function build($column, Context $context) { $this->validateSqlObject($column, 'Zend\Db\Sql\Ddl\Column\AbstractLengthColumn', __METHOD__); - $data = parent::getExpressionData($column, $context); + $data = parent::build($column, $context); if ($this->getLengthExpression($column)) { - $data[0][1][1]->setValue($data[0][1][1]->getValue() . '(' . $this->getLengthExpression($column) . ')'); + $data[0]['params'][1]->setValue($data[0]['params'][1]->getValue() . '(' . $this->getLengthExpression($column) . ')'); } return $data; diff --git a/src/Sql/Builder/sql92/Ddl/Column/AbstractTimestampColumnBuilder.php b/src/Sql/Builder/sql92/Ddl/Column/AbstractTimestampColumnBuilder.php index 7b4614ba18..b8611512fa 100644 --- a/src/Sql/Builder/sql92/Ddl/Column/AbstractTimestampColumnBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/Column/AbstractTimestampColumnBuilder.php @@ -15,7 +15,7 @@ class AbstractTimestampColumnBuilder extends ColumnBuilder { - public function getExpressionData($column, Context $context) + public function build($column, Context $context) { $this->validateSqlObject($column, 'Zend\Db\Sql\Ddl\Column\AbstractTimestampColumn', __METHOD__); $spec = $this->specification; @@ -42,8 +42,8 @@ public function getExpressionData($column, Context $context) } $data = [[ - $spec, - $params, + 'spec' => $spec, + 'params' => $params, ]]; foreach ($column->getConstraints() as $constraint) { diff --git a/src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php b/src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php index 04ff740d17..da94272b58 100644 --- a/src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php @@ -23,7 +23,7 @@ class ColumnBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function getExpressionData($column, Context $context) + public function build($column, Context $context) { $this->validateSqlObject($column, 'Zend\Db\Sql\Ddl\Column\Column', __METHOD__); $spec = $this->specification; @@ -43,15 +43,15 @@ public function getExpressionData($column, Context $context) } $data = [[ - $spec, - $params, + 'spec' => $spec, + 'params' => $params, ]]; foreach ($column->getConstraints() as $constraint) { $data[] = ' '; $data = array_merge( $data, - $this->platformBuilder->getPlatformBuilder($constraint, $context)->getExpressionData($constraint, $context) + $this->platformBuilder->getPlatformBuilder($constraint, $context)->build($constraint, $context) ); } diff --git a/src/Sql/Builder/sql92/Ddl/Column/IntegerBuilder.php b/src/Sql/Builder/sql92/Ddl/Column/IntegerBuilder.php index 6f61b89578..2eff8cd723 100644 --- a/src/Sql/Builder/sql92/Ddl/Column/IntegerBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/Column/IntegerBuilder.php @@ -13,10 +13,10 @@ class IntegerBuilder extends ColumnBuilder { - public function getExpressionData($column, Context $context) + public function build($column, Context $context) { $this->validateSqlObject($column, 'Zend\Db\Sql\Ddl\Column\Integer', __METHOD__); - $data = parent::getExpressionData($column, $context); + $data = parent::build($column, $context); $options = $column->getOptions(); if (isset($options['length'])) { diff --git a/src/Sql/Builder/sql92/Ddl/Constraint/AbstractBuilder.php b/src/Sql/Builder/sql92/Ddl/Constraint/AbstractBuilder.php index 98840321b8..b697b5cf6d 100644 --- a/src/Sql/Builder/sql92/Ddl/Constraint/AbstractBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/Constraint/AbstractBuilder.php @@ -36,7 +36,7 @@ class AbstractBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function getExpressionData($constraint, Context $context) + public function build($constraint, Context $context) { $this->validateSqlObject($constraint, 'Zend\Db\Sql\Ddl\Constraint\ConstraintInterface', __METHOD__); $parameters = []; @@ -60,8 +60,8 @@ public function getExpressionData($constraint, Context $context) } return [[ - $spec, - $parameters, + 'spec' => $spec, + 'params' => $parameters, ]]; } } diff --git a/src/Sql/Builder/sql92/Ddl/Constraint/CheckBuilder.php b/src/Sql/Builder/sql92/Ddl/Constraint/CheckBuilder.php index feb7181dc1..5b4161047e 100644 --- a/src/Sql/Builder/sql92/Ddl/Constraint/CheckBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/Constraint/CheckBuilder.php @@ -25,7 +25,7 @@ class CheckBuilder extends AbstractBuilder * @param Context $context * @return array */ - public function getExpressionData($check, Context $context) + public function build($check, Context $context) { $this->validateSqlObject($check, 'Zend\Db\Sql\Ddl\Constraint\Check', __METHOD__); $values = []; @@ -39,8 +39,8 @@ public function getExpressionData($check, Context $context) $values[] = new ExpressionParameter($check->getExpression(), ExpressionInterface::TYPE_LITERAL); return [[ - $spec . $this->specification, - $values, + 'spec' => $spec . $this->specification, + 'params' => $values, ]]; } } diff --git a/src/Sql/Builder/sql92/Ddl/Constraint/ForeignKeyBuilder.php b/src/Sql/Builder/sql92/Ddl/Constraint/ForeignKeyBuilder.php index 00bbe26578..e2917bd6d5 100644 --- a/src/Sql/Builder/sql92/Ddl/Constraint/ForeignKeyBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/Constraint/ForeignKeyBuilder.php @@ -33,11 +33,11 @@ class ForeignKeyBuilder extends AbstractBuilder * @param Context $context * @return array */ - public function getExpressionData($constraint, Context $context) + public function build($constraint, Context $context) { $this->validateSqlObject($constraint, 'Zend\Db\Sql\Ddl\Constraint\ForeignKey', __METHOD__); - $data = parent::getExpressionData($constraint, $context); - $parameters = &$data[0][1]; + $data = parent::build($constraint, $context); + $parameters = &$data[0]['params']; $parameters[] = new ExpressionParameter($constraint->getReferenceTable(), ExpressionInterface::TYPE_IDENTIFIER); $spec = ''; @@ -49,7 +49,7 @@ public function getExpressionData($constraint, Context $context) $spec = '(' . rtrim($spec, ', ') . ') '; } - $data[0][0] .= $this->referenceSpecification[0] . $spec . $this->referenceSpecification[1]; + $data[0]['spec'] .= $this->referenceSpecification[0] . $spec . $this->referenceSpecification[1]; $parameters[] = new ExpressionParameter($constraint->getOnDeleteRule(), ExpressionInterface::TYPE_LITERAL); $parameters[] = new ExpressionParameter($constraint->getOnUpdateRule(), ExpressionInterface::TYPE_LITERAL); diff --git a/src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php b/src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php index 478dc1bd3f..eb285339e0 100644 --- a/src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php @@ -15,25 +15,35 @@ class CreateTableBuilder extends AbstractSqlBuilder { - const SPECIFICATION_TABLE = 'table'; - const SPECIFICATION_COLUMNS = 'columns'; - const SPECIFICATION_CONSTRAINTS = 'constraints'; - - protected $specifications = [ - self::SPECIFICATION_TABLE => 'CREATE %1$sTABLE %2$s (', - self::SPECIFICATION_COLUMNS => [ - "\n %1\$s" => [ - [1 => '%1$s', 'combinedby' => ",\n "] - ] - ], - 'combinedBy' => ",", - self::SPECIFICATION_CONSTRAINTS => [ - "\n %1\$s" => [ - [1 => '%1$s', 'combinedby' => ",\n "] - ] + protected $tableSpecification = 'CREATE %1$sTABLE %2$s ('; + protected $columnsSpecification = [ + 'implode' => [ + 'prefix' => "\n ", + 'glue' => ",\n ", ], - 'statementEnd' => '%1$s', ]; + protected $combinedBySpecification = ",\n "; + protected $constraintsSpecification = [ + 'implode' => ",\n ", + ]; + protected $statementEndSpecification = "\n)"; + + /** + * @param CreateTable $sqlObject + * @param Context $context + * @return array + */ + public function build($sqlObject, Context $context) + { + $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Ddl\CreateTable', __METHOD__); + return [ + $this->build_Table($sqlObject, $context), + $this->build_Columns($sqlObject, $context), + $this->build_Combinedby($sqlObject, $context), + $this->build_Constraints($sqlObject, $context), + $this->build_StatementEnd($sqlObject, $context), + ]; + } /** * @param CreateTable $sqlObject @@ -43,8 +53,11 @@ class CreateTableBuilder extends AbstractSqlBuilder protected function build_Table(CreateTable $sqlObject, Context $context) { return [ - $sqlObject->isTemporary ? 'TEMPORARY ' : '', - $context->getPlatform()->quoteIdentifier($sqlObject->table), + 'spec' => $this->tableSpecification, + 'params' => [ + $sqlObject->isTemporary ? 'TEMPORARY ' : '', + $context->getPlatform()->quoteIdentifier($sqlObject->table), + ], ]; } @@ -55,18 +68,13 @@ protected function build_Table(CreateTable $sqlObject, Context $context) */ protected function build_Columns(CreateTable $sqlObject, Context $context) { - $COLUMNS = $sqlObject->columns; - if (! $COLUMNS) { + if (! $sqlObject->columns) { return; } - - $sqls = []; - - foreach ($COLUMNS as $column) { - $sqls[] = $this->buildSqlString($column, $context); - } - - return [$sqls]; + return [ + 'spec' => $this->columnsSpecification, + 'params' => $sqlObject->columns, + ]; } /** @@ -77,7 +85,10 @@ protected function build_Columns(CreateTable $sqlObject, Context $context) protected function build_Combinedby(CreateTable $sqlObject, Context $context) { if ($sqlObject->constraints && $sqlObject->columns) { - return $this->specifications['combinedBy']; + return $this->combinedBySpecification; + } + if ($sqlObject->constraints && !$sqlObject->columns) { + return "\n "; } } @@ -88,18 +99,14 @@ protected function build_Combinedby(CreateTable $sqlObject, Context $context) */ protected function build_Constraints(CreateTable $sqlObject, Context $context) { - $CONSTRAINTS = $sqlObject->constraints; - if (!$CONSTRAINTS) { + if (!$sqlObject->constraints) { return; } - $sqls = []; - - foreach ($CONSTRAINTS as $constraint) { - $sqls[] = $this->buildSqlString($constraint, $context); - } - - return [$sqls]; + return [ + 'spec' => $this->constraintsSpecification, + 'params' => $sqlObject->constraints, + ]; } /** @@ -109,6 +116,6 @@ protected function build_Constraints(CreateTable $sqlObject, Context $context) */ protected function build_StatementEnd(CreateTable $sqlObject, Context $context) { - return ["\n)"]; + return $this->statementEndSpecification; } } diff --git a/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php b/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php index e190bd97a2..bf6d3f3a0e 100644 --- a/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php @@ -15,11 +15,20 @@ class DropTableBuilder extends AbstractSqlBuilder { - const SPECIFICATION_TABLE = 'table'; + protected $tableSpecification = 'DROP TABLE %1$s'; - protected $specifications = [ - self::SPECIFICATION_TABLE => 'DROP TABLE %1$s' - ]; + /** + * @param DropTable $sqlObject + * @param Context $context + * @return array + */ + public function build($sqlObject, Context $context) + { + $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Ddl\DropTable', __METHOD__); + return [ + $this->build_Table($sqlObject, $context), + ]; + } /** * @param DropTable $sqlObject @@ -28,6 +37,11 @@ class DropTableBuilder extends AbstractSqlBuilder */ protected function build_Table(DropTable $sqlObject, Context $context) { - return [$context->getPlatform()->quoteIdentifier($sqlObject->table)]; + return [ + 'spec' => $this->tableSpecification, + 'params' => [ + $context->getPlatform()->quoteIdentifier($sqlObject->table), + ], + ]; } } diff --git a/src/Sql/Builder/sql92/Ddl/Index/IndexBuilder.php b/src/Sql/Builder/sql92/Ddl/Index/IndexBuilder.php index af6a9761f6..2eeda9a6d1 100644 --- a/src/Sql/Builder/sql92/Ddl/Index/IndexBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/Index/IndexBuilder.php @@ -26,7 +26,7 @@ class IndexBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function getExpressionData($index, Context $context) + public function build($index, Context $context) { $this->validateSqlObject($index, 'Zend\Db\Sql\Ddl\Index\AbstractIndex', __METHOD__); $properties = [ @@ -40,8 +40,8 @@ public function getExpressionData($index, Context $context) } return [[ - str_replace('...', rtrim($spec, ', '), $this->specification), - $properties, + 'spec' => str_replace('...', rtrim($spec, ', '), $this->specification), + 'params' => $properties, ]]; } } diff --git a/src/Sql/Builder/sql92/DeleteBuilder.php b/src/Sql/Builder/sql92/DeleteBuilder.php index e0f35f74d0..13d1e489bb 100644 --- a/src/Sql/Builder/sql92/DeleteBuilder.php +++ b/src/Sql/Builder/sql92/DeleteBuilder.php @@ -15,13 +15,22 @@ class DeleteBuilder extends AbstractSqlBuilder { - const SPECIFICATION_DELETE = 'delete'; - const SPECIFICATION_WHERE = 'where'; + protected $deleteSpecification ='DELETE FROM %1$s'; + protected $whereSpecification = 'WHERE %1$s'; - protected $specifications = [ - self::SPECIFICATION_DELETE => 'DELETE FROM %1$s', - self::SPECIFICATION_WHERE => 'WHERE %1$s' - ]; + /** + * @param Delete $sqlObject + * @param Context $context + * @return array + */ + public function build($sqlObject, Context $context) + { + $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Delete', __METHOD__); + return [ + $this->build_Delete($sqlObject, $context), + $this->build_Where($sqlObject, $context), + ]; + } /** * @param Delete $sqlObject @@ -30,10 +39,12 @@ class DeleteBuilder extends AbstractSqlBuilder */ protected function build_Delete(Delete $sqlObject, Context $context) { - return sprintf( - $this->specifications[self::SPECIFICATION_DELETE], - $this->resolveTable($sqlObject->table, $context) - ); + return [ + 'spec' => $this->deleteSpecification, + 'params' => [ + $this->nornalizeTable($sqlObject->table, $context)['name'], + ], + ]; } /** @@ -43,14 +54,12 @@ protected function build_Delete(Delete $sqlObject, Context $context) */ protected function build_Where(Delete $sqlObject, Context $context) { - $WHERE = $sqlObject->where; - if ($WHERE->count() == 0) { + if ($sqlObject->where->count() == 0) { return; } - - return sprintf( - $this->specifications[self::SPECIFICATION_WHERE], - $this->buildSqlString($WHERE, $context) - ); + return [ + 'spec' => $this->whereSpecification, + 'params' => $sqlObject->where + ]; } } diff --git a/src/Sql/Builder/sql92/ExpressionBuilder.php b/src/Sql/Builder/sql92/ExpressionBuilder.php index 4c8c4f13f5..5265017683 100644 --- a/src/Sql/Builder/sql92/ExpressionBuilder.php +++ b/src/Sql/Builder/sql92/ExpressionBuilder.php @@ -22,19 +22,13 @@ class ExpressionBuilder extends AbstractSqlBuilder * @return array * @throws Exception\RuntimeException */ - public function getExpressionData($expression, Context $context) + public function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Expression', __METHOD__); $parameters = (is_scalar($expression->getParameters())) ? [$expression->getParameters()] : $expression->getParameters(); $parametersCount = count($parameters); $expression = str_replace('%', '%%', $expression->getExpression()); - if ($parametersCount == 0) { - return [ - str_ireplace(Expression::PLACEHOLDER, '', $expression) - ]; - } - // assign locally, escaping % signs $expression = str_replace(Expression::PLACEHOLDER, '%s', $expression, $count); // test number of replacements without considering same variable begin used many times first, which is @@ -43,8 +37,8 @@ public function getExpressionData($expression, Context $context) throw new Exception\RuntimeException('The number of replacements in the expression does not match the number of parameters'); } return [[ - $expression, - $parameters, + 'spec' => $expression, + 'params' => $parameters, ]]; } } diff --git a/src/Sql/Builder/sql92/InsertBuilder.php b/src/Sql/Builder/sql92/InsertBuilder.php index 4ec73ab5b7..7bb8ef02db 100644 --- a/src/Sql/Builder/sql92/InsertBuilder.php +++ b/src/Sql/Builder/sql92/InsertBuilder.php @@ -16,20 +16,48 @@ class InsertBuilder extends AbstractSqlBuilder { - const SPECIFICATION_INSERT = 'insert'; - const SPECIFICATION_SELECT = 'select'; /** * @var array Specification array */ - protected $specifications = [ - self::SPECIFICATION_INSERT => 'INSERT INTO %1$s (%2$s) VALUES (%3$s)', - self::SPECIFICATION_SELECT => 'INSERT INTO %1$s %2$s %3$s', + protected $insertSpecification = [ + 'byArgNumber' => [ + 2 => ['implode' => ', '], + 3 => ['implode' => ', '], + ], + 'format' => 'INSERT INTO %1$s (%2$s) VALUES (%3$s)', + ]; + protected $selectSpecification = [ + 'byCount' => [ + 2 => [ + 'format' => 'INSERT INTO %1$s %2$s' + ], + 3 => [ + 'byArgNumber' => [ + 2 => ['implode' => ', '], + ], + 'format' => 'INSERT INTO %1$s (%2$s) %3$s' + ], + ], ]; /** * @param Insert $sqlObject * @param Context $context - * @return null|string + * @return array + */ + public function build($sqlObject, Context $context) + { + $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Insert', __METHOD__); + return [ + $this->build_Insert($sqlObject, $context), + $this->build_Select($sqlObject, $context), + ]; + } + + /** + * @param Insert $sqlObject + * @param Context $context + * @return null|array * @throws Exception\InvalidArgumentException */ protected function build_Insert(Insert $sqlObject, Context $context) @@ -54,12 +82,14 @@ protected function build_Insert(Insert $sqlObject, Context $context) } } - return sprintf( - $this->specifications[self::SPECIFICATION_INSERT], - $this->resolveTable($sqlObject->table, $context), - implode(', ', $columns), - implode(', ', $values) - ); + return [ + 'spec' => $this->insertSpecification, + 'params' => [ + $this->nornalizeTable($sqlObject->table, $context)['name'], + $columns, + $values, + ], + ]; } /** @@ -72,16 +102,23 @@ protected function build_Select(Insert $sqlObject, Context $context) if (!$sqlObject->select) { return; } - $selectSql = $this->buildSubSelect($sqlObject->select, $context); - $columns = array_map([$context->getPlatform(), 'quoteIdentifier'], $sqlObject->columns); - $columns = implode(', ', $columns); - - return sprintf( - $this->specifications[self::SPECIFICATION_SELECT], - $this->resolveTable($sqlObject->table, $context), - $columns ? "($columns)" : "", - $selectSql - ); + if ($sqlObject->columns) { + return [ + 'spec' => $this->selectSpecification, + 'params' => [ + $this->nornalizeTable($sqlObject->table, $context)['name'], + array_map([$context->getPlatform(), 'quoteIdentifier'], $sqlObject->columns), + $sqlObject->select + ], + ]; + } + return [ + 'spec' => $this->selectSpecification, + 'params' => [ + $this->nornalizeTable($sqlObject->table, $context)['name'], + $sqlObject->select + ], + ]; } } diff --git a/src/Sql/Builder/sql92/LiteralBuilder.php b/src/Sql/Builder/sql92/LiteralBuilder.php index 8edc520b7e..1bc954c526 100644 --- a/src/Sql/Builder/sql92/LiteralBuilder.php +++ b/src/Sql/Builder/sql92/LiteralBuilder.php @@ -19,12 +19,11 @@ class LiteralBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function getExpressionData($expression, Context $context) + public function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Literal', __METHOD__); - return [[ - str_replace('%', '%%', $expression->getLiteral()), - [], - ]]; + return [ + 'spec' => $expression->getLiteral() + ]; } } diff --git a/src/Sql/Builder/sql92/Predicate/BetweenBuilder.php b/src/Sql/Builder/sql92/Predicate/BetweenBuilder.php index c3400ec8b4..8388672f1e 100644 --- a/src/Sql/Builder/sql92/Predicate/BetweenBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/BetweenBuilder.php @@ -21,12 +21,12 @@ class BetweenBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function getExpressionData($expression, Context $context) + public function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\Between', __METHOD__); return [[ - $this->specification, - [ + 'spec' => $this->specification, + 'params' => [ $expression->getIdentifier(), $expression->getMinValue(), $expression->getMaxValue(), diff --git a/src/Sql/Builder/sql92/Predicate/InBuilder.php b/src/Sql/Builder/sql92/Predicate/InBuilder.php index 9e9915bae8..324fe58490 100644 --- a/src/Sql/Builder/sql92/Predicate/InBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/InBuilder.php @@ -21,7 +21,7 @@ class InBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function getExpressionData($expression, Context $context) + public function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\In', __METHOD__); $identifier = $expression->getIdentifier(); @@ -30,10 +30,10 @@ public function getExpressionData($expression, Context $context) if (is_array($identifier)) { $identifierSpecFragment = '(' . implode(', ', array_fill(0, count($identifier), '%s')) . ')'; - $replacements = $expression->getIdentifier(); + $replacements = $identifier; } else { $identifierSpecFragment = '%s'; - $replacements[] = $expression->getIdentifier(); + $replacements[] = $identifier; } if (is_array($values)) { @@ -51,8 +51,8 @@ public function getExpressionData($expression, Context $context) } return [[ - $specification, - $replacements, + 'spec' => $specification, + 'params' => $replacements, ]]; } } diff --git a/src/Sql/Builder/sql92/Predicate/IsNullBuilder.php b/src/Sql/Builder/sql92/Predicate/IsNullBuilder.php index 69888c49bb..75fa615648 100644 --- a/src/Sql/Builder/sql92/Predicate/IsNullBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/IsNullBuilder.php @@ -24,12 +24,12 @@ class IsNullBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function getExpressionData($expression, Context $context) + public function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\IsNull', __METHOD__); return [[ - $this->specification, - [$expression->getIdentifier()], + 'spec' => $this->specification, + 'params' => [$expression->getIdentifier()], ]]; } } diff --git a/src/Sql/Builder/sql92/Predicate/LikeBuilder.php b/src/Sql/Builder/sql92/Predicate/LikeBuilder.php index 18cc51754c..56525715ae 100644 --- a/src/Sql/Builder/sql92/Predicate/LikeBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/LikeBuilder.php @@ -24,12 +24,12 @@ class LikeBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function getExpressionData($expression, Context $context) + public function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\Like', __METHOD__); return [[ - $this->specification, - [ + 'spec' => $this->specification, + 'params' => [ $expression->getIdentifier(), $expression->getLike(), ], diff --git a/src/Sql/Builder/sql92/Predicate/NotBetweenBuilder.php b/src/Sql/Builder/sql92/Predicate/NotBetweenBuilder.php index 4d0f845fc6..c390dd8e1f 100644 --- a/src/Sql/Builder/sql92/Predicate/NotBetweenBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/NotBetweenBuilder.php @@ -21,12 +21,12 @@ class NotBetweenBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function getExpressionData($expression, Context $context) + public function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\NotBetween', __METHOD__); return [[ - $this->specification, - [ + 'spec' => $this->specification, + 'params' => [ $expression->getIdentifier(), $expression->getMinValue(), $expression->getMaxValue(), diff --git a/src/Sql/Builder/sql92/Predicate/OperatorBuilder.php b/src/Sql/Builder/sql92/Predicate/OperatorBuilder.php index 47f3877bf7..2825e08715 100644 --- a/src/Sql/Builder/sql92/Predicate/OperatorBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/OperatorBuilder.php @@ -19,12 +19,12 @@ class OperatorBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function getExpressionData($expression, Context $context) + public function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\Operator', __METHOD__); return [[ - '%s ' . $expression->getOperator() . ' %s', - [ + 'spec' => '%s ' . $expression->getOperator() . ' %s', + 'params' => [ $expression->getLeft(), $expression->getRight(), ], diff --git a/src/Sql/Builder/sql92/Predicate/PredicateSetBuilder.php b/src/Sql/Builder/sql92/Predicate/PredicateSetBuilder.php index 2525731b57..6403f02d95 100644 --- a/src/Sql/Builder/sql92/Predicate/PredicateSetBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/PredicateSetBuilder.php @@ -20,7 +20,7 @@ class PredicateSetBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function getExpressionData($expression, Context $context) + public function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\PredicateSet', __METHOD__); $predicates = $expression->getPredicates(); @@ -35,7 +35,7 @@ public function getExpressionData($expression, Context $context) $parts = array_merge( $parts, - $this->platformBuilder->getPlatformBuilder($predicate, $context)->getExpressionData($predicate, $context) + $this->platformBuilder->getPlatformBuilder($predicate, $context)->build($predicate, $context) ); if ($predicate instanceof PredicateSet) { diff --git a/src/Sql/Builder/sql92/SelectBuilder.php b/src/Sql/Builder/sql92/SelectBuilder.php index b257cbb453..fd15ef5e5a 100644 --- a/src/Sql/Builder/sql92/SelectBuilder.php +++ b/src/Sql/Builder/sql92/SelectBuilder.php @@ -10,86 +10,140 @@ namespace Zend\Db\Sql\Builder\sql92; use Zend\Db\Adapter; -use Zend\Db\Sql\TableIdentifier; use Zend\Db\Sql\Select; -use Zend\Db\Sql\SelectableInterface; use Zend\Db\Sql\ExpressionInterface; -use Zend\Db\Sql\Exception; use Zend\Db\Sql\Builder\AbstractSqlBuilder; use Zend\Db\Sql\Builder\Context; class SelectBuilder extends AbstractSqlBuilder { - const SPECIFICATION_SELECT = 'select'; - const SPECIFICATION_JOINS = 'joins'; - const SPECIFICATION_WHERE = 'where'; - const SPECIFICATION_GROUP = 'group'; - const SPECIFICATION_HAVING = 'having'; - const SPECIFICATION_ORDER = 'order'; - const SPECIFICATION_LIMIT = 'limit'; - const SPECIFICATION_OFFSET = 'offset'; - const SPECIFICATION_COMBINE = 'combine'; - - protected $specifications = [ - 'statementStart' => '%1$s', - self::SPECIFICATION_SELECT => [ - 'SELECT %1$s FROM %2$s' => [ - [1 => '%1$s', 2 => '%1$s AS %2$s', 'combinedby' => ', '], - null + protected $statementStartSpecification = '%1$s'; + protected $selectNoTableSpecification = [ + 'byArgNumber' => [ + 1 => [ + 'forEach' => [ + 'byCount' => [ + 1 => '%1$s', 2 => '%1$s AS %2$s' + ], + ], + 'implode' => ', ', ], - 'SELECT %1$s %2$s FROM %3$s' => [ - null, - [1 => '%1$s', 2 => '%1$s AS %2$s', 'combinedby' => ', '], - null + ], + 'format' => 'SELECT %1$s', + ]; + protected $selectColumnsTableSpecification = [ + 'byArgNumber' => [ + 1 => [ + 'forEach' => [ + 'byCount' => [ + 1 => '%1$s', 2 => '%1$s AS %2$s' + ], + ], + 'implode' => ', ', ], - 'SELECT %1$s' => [ - [1 => '%1$s', 2 => '%1$s AS %2$s', 'combinedby' => ', '], + 2 => [ + 'byCount' => [ + 1 => '%1$s', 2 => '%1$s AS %2$s' + ], ], ], - self::SPECIFICATION_JOINS => [ - '%1$s' => [ - [3 => '%1$s JOIN %2$s ON %3$s', 'combinedby' => ' '] - ] + 'format' => 'SELECT %1$s FROM %2$s', + ]; + protected $selectFullSpecification = [ + 'byArgNumber' => [ + 2 => [ + 'forEach' => [ + 'byCount' => [ + 1 => '%1$s', 2 => '%1$s AS %2$s' + ], + ], + 'implode' => ', ', + ], + 3 => [ + 'byCount' => [ + 1 => '%1$s', 2 => '%1$s AS %2$s' + ], + ], ], - self::SPECIFICATION_WHERE => 'WHERE %1$s', - self::SPECIFICATION_GROUP => [ - 'GROUP BY %1$s' => [ - [1 => '%1$s', 'combinedby' => ', '] - ] + 'format' => 'SELECT %1$s %2$s FROM %3$s', + ]; + protected $joinsSpecification = [ + 'forEach' => [ + 'byArgNumber' => [ + 2 => [ + 'byCount' => [ + 1 => '%1$s', 2 => '%1$s AS %2$s' + ], + ], + ], + 'format' => '%1$s JOIN %2$s ON %3$s', ], - self::SPECIFICATION_HAVING => 'HAVING %1$s', - self::SPECIFICATION_ORDER => [ - 'ORDER BY %1$s' => [ - [1 => '%1$s', 2 => '%1$s %2$s', 'combinedby' => ', '] - ] + 'implode' => ' ', + ]; + protected $whereSpecification = 'WHERE %1$s'; + protected $groupSpecification = [ + 'implode' => ', ', + 'format' => 'GROUP BY %1$s', + ]; + protected $havingSpecification = 'HAVING %1$s'; + protected $orderSpecification = [ + 'forEach' => [ + 'byCount' => [ + 1 => '%1$s', 2 => '%1$s %2$s' + ], ], - self::SPECIFICATION_LIMIT => 'LIMIT %1$s', - self::SPECIFICATION_OFFSET => 'OFFSET %1$s', - 'statementEnd' => '%1$s', - self::SPECIFICATION_COMBINE => '%1$s ( %2$s )', + 'implode' => ', ', + 'format' => 'ORDER BY %1$s', ]; + protected $limitSpecification = 'LIMIT %1$s'; + protected $offsetSpecification = 'OFFSET %1$s'; + protected $statementEndSpecification = '%1$s'; + protected $combineSpecification = '%1$s ( %2$s )'; /** * @param Select $sqlObject * @param Context $context * @return array|null */ + public function build($sqlObject, Context $context) + { + $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Select', __METHOD__); + $sqls = []; + $sqls['start'] = $this->build_StatementStart($sqlObject, $context, $sqls); + $sqls['select'] = $this->build_Select($sqlObject, $context, $sqls); + $sqls['joins'] = $this->build_Joins($sqlObject, $context, $sqls); + $sqls['where'] = $this->build_Where($sqlObject, $context, $sqls); + $sqls['group'] = $this->build_Group($sqlObject, $context, $sqls); + $sqls['having'] = $this->build_Having($sqlObject, $context, $sqls); + $sqls['order'] = $this->build_Order($sqlObject, $context, $sqls); + $sqls['limit'] = $this->build_Limit($sqlObject, $context, $sqls); + $sqls['offset'] = $this->build_Offset($sqlObject, $context, $sqls); + $sqls['end'] = $this->build_StatementEnd($sqlObject, $context, $sqls); + $sqls['combine'] = $this->build_Combine($sqlObject, $context, $sqls); + return $sqls; + } + + /** + * @param Select $sqlObject + * @param Context $context + * @return string|null + */ protected function build_StatementStart($sqlObject, Context $context) { if ($sqlObject->combine !== []) { - return ['(']; + return '('; } } /** * @param Select $sqlObject * @param Context $context - * @return array|null + * @return string|null */ protected function build_StatementEnd($sqlObject, Context $context) { if ($sqlObject->combine !== []) { - return [')']; + return ')'; } } @@ -100,7 +154,18 @@ protected function build_StatementEnd($sqlObject, Context $context) */ protected function build_Select(Select $sqlObject, Context $context) { - list($table, $fromTable) = $this->resolveTable($sqlObject->table, $context, $sqlObject); + $table = $this->nornalizeTable($sqlObject->table, $context); + $fromTable = ($sqlObject->prefixColumnsWithTable && $table['columnAlias']) + ? $table['columnAlias'] . $context->getPlatform()->getIdentifierSeparator() + : ''; + unset($table['columnAlias']); + if (!$table['alias']) { + unset($table['alias']); + } + if (!$table['name']) { + $table = null; + } + // build_ table columns $columns = []; foreach ($sqlObject->columns as $columnIndexOrAs => $column) { @@ -128,10 +193,8 @@ protected function build_Select(Select $sqlObject, Context $context) // build_ join columns foreach ($sqlObject->joins as $join) { - $joinName = parent::resolveTable( - is_array($join['name']) ? key($join['name']) : $join['name'], - $context - ); + $jTable = $this->nornalizeTable($join['name'], $context); + $joinName = $jTable['columnAlias']; foreach ($join['columns'] as $jKey => $jColumn) { $jColumns = []; @@ -155,18 +218,30 @@ protected function build_Select(Select $sqlObject, Context $context) } } - if ($quantifier = $sqlObject->quantifier) { - $quantifier = ($quantifier instanceof ExpressionInterface) - ? $this->buildSqlString($quantifier, $context) - : $quantifier; - } - - if (!isset($table)) { - return [$columns]; - } elseif (isset($quantifier)) { - return [$quantifier, $columns, $table]; + if (!$table) { + return [ + 'spec' => $this->selectNoTableSpecification, + 'params' => [ + $columns + ], + ]; + } elseif ($sqlObject->quantifier) { + return [ + 'spec' => $this->selectFullSpecification, + 'params' => [ + $sqlObject->quantifier, + $columns, + $table, + ], + ]; } else { - return [$columns, $table]; + return [ + 'spec' => $this->selectColumnsTableSpecification, + 'params' => [ + $columns, + $table, + ], + ]; } } @@ -181,7 +256,8 @@ protected function build_Where(Select $sqlObject, Context $context) return; } return [ - $this->buildSqlString($sqlObject->where, $context) + 'spec' => $this->whereSpecification, + 'params' => $sqlObject->where, ]; } @@ -198,15 +274,14 @@ protected function build_Group(Select $sqlObject, Context $context) // build_ table columns $groups = []; foreach ($sqlObject->group as $column) { - $groups[] = $this->resolveColumnValue( - [ - 'column' => $column, - 'isIdentifier' => true, - ], - $context - ); + $groups[] = is_scalar($column) + ? $context->getPlatform()->quoteIdentifierInFragment($column) + : $column; } - return [$groups]; + return [ + 'spec' => $this->groupSpecification, + 'params' => $groups, + ]; } /** @@ -220,7 +295,8 @@ protected function build_Having(Select $sqlObject, Context $context) return; } return [ - $this->buildSqlString($sqlObject->having, $context) + 'spec' => $this->havingSpecification, + 'params' => $sqlObject->having, ]; } @@ -238,7 +314,7 @@ protected function build_Order(Select $sqlObject, Context $context) foreach ($sqlObject->order as $k => $v) { if ($v instanceof ExpressionInterface) { $orders[] = [ - $this->buildSqlString($v, $context) + $v ]; continue; } @@ -256,7 +332,10 @@ protected function build_Order(Select $sqlObject, Context $context) $orders[] = [$context->getPlatform()->quoteIdentifierInFragment($k), Select::ORDER_ASCENDING]; } } - return [$orders]; + return [ + 'spec' => $this->orderSpecification, + 'params' => $orders, + ]; } /** @@ -272,9 +351,14 @@ protected function build_Limit(Select $sqlObject, Context $context) } if ($context->getParameterContainer()) { $context->getParameterContainer()->offsetSet('limit', $limit, Adapter\ParameterContainer::TYPE_INTEGER); - return [$context->getDriver()->formatParameterName('limit')]; + $limit = $context->getDriver()->formatParameterName('limit'); + } else { + $limit = $context->getPlatform()->quoteValue($limit); } - return [$context->getPlatform()->quoteValue($limit)]; + return [ + 'spec' => $this->limitSpecification, + 'params' => $limit, + ]; } /** @@ -290,10 +374,14 @@ protected function build_Offset(Select $sqlObject, Context $context) } if ($context->getParameterContainer()) { $context->getParameterContainer()->offsetSet('offset', $offset, Adapter\ParameterContainer::TYPE_INTEGER); - return [$context->getDriver()->formatParameterName('offset')]; + $offset = $context->getDriver()->formatParameterName('offset'); + } else { + $offset = $context->getPlatform()->quoteValue($offset); } - - return [$context->getPlatform()->quoteValue($offset)]; + return [ + 'spec' => $this->offsetSpecification, + 'params' => $offset + ]; } /** @@ -314,54 +402,11 @@ protected function build_Combine(Select $sqlObject, Context $context) } return [ - strtoupper($type), - $this->buildSubSelect($COMBINE['select'], $context), - ]; - } - - /** - * @param array|string|TableIdentifier|Select $table - * @param Context $context - * @param mixed $object - * @return array - */ - protected function resolveTable($table, Context $context, $object = null) - { - $alias = null; - - if (is_array($table)) { - $alias = key($table); - $table = current($table); - } - - $table = parent::resolveTable($table, $context); - - if ($alias) { - $fromTable = $context->getPlatform()->quoteIdentifier($alias); - $table = $this->renderTable($table, $fromTable); - } else { - $fromTable = $table; - } - - if ($object->prefixColumnsWithTable && $fromTable) { - $fromTable .= $context->getPlatform()->getIdentifierSeparator(); - } else { - $fromTable = ''; - } - - return [ - $table, - $fromTable + 'spec' => $this->combineSpecification, + 'params' => [ + strtoupper($type), + $COMBINE['select'], + ], ]; } - - /** - * @param string $table - * @param null|string $alias - * @return string - */ - protected function renderTable($table, $alias = null) - { - return $table . ($alias ? ' AS ' . $alias : ''); - } } diff --git a/src/Sql/Builder/sql92/UpdateBuilder.php b/src/Sql/Builder/sql92/UpdateBuilder.php index a1b65a6b5f..284acf9525 100644 --- a/src/Sql/Builder/sql92/UpdateBuilder.php +++ b/src/Sql/Builder/sql92/UpdateBuilder.php @@ -15,32 +15,62 @@ class UpdateBuilder extends AbstractSqlBuilder { - const SPECIFICATION_UPDATE = 'update'; - const SPECIFICATION_SET = 'set'; - const SPECIFICATION_WHERE = 'where'; - const SPECIFICATION_JOIN = 'joins'; - - protected $specifications = [ - self::SPECIFICATION_UPDATE => 'UPDATE %1$s', - self::SPECIFICATION_JOIN => [ - '%1$s' => [ - [3 => '%1$s JOIN %2$s ON %3$s', 'combinedby' => ' '] - ] + protected $updateSpecification = 'UPDATE %1$s'; + protected $whereSpecification = 'WHERE %1$s'; + /*protected $joinsSpecification = [ + '%1$s' => [ + [3 => '%1$s JOIN %2$s ON %3$s', 'combinedby' => ' '] + ] + ];*/ + protected $joinsSpecification = [ + 'forEach' => [ + 'byArgNumber' => [ + 2 => [ + 'byCount' => [ + 1 => '%1$s', 2 => '%1$s AS %2$s' + ], + ], + ], + 'format' => '%1$s JOIN %2$s ON %3$s', + ], + 'implode' => ' ', + ]; + protected $setSpecification = [ + 'byArgNumber' => [ + 1 => [ + 'forEach' => '%1$s = %2$s', + 'implode' => ', ', + ], ], - self::SPECIFICATION_SET => 'SET %1$s', - self::SPECIFICATION_WHERE => 'WHERE %1$s', + 'format' => 'SET %1$s', ]; /** * @param Update $sqlObject * @param Context $context - * @return string + * @return array + */ + public function build($sqlObject, Context $context) + { + $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Update', __METHOD__); + return [ + $this->build_Update($sqlObject, $context), + $this->build_Joins($sqlObject, $context), + $this->build_Set($sqlObject, $context), + $this->build_Where($sqlObject, $context), + ]; + } + + /** + * @param Update $sqlObject + * @param Context $context + * @return array */ protected function build_Update(Update $sqlObject, Context $context) { return sprintf( - $this->specifications[static::SPECIFICATION_UPDATE], - $this->resolveTable($sqlObject->table, $context) + $this->updateSpecification, + $this->nornalizeTable($sqlObject->table, $context)['name'] ); } @@ -53,37 +83,38 @@ protected function build_Set(Update $sqlObject, Context $context) { $setSql = []; foreach ($sqlObject->set as $column => $value) { - $prefix = $context->getPlatform()->quoteIdentifier($column) . ' = '; if (is_scalar($value) && $context->getParameterContainer()) { - $setSql[] = $prefix . $context->getDriver()->formatParameterName($column); $context->getParameterContainer()->offsetSet($column, $value); + $value = $context->getDriver()->formatParameterName($column); } else { - $setSql[] = $prefix . $this->resolveColumnValue( - $value, - $context - ); + $value = $this->resolveColumnValue($value, $context); } + $setSql[] = [ + $context->getPlatform()->quoteIdentifier($column), + $value + ]; } - - return sprintf( - $this->specifications[self::SPECIFICATION_SET], - implode(', ', $setSql) - ); + return [ + 'spec' => $this->setSpecification, + 'params' => [ + $setSql + ], + ]; } /** * @param Update $sqlObject * @param Context $context - * @return string|null + * @return array|null */ protected function build_Where(Update $sqlObject, Context $context) { if ($sqlObject->where->count() == 0) { return; } - return sprintf( - $this->specifications[self::SPECIFICATION_WHERE], - $this->buildSqlString($sqlObject->where, $context) - ); + return [ + 'spec' => $this->whereSpecification, + 'params' => $sqlObject->where + ]; } } diff --git a/test/Sql/Builder/AbstractTestCase.php b/test/Sql/Builder/AbstractTestCase.php index 8e129761b9..648293f26c 100644 --- a/test/Sql/Builder/AbstractTestCase.php +++ b/test/Sql/Builder/AbstractTestCase.php @@ -202,8 +202,8 @@ protected function resolveDecorator($decorator, $builder) if (!is_array($decorator)) { return $decorator; } - $decoratorMock = $this->getMock($decorator[0], ['buildSqlString'], [$builder]); - $decoratorMock->expects($this->any())->method('buildSqlString')->will($this->returnValue($decorator[1])); + $decoratorMock = $this->getMock($decorator[0], ['build'], [$builder]); + $decoratorMock->expects($this->any())->method('build')->will($this->returnValue([$decorator[1]])); return $decoratorMock; } diff --git a/test/Sql/Builder/AllBuildersTest.php b/test/Sql/Builder/AllBuildersTest.php index d1c834e8d9..934d8f926a 100644 --- a/test/Sql/Builder/AllBuildersTest.php +++ b/test/Sql/Builder/AllBuildersTest.php @@ -60,28 +60,28 @@ public function dataProvider() 'Zend\Db\Sql\Insert' => 'ZendTest\Db\TestAsset\InsertBuilder', // Decorator for root sqlObject 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\sql92\SelectBuilder', '{=SELECT_Sql92=}'] ], - 'string' => 'INSERT INTO "foo" {=SELECT_Sql92=}', + 'string' => 'INSERT INTO "foo" ({=SELECT_Sql92=})', ], 'MySql' => [ 'decorators' => [ 'Zend\Db\Sql\Insert' => 'ZendTest\Db\TestAsset\InsertBuilder', // Decorator for root sqlObject 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\sql92\SelectBuilder', '{=SELECT_MySql=}'] ], - 'string' => 'INSERT INTO `foo` {=SELECT_MySql=}', + 'string' => 'INSERT INTO `foo` ({=SELECT_MySql=})', ], 'Oracle' => [ 'decorators' => [ 'Zend\Db\Sql\Insert' => 'ZendTest\Db\TestAsset\InsertBuilder', // Decorator for root sqlObject 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\sql92\SelectBuilder', '{=SELECT_Oracle=}'] ], - 'string' => 'INSERT INTO "foo" {=SELECT_Oracle=}', + 'string' => 'INSERT INTO "foo" ({=SELECT_Oracle=})', ], 'SqlServer' => [ 'decorators' => [ 'Zend\Db\Sql\Insert' => 'ZendTest\Db\TestAsset\InsertBuilder', // Decorator for root sqlObject 'Zend\Db\Sql\Select' => ['Zend\Db\Sql\Builder\sql92\SelectBuilder', '{=SELECT_SqlServer=}'] ], - 'string' => 'INSERT INTO [foo] {=SELECT_SqlServer=}', + 'string' => 'INSERT INTO [foo] ({=SELECT_SqlServer=})', ], ], ], @@ -184,6 +184,14 @@ public function dataProvider() ], ], ], + 'DISTINCT in columns' => [ + 'sqlObject' => $this->select('foo')->columns([$this->expression('DISTINCT(bar) as bar')])->limit(5)->offset(10), + 'expected' => [ + 'SqlServer' => [ + 'string' => 'SELECT DISTINCT(bar) as bar FROM ( SELECT DISTINCT(bar) as bar, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 10+1 AND 5+10' + ], + ], + ], ]); } } diff --git a/test/Sql/Builder/Ddl/AlterTableBuilderTest.php b/test/Sql/Builder/Ddl/AlterTableBuilderTest.php index bf9b7cdc9d..742862c9e1 100644 --- a/test/Sql/Builder/Ddl/AlterTableBuilderTest.php +++ b/test/Sql/Builder/Ddl/AlterTableBuilderTest.php @@ -32,14 +32,16 @@ public function dataProvider() return $this->prepareDataProvider([ [ 'sqlObject' => $this->alterTable('foo') - ->addColumn(new Column\Varchar('another', 255)) + ->addColumn(new Column\Varchar('another1', 10)) + ->addColumn(new Column\Varchar('another2', 20)) ->changeColumn('name', new Column\Varchar('new_name', 50)) ->dropColumn('foo') ->addConstraint(new Constraint\ForeignKey('my_fk', 'other_id', 'other_table', 'id', 'CASCADE', 'CASCADE')) ->dropConstraint('my_index'), 'expected' => [ 'sql92' => 'ALTER TABLE "foo" - ADD COLUMN "another" VARCHAR(255) NOT NULL, + ADD COLUMN "another1" VARCHAR(10) NOT NULL, + ADD COLUMN "another2" VARCHAR(20) NOT NULL, CHANGE COLUMN "name" "new_name" VARCHAR(50) NOT NULL, DROP COLUMN "foo", ADD CONSTRAINT "my_fk" FOREIGN KEY ("other_id") REFERENCES "other_table" ("id") ON DELETE CASCADE ON UPDATE CASCADE, diff --git a/test/Sql/Builder/Ddl/CreateTableBuilderTest.php b/test/Sql/Builder/Ddl/CreateTableBuilderTest.php index d2996c5225..1d616e3db2 100644 --- a/test/Sql/Builder/Ddl/CreateTableBuilderTest.php +++ b/test/Sql/Builder/Ddl/CreateTableBuilderTest.php @@ -90,7 +90,7 @@ public function dataProvider_ColumnsAndConstraint() [ 'sqlObject' => $this->createTable('foo')->addColumn(new Column('bar'))->addConstraint(new Constraint\PrimaryKey('bat')), 'expected' => [ - 'sql92' => "CREATE TABLE \"foo\" ( \n \"bar\" INTEGER NOT NULL , \n PRIMARY KEY (\"bat\") \n)", + 'sql92' => "CREATE TABLE \"foo\" ( \n \"bar\" INTEGER NOT NULL ,\n PRIMARY KEY (\"bat\") \n)", ], ], [ diff --git a/test/Sql/Builder/InsertBuilderTest.php b/test/Sql/Builder/InsertBuilderTest.php index e99feb5458..0867fa2c75 100644 --- a/test/Sql/Builder/InsertBuilderTest.php +++ b/test/Sql/Builder/InsertBuilderTest.php @@ -92,23 +92,23 @@ public function dataProvider_ColumnsAndValues() ->select($this->select()->from('bar')->where(['x'=>5])), 'expected' => [ 'sql92' => [ - 'string' => 'INSERT INTO "foo" ("col1", "col2") SELECT "bar".* FROM "bar" WHERE "x" = \'5\'', - 'prepare' => 'INSERT INTO "foo" ("col1", "col2") SELECT "bar".* FROM "bar" WHERE "x" = ?', + 'string' => 'INSERT INTO "foo" ("col1", "col2") (SELECT "bar".* FROM "bar" WHERE "x" = \'5\')', + 'prepare' => 'INSERT INTO "foo" ("col1", "col2") (SELECT "bar".* FROM "bar" WHERE "x" = ?)', 'parameters' => ['subselect1expr1'=>5], ], 'MySql' => [ - 'string' => 'INSERT INTO `foo` (`col1`, `col2`) SELECT `bar`.* FROM `bar` WHERE `x` = \'5\'', - 'prepare' => 'INSERT INTO `foo` (`col1`, `col2`) SELECT `bar`.* FROM `bar` WHERE `x` = ?', + 'string' => 'INSERT INTO `foo` (`col1`, `col2`) (SELECT `bar`.* FROM `bar` WHERE `x` = \'5\')', + 'prepare' => 'INSERT INTO `foo` (`col1`, `col2`) (SELECT `bar`.* FROM `bar` WHERE `x` = ?)', 'parameters' => ['subselect1expr1' => 5], ], 'Oracle' => [ - 'string' => 'INSERT INTO "foo" ("col1", "col2") SELECT "bar".* FROM "bar" WHERE "x" = \'5\'', - 'prepare' => 'INSERT INTO "foo" ("col1", "col2") SELECT "bar".* FROM "bar" WHERE "x" = ?', + 'string' => 'INSERT INTO "foo" ("col1", "col2") (SELECT "bar".* FROM "bar" WHERE "x" = \'5\')', + 'prepare' => 'INSERT INTO "foo" ("col1", "col2") (SELECT "bar".* FROM "bar" WHERE "x" = ?)', 'parameters' => ['subselect1expr1' => 5], ], 'SqlServer' => [ - 'string' => 'INSERT INTO [foo] ([col1], [col2]) SELECT [bar].* FROM [bar] WHERE [x] = \'5\'', - 'prepare' => 'INSERT INTO [foo] ([col1], [col2]) SELECT [bar].* FROM [bar] WHERE [x] = ?', + 'string' => 'INSERT INTO [foo] ([col1], [col2]) (SELECT [bar].* FROM [bar] WHERE [x] = \'5\')', + 'prepare' => 'INSERT INTO [foo] ([col1], [col2]) (SELECT [bar].* FROM [bar] WHERE [x] = ?)', 'parameters' => ['subselect1expr1' => 5], ], ], @@ -118,23 +118,23 @@ public function dataProvider_ColumnsAndValues() ->select($this->select('bar')->where(['x'=>5])), 'expected' => [ 'sql92' => [ - 'string' => 'INSERT INTO "foo" SELECT "bar".* FROM "bar" WHERE "x" = \'5\'', - 'prepare' => 'INSERT INTO "foo" SELECT "bar".* FROM "bar" WHERE "x" = ?', + 'string' => 'INSERT INTO "foo" (SELECT "bar".* FROM "bar" WHERE "x" = \'5\')', + 'prepare' => 'INSERT INTO "foo" (SELECT "bar".* FROM "bar" WHERE "x" = ?)', 'parameters' => ['subselect1expr1' => 5], ], 'MySql' => [ - 'string' => 'INSERT INTO `foo` SELECT `bar`.* FROM `bar` WHERE `x` = \'5\'', - 'prepare' => 'INSERT INTO `foo` SELECT `bar`.* FROM `bar` WHERE `x` = ?', + 'string' => 'INSERT INTO `foo` (SELECT `bar`.* FROM `bar` WHERE `x` = \'5\')', + 'prepare' => 'INSERT INTO `foo` (SELECT `bar`.* FROM `bar` WHERE `x` = ?)', 'parameters' => ['subselect1expr1' => 5], ], 'Oracle' => [ - 'string' => 'INSERT INTO "foo" SELECT "bar".* FROM "bar" WHERE "x" = \'5\'', - 'prepare' => 'INSERT INTO "foo" SELECT "bar".* FROM "bar" WHERE "x" = ?', + 'string' => 'INSERT INTO "foo" (SELECT "bar".* FROM "bar" WHERE "x" = \'5\')', + 'prepare' => 'INSERT INTO "foo" (SELECT "bar".* FROM "bar" WHERE "x" = ?)', 'parameters' => ['subselect1expr1' => 5], ], 'SqlServer' => [ - 'string' => 'INSERT INTO [foo] SELECT [bar].* FROM [bar] WHERE [x] = \'5\'', - 'prepare' => 'INSERT INTO [foo] SELECT [bar].* FROM [bar] WHERE [x] = ?', + 'string' => 'INSERT INTO [foo] (SELECT [bar].* FROM [bar] WHERE [x] = \'5\')', + 'prepare' => 'INSERT INTO [foo] (SELECT [bar].* FROM [bar] WHERE [x] = ?)', 'parameters' => ['subselect1expr1' => 5], ], ], @@ -143,10 +143,10 @@ public function dataProvider_ColumnsAndValues() 'sqlObject' => $this->insert('foo') ->select($this->combine($this->select('bar'))), 'expected' => [ - 'sql92' => 'INSERT INTO "foo" (SELECT "bar".* FROM "bar")', - 'MySql' => 'INSERT INTO `foo` (SELECT `bar`.* FROM `bar`)', - 'Oracle' => 'INSERT INTO "foo" (SELECT "bar".* FROM "bar")', - 'SqlServer' => 'INSERT INTO [foo] (SELECT [bar].* FROM [bar])', + 'sql92' => 'INSERT INTO "foo" ((SELECT "bar".* FROM "bar"))', + 'MySql' => 'INSERT INTO `foo` ((SELECT `bar`.* FROM `bar`))', + 'Oracle' => 'INSERT INTO "foo" ((SELECT "bar".* FROM "bar"))', + 'SqlServer' => 'INSERT INTO [foo] ((SELECT [bar].* FROM [bar]))', ], ], ]; diff --git a/test/Sql/Builder/SelectBuilderTest.php b/test/Sql/Builder/SelectBuilderTest.php index 7a21457e38..06e504ffce 100644 --- a/test/Sql/Builder/SelectBuilderTest.php +++ b/test/Sql/Builder/SelectBuilderTest.php @@ -162,7 +162,7 @@ public function dataProvider_Combine() ), 'expected' => [ 'sql92' => [ - 'string' => '( SELECT "foo".* FROM "foo" WHERE a = b ) UNION ALL ( SELECT "bar".* FROM "bar" WHERE c = d )', + 'string' => '( SELECT "foo".* FROM "foo" WHERE a = b ) UNION ALL ( (SELECT "bar".* FROM "bar" WHERE c = d) )', 'prepare' => true, ], ], @@ -180,7 +180,7 @@ public function dataProvider_Combine() ->order('id DESC'), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "sub".* FROM (( SELECT "foo".* FROM "foo" WHERE a = b ) UNION ( SELECT "bar".* FROM "bar" WHERE c = d )) AS "sub" ORDER BY "id" DESC', + 'string' => 'SELECT "sub".* FROM (( SELECT "foo".* FROM "foo" WHERE a = b ) UNION ( (SELECT "bar".* FROM "bar" WHERE c = d) )) AS "sub" ORDER BY "id" DESC', 'prepare' => true, ], ], @@ -357,8 +357,8 @@ public function dataProvider_Join() . 'INNER JOIN "tableA" ON "id" = \'1\' INNER JOIN "tableB" ON "id" = \'2\' ' . 'INNER JOIN "tableC" ON "id" = \'3\' AND "number" > \'20\'', 'prepare' => 'SELECT "foo".*, "tableA".*, "tableB".*, "tableC".* FROM "foo"' - . ' INNER JOIN "tableA" ON "id" = :join1expr1 INNER JOIN "tableB" ON "id" = :join2expr1 ' - . 'INNER JOIN "tableC" ON "id" = :join3expr1 AND "number" > :join3expr2', + . ' INNER JOIN "tableA" ON "id" = :expr1 INNER JOIN "tableB" ON "id" = :expr2 ' + . 'INNER JOIN "tableC" ON "id" = :expr3 AND "number" > :expr4', 'useNamedParams' => true, ], ], @@ -669,7 +669,7 @@ public function dataProvider_LimitOffset() 'IbmDb2' => [ 'string' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" WHERE "x"."id" > \'10\' AND "x"."id" < \'31\' ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 11 AND 15', 'prepare' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" WHERE "x"."id" > ? AND "x"."id" < ? ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', - 'parameters' => ['expr1' => '10', 'expr2' => '31', 'offset' => 11, 'limit' => 15], + 'parameters' => ['offset' => 11, 'limit' => 15, 'expr1' => '10', 'expr2' => '31'], ], ], ], diff --git a/test/TestAsset/ExpressionBuilder.php b/test/TestAsset/ExpressionBuilder.php index 98c63a47fb..edbfdbcc77 100644 --- a/test/TestAsset/ExpressionBuilder.php +++ b/test/TestAsset/ExpressionBuilder.php @@ -13,11 +13,11 @@ class ExpressionBuilder extends \Zend\Db\Sql\Builder\sql92\ExpressionBuilder { - public function getExpressionData($expression, Context $context) + public function build($expression, Context $context) { $expressionString = $expression->getExpression(); $expression->setExpression('{decorate-' . $expressionString . '-decorate}'); - $result = parent::getExpressionData($expression, $context); + $result = parent::build($expression, $context); $expression->setExpression($expressionString); return $result; } From e384a6cacb7fcb7a6482d16891c093089db88162 Mon Sep 17 00:00:00 2001 From: turrsis Date: Sun, 12 Jul 2015 13:57:07 +0300 Subject: [PATCH 07/30] architecture fix 06: LIMIT and OFFSET builders --- src/Sql/Builder/AbstractSqlBuilder.php | 6 +- src/Sql/Builder/IbmDb2/SelectBuilder.php | 72 +-------- src/Sql/Builder/Mysql/SelectBuilder.php | 23 ++- src/Sql/Builder/Oracle/SelectBuilder.php | 77 +-------- src/Sql/Builder/SelectLimitOffsetTrait.php | 61 +++++++ src/Sql/Builder/SqlServer/SelectBuilder.php | 90 +---------- src/Sql/Builder/sql92/SelectBuilder.php | 29 ++-- test/Sql/Builder/AllBuildersTest.php | 4 +- test/Sql/Builder/SelectBuilderTest.php | 171 ++++++++++++-------- 9 files changed, 208 insertions(+), 325 deletions(-) create mode 100644 src/Sql/Builder/SelectLimitOffsetTrait.php diff --git a/src/Sql/Builder/AbstractSqlBuilder.php b/src/Sql/Builder/AbstractSqlBuilder.php index 36edb9a6f2..70742ae00f 100644 --- a/src/Sql/Builder/AbstractSqlBuilder.php +++ b/src/Sql/Builder/AbstractSqlBuilder.php @@ -251,10 +251,12 @@ private function buildSpecificationParameter($parameter, Context $context = null return $parameter; } + $isQuoted = false; if ($parameter instanceof ExpressionParameter) { $value = $parameter->getValue(); $type = $parameter->getType(); $paramName = $parameter->getName(); + $isQuoted = $parameter->getOption('isQuoted'); } else { $value = $parameter; $type = ExpressionInterface::TYPE_LITERAL; @@ -281,7 +283,9 @@ private function buildSpecificationParameter($parameter, Context $context = null } $parameter = $context->getDriver()->formatParameterName($name); } else { - $parameter = $context->getPlatform()->quoteValue($value); + $parameter = $isQuoted + ? $value + : $context->getPlatform()->quoteValue($value); } } elseif ($type == ExpressionInterface::TYPE_LITERAL) { $parameter = $value; diff --git a/src/Sql/Builder/IbmDb2/SelectBuilder.php b/src/Sql/Builder/IbmDb2/SelectBuilder.php index f6f980a867..89f7ecc2f1 100644 --- a/src/Sql/Builder/IbmDb2/SelectBuilder.php +++ b/src/Sql/Builder/IbmDb2/SelectBuilder.php @@ -9,13 +9,14 @@ namespace Zend\Db\Sql\Builder\IbmDb2; -use Zend\Db\Sql\Select; use Zend\Db\Sql\Builder\sql92\SelectBuilder as BaseBuilder; use Zend\Db\Sql\Builder\Builder; -use Zend\Db\Sql\Builder\Context; +use Zend\Db\Sql\Builder\SelectLimitOffsetTrait; class SelectBuilder extends BaseBuilder { + use SelectLimitOffsetTrait; + /** * {@inheritDoc} */ @@ -30,71 +31,4 @@ public function __construct(Builder $platformBuilder) $this->selectColumnsTableSpecification['byArgNumber'][2] = $asSpec; $this->selectFullSpecification['byArgNumber'][3] = $asSpec; } - - protected function build_Limit(Select $sqlObject, Context $context, &$sqls = null) - { - return; - } - - protected function build_Offset(Select $sqlObject, Context $context, &$sqls = null) - { - $LIMIT = $sqlObject->limit; - $OFFSET = $sqlObject->offset; - if ($LIMIT === null && $OFFSET === null) { - return; - } - - $selectParameters = $sqls['select']['params']; - - $starSuffix = $context->getPlatform()->getIdentifierSeparator() . Select::SQL_STAR; - foreach ($selectParameters[0] as $i => $columnParameters) { - if ($columnParameters[0] == Select::SQL_STAR - || (isset($columnParameters[1]) && $columnParameters[1] == Select::SQL_STAR) - || strpos($columnParameters[0], $starSuffix) - ) { - $selectParameters[0] = [[Select::SQL_STAR]]; - break; - } - - if (isset($columnParameters[1])) { - array_shift($columnParameters); - $selectParameters[0][$i] = $columnParameters; - } - } - - // first, produce column list without compound names (using the AS portion only) - $SSS = $sqls['select']; - $SSS['spec']['format'] = 'SELECT %1$s FROM ('; - $SSS['params'] = $selectParameters; - array_unshift($sqls, $this->buildSqlString($SSS, $context)); - - $offset = ((int) $OFFSET > 0) ? (int) $OFFSET + 1 : (int) $OFFSET; - $limit = (int) $LIMIT + (int) $OFFSET; - - if ($context->getParameterContainer()) { - $context->getParameterContainer()->offsetSet('offset', $offset); - $context->getParameterContainer()->offsetSet('limit', $limit); - - $limit = $context->getDriver()->formatParameterName('limit'); - $offset = $context->getDriver()->formatParameterName('offset'); - } - - array_push($sqls, sprintf( - ") AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN %s AND %s", - $offset, - $limit - )); - - if (isset($sqls['order'])) { - $orderBy = $sqls['order']; - unset($sqls['order']); - } else { - $orderBy = ''; - } - - // add a column for row_number() using the order specification //dense_rank() - $sqls['select']['params'][0][] = (preg_match('/DISTINCT/i', $sqls[0])) - ? ['DENSE_RANK() OVER (' . $orderBy . ')', 'ZEND_DB_ROWNUM'] - : ['ROW_NUMBER() OVER (' . $orderBy . ')', 'ZEND_DB_ROWNUM']; - } } diff --git a/src/Sql/Builder/Mysql/SelectBuilder.php b/src/Sql/Builder/Mysql/SelectBuilder.php index 312b7ba88b..9938dee686 100644 --- a/src/Sql/Builder/Mysql/SelectBuilder.php +++ b/src/Sql/Builder/Mysql/SelectBuilder.php @@ -13,6 +13,8 @@ use Zend\Db\Adapter; use Zend\Db\Sql\Builder\sql92\SelectBuilder as BaseBuilder; use Zend\Db\Sql\Builder\Context; +use Zend\Db\Sql\ExpressionParameter; +use Zend\Db\Sql\ExpressionInterface; class SelectBuilder extends BaseBuilder { @@ -28,9 +30,15 @@ protected function build_Limit(Select $sqlObject, Context $context) $limitParam = '18446744073709551615'; } elseif ($limit === null) { return; - } elseif ($context->getParameterContainer()) { - $context->getParameterContainer()->offsetSet('limit', $limit, Adapter\ParameterContainer::TYPE_INTEGER); - $limitParam = $context->getDriver()->formatParameterName('limit'); + } else { + $limitParam = new ExpressionParameter($limit); + $limitParam + ->setType(ExpressionInterface::TYPE_VALUE) + ->setName('limit') + ->setOptions([ + 'errata' => Adapter\ParameterContainer::TYPE_INTEGER, + 'isQuoted' => true, + ]); } return [ @@ -52,10 +60,11 @@ protected function build_Offset(Select $sqlObject, Context $context) if ($offset === null) { return; } - if ($context->getParameterContainer()) { - $context->getParameterContainer()->offsetSet('offset', $offset, Adapter\ParameterContainer::TYPE_INTEGER); - $offset = $context->getDriver()->formatParameterName('offset'); - } + $offset = new ExpressionParameter($offset, ExpressionInterface::TYPE_VALUE, 'offset'); + $offset->setOptions([ + 'errata' => Adapter\ParameterContainer::TYPE_INTEGER, + 'isQuoted' => true, + ]); return [ 'spec' => $this->offsetSpecification, 'params' => [ diff --git a/src/Sql/Builder/Oracle/SelectBuilder.php b/src/Sql/Builder/Oracle/SelectBuilder.php index 8a4ca6b0a9..f27b4abf9c 100644 --- a/src/Sql/Builder/Oracle/SelectBuilder.php +++ b/src/Sql/Builder/Oracle/SelectBuilder.php @@ -9,13 +9,14 @@ namespace Zend\Db\Sql\Builder\Oracle; -use Zend\Db\Sql\Select; use Zend\Db\Sql\Builder\sql92\SelectBuilder as BaseBuilder; use Zend\Db\Sql\Builder\Builder; -use Zend\Db\Sql\Builder\Context; +use Zend\Db\Sql\Builder\SelectLimitOffsetTrait; class SelectBuilder extends BaseBuilder { + use SelectLimitOffsetTrait; + /** * {@inheritDoc} */ @@ -31,76 +32,4 @@ public function __construct(Builder $platformBuilder) $this->selectFullSpecification['byArgNumber'][3] = $asSpec; $this->joinsSpecification['forEach']['byArgNumber'][2] = $asSpec; } - - protected function build_Limit(Select $sqlObject, Context $context, &$sqls = null) - { - return; - } - - protected function build_Offset(Select $sqlObject, Context $context, &$sqls = null) - { - $LIMIT = $sqlObject->limit; - $OFFSET = $sqlObject->offset; - if ($LIMIT === null && $OFFSET === null) { - return; - } - - $selectParameters = $sqls['select']['params']; - - $starSuffix = $context->getPlatform()->getIdentifierSeparator() . Select::SQL_STAR; - foreach ($selectParameters[0] as $i => $columnParameters) { - if ($columnParameters[0] == Select::SQL_STAR || (isset($columnParameters[1]) && $columnParameters[1] == Select::SQL_STAR) || strpos($columnParameters[0], $starSuffix)) { - $selectParameters[0] = [[Select::SQL_STAR]]; - break; - } - if (isset($columnParameters[1])) { - array_shift($columnParameters); - $selectParameters[0][$i] = $columnParameters; - } - } - - if ($OFFSET === null) { - $OFFSET = 0; - } - - // first, produce column list without compound names (using the AS portion only) - $SSS = $sqls['select']; - $SSS['spec']['format'] = 'SELECT %1$s FROM (SELECT b.%1$s, rownum b_rownum FROM ('; - - array_unshift($sqls, [ - 'spec' => $SSS['spec'], - 'params' => $selectParameters, - ]); - - if ($parameterContainer = $context->getParameterContainer()) { - if ($LIMIT === null) { - array_push($sqls, ') b ) WHERE b_rownum > (:offset)'); - $parameterContainer->offsetSet('offset', $OFFSET, $parameterContainer::TYPE_INTEGER); - } else { - // create bottom part of query, with offset and limit using row_number - array_push($sqls, ') b WHERE rownum <= (:offset+:limit)) WHERE b_rownum >= (:offset + 1)'); - $parameterContainer->offsetSet('offset', $OFFSET, $parameterContainer::TYPE_INTEGER); - $parameterContainer->offsetSet('limit', $LIMIT, $parameterContainer::TYPE_INTEGER); - } - } else { - if ($LIMIT === null) { - array_push($sqls, ') b ) WHERE b_rownum > ('. (int) $OFFSET. ')' - ); - } else { - array_push($sqls, ') b WHERE rownum <= (' - . (int) $OFFSET - . '+' - . (int) $LIMIT - . ')) WHERE b_rownum >= (' - . (int) $OFFSET - . ' + 1)' - ); - } - } - $parameters = $sqls['select']['params']; - $sqls['select'] = [ - 'spec' => $sqls['select']['spec'], - 'params' => $parameters, - ]; - } } diff --git a/src/Sql/Builder/SelectLimitOffsetTrait.php b/src/Sql/Builder/SelectLimitOffsetTrait.php new file mode 100644 index 0000000000..fb6914b97d --- /dev/null +++ b/src/Sql/Builder/SelectLimitOffsetTrait.php @@ -0,0 +1,61 @@ +validateSqlObject($sqlObject, 'Zend\Db\Sql\Select', __METHOD__); + if ($sqlObject->limit === null && $sqlObject->offset === null) { + return parent::build($sqlObject, $context); + } + + $sqlObject = clone $sqlObject; + $wrapObject = new Select(); + $newSelect = new Select([ + 'LIMIT_OFFSET_WRAP_2' => $wrapObject + ->columns([ + Select::SQL_STAR, + 'LIMIT_OFFSET_ROWNUM' => new Expression('ROW_NUMBER() OVER ()'), + ], false) + ->from([ + 'LIMIT_OFFSET_WRAP_1' => $sqlObject + ]) + ]); + $newSelect->columns([Select::SQL_STAR], false); + + if ($sqlObject->offset !== null) { + $offset = new ExpressionParameter((int) $sqlObject->offset, Expression::TYPE_VALUE, 'offset'); + $newSelect->where->greaterThan('LIMIT_OFFSET_ROWNUM', $offset); + } + + if ($sqlObject->limit !== null) { + $limit = new ExpressionParameter((int) $sqlObject->limit, Expression::TYPE_VALUE, 'limit'); + if ($sqlObject->offset !== null) { + $offset->setName(['offset', 'offsetForSum']); + $limit = new Operator($limit, '+', $offset); + } + $newSelect->where->lessThanOrEqualTo('LIMIT_OFFSET_ROWNUM', $limit); + } + unset($sqlObject->limit, $sqlObject->offset); + return parent::build($newSelect, $context); + } +} diff --git a/src/Sql/Builder/SqlServer/SelectBuilder.php b/src/Sql/Builder/SqlServer/SelectBuilder.php index 8bcc48b854..be362dccaa 100644 --- a/src/Sql/Builder/SqlServer/SelectBuilder.php +++ b/src/Sql/Builder/SqlServer/SelectBuilder.php @@ -10,95 +10,9 @@ namespace Zend\Db\Sql\Builder\SqlServer; use Zend\Db\Sql\Builder\sql92\SelectBuilder as BaseBuilder; -use Zend\Db\Sql\Builder\Context; -use Zend\Db\Sql\Select; +use Zend\Db\Sql\Builder\SelectLimitOffsetTrait; class SelectBuilder extends BaseBuilder { - protected function build_Limit(Select $sqlObject, Context $context, &$sqls = null) - { - return; - } - - protected function build_Offset(Select $sqlObject, Context $context, &$sqls = null) - { - $LIMIT = $sqlObject->limit; - $OFFSET = $sqlObject->offset; - if ($LIMIT === null && $OFFSET === null) { - return; - } - - $selectParameters = $sqls['select']['params']; - - /** if this is a DISTINCT query then real SELECT part goes to second element in array **/ - $parameterIndex = 0; - if ($selectParameters[0] === 'DISTINCT') { - unset($selectParameters[0]); - $selectParameters = array_values($selectParameters); - $parameterIndex = 1; - } - - $starSuffix = $context->getPlatform()->getIdentifierSeparator() . Select::SQL_STAR; - foreach ($selectParameters[0] as $i => $columnParameters) { - if ($columnParameters[0] == Select::SQL_STAR || (isset($columnParameters[1]) && $columnParameters[1] == Select::SQL_STAR) || strpos($columnParameters[0], $starSuffix)) { - $selectParameters[0] = [[Select::SQL_STAR]]; - break; - } - if (isset($columnParameters[1])) { - array_shift($columnParameters); - $selectParameters[0][$i] = $columnParameters; - } - } - - // first, produce column list without compound names (using the AS portion only) - $SSS = $sqls['select']; - $SSS['spec']['format'] = 'SELECT %1$s FROM ('; - - array_unshift($sqls, [ - 'spec' => $SSS['spec'], - 'params' => $selectParameters, - ]); - - if ($parameterContainer = $context->getParameterContainer()) { - // create bottom part of query, with offset and limit using row_number - $sqls[] = - ') AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ' - . $context->getDriver()->formatParameterName('offset') - . '+1 AND ' - . $context->getDriver()->formatParameterName('limit') - . '+' - . $context->getDriver()->formatParameterName('offsetForSum'); - - $parameterContainer->offsetSet('offset', $OFFSET); - $parameterContainer->offsetSet('limit', $LIMIT); - $parameterContainer->offsetSetReference('offsetForSum', 'offset'); - } else { - $sqls[] = - ') AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ' - . (int) $OFFSET - . '+1 AND ' - . (int) $LIMIT - . '+' - . (int) $OFFSET; - } - - if (isset($sqls['order'])) { - $orderBy = $this->buildSqlString($sqls['order'], $context); - unset($sqls['order']); - } else { - $orderBy = 'ORDER BY (SELECT 1)'; - } - - // add a column for row_number() using the order specification - $parameters = $sqls['select']['params']; - $parameters[$parameterIndex][] = [ - 'ROW_NUMBER() OVER (' . $orderBy . ')', - '[__ZEND_ROW_NUMBER]' - ]; - - $sqls['select'] = [ - 'spec' => $sqls['select']['spec'], - 'params' => $parameters, - ]; - } + use SelectLimitOffsetTrait; } diff --git a/src/Sql/Builder/sql92/SelectBuilder.php b/src/Sql/Builder/sql92/SelectBuilder.php index fd15ef5e5a..c3fafae5df 100644 --- a/src/Sql/Builder/sql92/SelectBuilder.php +++ b/src/Sql/Builder/sql92/SelectBuilder.php @@ -14,6 +14,7 @@ use Zend\Db\Sql\ExpressionInterface; use Zend\Db\Sql\Builder\AbstractSqlBuilder; use Zend\Db\Sql\Builder\Context; +use Zend\Db\Sql\ExpressionParameter; class SelectBuilder extends AbstractSqlBuilder { @@ -345,16 +346,15 @@ protected function build_Order(Select $sqlObject, Context $context) */ protected function build_Limit(Select $sqlObject, Context $context) { - $limit = $sqlObject->limit; - if ($limit === null) { + if ($sqlObject->limit === null) { return; } - if ($context->getParameterContainer()) { - $context->getParameterContainer()->offsetSet('limit', $limit, Adapter\ParameterContainer::TYPE_INTEGER); - $limit = $context->getDriver()->formatParameterName('limit'); - } else { - $limit = $context->getPlatform()->quoteValue($limit); - } + + $limit = new ExpressionParameter($sqlObject->limit); + $limit->setType(ExpressionInterface::TYPE_VALUE); + $limit->setName('limit'); + $limit->setOption('errata', Adapter\ParameterContainer::TYPE_INTEGER); + return [ 'spec' => $this->limitSpecification, 'params' => $limit, @@ -368,16 +368,13 @@ protected function build_Limit(Select $sqlObject, Context $context) */ protected function build_Offset(Select $sqlObject, Context $context) { - $offset = $sqlObject->offset; - if ($offset === null) { + if ($sqlObject->offset === null) { return; } - if ($context->getParameterContainer()) { - $context->getParameterContainer()->offsetSet('offset', $offset, Adapter\ParameterContainer::TYPE_INTEGER); - $offset = $context->getDriver()->formatParameterName('offset'); - } else { - $offset = $context->getPlatform()->quoteValue($offset); - } + + $offset = new ExpressionParameter($sqlObject->offset, ExpressionInterface::TYPE_VALUE, 'offset'); + $offset->setOption('errata', Adapter\ParameterContainer::TYPE_INTEGER); + return [ 'spec' => $this->offsetSpecification, 'params' => $offset diff --git a/test/Sql/Builder/AllBuildersTest.php b/test/Sql/Builder/AllBuildersTest.php index 934d8f926a..a0154dd055 100644 --- a/test/Sql/Builder/AllBuildersTest.php +++ b/test/Sql/Builder/AllBuildersTest.php @@ -185,10 +185,10 @@ public function dataProvider() ], ], 'DISTINCT in columns' => [ - 'sqlObject' => $this->select('foo')->columns([$this->expression('DISTINCT(bar) as bar')])->limit(5)->offset(10), + 'sqlObject' => $this->select('foo')->columns(['bar' => $this->expression('DISTINCT(bar)')])->limit(5)->offset(10), 'expected' => [ 'SqlServer' => [ - 'string' => 'SELECT DISTINCT(bar) as bar FROM ( SELECT DISTINCT(bar) as bar, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 10+1 AND 5+10' + 'string' => "SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS [LIMIT_OFFSET_ROWNUM] FROM (SELECT DISTINCT(bar) AS [bar] FROM [foo]) AS [LIMIT_OFFSET_WRAP_1]) AS [LIMIT_OFFSET_WRAP_2] WHERE [LIMIT_OFFSET_ROWNUM] > '10' AND [LIMIT_OFFSET_ROWNUM] <= '5' + '10'", ], ], ], diff --git a/test/Sql/Builder/SelectBuilderTest.php b/test/Sql/Builder/SelectBuilderTest.php index 06e504ffce..2ee72f609f 100644 --- a/test/Sql/Builder/SelectBuilderTest.php +++ b/test/Sql/Builder/SelectBuilderTest.php @@ -451,15 +451,20 @@ public function dataProvider_LimitOffset() 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET ?', 'parameters' => ['offset' => 0], ], + 'IbmDb2' => [ + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > \'0\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > ?', + 'parameters' => ['offset' => 0], + ], 'Oracle' => [ - 'string' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b ) WHERE b_rownum > (0)', - 'prepare' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b ) WHERE b_rownum > (:offset)', + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > \'0\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > ?', 'parameters' => ['offset' => 0], ], 'SqlServer' => [ - 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 0+1 AND 0+0', - 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', - 'parameters' => ['offset' => 0, 'limit' => null, 'offsetForSum' => 0], + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS [LIMIT_OFFSET_ROWNUM] FROM (SELECT [foo].* FROM [foo]) AS [LIMIT_OFFSET_WRAP_1]) AS [LIMIT_OFFSET_WRAP_2] WHERE [LIMIT_OFFSET_ROWNUM] > \'0\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS [LIMIT_OFFSET_ROWNUM] FROM (SELECT [foo].* FROM [foo]) AS [LIMIT_OFFSET_WRAP_1]) AS [LIMIT_OFFSET_WRAP_2] WHERE [LIMIT_OFFSET_ROWNUM] > ?', + 'parameters' => ['offset' => 0], ], ], ], @@ -477,19 +482,19 @@ public function dataProvider_LimitOffset() 'parameters' => ['limit' => 0], ], 'IbmDb2' => [ - 'string' => 'SELECT * FROM ( SELECT "foo".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 0 AND 0', - 'prepare' => 'SELECT * FROM ( SELECT "foo".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', - 'parameters' => ['offset' => 0, 'limit' => 0], + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" <= \'0\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" <= ?', + 'parameters' => ['limit' => 0], ], 'Oracle' => [ - 'string' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (0+0)) WHERE b_rownum >= (0 + 1)', - 'prepare' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (:offset+:limit)) WHERE b_rownum >= (:offset + 1)', - 'parameters' => ['offset' => 0, 'limit' => 0], + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" <= \'0\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" <= ?', + 'parameters' => ['limit' => 0], ], 'SqlServer' => [ - 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 0+1 AND 0+0', - 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', - 'parameters' => ['offset' => null, 'limit' => 0, 'offsetForSum' => null], + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS [LIMIT_OFFSET_ROWNUM] FROM (SELECT [foo].* FROM [foo]) AS [LIMIT_OFFSET_WRAP_1]) AS [LIMIT_OFFSET_WRAP_2] WHERE [LIMIT_OFFSET_ROWNUM] <= \'0\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS [LIMIT_OFFSET_ROWNUM] FROM (SELECT [foo].* FROM [foo]) AS [LIMIT_OFFSET_WRAP_1]) AS [LIMIT_OFFSET_WRAP_2] WHERE [LIMIT_OFFSET_ROWNUM] <= ?', + 'parameters' => ['limit' => 0], ], ], ], @@ -506,15 +511,20 @@ public function dataProvider_LimitOffset() 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT 18446744073709551615 OFFSET ?', 'parameters' => ['offset' => 10], ], + 'IbmDb2' => [ + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > \'10\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > ?', + 'parameters' => ['offset' => 10], + ], 'Oracle' => [ - 'string' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b ) WHERE b_rownum > (10)', - 'prepare' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b ) WHERE b_rownum > (:offset)', + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > \'10\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > ?', 'parameters' => ['offset' => 10], ], 'SqlServer' => [ - 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 10+1 AND 0+10', - 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', - 'parameters' => ['offset' => 10, 'limit' => null, 'offsetForSum' => 10], + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS [LIMIT_OFFSET_ROWNUM] FROM (SELECT [foo].* FROM [foo]) AS [LIMIT_OFFSET_WRAP_1]) AS [LIMIT_OFFSET_WRAP_2] WHERE [LIMIT_OFFSET_ROWNUM] > \'10\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS [LIMIT_OFFSET_ROWNUM] FROM (SELECT [foo].* FROM [foo]) AS [LIMIT_OFFSET_WRAP_1]) AS [LIMIT_OFFSET_WRAP_2] WHERE [LIMIT_OFFSET_ROWNUM] > ?', + 'parameters' => ['offset' => 10], ], ], ], @@ -531,14 +541,19 @@ public function dataProvider_LimitOffset() 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT ? OFFSET ?', 'parameters' => ['limit' => 0, 'offset' => 10], ], + 'IbmDb2' => [ + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > \'10\' AND "LIMIT_OFFSET_ROWNUM" <= \'0\' + \'10\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > ? AND "LIMIT_OFFSET_ROWNUM" <= ? + ?', + 'parameters' => ['offset' => 10, 'limit' => 0, 'offsetForSum' => 10], + ], 'Oracle' => [ - 'string' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (10+0)) WHERE b_rownum >= (10 + 1)', - 'prepare' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (:offset+:limit)) WHERE b_rownum >= (:offset + 1)', - 'parameters' => ['offset' => 10, 'limit' => 0], + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > \'10\' AND "LIMIT_OFFSET_ROWNUM" <= \'0\' + \'10\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > ? AND "LIMIT_OFFSET_ROWNUM" <= ? + ?', + 'parameters' => ['offset' => 10, 'limit' => 0, 'offsetForSum' => 10], ], 'SqlServer' => [ - 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 10+1 AND 0+10', - 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS [LIMIT_OFFSET_ROWNUM] FROM (SELECT [foo].* FROM [foo]) AS [LIMIT_OFFSET_WRAP_1]) AS [LIMIT_OFFSET_WRAP_2] WHERE [LIMIT_OFFSET_ROWNUM] > \'10\' AND [LIMIT_OFFSET_ROWNUM] <= \'0\' + \'10\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS [LIMIT_OFFSET_ROWNUM] FROM (SELECT [foo].* FROM [foo]) AS [LIMIT_OFFSET_WRAP_1]) AS [LIMIT_OFFSET_WRAP_2] WHERE [LIMIT_OFFSET_ROWNUM] > ? AND [LIMIT_OFFSET_ROWNUM] <= ? + ?', 'parameters' => ['offset' => 10, 'limit' => 0, 'offsetForSum' => 10], ], ], @@ -557,19 +572,19 @@ public function dataProvider_LimitOffset() 'parameters' => ['limit' => 10], ], 'IbmDb2' => [ - 'string' => 'SELECT * FROM ( SELECT "foo".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 0 AND 10', - 'prepare' => 'SELECT * FROM ( SELECT "foo".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', - 'parameters' => ['offset' => 0, 'limit' => 10], + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" <= \'10\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" <= ?', + 'parameters' => ['limit' => 10], ], 'Oracle' => [ - 'string' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (0+10)) WHERE b_rownum >= (0 + 1)', - 'prepare' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (:offset+:limit)) WHERE b_rownum >= (:offset + 1)', - 'parameters' => ['offset' => 0, 'limit' => 10], + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" <= \'10\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" <= ?', + 'parameters' => ['limit' => 10], ], 'SqlServer' => [ - 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 0+1 AND 10+0', - 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', - 'parameters' => ['offset' => null, 'limit' => 10, 'offsetForSum' => null], + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS [LIMIT_OFFSET_ROWNUM] FROM (SELECT [foo].* FROM [foo]) AS [LIMIT_OFFSET_WRAP_1]) AS [LIMIT_OFFSET_WRAP_2] WHERE [LIMIT_OFFSET_ROWNUM] <= \'10\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS [LIMIT_OFFSET_ROWNUM] FROM (SELECT [foo].* FROM [foo]) AS [LIMIT_OFFSET_WRAP_1]) AS [LIMIT_OFFSET_WRAP_2] WHERE [LIMIT_OFFSET_ROWNUM] <= ?', + 'parameters' => ['limit' => 10], ], ], ], @@ -587,18 +602,18 @@ public function dataProvider_LimitOffset() 'parameters' => ['limit' => 10, 'offset' => 0], ], 'IbmDb2' => [ - 'string' => 'SELECT * FROM ( SELECT "foo".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 0 AND 10', - 'prepare' => 'SELECT * FROM ( SELECT "foo".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', - 'parameters' => ['offset' => 0, 'limit' => 10], + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > \'0\' AND "LIMIT_OFFSET_ROWNUM" <= \'10\' + \'0\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > ? AND "LIMIT_OFFSET_ROWNUM" <= ? + ?', + 'parameters' => ['offset' => 0, 'limit' => 10, 'offsetForSum' => 0], ], 'Oracle' => [ - 'string' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (0+10)) WHERE b_rownum >= (0 + 1)', - 'prepare' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (:offset+:limit)) WHERE b_rownum >= (:offset + 1)', - 'parameters' => ['offset' => 0, 'limit' => 10], + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > \'0\' AND "LIMIT_OFFSET_ROWNUM" <= \'10\' + \'0\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > ? AND "LIMIT_OFFSET_ROWNUM" <= ? + ?', + 'parameters' => ['offset' => 0, 'limit' => 10, 'offsetForSum' => 0], ], 'SqlServer' => [ - 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 0+1 AND 10+0', - 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS [LIMIT_OFFSET_ROWNUM] FROM (SELECT [foo].* FROM [foo]) AS [LIMIT_OFFSET_WRAP_1]) AS [LIMIT_OFFSET_WRAP_2] WHERE [LIMIT_OFFSET_ROWNUM] > \'0\' AND [LIMIT_OFFSET_ROWNUM] <= \'10\' + \'0\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS [LIMIT_OFFSET_ROWNUM] FROM (SELECT [foo].* FROM [foo]) AS [LIMIT_OFFSET_WRAP_1]) AS [LIMIT_OFFSET_WRAP_2] WHERE [LIMIT_OFFSET_ROWNUM] > ? AND [LIMIT_OFFSET_ROWNUM] <= ? + ?', 'parameters' => ['offset' => 0, 'limit' => 10, 'offsetForSum' => 0], ], ], @@ -617,18 +632,18 @@ public function dataProvider_LimitOffset() 'parameters' => ['limit' => 10, 'offset' => 5], ], 'IbmDb2' => [ - 'string' => 'SELECT * FROM ( SELECT "foo".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 6 AND 15', - 'prepare' => 'SELECT * FROM ( SELECT "foo".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', - 'parameters' => ['offset' => 6, 'limit' => 15], + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > \'5\' AND "LIMIT_OFFSET_ROWNUM" <= \'10\' + \'5\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > ? AND "LIMIT_OFFSET_ROWNUM" <= ? + ?', + 'parameters' => ['offset' => 5, 'limit' => 10, 'offsetForSum' => 5], ], 'Oracle' => [ - 'string' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (5+10)) WHERE b_rownum >= (5 + 1)', - 'prepare' => 'SELECT * FROM (SELECT b.*, rownum b_rownum FROM ( SELECT "foo".* FROM "foo" ) b WHERE rownum <= (:offset+:limit)) WHERE b_rownum >= (:offset + 1)', - 'parameters' => ['offset' => 5, 'limit' => 10], + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > \'5\' AND "LIMIT_OFFSET_ROWNUM" <= \'10\' + \'5\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > ? AND "LIMIT_OFFSET_ROWNUM" <= ? + ?', + 'parameters' => ['offset' => 5, 'limit' => 10, 'offsetForSum' => 5], ], 'SqlServer' => [ - 'string' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN 5+1 AND 10+5', - 'prepare' => 'SELECT * FROM ( SELECT [foo].*, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [__ZEND_ROW_NUMBER] FROM [foo] ) AS [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION] WHERE [ZEND_SQL_SERVER_LIMIT_OFFSET_EMULATION].[__ZEND_ROW_NUMBER] BETWEEN ?+1 AND ?+?', + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS [LIMIT_OFFSET_ROWNUM] FROM (SELECT [foo].* FROM [foo]) AS [LIMIT_OFFSET_WRAP_1]) AS [LIMIT_OFFSET_WRAP_2] WHERE [LIMIT_OFFSET_ROWNUM] > \'5\' AND [LIMIT_OFFSET_ROWNUM] <= \'10\' + \'5\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS [LIMIT_OFFSET_ROWNUM] FROM (SELECT [foo].* FROM [foo]) AS [LIMIT_OFFSET_WRAP_1]) AS [LIMIT_OFFSET_WRAP_2] WHERE [LIMIT_OFFSET_ROWNUM] > ? AND [LIMIT_OFFSET_ROWNUM] <= ? + ?', 'parameters' => ['offset' => 5, 'limit' => 10, 'offsetForSum' => 5], ], ], @@ -657,31 +672,51 @@ public function dataProvider_LimitOffset() 'prepare' => 'SELECT `foo`.* FROM `foo` LIMIT ? OFFSET ?', 'parameters' => ['limit' => '10000000000000000000', 'offset' => '10000000000000000000'], ], + /* TODO + 'IbmDb2' => array( + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > 5 AND "LIMIT_OFFSET_ROWNUM" <= 10 + 5', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > ? AND "LIMIT_OFFSET_ROWNUM" <= ? + ?', + 'parameters' => array('offset' => 5, 'limit' => 10, 'offsetForSum' => 5), + ), + 'Oracle' => array( + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > 5 AND "LIMIT_OFFSET_ROWNUM" <= 10 + 5', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo") "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" > ? AND "LIMIT_OFFSET_ROWNUM" <= ? + ?', + 'parameters' => array('offset' => 5, 'limit' => 10, 'offsetForSum' => 5), + ), + 'SqlServer' => array( + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS [LIMIT_OFFSET_ROWNUM] FROM (SELECT [foo].* FROM [foo]) AS [LIMIT_OFFSET_WRAP_1]) AS [LIMIT_OFFSET_WRAP_2] WHERE [LIMIT_OFFSET_ROWNUM] > 5 AND [LIMIT_OFFSET_ROWNUM] <= 10 + 5', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS [LIMIT_OFFSET_ROWNUM] FROM (SELECT [foo].* FROM [foo]) AS [LIMIT_OFFSET_WRAP_1]) AS [LIMIT_OFFSET_WRAP_2] WHERE [LIMIT_OFFSET_ROWNUM] > ? AND [LIMIT_OFFSET_ROWNUM] <= ? + ?', + 'parameters' => array('offset' => 5, 'limit' => 10, 'offsetForSum' => 5), + ),*/ ], ], 'LimitOffset_ParametersOrder' => [ - 'sqlObject' => function () { - $select = $this->select()->from(['x' => 'foo'])->limit(5)->offset(10); - $select->where->greaterThan('x.id', '10')->AND->lessThan('x.id', '31'); - return $select; - }, + 'sqlObject' => $this->select()->from('foo')->where(['x' => 7])->limit(5), 'expected' => [ - 'IbmDb2' => [ - 'string' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" WHERE "x"."id" > \'10\' AND "x"."id" < \'31\' ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 11 AND 15', - 'prepare' => 'SELECT * FROM ( SELECT "x".*, ROW_NUMBER() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" WHERE "x"."id" > ? AND "x"."id" < ? ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', - 'parameters' => ['offset' => 11, 'limit' => 15, 'expr1' => '10', 'expr2' => '31'], + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo" WHERE "x" = \'7\' LIMIT \'5\'', + 'prepare' => 'SELECT "foo".* FROM "foo" WHERE "x" = ? LIMIT ?', + //TODO 'parameters' => array('subselect2expr1' => 7, 'limit' => 5), + ], + 'MySql' => [ + 'string' => 'SELECT `foo`.* FROM `foo` WHERE `x` = \'7\' LIMIT 5', + 'prepare' => 'SELECT `foo`.* FROM `foo` WHERE `x` = ? LIMIT ?', + //TODO 'parameters' => array('subselect2expr1' => 7, 'limit' => 5), ], - ], - ], - //================================================================== - // Else - [ - 'sqlObject' => $this->select()->columns([new Expression('DISTINCT(id) as id')])->from(['x' => 'foo'])->limit(5)->offset(10), - 'expected' => [ 'IbmDb2' => [ - 'string' => 'SELECT DISTINCT(id) as id FROM ( SELECT DISTINCT(id) as id, DENSE_RANK() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN 11 AND 15', - 'prepare' => 'SELECT DISTINCT(id) as id FROM ( SELECT DISTINCT(id) as id, DENSE_RANK() OVER () AS ZEND_DB_ROWNUM FROM "foo" "x" ) AS ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION WHERE ZEND_IBMDB2_SERVER_LIMIT_OFFSET_EMULATION.ZEND_DB_ROWNUM BETWEEN ? AND ?', - 'parameters' => ['offset' => 11, 'limit' => 15], + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo" WHERE "x" = \'7\') "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" <= \'5\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo" WHERE "x" = ?) "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" <= ?', + 'parameters' => ['subselect2expr1' => 7, 'limit' => 5], + ], + 'Oracle' => [ + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo" WHERE "x" = \'7\') "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" <= \'5\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS "LIMIT_OFFSET_ROWNUM" FROM (SELECT "foo".* FROM "foo" WHERE "x" = ?) "LIMIT_OFFSET_WRAP_1") "LIMIT_OFFSET_WRAP_2" WHERE "LIMIT_OFFSET_ROWNUM" <= ?', + 'parameters' => ['subselect2expr1' => 7, 'limit' => 5], + ], + 'SqlServer' => [ + 'string' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS [LIMIT_OFFSET_ROWNUM] FROM (SELECT [foo].* FROM [foo] WHERE [x] = \'7\') AS [LIMIT_OFFSET_WRAP_1]) AS [LIMIT_OFFSET_WRAP_2] WHERE [LIMIT_OFFSET_ROWNUM] <= \'5\'', + 'prepare' => 'SELECT * FROM (SELECT *, ROW_NUMBER() OVER () AS [LIMIT_OFFSET_ROWNUM] FROM (SELECT [foo].* FROM [foo] WHERE [x] = ?) AS [LIMIT_OFFSET_WRAP_1]) AS [LIMIT_OFFSET_WRAP_2] WHERE [LIMIT_OFFSET_ROWNUM] <= ?', + 'parameters' => ['subselect2expr1' => 7, 'limit' => 5], ], ], ], From ab3bef3f696afd2ea959be42383409ee30793ba6 Mon Sep 17 00:00:00 2001 From: turrsis Date: Wed, 29 Jul 2015 16:12:21 +0300 Subject: [PATCH 08/30] architecture fix 07: use TableIdentifier in all SqlObjects --- src/RowGateway/AbstractRowGateway.php | 4 +- src/RowGateway/RowGateway.php | 5 +- src/Sql/Builder/AbstractSqlBuilder.php | 18 ++-- .../SqlServer/Ddl/CreateTableBuilder.php | 2 +- .../Builder/sql92/Ddl/AlterTableBuilder.php | 2 +- .../Builder/sql92/Ddl/CreateTableBuilder.php | 2 +- .../Builder/sql92/Ddl/DropTableBuilder.php | 2 +- src/Sql/Builder/sql92/DeleteBuilder.php | 4 +- src/Sql/Builder/sql92/InsertBuilder.php | 6 +- src/Sql/Builder/sql92/UpdateBuilder.php | 12 +-- src/Sql/Ddl/AlterTable.php | 15 +-- src/Sql/Ddl/CreateTable.php | 13 +-- src/Sql/Ddl/DropTable.php | 11 ++- src/Sql/Delete.php | 19 ++-- src/Sql/Insert.php | 25 ++--- src/Sql/Join.php | 12 +-- src/Sql/Select.php | 59 +++--------- src/Sql/Sql.php | 43 +++++++-- src/Sql/TableIdentifier.php | 14 +++ src/Sql/TableSource.php | 92 +++++++++++++++++++ src/Sql/Update.php | 18 ++-- src/TableGateway/AbstractTableGateway.php | 29 ++---- src/TableGateway/TableGateway.php | 14 +-- test/RowGateway/AbstractRowGatewayTest.php | 10 +- test/Sql/Builder/SelectBuilderTest.php | 14 +++ test/Sql/Ddl/AlterTableTest.php | 9 +- test/Sql/Ddl/CreateTableTest.php | 20 ++-- test/Sql/Ddl/DropTableTest.php | 6 +- test/Sql/DeleteTest.php | 4 +- test/Sql/InsertTest.php | 6 +- test/Sql/SelectTest.php | 20 +--- test/Sql/SqlTest.php | 28 +++++- test/Sql/TableIdentifierTest.php | 2 +- test/Sql/TableSourceTest.php | 83 +++++++++++++++++ test/Sql/UpdateTest.php | 10 +- .../TableGateway/AbstractTableGatewayTest.php | 9 +- test/TableGateway/TableGatewayTest.php | 35 ++++--- 37 files changed, 442 insertions(+), 235 deletions(-) create mode 100644 src/Sql/TableSource.php create mode 100644 test/Sql/TableSourceTest.php diff --git a/src/RowGateway/AbstractRowGateway.php b/src/RowGateway/AbstractRowGateway.php index c4284a8b5b..cff1c7c337 100644 --- a/src/RowGateway/AbstractRowGateway.php +++ b/src/RowGateway/AbstractRowGateway.php @@ -22,7 +22,7 @@ abstract class AbstractRowGateway implements ArrayAccess, Countable, RowGatewayI protected $isInitialized = false; /** - * @var string|TableIdentifier + * @var TableIdentifier */ protected $table = null; @@ -67,7 +67,7 @@ public function initialize() $this->featureSet->setRowGateway($this); $this->featureSet->apply('preInitialize', []); - if (!is_string($this->table) && !$this->table instanceof TableIdentifier) { + if (!$this->table instanceof TableIdentifier) { throw new Exception\RuntimeException('This row object does not have a valid table set.'); } diff --git a/src/RowGateway/RowGateway.php b/src/RowGateway/RowGateway.php index 8ce5db176e..34407ec993 100644 --- a/src/RowGateway/RowGateway.php +++ b/src/RowGateway/RowGateway.php @@ -11,6 +11,7 @@ use Zend\Db\Adapter\Adapter; use Zend\Db\Sql\Sql; +use Zend\Db\Sql\TableIdentifier; class RowGateway extends AbstractRowGateway { @@ -28,7 +29,7 @@ public function __construct($primaryKeyColumn, $table, $adapterOrSql = null) $this->primaryKeyColumn = empty($primaryKeyColumn) ? null : (array) $primaryKeyColumn; // set table - $this->table = $table; + $this->table = new TableIdentifier($table); // set Sql object if ($adapterOrSql instanceof Sql) { @@ -39,7 +40,7 @@ public function __construct($primaryKeyColumn, $table, $adapterOrSql = null) throw new Exception\InvalidArgumentException('A valid Sql object was not provided.'); } - if ($this->sql->getTable() !== $this->table) { + if ($this->sql->getTable() != $this->table) { throw new Exception\InvalidArgumentException('The Sql object provided does not have a table that matches this row object'); } diff --git a/src/Sql/Builder/AbstractSqlBuilder.php b/src/Sql/Builder/AbstractSqlBuilder.php index 70742ae00f..a05be7aa4d 100644 --- a/src/Sql/Builder/AbstractSqlBuilder.php +++ b/src/Sql/Builder/AbstractSqlBuilder.php @@ -10,6 +10,7 @@ namespace Zend\Db\Sql\Builder; use Zend\Db\Sql\TableIdentifier; +use Zend\Db\Sql\TableSource; use Zend\Db\Sql\SelectableInterface; use Zend\Db\Sql\ExpressionInterface; use Zend\Db\Sql\ExpressionParameter; @@ -157,20 +158,15 @@ protected function nornalizeTable($identifier, Context $context) $alias = null; $columnAlias = null; + if ($identifier instanceof TableSource) { + $alias = $identifier->getAlias(); + $identifier = $identifier->getSource(); + } if ($identifier instanceof TableIdentifier) { $name = $identifier->getTable(); $schema = $identifier->getSchema(); - } elseif (is_string($identifier)) { + } else { $name = $identifier; - } elseif (is_array($identifier)) { - if (is_string(key($identifier))) { - $alias = key($identifier); - $name = current($identifier); - } elseif ($name) { - $schema = isset($identifier[0]) ? $identifier[0] : null; - $name = isset($identifier[1]) ? $identifier[1] : null; - $alias = isset($identifier[2]) ? $identifier[2] : null; - } } if ($alias) { @@ -262,7 +258,7 @@ private function buildSpecificationParameter($parameter, Context $context = null $type = ExpressionInterface::TYPE_LITERAL; } - if ($value instanceof TableIdentifier) { + if ($value instanceof TableIdentifier || $value instanceof TableSource) { $parameter = $this->nornalizeTable($value, $context)['name']; } elseif ($value instanceof SelectableInterface) { $parameter = $this->buildSubSelect($value, $context); diff --git a/src/Sql/Builder/SqlServer/Ddl/CreateTableBuilder.php b/src/Sql/Builder/SqlServer/Ddl/CreateTableBuilder.php index e1f3d7be11..3654383b29 100644 --- a/src/Sql/Builder/SqlServer/Ddl/CreateTableBuilder.php +++ b/src/Sql/Builder/SqlServer/Ddl/CreateTableBuilder.php @@ -22,7 +22,7 @@ class CreateTableBuilder extends BaseBuilder */ protected function build_Table(CreateTable $sqlObject, Context $context) { - $table = ($sqlObject->isTemporary ? '#' : '') . ltrim($sqlObject->table, '#'); + $table = ($sqlObject->isTemporary ? '#' : '') . ltrim($sqlObject->table->getTable(), '#'); return [ 'spec' => $this->tableSpecification, 'params' => [ diff --git a/src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php b/src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php index 2aa487ab6f..5bc8bbf8d6 100644 --- a/src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php @@ -65,7 +65,7 @@ protected function build_Table(AlterTable $sqlObject, Context $context) return [ 'spec' => $this->tableSpecification, 'params' => [ - $context->getPlatform()->quoteIdentifier($sqlObject->table), + $sqlObject->table, ], ]; } diff --git a/src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php b/src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php index eb285339e0..16764cf659 100644 --- a/src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php @@ -56,7 +56,7 @@ protected function build_Table(CreateTable $sqlObject, Context $context) 'spec' => $this->tableSpecification, 'params' => [ $sqlObject->isTemporary ? 'TEMPORARY ' : '', - $context->getPlatform()->quoteIdentifier($sqlObject->table), + $sqlObject->table, ], ]; } diff --git a/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php b/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php index bf6d3f3a0e..c8a025f7dc 100644 --- a/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php @@ -40,7 +40,7 @@ protected function build_Table(DropTable $sqlObject, Context $context) return [ 'spec' => $this->tableSpecification, 'params' => [ - $context->getPlatform()->quoteIdentifier($sqlObject->table), + $sqlObject->table, ], ]; } diff --git a/src/Sql/Builder/sql92/DeleteBuilder.php b/src/Sql/Builder/sql92/DeleteBuilder.php index 13d1e489bb..c8a30d600c 100644 --- a/src/Sql/Builder/sql92/DeleteBuilder.php +++ b/src/Sql/Builder/sql92/DeleteBuilder.php @@ -41,9 +41,7 @@ protected function build_Delete(Delete $sqlObject, Context $context) { return [ 'spec' => $this->deleteSpecification, - 'params' => [ - $this->nornalizeTable($sqlObject->table, $context)['name'], - ], + 'params' => $sqlObject->table, ]; } diff --git a/src/Sql/Builder/sql92/InsertBuilder.php b/src/Sql/Builder/sql92/InsertBuilder.php index 7bb8ef02db..a6fe0768e2 100644 --- a/src/Sql/Builder/sql92/InsertBuilder.php +++ b/src/Sql/Builder/sql92/InsertBuilder.php @@ -85,7 +85,7 @@ protected function build_Insert(Insert $sqlObject, Context $context) return [ 'spec' => $this->insertSpecification, 'params' => [ - $this->nornalizeTable($sqlObject->table, $context)['name'], + $sqlObject->table, $columns, $values, ], @@ -107,7 +107,7 @@ protected function build_Select(Insert $sqlObject, Context $context) return [ 'spec' => $this->selectSpecification, 'params' => [ - $this->nornalizeTable($sqlObject->table, $context)['name'], + $sqlObject->table, array_map([$context->getPlatform(), 'quoteIdentifier'], $sqlObject->columns), $sqlObject->select ], @@ -116,7 +116,7 @@ protected function build_Select(Insert $sqlObject, Context $context) return [ 'spec' => $this->selectSpecification, 'params' => [ - $this->nornalizeTable($sqlObject->table, $context)['name'], + $sqlObject->table, $sqlObject->select ], ]; diff --git a/src/Sql/Builder/sql92/UpdateBuilder.php b/src/Sql/Builder/sql92/UpdateBuilder.php index 284acf9525..36b347d485 100644 --- a/src/Sql/Builder/sql92/UpdateBuilder.php +++ b/src/Sql/Builder/sql92/UpdateBuilder.php @@ -24,8 +24,8 @@ class UpdateBuilder extends AbstractSqlBuilder ];*/ protected $joinsSpecification = [ 'forEach' => [ - 'byArgNumber' => [ - 2 => [ + 'byArgNumber' => [ + 2 => [ 'byCount' => [ 1 => '%1$s', 2 => '%1$s AS %2$s' ], @@ -68,10 +68,10 @@ public function build($sqlObject, Context $context) */ protected function build_Update(Update $sqlObject, Context $context) { - return sprintf( - $this->updateSpecification, - $this->nornalizeTable($sqlObject->table, $context)['name'] - ); + return [ + 'spec' => $this->updateSpecification, + 'params' => $sqlObject->table, + ]; } /** diff --git a/src/Sql/Ddl/AlterTable.php b/src/Sql/Ddl/AlterTable.php index cf156dae31..a07e28173a 100644 --- a/src/Sql/Ddl/AlterTable.php +++ b/src/Sql/Ddl/AlterTable.php @@ -10,6 +10,7 @@ namespace Zend\Db\Sql\Ddl; use Zend\Db\Sql\AbstractSqlObject; +use Zend\Db\Sql\TableIdentifier; /** * @property null|string|array|TableIdentifier $table @@ -48,9 +49,9 @@ class AlterTable extends AbstractSqlObject /** - * @var string + * @var TableIdentifier */ - protected $table = ''; + protected $table; protected $__getProperties = [ 'table', @@ -62,21 +63,21 @@ class AlterTable extends AbstractSqlObject ]; /** - * @param string $table + * @param string|array|TableIdentifier $table */ - public function __construct($table = '') + public function __construct($table = null) { parent::__construct(); - ($table) ? $this->setTable($table) : null; + $this->setTable($table); } /** - * @param string $name + * @param string|array|TableIdentifier $name * @return self */ public function setTable($name) { - $this->table = $name; + $this->table = TableIdentifier::factory($name); return $this; } diff --git a/src/Sql/Ddl/CreateTable.php b/src/Sql/Ddl/CreateTable.php index d0adb0de26..bc394979fc 100644 --- a/src/Sql/Ddl/CreateTable.php +++ b/src/Sql/Ddl/CreateTable.php @@ -10,9 +10,10 @@ namespace Zend\Db\Sql\Ddl; use Zend\Db\Sql\AbstractSqlObject; +use Zend\Db\Sql\TableIdentifier; /** - * @property null|string|array|TableIdentifier $table + * @property TableIdentifier $table * @property array $columns * @property array $constraints * @property bool $isTemporary @@ -42,18 +43,18 @@ class CreateTable extends AbstractSqlObject ]; /** - * @var string + * @var TableIdentifier */ - protected $table = ''; + protected $table; /** * @param string $table * @param bool $isTemporary */ - public function __construct($table = '', $isTemporary = false) + public function __construct($table = null, $isTemporary = false) { parent::__construct(); - $this->table = $table; + $this->setTable($table); $this->setTemporary($isTemporary); } @@ -81,7 +82,7 @@ public function isTemporary() */ public function setTable($name) { - $this->table = $name; + $this->table = TableIdentifier::factory($name); return $this; } diff --git a/src/Sql/Ddl/DropTable.php b/src/Sql/Ddl/DropTable.php index a6964324f6..29610329fa 100644 --- a/src/Sql/Ddl/DropTable.php +++ b/src/Sql/Ddl/DropTable.php @@ -10,16 +10,17 @@ namespace Zend\Db\Sql\Ddl; use Zend\Db\Sql\AbstractSqlObject; +use Zend\Db\Sql\TableIdentifier; /** - * @property null|string|array|TableIdentifier $table + * @property TableIdentifier $table */ class DropTable extends AbstractSqlObject { /** - * @var string + * @var TableIdentifier */ - protected $table = ''; + protected $table; protected $__getProperties = [ 'table', @@ -28,9 +29,9 @@ class DropTable extends AbstractSqlObject /** * @param string $table */ - public function __construct($table = '') + public function __construct($table = null) { parent::__construct(); - $this->table = $table; + $this->table = TableIdentifier::factory($table); } } diff --git a/src/Sql/Delete.php b/src/Sql/Delete.php index ffb7f62f39..6da40c0eb0 100644 --- a/src/Sql/Delete.php +++ b/src/Sql/Delete.php @@ -10,13 +10,13 @@ namespace Zend\Db\Sql; /** - * @property null|string|array|TableIdentifier $table + * @property TableSource $table * @property Where $where */ class Delete extends AbstractSqlObject implements PreparableSqlObjectInterface { /** - * @var string|TableIdentifier + * @var TableSource */ protected $table = ''; @@ -33,26 +33,24 @@ class Delete extends AbstractSqlObject implements PreparableSqlObjectInterface /** * Constructor * - * @param null|string|TableIdentifier $table + * @param null|string|array|TableIdentifier|TableSource $table */ public function __construct($table = null) { parent::__construct(); - if ($table) { - $this->from($table); - } + $this->from($table); $this->where = new Where(); } /** * Create from statement * - * @param string|TableIdentifier $table + * @param string|array|TableIdentifier|TableSource $table * @return Delete */ public function from($table) { - $this->table = $table; + $this->table = TableSource::factory($table); return $this; } @@ -73,4 +71,9 @@ public function where($predicate, $combination = Predicate\PredicateSet::OP_AND) } return $this; } + + public function __clone() + { + $this->table = clone $this->table; + } } diff --git a/src/Sql/Insert.php b/src/Sql/Insert.php index 02b01f8d13..f1de4343bc 100644 --- a/src/Sql/Insert.php +++ b/src/Sql/Insert.php @@ -10,7 +10,7 @@ namespace Zend\Db\Sql; /** - * @property null|string|array|TableIdentifier $table + * @property TableSource $table * @property array $columns * @property null|Select $select */ @@ -20,7 +20,7 @@ class Insert extends AbstractSqlObject implements PreparableSqlObjectInterface const VALUES_SET = 'set'; /** - * @var string|TableIdentifier + * @var TableSource */ protected $table = null; protected $columns = []; @@ -39,25 +39,23 @@ class Insert extends AbstractSqlObject implements PreparableSqlObjectInterface /** * Constructor * - * @param null|string|TableIdentifier $table + * @param null|string|array|TableIdentifier|TableSource $table */ public function __construct($table = null) { parent::__construct(); - if ($table) { - $this->into($table); - } + $this->into($table); } /** * Create INTO clause * - * @param string|TableIdentifier $table - * @return Insert + * @param string|array|TableIdentifier|TableSource $table + * @return self */ public function into($table) { - $this->table = $table; + $this->table = TableSource::factory($table); return $this; } @@ -65,7 +63,7 @@ public function into($table) * Specify columns * * @param array $columns - * @return Insert + * @return self */ public function columns(array $columns) { @@ -79,7 +77,7 @@ public function columns(array $columns) * @param array|SelectableInterface $values * @param string $flag one of VALUES_MERGE or VALUES_SET; defaults to VALUES_SET * @throws Exception\InvalidArgumentException - * @return Insert + * @return self */ public function values($values, $flag = self::VALUES_SET) { @@ -151,4 +149,9 @@ public function __get($name) } return parent::__get($name); } + + public function __clone() + { + $this->table = clone $this->table; + } } diff --git a/src/Sql/Join.php b/src/Sql/Join.php index 770e35a4c1..60bf3a4920 100644 --- a/src/Sql/Join.php +++ b/src/Sql/Join.php @@ -120,23 +120,15 @@ public function getJoins() */ public function join($name, $on, $columns = [Select::SQL_STAR], $type = Join::JOIN_INNER) { - if (is_array($name) && (! is_string(key($name)) || count($name) !== 1)) { - throw new Exception\InvalidArgumentException( - sprintf("join() expects '%s' as a single element associative array", array_shift($name)) - ); - } - - if (! is_array($columns)) { + if (!is_array($columns)) { $columns = [$columns]; } - $this->joins[] = [ - 'name' => $name, + 'name' => TableSource::factory($name), 'on' => $on, 'columns' => $columns, 'type' => $type ? $type : Join::JOIN_INNER ]; - return $this; } diff --git a/src/Sql/Select.php b/src/Sql/Select.php index 8fb257b920..8e0aa8c19c 100644 --- a/src/Sql/Select.php +++ b/src/Sql/Select.php @@ -11,7 +11,7 @@ /** * - * @property null|string|array|TableIdentifier $table + * @property TableSource $table * @property string|Expression $quantifier DISTINCT|ALL * @property array $columns * @property $joins @@ -46,18 +46,13 @@ class Select extends AbstractSqlObject implements PreparableSqlObjectInterface, * @var array Specifications */ - /** - * @var bool - */ - protected $tableReadOnly = false; - /** * @var bool */ protected $prefixColumnsWithTable = true; /** - * @var string|array|TableIdentifier + * @var TableSource */ protected $table = null; @@ -128,16 +123,12 @@ class Select extends AbstractSqlObject implements PreparableSqlObjectInterface, /** * Constructor * - * @param null|string|array|TableIdentifier $table + * @param null|string|array|TableIdentifier|TableSource $table */ public function __construct($table = null) { parent::__construct(); - if ($table) { - $this->from($table); - $this->tableReadOnly = true; - } - + $this->from($table); $this->where = new Where; $this->joins = new Join; $this->having = new Having; @@ -146,25 +137,12 @@ public function __construct($table = null) /** * Create from clause * - * @param string|array|TableIdentifier $table - * @throws Exception\InvalidArgumentException - * @return Select + * @param string|array|TableIdentifier|TableSource $table + * @return self */ public function from($table) { - if ($this->tableReadOnly) { - throw new Exception\InvalidArgumentException('Since this object was created with a table and/or schema in the constructor, it is read only.'); - } - - if (!is_string($table) && !is_array($table) && !$table instanceof TableIdentifier) { - throw new Exception\InvalidArgumentException('$table must be a string, array, or an instance of TableIdentifier'); - } - - if (is_array($table) && (!is_string(key($table)) || count($table) !== 1)) { - throw new Exception\InvalidArgumentException('from() expects $table as an array is a single element associative array'); - } - - $this->table = $table; + $this->table = TableSource::factory($table); return $this; } @@ -212,12 +190,11 @@ public function columns(array $columns, $prefixColumnsWithTable = true) /** * Create join clause * - * @param string|array $name + * @param string|array|TableIdentifier|TableSource $name * @param string $on * @param string|array $columns * @param string $type one of the JOIN_* constants * @return self - * @throws Exception\InvalidArgumentException */ public function join($name, $on, $columns = self::SQL_STAR, $type = self::JOIN_INNER) { @@ -365,12 +342,7 @@ public function __unset($name) { switch ($name) { case 'table': - if ($this->tableReadOnly) { - throw new Exception\InvalidArgumentException( - 'Since this object was created with a table and/or schema in the constructor, it is read only.' - ); - } - $this->table = null; + $this->table = TableSource::factory(null); break; case 'quantifier': $this->quantifier = null; @@ -413,16 +385,6 @@ public function __unset($name) return $this; } - /** - * Returns whether the table is read only or not. - * - * @return bool - */ - public function isTableReadOnly() - { - return $this->tableReadOnly; - } - /** * __clone * @@ -432,6 +394,9 @@ public function isTableReadOnly() */ public function __clone() { + if ($this->table) { + $this->table = clone $this->table; + } $this->where = clone $this->where; $this->joins = clone $this->joins; $this->having = clone $this->having; diff --git a/src/Sql/Sql.php b/src/Sql/Sql.php index 0026d715c8..018e0699f7 100644 --- a/src/Sql/Sql.php +++ b/src/Sql/Sql.php @@ -17,7 +17,7 @@ class Sql /** @var AdapterInterface */ protected $adapter = null; - /** @var string|array|TableIdentifier */ + /** @var TableIdentifier */ protected $table = null; /** @var Builder\Builder */ @@ -53,16 +53,23 @@ public function hasTable() return ($this->table !== null); } + /** + * @param null|string|array|TableIdentifier $table + * @return self + * @throws Exception\InvalidArgumentException + */ public function setTable($table) { - if (is_string($table) || is_array($table) || $table instanceof TableIdentifier) { - $this->table = $table; - } else { + if (!$table) { throw new Exception\InvalidArgumentException('Table must be a string, array or instance of TableIdentifier.'); } + $this->table = TableIdentifier::factory($table); return $this; } + /** + * @return TableIdentifier + */ public function getTable() { return $this->table; @@ -76,45 +83,65 @@ public function getBuilder() return $this->builder; } + /** + * @param null|string|array|TableIdentifier $table + * @return Select + * @throws Exception\InvalidArgumentException + */ public function select($table = null) { if ($this->table !== null && $table !== null) { throw new Exception\InvalidArgumentException(sprintf( 'This Sql object is intended to work with only the table "%s" provided at construction time.', - $this->table + $this->table->getTable() )); } return new Select(($table) ?: $this->table); } + /** + * @param null|string|array|TableIdentifier $table + * @return Insert + * @throws Exception\InvalidArgumentException + */ public function insert($table = null) { if ($this->table !== null && $table !== null) { throw new Exception\InvalidArgumentException(sprintf( 'This Sql object is intended to work with only the table "%s" provided at construction time.', - $this->table + $this->table->getTable() )); } return new Insert(($table) ?: $this->table); } + /** + * @param null|string|array|TableIdentifier $table + * @return Update + * @throws Exception\InvalidArgumentException + */ public function update($table = null) { if ($this->table !== null && $table !== null) { throw new Exception\InvalidArgumentException(sprintf( 'This Sql object is intended to work with only the table "%s" provided at construction time.', - $this->table + $this->table->getTable() )); } return new Update(($table) ?: $this->table); } + /** + * @param null|string|array|TableIdentifier $table + * @return Delete + * @throws Exception\InvalidArgumentException + */ public function delete($table = null) { if ($this->table !== null && $table !== null) { throw new Exception\InvalidArgumentException(sprintf( 'This Sql object is intended to work with only the table "%s" provided at construction time.', - $this->table + $this->table->getTable() )); } return new Delete(($table) ?: $this->table); diff --git a/src/Sql/TableIdentifier.php b/src/Sql/TableIdentifier.php index 85cb10e7f0..94bf6375a8 100644 --- a/src/Sql/TableIdentifier.php +++ b/src/Sql/TableIdentifier.php @@ -23,12 +23,26 @@ class TableIdentifier */ protected $schema; + public static function factory($table, $schema = null) + { + if (null === $table) { + return; + } + if ($table instanceof self) { + return $table; + } + return new self($table, $schema); + } /** * @param string $table * @param null|string $schema */ public function __construct($table, $schema = null) { + if (is_array($table)) { + $schema = isset($table[0]) ? $table[0] : $schema; + $table = isset($table[1]) ? $table[1] : null; + } if (! (is_string($table) || is_callable([$table, '__toString']))) { throw new Exception\InvalidArgumentException(sprintf( '$table must be a valid table name, parameter of type %s given', diff --git a/src/Sql/TableSource.php b/src/Sql/TableSource.php new file mode 100644 index 0000000000..5f957ded36 --- /dev/null +++ b/src/Sql/TableSource.php @@ -0,0 +1,92 @@ +setSource($source); + $this->alias = $alias; + } + + /** + * @param string $alias + * @return self + */ + public function setAlias($alias) + { + $this->alias = $alias; + return $this; + } + + /** + * @return string + */ + public function getAlias() + { + return $this->alias; + } + + /** + * @param string|array|TableIdentifier|SelectableInterface|ExpressionInterface $source + * @return self + */ + public function setSource($source) + { + if (is_string($source) || is_array($source)) { + $source = new TableIdentifier($source); + } elseif ($source !== null && !$source instanceof TableIdentifier && !$source instanceof ExpressionInterface && !$source instanceof SelectableInterface) { + throw new Exception\InvalidArgumentException('invalid $source parameter'); + } + + $this->source = $source; + return $this; + } + + /** + * @return TableIdentifier|SelectableInterface|ExpressionInterface + */ + public function getSource() + { + return $this->source; + } +} diff --git a/src/Sql/Update.php b/src/Sql/Update.php index 63d1c5e3c2..4374b8b488 100644 --- a/src/Sql/Update.php +++ b/src/Sql/Update.php @@ -12,7 +12,7 @@ use Zend\Stdlib\PriorityList; /** - * @property null|string|array|TableIdentifier $table + * @property TableSource $table * @property PriorityList $set * @property Where $where */ @@ -22,7 +22,7 @@ class Update extends AbstractSqlObject implements PreparableSqlObjectInterface const VALUES_SET = 'set'; /** - * @var string|TableIdentifier + * @var TableSource */ protected $table = ''; @@ -51,14 +51,12 @@ class Update extends AbstractSqlObject implements PreparableSqlObjectInterface /** * Constructor * - * @param null|string|TableIdentifier $table + * @param null|string|array|TableIdentifier|TableSource $table */ public function __construct($table = null) { parent::__construct(); - if ($table) { - $this->table($table); - } + $this->table($table); $this->where = new Where(); $this->joins = new Join(); $this->set = new PriorityList(); @@ -68,12 +66,12 @@ public function __construct($table = null) /** * Specify table for statement * - * @param string|TableIdentifier $table + * @param string|array|TableIdentifier|TableSource $table * @return self */ public function table($table) { - $this->table = $table; + $this->table = TableSource::factory($table); return $this; } @@ -87,7 +85,7 @@ public function table($table) */ public function set(array $values, $flag = self::VALUES_SET) { - if ($values === null) { + if ($values == null) { throw new Exception\InvalidArgumentException('set() expects an array of values'); } @@ -148,6 +146,8 @@ public function join($name, $on, $type = Join::JOIN_INNER) */ public function __clone() { + $this->table = clone $this->table; + $this->joins = clone $this->joins; $this->where = clone $this->where; $this->set = clone $this->set; } diff --git a/src/TableGateway/AbstractTableGateway.php b/src/TableGateway/AbstractTableGateway.php index 4f2fe5e73e..8292fe9f2c 100644 --- a/src/TableGateway/AbstractTableGateway.php +++ b/src/TableGateway/AbstractTableGateway.php @@ -17,7 +17,7 @@ use Zend\Db\Sql\Join; use Zend\Db\Sql\Select; use Zend\Db\Sql\Sql; -use Zend\Db\Sql\TableIdentifier; +use Zend\Db\Sql\TableSource; use Zend\Db\Sql\Update; use Zend\Db\Sql\Where; use Zend\Db\TableGateway\Feature\EventFeatureEventsInterface; @@ -41,7 +41,7 @@ abstract class AbstractTableGateway implements TableGatewayInterface protected $adapter = null; /** - * @var string|array|TableIdentifier + * @var TableSource */ protected $table = null; @@ -102,7 +102,7 @@ public function initialize() throw new Exception\RuntimeException('This table does not have an Adapter setup'); } - if (!is_string($this->table) && !$this->table instanceof TableIdentifier && !is_array($this->table)) { + if (!$this->table instanceof TableSource) { throw new Exception\RuntimeException('This table object does not have a valid table set.'); } @@ -122,7 +122,7 @@ public function initialize() /** * Get table name * - * @return string + * @return TableSource */ public function getTable() { @@ -216,11 +216,7 @@ public function selectWith(Select $select) */ protected function executeSelect(Select $select) { - $selectTable = $select->table; - if ($selectTable != $this->table - && (is_array($selectTable) - && end($selectTable) != $this->table) - ) { + if ($select->table->getSource() != $this->table->getSource()) { throw new Exception\RuntimeException( 'The table name of the provided Select object must match that of the table' ); @@ -285,7 +281,7 @@ public function insertWith(Insert $insert) */ protected function executeInsert(Insert $insert) { - if ($insert->table != $this->table) { + if ($insert->table->getSource() != $this->table->getSource()) { throw new Exception\RuntimeException( 'The table name of the provided Insert object must match that of the table' ); @@ -369,7 +365,7 @@ public function updateWith(Update $update) */ protected function executeUpdate(Update $update) { - if ($update->table != $this->table) { + if ($update->table->getSource() != $this->table->getSource()) { throw new Exception\RuntimeException( 'The table name of the provided Update object must match that of the table' ); @@ -438,7 +434,7 @@ public function deleteWith(Delete $delete) */ protected function executeDelete(Delete $delete) { - if ($delete->table != $this->table) { + if ($delete->table->getSource() != $this->table->getSource()) { throw new Exception\RuntimeException( 'The table name of the provided Delete object must match that of the table' ); @@ -528,15 +524,8 @@ public function __clone() { $this->resultSetPrototype = (isset($this->resultSetPrototype)) ? clone $this->resultSetPrototype : null; $this->sql = clone $this->sql; - if (is_object($this->table)) { + if ($this->table) { $this->table = clone $this->table; - } elseif (is_array($this->table) - && count($this->table) == 1 - && is_object(reset($this->table)) - ) { - foreach ($this->table as $alias => &$tableObject) { - $tableObject = clone $tableObject; - } } } } diff --git a/src/TableGateway/TableGateway.php b/src/TableGateway/TableGateway.php index e2622baea9..da020aeea4 100644 --- a/src/TableGateway/TableGateway.php +++ b/src/TableGateway/TableGateway.php @@ -13,14 +13,14 @@ use Zend\Db\ResultSet\ResultSet; use Zend\Db\ResultSet\ResultSetInterface; use Zend\Db\Sql\Sql; -use Zend\Db\Sql\TableIdentifier; +use Zend\Db\Sql\TableSource; class TableGateway extends AbstractTableGateway { /** * Constructor * - * @param string|TableIdentifier|array $table + * @param string|array|TableIdentifier|TableSource $table * @param AdapterInterface $adapter * @param Feature\AbstractFeature|Feature\FeatureSet|Feature\AbstractFeature[]|null $features * @param ResultSetInterface|null $resultSetPrototype @@ -31,10 +31,10 @@ class TableGateway extends AbstractTableGateway public function __construct($table, AdapterInterface $adapter, $features = null, ResultSetInterface $resultSetPrototype = null, Sql $sql = null) { // table - if (!(is_string($table) || $table instanceof TableIdentifier || is_array($table))) { + if (!$table) { throw new Exception\InvalidArgumentException('Table name must be a string or an instance of Zend\Db\Sql\TableIdentifier'); } - $this->table = $table; + $this->table = TableSource::factory($table); // adapter $this->adapter = $adapter; @@ -61,10 +61,10 @@ public function __construct($table, AdapterInterface $adapter, $features = null, $this->resultSetPrototype = ($resultSetPrototype) ?: new ResultSet; // Sql object (factory for select, insert, update, delete) - $this->sql = ($sql) ?: new Sql($this->adapter, $this->table); + $this->sql = ($sql) ?: new Sql($this->adapter, $this->table->getSource()); - // check sql object bound to same table - if ($this->sql->getTable() != $this->table) { + // check sql object bound to same table(); + if ($this->sql->getTable() != $this->table->getSource()) { throw new Exception\InvalidArgumentException('The table inside the provided Sql object must match the table of this TableGateway'); } diff --git a/test/RowGateway/AbstractRowGatewayTest.php b/test/RowGateway/AbstractRowGatewayTest.php index 6dc3d32f3c..f83d2540fe 100644 --- a/test/RowGateway/AbstractRowGatewayTest.php +++ b/test/RowGateway/AbstractRowGatewayTest.php @@ -12,6 +12,7 @@ use Zend\Db\RowGateway\RowGateway; use Zend\Db\Adapter\ParameterContainer; use ZendTest\Db\TestAsset\TrustingSql92Platform; +use Zend\Db\Sql\TableIdentifier; class AbstractRowGatewayTest extends \PHPUnit_Framework_TestCase { @@ -41,10 +42,11 @@ public function setup() $this->rowGateway = $this->getMockForAbstractClass('Zend\Db\RowGateway\AbstractRowGateway'); + $table = new TableIdentifier('foo'); $rgPropertyValues = [ 'primaryKeyColumn' => 'id', - 'table' => 'foo', - 'sql' => new \Zend\Db\Sql\Sql($this->mockAdapter) + 'table' => $table, + 'sql' => new \Zend\Db\Sql\Sql($this->mockAdapter, $table) ]; $this->setRowGatewayState($rgPropertyValues); } @@ -164,7 +166,7 @@ public function testSaveInsertMultiKey() $rgPropertyValues = [ 'primaryKeyColumn' => ['one', 'two'], - 'table' => 'foo', + 'table' => new TableIdentifier('foo'), 'sql' => $mockSql ]; $this->setRowGatewayState($rgPropertyValues); @@ -212,7 +214,7 @@ public function testSaveUpdateChangingPrimaryKey() ->with($this->equalTo(['id' => 7])) ->will($this->returnValue($selectMock)); - $sqlMock = $this->getMock('Zend\Db\Sql\Sql', ['select'], [$this->mockAdapter]); + $sqlMock = $this->getMock('Zend\Db\Sql\Sql', ['select'], [$this->mockAdapter, new TableIdentifier('foo')]); $sqlMock->expects($this->any()) ->method('select') ->will($this->returnValue($selectMock)); diff --git a/test/Sql/Builder/SelectBuilderTest.php b/test/Sql/Builder/SelectBuilderTest.php index 2ee72f609f..68d1a4557f 100644 --- a/test/Sql/Builder/SelectBuilderTest.php +++ b/test/Sql/Builder/SelectBuilderTest.php @@ -915,6 +915,20 @@ public function dataProvider_Table() ], ], ], + 'string table with alias and schema' => [ + 'sqlObject' => $this->select()->from(['x' => ['bar', 'foo']]), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "x".* FROM "bar"."foo" AS "x"', + 'prepare' => true, + ], + 'Oracle' => [ + 'string' => 'SELECT "x".* FROM "bar"."foo" "x"', + 'prepare' => true, + 'parameters' => [], + ], + ], + ], 'table as TableIdentifier' => [ // table as TableIdentifier 'sqlObject' => $this->select()->from(new TableIdentifier('foo', 'bar')), 'expected' => [ diff --git a/test/Sql/Ddl/AlterTableTest.php b/test/Sql/Ddl/AlterTableTest.php index 8f002b574a..e2b97d284c 100644 --- a/test/Sql/Ddl/AlterTableTest.php +++ b/test/Sql/Ddl/AlterTableTest.php @@ -10,6 +10,7 @@ namespace ZendTest\Db\Sql\Ddl; use Zend\Db\Sql\Ddl\AlterTable; +use Zend\Db\Sql\TableIdentifier; class AlterTableTest extends \PHPUnit_Framework_TestCase { @@ -19,9 +20,11 @@ class AlterTableTest extends \PHPUnit_Framework_TestCase public function testSetTable() { $at = new AlterTable(); - $this->assertEquals('', $at->table); - $this->assertSame($at, $at->setTable('test')); - $this->assertEquals('test', $at->table); + $this->assertEquals(null, $at->table); + + $this->assertSame(null, $at->setTable(null)->table); + $this->assertEquals('test', $at->setTable('test')->table->getTable()); + $this->assertEquals('test', $at->setTable(new TableIdentifier('test'))->table->getTable()); } /** diff --git a/test/Sql/Ddl/CreateTableTest.php b/test/Sql/Ddl/CreateTableTest.php index 9cb0954162..77c5766195 100644 --- a/test/Sql/Ddl/CreateTableTest.php +++ b/test/Sql/Ddl/CreateTableTest.php @@ -10,6 +10,7 @@ namespace ZendTest\Db\Sql\Ddl; use Zend\Db\Sql\Ddl\CreateTable; +use Zend\Db\Sql\TableIdentifier; class CreateTableTest extends \PHPUnit_Framework_TestCase { @@ -20,7 +21,7 @@ class CreateTableTest extends \PHPUnit_Framework_TestCase public function testObjectConstruction() { $ct = new CreateTable('foo', true); - $this->assertEquals('foo', $ct->table); + $this->assertEquals('foo', $ct->table->getTable()); $this->assertTrue($ct->isTemporary()); } @@ -36,6 +37,9 @@ public function testSetTemporary() $this->assertTrue($ct->isTemporary()); $ct->setTemporary('yes'); $this->assertTrue($ct->isTemporary()); + + $ct = new CreateTable('foo', true); + $this->assertTrue($ct->isTemporary()); } /** @@ -55,17 +59,11 @@ public function testIsTemporary() public function testSetTable() { $ct = new CreateTable(); - $this->assertEquals('', $ct->table); - $ct->setTable('test'); - return $ct; - } + $this->assertEquals(null, $ct->table); - /** - * @depends testSetTable - */ - public function testRawStateViaTable(CreateTable $ct) - { - $this->assertEquals('test', $ct->table); + $this->assertSame(null, $ct->setTable(null)->table); + $this->assertEquals('test', $ct->setTable('test')->table->getTable()); + $this->assertEquals('test', $ct->setTable(new TableIdentifier('test'))->table->getTable()); } /** diff --git a/test/Sql/Ddl/DropTableTest.php b/test/Sql/Ddl/DropTableTest.php index aed0dc90da..14c1fa1312 100644 --- a/test/Sql/Ddl/DropTableTest.php +++ b/test/Sql/Ddl/DropTableTest.php @@ -10,12 +10,16 @@ namespace ZendTest\Db\Sql\Ddl; use Zend\Db\Sql\Ddl\DropTable; +use Zend\Db\Sql\TableIdentifier; class DropTableTest extends \PHPUnit_Framework_TestCase { public function testObjectConstruction() { $ct = new DropTable('foo'); - $this->assertEquals('foo', $ct->table); + $this->assertEquals('foo', $ct->table->getTable()); + + $ct = new DropTable(new TableIdentifier('foo')); + $this->assertEquals('foo', $ct->table->getTable()); } } diff --git a/test/Sql/DeleteTest.php b/test/Sql/DeleteTest.php index 933b6a189f..a36a23f021 100644 --- a/test/Sql/DeleteTest.php +++ b/test/Sql/DeleteTest.php @@ -34,11 +34,11 @@ protected function setUp() public function testFrom() { $this->delete->from('foo', 'bar'); - $this->assertEquals('foo', $this->readAttribute($this->delete, 'table')); + $this->assertEquals('foo', $this->delete->table->getSource()->getTable()); $tableIdentifier = new TableIdentifier('foo', 'bar'); $this->delete->from($tableIdentifier); - $this->assertEquals($tableIdentifier, $this->readAttribute($this->delete, 'table')); + $this->assertEquals($tableIdentifier, $this->delete->table->getSource()); } public function test__Get() diff --git a/test/Sql/InsertTest.php b/test/Sql/InsertTest.php index 4148ee5b10..dca17e9436 100644 --- a/test/Sql/InsertTest.php +++ b/test/Sql/InsertTest.php @@ -11,7 +11,7 @@ use Zend\Db\Sql\Insert; use Zend\Db\Sql\Select; -use Zend\Db\Sql\TableIdentifier; +use Zend\Db\Sql\TableSource; class InsertTest extends \PHPUnit_Framework_TestCase { @@ -35,9 +35,9 @@ protected function setUp() public function testInto() { $this->insert->into('table', 'schema'); - $this->assertEquals('table', $this->insert->table); + $this->assertEquals('table', $this->insert->table->getSource()->getTable()); - $tableIdentifier = new TableIdentifier('table', 'schema'); + $tableIdentifier = TableSource::factory(['table', 'schema']); $this->insert->into($tableIdentifier); $this->assertEquals($tableIdentifier, $this->insert->table); } diff --git a/test/Sql/SelectTest.php b/test/Sql/SelectTest.php index dfaafb1d39..34665be12f 100644 --- a/test/Sql/SelectTest.php +++ b/test/Sql/SelectTest.php @@ -13,6 +13,8 @@ use Zend\Db\Sql\Where; use Zend\Db\Sql\Having; use Zend\Db\Sql\Predicate; +use Zend\Db\Sql\TableIdentifier; +use Zend\Db\Sql\TableSource; class SelectTest extends \PHPUnit_Framework_TestCase { @@ -22,7 +24,7 @@ class SelectTest extends \PHPUnit_Framework_TestCase public function testConstruct() { $select = new Select('foo'); - $this->assertEquals('foo', $select->table); + $this->assertEquals('foo', $select->table->getSource()->getTable()); } public function testMethodsReturnSelf() @@ -49,11 +51,11 @@ public function testMagicAccessor(Select $select) { $this->assertInstanceOf('Zend\Db\Sql\Where', $select->where); $this->assertEquals(['foo', 'bar'], $select->columns); - $this->assertEquals('foo', $select->table); + $this->assertEquals('foo', $select->table->getSource()->getTable()); $this->assertEquals(['col1', 'col2'], $select->group); $this->assertEquals( [[ - 'name' => 'foo', + 'name' => new TableSource(new TableIdentifier('foo')), 'on' => 'x = y', 'columns' => [Select::SQL_STAR], 'type' => Select::JOIN_INNER @@ -81,18 +83,6 @@ public function testQuantifierParameterExpressionInterface() ); } - /** - /** - * @testdox unit test: Test join() exception with bad join - * @covers Zend\Db\Sql\Select::join - */ - public function testBadJoin() - { - $select = new Select; - $this->setExpectedException('Zend\Db\Sql\Exception\InvalidArgumentException', "expects 'foo' as"); - $select->join(['foo'], 'x = y', Select::SQL_STAR, Select::JOIN_INNER); - } - /** * @testdox unit test: Test where() will accept any Predicate object as-is * @covers Zend\Db\Sql\Select::where diff --git a/test/Sql/SqlTest.php b/test/Sql/SqlTest.php index 698a73f4d4..cdf28b7e54 100644 --- a/test/Sql/SqlTest.php +++ b/test/Sql/SqlTest.php @@ -12,6 +12,7 @@ use Zend\Db\Sql\Sql; use ZendTest\Db\TestAsset; use Zend\Db\Adapter\Adapter; +use Zend\Db\Sql\TableIdentifier; class SqlTest extends \PHPUnit_Framework_TestCase { @@ -51,12 +52,29 @@ public function test__construct() $this->assertFalse($sql->hasTable()); $sql->setTable('foo'); - $this->assertSame('foo', $sql->getTable()); + $this->assertSame('foo', $sql->getTable()->getTable()); $this->setExpectedException('Zend\Db\Sql\Exception\InvalidArgumentException', 'Table must be a string, array or instance of TableIdentifier.'); $sql->setTable(null); } + /** + * @covers Zend\Db\Sql\Sql::setTable + */ + public function testSetTable() + { + $sql = new Sql($this->mockAdapter); + + $this->assertEquals('test', $sql->setTable('test')->getTable()->getTable()); + $this->assertEquals('test', $sql->setTable(new TableIdentifier('test'))->getTable()->getTable()); + + $this->setExpectedException( + 'Zend\Db\Sql\Exception\InvalidArgumentException', + 'Table must be a string, array or instance of TableIdentifier.' + ); + $sql->setTable(null); + } + /** * @covers Zend\Db\Sql\Sql::select */ @@ -64,7 +82,7 @@ public function testSelect() { $select = $this->sql->select(); $this->assertInstanceOf('Zend\Db\Sql\Select', $select); - $this->assertSame('foo', $select->table); + $this->assertSame('foo', $select->table->getSource()->getTable()); $this->setExpectedException('Zend\Db\Sql\Exception\InvalidArgumentException', 'This Sql object is intended to work with only the table "foo" provided at construction time.'); @@ -78,7 +96,7 @@ public function testInsert() { $insert = $this->sql->insert(); $this->assertInstanceOf('Zend\Db\Sql\Insert', $insert); - $this->assertSame('foo', $insert->table); + $this->assertSame('foo', $insert->table->getSource()->getTable()); $this->setExpectedException('Zend\Db\Sql\Exception\InvalidArgumentException', 'This Sql object is intended to work with only the table "foo" provided at construction time.'); @@ -92,7 +110,7 @@ public function testUpdate() { $update = $this->sql->update(); $this->assertInstanceOf('Zend\Db\Sql\Update', $update); - $this->assertSame('foo', $update->table); + $this->assertSame('foo', $update->table->getSource()->getTable()); $this->setExpectedException('Zend\Db\Sql\Exception\InvalidArgumentException', 'This Sql object is intended to work with only the table "foo" provided at construction time.'); @@ -107,7 +125,7 @@ public function testDelete() $delete = $this->sql->delete(); $this->assertInstanceOf('Zend\Db\Sql\Delete', $delete); - $this->assertSame('foo', $delete->table); + $this->assertSame('foo', $delete->table->getSource()->getTable()); $this->setExpectedException('Zend\Db\Sql\Exception\InvalidArgumentException', 'This Sql object is intended to work with only the table "foo" provided at construction time.'); diff --git a/test/Sql/TableIdentifierTest.php b/test/Sql/TableIdentifierTest.php index feb5c22cc6..fdaa6d1a4b 100644 --- a/test/Sql/TableIdentifierTest.php +++ b/test/Sql/TableIdentifierTest.php @@ -96,7 +96,7 @@ public function testRejectsInvalidSchema($invalidSchema) public function invalidTableProvider() { return array_merge( - [[null]], + [/*[null]*/], $this->invalidSchemaProvider() ); } diff --git a/test/Sql/TableSourceTest.php b/test/Sql/TableSourceTest.php new file mode 100644 index 0000000000..51c0ec70cc --- /dev/null +++ b/test/Sql/TableSourceTest.php @@ -0,0 +1,83 @@ +assertEquals( + ['schema', 'table', 'alias'], + [$t->getSource()->getSchema(), $t->getSource()->getTable(), $t->getAlias()] + ); + + $t = TableSource::factory(['alias'=>['schema', 'table']]); + $this->assertEquals( + ['schema', 'table', 'alias'], + [$t->getSource()->getSchema(), $t->getSource()->getTable(), $t->getAlias()] + ); + + $t = TableSource::factory(['alias'=>'table']); + $this->assertEquals( + [null, 'table', 'alias'], + [$t->getSource()->getSchema(), $t->getSource()->getTable(), $t->getAlias()] + ); + + $t = TableSource::factory(new TableIdentifier('table', 'schema')); + $this->assertEquals( + ['schema', 'table', null], + [$t->getSource()->getSchema(), $t->getSource()->getTable(), $t->getAlias()] + ); + + $t = TableSource::factory(['alias' => new TableIdentifier('table', 'schema')]); + $this->assertEquals( + ['schema', 'table', 'alias'], + [$t->getSource()->getSchema(), $t->getSource()->getTable(), $t->getAlias()] + ); + + $t = TableSource::factory(['schema', 'table']); + $this->assertEquals( + ['schema', 'table', null], + [$t->getSource()->getSchema(), $t->getSource()->getTable(), $t->getAlias()] + ); + + $t = TableSource::factory('table'); + $this->assertEquals( + [null, 'table', null], + [$t->getSource()->getSchema(), $t->getSource()->getTable(), $t->getAlias()] + ); + + $select = new Select(); + $t = TableSource::factory(['alias'=>$select]); + $this->assertEquals( + [null, $select, 'alias'], + [null, $t->getSource(), $t->getAlias()] + ); + + $t = TableSource::factory($select); + $this->assertEquals( + [null, $select, null], + [null, $t->getSource(), $t->getAlias()] + ); + + $expression = new Expression('psql_function_which_returns_table'); + $t = TableSource::factory(['alias' => $expression]); + $this->assertEquals( + [null, $expression, 'alias'], + [null, $t->getSource(), $t->getAlias()] + ); + } +} diff --git a/test/Sql/UpdateTest.php b/test/Sql/UpdateTest.php index 584d945160..6d3db27635 100644 --- a/test/Sql/UpdateTest.php +++ b/test/Sql/UpdateTest.php @@ -44,11 +44,11 @@ protected function tearDown() public function testTable() { $this->update->table('foo', 'bar'); - $this->assertEquals('foo', $this->readAttribute($this->update, 'table')); + $this->assertEquals('foo', $this->update->table->getSource()->getTable()); $tableIdentifier = new TableIdentifier('foo', 'bar'); $this->update->table($tableIdentifier); - $this->assertEquals($tableIdentifier, $this->readAttribute($this->update, 'table')); + $this->assertEquals($tableIdentifier, $this->update->table->getSource()); } /** @@ -57,7 +57,7 @@ public function testTable() public function testConstruct() { $update = new Update('foo'); - $this->assertEquals('foo', $this->readAttribute($update, 'table')); + $this->assertEquals('foo', $update->table->getSource()->getTable()); } /** @@ -99,7 +99,7 @@ public function test__Get() ->set(['bar' => 'baz']) ->where('x = y'); - $this->assertEquals('foo', $this->update->table); + $this->assertEquals('foo', $this->update->table->getSource()->getTable()); $this->assertEquals(['bar' => 'baz'], $this->update->set->toArray()); $this->assertInstanceOf('Zend\Db\Sql\Where', $this->update->where); } @@ -110,7 +110,7 @@ public function test__Get() */ public function testGetUpdate() { - $getWhere = $this->update->__get('where'); + $getWhere = $this->update->where; $this->assertInstanceOf('Zend\Db\Sql\Where', $getWhere); } diff --git a/test/TableGateway/AbstractTableGatewayTest.php b/test/TableGateway/AbstractTableGatewayTest.php index 9f019161fc..041da14f0b 100644 --- a/test/TableGateway/AbstractTableGatewayTest.php +++ b/test/TableGateway/AbstractTableGatewayTest.php @@ -13,6 +13,7 @@ use Zend\Db\Sql; use Zend\Db\Adapter\ParameterContainer; use Zend\Db\ResultSet\ResultSet; +use Zend\Db\Sql\TableSource; /** * Generated by PHPUnit_SkeletonGenerator on 2012-03-01 at 21:02:22. @@ -83,7 +84,7 @@ protected function setUp() $tgPropReflection->setAccessible(true); switch ($tgPropReflection->getName()) { case 'table': - $tgPropReflection->setValue($this->table, 'foo'); + $tgPropReflection->setValue($this->table, new TableSource('foo')); break; case 'adapter': $tgPropReflection->setValue($this->table, $this->mockAdapter); @@ -111,7 +112,7 @@ protected function tearDown() */ public function testGetTable() { - $this->assertEquals('foo', $this->table->getTable()); + $this->assertEquals('foo', $this->table->getTable()->getSource()->getTable()); } /** @@ -186,11 +187,11 @@ public function testSelectWithArrayTable() { // Case 1 - $select1 = new \Zend\Db\Sql\Select('bat'); + $select1 = new \Zend\Db\Sql\Select('foo'); $return = $this->table->selectWith($select1); $this->assertNotNull($return); - $this->assertEquals('SELECT "bat".* FROM "bat"', $this->mockStatement->getSql()); + $this->assertEquals('SELECT "foo".* FROM "foo"', $this->mockStatement->getSql()); // Case 2 diff --git a/test/TableGateway/TableGatewayTest.php b/test/TableGateway/TableGatewayTest.php index 7e3b334b9c..d4ddeca485 100644 --- a/test/TableGateway/TableGatewayTest.php +++ b/test/TableGateway/TableGatewayTest.php @@ -16,6 +16,7 @@ use Zend\Db\Sql\Update; use Zend\Db\Sql\Sql; use Zend\Db\Sql\TableIdentifier; +use Zend\Db\Sql\TableSource; /** * Generated by PHPUnit_SkeletonGenerator on 2012-03-01 at 21:02:22. @@ -50,7 +51,7 @@ public function testConstructor() $this->mockAdapter ); - $this->assertEquals('foo', $table->getTable()); + $this->assertEquals('foo', $table->getTable()->getSource()->getTable()); $this->assertSame($this->mockAdapter, $table->getAdapter()); $this->assertInstanceOf('Zend\Db\TableGateway\Feature\FeatureSet', $table->getFeatureSet()); $this->assertInstanceOf('Zend\Db\ResultSet\ResultSet', $table->getResultSetPrototype()); @@ -65,7 +66,7 @@ public function testConstructor() $sql = new Sql($this->mockAdapter, 'foo') ); - $this->assertEquals('foo', $table->getTable()); + $this->assertEquals('foo', $table->getTable()->getSource()->getTable()); $this->assertSame($this->mockAdapter, $table->getAdapter()); $this->assertSame($featureSet, $table->getFeatureSet()); $this->assertSame($resultSet, $table->getResultSetPrototype()); @@ -95,7 +96,7 @@ public function testTableAsString() $this->mockAdapter ); - $this->assertEquals($ti, $table->getTable()); + $this->assertEquals($ti, $table->getTable()->getSource()->getTable()); } /** @@ -111,7 +112,7 @@ public function testTableAsTableIdentifierObject() $this->mockAdapter ); - $this->assertEquals($ti, $table->getTable()); + $this->assertEquals($ti, $table->getTable()->getSource()); } /** @@ -127,7 +128,10 @@ public function testTableAsAliasedTableIdentifierObject() $this->mockAdapter ); - $this->assertEquals($aliasedTI, $table->getTable()); + $this->assertEquals( + ['foo', 'fooTable', 'barSchema'], + [$table->getTable()->getAlias(), $table->getTable()->getSource()->getTable(), $table->getTable()->getSource()->getSchema()] + ); } public function aliasedTables() @@ -163,7 +167,10 @@ public function testInsertShouldResetTableToUnaliasedTable($tableValue, $expecte ->will($this->returnValue($result)); $statementExpectation = function ($insert) use ($phpunit, $expected, $statement) { - $phpunit->assertSame($expected, $insert->table); + if ($expected instanceof TableIdentifier) { + $expected = $expected->getTable(); + } + $phpunit->assertSame($expected, $insert->table->getSource()->getTable()); return $statement; }; @@ -172,7 +179,7 @@ public function testInsertShouldResetTableToUnaliasedTable($tableValue, $expecte ->getMock(); $sql->expects($this->atLeastOnce()) ->method('getTable') - ->will($this->returnValue($tableValue)); + ->will($this->returnValue(TableSource::factory($tableValue)->getSource())); $sql->expects($this->once()) ->method('insert') ->will($this->returnValue($insert)); @@ -193,9 +200,9 @@ public function testInsertShouldResetTableToUnaliasedTable($tableValue, $expecte 'foo' => 'FOO', ]); - $this->assertInternalType('array', $insert->table); + $this->assertInstanceOf('Zend\Db\Sql\TableSource', $insert->table); $this->assertEquals( - $tableValue, + TableSource::factory($tableValue), $insert->table ); } @@ -223,7 +230,10 @@ public function testUpdateShouldResetTableToUnaliasedTable($tableValue, $expecte ->will($this->returnValue($result)); $statementExpectation = function ($update) use ($phpunit, $expected, $statement) { - $phpunit->assertSame($expected, $update->table); + if ($expected instanceof TableIdentifier) { + $expected = $expected->getTable(); + } + $phpunit->assertSame($expected, $update->table->getSource()->getTable()); return $statement; }; @@ -232,7 +242,7 @@ public function testUpdateShouldResetTableToUnaliasedTable($tableValue, $expecte ->getMock(); $sql->expects($this->atLeastOnce()) ->method('getTable') - ->will($this->returnValue($tableValue)); + ->will($this->returnValue(TableSource::factory($tableValue)->getSource())); $sql->expects($this->once()) ->method('update') ->will($this->returnValue($update)); @@ -255,8 +265,9 @@ public function testUpdateShouldResetTableToUnaliasedTable($tableValue, $expecte 'bar' => 'BAR' ]); + $this->assertInstanceOf('Zend\Db\Sql\TableSource', $update->table); $this->assertEquals( - $tableValue, + TableSource::factory($tableValue), $update->table ); } From d64c0baa0e71508af8ac68215c5c846ba119df85 Mon Sep 17 00:00:00 2001 From: turrsis Date: Sun, 12 Jul 2015 14:45:18 +0300 Subject: [PATCH 09/30] architecture fix 08: Column builder --- src/Sql/Builder/Builder.php | 15 +- .../Builder/Mysql/Ddl/AlterTableBuilder.php | 238 ------------------ .../Mysql/Ddl/Column/ColumnBuilder.php | 55 ++++ .../Builder/Mysql/Ddl/CreateTableBuilder.php | 170 ------------- .../Column/AbstractLengthColumnBuilder.php | 32 --- .../Column/AbstractPrecisionColumnBuilder.php | 22 -- .../Column/AbstractTimestampColumnBuilder.php | 56 ----- .../sql92/Ddl/Column/ColumnBuilder.php | 124 ++++++--- .../sql92/Ddl/Column/IntegerBuilder.php | 28 --- .../Builder/Ddl/CreateTableBuilderTest.php | 2 +- 10 files changed, 153 insertions(+), 589 deletions(-) delete mode 100644 src/Sql/Builder/Mysql/Ddl/AlterTableBuilder.php create mode 100644 src/Sql/Builder/Mysql/Ddl/Column/ColumnBuilder.php delete mode 100644 src/Sql/Builder/Mysql/Ddl/CreateTableBuilder.php delete mode 100644 src/Sql/Builder/sql92/Ddl/Column/AbstractLengthColumnBuilder.php delete mode 100644 src/Sql/Builder/sql92/Ddl/Column/AbstractPrecisionColumnBuilder.php delete mode 100644 src/Sql/Builder/sql92/Ddl/Column/AbstractTimestampColumnBuilder.php delete mode 100644 src/Sql/Builder/sql92/Ddl/Column/IntegerBuilder.php diff --git a/src/Sql/Builder/Builder.php b/src/Sql/Builder/Builder.php index cc01fe1da9..ba0d255afb 100644 --- a/src/Sql/Builder/Builder.php +++ b/src/Sql/Builder/Builder.php @@ -47,11 +47,9 @@ class Builder extends AbstractBuilder 'Zend\Db\Sql\Ddl\AlterTable' => [ 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\AlterTableBuilder', - 'mysql' => 'Zend\Db\Sql\Builder\MySql\Ddl\AlterTableBuilder', ], 'Zend\Db\Sql\Ddl\CreateTable' => [ 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\CreateTableBuilder', - 'mysql' => 'Zend\Db\Sql\Builder\MySql\Ddl\CreateTableBuilder', 'sqlserver' => 'Zend\Db\Sql\Builder\SqlServer\Ddl\CreateTableBuilder', ], 'Zend\Db\Sql\Ddl\DropTable' => [ @@ -91,20 +89,9 @@ class Builder extends AbstractBuilder 'Zend\Db\Sql\Predicate\Predicate' => [ 'sql92' => 'Zend\Db\Sql\Builder\sql92\Predicate\PredicateBuilder', ], - 'Zend\Db\Sql\Ddl\Column\AbstractPrecisionColumn' => [ - 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\Column\AbstractPrecisionColumnBuilder', - ], - 'Zend\Db\Sql\Ddl\Column\AbstractLengthColumn' => [ - 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\Column\AbstractLengthColumnBuilder', - ], - 'Zend\Db\Sql\Ddl\Column\AbstractTimestampColumn' => [ - 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\Column\AbstractTimestampColumnBuilder', - ], - 'Zend\Db\Sql\Ddl\Column\Integer' => [ - 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\Column\IntegerBuilder', - ], 'Zend\Db\Sql\Ddl\Column\Column' => [ 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\Column\ColumnBuilder', + 'mysql' => 'Zend\Db\Sql\Builder\Mysql\Ddl\Column\ColumnBuilder', ], 'Zend\Db\Sql\Ddl\Index\Index' => [ 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\Index\IndexBuilder', diff --git a/src/Sql/Builder/Mysql/Ddl/AlterTableBuilder.php b/src/Sql/Builder/Mysql/Ddl/AlterTableBuilder.php deleted file mode 100644 index 80d257023e..0000000000 --- a/src/Sql/Builder/Mysql/Ddl/AlterTableBuilder.php +++ /dev/null @@ -1,238 +0,0 @@ - 0, - 'zerofill' => 1, - 'identity' => 2, - 'serial' => 2, - 'autoincrement' => 2, - 'comment' => 3, - 'columnformat' => 4, - 'format' => 4, - 'storage' => 5, - ]; - - /** - * @param string $sql - * @return array - */ - protected function getSqlInsertOffsets($sql) - { - $sqlLength = strlen($sql); - $insertStart = []; - - foreach (['NOT NULL', 'NULL', 'DEFAULT', 'UNIQUE', 'PRIMARY', 'REFERENCES'] as $needle) { - $insertPos = strpos($sql, ' ' . $needle); - - if ($insertPos !== false) { - switch ($needle) { - case 'REFERENCES': - $insertStart[2] = !isset($insertStart[2]) ? $insertPos : $insertStart[2]; - // no break - case 'PRIMARY': - case 'UNIQUE': - $insertStart[1] = !isset($insertStart[1]) ? $insertPos : $insertStart[1]; - // no break - default: - $insertStart[0] = !isset($insertStart[0]) ? $insertPos : $insertStart[0]; - } - } - } - - foreach (range(0, 3) as $i) { - $insertStart[$i] = isset($insertStart[$i]) ? $insertStart[$i] : $sqlLength; - } - - return $insertStart; - } - - /** - * @param PlatformInterface $adapterPlatform - * @return array - */ - protected function build_AddColumns(AlterTable $sqlObject, Context $context) - { - $sqls = []; - - foreach ($sqlObject->addColumns as $i => $column) { - $sql = $this->buildSqlString($column, $context); - $insertStart = $this->getSqlInsertOffsets($sql); - $columnOptions = $column->getOptions(); - - uksort($columnOptions, [$this, 'compareColumnOptions']); - - foreach ($columnOptions as $coName => $coValue) { - $insert = ''; - - if (! $coValue) { - continue; - } - - switch ($this->normalizeColumnOption($coName)) { - case 'unsigned': - $insert = ' UNSIGNED'; - $j = 0; - break; - case 'zerofill': - $insert = ' ZEROFILL'; - $j = 0; - break; - case 'identity': - case 'serial': - case 'autoincrement': - $insert = ' AUTO_INCREMENT'; - $j = 1; - break; - case 'comment': - $insert = ' COMMENT ' . $context->getPlatform()->quoteValue($coValue); - $j = 2; - break; - case 'columnformat': - case 'format': - $insert = ' COLUMN_FORMAT ' . strtoupper($coValue); - $j = 2; - break; - case 'storage': - $insert = ' STORAGE ' . strtoupper($coValue); - $j = 2; - break; - } - - if ($insert) { - $j = isset($j) ? $j : 0; - $sql = substr_replace($sql, $insert, $insertStart[$j], 0); - $insertStartCount = count($insertStart); - for (; $j < $insertStartCount; ++$j) { - $insertStart[$j] += strlen($insert); - } - } - } - $sqls[$i] = $sql; - } - return [ - 'spec' => $this->specifications[self::SPECIFICATION_ADD_COLUMNS], - 'params' => [ - $sqls, - ], - ]; - } - - /** - * @param PlatformInterface $adapterPlatform - * @return array - */ - protected function build_ChangeColumns(AlterTable $sqlObject, Context $context) - { - $sqls = []; - foreach ($sqlObject->changeColumns as $name => $column) { - $sql = $this->buildSqlString($column, $context); - $insertStart = $this->getSqlInsertOffsets($sql); - $columnOptions = $column->getOptions(); - - uksort($columnOptions, [$this, 'compareColumnOptions']); - - foreach ($columnOptions as $coName => $coValue) { - $insert = ''; - - if (! $coValue) { - continue; - } - - switch ($this->normalizeColumnOption($coName)) { - case 'unsigned': - $insert = ' UNSIGNED'; - $j = 0; - break; - case 'zerofill': - $insert = ' ZEROFILL'; - $j = 0; - break; - case 'identity': - case 'serial': - case 'autoincrement': - $insert = ' AUTO_INCREMENT'; - $j = 1; - break; - case 'comment': - $insert = ' COMMENT ' . $context->getPlatform()->quoteValue($coValue); - $j = 2; - break; - case 'columnformat': - case 'format': - $insert = ' COLUMN_FORMAT ' . strtoupper($coValue); - $j = 2; - break; - case 'storage': - $insert = ' STORAGE ' . strtoupper($coValue); - $j = 2; - break; - } - - if ($insert) { - $j = isset($j) ? $j : 0; - $sql = substr_replace($sql, $insert, $insertStart[$j], 0); - $insertStartCount = count($insertStart); - for (; $j < $insertStartCount; ++$j) { - $insertStart[$j] += strlen($insert); - } - } - } - $sqls[] = [ - $adapterPlatform->quoteIdentifier($name), - $sql - ]; - } - - return [ - 'spec' => $this->specifications[self::SPECIFICATION_CHANGE_COLUMNS], - 'params' => [ - $sqls, - ], - ]; - } - - /** - * @param string $name - * - * @return string - */ - private function normalizeColumnOption($name) - { - return strtolower(str_replace(['-', '_', ' '], '', $name)); - } - - /** - * - * @param string $columnA - * @param string $columnB - * - * @return int - */ - private function compareColumnOptions($columnA, $columnB) - { - $columnA = $this->normalizeColumnOption($columnA); - $columnA = isset($this->columnOptionSortOrder[$columnA]) - ? $this->columnOptionSortOrder[$columnA] : count($this->columnOptionSortOrder); - - $columnB = $this->normalizeColumnOption($columnB); - $columnB = isset($this->columnOptionSortOrder[$columnB]) - ? $this->columnOptionSortOrder[$columnB] : count($this->columnOptionSortOrder); - - return $columnA - $columnB; - } -} diff --git a/src/Sql/Builder/Mysql/Ddl/Column/ColumnBuilder.php b/src/Sql/Builder/Mysql/Ddl/Column/ColumnBuilder.php new file mode 100644 index 0000000000..2eba064536 --- /dev/null +++ b/src/Sql/Builder/Mysql/Ddl/Column/ColumnBuilder.php @@ -0,0 +1,55 @@ +specifications = [ + 'name' => $this->specifications['name'], + 'type' => $this->specifications['type'], + 'typeData' => [ + 'spec' => [ + 'implode' => ' ', + ], + 'subProperties' => [ + 'unsigned' => [ + 'valueMap' => [true => 'UNSIGNED', false => null], + ], + 'zerofill' => [ + 'valueMap' => [true => 'ZEROFILL', false => null], + ], + ], + ], + 'nullable' => $this->specifications['nullable'], + 'identity' => [ + 'valueMap' => [true => 'AUTO_INCREMENT', false => null], + ], + 'constraints' => $this->specifications['constraints'], + 'default' => $this->specifications['default'], + 'comment' => [ + 'spec' => 'COMMENT %s', + 'propertyType' => ExpressionInterface::TYPE_VALUE, + ], + 'columnformat' => 'COLUMN_FORMAT %s', + 'storage' => 'STORAGE %s', + 'on_update' => 'ON UPDATE %s', + ]; + } +} diff --git a/src/Sql/Builder/Mysql/Ddl/CreateTableBuilder.php b/src/Sql/Builder/Mysql/Ddl/CreateTableBuilder.php deleted file mode 100644 index 8055463999..0000000000 --- a/src/Sql/Builder/Mysql/Ddl/CreateTableBuilder.php +++ /dev/null @@ -1,170 +0,0 @@ - 0, - 'zerofill' => 1, - 'identity' => 2, - 'serial' => 2, - 'autoincrement' => 2, - 'comment' => 3, - 'columnformat' => 4, - 'format' => 4, - 'storage' => 5, - ]; - - /** - * @param string $sql - * @return array - */ - protected function getSqlInsertOffsets($sql) - { - $sqlLength = strlen($sql); - $insertStart = []; - - foreach (['NOT NULL', 'NULL', 'DEFAULT', 'UNIQUE', 'PRIMARY', 'REFERENCES'] as $needle) { - $insertPos = strpos($sql, ' ' . $needle); - - if ($insertPos !== false) { - switch ($needle) { - case 'REFERENCES': - $insertStart[2] = !isset($insertStart[2]) ? $insertPos : $insertStart[2]; - // no break - case 'PRIMARY': - case 'UNIQUE': - $insertStart[1] = !isset($insertStart[1]) ? $insertPos : $insertStart[1]; - // no break - default: - $insertStart[0] = !isset($insertStart[0]) ? $insertPos : $insertStart[0]; - } - } - } - - foreach (range(0, 3) as $i) { - $insertStart[$i] = isset($insertStart[$i]) ? $insertStart[$i] : $sqlLength; - } - - return $insertStart; - } - - /** - * {@inheritDoc} - */ - protected function build_Columns(CreateTable $sqlObject, Context $context) - { - $COLUMNS = $sqlObject->columns; - if (! $COLUMNS) { - return; - } - - $sqls = []; - - foreach ($COLUMNS as $i => $column) { - $sql = $this->buildSqlString($column, $context); - $insertStart = $this->getSqlInsertOffsets($sql); - $columnOptions = $column->getOptions(); - - uksort($columnOptions, [$this, 'compareColumnOptions']); - - foreach ($columnOptions as $coName => $coValue) { - $insert = ''; - - if (! $coValue) { - continue; - } - - switch ($this->normalizeColumnOption($coName)) { - case 'unsigned': - $insert = ' UNSIGNED'; - $j = 0; - break; - case 'zerofill': - $insert = ' ZEROFILL'; - $j = 0; - break; - case 'identity': - case 'serial': - case 'autoincrement': - $insert = ' AUTO_INCREMENT'; - $j = 1; - break; - case 'comment': - $insert = ' COMMENT ' . $context->getPlatform()->quoteValue($coValue); - $j = 2; - break; - case 'columnformat': - case 'format': - $insert = ' COLUMN_FORMAT ' . strtoupper($coValue); - $j = 2; - break; - case 'storage': - $insert = ' STORAGE ' . strtoupper($coValue); - $j = 2; - break; - } - - if ($insert) { - $j = isset($j) ? $j : 0; - $sql = substr_replace($sql, $insert, $insertStart[$j], 0); - $insertStartCount = count($insertStart); - for (; $j < $insertStartCount; ++$j) { - $insertStart[$j] += strlen($insert); - } - } - } - - $sqls[$i] = $sql; - } - return [ - 'spec' => $this->columnsSpecification, - 'params' => $sqls, - ]; - } - - /** - * @param string $name - * - * @return string - */ - private function normalizeColumnOption($name) - { - return strtolower(str_replace(['-', '_', ' '], '', $name)); - } - - /** - * - * @param string $columnA - * @param string $columnB - * - * @return int - */ - private function compareColumnOptions($columnA, $columnB) - { - $columnA = $this->normalizeColumnOption($columnA); - $columnA = isset($this->columnOptionSortOrder[$columnA]) - ? $this->columnOptionSortOrder[$columnA] : count($this->columnOptionSortOrder); - - $columnB = $this->normalizeColumnOption($columnB); - $columnB = isset($this->columnOptionSortOrder[$columnB]) - ? $this->columnOptionSortOrder[$columnB] : count($this->columnOptionSortOrder); - - return $columnA - $columnB; - } -} diff --git a/src/Sql/Builder/sql92/Ddl/Column/AbstractLengthColumnBuilder.php b/src/Sql/Builder/sql92/Ddl/Column/AbstractLengthColumnBuilder.php deleted file mode 100644 index f3d91dafcf..0000000000 --- a/src/Sql/Builder/sql92/Ddl/Column/AbstractLengthColumnBuilder.php +++ /dev/null @@ -1,32 +0,0 @@ -validateSqlObject($column, 'Zend\Db\Sql\Ddl\Column\AbstractLengthColumn', __METHOD__); - $data = parent::build($column, $context); - - if ($this->getLengthExpression($column)) { - $data[0]['params'][1]->setValue($data[0]['params'][1]->getValue() . '(' . $this->getLengthExpression($column) . ')'); - } - - return $data; - } - - protected function getLengthExpression($column) - { - return (string) $column->getLength(); - } -} diff --git a/src/Sql/Builder/sql92/Ddl/Column/AbstractPrecisionColumnBuilder.php b/src/Sql/Builder/sql92/Ddl/Column/AbstractPrecisionColumnBuilder.php deleted file mode 100644 index 909edff9e2..0000000000 --- a/src/Sql/Builder/sql92/Ddl/Column/AbstractPrecisionColumnBuilder.php +++ /dev/null @@ -1,22 +0,0 @@ -getDecimal() !== null) { - return $column->getLength() . ',' . $column->getDecimal(); - } - - return $column->getLength(); - } -} diff --git a/src/Sql/Builder/sql92/Ddl/Column/AbstractTimestampColumnBuilder.php b/src/Sql/Builder/sql92/Ddl/Column/AbstractTimestampColumnBuilder.php deleted file mode 100644 index b8611512fa..0000000000 --- a/src/Sql/Builder/sql92/Ddl/Column/AbstractTimestampColumnBuilder.php +++ /dev/null @@ -1,56 +0,0 @@ -validateSqlObject($column, 'Zend\Db\Sql\Ddl\Column\AbstractTimestampColumn', __METHOD__); - $spec = $this->specification; - - $params = [ - new ExpressionParameter($column->getName(), ExpressionInterface::TYPE_IDENTIFIER), - new ExpressionParameter($column->getType(), ExpressionInterface::TYPE_LITERAL), - ]; - - if (!$column->isNullable()) { - $spec .= ' NOT NULL'; - } - - if ($column->getDefault() !== null) { - $spec .= ' DEFAULT %s'; - $params[] = new ExpressionParameter($column->getDefault(), ExpressionInterface::TYPE_VALUE); - } - - $options = $column->getOptions(); - - if (isset($options['on_update'])) { - $spec .= ' %s'; - $params[] = new ExpressionParameter('ON UPDATE CURRENT_TIMESTAMP', ExpressionInterface::TYPE_LITERAL); - } - - $data = [[ - 'spec' => $spec, - 'params' => $params, - ]]; - - foreach ($column->getConstraints() as $constraint) { - $data[] = ' '; - $data = array_merge($data, $this->platformBuilder->getPlatformBuilder($constraint, $context)->getExpressionData($constraint, $context)); - } - - return $data; - } -} diff --git a/src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php b/src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php index da94272b58..afceae4f89 100644 --- a/src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php @@ -11,12 +11,42 @@ use Zend\Db\Sql\Builder\AbstractSqlBuilder; use Zend\Db\Sql\ExpressionInterface; -use Zend\Db\Sql\ExpressionParameter; use Zend\Db\Sql\Builder\Context; class ColumnBuilder extends AbstractSqlBuilder { - protected $specification = '%s %s'; + protected $specifications = [ + 'name' => [ + 'spec' => '%s', + 'propertyType' => ExpressionInterface::TYPE_IDENTIFIER, + ], + 'type' => [ + 'spec' => [ + 'byCount' => [ + 1 => '%1$s', + 2 => '%1$s(%2$s)', + 3 => '%1$s(%2$s,%3$s)' + ], + ], + 'subProperties' => [ + 'type' => null, + 'length' => null, + 'decimal' => null, + ], + ], + 'nullable' => [ + 'valueMap' => [false => 'NOT NULL', true => null], + ], + 'constraints' => [ + 'spec' => [ + 'implode' => ' ', + ], + ], + 'default' => [ + 'spec' => 'DEFAULT %s', + 'propertyType' => ExpressionInterface::TYPE_VALUE, + ], + ]; /** * @param \Zend\Db\Sql\Ddl\Column\Column $column @@ -26,35 +56,73 @@ class ColumnBuilder extends AbstractSqlBuilder public function build($column, Context $context) { $this->validateSqlObject($column, 'Zend\Db\Sql\Ddl\Column\Column', __METHOD__); - $spec = $this->specification; - - $params = [ - new ExpressionParameter($column->getName(), ExpressionInterface::TYPE_IDENTIFIER), - new ExpressionParameter($column->getType(), ExpressionInterface::TYPE_LITERAL), - ]; - - if (!$column->isNullable()) { - $spec .= ' NOT NULL'; - } + $data = $this->buildColumnSpec($context, $this->specifications, $column); + $data[$this->implodeGlueKey] = ' '; + return $data; + } - if ($column->getDefault() !== null) { - $spec .= ' DEFAULT %s'; - $params[] = new ExpressionParameter($column->getDefault(), ExpressionInterface::TYPE_VALUE); + /** + * @param Context $context + * @param array $description + * @param \Zend\Db\Sql\Ddl\Column\Column $column + * @param array $options + * @return array + */ + protected function buildColumnSpec(Context $context, $description, $column, $options = null) + { + if ($options === null) { + $options = []; + foreach ($column->getOptions() as $k=>$v) { + $options[strtolower(str_replace(['-', '_', ' '], '', $k))] = $v; + } } + foreach ($description as $key => $spec) { + $value = null; + $spec = is_string($spec) ? ['spec' => $spec] : $spec; + if (isset($spec['subProperties'])) { + $value = $this->buildColumnSpec($context, $spec['subProperties'], $column, $options); + } else { + $methodGet = 'get' . ucfirst($key); + $methodIs = 'is' . ucfirst($key); + if (method_exists($column, $methodGet)) { + $value = $column->$methodGet(); + } elseif (method_exists($column, $methodIs)) { + $value = $column->$methodIs(); + } elseif (array_key_exists($key, $options)) { + $value = $options[$key]; + } + } + if ($value === null || $value === '') { + unset($description[$key]); + continue; + } + if (isset($spec['valueMap'])) { + $valueMapKey = is_bool($value) + ? (int)$value + : $value; + $value = array_key_exists($valueMapKey, $spec['valueMap']) + ? $spec['valueMap'][$valueMapKey] + : null; + } - $data = [[ - 'spec' => $spec, - 'params' => $params, - ]]; - - foreach ($column->getConstraints() as $constraint) { - $data[] = ' '; - $data = array_merge( - $data, - $this->platformBuilder->getPlatformBuilder($constraint, $context)->build($constraint, $context) - ); + if ($value == null || $value === '') { + unset($description[$key]); + continue; + } + if (isset($spec['propertyType'])) { + switch ($spec['propertyType']) { + case ExpressionInterface::TYPE_IDENTIFIER : + $value = $context->getPlatform()->quoteIdentifier($value); + break; + case ExpressionInterface::TYPE_VALUE : + $value = $context->getPlatform()->quoteValue($value); + break; + } + } + $description[$key] = isset($spec['spec']) + ? ['spec' => $spec['spec'], 'params' => $value] + : $value; } - - return $data; + return $description; } } diff --git a/src/Sql/Builder/sql92/Ddl/Column/IntegerBuilder.php b/src/Sql/Builder/sql92/Ddl/Column/IntegerBuilder.php deleted file mode 100644 index 2eff8cd723..0000000000 --- a/src/Sql/Builder/sql92/Ddl/Column/IntegerBuilder.php +++ /dev/null @@ -1,28 +0,0 @@ -validateSqlObject($column, 'Zend\Db\Sql\Ddl\Column\Integer', __METHOD__); - $data = parent::build($column, $context); - $options = $column->getOptions(); - - if (isset($options['length'])) { - $data[0][1][1] .= '(' . $options['length'] . ')'; - } - - return $data; - } -} diff --git a/test/Sql/Builder/Ddl/CreateTableBuilderTest.php b/test/Sql/Builder/Ddl/CreateTableBuilderTest.php index 1d616e3db2..da7b316b5a 100644 --- a/test/Sql/Builder/Ddl/CreateTableBuilderTest.php +++ b/test/Sql/Builder/Ddl/CreateTableBuilderTest.php @@ -57,7 +57,7 @@ public function dataProvider_ColumnsAndConstraint() $col->setOption('unsigned', true); $col->setOption('identity', true); $col->setOption('column-format', 'FIXED'); - $col->setOption('storage', 'memory'); + $col->setOption('storage', 'MEMORY'); $col->setOption('comment', 'baz'); $col->addConstraint(new Constraint\PrimaryKey()); From 7a22fcea33fc4787fb570df90aec89c7976f3faa Mon Sep 17 00:00:00 2001 From: turrsis Date: Sun, 12 Jul 2015 14:10:38 +0300 Subject: [PATCH 10/30] architecture fix 09: AbstractSqlBuilder::resolveColumnValue() --- src/Sql/Builder/AbstractSqlBuilder.php | 38 +++++------ src/Sql/Builder/sql92/InsertBuilder.php | 8 +-- src/Sql/Builder/sql92/SelectBuilder.php | 84 +++++++++++++------------ src/Sql/Builder/sql92/UpdateBuilder.php | 11 +--- test/Sql/Builder/InsertBuilderTest.php | 4 +- test/Sql/Builder/SelectBuilderTest.php | 14 +---- test/Sql/Builder/UpdateBuilderTest.php | 4 +- 7 files changed, 67 insertions(+), 96 deletions(-) diff --git a/src/Sql/Builder/AbstractSqlBuilder.php b/src/Sql/Builder/AbstractSqlBuilder.php index a05be7aa4d..307d269107 100644 --- a/src/Sql/Builder/AbstractSqlBuilder.php +++ b/src/Sql/Builder/AbstractSqlBuilder.php @@ -207,35 +207,27 @@ private function buildSubSelect(SelectableInterface $subselect, Context $context /** * @param string|array $column + * @param mixed $value * @param Context $context - * @return string + * @return array */ - protected function resolveColumnValue($column, Context $context) + protected function resolveColumnValue($column, $value, Context $context) { - $isIdentifier = false; - $fromTable = ''; - if (is_array($column)) { - if (isset($column['isIdentifier'])) { - $isIdentifier = (bool) $column['isIdentifier']; - } - if (isset($column['fromTable']) && $column['fromTable'] !== null) { - $fromTable = $column['fromTable']; + if (is_scalar($value) || $value === null) { + if ($context->getParameterContainer() && $column !== null) { + $context->getParameterContainer()->offsetSet($column, $value); + $value = $context->getDriver()->formatParameterName($column); + } elseif ($value === null) { + $value = 'NULL'; + } else { + $value = $context->getPlatform()->quoteValue($value); } - $column = $column['column']; } - if ($column instanceof ExpressionInterface) { - return $this->buildSqlString($column, $context); - } - if ($column instanceof SelectableInterface) { - return $this->buildSubSelect($column, $context); - } - if ($column === null) { - return 'NULL'; - } - return $isIdentifier - ? $fromTable . $context->getPlatform()->quoteIdentifierInFragment($column) - : $context->getPlatform()->quoteValue($column); + return [ + $context->getPlatform()->quoteIdentifier($column), + $value + ]; } private function buildSpecificationParameter($parameter, Context $context = null) diff --git a/src/Sql/Builder/sql92/InsertBuilder.php b/src/Sql/Builder/sql92/InsertBuilder.php index a6fe0768e2..605eb9e5a7 100644 --- a/src/Sql/Builder/sql92/InsertBuilder.php +++ b/src/Sql/Builder/sql92/InsertBuilder.php @@ -73,13 +73,7 @@ protected function build_Insert(Insert $sqlObject, Context $context) $columns = []; $values = []; foreach (array_combine($sqlObject->columns, $sqlObject->values) as $column=>$value) { - $columns[] = $context->getPlatform()->quoteIdentifier($column); - if (is_scalar($value) && $context->getParameterContainer()) { - $values[] = $context->getDriver()->formatParameterName($column); - $context->getParameterContainer()->offsetSet($column, $value); - } else { - $values[] = $this->resolveColumnValue($value, $context); - } + list($columns[], $values[]) = $this->resolveColumnValue($column, $value, $context); } return [ diff --git a/src/Sql/Builder/sql92/SelectBuilder.php b/src/Sql/Builder/sql92/SelectBuilder.php index c3fafae5df..d94434b170 100644 --- a/src/Sql/Builder/sql92/SelectBuilder.php +++ b/src/Sql/Builder/sql92/SelectBuilder.php @@ -12,6 +12,7 @@ use Zend\Db\Adapter; use Zend\Db\Sql\Select; use Zend\Db\Sql\ExpressionInterface; +use Zend\Db\Sql\SelectableInterface; use Zend\Db\Sql\Builder\AbstractSqlBuilder; use Zend\Db\Sql\Builder\Context; use Zend\Db\Sql\ExpressionParameter; @@ -170,52 +171,18 @@ protected function build_Select(Select $sqlObject, Context $context) // build_ table columns $columns = []; foreach ($sqlObject->columns as $columnIndexOrAs => $column) { - if ($column === Select::SQL_STAR) { - $columns[] = [$fromTable . Select::SQL_STAR]; - continue; - } - - $columnName = $this->resolveColumnValue( - [ - 'column' => $column, - 'fromTable' => $fromTable, - 'isIdentifier' => true, - ], - $context - ); - // build_ As portion - if (is_string($columnIndexOrAs)) { - $columnAs = $context->getPlatform()->quoteIdentifier($columnIndexOrAs); - } elseif (stripos($columnName, ' as ') === false) { - $columnAs = (is_string($column)) ? $context->getPlatform()->quoteIdentifier($column) : $context->getNestedAlias('column'); - } - $columns[] = (isset($columnAs)) ? [$columnName, $columnAs] : [$columnName]; + $columns[] = $this->resolveSelectColumn($fromTable, $columnIndexOrAs, $column, $context); } // build_ join columns foreach ($sqlObject->joins as $join) { $jTable = $this->nornalizeTable($join['name'], $context); - $joinName = $jTable['columnAlias']; + $joinName = $jTable['columnAlias'] + ? $jTable['columnAlias'] . $context->getPlatform()->getIdentifierSeparator() + : ''; - foreach ($join['columns'] as $jKey => $jColumn) { - $jColumns = []; - $jFromTable = is_scalar($jColumn) - ? $joinName . $context->getPlatform()->getIdentifierSeparator() - : ''; - $jColumns[] = $this->resolveColumnValue( - [ - 'column' => $jColumn, - 'fromTable' => $jFromTable, - 'isIdentifier' => true, - ], - $context - ); - if (is_string($jKey)) { - $jColumns[] = $context->getPlatform()->quoteIdentifier($jKey); - } elseif ($jColumn !== Select::SQL_STAR) { - $jColumns[] = $context->getPlatform()->quoteIdentifier($jColumn); - } - $columns[] = $jColumns; + foreach ($join['columns'] as $columnIndexOrAs => $column) { + $columns[] = $this->resolveSelectColumn($joinName, $columnIndexOrAs, $column, $context); } } @@ -406,4 +373,41 @@ protected function build_Combine(Select $sqlObject, Context $context) ], ]; } + + /** + * @param array $fromTable + * @param int|string $indexOrAlias + * @param null|string|ExpressionInterface|SelectableInterface $column + * @param Context $context + * @return array + */ + protected function resolveSelectColumn($fromTable, $indexOrAlias, $column, Context $context) + { + if ($column === Select::SQL_STAR) { + return [$fromTable . Select::SQL_STAR]; + } + + if (is_string($indexOrAlias)) { + $indexOrAlias = $context->getPlatform()->quoteIdentifier($indexOrAlias); + } elseif (is_string($column)) { + $indexOrAlias = $context->getPlatform()->quoteIdentifier($column); + } else { + $indexOrAlias = $context->getNestedAlias('column'); + } + + if ($column === null) { + $column = 'NULL'; + } elseif (!$column instanceof ExpressionInterface && !$column instanceof SelectableInterface) { + $column = $fromTable . $context->getPlatform()->quoteIdentifierInFragment($column); + } + + if ($indexOrAlias) { + return [ + $column, + $indexOrAlias, + ]; + } + + return [$column]; + } } diff --git a/src/Sql/Builder/sql92/UpdateBuilder.php b/src/Sql/Builder/sql92/UpdateBuilder.php index 36b347d485..d894c9209f 100644 --- a/src/Sql/Builder/sql92/UpdateBuilder.php +++ b/src/Sql/Builder/sql92/UpdateBuilder.php @@ -83,16 +83,7 @@ protected function build_Set(Update $sqlObject, Context $context) { $setSql = []; foreach ($sqlObject->set as $column => $value) { - if (is_scalar($value) && $context->getParameterContainer()) { - $context->getParameterContainer()->offsetSet($column, $value); - $value = $context->getDriver()->formatParameterName($column); - } else { - $value = $this->resolveColumnValue($value, $context); - } - $setSql[] = [ - $context->getPlatform()->quoteIdentifier($column), - $value - ]; + $setSql[] = $this->resolveColumnValue($column, $value, $context); } return [ 'spec' => $this->setSpecification, diff --git a/test/Sql/Builder/InsertBuilderTest.php b/test/Sql/Builder/InsertBuilderTest.php index 0867fa2c75..683dbe792d 100644 --- a/test/Sql/Builder/InsertBuilderTest.php +++ b/test/Sql/Builder/InsertBuilderTest.php @@ -67,8 +67,8 @@ public function dataProvider_ColumnsAndValues() 'expected' => [ 'sql92' => [ 'string' => 'INSERT INTO "foo" ("bar", "boo", "bam", "bat") VALUES (\'baz\', NOW(), NULL, (SELECT "bad".* FROM "bad"))', - 'prepare' => 'INSERT INTO "foo" ("bar", "boo", "bam", "bat") VALUES (?, NOW(), NULL, (SELECT "bad".* FROM "bad"))', - 'parameters' => ['bar' => 'baz',], + 'prepare' => 'INSERT INTO "foo" ("bar", "boo", "bam", "bat") VALUES (?, NOW(), ?, (SELECT "bad".* FROM "bad"))', + 'parameters' => ['bar' => 'baz', 'bam' => null], ], ], ], diff --git a/test/Sql/Builder/SelectBuilderTest.php b/test/Sql/Builder/SelectBuilderTest.php index 68d1a4557f..341c7bfc9b 100644 --- a/test/Sql/Builder/SelectBuilderTest.php +++ b/test/Sql/Builder/SelectBuilderTest.php @@ -88,26 +88,16 @@ public function dataProvider_Columns() ], ], ], - [ // columns where value is Expression - 'sqlObject' => $this->select()->from('foo')->columns([new Expression('COUNT(some_column) AS bar')]), - 'expected' => [ - 'sql92' => [ - 'string' => 'SELECT COUNT(some_column) AS bar FROM "foo"', - 'prepare' => true, - ], - ], - ], [ 'sqlObject' => $this->select() ->from('foo') ->columns( [ - new Expression( - '(COUNT(?) + ?) AS ?', + 'bar' => new Expression( + '(COUNT(?) + ?)', [ ['some_column', Expression::TYPE_IDENTIFIER], [5, Expression::TYPE_VALUE], - ['bar', Expression::TYPE_IDENTIFIER], ] ) ] diff --git a/test/Sql/Builder/UpdateBuilderTest.php b/test/Sql/Builder/UpdateBuilderTest.php index 753265b376..0f7da2acb3 100644 --- a/test/Sql/Builder/UpdateBuilderTest.php +++ b/test/Sql/Builder/UpdateBuilderTest.php @@ -55,8 +55,8 @@ public function dataProvider_Set() 'expected' => [ 'sql92' => [ 'string' => 'UPDATE "foo" SET "bar" = \'baz\', "boo" = NOW(), "bam" = NULL, "false" = \'\', "true" = \'1\'', - 'prepare' => 'UPDATE "foo" SET "bar" = ?, "boo" = NOW(), "bam" = NULL, "false" = ?, "true" = ?', - 'parameters' => ['bar' => 'baz', 'false' => false, 'true' => true], + 'prepare' => 'UPDATE "foo" SET "bar" = ?, "boo" = NOW(), "bam" = ?, "false" = ?, "true" = ?', + 'parameters' => ['bar' => 'baz', 'bam' => null, 'false' => false, 'true' => true], ], ], ], From 8b5b9fd6f085244cca6232d78b2a0bddf1db1460 Mon Sep 17 00:00:00 2001 From: turrsis Date: Sun, 12 Jul 2015 15:58:20 +0300 Subject: [PATCH 11/30] architecture 10: move functionality from AbstractSqlBuilder to Builder, protect all builders methods, unification names for getSqlString() and prepareStatement() methods --- src/RowGateway/AbstractRowGateway.php | 8 +- src/Sql/Builder/AbstractBuilder.php | 51 +++- src/Sql/Builder/AbstractSqlBuilder.php | 233 ------------------ src/Sql/Builder/Builder.php | 209 ++++++++++++++-- src/Sql/Builder/SelectLimitOffsetTrait.php | 2 +- src/Sql/Builder/sql92/CombineBuilder.php | 2 +- .../Builder/sql92/Ddl/AlterTableBuilder.php | 2 +- .../sql92/Ddl/Column/ColumnBuilder.php | 2 +- .../sql92/Ddl/Constraint/AbstractBuilder.php | 2 +- .../sql92/Ddl/Constraint/CheckBuilder.php | 2 +- .../Ddl/Constraint/ForeignKeyBuilder.php | 2 +- .../Builder/sql92/Ddl/CreateTableBuilder.php | 2 +- .../Builder/sql92/Ddl/DropTableBuilder.php | 2 +- .../Builder/sql92/Ddl/Index/IndexBuilder.php | 2 +- src/Sql/Builder/sql92/DeleteBuilder.php | 2 +- src/Sql/Builder/sql92/ExpressionBuilder.php | 2 +- src/Sql/Builder/sql92/InsertBuilder.php | 2 +- src/Sql/Builder/sql92/LiteralBuilder.php | 2 +- .../sql92/Predicate/BetweenBuilder.php | 2 +- src/Sql/Builder/sql92/Predicate/InBuilder.php | 2 +- .../Builder/sql92/Predicate/IsNullBuilder.php | 2 +- .../Builder/sql92/Predicate/LikeBuilder.php | 2 +- .../sql92/Predicate/NotBetweenBuilder.php | 2 +- .../sql92/Predicate/OperatorBuilder.php | 2 +- .../sql92/Predicate/PredicateSetBuilder.php | 2 +- src/Sql/Builder/sql92/SelectBuilder.php | 2 +- src/Sql/Builder/sql92/UpdateBuilder.php | 2 +- src/Sql/Sql.php | 6 +- src/TableGateway/AbstractTableGateway.php | 8 +- test/Sql/Builder/AbstractTestCase.php | 8 +- test/Sql/Builder/BuilderTest.php | 12 +- test/Sql/Builder/CombineBuilderTest.php | 6 +- test/Sql/Builder/DeleteBuilderTest.php | 2 +- test/Sql/SqlTest.php | 6 +- test/TableGateway/TableGatewayTest.php | 4 +- test/TestAsset/ExpressionBuilder.php | 2 +- 36 files changed, 298 insertions(+), 303 deletions(-) diff --git a/src/RowGateway/AbstractRowGateway.php b/src/RowGateway/AbstractRowGateway.php index cff1c7c337..74b7181ad6 100644 --- a/src/RowGateway/AbstractRowGateway.php +++ b/src/RowGateway/AbstractRowGateway.php @@ -142,7 +142,7 @@ public function save() } } - $statement = $this->sql->prepareStatementForSqlObject($this->sql->update()->set($data)->where($where)); + $statement = $this->sql->prepareSqlStatement($this->sql->update()->set($data)->where($where)); $result = $statement->execute(); $rowsAffected = $result->getAffectedRows(); unset($statement, $result); // cleanup @@ -160,7 +160,7 @@ public function save() $insert = $this->sql->insert(); $insert->values($this->data); - $statement = $this->sql->prepareStatementForSqlObject($insert); + $statement = $this->sql->prepareSqlStatement($insert); $result = $statement->execute(); if (($primaryKeyValue = $result->getGeneratedValue()) && count($this->primaryKeyColumn) == 1) { @@ -180,7 +180,7 @@ public function save() } // refresh data - $statement = $this->sql->prepareStatementForSqlObject($this->sql->select()->where($where)); + $statement = $this->sql->prepareSqlStatement($this->sql->select()->where($where)); $result = $statement->execute(); $rowData = $result->current(); unset($statement, $result); // cleanup @@ -209,7 +209,7 @@ public function delete() // @todo determine if we need to do a select to ensure 1 row will be affected - $statement = $this->sql->prepareStatementForSqlObject($this->sql->delete()->where($where)); + $statement = $this->sql->prepareSqlStatement($this->sql->delete()->where($where)); $result = $statement->execute(); $affectedRows = $result->getAffectedRows(); diff --git a/src/Sql/Builder/AbstractBuilder.php b/src/Sql/Builder/AbstractBuilder.php index 518a74f484..14e519db3c 100644 --- a/src/Sql/Builder/AbstractBuilder.php +++ b/src/Sql/Builder/AbstractBuilder.php @@ -9,9 +9,58 @@ namespace Zend\Db\Sql\Builder; +use Zend\Db\Sql\TableSource; +use Zend\Db\Sql\TableIdentifier; + abstract class AbstractBuilder { - abstract protected function buildSqlString($sqlObject, Context $context); + protected $implodeGlueKey = 'implode_glue'; + + abstract protected function build($sqlObject, Context $context); + + /** + * @param TableIdentifier|string|array $identifier + * @param Context $context + * @return array + */ + protected function nornalizeTable($identifier, Context $context) + { + $schema = null; + $name = null; + $alias = null; + $columnAlias = null; + + if ($identifier instanceof TableSource) { + $alias = $identifier->getAlias(); + $identifier = $identifier->getSource(); + } + if ($identifier instanceof TableIdentifier) { + $name = $identifier->getTable(); + $schema = $identifier->getSchema(); + } else { + $name = $identifier; + } + + if ($alias) { + $alias = $context->getPlatform()->quoteIdentifier($alias); + $columnAlias = $alias; + } + + if (is_string($name)) { + $name = $schema + ? $context->getPlatform()->quoteIdentifierInFragment($schema . '.' . $name) + : $context->getPlatform()->quoteIdentifier($name); + if (!$columnAlias) { + $columnAlias = $name; + } + } + + return [ + 'name' => $name, + 'alias' => $alias, + 'columnAlias' => $columnAlias, + ]; + } /** * diff --git a/src/Sql/Builder/AbstractSqlBuilder.php b/src/Sql/Builder/AbstractSqlBuilder.php index 307d269107..e19431b57f 100644 --- a/src/Sql/Builder/AbstractSqlBuilder.php +++ b/src/Sql/Builder/AbstractSqlBuilder.php @@ -9,17 +9,11 @@ namespace Zend\Db\Sql\Builder; -use Zend\Db\Sql\TableIdentifier; -use Zend\Db\Sql\TableSource; -use Zend\Db\Sql\SelectableInterface; use Zend\Db\Sql\ExpressionInterface; -use Zend\Db\Sql\ExpressionParameter; use Zend\Db\Sql\SqlObjectInterface; abstract class AbstractSqlBuilder extends AbstractBuilder { - protected $implodeGlueKey = 'implode_glue'; - protected $specifications = []; /** @@ -35,176 +29,6 @@ public function __construct(Builder $platformBuilder) $this->platformBuilder = $platformBuilder; } - protected function buildSqlString($sqlObject, Context $context) - { - if (is_array($sqlObject)) { - return $this->createSqlFromSpecificationAndParameters($sqlObject['spec'], $sqlObject['params'], $context); - } - - if (!$sqlObject instanceof SqlObjectInterface && !$sqlObject instanceof ExpressionInterface) { - throw new \Zend\Db\Sql\Exception\InvalidArgumentException(sprintf( - 'Argument $sqlObject passed to %s must be an instance of %s, instance of %s given', - __METHOD__ . '()', - 'Zend\Db\Sql\SqlObjectInterface or Zend\Db\Sql\ExpressionInterface', - is_object($sqlObject) ? get_class($sqlObject) : gettype($sqlObject) - )); - } - - $specAndParams = $this - ->platformBuilder - ->getPlatformBuilder($sqlObject, $context->getAdapter()) - ->build($sqlObject, $context); - - if (isset($specAndParams[$this->implodeGlueKey])) { - $implodeGlue = $specAndParams[$this->implodeGlueKey]; - unset($specAndParams[$this->implodeGlueKey]); - } else { - $implodeGlue = $sqlObject instanceof SqlObjectInterface ? ' ' : ''; - } - - $sqls = []; - foreach ($specAndParams as $spec) { - if (!$spec) { - continue; - } - if (is_scalar($spec)) { - $sqls[] = $spec; - continue; - } - if (is_array($spec)) { - $sqls[] = $this->createSqlFromSpecificationAndParameters($spec['spec'], $spec['params'], $context); - continue; - } - $sqls[] = $this->buildSpecificationParameter($spec, $context); - } - - return rtrim(implode($implodeGlue, $sqls), "\n ,"); - } - - /* - * $spec = array( - 'format' => ' string format : http://php.net/manual/en/function.sprintf.php', - 'byArgNumber' => array( - 'parameter index' => 'spec for parameter', - ' ... ' => ' ... ', - 'parameter index' => 'spec for parameter', - ), - 'byCount' => array( - -1 => 'spec if count not found or !is_array($args)', - 'count($args)' => 'spec', - ' ... ' => ' .. ', - 'count($args)' => 'spec', - ), - 'implode' => 'is isset - do implode array', - ); - */ - private function createSqlFromSpecificationAndParameters($specification, $args, Context $context = null) - { - if (is_string($specification)) { - return vsprintf( - $specification, - $this->buildSpecificationParameter($args, $context) - ); - } - - foreach ($specification as $specName => $spec) { - if ($specName == 'forEach') { - foreach ($args as $pName => &$param) { - $param = $this->createSqlFromSpecificationAndParameters($spec, $args[$pName], $context); - } - } elseif ($specName == 'byArgNumber') { - $i = 0; - foreach ($args as $pName => &$param) { - if (isset($spec[++$i])) { - $param = $this->createSqlFromSpecificationAndParameters($spec[$i], $args[$pName], $context); - } - } - } elseif ($specName == 'byCount') { - $pCount = is_array($args) ? count($args) : -1; - if (isset($spec[$pCount])) { - $spec = $spec[$pCount]; - } elseif (isset($spec[-1])) { - $spec = $spec[-1]; - } else { - throw new \Exception('A number of parameters (' . $pCount . ') was found that is not supported by this specification'); - } - $args = $this->createSqlFromSpecificationAndParameters($spec, $args, $context); - } elseif ($specName == 'implode') { - if (is_array($spec)) { - $prefix = isset($spec['prefix']) ? $spec['prefix'] : ''; - $suffix = isset($spec['suffix']) ? $spec['suffix'] : ''; - $glue = isset($spec['glue']) ? $spec['glue'] : ''; - $args = - $prefix - . implode($glue, $this->buildSpecificationParameter($args, $context)) - . $suffix; - } else { - $args = implode($spec, $this->buildSpecificationParameter($args, $context)); - } - } elseif ($specName == 'format') { - $args = vsprintf( - $spec, - $this->buildSpecificationParameter($args, $context) - ); - } - } - return $args; - } - - protected function nornalizeTable($identifier, Context $context) - { - $schema = null; - $name = null; - $alias = null; - $columnAlias = null; - - if ($identifier instanceof TableSource) { - $alias = $identifier->getAlias(); - $identifier = $identifier->getSource(); - } - if ($identifier instanceof TableIdentifier) { - $name = $identifier->getTable(); - $schema = $identifier->getSchema(); - } else { - $name = $identifier; - } - - if ($alias) { - $alias = $context->getPlatform()->quoteIdentifier($alias); - $columnAlias = $alias; - } - - if (is_string($name)) { - $name = $context->getPlatform()->quoteIdentifier($name); - if ($schema) { - $name = $context->getPlatform()->quoteIdentifier($schema) - . $context->getPlatform()->getIdentifierSeparator() - . $name; - } - if (!$columnAlias) { - $columnAlias = $name; - } - } - - return [ - 'name' => $name, - 'alias' => $alias, - 'columnAlias' => $columnAlias, - ]; - } - - private function buildSubSelect(SelectableInterface $subselect, Context $context) - { - $context->startPrefix('subselect'); - - $builder = $this->platformBuilder->getPlatformBuilder($subselect, $context->getPlatform()); - $result = '(' . $builder->buildSqlString($subselect, $context) . ')'; - - $context->endPrefix(); - - return $result; - } - /** * @param string|array $column * @param mixed $value @@ -230,63 +54,6 @@ protected function resolveColumnValue($column, $value, Context $context) ]; } - private function buildSpecificationParameter($parameter, Context $context = null) - { - if (is_array($parameter)) { - foreach ($parameter as &$ppp) { - $ppp = $this->buildSpecificationParameter($ppp, $context); - } - return $parameter; - } - - $isQuoted = false; - if ($parameter instanceof ExpressionParameter) { - $value = $parameter->getValue(); - $type = $parameter->getType(); - $paramName = $parameter->getName(); - $isQuoted = $parameter->getOption('isQuoted'); - } else { - $value = $parameter; - $type = ExpressionInterface::TYPE_LITERAL; - } - - if ($value instanceof TableIdentifier || $value instanceof TableSource) { - $parameter = $this->nornalizeTable($value, $context)['name']; - } elseif ($value instanceof SelectableInterface) { - $parameter = $this->buildSubSelect($value, $context); - } elseif ($value instanceof ExpressionInterface) { - $parameter = $this->buildSqlString($value, $context); - } elseif ($type == ExpressionInterface::TYPE_IDENTIFIER) { - $parameter = $context->getPlatform()->quoteIdentifierInFragment($value); - } elseif ($type == ExpressionInterface::TYPE_VALUE) { - if ($context->getParameterContainer()) { - $name = isset($paramName) - ? $paramName - : $context->getNestedAlias('expr'); - if (is_array($name)) { - $context->getParameterContainer()->offsetSet($name[0], $value); - $context->getParameterContainer()->offsetSetReference($name[1], $name[0]); - } else { - $context->getParameterContainer()->offsetSet($name, $value); - } - $parameter = $context->getDriver()->formatParameterName($name); - } else { - $parameter = $isQuoted - ? $value - : $context->getPlatform()->quoteValue($value); - } - } elseif ($type == ExpressionInterface::TYPE_LITERAL) { - $parameter = $value; - } - - return $parameter; - } - - protected function renderTable($table, $alias = null) - { - return $table . ($alias ? ' AS ' . $alias : ''); - } - /** * @param SqlObjectInterface $sqlObject * @param Context $context diff --git a/src/Sql/Builder/Builder.php b/src/Sql/Builder/Builder.php index ba0d255afb..0076bedb9e 100644 --- a/src/Sql/Builder/Builder.php +++ b/src/Sql/Builder/Builder.php @@ -12,6 +12,12 @@ use Zend\Db\Adapter; use Zend\Db\Adapter\Platform\PlatformInterface; use Zend\Db\Sql\Exception; +use Zend\Db\Sql\SqlObjectInterface; +use Zend\Db\Sql\SelectableInterface; +use Zend\Db\Sql\ExpressionParameter; +use Zend\Db\Sql\ExpressionInterface; +use Zend\Db\Sql\TableIdentifier; +use Zend\Db\Sql\TableSource; class Builder extends AbstractBuilder { @@ -225,10 +231,10 @@ public function getPlatformBuilder($sqlObject, $platform = 'sql92') * @param null|Adapter\AdapterInterface $adapter * @return string */ - public function getSqlString($object, Adapter\AdapterInterface $adapter = null) + public function buildSqlString($object, Adapter\AdapterInterface $adapter = null) { $adapter = $adapter ?: $this->defaultAdapter; - return $this->buildSqlString($object, new Context($adapter)); + return $this->build($object, new Context($adapter)); } /** @@ -236,7 +242,7 @@ public function getSqlString($object, Adapter\AdapterInterface $adapter = null) * @param null|Adapter\AdapterInterface $adapter * @return \Zend\Db\Adapter\Driver\StatementInterface */ - public function prepareStatement($object, Adapter\AdapterInterface $adapter = null) + public function prepareSqlStatement($object, Adapter\AdapterInterface $adapter = null) { $adapter = $adapter ?: $this->defaultAdapter; $statement = $adapter->getDriver()->createStatement(); @@ -244,23 +250,12 @@ public function prepareStatement($object, Adapter\AdapterInterface $adapter = nu $statement->setParameterContainer(new Adapter\ParameterContainer); } $statement->setSql( - $this->buildSqlString($object, new Context($adapter, $statement->getParameterContainer())) + $this->build($object, new Context($adapter, $statement->getParameterContainer())) ); return $statement; } - /** - * @param SqlObjectInterface $sqlObject - * @param Context $context - * @return string - */ - protected function buildSqlString($sqlObject, Context $context) - { - $builder = $this->getPlatformBuilder($sqlObject, $context); - return $builder->buildSqlString($sqlObject, $context); - } - /** * @param string|Context|PlatformInterface|Adapter\AdapterInterface $platform * @return string @@ -276,4 +271,188 @@ protected function resolvePlatformName($platform) } return str_replace(' ', '', strtolower($platform)); } + + /** + * @param SqlObjectInterface|ExpressionInterface $sqlObject + * @param Context $context + * @return string + * @throws \Zend\Db\Sql\Exception\InvalidArgumentException + */ + protected function build($sqlObject, Context $context) + { + if (is_array($sqlObject)) { + return $this->createSqlFromSpecificationAndParameters($sqlObject['spec'], $sqlObject['params'], $context); + } + + if (!$sqlObject instanceof SqlObjectInterface && !$sqlObject instanceof ExpressionInterface) { + throw new \Zend\Db\Sql\Exception\InvalidArgumentException(sprintf( + 'Argument $sqlObject passed to %s must be an instance of %s, instance of %s given', + __METHOD__ . '()', + 'Zend\Db\Sql\SqlObjectInterface or Zend\Db\Sql\ExpressionInterface', + is_object($sqlObject) ? get_class($sqlObject) : gettype($sqlObject) + )); + } + + $specAndParams = $this + ->getPlatformBuilder($sqlObject, $context->getAdapter()) + ->build($sqlObject, $context); + + if (isset($specAndParams[$this->implodeGlueKey])) { + $implodeGlue = $specAndParams[$this->implodeGlueKey]; + unset($specAndParams[$this->implodeGlueKey]); + } else { + $implodeGlue = $sqlObject instanceof SqlObjectInterface ? ' ' : ''; + } + + $sqls = []; + foreach ($specAndParams as $spec) { + if (!$spec) { + continue; + } + if (is_scalar($spec)) { + $sqls[] = $spec; + continue; + } + if (is_array($spec)) { + $sqls[] = $this->createSqlFromSpecificationAndParameters($spec['spec'], $spec['params'], $context); + continue; + } + $sqls[] = $this->buildSpecificationParameter($spec, $context); + } + + return rtrim(implode($implodeGlue, $sqls), "\n ,"); + } + + /* + * $spec = array( + 'format' => ' string format : http://php.net/manual/en/function.sprintf.php', + 'byArgNumber' => array( + 'parameter index' => 'spec for parameter', + ' ... ' => ' ... ', + 'parameter index' => 'spec for parameter', + ), + 'byCount' => array( + -1 => 'spec if count not found or !is_array($args)', + 'count($args)' => 'spec', + ' ... ' => ' .. ', + 'count($args)' => 'spec', + ), + 'implode' => 'is isset - do implode array', + ); + */ + private function createSqlFromSpecificationAndParameters($specification, $args, Context $context = null) + { + if (is_string($specification)) { + return vsprintf( + $specification, + $this->buildSpecificationParameter($args, $context) + ); + } + + foreach ($specification as $specName => $spec) { + if ($specName == 'forEach') { + foreach ($args as $pName => &$param) { + $param = $this->createSqlFromSpecificationAndParameters($spec, $args[$pName], $context); + } + } elseif ($specName == 'byArgNumber') { + $i = 0; + foreach ($args as $pName => &$param) { + if (isset($spec[++$i])) { + $param = $this->createSqlFromSpecificationAndParameters($spec[$i], $args[$pName], $context); + } + } + } elseif ($specName == 'byCount') { + $pCount = is_array($args) ? count($args) : -1; + if (isset($spec[$pCount])) { + $spec = $spec[$pCount]; + } elseif (isset($spec[-1])) { + $spec = $spec[-1]; + } else { + throw new \Exception('A number of parameters (' . $pCount . ') was found that is not supported by this specification'); + } + $args = $this->createSqlFromSpecificationAndParameters($spec, $args, $context); + } elseif ($specName == 'implode') { + if (is_array($spec)) { + $prefix = isset($spec['prefix']) ? $spec['prefix'] : ''; + $suffix = isset($spec['suffix']) ? $spec['suffix'] : ''; + $glue = isset($spec['glue']) ? $spec['glue'] : ''; + $args = + $prefix + . implode($glue, $this->buildSpecificationParameter($args, $context)) + . $suffix; + } else { + $args = implode($spec, $this->buildSpecificationParameter($args, $context)); + } + } elseif ($specName == 'format') { + $args = vsprintf( + $spec, + $this->buildSpecificationParameter($args, $context) + ); + } + } + return $args; + } + + private function buildSpecificationParameter($parameter, Context $context = null) + { + if (is_array($parameter)) { + foreach ($parameter as &$ppp) { + $ppp = $this->buildSpecificationParameter($ppp, $context); + } + return $parameter; + } + + $isQuoted = false; + if ($parameter instanceof ExpressionParameter) { + $value = $parameter->getValue(); + $type = $parameter->getType(); + $paramName = $parameter->getName(); + $isQuoted = $parameter->getOption('isQuoted'); + } else { + $value = $parameter; + $type = ExpressionInterface::TYPE_LITERAL; + } + + if ($value instanceof TableIdentifier || $value instanceof TableSource) { + $parameter = $this->nornalizeTable($value, $context)['name']; + } elseif ($value instanceof SelectableInterface) { + $parameter = $this->buildSubSelect($value, $context); + } elseif ($value instanceof ExpressionInterface) { + $parameter = $this->build($value, $context); + } elseif ($type == ExpressionInterface::TYPE_IDENTIFIER) { + $parameter = $context->getPlatform()->quoteIdentifierInFragment($value); + } elseif ($type == ExpressionInterface::TYPE_VALUE) { + if ($context->getParameterContainer()) { + $name = isset($paramName) + ? $paramName + : $context->getNestedAlias('expr'); + if (is_array($name)) { + $context->getParameterContainer()->offsetSet($name[0], $value); + $context->getParameterContainer()->offsetSetReference($name[1], $name[0]); + } else { + $context->getParameterContainer()->offsetSet($name, $value); + } + $parameter = $context->getDriver()->formatParameterName($name); + } else { + $parameter = $isQuoted + ? $value + : $context->getPlatform()->quoteValue($value); + } + } elseif ($type == ExpressionInterface::TYPE_LITERAL) { + $parameter = $value; + } + + return $parameter; + } + + private function buildSubSelect(SelectableInterface $subselect, Context $context) + { + $context->startPrefix('subselect'); + + $result = '(' . $this->build($subselect, $context) . ')'; + + $context->endPrefix(); + + return $result; + } } diff --git a/src/Sql/Builder/SelectLimitOffsetTrait.php b/src/Sql/Builder/SelectLimitOffsetTrait.php index fb6914b97d..45441ae26f 100644 --- a/src/Sql/Builder/SelectLimitOffsetTrait.php +++ b/src/Sql/Builder/SelectLimitOffsetTrait.php @@ -21,7 +21,7 @@ trait SelectLimitOffsetTrait * @param Context $context * @return null|string|array */ - public function build($sqlObject, Context $context) + protected function build($sqlObject, Context $context) { $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Select', __METHOD__); if ($sqlObject->limit === null && $sqlObject->offset === null) { diff --git a/src/Sql/Builder/sql92/CombineBuilder.php b/src/Sql/Builder/sql92/CombineBuilder.php index bc1142dc0f..d0d5e5d55d 100644 --- a/src/Sql/Builder/sql92/CombineBuilder.php +++ b/src/Sql/Builder/sql92/CombineBuilder.php @@ -19,7 +19,7 @@ class CombineBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function build($sqlObject, Context $context) + protected function build($sqlObject, Context $context) { $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Combine', __METHOD__); $res = []; diff --git a/src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php b/src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php index 5bc8bbf8d6..48e85c2d68 100644 --- a/src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php @@ -42,7 +42,7 @@ class AlterTableBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function build($sqlObject, Context $context) + protected function build($sqlObject, Context $context) { $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Ddl\AlterTable', __METHOD__); return [ diff --git a/src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php b/src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php index afceae4f89..8b8c8f1bf0 100644 --- a/src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php @@ -53,7 +53,7 @@ class ColumnBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function build($column, Context $context) + protected function build($column, Context $context) { $this->validateSqlObject($column, 'Zend\Db\Sql\Ddl\Column\Column', __METHOD__); $data = $this->buildColumnSpec($context, $this->specifications, $column); diff --git a/src/Sql/Builder/sql92/Ddl/Constraint/AbstractBuilder.php b/src/Sql/Builder/sql92/Ddl/Constraint/AbstractBuilder.php index b697b5cf6d..df72ee24c4 100644 --- a/src/Sql/Builder/sql92/Ddl/Constraint/AbstractBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/Constraint/AbstractBuilder.php @@ -36,7 +36,7 @@ class AbstractBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function build($constraint, Context $context) + protected function build($constraint, Context $context) { $this->validateSqlObject($constraint, 'Zend\Db\Sql\Ddl\Constraint\ConstraintInterface', __METHOD__); $parameters = []; diff --git a/src/Sql/Builder/sql92/Ddl/Constraint/CheckBuilder.php b/src/Sql/Builder/sql92/Ddl/Constraint/CheckBuilder.php index 5b4161047e..315cc27068 100644 --- a/src/Sql/Builder/sql92/Ddl/Constraint/CheckBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/Constraint/CheckBuilder.php @@ -25,7 +25,7 @@ class CheckBuilder extends AbstractBuilder * @param Context $context * @return array */ - public function build($check, Context $context) + protected function build($check, Context $context) { $this->validateSqlObject($check, 'Zend\Db\Sql\Ddl\Constraint\Check', __METHOD__); $values = []; diff --git a/src/Sql/Builder/sql92/Ddl/Constraint/ForeignKeyBuilder.php b/src/Sql/Builder/sql92/Ddl/Constraint/ForeignKeyBuilder.php index e2917bd6d5..cb0712f9fb 100644 --- a/src/Sql/Builder/sql92/Ddl/Constraint/ForeignKeyBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/Constraint/ForeignKeyBuilder.php @@ -33,7 +33,7 @@ class ForeignKeyBuilder extends AbstractBuilder * @param Context $context * @return array */ - public function build($constraint, Context $context) + protected function build($constraint, Context $context) { $this->validateSqlObject($constraint, 'Zend\Db\Sql\Ddl\Constraint\ForeignKey', __METHOD__); $data = parent::build($constraint, $context); diff --git a/src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php b/src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php index 16764cf659..f7222e7548 100644 --- a/src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php @@ -33,7 +33,7 @@ class CreateTableBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function build($sqlObject, Context $context) + protected function build($sqlObject, Context $context) { $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Ddl\CreateTable', __METHOD__); return [ diff --git a/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php b/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php index c8a025f7dc..7c6da64af5 100644 --- a/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php @@ -22,7 +22,7 @@ class DropTableBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function build($sqlObject, Context $context) + protected function build($sqlObject, Context $context) { $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Ddl\DropTable', __METHOD__); return [ diff --git a/src/Sql/Builder/sql92/Ddl/Index/IndexBuilder.php b/src/Sql/Builder/sql92/Ddl/Index/IndexBuilder.php index 2eeda9a6d1..4117cfa9c8 100644 --- a/src/Sql/Builder/sql92/Ddl/Index/IndexBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/Index/IndexBuilder.php @@ -26,7 +26,7 @@ class IndexBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function build($index, Context $context) + protected function build($index, Context $context) { $this->validateSqlObject($index, 'Zend\Db\Sql\Ddl\Index\AbstractIndex', __METHOD__); $properties = [ diff --git a/src/Sql/Builder/sql92/DeleteBuilder.php b/src/Sql/Builder/sql92/DeleteBuilder.php index c8a30d600c..cc6716aced 100644 --- a/src/Sql/Builder/sql92/DeleteBuilder.php +++ b/src/Sql/Builder/sql92/DeleteBuilder.php @@ -23,7 +23,7 @@ class DeleteBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function build($sqlObject, Context $context) + protected function build($sqlObject, Context $context) { $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Delete', __METHOD__); return [ diff --git a/src/Sql/Builder/sql92/ExpressionBuilder.php b/src/Sql/Builder/sql92/ExpressionBuilder.php index 5265017683..a3bc8e3cdf 100644 --- a/src/Sql/Builder/sql92/ExpressionBuilder.php +++ b/src/Sql/Builder/sql92/ExpressionBuilder.php @@ -22,7 +22,7 @@ class ExpressionBuilder extends AbstractSqlBuilder * @return array * @throws Exception\RuntimeException */ - public function build($expression, Context $context) + protected function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Expression', __METHOD__); $parameters = (is_scalar($expression->getParameters())) ? [$expression->getParameters()] : $expression->getParameters(); diff --git a/src/Sql/Builder/sql92/InsertBuilder.php b/src/Sql/Builder/sql92/InsertBuilder.php index 605eb9e5a7..e72af56a08 100644 --- a/src/Sql/Builder/sql92/InsertBuilder.php +++ b/src/Sql/Builder/sql92/InsertBuilder.php @@ -45,7 +45,7 @@ class InsertBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function build($sqlObject, Context $context) + protected function build($sqlObject, Context $context) { $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Insert', __METHOD__); return [ diff --git a/src/Sql/Builder/sql92/LiteralBuilder.php b/src/Sql/Builder/sql92/LiteralBuilder.php index 1bc954c526..1566733d75 100644 --- a/src/Sql/Builder/sql92/LiteralBuilder.php +++ b/src/Sql/Builder/sql92/LiteralBuilder.php @@ -19,7 +19,7 @@ class LiteralBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function build($expression, Context $context) + protected function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Literal', __METHOD__); return [ diff --git a/src/Sql/Builder/sql92/Predicate/BetweenBuilder.php b/src/Sql/Builder/sql92/Predicate/BetweenBuilder.php index 8388672f1e..d64d9a8c3f 100644 --- a/src/Sql/Builder/sql92/Predicate/BetweenBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/BetweenBuilder.php @@ -21,7 +21,7 @@ class BetweenBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function build($expression, Context $context) + protected function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\Between', __METHOD__); return [[ diff --git a/src/Sql/Builder/sql92/Predicate/InBuilder.php b/src/Sql/Builder/sql92/Predicate/InBuilder.php index 324fe58490..418b36bb72 100644 --- a/src/Sql/Builder/sql92/Predicate/InBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/InBuilder.php @@ -21,7 +21,7 @@ class InBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function build($expression, Context $context) + protected function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\In', __METHOD__); $identifier = $expression->getIdentifier(); diff --git a/src/Sql/Builder/sql92/Predicate/IsNullBuilder.php b/src/Sql/Builder/sql92/Predicate/IsNullBuilder.php index 75fa615648..e02bf93b6f 100644 --- a/src/Sql/Builder/sql92/Predicate/IsNullBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/IsNullBuilder.php @@ -24,7 +24,7 @@ class IsNullBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function build($expression, Context $context) + protected function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\IsNull', __METHOD__); return [[ diff --git a/src/Sql/Builder/sql92/Predicate/LikeBuilder.php b/src/Sql/Builder/sql92/Predicate/LikeBuilder.php index 56525715ae..e4d0179172 100644 --- a/src/Sql/Builder/sql92/Predicate/LikeBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/LikeBuilder.php @@ -24,7 +24,7 @@ class LikeBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function build($expression, Context $context) + protected function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\Like', __METHOD__); return [[ diff --git a/src/Sql/Builder/sql92/Predicate/NotBetweenBuilder.php b/src/Sql/Builder/sql92/Predicate/NotBetweenBuilder.php index c390dd8e1f..97ab531bcc 100644 --- a/src/Sql/Builder/sql92/Predicate/NotBetweenBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/NotBetweenBuilder.php @@ -21,7 +21,7 @@ class NotBetweenBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function build($expression, Context $context) + protected function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\NotBetween', __METHOD__); return [[ diff --git a/src/Sql/Builder/sql92/Predicate/OperatorBuilder.php b/src/Sql/Builder/sql92/Predicate/OperatorBuilder.php index 2825e08715..18fb3953f1 100644 --- a/src/Sql/Builder/sql92/Predicate/OperatorBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/OperatorBuilder.php @@ -19,7 +19,7 @@ class OperatorBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function build($expression, Context $context) + protected function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\Operator', __METHOD__); return [[ diff --git a/src/Sql/Builder/sql92/Predicate/PredicateSetBuilder.php b/src/Sql/Builder/sql92/Predicate/PredicateSetBuilder.php index 6403f02d95..abaea94b11 100644 --- a/src/Sql/Builder/sql92/Predicate/PredicateSetBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/PredicateSetBuilder.php @@ -20,7 +20,7 @@ class PredicateSetBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function build($expression, Context $context) + protected function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\PredicateSet', __METHOD__); $predicates = $expression->getPredicates(); diff --git a/src/Sql/Builder/sql92/SelectBuilder.php b/src/Sql/Builder/sql92/SelectBuilder.php index d94434b170..5c12dd1b53 100644 --- a/src/Sql/Builder/sql92/SelectBuilder.php +++ b/src/Sql/Builder/sql92/SelectBuilder.php @@ -107,7 +107,7 @@ class SelectBuilder extends AbstractSqlBuilder * @param Context $context * @return array|null */ - public function build($sqlObject, Context $context) + protected function build($sqlObject, Context $context) { $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Select', __METHOD__); $sqls = []; diff --git a/src/Sql/Builder/sql92/UpdateBuilder.php b/src/Sql/Builder/sql92/UpdateBuilder.php index d894c9209f..20424e1290 100644 --- a/src/Sql/Builder/sql92/UpdateBuilder.php +++ b/src/Sql/Builder/sql92/UpdateBuilder.php @@ -50,7 +50,7 @@ class UpdateBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - public function build($sqlObject, Context $context) + protected function build($sqlObject, Context $context) { $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Update', __METHOD__); return [ diff --git a/src/Sql/Sql.php b/src/Sql/Sql.php index 018e0699f7..573e03a1cf 100644 --- a/src/Sql/Sql.php +++ b/src/Sql/Sql.php @@ -153,9 +153,9 @@ public function delete($table = null) * * @return StatementInterface */ - public function prepareStatementForSqlObject(PreparableSqlObjectInterface $sqlObject, AdapterInterface $adapter = null) + public function prepareSqlStatement(PreparableSqlObjectInterface $sqlObject, AdapterInterface $adapter = null) { - return $this->builder->prepareStatement( + return $this->builder->prepareSqlStatement( $sqlObject, $adapter ?: $this->adapter ); @@ -171,7 +171,7 @@ public function prepareStatementForSqlObject(PreparableSqlObjectInterface $sqlOb */ public function buildSqlString(SqlObjectInterface $sqlObject, AdapterInterface $adapter = null) { - return $this->builder->getSqlString( + return $this->builder->buildSqlString( $sqlObject, $adapter ?: $this->adapter ); diff --git a/src/TableGateway/AbstractTableGateway.php b/src/TableGateway/AbstractTableGateway.php index 8292fe9f2c..6966d359ed 100644 --- a/src/TableGateway/AbstractTableGateway.php +++ b/src/TableGateway/AbstractTableGateway.php @@ -231,7 +231,7 @@ protected function executeSelect(Select $select) $this->featureSet->apply(EventFeatureEventsInterface::EVENT_PRE_SELECT, [$select]); // prepare and execute - $statement = $this->sql->prepareStatementForSqlObject($select); + $statement = $this->sql->prepareSqlStatement($select); $result = $statement->execute(); // build result set @@ -299,7 +299,7 @@ protected function executeInsert(Insert $insert) $insert->into(array_shift($tableData)); } - $statement = $this->sql->prepareStatementForSqlObject($insert); + $statement = $this->sql->prepareSqlStatement($insert); $result = $statement->execute(); $this->lastInsertValue = $this->adapter->getDriver()->getConnection()->getLastGeneratedValue(); @@ -381,7 +381,7 @@ protected function executeUpdate(Update $update) $update->table(array_shift($tableData)); } - $statement = $this->sql->prepareStatementForSqlObject($update); + $statement = $this->sql->prepareSqlStatement($update); $result = $statement->execute(); // apply postUpdate features @@ -443,7 +443,7 @@ protected function executeDelete(Delete $delete) // pre delete update $this->featureSet->apply(EventFeatureEventsInterface::EVENT_PRE_DELETE, [$delete]); - $statement = $this->sql->prepareStatementForSqlObject($delete); + $statement = $this->sql->prepareSqlStatement($delete); $result = $statement->execute(); // apply postDelete features diff --git a/test/Sql/Builder/AbstractTestCase.php b/test/Sql/Builder/AbstractTestCase.php index 648293f26c..1d9b4960a6 100644 --- a/test/Sql/Builder/AbstractTestCase.php +++ b/test/Sql/Builder/AbstractTestCase.php @@ -122,8 +122,8 @@ public function assertBuilder($sqlObject, $platform = null, $expected = null) $expectedString = is_string($expected) ? $expected : (isset($expected['string']) ? $expected['string'] : null); if ($expectedString) { - $actual = $builder->getSqlString($sqlObject, $adapter); - $this->assertEquals($expectedString, $actual, "getSqlString()"); + $actual = $builder->buildSqlString($sqlObject, $adapter); + $this->assertEquals($expectedString, $actual, "buildSqlString()"); } if (is_array($expected) && isset($expected['prepare'])) { if ($expected['prepare'] === true) { @@ -131,8 +131,8 @@ public function assertBuilder($sqlObject, $platform = null, $expected = null) } $this->useNamedParameters = isset($expected['useNamedParams']) && $expected['useNamedParams']; - $actual = $builder->prepareStatement($sqlObject, $adapter); - $this->assertEquals($expected['prepare'], $actual->getSql(), "prepareStatement()"); + $actual = $builder->prepareSqlStatement($sqlObject, $adapter); + $this->assertEquals($expected['prepare'], $actual->getSql(), "prepareSqlStatement()"); if (isset($expected['parameters'])) { $this->assertSame( $expected['parameters'], diff --git a/test/Sql/Builder/BuilderTest.php b/test/Sql/Builder/BuilderTest.php index 1ca455908b..77c6b5c8fd 100644 --- a/test/Sql/Builder/BuilderTest.php +++ b/test/Sql/Builder/BuilderTest.php @@ -128,13 +128,13 @@ public function testDefaultAdapter() } /** - * @covers Zend\Db\Sql\Builder\Builder::getSqlString + * @covers Zend\Db\Sql\Builder\Builder::buildSqlString */ - public function testGetSqlString() + public function testBuildSqlString() { $this->assertInternalType( 'string', - $this->builder->getSqlString( + $this->builder->buildSqlString( new Sql\Select('foo'), $this->getAdapterForPlatform('sql92') ) @@ -142,11 +142,11 @@ public function testGetSqlString() } /** - * @covers Zend\Db\Sql\Builder\Builder::prepareStatement + * @covers Zend\Db\Sql\Builder\Builder::prepareSqlStatement */ - public function testPrepareStatement() + public function testPrepareSqlStatement() { - $statement = $this->builder->prepareStatement( + $statement = $this->builder->prepareSqlStatement( new Sql\Select('foo'), $this->getAdapterForPlatform('sql92') ); diff --git a/test/Sql/Builder/CombineBuilderTest.php b/test/Sql/Builder/CombineBuilderTest.php index 861535e199..9a3a2c5fdb 100644 --- a/test/Sql/Builder/CombineBuilderTest.php +++ b/test/Sql/Builder/CombineBuilderTest.php @@ -28,7 +28,7 @@ public function test($sqlObject, $platform, $expected) public function dataProvider() { return $this->prepareDataProvider([ - [ // testGetSqlStringEmpty() + [ // testBuildSqlStringEmpty() 'sqlObject' => $this->combine(), 'expected' => [ 'sql92' => [ @@ -37,7 +37,7 @@ public function dataProvider() ], ], ], - [ // testGetSqlString() + [ // testBuildSqlString() 'sqlObject' => $this->combine() ->union($this->select('t1')) ->intersect($this->select('t2')) @@ -49,7 +49,7 @@ public function dataProvider() ], ], ], - [ // testGetSqlStringWithModifier() + [ // testBuildSqlStringWithModifier() 'sqlObject' => $this->combine() ->union($this->select('t1')) ->union($this->select('t2'), 'ALL'), diff --git a/test/Sql/Builder/DeleteBuilderTest.php b/test/Sql/Builder/DeleteBuilderTest.php index 1a8871b696..cfe55bfc35 100644 --- a/test/Sql/Builder/DeleteBuilderTest.php +++ b/test/Sql/Builder/DeleteBuilderTest.php @@ -92,7 +92,7 @@ public function dataProvider_Subselect() public function dataProvider_Where() { return [ - [ // testPrepareStatement(), testGetSqlString() + [ // testPrepareSqlStatement(), testBuildSqlString() 'sqlObject' => $this->delete()->from('foo')->where('x = y'), 'expected' => [ 'sql92' => [ diff --git a/test/Sql/SqlTest.php b/test/Sql/SqlTest.php index cdf28b7e54..086fcf6669 100644 --- a/test/Sql/SqlTest.php +++ b/test/Sql/SqlTest.php @@ -133,12 +133,12 @@ public function testDelete() } /** - * @covers Zend\Db\Sql\Sql::prepareStatementForSqlObject + * @covers Zend\Db\Sql\Sql::prepareSqlStatement */ - public function testPrepareStatementForSqlObject() + public function testPrepareSqlStatement() { $insert = $this->sql->insert()->columns(['foo'])->values(['foo'=>'bar']); - $stmt = $this->sql->prepareStatementForSqlObject($insert); + $stmt = $this->sql->prepareSqlStatement($insert); $this->assertInstanceOf('Zend\Db\Adapter\Driver\StatementInterface', $stmt); } } diff --git a/test/TableGateway/TableGatewayTest.php b/test/TableGateway/TableGatewayTest.php index d4ddeca485..fb5b6b55fb 100644 --- a/test/TableGateway/TableGatewayTest.php +++ b/test/TableGateway/TableGatewayTest.php @@ -184,7 +184,7 @@ public function testInsertShouldResetTableToUnaliasedTable($tableValue, $expecte ->method('insert') ->will($this->returnValue($insert)); $sql->expects($this->once()) - ->method('prepareStatementForSqlObject') + ->method('prepareSqlStatement') ->with($this->equalTo($insert)) ->will($this->returnCallback($statementExpectation)); @@ -247,7 +247,7 @@ public function testUpdateShouldResetTableToUnaliasedTable($tableValue, $expecte ->method('update') ->will($this->returnValue($update)); $sql->expects($this->once()) - ->method('prepareStatementForSqlObject') + ->method('prepareSqlStatement') ->with($this->equalTo($update)) ->will($this->returnCallback($statementExpectation)); diff --git a/test/TestAsset/ExpressionBuilder.php b/test/TestAsset/ExpressionBuilder.php index edbfdbcc77..e9cd1a08b7 100644 --- a/test/TestAsset/ExpressionBuilder.php +++ b/test/TestAsset/ExpressionBuilder.php @@ -13,7 +13,7 @@ class ExpressionBuilder extends \Zend\Db\Sql\Builder\sql92\ExpressionBuilder { - public function build($expression, Context $context) + protected function build($expression, Context $context) { $expressionString = $expression->getExpression(); $expression->setExpression('{decorate-' . $expressionString . '-decorate}'); From 70c484efd81aa816cd80b1d7365b00fb87092475 Mon Sep 17 00:00:00 2001 From: turrsis Date: Fri, 27 Nov 2015 11:21:46 +0200 Subject: [PATCH 12/30] architecture 10.1: unprotect builded methods, because protected is not stable decision --- src/Sql/Builder/AbstractBuilder.php | 2 -- src/Sql/Builder/AbstractSqlBuilder.php | 2 ++ src/Sql/Builder/SelectLimitOffsetTrait.php | 2 +- src/Sql/Builder/sql92/CombineBuilder.php | 2 +- src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php | 2 +- src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php | 2 +- src/Sql/Builder/sql92/Ddl/Constraint/AbstractBuilder.php | 2 +- src/Sql/Builder/sql92/Ddl/Constraint/CheckBuilder.php | 2 +- src/Sql/Builder/sql92/Ddl/Constraint/ForeignKeyBuilder.php | 2 +- src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php | 2 +- src/Sql/Builder/sql92/Ddl/DropTableBuilder.php | 2 +- src/Sql/Builder/sql92/Ddl/Index/IndexBuilder.php | 2 +- src/Sql/Builder/sql92/DeleteBuilder.php | 2 +- src/Sql/Builder/sql92/ExpressionBuilder.php | 2 +- src/Sql/Builder/sql92/InsertBuilder.php | 2 +- src/Sql/Builder/sql92/LiteralBuilder.php | 2 +- src/Sql/Builder/sql92/Predicate/BetweenBuilder.php | 2 +- src/Sql/Builder/sql92/Predicate/InBuilder.php | 2 +- src/Sql/Builder/sql92/Predicate/IsNullBuilder.php | 2 +- src/Sql/Builder/sql92/Predicate/LikeBuilder.php | 2 +- src/Sql/Builder/sql92/Predicate/NotBetweenBuilder.php | 2 +- src/Sql/Builder/sql92/Predicate/OperatorBuilder.php | 2 +- src/Sql/Builder/sql92/Predicate/PredicateSetBuilder.php | 2 +- src/Sql/Builder/sql92/SelectBuilder.php | 2 +- src/Sql/Builder/sql92/UpdateBuilder.php | 2 +- test/TestAsset/ExpressionBuilder.php | 2 +- 26 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/Sql/Builder/AbstractBuilder.php b/src/Sql/Builder/AbstractBuilder.php index 14e519db3c..b2289ea37f 100644 --- a/src/Sql/Builder/AbstractBuilder.php +++ b/src/Sql/Builder/AbstractBuilder.php @@ -16,8 +16,6 @@ abstract class AbstractBuilder { protected $implodeGlueKey = 'implode_glue'; - abstract protected function build($sqlObject, Context $context); - /** * @param TableIdentifier|string|array $identifier * @param Context $context diff --git a/src/Sql/Builder/AbstractSqlBuilder.php b/src/Sql/Builder/AbstractSqlBuilder.php index e19431b57f..afeeabd494 100644 --- a/src/Sql/Builder/AbstractSqlBuilder.php +++ b/src/Sql/Builder/AbstractSqlBuilder.php @@ -29,6 +29,8 @@ public function __construct(Builder $platformBuilder) $this->platformBuilder = $platformBuilder; } + abstract public function build($sqlObject, Context $context); + /** * @param string|array $column * @param mixed $value diff --git a/src/Sql/Builder/SelectLimitOffsetTrait.php b/src/Sql/Builder/SelectLimitOffsetTrait.php index 45441ae26f..fb6914b97d 100644 --- a/src/Sql/Builder/SelectLimitOffsetTrait.php +++ b/src/Sql/Builder/SelectLimitOffsetTrait.php @@ -21,7 +21,7 @@ trait SelectLimitOffsetTrait * @param Context $context * @return null|string|array */ - protected function build($sqlObject, Context $context) + public function build($sqlObject, Context $context) { $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Select', __METHOD__); if ($sqlObject->limit === null && $sqlObject->offset === null) { diff --git a/src/Sql/Builder/sql92/CombineBuilder.php b/src/Sql/Builder/sql92/CombineBuilder.php index d0d5e5d55d..bc1142dc0f 100644 --- a/src/Sql/Builder/sql92/CombineBuilder.php +++ b/src/Sql/Builder/sql92/CombineBuilder.php @@ -19,7 +19,7 @@ class CombineBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - protected function build($sqlObject, Context $context) + public function build($sqlObject, Context $context) { $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Combine', __METHOD__); $res = []; diff --git a/src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php b/src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php index 48e85c2d68..5bc8bbf8d6 100644 --- a/src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/AlterTableBuilder.php @@ -42,7 +42,7 @@ class AlterTableBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - protected function build($sqlObject, Context $context) + public function build($sqlObject, Context $context) { $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Ddl\AlterTable', __METHOD__); return [ diff --git a/src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php b/src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php index 8b8c8f1bf0..afceae4f89 100644 --- a/src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/Column/ColumnBuilder.php @@ -53,7 +53,7 @@ class ColumnBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - protected function build($column, Context $context) + public function build($column, Context $context) { $this->validateSqlObject($column, 'Zend\Db\Sql\Ddl\Column\Column', __METHOD__); $data = $this->buildColumnSpec($context, $this->specifications, $column); diff --git a/src/Sql/Builder/sql92/Ddl/Constraint/AbstractBuilder.php b/src/Sql/Builder/sql92/Ddl/Constraint/AbstractBuilder.php index df72ee24c4..b697b5cf6d 100644 --- a/src/Sql/Builder/sql92/Ddl/Constraint/AbstractBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/Constraint/AbstractBuilder.php @@ -36,7 +36,7 @@ class AbstractBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - protected function build($constraint, Context $context) + public function build($constraint, Context $context) { $this->validateSqlObject($constraint, 'Zend\Db\Sql\Ddl\Constraint\ConstraintInterface', __METHOD__); $parameters = []; diff --git a/src/Sql/Builder/sql92/Ddl/Constraint/CheckBuilder.php b/src/Sql/Builder/sql92/Ddl/Constraint/CheckBuilder.php index 315cc27068..5b4161047e 100644 --- a/src/Sql/Builder/sql92/Ddl/Constraint/CheckBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/Constraint/CheckBuilder.php @@ -25,7 +25,7 @@ class CheckBuilder extends AbstractBuilder * @param Context $context * @return array */ - protected function build($check, Context $context) + public function build($check, Context $context) { $this->validateSqlObject($check, 'Zend\Db\Sql\Ddl\Constraint\Check', __METHOD__); $values = []; diff --git a/src/Sql/Builder/sql92/Ddl/Constraint/ForeignKeyBuilder.php b/src/Sql/Builder/sql92/Ddl/Constraint/ForeignKeyBuilder.php index cb0712f9fb..e2917bd6d5 100644 --- a/src/Sql/Builder/sql92/Ddl/Constraint/ForeignKeyBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/Constraint/ForeignKeyBuilder.php @@ -33,7 +33,7 @@ class ForeignKeyBuilder extends AbstractBuilder * @param Context $context * @return array */ - protected function build($constraint, Context $context) + public function build($constraint, Context $context) { $this->validateSqlObject($constraint, 'Zend\Db\Sql\Ddl\Constraint\ForeignKey', __METHOD__); $data = parent::build($constraint, $context); diff --git a/src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php b/src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php index f7222e7548..16764cf659 100644 --- a/src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/CreateTableBuilder.php @@ -33,7 +33,7 @@ class CreateTableBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - protected function build($sqlObject, Context $context) + public function build($sqlObject, Context $context) { $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Ddl\CreateTable', __METHOD__); return [ diff --git a/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php b/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php index 7c6da64af5..c8a025f7dc 100644 --- a/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php @@ -22,7 +22,7 @@ class DropTableBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - protected function build($sqlObject, Context $context) + public function build($sqlObject, Context $context) { $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Ddl\DropTable', __METHOD__); return [ diff --git a/src/Sql/Builder/sql92/Ddl/Index/IndexBuilder.php b/src/Sql/Builder/sql92/Ddl/Index/IndexBuilder.php index 4117cfa9c8..2eeda9a6d1 100644 --- a/src/Sql/Builder/sql92/Ddl/Index/IndexBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/Index/IndexBuilder.php @@ -26,7 +26,7 @@ class IndexBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - protected function build($index, Context $context) + public function build($index, Context $context) { $this->validateSqlObject($index, 'Zend\Db\Sql\Ddl\Index\AbstractIndex', __METHOD__); $properties = [ diff --git a/src/Sql/Builder/sql92/DeleteBuilder.php b/src/Sql/Builder/sql92/DeleteBuilder.php index cc6716aced..c8a30d600c 100644 --- a/src/Sql/Builder/sql92/DeleteBuilder.php +++ b/src/Sql/Builder/sql92/DeleteBuilder.php @@ -23,7 +23,7 @@ class DeleteBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - protected function build($sqlObject, Context $context) + public function build($sqlObject, Context $context) { $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Delete', __METHOD__); return [ diff --git a/src/Sql/Builder/sql92/ExpressionBuilder.php b/src/Sql/Builder/sql92/ExpressionBuilder.php index a3bc8e3cdf..5265017683 100644 --- a/src/Sql/Builder/sql92/ExpressionBuilder.php +++ b/src/Sql/Builder/sql92/ExpressionBuilder.php @@ -22,7 +22,7 @@ class ExpressionBuilder extends AbstractSqlBuilder * @return array * @throws Exception\RuntimeException */ - protected function build($expression, Context $context) + public function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Expression', __METHOD__); $parameters = (is_scalar($expression->getParameters())) ? [$expression->getParameters()] : $expression->getParameters(); diff --git a/src/Sql/Builder/sql92/InsertBuilder.php b/src/Sql/Builder/sql92/InsertBuilder.php index e72af56a08..605eb9e5a7 100644 --- a/src/Sql/Builder/sql92/InsertBuilder.php +++ b/src/Sql/Builder/sql92/InsertBuilder.php @@ -45,7 +45,7 @@ class InsertBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - protected function build($sqlObject, Context $context) + public function build($sqlObject, Context $context) { $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Insert', __METHOD__); return [ diff --git a/src/Sql/Builder/sql92/LiteralBuilder.php b/src/Sql/Builder/sql92/LiteralBuilder.php index 1566733d75..1bc954c526 100644 --- a/src/Sql/Builder/sql92/LiteralBuilder.php +++ b/src/Sql/Builder/sql92/LiteralBuilder.php @@ -19,7 +19,7 @@ class LiteralBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - protected function build($expression, Context $context) + public function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Literal', __METHOD__); return [ diff --git a/src/Sql/Builder/sql92/Predicate/BetweenBuilder.php b/src/Sql/Builder/sql92/Predicate/BetweenBuilder.php index d64d9a8c3f..8388672f1e 100644 --- a/src/Sql/Builder/sql92/Predicate/BetweenBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/BetweenBuilder.php @@ -21,7 +21,7 @@ class BetweenBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - protected function build($expression, Context $context) + public function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\Between', __METHOD__); return [[ diff --git a/src/Sql/Builder/sql92/Predicate/InBuilder.php b/src/Sql/Builder/sql92/Predicate/InBuilder.php index 418b36bb72..324fe58490 100644 --- a/src/Sql/Builder/sql92/Predicate/InBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/InBuilder.php @@ -21,7 +21,7 @@ class InBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - protected function build($expression, Context $context) + public function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\In', __METHOD__); $identifier = $expression->getIdentifier(); diff --git a/src/Sql/Builder/sql92/Predicate/IsNullBuilder.php b/src/Sql/Builder/sql92/Predicate/IsNullBuilder.php index e02bf93b6f..75fa615648 100644 --- a/src/Sql/Builder/sql92/Predicate/IsNullBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/IsNullBuilder.php @@ -24,7 +24,7 @@ class IsNullBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - protected function build($expression, Context $context) + public function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\IsNull', __METHOD__); return [[ diff --git a/src/Sql/Builder/sql92/Predicate/LikeBuilder.php b/src/Sql/Builder/sql92/Predicate/LikeBuilder.php index e4d0179172..56525715ae 100644 --- a/src/Sql/Builder/sql92/Predicate/LikeBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/LikeBuilder.php @@ -24,7 +24,7 @@ class LikeBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - protected function build($expression, Context $context) + public function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\Like', __METHOD__); return [[ diff --git a/src/Sql/Builder/sql92/Predicate/NotBetweenBuilder.php b/src/Sql/Builder/sql92/Predicate/NotBetweenBuilder.php index 97ab531bcc..c390dd8e1f 100644 --- a/src/Sql/Builder/sql92/Predicate/NotBetweenBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/NotBetweenBuilder.php @@ -21,7 +21,7 @@ class NotBetweenBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - protected function build($expression, Context $context) + public function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\NotBetween', __METHOD__); return [[ diff --git a/src/Sql/Builder/sql92/Predicate/OperatorBuilder.php b/src/Sql/Builder/sql92/Predicate/OperatorBuilder.php index 18fb3953f1..2825e08715 100644 --- a/src/Sql/Builder/sql92/Predicate/OperatorBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/OperatorBuilder.php @@ -19,7 +19,7 @@ class OperatorBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - protected function build($expression, Context $context) + public function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\Operator', __METHOD__); return [[ diff --git a/src/Sql/Builder/sql92/Predicate/PredicateSetBuilder.php b/src/Sql/Builder/sql92/Predicate/PredicateSetBuilder.php index abaea94b11..6403f02d95 100644 --- a/src/Sql/Builder/sql92/Predicate/PredicateSetBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/PredicateSetBuilder.php @@ -20,7 +20,7 @@ class PredicateSetBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - protected function build($expression, Context $context) + public function build($expression, Context $context) { $this->validateSqlObject($expression, 'Zend\Db\Sql\Predicate\PredicateSet', __METHOD__); $predicates = $expression->getPredicates(); diff --git a/src/Sql/Builder/sql92/SelectBuilder.php b/src/Sql/Builder/sql92/SelectBuilder.php index 5c12dd1b53..d94434b170 100644 --- a/src/Sql/Builder/sql92/SelectBuilder.php +++ b/src/Sql/Builder/sql92/SelectBuilder.php @@ -107,7 +107,7 @@ class SelectBuilder extends AbstractSqlBuilder * @param Context $context * @return array|null */ - protected function build($sqlObject, Context $context) + public function build($sqlObject, Context $context) { $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Select', __METHOD__); $sqls = []; diff --git a/src/Sql/Builder/sql92/UpdateBuilder.php b/src/Sql/Builder/sql92/UpdateBuilder.php index 20424e1290..d894c9209f 100644 --- a/src/Sql/Builder/sql92/UpdateBuilder.php +++ b/src/Sql/Builder/sql92/UpdateBuilder.php @@ -50,7 +50,7 @@ class UpdateBuilder extends AbstractSqlBuilder * @param Context $context * @return array */ - protected function build($sqlObject, Context $context) + public function build($sqlObject, Context $context) { $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Update', __METHOD__); return [ diff --git a/test/TestAsset/ExpressionBuilder.php b/test/TestAsset/ExpressionBuilder.php index e9cd1a08b7..edbfdbcc77 100644 --- a/test/TestAsset/ExpressionBuilder.php +++ b/test/TestAsset/ExpressionBuilder.php @@ -13,7 +13,7 @@ class ExpressionBuilder extends \Zend\Db\Sql\Builder\sql92\ExpressionBuilder { - protected function build($expression, Context $context) + public function build($expression, Context $context) { $expressionString = $expression->getExpression(); $expression->setExpression('{decorate-' . $expressionString . '-decorate}'); From 5d77e286912892d7851897bec09e640cc41c723b Mon Sep 17 00:00:00 2001 From: turrsis Date: Fri, 31 Jul 2015 13:55:38 +0300 Subject: [PATCH 13/30] fix 11: SelectBuilder for Combine --- src/Sql/Builder/sql92/SelectBuilder.php | 56 +++++-------------------- src/Sql/Combine.php | 20 +++++---- src/Sql/Select.php | 2 +- test/Sql/Builder/SelectBuilderTest.php | 4 +- 4 files changed, 27 insertions(+), 55 deletions(-) diff --git a/src/Sql/Builder/sql92/SelectBuilder.php b/src/Sql/Builder/sql92/SelectBuilder.php index d94434b170..6f4c916363 100644 --- a/src/Sql/Builder/sql92/SelectBuilder.php +++ b/src/Sql/Builder/sql92/SelectBuilder.php @@ -11,6 +11,7 @@ use Zend\Db\Adapter; use Zend\Db\Sql\Select; +use Zend\Db\Sql\Combine; use Zend\Db\Sql\ExpressionInterface; use Zend\Db\Sql\SelectableInterface; use Zend\Db\Sql\Builder\AbstractSqlBuilder; @@ -19,7 +20,6 @@ class SelectBuilder extends AbstractSqlBuilder { - protected $statementStartSpecification = '%1$s'; protected $selectNoTableSpecification = [ 'byArgNumber' => [ 1 => [ @@ -99,8 +99,6 @@ class SelectBuilder extends AbstractSqlBuilder ]; protected $limitSpecification = 'LIMIT %1$s'; protected $offsetSpecification = 'OFFSET %1$s'; - protected $statementEndSpecification = '%1$s'; - protected $combineSpecification = '%1$s ( %2$s )'; /** * @param Select $sqlObject @@ -110,8 +108,12 @@ class SelectBuilder extends AbstractSqlBuilder public function build($sqlObject, Context $context) { $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Select', __METHOD__); + + if ($sqlObject->combine) { + return $this->build_Combine($sqlObject, $context); + } + $sqls = []; - $sqls['start'] = $this->build_StatementStart($sqlObject, $context, $sqls); $sqls['select'] = $this->build_Select($sqlObject, $context, $sqls); $sqls['joins'] = $this->build_Joins($sqlObject, $context, $sqls); $sqls['where'] = $this->build_Where($sqlObject, $context, $sqls); @@ -120,35 +122,9 @@ public function build($sqlObject, Context $context) $sqls['order'] = $this->build_Order($sqlObject, $context, $sqls); $sqls['limit'] = $this->build_Limit($sqlObject, $context, $sqls); $sqls['offset'] = $this->build_Offset($sqlObject, $context, $sqls); - $sqls['end'] = $this->build_StatementEnd($sqlObject, $context, $sqls); - $sqls['combine'] = $this->build_Combine($sqlObject, $context, $sqls); return $sqls; } - /** - * @param Select $sqlObject - * @param Context $context - * @return string|null - */ - protected function build_StatementStart($sqlObject, Context $context) - { - if ($sqlObject->combine !== []) { - return '('; - } - } - - /** - * @param Select $sqlObject - * @param Context $context - * @return string|null - */ - protected function build_StatementEnd($sqlObject, Context $context) - { - if ($sqlObject->combine !== []) { - return ')'; - } - } - /** * @param Select $sqlObject * @param Context $context @@ -355,23 +331,13 @@ protected function build_Offset(Select $sqlObject, Context $context) */ protected function build_Combine(Select $sqlObject, Context $context) { - $COMBINE = $sqlObject->combine; - if ($COMBINE == []) { - return; - } + $select = clone $sqlObject; - $type = $COMBINE['type']; - if ($COMBINE['modifier']) { - $type .= ' ' . $COMBINE['modifier']; - } + $combine = new Combine($select); + $combine->combine($select->combine); + unset($select->combine); - return [ - 'spec' => $this->combineSpecification, - 'params' => [ - strtoupper($type), - $COMBINE['select'], - ], - ]; + return $this->platformBuilder->getPlatformBuilder($combine)->build($combine, $context); } /** diff --git a/src/Sql/Combine.php b/src/Sql/Combine.php index 3d875578ac..0d94ae272f 100644 --- a/src/Sql/Combine.php +++ b/src/Sql/Combine.php @@ -59,14 +59,20 @@ public function combine($select, $type = self::COMBINE_UNION, $modifier = '') if (is_array($select)) { foreach ($select as $combine) { if ($combine instanceof SelectableInterface) { - $combine = [$combine]; + $this->combine($combine, $type, $modifier); + } elseif (is_string(key($combine))) { + $this->combine( + $combine['select'], + isset($combine['type']) ? $combine['type'] : $type, + isset($combine['modifier']) ? $combine['modifier'] : $modifier + ); + } else { + $this->combine( + $combine[0], + isset($combine[1]) ? $combine[1] : $type, + isset($combine[2]) ? $combine[2] : $modifier + ); } - - $this->combine( - $combine[0], - isset($combine[1]) ? $combine[1] : $type, - isset($combine[2]) ? $combine[2] : $modifier - ); } return $this; } diff --git a/src/Sql/Select.php b/src/Sql/Select.php index 8e0aa8c19c..1de86d52d9 100644 --- a/src/Sql/Select.php +++ b/src/Sql/Select.php @@ -329,7 +329,7 @@ public function combine(SelectableInterface $select, $type = self::COMBINE_UNION if ($this->combine !== []) { throw new Exception\InvalidArgumentException('This Select object is already combined and cannot be combined with multiple Selects objects'); } - $this->combine = [ + $this->combine[] = [ 'select' => $select, 'type' => $type, 'modifier' => $modifier diff --git a/test/Sql/Builder/SelectBuilderTest.php b/test/Sql/Builder/SelectBuilderTest.php index 341c7bfc9b..23edc0af68 100644 --- a/test/Sql/Builder/SelectBuilderTest.php +++ b/test/Sql/Builder/SelectBuilderTest.php @@ -152,7 +152,7 @@ public function dataProvider_Combine() ), 'expected' => [ 'sql92' => [ - 'string' => '( SELECT "foo".* FROM "foo" WHERE a = b ) UNION ALL ( (SELECT "bar".* FROM "bar" WHERE c = d) )', + 'string' => '(SELECT "foo".* FROM "foo" WHERE a = b) UNION ALL (SELECT "bar".* FROM "bar" WHERE c = d)', 'prepare' => true, ], ], @@ -170,7 +170,7 @@ public function dataProvider_Combine() ->order('id DESC'), 'expected' => [ 'sql92' => [ - 'string' => 'SELECT "sub".* FROM (( SELECT "foo".* FROM "foo" WHERE a = b ) UNION ( (SELECT "bar".* FROM "bar" WHERE c = d) )) AS "sub" ORDER BY "id" DESC', + 'string' => 'SELECT "sub".* FROM ((SELECT "foo".* FROM "foo" WHERE a = b) UNION (SELECT "bar".* FROM "bar" WHERE c = d)) AS "sub" ORDER BY "id" DESC', 'prepare' => true, ], ], From 5a76ed41c168b878fab2075e8484d729af956e69 Mon Sep 17 00:00:00 2001 From: turrsis Date: Sun, 12 Jul 2015 14:56:14 +0300 Subject: [PATCH 14/30] fix 12: remove $prefixColumnsWithTable from Select::columns() method --- src/Sql/Builder/SelectLimitOffsetTrait.php | 5 +++-- src/Sql/Select.php | 13 ++++++++++--- test/Sql/Builder/SelectBuilderTest.php | 4 ++-- test/Sql/SelectTest.php | 3 ++- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/Sql/Builder/SelectLimitOffsetTrait.php b/src/Sql/Builder/SelectLimitOffsetTrait.php index fb6914b97d..b8767299fb 100644 --- a/src/Sql/Builder/SelectLimitOffsetTrait.php +++ b/src/Sql/Builder/SelectLimitOffsetTrait.php @@ -35,12 +35,13 @@ public function build($sqlObject, Context $context) ->columns([ Select::SQL_STAR, 'LIMIT_OFFSET_ROWNUM' => new Expression('ROW_NUMBER() OVER ()'), - ], false) + ]) + ->setPrefixColumnsWithTable(false) ->from([ 'LIMIT_OFFSET_WRAP_1' => $sqlObject ]) ]); - $newSelect->columns([Select::SQL_STAR], false); + $newSelect->columns([Select::SQL_STAR])->setPrefixColumnsWithTable(false); if ($sqlObject->offset !== null) { $offset = new ExpressionParameter((int) $sqlObject->offset, Expression::TYPE_VALUE, 'offset'); diff --git a/src/Sql/Select.php b/src/Sql/Select.php index 1de86d52d9..17fa669807 100644 --- a/src/Sql/Select.php +++ b/src/Sql/Select.php @@ -177,13 +177,11 @@ public function quantifier($quantifier) * value can be string or Expression objects * * @param array $columns - * @param bool $prefixColumnsWithTable * @return self */ - public function columns(array $columns, $prefixColumnsWithTable = true) + public function columns(array $columns) { $this->columns = $columns; - $this->prefixColumnsWithTable = (bool) $prefixColumnsWithTable; return $this; } @@ -337,6 +335,15 @@ public function combine(SelectableInterface $select, $type = self::COMBINE_UNION return $this; } + /** + * @param bool $flag + * @return self + */ + public function setPrefixColumnsWithTable($flag) + { + $this->prefixColumnsWithTable = (bool)$flag; + return $this; + } public function __unset($name) { diff --git a/test/Sql/Builder/SelectBuilderTest.php b/test/Sql/Builder/SelectBuilderTest.php index 23edc0af68..cf73fab2cc 100644 --- a/test/Sql/Builder/SelectBuilderTest.php +++ b/test/Sql/Builder/SelectBuilderTest.php @@ -110,7 +110,7 @@ public function dataProvider_Columns() ], ], [ - 'sqlObject' => $this->select()->from(['x' => 'foo'])->columns(['bar' => 'foo.bar'], false), + 'sqlObject' => $this->select()->from(['x' => 'foo'])->columns(['bar' => 'foo.bar'])->setPrefixColumnsWithTable(false), 'expected' => [ 'sql92' => [ 'string' => 'SELECT "foo"."bar" AS "bar" FROM "foo" AS "x"', @@ -119,7 +119,7 @@ public function dataProvider_Columns() ], ], [ // @author robertbasic // @link https://github.com/zendframework/zf2/pull/2714 - 'sqlObject' => $this->select()->from('foo')->columns(['bar'], false), + 'sqlObject' => $this->select()->from('foo')->columns(['bar'])->setPrefixColumnsWithTable(false), 'expected' => [ 'sql92' => [ 'string' => 'SELECT "bar" AS "bar" FROM "foo"', diff --git a/test/Sql/SelectTest.php b/test/Sql/SelectTest.php index 34665be12f..f97c641cb0 100644 --- a/test/Sql/SelectTest.php +++ b/test/Sql/SelectTest.php @@ -185,7 +185,8 @@ public function testMagicUnset() $select ->from('foo', 'bar') ->quantifier(Select::QUANTIFIER_DISTINCT) - ->columns(['foo', 'bar'], false) + ->columns(['foo', 'bar']) + ->setPrefixColumnsWithTable(false) ->join('foo', 'x = y', Select::SQL_STAR, Select::JOIN_INNER) ->where('x = y') ->limit(5) From 6b11aa978ca0e16f2680a8b61326356cf20eb5bd Mon Sep 17 00:00:00 2001 From: turrsis Date: Fri, 31 Jul 2015 15:55:16 +0300 Subject: [PATCH 15/30] fix 13: build empty predicate --- src/Sql/Builder/Builder.php | 10 +++++++++- .../Builder/sql92/Predicate/PredicateSetBuilder.php | 7 ++++++- .../Builder/Predicate/PredicateSetBuilderTest.php | 10 ++++++++++ test/Sql/Builder/SelectBuilderTest.php | 12 ++++++++++++ 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Sql/Builder/Builder.php b/src/Sql/Builder/Builder.php index 0076bedb9e..48ecbad48d 100644 --- a/src/Sql/Builder/Builder.php +++ b/src/Sql/Builder/Builder.php @@ -297,6 +297,10 @@ protected function build($sqlObject, Context $context) ->getPlatformBuilder($sqlObject, $context->getAdapter()) ->build($sqlObject, $context); + if ($specAndParams === false) { + return; + } + if (isset($specAndParams[$this->implodeGlueKey])) { $implodeGlue = $specAndParams[$this->implodeGlueKey]; unset($specAndParams[$this->implodeGlueKey]); @@ -343,9 +347,13 @@ protected function build($sqlObject, Context $context) private function createSqlFromSpecificationAndParameters($specification, $args, Context $context = null) { if (is_string($specification)) { + $args = $this->buildSpecificationParameter($args, $context); + if ($args === null) { + return; + } return vsprintf( $specification, - $this->buildSpecificationParameter($args, $context) + $args ); } diff --git a/src/Sql/Builder/sql92/Predicate/PredicateSetBuilder.php b/src/Sql/Builder/sql92/Predicate/PredicateSetBuilder.php index 6403f02d95..1306327b5d 100644 --- a/src/Sql/Builder/sql92/Predicate/PredicateSetBuilder.php +++ b/src/Sql/Builder/sql92/Predicate/PredicateSetBuilder.php @@ -30,6 +30,9 @@ public function build($expression, Context $context) $predicate = $predicates[$i][1]; if ($predicate instanceof PredicateSet) { + if ($predicate->count() == 0) { + continue; + } $parts[] = '('; } @@ -46,6 +49,8 @@ public function build($expression, Context $context) $parts[] = sprintf(' %s ', $predicates[$i+1][0]); } } - return $parts; + return !$parts + ? false + : $parts; } } diff --git a/test/Sql/Builder/Predicate/PredicateSetBuilderTest.php b/test/Sql/Builder/Predicate/PredicateSetBuilderTest.php index a6d69b5d14..4b23aa435e 100644 --- a/test/Sql/Builder/Predicate/PredicateSetBuilderTest.php +++ b/test/Sql/Builder/Predicate/PredicateSetBuilderTest.php @@ -28,6 +28,16 @@ public function test($sqlObject, $platform, $expected) public function dataProvider() { return $this->prepareDataProvider([ + [ + 'sqlObject' => $this->predicate_PredicateSet(), + 'expected' => [ + 'sql92' => [ + 'string' => '', + 'prepare' => '', + 'parameters' => [], + ], + ], + ], [ 'sqlObject' => $this->predicate_PredicateSet() ->addPredicate($this->predicate_IsNull('foo')) diff --git a/test/Sql/Builder/SelectBuilderTest.php b/test/Sql/Builder/SelectBuilderTest.php index cf73fab2cc..466676f91a 100644 --- a/test/Sql/Builder/SelectBuilderTest.php +++ b/test/Sql/Builder/SelectBuilderTest.php @@ -1059,6 +1059,18 @@ public function dataProvider_Where() ], ], ], + [ // empty parameters + 'sqlObject' => $this + ->select() + ->from('foo') + ->where($this->predicate_PredicateSet()), + 'expected' => [ + 'sql92' => [ + 'string' => 'SELECT "foo".* FROM "foo"', + 'prepare' => true, + ], + ], + ], ]; } } From 039d30dbe3a8035eded8dc2fef3a64aab7bd3c87 Mon Sep 17 00:00:00 2001 From: turrsis Date: Thu, 6 Aug 2015 10:19:50 +0300 Subject: [PATCH 16/30] fix 14: Sql\Insert add multiple values --- src/Sql/Builder/sql92/InsertBuilder.php | 122 +++++++++++------------- src/Sql/Insert.php | 71 ++++++-------- test/Sql/Builder/InsertBuilderTest.php | 90 +++++++++++++++++ test/Sql/InsertTest.php | 12 ++- 4 files changed, 186 insertions(+), 109 deletions(-) diff --git a/src/Sql/Builder/sql92/InsertBuilder.php b/src/Sql/Builder/sql92/InsertBuilder.php index 605eb9e5a7..820be8b6e7 100644 --- a/src/Sql/Builder/sql92/InsertBuilder.php +++ b/src/Sql/Builder/sql92/InsertBuilder.php @@ -9,35 +9,29 @@ namespace Zend\Db\Sql\Builder\sql92; -use Zend\Db\Sql\Exception; use Zend\Db\Sql\Insert; use Zend\Db\Sql\Builder\AbstractSqlBuilder; use Zend\Db\Sql\Builder\Context; +use Zend\Db\Sql\SelectableInterface; class InsertBuilder extends AbstractSqlBuilder { - /** - * @var array Specification array - */ - protected $insertSpecification = [ - 'byArgNumber' => [ - 2 => ['implode' => ', '], - 3 => ['implode' => ', '], - ], - 'format' => 'INSERT INTO %1$s (%2$s) VALUES (%3$s)', + protected $specificationTable = 'INSERT INTO %1$s'; + protected $specificationColumns = [ + 'implode' => ', ', + 'format' => '(%s)', + ]; + protected $specificationValues = [ + 'implode' => ', ', + 'format' => 'VALUES (%s)', ]; - protected $selectSpecification = [ - 'byCount' => [ - 2 => [ - 'format' => 'INSERT INTO %1$s %2$s' - ], - 3 => [ - 'byArgNumber' => [ - 2 => ['implode' => ', '], - ], - 'format' => 'INSERT INTO %1$s (%2$s) %3$s' - ], + protected $specificationValuesMultiple = [ + 'forEach' => [ + 'implode' => ', ', + 'format' => '(%s)', ], + 'implode' => ', ', + 'format' => 'VALUES %s', ]; /** @@ -49,70 +43,64 @@ public function build($sqlObject, Context $context) { $this->validateSqlObject($sqlObject, 'Zend\Db\Sql\Insert', __METHOD__); return [ - $this->build_Insert($sqlObject, $context), - $this->build_Select($sqlObject, $context), + $this->build_Table($sqlObject, $context), + $this->build_Columns($sqlObject, $context), + $this->build_Values($sqlObject, $context), ]; } - /** - * @param Insert $sqlObject - * @param Context $context - * @return null|array - * @throws Exception\InvalidArgumentException - */ - protected function build_Insert(Insert $sqlObject, Context $context) + protected function build_Table(Insert $sqlObject, Context $context) { - if ($sqlObject->select) { - return; - } + return [ + 'spec' => $this->specificationTable, + 'params' => $sqlObject->table, + ]; + } + protected function build_Columns(Insert $sqlObject, Context $context) + { if (!$sqlObject->columns) { - throw new Exception\InvalidArgumentException('values or select should be present'); - } - - $columns = []; - $values = []; - foreach (array_combine($sqlObject->columns, $sqlObject->values) as $column=>$value) { - list($columns[], $values[]) = $this->resolveColumnValue($column, $value, $context); + return; } - return [ - 'spec' => $this->insertSpecification, - 'params' => [ - $sqlObject->table, - $columns, - $values, - ], + 'spec' => $this->specificationColumns, + 'params' => array_map([$context->getPlatform(), 'quoteIdentifier'], $sqlObject->columns), ]; } - /** - * @param Insert $sqlObject - * @param Context $context - * @return null|array - */ - protected function build_Select(Insert $sqlObject, Context $context) + protected function build_Values(Insert $sqlObject, Context $context) { - if (!$sqlObject->select) { - return; + $values = $sqlObject->values; + + if ($values instanceof SelectableInterface) { + return $values; } - if ($sqlObject->columns) { + if (!is_array(reset($values))) { + $pValues = []; + if ($sqlObject->columns) { + foreach (array_combine($sqlObject->columns, $values) as $column=>$value) { + list(, $pValues[]) = $this->resolveColumnValue($column, $value, $context); + } + } else { + foreach ($values as $value) { + list(, $pValues[]) = $this->resolveColumnValue(null, $value, $context); + } + } return [ - 'spec' => $this->selectSpecification, - 'params' => [ - $sqlObject->table, - array_map([$context->getPlatform(), 'quoteIdentifier'], $sqlObject->columns), - $sqlObject->select - ], + 'spec' => $this->specificationValues, + 'params' => $pValues, ]; } + + foreach ($values as &$valueRow) { + foreach ($valueRow as &$value) { + list(, $value) = $this->resolveColumnValue(null, $value, $context); + } + } return [ - 'spec' => $this->selectSpecification, - 'params' => [ - $sqlObject->table, - $sqlObject->select - ], + 'spec' => $this->specificationValuesMultiple, + 'params' => $values, ]; } } diff --git a/src/Sql/Insert.php b/src/Sql/Insert.php index f1de4343bc..ceb50b29c9 100644 --- a/src/Sql/Insert.php +++ b/src/Sql/Insert.php @@ -12,7 +12,7 @@ /** * @property TableSource $table * @property array $columns - * @property null|Select $select + * @property array|SelectableInterface $values */ class Insert extends AbstractSqlObject implements PreparableSqlObjectInterface { @@ -24,16 +24,12 @@ class Insert extends AbstractSqlObject implements PreparableSqlObjectInterface */ protected $table = null; protected $columns = []; - - /** - * @var array|Select - */ - protected $select = null; + protected $values = []; protected $__getProperties = [ 'table', 'columns', - 'select', + 'values', ]; /** @@ -67,7 +63,7 @@ public function into($table) */ public function columns(array $columns) { - $this->columns = array_flip($columns); + $this->columns = $columns; return $this; } @@ -87,7 +83,7 @@ public function values($values, $flag = self::VALUES_SET) 'A Zend\Db\Sql\SelectableInterface instance cannot be provided with the merge flag' ); } - $this->select = $values; + $this->values = $values; return $this; } @@ -96,36 +92,42 @@ public function values($values, $flag = self::VALUES_SET) 'values() expects an array of values or Zend\Db\Sql\SelectableInterface instance' ); } - - if ($this->select && $flag == self::VALUES_MERGE) { + if ($this->values instanceof SelectableInterface && $flag == self::VALUES_MERGE) { throw new Exception\InvalidArgumentException( 'An array of values cannot be provided with the merge flag when a Zend\Db\Sql\SelectableInterface instance already exists as the value source' ); } + $columns = null; + if (!is_numeric(key($values))) { + $columns = array_keys($values); + $values = array_values($values); + } + if ($flag == self::VALUES_SET) { - $this->columns = $this->isAssocativeArray($values) - ? $values - : array_combine(array_keys($this->columns), array_values($values)); - } else { - foreach ($values as $column => $value) { - $this->columns[$column] = $value; + $this->values = $values; + if ($columns) { + $this->columns = $columns; } + return $this; } - return $this; - } + if (!$columns) { + $this->values = array_merge($this->values, $values); + return $this; + } - /** - * Simple test for an associative array - * - * @link http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential - * @param array $array - * @return bool - */ - private function isAssocativeArray(array $array) - { - return array_keys($array) !== range(0, count($array) - 1); + foreach ($columns as $i=>$column) { + if (($k = array_search($column, $this->columns)) !== false) { + $this->values[$k] = $values[$i]; + unset($values[$i], $columns[$i]); + } else { + $this->values[] = $values[$i]; + $this->columns[] = $column; + } + } + + return $this; } /** @@ -139,17 +141,6 @@ public function select(SelectableInterface $select) return $this->values($select); } - public function __get($name) - { - if ($name == 'columns') { - return array_keys($this->columns); - } - if ($name == 'values') { - return array_values($this->columns); - } - return parent::__get($name); - } - public function __clone() { $this->table = clone $this->table; diff --git a/test/Sql/Builder/InsertBuilderTest.php b/test/Sql/Builder/InsertBuilderTest.php index 683dbe792d..6a73360fb0 100644 --- a/test/Sql/Builder/InsertBuilderTest.php +++ b/test/Sql/Builder/InsertBuilderTest.php @@ -50,6 +50,12 @@ public function dataProvider_Into() 'sql92' => 'INSERT INTO "foo" ("c1") VALUES (\'v1\')', ], ], + 'into_array' => [ + 'sqlObject' => $this->insert()->into(['schema', 'foo'])->values(['c1' => 'v1']), + 'expected' => [ + 'sql92' => 'INSERT INTO "schema"."foo" ("c1") VALUES (\'v1\')', + ], + ], ]; } @@ -86,6 +92,29 @@ public function dataProvider_ColumnsAndValues() ], ], ], + 'row_with_columns' => [ + 'sqlObject' => $this->insert('foo') + ->columns(['c1']) + ->values(['v1']), + 'expected' => [ + 'sql92' => [ + 'string' => 'INSERT INTO "foo" ("c1") VALUES (\'v1\')', + 'prepare' => 'INSERT INTO "foo" ("c1") VALUES (?)', + 'parameters' => ['c1' => 'v1'], + ], + ], + ], + 'row_without_columns' => [ + 'sqlObject' => $this->insert('foo') + ->values(['v1']), + 'expected' => [ + 'sql92' => [ + 'string' => 'INSERT INTO "foo" VALUES (\'v1\')', + 'prepare' => 'INSERT INTO "foo" VALUES (\'v1\')', + 'parameters' => [], + ], + ], + ], 'select_with_columns' => [ 'sqlObject' => $this->insert('foo') ->columns(['col1', 'col2']) @@ -149,6 +178,67 @@ public function dataProvider_ColumnsAndValues() 'SqlServer' => 'INSERT INTO [foo] ((SELECT [bar].* FROM [bar]))', ], ], + 'multiple_row_with_columns' => [ + 'sqlObject' => $this->insert() + ->into('foo') + ->columns(['c1', 'c2']) + ->values([ + ['1_v1', '1_v2'], + ['2_v1', '2_v2'], + ]), + 'expected' => [ + 'sql92' => [ + 'string' => 'INSERT INTO "foo" ("c1", "c2") VALUES (\'1_v1\', \'1_v2\'), (\'2_v1\', \'2_v2\')', + 'prepare' => 'INSERT INTO "foo" ("c1", "c2") VALUES (\'1_v1\', \'1_v2\'), (\'2_v1\', \'2_v2\')', + 'parameters' => [], + ], + ], + ], + 'multiple_row_without_columns' => [ + 'sqlObject' => $this->insert() + ->into('foo') + ->values([ + ['1_v1', '1_v2'], + ['2_v1', '2_v2'], + ]), + 'expected' => [ + 'sql92' => [ + 'string' => 'INSERT INTO "foo" VALUES (\'1_v1\', \'1_v2\'), (\'2_v1\', \'2_v2\')', + 'prepare' => 'INSERT INTO "foo" VALUES (\'1_v1\', \'1_v2\'), (\'2_v1\', \'2_v2\')', + 'parameters' => [], + ], + ], + ], + 'multiple_row_with_different_values_types' => [ + 'sqlObject' => $this->insert()->into('foo') + ->values([ + [ + 'v1', + 'v2', + 'v3', + 'v4', + ], + [ + 'bar', + null, + new Expression('NOW()'), + $this->select('baz'), + ], + [ + 'v5', + 'v6', + 'v7', + 'v8', + ], + ]), + 'expected' => [ + 'sql92' => [ + 'string' => 'INSERT INTO "foo" VALUES (\'v1\', \'v2\', \'v3\', \'v4\'), (\'bar\', NULL, NOW(), (SELECT "baz".* FROM "baz")), (\'v5\', \'v6\', \'v7\', \'v8\')', + 'string' => 'INSERT INTO "foo" VALUES (\'v1\', \'v2\', \'v3\', \'v4\'), (\'bar\', NULL, NOW(), (SELECT "baz".* FROM "baz")), (\'v5\', \'v6\', \'v7\', \'v8\')', + 'parameters' => [], + ], + ], + ], ]; } } diff --git a/test/Sql/InsertTest.php b/test/Sql/InsertTest.php index dca17e9436..c7cf7a9410 100644 --- a/test/Sql/InsertTest.php +++ b/test/Sql/InsertTest.php @@ -47,8 +47,9 @@ public function testInto() */ public function testColumns() { - $this->insert->columns(['foo', 'bar']); - $this->assertEquals(['foo', 'bar'], $this->insert->columns); + $columns = ['foo', 'bar']; + $this->insert->columns($columns); + $this->assertEquals($columns, $this->insert->columns); } /** @@ -69,6 +70,13 @@ public function testValues() $this->insert->values(['foo' => 'bax']); $this->assertEquals(['foo'], $this->insert->columns); $this->assertEquals(['bax'], $this->insert->values); + + $this->insert->columns(['c1', 'c2', 'c3']) + ->values(['bar']) + ->values(['bam'], Insert::VALUES_MERGE) + ->values(['c3' => 'baz'], Insert::VALUES_MERGE); + $this->assertEquals(['c1', 'c2', 'c3'], $this->insert->columns); + $this->assertEquals(['bar', 'bam', 'baz'], $this->insert->values); } /** From 6ce22b5234bf9aa5f72298bda84274659596ed39 Mon Sep 17 00:00:00 2001 From: turrsis Date: Thu, 6 Aug 2015 14:34:45 +0300 Subject: [PATCH 17/30] fix 15: DropTable add 'IF EXISTS' --- src/Sql/Builder/Builder.php | 1 + .../SqlServer/Ddl/DropTableBuilder.php | 48 +++++++++++++++++++ .../Builder/sql92/Ddl/DropTableBuilder.php | 5 +- src/Sql/Ddl/DropTable.php | 10 ++++ test/Sql/Builder/Ddl/DropTableBuilderTest.php | 7 +++ 5 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 src/Sql/Builder/SqlServer/Ddl/DropTableBuilder.php diff --git a/src/Sql/Builder/Builder.php b/src/Sql/Builder/Builder.php index 48ecbad48d..e87700698e 100644 --- a/src/Sql/Builder/Builder.php +++ b/src/Sql/Builder/Builder.php @@ -60,6 +60,7 @@ class Builder extends AbstractBuilder ], 'Zend\Db\Sql\Ddl\DropTable' => [ 'sql92' => 'Zend\Db\Sql\Builder\sql92\Ddl\DropTableBuilder', + 'sqlserver' => 'Zend\Db\Sql\Builder\SqlServer\Ddl\DropTableBuilder', ], 'Zend\Db\Sql\Predicate\NotBetween' => [ diff --git a/src/Sql/Builder/SqlServer/Ddl/DropTableBuilder.php b/src/Sql/Builder/SqlServer/Ddl/DropTableBuilder.php new file mode 100644 index 0000000000..d959f2f3af --- /dev/null +++ b/src/Sql/Builder/SqlServer/Ddl/DropTableBuilder.php @@ -0,0 +1,48 @@ +ifExists) { + $tableString = + $sqlObject->table->getSchema() + ? $sqlObject->table->getSchema() . $context->getPlatform()->getIdentifierSeparator() + : '' + . $sqlObject->table->getTable(); + + return [ + 'spec' => $this->ifExistsSpecification, + 'params' => [ + $tableString, + $sqlObject->table, + ], + ]; + } else { + return [ + 'spec' => $this->tableSpecification, + 'params' => $sqlObject->table, + ]; + } + } +} diff --git a/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php b/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php index c8a025f7dc..df2759fe5e 100644 --- a/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php +++ b/src/Sql/Builder/sql92/Ddl/DropTableBuilder.php @@ -15,7 +15,9 @@ class DropTableBuilder extends AbstractSqlBuilder { - protected $tableSpecification = 'DROP TABLE %1$s'; + protected $tableSpecification = 'DROP TABLE %1$s%2$s'; + + protected $ifExistsSpecification = 'IF EXISTS '; /** * @param DropTable $sqlObject @@ -40,6 +42,7 @@ protected function build_Table(DropTable $sqlObject, Context $context) return [ 'spec' => $this->tableSpecification, 'params' => [ + $sqlObject->ifExists ? $this->ifExistsSpecification : '', $sqlObject->table, ], ]; diff --git a/src/Sql/Ddl/DropTable.php b/src/Sql/Ddl/DropTable.php index 29610329fa..a008695185 100644 --- a/src/Sql/Ddl/DropTable.php +++ b/src/Sql/Ddl/DropTable.php @@ -14,6 +14,7 @@ /** * @property TableIdentifier $table + * @property bool $ifExists */ class DropTable extends AbstractSqlObject { @@ -22,8 +23,11 @@ class DropTable extends AbstractSqlObject */ protected $table; + protected $ifExists = false; + protected $__getProperties = [ 'table', + 'ifExists', ]; /** @@ -34,4 +38,10 @@ public function __construct($table = null) parent::__construct(); $this->table = TableIdentifier::factory($table); } + + public function ifExists($ifExists = false) + { + $this->ifExists = (bool)$ifExists; + return $this; + } } diff --git a/test/Sql/Builder/Ddl/DropTableBuilderTest.php b/test/Sql/Builder/Ddl/DropTableBuilderTest.php index 05565803a7..9812f53990 100644 --- a/test/Sql/Builder/Ddl/DropTableBuilderTest.php +++ b/test/Sql/Builder/Ddl/DropTableBuilderTest.php @@ -34,6 +34,13 @@ public function dataProvider() 'sql92' => 'DROP TABLE "foo"', ], ], + [ + 'sqlObject' => $this->dropTable('foo')->ifExists(true), + 'expected' => [ + 'sql92' => 'DROP TABLE IF EXISTS "foo"', + 'sqlserver' => 'IF OBJECT_ID(\'foo\', \'U\') IS NOT NULL DROP TABLE [foo];', + ], + ], ]); } } From c9590a8cf8bb41d545bc4db1325c64a7172f5230 Mon Sep 17 00:00:00 2001 From: turrsis Date: Mon, 10 Aug 2015 15:04:52 +0300 Subject: [PATCH 18/30] fix 16: Sql\Ddl\Column\Boolean can be nullable --- src/Sql/Ddl/Column/Boolean.php | 2 +- test/Sql/Ddl/Column/BooleanTest.php | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Sql/Ddl/Column/Boolean.php b/src/Sql/Ddl/Column/Boolean.php index 6c650e948e..79b98c44d2 100644 --- a/src/Sql/Ddl/Column/Boolean.php +++ b/src/Sql/Ddl/Column/Boolean.php @@ -26,6 +26,6 @@ class Boolean extends Column */ public function setNullable($nullable) { - return parent::setNullable(false); + return parent::setNullable($nullable); } } diff --git a/test/Sql/Ddl/Column/BooleanTest.php b/test/Sql/Ddl/Column/BooleanTest.php index 4288f98937..479104bf5f 100644 --- a/test/Sql/Ddl/Column/BooleanTest.php +++ b/test/Sql/Ddl/Column/BooleanTest.php @@ -18,14 +18,18 @@ class BooleanTest extends \PHPUnit_Framework_TestCase * * @group 6257 */ - public function testIsAlwaysNotNullable() + public function testSetNullable() { $column = new Boolean('foo', true); + $this->assertTrue($column->isNullable()); + $column = new Boolean('foo', false); $this->assertFalse($column->isNullable()); $column->setNullable(true); + $this->assertTrue($column->isNullable()); + $column->setNullable(false); $this->assertFalse($column->isNullable()); } } From 35338425b4003f66d261d5005da9a186b70a986c Mon Sep 17 00:00:00 2001 From: turrsis Date: Mon, 10 Aug 2015 15:44:39 +0300 Subject: [PATCH 19/30] fix 17: add Ddl\Sql object --- src/Sql/AbstractSql.php | 110 ++++++++++++++++++++++++++++++++++ src/Sql/Ddl/Sql.php | 49 +++++++++++++++ src/Sql/Sql.php | 125 ++++++--------------------------------- test/Sql/Ddl/SqlTest.php | 77 ++++++++++++++++++++++++ test/Sql/SqlTest.php | 17 ++++-- 5 files changed, 265 insertions(+), 113 deletions(-) create mode 100644 src/Sql/AbstractSql.php create mode 100644 src/Sql/Ddl/Sql.php create mode 100644 test/Sql/Ddl/SqlTest.php diff --git a/src/Sql/AbstractSql.php b/src/Sql/AbstractSql.php new file mode 100644 index 0000000000..06e4cbd211 --- /dev/null +++ b/src/Sql/AbstractSql.php @@ -0,0 +1,110 @@ +adapter = $adapter; + if ($table) { + $this->setTable($table); + } + $this->builder = $builder ?: new Builder\Builder($adapter); + } + + /** + * @return null|\Zend\Db\Adapter\AdapterInterface + */ + public function getAdapter() + { + return $this->adapter; + } + + /** + * @return bool + */ + public function hasTable() + { + return ($this->table !== null); + } + + /** + * @param null|string|array|TableIdentifier $table + * @return self + * @throws Exception\InvalidArgumentException + */ + public function setTable($table) + { + if (!$table) { + throw new Exception\InvalidArgumentException('Table must be a string, array or instance of TableIdentifier.'); + } + $this->table = TableIdentifier::factory($table); + return $this; + } + + /** + * @return TableIdentifier + */ + public function getTable() + { + return $this->table; + } + + /** + * @return Builder\Builder + */ + public function getBuilder() + { + return $this->builder; + } + + protected function validateTable($table = null) + { + if ($this->table !== null && $table !== null) { + throw new Exception\InvalidArgumentException(sprintf( + 'This Sql object is intended to work with only the table "%s" provided at construction time.', + $this->table->getTable() + )); + } + } + + /** + * @param SqlObjectInterface $sqlObject + * @param null|AdapterInterface $adapter + * + * @return string + * + * @throws Exception\InvalidArgumentException + */ + public function buildSqlString(SqlObjectInterface $sqlObject, AdapterInterface $adapter = null) + { + return $this->builder->buildSqlString( + $sqlObject, + $adapter ?: $this->adapter + ); + } +} diff --git a/src/Sql/Ddl/Sql.php b/src/Sql/Ddl/Sql.php new file mode 100644 index 0000000000..d220289d17 --- /dev/null +++ b/src/Sql/Ddl/Sql.php @@ -0,0 +1,49 @@ +validateTable($table); + return new AlterTable($table ?: $this->table); + } + + /** + * @param null|string|array|BaseSql\TableIdentifier $table + * @return CreateTable + * @throws Exception\InvalidArgumentException + */ + public function createTable($table = null) + { + $this->validateTable($table); + return new CreateTable($table ?: $this->table); + } + + /** + * @param null|string|array|BaseSql\TableIdentifier $table + * @return DropTable + * @throws Exception\InvalidArgumentException + */ + public function dropTable($table = null) + { + $this->validateTable($table); + return new DropTable($table ?: $this->table); + } +} diff --git a/src/Sql/Sql.php b/src/Sql/Sql.php index 573e03a1cf..395a72f1a3 100644 --- a/src/Sql/Sql.php +++ b/src/Sql/Sql.php @@ -12,76 +12,12 @@ use Zend\Db\Adapter\AdapterInterface; use Zend\Db\Adapter\Driver\StatementInterface; -class Sql +class Sql extends AbstractSql { - /** @var AdapterInterface */ - protected $adapter = null; - - /** @var TableIdentifier */ - protected $table = null; - - /** @var Builder\Builder */ - protected $builder = null; - - /** - * @param null|AdapterInterface $adapter - * @param null|string|array|TableIdentifier $table - * @param null|Builder\Builder $platformBuilder - */ - public function __construct(AdapterInterface $adapter = null, $table = null, Builder\Builder $builder = null) - { - $this->adapter = $adapter; - if ($table) { - $this->setTable($table); - } - $this->builder = $builder ?: new Builder\Builder($adapter); - } - - /** - * @return null|\Zend\Db\Adapter\AdapterInterface - */ - public function getAdapter() - { - return $this->adapter; - } - - /** - * @return bool - */ - public function hasTable() - { - return ($this->table !== null); - } - - /** - * @param null|string|array|TableIdentifier $table - * @return self - * @throws Exception\InvalidArgumentException - */ - public function setTable($table) - { - if (!$table) { - throw new Exception\InvalidArgumentException('Table must be a string, array or instance of TableIdentifier.'); - } - $this->table = TableIdentifier::factory($table); - return $this; - } - /** - * @return TableIdentifier + * @var Ddl\Sql */ - public function getTable() - { - return $this->table; - } - - /** - * @return Builder\Builder - */ - public function getBuilder() - { - return $this->builder; - } + protected $ddl; /** * @param null|string|array|TableIdentifier $table @@ -90,12 +26,7 @@ public function getBuilder() */ public function select($table = null) { - if ($this->table !== null && $table !== null) { - throw new Exception\InvalidArgumentException(sprintf( - 'This Sql object is intended to work with only the table "%s" provided at construction time.', - $this->table->getTable() - )); - } + $this->validateTable($table); return new Select(($table) ?: $this->table); } @@ -106,12 +37,7 @@ public function select($table = null) */ public function insert($table = null) { - if ($this->table !== null && $table !== null) { - throw new Exception\InvalidArgumentException(sprintf( - 'This Sql object is intended to work with only the table "%s" provided at construction time.', - $this->table->getTable() - )); - } + $this->validateTable($table); return new Insert(($table) ?: $this->table); } @@ -122,12 +48,7 @@ public function insert($table = null) */ public function update($table = null) { - if ($this->table !== null && $table !== null) { - throw new Exception\InvalidArgumentException(sprintf( - 'This Sql object is intended to work with only the table "%s" provided at construction time.', - $this->table->getTable() - )); - } + $this->validateTable($table); return new Update(($table) ?: $this->table); } @@ -138,40 +59,30 @@ public function update($table = null) */ public function delete($table = null) { - if ($this->table !== null && $table !== null) { - throw new Exception\InvalidArgumentException(sprintf( - 'This Sql object is intended to work with only the table "%s" provided at construction time.', - $this->table->getTable() - )); - } + $this->validateTable($table); return new Delete(($table) ?: $this->table); } /** - * @param PreparableSqlObjectInterface $sqlObject - * @param null|AdapterInterface $adapter - * - * @return StatementInterface + * @return Ddl\Sql */ - public function prepareSqlStatement(PreparableSqlObjectInterface $sqlObject, AdapterInterface $adapter = null) + public function getDdl() { - return $this->builder->prepareSqlStatement( - $sqlObject, - $adapter ?: $this->adapter - ); + if (!$this->ddl) { + $this->ddl = new Ddl\Sql($this->adapter, $this->table, $this->builder); + } + return $this->ddl; } /** - * @param SqlObjectInterface $sqlObject - * @param null|AdapterInterface $adapter - * - * @return string + * @param PreparableSqlObjectInterface $sqlObject + * @param null|AdapterInterface $adapter * - * @throws Exception\InvalidArgumentException + * @return StatementInterface */ - public function buildSqlString(SqlObjectInterface $sqlObject, AdapterInterface $adapter = null) + public function prepareSqlStatement(PreparableSqlObjectInterface $sqlObject, AdapterInterface $adapter = null) { - return $this->builder->buildSqlString( + return $this->builder->prepareSqlStatement( $sqlObject, $adapter ?: $this->adapter ); diff --git a/test/Sql/Ddl/SqlTest.php b/test/Sql/Ddl/SqlTest.php new file mode 100644 index 0000000000..fa53ec00ec --- /dev/null +++ b/test/Sql/Ddl/SqlTest.php @@ -0,0 +1,77 @@ +getMock('Zend\Db\Adapter\Driver\DriverInterface'); + $this->mockAdapter = $this->getMock('Zend\Db\Adapter\Adapter', null, [$mockDriver, new TestAsset\TrustingSql92Platform()]); + + $this->sql = new Sql\Ddl\Sql($this->mockAdapter, 'foo'); + } + + /** + * @covers Zend\Db\Sql\Ddl\Sql::alterTable + */ + public function testAlterTable() + { + $alterTable = $this->sql->alterTable(); + + $this->assertInstanceOf('Zend\Db\Sql\Ddl\AlterTable', $alterTable); + $this->assertSame('foo', $alterTable->table->getTable()); + + $this->setExpectedException('Zend\Db\Sql\Exception\InvalidArgumentException', + 'This Sql object is intended to work with only the table "foo" provided at construction time.'); + $this->sql->alterTable('bar'); + } + + /** + * @covers Zend\Db\Sql\Ddl\Sql::createTable + */ + public function testCreateTable() + { + $createTable = $this->sql->createTable(); + + $this->assertInstanceOf('Zend\Db\Sql\Ddl\CreateTable', $createTable); + $this->assertSame('foo', $createTable->table->getTable()); + + $this->setExpectedException('Zend\Db\Sql\Exception\InvalidArgumentException', + 'This Sql object is intended to work with only the table "foo" provided at construction time.'); + $this->sql->createTable('bar'); + } + + /** + * @covers Zend\Db\Sql\Ddl\Sql::dropTable + */ + public function testDropTable() + { + $dropTable = $this->sql->dropTable(); + + $this->assertInstanceOf('Zend\Db\Sql\Ddl\DropTable', $dropTable); + $this->assertSame('foo', $dropTable->table->getTable()); + + $this->setExpectedException('Zend\Db\Sql\Exception\InvalidArgumentException', + 'This Sql object is intended to work with only the table "foo" provided at construction time.'); + $this->sql->dropTable('bar'); + } +} diff --git a/test/Sql/SqlTest.php b/test/Sql/SqlTest.php index 086fcf6669..b4b2374a82 100644 --- a/test/Sql/SqlTest.php +++ b/test/Sql/SqlTest.php @@ -11,7 +11,6 @@ use Zend\Db\Sql\Sql; use ZendTest\Db\TestAsset; -use Zend\Db\Adapter\Adapter; use Zend\Db\Sql\TableIdentifier; class SqlTest extends \PHPUnit_Framework_TestCase @@ -27,14 +26,9 @@ class SqlTest extends \PHPUnit_Framework_TestCase public function setup() { // mock the adapter, driver, and parts - $mockResult = $this->getMock('Zend\Db\Adapter\Driver\ResultInterface'); $mockStatement = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); - $mockStatement->expects($this->any())->method('execute')->will($this->returnValue($mockResult)); - $mockConnection = $this->getMock('Zend\Db\Adapter\Driver\ConnectionInterface'); $mockDriver = $this->getMock('Zend\Db\Adapter\Driver\DriverInterface'); $mockDriver->expects($this->any())->method('createStatement')->will($this->returnValue($mockStatement)); - $mockDriver->expects($this->any())->method('getConnection')->will($this->returnValue($mockConnection)); - $mockDriver->expects($this->any())->method('formatParameterName')->will($this->returnValue('?')); // setup mock adapter $this->mockAdapter = $this->getMock('Zend\Db\Adapter\Adapter', null, [$mockDriver, new TestAsset\TrustingSql92Platform()]); @@ -132,6 +126,17 @@ public function testDelete() $this->sql->delete('bar'); } + /** + * @covers Zend\Db\Sql\Sql::getDdl + */ + public function testGetDdl() + { + $ddl = $this->sql->getDdl(); + $this->assertSame($this->sql->getTable(), $ddl->getTable()); + $this->assertSame($this->sql->getAdapter(), $ddl->getAdapter()); + $this->assertSame($this->sql->getBuilder(), $ddl->getBuilder()); + } + /** * @covers Zend\Db\Sql\Sql::prepareSqlStatement */ From 95207259d1f0c1085ba9ebf0311cb6344b0659f8 Mon Sep 17 00:00:00 2001 From: Turrsis Date: Thu, 21 Apr 2016 18:32:38 +0300 Subject: [PATCH 20/30] fix 18: rename joins --- src/Sql/{Join.php => Joins.php} | 6 ++-- src/Sql/Select.php | 14 +++----- src/Sql/Update.php | 6 ++-- src/TableGateway/AbstractTableGateway.php | 4 +-- test/Sql/Builder/SelectBuilderTest.php | 3 +- test/Sql/Builder/UpdateBuilderTest.php | 4 +-- test/Sql/{JoinTest.php => JoinsTest.php} | 36 +++++++++---------- test/Sql/SelectTest.php | 7 ++-- test/Sql/UpdateTest.php | 6 ++-- .../TableGateway/AbstractTableGatewayTest.php | 2 +- 10 files changed, 42 insertions(+), 46 deletions(-) rename src/Sql/{Join.php => Joins.php} (96%) rename test/Sql/{JoinTest.php => JoinsTest.php} (53%) diff --git a/src/Sql/Join.php b/src/Sql/Joins.php similarity index 96% rename from src/Sql/Join.php rename to src/Sql/Joins.php index 60bf3a4920..141729e9e7 100644 --- a/src/Sql/Join.php +++ b/src/Sql/Joins.php @@ -22,7 +22,7 @@ * - type: the type of JOIN being performed; see the `JOIN_*` constants; * defaults to `JOIN_INNER` */ -class Join implements Iterator, Countable +class Joins implements Iterator, Countable { const JOIN_INNER = 'inner'; const JOIN_OUTER = 'outer'; @@ -118,7 +118,7 @@ public function getJoins() * @return self Implements a fluent interface. * @throws Exception\InvalidArgumentException for invalid $name values. */ - public function join($name, $on, $columns = [Select::SQL_STAR], $type = Join::JOIN_INNER) + public function join($name, $on, $columns = [Select::SQL_STAR], $type = Joins::JOIN_INNER) { if (!is_array($columns)) { $columns = [$columns]; @@ -127,7 +127,7 @@ public function join($name, $on, $columns = [Select::SQL_STAR], $type = Join::JO 'name' => TableSource::factory($name), 'on' => $on, 'columns' => $columns, - 'type' => $type ? $type : Join::JOIN_INNER + 'type' => $type ? $type : Joins::JOIN_INNER ]; return $this; } diff --git a/src/Sql/Select.php b/src/Sql/Select.php index 17fa669807..1c39c16447 100644 --- a/src/Sql/Select.php +++ b/src/Sql/Select.php @@ -28,12 +28,6 @@ class Select extends AbstractSqlObject implements PreparableSqlObjectInterface, { const QUANTIFIER_DISTINCT = 'DISTINCT'; const QUANTIFIER_ALL = 'ALL'; - const JOIN_INNER = Join::JOIN_INNER; - const JOIN_OUTER = Join::JOIN_OUTER; - const JOIN_LEFT = Join::JOIN_LEFT; - const JOIN_RIGHT = Join::JOIN_RIGHT; - const JOIN_RIGHT_OUTER = Join::JOIN_RIGHT_OUTER; - const JOIN_LEFT_OUTER = Join::JOIN_LEFT_OUTER; const SQL_STAR = '*'; const ORDER_ASCENDING = 'ASC'; const ORDER_DESCENDING = 'DESC'; @@ -67,7 +61,7 @@ class Select extends AbstractSqlObject implements PreparableSqlObjectInterface, protected $columns = [self::SQL_STAR]; /** - * @var null|Join + * @var null|Joins */ protected $joins = null; @@ -130,7 +124,7 @@ public function __construct($table = null) parent::__construct(); $this->from($table); $this->where = new Where; - $this->joins = new Join; + $this->joins = new Joins; $this->having = new Having; } @@ -194,7 +188,7 @@ public function columns(array $columns) * @param string $type one of the JOIN_* constants * @return self */ - public function join($name, $on, $columns = self::SQL_STAR, $type = self::JOIN_INNER) + public function join($name, $on, $columns = self::SQL_STAR, $type = Joins::JOIN_INNER) { $this->joins->join($name, $on, $columns, $type); @@ -358,7 +352,7 @@ public function __unset($name) $this->columns = [self::SQL_STAR]; break; case 'joins': - $this->joins = new Join; + $this->joins = new Joins; break; case 'where': $this->where = new Where; diff --git a/src/Sql/Update.php b/src/Sql/Update.php index 4374b8b488..6e984f4e02 100644 --- a/src/Sql/Update.php +++ b/src/Sql/Update.php @@ -44,7 +44,7 @@ class Update extends AbstractSqlObject implements PreparableSqlObjectInterface ]; /** - * @var null|Join + * @var null|Joins */ protected $joins = null; @@ -58,7 +58,7 @@ public function __construct($table = null) parent::__construct(); $this->table($table); $this->where = new Where(); - $this->joins = new Join(); + $this->joins = new Joins(); $this->set = new PriorityList(); $this->set->isLIFO(false); } @@ -129,7 +129,7 @@ public function where($predicate, $combination = Predicate\PredicateSet::OP_AND) * @throws Exception\InvalidArgumentException * @return Update */ - public function join($name, $on, $type = Join::JOIN_INNER) + public function join($name, $on, $type = Joins::JOIN_INNER) { $this->joins->join($name, $on, [], $type); diff --git a/src/TableGateway/AbstractTableGateway.php b/src/TableGateway/AbstractTableGateway.php index 6966d359ed..6e84c2570c 100644 --- a/src/TableGateway/AbstractTableGateway.php +++ b/src/TableGateway/AbstractTableGateway.php @@ -14,7 +14,7 @@ use Zend\Db\ResultSet\ResultSetInterface; use Zend\Db\Sql\Delete; use Zend\Db\Sql\Insert; -use Zend\Db\Sql\Join; +use Zend\Db\Sql\Joins; use Zend\Db\Sql\Select; use Zend\Db\Sql\Sql; use Zend\Db\Sql\TableSource; @@ -336,7 +336,7 @@ public function update($set, $where = null, array $joins = null) if ($joins) { foreach ($joins as $join) { - $type = isset($join['type']) ? $join['type'] : Join::JOIN_INNER; + $type = isset($join['type']) ? $join['type'] : Joins::JOIN_INNER; $update->join($join['name'], $join['on'], $type); } } diff --git a/test/Sql/Builder/SelectBuilderTest.php b/test/Sql/Builder/SelectBuilderTest.php index 466676f91a..4df0644de7 100644 --- a/test/Sql/Builder/SelectBuilderTest.php +++ b/test/Sql/Builder/SelectBuilderTest.php @@ -13,6 +13,7 @@ use Zend\Db\Sql\Expression; use Zend\Db\Sql\Predicate; use Zend\Db\Sql\TableIdentifier; +use Zend\Db\Sql\Joins; /** * @covers Zend\Db\Sql\Builder\IbmDb2\SelectBuilder @@ -279,7 +280,7 @@ public function dataProvider_Join() ], ], [ // join with alternate type - 'sqlObject' => $this->select()->from('foo')->join('zac', 'm = n', ['bar', 'baz'], Select::JOIN_OUTER), + 'sqlObject' => $this->select()->from('foo')->join('zac', 'm = n', ['bar', 'baz'], Joins::JOIN_OUTER), 'expected' => [ 'sql92' => [ 'string' => 'SELECT "foo".*, "zac"."bar" AS "bar", "zac"."baz" AS "baz" FROM "foo" OUTER JOIN "zac" ON "m" = "n"', diff --git a/test/Sql/Builder/UpdateBuilderTest.php b/test/Sql/Builder/UpdateBuilderTest.php index 0f7da2acb3..7ac9938424 100644 --- a/test/Sql/Builder/UpdateBuilderTest.php +++ b/test/Sql/Builder/UpdateBuilderTest.php @@ -11,7 +11,7 @@ use Zend\Db\Sql\Expression; use Zend\Db\Sql\TableIdentifier; -use Zend\Db\Sql\Join; +use Zend\Db\Sql\Joins; /** * @covers Zend\Db\Sql\Builder\sql92\UpdateBuilder @@ -202,7 +202,7 @@ public function dataProvider_Joins() ->join( 'Category', 'Category.CategoryId = Document.CategoryId', - Join::JOIN_LEFT // (optional), one of inner, outer, left, right + Joins::JOIN_LEFT // (optional), one of inner, outer, left, right ), 'expected' => [ 'sql92' => [ diff --git a/test/Sql/JoinTest.php b/test/Sql/JoinsTest.php similarity index 53% rename from test/Sql/JoinTest.php rename to test/Sql/JoinsTest.php index 160120757e..3df7616c30 100644 --- a/test/Sql/JoinTest.php +++ b/test/Sql/JoinsTest.php @@ -8,31 +8,31 @@ namespace ZendTest\Db\Sql; use PHPUnit_Framework_TestCase as TestCase; -use Zend\Db\Sql\Join; +use Zend\Db\Sql\Joins; -class JoinTest extends TestCase +class JoinsTest extends TestCase { /** - * @testdox unit test: Test join() returns Join object (is chainable) - * @covers Zend\Db\Sql\Join::join + * @testdox unit test: Test join() returns Joins object (is chainable) + * @covers Zend\Db\Sql\Joins::join */ - public function testJoin() + public function testJoins() { - $join = new Join; - $return = $join->join('baz', 'foo.fooId = baz.fooId', Join::JOIN_LEFT); + $join = new Joins; + $return = $join->join('baz', 'foo.fooId = baz.fooId', Joins::JOIN_LEFT); $this->assertSame($join, $return); } /** * @testdox unit test: Test count() returns correct count - * @covers Zend\Db\Sql\Join::count - * @covers Zend\Db\Sql\Join::join + * @covers Zend\Db\Sql\Joins::count + * @covers Zend\Db\Sql\Joins::join */ public function testCount() { - $join = new Join; - $join->join('baz', 'foo.fooId = baz.fooId', Join::JOIN_LEFT); - $join->join('bar', 'foo.fooId = bar.fooId', Join::JOIN_LEFT); + $join = new Joins; + $join->join('baz', 'foo.fooId = baz.fooId', Joins::JOIN_LEFT); + $join->join('bar', 'foo.fooId = bar.fooId', Joins::JOIN_LEFT); $this->assertEquals(2, $join->count()); $this->assertEquals(count($join->getJoins()), $join->count()); @@ -40,15 +40,15 @@ public function testCount() /** * @testdox unit test: Test reset() resets the joins - * @covers Zend\Db\Sql\Join::count - * @covers Zend\Db\Sql\Join::join - * @covers Zend\Db\Sql\Join::reset + * @covers Zend\Db\Sql\Joins::count + * @covers Zend\Db\Sql\Joins::join + * @covers Zend\Db\Sql\Joins::reset */ public function testReset() { - $join = new Join; - $join->join('baz', 'foo.fooId = baz.fooId', Join::JOIN_LEFT); - $join->join('bar', 'foo.fooId = bar.fooId', Join::JOIN_LEFT); + $join = new Joins; + $join->join('baz', 'foo.fooId = baz.fooId', Joins::JOIN_LEFT); + $join->join('bar', 'foo.fooId = bar.fooId', Joins::JOIN_LEFT); $join->reset(); $this->assertEquals(0, $join->count()); diff --git a/test/Sql/SelectTest.php b/test/Sql/SelectTest.php index f97c641cb0..25f87b1053 100644 --- a/test/Sql/SelectTest.php +++ b/test/Sql/SelectTest.php @@ -15,6 +15,7 @@ use Zend\Db\Sql\Predicate; use Zend\Db\Sql\TableIdentifier; use Zend\Db\Sql\TableSource; +use Zend\Db\Sql\Joins; class SelectTest extends \PHPUnit_Framework_TestCase { @@ -33,7 +34,7 @@ public function testMethodsReturnSelf() $this->assertSame($select, $select->from('foo', 'bar')); $this->assertSame($select, $select->quantifier($select::QUANTIFIER_DISTINCT)); $this->assertSame($select, $select->columns(['foo', 'bar'])); - $this->assertSame($select, $select->join('foo', 'x = y', Select::SQL_STAR, Select::JOIN_INNER)); + $this->assertSame($select, $select->join('foo', 'x = y', Select::SQL_STAR, Joins::JOIN_INNER)); $this->assertSame($select, $select->where('x = y')); $this->assertSame($select, $select->limit(5)); $this->assertSame($select, $select->offset(10)); @@ -58,7 +59,7 @@ public function testMagicAccessor(Select $select) 'name' => new TableSource(new TableIdentifier('foo')), 'on' => 'x = y', 'columns' => [Select::SQL_STAR], - 'type' => Select::JOIN_INNER + 'type' => Joins::JOIN_INNER ]], $select->joins->getJoins() ); @@ -187,7 +188,7 @@ public function testMagicUnset() ->quantifier(Select::QUANTIFIER_DISTINCT) ->columns(['foo', 'bar']) ->setPrefixColumnsWithTable(false) - ->join('foo', 'x = y', Select::SQL_STAR, Select::JOIN_INNER) + ->join('foo', 'x = y', Select::SQL_STAR, Joins::JOIN_INNER) ->where('x = y') ->limit(5) ->offset(10) diff --git a/test/Sql/UpdateTest.php b/test/Sql/UpdateTest.php index 6d3db27635..146f810bb7 100644 --- a/test/Sql/UpdateTest.php +++ b/test/Sql/UpdateTest.php @@ -9,7 +9,7 @@ namespace ZendTest\Db\Sql; -use Zend\Db\Sql\Join; +use Zend\Db\Sql\Joins; use Zend\Db\Sql\Update; use Zend\Db\Sql\Where; use Zend\Db\Sql\TableIdentifier; @@ -128,9 +128,9 @@ public function testGetUpdateFails() * @testdox unit test: Test join() returns Update object (is chainable) * @covers Zend\Db\Sql\Update::join */ - public function testJoinChainable() + public function testJoinsChainable() { - $return = $this->update->join('baz', 'foo.fooId = baz.fooId', Join::JOIN_LEFT); + $return = $this->update->join('baz', 'foo.fooId = baz.fooId', Joins::JOIN_LEFT); $this->assertSame($this->update, $return); } } diff --git a/test/TableGateway/AbstractTableGatewayTest.php b/test/TableGateway/AbstractTableGatewayTest.php index 041da14f0b..d37cff9dc1 100644 --- a/test/TableGateway/AbstractTableGatewayTest.php +++ b/test/TableGateway/AbstractTableGatewayTest.php @@ -236,7 +236,7 @@ public function testUpdateWithJoin() [ 'name' => 'baz', 'on' => 'foo.fooId = baz.fooId', - 'type' => Sql\Join::JOIN_LEFT + 'type' => Sql\Joins::JOIN_LEFT ] ]; $affectedRows = $this->table->update(['foo.field' => 'bar'], 'id = 2', $joins); From 628b17e14537fcbc77149bfa466a92d96166f884 Mon Sep 17 00:00:00 2001 From: Turrsis Date: Tue, 24 May 2016 15:16:50 +0300 Subject: [PATCH 21/30] fix 19: combine in select --- src/Sql/Builder/sql92/SelectBuilder.php | 9 ++---- src/Sql/Combine.php | 14 +++++++++ src/Sql/Select.php | 39 +++++++++++++------------ test/Sql/Builder/SelectBuilderTest.php | 3 +- test/Sql/CombineTest.php | 14 +++++++++ test/Sql/SelectTest.php | 25 ++++++++++++++++ 6 files changed, 78 insertions(+), 26 deletions(-) diff --git a/src/Sql/Builder/sql92/SelectBuilder.php b/src/Sql/Builder/sql92/SelectBuilder.php index 6f4c916363..6d513cdeea 100644 --- a/src/Sql/Builder/sql92/SelectBuilder.php +++ b/src/Sql/Builder/sql92/SelectBuilder.php @@ -331,12 +331,9 @@ protected function build_Offset(Select $sqlObject, Context $context) */ protected function build_Combine(Select $sqlObject, Context $context) { - $select = clone $sqlObject; - - $combine = new Combine($select); - $combine->combine($select->combine); - unset($select->combine); - + $combine = clone $sqlObject->combine; + $combineInternal = $combine->combine; + unset($combineInternal[0]['select']->combine); return $this->platformBuilder->getPlatformBuilder($combine)->build($combine, $context); } diff --git a/src/Sql/Combine.php b/src/Sql/Combine.php index 0d94ae272f..dd128c4b25 100644 --- a/src/Sql/Combine.php +++ b/src/Sql/Combine.php @@ -169,4 +169,18 @@ public function __get($name) } return parent::__get($name); } + + /** + * __clone + * + * Resets the where object each time the Select is cloned. + * + * @return void + */ + public function __clone() + { + foreach ($this->combine as $k => $v) { + $this->combine[$k]['select'] = clone $v['select']; + } + } } diff --git a/src/Sql/Select.php b/src/Sql/Select.php index 1c39c16447..0f9b954272 100644 --- a/src/Sql/Select.php +++ b/src/Sql/Select.php @@ -31,14 +31,6 @@ class Select extends AbstractSqlObject implements PreparableSqlObjectInterface, const SQL_STAR = '*'; const ORDER_ASCENDING = 'ASC'; const ORDER_DESCENDING = 'DESC'; - const COMBINE = 'combine'; - const COMBINE_UNION = 'union'; - const COMBINE_EXCEPT = 'except'; - const COMBINE_INTERSECT = 'intersect'; - - /** - * @var array Specifications - */ /** * @var bool @@ -109,10 +101,11 @@ class Select extends AbstractSqlObject implements PreparableSqlObjectInterface, 'combine', 'prefixColumnsWithTable', ]; + /** - * @var array + * @var Combine */ - protected $combine = []; + protected $combine; /** * Constructor @@ -316,16 +309,12 @@ public function offset($offset) * @return self * @throws Exception\InvalidArgumentException */ - public function combine(SelectableInterface $select, $type = self::COMBINE_UNION, $modifier = '') + public function combine(SelectableInterface $select, $type = Combine::COMBINE_UNION, $modifier = '') { - if ($this->combine !== []) { - throw new Exception\InvalidArgumentException('This Select object is already combined and cannot be combined with multiple Selects objects'); + if (!$this->combine) { + $this->combine = new Combine($this); } - $this->combine[] = [ - 'select' => $select, - 'type' => $type, - 'modifier' => $modifier - ]; + $this->combine->combine($select, $type, $modifier); return $this; } @@ -376,7 +365,7 @@ public function __unset($name) $this->prefixColumnsWithTable = true; break; case 'combine': - $this->combine = []; + $this->combine = null; break; default : throw new Exception\InvalidArgumentException( @@ -401,5 +390,17 @@ public function __clone() $this->where = clone $this->where; $this->joins = clone $this->joins; $this->having = clone $this->having; + + if ($this->combine) { + $combine = $this->combine->combine; + $this->combine = new Combine(); + foreach ($combine as $i => $value) { + $this->combine->combine( + $i == 0 ? $this : clone $value['select'], + $value['type'], + $value['modifier'] + ); + } + } } } diff --git a/test/Sql/Builder/SelectBuilderTest.php b/test/Sql/Builder/SelectBuilderTest.php index 4df0644de7..0d447aad01 100644 --- a/test/Sql/Builder/SelectBuilderTest.php +++ b/test/Sql/Builder/SelectBuilderTest.php @@ -14,6 +14,7 @@ use Zend\Db\Sql\Predicate; use Zend\Db\Sql\TableIdentifier; use Zend\Db\Sql\Joins; +use Zend\Db\Sql\Combine; /** * @covers Zend\Db\Sql\Builder\IbmDb2\SelectBuilder @@ -148,7 +149,7 @@ public function dataProvider_Combine() ->where('a = b') ->combine( $this->select()->from('bar')->where('c = d'), - Select::COMBINE_UNION, + Combine::COMBINE_UNION, 'ALL' ), 'expected' => [ diff --git a/test/Sql/CombineTest.php b/test/Sql/CombineTest.php index cc9372acd5..c59e730459 100644 --- a/test/Sql/CombineTest.php +++ b/test/Sql/CombineTest.php @@ -29,6 +29,20 @@ protected function setUp() $this->combine = new Combine; } + public function testCloning() + { + $select = new Select(); + $select->from('foo'); + $this->combine->combine($select); + + $combine = clone $this->combine; + $selectCloned = $combine->combine[0]['select']; + $selectCloned->from('bar'); + + $this->assertEquals('foo', $select->table->getSource()->getTable()); + $this->assertEquals('bar', $selectCloned->table->getSource()->getTable()); + } + public function testRejectsInvalidStatement() { $this->setExpectedException('Zend\Db\Sql\Exception\InvalidArgumentException'); diff --git a/test/Sql/SelectTest.php b/test/Sql/SelectTest.php index 25f87b1053..66b6a9eab2 100644 --- a/test/Sql/SelectTest.php +++ b/test/Sql/SelectTest.php @@ -221,4 +221,29 @@ public function testCloning() $this->assertEquals(0, $select->having->count()); $this->assertEquals(1, $select1->having->count()); } + + public function testCloningWithCombine() + { + $selectInCombine = new Select; + $selectInCombine->from('subFoo'); + + $select = new Select; + $select + ->from('foo') + ->combine($selectInCombine); + + $selectCloned = clone $select; + $selectCloned->from('bar'); + + $this->assertEquals('foo', $select->table->getSource()->getTable()); + $this->assertEquals('bar', $selectCloned->table->getSource()->getTable()); + + $selectCloned0 = $selectCloned->combine->combine[0]['select']; + $this->assertEquals('bar', $selectCloned0->table->getSource()->getTable()); + + $selectCloned1 = $selectCloned->combine->combine[1]['select']; + $selectCloned1->from('subBar'); + $this->assertEquals('subFoo', $selectInCombine->table->getSource()->getTable()); + $this->assertEquals('subBar', $selectCloned1->table->getSource()->getTable()); + } } From ad9055c3a58b80e39ee6e45193ebc39a278560ba Mon Sep 17 00:00:00 2001 From: Turrsis Date: Wed, 7 Sep 2016 14:39:44 +0300 Subject: [PATCH 22/30] fix 20: Sql\Builder\Builder add Factory --- src/Adapter/AdapterAbstractServiceFactory.php | 4 +- src/Adapter/AdapterServiceFactory.php | 2 +- src/ConfigProvider.php | 1 + src/Sql/Builder/Builder.php | 13 +++ src/Sql/Builder/BuilderServiceFactory.php | 48 ++++++++++ .../AdapterAbstractServiceFactoryTest.php | 2 +- test/Adapter/AdapterServiceFactoryTest.php | 4 +- .../Sql/Builder/BuilderServiceFactoryTest.php | 94 +++++++++++++++++++ test/Sql/Builder/BuilderTest.php | 36 +++++++ 9 files changed, 198 insertions(+), 6 deletions(-) create mode 100644 src/Sql/Builder/BuilderServiceFactory.php create mode 100644 test/Sql/Builder/BuilderServiceFactoryTest.php diff --git a/src/Adapter/AdapterAbstractServiceFactory.php b/src/Adapter/AdapterAbstractServiceFactory.php index 470e48198d..0c881350c7 100644 --- a/src/Adapter/AdapterAbstractServiceFactory.php +++ b/src/Adapter/AdapterAbstractServiceFactory.php @@ -98,12 +98,12 @@ protected function getConfig(ContainerInterface $container) return $this->config; } - if (! $container->has('config')) { + if (! $container->has('Config')) { $this->config = []; return $this->config; } - $config = $container->get('config'); + $config = $container->get('Config'); if (! isset($config['db']) || ! is_array($config['db']) ) { diff --git a/src/Adapter/AdapterServiceFactory.php b/src/Adapter/AdapterServiceFactory.php index 95869f15e9..8a3a657570 100644 --- a/src/Adapter/AdapterServiceFactory.php +++ b/src/Adapter/AdapterServiceFactory.php @@ -23,7 +23,7 @@ class AdapterServiceFactory implements FactoryInterface */ public function __invoke(ContainerInterface $container, $requestedName, array $options = null) { - $config = $container->get('config'); + $config = $container->get('Config'); return new Adapter($config['db']); } diff --git a/src/ConfigProvider.php b/src/ConfigProvider.php index b2056ef967..a64ed8a406 100644 --- a/src/ConfigProvider.php +++ b/src/ConfigProvider.php @@ -34,6 +34,7 @@ public function getDependencyConfig() ], 'factories' => [ Adapter\AdapterInterface::class => Adapter\AdapterServiceFactory::class, + 'SqlBuilder' => Sql\Builder\BuilderServiceFactory::class, ], 'aliases' => [ Adapter\Adapter::class => Adapter\AdapterInterface::class, diff --git a/src/Sql/Builder/Builder.php b/src/Sql/Builder/Builder.php index e87700698e..2a7b98b6a9 100644 --- a/src/Sql/Builder/Builder.php +++ b/src/Sql/Builder/Builder.php @@ -151,6 +151,19 @@ public function getDefaultAdapter() return $this->defaultAdapter; } + /** + * @param array $builders + * @return self + */ + public function setPlatformBuilders(array $builders) + { + foreach ($builders as $platform => $classes) { + foreach ($classes as $objectClass => $builderClass) { + $this->setPlatformBuilder($platform, $objectClass, $builderClass); + } + } + return $this; + } /** * @param string|Context|PlatformInterface|Adapter\AdapterInterface $platform * @param string $objectClass diff --git a/src/Sql/Builder/BuilderServiceFactory.php b/src/Sql/Builder/BuilderServiceFactory.php new file mode 100644 index 0000000000..930952eb5e --- /dev/null +++ b/src/Sql/Builder/BuilderServiceFactory.php @@ -0,0 +1,48 @@ +has('Config')) { + return $builder; + } + $config = $container->get('Config'); + if (!isset($config['sql_builder'])) { + return $builder; + } + + $config = $config['sql_builder']; + + if (isset($config['default_adapter'])) { + $adapter = $container->get($config['default_adapter']); + $builder->setDefaultAdapter($adapter); + } + + if (isset($config['builders'])) { + $builder->setPlatformBuilders($config['builders']); + } + + return $builder; + } + + public function createService(ServiceLocatorInterface $serviceLocator) + { + return $this($serviceLocator, 'SqlBuilder'); + } +} diff --git a/test/Adapter/AdapterAbstractServiceFactoryTest.php b/test/Adapter/AdapterAbstractServiceFactoryTest.php index de177ccd18..0c1646b95d 100644 --- a/test/Adapter/AdapterAbstractServiceFactoryTest.php +++ b/test/Adapter/AdapterAbstractServiceFactoryTest.php @@ -33,7 +33,7 @@ protected function setUp() ]); $config->configureServiceManager($this->serviceManager); - $this->serviceManager->setService('config', [ + $this->serviceManager->setService('Config', [ 'db' => [ 'adapters' => [ 'Zend\Db\Adapter\Writer' => [ diff --git a/test/Adapter/AdapterServiceFactoryTest.php b/test/Adapter/AdapterServiceFactoryTest.php index 9b980d9e14..c8c45e2e04 100644 --- a/test/Adapter/AdapterServiceFactoryTest.php +++ b/test/Adapter/AdapterServiceFactoryTest.php @@ -31,7 +31,7 @@ public function setUp() public function testV2FactoryReturnsAdapter() { - $this->services->get('config')->willReturn([ + $this->services->get('Config')->willReturn([ 'db' => [ 'driver' => 'Pdo_Sqlite', 'database' => 'sqlite::memory:', @@ -44,7 +44,7 @@ public function testV2FactoryReturnsAdapter() public function testV3FactoryReturnsAdapter() { - $this->services->get('config')->willReturn([ + $this->services->get('Config')->willReturn([ 'db' => [ 'driver' => 'Pdo_Sqlite', 'database' => 'sqlite::memory:', diff --git a/test/Sql/Builder/BuilderServiceFactoryTest.php b/test/Sql/Builder/BuilderServiceFactoryTest.php new file mode 100644 index 0000000000..ebfaf7ddb4 --- /dev/null +++ b/test/Sql/Builder/BuilderServiceFactoryTest.php @@ -0,0 +1,94 @@ +getDependencyConfig(), + ArrayUtils::merge([ + 'services' => [ + 'Config' => [], + ], + ], $config) + ); + $serviceManager = new ServiceManager(); + (new Config($config))->configureServiceManager($serviceManager); + return $serviceManager->get('SqlBuilder'); + } + + public function testFactoryWithEmptyConfig() + { + $builder = $this->getBuilder(); + + $this->assertInstanceOf(Builder::class, $builder); + $this->assertNull($builder->getDefaultAdapter()); + $this->assertInstanceOf( + Db\Sql\Builder\sql92\SelectBuilder::class, + $builder->getPlatformBuilder(new Db\Sql\Select) + ); + } + + public function testFactoryWithoutAdapterConfig() + { + $builder = $this->getBuilder(['services' => ['Config' => [ + 'sql_builder' => [ + 'builders' => [ + 'sql92' => [ + Db\Sql\Select::class => Db\Sql\Builder\MySql\SelectBuilder::class, + ], + ], + ], + ]]]); + + $this->assertInstanceOf(Builder::class, $builder); + $this->assertNull($builder->getDefaultAdapter()); + $this->assertInstanceOf( + Db\Sql\Builder\MySql\SelectBuilder::class, + $builder->getPlatformBuilder(new Db\Sql\Select) + ); + } + + public function testFactoryWithFullConfig() + { + $builder = $this->getBuilder(['services' => ['Config' => [ + 'db' => [ + 'driver' => 'mysqli', + ], + 'sql_builder' => [ + 'default_adapter' => Db\Adapter\Adapter::class, + 'builders' => [ + 'sql92' => [ + Db\Sql\Select::class => Db\Sql\Builder\MySql\SelectBuilder::class, + ], + ], + ], + ]]]); + + $this->assertInstanceOf(Builder::class, $builder); + $this->assertInstanceOf( + Db\Adapter\Driver\Mysqli\Mysqli::class, + $builder->getDefaultAdapter()->getDriver() + ); + $this->assertInstanceOf( + Db\Sql\Builder\Mysql\SelectBuilder::class, + $builder->getPlatformBuilder(new Db\Sql\Select) + ); + } +} diff --git a/test/Sql/Builder/BuilderTest.php b/test/Sql/Builder/BuilderTest.php index 77c6b5c8fd..f308b467e8 100644 --- a/test/Sql/Builder/BuilderTest.php +++ b/test/Sql/Builder/BuilderTest.php @@ -44,6 +44,7 @@ public function testGePlatformBuilderForNotExistsObject() } /** + * @covers Zend\Db\Sql\Builder\Builder::getPlatformBuilder * @expectedException Zend\Db\Sql\Exception\RuntimeException */ public function testGePlatformBuilderForNotExistsPlatform() @@ -55,6 +56,9 @@ public function testGePlatformBuilderForNotExistsPlatform() $this->builder->getPlatformBuilder(new Sql\Ddl\CreateTable(), 'NotExistingPlatform'); } + /** + * @covers Zend\Db\Sql\Builder\Builder::getPlatformBuilder + */ public function testGetPlatformBuilder() { $this->assertInstanceOf( @@ -79,6 +83,9 @@ public function testGetPlatformBuilder() ); } + /** + * @covers Zend\Db\Sql\Builder\Builder::setPlatformBuilder + */ public function testSetPlatformBuilder() { $this->builder->setPlatformBuilder('ibmdb2', 'Zend\Db\Sql\Select', 'Zend\Db\Sql\Builder\IbmDb2\SelectBuilder'); @@ -99,6 +106,35 @@ public function testSetPlatformBuilder() ); } + /** + * @covers Zend\Db\Sql\Builder\Builder::setPlatformBuilders + */ + public function testSetPlatformBuilders() + { + $oracleSelectBuilder = new \Zend\Db\Sql\Builder\Oracle\SelectBuilder($this->builder); + $this->builder->setPlatformBuilders([ + 'ibmdb2' => [ + 'Zend\Db\Sql\Select' => 'Zend\Db\Sql\Builder\IbmDb2\SelectBuilder', + ], + 'oracle' => [ + 'Zend\Db\Sql\Select' => $oracleSelectBuilder, + ], + ]); + + $this->assertInstanceOf( + 'Zend\Db\Sql\Builder\sql92\SelectBuilder', + $this->builder->getPlatformBuilder(new Sql\Select(), 'sql92') + ); + $this->assertInstanceOf( + 'Zend\Db\Sql\Builder\IbmDb2\SelectBuilder', + $this->builder->getPlatformBuilder(new Sql\Select(), 'ibmdb2') + ); + $this->assertSame( + $oracleSelectBuilder, + $this->builder->getPlatformBuilder(new Sql\Select(), 'oracle') + ); + } + /** * @expectedException Zend\Db\Sql\Exception\InvalidArgumentException */ From 1a8a9a2f75e79a614e8039fc58eb63fd43644086 Mon Sep 17 00:00:00 2001 From: Turrsis Date: Tue, 24 May 2016 11:35:32 +0300 Subject: [PATCH 23/30] refactor docs --- doc/book/sql-ddl.md | 4 +-- doc/book/sql.md | 88 ++++++++++++++++++++++++++++++--------------- 2 files changed, 62 insertions(+), 30 deletions(-) diff --git a/doc/book/sql-ddl.md b/doc/book/sql-ddl.md index 8dd4467ab2..d187cb90da 100644 --- a/doc/book/sql-ddl.md +++ b/doc/book/sql-ddl.md @@ -115,13 +115,13 @@ use Zend\Db\Sql\Sql; $sql = new Sql($adapter); $adapter->query( - $sql->getSqlStringForSqlObject($ddl), + $sql->buildSqlString($ddl), $adapter::QUERY_MODE_EXECUTE ); ``` By passing the `$ddl` object through the `$sql` instance's -`getSqlStringForSqlObject()` method, we ensure that any platform specific +`buildSqlString()` method, we ensure that any platform specific specializations/modifications are utilized to create a platform specific SQL statement. diff --git a/doc/book/sql.md b/doc/book/sql.md index 9b6392b252..91796f62cc 100644 --- a/doc/book/sql.md +++ b/doc/book/sql.md @@ -43,7 +43,7 @@ $select = $sql->select(); $select->from('foo'); $select->where(['id' => 2]); -$statement = $sql->prepareStatementForSqlObject($select); +$statement = $sql->prepareSqlStatement($select); $results = $statement->execute(); ``` @@ -78,19 +78,16 @@ $select->where(['id' => 2]); // $select already has from('foo') applied Each of these objects implements the following two interfaces: ```php -interface PreparableSqlInterface +interface SelectableInterface { - public function prepareStatement(Adapter $adapter, StatementInterface $statement) : void; } -interface SqlInterface +interface PreparableSqlInterface { - public function getSqlString(PlatformInterface $adapterPlatform = null) : string; } ``` -Use these functions to produce either (a) a prepared statement, or (b) a string -to execute. +Use these interfaces for create user defined sql objects. ## Select @@ -113,22 +110,33 @@ Once you have a valid `Select` object, the following API can be used to further specify various select statement parts: ```php -class Select extends AbstractSql implements SqlInterface, PreparableSqlInterface +class Select extends AbstractSql implements PreparableSqlInterface, SelectableInterface { - const JOIN_INNER = 'inner'; - const JOIN_OUTER = 'outer'; - const JOIN_LEFT = 'left'; - const JOIN_RIGHT = 'right'; + const QUANTIFIER_DISTINCT = 'DISTINCT'; + const QUANTIFIER_ALL = 'ALL'; const SQL_STAR = '*'; const ORDER_ASCENDING = 'ASC'; const ORDER_DESCENDING = 'DESC'; + public $table // @param TableSource $table + public $quantifier; // @param string|Expression $quantifier DISTINCT|ALL + public $columns; // @param array $columns + public $joins; // @param $joins public $where; // @param Where $where - - public function __construct(string|array|TableIdentifier $table = null); - public function from(string|array|TableIdentifier $table) : self; - public function columns(array $columns, bool $prefixColumnsWithTable = true) : self; - public function join(string|array $name, string $on, string|array $columns = self::SQL_STAR, string $type = self::JOIN_INNER) : self; + public $order; // @param string|array $order + public $group; // @param $group + public $having; // @param Having $having + public $limit; // @param int $limit + public $offset; // @param int $offset + public $combine; // @param $combine + public $prefixColumnsWithTable; // @param $prefixColumnsWithTable + + public function __construct(null|string|array|TableIdentifier|TableSource $table = null); + public function from(string|array|TableIdentifier|TableSource $table) : self; + public function quantifier(string|ExpressionInterface $quantifier) :self; + public function columns(array $columns) : self; + public function setPrefixColumnsWithTable(bool $flag) :self; + public function join(string|array|TableIdentifier|TableSource $name, string $on, string|array $columns = self::SQL_STAR, string $type = Joins::JOIN_INNER) : self; public function where(Where|callable|string|array|PredicateInterface $predicate, string $combination = Predicate\PredicateSet::OP_AND) : self; public function group(string|array $group); public function having(Having|callable|string|array $predicate, string $combination = Predicate\PredicateSet::OP_AND) : self; @@ -148,9 +156,17 @@ $select->from('foo'); // (produces SELECT "t".* FROM "table" AS "t") $select->from(['t' => 'table']); +// As an array to specify an alias and schema +// (produces SELECT "t".* FROM "schema"."table" AS "t") +$select->from(['t' => ['schema', 'table']]); + // Using a Sql\TableIdentifier: -// (same output as above) +// (produces SELECT "t".* FROM "table" AS "t") $select->from(new TableIdentifier(['t' => 'table'])); + +// Using a Sql\TableSource: +// (produces SELECT "t".* FROM "table" AS "t") +$select->from(new TableSource('table', 't')); ``` ### columns() @@ -286,15 +302,20 @@ $select->offset(10); // similarly takes an integer/numeric The Insert API: ```php -class Insert implements SqlInterface, PreparableSqlInterface +class Insert extends AbstractSql implements PreparableSqlInterface { const VALUES_MERGE = 'merge'; const VALUES_SET = 'set'; - public function __construct(string|TableIdentifier $table = null); - public function into(string|TableIdentifier $table) : self; + public $table // @param TableSource $table + public $columns // @param array $columns + public $values // @param array|SelectableInterface $values + + public function __construct(null|string|array|TableIdentifier|TableSource $table = null); + public function into(string|array|TableIdentifier|TableSource $table) : self; public function columns(array $columns) : self; - public function values(array $values, string $flag = self::VALUES_SET) : self; + public function values(array|SelectableInterface $values, string $flag = self::VALUES_SET) : self; + public function select(SelectableInterface $select) : self; } ``` @@ -323,17 +344,27 @@ $insert->values([ $insert->values(['col_2' => 'value2'], $insert::VALUES_MERGE); ``` +```php +// To use `Select` for values: +$insert->values(new Select('foo'); +// or +$insert->select(new Select('foo'); +``` + ## Update ```php -class Update +class Update extends AbstractSql implements PreparableSqlInterface { const VALUES_MERGE = 'merge'; const VALUES_SET = 'set'; + public $table // @param TableSource $table + public $set // @param PriorityList $set public $where; // @param Where $where - public function __construct(string|TableIdentifier $table = null); - public function table(string|TableIdentifier $table) : self; + + public function __construct(null|string|array|TableIdentifier|TableSource $table = null); + public function table(string|array|TableIdentifier|TableSource $table) : self; public function set(array $values, string $flag = self::VALUES_SET) : self; public function where(Where|callable|string|array|PredicateInterface $predicate, string $combination = Predicate\PredicateSet::OP_AND) : self; } @@ -352,12 +383,13 @@ See the [section on Where and Having](#where-and-having). ## Delete ```php -class Delete +class Delete extends AbstractSql implements PreparableSqlInterface { + public $table // @param TableSource $table public $where; // @param Where $where - public function __construct(string|TableIdentifier $table = null); - public function from(string|TableIdentifier $table); + public function __construct(null|string|array|TableIdentifier|TableSource $table = null); + public function from(string|array|TableIdentifier|TableSource $table); public function where(Where|callable|string|array|PredicateInterface $predicate, string $combination = Predicate\PredicateSet::OP_AND) : self; } ``` From e60f49eb731eaa031f61f4eaa64876548f5d1f07 Mon Sep 17 00:00:00 2001 From: Turrsis Date: Tue, 1 Nov 2016 15:04:50 +0200 Subject: [PATCH 24/30] fix 21: fix namespaces --- test/Sql/Builder/AbstractTestCase.php | 32 +++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/test/Sql/Builder/AbstractTestCase.php b/test/Sql/Builder/AbstractTestCase.php index 1d9b4960a6..5acac9e8d6 100644 --- a/test/Sql/Builder/AbstractTestCase.php +++ b/test/Sql/Builder/AbstractTestCase.php @@ -48,22 +48,22 @@ * @method \Zend\Db\Sql\Ddl\Constraint\PrimaryKey constraint_PrimaryKey($columns = null, $name = null); * @method \Zend\Db\Sql\Ddl\Constraint\UniqueKey constraint_UniqueKey ($columns = null, $name = null); * - * @method \ZendTest\Db\Sql\Builder\Ddl\Column\BigInteger column_BigInteger ($name = null, $nullable = false, $default = null, array $options = array()); - * @method \ZendTest\Db\Sql\Builder\Ddl\Column\Binary column_Binary ($name, $length = null, $nullable = false, $default = null, array $options = array()); - * @method \ZendTest\Db\Sql\Builder\Ddl\Column\Blob column_Blob ($name, $length = null, $nullable = false, $default = null, array $options = array()); - * @method \ZendTest\Db\Sql\Builder\Ddl\Column\Boolean column_Boolean ($name = null, $nullable = false, $default = null, array $options = array()); - * @method \ZendTest\Db\Sql\Builder\Ddl\Column\Char column_Char ($name, $length = null, $nullable = false, $default = null, array $options = array()); - * @method \ZendTest\Db\Sql\Builder\Ddl\Column\Column column_Column ($name = null, $nullable = false, $default = null, array $options = array()); - * @method \ZendTest\Db\Sql\Builder\Ddl\Column\Date column_Date ($name = null, $nullable = false, $default = null, array $options = array()); - * @method \ZendTest\Db\Sql\Builder\Ddl\Column\Datetime column_Datetime ($name = null, $nullable = false, $default = null, array $options = array()); - * @method \ZendTest\Db\Sql\Builder\Ddl\Column\Decimal column_Decimal ($name, $digits = null, $decimal = null, $nullable = false, $default = null, array $options = array()); - * @method \ZendTest\Db\Sql\Builder\Ddl\Column\Floating column_Floating ($name, $digits = null, $decimal = null, $nullable = false, $default = null, array $options = array()); - * @method \ZendTest\Db\Sql\Builder\Ddl\Column\Integer column_Integer ($name = null, $nullable = false, $default = null, array $options = array()); - * @method \ZendTest\Db\Sql\Builder\Ddl\Column\Text column_Text ($name, $length = null, $nullable = false, $default = null, array $options = array()); - * @method \ZendTest\Db\Sql\Builder\Ddl\Column\Time column_Time ($name = null, $nullable = false, $default = null, array $options = array()); - * @method \ZendTest\Db\Sql\Builder\Ddl\Column\Timestamp column_Timestamp ($name = null, $nullable = false, $default = null, array $options = array()); - * @method \ZendTest\Db\Sql\Builder\Ddl\Column\Varbinary column_Varbinary ($name, $length = null, $nullable = false, $default = null, array $options = array()); - * @method \ZendTest\Db\Sql\Builder\Ddl\Column\Varchar column_Varchar ($name, $length = null, $nullable = false, $default = null, array $options = array()); + * @method \Zend\Db\Sql\Builder\Ddl\Column\BigInteger column_BigInteger ($name = null, $nullable = false, $default = null, array $options = array()); + * @method \Zend\Db\Sql\Builder\Ddl\Column\Binary column_Binary ($name, $length = null, $nullable = false, $default = null, array $options = array()); + * @method \Zend\Db\Sql\Builder\Ddl\Column\Blob column_Blob ($name, $length = null, $nullable = false, $default = null, array $options = array()); + * @method \Zend\Db\Sql\Builder\Ddl\Column\Boolean column_Boolean ($name = null, $nullable = false, $default = null, array $options = array()); + * @method \Zend\Db\Sql\Builder\Ddl\Column\Char column_Char ($name, $length = null, $nullable = false, $default = null, array $options = array()); + * @method \Zend\Db\Sql\Builder\Ddl\Column\Column column_Column ($name = null, $nullable = false, $default = null, array $options = array()); + * @method \Zend\Db\Sql\Builder\Ddl\Column\Date column_Date ($name = null, $nullable = false, $default = null, array $options = array()); + * @method \Zend\Db\Sql\Builder\Ddl\Column\Datetime column_Datetime ($name = null, $nullable = false, $default = null, array $options = array()); + * @method \Zend\Db\Sql\Builder\Ddl\Column\Decimal column_Decimal ($name, $digits = null, $decimal = null, $nullable = false, $default = null, array $options = array()); + * @method \Zend\Db\Sql\Builder\Ddl\Column\Floating column_Floating ($name, $digits = null, $decimal = null, $nullable = false, $default = null, array $options = array()); + * @method \Zend\Db\Sql\Builder\Ddl\Column\Integer column_Integer ($name = null, $nullable = false, $default = null, array $options = array()); + * @method \Zend\Db\Sql\Builder\Ddl\Column\Text column_Text ($name, $length = null, $nullable = false, $default = null, array $options = array()); + * @method \Zend\Db\Sql\Builder\Ddl\Column\Time column_Time ($name = null, $nullable = false, $default = null, array $options = array()); + * @method \Zend\Db\Sql\Builder\Ddl\Column\Timestamp column_Timestamp ($name = null, $nullable = false, $default = null, array $options = array()); + * @method \Zend\Db\Sql\Builder\Ddl\Column\Varbinary column_Varbinary ($name, $length = null, $nullable = false, $default = null, array $options = array()); + * @method \Zend\Db\Sql\Builder\Ddl\Column\Varchar column_Varchar ($name, $length = null, $nullable = false, $default = null, array $options = array()); */ class AbstractTestCase extends \PHPUnit_Framework_TestCase { From 2277e667ca127a2c18e6f0fcfbdb8a3c81588ebc Mon Sep 17 00:00:00 2001 From: Turrsis Date: Tue, 1 Nov 2016 15:05:22 +0200 Subject: [PATCH 25/30] fix 22: add 'charset' mysql option to ColumnBuilder --- src/Sql/Builder/Mysql/Ddl/Column/ColumnBuilder.php | 1 + test/Sql/Builder/Ddl/Column/ColumnBuilderTest.php | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/Sql/Builder/Mysql/Ddl/Column/ColumnBuilder.php b/src/Sql/Builder/Mysql/Ddl/Column/ColumnBuilder.php index 2eba064536..51a15f213e 100644 --- a/src/Sql/Builder/Mysql/Ddl/Column/ColumnBuilder.php +++ b/src/Sql/Builder/Mysql/Ddl/Column/ColumnBuilder.php @@ -37,6 +37,7 @@ public function __construct(Builder $platformBuilder) ], ], ], + 'charset' => 'CHARACTER SET %s', 'nullable' => $this->specifications['nullable'], 'identity' => [ 'valueMap' => [true => 'AUTO_INCREMENT', false => null], diff --git a/test/Sql/Builder/Ddl/Column/ColumnBuilderTest.php b/test/Sql/Builder/Ddl/Column/ColumnBuilderTest.php index 59569597f2..d871674ac1 100644 --- a/test/Sql/Builder/Ddl/Column/ColumnBuilderTest.php +++ b/test/Sql/Builder/Ddl/Column/ColumnBuilderTest.php @@ -184,6 +184,13 @@ public function dataProvider_OtherColumns() 'sql92' => '"foo" VARCHAR(20) NOT NULL DEFAULT \'bar\'', ], ], + [ + 'sqlObject' => $this->column_Varchar('foo', 20)->setOption('charset', 'UTF8'), + 'expected' => [ + 'sql92' => '"foo" VARCHAR(20) NOT NULL', + 'mysql' => '`foo` VARCHAR(20) CHARACTER SET UTF8 NOT NULL', + ], + ], ]; } } From 63d9ef23ecbf421929d776b7d14cb96e5bd350b1 Mon Sep 17 00:00:00 2001 From: Turrsis Date: Wed, 2 Nov 2016 10:26:46 +0200 Subject: [PATCH 26/30] fix 23: rename 'Config' to 'config' (for ServiceManager 3.0) --- src/Adapter/AdapterAbstractServiceFactory.php | 4 ++-- src/Adapter/AdapterServiceFactory.php | 2 +- src/Sql/Builder/BuilderServiceFactory.php | 4 ++-- test/Adapter/AdapterAbstractServiceFactoryTest.php | 2 +- test/Adapter/AdapterServiceFactoryTest.php | 4 ++-- test/Sql/Builder/BuilderServiceFactoryTest.php | 8 ++++---- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Adapter/AdapterAbstractServiceFactory.php b/src/Adapter/AdapterAbstractServiceFactory.php index 0c881350c7..470e48198d 100644 --- a/src/Adapter/AdapterAbstractServiceFactory.php +++ b/src/Adapter/AdapterAbstractServiceFactory.php @@ -98,12 +98,12 @@ protected function getConfig(ContainerInterface $container) return $this->config; } - if (! $container->has('Config')) { + if (! $container->has('config')) { $this->config = []; return $this->config; } - $config = $container->get('Config'); + $config = $container->get('config'); if (! isset($config['db']) || ! is_array($config['db']) ) { diff --git a/src/Adapter/AdapterServiceFactory.php b/src/Adapter/AdapterServiceFactory.php index 8a3a657570..95869f15e9 100644 --- a/src/Adapter/AdapterServiceFactory.php +++ b/src/Adapter/AdapterServiceFactory.php @@ -23,7 +23,7 @@ class AdapterServiceFactory implements FactoryInterface */ public function __invoke(ContainerInterface $container, $requestedName, array $options = null) { - $config = $container->get('Config'); + $config = $container->get('config'); return new Adapter($config['db']); } diff --git a/src/Sql/Builder/BuilderServiceFactory.php b/src/Sql/Builder/BuilderServiceFactory.php index 930952eb5e..6e6c042221 100644 --- a/src/Sql/Builder/BuilderServiceFactory.php +++ b/src/Sql/Builder/BuilderServiceFactory.php @@ -19,10 +19,10 @@ public function __invoke(ContainerInterface $container, $requestedName, array $o { $builder = new Builder(); - if (!$container->has('Config')) { + if (!$container->has('config')) { return $builder; } - $config = $container->get('Config'); + $config = $container->get('config'); if (!isset($config['sql_builder'])) { return $builder; } diff --git a/test/Adapter/AdapterAbstractServiceFactoryTest.php b/test/Adapter/AdapterAbstractServiceFactoryTest.php index 0c1646b95d..de177ccd18 100644 --- a/test/Adapter/AdapterAbstractServiceFactoryTest.php +++ b/test/Adapter/AdapterAbstractServiceFactoryTest.php @@ -33,7 +33,7 @@ protected function setUp() ]); $config->configureServiceManager($this->serviceManager); - $this->serviceManager->setService('Config', [ + $this->serviceManager->setService('config', [ 'db' => [ 'adapters' => [ 'Zend\Db\Adapter\Writer' => [ diff --git a/test/Adapter/AdapterServiceFactoryTest.php b/test/Adapter/AdapterServiceFactoryTest.php index c8c45e2e04..9b980d9e14 100644 --- a/test/Adapter/AdapterServiceFactoryTest.php +++ b/test/Adapter/AdapterServiceFactoryTest.php @@ -31,7 +31,7 @@ public function setUp() public function testV2FactoryReturnsAdapter() { - $this->services->get('Config')->willReturn([ + $this->services->get('config')->willReturn([ 'db' => [ 'driver' => 'Pdo_Sqlite', 'database' => 'sqlite::memory:', @@ -44,7 +44,7 @@ public function testV2FactoryReturnsAdapter() public function testV3FactoryReturnsAdapter() { - $this->services->get('Config')->willReturn([ + $this->services->get('config')->willReturn([ 'db' => [ 'driver' => 'Pdo_Sqlite', 'database' => 'sqlite::memory:', diff --git a/test/Sql/Builder/BuilderServiceFactoryTest.php b/test/Sql/Builder/BuilderServiceFactoryTest.php index ebfaf7ddb4..0ffe998fc4 100644 --- a/test/Sql/Builder/BuilderServiceFactoryTest.php +++ b/test/Sql/Builder/BuilderServiceFactoryTest.php @@ -24,7 +24,7 @@ public function getBuilder($config = []) (new Db\ConfigProvider)->getDependencyConfig(), ArrayUtils::merge([ 'services' => [ - 'Config' => [], + 'config' => [], ], ], $config) ); @@ -47,7 +47,7 @@ public function testFactoryWithEmptyConfig() public function testFactoryWithoutAdapterConfig() { - $builder = $this->getBuilder(['services' => ['Config' => [ + $builder = $this->getBuilder(['services' => ['config' => [ 'sql_builder' => [ 'builders' => [ 'sql92' => [ @@ -67,12 +67,12 @@ public function testFactoryWithoutAdapterConfig() public function testFactoryWithFullConfig() { - $builder = $this->getBuilder(['services' => ['Config' => [ + $builder = $this->getBuilder(['services' => ['config' => [ 'db' => [ 'driver' => 'mysqli', ], 'sql_builder' => [ - 'default_adapter' => Db\Adapter\Adapter::class, + 'default_adapter' => Db\Adapter\AdapterInterface::class, 'builders' => [ 'sql92' => [ Db\Sql\Select::class => Db\Sql\Builder\MySql\SelectBuilder::class, From 8be0cb2a6aad0d14c4f0448171652440da97bb5a Mon Sep 17 00:00:00 2001 From: Turrsis Date: Thu, 3 Nov 2016 09:39:09 +0200 Subject: [PATCH 27/30] fix 24: remove @deprecated --- src/Adapter/Adapter.php | 22 ---------------------- src/Sql/TableIdentifier.php | 20 -------------------- 2 files changed, 42 deletions(-) diff --git a/src/Adapter/Adapter.php b/src/Adapter/Adapter.php index 99de917cc9..f2918a1dd1 100644 --- a/src/Adapter/Adapter.php +++ b/src/Adapter/Adapter.php @@ -369,26 +369,4 @@ protected function createProfiler($parameters) } return $profiler; } - - /** - * @param array $parameters - * @return Driver\DriverInterface - * @throws \InvalidArgumentException - * @throws Exception\InvalidArgumentException - * @deprecated - */ - protected function createDriverFromParameters(array $parameters) - { - return $this->createDriver($parameters); - } - - /** - * @param Driver\DriverInterface $driver - * @return Platform\PlatformInterface - * @deprecated - */ - protected function createPlatformFromDriver(Driver\DriverInterface $driver) - { - return $this->createPlatform($driver); - } } diff --git a/src/Sql/TableIdentifier.php b/src/Sql/TableIdentifier.php index 94bf6375a8..2913ba190c 100644 --- a/src/Sql/TableIdentifier.php +++ b/src/Sql/TableIdentifier.php @@ -76,16 +76,6 @@ public function __construct($table, $schema = null) } } - /** - * @param string $table - * - * @deprecated please use the constructor and build a new {@see TableIdentifier} instead - */ - public function setTable($table) - { - $this->table = $table; - } - /** * @return string */ @@ -102,16 +92,6 @@ public function hasSchema() return ($this->schema !== null); } - /** - * @param $schema - * - * @deprecated please use the constructor and build a new {@see TableIdentifier} instead - */ - public function setSchema($schema) - { - $this->schema = $schema; - } - /** * @return null|string */ From 84ce3a55d454840065682b6ee3b6df9bd53daa62 Mon Sep 17 00:00:00 2001 From: Turrsis Date: Thu, 3 Nov 2016 09:44:05 +0200 Subject: [PATCH 28/30] fix 25: remove $lastPreparedStatement property because it never using --- src/Adapter/Adapter.php | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/Adapter/Adapter.php b/src/Adapter/Adapter.php index f2918a1dd1..a689b9cc34 100644 --- a/src/Adapter/Adapter.php +++ b/src/Adapter/Adapter.php @@ -55,11 +55,6 @@ class Adapter implements AdapterInterface, Profiler\ProfilerAwareInterface */ protected $queryResultSetPrototype = null; - /** - * @var Driver\StatementInterface - */ - protected $lastPreparedStatement = null; - /** * @param Driver\DriverInterface|array $driver * @param Platform\PlatformInterface $platform @@ -177,14 +172,13 @@ public function query($sql, $parametersOrQueryMode = self::QUERY_MODE_PREPARE, R } if ($mode == self::QUERY_MODE_PREPARE) { - $this->lastPreparedStatement = null; - $this->lastPreparedStatement = $this->driver->createStatement($sql); - $this->lastPreparedStatement->prepare(); + $preparedStatement = $this->driver->createStatement($sql); + $preparedStatement->prepare(); if (is_array($parameters) || $parameters instanceof ParameterContainer) { - $this->lastPreparedStatement->setParameterContainer((is_array($parameters)) ? new ParameterContainer($parameters) : $parameters); - $result = $this->lastPreparedStatement->execute(); + $preparedStatement->setParameterContainer((is_array($parameters)) ? new ParameterContainer($parameters) : $parameters); + $result = $preparedStatement->execute(); } else { - return $this->lastPreparedStatement; + return $preparedStatement; } } else { $result = $this->driver->getConnection()->execute($sql); From c0f7f5b83e00e379801281571f5f52a8d538fe99 Mon Sep 17 00:00:00 2001 From: Turrsis Date: Thu, 3 Nov 2016 09:45:41 +0200 Subject: [PATCH 29/30] fix 26: remove __get() method because it is excess --- src/Adapter/Adapter.php | 21 ----------------- src/Adapter/AdapterInterface.php | 5 ---- test/Adapter/AdapterTest.php | 39 ++++++++++---------------------- 3 files changed, 12 insertions(+), 53 deletions(-) diff --git a/src/Adapter/Adapter.php b/src/Adapter/Adapter.php index a689b9cc34..cc471d4a8c 100644 --- a/src/Adapter/Adapter.php +++ b/src/Adapter/Adapter.php @@ -11,10 +11,6 @@ use Zend\Db\ResultSet; -/** - * @property Driver\DriverInterface $driver - * @property Platform\PlatformInterface $platform - */ class Adapter implements AdapterInterface, Profiler\ProfilerAwareInterface { /** @@ -227,23 +223,6 @@ public function getHelpers(/* $functions */) } } - /** - * @param $name - * @throws Exception\InvalidArgumentException - * @return Driver\DriverInterface|Platform\PlatformInterface - */ - public function __get($name) - { - switch (strtolower($name)) { - case 'driver': - return $this->driver; - case 'platform': - return $this->platform; - default: - throw new Exception\InvalidArgumentException('Invalid magic property on adapter'); - } - } - /** * @param array $parameters * @return Driver\DriverInterface diff --git a/src/Adapter/AdapterInterface.php b/src/Adapter/AdapterInterface.php index 692ac56e5f..1d94e3e7c8 100644 --- a/src/Adapter/AdapterInterface.php +++ b/src/Adapter/AdapterInterface.php @@ -9,11 +9,6 @@ namespace Zend\Db\Adapter; -/** - * - * @property Driver\DriverInterface $driver - * @property Platform\PlatformInterface $platform - */ interface AdapterInterface { /** diff --git a/test/Adapter/AdapterTest.php b/test/Adapter/AdapterTest.php index 71c7212aec..8a9a7aabdf 100644 --- a/test/Adapter/AdapterTest.php +++ b/test/Adapter/AdapterTest.php @@ -83,25 +83,25 @@ public function testCreateDriver() { if (extension_loaded('mysqli')) { $adapter = new Adapter(['driver' => 'mysqli'], $this->mockPlatform); - $this->assertInstanceOf('Zend\Db\Adapter\Driver\Mysqli\Mysqli', $adapter->driver); + $this->assertInstanceOf('Zend\Db\Adapter\Driver\Mysqli\Mysqli', $adapter->getDriver()); unset($adapter); } if (extension_loaded('pgsql')) { $adapter = new Adapter(['driver' => 'pgsql'], $this->mockPlatform); - $this->assertInstanceOf('Zend\Db\Adapter\Driver\Pgsql\Pgsql', $adapter->driver); + $this->assertInstanceOf('Zend\Db\Adapter\Driver\Pgsql\Pgsql', $adapter->getDriver()); unset($adapter); } if (extension_loaded('sqlsrv')) { $adapter = new Adapter(['driver' => 'sqlsrv'], $this->mockPlatform); - $this->assertInstanceOf('Zend\Db\Adapter\Driver\Sqlsrv\Sqlsrv', $adapter->driver); + $this->assertInstanceOf('Zend\Db\Adapter\Driver\Sqlsrv\Sqlsrv', $adapter->getDriver()); unset($adapter); } if (extension_loaded('pdo')) { $adapter = new Adapter(['driver' => 'pdo_sqlite'], $this->mockPlatform); - $this->assertInstanceOf('Zend\Db\Adapter\Driver\Pdo\Pdo', $adapter->driver); + $this->assertInstanceOf('Zend\Db\Adapter\Driver\Pdo\Pdo', $adapter->getDriver()); unset($adapter); } } @@ -115,49 +115,49 @@ public function testCreatePlatform() $driver = clone $this->mockDriver; $driver->expects($this->any())->method('getDatabasePlatformName')->will($this->returnValue('Mysql')); $adapter = new Adapter($driver); - $this->assertInstanceOf('Zend\Db\Adapter\Platform\Mysql', $adapter->platform); + $this->assertInstanceOf('Zend\Db\Adapter\Platform\Mysql', $adapter->getPlatform()); unset($adapter, $driver); $driver = clone $this->mockDriver; $driver->expects($this->any())->method('getDatabasePlatformName')->will($this->returnValue('SqlServer')); $adapter = new Adapter($driver); - $this->assertInstanceOf('Zend\Db\Adapter\Platform\SqlServer', $adapter->platform); + $this->assertInstanceOf('Zend\Db\Adapter\Platform\SqlServer', $adapter->getPlatform()); unset($adapter, $driver); $driver = clone $this->mockDriver; $driver->expects($this->any())->method('getDatabasePlatformName')->will($this->returnValue('Postgresql')); $adapter = new Adapter($driver); - $this->assertInstanceOf('Zend\Db\Adapter\Platform\Postgresql', $adapter->platform); + $this->assertInstanceOf('Zend\Db\Adapter\Platform\Postgresql', $adapter->getPlatform()); unset($adapter, $driver); $driver = clone $this->mockDriver; $driver->expects($this->any())->method('getDatabasePlatformName')->will($this->returnValue('Sqlite')); $adapter = new Adapter($driver); - $this->assertInstanceOf('Zend\Db\Adapter\Platform\Sqlite', $adapter->platform); + $this->assertInstanceOf('Zend\Db\Adapter\Platform\Sqlite', $adapter->getPlatform()); unset($adapter, $driver); $driver = clone $this->mockDriver; $driver->expects($this->any())->method('getDatabasePlatformName')->will($this->returnValue('IbmDb2')); $adapter = new Adapter($driver); - $this->assertInstanceOf('Zend\Db\Adapter\Platform\IbmDb2', $adapter->platform); + $this->assertInstanceOf('Zend\Db\Adapter\Platform\IbmDb2', $adapter->getPlatform()); unset($adapter, $driver); $driver = clone $this->mockDriver; $driver->expects($this->any())->method('getDatabasePlatformName')->will($this->returnValue('Oracle')); $adapter = new Adapter($driver); - $this->assertInstanceOf('Zend\Db\Adapter\Platform\Oracle', $adapter->platform); + $this->assertInstanceOf('Zend\Db\Adapter\Platform\Oracle', $adapter->getPlatform()); unset($adapter, $driver); $driver = clone $this->mockDriver; $driver->expects($this->any())->method('getDatabasePlatformName')->will($this->returnValue('Foo')); $adapter = new Adapter($driver); - $this->assertInstanceOf('Zend\Db\Adapter\Platform\Sql92', $adapter->platform); + $this->assertInstanceOf('Zend\Db\Adapter\Platform\Sql92', $adapter->getPlatform()); unset($adapter, $driver); // ensure platform can created via string, and also that it passed in options to platform object $driver = ['driver' => 'pdo_sqlite', 'platform' => 'Oracle', 'platform_options' => ['quote_identifiers' => false]]; $adapter = new Adapter($driver); - $this->assertInstanceOf('Zend\Db\Adapter\Platform\Oracle', $adapter->platform); + $this->assertInstanceOf('Zend\Db\Adapter\Platform\Oracle', $adapter->getPlatform()); $this->assertEquals('foo', $adapter->getPlatform()->quoteIdentifier('foo')); unset($adapter, $driver); } @@ -285,21 +285,6 @@ public function testCreateStatement() { $this->assertSame($this->mockStatement, $this->adapter->createStatement()); } - - /** - * @testdox unit test: Test __get() works - * @covers Zend\Db\Adapter\Adapter::__get - */ - public function test__get() - { - $this->assertSame($this->mockDriver, $this->adapter->driver); - $this->assertSame($this->mockDriver, $this->adapter->DrivER); - $this->assertSame($this->mockPlatform, $this->adapter->PlatForm); - $this->assertSame($this->mockPlatform, $this->adapter->platform); - - $this->setExpectedException('InvalidArgumentException', 'Invalid magic'); - $this->adapter->foo; - } } class TemporaryResultSet extends \Zend\Db\ResultSet\ResultSet From a5d195efa34f75d9943b62ea2cc3ffd8517af10a Mon Sep 17 00:00:00 2001 From: Turrsis Date: Thu, 3 Nov 2016 10:40:00 +0200 Subject: [PATCH 30/30] fix 27: allow to use SqlObject in Adapter directly. --- src/Adapter/Adapter.php | 45 ++++++++++- src/Adapter/AdapterAbstractServiceFactory.php | 3 + src/Adapter/AdapterServiceFactory.php | 3 + src/Adapter/SqlBuilderInterface.php | 27 +++++++ src/ConfigProvider.php | 2 +- src/Sql/Builder/Builder.php | 3 +- .../AdapterAbstractServiceFactoryTest.php | 25 ++++++ test/Adapter/AdapterServiceFactoryTest.php | 17 ++++ test/Adapter/AdapterTest.php | 78 +++++++++++++++++++ .../Sql/Builder/BuilderServiceFactoryTest.php | 3 +- 10 files changed, 201 insertions(+), 5 deletions(-) create mode 100644 src/Adapter/SqlBuilderInterface.php diff --git a/src/Adapter/Adapter.php b/src/Adapter/Adapter.php index cc471d4a8c..4216a00550 100644 --- a/src/Adapter/Adapter.php +++ b/src/Adapter/Adapter.php @@ -51,6 +51,11 @@ class Adapter implements AdapterInterface, Profiler\ProfilerAwareInterface */ protected $queryResultSetPrototype = null; + /** + * @var SqlBuilderInterface + */ + protected $sqlBuilder; + /** * @param Driver\DriverInterface|array $driver * @param Platform\PlatformInterface $platform @@ -65,6 +70,9 @@ public function __construct($driver, Platform\PlatformInterface $platform = null if (is_array($driver)) { $parameters = $driver; + if (isset($parameters['sql_builder'])) { + $this->setSqlBuilder($parameters['sql_builder']); + } if ($profiler === null && isset($parameters['profiler'])) { $profiler = $this->createProfiler($parameters); } @@ -146,6 +154,24 @@ public function getCurrentSchema() return $this->driver->getConnection()->getCurrentSchema(); } + /** + * @return SqlBuilderInterface + */ + public function getSqlBuilder() + { + return $this->sqlBuilder; + } + + /** + * @param SqlBuilderInterface $sqlBuilder + * @return self + */ + public function setSqlBuilder(SqlBuilderInterface $sqlBuilder) + { + $this->sqlBuilder = $sqlBuilder; + return $this; + } + /** * query() is a convenience function * @@ -167,16 +193,31 @@ public function query($sql, $parametersOrQueryMode = self::QUERY_MODE_PREPARE, R throw new Exception\InvalidArgumentException('Parameter 2 to this method must be a flag, an array, or ParameterContainer'); } + $sqlIsString = is_string($sql) || (is_object($sql) && method_exists($sql, '__toString')); + if ($mode == self::QUERY_MODE_PREPARE) { - $preparedStatement = $this->driver->createStatement($sql); + if ($sqlIsString) { + $preparedStatement = $this->driver->createStatement($sql); + } else { + if (!$this->sqlBuilder) { + throw new Exception\RuntimeException('sqlBuilder must be set for non string sql'); + } + $preparedStatement = $this->sqlBuilder->prepareSqlStatement($sql, $this); + } $preparedStatement->prepare(); - if (is_array($parameters) || $parameters instanceof ParameterContainer) { + if ($parameters !== null) { $preparedStatement->setParameterContainer((is_array($parameters)) ? new ParameterContainer($parameters) : $parameters); $result = $preparedStatement->execute(); } else { return $preparedStatement; } } else { + if (!$sqlIsString) { + if (!$this->sqlBuilder) { + throw new Exception\RuntimeException('sqlBuilder must be set for non string sql'); + } + $sql = $this->sqlBuilder->buildSqlString($sql, $this); + } $result = $this->driver->getConnection()->execute($sql); } diff --git a/src/Adapter/AdapterAbstractServiceFactory.php b/src/Adapter/AdapterAbstractServiceFactory.php index 470e48198d..cb47eec0b4 100644 --- a/src/Adapter/AdapterAbstractServiceFactory.php +++ b/src/Adapter/AdapterAbstractServiceFactory.php @@ -70,6 +70,9 @@ public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator public function __invoke(ContainerInterface $container, $requestedName, array $options = null) { $config = $this->getConfig($container); + if (isset($config[$requestedName]['sql_builder'])) { + $config[$requestedName]['sql_builder'] = $container->get($config[$requestedName]['sql_builder']); + } return new Adapter($config[$requestedName]); } diff --git a/src/Adapter/AdapterServiceFactory.php b/src/Adapter/AdapterServiceFactory.php index 95869f15e9..4f1b447c4d 100644 --- a/src/Adapter/AdapterServiceFactory.php +++ b/src/Adapter/AdapterServiceFactory.php @@ -24,6 +24,9 @@ class AdapterServiceFactory implements FactoryInterface public function __invoke(ContainerInterface $container, $requestedName, array $options = null) { $config = $container->get('config'); + if (isset($config['db']['sql_builder'])) { + $config['db']['sql_builder'] = $container->get($config['db']['sql_builder']); + } return new Adapter($config['db']); } diff --git a/src/Adapter/SqlBuilderInterface.php b/src/Adapter/SqlBuilderInterface.php new file mode 100644 index 0000000000..5313bc4aa0 --- /dev/null +++ b/src/Adapter/SqlBuilderInterface.php @@ -0,0 +1,27 @@ + [ Adapter\AdapterInterface::class => Adapter\AdapterServiceFactory::class, - 'SqlBuilder' => Sql\Builder\BuilderServiceFactory::class, + Adapter\SqlBuilderInterface::class => Sql\Builder\BuilderServiceFactory::class, ], 'aliases' => [ Adapter\Adapter::class => Adapter\AdapterInterface::class, diff --git a/src/Sql/Builder/Builder.php b/src/Sql/Builder/Builder.php index 2a7b98b6a9..9de2b18353 100644 --- a/src/Sql/Builder/Builder.php +++ b/src/Sql/Builder/Builder.php @@ -18,8 +18,9 @@ use Zend\Db\Sql\ExpressionInterface; use Zend\Db\Sql\TableIdentifier; use Zend\Db\Sql\TableSource; +use Zend\Db\Adapter\SqlBuilderInterface; -class Builder extends AbstractBuilder +class Builder extends AbstractBuilder implements SqlBuilderInterface { /** * @var Adapter\AdapterInterface diff --git a/test/Adapter/AdapterAbstractServiceFactoryTest.php b/test/Adapter/AdapterAbstractServiceFactoryTest.php index de177ccd18..a94fa48b8e 100644 --- a/test/Adapter/AdapterAbstractServiceFactoryTest.php +++ b/test/Adapter/AdapterAbstractServiceFactoryTest.php @@ -88,4 +88,29 @@ public function testInvalidService($service) { $actual = $this->serviceManager->get($service); } + + public function testInjectSqlBuilder() + { + $mockBuilder = $this->getMock('Zend\Db\Adapter\SqlBuilderInterface'); + $this->serviceManager->setAllowOverride(true); + $this->serviceManager->setService('sqlBuilderAlias', $mockBuilder); + $this->serviceManager->setService('config', [ + 'db' => [ + 'adapters' => [ + 'Zend\Db\Adapter\Writer' => [ + 'driver' => 'mysqli', + 'sql_builder' => 'sqlBuilderAlias', + ], + 'Zend\Db\Adapter\Reader' => [ + 'driver' => 'mysqli', + 'sql_builder' => 'sqlBuilderAlias', + ], + ], + ], + ]); + + $adapter = $this->serviceManager->get('Zend\Db\Adapter\Writer'); + $this->assertInstanceOf('Zend\Db\Adapter\Adapter', $adapter); + $this->assertSame($mockBuilder, $adapter->getSqlBuilder()); + } } diff --git a/test/Adapter/AdapterServiceFactoryTest.php b/test/Adapter/AdapterServiceFactoryTest.php index 9b980d9e14..9c093f5733 100644 --- a/test/Adapter/AdapterServiceFactoryTest.php +++ b/test/Adapter/AdapterServiceFactoryTest.php @@ -54,4 +54,21 @@ public function testV3FactoryReturnsAdapter() $adapter = $this->factory->__invoke($this->services->reveal(), Adapter::class); $this->assertInstanceOf(Adapter::class, $adapter); } + + public function testInjectSqlBuilder() + { + $mockBuilder = $this->getMock('Zend\Db\Adapter\SqlBuilderInterface'); + $this->services->get('sqlBuilderAlias')->willReturn($mockBuilder); + $this->services->get('config')->willReturn([ + 'db' => [ + 'driver' => 'Pdo_Sqlite', + 'database' => 'sqlite::memory:', + 'sql_builder' => 'sqlBuilderAlias', + ], + ]); + + $adapter = $this->factory->__invoke($this->services->reveal(), Adapter::class); + $this->assertInstanceOf(Adapter::class, $adapter); + $this->assertSame($mockBuilder, $adapter->getSqlBuilder()); + } } diff --git a/test/Adapter/AdapterTest.php b/test/Adapter/AdapterTest.php index 8a9a7aabdf..6277df5880 100644 --- a/test/Adapter/AdapterTest.php +++ b/test/Adapter/AdapterTest.php @@ -11,6 +11,7 @@ use Zend\Db\Adapter\Adapter; use Zend\Db\Adapter\Profiler; +use Zend\Db\Sql\Select; class AdapterTest extends \PHPUnit_Framework_TestCase { @@ -200,6 +201,36 @@ public function testGetCurrentSchema() $this->assertEquals('FooSchema', $this->adapter->getCurrentSchema()); } + /** + * @covers Zend\Db\Adapter\Adapter::getSqlBuilder + * @covers Zend\Db\Adapter\Adapter::setSqlBuilder + */ + public function testSetGetSqlBuilder() + { + $mockBuilder = $this->getMock('Zend\Db\Adapter\SqlBuilderInterface'); + + $this->assertNull($this->adapter->getSqlBuilder()); + $this->assertSame($this->adapter, $this->adapter->setSqlBuilder($mockBuilder)); + $this->assertSame($mockBuilder, $this->adapter->getSqlBuilder()); + } + + /** + * @covers Zend\Db\Adapter\Adapter::getSqlBuilder + * @covers Zend\Db\Adapter\Adapter::setSqlBuilder + */ + public function testSetSqlBuilderViaConstructor() + { + $mockBuilder = $this->getMock('Zend\Db\Adapter\SqlBuilderInterface'); + $adapter = new Adapter( + [ + 'driver' => $this->mockDriver, + 'sql_builder' => $mockBuilder, + ], + $this->mockPlatform + ); + $this->assertSame($mockBuilder, $adapter->getSqlBuilder()); + } + /** * @testdox unit test: Test query() in prepare mode produces a statement object * @covers Zend\Db\Adapter\Adapter::query @@ -277,6 +308,53 @@ public function testQueryWhenExecutedProducesAResultSetObjectWhenResultIsQuery() $this->assertInstanceOf('ZendTest\Db\Adapter\TemporaryResultSet', $r); } + /** + * @covers Zend\Db\Adapter\Adapter::query + */ + public function testQueryWithObjectSql() + { + $sql = 'SELECT bar'; + $sqlObject = new Select('bar'); + + $resultInterface = $this->getMock('Zend\Db\Adapter\Driver\ResultInterface'); + $statementInterface = $this->getMock('Zend\Db\Adapter\Driver\StatementInterface'); + + $this->mockConnection->expects($this->any())->method('execute')->with($sql)->will($this->returnValue($resultInterface)); + + $mockBuilder = $this->getMock('Zend\Db\Adapter\SqlBuilderInterface'); + $mockBuilder->expects($this->any())->method('buildSqlString')->with($sqlObject)->will($this->returnValue($sql)); + $mockBuilder->expects($this->any())->method('prepareSqlStatement')->with($sqlObject)->will($this->returnValue($statementInterface)); + + $this->adapter->setSqlBuilder($mockBuilder); + + $this->assertSame( + $resultInterface, + $this->adapter->query($sqlObject, Adapter::QUERY_MODE_EXECUTE) + ); + $this->assertSame( + $statementInterface, + $this->adapter->query($sqlObject, Adapter::QUERY_MODE_PREPARE) + ); + } + + /** + * @covers Zend\Db\Adapter\Adapter::query + */ + public function testQueryExecuteObjectSqlWithoutSqlBuilder() + { + $this->setExpectedException('Zend\Db\Adapter\Exception\RuntimeException', 'sqlBuilder must be set for non string sql'); + $this->adapter->query(new Select('bar'), Adapter::QUERY_MODE_EXECUTE); + } + + /** + * @covers Zend\Db\Adapter\Adapter::query + */ + public function testQueryPrepareObjectSqlWithoutSqlBuilder() + { + $this->setExpectedException('Zend\Db\Adapter\Exception\RuntimeException', 'sqlBuilder must be set for non string sql'); + $this->adapter->query(new Select('bar'), Adapter::QUERY_MODE_PREPARE); + } + /** * @testdox unit test: Test createStatement() produces a statement object * @covers Zend\Db\Adapter\Adapter::createStatement diff --git a/test/Sql/Builder/BuilderServiceFactoryTest.php b/test/Sql/Builder/BuilderServiceFactoryTest.php index 0ffe998fc4..629dfe8ecc 100644 --- a/test/Sql/Builder/BuilderServiceFactoryTest.php +++ b/test/Sql/Builder/BuilderServiceFactoryTest.php @@ -15,6 +15,7 @@ use Zend\Stdlib\ArrayUtils; use Zend\Db; use Zend\Db\Sql\Builder\Builder; +use Zend\Db\Adapter\SqlBuilderInterface; class BuilderServiceFactoryTest extends TestCase { @@ -30,7 +31,7 @@ public function getBuilder($config = []) ); $serviceManager = new ServiceManager(); (new Config($config))->configureServiceManager($serviceManager); - return $serviceManager->get('SqlBuilder'); + return $serviceManager->get(SqlBuilderInterface::class); } public function testFactoryWithEmptyConfig()