Skip to content

Commit

Permalink
A few more Conditions and methods in GenericTableGateway to create them
Browse files Browse the repository at this point in the history
  • Loading branch information
sad-spirit committed Aug 18, 2023
1 parent 9d5cbc0 commit 70703f2
Show file tree
Hide file tree
Showing 6 changed files with 479 additions and 3 deletions.
45 changes: 45 additions & 0 deletions src/conditions/column/AnyCondition.php
@@ -0,0 +1,45 @@
<?php

/*
* This file is part of sad_spirit/pg_gateway package
*
* (c) Alexey Borzov <avb@php.net>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace sad_spirit\pg_gateway\conditions\column;

use sad_spirit\pg_gateway\TableGateway;
use sad_spirit\pg_builder\nodes\{
ColumnReference,
ScalarExpression,
expressions\ArrayComparisonExpression,
expressions\NamedParameter,
expressions\OperatorExpression,
expressions\TypecastExpression
};

/**
* Generates a "foo = any(:foo::foo_type[])" condition for the "foo" table column
*/
final class AnyCondition extends TypedCondition
{
protected function generateExpressionImpl(): ScalarExpression
{
$typeName = $this->converterFactory->createTypeNameNodeForOID($this->column->getTypeOID());
$typeName->bounds = [-1];

return new OperatorExpression(
'=',
new ColumnReference(TableGateway::ALIAS_SELF, $this->column->getName()),
new ArrayComparisonExpression(
ArrayComparisonExpression::ANY,
new TypecastExpression(new NamedParameter($this->column->getName()), $typeName)
)
);
}
}
44 changes: 44 additions & 0 deletions src/conditions/column/BoolCondition.php
@@ -0,0 +1,44 @@
<?php

/*
* This file is part of sad_spirit/pg_gateway package
*
* (c) Alexey Borzov <avb@php.net>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace sad_spirit\pg_gateway\conditions\column;

use sad_spirit\pg_gateway\{
TableGateway,
conditions\ColumnCondition,
exceptions\LogicException,
metadata\Column
};
use sad_spirit\pg_builder\nodes\ColumnReference;
use sad_spirit\pg_builder\nodes\ScalarExpression;

/**
* Uses the value of the bool-typed column as a Condition
*/
final class BoolCondition extends ColumnCondition
{
public const BOOL_OID = 16;

public function __construct(Column $column)
{
if (self::BOOL_OID !== (int)$column->getTypeOID()) {
throw new LogicException("Column '{$column->getName()}' is not of type 'bool'");
}
parent::__construct($column);
}

protected function generateExpressionImpl(): ScalarExpression
{
return new ColumnReference(TableGateway::ALIAS_SELF, $this->column->getName());
}
}
36 changes: 36 additions & 0 deletions src/conditions/column/IsNullCondition.php
@@ -0,0 +1,36 @@
<?php

/*
* This file is part of sad_spirit/pg_gateway package
*
* (c) Alexey Borzov <avb@php.net>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace sad_spirit\pg_gateway\conditions\column;

use sad_spirit\pg_gateway\TableGateway;
use sad_spirit\pg_gateway\conditions\ColumnCondition;
use sad_spirit\pg_builder\nodes\{
ColumnReference,
ScalarExpression,
expressions\IsExpression
};

/**
* Generates a "foo IS [NOT] NULL" Condition for the "foo" table column
*/
final class IsNullCondition extends ColumnCondition
{
protected function generateExpressionImpl(): ScalarExpression
{
return new IsExpression(
new ColumnReference(TableGateway::ALIAS_SELF, $this->column->getName()),
IsExpression::NULL
);
}
}
147 changes: 146 additions & 1 deletion src/gateways/GenericTableGateway.php
Expand Up @@ -19,14 +19,24 @@
TableGateway,
TableLocator,
TableSelect,
exceptions\InvalidArgumentException,
fragments\ClosureFragment,
fragments\InsertSelectFragment,
fragments\SetClauseFragment,
exceptions\InvalidArgumentException,
metadata\Columns,
metadata\PrimaryKey,
metadata\References
};
use sad_spirit\pg_gateway\conditions\{
NotCondition,
ParametrizedCondition,
SqlStringCondition,
column\AnyCondition,
column\BoolCondition,
column\IsNullCondition,
column\NotAllCondition,
column\OperatorCondition
};
use sad_spirit\pg_builder\{
Delete,
Insert,
Expand Down Expand Up @@ -273,4 +283,139 @@ protected function generateStatementKey(string $statementType, FragmentList $fra
$fragmentKey
);
}

/**
* Creates a "column = any(values::column_type[])" Condition
*
* This is roughly equivalent to "column IN (...values)" but requires only one placeholder
*
* @param string $column
* @param array $values
* @return ParametrizedCondition
*/
public function any(string $column, array $values): ParametrizedCondition
{
return new ParametrizedCondition(
new AnyCondition(
$this->getColumns()->get($column),
$this->tableLocator->getTypeConverterFactory()
),
[$column => $values]
);
}

/**
* Creates a "column" Condition for a column of "bool" type
*
* @param string $column
* @return BoolCondition
*/
public function column(string $column): BoolCondition
{
return new BoolCondition($this->getColumns()->get($column));
}

/**
* Creates a "NOT column" Condition for a column of "bool" type
*
* @param string $column
* @return NotCondition
*/
public function notColumn(string $column): NotCondition
{
return new NotCondition($this->column($column));
}

/**
* Creates a "column IS NULL" Condition
*
* @param string $column
* @return IsNullCondition
*/
public function isNull(string $column): IsNullCondition
{
return new IsNullCondition($this->getColumns()->get($column));
}

/**
* Creates a "column IS NOT NULL" Condition
*
* @param string $column
* @return NotCondition
*/
public function isNotNull(string $column): NotCondition
{
return new NotCondition($this->isNull($column));
}

/**
* Creates a "column <> all(values::column_type[])" Condition
*
* This is roughly equivalent to "column NOT IN (...values)" but requires only one placeholder
*
* @param string $column
* @param array $values
* @return ParametrizedCondition
*/
public function notAll(string $column, array $values): ParametrizedCondition
{
return new ParametrizedCondition(
new NotAllCondition(
$this->getColumns()->get($column),
$this->tableLocator->getTypeConverterFactory()
),
[$column => $values]
);
}

/**
* Creates a "column OPERATOR value" condition
*
* The value will be actually passed separately as a query parameter
*
* @param string $column
* @param string $operator
* @param mixed $value
* @return ParametrizedCondition
*/
public function operatorCondition(string $column, string $operator, $value): ParametrizedCondition
{
return new ParametrizedCondition(
new OperatorCondition(
$this->getColumns()->get($column),
$this->tableLocator->getTypeConverterFactory(),
$operator
),
[$column => $value]
);
}

/**
* Creates a "column = value" condition
*
* The value will be actually passed separately as a query parameter
*
* @param string $column
* @param mixed $value
* @return ParametrizedCondition
*/
public function equal(string $column, $value): ParametrizedCondition
{
return $this->operatorCondition($column, '=', $value);
}

/**
* Creates a Condition based on the given SQL expression
*
* @param string $sql
* @param array $parameters
* @return ParametrizedCondition
*/
public function sqlCondition(string $sql, array $parameters = []): ParametrizedCondition
{
return new ParametrizedCondition(
new SqlStringCondition($this->tableLocator->getParser(), $sql),
$parameters
);
}
}
5 changes: 3 additions & 2 deletions tests/assets/update-create.sql
Expand Up @@ -3,13 +3,14 @@
create table update_test (
id integer not null,
title text default 'A string',
added timestamp with time zone default now()
added timestamp with time zone default now(),
flag bool default false
);

insert into update_test (id, title) values (1, 'One');
insert into update_test (id, title) values (2, 'Two');
insert into update_test (id, title, added) values (3, 'Many', '2020-01-01');
insert into update_test (id, title) values (4, 'Too many');
insert into update_test (id, title, flag) values (4, 'Too many', true);

create table unconditional (
id integer not null,
Expand Down

0 comments on commit 70703f2

Please sign in to comment.