0 follower

Class Yiisoft\Db\QueryBuilder\Condition\Builder\InBuilder

InheritanceYiisoft\Db\QueryBuilder\Condition\Builder\InBuilder
ImplementsYiisoft\Db\Expression\ExpressionBuilderInterface

Build an object of {@see In} or {@see NotIn} into SQL expressions.

Protected Methods

Hide inherited methods

Method Description Defined By
buildCompositeInCondition() Builds an SQL statement for checking the existence of rows with the specified composite column values. Yiisoft\Db\QueryBuilder\Condition\Builder\InBuilder
buildSubqueryInCondition() Build SQL for composite IN condition. Yiisoft\Db\QueryBuilder\Condition\Builder\InBuilder
buildValues() Builds $values to use in condition. Yiisoft\Db\QueryBuilder\Condition\Builder\InBuilder
getNullCondition() The Builds are null/is not null condition for column based on the operator. Yiisoft\Db\QueryBuilder\Condition\Builder\InBuilder
getRawValuesFromTraversableObject() Yiisoft\Db\QueryBuilder\Condition\Builder\InBuilder

Property Details

Method Details

Hide inherited methods

__construct() public method

public mixed __construct ( Yiisoft\Db\QueryBuilder\QueryBuilderInterface $queryBuilder )
$queryBuilder Yiisoft\Db\QueryBuilder\QueryBuilderInterface

                public function __construct(protected QueryBuilderInterface $queryBuilder) {}

            
build() public method

Build SQL for {@see In} or {@see NotIn}.

public string build ( Yiisoft\Db\QueryBuilder\Condition\In|Yiisoft\Db\QueryBuilder\Condition\NotIn $expression, array &$params = [] )
$expression Yiisoft\Db\QueryBuilder\Condition\In|Yiisoft\Db\QueryBuilder\Condition\NotIn
$params array
throws InvalidArgumentException
throws Yiisoft\Db\Exception\NotSupportedException

                public function build(ExpressionInterface $expression, array &$params = []): string
{
    $column = $expression->column instanceof Traversable
        ? iterator_to_array($expression->column)
        : $expression->column;
    $operator = match ($expression::class) {
        In::class => 'IN',
        NotIn::class => 'NOT IN',
    };
    $values = $expression->values;
    if ($column === []) {
        /** no columns to test against */
        return $operator === 'IN' ? '0=1' : '';
    }
    if ($column instanceof ExpressionInterface) {
        $column = $this->queryBuilder->buildExpression($column);
    }
    if ($values instanceof QueryInterface) {
        return $this->buildSubqueryInCondition($operator, $column, $values, $params);
    }
    if (is_array($column)) {
        if (count($column) > 1) {
            return $this->buildCompositeInCondition($operator, $column, $values, $params);
        }
        $column = reset($column);
        if ($column instanceof ExpressionInterface) {
            $column = $this->queryBuilder->buildExpression($column);
        }
    }
    $rawValues = is_array($values)
        ? $values
        : $this->getRawValuesFromTraversableObject($values);
    $nullCondition = null;
    $nullConditionOperator = null;
    if (in_array(null, $rawValues, true)) {
        $nullCondition = $this->getNullCondition($operator, $column);
        $nullConditionOperator = $operator === 'IN' ? 'OR' : 'AND';
    }
    $sqlValues = $this->buildValues($column, $values, $params);
    if (empty($sqlValues)) {
        return $nullCondition ?? ($operator === 'IN' ? '0=1' : '');
    }
    $column = $this->queryBuilder->getQuoter()->quoteColumnName($column);
    if (count($sqlValues) > 1) {
        $sql = "$column $operator (" . implode(', ', $sqlValues) . ')';
    } else {
        $operator = $operator === 'IN' ? '=' : '<>';
        $sql = $column . $operator . reset($sqlValues);
    }
    return $nullCondition !== null && $nullConditionOperator !== null
        ? sprintf('%s %s %s', $sql, $nullConditionOperator, $nullCondition)
        : $sql;
}

            
buildCompositeInCondition() protected method

Builds an SQL statement for checking the existence of rows with the specified composite column values.

protected string buildCompositeInCondition ( string|null $operator, array $columns, iterable|Iterator $values, array &$params = [] )
$operator string|null
$columns array
$values iterable|Iterator
$params array
throws InvalidArgumentException
throws Yiisoft\Db\Exception\NotSupportedException

                protected function buildCompositeInCondition(
    ?string $operator,
    array $columns,
    iterable|Iterator $values,
    array &$params = [],
): string {
    $vss = [];
    /** @var string[][] $values */
    foreach ($values as $value) {
        $vs = [];
        foreach ($columns as $column) {
            if ($column instanceof ExpressionInterface) {
                $column = $this->queryBuilder->buildExpression($column);
            }
            $vs[] = isset($value[$column])
                ? $this->queryBuilder->buildValue($value[$column], $params)
                : 'NULL';
        }
        $vss[] = '(' . implode(', ', $vs) . ')';
    }
    if (empty($vss)) {
        return $operator === 'IN' ? '0=1' : '';
    }
    $sqlColumns = [];
    foreach ($columns as $column) {
        if ($column instanceof ExpressionInterface) {
            $sqlColumns[] = $this->queryBuilder->buildExpression($column);
            continue;
        }
        $sqlColumns[] = !str_contains($column, '(')
            ? $this->queryBuilder->getQuoter()->quoteColumnName($column) : $column;
    }
    return '(' . implode(', ', $sqlColumns) . ") $operator (" . implode(', ', $vss) . ')';
}

            
buildSubqueryInCondition() protected method

Build SQL for composite IN condition.

protected string buildSubqueryInCondition ( string $operator, array|string $columns, Yiisoft\Db\Expression\ExpressionInterface $values, array &$params = [] )
$operator string
$columns array|string
$values Yiisoft\Db\Expression\ExpressionInterface
$params array
throws Yiisoft\Db\Exception\NotSupportedException

                protected function buildSubqueryInCondition(
    string $operator,
    array|string $columns,
    ExpressionInterface $values,
    array &$params = [],
): string {
    $query = '';
    $sql = $this->queryBuilder->buildExpression($values, $params);
    if (is_array($columns)) {
        $preparedColumns = [];
        foreach ($columns as $column) {
            if ($column instanceof ExpressionInterface) {
                $preparedColumns[] = $this->queryBuilder->buildExpression($column);
                continue;
            }
            $preparedColumns[] = $this->queryBuilder->getQuoter()->quoteColumnName($column);
        }
        return '(' . implode(', ', $preparedColumns) . ") $operator $sql";
    }
    if (str_contains($columns, '(')) {
        return $query;
    }
    $columns = $this->queryBuilder->getQuoter()->quoteColumnName($columns);
    return "$columns $operator $sql";
}

            
buildValues() protected method

Builds $values to use in condition.

protected array buildValues ( string $column, iterable $values, array &$params = [] )
$column string
$values iterable
$params array
throws InvalidArgumentException

                protected function buildValues(string $column, iterable $values, array &$params = []): array
{
    $sqlValues = [];
    foreach ($values as $value) {
        if (is_array($value) || $value instanceof ArrayAccess) {
            $value = $value[$column] ?? null;
        }
        if ($value === null) {
            continue;
        }
        $sqlValues[] = $this->queryBuilder->buildValue($value, $params);
    }
    return $sqlValues;
}

            
getNullCondition() protected method

The Builds are null/is not null condition for column based on the operator.

protected string getNullCondition ( string $operator, string $column )
$operator string
$column string

                protected function getNullCondition(string $operator, string $column): string
{
    $column = $this->queryBuilder->getQuoter()->quoteColumnName($column);
    if ($operator === 'IN') {
        return sprintf('%s IS NULL', $column);
    }
    return sprintf('%s IS NOT NULL', $column);
}

            
getRawValuesFromTraversableObject() protected method

protected array getRawValuesFromTraversableObject ( Traversable $traversableObject )
$traversableObject Traversable

                protected function getRawValuesFromTraversableObject(Traversable $traversableObject): array
{
    $rawValues = [];
    foreach ($traversableObject as $value) {
        if (is_array($value)) {
            $values = array_values($value);
            $rawValues = array_merge($rawValues, $values);
        } else {
            $rawValues[] = $value;
        }
    }
    return $rawValues;
}