Skip to content

Commit

Permalink
Added basic support for joins and whereRaw
Browse files Browse the repository at this point in the history
  • Loading branch information
timohund authored and Timo Hund committed Jul 28, 2023
1 parent a6614c4 commit 3dd1c7c
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 2 deletions.
53 changes: 51 additions & 2 deletions src/Builder/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,24 @@ abstract class Builder implements QueryBuilderContract
{
use BuildersConcern;

public const JOIN_TYPE_LEFT = 'LEFT';
public const JOIN_TYPE_RIGHT = 'RIGHT';
public const JOIN_TYPE_INNER = 'INNER';
public const JOIN_TYPE_FULL = 'FULL';
public const JOIN_TYPE_LEFT_OUTER = 'LEFT OUTER';
public const JOIN_TYPE_RIGHT_OUTER = 'RIGHT OUTER';
public const JOIN_TYPE_FULL_OUTER = 'FULL OUTER';

public const JOIN_TYPES = [
self::JOIN_TYPE_LEFT,
self::JOIN_TYPE_RIGHT,
self::JOIN_TYPE_INNER,
self::JOIN_TYPE_FULL,
self::JOIN_TYPE_LEFT_OUTER,
self::JOIN_TYPE_RIGHT_OUTER,
self::JOIN_TYPE_FULL_OUTER,
];

protected string $database = '';
protected string $table = '';
protected string $fromQuery = '';
Expand All @@ -21,6 +39,7 @@ abstract class Builder implements QueryBuilderContract
protected string $groupByQuery = '';
protected string $limitByQuery = '';
protected array $withQueries = [];
protected array $joinQueries = [];

public function selectRaw(string $statement): self
{
Expand All @@ -44,12 +63,35 @@ public function from(string $database, string $table, string $alias = null): sel
$this->fromQuery = 'FROM "' . $database . '"."' . $table . '"';

if ($alias) {
$this->fromQuery = Str::of($this->fromQuery)->append(" {$alias}");
$this->fromQuery = Str::of($this->fromQuery)->append(" AS {$alias}");
}

return $this;
}

public function join(string $database, string $table, string $type = 'LEFT', ?string $alias = null, ?string $on = null): Builder
{
if (!in_array($type, self::JOIN_TYPES)) {
throw new \InvalidArgumentException(sprintf('Invalid join type %s', $type));
}
$joinQuery = $type . ' JOIN "' . $database . '"."' . $table . '"';
if ($alias) {
$joinQuery = Str::of($joinQuery)->append(" AS {$alias}");
}

if ($on) {
$joinQuery = Str::of($joinQuery)->append(" ON {$on}");
}
$this->joinQueries = array_merge($this->joinQueries, [$joinQuery]);

return $this;
}

public function leftJoin(string $database, string $table, string $alias = null, string $on = null): self
{
return $this->join($database, $table, self::JOIN_TYPE_LEFT, $alias, $on);
}

public function fromRaw(string $statement): self
{
$this->fromQuery = $statement;
Expand All @@ -72,6 +114,13 @@ public function groupBy($args): self
return $this;
}

public function whereRaw(string $statement): self
{
$this->whereQuery = $statement;

return $this;
}

public function where(string $column, $value, string $operator = '=', string $boolean = 'and', bool $ago = false): self
{
$query = Str::of($this->whereQuery);
Expand Down Expand Up @@ -253,7 +302,7 @@ public function whereNotNull(string|array $columns, $boolean = 'and'): self

public function limitBy(int $limit): self
{
$this->limitByQuery = sprintf('LIMIT %s ', $limit);
$this->limitByQuery = sprintf('LIMIT %s', $limit);

return $this;
}
Expand Down
12 changes: 12 additions & 0 deletions src/Concerns/BuildersConcern.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ public function getWithQueries(): array
return $this->withQueries;
}

public function getJoinQueries(): array
{
return $this->joinQueries;
}

public function getQueryString(): string
{
if ($this->getWithQueries()) {
Expand All @@ -84,6 +89,13 @@ public function getQueryString(): string
->append($this->getFromQuery());
}

if ($this->getJoinQueries()) {
$joinQueries = implode(' ', $this->getJoinQueries());
$queryString = $queryString
->append(' ')
->append($joinQueries);
}

if ($this->getWhereQuery()) {
$queryString = $queryString
->append(' ')
Expand Down
63 changes: 63 additions & 0 deletions tests/Unit/ReaderUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,69 @@ public function test_query_builder_should_return_query_string()
$this->assertEquals($queryBuilder->getSql(), $sql);
}

public function test_query_builder_can_alias_tables()
{
$sql = "SELECT * FROM \"database-name\".\"table-name\" AS t1 WHERE time >= ago(24h) AND measure_value::varchar NOT IN ('reviewer','open','closed') ORDER BY time desc";
$queryBuilder = TimestreamBuilder::query()
->select('*')
->from("database-name", 'table-name', 't1')
->whereAgo('time', '24h', '>=')
->whereNotIn('measure_value::varchar', ['reviewer', 'open', 'closed'])
->orderBy('time', 'desc');

$this->assertInstanceOf(Builder::class, $queryBuilder);
$this->assertIsString($queryBuilder->getSql());
$this->assertEquals($queryBuilder->getSql(), $sql);
}

public function test_query_builder_can_left_join_tables()
{
$sql = "SELECT * FROM \"database-name\".\"table-name\" AS t1 LEFT JOIN \"database-name\".\"table-name2\" AS t2 ON t1.id = t2.id WHERE time >= ago(24h) AND measure_value::varchar NOT IN ('reviewer','open','closed') ORDER BY time desc";
$queryBuilder = TimestreamBuilder::query()
->select('*')
->from("database-name", 'table-name', 't1')
->leftJoin("database-name", 'table-name2', 't2', 't1.id = t2.id')
->whereAgo('time', '24h', '>=')
->whereNotIn('measure_value::varchar', ['reviewer', 'open', 'closed'])
->orderBy('time', 'desc');

$this->assertInstanceOf(Builder::class, $queryBuilder);
$this->assertIsString($queryBuilder->getSql());
$this->assertEquals($queryBuilder->getSql(), $sql);
}

public function test_query_builder_can_use_aliases_in_selects()
{
$sql = "SELECT p.name, avg(r.rating) AS avg_rating FROM \"shop\".\"products\" AS p LEFT JOIN \"shop\".\"reviews\" AS r ON p.id = r.product_id ORDER BY time desc LIMIT 10";
$queryBuilder = TimestreamBuilder::query()
->select('p.name, avg(r.rating) AS avg_rating')
->from("shop", 'products', 'p')
->leftJoin("shop", 'reviews', 'r', 'p.id = r.product_id')
->orderBy('time', 'desc')
->limitBy(10);

$this->assertInstanceOf(Builder::class, $queryBuilder);
$this->assertIsString($queryBuilder->getSql());
$this->assertEquals($queryBuilder->getSql(), $sql);
}

public function test_query_builder_can_add_rawWhere()
{
$sql = "SELECT p.name, avg(r.rating) AS avg_rating FROM \"shop\".\"products\" AS p LEFT JOIN \"shop\".\"reviews\" AS r ON p.id = r.product_id WHERE p.name = \"test\" AND avg_rating > 4 ORDER BY time desc LIMIT 10";
$queryBuilder = TimestreamBuilder::query()
->select('p.name, avg(r.rating) AS avg_rating')
->from("shop", 'products', 'p')
->leftJoin("shop", 'reviews', 'r', 'p.id = r.product_id')
->whereRaw("WHERE p.name = \"test\"")
->andWhere('avg_rating', 4, '>')
->orderBy('time', 'desc')
->limitBy(10);

$this->assertInstanceOf(Builder::class, $queryBuilder);
$this->assertIsString($queryBuilder->getSql());
$this->assertEquals($queryBuilder->getSql(), $sql);
}

public function test_reader_dto_should_return_correct_query_string_from_query_builder()
{
$queryBuilder = TimestreamBuilder::query()
Expand Down

0 comments on commit 3dd1c7c

Please sign in to comment.