Skip to content

Commit

Permalink
Merge pull request #26 from php-etl/feature/expressions-in-query
Browse files Browse the repository at this point in the history
expressions in "query", iterable parameters
  • Loading branch information
gplanchat authored Jul 10, 2023
2 parents 03a1347 + 505d212 commit 8de7414
Show file tree
Hide file tree
Showing 11 changed files with 860 additions and 403 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
},
"extra": {
"branch-alias": {
"dev-main": "0.4.x-dev"
"dev-main": "0.5.x-dev"
},
"gyroscops": {
"plugins": ["Kiboko\\Plugin\\SQL\\Service"]
Expand Down
288 changes: 190 additions & 98 deletions src/Builder/AlternativeLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ final class AlternativeLoader implements StepBuilderInterface
{
/** @var array<array-key, array{value: Node\Expr, type: string}> */
private array $parameters = [];
/** @var array<array-key, array{value: Node\Expr, type: string}> */
private array $parametersLists = [];

public function __construct(private readonly Node\Expr $query)
{
Expand Down Expand Up @@ -101,6 +103,76 @@ public function addBinaryParam(int|string $key, Node\Expr $param): self
return $this;
}

public function addStringParamList(int|string $key, Node\Expr $param): StepBuilderInterface
{
$this->parametersLists[$key] = [
'value' => $param,
'type' => 'string',
];

return $this;
}

public function addIntegerParamList(int|string $key, Node\Expr $param): StepBuilderInterface
{
$this->parametersLists[$key] = [
'value' => $param,
'type' => 'integer',
];

return $this;
}

public function addBooleanParamList(int|string $key, Node\Expr $param): StepBuilderInterface
{
$this->parametersLists[$key] = [
'value' => $param,
'type' => 'boolean',
];

return $this;
}

public function addDateParamList(int|string $key, Node\Expr $param): self
{
$this->parametersLists[$key] = [
'value' => $param,
'type' => 'date',
];

return $this;
}

public function addDateTimeParamList(int|string $key, Node\Expr $param): self
{
$this->parametersLists[$key] = [
'value' => $param,
'type' => 'datetime',
];

return $this;
}

public function addJSONParamList(int|string $key, Node\Expr $param): self
{
$this->parametersLists[$key] = [
'value' => $param,
'type' => 'json',
];

return $this;
}

public function addBinaryParamList(int|string $key, Node\Expr $param): self
{
$this->parametersLists[$key] = [
'value' => $param,
'type' => 'binary',
];

return $this;
}

public function getNode(): Node
{
return new Node\Stmt\Expression(
Expand All @@ -126,7 +198,7 @@ public function getNode(): Node
)
)
),
...$this->compileParameters(),
...$this->walkParameters(),
new Node\Stmt\Expression(
expr: new Node\Expr\MethodCall(
var: new Node\Expr\Variable('statement'),
Expand All @@ -147,115 +219,135 @@ public function getNode(): Node
);
}

public function compileParameters(): iterable
public function walkParameters(): iterable
{
foreach ($this->parameters as $key => $parameter) {
yield match ($parameter['type']) {
'datetime' => new Node\Stmt\Expression(
new Node\Expr\MethodCall(
var: new Node\Expr\Variable('statement'),
name: new Node\Identifier('bindValue'),
args: [
yield $this->compileParameter($key, $parameter);
}

foreach ($this->parametersLists as $key => $parameter) {
yield new Node\Stmt\Foreach_(
expr: $parameter['value'],
valueVar: new Node\Expr\Variable('value'),
subNodes: [
'keyVar' => new Node\Expr\Variable('key'),
'stmts' => [
$this->compileParameter(
new Node\Arg(
\is_string($key) ? new Node\Scalar\Encapsed(
[
new Node\Scalar\EncapsedStringPart(':'),
new Node\Scalar\EncapsedStringPart($key),
]
) : new Node\Scalar\LNumber($key)
new Node\Expr\BinaryOp\Concat(
new Node\Scalar\String_($key.'_'),
new Node\Expr\Variable('key'),
)
),
new Node\Arg(
value: new Node\Expr\MethodCall(
var: $parameter['value'],
name: new Node\Name('format'),
args: [
new Node\Arg(
value: new Node\Scalar\String_('YYYY-MM-DD HH:MI:SS')
),
],
),
[
'type' => $parameter['type'],
'value' => new Node\Expr\Variable('value'),
]
),
],
]
);
}
}

public function compileParameter(int|string|Node\Arg $key, array $parameter): Node\Stmt\Expression
{
return match ($parameter['type']) {
'datetime' => new Node\Stmt\Expression(
new Node\Expr\MethodCall(
var: new Node\Expr\Variable('statement'),
name: new Node\Identifier('bindValue'),
args: [
$this->compileParameterKey($key),
new Node\Arg(
value: new Node\Expr\MethodCall(
var: $parameter['value'],
name: new Node\Name('format'),
args: [
new Node\Arg(
value: new Node\Scalar\String_('YYYY-MM-DD HH:MI:SS')
),
],
),
$this->compileParameterType($parameter),
],
),
),
$this->compileParameterType($parameter),
],
),
'date' => new Node\Stmt\Expression(
new Node\Expr\MethodCall(
var: new Node\Expr\Variable('statement'),
name: new Node\Identifier('bindValue'),
args: [
new Node\Arg(
\is_string($key) ? new Node\Scalar\Encapsed(
[
new Node\Scalar\EncapsedStringPart(':'),
new Node\Scalar\EncapsedStringPart($key),
]
) : new Node\Scalar\LNumber($key)
),
new Node\Arg(
value: new Node\Expr\MethodCall(
var: $parameter['value'],
name: new Node\Name('format'),
args: [
new Node\Arg(
value: new Node\Scalar\String_('YYYY-MM-DD')
),
],
),
),
'date' => new Node\Stmt\Expression(
new Node\Expr\MethodCall(
var: new Node\Expr\Variable('statement'),
name: new Node\Identifier('bindValue'),
args: [
$this->compileParameterKey($key),
new Node\Arg(
value: new Node\Expr\MethodCall(
var: $parameter['value'],
name: new Node\Name('format'),
args: [
new Node\Arg(
value: new Node\Scalar\String_('YYYY-MM-DD')
),
],
),
$this->compileParameterType($parameter),
],
),
),
$this->compileParameterType($parameter),
],
),
'json' => new Node\Stmt\Expression(
new Node\Expr\MethodCall(
var: new Node\Expr\Variable('statement'),
name: new Node\Identifier('bindValue'),
args: [
new Node\Arg(
\is_string($key) ? new Node\Scalar\Encapsed(
[
new Node\Scalar\EncapsedStringPart(':'),
new Node\Scalar\EncapsedStringPart($key),
]
) : new Node\Scalar\LNumber($key)
),
new Node\Arg(
new Node\Expr\FuncCall(
name: new Node\Name('json_encode'),
args: [
new Node\Arg(
value: $parameter['value']
),
],
),
),
'json' => new Node\Stmt\Expression(
new Node\Expr\MethodCall(
var: new Node\Expr\Variable('statement'),
name: new Node\Identifier('bindValue'),
args: [
$this->compileParameterKey($key),
new Node\Arg(
new Node\Expr\FuncCall(
name: new Node\Name('json_encode'),
args: [
new Node\Arg(
value: $parameter['value']
),
],
),
$this->compileParameterType($parameter),
],
),
),
$this->compileParameterType($parameter),
],
),
default => new Node\Stmt\Expression(
new Node\Expr\MethodCall(
var: new Node\Expr\Variable('statement'),
name: new Node\Identifier('bindValue'),
args: [
new Node\Arg(
\is_string($key) ? new Node\Scalar\Encapsed(
[
new Node\Scalar\EncapsedStringPart(':'),
new Node\Scalar\EncapsedStringPart($key),
]
) : new Node\Scalar\LNumber($key)
),
new Node\Arg(
$parameter['value']
),
$this->compileParameterType($parameter),
],
),
),
default => new Node\Stmt\Expression(
new Node\Expr\MethodCall(
var: new Node\Expr\Variable('statement'),
name: new Node\Identifier('bindValue'),
args: [
$this->compileParameterKey($key),
new Node\Arg(
$parameter['value']
),
$this->compileParameterType($parameter),
],
),
};
),
};
}

private function compileParameterKey(int|string|Node\Arg $key): Node\Arg
{
if (\is_string($key)) {
return new Node\Arg(
new Node\Scalar\Encapsed([
new Node\Scalar\EncapsedStringPart(':'),
new Node\Scalar\EncapsedStringPart($key),
])
);
}
if ($key instanceof Node\Arg) {
return $key;
}

return new Node\Arg(
new Node\Scalar\LNumber($key)
);
}

private function compileParameterType(array $parameter): Node\Arg
Expand Down
Loading

0 comments on commit 8de7414

Please sign in to comment.