Skip to content

Commit

Permalink
feat: added ability to select from within a SubQuery or Closure
Browse files Browse the repository at this point in the history
  • Loading branch information
mgcostaParedes committed May 17, 2021
1 parent 7b8e2dc commit f8a4add
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 14 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,14 @@ use MgCosta\Spanner\Model\Model;

class User extends Model {

protected $primaryKey = 'UserId';
protected $primaryKey = 'userId';

// available strategies [uuid4, increment]
// increment is not recommend by cloud spanner
protected $keyStrategy = 'uuid4';

// we must define the properties which corresponds to the columns of the table as public
public $userId;
public $name;
public $age;
public $email;
Expand Down
20 changes: 19 additions & 1 deletion src/Spanner/Builder/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,30 @@ public function getModel(): Model
return $this->model;
}

public function from(string $table, string $as = null): self
public function from($table, string $as = null): self
{
if ($this->isQueryable($table)) {
return $this->fromSub($table, $as);
}

$this->from = $as ? "{$table} as {$as}" : $table;
return $this;
}

public function fromSub($query, $as): self
{
[$query, $bindings] = $this->createSub($query);
return $this->fromRaw('(' . $query . ') as ' . $this->grammar->wrapTable($as), $bindings);
}

public function fromRaw($expression, $bindings = []): self
{
$this->from = new Expression($expression);

$this->addBinding($bindings, 'from');
return $this;
}

public function join($table, $first, $operator = null, $second = null, $type = 'inner', $where = false): self
{
$join = $this->newJoinClause($this, $type, $table);
Expand Down
20 changes: 10 additions & 10 deletions src/Spanner/Builder/Grammar/SpannerGrammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ protected function concatenate($segments): string
}));
}

protected function wrapTable($table)
public function wrapTable($table)
{
if (! $this->isExpression($table)) {
return $this->wrap($this->tablePrefix . $table, true);
Expand All @@ -325,7 +325,7 @@ protected function wrapTable($table)
return $table->getValue($table);
}

private function wrap($value, $prefixAlias = false)
protected function wrap($value, $prefixAlias = false)
{
if ($this->isExpression($value)) {
return $value->getValue($value);
Expand All @@ -339,7 +339,7 @@ private function wrap($value, $prefixAlias = false)
return $this->wrapSegments(explode('.', $value));
}

private function wrapAliasedValue($value, $prefixAlias = false): string
protected function wrapAliasedValue($value, $prefixAlias = false): string
{
$segments = preg_split('/\s+as\s+/i', $value);

Expand All @@ -350,7 +350,7 @@ private function wrapAliasedValue($value, $prefixAlias = false): string
return $this->wrap($segments[0]) . ' as ' . $this->wrapValue($segments[1]);
}

private function wrapValue($value): string
protected function wrapValue($value): string
{
if ($value !== '*') {
return str_replace('"', '""', $value);
Expand All @@ -359,12 +359,7 @@ private function wrapValue($value): string
return $value;
}

private function isExpression($value): bool
{
return $value instanceof Expression;
}

private function wrapSegments($segments): string
protected function wrapSegments($segments): string
{
return collect($segments)->map(function ($segment, $key) use ($segments) {
return $key == 0 && count($segments) > 1
Expand All @@ -373,6 +368,11 @@ private function wrapSegments($segments): string
})->implode('.');
}

private function isExpression($value): bool
{
return $value instanceof Expression;
}

private function columnize(array $columns): string
{
return implode(', ', array_map([$this, 'wrap'], $columns));
Expand Down
4 changes: 4 additions & 0 deletions src/Spanner/Builder/Interfaces/Operator.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

interface Operator
{
public function from($table, string $as = null): Builder;
public function fromSub($query, $as): Builder;
public function fromRaw($expression, $bindings = []): Builder;

public function select($columns = ['*']): Builder;
public function selectSub($query, $as): Builder;
public function selectRaw($expression, array $bindings = []): Builder;
Expand Down
4 changes: 2 additions & 2 deletions src/Spanner/Facade/SpannerDB.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ public function __construct(Database $connection = null)
$this->connection = $connection ?? Manager::getConnection();
}

public function table(string $name): Builder
public function table($name, $as = null): Builder
{
return (new Builder($this->connection))->from($name);
return (new Builder($this->connection))->from($name, $as);
}
}
9 changes: 9 additions & 0 deletions tests/unit/BuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ public function testShouldAssignFromAndModelWhenCallingSetModelProperly()
$this->assertEquals('dummymodel', $this->builder->from);
}

public function testShouldAssignProperBindingsWhenCallingFromWithSubQuery()
{
$subQuery = new Builder(m::mock(Database::class));
$subQuery->from('persons')->where('age', '>=', 35);
$this->builder->from($subQuery, 'table');

$this->assertEquals(['param1' => 35], $this->builder->bindings['from']);
$this->assertEquals('(select * from persons where age >= @param1) as table', $this->builder->from);
}

public function testShouldThrowAnInvalidArgumentExceptionModelWhenCallingAddBindingWithInvalidType()
{
Expand Down

0 comments on commit f8a4add

Please sign in to comment.