Skip to content
Permalink
Browse files

Merge pull request #35 from shadowhand/fix/join-select

Allow temporary tables in JOINs
  • Loading branch information...
shadowhand committed Oct 3, 2017
2 parents e6533f8 + 3ec3893 commit d6c42a4066014d25dc1f7abf8f4616e2ebf649af
@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [3.0.0]

### Added

- Add `Query` interface to differentiate between queries and statements
- Add `Alias` and `Reference` objects for additional flexibility

## [2.2.0]

### Added
@@ -47,6 +47,7 @@ Helpers

- [Factory](#factory)
- [Conditions](#conditions)
- [Aliases](#aliases)
- [Expressions](#expressions)
- [Identifier Escaping](#identifier-escaping)
- [Booleans and Nulls](#booleans-and-nulls)
@@ -394,6 +395,38 @@ print_r($select->params());
// ['2017-01-01', '2017-12-31']
```

### Aliases

The builder includes a wrapper for SQL aliases which can be used for column names
in `SELECT` statements:

```php
use Latitude\QueryBuilder\Alias as a;
$select = SelectQuery::make(
a::make('id', 'user_id')
)
->from('users');
echo $select->sql();
// SELECT id AS user_id FROM users
```

**Note:** Aliases are automatically generated when using `'column alias'` as
a column name. The same is true for `'table alias'` as a table alias.

Aliases can also be used for complete queries:

```php
$select = SelectQuery::make('id')->from('users');
$alias = a::make($select, 'u');
echo $alias->sql();
// (SELECT id FROM users) AS u
```

This is generally used to create a temporary table for a `JOIN` expression.

### Expressions

The builder includes a simple wrapper for database expressions which can be used
@@ -19,6 +19,9 @@
"spatie/7to5": "^1.0"
},
"autoload": {
"files": [
"src/functions.php"
],
"psr-4": {
"Latitude\\QueryBuilder\\": "src/"
}
@@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
namespace Latitude\QueryBuilder;
class Alias implements Statement
{
/**
* Create a new alias.
*
* @param Statement|string $statement
*/
public static function make($statement, string $alias): Alias
{
return new static(reference($statement), $alias);
}
// Statement
public function sql(Identifier $identifier = null): string
{
return sprintf(
isQuery($this->statement) ? '(%s) AS %s' : '%s AS %s',
$this->statement->sql($identifier),
$this->alias
);
}
// Statement
public function params(): array
{
return $this->statement->params();
}
/**
* @var Statement
*/
protected $statement;
/**
* @var string
*/
protected $alias;
/**
* @see Alias::make()
*/
protected function __construct(Statement $statement, string $alias)
{
$this->statement = $statement;
$this->alias = $alias;
}
}
@@ -5,7 +5,7 @@
use Iterator;
class DeleteQuery implements Statement
class DeleteQuery implements Query
{
use Traits\CanUseDefaultIdentifier;
@@ -3,9 +3,10 @@
namespace Latitude\QueryBuilder;
class Expression
class Expression implements Statement
{
use Traits\CanUseDefaultIdentifier;
use Traits\HasNoParameters;
/**
* Create a new expression.
@@ -15,10 +16,8 @@ public static function make(string $template, string ...$identifiers): Expressio
return new static($template, $identifiers);
}
/**
* Get the SQL for the expression.
*/
public function sql(Identifier $identifier = null)
// Statement
public function sql(Identifier $identifier = null): string
{
$identifier = $this->getDefaultIdentifier($identifier);
@@ -6,7 +6,7 @@
use InvalidArgumentException;
use Iterator;
class InsertQuery implements Statement
class InsertQuery implements Query
{
use Traits\CanConvertIteratorToString;
use Traits\CanUseDefaultIdentifier;
@@ -0,0 +1,8 @@
<?php
declare(strict_types=1);
namespace Latitude\QueryBuilder;
interface Query extends Statement
{
}
@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace Latitude\QueryBuilder;
class Reference implements Statement
{
use Traits\CanUseDefaultIdentifier;
use Traits\HasNoParameters;
/**
* Create a new table or column reference.
*/
public static function make(string $reference)
{
return new static($reference);
}
// Statement
public function sql(Identifier $identifier = null): string
{
$identifier = $this->getDefaultIdentifier($identifier);
return $identifier->escapeQualified($this->reference);
}
/**
* @var string
*/
protected $reference;
/**
* @see Reference::make()
*/
protected function __construct(string $reference)
{
$this->reference = $reference;
}
}
@@ -5,7 +5,7 @@
use Iterator;
class SelectQuery implements Statement
class SelectQuery implements Query
{
use Traits\CanConvertIteratorToString;
use Traits\CanLimit;
@@ -39,48 +39,48 @@ public function from(string ...$tables): self
return $this;
}
public function join(string $table, Conditions $conditions, string $type = ''): self
public function join($table, Conditions $conditions, string $type = ''): self
{
$this->join[] = [\strtoupper($type), $table, $conditions];
$this->join[] = [\strtoupper($type), reference($table), $conditions];
return $this;
}
public function innerJoin(string $table, Conditions $conditions): self
public function innerJoin($table, Conditions $conditions): self
{
return $this->join($table, $conditions, 'INNER');
}
public function outerJoin(string $table, Conditions $conditions): self
public function outerJoin($table, Conditions $conditions): self
{
return $this->join($table, $conditions, 'OUTER');
}
public function leftJoin(string $table, Conditions $conditions): self
public function leftJoin($table, Conditions $conditions): self
{
return $this->join($table, $conditions, 'LEFT');
}
public function leftOuterJoin(string $table, Conditions $conditions): self
public function leftOuterJoin($table, Conditions $conditions): self
{
return $this->join($table, $conditions, 'LEFT OUTER');
}
public function rightJoin(string $table, Conditions $conditions): self
public function rightJoin($table, Conditions $conditions): self
{
return $this->join($table, $conditions, 'RIGHT');
}
public function rightOuterJoin(string $table, Conditions $conditions): self
public function rightOuterJoin($table, Conditions $conditions): self
{
return $this->join($table, $conditions, 'RIGHT OUTER');
}
public function fullJoin(string $table, Conditions $conditions): self
public function fullJoin($table, Conditions $conditions): self
{
return $this->join($table, $conditions, 'FULL');
}
public function fullOuterJoin(string $table, Conditions $conditions): self
public function fullOuterJoin($table, Conditions $conditions): self
{
return $this->join($table, $conditions, 'FULL OUTER');
}
@@ -238,7 +238,7 @@ protected function generateJoins(Identifier $identifier): Iterator
yield \trim(sprintf(
'%s JOIN %s ON %s',
$join[0],
$identifier->escapeAlias($join[1]),
$join[1]->sql($identifier),
$join[2]->sql($identifier)
));
}
@@ -251,6 +251,7 @@ protected function joinParams(): array
{
$params = [];
foreach ($this->join as $join) {
$params[] = $join[1]->params();
$params[] = $join[2]->params();
}
@@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
namespace Latitude\QueryBuilder\Traits;
trait HasNoParameters
{
// Statement
public function params(): array
{
return [];
}
}
@@ -5,7 +5,7 @@
use Iterator;
class UpdateQuery implements Statement
class UpdateQuery implements Query
{
use Traits\CanConvertIteratorToString;
use Traits\CanReplaceBooleanAndNullValues;
@@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Latitude\QueryBuilder;
function isQuery($value): bool
{
return $value instanceof Query;
}
function isStatement($value): bool
{
return $value instanceof Statement;
}
function reference($sql): Statement
{
if (isStatement($sql)) {
return $sql;
}
if (strpos($sql, ' ') === false) {
return Reference::make($sql);
}
return Alias::make(...\preg_split('/ (?:AS )?/i', $sql));
}
@@ -7,6 +7,11 @@
class DeleteQueryTest extends TestCase
{
public function testQuery()
{
$this->assertInstanceOf(Query::class, DeleteQuery::make('users'));
}
public function testDelete()
{
$table = 'users';
@@ -7,6 +7,11 @@
class InsertQueryTest extends TestCase
{
public function testQuery()
{
$this->assertInstanceOf(Query::class, InsertQuery::make('users'));
}
public function testInsert()
{
$table = 'users';
Oops, something went wrong.

0 comments on commit d6c42a4

Please sign in to comment.
You can’t perform that action at this time.