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

Commit

Permalink
Merging develop to master in preparation for 2.8.0
Browse files Browse the repository at this point in the history
  • Loading branch information
weierophinney committed Apr 12, 2016
2 parents aebb9b8 + f58c8a0 commit e9af771
Show file tree
Hide file tree
Showing 14 changed files with 557 additions and 92 deletions.
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,37 @@

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

## 2.8.0 - TBD

### Added

- [#92](https://github.com/zendframework/zend-db/pull/92) adds the class
`Zend\Db\Sql\Join` for creating and aggregating JOIN specifications. This is
now consumed by all `Zend\Db\Sql` implementations in order to represent JOIN
statements.
- [#92](https://github.com/zendframework/zend-db/pull/92) adds support for JOIN
operations to UPDATE statements.
- [#92](https://github.com/zendframework/zend-db/pull/92) adds support for joins
to `AbstractTableGateway::update`; you can now pass an array of
specifications via a third argument to the method.
- [#96](https://github.com/zendframework/zend-db/pull/96) exposes the package as
config-provider/component, but adding:
- `Zend\Db\ConfigProvider`, which maps the `AdapterInterface` to the
`AdapterServiceFactory`, and enables the `AdapterAbstractServiceFactory`.
- `Zend\Db\Module`, which does the same, for a zend-mvc context.

### Deprecated

- Nothing.

### Removed

- Nothing.

### Fixed

- Nothing.

## 2.7.1 - 2016-04-12

### Added
Expand Down
4 changes: 4 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
"branch-alias": {
"dev-master": "2.7-dev",
"dev-develop": "2.8-dev"
},
"zf": {
"component": "Zend\\Db",
"config-provider": "Zend\\Db\\ConfigProvider"
}
},
"autoload-dev": {
Expand Down
40 changes: 40 additions & 0 deletions src/ConfigProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php
/**
* @link http://github.com/zendframework/zend-db for the canonical source repository
* @copyright Copyright (c) 2005-2016 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace Zend\Db;

class ConfigProvider
{
/**
* Retrieve zend-db default configuration.
*
* @return array
*/
public function __invoke()
{
return [
'dependencies' => $this->getDependencyConfig(),
];
}

/**
* Retrieve zend-db default dependency configuration.
*
* @return array
*/
public function getDependencyConfig()
{
return [
'abstract_factories' => [
Adapter\AdapterAbstractServiceFactory::class,
],
'factories' => [
Adapter\AdapterInterface::class => Adapter\AdapterServiceFactory::class,
],
];
}
}
24 changes: 24 additions & 0 deletions src/Module.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php
/**
* @link http://github.com/zendframework/zend-db for the canonical source repository
* @copyright Copyright (c) 2005-2016 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace Zend\Db;

class Module
{
/**
* Retrieve default zend-db configuration for zend-mvc context.
*
* @return array
*/
public function getConfig()
{
$provider = new ConfigProvider();
return [
'service_manager' => $provider->getDependencyConfig(),
];
}
}
75 changes: 75 additions & 0 deletions src/Sql/AbstractSql.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,23 @@ protected function buildSqlString(
$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)
{
return $table . ($alias ? ' AS ' . $alias : '');
}

/**
* @staticvar int $runtimeExpressionPrefix
* @param ExpressionInterface $expression
Expand Down Expand Up @@ -291,6 +305,67 @@ protected function processSubSelect(
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
Expand Down
163 changes: 163 additions & 0 deletions src/Sql/Join.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
<?php
/**
* @link http://github.com/zendframework/zend-db for the canonical source repository
* @copyright Copyright (c) 2005-2016 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace Zend\Db\Sql;

use Countable;
use Iterator;

/**
* Aggregate JOIN specifications.
*
* Each specification is an array with the following keys:
*
* - name: the JOIN name
* - on: the table on which the JOIN occurs
* - columns: the columns to include with the JOIN operation; defaults to
* `Select::SQL_STAR`.
* - type: the type of JOIN being performed; see the `JOIN_*` constants;
* defaults to `JOIN_INNER`
*/
class Join implements Iterator, Countable
{
const JOIN_INNER = 'inner';
const JOIN_OUTER = 'outer';
const JOIN_LEFT = 'left';
const JOIN_RIGHT = 'right';
const JOIN_RIGHT_OUTER = 'right outer';
const JOIN_LEFT_OUTER = 'left outer';

/**
* Current iterator position.
*
* @var int
*/
private $position = 0;

/**
* JOIN specifications
*
* @var array
*/
protected $joins = [];

/**
* Initialize iterator position.
*/
public function __construct()
{
$this->position = 0;
}

/**
* Rewind iterator.
*/
public function rewind()
{
$this->position = 0;
}

/**
* Return current join specification.
*
* @return array
*/
public function current()
{
return $this->joins[$this->position];
}

/**
* Return the current iterator index.
*
* @return int
*/
public function key()
{
return $this->position;
}

/**
* Advance to the next JOIN specification.
*/
public function next()
{
++$this->position;
}

/**
* Is the iterator at a valid position?
*
* @return bool
*/
public function valid()
{
return isset($this->joins[$this->position]);
}

/**
* @return array
*/
public function getJoins()
{
return $this->joins;
}

/**
* @param string|array $name A table name on which to join, or a single
* element associative array, of the form alias => table
* @param string $on A string specification describing the fields to join on.
* @param string|string[]|int|int[] $columns A single column name, an array
* of column names, or (a) specification(s) such as SQL_STAR representing
* the columns to join.
* @param string $type The JOIN type to use; see the JOIN_* constants.
* @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)
{
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)) {
$columns = [$columns];
}

$this->joins[] = [
'name' => $name,
'on' => $on,
'columns' => $columns ? $columns : [Select::SQL_STAR],
'type' => $type ? $type : Join::JOIN_INNER
];

return $this;
}

/**
* Reset to an empty list of JOIN specifications.
*
* @return self Implements a fluent interface.
*/
public function reset()
{
$this->joins = [];
return $this;
}

/**
* Get count of attached predicates
*
* @return int
*/
public function count()
{
return count($this->joins);
}
}
Loading

0 comments on commit e9af771

Please sign in to comment.