Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM php:8.2-cli

RUN apt-get update && apt-get install -y \
git \
curl \
wget \
unzip \
zip \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*

RUN docker-php-ext-install \
pcntl \
sockets

COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

ENV COMPOSER_ALLOW_SUPERUSER=1
ENV COMPOSER_HOME=/composer
23 changes: 23 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "PHP",
"build": {
"dockerfile": "./Dockerfile",
"context": ".."
},
"customizations": {
"vscode": {
"extensions": [
"bmewburn.vscode-intelephense-client",
"xdebug.php-pack",
"devsense.phptools-vscode",
"mehedidracula.php-namespace-resolver",
"devsense.composer-php-vscode",
"phiter.phpstorm-snippets"
]
}
},
"forwardPorts": [
8080
],
"remoteUser": "root"
}
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for more information:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
# https://containers.dev/guide/dependabot

version: 2
updates:
- package-ecosystem: "devcontainers"
directory: "/"
schedule:
interval: weekly
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
"require": {
"php": "^8.2",
"ext-pcntl": "*",
"ext-sockets": "*",
"adbario/php-dot-notation": "^3.1",
"ahjdev/amphp-sqlite3": "dev-main",
"amphp/cache": "^2.0",
"amphp/cluster": "^2.0",
"amphp/file": "^v3.0.0",
Expand Down
1 change: 1 addition & 0 deletions src/Database/Clause.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ abstract class Clause extends Grammar implements Builder
use PrepareColumns;

protected array $clauses;

protected array $arguments;

protected function resolveWhereMethod(
Expand Down
166 changes: 31 additions & 135 deletions src/Database/Concerns/Query/BuildsQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,17 @@
use Phenix\Database\Constants\Operator;
use Phenix\Database\Constants\Order;
use Phenix\Database\Constants\SQL;
use Phenix\Database\Dialects\DialectFactory;
use Phenix\Database\Functions;
use Phenix\Database\Having;
use Phenix\Database\QueryAst;
use Phenix\Database\SelectCase;
use Phenix\Database\Subquery;
use Phenix\Database\Value;
use Phenix\Util\Arr;

use function array_is_list;
use function array_keys;
use function array_unique;
use function array_values;
use function ksort;

trait BuildsQuery
{
use HasLock;

public function table(string $table): static
{
$this->table = $table;
Expand Down Expand Up @@ -70,74 +64,7 @@ public function selectAllColumns(): static
return $this;
}

public function insert(array $data): static
{
$this->action = Action::INSERT;

$this->prepareDataToInsert($data);

return $this;
}

public function insertOrIgnore(array $values): static
{
$this->ignore = true;

$this->insert($values);

return $this;
}

public function upsert(array $values, array $columns): static
{
$this->action = Action::INSERT;

$this->uniqueColumns = $columns;

$this->prepareDataToInsert($values);

return $this;
}

public function insertFrom(Closure $subquery, array $columns, bool $ignore = false): static
{
$builder = new Subquery($this->driver);
$builder->selectAllColumns();

$subquery($builder);

[$dml, $arguments] = $builder->toSql();

$this->rawStatement = trim($dml, '()');

$this->arguments = array_merge($this->arguments, $arguments);

$this->action = Action::INSERT;

$this->ignore = $ignore;

$this->columns = $columns;

return $this;
}

public function update(array $values): static
{
$this->action = Action::UPDATE;

$this->values = $values;

return $this;
}

public function delete(): static
{
$this->action = Action::DELETE;

return $this;
}

public function groupBy(Functions|array|string $column)
public function groupBy(Functions|array|string $column): static
{
$column = match (true) {
$column instanceof Functions => (string) $column,
Expand All @@ -164,7 +91,7 @@ public function having(Closure $clause): static
return $this;
}

public function orderBy(SelectCase|array|string $column, Order $order = Order::DESC)
public function orderBy(SelectCase|array|string $column, Order $order = Order::DESC): static
{
$column = match (true) {
$column instanceof SelectCase => '(' . $column . ')',
Expand Down Expand Up @@ -196,50 +123,38 @@ public function page(int $page = 1, int $perPage = 15): static
return $this;
}

public function count(string $column = '*'): static
{
$this->action = Action::SELECT;

$this->columns = [Functions::count($column)];

return $this;
}

public function exists(): static
{
$this->action = Action::EXISTS;

$this->columns = [Operator::EXISTS->value];

return $this;
}

public function doesntExist(): static
{
$this->action = Action::EXISTS;

$this->columns = [Operator::NOT_EXISTS->value];

return $this;
}

/**
* @return array<int, mixed>
* @return array{0: string, 1: array<int, mixed>}
*/
public function toSql(): array
{
$sql = match ($this->action) {
Action::SELECT => $this->buildSelectQuery(),
Action::EXISTS => $this->buildExistsQuery(),
Action::INSERT => $this->buildInsertSentence(),
Action::UPDATE => $this->buildUpdateSentence(),
Action::DELETE => $this->buildDeleteSentence(),
};
$ast = $this->buildAst();
$dialect = DialectFactory::fromDriver($this->driver);

return [
$sql,
$this->arguments,
];
return $dialect->compile($ast);
}

protected function buildAst(): QueryAst
{
$ast = new QueryAst();
$ast->action = $this->action;
$ast->table = $this->table;
$ast->columns = $this->columns;
$ast->values = $this->values ?? [];
$ast->wheres = $this->clauses ?? [];
$ast->joins = $this->joins ?? [];
$ast->groups = $this->groupBy ?? [];
$ast->orders = $this->orderBy ?? [];
$ast->limit = isset($this->limit) ? $this->limit[1] : null;
$ast->offset = isset($this->offset) ? $this->offset[1] : null;
$ast->lock = $this->lockType ?? null;
$ast->having = $this->having ?? null;
$ast->rawStatement = $this->rawStatement ?? null;
$ast->ignore = $this->ignore ?? false;
$ast->uniqueColumns = $this->uniqueColumns ?? [];
$ast->params = $this->arguments;

return $ast;
}

protected function buildSelectQuery(): string
Expand Down Expand Up @@ -304,25 +219,6 @@ protected function buildExistsQuery(): string
return Arr::implodeDeeply($query);
}

private function prepareDataToInsert(array $data): void
{
if (array_is_list($data)) {
foreach ($data as $record) {
$this->prepareDataToInsert($record);
}

return;
}

ksort($data);

$this->columns = array_unique([...$this->columns, ...array_keys($data)]);

$this->arguments = \array_merge($this->arguments, array_values($data));

$this->values[] = array_fill(0, count($data), SQL::PLACEHOLDER->value);
}

private function buildInsertSentence(): string
{
$dml = [
Expand Down
Loading